Bug 1354211 - Add element.findClosest for finding ancestor by CSS selector. r=automatedtester

Introduces a new function, element.findClosest, that finds the
closest parent node by a CSS selector expression.  This is useful to
find arbitrary elements in the tree above us and is quite possibly
reusable for element.getContainer.

MozReview-Commit-ID: 8rBEepmDdPm

--HG--
extra : rebase_source : 3055d23ce7aeba355de93fdeff52eb4ffdffbc24
This commit is contained in:
Andreas Tolfsen 2017-12-31 14:39:14 +00:00
Родитель 3fcc02c1df
Коммит 662639d9ba
2 изменённых файлов: 42 добавлений и 0 удалений

Просмотреть файл

@ -655,6 +655,30 @@ function findElements(strategy, selector, document, startNode = undefined) {
}
}
/**
* Finds the closest parent node of <var>startNode</var> by CSS a
* <var>selector</var> expression.
*
* @param {Node} startNode
* Cyce through <var>startNode</var>'s parent nodes in tree-order
* and return the first match to <var>selector</var>.
* @param {string} selector
* CSS selector expression.
*
* @return {Node=}
* First match to <var>selector</var>, or null if no match was found.
*/
element.findClosest = function(startNode, selector) {
let node = startNode;
while (node.parentNode && node.parentNode.nodeType == ELEMENT_NODE) {
node = node.parentNode;
if (node.matches(selector)) {
return node;
}
}
return null;
};
/**
* Determines if <var>obj<var> is an HTML or JS collection.
*

Просмотреть файл

@ -31,6 +31,13 @@ class Element {
get nodeType() { return 1; }
get ELEMENT_NODE() { return 1; }
// this is a severely limited CSS selector
// that only supports lists of tag names
matches(selector) {
let tags = selector.split(",");
return tags.includes(this.localName);
}
}
class DOMElement extends Element {
@ -94,6 +101,17 @@ const domFrame = new class extends WindowProxy {
get parent() { return domWin; }
};
add_test(function test_findClosest() {
equal(element.findClosest(domEl, "foo"), null);
let foo = new DOMElement("foo");
let bar = new DOMElement("bar");
bar.parentNode = foo;
equal(element.findClosest(bar, "foo"), foo);
run_next_test();
});
add_test(function test_isSelected() {
let checkbox = new DOMElement("input", {type: "checkbox"});
ok(!element.isSelected(checkbox));