blob: 93c6ebde1361d11209faa72be08d489721bfe441 [file] [log] [blame]
Leo Repp58b9f112021-11-22 11:57:47 +01001"use strict";
2
3module.exports = CSSselect;
4
5var DomUtils = require("domutils");
6var falseFunc = require("boolbase").falseFunc;
7var compileRaw = require("./lib/compile.js");
8
9function wrapCompile(func) {
10 return function addAdapter(selector, options, context) {
11 options = options || {};
12 options.adapter = options.adapter || DomUtils;
13
14 return func(selector, options, context);
15 };
16}
17
18var compile = wrapCompile(compileRaw);
19var compileUnsafe = wrapCompile(compileRaw.compileUnsafe);
20
21function getSelectorFunc(searchFunc) {
22 return function select(query, elems, options) {
23 options = options || {};
24 options.adapter = options.adapter || DomUtils;
25
26 if (typeof query !== "function") {
27 query = compileUnsafe(query, options, elems);
28 }
29 if (query.shouldTestNextSiblings) {
30 elems = appendNextSiblings((options && options.context) || elems, options.adapter);
31 }
32 if (!Array.isArray(elems)) elems = options.adapter.getChildren(elems);
33 else elems = options.adapter.removeSubsets(elems);
34 return searchFunc(query, elems, options);
35 };
36}
37
38function getNextSiblings(elem, adapter) {
39 var siblings = adapter.getSiblings(elem);
40 if (!Array.isArray(siblings)) return [];
41 siblings = siblings.slice(0);
42 while (siblings.shift() !== elem);
43 return siblings;
44}
45
46function appendNextSiblings(elems, adapter) {
47 // Order matters because jQuery seems to check the children before the siblings
48 if (!Array.isArray(elems)) elems = [elems];
49 var newElems = elems.slice(0);
50
51 for (var i = 0, len = elems.length; i < len; i++) {
52 var nextSiblings = getNextSiblings(newElems[i], adapter);
53 newElems.push.apply(newElems, nextSiblings);
54 }
55 return newElems;
56}
57
58var selectAll = getSelectorFunc(function selectAll(query, elems, options) {
59 return query === falseFunc || !elems || elems.length === 0 ? [] : options.adapter.findAll(query, elems);
60});
61
62var selectOne = getSelectorFunc(function selectOne(query, elems, options) {
63 return query === falseFunc || !elems || elems.length === 0 ? null : options.adapter.findOne(query, elems);
64});
65
66function is(elem, query, options) {
67 options = options || {};
68 options.adapter = options.adapter || DomUtils;
69 return (typeof query === "function" ? query : compile(query, options))(elem);
70}
71
72/*
73 the exported interface
74*/
75function CSSselect(query, elems, options) {
76 return selectAll(query, elems, options);
77}
78
79CSSselect.compile = compile;
80CSSselect.filters = compileRaw.Pseudos.filters;
81CSSselect.pseudos = compileRaw.Pseudos.pseudos;
82
83CSSselect.selectAll = selectAll;
84CSSselect.selectOne = selectOne;
85
86CSSselect.is = is;
87
88//legacy methods (might be removed)
89CSSselect.parse = compile;
90CSSselect.iterate = selectAll;
91
92//hooks
93CSSselect._compileUnsafe = compileUnsafe;
94CSSselect._compileToken = compileRaw.compileToken;