nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
// or :nth-last-child(...) or :nth(-last)?-of-type(...)
// Use the same loop as above to seek `elem` from the start
while ( ( node = ++nodeIndex && node && node[ dir ] ||
( diff = nodeIndex = 0 ) || start.pop() ) ) {
node.nodeName.toLowerCase() === name :
// Cache the index of each encountered element
outerCache = node[ expando ] ||
( node[ expando ] = {} );
// Defend against cloned attroperties (jQuery gh-1709)
uniqueCache = outerCache[ node.uniqueID ] ||
( outerCache[ node.uniqueID ] = {} );
uniqueCache[ type ] = [ dirruns, diff ];
// Incorporate the offset, then check against cycle size
return diff === first || ( diff % first === 0 && diff / first >= 0 );
"PSEUDO": function( pseudo, argument ) {
// pseudo-class names are case-insensitive
// http://www.w3.org/TR/selectors/#pseudo-classes
// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
// Remember that setFilters inherits from pseudos
fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
Sizzle.error( "unsupported pseudo: " + pseudo );
// The user may use createPseudo to indicate that
// arguments are needed to create the filter function
// But maintain support for old signatures
args = [ pseudo, pseudo, "", argument ];
return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
markFunction( function( seed, matches ) {
matched = fn( seed, argument ),
idx = indexOf( seed, matched[ i ] );
seed[ idx ] = !( matches[ idx ] = matched[ i ] );
return fn( elem, 0, args );
// Potentially complex pseudos
"not": markFunction( function( selector ) {
// Trim the selector passed to compile
// to avoid treating leading and trailing
matcher = compile( selector.replace( rtrim, "$1" ) );
return matcher[ expando ] ?
markFunction( function( seed, matches, _context, xml ) {
unmatched = matcher( seed, null, xml, [] ),
// Match elements unmatched by `matcher`
if ( ( elem = unmatched[ i ] ) ) {
seed[ i ] = !( matches[ i ] = elem );
function( elem, _context, xml ) {
matcher( input, null, xml, results );
// Don't keep the element (issue #299)
"has": markFunction( function( selector ) {
return function( elem ) {
return Sizzle( selector, elem ).length > 0;
"contains": markFunction( function( text ) {
text = text.replace( runescape, funescape );
return function( elem ) {
return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1;
// "Whether an element is represented by a :lang() selector
// is based solely on the element's language value
// being equal to the identifier C,
// or beginning with the identifier C immediately followed by "-".
// The matching of C against the element's language value is performed case-insensitively.
// The identifier C does not have to be a valid language name."
// http://www.w3.org/TR/selectors/#lang-pseudo
"lang": markFunction( function( lang ) {
// lang value must be a valid identifier
if ( !ridentifier.test( lang || "" ) ) {
Sizzle.error( "unsupported lang: " + lang );
lang = lang.replace( runescape, funescape ).toLowerCase();
return function( elem ) {
if ( ( elemLang = documentIsHTML ?
elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) {
elemLang = elemLang.toLowerCase();
return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
} while ( ( elem = elem.parentNode ) && elem.nodeType === 1 );
"target": function( elem ) {
var hash = window.location && window.location.hash;
return hash && hash.slice( 1 ) === elem.id;
"root": function( elem ) {
"focus": function( elem ) {
return elem === document.activeElement &&
( !document.hasFocus || document.hasFocus() ) &&
!!( elem.type || elem.href || ~elem.tabIndex );
"enabled": createDisabledPseudo( false ),
"disabled": createDisabledPseudo( true ),
"checked": function( elem ) {
// In CSS3, :checked should return both checked and selected elements
// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
var nodeName = elem.nodeName.toLowerCase();
return ( nodeName === "input" && !!elem.checked ) ||
( nodeName === "option" && !!elem.selected );
"selected": function( elem ) {
// Accessing this property makes selected-by-default
// options in Safari work properly
// eslint-disable-next-line no-unused-expressions
elem.parentNode.selectedIndex;
return elem.selected === true;
"empty": function( elem ) {
// http://www.w3.org/TR/selectors/#empty-pseudo
// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
// but not by others (comment: 8; processing instruction: 7; etc.)
// nodeType < 6 works because attributes (2) do not appear as children
for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
if ( elem.nodeType < 6 ) {
"parent": function( elem ) {
return !Expr.pseudos[ "empty" ]( elem );
"header": function( elem ) {
return rheader.test( elem.nodeName );
"input": function( elem ) {
return rinputs.test( elem.nodeName );
"button": function( elem ) {
var name = elem.nodeName.toLowerCase();
return name === "input" && elem.type === "button" || name === "button";
"text": function( elem ) {
return elem.nodeName.toLowerCase() === "input" &&
// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
( ( attr = elem.getAttribute( "type" ) ) == null ||
attr.toLowerCase() === "text" );
// Position-in-collection
"first": createPositionalPseudo( function() {
"last": createPositionalPseudo( function( _matchIndexes, length ) {
"eq": createPositionalPseudo( function( _matchIndexes, length, argument ) {
return [ argument < 0 ? argument + length : argument ];
"even": createPositionalPseudo( function( matchIndexes, length ) {
for ( ; i < length; i += 2 ) {
"odd": createPositionalPseudo( function( matchIndexes, length ) {
for ( ; i < length; i += 2 ) {
"lt": createPositionalPseudo( function( matchIndexes, length, argument ) {
"gt": createPositionalPseudo( function( matchIndexes, length, argument ) {
var i = argument < 0 ? argument + length : argument;
for ( ; ++i < length; ) {
Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ];
// Add button/input type pseudos
for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
Expr.pseudos[ i ] = createInputPseudo( i );
for ( i in { submit: true, reset: true } ) {
Expr.pseudos[ i ] = createButtonPseudo( i );
// Easy API for creating new setFilters
setFilters.prototype = Expr.filters = Expr.pseudos;
Expr.setFilters = new setFilters();
tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
var matched, match, tokens, type,
soFar, groups, preFilters,
cached = tokenCache[ selector + " " ];
return parseOnly ? 0 : cached.slice( 0 );
preFilters = Expr.preFilter;
if ( !matched || ( match = rcomma.exec( soFar ) ) ) {
// Don't consume trailing commas as valid
soFar = soFar.slice( match[ 0 ].length ) || soFar;
groups.push( ( tokens = [] ) );
if ( ( match = rcombinators.exec( soFar ) ) ) {
// Cast descendant combinators to space
type: match[ 0 ].replace( rtrim, " " )
soFar = soFar.slice( matched.length );
for ( type in Expr.filter ) {
if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] ||
( match = preFilters[ type ]( match ) ) ) ) {
soFar = soFar.slice( matched.length );
// Return the length of the invalid excess
// Otherwise, throw an error or return tokens
Sizzle.error( selector ) :
tokenCache( selector, groups ).slice( 0 );
function toSelector( tokens ) {
selector += tokens[ i ].value;
function addCombinator( matcher, combinator, base ) {
var dir = combinator.dir,
checkNonElements = base && key === "parentNode",
return combinator.first ?
// Check against closest ancestor/preceding element
function( elem, context, xml ) {
while ( ( elem = elem[ dir ] ) ) {
if ( elem.nodeType === 1 || checkNonElements ) {
return matcher( elem, context, xml );
// Check against all ancestor/preceding elements
function( elem, context, xml ) {
var oldCache, uniqueCache, outerCache,
newCache = [ dirruns, doneName ];
// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
while ( ( elem = elem[ dir ] ) ) {
if ( elem.nodeType === 1 || checkNonElements ) {
if ( matcher( elem, context, xml ) ) {
while ( ( elem = elem[ dir ] ) ) {
if ( elem.nodeType === 1 || checkNonElements ) {
outerCache = elem[ expando ] || ( elem[ expando ] = {} );
// Defend against cloned attroperties (jQuery gh-1709)
uniqueCache = outerCache[ elem.uniqueID ] ||
( outerCache[ elem.uniqueID ] = {} );
if ( skip && skip === elem.nodeName.toLowerCase() ) {
elem = elem[ dir ] || elem;
} else if ( ( oldCache = uniqueCache[ key ] ) &&
oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
// Assign to newCache so results back-propagate to previous elements
return ( newCache[ 2 ] = oldCache[ 2 ] );
// Reuse newcache so results back-propagate to previous elements
uniqueCache[ key ] = newCache;
// A match means we're done; a fail means we have to keep checking
if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) {
function elementMatcher( matchers ) {
return matchers.length > 1 ?
function( elem, context, xml ) {
if ( !matchers[ i ]( elem, context, xml ) ) {
function multipleContexts( selector, contexts, results ) {
Sizzle( selector, contexts[ i ], results );
function condense( unmatched, map, filter, context, xml ) {
if ( ( elem = unmatched[ i ] ) ) {
if ( !filter || filter( elem, context, xml ) ) {
newUnmatched.push( elem );