Skip to content

Instantly share code, notes, and snippets.

@Phoenix35
Last active March 20, 2021 03:02
Show Gist options
  • Save Phoenix35/1c7207234ed7ae6b43d517393926521b to your computer and use it in GitHub Desktop.
Save Phoenix35/1c7207234ed7ae6b43d517393926521b to your computer and use it in GitHub Desktop.
Finds the common ancestor of nodes in a document. Useful for event delegation for example.
/**
* greatestCommonAncestor - Finds the common ancestor of nodes in a document.
* The nodes MUST belong to the same document(fragment).
* @param {...Node} nodes - The nodes whose common ancestor is sought.
* @returns {Node} - The common ancestor to all nodes given as arguments.
*/
export function greatestCommonAncestor () {
return Array.prototype.reduce.call(
arguments, // partial application `?` when? :(
(ancestor, node) => {
if (node === ancestor)
return ancestor;
let mask = node.compareDocumentPosition(ancestor);
// The current node contains the ancestor
if (mask & Node.DOCUMENT_POSITION_CONTAINED_BY)
return node;
// The ancestor contains the current node?
while ((mask & Node.DOCUMENT_POSITION_CONTAINS) === 0) {
// No: We find the closest parent of the ancestor that does
ancestor = ancestor.parentNode;
mask = node.compareDocumentPosition(ancestor);
}
return ancestor;
}
);
}
// Use
const parent = greatestCommonAncestor(input1, input2, input3);
parent.addEventListener("click", (evt) => {
switch (evt.target) {
case input1:
...
}
}, false);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment