Skip to content
Permalink
Newer
Older
100644 2478 lines (2057 sloc) 68.9 KB
2
* Sizzle CSS Selector Engine v@VERSION
3
* https://sizzlejs.com/
4
*
5
* Copyright JS Foundation and other contributors
6
* Released under the MIT license
7
* https://js.foundation/
8
*
9
* Date: @DATE
11
( function( window ) {
14
Expr,
15
getText,
16
isXML,
18
compile,
22
hasDuplicate,
24
// Local document vars
25
setDocument,
26
document,
27
docElem,
28
documentIsHTML,
29
rbuggyQSA,
30
rbuggyMatches,
31
matches,
32
contains,
33
Dec 21, 2012
34
// Instance-specific data
35
expando = "sizzle" + 1 * new Date(),
36
preferredDoc = window.document,
Dec 21, 2012
39
classCache = createCache(),
40
tokenCache = createCache(),
41
compilerCache = createCache(),
42
nonnativeSelectorCache = createCache(),
43
sortOrder = function( a, b ) {
44
if ( a === b ) {
45
hasDuplicate = true;
46
}
47
return 0;
48
},
Dec 21, 2012
49
51
hasOwn = ( {} ).hasOwnProperty,
52
arr = [],
53
pop = arr.pop,
54
pushNative = arr.push,
55
push = arr.push,
56
slice = arr.slice,
58
// Use a stripped-down indexOf as it's faster than native
59
// https://jsperf.com/thor-indexof-vs-for/5
60
indexOf = function( list, elem ) {
62
len = list.length;
64
if ( list[ i ] === elem ) {
65
return i;
66
}
67
}
68
return -1;
69
},
71
booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" +
72
"ismap|loop|multiple|open|readonly|required|scoped",
Dec 21, 2012
74
// Regular expressions
76
// http://www.w3.org/TR/css3-selectors/#whitespace
77
whitespace = "[\\x20\\t\\r\\n\\f]",
79
// https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
80
identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace +
81
"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",
83
// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
84
attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
86
// Operator (capture 2)
87
"*([*^$|!~]?=)" + whitespace +
88
89
// "Attribute values must be CSS identifiers [capture 5]
90
// or strings [capture 3 or capture 4]"
91
"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" +
92
whitespace + "*\\]",
94
pseudos = ":(" + identifier + ")(?:\\((" +
96
// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
97
// 1. quoted (capture 3; capture 4 or capture 5)
98
"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
100
// 2. simple (capture 6)
101
"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
103
// 3. anything else (capture 2)
104
".*" +
105
")\\)|)",
107
// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
108
rwhitespace = new RegExp( whitespace + "+", "g" ),
109
rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" +
110
whitespace + "+$", "g" ),
112
rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
113
rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace +
114
"*" ),
Nov 4, 2018
115
rdescend = new RegExp( whitespace + "|>" ),
Apr 5, 2013
116
117
rpseudo = new RegExp( pseudos ),
118
ridentifier = new RegExp( "^" + identifier + "$" ),
Dec 21, 2012
120
matchExpr = {
121
"ID": new RegExp( "^#(" + identifier + ")" ),
122
"CLASS": new RegExp( "^\\.(" + identifier + ")" ),
123
"TAG": new RegExp( "^(" + identifier + "|[*])" ),
Dec 21, 2012
124
"ATTR": new RegExp( "^" + attributes ),
125
"PSEUDO": new RegExp( "^" + pseudos ),
126
"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" +
127
whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" +
128
whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
129
"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
Dec 21, 2012
131
// For use in libraries implementing .is()
132
// We use this for POS matching in `select`
133
"needsContext": new RegExp( "^" + whitespace +
134
"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
135
"*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
Dec 21, 2012
136
},
139
rinputs = /^(?:input|select|textarea|button)$/i,
140
rheader = /^h\d$/i,
141
Apr 5, 2013
142
rnative = /^[^{]+\{\s*\[native \w/,
Dec 21, 2012
144
// Easily-parseable/retrievable ID or TAG or CLASS selectors
145
rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
146
147
rsibling = /[+~]/,
149
// CSS escapes
150
// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
151
runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ),
152
funescape = function( escape, nonHex ) {
153
var high = "0x" + escape.slice( 1 ) - 0x10000;
155
return nonHex ?
156
157
// Strip the backslash prefix from a non-hex escape sequence
158
nonHex :
160
// Replace a hexadecimal escape sequence with the encoded Unicode code point
161
// Support: IE <=11+
162
// For values outside the Basic Multilingual Plane (BMP), manually construct a
163
// surrogate pair
164
high < 0 ?
165
String.fromCharCode( high + 0x10000 ) :
166
String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
169
// CSS string/identifier serialization
170
// https://drafts.csswg.org/cssom/#common-serializing-idioms
171
rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
172
fcssescape = function( ch, asCodePoint ) {
173
if ( asCodePoint ) {
174
175
// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
176
if ( ch === "\0" ) {
177
return "\uFFFD";
178
}
179
180
// Control characters and (dependent upon position) numbers get escaped as code points
181
return ch.slice( 0, -1 ) + "\\" +
182
ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
183
}
184
185
// Other potentially-special ASCII characters get backslash-escaped
186
return "\\" + ch;
187
},
188
189
// Used for iframes
190
// See setDocument()
191
// Removing the function wrapper causes a "Permission Denied"
192
// error in IE
193
unloadHandler = function() {
194
setDocument();
197
inDisabledFieldset = addCombinator(
199
return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset";
200
},
201
{ dir: "parentNode", next: "legend" }
202
);
204
// Optimize for push.apply( _, NodeList )
207
( arr = slice.call( preferredDoc.childNodes ) ),
208
preferredDoc.childNodes
209
);
212
// Detect silently failing push.apply
213
// eslint-disable-next-line no-unused-expressions
214
arr[ preferredDoc.childNodes.length ].nodeType;
215
} catch ( e ) {
218
// Leverage slice if possible
219
function( target, els ) {
220
pushNative.apply( target, slice.call( els ) );
221
} :
222
223
// Support: IE<9
224
// Otherwise append directly
225
function( target, els ) {
226
var j = target.length,
227
i = 0;
229
// Can't trust NodeList.length
230
while ( ( target[ j++ ] = els[ i++ ] ) ) {}
231
target.length = j - 1;
232
}
233
};
236
function Sizzle( selector, context, results, seed ) {
237
var m, i, elem, nid, match, groups, newSelector,
238
newContext = context && context.ownerDocument,
239
240
// nodeType defaults to 9, since context defaults to document
241
nodeType = context ? context.nodeType : 9;
242
243
results = results || [];
244
245
// Return early from calls with invalid selector or context
246
if ( typeof selector !== "string" || !selector ||
247
nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
249
return results;
252
// Try to shortcut find operations (as opposed to filters) in HTML documents
255
context = context || document;
256
257
if ( documentIsHTML ) {
258
259
// If the selector is sufficiently simple, try using a "get*By*" DOM method
260
// (excepting DocumentFragment context, where the methods don't exist)
261
if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) {
262
263
// ID selector
264
if ( ( m = match[ 1 ] ) ) {
265
266
// Document context
267
if ( nodeType === 9 ) {
268
if ( ( elem = context.getElementById( m ) ) ) {
269
270
// Support: IE, Opera, Webkit
271
// TODO: identify versions
272
// getElementById can match elements by name instead of ID
273
if ( elem.id === m ) {
274
results.push( elem );
275
return results;
276
}
277
} else {
280
281
// Element context
283
284
// Support: IE, Opera, Webkit
285
// TODO: identify versions
286
// getElementById can match elements by name instead of ID
287
if ( newContext && ( elem = newContext.getElementById( m ) ) &&
288
contains( context, elem ) &&
289
elem.id === m ) {
291
results.push( elem );
292
return results;
293
}
296
// Type selector
297
} else if ( match[ 2 ] ) {
298
push.apply( results, context.getElementsByTagName( selector ) );
299
return results;
301
// Class selector
302
} else if ( ( m = match[ 3 ] ) && support.getElementsByClassName &&
303
context.getElementsByClassName ) {
304
305
push.apply( results, context.getElementsByClassName( m ) );
306
return results;
307
}
310
// Take advantage of querySelectorAll
311
if ( support.qsa &&
312
!nonnativeSelectorCache[ selector + " " ] &&
313
( !rbuggyQSA || !rbuggyQSA.test( selector ) ) &&
Nov 4, 2018
315
// Support: IE 8 only
316
// Exclude object elements
317
( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) {
Nov 4, 2018
318
319
newSelector = selector;
320
newContext = context;
Nov 4, 2018
322
// qSA considers elements outside a scoping root when evaluating child or
323
// descendant combinators, which is not what we want.
324
// In such cases, we work around the behavior by prefixing every selector in the
325
// list with an ID selector referencing the scope context.
326
// The technique has to be used as well when a leading combinator is used
327
// as such selectors are not recognized by querySelectorAll.
Nov 4, 2018
328
// Thanks to Andrew Dupont for this technique.
329
if ( nodeType === 1 &&
330
( rdescend.test( selector ) || rcombinators.test( selector ) ) ) {
Nov 4, 2018
331
332
// Expand context for sibling selectors
333
newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
334
context;
335
336
// We can use :scope instead of the ID hack if the browser
337
// supports it & if we're not changing the context.
338
if ( newContext !== context || !support.scope ) {
339
340
// Capture the context ID, setting it first if necessary
341
if ( ( nid = context.getAttribute( "id" ) ) ) {
342
nid = nid.replace( rcssescape, fcssescape );
343
} else {
344
context.setAttribute( "id", ( nid = expando ) );
345
}
Nov 4, 2018
346
}
Nov 4, 2018
348
// Prefix every selector in the list
349
groups = tokenize( selector );
350
i = groups.length;
351
while ( i-- ) {
352
groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " +
353
toSelector( groups[ i ] );
Nov 4, 2018
355
newSelector = groups.join( "," );
Nov 4, 2018
358
try {
359
push.apply( results,
360
newContext.querySelectorAll( newSelector )
361
);
362
return results;
363
} catch ( qsaError ) {
364
nonnativeSelectorCache( selector, true );
365
} finally {
366
if ( nid === expando ) {
367
context.removeAttribute( "id" );
372
}
373
374
// All others
375
return select( selector.replace( rtrim, "$1" ), context, results, seed );
378
/**
379
* Create key-value caches of limited size
380
* @returns {function(string, object)} Returns the Object data after storing it on itself with
381
* property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
382
* deleting the oldest entry
383
*/
384
function createCache() {
385
var keys = [];
386
387
function cache( key, value ) {
389
// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
390
if ( keys.push( key + " " ) > Expr.cacheLength ) {
392
// Only keep the most recent entries
393
delete cache[ keys.shift() ];
394
}
395
return ( cache[ key + " " ] = value );
396
}
397
return cache;
398
}
399
400
/**
401
* Mark a function for special use by Sizzle
402
* @param {Function} fn The function to mark
403
*/
404
function markFunction( fn ) {
405
fn[ expando ] = true;
406
return fn;
407
}
408
409
/**
410
* Support testing using an element
411
* @param {Function} fn Passed the created element and returns a boolean result
414
var el = document.createElement( "fieldset" );
418
} catch ( e ) {
422
// Remove from its parent by default
423
if ( el.parentNode ) {
424
el.parentNode.removeChild( el );
429
}
430
}
431
432
/**
433
* Adds the same handler for all of the specified attrs
434
* @param {String} attrs Pipe-separated list of attributes
Jun 3, 2013
435
* @param {Function} handler The method that will be applied
437
function addHandle( attrs, handler ) {
438
var arr = attrs.split( "|" ),
439
i = arr.length;
442
Expr.attrHandle[ arr[ i ] ] = handler;
443
}
444
}
445
446
/**
447
* Checks document order of two siblings
448
* @param {Element} a
449
* @param {Element} b
Jun 3, 2013
450
* @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
451
*/
452
function siblingCheck( a, b ) {
453
var cur = b && a,
454
diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
455
a.sourceIndex - b.sourceIndex;
456
457
// Use IE sourceIndex if available on both nodes
458
if ( diff ) {
459
return diff;
460
}
461
462
// Check if b follows a
463
if ( cur ) {
464
while ( ( cur = cur.nextSibling ) ) {
465
if ( cur === b ) {
466
return -1;
467
}
468
}
469
}
470
471
return a ? 1 : -1;
472
}
473
474
/**
475
* Returns a function to use in pseudos for input types
476
* @param {String} type
477
*/
478
function createInputPseudo( type ) {
479
return function( elem ) {
480
var name = elem.nodeName.toLowerCase();
481
return name === "input" && elem.type === type;
482
};
483
}
484
485
/**
486
* Returns a function to use in pseudos for buttons
487
* @param {String} type
488
*/
489
function createButtonPseudo( type ) {
490
return function( elem ) {
491
var name = elem.nodeName.toLowerCase();
492
return ( name === "input" || name === "button" ) && elem.type === type;
496
/**
497
* Returns a function to use in pseudos for :enabled/:disabled
498
* @param {Boolean} disabled true for :disabled; false for :enabled
499
*/
500
function createDisabledPseudo( disabled ) {
501
502
// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
505
// Only certain elements can match :enabled or :disabled
506
// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
507
// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
508
if ( "form" in elem ) {
509
510
// Check for inherited disabledness on relevant non-disabled elements:
511
// * listed form-associated elements in a disabled fieldset
512
// https://html.spec.whatwg.org/multipage/forms.html#category-listed
513
// https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
514
// * option elements in a disabled optgroup
515
// https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
516
// All such elements have a "form" property.
517
if ( elem.parentNode && elem.disabled === false ) {
518
519
// Option elements defer to a parent optgroup if present
520
if ( "label" in elem ) {
521
if ( "label" in elem.parentNode ) {
522
return elem.parentNode.disabled === disabled;
523
} else {
524
return elem.disabled === disabled;
525
}
526
}
527
528
// Support: IE 6 - 11
529
// Use the isDisabled shortcut property to check for disabled fieldset ancestors
530
return elem.isDisabled === disabled ||
531
532
// Where there is no isDisabled, check manually
533
/* jshint -W018 */
534
elem.isDisabled !== !disabled &&
535
inDisabledFieldset( elem ) === disabled;
536
}
537
538
return elem.disabled === disabled;
539
540
// Try to winnow out elements that can't be disabled before trusting the disabled property.
541
// Some victims get caught in our net (label, legend, menu, track), but it shouldn't
542
// even exist on them, let alone have a boolean value.
543
} else if ( "label" in elem ) {
544
return elem.disabled === disabled;
545
}
546
547
// Remaining elements are neither :enabled nor :disabled
548
return false;
552
/**
553
* Returns a function to use in pseudos for positionals
554
* @param {Function} fn
555
*/
556
function createPositionalPseudo( fn ) {
557
return markFunction( function( argument ) {
559
return markFunction( function( seed, matches ) {
560
var j,
561
matchIndexes = fn( [], seed.length, argument ),
562
i = matchIndexes.length;
563
564
// Match elements found at the specified indexes
565
while ( i-- ) {
566
if ( seed[ ( j = matchIndexes[ i ] ) ] ) {
567
seed[ j ] = !( matches[ j ] = seed[ j ] );
570
} );
571
} );
574
/**
575
* Checks a node for validity as a Sizzle context
576
* @param {Element|Object=} context
577
* @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
578
*/
579
function testContext( context ) {
580
return context && typeof context.getElementsByTagName !== "undefined" && context;
583
// Expose support vars for convenience
584
support = Sizzle.support = {};
585
587
* Detects XML nodes
588
* @param {Element|Object} elem An element or a document
589
* @returns {Boolean} True iff elem is a non-HTML XML node
590
*/
591
isXML = Sizzle.isXML = function( elem ) {
592
var namespace = elem && elem.namespaceURI,
593
docElem = elem && ( elem.ownerDocument || elem ).documentElement;
594
595
// Support: IE <=8
596
// Assume HTML when documentElement doesn't yet exist, such as inside loading iframes
597
// https://bugs.jquery.com/ticket/4833
598
return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" );
599
};
600
601
/**
602
* Sets document-related variables once based on the current document
603
* @param {Element|Object} [doc] An element or document object to use to set the document
604
* @returns {Object} Returns the current document
Dec 19, 2012
606
setDocument = Sizzle.setDocument = function( node ) {
607
var hasCompare, subWindow,
608
doc = node ? node.ownerDocument || node : preferredDoc;
610
// Return early if doc is invalid or already selected
611
// Support: IE 11+, Edge 17 - 18+
612
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
613
// two documents; shallow comparisons work.
614
// eslint-disable-next-line eqeqeq
615
if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) {
616
return document;
619
// Update global variables
621
docElem = document.documentElement;
622
documentIsHTML = !isXML( document );
624
// Support: IE 9 - 11+, Edge 12 - 18+
625
// Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
626
// Support: IE 11+, Edge 17 - 18+
627
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
628
// two documents; shallow comparisons work.
629
// eslint-disable-next-line eqeqeq
630
if ( preferredDoc != document &&
631
( subWindow = document.defaultView ) && subWindow.top !== subWindow ) {
634
if ( subWindow.addEventListener ) {
635
subWindow.addEventListener( "unload", unloadHandler, false );
636
637
// Support: IE 9 - 10 only
638
} else if ( subWindow.attachEvent ) {
639
subWindow.attachEvent( "onunload", unloadHandler );
643
// Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only,
644
// Safari 4 - 5 only, Opera <=11.6 - 12.x only
645
// IE/Edge & older browsers don't support the :scope pseudo-class.
646
// Support: Safari 6.0 only
647
// Safari 6.0 supports :scope but it's an alias of :root there.
648
support.scope = assert( function( el ) {
649
docElem.appendChild( el ).appendChild( document.createElement( "div" ) );
650
return typeof el.querySelectorAll !== "undefined" &&
651
!el.querySelectorAll( ":scope fieldset div" ).length;
652
} );
653
654
/* Attributes
655
---------------------------------------------------------------------- */
658
// Verify that getAttribute really returns attributes and not properties
659
// (excepting IE8 booleans)
660
support.attributes = assert( function( el ) {
662
return !el.getAttribute( "className" );
663
} );
665
/* getElement(s)By*
666
---------------------------------------------------------------------- */
667
668
// Check if getElementsByTagName("*") returns only elements
669
support.getElementsByTagName = assert( function( el ) {
670
el.appendChild( document.createComment( "" ) );
671
return !el.getElementsByTagName( "*" ).length;
672
} );
674
// Support: IE<9
675
support.getElementsByClassName = rnative.test( document.getElementsByClassName );
677
// Support: IE<10
678
// Check if getElementById returns elements by name
679
// The broken getElementById methods don't pick up programmatically-set names,
680
// so use a roundabout getElementsByName test
681
support.getById = assert( function( el ) {
682
docElem.appendChild( el ).id = expando;
683
return !document.getElementsByName || !document.getElementsByName( expando ).length;
686
// ID filter and find
687
if ( support.getById ) {
688
Expr.filter[ "ID" ] = function( id ) {
689
var attrId = id.replace( runescape, funescape );
691
return elem.getAttribute( "id" ) === attrId;
694
Expr.find[ "ID" ] = function( id, context ) {
695
if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
696
var elem = context.getElementById( id );
697
return elem ? [ elem ] : [];
698
}
699
};
701
Expr.filter[ "ID" ] = function( id ) {
702
var attrId = id.replace( runescape, funescape );
704
var node = typeof elem.getAttributeNode !== "undefined" &&
705
elem.getAttributeNode( "id" );
706
return node && node.value === attrId;
707
};
708
};
709
710
// Support: IE 6 - 7 only
711
// getElementById is not reliable as a find shortcut
712
Expr.find[ "ID" ] = function( id, context ) {
713
if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
714
var node, i, elems,
715
elem = context.getElementById( id );
716
717
if ( elem ) {
718
719
// Verify the id attribute
720
node = elem.getAttributeNode( "id" );
721
if ( node && node.value === id ) {
722
return [ elem ];
723
}
724
725
// Fall back on getElementsByName
726
elems = context.getElementsByName( id );
727
i = 0;
728
while ( ( elem = elems[ i++ ] ) ) {
729
node = elem.getAttributeNode( "id" );
730
if ( node && node.value === id ) {
731
return [ elem ];
732
}
733
}
734
}
735
736
return [];
737
}
738
};
742
Expr.find[ "TAG" ] = support.getElementsByTagName ?
744
if ( typeof context.getElementsByTagName !== "undefined" ) {
745
return context.getElementsByTagName( tag );
746
747
// DocumentFragment nodes don't have gEBTN
748
} else if ( support.qsa ) {
749
return context.querySelectorAll( tag );
753
function( tag, context ) {
754
var elem,
755
tmp = [],
756
i = 0,
758
// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
759
results = context.getElementsByTagName( tag );
760
761
// Filter out possible comments
762
if ( tag === "*" ) {
763
while ( ( elem = results[ i++ ] ) ) {
764
if ( elem.nodeType === 1 ) {
765
tmp.push( elem );
766
}
767
}
768
769
return tmp;
770
}
771
return results;
772
};
773
774
// Class
775
Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) {
776
if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
777
return context.getElementsByClassName( className );
778
}
779
};
780
781
/* QSA/matchesSelector
782
---------------------------------------------------------------------- */
783
784
// QSA and matchesSelector support
785
786
// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
787
rbuggyMatches = [];
788
789
// qSa(:focus) reports false when true (Chrome 21)
790
// We allow this because of a bug in IE8/9 that throws an error
791
// whenever `document.activeElement` is accessed on an iframe
792
// So, we allow :focus to pass through QSA all the time to avoid the IE error
793
// See https://bugs.jquery.com/ticket/13378
796
if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) {
797
798
// Build QSA regex
799
// Regex strategy adopted from Diego Perini
800
assert( function( el ) {
801
804
// Select is set to empty string on purpose
805
// This is to test IE's treatment of not explicitly
806
// setting a boolean content attribute,
807
// since its presence should be enough
808
// https://bugs.jquery.com/ticket/12359
809
docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
810
"<select id='" + expando + "-\r\\' msallowcapture=''>" +
811
"<option selected=''></option></select>";
813
// Support: IE8, Opera 11-12.16
814
// Nothing should be selected when empty strings follow ^= or $= or *=
815
// The test attribute must be unknown in Opera but "safe" for WinRT
816
// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
817
if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) {
818
rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
819
}
821
// Support: IE8
822
// Boolean attributes and "value" are not treated correctly
823
if ( !el.querySelectorAll( "[selected]" ).length ) {
824
rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
827
// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
828
if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
829
rbuggyQSA.push( "~=" );
832
// Support: IE 11+, Edge 15 - 18+
833
// IE 11/Edge don't find elements on a `[name='']` query in some cases.
834
// Adding a temporary attribute to the document before the selection works
835
// around the issue.
836
// Interestingly, IE 10 & older don't seem to have the issue.
837
input = document.createElement( "input" );
838
input.setAttribute( "name", "" );
839
el.appendChild( input );
840
if ( !el.querySelectorAll( "[name='']" ).length ) {
841
rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" +
842
whitespace + "*(?:''|\"\")" );
843
}
844
845
// Webkit/Opera - :checked should return selected option elements
846
// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
847
// IE8 throws error here and will not see later tests
848
if ( !el.querySelectorAll( ":checked" ).length ) {
849
rbuggyQSA.push( ":checked" );
851
852
// Support: Safari 8+, iOS 8+
853
// https://bugs.webkit.org/show_bug.cgi?id=136851
854
// In-page `selector#id sibling-combinator selector` fails
855
if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
856
rbuggyQSA.push( ".#.+[+~]" );
858
859
// Support: Firefox <=3.6 - 5 only
860
// Old Firefox doesn't throw on a badly-escaped identifier.
861
el.querySelectorAll( "\\\f" );
862
rbuggyQSA.push( "[\\r\\n\\f]" );
865
assert( function( el ) {
866
el.innerHTML = "<a href='' disabled='disabled'></a>" +
867
"<select disabled='disabled'><option/></select>";
868
869
// Support: Windows 8 Native Apps
870
// The type and name attributes are restricted during .innerHTML assignment
871
var input = document.createElement( "input" );
872
input.setAttribute( "type", "hidden" );
873
el.appendChild( input ).setAttribute( "name", "D" );
875
// Support: IE8
876
// Enforce case-sensitivity of name attribute
877
if ( el.querySelectorAll( "[name=d]" ).length ) {
878
rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
879
}
880
881
// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
882
// IE8 throws error here and will not see later tests
883
if ( el.querySelectorAll( ":enabled" ).length !== 2 ) {
884
rbuggyQSA.push( ":enabled", ":disabled" );
885
}
886
887
// Support: IE9-11+
888
// IE's :disabled selector does not pick up the children of disabled fieldsets
889
docElem.appendChild( el ).disabled = true;
890
if ( el.querySelectorAll( ":disabled" ).length !== 2 ) {
891
rbuggyQSA.push( ":enabled", ":disabled" );
892
}
893
894
// Support: Opera 10 - 11 only
895
// Opera 10-11 does not throw on post-comma invalid pseudos
896
el.querySelectorAll( "*,:x" );
897
rbuggyQSA.push( ",.*:" );
898
} );
901
if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches ||
902
docElem.webkitMatchesSelector ||
903
docElem.mozMatchesSelector ||
904
docElem.oMatchesSelector ||
905
docElem.msMatchesSelector ) ) ) ) {
906
907
assert( function( el ) {
909
// Check to see if it's possible to do matchesSelector
910
// on a disconnected node (IE 9)
911
support.disconnectedMatch = matches.call( el, "*" );
912
913
// This should fail with an exception
914
// Gecko does not error, returns false instead
916
rbuggyMatches.push( "!=", pseudos );
920
rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) );
921
rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) );
923
/* Contains
924
---------------------------------------------------------------------- */
925
hasCompare = rnative.test( docElem.compareDocumentPosition );
928
// Purposefully self-exclusive
929
// As in, an element does not contain itself
930
contains = hasCompare || rnative.test( docElem.contains ) ?
932
var adown = a.nodeType === 9 ? a.documentElement : a,
933
bup = b && b.parentNode;
934
return a === bup || !!( bup && bup.nodeType === 1 && (
935
adown.contains ?
936
adown.contains( bup ) :
937
a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
942
while ( ( b = b.parentNode ) ) {
943
if ( b === a ) {
944
return true;
945
}
946
}
947
}
948
return false;
949
};
950
951
/* Sorting
952
---------------------------------------------------------------------- */
953
959
if ( a === b ) {
960
hasDuplicate = true;
961
return 0;
962
}
963
964
// Sort on method existence if only one input has compareDocumentPosition
965
var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
970
// Calculate position if both inputs belong to the same document
971
// Support: IE 11+, Edge 17 - 18+
972
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
973
// two documents; shallow comparisons work.
974
// eslint-disable-next-line eqeqeq
975
compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ?
976
a.compareDocumentPosition( b ) :
977
978
// Otherwise we know they are disconnected
979
1;
981
// Disconnected nodes
982
if ( compare & 1 ||
983
( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) {
984
985
// Choose the first element that is related to our preferred document
986
// Support: IE 11+, Edge 17 - 18+
987
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
988
// two documents; shallow comparisons work.
989
// eslint-disable-next-line eqeqeq
990
if ( a == document || a.ownerDocument == preferredDoc &&
991
contains( preferredDoc, a ) ) {
994
995
// Support: IE 11+, Edge 17 - 18+
996
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
997
// two documents; shallow comparisons work.
998
// eslint-disable-next-line eqeqeq
999
if ( b == document || b.ownerDocument == preferredDoc &&
1000
contains( preferredDoc, b ) ) {
1004
// Maintain original order
1005
return sortInput ?
1006
( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1010
return compare & 4 ? -1 : 1;
1011
} :
1012
function( a, b ) {
1014
// Exit early if the nodes are identical
1015
if ( a === b ) {
1016
hasDuplicate = true;
1017
return 0;
1018
}
1019
1020
var cur,
1021
i = 0,
1022
aup = a.parentNode,
1023
bup = b.parentNode,
1024
ap = [ a ],
1025
bp = [ b ];
1026
1027
// Parentless nodes are either documents or disconnected
1028
if ( !aup || !bup ) {
1029
1030
// Support: IE 11+, Edge 17 - 18+
1031
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1032
// two documents; shallow comparisons work.
1033
/* eslint-disable eqeqeq */
1034
return a == document ? -1 :
1035
b == document ? 1 :
1036
/* eslint-enable eqeqeq */
1040
( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1041
0;
1042
1043
// If the nodes are siblings, we can do a quick check
1044
} else if ( aup === bup ) {
1045
return siblingCheck( a, b );
1046
}
1047
1048
// Otherwise we need full lists of their ancestors for comparison
1049
cur = a;
1050
while ( ( cur = cur.parentNode ) ) {
1051
ap.unshift( cur );
1052
}
1053
cur = b;
1054
while ( ( cur = cur.parentNode ) ) {
1055
bp.unshift( cur );
1056
}
1057
1058
// Walk down the tree looking for a discrepancy
1059
while ( ap[ i ] === bp[ i ] ) {
1060
i++;
1061
}
1062
1063
return i ?
1065
// Do a sibling check if the nodes have a common ancestor
1066
siblingCheck( ap[ i ], bp[ i ] ) :
1067
1068
// Otherwise nodes in our document sort first
1069
// Support: IE 11+, Edge 17 - 18+
1070
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1071
// two documents; shallow comparisons work.
1072
/* eslint-disable eqeqeq */
1073
ap[ i ] == preferredDoc ? -1 :
1074
bp[ i ] == preferredDoc ? 1 :
1075
/* eslint-enable eqeqeq */
1079
return document;
1082
Sizzle.matches = function( expr, elements ) {
Dec 19, 2012
1083
return Sizzle( expr, null, null, elements );
1084
};
1085
1086
Sizzle.matchesSelector = function( elem, expr ) {
1089
if ( support.matchesSelector && documentIsHTML &&
1090
!nonnativeSelectorCache[ expr + " " ] &&
1091
( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1092
( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
1094
try {
1095
var ret = matches.call( elem, expr );
1096
1097
// IE 9's matchesSelector returns false on disconnected nodes
1098
if ( ret || support.disconnectedMatch ||
1099
1100
// As well, disconnected nodes are said to be in a document
1101
// fragment in IE 9
1102
elem.document && elem.document.nodeType !== 11 ) {
1105
} catch ( e ) {
1106
nonnativeSelectorCache( expr, true );
1110
return Sizzle( expr, document, null, [ elem ] ).length > 0;
1111
};
1112
1113
Sizzle.contains = function( context, elem ) {
1115
// Set document vars if needed
1116
// Support: IE 11+, Edge 17 - 18+
1117
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1118
// two documents; shallow comparisons work.
1119
// eslint-disable-next-line eqeqeq
1120
if ( ( context.ownerDocument || context ) != document ) {
1121
setDocument( context );
1122
}
1123
return contains( context, elem );
1124
};
1125
1126
Sizzle.attr = function( elem, name ) {
1128
// Set document vars if needed
1129
// Support: IE 11+, Edge 17 - 18+
1130
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
1131
// two documents; shallow comparisons work.
1132
// eslint-disable-next-line eqeqeq
1133
if ( ( elem.ownerDocument || elem ) != document ) {
1134
setDocument( elem );
1135
}
1137
var fn = Expr.attrHandle[ name.toLowerCase() ],
1139
// Don't get fooled by Object.prototype properties (jQuery #13807)
1140
val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1141
fn( elem, name, !documentIsHTML ) :
1142
undefined;
1144
return val !== undefined ?
1145
val :
1146
support.attributes || !documentIsHTML ?
1147
elem.getAttribute( name ) :
1148
( val = elem.getAttributeNode( name ) ) && val.specified ?
1153
Sizzle.escape = function( sel ) {
1154
return ( sel + "" ).replace( rcssescape, fcssescape );
1155
};
1156
1157
Sizzle.error = function( msg ) {
1158
throw new Error( "Syntax error, unrecognized expression: " + msg );
1159
};
1160
1161
/**
1162
* Document sorting and removing duplicates
1163
* @param {ArrayLike} results
1164
*/
1165
Sizzle.uniqueSort = function( results ) {
1166
var elem,
1167
duplicates = [],
1168
j = 0,
1169
i = 0;
1171
// Unless we *know* we can detect duplicates, assume their presence
1172
hasDuplicate = !support.detectDuplicates;
1173
sortInput = !support.sortStable && results.slice( 0 );
1174
results.sort( sortOrder );
1175
1176
if ( hasDuplicate ) {
1177
while ( ( elem = results[ i++ ] ) ) {
1178
if ( elem === results[ i ] ) {
1179
j = duplicates.push( i );
1180
}
1181
}
1182
while ( j-- ) {
1183
results.splice( duplicates[ j ], 1 );
1184
}
1185
}
1186
1187
// Clear input after sorting to release objects
1188
// See https://github.com/jquery/sizzle/pull/225
1189
sortInput = null;
1190
1191
return results;
1192
};
1193
1194
/**
1195
* Utility function for retrieving the text value of an array of DOM nodes
1196
* @param {Array|Element} elem
1197
*/
1198
getText = Sizzle.getText = function( elem ) {
1199
var node,
1200
ret = "",
1201
i = 0,
1202
nodeType = elem.nodeType;
1203
Nov 16, 2012
1204
if ( !nodeType ) {
1206
// If no nodeType, this is expected to be an array
1207
while ( ( node = elem[ i++ ] ) ) {
1208
1209
// Do not traverse comment nodes
1210
ret += getText( node );
1211
}
Nov 16, 2012
1212
} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
Nov 16, 2012
1214
// Use textContent for elements
1215
// innerText usage removed for consistency of new lines (jQuery #11153)
Nov 16, 2012
1216
if ( typeof elem.textContent === "string" ) {
1217
return elem.textContent;
1218
} else {
Nov 16, 2012
1220
// Traverse its children
1221
for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1222
ret += getText( elem );
1223
}
1224
}
1225
} else if ( nodeType === 3 || nodeType === 4 ) {
1226
return elem.nodeValue;
Nov 16, 2012
1229
// Do not include comment or processing instruction nodes
1230
1231
return ret;
1232
};
1233
1234
Expr = Sizzle.selectors = {
1237
cacheLength: 50,
1239
createPseudo: markFunction,
1241
match: matchExpr,
1243
attrHandle: {},
1244
1247
relative: {
1248
">": { dir: "parentNode", first: true },
1249
" ": { dir: "parentNode" },
1250
"+": { dir: "previousSibling", first: true },
1251
"~": { dir: "previousSibling" }
1252
},
1254
preFilter: {
1256
match[ 1 ] = match[ 1 ].replace( runescape, funescape );
1258
// Move the given value to match[3] whether quoted or unquoted
1259
match[ 3 ] = ( match[ 3 ] || match[ 4 ] ||
1260
match[ 5 ] || "" ).replace( runescape, funescape );
1262
if ( match[ 2 ] === "~=" ) {
1263
match[ 3 ] = " " + match[ 3 ] + " ";
1266
return match.slice( 0, 4 );
1267
},
1271
/* matches from matchExpr["CHILD"]
1273
2 what (child|of-type)
1274
3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1275
4 xn-component of xn+y argument ([+-]?\d*n|)
1276
5 sign of xn-component
1277
6 x of xn-component
1278
7 sign of y-component
1279
8 y of y-component
1281
match[ 1 ] = match[ 1 ].toLowerCase();
1282
1283
if ( match[ 1 ].slice( 0, 3 ) === "nth" ) {
1285
// nth-* requires argument
1286
if ( !match[ 3 ] ) {
1287
Sizzle.error( match[ 0 ] );
1290
// numeric x and y parameters for Expr.filter.CHILD
1291
// remember that false/true cast respectively to 0/1
1292
match[ 4 ] = +( match[ 4 ] ?
1293
match[ 5 ] + ( match[ 6 ] || 1 ) :
1294
2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) );
1295
match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" );
1296
1297
// other types prohibit arguments
1298
} else if ( match[ 3 ] ) {
1299
Sizzle.error( match[ 0 ] );
1302
return match;
1303
},
Dec 4, 2012
1306
var excess,
1307
unquoted = !match[ 6 ] && match[ 2 ];
Dec 4, 2012
1308
1309
if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) {
Dec 4, 2012
1313
// Accept quoted arguments as-is
1314
if ( match[ 3 ] ) {
1315
match[ 2 ] = match[ 4 ] || match[ 5 ] || "";
Dec 4, 2012
1316
1317
// Strip excess characters from unquoted arguments
1318
} else if ( unquoted && rpseudo.test( unquoted ) &&
Dec 4, 2012
1320
// Get excess from tokenize (recursively)
1321
( excess = tokenize( unquoted, true ) ) &&
1322
Dec 4, 2012
1323
// advance to the next closing parenthesis
1324
( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) {
Dec 4, 2012
1325
1326
// excess is a negative index
1327
match[ 0 ] = match[ 0 ].slice( 0, excess );
1328
match[ 2 ] = unquoted.slice( 0, excess );
1331
// Return only captures needed by the pseudo filter method (type and argument)
1336
filter: {
Apr 5, 2013
1338
"TAG": function( nodeNameSelector ) {
1339
var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1340
return nodeNameSelector === "*" ?
1341
function() {
1342
return true;
1343
} :
Apr 5, 2013
1344
function( elem ) {
1345
return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
1346
};
1349
"CLASS": function( className ) {
Dec 21, 2012
1350
var pattern = classCache[ className + " " ];
1353
( pattern = new RegExp( "(^|" + whitespace +
1354
")" + className + "(" + whitespace + "|$)" ) ) && classCache(
1355
className, function( elem ) {
1356
return pattern.test(
1357
typeof elem.className === "string" && elem.className ||
1358
typeof elem.getAttribute !== "undefined" &&
1359
elem.getAttribute( "class" ) ||
1360
""
1361
);
1362
} );
1365
"ATTR": function( name, operator, check ) {
1367
var result = Sizzle.attr( elem, name );
1369
if ( result == null ) {
1370
return operator === "!=";
1372
if ( !operator ) {
1373
return true;
1378
/* eslint-disable max-len */
1379
1380
return operator === "=" ? result === check :
1381
operator === "!=" ? result !== check :
1382
operator === "^=" ? check && result.indexOf( check ) === 0 :
1383
operator === "*=" ? check && result.indexOf( check ) > -1 :
1384
operator === "$=" ? check && result.slice( -check.length ) === check :
1385
operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
1386
operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
1388
/* eslint-enable max-len */
1389
1390
};
1391
},
1392
1393
"CHILD": function( type, what, _argument, first, last ) {
1394
var simple = type.slice( 0, 3 ) !== "nth",
1395
forward = type.slice( -4 ) !== "last",
1396
ofType = what === "of-type";
1398
return first === 1 && last === 0 ?
1400
// Shortcut for :nth-*(n)
1401
function( elem ) {
1402
return !!elem.parentNode;
1403
} :
1405
function( elem, _context, xml ) {
1406
var cache, uniqueCache, outerCache, node, nodeIndex, start,
1407
dir = simple !== forward ? "nextSibling" : "previousSibling",
1408
parent = elem.parentNode,
1409
name = ofType && elem.nodeName.toLowerCase(),
1410
useCache = !xml && !ofType,
1411
diff = false;
1412
1413
if ( parent ) {
1414
1415
// :(first|last|only)-(child|of-type)
1416
if ( simple ) {
1417
while ( dir ) {
1418
node = elem;
1419
while ( ( node = node[ dir ] ) ) {
1420
if ( ofType ?
1421
node.nodeName.toLowerCase() === name :
1422
node.nodeType === 1 ) {
1423
1424
return false;
1425
}
1426
}
1428
// Reverse direction for :only-* (if we haven't yet done so)
1429
start = dir = type === "only" && !start && "nextSibling";
1430
}
1431
return true;
1432
}
1434
start = [ forward ? parent.firstChild : parent.lastChild ];
1436
// non-xml :nth-child(...) stores cache data on `parent`
1437
if ( forward && useCache ) {
1439
// Seek `elem` from a previously-cached index
1440
1441
// ...in a gzip-friendly way
1442
node = parent;
1443
outerCache = node[ expando ] || ( node[ expando ] = {} );
1444
1445
// Support: IE <9 only
1446
// Defend against cloned attroperties (jQuery gh-1709)
1447
uniqueCache = outerCache[ node.uniqueID ] ||
1448
( outerCache[ node.uniqueID ] = {} );
1449
1450
cache = uniqueCache[ type ] || [];
1451
nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1452
diff = nodeIndex && cache[ 2 ];
1453
node = nodeIndex && parent.childNodes[ nodeIndex ];
1454
1455
while ( ( node = ++nodeIndex && node && node[ dir ] ||
1456
1457
// Fallback to seeking `elem` from the start
1458
( diff = nodeIndex = 0 ) || start.pop() ) ) {
1460
// When found, cache indexes on `parent` and break
1461
if ( node.nodeType === 1 && ++diff && node === elem ) {
1462
uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
1463
break;
1469
// Use previously-cached element index if available
1470
if ( useCache ) {
1472
// ...in a gzip-friendly way
1473
node = elem;
1474
outerCache = node[ expando ] || ( node[ expando ] = {} );
1476
// Support: IE <9 only
1477
// Defend against cloned attroperties (jQuery gh-1709)
1478
uniqueCache = outerCache[ node.uniqueID ] ||
1479
( outerCache[ node.uniqueID ] = {} );
1481
cache = uniqueCache[ type ] || [];
1482
nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1483
diff = nodeIndex;
1484
}
1485
1486
// xml :nth-child(...)
1487
// or :nth-last-child(...) or :nth(-last)?-of-type(...)
1488
if ( diff === false ) {
1490
// Use the same loop as above to seek `elem` from the start
1491
while ( ( node = ++nodeIndex && node && node[ dir ] ||
1492
( diff = nodeIndex = 0 ) || start.pop() ) ) {
1493
1494
if ( ( ofType ?
1495
node.nodeName.toLowerCase() === name :
1496
node.nodeType === 1 ) &&
1497
++diff ) {
1498
1499
// Cache the index of each encountered element
1500
if ( useCache ) {
1501
outerCache = node[ expando ] ||
1502
( node[ expando ] = {} );
1503
1504
// Support: IE <9 only
1505
// Defend against cloned attroperties (jQuery gh-1709)
1506
uniqueCache = outerCache[ node.uniqueID ] ||
1507
( outerCache[ node.uniqueID ] = {} );
1508
1509
uniqueCache[ type ] = [ dirruns, diff ];
1510
}
1511
1512
if ( node === elem ) {
1513
break;
1514
}
1520
// Incorporate the offset, then check against cycle size
1521
diff -= last;
1522
return diff === first || ( diff % first === 0 && diff / first >= 0 );
1527
"PSEUDO": function( pseudo, argument ) {
1529
// pseudo-class names are case-insensitive
1530
// http://www.w3.org/TR/selectors/#pseudo-classes
1531
// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
1532
// Remember that setFilters inherits from pseudos
1534
fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
1535
Sizzle.error( "unsupported pseudo: " + pseudo );
1537
// The user may use createPseudo to indicate that
1538
// arguments are needed to create the filter function
1539
// just as Sizzle does
1542
}
1543
1544
// But maintain support for old signatures
1545
if ( fn.length > 1 ) {
1546
args = [ pseudo, pseudo, "", argument ];
1547
return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
1548
markFunction( function( seed, matches ) {
1549
var idx,
1550
matched = fn( seed, argument ),
1551
i = matched.length;
1552
while ( i-- ) {
1553
idx = indexOf( seed, matched[ i ] );
1554
seed[ idx ] = !( matches[ idx ] = matched[ i ] );
1558
return fn( elem, 0, args );
1559
};
1563
}
1564
},
1566
pseudos: {
1568
// Potentially complex pseudos
1569
"not": markFunction( function( selector ) {
1570
1571
// Trim the selector passed to compile
1572
// to avoid treating leading and trailing
1573
// spaces as combinators
1574
var input = [],
1575
results = [],
1576
matcher = compile( selector.replace( rtrim, "$1" ) );
1577
1578
return matcher[ expando ] ?
1579
markFunction( function( seed, matches, _context, xml ) {
1580
var elem,
1581
unmatched = matcher( seed, null, xml, [] ),
1582
i = seed.length;
1583
1584
// Match elements unmatched by `matcher`
1585
while ( i-- ) {
1586
if ( ( elem = unmatched[ i ] ) ) {
1587
seed[ i ] = !( matches[ i ] = elem );
1591
function( elem, _context, xml ) {
1592
input[ 0 ] = elem;
1593
matcher( input, null, xml, results );
1595
// Don't keep the element (issue #299)
1596
input[ 0 ] = null;
1601
"has": markFunction( function( selector ) {
1602
return function( elem ) {
1603
return Sizzle( selector, elem ).length > 0;
1604
};
1607
"contains": markFunction( function( text ) {
1608
text = text.replace( runescape, funescape );
1609
return function( elem ) {
1610
return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1;
1614
// "Whether an element is represented by a :lang() selector
1615
// is based solely on the element's language value
1616
// being equal to the identifier C,
1617
// or beginning with the identifier C immediately followed by "-".
1618
// The matching of C against the element's language value is performed case-insensitively.
1619
// The identifier C does not have to be a valid language name."
1620
// http://www.w3.org/TR/selectors/#lang-pseudo
1621
"lang": markFunction( function( lang ) {
1623
// lang value must be a valid identifier
1624
if ( !ridentifier.test( lang || "" ) ) {
1625
Sizzle.error( "unsupported lang: " + lang );
1626
}
1627
lang = lang.replace( runescape, funescape ).toLowerCase();
1628
return function( elem ) {
1630
do {
1631
if ( ( elemLang = documentIsHTML ?
1632
elem.lang :
1633
elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) {
1634
1635
elemLang = elemLang.toLowerCase();
1636
return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
1637
}
1638
} while ( ( elem = elem.parentNode ) && elem.nodeType === 1 );
1639
return false;
1640
};
1643
// Miscellaneous
1644
"target": function( elem ) {
1645
var hash = window.location && window.location.hash;
1646
return hash && hash.slice( 1 ) === elem.id;
1647
},
1648
1649
"root": function( elem ) {
1650
return elem === docElem;
1651
},
1652
1653
"focus": function( elem ) {
1654
return elem === document.activeElement &&
1655
( !document.hasFocus || document.hasFocus() ) &&
1656
!!( elem.type || elem.href || ~elem.tabIndex );
1657
},
1658
1659
// Boolean properties
1660
"enabled": createDisabledPseudo( false ),
1661
"disabled": createDisabledPseudo( true ),
1663
"checked": function( elem ) {
1665
// In CSS3, :checked should return both checked and selected elements
1666
// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1667
var nodeName = elem.nodeName.toLowerCase();
1668
return ( nodeName === "input" && !!elem.checked ) ||
1669
( nodeName === "option" && !!elem.selected );
1672
"selected": function( elem ) {
1674
// Accessing this property makes selected-by-default
1675
// options in Safari work properly
1676
if ( elem.parentNode ) {
1677
// eslint-disable-next-line no-unused-expressions
1678
elem.parentNode.selectedIndex;
1681
return elem.selected === true;
1684
// Contents
1687
// http://www.w3.org/TR/selectors/#empty-pseudo
1688
// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
1689
// but not by others (comment: 8; processing instruction: 7; etc.)
1690
// nodeType < 6 works because attributes (2) do not appear as children
1691
for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1692
if ( elem.nodeType < 6 ) {
1693
return false;
1694
}
1695
}
1696
return true;
1699
"parent": function( elem ) {
1700
return !Expr.pseudos[ "empty" ]( elem );
1703
// Element/input types
1704
"header": function( elem ) {
1705
return rheader.test( elem.nodeName );
1708
"input": function( elem ) {
1709
return rinputs.test( elem.nodeName );
1713
var name = elem.nodeName.toLowerCase();
1714
return name === "input" && elem.type === "button" || name === "button";
1717
"text": function( elem ) {
1718
var attr;
1719
return elem.nodeName.toLowerCase() === "input" &&
1720
elem.type === "text" &&
1721
1722
// Support: IE<8
1723
// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
1724
( ( attr = elem.getAttribute( "type" ) ) == null ||
1725
attr.toLowerCase() === "text" );
1728
// Position-in-collection
1729
"first": createPositionalPseudo( function() {
1733
"last": createPositionalPseudo( function( _matchIndexes, length ) {
1737
"eq": createPositionalPseudo( function( _matchIndexes, length, argument ) {
1738
return [ argument < 0 ? argument + length : argument ];
1741
"even": createPositionalPseudo( function( matchIndexes, length ) {
Nov 16, 2012
1742
var i = 0;
1743
for ( ; i < length; i += 2 ) {
1749
"odd": createPositionalPseudo( function( matchIndexes, length ) {
Nov 16, 2012
1750
var i = 1;
1751
for ( ; i < length; i += 2 ) {
1752
matchIndexes.push( i );
1753
}
1754
return matchIndexes;
1757
"lt": createPositionalPseudo( function( matchIndexes, length, argument ) {
1758
var i = argument < 0 ?
1759
argument + length :
1760
argument > length ?
1761
length :
1762
argument;
Nov 16, 2012
1763
for ( ; --i >= 0; ) {
1764
matchIndexes.push( i );
1765
}
1766
return matchIndexes;
1769
"gt": createPositionalPseudo( function( matchIndexes, length, argument ) {
Nov 16, 2012
1770
var i = argument < 0 ? argument + length : argument;
1771
for ( ; ++i < length; ) {
1772
matchIndexes.push( i );
1773
}
1774
return matchIndexes;
1776
}
1777
};
1778
1779
Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ];
1781
// Add button/input type pseudos
1782
for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
1783
Expr.pseudos[ i ] = createInputPseudo( i );
1784
}
1785
for ( i in { submit: true, reset: true } ) {
1786
Expr.pseudos[ i ] = createButtonPseudo( i );
1787
}
1788
1789
// Easy API for creating new setFilters
1790
function setFilters() {}
1791
setFilters.prototype = Expr.filters = Expr.pseudos;
1792
Expr.setFilters = new setFilters();
1793
1794
tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
1795
var matched, match, tokens, type,
1796
soFar, groups, preFilters,
Dec 21, 2012
1797
cached = tokenCache[ selector + " " ];
1800
return parseOnly ? 0 : cached.slice( 0 );
1803
soFar = selector;
1804
groups = [];
1805
preFilters = Expr.preFilter;
1810
if ( !matched || ( match = rcomma.exec( soFar ) ) ) {
1813
// Don't consume trailing commas as valid
1814
soFar = soFar.slice( match[ 0 ].length ) || soFar;
1816
groups.push( ( tokens = [] ) );
1822
if ( ( match = rcombinators.exec( soFar ) ) ) {
1824
tokens.push( {
1827
// Cast descendant combinators to space
1828
type: match[ 0 ].replace( rtrim, " " )
1829
} );
1830
soFar = soFar.slice( matched.length );
1835
if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] ||
1836
( match = preFilters[ type ]( match ) ) ) ) {
1838
tokens.push( {
1843
soFar = soFar.slice( matched.length );
1852
// Return the length of the invalid excess
1853
// if we're just parsing
1854
// Otherwise, throw an error or return tokens
1855
return parseOnly ?
1856
soFar.length :
1857
soFar ?
1858
Sizzle.error( selector ) :
1861
tokenCache( selector, groups ).slice( 0 );
1864
function toSelector( tokens ) {
1865
var i = 0,
1866
len = tokens.length,
1867
selector = "";
1868
for ( ; i < len; i++ ) {
1869
selector += tokens[ i ].value;
1870
}
1871
return selector;
1872
}
1873
1874
function addCombinator( matcher, combinator, base ) {
1875
var dir = combinator.dir,
1876
skip = combinator.next,
1877
key = skip || dir,
1878
checkNonElements = base && key === "parentNode",
1883
// Check against closest ancestor/preceding element
1884
function( elem, context, xml ) {
1885
while ( ( elem = elem[ dir ] ) ) {
1886
if ( elem.nodeType === 1 || checkNonElements ) {
1887
return matcher( elem, context, xml );
1893
// Check against all ancestor/preceding elements
1894
function( elem, context, xml ) {
1895
var oldCache, uniqueCache, outerCache,
1896
newCache = [ dirruns, doneName ];
1898
// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
1900
while ( ( elem = elem[ dir ] ) ) {
1901
if ( elem.nodeType === 1 || checkNonElements ) {
1902
if ( matcher( elem, context, xml ) ) {
1903
return true;
1908
while ( ( elem = elem[ dir ] ) ) {
1909
if ( elem.nodeType === 1 || checkNonElements ) {
1910
outerCache = elem[ expando ] || ( elem[ expando ] = {} );
1911
1912
// Support: IE <9 only
1913
// Defend against cloned attroperties (jQuery gh-1709)
1914
uniqueCache = outerCache[ elem.uniqueID ] ||
1915
( outerCache[ elem.uniqueID ] = {} );
1917
if ( skip && skip === elem.nodeName.toLowerCase() ) {
1918
elem = elem[ dir ] || elem;
1919
} else if ( ( oldCache = uniqueCache[ key ] ) &&
1920
oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
1921
1922
// Assign to newCache so results back-propagate to previous elements
1923
return ( newCache[ 2 ] = oldCache[ 2 ] );
1926
// Reuse newcache so results back-propagate to previous elements
1928
1929
// A match means we're done; a fail means we have to keep checking
1930
if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) {
1941
function elementMatcher( matchers ) {
1942
return matchers.length > 1 ?
1943
function( elem, context, xml ) {
1944
var i = matchers.length;
1945
while ( i-- ) {
1946
if ( !matchers[ i ]( elem, context, xml ) ) {
1947
return false;
1948
}
1949
}
1950
return true;
1952
matchers[ 0 ];
1955
function multipleContexts( selector, contexts, results ) {
1956
var i = 0,
1957
len = contexts.length;
1958
for ( ; i < len; i++ ) {
1959
Sizzle( selector, contexts[ i ], results );
1960
}
1961
return results;
1962
}
1963
1964
function condense( unmatched, map, filter, context, xml ) {
1965
var elem,
1966
newUnmatched = [],
1967
i = 0,
1968
len = unmatched.length,
1969
mapped = map != null;
1970
1971
for ( ; i < len; i++ ) {
1972
if ( ( elem = unmatched[ i ] ) ) {
1973
if ( !filter || filter( elem, context, xml ) ) {
1974
newUnmatched.push( elem );
1975
if ( mapped ) {
1976
map.push( i );
1977
}
1978
}
1979
}
1980
}
1981
1982
return newUnmatched;
1983
}
1984
1985
function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
1986
if ( postFilter && !postFilter[ expando ] ) {
1987
postFilter = setMatcher( postFilter );
1989
if ( postFinder && !postFinder[ expando ] ) {
1990
postFinder = setMatcher( postFinder, postSelector );
1991
}
1992
return markFunction( function( seed, results, context, xml ) {
1994
preMap = [],
1995
postMap = [],
1996
preexisting = results.length,
1998
// Get initial elements from seed or context
1999
elems = seed || multipleContexts(
2000
selector || "*",
2001
context.nodeType ? [ context ] : context,
2002
[]
2003
),
2005
// Prefilter to get matcher input, preserving a map for seed-results synchronization
2006
matcherIn = preFilter && ( seed || !selector ) ?
2007
condense( elems, preMap, preFilter, context, xml ) :
2008
elems,
2012
// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2013
postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2015
// ...intermediate processing is necessary
2016
[] :
2018
// ...otherwise use results directly
2019
results :
2020
matcherIn;
2022
// Find primary matches
2023
if ( matcher ) {
2024
matcher( matcherIn, matcherOut, context, xml );
2025
}
2027
// Apply postFilter
2028
if ( postFilter ) {
2029
temp = condense( matcherOut, postMap );
2030
postFilter( temp, [], context, xml );
2032
// Un-match failing elements by moving them back to matcherIn
2035
if ( ( elem = temp[ i ] ) ) {
2036
matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem );
2037
}
2038
}
2039
}
2040
2041
if ( seed ) {
2042
if ( postFinder || preFilter ) {
2043
if ( postFinder ) {
2045
// Get the final matcherOut by condensing this intermediate into postFinder contexts
2046
temp = [];
2047
i = matcherOut.length;
2048
while ( i-- ) {
2049
if ( ( elem = matcherOut[ i ] ) ) {
2050
2051
// Restore matcherIn since elem is not yet a final match
2052
temp.push( ( matcherIn[ i ] = elem ) );
2055
postFinder( null, ( matcherOut = [] ), temp, xml );
2056
}
2057
2058
// Move matched elements from seed to results to keep them synchronized
2059
i = matcherOut.length;
2060
while ( i-- ) {
2061
if ( ( elem = matcherOut[ i ] ) &&
2062
( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) {
2064
seed[ temp ] = !( results[ temp ] = elem );
2068
2069
// Add elements to results, through postFinder if defined
2070
} else {
2071
matcherOut = condense(
2072
matcherOut === results ?
2073
matcherOut.splice( preexisting, matcherOut.length ) :
2074
matcherOut
2075
);
2076
if ( postFinder ) {
2077
postFinder( null, results, matcherOut, xml );
2078
} else {
2079
push.apply( results, matcherOut );
2080
}
2081
}
2085
function matcherFromTokens( tokens ) {
2086
var checkContext, matcher, j,
2087
len = tokens.length,
2088
leadingRelative = Expr.relative[ tokens[ 0 ].type ],
2089
implicitRelative = leadingRelative || Expr.relative[ " " ],
2090
i = leadingRelative ? 1 : 0,
2091
2092
// The foundational matcher ensures that elements are reachable from top-level context(s)
2093
matchContext = addCombinator( function( elem ) {
2094
return elem === checkContext;
2096
matchAnyContext = addCombinator( function( elem ) {
2097
return indexOf( checkContext, elem ) > -1;
2099
matchers = [ function( elem, context, xml ) {
2100
var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
2101
( checkContext = context ).nodeType ?
2102
matchContext( elem, context, xml ) :
2103
matchAnyContext( elem, context, xml ) );
2105
// Avoid hanging onto element (issue #299)
2106
checkContext = null;
2107
return ret;
2108
} ];
2109
2110
for ( ; i < len; i++ ) {
2111
if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) {
2112
matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
2114
matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches );
2115
2116
// Return special upon seeing a positional matcher
2117
if ( matcher[ expando ] ) {
2119
// Find the next relative operator (if any) for proper handling
2120
j = ++i;
2121
for ( ; j < len; j++ ) {
2122
if ( Expr.relative[ tokens[ j ].type ] ) {
2123
break;
2124
}
2125
}
2126
return setMatcher(
2127
i > 1 && elementMatcher( matchers ),
2129
2130
// If the preceding token was a descendant combinator, insert an implicit any-element `*`
2131
tokens
2132
.slice( 0, i - 1 )
2133
.concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } )
2135
matcher,
2136
i < j && matcherFromTokens( tokens.slice( i, j ) ),
2137
j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),
2138
j < len && toSelector( tokens )
2139
);
2140
}
2141
matchers.push( matcher );
2142
}
2145
return elementMatcher( matchers );
2148
function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2149
var bySet = setMatchers.length > 0,
2150
byElement = elementMatchers.length > 0,
2151
superMatcher = function( seed, context, xml, results, outermost ) {
2152
var elem, j, matcher,
2153
matchedCount = 0,
2154
i = "0",
2155
unmatched = seed && [],
2157
contextBackup = outermostContext,
2159
// We must always have either seed elements or outermost context
2160
elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ),
2161
2162
// Use integer dirruns iff this is the outermost matcher
2163
dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ),
2167
2168
// Support: IE 11+, Edge 17 - 18+
2169
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
2170
// two documents; shallow comparisons work.
2171
// eslint-disable-next-line eqeqeq
2172
outermostContext = context == document || context || outermost;
2175
// Add elements passing elementMatchers directly to results
2176
// Support: IE<9, Safari
2177
// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
2178
for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) {
2181
2182
// Support: IE 11+, Edge 17 - 18+
2183
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
2184
// two documents; shallow comparisons work.
2185
// eslint-disable-next-line eqeqeq
2186
if ( !context && elem.ownerDocument != document ) {
2187
setDocument( elem );
2188
xml = !documentIsHTML;
2190
while ( ( matcher = elementMatchers[ j++ ] ) ) {
2191
if ( matcher( elem, context || document, xml ) ) {
2192
results.push( elem );
2193
break;
2195
}
2196
if ( outermost ) {
2197
dirruns = dirrunsUnique;
2198
}
2199
}
2201
// Track unmatched elements for set filters
2202
if ( bySet ) {
2204
// They will have gone through all possible matchers
2205
if ( ( elem = !matcher && elem ) ) {
2206
matchedCount--;
2207
}
2208
2209
// Lengthen the array for every element, matched or not
2210
if ( seed ) {
2211
unmatched.push( elem );
2212
}
2213
}
2214
}
2216
// `i` is now the count of elements visited above, and adding it to `matchedCount`
2217
// makes the latter nonnegative.
2219
2220
// Apply set filters to unmatched elements
2221
// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
2222
// equals `i`), unless we didn't visit _any_ elements in the above loop because we have
2223
// no element matchers and no seed.
2224
// Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
2225
// case, which will result in a "00" `matchedCount` that differs from `i` but is also
2226
// numerically zero.
2227
if ( bySet && i !== matchedCount ) {
2229
while ( ( matcher = setMatchers[ j++ ] ) ) {
2230
matcher( unmatched, setMatched, context, xml );
2231
}
2232
2235
// Reintegrate element matches to eliminate the need for sorting
2236
if ( matchedCount > 0 ) {
2237
while ( i-- ) {
2238
if ( !( unmatched[ i ] || setMatched[ i ] ) ) {
2239
setMatched[ i ] = pop.call( results );
2243
2244
// Discard index placeholder values to get only actual matches
2245
setMatched = condense( setMatched );
2248
// Add matches to results
2249
push.apply( results, setMatched );
2250
2251
// Seedless set matches succeeding multiple successful matchers stipulate sorting
2252
if ( outermost && !seed && setMatched.length > 0 &&
2253
( matchedCount + setMatchers.length ) > 1 ) {
2254
2255
Sizzle.uniqueSort( results );
2256
}
2259
// Override manipulation of globals by nested matchers
2260
if ( outermost ) {
2261
dirruns = dirrunsUnique;
2262
outermostContext = contextBackup;
2265
return unmatched;
2266
};
2267
2268
return bySet ?
2269
markFunction( superMatcher ) :
2270
superMatcher;
2271
}
2272
2273
compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
2274
var i,
2275
setMatchers = [],
2276
elementMatchers = [],
Dec 21, 2012
2277
cached = compilerCache[ selector + " " ];
2281
// Generate a function of recursive functions that can be used to check each element
2282
if ( !match ) {
2283
match = tokenize( selector );
2285
i = match.length;
2287
cached = matcherFromTokens( match[ i ] );
2288
if ( cached[ expando ] ) {
2289
setMatchers.push( cached );
2291
elementMatchers.push( cached );
2294
2295
// Cache the compiled function
2296
cached = compilerCache(
2297
selector,
2298
matcherFromGroupMatchers( elementMatchers, setMatchers )
2299
);
2300
2301
// Save selector and tokenization
2302
cached.selector = selector;
2307
/**
2308
* A low-level selection function that works with Sizzle's compiled
2309
* selector functions
2310
* @param {String|Function} selector A selector or a pre-compiled
2311
* selector function built with Sizzle.compile
2312
* @param {Element} context
2313
* @param {Array} [results]
2314
* @param {Array} [seed] A set of elements to match against
2315
*/
2316
select = Sizzle.select = function( selector, context, results, seed ) {
2317
var i, tokens, token, type, find,
2318
compiled = typeof selector === "function" && selector,
2319
match = !seed && tokenize( ( selector = compiled.selector || selector ) );
2321
results = results || [];
2322
2323
// Try to minimize operations if there is only one selector in the list and no seed
2324
// (the latter of which guarantees us context)
2325
if ( match.length === 1 ) {
2327
// Reduce context if the leading compound selector is an ID
2328
tokens = match[ 0 ] = match[ 0 ].slice( 0 );
2329
if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" &&
2330
context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {
2332
context = ( Expr.find[ "ID" ]( token.matches[ 0 ]
2333
.replace( runescape, funescape ), context ) || [] )[ 0 ];
2334
if ( !context ) {
2335
return results;
2337
// Precompiled matchers will still verify ancestry, so step up a level
2338
} else if ( compiled ) {
2339
context = context.parentNode;
2342
selector = selector.slice( tokens.shift().value.length );
2343
}
2345
// Fetch a seed set for right-to-left matching
2346
i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length;
2348
token = tokens[ i ];
2350
// Abort if we hit a combinator
2351
if ( Expr.relative[ ( type = token.type ) ] ) {
2354
if ( ( find = Expr.find[ type ] ) ) {
2355
2356
// Search, expanding context for leading sibling combinators
2357
if ( ( seed = find(
2358
token.matches[ 0 ].replace( runescape, funescape ),
2359
rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) ||
2360
context
2361
) ) ) {
2362
2363
// If seed is empty or no tokens remain, we can return early
2364
tokens.splice( i, 1 );
2365
selector = seed.length && toSelector( tokens );
2366
if ( !selector ) {
2367
push.apply( results, seed );
2368
return results;
2373
}
2374
}
2375
}
2377
// Compile and execute a filtering function if one is not provided
2378
// Provide `match` to avoid retokenization if we modified the selector above
2379
( compiled || compile( selector, match ) )(
2382
!documentIsHTML,
2384
!context || rsibling.test( selector ) && testContext( context.parentNode ) || context
2386
return results;
2389
// One-time assignments
2390
2391
// Sort stability
2392
support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando;
2394
// Support: Chrome 14-35+
2395
// Always assume duplicates if they aren't passed to the comparison function
2396
support.detectDuplicates = !!hasDuplicate;
2398
// Initialize against the default document
2399
setDocument();
2400
2401
// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2402
// Detached nodes confoundingly follow *each other*
2403
support.sortDetached = assert( function( el ) {
2404
2405
// Should return 1, but returns 4 (following)
2406
return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1;
2407
} );
2408
2409
// Support: IE<8
2410
// Prevent attribute/property "interpolation"
2411
// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2412
if ( !assert( function( el ) {
2413
el.innerHTML = "<a href='#'></a>";
2414
return el.firstChild.getAttribute( "href" ) === "#";
2415
} ) ) {
2416
addHandle( "type|href|height|width", function( elem, name, isXML ) {
2417
if ( !isXML ) {
2418
return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
2419
}
2421
}
2422
2423
// Support: IE<9
2424
// Use defaultValue in place of getAttribute("value")
2425
if ( !support.attributes || !assert( function( el ) {
2426
el.innerHTML = "<input/>";
2427
el.firstChild.setAttribute( "value", "" );
2428
return el.firstChild.getAttribute( "value" ) === "";
2430
addHandle( "value", function( elem, _name, isXML ) {
2431
if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2432
return elem.defaultValue;
2433
}
2435
}
2436
2437
// Support: IE<9
2438
// Use getAttributeNode to fetch booleans when getAttribute lies
2439
if ( !assert( function( el ) {
2440
return el.getAttribute( "disabled" ) == null;
2441
} ) ) {
2442
addHandle( booleans, function( elem, name, isXML ) {
2444
if ( !isXML ) {
2445
return elem[ name ] === true ? name.toLowerCase() :
2446
( val = elem.getAttributeNode( name ) ) && val.specified ?
2447
val.value :
2451
}
2452
2454
var _sizzle = window.Sizzle;
2455
2456
Sizzle.noConflict = function() {
2457
if ( window.Sizzle === Sizzle ) {
2458
window.Sizzle = _sizzle;
2459
}
2460
2461
return Sizzle;
2462
};
2463
2464
if ( typeof define === "function" && define.amd ) {
2465
define( function() {
2466
return Sizzle;
2467
} );
2468
2469
// Sizzle requires that there be a global window in Common-JS like environments
2470
} else if ( typeof module !== "undefined" && module.exports ) {
2471
module.exports = Sizzle;
2472
} else {
2473
window.Sizzle = Sizzle;
2474
}
2478
} )( window );