Class: Moxml::NodeSet

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/moxml/node_set.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(native_nodes = []) ⇒ NodeSet

Returns a new instance of NodeSet.



8
9
10
# File 'lib/moxml/node_set.rb', line 8

def initialize(native_nodes = [])
  @native_nodes = Array(native_nodes)
end

Instance Attribute Details

#native_nodesObject (readonly)

Returns the value of attribute native_nodes.



6
7
8
# File 'lib/moxml/node_set.rb', line 6

def native_nodes
  @native_nodes
end

Instance Method Details

#&(other) ⇒ Object



123
124
125
# File 'lib/moxml/node_set.rb', line 123

def &(other)
  NodeSet.new(native_nodes & other.native_nodes)
end

#+(other) ⇒ Object

Collection operations



115
116
117
# File 'lib/moxml/node_set.rb', line 115

def +(other)
  NodeSet.new(native_nodes + other.native_nodes)
end

#-(other) ⇒ Object



119
120
121
# File 'lib/moxml/node_set.rb', line 119

def -(other)
  NodeSet.new(native_nodes - other.native_nodes)
end

#[](index) ⇒ Object



18
19
20
21
22
23
24
25
# File 'lib/moxml/node_set.rb', line 18

def [](index)
  case index
  when Integer
    Node.wrap(native_nodes[index])
  when Range
    NodeSet.new(native_nodes[index])
  end
end

#add_class(names) ⇒ Object



85
86
87
88
89
90
91
92
93
# File 'lib/moxml/node_set.rb', line 85

def add_class(names)
  each do |node|
    next unless node.is_a?(Element)
    current = (node["class"] || "").split(/\s+/)
    new_classes = names.is_a?(Array) ? names : names.split(/\s+/)
    node["class"] = (current + new_classes).uniq.join(" ")
  end
  self
end

#after(node_or_nodes) ⇒ Object



169
170
171
172
# File 'lib/moxml/node_set.rb', line 169

def after(node_or_nodes)
  each { |node| node.add_next_sibling(node_or_nodes) }
  self
end

#attr(name, value = nil) ⇒ Object



105
106
107
108
109
110
111
112
# File 'lib/moxml/node_set.rb', line 105

def attr(name, value = nil)
  if value.nil?
    first&.[](name)
  else
    each { |node| node[name] = value if node.is_a?(Element) }
    self
  end
end

#before(node_or_nodes) ⇒ Object

DOM Manipulation



164
165
166
167
# File 'lib/moxml/node_set.rb', line 164

def before(node_or_nodes)
  each { |node| node.add_previous_sibling(node_or_nodes) }
  self
end

#childrenObject



244
245
246
247
248
# File 'lib/moxml/node_set.rb', line 244

def children
  NodeSet.new(
    flat_map { |node| node.children.to_a }
  )
end

#eachObject



12
13
14
15
16
# File 'lib/moxml/node_set.rb', line 12

def each
  return enum_for(:each) unless block_given?
  native_nodes.each { |node| yield Node.wrap(node) }
  self
end

#empty?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/moxml/node_set.rb', line 35

def empty?
  native_nodes.empty?
end

#filter(selector) ⇒ Object



49
50
51
52
53
# File 'lib/moxml/node_set.rb', line 49

def filter(selector)
  NodeSet.new(
    native_nodes.select { |node| Moxml.adapter.matches?(node, selector) }
  )
end

#find_by_attribute(name, value = nil) ⇒ Object



148
149
150
151
152
153
154
155
156
157
# File 'lib/moxml/node_set.rb', line 148

def find_by_attribute(name, value = nil)
  select do |node|
    next unless node.is_a?(Element)
    if value.nil?
      node.attributes.key?(name)
    else
      node[name] == value
    end
  end
end

#find_by_class(class_name) ⇒ Object



144
145
146
# File 'lib/moxml/node_set.rb', line 144

def find_by_class(class_name)
  select { |node| node.is_a?(Element) && (node["class"] || "").split(/\s+/).include?(class_name) }
end

#find_by_id(id) ⇒ Object

Search and filtering



140
141
142
# File 'lib/moxml/node_set.rb', line 140

def find_by_id(id)
  detect { |node| node.is_a?(Element) && node["id"] == id }
end

#firstObject



27
28
29
# File 'lib/moxml/node_set.rb', line 27

def first
  Node.wrap(native_nodes.first)
end

#has_class?(name) ⇒ Boolean

Returns:

  • (Boolean)


225
226
227
# File 'lib/moxml/node_set.rb', line 225

def has_class?(name)
  any? { |node| node.is_a?(Element) && (node["class"] || "").split(/\s+/).include?(name) }
end

#inner_htmlObject



64
65
66
# File 'lib/moxml/node_set.rb', line 64

def inner_html
  map(&:inner_html).join
end

#inner_html=(html) ⇒ Object



202
203
204
205
# File 'lib/moxml/node_set.rb', line 202

def inner_html=(html)
  each { |node| node.inner_html = html }
  self
end

#inner_text=(text) ⇒ Object

Content manipulation



197
198
199
200
# File 'lib/moxml/node_set.rb', line 197

def inner_text=(text)
  each { |node| node.inner_text = text }
  self
end

#lastObject



31
32
33
# File 'lib/moxml/node_set.rb', line 31

def last
  Node.wrap(native_nodes.last)
end

#nextObject



256
257
258
259
260
# File 'lib/moxml/node_set.rb', line 256

def next
  NodeSet.new(
    map { |node| node.next_sibling }.compact
  )
end

#of_type(type) ⇒ Object



159
160
161
# File 'lib/moxml/node_set.rb', line 159

def of_type(type)
  select { |node| node.is_a?(type) }
end

#parentsObject

Position and hierarchy



238
239
240
241
242
# File 'lib/moxml/node_set.rb', line 238

def parents
  NodeSet.new(
    map { |node| node.parent }.compact.uniq
  )
end

#previousObject



262
263
264
265
266
# File 'lib/moxml/node_set.rb', line 262

def previous
  NodeSet.new(
    map { |node| node.previous_sibling }.compact
  )
end

#removeObject



55
56
57
58
# File 'lib/moxml/node_set.rb', line 55

def remove
  each(&:remove)
  self
end

#remove_attr(*attrs) ⇒ Object



229
230
231
232
233
234
235
# File 'lib/moxml/node_set.rb', line 229

def remove_attr(*attrs)
  each do |node|
    next unless node.is_a?(Element)
    attrs.each { |attr| node.remove_attribute(attr) }
  end
  self
end

#remove_class(names) ⇒ Object



95
96
97
98
99
100
101
102
103
# File 'lib/moxml/node_set.rb', line 95

def remove_class(names)
  each do |node|
    next unless node.is_a?(Element)
    current = (node["class"] || "").split(/\s+/)
    remove_classes = names.is_a?(Array) ? names : names.split(/\s+/)
    node["class"] = (current - remove_classes).join(" ")
  end
  self
end

#replace_with(node_or_nodes) ⇒ Object



174
175
176
177
# File 'lib/moxml/node_set.rb', line 174

def replace_with(node_or_nodes)
  each { |node| node.replace(node_or_nodes) }
  self
end

#reverseObject



135
136
137
# File 'lib/moxml/node_set.rb', line 135

def reverse
  NodeSet.new(native_nodes.reverse)
end

#siblingsObject



250
251
252
253
254
# File 'lib/moxml/node_set.rb', line 250

def siblings
  NodeSet.new(
    flat_map { |node| node.parent ? node.parent.children.reject { |sibling| sibling == node } : [] }
  ).uniq
end

#sizeObject Also known as: length



39
40
41
# File 'lib/moxml/node_set.rb', line 39

def size
  native_nodes.size
end

#textObject



60
61
62
# File 'lib/moxml/node_set.rb', line 60

def text
  map(&:text).join
end

#to_aObject



45
46
47
# File 'lib/moxml/node_set.rb', line 45

def to_a
  map { |node| node }
end

#toggle_class(names) ⇒ Object

Attribute operations



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/moxml/node_set.rb', line 208

def toggle_class(names)
  names = names.split(/\s+/) if names.is_a?(String)
  each do |node|
    next unless node.is_a?(Element)
    current = (node["class"] || "").split(/\s+/)
    names.each do |name|
      if current.include?(name)
        current.delete(name)
      else
        current << name
      end
    end
    node["class"] = current.uniq.join(" ")
  end
  self
end

#uniqObject



131
132
133
# File 'lib/moxml/node_set.rb', line 131

def uniq
  NodeSet.new(native_nodes.uniq)
end

#wrap(html_or_element) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/moxml/node_set.rb', line 68

def wrap(html_or_element)
  each do |node|
    wrapper = case html_or_element
      when String
        Document.parse("<div>#{html_or_element}</div>").root.children.first
      when Element
        html_or_element.dup
      else
        raise ArgumentError, "Expected String or Element"
      end

    node.add_previous_sibling(wrapper)
    wrapper.add_child(node)
  end
  self
end

#wrap_all(wrapper) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/moxml/node_set.rb', line 179

def wrap_all(wrapper)
  return self if empty?

  wrapper_node = case wrapper
    when String
      Document.parse(wrapper).root
    when Element
      wrapper
    else
      raise ArgumentError, "Expected String or Element"
    end

  first.add_previous_sibling(wrapper_node)
  wrapper_node.add_child(self)
  self
end

#|(other) ⇒ Object



127
128
129
# File 'lib/moxml/node_set.rb', line 127

def |(other)
  NodeSet.new(native_nodes | other.native_nodes)
end