Module: Dommy::Internal::ParentNode
- Includes:
- ChildNode
- Included in:
- Element, Fragment, ShadowRoot
- Defined in:
- lib/dommy/internal/parent_node.rb
Overview
Shared ParentNode tree-mutation surface for Element, Fragment, and
ShadowRoot. Includers must expose @__node__ (the backing Nokogiri
node) and @document (the owning Dommy::Document).
All child-list mutations funnel through notify_child_list, which
forwards to MutationCoordinator#notify_child_list_mutation. That
coordinator already no-ops on empty added/removed sets and on an
unwrappable target, so callers may invoke it unconditionally.
Instance Method Summary collapse
-
#append(*args) ⇒ Object
ParentNode#append — mixed Node/String args appended in order.
-
#append_child(child) ⇒ Object
appendChild(child)— detach the node(s) from any current parent and append to the end of this node's child list. -
#normalize ⇒ Object
Node#normalize — merge each run of adjacent exclusive Text descendants into its first node (preserving that node's identity, so a JS reference to it survives) and drop empty Text nodes.
-
#prepend(*args) ⇒ Object
ParentNode#prepend — insert before the current first child.
-
#replace_children(*args) ⇒ Object
ParentNode#replaceChildren — remove all existing children, then append the new set.
Methods included from ChildNode
#child_node_after, #child_node_before, #child_node_replace_with, #nullable_dom_string, #validate_insert_before_ref!
Instance Method Details
#append(*args) ⇒ Object
ParentNode#append — mixed Node/String args appended in order.
31 32 33 34 35 36 37 |
# File 'lib/dommy/internal/parent_node.rb', line 31 def append(*args) validate_insertion_args!(args) nodes = args.flat_map { |arg| detach_dom_nodes(arg) } nodes.each { |n| @__node__.add_child(n) } notify_child_list(added: nodes) nil end |
#append_child(child) ⇒ Object
appendChild(child) — detach the node(s) from any current parent
and append to the end of this node's child list.
21 22 23 24 25 26 27 28 |
# File 'lib/dommy/internal/parent_node.rb', line 21 def append_child(child) coerce_node_argument!(child) ensure_pre_insertion_validity!(child, nil) nodes = detach_dom_nodes(child) nodes.each { |n| @__node__.add_child(n) } notify_child_list(added: nodes) child end |
#normalize ⇒ Object
Node#normalize — merge each run of adjacent exclusive Text descendants into its first node (preserving that node's identity, so a JS reference to it survives) and drop empty Text nodes. Recurses the whole subtree, so it works for Element, DocumentFragment, and ShadowRoot alike.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/dommy/internal/parent_node.rb', line 72 def normalize text_nodes = [] @__node__.traverse { |node| text_nodes << node if node.respond_to?(:text?) && node.text? } text_nodes.each do |node| next unless node.parent # already removed as part of an earlier run if node.content.to_s.empty? @document.remove_node_with_notify(node) next end merged = [] sib = node.next while sib.respond_to?(:text?) && sib.text? merged << sib sib = sib.next end next if merged.empty? old = node.content.to_s node.content = old + merged.map { |m| m.content.to_s }.join @document.notify_character_data_mutation(target_node: node, old_value: old) merged.each { |m| @document.remove_node_with_notify(m) } end nil end |
#prepend(*args) ⇒ Object
ParentNode#prepend — insert before the current first child.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/dommy/internal/parent_node.rb', line 40 def prepend(*args) validate_insertion_args!(args) nodes = args.flat_map { |arg| detach_dom_nodes(arg) } anchor = @__node__.children.first if anchor # Insert each node before the (fixed) original first child in order: # forward iteration keeps document order (n1, n2, … then the old first # child). Reversing here would emit them backwards. nodes.each { |n| anchor.add_previous_sibling(n) } else nodes.each { |n| @__node__.add_child(n) } end notify_child_list(added: nodes) nil end |
#replace_children(*args) ⇒ Object
ParentNode#replaceChildren — remove all existing children, then append the new set. One mutation record carries both sides.
58 59 60 61 62 63 64 65 66 |
# File 'lib/dommy/internal/parent_node.rb', line 58 def replace_children(*args) validate_insertion_args!(args) removed = @__node__.children.to_a removed.each(&:unlink) nodes = args.flat_map { |arg| detach_dom_nodes(arg) } nodes.each { |n| @__node__.add_child(n) } notify_child_list(added: nodes, removed: removed) nil end |