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