· 8 years ago · Aug 20, 2018, 09:54 AM
1/*!
2 * jQuery JavaScript Library v3.2.1
3 * https://jquery.com/
4 *
5 * Includes Sizzle.js
6 * https://sizzlejs.com/
7 *
8 * Copyright JS Foundation and other contributors
9 * Released under the MIT license
10 * https://jquery.org/license
11 *
12 * Date: 2017-03-20T18:59Z
13 */
14( function( global, factory ) {
15
16 "use strict";
17
18 if ( typeof module === "object" && typeof module.exports === "object" ) {
19
20 // For CommonJS and CommonJS-like environments where a proper `window`
21 // is present, execute the factory and get jQuery.
22 // For environments that do not have a `window` with a `document`
23 // (such as Node.js), expose a factory as module.exports.
24 // This accentuates the need for the creation of a real `window`.
25 // e.g. var jQuery = require("jquery")(window);
26 // See ticket #14549 for more info.
27 module.exports = global.document ?
28 factory( global, true ) :
29 function( w ) {
30 if ( !w.document ) {
31 throw new Error( "jQuery requires a window with a document" );
32 }
33 return factory( w );
34 };
35 } else {
36 factory( global );
37 }
38
39// Pass this if window is not defined yet
40} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
41
42// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
43// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
44// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
45// enough that all such attempts are guarded in a try block.
46"use strict";
47
48var arr = [];
49
50var document = window.document;
51
52var getProto = Object.getPrototypeOf;
53
54var slice = arr.slice;
55
56var concat = arr.concat;
57
58var push = arr.push;
59
60var indexOf = arr.indexOf;
61
62var class2type = {};
63
64var toString = class2type.toString;
65
66var hasOwn = class2type.hasOwnProperty;
67
68var fnToString = hasOwn.toString;
69
70var ObjectFunctionString = fnToString.call( Object );
71
72var support = {};
73
74
75
76 function DOMEval( code, doc ) {
77 doc = doc || document;
78
79 var script = doc.createElement( "script" );
80
81 script.text = code;
82 doc.head.appendChild( script ).parentNode.removeChild( script );
83 }
84/* global Symbol */
85// Defining this global in .eslintrc.json would create a danger of using the global
86// unguarded in another place, it seems safer to define global only for this module
87
88
89
90var
91 version = "3.2.1",
92
93 // Define a local copy of jQuery
94 jQuery = function( selector, context ) {
95
96 // The jQuery object is actually just the init constructor 'enhanced'
97 // Need init if jQuery is called (just allow error to be thrown if not included)
98 return new jQuery.fn.init( selector, context );
99 },
100
101 // Support: Android <=4.0 only
102 // Make sure we trim BOM and NBSP
103 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
104
105 // Matches dashed string for camelizing
106 rmsPrefix = /^-ms-/,
107 rdashAlpha = /-([a-z])/g,
108
109 // Used by jQuery.camelCase as callback to replace()
110 fcamelCase = function( all, letter ) {
111 return letter.toUpperCase();
112 };
113
114jQuery.fn = jQuery.prototype = {
115
116 // The current version of jQuery being used
117 jquery: version,
118
119 constructor: jQuery,
120
121 // The default length of a jQuery object is 0
122 length: 0,
123
124 toArray: function() {
125 return slice.call( this );
126 },
127
128 // Get the Nth element in the matched element set OR
129 // Get the whole matched element set as a clean array
130 get: function( num ) {
131
132 // Return all the elements in a clean array
133 if ( num == null ) {
134 return slice.call( this );
135 }
136
137 // Return just the one element from the set
138 return num < 0 ? this[ num + this.length ] : this[ num ];
139 },
140
141 // Take an array of elements and push it onto the stack
142 // (returning the new matched element set)
143 pushStack: function( elems ) {
144
145 // Build a new jQuery matched element set
146 var ret = jQuery.merge( this.constructor(), elems );
147
148 // Add the old object onto the stack (as a reference)
149 ret.prevObject = this;
150
151 // Return the newly-formed element set
152 return ret;
153 },
154
155 // Execute a callback for every element in the matched set.
156 each: function( callback ) {
157 return jQuery.each( this, callback );
158 },
159
160 map: function( callback ) {
161 return this.pushStack( jQuery.map( this, function( elem, i ) {
162 return callback.call( elem, i, elem );
163 } ) );
164 },
165
166 slice: function() {
167 return this.pushStack( slice.apply( this, arguments ) );
168 },
169
170 first: function() {
171 return this.eq( 0 );
172 },
173
174 last: function() {
175 return this.eq( -1 );
176 },
177
178 eq: function( i ) {
179 var len = this.length,
180 j = +i + ( i < 0 ? len : 0 );
181 return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
182 },
183
184 end: function() {
185 return this.prevObject || this.constructor();
186 },
187
188 // For internal use only.
189 // Behaves like an Array's method, not like a jQuery method.
190 push: push,
191 sort: arr.sort,
192 splice: arr.splice
193};
194
195jQuery.extend = jQuery.fn.extend = function() {
196 var options, name, src, copy, copyIsArray, clone,
197 target = arguments[ 0 ] || {},
198 i = 1,
199 length = arguments.length,
200 deep = false;
201
202 // Handle a deep copy situation
203 if ( typeof target === "boolean" ) {
204 deep = target;
205
206 // Skip the boolean and the target
207 target = arguments[ i ] || {};
208 i++;
209 }
210
211 // Handle case when target is a string or something (possible in deep copy)
212 if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
213 target = {};
214 }
215
216 // Extend jQuery itself if only one argument is passed
217 if ( i === length ) {
218 target = this;
219 i--;
220 }
221
222 for ( ; i < length; i++ ) {
223
224 // Only deal with non-null/undefined values
225 if ( ( options = arguments[ i ] ) != null ) {
226
227 // Extend the base object
228 for ( name in options ) {
229 src = target[ name ];
230 copy = options[ name ];
231
232 // Prevent never-ending loop
233 if ( target === copy ) {
234 continue;
235 }
236
237 // Recurse if we're merging plain objects or arrays
238 if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
239 ( copyIsArray = Array.isArray( copy ) ) ) ) {
240
241 if ( copyIsArray ) {
242 copyIsArray = false;
243 clone = src && Array.isArray( src ) ? src : [];
244
245 } else {
246 clone = src && jQuery.isPlainObject( src ) ? src : {};
247 }
248
249 // Never move original objects, clone them
250 target[ name ] = jQuery.extend( deep, clone, copy );
251
252 // Don't bring in undefined values
253 } else if ( copy !== undefined ) {
254 target[ name ] = copy;
255 }
256 }
257 }
258 }
259
260 // Return the modified object
261 return target;
262};
263
264jQuery.extend( {
265
266 // Unique for each copy of jQuery on the page
267 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
268
269 // Assume jQuery is ready without the ready module
270 isReady: true,
271
272 error: function( msg ) {
273 throw new Error( msg );
274 },
275
276 noop: function() {},
277
278 isFunction: function( obj ) {
279 return jQuery.type( obj ) === "function";
280 },
281
282 isWindow: function( obj ) {
283 return obj != null && obj === obj.window;
284 },
285
286 isNumeric: function( obj ) {
287
288 // As of jQuery 3.0, isNumeric is limited to
289 // strings and numbers (primitives or objects)
290 // that can be coerced to finite numbers (gh-2662)
291 var type = jQuery.type( obj );
292 return ( type === "number" || type === "string" ) &&
293
294 // parseFloat NaNs numeric-cast false positives ("")
295 // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
296 // subtraction forces infinities to NaN
297 !isNaN( obj - parseFloat( obj ) );
298 },
299
300 isPlainObject: function( obj ) {
301 var proto, Ctor;
302
303 // Detect obvious negatives
304 // Use toString instead of jQuery.type to catch host objects
305 if ( !obj || toString.call( obj ) !== "[object Object]" ) {
306 return false;
307 }
308
309 proto = getProto( obj );
310
311 // Objects with no prototype (e.g., `Object.create( null )`) are plain
312 if ( !proto ) {
313 return true;
314 }
315
316 // Objects with prototype are plain iff they were constructed by a global Object function
317 Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
318 return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
319 },
320
321 isEmptyObject: function( obj ) {
322
323 /* eslint-disable no-unused-vars */
324 // See https://github.com/eslint/eslint/issues/6125
325 var name;
326
327 for ( name in obj ) {
328 return false;
329 }
330 return true;
331 },
332
333 type: function( obj ) {
334 if ( obj == null ) {
335 return obj + "";
336 }
337
338 // Support: Android <=2.3 only (functionish RegExp)
339 return typeof obj === "object" || typeof obj === "function" ?
340 class2type[ toString.call( obj ) ] || "object" :
341 typeof obj;
342 },
343
344 // Evaluates a script in a global context
345 globalEval: function( code ) {
346 DOMEval( code );
347 },
348
349 // Convert dashed to camelCase; used by the css and data modules
350 // Support: IE <=9 - 11, Edge 12 - 13
351 // Microsoft forgot to hump their vendor prefix (#9572)
352 camelCase: function( string ) {
353 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
354 },
355
356 each: function( obj, callback ) {
357 var length, i = 0;
358
359 if ( isArrayLike( obj ) ) {
360 length = obj.length;
361 for ( ; i < length; i++ ) {
362 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
363 break;
364 }
365 }
366 } else {
367 for ( i in obj ) {
368 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
369 break;
370 }
371 }
372 }
373
374 return obj;
375 },
376
377 // Support: Android <=4.0 only
378 trim: function( text ) {
379 return text == null ?
380 "" :
381 ( text + "" ).replace( rtrim, "" );
382 },
383
384 // results is for internal usage only
385 makeArray: function( arr, results ) {
386 var ret = results || [];
387
388 if ( arr != null ) {
389 if ( isArrayLike( Object( arr ) ) ) {
390 jQuery.merge( ret,
391 typeof arr === "string" ?
392 [ arr ] : arr
393 );
394 } else {
395 push.call( ret, arr );
396 }
397 }
398
399 return ret;
400 },
401
402 inArray: function( elem, arr, i ) {
403 return arr == null ? -1 : indexOf.call( arr, elem, i );
404 },
405
406 // Support: Android <=4.0 only, PhantomJS 1 only
407 // push.apply(_, arraylike) throws on ancient WebKit
408 merge: function( first, second ) {
409 var len = +second.length,
410 j = 0,
411 i = first.length;
412
413 for ( ; j < len; j++ ) {
414 first[ i++ ] = second[ j ];
415 }
416
417 first.length = i;
418
419 return first;
420 },
421
422 grep: function( elems, callback, invert ) {
423 var callbackInverse,
424 matches = [],
425 i = 0,
426 length = elems.length,
427 callbackExpect = !invert;
428
429 // Go through the array, only saving the items
430 // that pass the validator function
431 for ( ; i < length; i++ ) {
432 callbackInverse = !callback( elems[ i ], i );
433 if ( callbackInverse !== callbackExpect ) {
434 matches.push( elems[ i ] );
435 }
436 }
437
438 return matches;
439 },
440
441 // arg is for internal usage only
442 map: function( elems, callback, arg ) {
443 var length, value,
444 i = 0,
445 ret = [];
446
447 // Go through the array, translating each of the items to their new values
448 if ( isArrayLike( elems ) ) {
449 length = elems.length;
450 for ( ; i < length; i++ ) {
451 value = callback( elems[ i ], i, arg );
452
453 if ( value != null ) {
454 ret.push( value );
455 }
456 }
457
458 // Go through every key on the object,
459 } else {
460 for ( i in elems ) {
461 value = callback( elems[ i ], i, arg );
462
463 if ( value != null ) {
464 ret.push( value );
465 }
466 }
467 }
468
469 // Flatten any nested arrays
470 return concat.apply( [], ret );
471 },
472
473 // A global GUID counter for objects
474 guid: 1,
475
476 // Bind a function to a context, optionally partially applying any
477 // arguments.
478 proxy: function( fn, context ) {
479 var tmp, args, proxy;
480
481 if ( typeof context === "string" ) {
482 tmp = fn[ context ];
483 context = fn;
484 fn = tmp;
485 }
486
487 // Quick check to determine if target is callable, in the spec
488 // this throws a TypeError, but we will just return undefined.
489 if ( !jQuery.isFunction( fn ) ) {
490 return undefined;
491 }
492
493 // Simulated bind
494 args = slice.call( arguments, 2 );
495 proxy = function() {
496 return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
497 };
498
499 // Set the guid of unique handler to the same of original handler, so it can be removed
500 proxy.guid = fn.guid = fn.guid || jQuery.guid++;
501
502 return proxy;
503 },
504
505 now: Date.now,
506
507 // jQuery.support is not used in Core but other projects attach their
508 // properties to it so it needs to exist.
509 support: support
510} );
511
512if ( typeof Symbol === "function" ) {
513 jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
514}
515
516// Populate the class2type map
517jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
518function( i, name ) {
519 class2type[ "[object " + name + "]" ] = name.toLowerCase();
520} );
521
522function isArrayLike( obj ) {
523
524 // Support: real iOS 8.2 only (not reproducible in simulator)
525 // `in` check used to prevent JIT error (gh-2145)
526 // hasOwn isn't used here due to false negatives
527 // regarding Nodelist length in IE
528 var length = !!obj && "length" in obj && obj.length,
529 type = jQuery.type( obj );
530
531 if ( type === "function" || jQuery.isWindow( obj ) ) {
532 return false;
533 }
534
535 return type === "array" || length === 0 ||
536 typeof length === "number" && length > 0 && ( length - 1 ) in obj;
537}
538var Sizzle =
539/*!
540 * Sizzle CSS Selector Engine v2.3.3
541 * https://sizzlejs.com/
542 *
543 * Copyright jQuery Foundation and other contributors
544 * Released under the MIT license
545 * http://jquery.org/license
546 *
547 * Date: 2016-08-08
548 */
549(function( window ) {
550
551var i,
552 support,
553 Expr,
554 getText,
555 isXML,
556 tokenize,
557 compile,
558 select,
559 outermostContext,
560 sortInput,
561 hasDuplicate,
562
563 // Local document vars
564 setDocument,
565 document,
566 docElem,
567 documentIsHTML,
568 rbuggyQSA,
569 rbuggyMatches,
570 matches,
571 contains,
572
573 // Instance-specific data
574 expando = "sizzle" + 1 * new Date(),
575 preferredDoc = window.document,
576 dirruns = 0,
577 done = 0,
578 classCache = createCache(),
579 tokenCache = createCache(),
580 compilerCache = createCache(),
581 sortOrder = function( a, b ) {
582 if ( a === b ) {
583 hasDuplicate = true;
584 }
585 return 0;
586 },
587
588 // Instance methods
589 hasOwn = ({}).hasOwnProperty,
590 arr = [],
591 pop = arr.pop,
592 push_native = arr.push,
593 push = arr.push,
594 slice = arr.slice,
595 // Use a stripped-down indexOf as it's faster than native
596 // https://jsperf.com/thor-indexof-vs-for/5
597 indexOf = function( list, elem ) {
598 var i = 0,
599 len = list.length;
600 for ( ; i < len; i++ ) {
601 if ( list[i] === elem ) {
602 return i;
603 }
604 }
605 return -1;
606 },
607
608 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
609
610 // Regular expressions
611
612 // http://www.w3.org/TR/css3-selectors/#whitespace
613 whitespace = "[\\x20\\t\\r\\n\\f]",
614
615 // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
616 identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
617
618 // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
619 attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
620 // Operator (capture 2)
621 "*([*^$|!~]?=)" + whitespace +
622 // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
623 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
624 "*\\]",
625
626 pseudos = ":(" + identifier + ")(?:\\((" +
627 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
628 // 1. quoted (capture 3; capture 4 or capture 5)
629 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
630 // 2. simple (capture 6)
631 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
632 // 3. anything else (capture 2)
633 ".*" +
634 ")\\)|)",
635
636 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
637 rwhitespace = new RegExp( whitespace + "+", "g" ),
638 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
639
640 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
641 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
642
643 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
644
645 rpseudo = new RegExp( pseudos ),
646 ridentifier = new RegExp( "^" + identifier + "$" ),
647
648 matchExpr = {
649 "ID": new RegExp( "^#(" + identifier + ")" ),
650 "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
651 "TAG": new RegExp( "^(" + identifier + "|[*])" ),
652 "ATTR": new RegExp( "^" + attributes ),
653 "PSEUDO": new RegExp( "^" + pseudos ),
654 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
655 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
656 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
657 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
658 // For use in libraries implementing .is()
659 // We use this for POS matching in `select`
660 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
661 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
662 },
663
664 rinputs = /^(?:input|select|textarea|button)$/i,
665 rheader = /^h\d$/i,
666
667 rnative = /^[^{]+\{\s*\[native \w/,
668
669 // Easily-parseable/retrievable ID or TAG or CLASS selectors
670 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
671
672 rsibling = /[+~]/,
673
674 // CSS escapes
675 // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
676 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
677 funescape = function( _, escaped, escapedWhitespace ) {
678 var high = "0x" + escaped - 0x10000;
679 // NaN means non-codepoint
680 // Support: Firefox<24
681 // Workaround erroneous numeric interpretation of +"0x"
682 return high !== high || escapedWhitespace ?
683 escaped :
684 high < 0 ?
685 // BMP codepoint
686 String.fromCharCode( high + 0x10000 ) :
687 // Supplemental Plane codepoint (surrogate pair)
688 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
689 },
690
691 // CSS string/identifier serialization
692 // https://drafts.csswg.org/cssom/#common-serializing-idioms
693 rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
694 fcssescape = function( ch, asCodePoint ) {
695 if ( asCodePoint ) {
696
697 // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
698 if ( ch === "\0" ) {
699 return "\uFFFD";
700 }
701
702 // Control characters and (dependent upon position) numbers get escaped as code points
703 return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
704 }
705
706 // Other potentially-special ASCII characters get backslash-escaped
707 return "\\" + ch;
708 },
709
710 // Used for iframes
711 // See setDocument()
712 // Removing the function wrapper causes a "Permission Denied"
713 // error in IE
714 unloadHandler = function() {
715 setDocument();
716 },
717
718 disabledAncestor = addCombinator(
719 function( elem ) {
720 return elem.disabled === true && ("form" in elem || "label" in elem);
721 },
722 { dir: "parentNode", next: "legend" }
723 );
724
725// Optimize for push.apply( _, NodeList )
726try {
727 push.apply(
728 (arr = slice.call( preferredDoc.childNodes )),
729 preferredDoc.childNodes
730 );
731 // Support: Android<4.0
732 // Detect silently failing push.apply
733 arr[ preferredDoc.childNodes.length ].nodeType;
734} catch ( e ) {
735 push = { apply: arr.length ?
736
737 // Leverage slice if possible
738 function( target, els ) {
739 push_native.apply( target, slice.call(els) );
740 } :
741
742 // Support: IE<9
743 // Otherwise append directly
744 function( target, els ) {
745 var j = target.length,
746 i = 0;
747 // Can't trust NodeList.length
748 while ( (target[j++] = els[i++]) ) {}
749 target.length = j - 1;
750 }
751 };
752}
753
754function Sizzle( selector, context, results, seed ) {
755 var m, i, elem, nid, match, groups, newSelector,
756 newContext = context && context.ownerDocument,
757
758 // nodeType defaults to 9, since context defaults to document
759 nodeType = context ? context.nodeType : 9;
760
761 results = results || [];
762
763 // Return early from calls with invalid selector or context
764 if ( typeof selector !== "string" || !selector ||
765 nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
766
767 return results;
768 }
769
770 // Try to shortcut find operations (as opposed to filters) in HTML documents
771 if ( !seed ) {
772
773 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
774 setDocument( context );
775 }
776 context = context || document;
777
778 if ( documentIsHTML ) {
779
780 // If the selector is sufficiently simple, try using a "get*By*" DOM method
781 // (excepting DocumentFragment context, where the methods don't exist)
782 if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
783
784 // ID selector
785 if ( (m = match[1]) ) {
786
787 // Document context
788 if ( nodeType === 9 ) {
789 if ( (elem = context.getElementById( m )) ) {
790
791 // Support: IE, Opera, Webkit
792 // TODO: identify versions
793 // getElementById can match elements by name instead of ID
794 if ( elem.id === m ) {
795 results.push( elem );
796 return results;
797 }
798 } else {
799 return results;
800 }
801
802 // Element context
803 } else {
804
805 // Support: IE, Opera, Webkit
806 // TODO: identify versions
807 // getElementById can match elements by name instead of ID
808 if ( newContext && (elem = newContext.getElementById( m )) &&
809 contains( context, elem ) &&
810 elem.id === m ) {
811
812 results.push( elem );
813 return results;
814 }
815 }
816
817 // Type selector
818 } else if ( match[2] ) {
819 push.apply( results, context.getElementsByTagName( selector ) );
820 return results;
821
822 // Class selector
823 } else if ( (m = match[3]) && support.getElementsByClassName &&
824 context.getElementsByClassName ) {
825
826 push.apply( results, context.getElementsByClassName( m ) );
827 return results;
828 }
829 }
830
831 // Take advantage of querySelectorAll
832 if ( support.qsa &&
833 !compilerCache[ selector + " " ] &&
834 (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
835
836 if ( nodeType !== 1 ) {
837 newContext = context;
838 newSelector = selector;
839
840 // qSA looks outside Element context, which is not what we want
841 // Thanks to Andrew Dupont for this workaround technique
842 // Support: IE <=8
843 // Exclude object elements
844 } else if ( context.nodeName.toLowerCase() !== "object" ) {
845
846 // Capture the context ID, setting it first if necessary
847 if ( (nid = context.getAttribute( "id" )) ) {
848 nid = nid.replace( rcssescape, fcssescape );
849 } else {
850 context.setAttribute( "id", (nid = expando) );
851 }
852
853 // Prefix every selector in the list
854 groups = tokenize( selector );
855 i = groups.length;
856 while ( i-- ) {
857 groups[i] = "#" + nid + " " + toSelector( groups[i] );
858 }
859 newSelector = groups.join( "," );
860
861 // Expand context for sibling selectors
862 newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
863 context;
864 }
865
866 if ( newSelector ) {
867 try {
868 push.apply( results,
869 newContext.querySelectorAll( newSelector )
870 );
871 return results;
872 } catch ( qsaError ) {
873 } finally {
874 if ( nid === expando ) {
875 context.removeAttribute( "id" );
876 }
877 }
878 }
879 }
880 }
881 }
882
883 // All others
884 return select( selector.replace( rtrim, "$1" ), context, results, seed );
885}
886
887/**
888 * Create key-value caches of limited size
889 * @returns {function(string, object)} Returns the Object data after storing it on itself with
890 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
891 * deleting the oldest entry
892 */
893function createCache() {
894 var keys = [];
895
896 function cache( key, value ) {
897 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
898 if ( keys.push( key + " " ) > Expr.cacheLength ) {
899 // Only keep the most recent entries
900 delete cache[ keys.shift() ];
901 }
902 return (cache[ key + " " ] = value);
903 }
904 return cache;
905}
906
907/**
908 * Mark a function for special use by Sizzle
909 * @param {Function} fn The function to mark
910 */
911function markFunction( fn ) {
912 fn[ expando ] = true;
913 return fn;
914}
915
916/**
917 * Support testing using an element
918 * @param {Function} fn Passed the created element and returns a boolean result
919 */
920function assert( fn ) {
921 var el = document.createElement("fieldset");
922
923 try {
924 return !!fn( el );
925 } catch (e) {
926 return false;
927 } finally {
928 // Remove from its parent by default
929 if ( el.parentNode ) {
930 el.parentNode.removeChild( el );
931 }
932 // release memory in IE
933 el = null;
934 }
935}
936
937/**
938 * Adds the same handler for all of the specified attrs
939 * @param {String} attrs Pipe-separated list of attributes
940 * @param {Function} handler The method that will be applied
941 */
942function addHandle( attrs, handler ) {
943 var arr = attrs.split("|"),
944 i = arr.length;
945
946 while ( i-- ) {
947 Expr.attrHandle[ arr[i] ] = handler;
948 }
949}
950
951/**
952 * Checks document order of two siblings
953 * @param {Element} a
954 * @param {Element} b
955 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
956 */
957function siblingCheck( a, b ) {
958 var cur = b && a,
959 diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
960 a.sourceIndex - b.sourceIndex;
961
962 // Use IE sourceIndex if available on both nodes
963 if ( diff ) {
964 return diff;
965 }
966
967 // Check if b follows a
968 if ( cur ) {
969 while ( (cur = cur.nextSibling) ) {
970 if ( cur === b ) {
971 return -1;
972 }
973 }
974 }
975
976 return a ? 1 : -1;
977}
978
979/**
980 * Returns a function to use in pseudos for input types
981 * @param {String} type
982 */
983function createInputPseudo( type ) {
984 return function( elem ) {
985 var name = elem.nodeName.toLowerCase();
986 return name === "input" && elem.type === type;
987 };
988}
989
990/**
991 * Returns a function to use in pseudos for buttons
992 * @param {String} type
993 */
994function createButtonPseudo( type ) {
995 return function( elem ) {
996 var name = elem.nodeName.toLowerCase();
997 return (name === "input" || name === "button") && elem.type === type;
998 };
999}
1000
1001/**
1002 * Returns a function to use in pseudos for :enabled/:disabled
1003 * @param {Boolean} disabled true for :disabled; false for :enabled
1004 */
1005function createDisabledPseudo( disabled ) {
1006
1007 // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
1008 return function( elem ) {
1009
1010 // Only certain elements can match :enabled or :disabled
1011 // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
1012 // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
1013 if ( "form" in elem ) {
1014
1015 // Check for inherited disabledness on relevant non-disabled elements:
1016 // * listed form-associated elements in a disabled fieldset
1017 // https://html.spec.whatwg.org/multipage/forms.html#category-listed
1018 // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
1019 // * option elements in a disabled optgroup
1020 // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
1021 // All such elements have a "form" property.
1022 if ( elem.parentNode && elem.disabled === false ) {
1023
1024 // Option elements defer to a parent optgroup if present
1025 if ( "label" in elem ) {
1026 if ( "label" in elem.parentNode ) {
1027 return elem.parentNode.disabled === disabled;
1028 } else {
1029 return elem.disabled === disabled;
1030 }
1031 }
1032
1033 // Support: IE 6 - 11
1034 // Use the isDisabled shortcut property to check for disabled fieldset ancestors
1035 return elem.isDisabled === disabled ||
1036
1037 // Where there is no isDisabled, check manually
1038 /* jshint -W018 */
1039 elem.isDisabled !== !disabled &&
1040 disabledAncestor( elem ) === disabled;
1041 }
1042
1043 return elem.disabled === disabled;
1044
1045 // Try to winnow out elements that can't be disabled before trusting the disabled property.
1046 // Some victims get caught in our net (label, legend, menu, track), but it shouldn't
1047 // even exist on them, let alone have a boolean value.
1048 } else if ( "label" in elem ) {
1049 return elem.disabled === disabled;
1050 }
1051
1052 // Remaining elements are neither :enabled nor :disabled
1053 return false;
1054 };
1055}
1056
1057/**
1058 * Returns a function to use in pseudos for positionals
1059 * @param {Function} fn
1060 */
1061function createPositionalPseudo( fn ) {
1062 return markFunction(function( argument ) {
1063 argument = +argument;
1064 return markFunction(function( seed, matches ) {
1065 var j,
1066 matchIndexes = fn( [], seed.length, argument ),
1067 i = matchIndexes.length;
1068
1069 // Match elements found at the specified indexes
1070 while ( i-- ) {
1071 if ( seed[ (j = matchIndexes[i]) ] ) {
1072 seed[j] = !(matches[j] = seed[j]);
1073 }
1074 }
1075 });
1076 });
1077}
1078
1079/**
1080 * Checks a node for validity as a Sizzle context
1081 * @param {Element|Object=} context
1082 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
1083 */
1084function testContext( context ) {
1085 return context && typeof context.getElementsByTagName !== "undefined" && context;
1086}
1087
1088// Expose support vars for convenience
1089support = Sizzle.support = {};
1090
1091/**
1092 * Detects XML nodes
1093 * @param {Element|Object} elem An element or a document
1094 * @returns {Boolean} True iff elem is a non-HTML XML node
1095 */
1096isXML = Sizzle.isXML = function( elem ) {
1097 // documentElement is verified for cases where it doesn't yet exist
1098 // (such as loading iframes in IE - #4833)
1099 var documentElement = elem && (elem.ownerDocument || elem).documentElement;
1100 return documentElement ? documentElement.nodeName !== "HTML" : false;
1101};
1102
1103/**
1104 * Sets document-related variables once based on the current document
1105 * @param {Element|Object} [doc] An element or document object to use to set the document
1106 * @returns {Object} Returns the current document
1107 */
1108setDocument = Sizzle.setDocument = function( node ) {
1109 var hasCompare, subWindow,
1110 doc = node ? node.ownerDocument || node : preferredDoc;
1111
1112 // Return early if doc is invalid or already selected
1113 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
1114 return document;
1115 }
1116
1117 // Update global variables
1118 document = doc;
1119 docElem = document.documentElement;
1120 documentIsHTML = !isXML( document );
1121
1122 // Support: IE 9-11, Edge
1123 // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
1124 if ( preferredDoc !== document &&
1125 (subWindow = document.defaultView) && subWindow.top !== subWindow ) {
1126
1127 // Support: IE 11, Edge
1128 if ( subWindow.addEventListener ) {
1129 subWindow.addEventListener( "unload", unloadHandler, false );
1130
1131 // Support: IE 9 - 10 only
1132 } else if ( subWindow.attachEvent ) {
1133 subWindow.attachEvent( "onunload", unloadHandler );
1134 }
1135 }
1136
1137 /* Attributes
1138 ---------------------------------------------------------------------- */
1139
1140 // Support: IE<8
1141 // Verify that getAttribute really returns attributes and not properties
1142 // (excepting IE8 booleans)
1143 support.attributes = assert(function( el ) {
1144 el.className = "i";
1145 return !el.getAttribute("className");
1146 });
1147
1148 /* getElement(s)By*
1149 ---------------------------------------------------------------------- */
1150
1151 // Check if getElementsByTagName("*") returns only elements
1152 support.getElementsByTagName = assert(function( el ) {
1153 el.appendChild( document.createComment("") );
1154 return !el.getElementsByTagName("*").length;
1155 });
1156
1157 // Support: IE<9
1158 support.getElementsByClassName = rnative.test( document.getElementsByClassName );
1159
1160 // Support: IE<10
1161 // Check if getElementById returns elements by name
1162 // The broken getElementById methods don't pick up programmatically-set names,
1163 // so use a roundabout getElementsByName test
1164 support.getById = assert(function( el ) {
1165 docElem.appendChild( el ).id = expando;
1166 return !document.getElementsByName || !document.getElementsByName( expando ).length;
1167 });
1168
1169 // ID filter and find
1170 if ( support.getById ) {
1171 Expr.filter["ID"] = function( id ) {
1172 var attrId = id.replace( runescape, funescape );
1173 return function( elem ) {
1174 return elem.getAttribute("id") === attrId;
1175 };
1176 };
1177 Expr.find["ID"] = function( id, context ) {
1178 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1179 var elem = context.getElementById( id );
1180 return elem ? [ elem ] : [];
1181 }
1182 };
1183 } else {
1184 Expr.filter["ID"] = function( id ) {
1185 var attrId = id.replace( runescape, funescape );
1186 return function( elem ) {
1187 var node = typeof elem.getAttributeNode !== "undefined" &&
1188 elem.getAttributeNode("id");
1189 return node && node.value === attrId;
1190 };
1191 };
1192
1193 // Support: IE 6 - 7 only
1194 // getElementById is not reliable as a find shortcut
1195 Expr.find["ID"] = function( id, context ) {
1196 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1197 var node, i, elems,
1198 elem = context.getElementById( id );
1199
1200 if ( elem ) {
1201
1202 // Verify the id attribute
1203 node = elem.getAttributeNode("id");
1204 if ( node && node.value === id ) {
1205 return [ elem ];
1206 }
1207
1208 // Fall back on getElementsByName
1209 elems = context.getElementsByName( id );
1210 i = 0;
1211 while ( (elem = elems[i++]) ) {
1212 node = elem.getAttributeNode("id");
1213 if ( node && node.value === id ) {
1214 return [ elem ];
1215 }
1216 }
1217 }
1218
1219 return [];
1220 }
1221 };
1222 }
1223
1224 // Tag
1225 Expr.find["TAG"] = support.getElementsByTagName ?
1226 function( tag, context ) {
1227 if ( typeof context.getElementsByTagName !== "undefined" ) {
1228 return context.getElementsByTagName( tag );
1229
1230 // DocumentFragment nodes don't have gEBTN
1231 } else if ( support.qsa ) {
1232 return context.querySelectorAll( tag );
1233 }
1234 } :
1235
1236 function( tag, context ) {
1237 var elem,
1238 tmp = [],
1239 i = 0,
1240 // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
1241 results = context.getElementsByTagName( tag );
1242
1243 // Filter out possible comments
1244 if ( tag === "*" ) {
1245 while ( (elem = results[i++]) ) {
1246 if ( elem.nodeType === 1 ) {
1247 tmp.push( elem );
1248 }
1249 }
1250
1251 return tmp;
1252 }
1253 return results;
1254 };
1255
1256 // Class
1257 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
1258 if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
1259 return context.getElementsByClassName( className );
1260 }
1261 };
1262
1263 /* QSA/matchesSelector
1264 ---------------------------------------------------------------------- */
1265
1266 // QSA and matchesSelector support
1267
1268 // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
1269 rbuggyMatches = [];
1270
1271 // qSa(:focus) reports false when true (Chrome 21)
1272 // We allow this because of a bug in IE8/9 that throws an error
1273 // whenever `document.activeElement` is accessed on an iframe
1274 // So, we allow :focus to pass through QSA all the time to avoid the IE error
1275 // See https://bugs.jquery.com/ticket/13378
1276 rbuggyQSA = [];
1277
1278 if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
1279 // Build QSA regex
1280 // Regex strategy adopted from Diego Perini
1281 assert(function( el ) {
1282 // Select is set to empty string on purpose
1283 // This is to test IE's treatment of not explicitly
1284 // setting a boolean content attribute,
1285 // since its presence should be enough
1286 // https://bugs.jquery.com/ticket/12359
1287 docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
1288 "<select id='" + expando + "-\r\\' msallowcapture=''>" +
1289 "<option selected=''></option></select>";
1290
1291 // Support: IE8, Opera 11-12.16
1292 // Nothing should be selected when empty strings follow ^= or $= or *=
1293 // The test attribute must be unknown in Opera but "safe" for WinRT
1294 // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
1295 if ( el.querySelectorAll("[msallowcapture^='']").length ) {
1296 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
1297 }
1298
1299 // Support: IE8
1300 // Boolean attributes and "value" are not treated correctly
1301 if ( !el.querySelectorAll("[selected]").length ) {
1302 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1303 }
1304
1305 // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
1306 if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
1307 rbuggyQSA.push("~=");
1308 }
1309
1310 // Webkit/Opera - :checked should return selected option elements
1311 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1312 // IE8 throws error here and will not see later tests
1313 if ( !el.querySelectorAll(":checked").length ) {
1314 rbuggyQSA.push(":checked");
1315 }
1316
1317 // Support: Safari 8+, iOS 8+
1318 // https://bugs.webkit.org/show_bug.cgi?id=136851
1319 // In-page `selector#id sibling-combinator selector` fails
1320 if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
1321 rbuggyQSA.push(".#.+[+~]");
1322 }
1323 });
1324
1325 assert(function( el ) {
1326 el.innerHTML = "<a href='' disabled='disabled'></a>" +
1327 "<select disabled='disabled'><option/></select>";
1328
1329 // Support: Windows 8 Native Apps
1330 // The type and name attributes are restricted during .innerHTML assignment
1331 var input = document.createElement("input");
1332 input.setAttribute( "type", "hidden" );
1333 el.appendChild( input ).setAttribute( "name", "D" );
1334
1335 // Support: IE8
1336 // Enforce case-sensitivity of name attribute
1337 if ( el.querySelectorAll("[name=d]").length ) {
1338 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
1339 }
1340
1341 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
1342 // IE8 throws error here and will not see later tests
1343 if ( el.querySelectorAll(":enabled").length !== 2 ) {
1344 rbuggyQSA.push( ":enabled", ":disabled" );
1345 }
1346
1347 // Support: IE9-11+
1348 // IE's :disabled selector does not pick up the children of disabled fieldsets
1349 docElem.appendChild( el ).disabled = true;
1350 if ( el.querySelectorAll(":disabled").length !== 2 ) {
1351 rbuggyQSA.push( ":enabled", ":disabled" );
1352 }
1353
1354 // Opera 10-11 does not throw on post-comma invalid pseudos
1355 el.querySelectorAll("*,:x");
1356 rbuggyQSA.push(",.*:");
1357 });
1358 }
1359
1360 if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
1361 docElem.webkitMatchesSelector ||
1362 docElem.mozMatchesSelector ||
1363 docElem.oMatchesSelector ||
1364 docElem.msMatchesSelector) )) ) {
1365
1366 assert(function( el ) {
1367 // Check to see if it's possible to do matchesSelector
1368 // on a disconnected node (IE 9)
1369 support.disconnectedMatch = matches.call( el, "*" );
1370
1371 // This should fail with an exception
1372 // Gecko does not error, returns false instead
1373 matches.call( el, "[s!='']:x" );
1374 rbuggyMatches.push( "!=", pseudos );
1375 });
1376 }
1377
1378 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
1379 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
1380
1381 /* Contains
1382 ---------------------------------------------------------------------- */
1383 hasCompare = rnative.test( docElem.compareDocumentPosition );
1384
1385 // Element contains another
1386 // Purposefully self-exclusive
1387 // As in, an element does not contain itself
1388 contains = hasCompare || rnative.test( docElem.contains ) ?
1389 function( a, b ) {
1390 var adown = a.nodeType === 9 ? a.documentElement : a,
1391 bup = b && b.parentNode;
1392 return a === bup || !!( bup && bup.nodeType === 1 && (
1393 adown.contains ?
1394 adown.contains( bup ) :
1395 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
1396 ));
1397 } :
1398 function( a, b ) {
1399 if ( b ) {
1400 while ( (b = b.parentNode) ) {
1401 if ( b === a ) {
1402 return true;
1403 }
1404 }
1405 }
1406 return false;
1407 };
1408
1409 /* Sorting
1410 ---------------------------------------------------------------------- */
1411
1412 // Document order sorting
1413 sortOrder = hasCompare ?
1414 function( a, b ) {
1415
1416 // Flag for duplicate removal
1417 if ( a === b ) {
1418 hasDuplicate = true;
1419 return 0;
1420 }
1421
1422 // Sort on method existence if only one input has compareDocumentPosition
1423 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1424 if ( compare ) {
1425 return compare;
1426 }
1427
1428 // Calculate position if both inputs belong to the same document
1429 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
1430 a.compareDocumentPosition( b ) :
1431
1432 // Otherwise we know they are disconnected
1433 1;
1434
1435 // Disconnected nodes
1436 if ( compare & 1 ||
1437 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
1438
1439 // Choose the first element that is related to our preferred document
1440 if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
1441 return -1;
1442 }
1443 if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
1444 return 1;
1445 }
1446
1447 // Maintain original order
1448 return sortInput ?
1449 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1450 0;
1451 }
1452
1453 return compare & 4 ? -1 : 1;
1454 } :
1455 function( a, b ) {
1456 // Exit early if the nodes are identical
1457 if ( a === b ) {
1458 hasDuplicate = true;
1459 return 0;
1460 }
1461
1462 var cur,
1463 i = 0,
1464 aup = a.parentNode,
1465 bup = b.parentNode,
1466 ap = [ a ],
1467 bp = [ b ];
1468
1469 // Parentless nodes are either documents or disconnected
1470 if ( !aup || !bup ) {
1471 return a === document ? -1 :
1472 b === document ? 1 :
1473 aup ? -1 :
1474 bup ? 1 :
1475 sortInput ?
1476 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1477 0;
1478
1479 // If the nodes are siblings, we can do a quick check
1480 } else if ( aup === bup ) {
1481 return siblingCheck( a, b );
1482 }
1483
1484 // Otherwise we need full lists of their ancestors for comparison
1485 cur = a;
1486 while ( (cur = cur.parentNode) ) {
1487 ap.unshift( cur );
1488 }
1489 cur = b;
1490 while ( (cur = cur.parentNode) ) {
1491 bp.unshift( cur );
1492 }
1493
1494 // Walk down the tree looking for a discrepancy
1495 while ( ap[i] === bp[i] ) {
1496 i++;
1497 }
1498
1499 return i ?
1500 // Do a sibling check if the nodes have a common ancestor
1501 siblingCheck( ap[i], bp[i] ) :
1502
1503 // Otherwise nodes in our document sort first
1504 ap[i] === preferredDoc ? -1 :
1505 bp[i] === preferredDoc ? 1 :
1506 0;
1507 };
1508
1509 return document;
1510};
1511
1512Sizzle.matches = function( expr, elements ) {
1513 return Sizzle( expr, null, null, elements );
1514};
1515
1516Sizzle.matchesSelector = function( elem, expr ) {
1517 // Set document vars if needed
1518 if ( ( elem.ownerDocument || elem ) !== document ) {
1519 setDocument( elem );
1520 }
1521
1522 // Make sure that attribute selectors are quoted
1523 expr = expr.replace( rattributeQuotes, "='$1']" );
1524
1525 if ( support.matchesSelector && documentIsHTML &&
1526 !compilerCache[ expr + " " ] &&
1527 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1528 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
1529
1530 try {
1531 var ret = matches.call( elem, expr );
1532
1533 // IE 9's matchesSelector returns false on disconnected nodes
1534 if ( ret || support.disconnectedMatch ||
1535 // As well, disconnected nodes are said to be in a document
1536 // fragment in IE 9
1537 elem.document && elem.document.nodeType !== 11 ) {
1538 return ret;
1539 }
1540 } catch (e) {}
1541 }
1542
1543 return Sizzle( expr, document, null, [ elem ] ).length > 0;
1544};
1545
1546Sizzle.contains = function( context, elem ) {
1547 // Set document vars if needed
1548 if ( ( context.ownerDocument || context ) !== document ) {
1549 setDocument( context );
1550 }
1551 return contains( context, elem );
1552};
1553
1554Sizzle.attr = function( elem, name ) {
1555 // Set document vars if needed
1556 if ( ( elem.ownerDocument || elem ) !== document ) {
1557 setDocument( elem );
1558 }
1559
1560 var fn = Expr.attrHandle[ name.toLowerCase() ],
1561 // Don't get fooled by Object.prototype properties (jQuery #13807)
1562 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1563 fn( elem, name, !documentIsHTML ) :
1564 undefined;
1565
1566 return val !== undefined ?
1567 val :
1568 support.attributes || !documentIsHTML ?
1569 elem.getAttribute( name ) :
1570 (val = elem.getAttributeNode(name)) && val.specified ?
1571 val.value :
1572 null;
1573};
1574
1575Sizzle.escape = function( sel ) {
1576 return (sel + "").replace( rcssescape, fcssescape );
1577};
1578
1579Sizzle.error = function( msg ) {
1580 throw new Error( "Syntax error, unrecognized expression: " + msg );
1581};
1582
1583/**
1584 * Document sorting and removing duplicates
1585 * @param {ArrayLike} results
1586 */
1587Sizzle.uniqueSort = function( results ) {
1588 var elem,
1589 duplicates = [],
1590 j = 0,
1591 i = 0;
1592
1593 // Unless we *know* we can detect duplicates, assume their presence
1594 hasDuplicate = !support.detectDuplicates;
1595 sortInput = !support.sortStable && results.slice( 0 );
1596 results.sort( sortOrder );
1597
1598 if ( hasDuplicate ) {
1599 while ( (elem = results[i++]) ) {
1600 if ( elem === results[ i ] ) {
1601 j = duplicates.push( i );
1602 }
1603 }
1604 while ( j-- ) {
1605 results.splice( duplicates[ j ], 1 );
1606 }
1607 }
1608
1609 // Clear input after sorting to release objects
1610 // See https://github.com/jquery/sizzle/pull/225
1611 sortInput = null;
1612
1613 return results;
1614};
1615
1616/**
1617 * Utility function for retrieving the text value of an array of DOM nodes
1618 * @param {Array|Element} elem
1619 */
1620getText = Sizzle.getText = function( elem ) {
1621 var node,
1622 ret = "",
1623 i = 0,
1624 nodeType = elem.nodeType;
1625
1626 if ( !nodeType ) {
1627 // If no nodeType, this is expected to be an array
1628 while ( (node = elem[i++]) ) {
1629 // Do not traverse comment nodes
1630 ret += getText( node );
1631 }
1632 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
1633 // Use textContent for elements
1634 // innerText usage removed for consistency of new lines (jQuery #11153)
1635 if ( typeof elem.textContent === "string" ) {
1636 return elem.textContent;
1637 } else {
1638 // Traverse its children
1639 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1640 ret += getText( elem );
1641 }
1642 }
1643 } else if ( nodeType === 3 || nodeType === 4 ) {
1644 return elem.nodeValue;
1645 }
1646 // Do not include comment or processing instruction nodes
1647
1648 return ret;
1649};
1650
1651Expr = Sizzle.selectors = {
1652
1653 // Can be adjusted by the user
1654 cacheLength: 50,
1655
1656 createPseudo: markFunction,
1657
1658 match: matchExpr,
1659
1660 attrHandle: {},
1661
1662 find: {},
1663
1664 relative: {
1665 ">": { dir: "parentNode", first: true },
1666 " ": { dir: "parentNode" },
1667 "+": { dir: "previousSibling", first: true },
1668 "~": { dir: "previousSibling" }
1669 },
1670
1671 preFilter: {
1672 "ATTR": function( match ) {
1673 match[1] = match[1].replace( runescape, funescape );
1674
1675 // Move the given value to match[3] whether quoted or unquoted
1676 match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
1677
1678 if ( match[2] === "~=" ) {
1679 match[3] = " " + match[3] + " ";
1680 }
1681
1682 return match.slice( 0, 4 );
1683 },
1684
1685 "CHILD": function( match ) {
1686 /* matches from matchExpr["CHILD"]
1687 1 type (only|nth|...)
1688 2 what (child|of-type)
1689 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1690 4 xn-component of xn+y argument ([+-]?\d*n|)
1691 5 sign of xn-component
1692 6 x of xn-component
1693 7 sign of y-component
1694 8 y of y-component
1695 */
1696 match[1] = match[1].toLowerCase();
1697
1698 if ( match[1].slice( 0, 3 ) === "nth" ) {
1699 // nth-* requires argument
1700 if ( !match[3] ) {
1701 Sizzle.error( match[0] );
1702 }
1703
1704 // numeric x and y parameters for Expr.filter.CHILD
1705 // remember that false/true cast respectively to 0/1
1706 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
1707 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
1708
1709 // other types prohibit arguments
1710 } else if ( match[3] ) {
1711 Sizzle.error( match[0] );
1712 }
1713
1714 return match;
1715 },
1716
1717 "PSEUDO": function( match ) {
1718 var excess,
1719 unquoted = !match[6] && match[2];
1720
1721 if ( matchExpr["CHILD"].test( match[0] ) ) {
1722 return null;
1723 }
1724
1725 // Accept quoted arguments as-is
1726 if ( match[3] ) {
1727 match[2] = match[4] || match[5] || "";
1728
1729 // Strip excess characters from unquoted arguments
1730 } else if ( unquoted && rpseudo.test( unquoted ) &&
1731 // Get excess from tokenize (recursively)
1732 (excess = tokenize( unquoted, true )) &&
1733 // advance to the next closing parenthesis
1734 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
1735
1736 // excess is a negative index
1737 match[0] = match[0].slice( 0, excess );
1738 match[2] = unquoted.slice( 0, excess );
1739 }
1740
1741 // Return only captures needed by the pseudo filter method (type and argument)
1742 return match.slice( 0, 3 );
1743 }
1744 },
1745
1746 filter: {
1747
1748 "TAG": function( nodeNameSelector ) {
1749 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1750 return nodeNameSelector === "*" ?
1751 function() { return true; } :
1752 function( elem ) {
1753 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
1754 };
1755 },
1756
1757 "CLASS": function( className ) {
1758 var pattern = classCache[ className + " " ];
1759
1760 return pattern ||
1761 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
1762 classCache( className, function( elem ) {
1763 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
1764 });
1765 },
1766
1767 "ATTR": function( name, operator, check ) {
1768 return function( elem ) {
1769 var result = Sizzle.attr( elem, name );
1770
1771 if ( result == null ) {
1772 return operator === "!=";
1773 }
1774 if ( !operator ) {
1775 return true;
1776 }
1777
1778 result += "";
1779
1780 return operator === "=" ? result === check :
1781 operator === "!=" ? result !== check :
1782 operator === "^=" ? check && result.indexOf( check ) === 0 :
1783 operator === "*=" ? check && result.indexOf( check ) > -1 :
1784 operator === "$=" ? check && result.slice( -check.length ) === check :
1785 operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
1786 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
1787 false;
1788 };
1789 },
1790
1791 "CHILD": function( type, what, argument, first, last ) {
1792 var simple = type.slice( 0, 3 ) !== "nth",
1793 forward = type.slice( -4 ) !== "last",
1794 ofType = what === "of-type";
1795
1796 return first === 1 && last === 0 ?
1797
1798 // Shortcut for :nth-*(n)
1799 function( elem ) {
1800 return !!elem.parentNode;
1801 } :
1802
1803 function( elem, context, xml ) {
1804 var cache, uniqueCache, outerCache, node, nodeIndex, start,
1805 dir = simple !== forward ? "nextSibling" : "previousSibling",
1806 parent = elem.parentNode,
1807 name = ofType && elem.nodeName.toLowerCase(),
1808 useCache = !xml && !ofType,
1809 diff = false;
1810
1811 if ( parent ) {
1812
1813 // :(first|last|only)-(child|of-type)
1814 if ( simple ) {
1815 while ( dir ) {
1816 node = elem;
1817 while ( (node = node[ dir ]) ) {
1818 if ( ofType ?
1819 node.nodeName.toLowerCase() === name :
1820 node.nodeType === 1 ) {
1821
1822 return false;
1823 }
1824 }
1825 // Reverse direction for :only-* (if we haven't yet done so)
1826 start = dir = type === "only" && !start && "nextSibling";
1827 }
1828 return true;
1829 }
1830
1831 start = [ forward ? parent.firstChild : parent.lastChild ];
1832
1833 // non-xml :nth-child(...) stores cache data on `parent`
1834 if ( forward && useCache ) {
1835
1836 // Seek `elem` from a previously-cached index
1837
1838 // ...in a gzip-friendly way
1839 node = parent;
1840 outerCache = node[ expando ] || (node[ expando ] = {});
1841
1842 // Support: IE <9 only
1843 // Defend against cloned attroperties (jQuery gh-1709)
1844 uniqueCache = outerCache[ node.uniqueID ] ||
1845 (outerCache[ node.uniqueID ] = {});
1846
1847 cache = uniqueCache[ type ] || [];
1848 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1849 diff = nodeIndex && cache[ 2 ];
1850 node = nodeIndex && parent.childNodes[ nodeIndex ];
1851
1852 while ( (node = ++nodeIndex && node && node[ dir ] ||
1853
1854 // Fallback to seeking `elem` from the start
1855 (diff = nodeIndex = 0) || start.pop()) ) {
1856
1857 // When found, cache indexes on `parent` and break
1858 if ( node.nodeType === 1 && ++diff && node === elem ) {
1859 uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
1860 break;
1861 }
1862 }
1863
1864 } else {
1865 // Use previously-cached element index if available
1866 if ( useCache ) {
1867 // ...in a gzip-friendly way
1868 node = elem;
1869 outerCache = node[ expando ] || (node[ expando ] = {});
1870
1871 // Support: IE <9 only
1872 // Defend against cloned attroperties (jQuery gh-1709)
1873 uniqueCache = outerCache[ node.uniqueID ] ||
1874 (outerCache[ node.uniqueID ] = {});
1875
1876 cache = uniqueCache[ type ] || [];
1877 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1878 diff = nodeIndex;
1879 }
1880
1881 // xml :nth-child(...)
1882 // or :nth-last-child(...) or :nth(-last)?-of-type(...)
1883 if ( diff === false ) {
1884 // Use the same loop as above to seek `elem` from the start
1885 while ( (node = ++nodeIndex && node && node[ dir ] ||
1886 (diff = nodeIndex = 0) || start.pop()) ) {
1887
1888 if ( ( ofType ?
1889 node.nodeName.toLowerCase() === name :
1890 node.nodeType === 1 ) &&
1891 ++diff ) {
1892
1893 // Cache the index of each encountered element
1894 if ( useCache ) {
1895 outerCache = node[ expando ] || (node[ expando ] = {});
1896
1897 // Support: IE <9 only
1898 // Defend against cloned attroperties (jQuery gh-1709)
1899 uniqueCache = outerCache[ node.uniqueID ] ||
1900 (outerCache[ node.uniqueID ] = {});
1901
1902 uniqueCache[ type ] = [ dirruns, diff ];
1903 }
1904
1905 if ( node === elem ) {
1906 break;
1907 }
1908 }
1909 }
1910 }
1911 }
1912
1913 // Incorporate the offset, then check against cycle size
1914 diff -= last;
1915 return diff === first || ( diff % first === 0 && diff / first >= 0 );
1916 }
1917 };
1918 },
1919
1920 "PSEUDO": function( pseudo, argument ) {
1921 // pseudo-class names are case-insensitive
1922 // http://www.w3.org/TR/selectors/#pseudo-classes
1923 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
1924 // Remember that setFilters inherits from pseudos
1925 var args,
1926 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
1927 Sizzle.error( "unsupported pseudo: " + pseudo );
1928
1929 // The user may use createPseudo to indicate that
1930 // arguments are needed to create the filter function
1931 // just as Sizzle does
1932 if ( fn[ expando ] ) {
1933 return fn( argument );
1934 }
1935
1936 // But maintain support for old signatures
1937 if ( fn.length > 1 ) {
1938 args = [ pseudo, pseudo, "", argument ];
1939 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
1940 markFunction(function( seed, matches ) {
1941 var idx,
1942 matched = fn( seed, argument ),
1943 i = matched.length;
1944 while ( i-- ) {
1945 idx = indexOf( seed, matched[i] );
1946 seed[ idx ] = !( matches[ idx ] = matched[i] );
1947 }
1948 }) :
1949 function( elem ) {
1950 return fn( elem, 0, args );
1951 };
1952 }
1953
1954 return fn;
1955 }
1956 },
1957
1958 pseudos: {
1959 // Potentially complex pseudos
1960 "not": markFunction(function( selector ) {
1961 // Trim the selector passed to compile
1962 // to avoid treating leading and trailing
1963 // spaces as combinators
1964 var input = [],
1965 results = [],
1966 matcher = compile( selector.replace( rtrim, "$1" ) );
1967
1968 return matcher[ expando ] ?
1969 markFunction(function( seed, matches, context, xml ) {
1970 var elem,
1971 unmatched = matcher( seed, null, xml, [] ),
1972 i = seed.length;
1973
1974 // Match elements unmatched by `matcher`
1975 while ( i-- ) {
1976 if ( (elem = unmatched[i]) ) {
1977 seed[i] = !(matches[i] = elem);
1978 }
1979 }
1980 }) :
1981 function( elem, context, xml ) {
1982 input[0] = elem;
1983 matcher( input, null, xml, results );
1984 // Don't keep the element (issue #299)
1985 input[0] = null;
1986 return !results.pop();
1987 };
1988 }),
1989
1990 "has": markFunction(function( selector ) {
1991 return function( elem ) {
1992 return Sizzle( selector, elem ).length > 0;
1993 };
1994 }),
1995
1996 "contains": markFunction(function( text ) {
1997 text = text.replace( runescape, funescape );
1998 return function( elem ) {
1999 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
2000 };
2001 }),
2002
2003 // "Whether an element is represented by a :lang() selector
2004 // is based solely on the element's language value
2005 // being equal to the identifier C,
2006 // or beginning with the identifier C immediately followed by "-".
2007 // The matching of C against the element's language value is performed case-insensitively.
2008 // The identifier C does not have to be a valid language name."
2009 // http://www.w3.org/TR/selectors/#lang-pseudo
2010 "lang": markFunction( function( lang ) {
2011 // lang value must be a valid identifier
2012 if ( !ridentifier.test(lang || "") ) {
2013 Sizzle.error( "unsupported lang: " + lang );
2014 }
2015 lang = lang.replace( runescape, funescape ).toLowerCase();
2016 return function( elem ) {
2017 var elemLang;
2018 do {
2019 if ( (elemLang = documentIsHTML ?
2020 elem.lang :
2021 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
2022
2023 elemLang = elemLang.toLowerCase();
2024 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
2025 }
2026 } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
2027 return false;
2028 };
2029 }),
2030
2031 // Miscellaneous
2032 "target": function( elem ) {
2033 var hash = window.location && window.location.hash;
2034 return hash && hash.slice( 1 ) === elem.id;
2035 },
2036
2037 "root": function( elem ) {
2038 return elem === docElem;
2039 },
2040
2041 "focus": function( elem ) {
2042 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
2043 },
2044
2045 // Boolean properties
2046 "enabled": createDisabledPseudo( false ),
2047 "disabled": createDisabledPseudo( true ),
2048
2049 "checked": function( elem ) {
2050 // In CSS3, :checked should return both checked and selected elements
2051 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
2052 var nodeName = elem.nodeName.toLowerCase();
2053 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
2054 },
2055
2056 "selected": function( elem ) {
2057 // Accessing this property makes selected-by-default
2058 // options in Safari work properly
2059 if ( elem.parentNode ) {
2060 elem.parentNode.selectedIndex;
2061 }
2062
2063 return elem.selected === true;
2064 },
2065
2066 // Contents
2067 "empty": function( elem ) {
2068 // http://www.w3.org/TR/selectors/#empty-pseudo
2069 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
2070 // but not by others (comment: 8; processing instruction: 7; etc.)
2071 // nodeType < 6 works because attributes (2) do not appear as children
2072 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
2073 if ( elem.nodeType < 6 ) {
2074 return false;
2075 }
2076 }
2077 return true;
2078 },
2079
2080 "parent": function( elem ) {
2081 return !Expr.pseudos["empty"]( elem );
2082 },
2083
2084 // Element/input types
2085 "header": function( elem ) {
2086 return rheader.test( elem.nodeName );
2087 },
2088
2089 "input": function( elem ) {
2090 return rinputs.test( elem.nodeName );
2091 },
2092
2093 "button": function( elem ) {
2094 var name = elem.nodeName.toLowerCase();
2095 return name === "input" && elem.type === "button" || name === "button";
2096 },
2097
2098 "text": function( elem ) {
2099 var attr;
2100 return elem.nodeName.toLowerCase() === "input" &&
2101 elem.type === "text" &&
2102
2103 // Support: IE<8
2104 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
2105 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
2106 },
2107
2108 // Position-in-collection
2109 "first": createPositionalPseudo(function() {
2110 return [ 0 ];
2111 }),
2112
2113 "last": createPositionalPseudo(function( matchIndexes, length ) {
2114 return [ length - 1 ];
2115 }),
2116
2117 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
2118 return [ argument < 0 ? argument + length : argument ];
2119 }),
2120
2121 "even": createPositionalPseudo(function( matchIndexes, length ) {
2122 var i = 0;
2123 for ( ; i < length; i += 2 ) {
2124 matchIndexes.push( i );
2125 }
2126 return matchIndexes;
2127 }),
2128
2129 "odd": createPositionalPseudo(function( matchIndexes, length ) {
2130 var i = 1;
2131 for ( ; i < length; i += 2 ) {
2132 matchIndexes.push( i );
2133 }
2134 return matchIndexes;
2135 }),
2136
2137 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2138 var i = argument < 0 ? argument + length : argument;
2139 for ( ; --i >= 0; ) {
2140 matchIndexes.push( i );
2141 }
2142 return matchIndexes;
2143 }),
2144
2145 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2146 var i = argument < 0 ? argument + length : argument;
2147 for ( ; ++i < length; ) {
2148 matchIndexes.push( i );
2149 }
2150 return matchIndexes;
2151 })
2152 }
2153};
2154
2155Expr.pseudos["nth"] = Expr.pseudos["eq"];
2156
2157// Add button/input type pseudos
2158for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2159 Expr.pseudos[ i ] = createInputPseudo( i );
2160}
2161for ( i in { submit: true, reset: true } ) {
2162 Expr.pseudos[ i ] = createButtonPseudo( i );
2163}
2164
2165// Easy API for creating new setFilters
2166function setFilters() {}
2167setFilters.prototype = Expr.filters = Expr.pseudos;
2168Expr.setFilters = new setFilters();
2169
2170tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
2171 var matched, match, tokens, type,
2172 soFar, groups, preFilters,
2173 cached = tokenCache[ selector + " " ];
2174
2175 if ( cached ) {
2176 return parseOnly ? 0 : cached.slice( 0 );
2177 }
2178
2179 soFar = selector;
2180 groups = [];
2181 preFilters = Expr.preFilter;
2182
2183 while ( soFar ) {
2184
2185 // Comma and first run
2186 if ( !matched || (match = rcomma.exec( soFar )) ) {
2187 if ( match ) {
2188 // Don't consume trailing commas as valid
2189 soFar = soFar.slice( match[0].length ) || soFar;
2190 }
2191 groups.push( (tokens = []) );
2192 }
2193
2194 matched = false;
2195
2196 // Combinators
2197 if ( (match = rcombinators.exec( soFar )) ) {
2198 matched = match.shift();
2199 tokens.push({
2200 value: matched,
2201 // Cast descendant combinators to space
2202 type: match[0].replace( rtrim, " " )
2203 });
2204 soFar = soFar.slice( matched.length );
2205 }
2206
2207 // Filters
2208 for ( type in Expr.filter ) {
2209 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
2210 (match = preFilters[ type ]( match ))) ) {
2211 matched = match.shift();
2212 tokens.push({
2213 value: matched,
2214 type: type,
2215 matches: match
2216 });
2217 soFar = soFar.slice( matched.length );
2218 }
2219 }
2220
2221 if ( !matched ) {
2222 break;
2223 }
2224 }
2225
2226 // Return the length of the invalid excess
2227 // if we're just parsing
2228 // Otherwise, throw an error or return tokens
2229 return parseOnly ?
2230 soFar.length :
2231 soFar ?
2232 Sizzle.error( selector ) :
2233 // Cache the tokens
2234 tokenCache( selector, groups ).slice( 0 );
2235};
2236
2237function toSelector( tokens ) {
2238 var i = 0,
2239 len = tokens.length,
2240 selector = "";
2241 for ( ; i < len; i++ ) {
2242 selector += tokens[i].value;
2243 }
2244 return selector;
2245}
2246
2247function addCombinator( matcher, combinator, base ) {
2248 var dir = combinator.dir,
2249 skip = combinator.next,
2250 key = skip || dir,
2251 checkNonElements = base && key === "parentNode",
2252 doneName = done++;
2253
2254 return combinator.first ?
2255 // Check against closest ancestor/preceding element
2256 function( elem, context, xml ) {
2257 while ( (elem = elem[ dir ]) ) {
2258 if ( elem.nodeType === 1 || checkNonElements ) {
2259 return matcher( elem, context, xml );
2260 }
2261 }
2262 return false;
2263 } :
2264
2265 // Check against all ancestor/preceding elements
2266 function( elem, context, xml ) {
2267 var oldCache, uniqueCache, outerCache,
2268 newCache = [ dirruns, doneName ];
2269
2270 // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
2271 if ( xml ) {
2272 while ( (elem = elem[ dir ]) ) {
2273 if ( elem.nodeType === 1 || checkNonElements ) {
2274 if ( matcher( elem, context, xml ) ) {
2275 return true;
2276 }
2277 }
2278 }
2279 } else {
2280 while ( (elem = elem[ dir ]) ) {
2281 if ( elem.nodeType === 1 || checkNonElements ) {
2282 outerCache = elem[ expando ] || (elem[ expando ] = {});
2283
2284 // Support: IE <9 only
2285 // Defend against cloned attroperties (jQuery gh-1709)
2286 uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
2287
2288 if ( skip && skip === elem.nodeName.toLowerCase() ) {
2289 elem = elem[ dir ] || elem;
2290 } else if ( (oldCache = uniqueCache[ key ]) &&
2291 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
2292
2293 // Assign to newCache so results back-propagate to previous elements
2294 return (newCache[ 2 ] = oldCache[ 2 ]);
2295 } else {
2296 // Reuse newcache so results back-propagate to previous elements
2297 uniqueCache[ key ] = newCache;
2298
2299 // A match means we're done; a fail means we have to keep checking
2300 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
2301 return true;
2302 }
2303 }
2304 }
2305 }
2306 }
2307 return false;
2308 };
2309}
2310
2311function elementMatcher( matchers ) {
2312 return matchers.length > 1 ?
2313 function( elem, context, xml ) {
2314 var i = matchers.length;
2315 while ( i-- ) {
2316 if ( !matchers[i]( elem, context, xml ) ) {
2317 return false;
2318 }
2319 }
2320 return true;
2321 } :
2322 matchers[0];
2323}
2324
2325function multipleContexts( selector, contexts, results ) {
2326 var i = 0,
2327 len = contexts.length;
2328 for ( ; i < len; i++ ) {
2329 Sizzle( selector, contexts[i], results );
2330 }
2331 return results;
2332}
2333
2334function condense( unmatched, map, filter, context, xml ) {
2335 var elem,
2336 newUnmatched = [],
2337 i = 0,
2338 len = unmatched.length,
2339 mapped = map != null;
2340
2341 for ( ; i < len; i++ ) {
2342 if ( (elem = unmatched[i]) ) {
2343 if ( !filter || filter( elem, context, xml ) ) {
2344 newUnmatched.push( elem );
2345 if ( mapped ) {
2346 map.push( i );
2347 }
2348 }
2349 }
2350 }
2351
2352 return newUnmatched;
2353}
2354
2355function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2356 if ( postFilter && !postFilter[ expando ] ) {
2357 postFilter = setMatcher( postFilter );
2358 }
2359 if ( postFinder && !postFinder[ expando ] ) {
2360 postFinder = setMatcher( postFinder, postSelector );
2361 }
2362 return markFunction(function( seed, results, context, xml ) {
2363 var temp, i, elem,
2364 preMap = [],
2365 postMap = [],
2366 preexisting = results.length,
2367
2368 // Get initial elements from seed or context
2369 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
2370
2371 // Prefilter to get matcher input, preserving a map for seed-results synchronization
2372 matcherIn = preFilter && ( seed || !selector ) ?
2373 condense( elems, preMap, preFilter, context, xml ) :
2374 elems,
2375
2376 matcherOut = matcher ?
2377 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2378 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2379
2380 // ...intermediate processing is necessary
2381 [] :
2382
2383 // ...otherwise use results directly
2384 results :
2385 matcherIn;
2386
2387 // Find primary matches
2388 if ( matcher ) {
2389 matcher( matcherIn, matcherOut, context, xml );
2390 }
2391
2392 // Apply postFilter
2393 if ( postFilter ) {
2394 temp = condense( matcherOut, postMap );
2395 postFilter( temp, [], context, xml );
2396
2397 // Un-match failing elements by moving them back to matcherIn
2398 i = temp.length;
2399 while ( i-- ) {
2400 if ( (elem = temp[i]) ) {
2401 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
2402 }
2403 }
2404 }
2405
2406 if ( seed ) {
2407 if ( postFinder || preFilter ) {
2408 if ( postFinder ) {
2409 // Get the final matcherOut by condensing this intermediate into postFinder contexts
2410 temp = [];
2411 i = matcherOut.length;
2412 while ( i-- ) {
2413 if ( (elem = matcherOut[i]) ) {
2414 // Restore matcherIn since elem is not yet a final match
2415 temp.push( (matcherIn[i] = elem) );
2416 }
2417 }
2418 postFinder( null, (matcherOut = []), temp, xml );
2419 }
2420
2421 // Move matched elements from seed to results to keep them synchronized
2422 i = matcherOut.length;
2423 while ( i-- ) {
2424 if ( (elem = matcherOut[i]) &&
2425 (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
2426
2427 seed[temp] = !(results[temp] = elem);
2428 }
2429 }
2430 }
2431
2432 // Add elements to results, through postFinder if defined
2433 } else {
2434 matcherOut = condense(
2435 matcherOut === results ?
2436 matcherOut.splice( preexisting, matcherOut.length ) :
2437 matcherOut
2438 );
2439 if ( postFinder ) {
2440 postFinder( null, results, matcherOut, xml );
2441 } else {
2442 push.apply( results, matcherOut );
2443 }
2444 }
2445 });
2446}
2447
2448function matcherFromTokens( tokens ) {
2449 var checkContext, matcher, j,
2450 len = tokens.length,
2451 leadingRelative = Expr.relative[ tokens[0].type ],
2452 implicitRelative = leadingRelative || Expr.relative[" "],
2453 i = leadingRelative ? 1 : 0,
2454
2455 // The foundational matcher ensures that elements are reachable from top-level context(s)
2456 matchContext = addCombinator( function( elem ) {
2457 return elem === checkContext;
2458 }, implicitRelative, true ),
2459 matchAnyContext = addCombinator( function( elem ) {
2460 return indexOf( checkContext, elem ) > -1;
2461 }, implicitRelative, true ),
2462 matchers = [ function( elem, context, xml ) {
2463 var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
2464 (checkContext = context).nodeType ?
2465 matchContext( elem, context, xml ) :
2466 matchAnyContext( elem, context, xml ) );
2467 // Avoid hanging onto element (issue #299)
2468 checkContext = null;
2469 return ret;
2470 } ];
2471
2472 for ( ; i < len; i++ ) {
2473 if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
2474 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
2475 } else {
2476 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
2477
2478 // Return special upon seeing a positional matcher
2479 if ( matcher[ expando ] ) {
2480 // Find the next relative operator (if any) for proper handling
2481 j = ++i;
2482 for ( ; j < len; j++ ) {
2483 if ( Expr.relative[ tokens[j].type ] ) {
2484 break;
2485 }
2486 }
2487 return setMatcher(
2488 i > 1 && elementMatcher( matchers ),
2489 i > 1 && toSelector(
2490 // If the preceding token was a descendant combinator, insert an implicit any-element `*`
2491 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
2492 ).replace( rtrim, "$1" ),
2493 matcher,
2494 i < j && matcherFromTokens( tokens.slice( i, j ) ),
2495 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
2496 j < len && toSelector( tokens )
2497 );
2498 }
2499 matchers.push( matcher );
2500 }
2501 }
2502
2503 return elementMatcher( matchers );
2504}
2505
2506function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2507 var bySet = setMatchers.length > 0,
2508 byElement = elementMatchers.length > 0,
2509 superMatcher = function( seed, context, xml, results, outermost ) {
2510 var elem, j, matcher,
2511 matchedCount = 0,
2512 i = "0",
2513 unmatched = seed && [],
2514 setMatched = [],
2515 contextBackup = outermostContext,
2516 // We must always have either seed elements or outermost context
2517 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
2518 // Use integer dirruns iff this is the outermost matcher
2519 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
2520 len = elems.length;
2521
2522 if ( outermost ) {
2523 outermostContext = context === document || context || outermost;
2524 }
2525
2526 // Add elements passing elementMatchers directly to results
2527 // Support: IE<9, Safari
2528 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
2529 for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
2530 if ( byElement && elem ) {
2531 j = 0;
2532 if ( !context && elem.ownerDocument !== document ) {
2533 setDocument( elem );
2534 xml = !documentIsHTML;
2535 }
2536 while ( (matcher = elementMatchers[j++]) ) {
2537 if ( matcher( elem, context || document, xml) ) {
2538 results.push( elem );
2539 break;
2540 }
2541 }
2542 if ( outermost ) {
2543 dirruns = dirrunsUnique;
2544 }
2545 }
2546
2547 // Track unmatched elements for set filters
2548 if ( bySet ) {
2549 // They will have gone through all possible matchers
2550 if ( (elem = !matcher && elem) ) {
2551 matchedCount--;
2552 }
2553
2554 // Lengthen the array for every element, matched or not
2555 if ( seed ) {
2556 unmatched.push( elem );
2557 }
2558 }
2559 }
2560
2561 // `i` is now the count of elements visited above, and adding it to `matchedCount`
2562 // makes the latter nonnegative.
2563 matchedCount += i;
2564
2565 // Apply set filters to unmatched elements
2566 // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
2567 // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
2568 // no element matchers and no seed.
2569 // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
2570 // case, which will result in a "00" `matchedCount` that differs from `i` but is also
2571 // numerically zero.
2572 if ( bySet && i !== matchedCount ) {
2573 j = 0;
2574 while ( (matcher = setMatchers[j++]) ) {
2575 matcher( unmatched, setMatched, context, xml );
2576 }
2577
2578 if ( seed ) {
2579 // Reintegrate element matches to eliminate the need for sorting
2580 if ( matchedCount > 0 ) {
2581 while ( i-- ) {
2582 if ( !(unmatched[i] || setMatched[i]) ) {
2583 setMatched[i] = pop.call( results );
2584 }
2585 }
2586 }
2587
2588 // Discard index placeholder values to get only actual matches
2589 setMatched = condense( setMatched );
2590 }
2591
2592 // Add matches to results
2593 push.apply( results, setMatched );
2594
2595 // Seedless set matches succeeding multiple successful matchers stipulate sorting
2596 if ( outermost && !seed && setMatched.length > 0 &&
2597 ( matchedCount + setMatchers.length ) > 1 ) {
2598
2599 Sizzle.uniqueSort( results );
2600 }
2601 }
2602
2603 // Override manipulation of globals by nested matchers
2604 if ( outermost ) {
2605 dirruns = dirrunsUnique;
2606 outermostContext = contextBackup;
2607 }
2608
2609 return unmatched;
2610 };
2611
2612 return bySet ?
2613 markFunction( superMatcher ) :
2614 superMatcher;
2615}
2616
2617compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
2618 var i,
2619 setMatchers = [],
2620 elementMatchers = [],
2621 cached = compilerCache[ selector + " " ];
2622
2623 if ( !cached ) {
2624 // Generate a function of recursive functions that can be used to check each element
2625 if ( !match ) {
2626 match = tokenize( selector );
2627 }
2628 i = match.length;
2629 while ( i-- ) {
2630 cached = matcherFromTokens( match[i] );
2631 if ( cached[ expando ] ) {
2632 setMatchers.push( cached );
2633 } else {
2634 elementMatchers.push( cached );
2635 }
2636 }
2637
2638 // Cache the compiled function
2639 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2640
2641 // Save selector and tokenization
2642 cached.selector = selector;
2643 }
2644 return cached;
2645};
2646
2647/**
2648 * A low-level selection function that works with Sizzle's compiled
2649 * selector functions
2650 * @param {String|Function} selector A selector or a pre-compiled
2651 * selector function built with Sizzle.compile
2652 * @param {Element} context
2653 * @param {Array} [results]
2654 * @param {Array} [seed] A set of elements to match against
2655 */
2656select = Sizzle.select = function( selector, context, results, seed ) {
2657 var i, tokens, token, type, find,
2658 compiled = typeof selector === "function" && selector,
2659 match = !seed && tokenize( (selector = compiled.selector || selector) );
2660
2661 results = results || [];
2662
2663 // Try to minimize operations if there is only one selector in the list and no seed
2664 // (the latter of which guarantees us context)
2665 if ( match.length === 1 ) {
2666
2667 // Reduce context if the leading compound selector is an ID
2668 tokens = match[0] = match[0].slice( 0 );
2669 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
2670 context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {
2671
2672 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
2673 if ( !context ) {
2674 return results;
2675
2676 // Precompiled matchers will still verify ancestry, so step up a level
2677 } else if ( compiled ) {
2678 context = context.parentNode;
2679 }
2680
2681 selector = selector.slice( tokens.shift().value.length );
2682 }
2683
2684 // Fetch a seed set for right-to-left matching
2685 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
2686 while ( i-- ) {
2687 token = tokens[i];
2688
2689 // Abort if we hit a combinator
2690 if ( Expr.relative[ (type = token.type) ] ) {
2691 break;
2692 }
2693 if ( (find = Expr.find[ type ]) ) {
2694 // Search, expanding context for leading sibling combinators
2695 if ( (seed = find(
2696 token.matches[0].replace( runescape, funescape ),
2697 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
2698 )) ) {
2699
2700 // If seed is empty or no tokens remain, we can return early
2701 tokens.splice( i, 1 );
2702 selector = seed.length && toSelector( tokens );
2703 if ( !selector ) {
2704 push.apply( results, seed );
2705 return results;
2706 }
2707
2708 break;
2709 }
2710 }
2711 }
2712 }
2713
2714 // Compile and execute a filtering function if one is not provided
2715 // Provide `match` to avoid retokenization if we modified the selector above
2716 ( compiled || compile( selector, match ) )(
2717 seed,
2718 context,
2719 !documentIsHTML,
2720 results,
2721 !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
2722 );
2723 return results;
2724};
2725
2726// One-time assignments
2727
2728// Sort stability
2729support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
2730
2731// Support: Chrome 14-35+
2732// Always assume duplicates if they aren't passed to the comparison function
2733support.detectDuplicates = !!hasDuplicate;
2734
2735// Initialize against the default document
2736setDocument();
2737
2738// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2739// Detached nodes confoundingly follow *each other*
2740support.sortDetached = assert(function( el ) {
2741 // Should return 1, but returns 4 (following)
2742 return el.compareDocumentPosition( document.createElement("fieldset") ) & 1;
2743});
2744
2745// Support: IE<8
2746// Prevent attribute/property "interpolation"
2747// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2748if ( !assert(function( el ) {
2749 el.innerHTML = "<a href='#'></a>";
2750 return el.firstChild.getAttribute("href") === "#" ;
2751}) ) {
2752 addHandle( "type|href|height|width", function( elem, name, isXML ) {
2753 if ( !isXML ) {
2754 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
2755 }
2756 });
2757}
2758
2759// Support: IE<9
2760// Use defaultValue in place of getAttribute("value")
2761if ( !support.attributes || !assert(function( el ) {
2762 el.innerHTML = "<input/>";
2763 el.firstChild.setAttribute( "value", "" );
2764 return el.firstChild.getAttribute( "value" ) === "";
2765}) ) {
2766 addHandle( "value", function( elem, name, isXML ) {
2767 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2768 return elem.defaultValue;
2769 }
2770 });
2771}
2772
2773// Support: IE<9
2774// Use getAttributeNode to fetch booleans when getAttribute lies
2775if ( !assert(function( el ) {
2776 return el.getAttribute("disabled") == null;
2777}) ) {
2778 addHandle( booleans, function( elem, name, isXML ) {
2779 var val;
2780 if ( !isXML ) {
2781 return elem[ name ] === true ? name.toLowerCase() :
2782 (val = elem.getAttributeNode( name )) && val.specified ?
2783 val.value :
2784 null;
2785 }
2786 });
2787}
2788
2789return Sizzle;
2790
2791})( window );
2792
2793
2794
2795jQuery.find = Sizzle;
2796jQuery.expr = Sizzle.selectors;
2797
2798// Deprecated
2799jQuery.expr[ ":" ] = jQuery.expr.pseudos;
2800jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
2801jQuery.text = Sizzle.getText;
2802jQuery.isXMLDoc = Sizzle.isXML;
2803jQuery.contains = Sizzle.contains;
2804jQuery.escapeSelector = Sizzle.escape;
2805
2806
2807
2808
2809var dir = function( elem, dir, until ) {
2810 var matched = [],
2811 truncate = until !== undefined;
2812
2813 while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
2814 if ( elem.nodeType === 1 ) {
2815 if ( truncate && jQuery( elem ).is( until ) ) {
2816 break;
2817 }
2818 matched.push( elem );
2819 }
2820 }
2821 return matched;
2822};
2823
2824
2825var siblings = function( n, elem ) {
2826 var matched = [];
2827
2828 for ( ; n; n = n.nextSibling ) {
2829 if ( n.nodeType === 1 && n !== elem ) {
2830 matched.push( n );
2831 }
2832 }
2833
2834 return matched;
2835};
2836
2837
2838var rneedsContext = jQuery.expr.match.needsContext;
2839
2840
2841
2842function nodeName( elem, name ) {
2843
2844 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
2845
2846};
2847var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
2848
2849
2850
2851var risSimple = /^.[^:#\[\.,]*$/;
2852
2853// Implement the identical functionality for filter and not
2854function winnow( elements, qualifier, not ) {
2855 if ( jQuery.isFunction( qualifier ) ) {
2856 return jQuery.grep( elements, function( elem, i ) {
2857 return !!qualifier.call( elem, i, elem ) !== not;
2858 } );
2859 }
2860
2861 // Single element
2862 if ( qualifier.nodeType ) {
2863 return jQuery.grep( elements, function( elem ) {
2864 return ( elem === qualifier ) !== not;
2865 } );
2866 }
2867
2868 // Arraylike of elements (jQuery, arguments, Array)
2869 if ( typeof qualifier !== "string" ) {
2870 return jQuery.grep( elements, function( elem ) {
2871 return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
2872 } );
2873 }
2874
2875 // Simple selector that can be filtered directly, removing non-Elements
2876 if ( risSimple.test( qualifier ) ) {
2877 return jQuery.filter( qualifier, elements, not );
2878 }
2879
2880 // Complex selector, compare the two sets, removing non-Elements
2881 qualifier = jQuery.filter( qualifier, elements );
2882 return jQuery.grep( elements, function( elem ) {
2883 return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;
2884 } );
2885}
2886
2887jQuery.filter = function( expr, elems, not ) {
2888 var elem = elems[ 0 ];
2889
2890 if ( not ) {
2891 expr = ":not(" + expr + ")";
2892 }
2893
2894 if ( elems.length === 1 && elem.nodeType === 1 ) {
2895 return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
2896 }
2897
2898 return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
2899 return elem.nodeType === 1;
2900 } ) );
2901};
2902
2903jQuery.fn.extend( {
2904 find: function( selector ) {
2905 var i, ret,
2906 len = this.length,
2907 self = this;
2908
2909 if ( typeof selector !== "string" ) {
2910 return this.pushStack( jQuery( selector ).filter( function() {
2911 for ( i = 0; i < len; i++ ) {
2912 if ( jQuery.contains( self[ i ], this ) ) {
2913 return true;
2914 }
2915 }
2916 } ) );
2917 }
2918
2919 ret = this.pushStack( [] );
2920
2921 for ( i = 0; i < len; i++ ) {
2922 jQuery.find( selector, self[ i ], ret );
2923 }
2924
2925 return len > 1 ? jQuery.uniqueSort( ret ) : ret;
2926 },
2927 filter: function( selector ) {
2928 return this.pushStack( winnow( this, selector || [], false ) );
2929 },
2930 not: function( selector ) {
2931 return this.pushStack( winnow( this, selector || [], true ) );
2932 },
2933 is: function( selector ) {
2934 return !!winnow(
2935 this,
2936
2937 // If this is a positional/relative selector, check membership in the returned set
2938 // so $("p:first").is("p:last") won't return true for a doc with two "p".
2939 typeof selector === "string" && rneedsContext.test( selector ) ?
2940 jQuery( selector ) :
2941 selector || [],
2942 false
2943 ).length;
2944 }
2945} );
2946
2947
2948// Initialize a jQuery object
2949
2950
2951// A central reference to the root jQuery(document)
2952var rootjQuery,
2953
2954 // A simple way to check for HTML strings
2955 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
2956 // Strict HTML recognition (#11290: must start with <)
2957 // Shortcut simple #id case for speed
2958 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
2959
2960 init = jQuery.fn.init = function( selector, context, root ) {
2961 var match, elem;
2962
2963 // HANDLE: $(""), $(null), $(undefined), $(false)
2964 if ( !selector ) {
2965 return this;
2966 }
2967
2968 // Method init() accepts an alternate rootjQuery
2969 // so migrate can support jQuery.sub (gh-2101)
2970 root = root || rootjQuery;
2971
2972 // Handle HTML strings
2973 if ( typeof selector === "string" ) {
2974 if ( selector[ 0 ] === "<" &&
2975 selector[ selector.length - 1 ] === ">" &&
2976 selector.length >= 3 ) {
2977
2978 // Assume that strings that start and end with <> are HTML and skip the regex check
2979 match = [ null, selector, null ];
2980
2981 } else {
2982 match = rquickExpr.exec( selector );
2983 }
2984
2985 // Match html or make sure no context is specified for #id
2986 if ( match && ( match[ 1 ] || !context ) ) {
2987
2988 // HANDLE: $(html) -> $(array)
2989 if ( match[ 1 ] ) {
2990 context = context instanceof jQuery ? context[ 0 ] : context;
2991
2992 // Option to run scripts is true for back-compat
2993 // Intentionally let the error be thrown if parseHTML is not present
2994 jQuery.merge( this, jQuery.parseHTML(
2995 match[ 1 ],
2996 context && context.nodeType ? context.ownerDocument || context : document,
2997 true
2998 ) );
2999
3000 // HANDLE: $(html, props)
3001 if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
3002 for ( match in context ) {
3003
3004 // Properties of context are called as methods if possible
3005 if ( jQuery.isFunction( this[ match ] ) ) {
3006 this[ match ]( context[ match ] );
3007
3008 // ...and otherwise set as attributes
3009 } else {
3010 this.attr( match, context[ match ] );
3011 }
3012 }
3013 }
3014
3015 return this;
3016
3017 // HANDLE: $(#id)
3018 } else {
3019 elem = document.getElementById( match[ 2 ] );
3020
3021 if ( elem ) {
3022
3023 // Inject the element directly into the jQuery object
3024 this[ 0 ] = elem;
3025 this.length = 1;
3026 }
3027 return this;
3028 }
3029
3030 // HANDLE: $(expr, $(...))
3031 } else if ( !context || context.jquery ) {
3032 return ( context || root ).find( selector );
3033
3034 // HANDLE: $(expr, context)
3035 // (which is just equivalent to: $(context).find(expr)
3036 } else {
3037 return this.constructor( context ).find( selector );
3038 }
3039
3040 // HANDLE: $(DOMElement)
3041 } else if ( selector.nodeType ) {
3042 this[ 0 ] = selector;
3043 this.length = 1;
3044 return this;
3045
3046 // HANDLE: $(function)
3047 // Shortcut for document ready
3048 } else if ( jQuery.isFunction( selector ) ) {
3049 return root.ready !== undefined ?
3050 root.ready( selector ) :
3051
3052 // Execute immediately if ready is not present
3053 selector( jQuery );
3054 }
3055
3056 return jQuery.makeArray( selector, this );
3057 };
3058
3059// Give the init function the jQuery prototype for later instantiation
3060init.prototype = jQuery.fn;
3061
3062// Initialize central reference
3063rootjQuery = jQuery( document );
3064
3065
3066var rparentsprev = /^(?:parents|prev(?:Until|All))/,
3067
3068 // Methods guaranteed to produce a unique set when starting from a unique set
3069 guaranteedUnique = {
3070 children: true,
3071 contents: true,
3072 next: true,
3073 prev: true
3074 };
3075
3076jQuery.fn.extend( {
3077 has: function( target ) {
3078 var targets = jQuery( target, this ),
3079 l = targets.length;
3080
3081 return this.filter( function() {
3082 var i = 0;
3083 for ( ; i < l; i++ ) {
3084 if ( jQuery.contains( this, targets[ i ] ) ) {
3085 return true;
3086 }
3087 }
3088 } );
3089 },
3090
3091 closest: function( selectors, context ) {
3092 var cur,
3093 i = 0,
3094 l = this.length,
3095 matched = [],
3096 targets = typeof selectors !== "string" && jQuery( selectors );
3097
3098 // Positional selectors never match, since there's no _selection_ context
3099 if ( !rneedsContext.test( selectors ) ) {
3100 for ( ; i < l; i++ ) {
3101 for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
3102
3103 // Always skip document fragments
3104 if ( cur.nodeType < 11 && ( targets ?
3105 targets.index( cur ) > -1 :
3106
3107 // Don't pass non-elements to Sizzle
3108 cur.nodeType === 1 &&
3109 jQuery.find.matchesSelector( cur, selectors ) ) ) {
3110
3111 matched.push( cur );
3112 break;
3113 }
3114 }
3115 }
3116 }
3117
3118 return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
3119 },
3120
3121 // Determine the position of an element within the set
3122 index: function( elem ) {
3123
3124 // No argument, return index in parent
3125 if ( !elem ) {
3126 return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
3127 }
3128
3129 // Index in selector
3130 if ( typeof elem === "string" ) {
3131 return indexOf.call( jQuery( elem ), this[ 0 ] );
3132 }
3133
3134 // Locate the position of the desired element
3135 return indexOf.call( this,
3136
3137 // If it receives a jQuery object, the first element is used
3138 elem.jquery ? elem[ 0 ] : elem
3139 );
3140 },
3141
3142 add: function( selector, context ) {
3143 return this.pushStack(
3144 jQuery.uniqueSort(
3145 jQuery.merge( this.get(), jQuery( selector, context ) )
3146 )
3147 );
3148 },
3149
3150 addBack: function( selector ) {
3151 return this.add( selector == null ?
3152 this.prevObject : this.prevObject.filter( selector )
3153 );
3154 }
3155} );
3156
3157function sibling( cur, dir ) {
3158 while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
3159 return cur;
3160}
3161
3162jQuery.each( {
3163 parent: function( elem ) {
3164 var parent = elem.parentNode;
3165 return parent && parent.nodeType !== 11 ? parent : null;
3166 },
3167 parents: function( elem ) {
3168 return dir( elem, "parentNode" );
3169 },
3170 parentsUntil: function( elem, i, until ) {
3171 return dir( elem, "parentNode", until );
3172 },
3173 next: function( elem ) {
3174 return sibling( elem, "nextSibling" );
3175 },
3176 prev: function( elem ) {
3177 return sibling( elem, "previousSibling" );
3178 },
3179 nextAll: function( elem ) {
3180 return dir( elem, "nextSibling" );
3181 },
3182 prevAll: function( elem ) {
3183 return dir( elem, "previousSibling" );
3184 },
3185 nextUntil: function( elem, i, until ) {
3186 return dir( elem, "nextSibling", until );
3187 },
3188 prevUntil: function( elem, i, until ) {
3189 return dir( elem, "previousSibling", until );
3190 },
3191 siblings: function( elem ) {
3192 return siblings( ( elem.parentNode || {} ).firstChild, elem );
3193 },
3194 children: function( elem ) {
3195 return siblings( elem.firstChild );
3196 },
3197 contents: function( elem ) {
3198 if ( nodeName( elem, "iframe" ) ) {
3199 return elem.contentDocument;
3200 }
3201
3202 // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
3203 // Treat the template element as a regular one in browsers that
3204 // don't support it.
3205 if ( nodeName( elem, "template" ) ) {
3206 elem = elem.content || elem;
3207 }
3208
3209 return jQuery.merge( [], elem.childNodes );
3210 }
3211}, function( name, fn ) {
3212 jQuery.fn[ name ] = function( until, selector ) {
3213 var matched = jQuery.map( this, fn, until );
3214
3215 if ( name.slice( -5 ) !== "Until" ) {
3216 selector = until;
3217 }
3218
3219 if ( selector && typeof selector === "string" ) {
3220 matched = jQuery.filter( selector, matched );
3221 }
3222
3223 if ( this.length > 1 ) {
3224
3225 // Remove duplicates
3226 if ( !guaranteedUnique[ name ] ) {
3227 jQuery.uniqueSort( matched );
3228 }
3229
3230 // Reverse order for parents* and prev-derivatives
3231 if ( rparentsprev.test( name ) ) {
3232 matched.reverse();
3233 }
3234 }
3235
3236 return this.pushStack( matched );
3237 };
3238} );
3239var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
3240
3241
3242
3243// Convert String-formatted options into Object-formatted ones
3244function createOptions( options ) {
3245 var object = {};
3246 jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
3247 object[ flag ] = true;
3248 } );
3249 return object;
3250}
3251
3252/*
3253 * Create a callback list using the following parameters:
3254 *
3255 * options: an optional list of space-separated options that will change how
3256 * the callback list behaves or a more traditional option object
3257 *
3258 * By default a callback list will act like an event callback list and can be
3259 * "fired" multiple times.
3260 *
3261 * Possible options:
3262 *
3263 * once: will ensure the callback list can only be fired once (like a Deferred)
3264 *
3265 * memory: will keep track of previous values and will call any callback added
3266 * after the list has been fired right away with the latest "memorized"
3267 * values (like a Deferred)
3268 *
3269 * unique: will ensure a callback can only be added once (no duplicate in the list)
3270 *
3271 * stopOnFalse: interrupt callings when a callback returns false
3272 *
3273 */
3274jQuery.Callbacks = function( options ) {
3275
3276 // Convert options from String-formatted to Object-formatted if needed
3277 // (we check in cache first)
3278 options = typeof options === "string" ?
3279 createOptions( options ) :
3280 jQuery.extend( {}, options );
3281
3282 var // Flag to know if list is currently firing
3283 firing,
3284
3285 // Last fire value for non-forgettable lists
3286 memory,
3287
3288 // Flag to know if list was already fired
3289 fired,
3290
3291 // Flag to prevent firing
3292 locked,
3293
3294 // Actual callback list
3295 list = [],
3296
3297 // Queue of execution data for repeatable lists
3298 queue = [],
3299
3300 // Index of currently firing callback (modified by add/remove as needed)
3301 firingIndex = -1,
3302
3303 // Fire callbacks
3304 fire = function() {
3305
3306 // Enforce single-firing
3307 locked = locked || options.once;
3308
3309 // Execute callbacks for all pending executions,
3310 // respecting firingIndex overrides and runtime changes
3311 fired = firing = true;
3312 for ( ; queue.length; firingIndex = -1 ) {
3313 memory = queue.shift();
3314 while ( ++firingIndex < list.length ) {
3315
3316 // Run callback and check for early termination
3317 if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
3318 options.stopOnFalse ) {
3319
3320 // Jump to end and forget the data so .add doesn't re-fire
3321 firingIndex = list.length;
3322 memory = false;
3323 }
3324 }
3325 }
3326
3327 // Forget the data if we're done with it
3328 if ( !options.memory ) {
3329 memory = false;
3330 }
3331
3332 firing = false;
3333
3334 // Clean up if we're done firing for good
3335 if ( locked ) {
3336
3337 // Keep an empty list if we have data for future add calls
3338 if ( memory ) {
3339 list = [];
3340
3341 // Otherwise, this object is spent
3342 } else {
3343 list = "";
3344 }
3345 }
3346 },
3347
3348 // Actual Callbacks object
3349 self = {
3350
3351 // Add a callback or a collection of callbacks to the list
3352 add: function() {
3353 if ( list ) {
3354
3355 // If we have memory from a past run, we should fire after adding
3356 if ( memory && !firing ) {
3357 firingIndex = list.length - 1;
3358 queue.push( memory );
3359 }
3360
3361 ( function add( args ) {
3362 jQuery.each( args, function( _, arg ) {
3363 if ( jQuery.isFunction( arg ) ) {
3364 if ( !options.unique || !self.has( arg ) ) {
3365 list.push( arg );
3366 }
3367 } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
3368
3369 // Inspect recursively
3370 add( arg );
3371 }
3372 } );
3373 } )( arguments );
3374
3375 if ( memory && !firing ) {
3376 fire();
3377 }
3378 }
3379 return this;
3380 },
3381
3382 // Remove a callback from the list
3383 remove: function() {
3384 jQuery.each( arguments, function( _, arg ) {
3385 var index;
3386 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3387 list.splice( index, 1 );
3388
3389 // Handle firing indexes
3390 if ( index <= firingIndex ) {
3391 firingIndex--;
3392 }
3393 }
3394 } );
3395 return this;
3396 },
3397
3398 // Check if a given callback is in the list.
3399 // If no argument is given, return whether or not list has callbacks attached.
3400 has: function( fn ) {
3401 return fn ?
3402 jQuery.inArray( fn, list ) > -1 :
3403 list.length > 0;
3404 },
3405
3406 // Remove all callbacks from the list
3407 empty: function() {
3408 if ( list ) {
3409 list = [];
3410 }
3411 return this;
3412 },
3413
3414 // Disable .fire and .add
3415 // Abort any current/pending executions
3416 // Clear all callbacks and values
3417 disable: function() {
3418 locked = queue = [];
3419 list = memory = "";
3420 return this;
3421 },
3422 disabled: function() {
3423 return !list;
3424 },
3425
3426 // Disable .fire
3427 // Also disable .add unless we have memory (since it would have no effect)
3428 // Abort any pending executions
3429 lock: function() {
3430 locked = queue = [];
3431 if ( !memory && !firing ) {
3432 list = memory = "";
3433 }
3434 return this;
3435 },
3436 locked: function() {
3437 return !!locked;
3438 },
3439
3440 // Call all callbacks with the given context and arguments
3441 fireWith: function( context, args ) {
3442 if ( !locked ) {
3443 args = args || [];
3444 args = [ context, args.slice ? args.slice() : args ];
3445 queue.push( args );
3446 if ( !firing ) {
3447 fire();
3448 }
3449 }
3450 return this;
3451 },
3452
3453 // Call all the callbacks with the given arguments
3454 fire: function() {
3455 self.fireWith( this, arguments );
3456 return this;
3457 },
3458
3459 // To know if the callbacks have already been called at least once
3460 fired: function() {
3461 return !!fired;
3462 }
3463 };
3464
3465 return self;
3466};
3467
3468
3469function Identity( v ) {
3470 return v;
3471}
3472function Thrower( ex ) {
3473 throw ex;
3474}
3475
3476function adoptValue( value, resolve, reject, noValue ) {
3477 var method;
3478
3479 try {
3480
3481 // Check for promise aspect first to privilege synchronous behavior
3482 if ( value && jQuery.isFunction( ( method = value.promise ) ) ) {
3483 method.call( value ).done( resolve ).fail( reject );
3484
3485 // Other thenables
3486 } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {
3487 method.call( value, resolve, reject );
3488
3489 // Other non-thenables
3490 } else {
3491
3492 // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
3493 // * false: [ value ].slice( 0 ) => resolve( value )
3494 // * true: [ value ].slice( 1 ) => resolve()
3495 resolve.apply( undefined, [ value ].slice( noValue ) );
3496 }
3497
3498 // For Promises/A+, convert exceptions into rejections
3499 // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
3500 // Deferred#then to conditionally suppress rejection.
3501 } catch ( value ) {
3502
3503 // Support: Android 4.0 only
3504 // Strict mode functions invoked without .call/.apply get global-object context
3505 reject.apply( undefined, [ value ] );
3506 }
3507}
3508
3509jQuery.extend( {
3510
3511 Deferred: function( func ) {
3512 var tuples = [
3513
3514 // action, add listener, callbacks,
3515 // ... .then handlers, argument index, [final state]
3516 [ "notify", "progress", jQuery.Callbacks( "memory" ),
3517 jQuery.Callbacks( "memory" ), 2 ],
3518 [ "resolve", "done", jQuery.Callbacks( "once memory" ),
3519 jQuery.Callbacks( "once memory" ), 0, "resolved" ],
3520 [ "reject", "fail", jQuery.Callbacks( "once memory" ),
3521 jQuery.Callbacks( "once memory" ), 1, "rejected" ]
3522 ],
3523 state = "pending",
3524 promise = {
3525 state: function() {
3526 return state;
3527 },
3528 always: function() {
3529 deferred.done( arguments ).fail( arguments );
3530 return this;
3531 },
3532 "catch": function( fn ) {
3533 return promise.then( null, fn );
3534 },
3535
3536 // Keep pipe for back-compat
3537 pipe: function( /* fnDone, fnFail, fnProgress */ ) {
3538 var fns = arguments;
3539
3540 return jQuery.Deferred( function( newDefer ) {
3541 jQuery.each( tuples, function( i, tuple ) {
3542
3543 // Map tuples (progress, done, fail) to arguments (done, fail, progress)
3544 var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
3545
3546 // deferred.progress(function() { bind to newDefer or newDefer.notify })
3547 // deferred.done(function() { bind to newDefer or newDefer.resolve })
3548 // deferred.fail(function() { bind to newDefer or newDefer.reject })
3549 deferred[ tuple[ 1 ] ]( function() {
3550 var returned = fn && fn.apply( this, arguments );
3551 if ( returned && jQuery.isFunction( returned.promise ) ) {
3552 returned.promise()
3553 .progress( newDefer.notify )
3554 .done( newDefer.resolve )
3555 .fail( newDefer.reject );
3556 } else {
3557 newDefer[ tuple[ 0 ] + "With" ](
3558 this,
3559 fn ? [ returned ] : arguments
3560 );
3561 }
3562 } );
3563 } );
3564 fns = null;
3565 } ).promise();
3566 },
3567 then: function( onFulfilled, onRejected, onProgress ) {
3568 var maxDepth = 0;
3569 function resolve( depth, deferred, handler, special ) {
3570 return function() {
3571 var that = this,
3572 args = arguments,
3573 mightThrow = function() {
3574 var returned, then;
3575
3576 // Support: Promises/A+ section 2.3.3.3.3
3577 // https://promisesaplus.com/#point-59
3578 // Ignore double-resolution attempts
3579 if ( depth < maxDepth ) {
3580 return;
3581 }
3582
3583 returned = handler.apply( that, args );
3584
3585 // Support: Promises/A+ section 2.3.1
3586 // https://promisesaplus.com/#point-48
3587 if ( returned === deferred.promise() ) {
3588 throw new TypeError( "Thenable self-resolution" );
3589 }
3590
3591 // Support: Promises/A+ sections 2.3.3.1, 3.5
3592 // https://promisesaplus.com/#point-54
3593 // https://promisesaplus.com/#point-75
3594 // Retrieve `then` only once
3595 then = returned &&
3596
3597 // Support: Promises/A+ section 2.3.4
3598 // https://promisesaplus.com/#point-64
3599 // Only check objects and functions for thenability
3600 ( typeof returned === "object" ||
3601 typeof returned === "function" ) &&
3602 returned.then;
3603
3604 // Handle a returned thenable
3605 if ( jQuery.isFunction( then ) ) {
3606
3607 // Special processors (notify) just wait for resolution
3608 if ( special ) {
3609 then.call(
3610 returned,
3611 resolve( maxDepth, deferred, Identity, special ),
3612 resolve( maxDepth, deferred, Thrower, special )
3613 );
3614
3615 // Normal processors (resolve) also hook into progress
3616 } else {
3617
3618 // ...and disregard older resolution values
3619 maxDepth++;
3620
3621 then.call(
3622 returned,
3623 resolve( maxDepth, deferred, Identity, special ),
3624 resolve( maxDepth, deferred, Thrower, special ),
3625 resolve( maxDepth, deferred, Identity,
3626 deferred.notifyWith )
3627 );
3628 }
3629
3630 // Handle all other returned values
3631 } else {
3632
3633 // Only substitute handlers pass on context
3634 // and multiple values (non-spec behavior)
3635 if ( handler !== Identity ) {
3636 that = undefined;
3637 args = [ returned ];
3638 }
3639
3640 // Process the value(s)
3641 // Default process is resolve
3642 ( special || deferred.resolveWith )( that, args );
3643 }
3644 },
3645
3646 // Only normal processors (resolve) catch and reject exceptions
3647 process = special ?
3648 mightThrow :
3649 function() {
3650 try {
3651 mightThrow();
3652 } catch ( e ) {
3653
3654 if ( jQuery.Deferred.exceptionHook ) {
3655 jQuery.Deferred.exceptionHook( e,
3656 process.stackTrace );
3657 }
3658
3659 // Support: Promises/A+ section 2.3.3.3.4.1
3660 // https://promisesaplus.com/#point-61
3661 // Ignore post-resolution exceptions
3662 if ( depth + 1 >= maxDepth ) {
3663
3664 // Only substitute handlers pass on context
3665 // and multiple values (non-spec behavior)
3666 if ( handler !== Thrower ) {
3667 that = undefined;
3668 args = [ e ];
3669 }
3670
3671 deferred.rejectWith( that, args );
3672 }
3673 }
3674 };
3675
3676 // Support: Promises/A+ section 2.3.3.3.1
3677 // https://promisesaplus.com/#point-57
3678 // Re-resolve promises immediately to dodge false rejection from
3679 // subsequent errors
3680 if ( depth ) {
3681 process();
3682 } else {
3683
3684 // Call an optional hook to record the stack, in case of exception
3685 // since it's otherwise lost when execution goes async
3686 if ( jQuery.Deferred.getStackHook ) {
3687 process.stackTrace = jQuery.Deferred.getStackHook();
3688 }
3689 window.setTimeout( process );
3690 }
3691 };
3692 }
3693
3694 return jQuery.Deferred( function( newDefer ) {
3695
3696 // progress_handlers.add( ... )
3697 tuples[ 0 ][ 3 ].add(
3698 resolve(
3699 0,
3700 newDefer,
3701 jQuery.isFunction( onProgress ) ?
3702 onProgress :
3703 Identity,
3704 newDefer.notifyWith
3705 )
3706 );
3707
3708 // fulfilled_handlers.add( ... )
3709 tuples[ 1 ][ 3 ].add(
3710 resolve(
3711 0,
3712 newDefer,
3713 jQuery.isFunction( onFulfilled ) ?
3714 onFulfilled :
3715 Identity
3716 )
3717 );
3718
3719 // rejected_handlers.add( ... )
3720 tuples[ 2 ][ 3 ].add(
3721 resolve(
3722 0,
3723 newDefer,
3724 jQuery.isFunction( onRejected ) ?
3725 onRejected :
3726 Thrower
3727 )
3728 );
3729 } ).promise();
3730 },
3731
3732 // Get a promise for this deferred
3733 // If obj is provided, the promise aspect is added to the object
3734 promise: function( obj ) {
3735 return obj != null ? jQuery.extend( obj, promise ) : promise;
3736 }
3737 },
3738 deferred = {};
3739
3740 // Add list-specific methods
3741 jQuery.each( tuples, function( i, tuple ) {
3742 var list = tuple[ 2 ],
3743 stateString = tuple[ 5 ];
3744
3745 // promise.progress = list.add
3746 // promise.done = list.add
3747 // promise.fail = list.add
3748 promise[ tuple[ 1 ] ] = list.add;
3749
3750 // Handle state
3751 if ( stateString ) {
3752 list.add(
3753 function() {
3754
3755 // state = "resolved" (i.e., fulfilled)
3756 // state = "rejected"
3757 state = stateString;
3758 },
3759
3760 // rejected_callbacks.disable
3761 // fulfilled_callbacks.disable
3762 tuples[ 3 - i ][ 2 ].disable,
3763
3764 // progress_callbacks.lock
3765 tuples[ 0 ][ 2 ].lock
3766 );
3767 }
3768
3769 // progress_handlers.fire
3770 // fulfilled_handlers.fire
3771 // rejected_handlers.fire
3772 list.add( tuple[ 3 ].fire );
3773
3774 // deferred.notify = function() { deferred.notifyWith(...) }
3775 // deferred.resolve = function() { deferred.resolveWith(...) }
3776 // deferred.reject = function() { deferred.rejectWith(...) }
3777 deferred[ tuple[ 0 ] ] = function() {
3778 deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
3779 return this;
3780 };
3781
3782 // deferred.notifyWith = list.fireWith
3783 // deferred.resolveWith = list.fireWith
3784 // deferred.rejectWith = list.fireWith
3785 deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
3786 } );
3787
3788 // Make the deferred a promise
3789 promise.promise( deferred );
3790
3791 // Call given func if any
3792 if ( func ) {
3793 func.call( deferred, deferred );
3794 }
3795
3796 // All done!
3797 return deferred;
3798 },
3799
3800 // Deferred helper
3801 when: function( singleValue ) {
3802 var
3803
3804 // count of uncompleted subordinates
3805 remaining = arguments.length,
3806
3807 // count of unprocessed arguments
3808 i = remaining,
3809
3810 // subordinate fulfillment data
3811 resolveContexts = Array( i ),
3812 resolveValues = slice.call( arguments ),
3813
3814 // the master Deferred
3815 master = jQuery.Deferred(),
3816
3817 // subordinate callback factory
3818 updateFunc = function( i ) {
3819 return function( value ) {
3820 resolveContexts[ i ] = this;
3821 resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
3822 if ( !( --remaining ) ) {
3823 master.resolveWith( resolveContexts, resolveValues );
3824 }
3825 };
3826 };
3827
3828 // Single- and empty arguments are adopted like Promise.resolve
3829 if ( remaining <= 1 ) {
3830 adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
3831 !remaining );
3832
3833 // Use .then() to unwrap secondary thenables (cf. gh-3000)
3834 if ( master.state() === "pending" ||
3835 jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
3836
3837 return master.then();
3838 }
3839 }
3840
3841 // Multiple arguments are aggregated like Promise.all array elements
3842 while ( i-- ) {
3843 adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
3844 }
3845
3846 return master.promise();
3847 }
3848} );
3849
3850
3851// These usually indicate a programmer mistake during development,
3852// warn about them ASAP rather than swallowing them by default.
3853var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
3854
3855jQuery.Deferred.exceptionHook = function( error, stack ) {
3856
3857 // Support: IE 8 - 9 only
3858 // Console exists when dev tools are open, which can happen at any time
3859 if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
3860 window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
3861 }
3862};
3863
3864
3865
3866
3867jQuery.readyException = function( error ) {
3868 window.setTimeout( function() {
3869 throw error;
3870 } );
3871};
3872
3873
3874
3875
3876// The deferred used on DOM ready
3877var readyList = jQuery.Deferred();
3878
3879jQuery.fn.ready = function( fn ) {
3880
3881 readyList
3882 .then( fn )
3883
3884 // Wrap jQuery.readyException in a function so that the lookup
3885 // happens at the time of error handling instead of callback
3886 // registration.
3887 .catch( function( error ) {
3888 jQuery.readyException( error );
3889 } );
3890
3891 return this;
3892};
3893
3894jQuery.extend( {
3895
3896 // Is the DOM ready to be used? Set to true once it occurs.
3897 isReady: false,
3898
3899 // A counter to track how many items to wait for before
3900 // the ready event fires. See #6781
3901 readyWait: 1,
3902
3903 // Handle when the DOM is ready
3904 ready: function( wait ) {
3905
3906 // Abort if there are pending holds or we're already ready
3907 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
3908 return;
3909 }
3910
3911 // Remember that the DOM is ready
3912 jQuery.isReady = true;
3913
3914 // If a normal DOM Ready event fired, decrement, and wait if need be
3915 if ( wait !== true && --jQuery.readyWait > 0 ) {
3916 return;
3917 }
3918
3919 // If there are functions bound, to execute
3920 readyList.resolveWith( document, [ jQuery ] );
3921 }
3922} );
3923
3924jQuery.ready.then = readyList.then;
3925
3926// The ready event handler and self cleanup method
3927function completed() {
3928 document.removeEventListener( "DOMContentLoaded", completed );
3929 window.removeEventListener( "load", completed );
3930 jQuery.ready();
3931}
3932
3933// Catch cases where $(document).ready() is called
3934// after the browser event has already occurred.
3935// Support: IE <=9 - 10 only
3936// Older IE sometimes signals "interactive" too soon
3937if ( document.readyState === "complete" ||
3938 ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
3939
3940 // Handle it asynchronously to allow scripts the opportunity to delay ready
3941 window.setTimeout( jQuery.ready );
3942
3943} else {
3944
3945 // Use the handy event callback
3946 document.addEventListener( "DOMContentLoaded", completed );
3947
3948 // A fallback to window.onload, that will always work
3949 window.addEventListener( "load", completed );
3950}
3951
3952
3953
3954
3955// Multifunctional method to get and set values of a collection
3956// The value/s can optionally be executed if it's a function
3957var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
3958 var i = 0,
3959 len = elems.length,
3960 bulk = key == null;
3961
3962 // Sets many values
3963 if ( jQuery.type( key ) === "object" ) {
3964 chainable = true;
3965 for ( i in key ) {
3966 access( elems, fn, i, key[ i ], true, emptyGet, raw );
3967 }
3968
3969 // Sets one value
3970 } else if ( value !== undefined ) {
3971 chainable = true;
3972
3973 if ( !jQuery.isFunction( value ) ) {
3974 raw = true;
3975 }
3976
3977 if ( bulk ) {
3978
3979 // Bulk operations run against the entire set
3980 if ( raw ) {
3981 fn.call( elems, value );
3982 fn = null;
3983
3984 // ...except when executing function values
3985 } else {
3986 bulk = fn;
3987 fn = function( elem, key, value ) {
3988 return bulk.call( jQuery( elem ), value );
3989 };
3990 }
3991 }
3992
3993 if ( fn ) {
3994 for ( ; i < len; i++ ) {
3995 fn(
3996 elems[ i ], key, raw ?
3997 value :
3998 value.call( elems[ i ], i, fn( elems[ i ], key ) )
3999 );
4000 }
4001 }
4002 }
4003
4004 if ( chainable ) {
4005 return elems;
4006 }
4007
4008 // Gets
4009 if ( bulk ) {
4010 return fn.call( elems );
4011 }
4012
4013 return len ? fn( elems[ 0 ], key ) : emptyGet;
4014};
4015var acceptData = function( owner ) {
4016
4017 // Accepts only:
4018 // - Node
4019 // - Node.ELEMENT_NODE
4020 // - Node.DOCUMENT_NODE
4021 // - Object
4022 // - Any
4023 return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
4024};
4025
4026
4027
4028
4029function Data() {
4030 this.expando = jQuery.expando + Data.uid++;
4031}
4032
4033Data.uid = 1;
4034
4035Data.prototype = {
4036
4037 cache: function( owner ) {
4038
4039 // Check if the owner object already has a cache
4040 var value = owner[ this.expando ];
4041
4042 // If not, create one
4043 if ( !value ) {
4044 value = {};
4045
4046 // We can accept data for non-element nodes in modern browsers,
4047 // but we should not, see #8335.
4048 // Always return an empty object.
4049 if ( acceptData( owner ) ) {
4050
4051 // If it is a node unlikely to be stringify-ed or looped over
4052 // use plain assignment
4053 if ( owner.nodeType ) {
4054 owner[ this.expando ] = value;
4055
4056 // Otherwise secure it in a non-enumerable property
4057 // configurable must be true to allow the property to be
4058 // deleted when data is removed
4059 } else {
4060 Object.defineProperty( owner, this.expando, {
4061 value: value,
4062 configurable: true
4063 } );
4064 }
4065 }
4066 }
4067
4068 return value;
4069 },
4070 set: function( owner, data, value ) {
4071 var prop,
4072 cache = this.cache( owner );
4073
4074 // Handle: [ owner, key, value ] args
4075 // Always use camelCase key (gh-2257)
4076 if ( typeof data === "string" ) {
4077 cache[ jQuery.camelCase( data ) ] = value;
4078
4079 // Handle: [ owner, { properties } ] args
4080 } else {
4081
4082 // Copy the properties one-by-one to the cache object
4083 for ( prop in data ) {
4084 cache[ jQuery.camelCase( prop ) ] = data[ prop ];
4085 }
4086 }
4087 return cache;
4088 },
4089 get: function( owner, key ) {
4090 return key === undefined ?
4091 this.cache( owner ) :
4092
4093 // Always use camelCase key (gh-2257)
4094 owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];
4095 },
4096 access: function( owner, key, value ) {
4097
4098 // In cases where either:
4099 //
4100 // 1. No key was specified
4101 // 2. A string key was specified, but no value provided
4102 //
4103 // Take the "read" path and allow the get method to determine
4104 // which value to return, respectively either:
4105 //
4106 // 1. The entire cache object
4107 // 2. The data stored at the key
4108 //
4109 if ( key === undefined ||
4110 ( ( key && typeof key === "string" ) && value === undefined ) ) {
4111
4112 return this.get( owner, key );
4113 }
4114
4115 // When the key is not a string, or both a key and value
4116 // are specified, set or extend (existing objects) with either:
4117 //
4118 // 1. An object of properties
4119 // 2. A key and value
4120 //
4121 this.set( owner, key, value );
4122
4123 // Since the "set" path can have two possible entry points
4124 // return the expected data based on which path was taken[*]
4125 return value !== undefined ? value : key;
4126 },
4127 remove: function( owner, key ) {
4128 var i,
4129 cache = owner[ this.expando ];
4130
4131 if ( cache === undefined ) {
4132 return;
4133 }
4134
4135 if ( key !== undefined ) {
4136
4137 // Support array or space separated string of keys
4138 if ( Array.isArray( key ) ) {
4139
4140 // If key is an array of keys...
4141 // We always set camelCase keys, so remove that.
4142 key = key.map( jQuery.camelCase );
4143 } else {
4144 key = jQuery.camelCase( key );
4145
4146 // If a key with the spaces exists, use it.
4147 // Otherwise, create an array by matching non-whitespace
4148 key = key in cache ?
4149 [ key ] :
4150 ( key.match( rnothtmlwhite ) || [] );
4151 }
4152
4153 i = key.length;
4154
4155 while ( i-- ) {
4156 delete cache[ key[ i ] ];
4157 }
4158 }
4159
4160 // Remove the expando if there's no more data
4161 if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
4162
4163 // Support: Chrome <=35 - 45
4164 // Webkit & Blink performance suffers when deleting properties
4165 // from DOM nodes, so set to undefined instead
4166 // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
4167 if ( owner.nodeType ) {
4168 owner[ this.expando ] = undefined;
4169 } else {
4170 delete owner[ this.expando ];
4171 }
4172 }
4173 },
4174 hasData: function( owner ) {
4175 var cache = owner[ this.expando ];
4176 return cache !== undefined && !jQuery.isEmptyObject( cache );
4177 }
4178};
4179var dataPriv = new Data();
4180
4181var dataUser = new Data();
4182
4183
4184
4185// Implementation Summary
4186//
4187// 1. Enforce API surface and semantic compatibility with 1.9.x branch
4188// 2. Improve the module's maintainability by reducing the storage
4189// paths to a single mechanism.
4190// 3. Use the same single mechanism to support "private" and "user" data.
4191// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
4192// 5. Avoid exposing implementation details on user objects (eg. expando properties)
4193// 6. Provide a clear path for implementation upgrade to WeakMap in 2014
4194
4195var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
4196 rmultiDash = /[A-Z]/g;
4197
4198function getData( data ) {
4199 if ( data === "true" ) {
4200 return true;
4201 }
4202
4203 if ( data === "false" ) {
4204 return false;
4205 }
4206
4207 if ( data === "null" ) {
4208 return null;
4209 }
4210
4211 // Only convert to a number if it doesn't change the string
4212 if ( data === +data + "" ) {
4213 return +data;
4214 }
4215
4216 if ( rbrace.test( data ) ) {
4217 return JSON.parse( data );
4218 }
4219
4220 return data;
4221}
4222
4223function dataAttr( elem, key, data ) {
4224 var name;
4225
4226 // If nothing was found internally, try to fetch any
4227 // data from the HTML5 data-* attribute
4228 if ( data === undefined && elem.nodeType === 1 ) {
4229 name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
4230 data = elem.getAttribute( name );
4231
4232 if ( typeof data === "string" ) {
4233 try {
4234 data = getData( data );
4235 } catch ( e ) {}
4236
4237 // Make sure we set the data so it isn't changed later
4238 dataUser.set( elem, key, data );
4239 } else {
4240 data = undefined;
4241 }
4242 }
4243 return data;
4244}
4245
4246jQuery.extend( {
4247 hasData: function( elem ) {
4248 return dataUser.hasData( elem ) || dataPriv.hasData( elem );
4249 },
4250
4251 data: function( elem, name, data ) {
4252 return dataUser.access( elem, name, data );
4253 },
4254
4255 removeData: function( elem, name ) {
4256 dataUser.remove( elem, name );
4257 },
4258
4259 // TODO: Now that all calls to _data and _removeData have been replaced
4260 // with direct calls to dataPriv methods, these can be deprecated.
4261 _data: function( elem, name, data ) {
4262 return dataPriv.access( elem, name, data );
4263 },
4264
4265 _removeData: function( elem, name ) {
4266 dataPriv.remove( elem, name );
4267 }
4268} );
4269
4270jQuery.fn.extend( {
4271 data: function( key, value ) {
4272 var i, name, data,
4273 elem = this[ 0 ],
4274 attrs = elem && elem.attributes;
4275
4276 // Gets all values
4277 if ( key === undefined ) {
4278 if ( this.length ) {
4279 data = dataUser.get( elem );
4280
4281 if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
4282 i = attrs.length;
4283 while ( i-- ) {
4284
4285 // Support: IE 11 only
4286 // The attrs elements can be null (#14894)
4287 if ( attrs[ i ] ) {
4288 name = attrs[ i ].name;
4289 if ( name.indexOf( "data-" ) === 0 ) {
4290 name = jQuery.camelCase( name.slice( 5 ) );
4291 dataAttr( elem, name, data[ name ] );
4292 }
4293 }
4294 }
4295 dataPriv.set( elem, "hasDataAttrs", true );
4296 }
4297 }
4298
4299 return data;
4300 }
4301
4302 // Sets multiple values
4303 if ( typeof key === "object" ) {
4304 return this.each( function() {
4305 dataUser.set( this, key );
4306 } );
4307 }
4308
4309 return access( this, function( value ) {
4310 var data;
4311
4312 // The calling jQuery object (element matches) is not empty
4313 // (and therefore has an element appears at this[ 0 ]) and the
4314 // `value` parameter was not undefined. An empty jQuery object
4315 // will result in `undefined` for elem = this[ 0 ] which will
4316 // throw an exception if an attempt to read a data cache is made.
4317 if ( elem && value === undefined ) {
4318
4319 // Attempt to get data from the cache
4320 // The key will always be camelCased in Data
4321 data = dataUser.get( elem, key );
4322 if ( data !== undefined ) {
4323 return data;
4324 }
4325
4326 // Attempt to "discover" the data in
4327 // HTML5 custom data-* attrs
4328 data = dataAttr( elem, key );
4329 if ( data !== undefined ) {
4330 return data;
4331 }
4332
4333 // We tried really hard, but the data doesn't exist.
4334 return;
4335 }
4336
4337 // Set the data...
4338 this.each( function() {
4339
4340 // We always store the camelCased key
4341 dataUser.set( this, key, value );
4342 } );
4343 }, null, value, arguments.length > 1, null, true );
4344 },
4345
4346 removeData: function( key ) {
4347 return this.each( function() {
4348 dataUser.remove( this, key );
4349 } );
4350 }
4351} );
4352
4353
4354jQuery.extend( {
4355 queue: function( elem, type, data ) {
4356 var queue;
4357
4358 if ( elem ) {
4359 type = ( type || "fx" ) + "queue";
4360 queue = dataPriv.get( elem, type );
4361
4362 // Speed up dequeue by getting out quickly if this is just a lookup
4363 if ( data ) {
4364 if ( !queue || Array.isArray( data ) ) {
4365 queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
4366 } else {
4367 queue.push( data );
4368 }
4369 }
4370 return queue || [];
4371 }
4372 },
4373
4374 dequeue: function( elem, type ) {
4375 type = type || "fx";
4376
4377 var queue = jQuery.queue( elem, type ),
4378 startLength = queue.length,
4379 fn = queue.shift(),
4380 hooks = jQuery._queueHooks( elem, type ),
4381 next = function() {
4382 jQuery.dequeue( elem, type );
4383 };
4384
4385 // If the fx queue is dequeued, always remove the progress sentinel
4386 if ( fn === "inprogress" ) {
4387 fn = queue.shift();
4388 startLength--;
4389 }
4390
4391 if ( fn ) {
4392
4393 // Add a progress sentinel to prevent the fx queue from being
4394 // automatically dequeued
4395 if ( type === "fx" ) {
4396 queue.unshift( "inprogress" );
4397 }
4398
4399 // Clear up the last queue stop function
4400 delete hooks.stop;
4401 fn.call( elem, next, hooks );
4402 }
4403
4404 if ( !startLength && hooks ) {
4405 hooks.empty.fire();
4406 }
4407 },
4408
4409 // Not public - generate a queueHooks object, or return the current one
4410 _queueHooks: function( elem, type ) {
4411 var key = type + "queueHooks";
4412 return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
4413 empty: jQuery.Callbacks( "once memory" ).add( function() {
4414 dataPriv.remove( elem, [ type + "queue", key ] );
4415 } )
4416 } );
4417 }
4418} );
4419
4420jQuery.fn.extend( {
4421 queue: function( type, data ) {
4422 var setter = 2;
4423
4424 if ( typeof type !== "string" ) {
4425 data = type;
4426 type = "fx";
4427 setter--;
4428 }
4429
4430 if ( arguments.length < setter ) {
4431 return jQuery.queue( this[ 0 ], type );
4432 }
4433
4434 return data === undefined ?
4435 this :
4436 this.each( function() {
4437 var queue = jQuery.queue( this, type, data );
4438
4439 // Ensure a hooks for this queue
4440 jQuery._queueHooks( this, type );
4441
4442 if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
4443 jQuery.dequeue( this, type );
4444 }
4445 } );
4446 },
4447 dequeue: function( type ) {
4448 return this.each( function() {
4449 jQuery.dequeue( this, type );
4450 } );
4451 },
4452 clearQueue: function( type ) {
4453 return this.queue( type || "fx", [] );
4454 },
4455
4456 // Get a promise resolved when queues of a certain type
4457 // are emptied (fx is the type by default)
4458 promise: function( type, obj ) {
4459 var tmp,
4460 count = 1,
4461 defer = jQuery.Deferred(),
4462 elements = this,
4463 i = this.length,
4464 resolve = function() {
4465 if ( !( --count ) ) {
4466 defer.resolveWith( elements, [ elements ] );
4467 }
4468 };
4469
4470 if ( typeof type !== "string" ) {
4471 obj = type;
4472 type = undefined;
4473 }
4474 type = type || "fx";
4475
4476 while ( i-- ) {
4477 tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
4478 if ( tmp && tmp.empty ) {
4479 count++;
4480 tmp.empty.add( resolve );
4481 }
4482 }
4483 resolve();
4484 return defer.promise( obj );
4485 }
4486} );
4487var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
4488
4489var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
4490
4491
4492var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
4493
4494var isHiddenWithinTree = function( elem, el ) {
4495
4496 // isHiddenWithinTree might be called from jQuery#filter function;
4497 // in that case, element will be second argument
4498 elem = el || elem;
4499
4500 // Inline style trumps all
4501 return elem.style.display === "none" ||
4502 elem.style.display === "" &&
4503
4504 // Otherwise, check computed style
4505 // Support: Firefox <=43 - 45
4506 // Disconnected elements can have computed display: none, so first confirm that elem is
4507 // in the document.
4508 jQuery.contains( elem.ownerDocument, elem ) &&
4509
4510 jQuery.css( elem, "display" ) === "none";
4511 };
4512
4513var swap = function( elem, options, callback, args ) {
4514 var ret, name,
4515 old = {};
4516
4517 // Remember the old values, and insert the new ones
4518 for ( name in options ) {
4519 old[ name ] = elem.style[ name ];
4520 elem.style[ name ] = options[ name ];
4521 }
4522
4523 ret = callback.apply( elem, args || [] );
4524
4525 // Revert the old values
4526 for ( name in options ) {
4527 elem.style[ name ] = old[ name ];
4528 }
4529
4530 return ret;
4531};
4532
4533
4534
4535
4536function adjustCSS( elem, prop, valueParts, tween ) {
4537 var adjusted,
4538 scale = 1,
4539 maxIterations = 20,
4540 currentValue = tween ?
4541 function() {
4542 return tween.cur();
4543 } :
4544 function() {
4545 return jQuery.css( elem, prop, "" );
4546 },
4547 initial = currentValue(),
4548 unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
4549
4550 // Starting value computation is required for potential unit mismatches
4551 initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
4552 rcssNum.exec( jQuery.css( elem, prop ) );
4553
4554 if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
4555
4556 // Trust units reported by jQuery.css
4557 unit = unit || initialInUnit[ 3 ];
4558
4559 // Make sure we update the tween properties later on
4560 valueParts = valueParts || [];
4561
4562 // Iteratively approximate from a nonzero starting point
4563 initialInUnit = +initial || 1;
4564
4565 do {
4566
4567 // If previous iteration zeroed out, double until we get *something*.
4568 // Use string for doubling so we don't accidentally see scale as unchanged below
4569 scale = scale || ".5";
4570
4571 // Adjust and apply
4572 initialInUnit = initialInUnit / scale;
4573 jQuery.style( elem, prop, initialInUnit + unit );
4574
4575 // Update scale, tolerating zero or NaN from tween.cur()
4576 // Break the loop if scale is unchanged or perfect, or if we've just had enough.
4577 } while (
4578 scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
4579 );
4580 }
4581
4582 if ( valueParts ) {
4583 initialInUnit = +initialInUnit || +initial || 0;
4584
4585 // Apply relative offset (+=/-=) if specified
4586 adjusted = valueParts[ 1 ] ?
4587 initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
4588 +valueParts[ 2 ];
4589 if ( tween ) {
4590 tween.unit = unit;
4591 tween.start = initialInUnit;
4592 tween.end = adjusted;
4593 }
4594 }
4595 return adjusted;
4596}
4597
4598
4599var defaultDisplayMap = {};
4600
4601function getDefaultDisplay( elem ) {
4602 var temp,
4603 doc = elem.ownerDocument,
4604 nodeName = elem.nodeName,
4605 display = defaultDisplayMap[ nodeName ];
4606
4607 if ( display ) {
4608 return display;
4609 }
4610
4611 temp = doc.body.appendChild( doc.createElement( nodeName ) );
4612 display = jQuery.css( temp, "display" );
4613
4614 temp.parentNode.removeChild( temp );
4615
4616 if ( display === "none" ) {
4617 display = "block";
4618 }
4619 defaultDisplayMap[ nodeName ] = display;
4620
4621 return display;
4622}
4623
4624function showHide( elements, show ) {
4625 var display, elem,
4626 values = [],
4627 index = 0,
4628 length = elements.length;
4629
4630 // Determine new display value for elements that need to change
4631 for ( ; index < length; index++ ) {
4632 elem = elements[ index ];
4633 if ( !elem.style ) {
4634 continue;
4635 }
4636
4637 display = elem.style.display;
4638 if ( show ) {
4639
4640 // Since we force visibility upon cascade-hidden elements, an immediate (and slow)
4641 // check is required in this first loop unless we have a nonempty display value (either
4642 // inline or about-to-be-restored)
4643 if ( display === "none" ) {
4644 values[ index ] = dataPriv.get( elem, "display" ) || null;
4645 if ( !values[ index ] ) {
4646 elem.style.display = "";
4647 }
4648 }
4649 if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
4650 values[ index ] = getDefaultDisplay( elem );
4651 }
4652 } else {
4653 if ( display !== "none" ) {
4654 values[ index ] = "none";
4655
4656 // Remember what we're overwriting
4657 dataPriv.set( elem, "display", display );
4658 }
4659 }
4660 }
4661
4662 // Set the display of the elements in a second loop to avoid constant reflow
4663 for ( index = 0; index < length; index++ ) {
4664 if ( values[ index ] != null ) {
4665 elements[ index ].style.display = values[ index ];
4666 }
4667 }
4668
4669 return elements;
4670}
4671
4672jQuery.fn.extend( {
4673 show: function() {
4674 return showHide( this, true );
4675 },
4676 hide: function() {
4677 return showHide( this );
4678 },
4679 toggle: function( state ) {
4680 if ( typeof state === "boolean" ) {
4681 return state ? this.show() : this.hide();
4682 }
4683
4684 return this.each( function() {
4685 if ( isHiddenWithinTree( this ) ) {
4686 jQuery( this ).show();
4687 } else {
4688 jQuery( this ).hide();
4689 }
4690 } );
4691 }
4692} );
4693var rcheckableType = ( /^(?:checkbox|radio)$/i );
4694
4695var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i );
4696
4697var rscriptType = ( /^$|\/(?:java|ecma)script/i );
4698
4699
4700
4701// We have to close these tags to support XHTML (#13200)
4702var wrapMap = {
4703
4704 // Support: IE <=9 only
4705 option: [ 1, "<select multiple='multiple'>", "</select>" ],
4706
4707 // XHTML parsers do not magically insert elements in the
4708 // same way that tag soup parsers do. So we cannot shorten
4709 // this by omitting <tbody> or other required elements.
4710 thead: [ 1, "<table>", "</table>" ],
4711 col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
4712 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
4713 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
4714
4715 _default: [ 0, "", "" ]
4716};
4717
4718// Support: IE <=9 only
4719wrapMap.optgroup = wrapMap.option;
4720
4721wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
4722wrapMap.th = wrapMap.td;
4723
4724
4725function getAll( context, tag ) {
4726
4727 // Support: IE <=9 - 11 only
4728 // Use typeof to avoid zero-argument method invocation on host objects (#15151)
4729 var ret;
4730
4731 if ( typeof context.getElementsByTagName !== "undefined" ) {
4732 ret = context.getElementsByTagName( tag || "*" );
4733
4734 } else if ( typeof context.querySelectorAll !== "undefined" ) {
4735 ret = context.querySelectorAll( tag || "*" );
4736
4737 } else {
4738 ret = [];
4739 }
4740
4741 if ( tag === undefined || tag && nodeName( context, tag ) ) {
4742 return jQuery.merge( [ context ], ret );
4743 }
4744
4745 return ret;
4746}
4747
4748
4749// Mark scripts as having already been evaluated
4750function setGlobalEval( elems, refElements ) {
4751 var i = 0,
4752 l = elems.length;
4753
4754 for ( ; i < l; i++ ) {
4755 dataPriv.set(
4756 elems[ i ],
4757 "globalEval",
4758 !refElements || dataPriv.get( refElements[ i ], "globalEval" )
4759 );
4760 }
4761}
4762
4763
4764var rhtml = /<|&#?\w+;/;
4765
4766function buildFragment( elems, context, scripts, selection, ignored ) {
4767 var elem, tmp, tag, wrap, contains, j,
4768 fragment = context.createDocumentFragment(),
4769 nodes = [],
4770 i = 0,
4771 l = elems.length;
4772
4773 for ( ; i < l; i++ ) {
4774 elem = elems[ i ];
4775
4776 if ( elem || elem === 0 ) {
4777
4778 // Add nodes directly
4779 if ( jQuery.type( elem ) === "object" ) {
4780
4781 // Support: Android <=4.0 only, PhantomJS 1 only
4782 // push.apply(_, arraylike) throws on ancient WebKit
4783 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
4784
4785 // Convert non-html into a text node
4786 } else if ( !rhtml.test( elem ) ) {
4787 nodes.push( context.createTextNode( elem ) );
4788
4789 // Convert html into DOM nodes
4790 } else {
4791 tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
4792
4793 // Deserialize a standard representation
4794 tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
4795 wrap = wrapMap[ tag ] || wrapMap._default;
4796 tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
4797
4798 // Descend through wrappers to the right content
4799 j = wrap[ 0 ];
4800 while ( j-- ) {
4801 tmp = tmp.lastChild;
4802 }
4803
4804 // Support: Android <=4.0 only, PhantomJS 1 only
4805 // push.apply(_, arraylike) throws on ancient WebKit
4806 jQuery.merge( nodes, tmp.childNodes );
4807
4808 // Remember the top-level container
4809 tmp = fragment.firstChild;
4810
4811 // Ensure the created nodes are orphaned (#12392)
4812 tmp.textContent = "";
4813 }
4814 }
4815 }
4816
4817 // Remove wrapper from fragment
4818 fragment.textContent = "";
4819
4820 i = 0;
4821 while ( ( elem = nodes[ i++ ] ) ) {
4822
4823 // Skip elements already in the context collection (trac-4087)
4824 if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
4825 if ( ignored ) {
4826 ignored.push( elem );
4827 }
4828 continue;
4829 }
4830
4831 contains = jQuery.contains( elem.ownerDocument, elem );
4832
4833 // Append to fragment
4834 tmp = getAll( fragment.appendChild( elem ), "script" );
4835
4836 // Preserve script evaluation history
4837 if ( contains ) {
4838 setGlobalEval( tmp );
4839 }
4840
4841 // Capture executables
4842 if ( scripts ) {
4843 j = 0;
4844 while ( ( elem = tmp[ j++ ] ) ) {
4845 if ( rscriptType.test( elem.type || "" ) ) {
4846 scripts.push( elem );
4847 }
4848 }
4849 }
4850 }
4851
4852 return fragment;
4853}
4854
4855
4856( function() {
4857 var fragment = document.createDocumentFragment(),
4858 div = fragment.appendChild( document.createElement( "div" ) ),
4859 input = document.createElement( "input" );
4860
4861 // Support: Android 4.0 - 4.3 only
4862 // Check state lost if the name is set (#11217)
4863 // Support: Windows Web Apps (WWA)
4864 // `name` and `type` must use .setAttribute for WWA (#14901)
4865 input.setAttribute( "type", "radio" );
4866 input.setAttribute( "checked", "checked" );
4867 input.setAttribute( "name", "t" );
4868
4869 div.appendChild( input );
4870
4871 // Support: Android <=4.1 only
4872 // Older WebKit doesn't clone checked state correctly in fragments
4873 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
4874
4875 // Support: IE <=11 only
4876 // Make sure textarea (and checkbox) defaultValue is properly cloned
4877 div.innerHTML = "<textarea>x</textarea>";
4878 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
4879} )();
4880var documentElement = document.documentElement;
4881
4882
4883
4884var
4885 rkeyEvent = /^key/,
4886 rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
4887 rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
4888
4889function returnTrue() {
4890 return true;
4891}
4892
4893function returnFalse() {
4894 return false;
4895}
4896
4897// Support: IE <=9 only
4898// See #13393 for more info
4899function safeActiveElement() {
4900 try {
4901 return document.activeElement;
4902 } catch ( err ) { }
4903}
4904
4905function on( elem, types, selector, data, fn, one ) {
4906 var origFn, type;
4907
4908 // Types can be a map of types/handlers
4909 if ( typeof types === "object" ) {
4910
4911 // ( types-Object, selector, data )
4912 if ( typeof selector !== "string" ) {
4913
4914 // ( types-Object, data )
4915 data = data || selector;
4916 selector = undefined;
4917 }
4918 for ( type in types ) {
4919 on( elem, type, selector, data, types[ type ], one );
4920 }
4921 return elem;
4922 }
4923
4924 if ( data == null && fn == null ) {
4925
4926 // ( types, fn )
4927 fn = selector;
4928 data = selector = undefined;
4929 } else if ( fn == null ) {
4930 if ( typeof selector === "string" ) {
4931
4932 // ( types, selector, fn )
4933 fn = data;
4934 data = undefined;
4935 } else {
4936
4937 // ( types, data, fn )
4938 fn = data;
4939 data = selector;
4940 selector = undefined;
4941 }
4942 }
4943 if ( fn === false ) {
4944 fn = returnFalse;
4945 } else if ( !fn ) {
4946 return elem;
4947 }
4948
4949 if ( one === 1 ) {
4950 origFn = fn;
4951 fn = function( event ) {
4952
4953 // Can use an empty set, since event contains the info
4954 jQuery().off( event );
4955 return origFn.apply( this, arguments );
4956 };
4957
4958 // Use same guid so caller can remove using origFn
4959 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
4960 }
4961 return elem.each( function() {
4962 jQuery.event.add( this, types, fn, data, selector );
4963 } );
4964}
4965
4966/*
4967 * Helper functions for managing events -- not part of the public interface.
4968 * Props to Dean Edwards' addEvent library for many of the ideas.
4969 */
4970jQuery.event = {
4971
4972 global: {},
4973
4974 add: function( elem, types, handler, data, selector ) {
4975
4976 var handleObjIn, eventHandle, tmp,
4977 events, t, handleObj,
4978 special, handlers, type, namespaces, origType,
4979 elemData = dataPriv.get( elem );
4980
4981 // Don't attach events to noData or text/comment nodes (but allow plain objects)
4982 if ( !elemData ) {
4983 return;
4984 }
4985
4986 // Caller can pass in an object of custom data in lieu of the handler
4987 if ( handler.handler ) {
4988 handleObjIn = handler;
4989 handler = handleObjIn.handler;
4990 selector = handleObjIn.selector;
4991 }
4992
4993 // Ensure that invalid selectors throw exceptions at attach time
4994 // Evaluate against documentElement in case elem is a non-element node (e.g., document)
4995 if ( selector ) {
4996 jQuery.find.matchesSelector( documentElement, selector );
4997 }
4998
4999 // Make sure that the handler has a unique ID, used to find/remove it later
5000 if ( !handler.guid ) {
5001 handler.guid = jQuery.guid++;
5002 }
5003
5004 // Init the element's event structure and main handler, if this is the first
5005 if ( !( events = elemData.events ) ) {
5006 events = elemData.events = {};
5007 }
5008 if ( !( eventHandle = elemData.handle ) ) {
5009 eventHandle = elemData.handle = function( e ) {
5010
5011 // Discard the second event of a jQuery.event.trigger() and
5012 // when an event is called after a page has unloaded
5013 return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
5014 jQuery.event.dispatch.apply( elem, arguments ) : undefined;
5015 };
5016 }
5017
5018 // Handle multiple events separated by a space
5019 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
5020 t = types.length;
5021 while ( t-- ) {
5022 tmp = rtypenamespace.exec( types[ t ] ) || [];
5023 type = origType = tmp[ 1 ];
5024 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
5025
5026 // There *must* be a type, no attaching namespace-only handlers
5027 if ( !type ) {
5028 continue;
5029 }
5030
5031 // If event changes its type, use the special event handlers for the changed type
5032 special = jQuery.event.special[ type ] || {};
5033
5034 // If selector defined, determine special event api type, otherwise given type
5035 type = ( selector ? special.delegateType : special.bindType ) || type;
5036
5037 // Update special based on newly reset type
5038 special = jQuery.event.special[ type ] || {};
5039
5040 // handleObj is passed to all event handlers
5041 handleObj = jQuery.extend( {
5042 type: type,
5043 origType: origType,
5044 data: data,
5045 handler: handler,
5046 guid: handler.guid,
5047 selector: selector,
5048 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
5049 namespace: namespaces.join( "." )
5050 }, handleObjIn );
5051
5052 // Init the event handler queue if we're the first
5053 if ( !( handlers = events[ type ] ) ) {
5054 handlers = events[ type ] = [];
5055 handlers.delegateCount = 0;
5056
5057 // Only use addEventListener if the special events handler returns false
5058 if ( !special.setup ||
5059 special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
5060
5061 if ( elem.addEventListener ) {
5062 elem.addEventListener( type, eventHandle );
5063 }
5064 }
5065 }
5066
5067 if ( special.add ) {
5068 special.add.call( elem, handleObj );
5069
5070 if ( !handleObj.handler.guid ) {
5071 handleObj.handler.guid = handler.guid;
5072 }
5073 }
5074
5075 // Add to the element's handler list, delegates in front
5076 if ( selector ) {
5077 handlers.splice( handlers.delegateCount++, 0, handleObj );
5078 } else {
5079 handlers.push( handleObj );
5080 }
5081
5082 // Keep track of which events have ever been used, for event optimization
5083 jQuery.event.global[ type ] = true;
5084 }
5085
5086 },
5087
5088 // Detach an event or set of events from an element
5089 remove: function( elem, types, handler, selector, mappedTypes ) {
5090
5091 var j, origCount, tmp,
5092 events, t, handleObj,
5093 special, handlers, type, namespaces, origType,
5094 elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
5095
5096 if ( !elemData || !( events = elemData.events ) ) {
5097 return;
5098 }
5099
5100 // Once for each type.namespace in types; type may be omitted
5101 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
5102 t = types.length;
5103 while ( t-- ) {
5104 tmp = rtypenamespace.exec( types[ t ] ) || [];
5105 type = origType = tmp[ 1 ];
5106 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
5107
5108 // Unbind all events (on this namespace, if provided) for the element
5109 if ( !type ) {
5110 for ( type in events ) {
5111 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
5112 }
5113 continue;
5114 }
5115
5116 special = jQuery.event.special[ type ] || {};
5117 type = ( selector ? special.delegateType : special.bindType ) || type;
5118 handlers = events[ type ] || [];
5119 tmp = tmp[ 2 ] &&
5120 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
5121
5122 // Remove matching events
5123 origCount = j = handlers.length;
5124 while ( j-- ) {
5125 handleObj = handlers[ j ];
5126
5127 if ( ( mappedTypes || origType === handleObj.origType ) &&
5128 ( !handler || handler.guid === handleObj.guid ) &&
5129 ( !tmp || tmp.test( handleObj.namespace ) ) &&
5130 ( !selector || selector === handleObj.selector ||
5131 selector === "**" && handleObj.selector ) ) {
5132 handlers.splice( j, 1 );
5133
5134 if ( handleObj.selector ) {
5135 handlers.delegateCount--;
5136 }
5137 if ( special.remove ) {
5138 special.remove.call( elem, handleObj );
5139 }
5140 }
5141 }
5142
5143 // Remove generic event handler if we removed something and no more handlers exist
5144 // (avoids potential for endless recursion during removal of special event handlers)
5145 if ( origCount && !handlers.length ) {
5146 if ( !special.teardown ||
5147 special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
5148
5149 jQuery.removeEvent( elem, type, elemData.handle );
5150 }
5151
5152 delete events[ type ];
5153 }
5154 }
5155
5156 // Remove data and the expando if it's no longer used
5157 if ( jQuery.isEmptyObject( events ) ) {
5158 dataPriv.remove( elem, "handle events" );
5159 }
5160 },
5161
5162 dispatch: function( nativeEvent ) {
5163
5164 // Make a writable jQuery.Event from the native event object
5165 var event = jQuery.event.fix( nativeEvent );
5166
5167 var i, j, ret, matched, handleObj, handlerQueue,
5168 args = new Array( arguments.length ),
5169 handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
5170 special = jQuery.event.special[ event.type ] || {};
5171
5172 // Use the fix-ed jQuery.Event rather than the (read-only) native event
5173 args[ 0 ] = event;
5174
5175 for ( i = 1; i < arguments.length; i++ ) {
5176 args[ i ] = arguments[ i ];
5177 }
5178
5179 event.delegateTarget = this;
5180
5181 // Call the preDispatch hook for the mapped type, and let it bail if desired
5182 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
5183 return;
5184 }
5185
5186 // Determine handlers
5187 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
5188
5189 // Run delegates first; they may want to stop propagation beneath us
5190 i = 0;
5191 while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
5192 event.currentTarget = matched.elem;
5193
5194 j = 0;
5195 while ( ( handleObj = matched.handlers[ j++ ] ) &&
5196 !event.isImmediatePropagationStopped() ) {
5197
5198 // Triggered event must either 1) have no namespace, or 2) have namespace(s)
5199 // a subset or equal to those in the bound event (both can have no namespace).
5200 if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
5201
5202 event.handleObj = handleObj;
5203 event.data = handleObj.data;
5204
5205 ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
5206 handleObj.handler ).apply( matched.elem, args );
5207
5208 if ( ret !== undefined ) {
5209 if ( ( event.result = ret ) === false ) {
5210 event.preventDefault();
5211 event.stopPropagation();
5212 }
5213 }
5214 }
5215 }
5216 }
5217
5218 // Call the postDispatch hook for the mapped type
5219 if ( special.postDispatch ) {
5220 special.postDispatch.call( this, event );
5221 }
5222
5223 return event.result;
5224 },
5225
5226 handlers: function( event, handlers ) {
5227 var i, handleObj, sel, matchedHandlers, matchedSelectors,
5228 handlerQueue = [],
5229 delegateCount = handlers.delegateCount,
5230 cur = event.target;
5231
5232 // Find delegate handlers
5233 if ( delegateCount &&
5234
5235 // Support: IE <=9
5236 // Black-hole SVG <use> instance trees (trac-13180)
5237 cur.nodeType &&
5238
5239 // Support: Firefox <=42
5240 // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
5241 // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
5242 // Support: IE 11 only
5243 // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
5244 !( event.type === "click" && event.button >= 1 ) ) {
5245
5246 for ( ; cur !== this; cur = cur.parentNode || this ) {
5247
5248 // Don't check non-elements (#13208)
5249 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
5250 if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
5251 matchedHandlers = [];
5252 matchedSelectors = {};
5253 for ( i = 0; i < delegateCount; i++ ) {
5254 handleObj = handlers[ i ];
5255
5256 // Don't conflict with Object.prototype properties (#13203)
5257 sel = handleObj.selector + " ";
5258
5259 if ( matchedSelectors[ sel ] === undefined ) {
5260 matchedSelectors[ sel ] = handleObj.needsContext ?
5261 jQuery( sel, this ).index( cur ) > -1 :
5262 jQuery.find( sel, this, null, [ cur ] ).length;
5263 }
5264 if ( matchedSelectors[ sel ] ) {
5265 matchedHandlers.push( handleObj );
5266 }
5267 }
5268 if ( matchedHandlers.length ) {
5269 handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
5270 }
5271 }
5272 }
5273 }
5274
5275 // Add the remaining (directly-bound) handlers
5276 cur = this;
5277 if ( delegateCount < handlers.length ) {
5278 handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
5279 }
5280
5281 return handlerQueue;
5282 },
5283
5284 addProp: function( name, hook ) {
5285 Object.defineProperty( jQuery.Event.prototype, name, {
5286 enumerable: true,
5287 configurable: true,
5288
5289 get: jQuery.isFunction( hook ) ?
5290 function() {
5291 if ( this.originalEvent ) {
5292 return hook( this.originalEvent );
5293 }
5294 } :
5295 function() {
5296 if ( this.originalEvent ) {
5297 return this.originalEvent[ name ];
5298 }
5299 },
5300
5301 set: function( value ) {
5302 Object.defineProperty( this, name, {
5303 enumerable: true,
5304 configurable: true,
5305 writable: true,
5306 value: value
5307 } );
5308 }
5309 } );
5310 },
5311
5312 fix: function( originalEvent ) {
5313 return originalEvent[ jQuery.expando ] ?
5314 originalEvent :
5315 new jQuery.Event( originalEvent );
5316 },
5317
5318 special: {
5319 load: {
5320
5321 // Prevent triggered image.load events from bubbling to window.load
5322 noBubble: true
5323 },
5324 focus: {
5325
5326 // Fire native event if possible so blur/focus sequence is correct
5327 trigger: function() {
5328 if ( this !== safeActiveElement() && this.focus ) {
5329 this.focus();
5330 return false;
5331 }
5332 },
5333 delegateType: "focusin"
5334 },
5335 blur: {
5336 trigger: function() {
5337 if ( this === safeActiveElement() && this.blur ) {
5338 this.blur();
5339 return false;
5340 }
5341 },
5342 delegateType: "focusout"
5343 },
5344 click: {
5345
5346 // For checkbox, fire native event so checked state will be right
5347 trigger: function() {
5348 if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) {
5349 this.click();
5350 return false;
5351 }
5352 },
5353
5354 // For cross-browser consistency, don't fire native .click() on links
5355 _default: function( event ) {
5356 return nodeName( event.target, "a" );
5357 }
5358 },
5359
5360 beforeunload: {
5361 postDispatch: function( event ) {
5362
5363 // Support: Firefox 20+
5364 // Firefox doesn't alert if the returnValue field is not set.
5365 if ( event.result !== undefined && event.originalEvent ) {
5366 event.originalEvent.returnValue = event.result;
5367 }
5368 }
5369 }
5370 }
5371};
5372
5373jQuery.removeEvent = function( elem, type, handle ) {
5374
5375 // This "if" is needed for plain objects
5376 if ( elem.removeEventListener ) {
5377 elem.removeEventListener( type, handle );
5378 }
5379};
5380
5381jQuery.Event = function( src, props ) {
5382
5383 // Allow instantiation without the 'new' keyword
5384 if ( !( this instanceof jQuery.Event ) ) {
5385 return new jQuery.Event( src, props );
5386 }
5387
5388 // Event object
5389 if ( src && src.type ) {
5390 this.originalEvent = src;
5391 this.type = src.type;
5392
5393 // Events bubbling up the document may have been marked as prevented
5394 // by a handler lower down the tree; reflect the correct value.
5395 this.isDefaultPrevented = src.defaultPrevented ||
5396 src.defaultPrevented === undefined &&
5397
5398 // Support: Android <=2.3 only
5399 src.returnValue === false ?
5400 returnTrue :
5401 returnFalse;
5402
5403 // Create target properties
5404 // Support: Safari <=6 - 7 only
5405 // Target should not be a text node (#504, #13143)
5406 this.target = ( src.target && src.target.nodeType === 3 ) ?
5407 src.target.parentNode :
5408 src.target;
5409
5410 this.currentTarget = src.currentTarget;
5411 this.relatedTarget = src.relatedTarget;
5412
5413 // Event type
5414 } else {
5415 this.type = src;
5416 }
5417
5418 // Put explicitly provided properties onto the event object
5419 if ( props ) {
5420 jQuery.extend( this, props );
5421 }
5422
5423 // Create a timestamp if incoming event doesn't have one
5424 this.timeStamp = src && src.timeStamp || jQuery.now();
5425
5426 // Mark it as fixed
5427 this[ jQuery.expando ] = true;
5428};
5429
5430// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
5431// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
5432jQuery.Event.prototype = {
5433 constructor: jQuery.Event,
5434 isDefaultPrevented: returnFalse,
5435 isPropagationStopped: returnFalse,
5436 isImmediatePropagationStopped: returnFalse,
5437 isSimulated: false,
5438
5439 preventDefault: function() {
5440 var e = this.originalEvent;
5441
5442 this.isDefaultPrevented = returnTrue;
5443
5444 if ( e && !this.isSimulated ) {
5445 e.preventDefault();
5446 }
5447 },
5448 stopPropagation: function() {
5449 var e = this.originalEvent;
5450
5451 this.isPropagationStopped = returnTrue;
5452
5453 if ( e && !this.isSimulated ) {
5454 e.stopPropagation();
5455 }
5456 },
5457 stopImmediatePropagation: function() {
5458 var e = this.originalEvent;
5459
5460 this.isImmediatePropagationStopped = returnTrue;
5461
5462 if ( e && !this.isSimulated ) {
5463 e.stopImmediatePropagation();
5464 }
5465
5466 this.stopPropagation();
5467 }
5468};
5469
5470// Includes all common event props including KeyEvent and MouseEvent specific props
5471jQuery.each( {
5472 altKey: true,
5473 bubbles: true,
5474 cancelable: true,
5475 changedTouches: true,
5476 ctrlKey: true,
5477 detail: true,
5478 eventPhase: true,
5479 metaKey: true,
5480 pageX: true,
5481 pageY: true,
5482 shiftKey: true,
5483 view: true,
5484 "char": true,
5485 charCode: true,
5486 key: true,
5487 keyCode: true,
5488 button: true,
5489 buttons: true,
5490 clientX: true,
5491 clientY: true,
5492 offsetX: true,
5493 offsetY: true,
5494 pointerId: true,
5495 pointerType: true,
5496 screenX: true,
5497 screenY: true,
5498 targetTouches: true,
5499 toElement: true,
5500 touches: true,
5501
5502 which: function( event ) {
5503 var button = event.button;
5504
5505 // Add which for key events
5506 if ( event.which == null && rkeyEvent.test( event.type ) ) {
5507 return event.charCode != null ? event.charCode : event.keyCode;
5508 }
5509
5510 // Add which for click: 1 === left; 2 === middle; 3 === right
5511 if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
5512 if ( button & 1 ) {
5513 return 1;
5514 }
5515
5516 if ( button & 2 ) {
5517 return 3;
5518 }
5519
5520 if ( button & 4 ) {
5521 return 2;
5522 }
5523
5524 return 0;
5525 }
5526
5527 return event.which;
5528 }
5529}, jQuery.event.addProp );
5530
5531// Create mouseenter/leave events using mouseover/out and event-time checks
5532// so that event delegation works in jQuery.
5533// Do the same for pointerenter/pointerleave and pointerover/pointerout
5534//
5535// Support: Safari 7 only
5536// Safari sends mouseenter too often; see:
5537// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
5538// for the description of the bug (it existed in older Chrome versions as well).
5539jQuery.each( {
5540 mouseenter: "mouseover",
5541 mouseleave: "mouseout",
5542 pointerenter: "pointerover",
5543 pointerleave: "pointerout"
5544}, function( orig, fix ) {
5545 jQuery.event.special[ orig ] = {
5546 delegateType: fix,
5547 bindType: fix,
5548
5549 handle: function( event ) {
5550 var ret,
5551 target = this,
5552 related = event.relatedTarget,
5553 handleObj = event.handleObj;
5554
5555 // For mouseenter/leave call the handler if related is outside the target.
5556 // NB: No relatedTarget if the mouse left/entered the browser window
5557 if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
5558 event.type = handleObj.origType;
5559 ret = handleObj.handler.apply( this, arguments );
5560 event.type = fix;
5561 }
5562 return ret;
5563 }
5564 };
5565} );
5566
5567jQuery.fn.extend( {
5568
5569 on: function( types, selector, data, fn ) {
5570 return on( this, types, selector, data, fn );
5571 },
5572 one: function( types, selector, data, fn ) {
5573 return on( this, types, selector, data, fn, 1 );
5574 },
5575 off: function( types, selector, fn ) {
5576 var handleObj, type;
5577 if ( types && types.preventDefault && types.handleObj ) {
5578
5579 // ( event ) dispatched jQuery.Event
5580 handleObj = types.handleObj;
5581 jQuery( types.delegateTarget ).off(
5582 handleObj.namespace ?
5583 handleObj.origType + "." + handleObj.namespace :
5584 handleObj.origType,
5585 handleObj.selector,
5586 handleObj.handler
5587 );
5588 return this;
5589 }
5590 if ( typeof types === "object" ) {
5591
5592 // ( types-object [, selector] )
5593 for ( type in types ) {
5594 this.off( type, selector, types[ type ] );
5595 }
5596 return this;
5597 }
5598 if ( selector === false || typeof selector === "function" ) {
5599
5600 // ( types [, fn] )
5601 fn = selector;
5602 selector = undefined;
5603 }
5604 if ( fn === false ) {
5605 fn = returnFalse;
5606 }
5607 return this.each( function() {
5608 jQuery.event.remove( this, types, fn, selector );
5609 } );
5610 }
5611} );
5612
5613
5614var
5615
5616 /* eslint-disable max-len */
5617
5618 // See https://github.com/eslint/eslint/issues/3229
5619 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
5620
5621 /* eslint-enable */
5622
5623 // Support: IE <=10 - 11, Edge 12 - 13
5624 // In IE/Edge using regex groups here causes severe slowdowns.
5625 // See https://connect.microsoft.com/IE/feedback/details/1736512/
5626 rnoInnerhtml = /<script|<style|<link/i,
5627
5628 // checked="checked" or checked
5629 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5630 rscriptTypeMasked = /^true\/(.*)/,
5631 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
5632
5633// Prefer a tbody over its parent table for containing new rows
5634function manipulationTarget( elem, content ) {
5635 if ( nodeName( elem, "table" ) &&
5636 nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
5637
5638 return jQuery( ">tbody", elem )[ 0 ] || elem;
5639 }
5640
5641 return elem;
5642}
5643
5644// Replace/restore the type attribute of script elements for safe DOM manipulation
5645function disableScript( elem ) {
5646 elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
5647 return elem;
5648}
5649function restoreScript( elem ) {
5650 var match = rscriptTypeMasked.exec( elem.type );
5651
5652 if ( match ) {
5653 elem.type = match[ 1 ];
5654 } else {
5655 elem.removeAttribute( "type" );
5656 }
5657
5658 return elem;
5659}
5660
5661function cloneCopyEvent( src, dest ) {
5662 var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
5663
5664 if ( dest.nodeType !== 1 ) {
5665 return;
5666 }
5667
5668 // 1. Copy private data: events, handlers, etc.
5669 if ( dataPriv.hasData( src ) ) {
5670 pdataOld = dataPriv.access( src );
5671 pdataCur = dataPriv.set( dest, pdataOld );
5672 events = pdataOld.events;
5673
5674 if ( events ) {
5675 delete pdataCur.handle;
5676 pdataCur.events = {};
5677
5678 for ( type in events ) {
5679 for ( i = 0, l = events[ type ].length; i < l; i++ ) {
5680 jQuery.event.add( dest, type, events[ type ][ i ] );
5681 }
5682 }
5683 }
5684 }
5685
5686 // 2. Copy user data
5687 if ( dataUser.hasData( src ) ) {
5688 udataOld = dataUser.access( src );
5689 udataCur = jQuery.extend( {}, udataOld );
5690
5691 dataUser.set( dest, udataCur );
5692 }
5693}
5694
5695// Fix IE bugs, see support tests
5696function fixInput( src, dest ) {
5697 var nodeName = dest.nodeName.toLowerCase();
5698
5699 // Fails to persist the checked state of a cloned checkbox or radio button.
5700 if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
5701 dest.checked = src.checked;
5702
5703 // Fails to return the selected option to the default selected state when cloning options
5704 } else if ( nodeName === "input" || nodeName === "textarea" ) {
5705 dest.defaultValue = src.defaultValue;
5706 }
5707}
5708
5709function domManip( collection, args, callback, ignored ) {
5710
5711 // Flatten any nested arrays
5712 args = concat.apply( [], args );
5713
5714 var fragment, first, scripts, hasScripts, node, doc,
5715 i = 0,
5716 l = collection.length,
5717 iNoClone = l - 1,
5718 value = args[ 0 ],
5719 isFunction = jQuery.isFunction( value );
5720
5721 // We can't cloneNode fragments that contain checked, in WebKit
5722 if ( isFunction ||
5723 ( l > 1 && typeof value === "string" &&
5724 !support.checkClone && rchecked.test( value ) ) ) {
5725 return collection.each( function( index ) {
5726 var self = collection.eq( index );
5727 if ( isFunction ) {
5728 args[ 0 ] = value.call( this, index, self.html() );
5729 }
5730 domManip( self, args, callback, ignored );
5731 } );
5732 }
5733
5734 if ( l ) {
5735 fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
5736 first = fragment.firstChild;
5737
5738 if ( fragment.childNodes.length === 1 ) {
5739 fragment = first;
5740 }
5741
5742 // Require either new content or an interest in ignored elements to invoke the callback
5743 if ( first || ignored ) {
5744 scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
5745 hasScripts = scripts.length;
5746
5747 // Use the original fragment for the last item
5748 // instead of the first because it can end up
5749 // being emptied incorrectly in certain situations (#8070).
5750 for ( ; i < l; i++ ) {
5751 node = fragment;
5752
5753 if ( i !== iNoClone ) {
5754 node = jQuery.clone( node, true, true );
5755
5756 // Keep references to cloned scripts for later restoration
5757 if ( hasScripts ) {
5758
5759 // Support: Android <=4.0 only, PhantomJS 1 only
5760 // push.apply(_, arraylike) throws on ancient WebKit
5761 jQuery.merge( scripts, getAll( node, "script" ) );
5762 }
5763 }
5764
5765 callback.call( collection[ i ], node, i );
5766 }
5767
5768 if ( hasScripts ) {
5769 doc = scripts[ scripts.length - 1 ].ownerDocument;
5770
5771 // Reenable scripts
5772 jQuery.map( scripts, restoreScript );
5773
5774 // Evaluate executable scripts on first document insertion
5775 for ( i = 0; i < hasScripts; i++ ) {
5776 node = scripts[ i ];
5777 if ( rscriptType.test( node.type || "" ) &&
5778 !dataPriv.access( node, "globalEval" ) &&
5779 jQuery.contains( doc, node ) ) {
5780
5781 if ( node.src ) {
5782
5783 // Optional AJAX dependency, but won't run scripts if not present
5784 if ( jQuery._evalUrl ) {
5785 jQuery._evalUrl( node.src );
5786 }
5787 } else {
5788 DOMEval( node.textContent.replace( rcleanScript, "" ), doc );
5789 }
5790 }
5791 }
5792 }
5793 }
5794 }
5795
5796 return collection;
5797}
5798
5799function remove( elem, selector, keepData ) {
5800 var node,
5801 nodes = selector ? jQuery.filter( selector, elem ) : elem,
5802 i = 0;
5803
5804 for ( ; ( node = nodes[ i ] ) != null; i++ ) {
5805 if ( !keepData && node.nodeType === 1 ) {
5806 jQuery.cleanData( getAll( node ) );
5807 }
5808
5809 if ( node.parentNode ) {
5810 if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
5811 setGlobalEval( getAll( node, "script" ) );
5812 }
5813 node.parentNode.removeChild( node );
5814 }
5815 }
5816
5817 return elem;
5818}
5819
5820jQuery.extend( {
5821 htmlPrefilter: function( html ) {
5822 return html.replace( rxhtmlTag, "<$1></$2>" );
5823 },
5824
5825 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
5826 var i, l, srcElements, destElements,
5827 clone = elem.cloneNode( true ),
5828 inPage = jQuery.contains( elem.ownerDocument, elem );
5829
5830 // Fix IE cloning issues
5831 if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
5832 !jQuery.isXMLDoc( elem ) ) {
5833
5834 // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
5835 destElements = getAll( clone );
5836 srcElements = getAll( elem );
5837
5838 for ( i = 0, l = srcElements.length; i < l; i++ ) {
5839 fixInput( srcElements[ i ], destElements[ i ] );
5840 }
5841 }
5842
5843 // Copy the events from the original to the clone
5844 if ( dataAndEvents ) {
5845 if ( deepDataAndEvents ) {
5846 srcElements = srcElements || getAll( elem );
5847 destElements = destElements || getAll( clone );
5848
5849 for ( i = 0, l = srcElements.length; i < l; i++ ) {
5850 cloneCopyEvent( srcElements[ i ], destElements[ i ] );
5851 }
5852 } else {
5853 cloneCopyEvent( elem, clone );
5854 }
5855 }
5856
5857 // Preserve script evaluation history
5858 destElements = getAll( clone, "script" );
5859 if ( destElements.length > 0 ) {
5860 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
5861 }
5862
5863 // Return the cloned set
5864 return clone;
5865 },
5866
5867 cleanData: function( elems ) {
5868 var data, elem, type,
5869 special = jQuery.event.special,
5870 i = 0;
5871
5872 for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
5873 if ( acceptData( elem ) ) {
5874 if ( ( data = elem[ dataPriv.expando ] ) ) {
5875 if ( data.events ) {
5876 for ( type in data.events ) {
5877 if ( special[ type ] ) {
5878 jQuery.event.remove( elem, type );
5879
5880 // This is a shortcut to avoid jQuery.event.remove's overhead
5881 } else {
5882 jQuery.removeEvent( elem, type, data.handle );
5883 }
5884 }
5885 }
5886
5887 // Support: Chrome <=35 - 45+
5888 // Assign undefined instead of using delete, see Data#remove
5889 elem[ dataPriv.expando ] = undefined;
5890 }
5891 if ( elem[ dataUser.expando ] ) {
5892
5893 // Support: Chrome <=35 - 45+
5894 // Assign undefined instead of using delete, see Data#remove
5895 elem[ dataUser.expando ] = undefined;
5896 }
5897 }
5898 }
5899 }
5900} );
5901
5902jQuery.fn.extend( {
5903 detach: function( selector ) {
5904 return remove( this, selector, true );
5905 },
5906
5907 remove: function( selector ) {
5908 return remove( this, selector );
5909 },
5910
5911 text: function( value ) {
5912 return access( this, function( value ) {
5913 return value === undefined ?
5914 jQuery.text( this ) :
5915 this.empty().each( function() {
5916 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5917 this.textContent = value;
5918 }
5919 } );
5920 }, null, value, arguments.length );
5921 },
5922
5923 append: function() {
5924 return domManip( this, arguments, function( elem ) {
5925 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5926 var target = manipulationTarget( this, elem );
5927 target.appendChild( elem );
5928 }
5929 } );
5930 },
5931
5932 prepend: function() {
5933 return domManip( this, arguments, function( elem ) {
5934 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5935 var target = manipulationTarget( this, elem );
5936 target.insertBefore( elem, target.firstChild );
5937 }
5938 } );
5939 },
5940
5941 before: function() {
5942 return domManip( this, arguments, function( elem ) {
5943 if ( this.parentNode ) {
5944 this.parentNode.insertBefore( elem, this );
5945 }
5946 } );
5947 },
5948
5949 after: function() {
5950 return domManip( this, arguments, function( elem ) {
5951 if ( this.parentNode ) {
5952 this.parentNode.insertBefore( elem, this.nextSibling );
5953 }
5954 } );
5955 },
5956
5957 empty: function() {
5958 var elem,
5959 i = 0;
5960
5961 for ( ; ( elem = this[ i ] ) != null; i++ ) {
5962 if ( elem.nodeType === 1 ) {
5963
5964 // Prevent memory leaks
5965 jQuery.cleanData( getAll( elem, false ) );
5966
5967 // Remove any remaining nodes
5968 elem.textContent = "";
5969 }
5970 }
5971
5972 return this;
5973 },
5974
5975 clone: function( dataAndEvents, deepDataAndEvents ) {
5976 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
5977 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
5978
5979 return this.map( function() {
5980 return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
5981 } );
5982 },
5983
5984 html: function( value ) {
5985 return access( this, function( value ) {
5986 var elem = this[ 0 ] || {},
5987 i = 0,
5988 l = this.length;
5989
5990 if ( value === undefined && elem.nodeType === 1 ) {
5991 return elem.innerHTML;
5992 }
5993
5994 // See if we can take a shortcut and just use innerHTML
5995 if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
5996 !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
5997
5998 value = jQuery.htmlPrefilter( value );
5999
6000 try {
6001 for ( ; i < l; i++ ) {
6002 elem = this[ i ] || {};
6003
6004 // Remove element nodes and prevent memory leaks
6005 if ( elem.nodeType === 1 ) {
6006 jQuery.cleanData( getAll( elem, false ) );
6007 elem.innerHTML = value;
6008 }
6009 }
6010
6011 elem = 0;
6012
6013 // If using innerHTML throws an exception, use the fallback method
6014 } catch ( e ) {}
6015 }
6016
6017 if ( elem ) {
6018 this.empty().append( value );
6019 }
6020 }, null, value, arguments.length );
6021 },
6022
6023 replaceWith: function() {
6024 var ignored = [];
6025
6026 // Make the changes, replacing each non-ignored context element with the new content
6027 return domManip( this, arguments, function( elem ) {
6028 var parent = this.parentNode;
6029
6030 if ( jQuery.inArray( this, ignored ) < 0 ) {
6031 jQuery.cleanData( getAll( this ) );
6032 if ( parent ) {
6033 parent.replaceChild( elem, this );
6034 }
6035 }
6036
6037 // Force callback invocation
6038 }, ignored );
6039 }
6040} );
6041
6042jQuery.each( {
6043 appendTo: "append",
6044 prependTo: "prepend",
6045 insertBefore: "before",
6046 insertAfter: "after",
6047 replaceAll: "replaceWith"
6048}, function( name, original ) {
6049 jQuery.fn[ name ] = function( selector ) {
6050 var elems,
6051 ret = [],
6052 insert = jQuery( selector ),
6053 last = insert.length - 1,
6054 i = 0;
6055
6056 for ( ; i <= last; i++ ) {
6057 elems = i === last ? this : this.clone( true );
6058 jQuery( insert[ i ] )[ original ]( elems );
6059
6060 // Support: Android <=4.0 only, PhantomJS 1 only
6061 // .get() because push.apply(_, arraylike) throws on ancient WebKit
6062 push.apply( ret, elems.get() );
6063 }
6064
6065 return this.pushStack( ret );
6066 };
6067} );
6068var rmargin = ( /^margin/ );
6069
6070var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
6071
6072var getStyles = function( elem ) {
6073
6074 // Support: IE <=11 only, Firefox <=30 (#15098, #14150)
6075 // IE throws on elements created in popups
6076 // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
6077 var view = elem.ownerDocument.defaultView;
6078
6079 if ( !view || !view.opener ) {
6080 view = window;
6081 }
6082
6083 return view.getComputedStyle( elem );
6084 };
6085
6086
6087
6088( function() {
6089
6090 // Executing both pixelPosition & boxSizingReliable tests require only one layout
6091 // so they're executed at the same time to save the second computation.
6092 function computeStyleTests() {
6093
6094 // This is a singleton, we need to execute it only once
6095 if ( !div ) {
6096 return;
6097 }
6098
6099 div.style.cssText =
6100 "box-sizing:border-box;" +
6101 "position:relative;display:block;" +
6102 "margin:auto;border:1px;padding:1px;" +
6103 "top:1%;width:50%";
6104 div.innerHTML = "";
6105 documentElement.appendChild( container );
6106
6107 var divStyle = window.getComputedStyle( div );
6108 pixelPositionVal = divStyle.top !== "1%";
6109
6110 // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
6111 reliableMarginLeftVal = divStyle.marginLeft === "2px";
6112 boxSizingReliableVal = divStyle.width === "4px";
6113
6114 // Support: Android 4.0 - 4.3 only
6115 // Some styles come back with percentage values, even though they shouldn't
6116 div.style.marginRight = "50%";
6117 pixelMarginRightVal = divStyle.marginRight === "4px";
6118
6119 documentElement.removeChild( container );
6120
6121 // Nullify the div so it wouldn't be stored in the memory and
6122 // it will also be a sign that checks already performed
6123 div = null;
6124 }
6125
6126 var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
6127 container = document.createElement( "div" ),
6128 div = document.createElement( "div" );
6129
6130 // Finish early in limited (non-browser) environments
6131 if ( !div.style ) {
6132 return;
6133 }
6134
6135 // Support: IE <=9 - 11 only
6136 // Style of cloned element affects source element cloned (#8908)
6137 div.style.backgroundClip = "content-box";
6138 div.cloneNode( true ).style.backgroundClip = "";
6139 support.clearCloneStyle = div.style.backgroundClip === "content-box";
6140
6141 container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
6142 "padding:0;margin-top:1px;position:absolute";
6143 container.appendChild( div );
6144
6145 jQuery.extend( support, {
6146 pixelPosition: function() {
6147 computeStyleTests();
6148 return pixelPositionVal;
6149 },
6150 boxSizingReliable: function() {
6151 computeStyleTests();
6152 return boxSizingReliableVal;
6153 },
6154 pixelMarginRight: function() {
6155 computeStyleTests();
6156 return pixelMarginRightVal;
6157 },
6158 reliableMarginLeft: function() {
6159 computeStyleTests();
6160 return reliableMarginLeftVal;
6161 }
6162 } );
6163} )();
6164
6165
6166function curCSS( elem, name, computed ) {
6167 var width, minWidth, maxWidth, ret,
6168
6169 // Support: Firefox 51+
6170 // Retrieving style before computed somehow
6171 // fixes an issue with getting wrong values
6172 // on detached elements
6173 style = elem.style;
6174
6175 computed = computed || getStyles( elem );
6176
6177 // getPropertyValue is needed for:
6178 // .css('filter') (IE 9 only, #12537)
6179 // .css('--customProperty) (#3144)
6180 if ( computed ) {
6181 ret = computed.getPropertyValue( name ) || computed[ name ];
6182
6183 if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
6184 ret = jQuery.style( elem, name );
6185 }
6186
6187 // A tribute to the "awesome hack by Dean Edwards"
6188 // Android Browser returns percentage for some values,
6189 // but width seems to be reliably pixels.
6190 // This is against the CSSOM draft spec:
6191 // https://drafts.csswg.org/cssom/#resolved-values
6192 if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {
6193
6194 // Remember the original values
6195 width = style.width;
6196 minWidth = style.minWidth;
6197 maxWidth = style.maxWidth;
6198
6199 // Put in the new values to get a computed value out
6200 style.minWidth = style.maxWidth = style.width = ret;
6201 ret = computed.width;
6202
6203 // Revert the changed values
6204 style.width = width;
6205 style.minWidth = minWidth;
6206 style.maxWidth = maxWidth;
6207 }
6208 }
6209
6210 return ret !== undefined ?
6211
6212 // Support: IE <=9 - 11 only
6213 // IE returns zIndex value as an integer.
6214 ret + "" :
6215 ret;
6216}
6217
6218
6219function addGetHookIf( conditionFn, hookFn ) {
6220
6221 // Define the hook, we'll check on the first run if it's really needed.
6222 return {
6223 get: function() {
6224 if ( conditionFn() ) {
6225
6226 // Hook not needed (or it's not possible to use it due
6227 // to missing dependency), remove it.
6228 delete this.get;
6229 return;
6230 }
6231
6232 // Hook needed; redefine it so that the support test is not executed again.
6233 return ( this.get = hookFn ).apply( this, arguments );
6234 }
6235 };
6236}
6237
6238
6239var
6240
6241 // Swappable if display is none or starts with table
6242 // except "table", "table-cell", or "table-caption"
6243 // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6244 rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6245 rcustomProp = /^--/,
6246 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6247 cssNormalTransform = {
6248 letterSpacing: "0",
6249 fontWeight: "400"
6250 },
6251
6252 cssPrefixes = [ "Webkit", "Moz", "ms" ],
6253 emptyStyle = document.createElement( "div" ).style;
6254
6255// Return a css property mapped to a potentially vendor prefixed property
6256function vendorPropName( name ) {
6257
6258 // Shortcut for names that are not vendor prefixed
6259 if ( name in emptyStyle ) {
6260 return name;
6261 }
6262
6263 // Check for vendor prefixed names
6264 var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
6265 i = cssPrefixes.length;
6266
6267 while ( i-- ) {
6268 name = cssPrefixes[ i ] + capName;
6269 if ( name in emptyStyle ) {
6270 return name;
6271 }
6272 }
6273}
6274
6275// Return a property mapped along what jQuery.cssProps suggests or to
6276// a vendor prefixed property.
6277function finalPropName( name ) {
6278 var ret = jQuery.cssProps[ name ];
6279 if ( !ret ) {
6280 ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name;
6281 }
6282 return ret;
6283}
6284
6285function setPositiveNumber( elem, value, subtract ) {
6286
6287 // Any relative (+/-) values have already been
6288 // normalized at this point
6289 var matches = rcssNum.exec( value );
6290 return matches ?
6291
6292 // Guard against undefined "subtract", e.g., when used as in cssHooks
6293 Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
6294 value;
6295}
6296
6297function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
6298 var i,
6299 val = 0;
6300
6301 // If we already have the right measurement, avoid augmentation
6302 if ( extra === ( isBorderBox ? "border" : "content" ) ) {
6303 i = 4;
6304
6305 // Otherwise initialize for horizontal or vertical properties
6306 } else {
6307 i = name === "width" ? 1 : 0;
6308 }
6309
6310 for ( ; i < 4; i += 2 ) {
6311
6312 // Both box models exclude margin, so add it if we want it
6313 if ( extra === "margin" ) {
6314 val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
6315 }
6316
6317 if ( isBorderBox ) {
6318
6319 // border-box includes padding, so remove it if we want content
6320 if ( extra === "content" ) {
6321 val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6322 }
6323
6324 // At this point, extra isn't border nor margin, so remove border
6325 if ( extra !== "margin" ) {
6326 val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6327 }
6328 } else {
6329
6330 // At this point, extra isn't content, so add padding
6331 val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6332
6333 // At this point, extra isn't content nor padding, so add border
6334 if ( extra !== "padding" ) {
6335 val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6336 }
6337 }
6338 }
6339
6340 return val;
6341}
6342
6343function getWidthOrHeight( elem, name, extra ) {
6344
6345 // Start with computed style
6346 var valueIsBorderBox,
6347 styles = getStyles( elem ),
6348 val = curCSS( elem, name, styles ),
6349 isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
6350
6351 // Computed unit is not pixels. Stop here and return.
6352 if ( rnumnonpx.test( val ) ) {
6353 return val;
6354 }
6355
6356 // Check for style in case a browser which returns unreliable values
6357 // for getComputedStyle silently falls back to the reliable elem.style
6358 valueIsBorderBox = isBorderBox &&
6359 ( support.boxSizingReliable() || val === elem.style[ name ] );
6360
6361 // Fall back to offsetWidth/Height when value is "auto"
6362 // This happens for inline elements with no explicit setting (gh-3571)
6363 if ( val === "auto" ) {
6364 val = elem[ "offset" + name[ 0 ].toUpperCase() + name.slice( 1 ) ];
6365 }
6366
6367 // Normalize "", auto, and prepare for extra
6368 val = parseFloat( val ) || 0;
6369
6370 // Use the active box-sizing model to add/subtract irrelevant styles
6371 return ( val +
6372 augmentWidthOrHeight(
6373 elem,
6374 name,
6375 extra || ( isBorderBox ? "border" : "content" ),
6376 valueIsBorderBox,
6377 styles
6378 )
6379 ) + "px";
6380}
6381
6382jQuery.extend( {
6383
6384 // Add in style property hooks for overriding the default
6385 // behavior of getting and setting a style property
6386 cssHooks: {
6387 opacity: {
6388 get: function( elem, computed ) {
6389 if ( computed ) {
6390
6391 // We should always get a number back from opacity
6392 var ret = curCSS( elem, "opacity" );
6393 return ret === "" ? "1" : ret;
6394 }
6395 }
6396 }
6397 },
6398
6399 // Don't automatically add "px" to these possibly-unitless properties
6400 cssNumber: {
6401 "animationIterationCount": true,
6402 "columnCount": true,
6403 "fillOpacity": true,
6404 "flexGrow": true,
6405 "flexShrink": true,
6406 "fontWeight": true,
6407 "lineHeight": true,
6408 "opacity": true,
6409 "order": true,
6410 "orphans": true,
6411 "widows": true,
6412 "zIndex": true,
6413 "zoom": true
6414 },
6415
6416 // Add in properties whose names you wish to fix before
6417 // setting or getting the value
6418 cssProps: {
6419 "float": "cssFloat"
6420 },
6421
6422 // Get and set the style property on a DOM Node
6423 style: function( elem, name, value, extra ) {
6424
6425 // Don't set styles on text and comment nodes
6426 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6427 return;
6428 }
6429
6430 // Make sure that we're working with the right name
6431 var ret, type, hooks,
6432 origName = jQuery.camelCase( name ),
6433 isCustomProp = rcustomProp.test( name ),
6434 style = elem.style;
6435
6436 // Make sure that we're working with the right name. We don't
6437 // want to query the value if it is a CSS custom property
6438 // since they are user-defined.
6439 if ( !isCustomProp ) {
6440 name = finalPropName( origName );
6441 }
6442
6443 // Gets hook for the prefixed version, then unprefixed version
6444 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6445
6446 // Check if we're setting a value
6447 if ( value !== undefined ) {
6448 type = typeof value;
6449
6450 // Convert "+=" or "-=" to relative numbers (#7345)
6451 if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
6452 value = adjustCSS( elem, name, ret );
6453
6454 // Fixes bug #9237
6455 type = "number";
6456 }
6457
6458 // Make sure that null and NaN values aren't set (#7116)
6459 if ( value == null || value !== value ) {
6460 return;
6461 }
6462
6463 // If a number was passed in, add the unit (except for certain CSS properties)
6464 if ( type === "number" ) {
6465 value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
6466 }
6467
6468 // background-* props affect original clone's values
6469 if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
6470 style[ name ] = "inherit";
6471 }
6472
6473 // If a hook was provided, use that value, otherwise just set the specified value
6474 if ( !hooks || !( "set" in hooks ) ||
6475 ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
6476
6477 if ( isCustomProp ) {
6478 style.setProperty( name, value );
6479 } else {
6480 style[ name ] = value;
6481 }
6482 }
6483
6484 } else {
6485
6486 // If a hook was provided get the non-computed value from there
6487 if ( hooks && "get" in hooks &&
6488 ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
6489
6490 return ret;
6491 }
6492
6493 // Otherwise just get the value from the style object
6494 return style[ name ];
6495 }
6496 },
6497
6498 css: function( elem, name, extra, styles ) {
6499 var val, num, hooks,
6500 origName = jQuery.camelCase( name ),
6501 isCustomProp = rcustomProp.test( name );
6502
6503 // Make sure that we're working with the right name. We don't
6504 // want to modify the value if it is a CSS custom property
6505 // since they are user-defined.
6506 if ( !isCustomProp ) {
6507 name = finalPropName( origName );
6508 }
6509
6510 // Try prefixed name followed by the unprefixed name
6511 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6512
6513 // If a hook was provided get the computed value from there
6514 if ( hooks && "get" in hooks ) {
6515 val = hooks.get( elem, true, extra );
6516 }
6517
6518 // Otherwise, if a way to get the computed value exists, use that
6519 if ( val === undefined ) {
6520 val = curCSS( elem, name, styles );
6521 }
6522
6523 // Convert "normal" to computed value
6524 if ( val === "normal" && name in cssNormalTransform ) {
6525 val = cssNormalTransform[ name ];
6526 }
6527
6528 // Make numeric if forced or a qualifier was provided and val looks numeric
6529 if ( extra === "" || extra ) {
6530 num = parseFloat( val );
6531 return extra === true || isFinite( num ) ? num || 0 : val;
6532 }
6533
6534 return val;
6535 }
6536} );
6537
6538jQuery.each( [ "height", "width" ], function( i, name ) {
6539 jQuery.cssHooks[ name ] = {
6540 get: function( elem, computed, extra ) {
6541 if ( computed ) {
6542
6543 // Certain elements can have dimension info if we invisibly show them
6544 // but it must have a current display style that would benefit
6545 return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
6546
6547 // Support: Safari 8+
6548 // Table columns in Safari have non-zero offsetWidth & zero
6549 // getBoundingClientRect().width unless display is changed.
6550 // Support: IE <=11 only
6551 // Running getBoundingClientRect on a disconnected node
6552 // in IE throws an error.
6553 ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
6554 swap( elem, cssShow, function() {
6555 return getWidthOrHeight( elem, name, extra );
6556 } ) :
6557 getWidthOrHeight( elem, name, extra );
6558 }
6559 },
6560
6561 set: function( elem, value, extra ) {
6562 var matches,
6563 styles = extra && getStyles( elem ),
6564 subtract = extra && augmentWidthOrHeight(
6565 elem,
6566 name,
6567 extra,
6568 jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6569 styles
6570 );
6571
6572 // Convert to pixels if value adjustment is needed
6573 if ( subtract && ( matches = rcssNum.exec( value ) ) &&
6574 ( matches[ 3 ] || "px" ) !== "px" ) {
6575
6576 elem.style[ name ] = value;
6577 value = jQuery.css( elem, name );
6578 }
6579
6580 return setPositiveNumber( elem, value, subtract );
6581 }
6582 };
6583} );
6584
6585jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
6586 function( elem, computed ) {
6587 if ( computed ) {
6588 return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
6589 elem.getBoundingClientRect().left -
6590 swap( elem, { marginLeft: 0 }, function() {
6591 return elem.getBoundingClientRect().left;
6592 } )
6593 ) + "px";
6594 }
6595 }
6596);
6597
6598// These hooks are used by animate to expand properties
6599jQuery.each( {
6600 margin: "",
6601 padding: "",
6602 border: "Width"
6603}, function( prefix, suffix ) {
6604 jQuery.cssHooks[ prefix + suffix ] = {
6605 expand: function( value ) {
6606 var i = 0,
6607 expanded = {},
6608
6609 // Assumes a single number if not a string
6610 parts = typeof value === "string" ? value.split( " " ) : [ value ];
6611
6612 for ( ; i < 4; i++ ) {
6613 expanded[ prefix + cssExpand[ i ] + suffix ] =
6614 parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
6615 }
6616
6617 return expanded;
6618 }
6619 };
6620
6621 if ( !rmargin.test( prefix ) ) {
6622 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
6623 }
6624} );
6625
6626jQuery.fn.extend( {
6627 css: function( name, value ) {
6628 return access( this, function( elem, name, value ) {
6629 var styles, len,
6630 map = {},
6631 i = 0;
6632
6633 if ( Array.isArray( name ) ) {
6634 styles = getStyles( elem );
6635 len = name.length;
6636
6637 for ( ; i < len; i++ ) {
6638 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6639 }
6640
6641 return map;
6642 }
6643
6644 return value !== undefined ?
6645 jQuery.style( elem, name, value ) :
6646 jQuery.css( elem, name );
6647 }, name, value, arguments.length > 1 );
6648 }
6649} );
6650
6651
6652function Tween( elem, options, prop, end, easing ) {
6653 return new Tween.prototype.init( elem, options, prop, end, easing );
6654}
6655jQuery.Tween = Tween;
6656
6657Tween.prototype = {
6658 constructor: Tween,
6659 init: function( elem, options, prop, end, easing, unit ) {
6660 this.elem = elem;
6661 this.prop = prop;
6662 this.easing = easing || jQuery.easing._default;
6663 this.options = options;
6664 this.start = this.now = this.cur();
6665 this.end = end;
6666 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
6667 },
6668 cur: function() {
6669 var hooks = Tween.propHooks[ this.prop ];
6670
6671 return hooks && hooks.get ?
6672 hooks.get( this ) :
6673 Tween.propHooks._default.get( this );
6674 },
6675 run: function( percent ) {
6676 var eased,
6677 hooks = Tween.propHooks[ this.prop ];
6678
6679 if ( this.options.duration ) {
6680 this.pos = eased = jQuery.easing[ this.easing ](
6681 percent, this.options.duration * percent, 0, 1, this.options.duration
6682 );
6683 } else {
6684 this.pos = eased = percent;
6685 }
6686 this.now = ( this.end - this.start ) * eased + this.start;
6687
6688 if ( this.options.step ) {
6689 this.options.step.call( this.elem, this.now, this );
6690 }
6691
6692 if ( hooks && hooks.set ) {
6693 hooks.set( this );
6694 } else {
6695 Tween.propHooks._default.set( this );
6696 }
6697 return this;
6698 }
6699};
6700
6701Tween.prototype.init.prototype = Tween.prototype;
6702
6703Tween.propHooks = {
6704 _default: {
6705 get: function( tween ) {
6706 var result;
6707
6708 // Use a property on the element directly when it is not a DOM element,
6709 // or when there is no matching style property that exists.
6710 if ( tween.elem.nodeType !== 1 ||
6711 tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
6712 return tween.elem[ tween.prop ];
6713 }
6714
6715 // Passing an empty string as a 3rd parameter to .css will automatically
6716 // attempt a parseFloat and fallback to a string if the parse fails.
6717 // Simple values such as "10px" are parsed to Float;
6718 // complex values such as "rotate(1rad)" are returned as-is.
6719 result = jQuery.css( tween.elem, tween.prop, "" );
6720
6721 // Empty strings, null, undefined and "auto" are converted to 0.
6722 return !result || result === "auto" ? 0 : result;
6723 },
6724 set: function( tween ) {
6725
6726 // Use step hook for back compat.
6727 // Use cssHook if its there.
6728 // Use .style if available and use plain properties where available.
6729 if ( jQuery.fx.step[ tween.prop ] ) {
6730 jQuery.fx.step[ tween.prop ]( tween );
6731 } else if ( tween.elem.nodeType === 1 &&
6732 ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
6733 jQuery.cssHooks[ tween.prop ] ) ) {
6734 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
6735 } else {
6736 tween.elem[ tween.prop ] = tween.now;
6737 }
6738 }
6739 }
6740};
6741
6742// Support: IE <=9 only
6743// Panic based approach to setting things on disconnected nodes
6744Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
6745 set: function( tween ) {
6746 if ( tween.elem.nodeType && tween.elem.parentNode ) {
6747 tween.elem[ tween.prop ] = tween.now;
6748 }
6749 }
6750};
6751
6752jQuery.easing = {
6753 linear: function( p ) {
6754 return p;
6755 },
6756 swing: function( p ) {
6757 return 0.5 - Math.cos( p * Math.PI ) / 2;
6758 },
6759 _default: "swing"
6760};
6761
6762jQuery.fx = Tween.prototype.init;
6763
6764// Back compat <1.8 extension point
6765jQuery.fx.step = {};
6766
6767
6768
6769
6770var
6771 fxNow, inProgress,
6772 rfxtypes = /^(?:toggle|show|hide)$/,
6773 rrun = /queueHooks$/;
6774
6775function schedule() {
6776 if ( inProgress ) {
6777 if ( document.hidden === false && window.requestAnimationFrame ) {
6778 window.requestAnimationFrame( schedule );
6779 } else {
6780 window.setTimeout( schedule, jQuery.fx.interval );
6781 }
6782
6783 jQuery.fx.tick();
6784 }
6785}
6786
6787// Animations created synchronously will run synchronously
6788function createFxNow() {
6789 window.setTimeout( function() {
6790 fxNow = undefined;
6791 } );
6792 return ( fxNow = jQuery.now() );
6793}
6794
6795// Generate parameters to create a standard animation
6796function genFx( type, includeWidth ) {
6797 var which,
6798 i = 0,
6799 attrs = { height: type };
6800
6801 // If we include width, step value is 1 to do all cssExpand values,
6802 // otherwise step value is 2 to skip over Left and Right
6803 includeWidth = includeWidth ? 1 : 0;
6804 for ( ; i < 4; i += 2 - includeWidth ) {
6805 which = cssExpand[ i ];
6806 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
6807 }
6808
6809 if ( includeWidth ) {
6810 attrs.opacity = attrs.width = type;
6811 }
6812
6813 return attrs;
6814}
6815
6816function createTween( value, prop, animation ) {
6817 var tween,
6818 collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
6819 index = 0,
6820 length = collection.length;
6821 for ( ; index < length; index++ ) {
6822 if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
6823
6824 // We're done with this property
6825 return tween;
6826 }
6827 }
6828}
6829
6830function defaultPrefilter( elem, props, opts ) {
6831 var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
6832 isBox = "width" in props || "height" in props,
6833 anim = this,
6834 orig = {},
6835 style = elem.style,
6836 hidden = elem.nodeType && isHiddenWithinTree( elem ),
6837 dataShow = dataPriv.get( elem, "fxshow" );
6838
6839 // Queue-skipping animations hijack the fx hooks
6840 if ( !opts.queue ) {
6841 hooks = jQuery._queueHooks( elem, "fx" );
6842 if ( hooks.unqueued == null ) {
6843 hooks.unqueued = 0;
6844 oldfire = hooks.empty.fire;
6845 hooks.empty.fire = function() {
6846 if ( !hooks.unqueued ) {
6847 oldfire();
6848 }
6849 };
6850 }
6851 hooks.unqueued++;
6852
6853 anim.always( function() {
6854
6855 // Ensure the complete handler is called before this completes
6856 anim.always( function() {
6857 hooks.unqueued--;
6858 if ( !jQuery.queue( elem, "fx" ).length ) {
6859 hooks.empty.fire();
6860 }
6861 } );
6862 } );
6863 }
6864
6865 // Detect show/hide animations
6866 for ( prop in props ) {
6867 value = props[ prop ];
6868 if ( rfxtypes.test( value ) ) {
6869 delete props[ prop ];
6870 toggle = toggle || value === "toggle";
6871 if ( value === ( hidden ? "hide" : "show" ) ) {
6872
6873 // Pretend to be hidden if this is a "show" and
6874 // there is still data from a stopped show/hide
6875 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
6876 hidden = true;
6877
6878 // Ignore all other no-op show/hide data
6879 } else {
6880 continue;
6881 }
6882 }
6883 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
6884 }
6885 }
6886
6887 // Bail out if this is a no-op like .hide().hide()
6888 propTween = !jQuery.isEmptyObject( props );
6889 if ( !propTween && jQuery.isEmptyObject( orig ) ) {
6890 return;
6891 }
6892
6893 // Restrict "overflow" and "display" styles during box animations
6894 if ( isBox && elem.nodeType === 1 ) {
6895
6896 // Support: IE <=9 - 11, Edge 12 - 13
6897 // Record all 3 overflow attributes because IE does not infer the shorthand
6898 // from identically-valued overflowX and overflowY
6899 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
6900
6901 // Identify a display type, preferring old show/hide data over the CSS cascade
6902 restoreDisplay = dataShow && dataShow.display;
6903 if ( restoreDisplay == null ) {
6904 restoreDisplay = dataPriv.get( elem, "display" );
6905 }
6906 display = jQuery.css( elem, "display" );
6907 if ( display === "none" ) {
6908 if ( restoreDisplay ) {
6909 display = restoreDisplay;
6910 } else {
6911
6912 // Get nonempty value(s) by temporarily forcing visibility
6913 showHide( [ elem ], true );
6914 restoreDisplay = elem.style.display || restoreDisplay;
6915 display = jQuery.css( elem, "display" );
6916 showHide( [ elem ] );
6917 }
6918 }
6919
6920 // Animate inline elements as inline-block
6921 if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
6922 if ( jQuery.css( elem, "float" ) === "none" ) {
6923
6924 // Restore the original display value at the end of pure show/hide animations
6925 if ( !propTween ) {
6926 anim.done( function() {
6927 style.display = restoreDisplay;
6928 } );
6929 if ( restoreDisplay == null ) {
6930 display = style.display;
6931 restoreDisplay = display === "none" ? "" : display;
6932 }
6933 }
6934 style.display = "inline-block";
6935 }
6936 }
6937 }
6938
6939 if ( opts.overflow ) {
6940 style.overflow = "hidden";
6941 anim.always( function() {
6942 style.overflow = opts.overflow[ 0 ];
6943 style.overflowX = opts.overflow[ 1 ];
6944 style.overflowY = opts.overflow[ 2 ];
6945 } );
6946 }
6947
6948 // Implement show/hide animations
6949 propTween = false;
6950 for ( prop in orig ) {
6951
6952 // General show/hide setup for this element animation
6953 if ( !propTween ) {
6954 if ( dataShow ) {
6955 if ( "hidden" in dataShow ) {
6956 hidden = dataShow.hidden;
6957 }
6958 } else {
6959 dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
6960 }
6961
6962 // Store hidden/visible for toggle so `.stop().toggle()` "reverses"
6963 if ( toggle ) {
6964 dataShow.hidden = !hidden;
6965 }
6966
6967 // Show elements before animating them
6968 if ( hidden ) {
6969 showHide( [ elem ], true );
6970 }
6971
6972 /* eslint-disable no-loop-func */
6973
6974 anim.done( function() {
6975
6976 /* eslint-enable no-loop-func */
6977
6978 // The final step of a "hide" animation is actually hiding the element
6979 if ( !hidden ) {
6980 showHide( [ elem ] );
6981 }
6982 dataPriv.remove( elem, "fxshow" );
6983 for ( prop in orig ) {
6984 jQuery.style( elem, prop, orig[ prop ] );
6985 }
6986 } );
6987 }
6988
6989 // Per-property setup
6990 propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
6991 if ( !( prop in dataShow ) ) {
6992 dataShow[ prop ] = propTween.start;
6993 if ( hidden ) {
6994 propTween.end = propTween.start;
6995 propTween.start = 0;
6996 }
6997 }
6998 }
6999}
7000
7001function propFilter( props, specialEasing ) {
7002 var index, name, easing, value, hooks;
7003
7004 // camelCase, specialEasing and expand cssHook pass
7005 for ( index in props ) {
7006 name = jQuery.camelCase( index );
7007 easing = specialEasing[ name ];
7008 value = props[ index ];
7009 if ( Array.isArray( value ) ) {
7010 easing = value[ 1 ];
7011 value = props[ index ] = value[ 0 ];
7012 }
7013
7014 if ( index !== name ) {
7015 props[ name ] = value;
7016 delete props[ index ];
7017 }
7018
7019 hooks = jQuery.cssHooks[ name ];
7020 if ( hooks && "expand" in hooks ) {
7021 value = hooks.expand( value );
7022 delete props[ name ];
7023
7024 // Not quite $.extend, this won't overwrite existing keys.
7025 // Reusing 'index' because we have the correct "name"
7026 for ( index in value ) {
7027 if ( !( index in props ) ) {
7028 props[ index ] = value[ index ];
7029 specialEasing[ index ] = easing;
7030 }
7031 }
7032 } else {
7033 specialEasing[ name ] = easing;
7034 }
7035 }
7036}
7037
7038function Animation( elem, properties, options ) {
7039 var result,
7040 stopped,
7041 index = 0,
7042 length = Animation.prefilters.length,
7043 deferred = jQuery.Deferred().always( function() {
7044
7045 // Don't match elem in the :animated selector
7046 delete tick.elem;
7047 } ),
7048 tick = function() {
7049 if ( stopped ) {
7050 return false;
7051 }
7052 var currentTime = fxNow || createFxNow(),
7053 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
7054
7055 // Support: Android 2.3 only
7056 // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
7057 temp = remaining / animation.duration || 0,
7058 percent = 1 - temp,
7059 index = 0,
7060 length = animation.tweens.length;
7061
7062 for ( ; index < length; index++ ) {
7063 animation.tweens[ index ].run( percent );
7064 }
7065
7066 deferred.notifyWith( elem, [ animation, percent, remaining ] );
7067
7068 // If there's more to do, yield
7069 if ( percent < 1 && length ) {
7070 return remaining;
7071 }
7072
7073 // If this was an empty animation, synthesize a final progress notification
7074 if ( !length ) {
7075 deferred.notifyWith( elem, [ animation, 1, 0 ] );
7076 }
7077
7078 // Resolve the animation and report its conclusion
7079 deferred.resolveWith( elem, [ animation ] );
7080 return false;
7081 },
7082 animation = deferred.promise( {
7083 elem: elem,
7084 props: jQuery.extend( {}, properties ),
7085 opts: jQuery.extend( true, {
7086 specialEasing: {},
7087 easing: jQuery.easing._default
7088 }, options ),
7089 originalProperties: properties,
7090 originalOptions: options,
7091 startTime: fxNow || createFxNow(),
7092 duration: options.duration,
7093 tweens: [],
7094 createTween: function( prop, end ) {
7095 var tween = jQuery.Tween( elem, animation.opts, prop, end,
7096 animation.opts.specialEasing[ prop ] || animation.opts.easing );
7097 animation.tweens.push( tween );
7098 return tween;
7099 },
7100 stop: function( gotoEnd ) {
7101 var index = 0,
7102
7103 // If we are going to the end, we want to run all the tweens
7104 // otherwise we skip this part
7105 length = gotoEnd ? animation.tweens.length : 0;
7106 if ( stopped ) {
7107 return this;
7108 }
7109 stopped = true;
7110 for ( ; index < length; index++ ) {
7111 animation.tweens[ index ].run( 1 );
7112 }
7113
7114 // Resolve when we played the last frame; otherwise, reject
7115 if ( gotoEnd ) {
7116 deferred.notifyWith( elem, [ animation, 1, 0 ] );
7117 deferred.resolveWith( elem, [ animation, gotoEnd ] );
7118 } else {
7119 deferred.rejectWith( elem, [ animation, gotoEnd ] );
7120 }
7121 return this;
7122 }
7123 } ),
7124 props = animation.props;
7125
7126 propFilter( props, animation.opts.specialEasing );
7127
7128 for ( ; index < length; index++ ) {
7129 result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
7130 if ( result ) {
7131 if ( jQuery.isFunction( result.stop ) ) {
7132 jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
7133 jQuery.proxy( result.stop, result );
7134 }
7135 return result;
7136 }
7137 }
7138
7139 jQuery.map( props, createTween, animation );
7140
7141 if ( jQuery.isFunction( animation.opts.start ) ) {
7142 animation.opts.start.call( elem, animation );
7143 }
7144
7145 // Attach callbacks from options
7146 animation
7147 .progress( animation.opts.progress )
7148 .done( animation.opts.done, animation.opts.complete )
7149 .fail( animation.opts.fail )
7150 .always( animation.opts.always );
7151
7152 jQuery.fx.timer(
7153 jQuery.extend( tick, {
7154 elem: elem,
7155 anim: animation,
7156 queue: animation.opts.queue
7157 } )
7158 );
7159
7160 return animation;
7161}
7162
7163jQuery.Animation = jQuery.extend( Animation, {
7164
7165 tweeners: {
7166 "*": [ function( prop, value ) {
7167 var tween = this.createTween( prop, value );
7168 adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
7169 return tween;
7170 } ]
7171 },
7172
7173 tweener: function( props, callback ) {
7174 if ( jQuery.isFunction( props ) ) {
7175 callback = props;
7176 props = [ "*" ];
7177 } else {
7178 props = props.match( rnothtmlwhite );
7179 }
7180
7181 var prop,
7182 index = 0,
7183 length = props.length;
7184
7185 for ( ; index < length; index++ ) {
7186 prop = props[ index ];
7187 Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
7188 Animation.tweeners[ prop ].unshift( callback );
7189 }
7190 },
7191
7192 prefilters: [ defaultPrefilter ],
7193
7194 prefilter: function( callback, prepend ) {
7195 if ( prepend ) {
7196 Animation.prefilters.unshift( callback );
7197 } else {
7198 Animation.prefilters.push( callback );
7199 }
7200 }
7201} );
7202
7203jQuery.speed = function( speed, easing, fn ) {
7204 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
7205 complete: fn || !fn && easing ||
7206 jQuery.isFunction( speed ) && speed,
7207 duration: speed,
7208 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
7209 };
7210
7211 // Go to the end state if fx are off
7212 if ( jQuery.fx.off ) {
7213 opt.duration = 0;
7214
7215 } else {
7216 if ( typeof opt.duration !== "number" ) {
7217 if ( opt.duration in jQuery.fx.speeds ) {
7218 opt.duration = jQuery.fx.speeds[ opt.duration ];
7219
7220 } else {
7221 opt.duration = jQuery.fx.speeds._default;
7222 }
7223 }
7224 }
7225
7226 // Normalize opt.queue - true/undefined/null -> "fx"
7227 if ( opt.queue == null || opt.queue === true ) {
7228 opt.queue = "fx";
7229 }
7230
7231 // Queueing
7232 opt.old = opt.complete;
7233
7234 opt.complete = function() {
7235 if ( jQuery.isFunction( opt.old ) ) {
7236 opt.old.call( this );
7237 }
7238
7239 if ( opt.queue ) {
7240 jQuery.dequeue( this, opt.queue );
7241 }
7242 };
7243
7244 return opt;
7245};
7246
7247jQuery.fn.extend( {
7248 fadeTo: function( speed, to, easing, callback ) {
7249
7250 // Show any hidden elements after setting opacity to 0
7251 return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
7252
7253 // Animate to the value specified
7254 .end().animate( { opacity: to }, speed, easing, callback );
7255 },
7256 animate: function( prop, speed, easing, callback ) {
7257 var empty = jQuery.isEmptyObject( prop ),
7258 optall = jQuery.speed( speed, easing, callback ),
7259 doAnimation = function() {
7260
7261 // Operate on a copy of prop so per-property easing won't be lost
7262 var anim = Animation( this, jQuery.extend( {}, prop ), optall );
7263
7264 // Empty animations, or finishing resolves immediately
7265 if ( empty || dataPriv.get( this, "finish" ) ) {
7266 anim.stop( true );
7267 }
7268 };
7269 doAnimation.finish = doAnimation;
7270
7271 return empty || optall.queue === false ?
7272 this.each( doAnimation ) :
7273 this.queue( optall.queue, doAnimation );
7274 },
7275 stop: function( type, clearQueue, gotoEnd ) {
7276 var stopQueue = function( hooks ) {
7277 var stop = hooks.stop;
7278 delete hooks.stop;
7279 stop( gotoEnd );
7280 };
7281
7282 if ( typeof type !== "string" ) {
7283 gotoEnd = clearQueue;
7284 clearQueue = type;
7285 type = undefined;
7286 }
7287 if ( clearQueue && type !== false ) {
7288 this.queue( type || "fx", [] );
7289 }
7290
7291 return this.each( function() {
7292 var dequeue = true,
7293 index = type != null && type + "queueHooks",
7294 timers = jQuery.timers,
7295 data = dataPriv.get( this );
7296
7297 if ( index ) {
7298 if ( data[ index ] && data[ index ].stop ) {
7299 stopQueue( data[ index ] );
7300 }
7301 } else {
7302 for ( index in data ) {
7303 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
7304 stopQueue( data[ index ] );
7305 }
7306 }
7307 }
7308
7309 for ( index = timers.length; index--; ) {
7310 if ( timers[ index ].elem === this &&
7311 ( type == null || timers[ index ].queue === type ) ) {
7312
7313 timers[ index ].anim.stop( gotoEnd );
7314 dequeue = false;
7315 timers.splice( index, 1 );
7316 }
7317 }
7318
7319 // Start the next in the queue if the last step wasn't forced.
7320 // Timers currently will call their complete callbacks, which
7321 // will dequeue but only if they were gotoEnd.
7322 if ( dequeue || !gotoEnd ) {
7323 jQuery.dequeue( this, type );
7324 }
7325 } );
7326 },
7327 finish: function( type ) {
7328 if ( type !== false ) {
7329 type = type || "fx";
7330 }
7331 return this.each( function() {
7332 var index,
7333 data = dataPriv.get( this ),
7334 queue = data[ type + "queue" ],
7335 hooks = data[ type + "queueHooks" ],
7336 timers = jQuery.timers,
7337 length = queue ? queue.length : 0;
7338
7339 // Enable finishing flag on private data
7340 data.finish = true;
7341
7342 // Empty the queue first
7343 jQuery.queue( this, type, [] );
7344
7345 if ( hooks && hooks.stop ) {
7346 hooks.stop.call( this, true );
7347 }
7348
7349 // Look for any active animations, and finish them
7350 for ( index = timers.length; index--; ) {
7351 if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
7352 timers[ index ].anim.stop( true );
7353 timers.splice( index, 1 );
7354 }
7355 }
7356
7357 // Look for any animations in the old queue and finish them
7358 for ( index = 0; index < length; index++ ) {
7359 if ( queue[ index ] && queue[ index ].finish ) {
7360 queue[ index ].finish.call( this );
7361 }
7362 }
7363
7364 // Turn off finishing flag
7365 delete data.finish;
7366 } );
7367 }
7368} );
7369
7370jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
7371 var cssFn = jQuery.fn[ name ];
7372 jQuery.fn[ name ] = function( speed, easing, callback ) {
7373 return speed == null || typeof speed === "boolean" ?
7374 cssFn.apply( this, arguments ) :
7375 this.animate( genFx( name, true ), speed, easing, callback );
7376 };
7377} );
7378
7379// Generate shortcuts for custom animations
7380jQuery.each( {
7381 slideDown: genFx( "show" ),
7382 slideUp: genFx( "hide" ),
7383 slideToggle: genFx( "toggle" ),
7384 fadeIn: { opacity: "show" },
7385 fadeOut: { opacity: "hide" },
7386 fadeToggle: { opacity: "toggle" }
7387}, function( name, props ) {
7388 jQuery.fn[ name ] = function( speed, easing, callback ) {
7389 return this.animate( props, speed, easing, callback );
7390 };
7391} );
7392
7393jQuery.timers = [];
7394jQuery.fx.tick = function() {
7395 var timer,
7396 i = 0,
7397 timers = jQuery.timers;
7398
7399 fxNow = jQuery.now();
7400
7401 for ( ; i < timers.length; i++ ) {
7402 timer = timers[ i ];
7403
7404 // Run the timer and safely remove it when done (allowing for external removal)
7405 if ( !timer() && timers[ i ] === timer ) {
7406 timers.splice( i--, 1 );
7407 }
7408 }
7409
7410 if ( !timers.length ) {
7411 jQuery.fx.stop();
7412 }
7413 fxNow = undefined;
7414};
7415
7416jQuery.fx.timer = function( timer ) {
7417 jQuery.timers.push( timer );
7418 jQuery.fx.start();
7419};
7420
7421jQuery.fx.interval = 13;
7422jQuery.fx.start = function() {
7423 if ( inProgress ) {
7424 return;
7425 }
7426
7427 inProgress = true;
7428 schedule();
7429};
7430
7431jQuery.fx.stop = function() {
7432 inProgress = null;
7433};
7434
7435jQuery.fx.speeds = {
7436 slow: 600,
7437 fast: 200,
7438
7439 // Default speed
7440 _default: 400
7441};
7442
7443
7444// Based off of the plugin by Clint Helfers, with permission.
7445// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
7446jQuery.fn.delay = function( time, type ) {
7447 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
7448 type = type || "fx";
7449
7450 return this.queue( type, function( next, hooks ) {
7451 var timeout = window.setTimeout( next, time );
7452 hooks.stop = function() {
7453 window.clearTimeout( timeout );
7454 };
7455 } );
7456};
7457
7458
7459( function() {
7460 var input = document.createElement( "input" ),
7461 select = document.createElement( "select" ),
7462 opt = select.appendChild( document.createElement( "option" ) );
7463
7464 input.type = "checkbox";
7465
7466 // Support: Android <=4.3 only
7467 // Default value for a checkbox should be "on"
7468 support.checkOn = input.value !== "";
7469
7470 // Support: IE <=11 only
7471 // Must access selectedIndex to make default options select
7472 support.optSelected = opt.selected;
7473
7474 // Support: IE <=11 only
7475 // An input loses its value after becoming a radio
7476 input = document.createElement( "input" );
7477 input.value = "t";
7478 input.type = "radio";
7479 support.radioValue = input.value === "t";
7480} )();
7481
7482
7483var boolHook,
7484 attrHandle = jQuery.expr.attrHandle;
7485
7486jQuery.fn.extend( {
7487 attr: function( name, value ) {
7488 return access( this, jQuery.attr, name, value, arguments.length > 1 );
7489 },
7490
7491 removeAttr: function( name ) {
7492 return this.each( function() {
7493 jQuery.removeAttr( this, name );
7494 } );
7495 }
7496} );
7497
7498jQuery.extend( {
7499 attr: function( elem, name, value ) {
7500 var ret, hooks,
7501 nType = elem.nodeType;
7502
7503 // Don't get/set attributes on text, comment and attribute nodes
7504 if ( nType === 3 || nType === 8 || nType === 2 ) {
7505 return;
7506 }
7507
7508 // Fallback to prop when attributes are not supported
7509 if ( typeof elem.getAttribute === "undefined" ) {
7510 return jQuery.prop( elem, name, value );
7511 }
7512
7513 // Attribute hooks are determined by the lowercase version
7514 // Grab necessary hook if one is defined
7515 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
7516 hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
7517 ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
7518 }
7519
7520 if ( value !== undefined ) {
7521 if ( value === null ) {
7522 jQuery.removeAttr( elem, name );
7523 return;
7524 }
7525
7526 if ( hooks && "set" in hooks &&
7527 ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
7528 return ret;
7529 }
7530
7531 elem.setAttribute( name, value + "" );
7532 return value;
7533 }
7534
7535 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
7536 return ret;
7537 }
7538
7539 ret = jQuery.find.attr( elem, name );
7540
7541 // Non-existent attributes return null, we normalize to undefined
7542 return ret == null ? undefined : ret;
7543 },
7544
7545 attrHooks: {
7546 type: {
7547 set: function( elem, value ) {
7548 if ( !support.radioValue && value === "radio" &&
7549 nodeName( elem, "input" ) ) {
7550 var val = elem.value;
7551 elem.setAttribute( "type", value );
7552 if ( val ) {
7553 elem.value = val;
7554 }
7555 return value;
7556 }
7557 }
7558 }
7559 },
7560
7561 removeAttr: function( elem, value ) {
7562 var name,
7563 i = 0,
7564
7565 // Attribute names can contain non-HTML whitespace characters
7566 // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
7567 attrNames = value && value.match( rnothtmlwhite );
7568
7569 if ( attrNames && elem.nodeType === 1 ) {
7570 while ( ( name = attrNames[ i++ ] ) ) {
7571 elem.removeAttribute( name );
7572 }
7573 }
7574 }
7575} );
7576
7577// Hooks for boolean attributes
7578boolHook = {
7579 set: function( elem, value, name ) {
7580 if ( value === false ) {
7581
7582 // Remove boolean attributes when set to false
7583 jQuery.removeAttr( elem, name );
7584 } else {
7585 elem.setAttribute( name, name );
7586 }
7587 return name;
7588 }
7589};
7590
7591jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
7592 var getter = attrHandle[ name ] || jQuery.find.attr;
7593
7594 attrHandle[ name ] = function( elem, name, isXML ) {
7595 var ret, handle,
7596 lowercaseName = name.toLowerCase();
7597
7598 if ( !isXML ) {
7599
7600 // Avoid an infinite loop by temporarily removing this function from the getter
7601 handle = attrHandle[ lowercaseName ];
7602 attrHandle[ lowercaseName ] = ret;
7603 ret = getter( elem, name, isXML ) != null ?
7604 lowercaseName :
7605 null;
7606 attrHandle[ lowercaseName ] = handle;
7607 }
7608 return ret;
7609 };
7610} );
7611
7612
7613
7614
7615var rfocusable = /^(?:input|select|textarea|button)$/i,
7616 rclickable = /^(?:a|area)$/i;
7617
7618jQuery.fn.extend( {
7619 prop: function( name, value ) {
7620 return access( this, jQuery.prop, name, value, arguments.length > 1 );
7621 },
7622
7623 removeProp: function( name ) {
7624 return this.each( function() {
7625 delete this[ jQuery.propFix[ name ] || name ];
7626 } );
7627 }
7628} );
7629
7630jQuery.extend( {
7631 prop: function( elem, name, value ) {
7632 var ret, hooks,
7633 nType = elem.nodeType;
7634
7635 // Don't get/set properties on text, comment and attribute nodes
7636 if ( nType === 3 || nType === 8 || nType === 2 ) {
7637 return;
7638 }
7639
7640 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
7641
7642 // Fix name and attach hooks
7643 name = jQuery.propFix[ name ] || name;
7644 hooks = jQuery.propHooks[ name ];
7645 }
7646
7647 if ( value !== undefined ) {
7648 if ( hooks && "set" in hooks &&
7649 ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
7650 return ret;
7651 }
7652
7653 return ( elem[ name ] = value );
7654 }
7655
7656 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
7657 return ret;
7658 }
7659
7660 return elem[ name ];
7661 },
7662
7663 propHooks: {
7664 tabIndex: {
7665 get: function( elem ) {
7666
7667 // Support: IE <=9 - 11 only
7668 // elem.tabIndex doesn't always return the
7669 // correct value when it hasn't been explicitly set
7670 // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
7671 // Use proper attribute retrieval(#12072)
7672 var tabindex = jQuery.find.attr( elem, "tabindex" );
7673
7674 if ( tabindex ) {
7675 return parseInt( tabindex, 10 );
7676 }
7677
7678 if (
7679 rfocusable.test( elem.nodeName ) ||
7680 rclickable.test( elem.nodeName ) &&
7681 elem.href
7682 ) {
7683 return 0;
7684 }
7685
7686 return -1;
7687 }
7688 }
7689 },
7690
7691 propFix: {
7692 "for": "htmlFor",
7693 "class": "className"
7694 }
7695} );
7696
7697// Support: IE <=11 only
7698// Accessing the selectedIndex property
7699// forces the browser to respect setting selected
7700// on the option
7701// The getter ensures a default option is selected
7702// when in an optgroup
7703// eslint rule "no-unused-expressions" is disabled for this code
7704// since it considers such accessions noop
7705if ( !support.optSelected ) {
7706 jQuery.propHooks.selected = {
7707 get: function( elem ) {
7708
7709 /* eslint no-unused-expressions: "off" */
7710
7711 var parent = elem.parentNode;
7712 if ( parent && parent.parentNode ) {
7713 parent.parentNode.selectedIndex;
7714 }
7715 return null;
7716 },
7717 set: function( elem ) {
7718
7719 /* eslint no-unused-expressions: "off" */
7720
7721 var parent = elem.parentNode;
7722 if ( parent ) {
7723 parent.selectedIndex;
7724
7725 if ( parent.parentNode ) {
7726 parent.parentNode.selectedIndex;
7727 }
7728 }
7729 }
7730 };
7731}
7732
7733jQuery.each( [
7734 "tabIndex",
7735 "readOnly",
7736 "maxLength",
7737 "cellSpacing",
7738 "cellPadding",
7739 "rowSpan",
7740 "colSpan",
7741 "useMap",
7742 "frameBorder",
7743 "contentEditable"
7744], function() {
7745 jQuery.propFix[ this.toLowerCase() ] = this;
7746} );
7747
7748
7749
7750
7751 // Strip and collapse whitespace according to HTML spec
7752 // https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace
7753 function stripAndCollapse( value ) {
7754 var tokens = value.match( rnothtmlwhite ) || [];
7755 return tokens.join( " " );
7756 }
7757
7758
7759function getClass( elem ) {
7760 return elem.getAttribute && elem.getAttribute( "class" ) || "";
7761}
7762
7763jQuery.fn.extend( {
7764 addClass: function( value ) {
7765 var classes, elem, cur, curValue, clazz, j, finalValue,
7766 i = 0;
7767
7768 if ( jQuery.isFunction( value ) ) {
7769 return this.each( function( j ) {
7770 jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
7771 } );
7772 }
7773
7774 if ( typeof value === "string" && value ) {
7775 classes = value.match( rnothtmlwhite ) || [];
7776
7777 while ( ( elem = this[ i++ ] ) ) {
7778 curValue = getClass( elem );
7779 cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
7780
7781 if ( cur ) {
7782 j = 0;
7783 while ( ( clazz = classes[ j++ ] ) ) {
7784 if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
7785 cur += clazz + " ";
7786 }
7787 }
7788
7789 // Only assign if different to avoid unneeded rendering.
7790 finalValue = stripAndCollapse( cur );
7791 if ( curValue !== finalValue ) {
7792 elem.setAttribute( "class", finalValue );
7793 }
7794 }
7795 }
7796 }
7797
7798 return this;
7799 },
7800
7801 removeClass: function( value ) {
7802 var classes, elem, cur, curValue, clazz, j, finalValue,
7803 i = 0;
7804
7805 if ( jQuery.isFunction( value ) ) {
7806 return this.each( function( j ) {
7807 jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
7808 } );
7809 }
7810
7811 if ( !arguments.length ) {
7812 return this.attr( "class", "" );
7813 }
7814
7815 if ( typeof value === "string" && value ) {
7816 classes = value.match( rnothtmlwhite ) || [];
7817
7818 while ( ( elem = this[ i++ ] ) ) {
7819 curValue = getClass( elem );
7820
7821 // This expression is here for better compressibility (see addClass)
7822 cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
7823
7824 if ( cur ) {
7825 j = 0;
7826 while ( ( clazz = classes[ j++ ] ) ) {
7827
7828 // Remove *all* instances
7829 while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
7830 cur = cur.replace( " " + clazz + " ", " " );
7831 }
7832 }
7833
7834 // Only assign if different to avoid unneeded rendering.
7835 finalValue = stripAndCollapse( cur );
7836 if ( curValue !== finalValue ) {
7837 elem.setAttribute( "class", finalValue );
7838 }
7839 }
7840 }
7841 }
7842
7843 return this;
7844 },
7845
7846 toggleClass: function( value, stateVal ) {
7847 var type = typeof value;
7848
7849 if ( typeof stateVal === "boolean" && type === "string" ) {
7850 return stateVal ? this.addClass( value ) : this.removeClass( value );
7851 }
7852
7853 if ( jQuery.isFunction( value ) ) {
7854 return this.each( function( i ) {
7855 jQuery( this ).toggleClass(
7856 value.call( this, i, getClass( this ), stateVal ),
7857 stateVal
7858 );
7859 } );
7860 }
7861
7862 return this.each( function() {
7863 var className, i, self, classNames;
7864
7865 if ( type === "string" ) {
7866
7867 // Toggle individual class names
7868 i = 0;
7869 self = jQuery( this );
7870 classNames = value.match( rnothtmlwhite ) || [];
7871
7872 while ( ( className = classNames[ i++ ] ) ) {
7873
7874 // Check each className given, space separated list
7875 if ( self.hasClass( className ) ) {
7876 self.removeClass( className );
7877 } else {
7878 self.addClass( className );
7879 }
7880 }
7881
7882 // Toggle whole class name
7883 } else if ( value === undefined || type === "boolean" ) {
7884 className = getClass( this );
7885 if ( className ) {
7886
7887 // Store className if set
7888 dataPriv.set( this, "__className__", className );
7889 }
7890
7891 // If the element has a class name or if we're passed `false`,
7892 // then remove the whole classname (if there was one, the above saved it).
7893 // Otherwise bring back whatever was previously saved (if anything),
7894 // falling back to the empty string if nothing was stored.
7895 if ( this.setAttribute ) {
7896 this.setAttribute( "class",
7897 className || value === false ?
7898 "" :
7899 dataPriv.get( this, "__className__" ) || ""
7900 );
7901 }
7902 }
7903 } );
7904 },
7905
7906 hasClass: function( selector ) {
7907 var className, elem,
7908 i = 0;
7909
7910 className = " " + selector + " ";
7911 while ( ( elem = this[ i++ ] ) ) {
7912 if ( elem.nodeType === 1 &&
7913 ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
7914 return true;
7915 }
7916 }
7917
7918 return false;
7919 }
7920} );
7921
7922
7923
7924
7925var rreturn = /\r/g;
7926
7927jQuery.fn.extend( {
7928 val: function( value ) {
7929 var hooks, ret, isFunction,
7930 elem = this[ 0 ];
7931
7932 if ( !arguments.length ) {
7933 if ( elem ) {
7934 hooks = jQuery.valHooks[ elem.type ] ||
7935 jQuery.valHooks[ elem.nodeName.toLowerCase() ];
7936
7937 if ( hooks &&
7938 "get" in hooks &&
7939 ( ret = hooks.get( elem, "value" ) ) !== undefined
7940 ) {
7941 return ret;
7942 }
7943
7944 ret = elem.value;
7945
7946 // Handle most common string cases
7947 if ( typeof ret === "string" ) {
7948 return ret.replace( rreturn, "" );
7949 }
7950
7951 // Handle cases where value is null/undef or number
7952 return ret == null ? "" : ret;
7953 }
7954
7955 return;
7956 }
7957
7958 isFunction = jQuery.isFunction( value );
7959
7960 return this.each( function( i ) {
7961 var val;
7962
7963 if ( this.nodeType !== 1 ) {
7964 return;
7965 }
7966
7967 if ( isFunction ) {
7968 val = value.call( this, i, jQuery( this ).val() );
7969 } else {
7970 val = value;
7971 }
7972
7973 // Treat null/undefined as ""; convert numbers to string
7974 if ( val == null ) {
7975 val = "";
7976
7977 } else if ( typeof val === "number" ) {
7978 val += "";
7979
7980 } else if ( Array.isArray( val ) ) {
7981 val = jQuery.map( val, function( value ) {
7982 return value == null ? "" : value + "";
7983 } );
7984 }
7985
7986 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
7987
7988 // If set returns undefined, fall back to normal setting
7989 if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
7990 this.value = val;
7991 }
7992 } );
7993 }
7994} );
7995
7996jQuery.extend( {
7997 valHooks: {
7998 option: {
7999 get: function( elem ) {
8000
8001 var val = jQuery.find.attr( elem, "value" );
8002 return val != null ?
8003 val :
8004
8005 // Support: IE <=10 - 11 only
8006 // option.text throws exceptions (#14686, #14858)
8007 // Strip and collapse whitespace
8008 // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
8009 stripAndCollapse( jQuery.text( elem ) );
8010 }
8011 },
8012 select: {
8013 get: function( elem ) {
8014 var value, option, i,
8015 options = elem.options,
8016 index = elem.selectedIndex,
8017 one = elem.type === "select-one",
8018 values = one ? null : [],
8019 max = one ? index + 1 : options.length;
8020
8021 if ( index < 0 ) {
8022 i = max;
8023
8024 } else {
8025 i = one ? index : 0;
8026 }
8027
8028 // Loop through all the selected options
8029 for ( ; i < max; i++ ) {
8030 option = options[ i ];
8031
8032 // Support: IE <=9 only
8033 // IE8-9 doesn't update selected after form reset (#2551)
8034 if ( ( option.selected || i === index ) &&
8035
8036 // Don't return options that are disabled or in a disabled optgroup
8037 !option.disabled &&
8038 ( !option.parentNode.disabled ||
8039 !nodeName( option.parentNode, "optgroup" ) ) ) {
8040
8041 // Get the specific value for the option
8042 value = jQuery( option ).val();
8043
8044 // We don't need an array for one selects
8045 if ( one ) {
8046 return value;
8047 }
8048
8049 // Multi-Selects return an array
8050 values.push( value );
8051 }
8052 }
8053
8054 return values;
8055 },
8056
8057 set: function( elem, value ) {
8058 var optionSet, option,
8059 options = elem.options,
8060 values = jQuery.makeArray( value ),
8061 i = options.length;
8062
8063 while ( i-- ) {
8064 option = options[ i ];
8065
8066 /* eslint-disable no-cond-assign */
8067
8068 if ( option.selected =
8069 jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
8070 ) {
8071 optionSet = true;
8072 }
8073
8074 /* eslint-enable no-cond-assign */
8075 }
8076
8077 // Force browsers to behave consistently when non-matching value is set
8078 if ( !optionSet ) {
8079 elem.selectedIndex = -1;
8080 }
8081 return values;
8082 }
8083 }
8084 }
8085} );
8086
8087// Radios and checkboxes getter/setter
8088jQuery.each( [ "radio", "checkbox" ], function() {
8089 jQuery.valHooks[ this ] = {
8090 set: function( elem, value ) {
8091 if ( Array.isArray( value ) ) {
8092 return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
8093 }
8094 }
8095 };
8096 if ( !support.checkOn ) {
8097 jQuery.valHooks[ this ].get = function( elem ) {
8098 return elem.getAttribute( "value" ) === null ? "on" : elem.value;
8099 };
8100 }
8101} );
8102
8103
8104
8105
8106// Return jQuery for attributes-only inclusion
8107
8108
8109var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
8110
8111jQuery.extend( jQuery.event, {
8112
8113 trigger: function( event, data, elem, onlyHandlers ) {
8114
8115 var i, cur, tmp, bubbleType, ontype, handle, special,
8116 eventPath = [ elem || document ],
8117 type = hasOwn.call( event, "type" ) ? event.type : event,
8118 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
8119
8120 cur = tmp = elem = elem || document;
8121
8122 // Don't do events on text and comment nodes
8123 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
8124 return;
8125 }
8126
8127 // focus/blur morphs to focusin/out; ensure we're not firing them right now
8128 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
8129 return;
8130 }
8131
8132 if ( type.indexOf( "." ) > -1 ) {
8133
8134 // Namespaced trigger; create a regexp to match event type in handle()
8135 namespaces = type.split( "." );
8136 type = namespaces.shift();
8137 namespaces.sort();
8138 }
8139 ontype = type.indexOf( ":" ) < 0 && "on" + type;
8140
8141 // Caller can pass in a jQuery.Event object, Object, or just an event type string
8142 event = event[ jQuery.expando ] ?
8143 event :
8144 new jQuery.Event( type, typeof event === "object" && event );
8145
8146 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
8147 event.isTrigger = onlyHandlers ? 2 : 3;
8148 event.namespace = namespaces.join( "." );
8149 event.rnamespace = event.namespace ?
8150 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
8151 null;
8152
8153 // Clean up the event in case it is being reused
8154 event.result = undefined;
8155 if ( !event.target ) {
8156 event.target = elem;
8157 }
8158
8159 // Clone any incoming data and prepend the event, creating the handler arg list
8160 data = data == null ?
8161 [ event ] :
8162 jQuery.makeArray( data, [ event ] );
8163
8164 // Allow special events to draw outside the lines
8165 special = jQuery.event.special[ type ] || {};
8166 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
8167 return;
8168 }
8169
8170 // Determine event propagation path in advance, per W3C events spec (#9951)
8171 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
8172 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
8173
8174 bubbleType = special.delegateType || type;
8175 if ( !rfocusMorph.test( bubbleType + type ) ) {
8176 cur = cur.parentNode;
8177 }
8178 for ( ; cur; cur = cur.parentNode ) {
8179 eventPath.push( cur );
8180 tmp = cur;
8181 }
8182
8183 // Only add window if we got to document (e.g., not plain obj or detached DOM)
8184 if ( tmp === ( elem.ownerDocument || document ) ) {
8185 eventPath.push( tmp.defaultView || tmp.parentWindow || window );
8186 }
8187 }
8188
8189 // Fire handlers on the event path
8190 i = 0;
8191 while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
8192
8193 event.type = i > 1 ?
8194 bubbleType :
8195 special.bindType || type;
8196
8197 // jQuery handler
8198 handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
8199 dataPriv.get( cur, "handle" );
8200 if ( handle ) {
8201 handle.apply( cur, data );
8202 }
8203
8204 // Native handler
8205 handle = ontype && cur[ ontype ];
8206 if ( handle && handle.apply && acceptData( cur ) ) {
8207 event.result = handle.apply( cur, data );
8208 if ( event.result === false ) {
8209 event.preventDefault();
8210 }
8211 }
8212 }
8213 event.type = type;
8214
8215 // If nobody prevented the default action, do it now
8216 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
8217
8218 if ( ( !special._default ||
8219 special._default.apply( eventPath.pop(), data ) === false ) &&
8220 acceptData( elem ) ) {
8221
8222 // Call a native DOM method on the target with the same name as the event.
8223 // Don't do default actions on window, that's where global variables be (#6170)
8224 if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
8225
8226 // Don't re-trigger an onFOO event when we call its FOO() method
8227 tmp = elem[ ontype ];
8228
8229 if ( tmp ) {
8230 elem[ ontype ] = null;
8231 }
8232
8233 // Prevent re-triggering of the same event, since we already bubbled it above
8234 jQuery.event.triggered = type;
8235 elem[ type ]();
8236 jQuery.event.triggered = undefined;
8237
8238 if ( tmp ) {
8239 elem[ ontype ] = tmp;
8240 }
8241 }
8242 }
8243 }
8244
8245 return event.result;
8246 },
8247
8248 // Piggyback on a donor event to simulate a different one
8249 // Used only for `focus(in | out)` events
8250 simulate: function( type, elem, event ) {
8251 var e = jQuery.extend(
8252 new jQuery.Event(),
8253 event,
8254 {
8255 type: type,
8256 isSimulated: true
8257 }
8258 );
8259
8260 jQuery.event.trigger( e, null, elem );
8261 }
8262
8263} );
8264
8265jQuery.fn.extend( {
8266
8267 trigger: function( type, data ) {
8268 return this.each( function() {
8269 jQuery.event.trigger( type, data, this );
8270 } );
8271 },
8272 triggerHandler: function( type, data ) {
8273 var elem = this[ 0 ];
8274 if ( elem ) {
8275 return jQuery.event.trigger( type, data, elem, true );
8276 }
8277 }
8278} );
8279
8280
8281jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
8282 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
8283 "change select submit keydown keypress keyup contextmenu" ).split( " " ),
8284 function( i, name ) {
8285
8286 // Handle event binding
8287 jQuery.fn[ name ] = function( data, fn ) {
8288 return arguments.length > 0 ?
8289 this.on( name, null, data, fn ) :
8290 this.trigger( name );
8291 };
8292} );
8293
8294jQuery.fn.extend( {
8295 hover: function( fnOver, fnOut ) {
8296 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
8297 }
8298} );
8299
8300
8301
8302
8303support.focusin = "onfocusin" in window;
8304
8305
8306// Support: Firefox <=44
8307// Firefox doesn't have focus(in | out) events
8308// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
8309//
8310// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
8311// focus(in | out) events fire after focus & blur events,
8312// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
8313// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
8314if ( !support.focusin ) {
8315 jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
8316
8317 // Attach a single capturing handler on the document while someone wants focusin/focusout
8318 var handler = function( event ) {
8319 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
8320 };
8321
8322 jQuery.event.special[ fix ] = {
8323 setup: function() {
8324 var doc = this.ownerDocument || this,
8325 attaches = dataPriv.access( doc, fix );
8326
8327 if ( !attaches ) {
8328 doc.addEventListener( orig, handler, true );
8329 }
8330 dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
8331 },
8332 teardown: function() {
8333 var doc = this.ownerDocument || this,
8334 attaches = dataPriv.access( doc, fix ) - 1;
8335
8336 if ( !attaches ) {
8337 doc.removeEventListener( orig, handler, true );
8338 dataPriv.remove( doc, fix );
8339
8340 } else {
8341 dataPriv.access( doc, fix, attaches );
8342 }
8343 }
8344 };
8345 } );
8346}
8347var location = window.location;
8348
8349var nonce = jQuery.now();
8350
8351var rquery = ( /\?/ );
8352
8353
8354
8355// Cross-browser xml parsing
8356jQuery.parseXML = function( data ) {
8357 var xml;
8358 if ( !data || typeof data !== "string" ) {
8359 return null;
8360 }
8361
8362 // Support: IE 9 - 11 only
8363 // IE throws on parseFromString with invalid input.
8364 try {
8365 xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
8366 } catch ( e ) {
8367 xml = undefined;
8368 }
8369
8370 if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
8371 jQuery.error( "Invalid XML: " + data );
8372 }
8373 return xml;
8374};
8375
8376
8377var
8378 rbracket = /\[\]$/,
8379 rCRLF = /\r?\n/g,
8380 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
8381 rsubmittable = /^(?:input|select|textarea|keygen)/i;
8382
8383function buildParams( prefix, obj, traditional, add ) {
8384 var name;
8385
8386 if ( Array.isArray( obj ) ) {
8387
8388 // Serialize array item.
8389 jQuery.each( obj, function( i, v ) {
8390 if ( traditional || rbracket.test( prefix ) ) {
8391
8392 // Treat each array item as a scalar.
8393 add( prefix, v );
8394
8395 } else {
8396
8397 // Item is non-scalar (array or object), encode its numeric index.
8398 buildParams(
8399 prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
8400 v,
8401 traditional,
8402 add
8403 );
8404 }
8405 } );
8406
8407 } else if ( !traditional && jQuery.type( obj ) === "object" ) {
8408
8409 // Serialize object item.
8410 for ( name in obj ) {
8411 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
8412 }
8413
8414 } else {
8415
8416 // Serialize scalar item.
8417 add( prefix, obj );
8418 }
8419}
8420
8421// Serialize an array of form elements or a set of
8422// key/values into a query string
8423jQuery.param = function( a, traditional ) {
8424 var prefix,
8425 s = [],
8426 add = function( key, valueOrFunction ) {
8427
8428 // If value is a function, invoke it and use its return value
8429 var value = jQuery.isFunction( valueOrFunction ) ?
8430 valueOrFunction() :
8431 valueOrFunction;
8432
8433 s[ s.length ] = encodeURIComponent( key ) + "=" +
8434 encodeURIComponent( value == null ? "" : value );
8435 };
8436
8437 // If an array was passed in, assume that it is an array of form elements.
8438 if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
8439
8440 // Serialize the form elements
8441 jQuery.each( a, function() {
8442 add( this.name, this.value );
8443 } );
8444
8445 } else {
8446
8447 // If traditional, encode the "old" way (the way 1.3.2 or older
8448 // did it), otherwise encode params recursively.
8449 for ( prefix in a ) {
8450 buildParams( prefix, a[ prefix ], traditional, add );
8451 }
8452 }
8453
8454 // Return the resulting serialization
8455 return s.join( "&" );
8456};
8457
8458jQuery.fn.extend( {
8459 serialize: function() {
8460 return jQuery.param( this.serializeArray() );
8461 },
8462 serializeArray: function() {
8463 return this.map( function() {
8464
8465 // Can add propHook for "elements" to filter or add form elements
8466 var elements = jQuery.prop( this, "elements" );
8467 return elements ? jQuery.makeArray( elements ) : this;
8468 } )
8469 .filter( function() {
8470 var type = this.type;
8471
8472 // Use .is( ":disabled" ) so that fieldset[disabled] works
8473 return this.name && !jQuery( this ).is( ":disabled" ) &&
8474 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
8475 ( this.checked || !rcheckableType.test( type ) );
8476 } )
8477 .map( function( i, elem ) {
8478 var val = jQuery( this ).val();
8479
8480 if ( val == null ) {
8481 return null;
8482 }
8483
8484 if ( Array.isArray( val ) ) {
8485 return jQuery.map( val, function( val ) {
8486 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8487 } );
8488 }
8489
8490 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8491 } ).get();
8492 }
8493} );
8494
8495
8496var
8497 r20 = /%20/g,
8498 rhash = /#.*$/,
8499 rantiCache = /([?&])_=[^&]*/,
8500 rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
8501
8502 // #7653, #8125, #8152: local protocol detection
8503 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
8504 rnoContent = /^(?:GET|HEAD)$/,
8505 rprotocol = /^\/\//,
8506
8507 /* Prefilters
8508 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
8509 * 2) These are called:
8510 * - BEFORE asking for a transport
8511 * - AFTER param serialization (s.data is a string if s.processData is true)
8512 * 3) key is the dataType
8513 * 4) the catchall symbol "*" can be used
8514 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
8515 */
8516 prefilters = {},
8517
8518 /* Transports bindings
8519 * 1) key is the dataType
8520 * 2) the catchall symbol "*" can be used
8521 * 3) selection will start with transport dataType and THEN go to "*" if needed
8522 */
8523 transports = {},
8524
8525 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
8526 allTypes = "*/".concat( "*" ),
8527
8528 // Anchor tag for parsing the document origin
8529 originAnchor = document.createElement( "a" );
8530 originAnchor.href = location.href;
8531
8532// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
8533function addToPrefiltersOrTransports( structure ) {
8534
8535 // dataTypeExpression is optional and defaults to "*"
8536 return function( dataTypeExpression, func ) {
8537
8538 if ( typeof dataTypeExpression !== "string" ) {
8539 func = dataTypeExpression;
8540 dataTypeExpression = "*";
8541 }
8542
8543 var dataType,
8544 i = 0,
8545 dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
8546
8547 if ( jQuery.isFunction( func ) ) {
8548
8549 // For each dataType in the dataTypeExpression
8550 while ( ( dataType = dataTypes[ i++ ] ) ) {
8551
8552 // Prepend if requested
8553 if ( dataType[ 0 ] === "+" ) {
8554 dataType = dataType.slice( 1 ) || "*";
8555 ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
8556
8557 // Otherwise append
8558 } else {
8559 ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
8560 }
8561 }
8562 }
8563 };
8564}
8565
8566// Base inspection function for prefilters and transports
8567function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
8568
8569 var inspected = {},
8570 seekingTransport = ( structure === transports );
8571
8572 function inspect( dataType ) {
8573 var selected;
8574 inspected[ dataType ] = true;
8575 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
8576 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
8577 if ( typeof dataTypeOrTransport === "string" &&
8578 !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
8579
8580 options.dataTypes.unshift( dataTypeOrTransport );
8581 inspect( dataTypeOrTransport );
8582 return false;
8583 } else if ( seekingTransport ) {
8584 return !( selected = dataTypeOrTransport );
8585 }
8586 } );
8587 return selected;
8588 }
8589
8590 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
8591}
8592
8593// A special extend for ajax options
8594// that takes "flat" options (not to be deep extended)
8595// Fixes #9887
8596function ajaxExtend( target, src ) {
8597 var key, deep,
8598 flatOptions = jQuery.ajaxSettings.flatOptions || {};
8599
8600 for ( key in src ) {
8601 if ( src[ key ] !== undefined ) {
8602 ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
8603 }
8604 }
8605 if ( deep ) {
8606 jQuery.extend( true, target, deep );
8607 }
8608
8609 return target;
8610}
8611
8612/* Handles responses to an ajax request:
8613 * - finds the right dataType (mediates between content-type and expected dataType)
8614 * - returns the corresponding response
8615 */
8616function ajaxHandleResponses( s, jqXHR, responses ) {
8617
8618 var ct, type, finalDataType, firstDataType,
8619 contents = s.contents,
8620 dataTypes = s.dataTypes;
8621
8622 // Remove auto dataType and get content-type in the process
8623 while ( dataTypes[ 0 ] === "*" ) {
8624 dataTypes.shift();
8625 if ( ct === undefined ) {
8626 ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
8627 }
8628 }
8629
8630 // Check if we're dealing with a known content-type
8631 if ( ct ) {
8632 for ( type in contents ) {
8633 if ( contents[ type ] && contents[ type ].test( ct ) ) {
8634 dataTypes.unshift( type );
8635 break;
8636 }
8637 }
8638 }
8639
8640 // Check to see if we have a response for the expected dataType
8641 if ( dataTypes[ 0 ] in responses ) {
8642 finalDataType = dataTypes[ 0 ];
8643 } else {
8644
8645 // Try convertible dataTypes
8646 for ( type in responses ) {
8647 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
8648 finalDataType = type;
8649 break;
8650 }
8651 if ( !firstDataType ) {
8652 firstDataType = type;
8653 }
8654 }
8655
8656 // Or just use first one
8657 finalDataType = finalDataType || firstDataType;
8658 }
8659
8660 // If we found a dataType
8661 // We add the dataType to the list if needed
8662 // and return the corresponding response
8663 if ( finalDataType ) {
8664 if ( finalDataType !== dataTypes[ 0 ] ) {
8665 dataTypes.unshift( finalDataType );
8666 }
8667 return responses[ finalDataType ];
8668 }
8669}
8670
8671/* Chain conversions given the request and the original response
8672 * Also sets the responseXXX fields on the jqXHR instance
8673 */
8674function ajaxConvert( s, response, jqXHR, isSuccess ) {
8675 var conv2, current, conv, tmp, prev,
8676 converters = {},
8677
8678 // Work with a copy of dataTypes in case we need to modify it for conversion
8679 dataTypes = s.dataTypes.slice();
8680
8681 // Create converters map with lowercased keys
8682 if ( dataTypes[ 1 ] ) {
8683 for ( conv in s.converters ) {
8684 converters[ conv.toLowerCase() ] = s.converters[ conv ];
8685 }
8686 }
8687
8688 current = dataTypes.shift();
8689
8690 // Convert to each sequential dataType
8691 while ( current ) {
8692
8693 if ( s.responseFields[ current ] ) {
8694 jqXHR[ s.responseFields[ current ] ] = response;
8695 }
8696
8697 // Apply the dataFilter if provided
8698 if ( !prev && isSuccess && s.dataFilter ) {
8699 response = s.dataFilter( response, s.dataType );
8700 }
8701
8702 prev = current;
8703 current = dataTypes.shift();
8704
8705 if ( current ) {
8706
8707 // There's only work to do if current dataType is non-auto
8708 if ( current === "*" ) {
8709
8710 current = prev;
8711
8712 // Convert response if prev dataType is non-auto and differs from current
8713 } else if ( prev !== "*" && prev !== current ) {
8714
8715 // Seek a direct converter
8716 conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8717
8718 // If none found, seek a pair
8719 if ( !conv ) {
8720 for ( conv2 in converters ) {
8721
8722 // If conv2 outputs current
8723 tmp = conv2.split( " " );
8724 if ( tmp[ 1 ] === current ) {
8725
8726 // If prev can be converted to accepted input
8727 conv = converters[ prev + " " + tmp[ 0 ] ] ||
8728 converters[ "* " + tmp[ 0 ] ];
8729 if ( conv ) {
8730
8731 // Condense equivalence converters
8732 if ( conv === true ) {
8733 conv = converters[ conv2 ];
8734
8735 // Otherwise, insert the intermediate dataType
8736 } else if ( converters[ conv2 ] !== true ) {
8737 current = tmp[ 0 ];
8738 dataTypes.unshift( tmp[ 1 ] );
8739 }
8740 break;
8741 }
8742 }
8743 }
8744 }
8745
8746 // Apply converter (if not an equivalence)
8747 if ( conv !== true ) {
8748
8749 // Unless errors are allowed to bubble, catch and return them
8750 if ( conv && s.throws ) {
8751 response = conv( response );
8752 } else {
8753 try {
8754 response = conv( response );
8755 } catch ( e ) {
8756 return {
8757 state: "parsererror",
8758 error: conv ? e : "No conversion from " + prev + " to " + current
8759 };
8760 }
8761 }
8762 }
8763 }
8764 }
8765 }
8766
8767 return { state: "success", data: response };
8768}
8769
8770jQuery.extend( {
8771
8772 // Counter for holding the number of active queries
8773 active: 0,
8774
8775 // Last-Modified header cache for next request
8776 lastModified: {},
8777 etag: {},
8778
8779 ajaxSettings: {
8780 url: location.href,
8781 type: "GET",
8782 isLocal: rlocalProtocol.test( location.protocol ),
8783 global: true,
8784 processData: true,
8785 async: true,
8786 contentType: "application/x-www-form-urlencoded; charset=UTF-8",
8787
8788 /*
8789 timeout: 0,
8790 data: null,
8791 dataType: null,
8792 username: null,
8793 password: null,
8794 cache: null,
8795 throws: false,
8796 traditional: false,
8797 headers: {},
8798 */
8799
8800 accepts: {
8801 "*": allTypes,
8802 text: "text/plain",
8803 html: "text/html",
8804 xml: "application/xml, text/xml",
8805 json: "application/json, text/javascript"
8806 },
8807
8808 contents: {
8809 xml: /\bxml\b/,
8810 html: /\bhtml/,
8811 json: /\bjson\b/
8812 },
8813
8814 responseFields: {
8815 xml: "responseXML",
8816 text: "responseText",
8817 json: "responseJSON"
8818 },
8819
8820 // Data converters
8821 // Keys separate source (or catchall "*") and destination types with a single space
8822 converters: {
8823
8824 // Convert anything to text
8825 "* text": String,
8826
8827 // Text to html (true = no transformation)
8828 "text html": true,
8829
8830 // Evaluate text as a json expression
8831 "text json": JSON.parse,
8832
8833 // Parse text as xml
8834 "text xml": jQuery.parseXML
8835 },
8836
8837 // For options that shouldn't be deep extended:
8838 // you can add your own custom options here if
8839 // and when you create one that shouldn't be
8840 // deep extended (see ajaxExtend)
8841 flatOptions: {
8842 url: true,
8843 context: true
8844 }
8845 },
8846
8847 // Creates a full fledged settings object into target
8848 // with both ajaxSettings and settings fields.
8849 // If target is omitted, writes into ajaxSettings.
8850 ajaxSetup: function( target, settings ) {
8851 return settings ?
8852
8853 // Building a settings object
8854 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
8855
8856 // Extending ajaxSettings
8857 ajaxExtend( jQuery.ajaxSettings, target );
8858 },
8859
8860 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
8861 ajaxTransport: addToPrefiltersOrTransports( transports ),
8862
8863 // Main method
8864 ajax: function( url, options ) {
8865
8866 // If url is an object, simulate pre-1.5 signature
8867 if ( typeof url === "object" ) {
8868 options = url;
8869 url = undefined;
8870 }
8871
8872 // Force options to be an object
8873 options = options || {};
8874
8875 var transport,
8876
8877 // URL without anti-cache param
8878 cacheURL,
8879
8880 // Response headers
8881 responseHeadersString,
8882 responseHeaders,
8883
8884 // timeout handle
8885 timeoutTimer,
8886
8887 // Url cleanup var
8888 urlAnchor,
8889
8890 // Request state (becomes false upon send and true upon completion)
8891 completed,
8892
8893 // To know if global events are to be dispatched
8894 fireGlobals,
8895
8896 // Loop variable
8897 i,
8898
8899 // uncached part of the url
8900 uncached,
8901
8902 // Create the final options object
8903 s = jQuery.ajaxSetup( {}, options ),
8904
8905 // Callbacks context
8906 callbackContext = s.context || s,
8907
8908 // Context for global events is callbackContext if it is a DOM node or jQuery collection
8909 globalEventContext = s.context &&
8910 ( callbackContext.nodeType || callbackContext.jquery ) ?
8911 jQuery( callbackContext ) :
8912 jQuery.event,
8913
8914 // Deferreds
8915 deferred = jQuery.Deferred(),
8916 completeDeferred = jQuery.Callbacks( "once memory" ),
8917
8918 // Status-dependent callbacks
8919 statusCode = s.statusCode || {},
8920
8921 // Headers (they are sent all at once)
8922 requestHeaders = {},
8923 requestHeadersNames = {},
8924
8925 // Default abort message
8926 strAbort = "canceled",
8927
8928 // Fake xhr
8929 jqXHR = {
8930 readyState: 0,
8931
8932 // Builds headers hashtable if needed
8933 getResponseHeader: function( key ) {
8934 var match;
8935 if ( completed ) {
8936 if ( !responseHeaders ) {
8937 responseHeaders = {};
8938 while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
8939 responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
8940 }
8941 }
8942 match = responseHeaders[ key.toLowerCase() ];
8943 }
8944 return match == null ? null : match;
8945 },
8946
8947 // Raw string
8948 getAllResponseHeaders: function() {
8949 return completed ? responseHeadersString : null;
8950 },
8951
8952 // Caches the header
8953 setRequestHeader: function( name, value ) {
8954 if ( completed == null ) {
8955 name = requestHeadersNames[ name.toLowerCase() ] =
8956 requestHeadersNames[ name.toLowerCase() ] || name;
8957 requestHeaders[ name ] = value;
8958 }
8959 return this;
8960 },
8961
8962 // Overrides response content-type header
8963 overrideMimeType: function( type ) {
8964 if ( completed == null ) {
8965 s.mimeType = type;
8966 }
8967 return this;
8968 },
8969
8970 // Status-dependent callbacks
8971 statusCode: function( map ) {
8972 var code;
8973 if ( map ) {
8974 if ( completed ) {
8975
8976 // Execute the appropriate callbacks
8977 jqXHR.always( map[ jqXHR.status ] );
8978 } else {
8979
8980 // Lazy-add the new callbacks in a way that preserves old ones
8981 for ( code in map ) {
8982 statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
8983 }
8984 }
8985 }
8986 return this;
8987 },
8988
8989 // Cancel the request
8990 abort: function( statusText ) {
8991 var finalText = statusText || strAbort;
8992 if ( transport ) {
8993 transport.abort( finalText );
8994 }
8995 done( 0, finalText );
8996 return this;
8997 }
8998 };
8999
9000 // Attach deferreds
9001 deferred.promise( jqXHR );
9002
9003 // Add protocol if not provided (prefilters might expect it)
9004 // Handle falsy url in the settings object (#10093: consistency with old signature)
9005 // We also use the url parameter if available
9006 s.url = ( ( url || s.url || location.href ) + "" )
9007 .replace( rprotocol, location.protocol + "//" );
9008
9009 // Alias method option to type as per ticket #12004
9010 s.type = options.method || options.type || s.method || s.type;
9011
9012 // Extract dataTypes list
9013 s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
9014
9015 // A cross-domain request is in order when the origin doesn't match the current origin.
9016 if ( s.crossDomain == null ) {
9017 urlAnchor = document.createElement( "a" );
9018
9019 // Support: IE <=8 - 11, Edge 12 - 13
9020 // IE throws exception on accessing the href property if url is malformed,
9021 // e.g. http://example.com:80x/
9022 try {
9023 urlAnchor.href = s.url;
9024
9025 // Support: IE <=8 - 11 only
9026 // Anchor's host property isn't correctly set when s.url is relative
9027 urlAnchor.href = urlAnchor.href;
9028 s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
9029 urlAnchor.protocol + "//" + urlAnchor.host;
9030 } catch ( e ) {
9031
9032 // If there is an error parsing the URL, assume it is crossDomain,
9033 // it can be rejected by the transport if it is invalid
9034 s.crossDomain = true;
9035 }
9036 }
9037
9038 // Convert data if not already a string
9039 if ( s.data && s.processData && typeof s.data !== "string" ) {
9040 s.data = jQuery.param( s.data, s.traditional );
9041 }
9042
9043 // Apply prefilters
9044 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
9045
9046 // If request was aborted inside a prefilter, stop there
9047 if ( completed ) {
9048 return jqXHR;
9049 }
9050
9051 // We can fire global events as of now if asked to
9052 // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
9053 fireGlobals = jQuery.event && s.global;
9054
9055 // Watch for a new set of requests
9056 if ( fireGlobals && jQuery.active++ === 0 ) {
9057 jQuery.event.trigger( "ajaxStart" );
9058 }
9059
9060 // Uppercase the type
9061 s.type = s.type.toUpperCase();
9062
9063 // Determine if request has content
9064 s.hasContent = !rnoContent.test( s.type );
9065
9066 // Save the URL in case we're toying with the If-Modified-Since
9067 // and/or If-None-Match header later on
9068 // Remove hash to simplify url manipulation
9069 cacheURL = s.url.replace( rhash, "" );
9070
9071 // More options handling for requests with no content
9072 if ( !s.hasContent ) {
9073
9074 // Remember the hash so we can put it back
9075 uncached = s.url.slice( cacheURL.length );
9076
9077 // If data is available, append data to url
9078 if ( s.data ) {
9079 cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
9080
9081 // #9682: remove data so that it's not used in an eventual retry
9082 delete s.data;
9083 }
9084
9085 // Add or update anti-cache param if needed
9086 if ( s.cache === false ) {
9087 cacheURL = cacheURL.replace( rantiCache, "$1" );
9088 uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached;
9089 }
9090
9091 // Put hash and anti-cache on the URL that will be requested (gh-1732)
9092 s.url = cacheURL + uncached;
9093
9094 // Change '%20' to '+' if this is encoded form body content (gh-2658)
9095 } else if ( s.data && s.processData &&
9096 ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
9097 s.data = s.data.replace( r20, "+" );
9098 }
9099
9100 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9101 if ( s.ifModified ) {
9102 if ( jQuery.lastModified[ cacheURL ] ) {
9103 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
9104 }
9105 if ( jQuery.etag[ cacheURL ] ) {
9106 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
9107 }
9108 }
9109
9110 // Set the correct header, if data is being sent
9111 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
9112 jqXHR.setRequestHeader( "Content-Type", s.contentType );
9113 }
9114
9115 // Set the Accepts header for the server, depending on the dataType
9116 jqXHR.setRequestHeader(
9117 "Accept",
9118 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
9119 s.accepts[ s.dataTypes[ 0 ] ] +
9120 ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
9121 s.accepts[ "*" ]
9122 );
9123
9124 // Check for headers option
9125 for ( i in s.headers ) {
9126 jqXHR.setRequestHeader( i, s.headers[ i ] );
9127 }
9128
9129 // Allow custom headers/mimetypes and early abort
9130 if ( s.beforeSend &&
9131 ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
9132
9133 // Abort if not done already and return
9134 return jqXHR.abort();
9135 }
9136
9137 // Aborting is no longer a cancellation
9138 strAbort = "abort";
9139
9140 // Install callbacks on deferreds
9141 completeDeferred.add( s.complete );
9142 jqXHR.done( s.success );
9143 jqXHR.fail( s.error );
9144
9145 // Get transport
9146 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
9147
9148 // If no transport, we auto-abort
9149 if ( !transport ) {
9150 done( -1, "No Transport" );
9151 } else {
9152 jqXHR.readyState = 1;
9153
9154 // Send global event
9155 if ( fireGlobals ) {
9156 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
9157 }
9158
9159 // If request was aborted inside ajaxSend, stop there
9160 if ( completed ) {
9161 return jqXHR;
9162 }
9163
9164 // Timeout
9165 if ( s.async && s.timeout > 0 ) {
9166 timeoutTimer = window.setTimeout( function() {
9167 jqXHR.abort( "timeout" );
9168 }, s.timeout );
9169 }
9170
9171 try {
9172 completed = false;
9173 transport.send( requestHeaders, done );
9174 } catch ( e ) {
9175
9176 // Rethrow post-completion exceptions
9177 if ( completed ) {
9178 throw e;
9179 }
9180
9181 // Propagate others as results
9182 done( -1, e );
9183 }
9184 }
9185
9186 // Callback for when everything is done
9187 function done( status, nativeStatusText, responses, headers ) {
9188 var isSuccess, success, error, response, modified,
9189 statusText = nativeStatusText;
9190
9191 // Ignore repeat invocations
9192 if ( completed ) {
9193 return;
9194 }
9195
9196 completed = true;
9197
9198 // Clear timeout if it exists
9199 if ( timeoutTimer ) {
9200 window.clearTimeout( timeoutTimer );
9201 }
9202
9203 // Dereference transport for early garbage collection
9204 // (no matter how long the jqXHR object will be used)
9205 transport = undefined;
9206
9207 // Cache response headers
9208 responseHeadersString = headers || "";
9209
9210 // Set readyState
9211 jqXHR.readyState = status > 0 ? 4 : 0;
9212
9213 // Determine if successful
9214 isSuccess = status >= 200 && status < 300 || status === 304;
9215
9216 // Get response data
9217 if ( responses ) {
9218 response = ajaxHandleResponses( s, jqXHR, responses );
9219 }
9220
9221 // Convert no matter what (that way responseXXX fields are always set)
9222 response = ajaxConvert( s, response, jqXHR, isSuccess );
9223
9224 // If successful, handle type chaining
9225 if ( isSuccess ) {
9226
9227 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9228 if ( s.ifModified ) {
9229 modified = jqXHR.getResponseHeader( "Last-Modified" );
9230 if ( modified ) {
9231 jQuery.lastModified[ cacheURL ] = modified;
9232 }
9233 modified = jqXHR.getResponseHeader( "etag" );
9234 if ( modified ) {
9235 jQuery.etag[ cacheURL ] = modified;
9236 }
9237 }
9238
9239 // if no content
9240 if ( status === 204 || s.type === "HEAD" ) {
9241 statusText = "nocontent";
9242
9243 // if not modified
9244 } else if ( status === 304 ) {
9245 statusText = "notmodified";
9246
9247 // If we have data, let's convert it
9248 } else {
9249 statusText = response.state;
9250 success = response.data;
9251 error = response.error;
9252 isSuccess = !error;
9253 }
9254 } else {
9255
9256 // Extract error from statusText and normalize for non-aborts
9257 error = statusText;
9258 if ( status || !statusText ) {
9259 statusText = "error";
9260 if ( status < 0 ) {
9261 status = 0;
9262 }
9263 }
9264 }
9265
9266 // Set data for the fake xhr object
9267 jqXHR.status = status;
9268 jqXHR.statusText = ( nativeStatusText || statusText ) + "";
9269
9270 // Success/Error
9271 if ( isSuccess ) {
9272 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
9273 } else {
9274 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
9275 }
9276
9277 // Status-dependent callbacks
9278 jqXHR.statusCode( statusCode );
9279 statusCode = undefined;
9280
9281 if ( fireGlobals ) {
9282 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
9283 [ jqXHR, s, isSuccess ? success : error ] );
9284 }
9285
9286 // Complete
9287 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
9288
9289 if ( fireGlobals ) {
9290 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
9291
9292 // Handle the global AJAX counter
9293 if ( !( --jQuery.active ) ) {
9294 jQuery.event.trigger( "ajaxStop" );
9295 }
9296 }
9297 }
9298
9299 return jqXHR;
9300 },
9301
9302 getJSON: function( url, data, callback ) {
9303 return jQuery.get( url, data, callback, "json" );
9304 },
9305
9306 getScript: function( url, callback ) {
9307 return jQuery.get( url, undefined, callback, "script" );
9308 }
9309} );
9310
9311jQuery.each( [ "get", "post" ], function( i, method ) {
9312 jQuery[ method ] = function( url, data, callback, type ) {
9313
9314 // Shift arguments if data argument was omitted
9315 if ( jQuery.isFunction( data ) ) {
9316 type = type || callback;
9317 callback = data;
9318 data = undefined;
9319 }
9320
9321 // The url can be an options object (which then must have .url)
9322 return jQuery.ajax( jQuery.extend( {
9323 url: url,
9324 type: method,
9325 dataType: type,
9326 data: data,
9327 success: callback
9328 }, jQuery.isPlainObject( url ) && url ) );
9329 };
9330} );
9331
9332
9333jQuery._evalUrl = function( url ) {
9334 return jQuery.ajax( {
9335 url: url,
9336
9337 // Make this explicit, since user can override this through ajaxSetup (#11264)
9338 type: "GET",
9339 dataType: "script",
9340 cache: true,
9341 async: false,
9342 global: false,
9343 "throws": true
9344 } );
9345};
9346
9347
9348jQuery.fn.extend( {
9349 wrapAll: function( html ) {
9350 var wrap;
9351
9352 if ( this[ 0 ] ) {
9353 if ( jQuery.isFunction( html ) ) {
9354 html = html.call( this[ 0 ] );
9355 }
9356
9357 // The elements to wrap the target around
9358 wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
9359
9360 if ( this[ 0 ].parentNode ) {
9361 wrap.insertBefore( this[ 0 ] );
9362 }
9363
9364 wrap.map( function() {
9365 var elem = this;
9366
9367 while ( elem.firstElementChild ) {
9368 elem = elem.firstElementChild;
9369 }
9370
9371 return elem;
9372 } ).append( this );
9373 }
9374
9375 return this;
9376 },
9377
9378 wrapInner: function( html ) {
9379 if ( jQuery.isFunction( html ) ) {
9380 return this.each( function( i ) {
9381 jQuery( this ).wrapInner( html.call( this, i ) );
9382 } );
9383 }
9384
9385 return this.each( function() {
9386 var self = jQuery( this ),
9387 contents = self.contents();
9388
9389 if ( contents.length ) {
9390 contents.wrapAll( html );
9391
9392 } else {
9393 self.append( html );
9394 }
9395 } );
9396 },
9397
9398 wrap: function( html ) {
9399 var isFunction = jQuery.isFunction( html );
9400
9401 return this.each( function( i ) {
9402 jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
9403 } );
9404 },
9405
9406 unwrap: function( selector ) {
9407 this.parent( selector ).not( "body" ).each( function() {
9408 jQuery( this ).replaceWith( this.childNodes );
9409 } );
9410 return this;
9411 }
9412} );
9413
9414
9415jQuery.expr.pseudos.hidden = function( elem ) {
9416 return !jQuery.expr.pseudos.visible( elem );
9417};
9418jQuery.expr.pseudos.visible = function( elem ) {
9419 return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
9420};
9421
9422
9423
9424
9425jQuery.ajaxSettings.xhr = function() {
9426 try {
9427 return new window.XMLHttpRequest();
9428 } catch ( e ) {}
9429};
9430
9431var xhrSuccessStatus = {
9432
9433 // File protocol always yields status code 0, assume 200
9434 0: 200,
9435
9436 // Support: IE <=9 only
9437 // #1450: sometimes IE returns 1223 when it should be 204
9438 1223: 204
9439 },
9440 xhrSupported = jQuery.ajaxSettings.xhr();
9441
9442support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
9443support.ajax = xhrSupported = !!xhrSupported;
9444
9445jQuery.ajaxTransport( function( options ) {
9446 var callback, errorCallback;
9447
9448 // Cross domain only allowed if supported through XMLHttpRequest
9449 if ( support.cors || xhrSupported && !options.crossDomain ) {
9450 return {
9451 send: function( headers, complete ) {
9452 var i,
9453 xhr = options.xhr();
9454
9455 xhr.open(
9456 options.type,
9457 options.url,
9458 options.async,
9459 options.username,
9460 options.password
9461 );
9462
9463 // Apply custom fields if provided
9464 if ( options.xhrFields ) {
9465 for ( i in options.xhrFields ) {
9466 xhr[ i ] = options.xhrFields[ i ];
9467 }
9468 }
9469
9470 // Override mime type if needed
9471 if ( options.mimeType && xhr.overrideMimeType ) {
9472 xhr.overrideMimeType( options.mimeType );
9473 }
9474
9475 // X-Requested-With header
9476 // For cross-domain requests, seeing as conditions for a preflight are
9477 // akin to a jigsaw puzzle, we simply never set it to be sure.
9478 // (it can always be set on a per-request basis or even using ajaxSetup)
9479 // For same-domain requests, won't change header if already provided.
9480 if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
9481 headers[ "X-Requested-With" ] = "XMLHttpRequest";
9482 }
9483
9484 // Set headers
9485 for ( i in headers ) {
9486 xhr.setRequestHeader( i, headers[ i ] );
9487 }
9488
9489 // Callback
9490 callback = function( type ) {
9491 return function() {
9492 if ( callback ) {
9493 callback = errorCallback = xhr.onload =
9494 xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
9495
9496 if ( type === "abort" ) {
9497 xhr.abort();
9498 } else if ( type === "error" ) {
9499
9500 // Support: IE <=9 only
9501 // On a manual native abort, IE9 throws
9502 // errors on any property access that is not readyState
9503 if ( typeof xhr.status !== "number" ) {
9504 complete( 0, "error" );
9505 } else {
9506 complete(
9507
9508 // File: protocol always yields status 0; see #8605, #14207
9509 xhr.status,
9510 xhr.statusText
9511 );
9512 }
9513 } else {
9514 complete(
9515 xhrSuccessStatus[ xhr.status ] || xhr.status,
9516 xhr.statusText,
9517
9518 // Support: IE <=9 only
9519 // IE9 has no XHR2 but throws on binary (trac-11426)
9520 // For XHR2 non-text, let the caller handle it (gh-2498)
9521 ( xhr.responseType || "text" ) !== "text" ||
9522 typeof xhr.responseText !== "string" ?
9523 { binary: xhr.response } :
9524 { text: xhr.responseText },
9525 xhr.getAllResponseHeaders()
9526 );
9527 }
9528 }
9529 };
9530 };
9531
9532 // Listen to events
9533 xhr.onload = callback();
9534 errorCallback = xhr.onerror = callback( "error" );
9535
9536 // Support: IE 9 only
9537 // Use onreadystatechange to replace onabort
9538 // to handle uncaught aborts
9539 if ( xhr.onabort !== undefined ) {
9540 xhr.onabort = errorCallback;
9541 } else {
9542 xhr.onreadystatechange = function() {
9543
9544 // Check readyState before timeout as it changes
9545 if ( xhr.readyState === 4 ) {
9546
9547 // Allow onerror to be called first,
9548 // but that will not handle a native abort
9549 // Also, save errorCallback to a variable
9550 // as xhr.onerror cannot be accessed
9551 window.setTimeout( function() {
9552 if ( callback ) {
9553 errorCallback();
9554 }
9555 } );
9556 }
9557 };
9558 }
9559
9560 // Create the abort callback
9561 callback = callback( "abort" );
9562
9563 try {
9564
9565 // Do send the request (this may raise an exception)
9566 xhr.send( options.hasContent && options.data || null );
9567 } catch ( e ) {
9568
9569 // #14683: Only rethrow if this hasn't been notified as an error yet
9570 if ( callback ) {
9571 throw e;
9572 }
9573 }
9574 },
9575
9576 abort: function() {
9577 if ( callback ) {
9578 callback();
9579 }
9580 }
9581 };
9582 }
9583} );
9584
9585
9586
9587
9588// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
9589jQuery.ajaxPrefilter( function( s ) {
9590 if ( s.crossDomain ) {
9591 s.contents.script = false;
9592 }
9593} );
9594
9595// Install script dataType
9596jQuery.ajaxSetup( {
9597 accepts: {
9598 script: "text/javascript, application/javascript, " +
9599 "application/ecmascript, application/x-ecmascript"
9600 },
9601 contents: {
9602 script: /\b(?:java|ecma)script\b/
9603 },
9604 converters: {
9605 "text script": function( text ) {
9606 jQuery.globalEval( text );
9607 return text;
9608 }
9609 }
9610} );
9611
9612// Handle cache's special case and crossDomain
9613jQuery.ajaxPrefilter( "script", function( s ) {
9614 if ( s.cache === undefined ) {
9615 s.cache = false;
9616 }
9617 if ( s.crossDomain ) {
9618 s.type = "GET";
9619 }
9620} );
9621
9622// Bind script tag hack transport
9623jQuery.ajaxTransport( "script", function( s ) {
9624
9625 // This transport only deals with cross domain requests
9626 if ( s.crossDomain ) {
9627 var script, callback;
9628 return {
9629 send: function( _, complete ) {
9630 script = jQuery( "<script>" ).prop( {
9631 charset: s.scriptCharset,
9632 src: s.url
9633 } ).on(
9634 "load error",
9635 callback = function( evt ) {
9636 script.remove();
9637 callback = null;
9638 if ( evt ) {
9639 complete( evt.type === "error" ? 404 : 200, evt.type );
9640 }
9641 }
9642 );
9643
9644 // Use native DOM manipulation to avoid our domManip AJAX trickery
9645 document.head.appendChild( script[ 0 ] );
9646 },
9647 abort: function() {
9648 if ( callback ) {
9649 callback();
9650 }
9651 }
9652 };
9653 }
9654} );
9655
9656
9657
9658
9659var oldCallbacks = [],
9660 rjsonp = /(=)\?(?=&|$)|\?\?/;
9661
9662// Default jsonp settings
9663jQuery.ajaxSetup( {
9664 jsonp: "callback",
9665 jsonpCallback: function() {
9666 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
9667 this[ callback ] = true;
9668 return callback;
9669 }
9670} );
9671
9672// Detect, normalize options and install callbacks for jsonp requests
9673jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
9674
9675 var callbackName, overwritten, responseContainer,
9676 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
9677 "url" :
9678 typeof s.data === "string" &&
9679 ( s.contentType || "" )
9680 .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
9681 rjsonp.test( s.data ) && "data"
9682 );
9683
9684 // Handle iff the expected data type is "jsonp" or we have a parameter to set
9685 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
9686
9687 // Get callback name, remembering preexisting value associated with it
9688 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
9689 s.jsonpCallback() :
9690 s.jsonpCallback;
9691
9692 // Insert callback into url or form data
9693 if ( jsonProp ) {
9694 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
9695 } else if ( s.jsonp !== false ) {
9696 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
9697 }
9698
9699 // Use data converter to retrieve json after script execution
9700 s.converters[ "script json" ] = function() {
9701 if ( !responseContainer ) {
9702 jQuery.error( callbackName + " was not called" );
9703 }
9704 return responseContainer[ 0 ];
9705 };
9706
9707 // Force json dataType
9708 s.dataTypes[ 0 ] = "json";
9709
9710 // Install callback
9711 overwritten = window[ callbackName ];
9712 window[ callbackName ] = function() {
9713 responseContainer = arguments;
9714 };
9715
9716 // Clean-up function (fires after converters)
9717 jqXHR.always( function() {
9718
9719 // If previous value didn't exist - remove it
9720 if ( overwritten === undefined ) {
9721 jQuery( window ).removeProp( callbackName );
9722
9723 // Otherwise restore preexisting value
9724 } else {
9725 window[ callbackName ] = overwritten;
9726 }
9727
9728 // Save back as free
9729 if ( s[ callbackName ] ) {
9730
9731 // Make sure that re-using the options doesn't screw things around
9732 s.jsonpCallback = originalSettings.jsonpCallback;
9733
9734 // Save the callback name for future use
9735 oldCallbacks.push( callbackName );
9736 }
9737
9738 // Call if it was a function and we have a response
9739 if ( responseContainer && jQuery.isFunction( overwritten ) ) {
9740 overwritten( responseContainer[ 0 ] );
9741 }
9742
9743 responseContainer = overwritten = undefined;
9744 } );
9745
9746 // Delegate to script
9747 return "script";
9748 }
9749} );
9750
9751
9752
9753
9754// Support: Safari 8 only
9755// In Safari 8 documents created via document.implementation.createHTMLDocument
9756// collapse sibling forms: the second one becomes a child of the first one.
9757// Because of that, this security measure has to be disabled in Safari 8.
9758// https://bugs.webkit.org/show_bug.cgi?id=137337
9759support.createHTMLDocument = ( function() {
9760 var body = document.implementation.createHTMLDocument( "" ).body;
9761 body.innerHTML = "<form></form><form></form>";
9762 return body.childNodes.length === 2;
9763} )();
9764
9765
9766// Argument "data" should be string of html
9767// context (optional): If specified, the fragment will be created in this context,
9768// defaults to document
9769// keepScripts (optional): If true, will include scripts passed in the html string
9770jQuery.parseHTML = function( data, context, keepScripts ) {
9771 if ( typeof data !== "string" ) {
9772 return [];
9773 }
9774 if ( typeof context === "boolean" ) {
9775 keepScripts = context;
9776 context = false;
9777 }
9778
9779 var base, parsed, scripts;
9780
9781 if ( !context ) {
9782
9783 // Stop scripts or inline event handlers from being executed immediately
9784 // by using document.implementation
9785 if ( support.createHTMLDocument ) {
9786 context = document.implementation.createHTMLDocument( "" );
9787
9788 // Set the base href for the created document
9789 // so any parsed elements with URLs
9790 // are based on the document's URL (gh-2965)
9791 base = context.createElement( "base" );
9792 base.href = document.location.href;
9793 context.head.appendChild( base );
9794 } else {
9795 context = document;
9796 }
9797 }
9798
9799 parsed = rsingleTag.exec( data );
9800 scripts = !keepScripts && [];
9801
9802 // Single tag
9803 if ( parsed ) {
9804 return [ context.createElement( parsed[ 1 ] ) ];
9805 }
9806
9807 parsed = buildFragment( [ data ], context, scripts );
9808
9809 if ( scripts && scripts.length ) {
9810 jQuery( scripts ).remove();
9811 }
9812
9813 return jQuery.merge( [], parsed.childNodes );
9814};
9815
9816
9817/**
9818 * Load a url into a page
9819 */
9820jQuery.fn.load = function( url, params, callback ) {
9821 var selector, type, response,
9822 self = this,
9823 off = url.indexOf( " " );
9824
9825 if ( off > -1 ) {
9826 selector = stripAndCollapse( url.slice( off ) );
9827 url = url.slice( 0, off );
9828 }
9829
9830 // If it's a function
9831 if ( jQuery.isFunction( params ) ) {
9832
9833 // We assume that it's the callback
9834 callback = params;
9835 params = undefined;
9836
9837 // Otherwise, build a param string
9838 } else if ( params && typeof params === "object" ) {
9839 type = "POST";
9840 }
9841
9842 // If we have elements to modify, make the request
9843 if ( self.length > 0 ) {
9844 jQuery.ajax( {
9845 url: url,
9846
9847 // If "type" variable is undefined, then "GET" method will be used.
9848 // Make value of this field explicit since
9849 // user can override it through ajaxSetup method
9850 type: type || "GET",
9851 dataType: "html",
9852 data: params
9853 } ).done( function( responseText ) {
9854
9855 // Save response for use in complete callback
9856 response = arguments;
9857
9858 self.html( selector ?
9859
9860 // If a selector was specified, locate the right elements in a dummy div
9861 // Exclude scripts to avoid IE 'Permission Denied' errors
9862 jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
9863
9864 // Otherwise use the full result
9865 responseText );
9866
9867 // If the request succeeds, this function gets "data", "status", "jqXHR"
9868 // but they are ignored because response was set above.
9869 // If it fails, this function gets "jqXHR", "status", "error"
9870 } ).always( callback && function( jqXHR, status ) {
9871 self.each( function() {
9872 callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
9873 } );
9874 } );
9875 }
9876
9877 return this;
9878};
9879
9880
9881
9882
9883// Attach a bunch of functions for handling common AJAX events
9884jQuery.each( [
9885 "ajaxStart",
9886 "ajaxStop",
9887 "ajaxComplete",
9888 "ajaxError",
9889 "ajaxSuccess",
9890 "ajaxSend"
9891], function( i, type ) {
9892 jQuery.fn[ type ] = function( fn ) {
9893 return this.on( type, fn );
9894 };
9895} );
9896
9897
9898
9899
9900jQuery.expr.pseudos.animated = function( elem ) {
9901 return jQuery.grep( jQuery.timers, function( fn ) {
9902 return elem === fn.elem;
9903 } ).length;
9904};
9905
9906
9907
9908
9909jQuery.offset = {
9910 setOffset: function( elem, options, i ) {
9911 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
9912 position = jQuery.css( elem, "position" ),
9913 curElem = jQuery( elem ),
9914 props = {};
9915
9916 // Set position first, in-case top/left are set even on static elem
9917 if ( position === "static" ) {
9918 elem.style.position = "relative";
9919 }
9920
9921 curOffset = curElem.offset();
9922 curCSSTop = jQuery.css( elem, "top" );
9923 curCSSLeft = jQuery.css( elem, "left" );
9924 calculatePosition = ( position === "absolute" || position === "fixed" ) &&
9925 ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
9926
9927 // Need to be able to calculate position if either
9928 // top or left is auto and position is either absolute or fixed
9929 if ( calculatePosition ) {
9930 curPosition = curElem.position();
9931 curTop = curPosition.top;
9932 curLeft = curPosition.left;
9933
9934 } else {
9935 curTop = parseFloat( curCSSTop ) || 0;
9936 curLeft = parseFloat( curCSSLeft ) || 0;
9937 }
9938
9939 if ( jQuery.isFunction( options ) ) {
9940
9941 // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
9942 options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
9943 }
9944
9945 if ( options.top != null ) {
9946 props.top = ( options.top - curOffset.top ) + curTop;
9947 }
9948 if ( options.left != null ) {
9949 props.left = ( options.left - curOffset.left ) + curLeft;
9950 }
9951
9952 if ( "using" in options ) {
9953 options.using.call( elem, props );
9954
9955 } else {
9956 curElem.css( props );
9957 }
9958 }
9959};
9960
9961jQuery.fn.extend( {
9962 offset: function( options ) {
9963
9964 // Preserve chaining for setter
9965 if ( arguments.length ) {
9966 return options === undefined ?
9967 this :
9968 this.each( function( i ) {
9969 jQuery.offset.setOffset( this, options, i );
9970 } );
9971 }
9972
9973 var doc, docElem, rect, win,
9974 elem = this[ 0 ];
9975
9976 if ( !elem ) {
9977 return;
9978 }
9979
9980 // Return zeros for disconnected and hidden (display: none) elements (gh-2310)
9981 // Support: IE <=11 only
9982 // Running getBoundingClientRect on a
9983 // disconnected node in IE throws an error
9984 if ( !elem.getClientRects().length ) {
9985 return { top: 0, left: 0 };
9986 }
9987
9988 rect = elem.getBoundingClientRect();
9989
9990 doc = elem.ownerDocument;
9991 docElem = doc.documentElement;
9992 win = doc.defaultView;
9993
9994 return {
9995 top: rect.top + win.pageYOffset - docElem.clientTop,
9996 left: rect.left + win.pageXOffset - docElem.clientLeft
9997 };
9998 },
9999
10000 position: function() {
10001 if ( !this[ 0 ] ) {
10002 return;
10003 }
10004
10005 var offsetParent, offset,
10006 elem = this[ 0 ],
10007 parentOffset = { top: 0, left: 0 };
10008
10009 // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
10010 // because it is its only offset parent
10011 if ( jQuery.css( elem, "position" ) === "fixed" ) {
10012
10013 // Assume getBoundingClientRect is there when computed position is fixed
10014 offset = elem.getBoundingClientRect();
10015
10016 } else {
10017
10018 // Get *real* offsetParent
10019 offsetParent = this.offsetParent();
10020
10021 // Get correct offsets
10022 offset = this.offset();
10023 if ( !nodeName( offsetParent[ 0 ], "html" ) ) {
10024 parentOffset = offsetParent.offset();
10025 }
10026
10027 // Add offsetParent borders
10028 parentOffset = {
10029 top: parentOffset.top + jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ),
10030 left: parentOffset.left + jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true )
10031 };
10032 }
10033
10034 // Subtract parent offsets and element margins
10035 return {
10036 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
10037 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
10038 };
10039 },
10040
10041 // This method will return documentElement in the following cases:
10042 // 1) For the element inside the iframe without offsetParent, this method will return
10043 // documentElement of the parent window
10044 // 2) For the hidden or detached element
10045 // 3) For body or html element, i.e. in case of the html node - it will return itself
10046 //
10047 // but those exceptions were never presented as a real life use-cases
10048 // and might be considered as more preferable results.
10049 //
10050 // This logic, however, is not guaranteed and can change at any point in the future
10051 offsetParent: function() {
10052 return this.map( function() {
10053 var offsetParent = this.offsetParent;
10054
10055 while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
10056 offsetParent = offsetParent.offsetParent;
10057 }
10058
10059 return offsetParent || documentElement;
10060 } );
10061 }
10062} );
10063
10064// Create scrollLeft and scrollTop methods
10065jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
10066 var top = "pageYOffset" === prop;
10067
10068 jQuery.fn[ method ] = function( val ) {
10069 return access( this, function( elem, method, val ) {
10070
10071 // Coalesce documents and windows
10072 var win;
10073 if ( jQuery.isWindow( elem ) ) {
10074 win = elem;
10075 } else if ( elem.nodeType === 9 ) {
10076 win = elem.defaultView;
10077 }
10078
10079 if ( val === undefined ) {
10080 return win ? win[ prop ] : elem[ method ];
10081 }
10082
10083 if ( win ) {
10084 win.scrollTo(
10085 !top ? val : win.pageXOffset,
10086 top ? val : win.pageYOffset
10087 );
10088
10089 } else {
10090 elem[ method ] = val;
10091 }
10092 }, method, val, arguments.length );
10093 };
10094} );
10095
10096// Support: Safari <=7 - 9.1, Chrome <=37 - 49
10097// Add the top/left cssHooks using jQuery.fn.position
10098// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
10099// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
10100// getComputedStyle returns percent when specified for top/left/bottom/right;
10101// rather than make the css module depend on the offset module, just check for it here
10102jQuery.each( [ "top", "left" ], function( i, prop ) {
10103 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
10104 function( elem, computed ) {
10105 if ( computed ) {
10106 computed = curCSS( elem, prop );
10107
10108 // If curCSS returns percentage, fallback to offset
10109 return rnumnonpx.test( computed ) ?
10110 jQuery( elem ).position()[ prop ] + "px" :
10111 computed;
10112 }
10113 }
10114 );
10115} );
10116
10117
10118// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
10119jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
10120 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
10121 function( defaultExtra, funcName ) {
10122
10123 // Margin is only for outerHeight, outerWidth
10124 jQuery.fn[ funcName ] = function( margin, value ) {
10125 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
10126 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
10127
10128 return access( this, function( elem, type, value ) {
10129 var doc;
10130
10131 if ( jQuery.isWindow( elem ) ) {
10132
10133 // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
10134 return funcName.indexOf( "outer" ) === 0 ?
10135 elem[ "inner" + name ] :
10136 elem.document.documentElement[ "client" + name ];
10137 }
10138
10139 // Get document width or height
10140 if ( elem.nodeType === 9 ) {
10141 doc = elem.documentElement;
10142
10143 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
10144 // whichever is greatest
10145 return Math.max(
10146 elem.body[ "scroll" + name ], doc[ "scroll" + name ],
10147 elem.body[ "offset" + name ], doc[ "offset" + name ],
10148 doc[ "client" + name ]
10149 );
10150 }
10151
10152 return value === undefined ?
10153
10154 // Get width or height on the element, requesting but not forcing parseFloat
10155 jQuery.css( elem, type, extra ) :
10156
10157 // Set width or height on the element
10158 jQuery.style( elem, type, value, extra );
10159 }, type, chainable ? margin : undefined, chainable );
10160 };
10161 } );
10162} );
10163
10164
10165jQuery.fn.extend( {
10166
10167 bind: function( types, data, fn ) {
10168 return this.on( types, null, data, fn );
10169 },
10170 unbind: function( types, fn ) {
10171 return this.off( types, null, fn );
10172 },
10173
10174 delegate: function( selector, types, data, fn ) {
10175 return this.on( types, selector, data, fn );
10176 },
10177 undelegate: function( selector, types, fn ) {
10178
10179 // ( namespace ) or ( selector, types [, fn] )
10180 return arguments.length === 1 ?
10181 this.off( selector, "**" ) :
10182 this.off( types, selector || "**", fn );
10183 }
10184} );
10185
10186jQuery.holdReady = function( hold ) {
10187 if ( hold ) {
10188 jQuery.readyWait++;
10189 } else {
10190 jQuery.ready( true );
10191 }
10192};
10193jQuery.isArray = Array.isArray;
10194jQuery.parseJSON = JSON.parse;
10195jQuery.nodeName = nodeName;
10196
10197
10198
10199
10200// Register as a named AMD module, since jQuery can be concatenated with other
10201// files that may use define, but not via a proper concatenation script that
10202// understands anonymous AMD modules. A named AMD is safest and most robust
10203// way to register. Lowercase jquery is used because AMD module names are
10204// derived from file names, and jQuery is normally delivered in a lowercase
10205// file name. Do this after creating the global so that if an AMD module wants
10206// to call noConflict to hide this version of jQuery, it will work.
10207
10208// Note that for maximum portability, libraries that are not jQuery should
10209// declare themselves as anonymous modules, and avoid setting a global if an
10210// AMD loader is present. jQuery is a special case. For more information, see
10211// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
10212
10213if ( typeof define === "function" && define.amd ) {
10214 define( "jquery", [], function() {
10215 return jQuery;
10216 } );
10217}
10218
10219
10220
10221
10222var
10223
10224 // Map over jQuery in case of overwrite
10225 _jQuery = window.jQuery,
10226
10227 // Map over the $ in case of overwrite
10228 _$ = window.$;
10229
10230jQuery.noConflict = function( deep ) {
10231 if ( window.$ === jQuery ) {
10232 window.$ = _$;
10233 }
10234
10235 if ( deep && window.jQuery === jQuery ) {
10236 window.jQuery = _jQuery;
10237 }
10238
10239 return jQuery;
10240};
10241
10242// Expose jQuery and $ identifiers, even in AMD
10243// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
10244// and CommonJS for browser emulators (#13566)
10245if ( !noGlobal ) {
10246 window.jQuery = window.$ = jQuery;
10247}
10248
10249
10250
10251
10252return jQuery;
10253} );
10254
10255/*!
10256 * Lightbox v1.0.0
10257 * by ßlack Wizard
10258 *
10259 *
10260 * Copyright 2018 ßlack Wizard r
10261 * Released under the MIT license
10262 *
10263 *
10264 * @preserve
10265 */
10266
10267// Uses Node, AMD or browser globals to create a module.
10268(function (root, factory) {
10269 if (typeof define === 'function' && define.amd) {
10270 // AMD. Register as an anonymous module.
10271 define(['jquery'], factory);
10272 } else if (typeof exports === 'object') {
10273 // Node. Does not work with strict CommonJS, but
10274 // only CommonJS-like environments that support module.exports,
10275 // like Node.
10276 module.exports = factory(require('jquery'));
10277 } else {
10278 // Browser globals (root is window)
10279 root.lightbox = factory(root.jQuery);
10280 }
10281}(this, function ($) {
10282
10283 function Lightbox(options) {
10284 this.album = [];
10285 this.currentImageIndex = void 0;
10286 this.init();
10287
10288 // options
10289 this.options = $.extend({}, this.constructor.defaults);
10290 this.option(options);
10291 }
10292
10293
10294 Lightbox.defaults = {
10295 albumLabel: 'Image %1 of %2',
10296 alwaysShowNavOnTouchDevices: false,
10297 fadeDuration: 600,
10298 fitImagesInViewport: true,
10299 imageFadeDuration: 600,
10300 // maxWidth: 800,
10301 // maxHeight: 600,
10302 positionFromTop: 50,
10303 resizeDuration: 700,
10304 showImageNumberLabel: true,
10305 wrapAround: false,
10306 disableScrolling: false,
10307 /*
10308 Sanitize Title
10309 If the caption data is trusted, for example you are hardcoding it in, then leave this to false.
10310 This will free you to add html tags, such as links, in the caption.
10311
10312 If the caption data is user submitted or from some other untrusted source, then set this to true
10313 to prevent xss and other injection attacks.
10314 */
10315 sanitizeTitle: false
10316 };
10317
10318 Lightbox.prototype.option = function(options) {
10319 $.extend(this.options, options);
10320 };
10321
10322 Lightbox.prototype.imageCountLabel = function(currentImageNum, totalImages) {
10323 return this.options.albumLabel.replace(/%1/g, currentImageNum).replace(/%2/g, totalImages);
10324 };
10325
10326 Lightbox.prototype.init = function() {
10327 var self = this;
10328 // Both enable and build methods require the body tag to be in the DOM.
10329 $(document).ready(function() {
10330 self.enable();
10331 self.build();
10332 });
10333 };
10334
10335 // Loop through anchors and areamaps looking for either data-lightbox attributes or rel attributes
10336 // that contain 'lightbox'. When these are clicked, start lightbox.
10337 Lightbox.prototype.enable = function() {
10338 var self = this;
10339 $('body').on('click', 'a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]', function(event) {
10340 self.start($(event.currentTarget));
10341 return false;
10342 });
10343 };
10344
10345 // Build html for the lightbox and the overlay.
10346 // Attach event handlers to the new DOM elements. click click click
10347 Lightbox.prototype.build = function() {
10348 if ($('#lightbox').length > 0) {
10349 return;
10350 }
10351
10352 var self = this;
10353 $('<div id="lightboxOverlay" class="lightboxOverlay"></div><div id="lightbox" class="lightbox"><div class="lb-outerContainer"><div class="lb-container"><img class="lb-image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" /><div class="lb-nav"><a class="lb-prev" href="" ></a><a class="lb-next" href="" ></a></div><div class="lb-loader"><a class="lb-cancel"></a></div></div></div><div class="lb-dataContainer"><div class="lb-data"><div class="lb-details"><span class="lb-caption"></span><span class="lb-number"></span></div><div class="lb-closeContainer"><a class="lb-close"></a></div></div></div></div>').appendTo($('body'));
10354
10355 // Cache jQuery objects
10356 this.$lightbox = $('#lightbox');
10357 this.$overlay = $('#lightboxOverlay');
10358 this.$outerContainer = this.$lightbox.find('.lb-outerContainer');
10359 this.$container = this.$lightbox.find('.lb-container');
10360 this.$image = this.$lightbox.find('.lb-image');
10361 this.$nav = this.$lightbox.find('.lb-nav');
10362
10363 // Store css values for future lookup
10364 this.containerPadding = {
10365 top: parseInt(this.$container.css('padding-top'), 10),
10366 right: parseInt(this.$container.css('padding-right'), 10),
10367 bottom: parseInt(this.$container.css('padding-bottom'), 10),
10368 left: parseInt(this.$container.css('padding-left'), 10)
10369 };
10370
10371 this.imageBorderWidth = {
10372 top: parseInt(this.$image.css('border-top-width'), 10),
10373 right: parseInt(this.$image.css('border-right-width'), 10),
10374 bottom: parseInt(this.$image.css('border-bottom-width'), 10),
10375 left: parseInt(this.$image.css('border-left-width'), 10)
10376 };
10377
10378 // Attach event handlers to the newly minted DOM elements
10379 this.$overlay.hide().on('click', function() {
10380 self.end();
10381 return false;
10382 });
10383
10384 this.$lightbox.hide().on('click', function(event) {
10385 if ($(event.target).attr('id') === 'lightbox') {
10386 self.end();
10387 }
10388 return false;
10389 });
10390
10391 this.$outerContainer.on('click', function(event) {
10392 if ($(event.target).attr('id') === 'lightbox') {
10393 self.end();
10394 }
10395 return false;
10396 });
10397
10398 this.$lightbox.find('.lb-prev').on('click', function() {
10399 if (self.currentImageIndex === 0) {
10400 self.changeImage(self.album.length - 1);
10401 } else {
10402 self.changeImage(self.currentImageIndex - 1);
10403 }
10404 return false;
10405 });
10406
10407 this.$lightbox.find('.lb-next').on('click', function() {
10408 if (self.currentImageIndex === self.album.length - 1) {
10409
10410 self.changeImage(0);
10411 } else {
10412 self.changeImage(self.currentImageIndex + 1);
10413 }
10414 return false;
10415 });
10416
10417 /*
10418 Show context menu for image on right-click
10419
10420 There is a div containing the navigation that spans the entire image and lives above of it. If
10421 you right-click, you are right clicking this div and not the image. This prevents users from
10422 saving the image or using other context menu actions with the image.
10423
10424 To fix this, when we detect the right mouse button is pressed down, but not yet clicked, we
10425 set pointer-events to none on the nav div. This is so that the upcoming right-click event on
10426 the next mouseup will bubble down to the image. Once the right-click/contextmenu event occurs
10427 we set the pointer events back to auto for the nav div so it can capture hover and left-click
10428 events as usual.
10429 */
10430 this.$nav.on('mousedown', function(event) {
10431 if (event.which === 3) {
10432 self.$nav.css('pointer-events', 'none');
10433
10434 self.$lightbox.one('contextmenu', function() {
10435 setTimeout(function() {
10436 this.$nav.css('pointer-events', 'auto');
10437 }.bind(self), 0);
10438 });
10439 }
10440 });
10441
10442
10443 this.$lightbox.find('.lb-loader, .lb-close').on('click', function() {
10444 self.end();
10445 return false;
10446 });
10447 };
10448
10449 // Show overlay and lightbox. If the image is part of a set, add siblings to album array.
10450 Lightbox.prototype.start = function($link) {
10451 var self = this;
10452 var $window = $(window);
10453
10454 $window.on('resize', $.proxy(this.sizeOverlay, this));
10455
10456 $('select, object, embed').css({
10457 visibility: 'hidden'
10458 });
10459
10460 this.sizeOverlay();
10461
10462 this.album = [];
10463 var imageNumber = 0;
10464
10465 function addToAlbum($link) {
10466 self.album.push({
10467 alt: $link.attr('data-alt'),
10468 link: $link.attr('href'),
10469 title: $link.attr('data-title') || $link.attr('title'),
10470 id: $link.attr('data-id') || $link.attr('title')
10471 });
10472 }
10473
10474 // Support both data-lightbox attribute and rel attribute implementations
10475 var dataLightboxValue = $link.attr('data-lightbox');
10476 var $links;
10477
10478 if (dataLightboxValue) {
10479 $links = $($link.prop('tagName') + '[data-lightbox="' + dataLightboxValue + '"]');
10480 for (var i = 0; i < $links.length; i = ++i) {
10481 addToAlbum($($links[i]));
10482 if ($links[i] === $link[0]) {
10483 imageNumber = i;
10484 }
10485 }
10486 } else {
10487 if ($link.attr('rel') === 'lightbox') {
10488 // If image is not part of a set
10489 addToAlbum($link);
10490 } else {
10491 // If image is part of a set
10492 $links = $($link.prop('tagName') + '[rel="' + $link.attr('rel') + '"]');
10493 for (var j = 0; j < $links.length; j = ++j) {
10494 addToAlbum($($links[j]));
10495 if ($links[j] === $link[0]) {
10496 imageNumber = j;
10497 }
10498 }
10499 }
10500 }
10501
10502 // Position Lightbox
10503 var top = $window.scrollTop() + this.options.positionFromTop;
10504 var left = $window.scrollLeft();
10505 this.$lightbox.css({
10506 top: top + 'px',
10507 left: left + 'px'
10508 }).fadeIn(this.options.fadeDuration);
10509
10510 // Disable scrolling of the page while open
10511 if (this.options.disableScrolling) {
10512 $('html').addClass('lb-disable-scrolling');
10513 }
10514
10515 this.changeImage(imageNumber);
10516 };
10517
10518 // Hide most UI elements in preparation for the animated resizing of the lightbox.
10519 Lightbox.prototype.changeImage = function(imageNumber) {
10520 var self = this;
10521
10522 this.disableKeyboardNav();
10523 var $image = this.$lightbox.find('.lb-image');
10524
10525 this.$overlay.fadeIn(this.options.fadeDuration);
10526
10527 $('.lb-loader').fadeIn('slow');
10528 this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption').hide();
10529
10530 this.$outerContainer.addClass('animating');
10531
10532 // When image to show is preloaded, we send the width and height to sizeContainer()
10533 var preloader = new Image();
10534 preloader.onload = function() {
10535 var $preloader;
10536 var imageHeight;
10537 var imageWidth;
10538 var maxImageHeight;
10539 var maxImageWidth;
10540 var windowHeight;
10541 var windowWidth;
10542
10543 $image.attr({
10544 'alt': self.album[imageNumber].alt,
10545 'src': self.album[imageNumber].link,
10546 'href': self.album[imageNumber].id
10547 });
10548
10549 $preloader = $(preloader);
10550
10551 $image.width(preloader.width);
10552 $image.height(preloader.height);
10553
10554 if (self.options.fitImagesInViewport) {
10555 // Fit image inside the viewport.
10556 // Take into account the border around the image and an additional 10px gutter on each side.
10557
10558 windowWidth = $(window).width();
10559 windowHeight = $(window).height();
10560 maxImageWidth = windowWidth - self.containerPadding.left - self.containerPadding.right - self.imageBorderWidth.left - self.imageBorderWidth.right - 20;
10561 maxImageHeight = windowHeight - self.containerPadding.top - self.containerPadding.bottom - self.imageBorderWidth.top - self.imageBorderWidth.bottom - 120;
10562
10563 // Check if image size is larger then maxWidth|maxHeight in settings
10564 if (self.options.maxWidth && self.options.maxWidth < maxImageWidth) {
10565 maxImageWidth = self.options.maxWidth;
10566 }
10567 if (self.options.maxHeight && self.options.maxHeight < maxImageWidth) {
10568 maxImageHeight = self.options.maxHeight;
10569 }
10570
10571 // Is the current image's width or height is greater than the maxImageWidth or maxImageHeight
10572 // option than we need to size down while maintaining the aspect ratio.
10573 if ((preloader.width > maxImageWidth) || (preloader.height > maxImageHeight)) {
10574 if ((preloader.width / maxImageWidth) > (preloader.height / maxImageHeight)) {
10575 imageWidth = maxImageWidth;
10576 imageHeight = parseInt(preloader.height / (preloader.width / imageWidth), 10);
10577 $image.width(imageWidth);
10578 $image.height(imageHeight);
10579 } else {
10580 imageHeight = maxImageHeight;
10581 imageWidth = parseInt(preloader.width / (preloader.height / imageHeight), 10);
10582 $image.width(imageWidth);
10583 $image.height(imageHeight);
10584 }
10585 }
10586 }
10587 self.sizeContainer($image.width(), $image.height());
10588 };
10589
10590 preloader.src = this.album[imageNumber].link;
10591 this.currentImageIndex = imageNumber;
10592 };
10593
10594 // Stretch overlay to fit the viewport
10595 Lightbox.prototype.sizeOverlay = function() {
10596 this.$overlay
10597 .width($(document).width())
10598 .height($(document).height());
10599 };
10600
10601 // Animate the size of the lightbox to fit the image we are showing
10602 Lightbox.prototype.sizeContainer = function(imageWidth, imageHeight) {
10603 var self = this;
10604
10605 var oldWidth = this.$outerContainer.outerWidth();
10606 var oldHeight = this.$outerContainer.outerHeight();
10607 var newWidth = imageWidth + this.containerPadding.left + this.containerPadding.right + this.imageBorderWidth.left + this.imageBorderWidth.right;
10608 var newHeight = imageHeight + this.containerPadding.top + this.containerPadding.bottom + this.imageBorderWidth.top + this.imageBorderWidth.bottom;
10609
10610 function postResize() {
10611 self.$lightbox.find('.lb-dataContainer').width(newWidth);
10612 self.$lightbox.find('.lb-prevLink').height(newHeight);
10613 self.$lightbox.find('.lb-nextLink').height(newHeight);
10614 self.showImage();
10615 }
10616
10617 if (oldWidth !== newWidth || oldHeight !== newHeight) {
10618 this.$outerContainer.animate({
10619 width: newWidth,
10620 height: newHeight
10621 }, this.options.resizeDuration, 'swing', function() {
10622 postResize();
10623 });
10624 } else {
10625 postResize();
10626 }
10627 };
10628
10629 // Display the image and its details and begin preload neighboring images.
10630 Lightbox.prototype.showImage = function() {
10631 this.$lightbox.find('.lb-loader').stop(true).hide();
10632 this.$lightbox.find('.lb-image').fadeIn(this.options.imageFadeDuration);
10633
10634 this.updateNav();
10635 this.updateDetails();
10636 this.preloadNeighboringImages();
10637 this.enableKeyboardNav();
10638 };
10639
10640 // Display previous and next navigation if appropriate.
10641 Lightbox.prototype.updateNav = function() {
10642 // Check to see if the browser supports touch events. If so, we take the conservative approach
10643 // and assume that mouse hover events are not supported and always show prev/next navigation
10644 // arrows in image sets.
10645 var alwaysShowNav = false;
10646 try {
10647 document.createEvent('TouchEvent');
10648 alwaysShowNav = (this.options.alwaysShowNavOnTouchDevices) ? true : false;
10649 } catch (e) {}
10650
10651 this.$lightbox.find('.lb-nav').show();
10652
10653 if (this.album.length > 1) {
10654 if (this.options.wrapAround) {
10655 if (alwaysShowNav) {
10656 this.$lightbox.find('.lb-prev, .lb-next').css('opacity', '1');
10657 }
10658 this.$lightbox.find('.lb-prev, .lb-next').show();
10659 } else {
10660 if (this.currentImageIndex > 0) {
10661 this.$lightbox.find('.lb-prev').show();
10662 if (alwaysShowNav) {
10663 this.$lightbox.find('.lb-prev').css('opacity', '1');
10664 }
10665 }
10666 if (this.currentImageIndex < this.album.length - 1) {
10667 this.$lightbox.find('.lb-next').show();
10668 if (alwaysShowNav) {
10669 this.$lightbox.find('.lb-next').css('opacity', '1');
10670 }
10671 }
10672 }
10673 }
10674 };
10675
10676 // Display caption, image number, and closing button.
10677 Lightbox.prototype.updateDetails = function() {
10678 var self = this;
10679
10680 // Enable anchor clicks in the injected caption html.
10681 // Thanks Nate Wright for the fix. @https://github.com/NateWr
10682 if (typeof this.album[this.currentImageIndex].title !== 'undefined' &&
10683 this.album[this.currentImageIndex].title !== '') {
10684 var $caption = this.$lightbox.find('.lb-caption');
10685 if (this.options.sanitizeTitle) {
10686 $caption.text(this.album[this.currentImageIndex].title);
10687 } else {
10688 $caption.html(this.album[this.currentImageIndex].title);
10689 }
10690 $caption.fadeIn('fast')
10691 .find('a').on('click', function(event) {
10692 if ($(this).attr('target') !== undefined) {
10693 window.open($(this).attr('href'), $(this).attr('target'));
10694 } else {
10695 location.href = $(this).attr('href');
10696 }
10697 });
10698 }
10699
10700 if (this.album.length > 1 && this.options.showImageNumberLabel) {
10701 var labelText = this.imageCountLabel(this.currentImageIndex + 1, this.album.length);
10702 this.$lightbox.find('.lb-number').text(labelText).fadeIn('fast');
10703 } else {
10704 this.$lightbox.find('.lb-number').hide();
10705 }
10706
10707 this.$outerContainer.removeClass('animating');
10708
10709 this.$lightbox.find('.lb-dataContainer').fadeIn(this.options.resizeDuration, function() {
10710 return self.sizeOverlay();
10711 });
10712 };
10713
10714 // Preload previous and next images in set.
10715 Lightbox.prototype.preloadNeighboringImages = function() {
10716 if (this.album.length > this.currentImageIndex + 1) {
10717 var preloadNext = new Image();
10718 preloadNext.src = this.album[this.currentImageIndex + 1].link;
10719 }
10720 if (this.currentImageIndex > 0) {
10721 var preloadPrev = new Image();
10722 preloadPrev.src = this.album[this.currentImageIndex - 1].link;
10723 }
10724 };
10725
10726 Lightbox.prototype.enableKeyboardNav = function() {
10727 $(document).on('keyup.keyboard', $.proxy(this.keyboardAction, this));
10728 };
10729
10730 Lightbox.prototype.disableKeyboardNav = function() {
10731 $(document).off('.keyboard');
10732 };
10733
10734 Lightbox.prototype.keyboardAction = function(event) {
10735 var KEYCODE_ESC = 27;
10736 var KEYCODE_LEFTARROW = 37;
10737 var KEYCODE_RIGHTARROW = 39;
10738
10739 var keycode = event.keyCode;
10740 var key = String.fromCharCode(keycode).toLowerCase();
10741 if (keycode === KEYCODE_ESC || key.match(/x|o|c/)) {
10742 this.end();
10743 } else if (key === 'p' || keycode === KEYCODE_LEFTARROW) {
10744 if (this.currentImageIndex !== 0) {
10745 this.changeImage(this.currentImageIndex - 1);
10746 } else if (this.options.wrapAround && this.album.length > 1) {
10747 this.changeImage(this.album.length - 1);
10748 }
10749 } else if (key === 'n' || keycode === KEYCODE_RIGHTARROW) {
10750 if (this.currentImageIndex !== this.album.length - 1) {
10751 this.changeImage(this.currentImageIndex + 1);
10752 } else if (this.options.wrapAround && this.album.length > 1) {
10753 this.changeImage(0);
10754 }
10755 }
10756 };
10757
10758 // Closing time. :-(
10759 Lightbox.prototype.end = function() {
10760 this.disableKeyboardNav();
10761 $(window).off('resize', this.sizeOverlay);
10762 this.$lightbox.fadeOut(this.options.fadeDuration);
10763 this.$overlay.fadeOut(this.options.fadeDuration);
10764 $('select, object, embed').css({
10765 visibility: 'visible'
10766 });
10767 if (this.options.disableScrolling) {
10768 $('html').removeClass('lb-disable-scrolling');
10769 }
10770 };
10771
10772 return new Lightbox();
10773}));