1 import { jQuery } from "./core.js";
2 import { nodeName } from "./core/nodeName.js";
3 import { document as preferredDoc } from "./var/document.js";
4 import { indexOf } from "./var/indexOf.js";
5 import { pop } from "./var/pop.js";
6 import { push } from "./var/push.js";
7 import { whitespace } from "./var/whitespace.js";
8 import { rbuggyQSA } from "./selector/rbuggyQSA.js";
9 import { rtrimCSS } from "./var/rtrimCSS.js";
10 import { isIE } from "./var/isIE.js";
11 import { identifier } from "./selector/var/identifier.js";
12 import { booleans } from "./selector/var/booleans.js";
13 import { rleadingCombinator } from "./selector/var/rleadingCombinator.js";
14 import { rdescend } from "./selector/var/rdescend.js";
15 import { rsibling } from "./selector/var/rsibling.js";
16 import { matches } from "./selector/var/matches.js";
17 import { createCache } from "./selector/createCache.js";
18 import { testContext } from "./selector/testContext.js";
19 import { filterMatchExpr } from "./selector/filterMatchExpr.js";
20 import { preFilter } from "./selector/preFilter.js";
21 import { selectorError } from "./selector/selectorError.js";
22 import { unescapeSelector } from "./selector/unescapeSelector.js";
23 import { tokenize } from "./selector/tokenize.js";
24 import { toSelector } from "./selector/toSelector.js";
26 // The following utils are attached directly to the jQuery object.
27 import "./selector/escapeSelector.js";
28 import "./selector/uniqueSort.js";
33 // Local document vars
38 // Instance-specific data
41 classCache = createCache(),
42 compilerCache = createCache(),
43 nonnativeSelectorCache = createCache(),
45 // Regular expressions
47 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
48 rwhitespace = new RegExp( whitespace + "+", "g" ),
50 ridentifier = new RegExp( "^" + identifier + "$" ),
52 matchExpr = jQuery.extend( {
53 bool: new RegExp( "^(?:" + booleans + ")$", "i" ),
55 // For use in libraries implementing .is()
56 // We use this for POS matching in `select`
57 needsContext: new RegExp( "^" + whitespace +
58 "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
59 "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
62 rinputs = /^(?:input|select|textarea|button)$/i,
65 // Easily-parseable/retrievable ID or TAG or CLASS selectors
66 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
68 // Used for iframes; see `setDocument`.
69 // Support: IE 9 - 11+
70 // Removing the function wrapper causes a "Permission Denied"
72 unloadHandler = function() {
76 inDisabledFieldset = addCombinator(
78 return elem.disabled === true && nodeName( elem, "fieldset" );
80 { dir: "parentNode", next: "legend" }
83 function find( selector, context, results, seed ) {
84 var m, i, elem, nid, match, groups, newSelector,
85 newContext = context && context.ownerDocument,
87 // nodeType defaults to 9, since context defaults to document
88 nodeType = context ? context.nodeType : 9;
90 results = results || [];
92 // Return early from calls with invalid selector or context
93 if ( typeof selector !== "string" || !selector ||
94 nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
99 // Try to shortcut find operations (as opposed to filters) in HTML documents
101 setDocument( context );
102 context = context || document;
104 if ( documentIsHTML ) {
106 // If the selector is sufficiently simple, try using a "get*By*" DOM method
107 // (excepting DocumentFragment context, where the methods don't exist)
108 if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) {
111 if ( ( m = match[ 1 ] ) ) {
114 if ( nodeType === 9 ) {
115 if ( ( elem = context.getElementById( m ) ) ) {
116 push.call( results, elem );
122 if ( newContext && ( elem = newContext.getElementById( m ) ) &&
123 jQuery.contains( context, elem ) ) {
125 push.call( results, elem );
131 } else if ( match[ 2 ] ) {
132 push.apply( results, context.getElementsByTagName( selector ) );
136 } else if ( ( m = match[ 3 ] ) && context.getElementsByClassName ) {
137 push.apply( results, context.getElementsByClassName( m ) );
142 // Take advantage of querySelectorAll
143 if ( !nonnativeSelectorCache[ selector + " " ] &&
144 ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) ) {
146 newSelector = selector;
147 newContext = context;
149 // qSA considers elements outside a scoping root when evaluating child or
150 // descendant combinators, which is not what we want.
151 // In such cases, we work around the behavior by prefixing every selector in the
152 // list with an ID selector referencing the scope context.
153 // The technique has to be used as well when a leading combinator is used
154 // as such selectors are not recognized by querySelectorAll.
155 // Thanks to Andrew Dupont for this technique.
156 if ( nodeType === 1 &&
157 ( rdescend.test( selector ) || rleadingCombinator.test( selector ) ) ) {
159 // Expand context for sibling selectors
160 newContext = rsibling.test( selector ) &&
161 testContext( context.parentNode ) ||
164 // Outside of IE, if we're not changing the context we can
165 // use :scope instead of an ID.
167 // IE sometimes throws a "Permission denied" error when strict-comparing
168 // two documents; shallow comparisons work.
169 // eslint-disable-next-line eqeqeq
170 if ( newContext != context || isIE ) {
172 // Capture the context ID, setting it first if necessary
173 if ( ( nid = context.getAttribute( "id" ) ) ) {
174 nid = jQuery.escapeSelector( nid );
176 context.setAttribute( "id", ( nid = jQuery.expando ) );
180 // Prefix every selector in the list
181 groups = tokenize( selector );
184 groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " +
185 toSelector( groups[ i ] );
187 newSelector = groups.join( "," );
192 newContext.querySelectorAll( newSelector )
195 } catch ( qsaError ) {
196 nonnativeSelectorCache( selector, true );
198 if ( nid === jQuery.expando ) {
199 context.removeAttribute( "id" );
207 return select( selector.replace( rtrimCSS, "$1" ), context, results, seed );
211 * Mark a function for special use by jQuery selector module
212 * @param {Function} fn The function to mark
214 function markFunction( fn ) {
215 fn[ jQuery.expando ] = true;
220 * Returns a function to use in pseudos for input types
221 * @param {String} type
223 function createInputPseudo( type ) {
224 return function( elem ) {
225 return nodeName( elem, "input" ) && elem.type === type;
230 * Returns a function to use in pseudos for buttons
231 * @param {String} type
233 function createButtonPseudo( type ) {
234 return function( elem ) {
235 return ( nodeName( elem, "input" ) || nodeName( elem, "button" ) ) &&
241 * Returns a function to use in pseudos for :enabled/:disabled
242 * @param {Boolean} disabled true for :disabled; false for :enabled
244 function createDisabledPseudo( disabled ) {
246 // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
247 return function( elem ) {
249 // Only certain elements can match :enabled or :disabled
250 // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
251 // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
252 if ( "form" in elem ) {
254 // Check for inherited disabledness on relevant non-disabled elements:
255 // * listed form-associated elements in a disabled fieldset
256 // https://html.spec.whatwg.org/multipage/forms.html#category-listed
257 // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
258 // * option elements in a disabled optgroup
259 // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
260 // All such elements have a "form" property.
261 if ( elem.parentNode && elem.disabled === false ) {
263 // Option elements defer to a parent optgroup if present
264 if ( "label" in elem ) {
265 if ( "label" in elem.parentNode ) {
266 return elem.parentNode.disabled === disabled;
268 return elem.disabled === disabled;
272 // Support: IE 6 - 11+
273 // Use the isDisabled shortcut property to check for disabled fieldset ancestors
274 return elem.isDisabled === disabled ||
276 // Where there is no isDisabled, check manually
277 elem.isDisabled !== !disabled &&
278 inDisabledFieldset( elem ) === disabled;
281 return elem.disabled === disabled;
283 // Try to winnow out elements that can't be disabled before trusting the disabled property.
284 // Some victims get caught in our net (label, legend, menu, track), but it shouldn't
285 // even exist on them, let alone have a boolean value.
286 } else if ( "label" in elem ) {
287 return elem.disabled === disabled;
290 // Remaining elements are neither :enabled nor :disabled
296 * Returns a function to use in pseudos for positionals
297 * @param {Function} fn
299 function createPositionalPseudo( fn ) {
300 return markFunction( function( argument ) {
301 argument = +argument;
302 return markFunction( function( seed, matches ) {
304 matchIndexes = fn( [], seed.length, argument ),
305 i = matchIndexes.length;
307 // Match elements found at the specified indexes
309 if ( seed[ ( j = matchIndexes[ i ] ) ] ) {
310 seed[ j ] = !( matches[ j ] = seed[ j ] );
318 * Sets document-related variables once based on the current document
319 * @param {Element|Object} [node] An element or document object to use to set the document
321 function setDocument( node ) {
323 doc = node ? node.ownerDocument || node : preferredDoc;
325 // Return early if doc is invalid or already selected
327 // IE sometimes throws a "Permission denied" error when strict-comparing
328 // two documents; shallow comparisons work.
329 // eslint-disable-next-line eqeqeq
330 if ( doc == document || doc.nodeType !== 9 ) {
334 // Update global variables
336 documentElement = document.documentElement;
337 documentIsHTML = !jQuery.isXMLDoc( document );
339 // Support: IE 9 - 11+
340 // Accessing iframe documents after unload throws "permission denied" errors (see trac-13936)
342 // IE sometimes throws a "Permission denied" error when strict-comparing
343 // two documents; shallow comparisons work.
344 // eslint-disable-next-line eqeqeq
345 if ( isIE && preferredDoc != document &&
346 ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) {
347 subWindow.addEventListener( "unload", unloadHandler );
351 find.matches = function( expr, elements ) {
352 return find( expr, null, null, elements );
355 find.matchesSelector = function( elem, expr ) {
358 if ( documentIsHTML &&
359 !nonnativeSelectorCache[ expr + " " ] &&
360 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
363 return matches.call( elem, expr );
365 nonnativeSelectorCache( expr, true );
369 return find( expr, document, null, [ elem ] ).length > 0;
374 // Can be adjusted by the user
377 createPseudo: markFunction,
382 ID: function( id, context ) {
383 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
384 var elem = context.getElementById( id );
385 return elem ? [ elem ] : [];
389 TAG: function( tag, context ) {
390 if ( typeof context.getElementsByTagName !== "undefined" ) {
391 return context.getElementsByTagName( tag );
393 // DocumentFragment nodes don't have gEBTN
395 return context.querySelectorAll( tag );
399 CLASS: function( className, context ) {
400 if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
401 return context.getElementsByClassName( className );
407 ">": { dir: "parentNode", first: true },
408 " ": { dir: "parentNode" },
409 "+": { dir: "previousSibling", first: true },
410 "~": { dir: "previousSibling" }
413 preFilter: preFilter,
417 var attrId = unescapeSelector( id );
418 return function( elem ) {
419 return elem.getAttribute( "id" ) === attrId;
423 TAG: function( nodeNameSelector ) {
424 var expectedNodeName = unescapeSelector( nodeNameSelector ).toLowerCase();
425 return nodeNameSelector === "*" ?
432 return nodeName( elem, expectedNodeName );
436 CLASS: function( className ) {
437 var pattern = classCache[ className + " " ];
440 ( pattern = new RegExp( "(^|" + whitespace + ")" + className +
441 "(" + whitespace + "|$)" ) ) &&
442 classCache( className, function( elem ) {
444 typeof elem.className === "string" && elem.className ||
445 typeof elem.getAttribute !== "undefined" &&
446 elem.getAttribute( "class" ) ||
452 ATTR: function( name, operator, check ) {
453 return function( elem ) {
454 var result = jQuery.attr( elem, name );
456 if ( result == null ) {
457 return operator === "!=";
465 if ( operator === "=" ) {
466 return result === check;
468 if ( operator === "!=" ) {
469 return result !== check;
471 if ( operator === "^=" ) {
472 return check && result.indexOf( check ) === 0;
474 if ( operator === "*=" ) {
475 return check && result.indexOf( check ) > -1;
477 if ( operator === "$=" ) {
478 return check && result.slice( -check.length ) === check;
480 if ( operator === "~=" ) {
481 return ( " " + result.replace( rwhitespace, " " ) + " " )
482 .indexOf( check ) > -1;
484 if ( operator === "|=" ) {
485 return result === check || result.slice( 0, check.length + 1 ) === check + "-";
492 CHILD: function( type, what, _argument, first, last ) {
493 var simple = type.slice( 0, 3 ) !== "nth",
494 forward = type.slice( -4 ) !== "last",
495 ofType = what === "of-type";
497 return first === 1 && last === 0 ?
499 // Shortcut for :nth-*(n)
501 return !!elem.parentNode;
504 function( elem, _context, xml ) {
505 var cache, outerCache, node, nodeIndex, start,
506 dir = simple !== forward ? "nextSibling" : "previousSibling",
507 parent = elem.parentNode,
508 name = ofType && elem.nodeName.toLowerCase(),
509 useCache = !xml && !ofType,
514 // :(first|last|only)-(child|of-type)
518 while ( ( node = node[ dir ] ) ) {
520 nodeName( node, name ) :
521 node.nodeType === 1 ) {
527 // Reverse direction for :only-* (if we haven't yet done so)
528 start = dir = type === "only" && !start && "nextSibling";
533 start = [ forward ? parent.firstChild : parent.lastChild ];
535 // non-xml :nth-child(...) stores cache data on `parent`
536 if ( forward && useCache ) {
538 // Seek `elem` from a previously-cached index
539 outerCache = parent[ jQuery.expando ] ||
540 ( parent[ jQuery.expando ] = {} );
541 cache = outerCache[ type ] || [];
542 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
543 diff = nodeIndex && cache[ 2 ];
544 node = nodeIndex && parent.childNodes[ nodeIndex ];
546 while ( ( node = ++nodeIndex && node && node[ dir ] ||
548 // Fallback to seeking `elem` from the start
549 ( diff = nodeIndex = 0 ) || start.pop() ) ) {
551 // When found, cache indexes on `parent` and break
552 if ( node.nodeType === 1 && ++diff && node === elem ) {
553 outerCache[ type ] = [ dirruns, nodeIndex, diff ];
560 // Use previously-cached element index if available
562 outerCache = elem[ jQuery.expando ] ||
563 ( elem[ jQuery.expando ] = {} );
564 cache = outerCache[ type ] || [];
565 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
569 // xml :nth-child(...)
570 // or :nth-last-child(...) or :nth(-last)?-of-type(...)
571 if ( diff === false ) {
573 // Use the same loop as above to seek `elem` from the start
574 while ( ( node = ++nodeIndex && node && node[ dir ] ||
575 ( diff = nodeIndex = 0 ) || start.pop() ) ) {
578 nodeName( node, name ) :
579 node.nodeType === 1 ) &&
582 // Cache the index of each encountered element
584 outerCache = node[ jQuery.expando ] ||
585 ( node[ jQuery.expando ] = {} );
586 outerCache[ type ] = [ dirruns, diff ];
589 if ( node === elem ) {
597 // Incorporate the offset, then check against cycle size
599 return diff === first || ( diff % first === 0 && diff / first >= 0 );
604 PSEUDO: function( pseudo, argument ) {
606 // pseudo-class names are case-insensitive
607 // https://www.w3.org/TR/selectors/#pseudo-classes
608 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
609 // Remember that setFilters inherits from pseudos
610 var fn = jQuery.expr.pseudos[ pseudo ] ||
611 jQuery.expr.setFilters[ pseudo.toLowerCase() ] ||
612 selectorError( "unsupported pseudo: " + pseudo );
614 // The user may use createPseudo to indicate that
615 // arguments are needed to create the filter function
616 // just as jQuery does
617 if ( fn[ jQuery.expando ] ) {
618 return fn( argument );
627 // Potentially complex pseudos
628 not: markFunction( function( selector ) {
630 // Trim the selector passed to compile
631 // to avoid treating leading and trailing
632 // spaces as combinators
635 matcher = compile( selector.replace( rtrimCSS, "$1" ) );
637 return matcher[ jQuery.expando ] ?
638 markFunction( function( seed, matches, _context, xml ) {
640 unmatched = matcher( seed, null, xml, [] ),
643 // Match elements unmatched by `matcher`
645 if ( ( elem = unmatched[ i ] ) ) {
646 seed[ i ] = !( matches[ i ] = elem );
650 function( elem, _context, xml ) {
652 matcher( input, null, xml, results );
654 // Don't keep the element
655 // (see https://github.com/jquery/sizzle/issues/299)
657 return !results.pop();
661 has: markFunction( function( selector ) {
662 return function( elem ) {
663 return find( selector, elem ).length > 0;
667 contains: markFunction( function( text ) {
668 text = unescapeSelector( text );
669 return function( elem ) {
670 return ( elem.textContent || jQuery.text( elem ) ).indexOf( text ) > -1;
674 // "Whether an element is represented by a :lang() selector
675 // is based solely on the element's language value
676 // being equal to the identifier C,
677 // or beginning with the identifier C immediately followed by "-".
678 // The matching of C against the element's language value is performed case-insensitively.
679 // The identifier C does not have to be a valid language name."
680 // https://www.w3.org/TR/selectors/#lang-pseudo
681 lang: markFunction( function( lang ) {
683 // lang value must be a valid identifier
684 if ( !ridentifier.test( lang || "" ) ) {
685 selectorError( "unsupported lang: " + lang );
687 lang = unescapeSelector( lang ).toLowerCase();
688 return function( elem ) {
691 if ( ( elemLang = documentIsHTML ?
693 elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) {
695 elemLang = elemLang.toLowerCase();
696 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
698 } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 );
704 target: function( elem ) {
705 var hash = window.location && window.location.hash;
706 return hash && hash.slice( 1 ) === elem.id;
709 root: function( elem ) {
710 return elem === documentElement;
713 focus: function( elem ) {
714 return elem === document.activeElement &&
715 document.hasFocus() &&
716 !!( elem.type || elem.href || ~elem.tabIndex );
719 // Boolean properties
720 enabled: createDisabledPseudo( false ),
721 disabled: createDisabledPseudo( true ),
723 checked: function( elem ) {
725 // In CSS3, :checked should return both checked and selected elements
726 // https://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
727 return ( nodeName( elem, "input" ) && !!elem.checked ) ||
728 ( nodeName( elem, "option" ) && !!elem.selected );
731 selected: function( elem ) {
734 // Accessing the selectedIndex property
735 // forces the browser to treat the default option as
736 // selected when in an optgroup.
737 if ( isIE && elem.parentNode ) {
738 // eslint-disable-next-line no-unused-expressions
739 elem.parentNode.selectedIndex;
742 return elem.selected === true;
746 empty: function( elem ) {
748 // https://www.w3.org/TR/selectors/#empty-pseudo
749 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
750 // but not by others (comment: 8; processing instruction: 7; etc.)
751 // nodeType < 6 works because attributes (2) do not appear as children
752 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
753 if ( elem.nodeType < 6 ) {
760 parent: function( elem ) {
761 return !jQuery.expr.pseudos.empty( elem );
764 // Element/input types
765 header: function( elem ) {
766 return rheader.test( elem.nodeName );
769 input: function( elem ) {
770 return rinputs.test( elem.nodeName );
773 button: function( elem ) {
774 return nodeName( elem, "input" ) && elem.type === "button" ||
775 nodeName( elem, "button" );
778 text: function( elem ) {
779 return nodeName( elem, "input" ) && elem.type === "text";
782 // Position-in-collection
783 first: createPositionalPseudo( function() {
787 last: createPositionalPseudo( function( _matchIndexes, length ) {
788 return [ length - 1 ];
791 eq: createPositionalPseudo( function( _matchIndexes, length, argument ) {
792 return [ argument < 0 ? argument + length : argument ];
795 even: createPositionalPseudo( function( matchIndexes, length ) {
797 for ( ; i < length; i += 2 ) {
798 matchIndexes.push( i );
803 odd: createPositionalPseudo( function( matchIndexes, length ) {
805 for ( ; i < length; i += 2 ) {
806 matchIndexes.push( i );
811 lt: createPositionalPseudo( function( matchIndexes, length, argument ) {
814 if ( argument < 0 ) {
815 i = argument + length;
816 } else if ( argument > length ) {
822 for ( ; --i >= 0; ) {
823 matchIndexes.push( i );
828 gt: createPositionalPseudo( function( matchIndexes, length, argument ) {
829 var i = argument < 0 ? argument + length : argument;
830 for ( ; ++i < length; ) {
831 matchIndexes.push( i );
838 jQuery.expr.pseudos.nth = jQuery.expr.pseudos.eq;
840 // Add button/input type pseudos
841 for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
842 jQuery.expr.pseudos[ i ] = createInputPseudo( i );
844 for ( i in { submit: true, reset: true } ) {
845 jQuery.expr.pseudos[ i ] = createButtonPseudo( i );
848 // Easy API for creating new setFilters
849 function setFilters() {}
850 setFilters.prototype = jQuery.expr.filters = jQuery.expr.pseudos;
851 jQuery.expr.setFilters = new setFilters();
853 function addCombinator( matcher, combinator, base ) {
854 var dir = combinator.dir,
855 skip = combinator.next,
857 checkNonElements = base && key === "parentNode",
860 return combinator.first ?
862 // Check against closest ancestor/preceding element
863 function( elem, context, xml ) {
864 while ( ( elem = elem[ dir ] ) ) {
865 if ( elem.nodeType === 1 || checkNonElements ) {
866 return matcher( elem, context, xml );
872 // Check against all ancestor/preceding elements
873 function( elem, context, xml ) {
874 var oldCache, outerCache,
875 newCache = [ dirruns, doneName ];
877 // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
879 while ( ( elem = elem[ dir ] ) ) {
880 if ( elem.nodeType === 1 || checkNonElements ) {
881 if ( matcher( elem, context, xml ) ) {
887 while ( ( elem = elem[ dir ] ) ) {
888 if ( elem.nodeType === 1 || checkNonElements ) {
889 outerCache = elem[ jQuery.expando ] || ( elem[ jQuery.expando ] = {} );
891 if ( skip && nodeName( elem, skip ) ) {
892 elem = elem[ dir ] || elem;
893 } else if ( ( oldCache = outerCache[ key ] ) &&
894 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
896 // Assign to newCache so results back-propagate to previous elements
897 return ( newCache[ 2 ] = oldCache[ 2 ] );
900 // Reuse newcache so results back-propagate to previous elements
901 outerCache[ key ] = newCache;
903 // A match means we're done; a fail means we have to keep checking
904 if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) {
915 function elementMatcher( matchers ) {
916 return matchers.length > 1 ?
917 function( elem, context, xml ) {
918 var i = matchers.length;
920 if ( !matchers[ i ]( elem, context, xml ) ) {
929 function multipleContexts( selector, contexts, results ) {
931 len = contexts.length;
932 for ( ; i < len; i++ ) {
933 find( selector, contexts[ i ], results );
938 function condense( unmatched, map, filter, context, xml ) {
942 len = unmatched.length,
943 mapped = map != null;
945 for ( ; i < len; i++ ) {
946 if ( ( elem = unmatched[ i ] ) ) {
947 if ( !filter || filter( elem, context, xml ) ) {
948 newUnmatched.push( elem );
959 function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
960 if ( postFilter && !postFilter[ jQuery.expando ] ) {
961 postFilter = setMatcher( postFilter );
963 if ( postFinder && !postFinder[ jQuery.expando ] ) {
964 postFinder = setMatcher( postFinder, postSelector );
966 return markFunction( function( seed, results, context, xml ) {
967 var temp, i, elem, matcherOut,
970 preexisting = results.length,
972 // Get initial elements from seed or context
974 multipleContexts( selector || "*",
975 context.nodeType ? [ context ] : context, [] ),
977 // Prefilter to get matcher input, preserving a map for seed-results synchronization
978 matcherIn = preFilter && ( seed || !selector ) ?
979 condense( elems, preMap, preFilter, context, xml ) :
984 // If we have a postFinder, or filtered seed, or non-seed postFilter
985 // or preexisting results,
986 matcherOut = postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
988 // ...intermediate processing is necessary
991 // ...otherwise use results directly
994 // Find primary matches
995 matcher( matcherIn, matcherOut, context, xml );
997 matcherOut = matcherIn;
1002 temp = condense( matcherOut, postMap );
1003 postFilter( temp, [], context, xml );
1005 // Un-match failing elements by moving them back to matcherIn
1008 if ( ( elem = temp[ i ] ) ) {
1009 matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem );
1015 if ( postFinder || preFilter ) {
1018 // Get the final matcherOut by condensing this intermediate into postFinder contexts
1020 i = matcherOut.length;
1022 if ( ( elem = matcherOut[ i ] ) ) {
1024 // Restore matcherIn since elem is not yet a final match
1025 temp.push( ( matcherIn[ i ] = elem ) );
1028 postFinder( null, ( matcherOut = [] ), temp, xml );
1031 // Move matched elements from seed to results to keep them synchronized
1032 i = matcherOut.length;
1034 if ( ( elem = matcherOut[ i ] ) &&
1035 ( temp = postFinder ? indexOf.call( seed, elem ) : preMap[ i ] ) > -1 ) {
1037 seed[ temp ] = !( results[ temp ] = elem );
1042 // Add elements to results, through postFinder if defined
1044 matcherOut = condense(
1045 matcherOut === results ?
1046 matcherOut.splice( preexisting, matcherOut.length ) :
1050 postFinder( null, results, matcherOut, xml );
1052 push.apply( results, matcherOut );
1058 function matcherFromTokens( tokens ) {
1059 var checkContext, matcher, j,
1060 len = tokens.length,
1061 leadingRelative = jQuery.expr.relative[ tokens[ 0 ].type ],
1062 implicitRelative = leadingRelative || jQuery.expr.relative[ " " ],
1063 i = leadingRelative ? 1 : 0,
1065 // The foundational matcher ensures that elements are reachable from top-level context(s)
1066 matchContext = addCombinator( function( elem ) {
1067 return elem === checkContext;
1068 }, implicitRelative, true ),
1069 matchAnyContext = addCombinator( function( elem ) {
1070 return indexOf.call( checkContext, elem ) > -1;
1071 }, implicitRelative, true ),
1072 matchers = [ function( elem, context, xml ) {
1075 // IE sometimes throws a "Permission denied" error when strict-comparing
1076 // two documents; shallow comparisons work.
1077 // eslint-disable-next-line eqeqeq
1078 var ret = ( !leadingRelative && ( xml || context != outermostContext ) ) || (
1079 ( checkContext = context ).nodeType ?
1080 matchContext( elem, context, xml ) :
1081 matchAnyContext( elem, context, xml ) );
1083 // Avoid hanging onto element
1084 // (see https://github.com/jquery/sizzle/issues/299)
1085 checkContext = null;
1089 for ( ; i < len; i++ ) {
1090 if ( ( matcher = jQuery.expr.relative[ tokens[ i ].type ] ) ) {
1091 matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
1093 matcher = jQuery.expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches );
1095 // Return special upon seeing a positional matcher
1096 if ( matcher[ jQuery.expando ] ) {
1098 // Find the next relative operator (if any) for proper handling
1100 for ( ; j < len; j++ ) {
1101 if ( jQuery.expr.relative[ tokens[ j ].type ] ) {
1106 i > 1 && elementMatcher( matchers ),
1107 i > 1 && toSelector(
1109 // If the preceding token was a descendant combinator, insert an implicit any-element `*`
1110 tokens.slice( 0, i - 1 )
1111 .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } )
1112 ).replace( rtrimCSS, "$1" ),
1114 i < j && matcherFromTokens( tokens.slice( i, j ) ),
1115 j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),
1116 j < len && toSelector( tokens )
1119 matchers.push( matcher );
1123 return elementMatcher( matchers );
1126 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
1127 var bySet = setMatchers.length > 0,
1128 byElement = elementMatchers.length > 0,
1129 superMatcher = function( seed, context, xml, results, outermost ) {
1130 var elem, j, matcher,
1133 unmatched = seed && [],
1135 contextBackup = outermostContext,
1137 // We must always have either seed elements or outermost context
1138 elems = seed || byElement && jQuery.expr.find.TAG( "*", outermost ),
1140 // Use integer dirruns iff this is the outermost matcher
1141 dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 );
1146 // IE sometimes throws a "Permission denied" error when strict-comparing
1147 // two documents; shallow comparisons work.
1148 // eslint-disable-next-line eqeqeq
1149 outermostContext = context == document || context || outermost;
1152 // Add elements passing elementMatchers directly to results
1153 for ( ; ( elem = elems[ i ] ) != null; i++ ) {
1154 if ( byElement && elem ) {
1158 // IE sometimes throws a "Permission denied" error when strict-comparing
1159 // two documents; shallow comparisons work.
1160 // eslint-disable-next-line eqeqeq
1161 if ( !context && elem.ownerDocument != document ) {
1162 setDocument( elem );
1163 xml = !documentIsHTML;
1165 while ( ( matcher = elementMatchers[ j++ ] ) ) {
1166 if ( matcher( elem, context || document, xml ) ) {
1167 push.call( results, elem );
1172 dirruns = dirrunsUnique;
1176 // Track unmatched elements for set filters
1179 // They will have gone through all possible matchers
1180 if ( ( elem = !matcher && elem ) ) {
1184 // Lengthen the array for every element, matched or not
1186 unmatched.push( elem );
1191 // `i` is now the count of elements visited above, and adding it to `matchedCount`
1192 // makes the latter nonnegative.
1195 // Apply set filters to unmatched elements
1196 // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
1197 // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
1198 // no element matchers and no seed.
1199 // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
1200 // case, which will result in a "00" `matchedCount` that differs from `i` but is also
1201 // numerically zero.
1202 if ( bySet && i !== matchedCount ) {
1204 while ( ( matcher = setMatchers[ j++ ] ) ) {
1205 matcher( unmatched, setMatched, context, xml );
1210 // Reintegrate element matches to eliminate the need for sorting
1211 if ( matchedCount > 0 ) {
1213 if ( !( unmatched[ i ] || setMatched[ i ] ) ) {
1214 setMatched[ i ] = pop.call( results );
1219 // Discard index placeholder values to get only actual matches
1220 setMatched = condense( setMatched );
1223 // Add matches to results
1224 push.apply( results, setMatched );
1226 // Seedless set matches succeeding multiple successful matchers stipulate sorting
1227 if ( outermost && !seed && setMatched.length > 0 &&
1228 ( matchedCount + setMatchers.length ) > 1 ) {
1230 jQuery.uniqueSort( results );
1234 // Override manipulation of globals by nested matchers
1236 dirruns = dirrunsUnique;
1237 outermostContext = contextBackup;
1244 markFunction( superMatcher ) :
1248 function compile( selector, match /* Internal Use Only */ ) {
1251 elementMatchers = [],
1252 cached = compilerCache[ selector + " " ];
1256 // Generate a function of recursive functions that can be used to check each element
1258 match = tokenize( selector );
1262 cached = matcherFromTokens( match[ i ] );
1263 if ( cached[ jQuery.expando ] ) {
1264 setMatchers.push( cached );
1266 elementMatchers.push( cached );
1270 // Cache the compiled function
1271 cached = compilerCache( selector,
1272 matcherFromGroupMatchers( elementMatchers, setMatchers ) );
1274 // Save selector and tokenization
1275 cached.selector = selector;
1281 * A low-level selection function that works with jQuery's compiled
1282 * selector functions
1283 * @param {String|Function} selector A selector or a pre-compiled
1284 * selector function built with jQuery selector compile
1285 * @param {Element} context
1286 * @param {Array} [results]
1287 * @param {Array} [seed] A set of elements to match against
1289 function select( selector, context, results, seed ) {
1290 var i, tokens, token, type, find,
1291 compiled = typeof selector === "function" && selector,
1292 match = !seed && tokenize( ( selector = compiled.selector || selector ) );
1294 results = results || [];
1296 // Try to minimize operations if there is only one selector in the list and no seed
1297 // (the latter of which guarantees us context)
1298 if ( match.length === 1 ) {
1300 // Reduce context if the leading compound selector is an ID
1301 tokens = match[ 0 ] = match[ 0 ].slice( 0 );
1302 if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" &&
1303 context.nodeType === 9 && documentIsHTML &&
1304 jQuery.expr.relative[ tokens[ 1 ].type ] ) {
1306 context = ( jQuery.expr.find.ID(
1307 unescapeSelector( token.matches[ 0 ] ),
1313 // Precompiled matchers will still verify ancestry, so step up a level
1314 } else if ( compiled ) {
1315 context = context.parentNode;
1318 selector = selector.slice( tokens.shift().value.length );
1321 // Fetch a seed set for right-to-left matching
1322 i = matchExpr.needsContext.test( selector ) ? 0 : tokens.length;
1324 token = tokens[ i ];
1326 // Abort if we hit a combinator
1327 if ( jQuery.expr.relative[ ( type = token.type ) ] ) {
1330 if ( ( find = jQuery.expr.find[ type ] ) ) {
1332 // Search, expanding context for leading sibling combinators
1334 unescapeSelector( token.matches[ 0 ] ),
1335 rsibling.test( tokens[ 0 ].type ) &&
1336 testContext( context.parentNode ) || context
1339 // If seed is empty or no tokens remain, we can return early
1340 tokens.splice( i, 1 );
1341 selector = seed.length && toSelector( tokens );
1343 push.apply( results, seed );
1353 // Compile and execute a filtering function if one is not provided
1354 // Provide `match` to avoid retokenization if we modified the selector above
1355 ( compiled || compile( selector, match ) )(
1360 !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
1365 // Initialize against the default document
1370 // These have always been private, but they used to be documented as part of
1371 // Sizzle so let's maintain them for now for backwards compatibility purposes.
1372 find.compile = compile;
1373 find.select = select;
1374 find.setDocument = setDocument;
1375 find.tokenize = tokenize;
1377 export { jQuery, jQuery as $ };