Skip to content

Commit 2d7a0e9

Browse files
committed
tech(core dom): querySelectorAllAndMe - Support multiple root nodes.
querySelectorAllAndMe supports now multiple root nodes. All of them are searched for a selector match.
1 parent e096ed0 commit 2d7a0e9

File tree

2 files changed

+59
-10
lines changed

2 files changed

+59
-10
lines changed

src/core/dom.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,21 @@ const to_element_array = (nodes) => {
7070
* Like querySelectorAll but including the element where it starts from.
7171
* Returns an Array, not a NodeList
7272
*
73-
* @param {Node} el - The DOM node to start the search from.
73+
* @param {Element|NodeList|Array} el - The DOM element, NodeList or array of elements to start the search from.
7474
*
75-
* @returns {Array} - The DOM nodes found.
75+
* @returns {Array} - The DOM elements found.
7676
*/
7777
const querySelectorAllAndMe = (el, selector) => {
78-
if (!el || !el.querySelectorAll) {
79-
return [];
80-
}
81-
82-
const all = [...el.querySelectorAll(selector)];
83-
if (el.matches(selector)) {
84-
all.unshift(el); // start element should be first.
78+
// Ensure we have a list of DOM elements.
79+
const roots = to_element_array(el);
80+
const all = [];
81+
for (const root of roots) {
82+
all.push(...root.querySelectorAll(selector));
83+
if (root.matches(selector)) {
84+
all.unshift(root); // root element should be first.
85+
}
8586
}
86-
return all;
87+
return [... new Set(all)];
8788
};
8889

8990
/**

src/core/dom.test.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,54 @@ describe("core.dom tests", () => {
272272
done();
273273
});
274274

275+
it("Support multiple root nodes", (done) => {
276+
const el1 = document.createElement("div");
277+
el1.className = "el1";
278+
const el2 = document.createElement("span");
279+
el2.className = "el2";
280+
const el3 = document.createElement("div");
281+
el3.className = "el3";
282+
283+
const ret = dom.querySelectorAllAndMe([el1, el2, el3], "div");
284+
const ids = ret.map(el => el.className).sort().join(" ");
285+
286+
expect(ret.length).toBe(2);
287+
expect(ids).toBe("el1 el3");
288+
289+
done();
290+
});
291+
292+
it("Support nesting", (done) => {
293+
const el1 = document.createElement("div");
294+
el1.className = "el1";
295+
el1.innerHTML = '<div class="el11"></div>';
296+
const el2 = document.createElement("span");
297+
el2.className = "el2";
298+
const el3 = document.createElement("div");
299+
el3.className = "el3";
300+
301+
const ret = dom.querySelectorAllAndMe([el1, el2, el3], "div");
302+
const ids = ret.map(el => el.className).sort().join(" ");
303+
304+
expect(ret.length).toBe(3);
305+
expect(ids).toBe("el1 el11 el3");
306+
307+
done();
308+
});
309+
310+
it("Does not return the same element twice", (done) => {
311+
const el1 = document.createElement("div");
312+
el1.className = "el1";
313+
314+
const ret = dom.querySelectorAllAndMe([el1, el1, el1], "div");
315+
const ids = ret.map(el => el.className).sort().join(" ");
316+
317+
expect(ret.length).toBe(1);
318+
expect(ids).toBe("el1");
319+
320+
done();
321+
});
322+
275323
it("return empty list, if no element is passed.", (done) => {
276324
const res = dom.querySelectorAllAndMe();
277325
expect(Array.isArray(res)).toBe(true);

0 commit comments

Comments
 (0)