Module: Dommy::Internal::NodeEquality
- Defined in:
- lib/dommy/internal/node_equality.rb
Overview
WHATWG DOM “equals” / Node.isEqualNode (dom.spec.whatwg.org/#concept-node-equals). Operates on Dommy node wrappers through their bridge-facing accessors (js_get for the per-type data, #child_nodes / #attributes for the structure), so it works uniformly across the heterogeneous node classes.
Class Method Summary collapse
- .attribute_descriptors(node) ⇒ Object
-
.attributes_equal?(a, b) ⇒ Boolean
Equal attribute lists, order-independent (each attribute of A must have a (namespace, localName, value) match in B, and the counts must match).
- .children(node) ⇒ Object
-
.data_equal?(a, b, type) ⇒ Boolean
Per-type “these two nodes have equal own properties” (children compared separately by #equal?).
- .equal?(a, b) ⇒ Boolean
- .prop(node, key) ⇒ Object
Class Method Details
.attribute_descriptors(node) ⇒ Object
64 65 66 67 68 69 70 71 72 |
# File 'lib/dommy/internal/node_equality.rb', line 64 def attribute_descriptors(node) return [] unless node.respond_to?(:attributes) map = node.attributes (0...map.length).map do |i| attr = map.item(i) [attr.namespace_uri, attr.local_name, attr.value] end end |
.attributes_equal?(a, b) ⇒ Boolean
Equal attribute lists, order-independent (each attribute of A must have a (namespace, localName, value) match in B, and the counts must match).
56 57 58 59 60 61 62 |
# File 'lib/dommy/internal/node_equality.rb', line 56 def attributes_equal?(a, b) attrs_a = attribute_descriptors(a) attrs_b = attribute_descriptors(b) return false unless attrs_a.length == attrs_b.length attrs_a.all? { |x| attrs_b.include?(x) } end |
.children(node) ⇒ Object
74 75 76 77 78 79 |
# File 'lib/dommy/internal/node_equality.rb', line 74 def children(node) return [] unless node.respond_to?(:child_nodes) list = node.child_nodes list.respond_to?(:to_a) ? list.to_a : (0...list.length).map { |i| list.item(i) } end |
.data_equal?(a, b, type) ⇒ Boolean
Per-type “these two nodes have equal own properties” (children compared separately by #equal?).
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/dommy/internal/node_equality.rb', line 29 def data_equal?(a, b, type) case type when Node::ELEMENT_NODE prop(a, "namespaceURI") == prop(b, "namespaceURI") && prop(a, "prefix") == prop(b, "prefix") && prop(a, "localName") == prop(b, "localName") && attributes_equal?(a, b) when Node::DOCUMENT_TYPE_NODE prop(a, "nodeName") == prop(b, "nodeName") && prop(a, "publicId") == prop(b, "publicId") && prop(a, "systemId") == prop(b, "systemId") when Node::PROCESSING_INSTRUCTION_NODE prop(a, "target") == prop(b, "target") && prop(a, "data") == prop(b, "data") when Node::TEXT_NODE, Node::CDATA_SECTION_NODE, Node::COMMENT_NODE prop(a, "data") == prop(b, "data") when Node::ATTRIBUTE_NODE prop(a, "namespaceURI") == prop(b, "namespaceURI") && prop(a, "localName") == prop(b, "localName") && prop(a, "value") == prop(b, "value") else # Document / DocumentFragment carry no own properties to compare. true end end |
.equal?(a, b) ⇒ Boolean
12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/dommy/internal/node_equality.rb', line 12 def equal?(a, b) return false if b.nil? type = prop(a, "nodeType") return false unless type == prop(b, "nodeType") return false unless data_equal?(a, b, type) kids_a = children(a) kids_b = children(b) return false unless kids_a.length == kids_b.length kids_a.each_index { |i| return false unless equal?(kids_a[i], kids_b[i]) } true end |
.prop(node, key) ⇒ Object
81 82 83 |
# File 'lib/dommy/internal/node_equality.rb', line 81 def prop(node, key) node.__js_get__(key) end |