Class: Dommy::HTMLCollection
- Inherits:
-
Object
- Object
- Dommy::HTMLCollection
- Includes:
- Bridge::Methods, Enumerable
- Defined in:
- lib/dommy/html_collection.rb
Overview
‘HTMLCollection` — live, ordered set of Element nodes. Distinct from `NodeList` in two ways:
- Always element-only (Node types other than Element are skipped)
- Supports `namedItem(name)` lookup by `id` or `name` attribute
Live behavior: pass an evaluator block (called ‘&compute`) that returns the current element list on every access. Each query re-evaluates, so mutations to the parent tree are reflected immediately.
Intentionally NOT a subclass of Array; spec semantics demand ‘Array.isArray(html_collection) === false` in real browsers, and mirroring that here helps tests written against MDN behavior.
Direct Known Subclasses
Class Method Summary collapse
-
.elements_by_tag_name_ns(root, document, namespace, local_name) ⇒ Object
Shared ‘getElementsByTagNameNS(namespace, localName)` — a live collection of descendants of `root` matching the (namespace, localName) filter, where “*” matches any.
Instance Method Summary collapse
- #[](key) ⇒ Object
- #__js_call__(method, args) ⇒ Object
- #__js_get__(key) ⇒ Object
-
#__js_named_props__ ⇒ Object
WebIDL “supported property names” for HTMLCollection: in tree order, each element contributes its non-empty ‘id`, then (if it is in the HTML namespace) its non-empty `name` — ignoring duplicates.
- #each(&blk) ⇒ Object
- #empty? ⇒ Boolean
- #first(n = nil) ⇒ Object
-
#initialize(&compute) ⇒ HTMLCollection
constructor
A new instance of HTMLCollection.
- #item(index) ⇒ Object
- #last(n = nil) ⇒ Object
- #length ⇒ Object (also: #size)
-
#named_item(name) ⇒ Object
‘namedItem(name)` returns the first element whose `id` or `name` attribute equals `name`.
- #to_a ⇒ Object
Methods included from Bridge::Methods
Constructor Details
#initialize(&compute) ⇒ HTMLCollection
Returns a new instance of HTMLCollection.
21 22 23 |
# File 'lib/dommy/html_collection.rb', line 21 def initialize(&compute) @compute = compute end |
Class Method Details
.elements_by_tag_name_ns(root, document, namespace, local_name) ⇒ Object
Shared ‘getElementsByTagNameNS(namespace, localName)` — a live collection of descendants of `root` matching the (namespace, localName) filter, where “*” matches any. An empty-string namespace means the null namespace.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/dommy/html_collection.rb', line 28 def self.elements_by_tag_name_ns(root, document, namespace, local_name) ns = namespace.to_s ns_filter = ns == "*" ? :any : (ns.empty? ? nil : ns) local = local_name.to_s new do nodes = local == "*" ? root.css("*") : root.css(local) nodes.filter_map do |node| el = document.wrap_node(node) next nil unless el el_ns = el.respond_to?(:namespace_uri) ? el.namespace_uri : nil (ns_filter == :any || el_ns == ns_filter) ? el : nil end end end |
Instance Method Details
#[](key) ⇒ Object
81 82 83 84 85 86 87 88 89 90 |
# File 'lib/dommy/html_collection.rb', line 81 def [](key) case key when Integer to_a[key] when /\A-?\d+\z/ to_a[key.to_i] else named_item(key) end end |
#__js_call__(method, args) ⇒ Object
151 152 153 154 155 156 157 158 |
# File 'lib/dommy/html_collection.rb', line 151 def __js_call__(method, args) case method when "item" item(args[0]) when "namedItem" named_item(args[0]) end end |
#__js_get__(key) ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/dommy/html_collection.rb', line 108 def __js_get__(key) case key when "length" length when Integer item(key) else s = key.to_s if s.match?(/\A\d+\z/) && s.to_i < 4_294_967_295 # A valid array index (0 ≤ n < 2^32-1) is a pure indexed lookup — out # of range yields nil (→ undefined), never a named fallback. item(s.to_i) else # Non-array-index strings (negative, ≥ 2^32-1, or names) use the named # getter. named_item(s) || (s == "length" ? length : nil) end end end |
#__js_named_props__ ⇒ Object
WebIDL “supported property names” for HTMLCollection: in tree order, each element contributes its non-empty ‘id`, then (if it is in the HTML namespace) its non-empty `name` — ignoring duplicates.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/dommy/html_collection.rb', line 131 def __js_named_props__ names = [] to_a.each do |el| next unless el.respond_to?(:__dommy_backend_node__) node = el.__dommy_backend_node__ id = node["id"].to_s names << id if !id.empty? && !names.include?(id) name = node["name"].to_s next if name.empty? || names.include?(name) html_ns = !el.respond_to?(:namespace_uri) || el.namespace_uri == "http://www.w3.org/1999/xhtml" names << name if html_ns end names end |
#each(&blk) ⇒ Object
100 101 102 |
# File 'lib/dommy/html_collection.rb', line 100 def each(&blk) to_a.each(&blk) end |
#empty? ⇒ Boolean
50 51 52 |
# File 'lib/dommy/html_collection.rb', line 50 def empty? to_a.empty? end |
#first(n = nil) ⇒ Object
92 93 94 |
# File 'lib/dommy/html_collection.rb', line 92 def first(n = nil) n.nil? ? to_a.first : to_a.first(n) end |
#item(index) ⇒ Object
54 55 56 57 58 59 |
# File 'lib/dommy/html_collection.rb', line 54 def item(index) i = index.to_i return nil if i < 0 to_a[i] end |
#last(n = nil) ⇒ Object
96 97 98 |
# File 'lib/dommy/html_collection.rb', line 96 def last(n = nil) n.nil? ? to_a.last : to_a.last(n) end |
#length ⇒ Object Also known as: size
44 45 46 |
# File 'lib/dommy/html_collection.rb', line 44 def length to_a.length end |
#named_item(name) ⇒ Object
‘namedItem(name)` returns the first element whose `id` or `name` attribute equals `name`. Returns nil if no match.
63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/dommy/html_collection.rb', line 63 def named_item(name) # A numeric argument (`namedItem(2147483648)`) crosses from JS as a Float # for values past int32; format it as an integer string so it matches an # `id`/`name` attribute like "2147483648" (not "2147483648.0"). key = (name.is_a?(Float) && name.finite? && name == name.to_i) ? name.to_i.to_s : name.to_s return nil if key.empty? to_a.find do |el| next false unless el.respond_to?(:__dommy_backend_node__) el.__dommy_backend_node__["id"].to_s == key || el.__dommy_backend_node__["name"].to_s == key end end |
#to_a ⇒ Object
104 105 106 |
# File 'lib/dommy/html_collection.rb', line 104 def to_a @compute.call end |