Last active
October 8, 2015 00:09
-
-
Save tilgovi/04c13e202c5becdd1d21 to your computer and use it in GitHub Desktop.
DOM tree traversal helpers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Return true if the given predicate is true for every Node of the tree. | |
# The predicate function is invoked once for each Node in the tree. | |
# An optional third argument specifies a traversal order and should be a | |
# function that takes a Node and returns its successor. The default order is | |
# DOM position order (pre-order). | |
everyNode = (node, fn, next = preFirst) -> | |
return !someNode(node, ((n) -> !fn(n)), next) | |
# Return the first Node in the tree that matches the predicate. | |
# An optional third argument specifies a traversal and should be a function | |
# that returns the successor of its argument. The default is document order. | |
findNode = (node, fn, next = preFirst) -> | |
node = next(node) while node? and not result = fn(node) | |
return (if result then node else undefined) | |
# Return true if the given predicate is true for any Node of the tree. | |
# An optional third argument specifies a traversal and should be a function | |
# that returns the successor of its argument. The default is document order. | |
someNode = (node, fn, next = preFirst) -> | |
return !!findNode(node, fn, next) | |
# Return an Array of each Node in the tree for which the predicate is true. | |
# An optional third argument specifies a traversal and should be a function | |
# that returns the successor of its argument. The default is document order. | |
filterNode = (node, fn, next = preFirst) -> | |
collect = (acc, n) -> if fn(n) then acc.concat([n]) else acc | |
return reduceNode(node, collect, [], next) | |
# Return an Array of the result of applying a function to each Node in a tree. | |
# An optional third argument specifies a traversal and should be a function | |
# that returns the successor of its argument. The default is document order. | |
mapNode = (node, fn, next = preFirst) -> | |
return reduceNode(node, ((acc, n) -> acc.push(fn(n))), [], next) | |
reduceNode = (node, fn, initialValue = undefined, next = preFirst) -> | |
acc = initialValue | |
last = lastLeaf(node) | |
if arguments.length is 2 | |
if node is last then return node | |
acc = node | |
node = preFirst(node) | |
else | |
acc = fn(acc, node) | |
while node = preFirst(node) | |
acc = fn(acc, node) | |
if node is last then break | |
return acc | |
# Split a TextNode at an offset, returning the successor. | |
# https://github.com/Raynos/DOM-shim/issues/11 | |
splitText = (node, offset) -> | |
tail = node.cloneNode(false) | |
tail.deleteData(0, offset) | |
node.deleteData(offset, node.length - offset) | |
return insertAfter(tail, node) | |
# Predicate for checking if a node is a TextNode. | |
isTextNode = (node) -> | |
return node.nodeType is TEXT_NODE | |
# Return the next Node in a first-to-last-child pre-order traversal. | |
preFirst = (node) -> | |
if node.firstChild? | |
return node.firstChild | |
while not node.nextSibling? | |
node = node.parentNode | |
if node is null then return null | |
return node.nextSibling | |
# Return the next Node in a last-to-first-child pre-order traversal. | |
preLast = (node) -> | |
if node.lastChild? | |
return node.lastChild | |
while not node.previousSibling? | |
node = node.parentNode | |
if node is null then return null | |
return node.previousSibling | |
# Find the first leaf node. | |
firstLeaf = (node) -> | |
node = node.firstChild while node.hasChildNodes() | |
return node | |
# Find the last leaf node. | |
lastLeaf = (node) -> | |
node = node.lastChild while node.hasChildNodes() | |
return node | |
# Find a common ancestor Node. | |
commonAncestor = (node, other) -> | |
while node? and not contains(node, other) | |
node = node.parentNode | |
return node |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment