function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
if ( postFilter && !postFilter[ expando ] ) {
postFilter = setMatcher( postFilter );
if ( postFinder && !postFinder[ expando ] ) {
postFinder = setMatcher( postFinder, postSelector );
return markFunction( function( seed, results, context, xml ) {
preexisting = results.length,
// Get initial elements from seed or context
elems = seed || multipleContexts(
context.nodeType ? [ context ] : context,
// Prefilter to get matcher input, preserving a map for seed-results synchronization
matcherIn = preFilter && ( seed || !selector ) ?
condense( elems, preMap, preFilter, context, xml ) :
// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
// ...intermediate processing is necessary
// ...otherwise use results directly
matcher( matcherIn, matcherOut, context, xml );
temp = condense( matcherOut, postMap );
postFilter( temp, [], context, xml );
// Un-match failing elements by moving them back to matcherIn
if ( ( elem = temp[ i ] ) ) {
matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem );
if ( postFinder || preFilter ) {
// Get the final matcherOut by condensing this intermediate into postFinder contexts
if ( ( elem = matcherOut[ i ] ) ) {
// Restore matcherIn since elem is not yet a final match
temp.push( ( matcherIn[ i ] = elem ) );
postFinder( null, ( matcherOut = [] ), temp, xml );
// Move matched elements from seed to results to keep them synchronized
if ( ( elem = matcherOut[ i ] ) &&
( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) {
seed[ temp ] = !( results[ temp ] = elem );
// Add elements to results, through postFinder if defined
matcherOut.splice( preexisting, matcherOut.length ) :
postFinder( null, results, matcherOut, xml );
push.apply( results, matcherOut );
function matcherFromTokens( tokens ) {
var checkContext, matcher, j,
leadingRelative = Expr.relative[ tokens[ 0 ].type ],
implicitRelative = leadingRelative || Expr.relative[ " " ],
i = leadingRelative ? 1 : 0,
// The foundational matcher ensures that elements are reachable from top-level context(s)
matchContext = addCombinator( function( elem ) {
return elem === checkContext;
}, implicitRelative, true ),
matchAnyContext = addCombinator( function( elem ) {
return indexOf( checkContext, elem ) > -1;
}, implicitRelative, true ),
matchers = [ function( elem, context, xml ) {
var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
( checkContext = context ).nodeType ?
matchContext( elem, context, xml ) :
matchAnyContext( elem, context, xml ) );
// Avoid hanging onto element (issue #299)
if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) {
matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches );
// Return special upon seeing a positional matcher
if ( matcher[ expando ] ) {
// Find the next relative operator (if any) for proper handling
if ( Expr.relative[ tokens[ j ].type ] ) {
i > 1 && elementMatcher( matchers ),
// If the preceding token was a descendant combinator, insert an implicit any-element `*`
.concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } )
).replace( rtrim, "$1" ),
i < j && matcherFromTokens( tokens.slice( i, j ) ),
j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),
j < len && toSelector( tokens )
matchers.push( matcher );
return elementMatcher( matchers );
function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
var bySet = setMatchers.length > 0,
byElement = elementMatchers.length > 0,
superMatcher = function( seed, context, xml, results, outermost ) {
contextBackup = outermostContext,
// We must always have either seed elements or outermost context
elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ),
// Use integer dirruns iff this is the outermost matcher
dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ),
// Support: IE 11+, Edge 17 - 18+
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
// two documents; shallow comparisons work.
// eslint-disable-next-line eqeqeq
outermostContext = context == document || context || outermost;
// Add elements passing elementMatchers directly to results
// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) {
if ( byElement && elem ) {
// Support: IE 11+, Edge 17 - 18+
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
// two documents; shallow comparisons work.
// eslint-disable-next-line eqeqeq
if ( !context && elem.ownerDocument != document ) {
while ( ( matcher = elementMatchers[ j++ ] ) ) {
if ( matcher( elem, context || document, xml ) ) {
// Track unmatched elements for set filters
// They will have gone through all possible matchers
if ( ( elem = !matcher && elem ) ) {
// Lengthen the array for every element, matched or not
// `i` is now the count of elements visited above, and adding it to `matchedCount`
// makes the latter nonnegative.
// Apply set filters to unmatched elements
// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
// equals `i`), unless we didn't visit _any_ elements in the above loop because we have
// no element matchers and no seed.
// Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
// case, which will result in a "00" `matchedCount` that differs from `i` but is also
if ( bySet && i !== matchedCount ) {
while ( ( matcher = setMatchers[ j++ ] ) ) {
matcher( unmatched, setMatched, context, xml );
// Reintegrate element matches to eliminate the need for sorting
if ( matchedCount > 0 ) {
if ( !( unmatched[ i ] || setMatched[ i ] ) ) {
setMatched[ i ] = pop.call( results );
// Discard index placeholder values to get only actual matches
setMatched = condense( setMatched );
// Add matches to results
push.apply( results, setMatched );
// Seedless set matches succeeding multiple successful matchers stipulate sorting
if ( outermost && !seed && setMatched.length > 0 &&
( matchedCount + setMatchers.length ) > 1 ) {
Sizzle.uniqueSort( results );
// Override manipulation of globals by nested matchers
outermostContext = contextBackup;
markFunction( superMatcher ) :
compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
cached = compilerCache[ selector + " " ];
// Generate a function of recursive functions that can be used to check each element
match = tokenize( selector );
cached = matcherFromTokens( match[ i ] );
if ( cached[ expando ] ) {
setMatchers.push( cached );
elementMatchers.push( cached );
// Cache the compiled function
matcherFromGroupMatchers( elementMatchers, setMatchers )
// Save selector and tokenization
cached.selector = selector;
* A low-level selection function that works with Sizzle's compiled
* @param {String|Function} selector A selector or a pre-compiled
* selector function built with Sizzle.compile
* @param {Element} context
* @param {Array} [results]
* @param {Array} [seed] A set of elements to match against
select = Sizzle.select = function( selector, context, results, seed ) {
var i, tokens, token, type, find,
compiled = typeof selector === "function" && selector,
match = !seed && tokenize( ( selector = compiled.selector || selector ) );
// Try to minimize operations if there is only one selector in the list and no seed
// (the latter of which guarantees us context)
if ( match.length === 1 ) {
// Reduce context if the leading compound selector is an ID
tokens = match[ 0 ] = match[ 0 ].slice( 0 );
if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" &&
context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {
context = ( Expr.find[ "ID" ]( token.matches[ 0 ]
.replace( runescape, funescape ), context ) || [] )[ 0 ];
// Precompiled matchers will still verify ancestry, so step up a level
context = context.parentNode;
selector = selector.slice( tokens.shift().value.length );
// Fetch a seed set for right-to-left matching
i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length;
// Abort if we hit a combinator
if ( Expr.relative[ ( type = token.type ) ] ) {
if ( ( find = Expr.find[ type ] ) ) {
// Search, expanding context for leading sibling combinators
token.matches[ 0 ].replace( runescape, funescape ),
rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) ||
// If seed is empty or no tokens remain, we can return early
selector = seed.length && toSelector( tokens );
push.apply( results, seed );
// Compile and execute a filtering function if one is not provided
// Provide `match` to avoid retokenization if we modified the selector above
( compiled || compile( selector, match ) )(
!context || rsibling.test( selector ) && testContext( context.parentNode ) || context
support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando;
// Support: Chrome 14-35+
// Always assume duplicates if they aren't passed to the comparison function
support.detectDuplicates = !!hasDuplicate;
// Initialize against the default document
// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
// Detached nodes confoundingly follow *each other*
support.sortDetached = assert( function( el ) {
// Should return 1, but returns 4 (following)
return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1;
// Prevent attribute/property "interpolation"
// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
if ( !assert( function( el ) {
el.innerHTML = "<a href='#'></a>";
return el.firstChild.getAttribute( "href" ) === "#";
addHandle( "type|href|height|width", function( elem, name, isXML ) {
return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
// Use defaultValue in place of getAttribute("value")
if ( !support.attributes || !assert( function( el ) {
el.innerHTML = "<input/>";
el.firstChild.setAttribute( "value", "" );
return el.firstChild.getAttribute( "value" ) === "";
addHandle( "value", function( elem, _name, isXML ) {
if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
return elem.defaultValue;
// Use getAttributeNode to fetch booleans when getAttribute lies
if ( !assert( function( el ) {
return el.getAttribute( "disabled" ) == null;
addHandle( booleans, function( elem, name, isXML ) {
return elem[ name ] === true ? name.toLowerCase() :
( val = elem.getAttributeNode( name ) ) && val.specified ?
jQuery.expr = Sizzle.selectors;
jQuery.expr[ ":" ] = jQuery.expr.pseudos;
jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;
jQuery.escapeSelector = Sizzle.escape;
var dir = function( elem, dir, until ) {
truncate = until !== undefined;
while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
if ( elem.nodeType === 1 ) {
if ( truncate && jQuery( elem ).is( until ) ) {