initial commit
[chaz/website] / static / lib / jquery / jquery-1.8.3.js
1 /*!
2 * jQuery JavaScript Library v1.8.3
3 * http://jquery.com/
4 *
5 * Includes Sizzle.js
6 * http://sizzlejs.com/
7 *
8 * Copyright 2012 jQuery Foundation and other contributors
9 * Released under the MIT license
10 * http://jquery.org/license
11 *
12 * Date: Tue Nov 13 2012 08:20:33 GMT-0500 (Eastern Standard Time)
13 */
14 (function( window, undefined ) {
15 var
16 // A central reference to the root jQuery(document)
17 rootjQuery,
18
19 // The deferred used on DOM ready
20 readyList,
21
22 // Use the correct document accordingly with window argument (sandbox)
23 document = window.document,
24 location = window.location,
25 navigator = window.navigator,
26
27 // Map over jQuery in case of overwrite
28 _jQuery = window.jQuery,
29
30 // Map over the $ in case of overwrite
31 _$ = window.$,
32
33 // Save a reference to some core methods
34 core_push = Array.prototype.push,
35 core_slice = Array.prototype.slice,
36 core_indexOf = Array.prototype.indexOf,
37 core_toString = Object.prototype.toString,
38 core_hasOwn = Object.prototype.hasOwnProperty,
39 core_trim = String.prototype.trim,
40
41 // Define a local copy of jQuery
42 jQuery = function( selector, context ) {
43 // The jQuery object is actually just the init constructor 'enhanced'
44 return new jQuery.fn.init( selector, context, rootjQuery );
45 },
46
47 // Used for matching numbers
48 core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,
49
50 // Used for detecting and trimming whitespace
51 core_rnotwhite = /\S/,
52 core_rspace = /\s+/,
53
54 // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
55 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
56
57 // A simple way to check for HTML strings
58 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
59 rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
60
61 // Match a standalone tag
62 rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
63
64 // JSON RegExp
65 rvalidchars = /^[\],:{}\s]*$/,
66 rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
67 rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
68 rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,
69
70 // Matches dashed string for camelizing
71 rmsPrefix = /^-ms-/,
72 rdashAlpha = /-([\da-z])/gi,
73
74 // Used by jQuery.camelCase as callback to replace()
75 fcamelCase = function( all, letter ) {
76 return ( letter + "" ).toUpperCase();
77 },
78
79 // The ready event handler and self cleanup method
80 DOMContentLoaded = function() {
81 if ( document.addEventListener ) {
82 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
83 jQuery.ready();
84 } else if ( document.readyState === "complete" ) {
85 // we're here because readyState === "complete" in oldIE
86 // which is good enough for us to call the dom ready!
87 document.detachEvent( "onreadystatechange", DOMContentLoaded );
88 jQuery.ready();
89 }
90 },
91
92 // [[Class]] -> type pairs
93 class2type = {};
94
95 jQuery.fn = jQuery.prototype = {
96 constructor: jQuery,
97 init: function( selector, context, rootjQuery ) {
98 var match, elem, ret, doc;
99
100 // Handle $(""), $(null), $(undefined), $(false)
101 if ( !selector ) {
102 return this;
103 }
104
105 // Handle $(DOMElement)
106 if ( selector.nodeType ) {
107 this.context = this[0] = selector;
108 this.length = 1;
109 return this;
110 }
111
112 // Handle HTML strings
113 if ( typeof selector === "string" ) {
114 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
115 // Assume that strings that start and end with <> are HTML and skip the regex check
116 match = [ null, selector, null ];
117
118 } else {
119 match = rquickExpr.exec( selector );
120 }
121
122 // Match html or make sure no context is specified for #id
123 if ( match && (match[1] || !context) ) {
124
125 // HANDLE: $(html) -> $(array)
126 if ( match[1] ) {
127 context = context instanceof jQuery ? context[0] : context;
128 doc = ( context && context.nodeType ? context.ownerDocument || context : document );
129
130 // scripts is true for back-compat
131 selector = jQuery.parseHTML( match[1], doc, true );
132 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
133 this.attr.call( selector, context, true );
134 }
135
136 return jQuery.merge( this, selector );
137
138 // HANDLE: $(#id)
139 } else {
140 elem = document.getElementById( match[2] );
141
142 // Check parentNode to catch when Blackberry 4.6 returns
143 // nodes that are no longer in the document #6963
144 if ( elem && elem.parentNode ) {
145 // Handle the case where IE and Opera return items
146 // by name instead of ID
147 if ( elem.id !== match[2] ) {
148 return rootjQuery.find( selector );
149 }
150
151 // Otherwise, we inject the element directly into the jQuery object
152 this.length = 1;
153 this[0] = elem;
154 }
155
156 this.context = document;
157 this.selector = selector;
158 return this;
159 }
160
161 // HANDLE: $(expr, $(...))
162 } else if ( !context || context.jquery ) {
163 return ( context || rootjQuery ).find( selector );
164
165 // HANDLE: $(expr, context)
166 // (which is just equivalent to: $(context).find(expr)
167 } else {
168 return this.constructor( context ).find( selector );
169 }
170
171 // HANDLE: $(function)
172 // Shortcut for document ready
173 } else if ( jQuery.isFunction( selector ) ) {
174 return rootjQuery.ready( selector );
175 }
176
177 if ( selector.selector !== undefined ) {
178 this.selector = selector.selector;
179 this.context = selector.context;
180 }
181
182 return jQuery.makeArray( selector, this );
183 },
184
185 // Start with an empty selector
186 selector: "",
187
188 // The current version of jQuery being used
189 jquery: "1.8.3",
190
191 // The default length of a jQuery object is 0
192 length: 0,
193
194 // The number of elements contained in the matched element set
195 size: function() {
196 return this.length;
197 },
198
199 toArray: function() {
200 return core_slice.call( this );
201 },
202
203 // Get the Nth element in the matched element set OR
204 // Get the whole matched element set as a clean array
205 get: function( num ) {
206 return num == null ?
207
208 // Return a 'clean' array
209 this.toArray() :
210
211 // Return just the object
212 ( num < 0 ? this[ this.length + num ] : this[ num ] );
213 },
214
215 // Take an array of elements and push it onto the stack
216 // (returning the new matched element set)
217 pushStack: function( elems, name, selector ) {
218
219 // Build a new jQuery matched element set
220 var ret = jQuery.merge( this.constructor(), elems );
221
222 // Add the old object onto the stack (as a reference)
223 ret.prevObject = this;
224
225 ret.context = this.context;
226
227 if ( name === "find" ) {
228 ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
229 } else if ( name ) {
230 ret.selector = this.selector + "." + name + "(" + selector + ")";
231 }
232
233 // Return the newly-formed element set
234 return ret;
235 },
236
237 // Execute a callback for every element in the matched set.
238 // (You can seed the arguments with an array of args, but this is
239 // only used internally.)
240 each: function( callback, args ) {
241 return jQuery.each( this, callback, args );
242 },
243
244 ready: function( fn ) {
245 // Add the callback
246 jQuery.ready.promise().done( fn );
247
248 return this;
249 },
250
251 eq: function( i ) {
252 i = +i;
253 return i === -1 ?
254 this.slice( i ) :
255 this.slice( i, i + 1 );
256 },
257
258 first: function() {
259 return this.eq( 0 );
260 },
261
262 last: function() {
263 return this.eq( -1 );
264 },
265
266 slice: function() {
267 return this.pushStack( core_slice.apply( this, arguments ),
268 "slice", core_slice.call(arguments).join(",") );
269 },
270
271 map: function( callback ) {
272 return this.pushStack( jQuery.map(this, function( elem, i ) {
273 return callback.call( elem, i, elem );
274 }));
275 },
276
277 end: function() {
278 return this.prevObject || this.constructor(null);
279 },
280
281 // For internal use only.
282 // Behaves like an Array's method, not like a jQuery method.
283 push: core_push,
284 sort: [].sort,
285 splice: [].splice
286 };
287
288 // Give the init function the jQuery prototype for later instantiation
289 jQuery.fn.init.prototype = jQuery.fn;
290
291 jQuery.extend = jQuery.fn.extend = function() {
292 var options, name, src, copy, copyIsArray, clone,
293 target = arguments[0] || {},
294 i = 1,
295 length = arguments.length,
296 deep = false;
297
298 // Handle a deep copy situation
299 if ( typeof target === "boolean" ) {
300 deep = target;
301 target = arguments[1] || {};
302 // skip the boolean and the target
303 i = 2;
304 }
305
306 // Handle case when target is a string or something (possible in deep copy)
307 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
308 target = {};
309 }
310
311 // extend jQuery itself if only one argument is passed
312 if ( length === i ) {
313 target = this;
314 --i;
315 }
316
317 for ( ; i < length; i++ ) {
318 // Only deal with non-null/undefined values
319 if ( (options = arguments[ i ]) != null ) {
320 // Extend the base object
321 for ( name in options ) {
322 src = target[ name ];
323 copy = options[ name ];
324
325 // Prevent never-ending loop
326 if ( target === copy ) {
327 continue;
328 }
329
330 // Recurse if we're merging plain objects or arrays
331 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
332 if ( copyIsArray ) {
333 copyIsArray = false;
334 clone = src && jQuery.isArray(src) ? src : [];
335
336 } else {
337 clone = src && jQuery.isPlainObject(src) ? src : {};
338 }
339
340 // Never move original objects, clone them
341 target[ name ] = jQuery.extend( deep, clone, copy );
342
343 // Don't bring in undefined values
344 } else if ( copy !== undefined ) {
345 target[ name ] = copy;
346 }
347 }
348 }
349 }
350
351 // Return the modified object
352 return target;
353 };
354
355 jQuery.extend({
356 noConflict: function( deep ) {
357 if ( window.$ === jQuery ) {
358 window.$ = _$;
359 }
360
361 if ( deep && window.jQuery === jQuery ) {
362 window.jQuery = _jQuery;
363 }
364
365 return jQuery;
366 },
367
368 // Is the DOM ready to be used? Set to true once it occurs.
369 isReady: false,
370
371 // A counter to track how many items to wait for before
372 // the ready event fires. See #6781
373 readyWait: 1,
374
375 // Hold (or release) the ready event
376 holdReady: function( hold ) {
377 if ( hold ) {
378 jQuery.readyWait++;
379 } else {
380 jQuery.ready( true );
381 }
382 },
383
384 // Handle when the DOM is ready
385 ready: function( wait ) {
386
387 // Abort if there are pending holds or we're already ready
388 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
389 return;
390 }
391
392 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
393 if ( !document.body ) {
394 return setTimeout( jQuery.ready, 1 );
395 }
396
397 // Remember that the DOM is ready
398 jQuery.isReady = true;
399
400 // If a normal DOM Ready event fired, decrement, and wait if need be
401 if ( wait !== true && --jQuery.readyWait > 0 ) {
402 return;
403 }
404
405 // If there are functions bound, to execute
406 readyList.resolveWith( document, [ jQuery ] );
407
408 // Trigger any bound ready events
409 if ( jQuery.fn.trigger ) {
410 jQuery( document ).trigger("ready").off("ready");
411 }
412 },
413
414 // See test/unit/core.js for details concerning isFunction.
415 // Since version 1.3, DOM methods and functions like alert
416 // aren't supported. They return false on IE (#2968).
417 isFunction: function( obj ) {
418 return jQuery.type(obj) === "function";
419 },
420
421 isArray: Array.isArray || function( obj ) {
422 return jQuery.type(obj) === "array";
423 },
424
425 isWindow: function( obj ) {
426 return obj != null && obj == obj.window;
427 },
428
429 isNumeric: function( obj ) {
430 return !isNaN( parseFloat(obj) ) && isFinite( obj );
431 },
432
433 type: function( obj ) {
434 return obj == null ?
435 String( obj ) :
436 class2type[ core_toString.call(obj) ] || "object";
437 },
438
439 isPlainObject: function( obj ) {
440 // Must be an Object.
441 // Because of IE, we also have to check the presence of the constructor property.
442 // Make sure that DOM nodes and window objects don't pass through, as well
443 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
444 return false;
445 }
446
447 try {
448 // Not own constructor property must be Object
449 if ( obj.constructor &&
450 !core_hasOwn.call(obj, "constructor") &&
451 !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
452 return false;
453 }
454 } catch ( e ) {
455 // IE8,9 Will throw exceptions on certain host objects #9897
456 return false;
457 }
458
459 // Own properties are enumerated firstly, so to speed up,
460 // if last one is own, then all properties are own.
461
462 var key;
463 for ( key in obj ) {}
464
465 return key === undefined || core_hasOwn.call( obj, key );
466 },
467
468 isEmptyObject: function( obj ) {
469 var name;
470 for ( name in obj ) {
471 return false;
472 }
473 return true;
474 },
475
476 error: function( msg ) {
477 throw new Error( msg );
478 },
479
480 // data: string of html
481 // context (optional): If specified, the fragment will be created in this context, defaults to document
482 // scripts (optional): If true, will include scripts passed in the html string
483 parseHTML: function( data, context, scripts ) {
484 var parsed;
485 if ( !data || typeof data !== "string" ) {
486 return null;
487 }
488 if ( typeof context === "boolean" ) {
489 scripts = context;
490 context = 0;
491 }
492 context = context || document;
493
494 // Single tag
495 if ( (parsed = rsingleTag.exec( data )) ) {
496 return [ context.createElement( parsed[1] ) ];
497 }
498
499 parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );
500 return jQuery.merge( [],
501 (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );
502 },
503
504 parseJSON: function( data ) {
505 if ( !data || typeof data !== "string") {
506 return null;
507 }
508
509 // Make sure leading/trailing whitespace is removed (IE can't handle it)
510 data = jQuery.trim( data );
511
512 // Attempt to parse using the native JSON parser first
513 if ( window.JSON && window.JSON.parse ) {
514 return window.JSON.parse( data );
515 }
516
517 // Make sure the incoming data is actual JSON
518 // Logic borrowed from http://json.org/json2.js
519 if ( rvalidchars.test( data.replace( rvalidescape, "@" )
520 .replace( rvalidtokens, "]" )
521 .replace( rvalidbraces, "")) ) {
522
523 return ( new Function( "return " + data ) )();
524
525 }
526 jQuery.error( "Invalid JSON: " + data );
527 },
528
529 // Cross-browser xml parsing
530 parseXML: function( data ) {
531 var xml, tmp;
532 if ( !data || typeof data !== "string" ) {
533 return null;
534 }
535 try {
536 if ( window.DOMParser ) { // Standard
537 tmp = new DOMParser();
538 xml = tmp.parseFromString( data , "text/xml" );
539 } else { // IE
540 xml = new ActiveXObject( "Microsoft.XMLDOM" );
541 xml.async = "false";
542 xml.loadXML( data );
543 }
544 } catch( e ) {
545 xml = undefined;
546 }
547 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
548 jQuery.error( "Invalid XML: " + data );
549 }
550 return xml;
551 },
552
553 noop: function() {},
554
555 // Evaluates a script in a global context
556 // Workarounds based on findings by Jim Driscoll
557 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
558 globalEval: function( data ) {
559 if ( data && core_rnotwhite.test( data ) ) {
560 // We use execScript on Internet Explorer
561 // We use an anonymous function so that context is window
562 // rather than jQuery in Firefox
563 ( window.execScript || function( data ) {
564 window[ "eval" ].call( window, data );
565 } )( data );
566 }
567 },
568
569 // Convert dashed to camelCase; used by the css and data modules
570 // Microsoft forgot to hump their vendor prefix (#9572)
571 camelCase: function( string ) {
572 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
573 },
574
575 nodeName: function( elem, name ) {
576 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
577 },
578
579 // args is for internal usage only
580 each: function( obj, callback, args ) {
581 var name,
582 i = 0,
583 length = obj.length,
584 isObj = length === undefined || jQuery.isFunction( obj );
585
586 if ( args ) {
587 if ( isObj ) {
588 for ( name in obj ) {
589 if ( callback.apply( obj[ name ], args ) === false ) {
590 break;
591 }
592 }
593 } else {
594 for ( ; i < length; ) {
595 if ( callback.apply( obj[ i++ ], args ) === false ) {
596 break;
597 }
598 }
599 }
600
601 // A special, fast, case for the most common use of each
602 } else {
603 if ( isObj ) {
604 for ( name in obj ) {
605 if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {
606 break;
607 }
608 }
609 } else {
610 for ( ; i < length; ) {
611 if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {
612 break;
613 }
614 }
615 }
616 }
617
618 return obj;
619 },
620
621 // Use native String.trim function wherever possible
622 trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
623 function( text ) {
624 return text == null ?
625 "" :
626 core_trim.call( text );
627 } :
628
629 // Otherwise use our own trimming functionality
630 function( text ) {
631 return text == null ?
632 "" :
633 ( text + "" ).replace( rtrim, "" );
634 },
635
636 // results is for internal usage only
637 makeArray: function( arr, results ) {
638 var type,
639 ret = results || [];
640
641 if ( arr != null ) {
642 // The window, strings (and functions) also have 'length'
643 // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
644 type = jQuery.type( arr );
645
646 if ( arr.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( arr ) ) {
647 core_push.call( ret, arr );
648 } else {
649 jQuery.merge( ret, arr );
650 }
651 }
652
653 return ret;
654 },
655
656 inArray: function( elem, arr, i ) {
657 var len;
658
659 if ( arr ) {
660 if ( core_indexOf ) {
661 return core_indexOf.call( arr, elem, i );
662 }
663
664 len = arr.length;
665 i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
666
667 for ( ; i < len; i++ ) {
668 // Skip accessing in sparse arrays
669 if ( i in arr && arr[ i ] === elem ) {
670 return i;
671 }
672 }
673 }
674
675 return -1;
676 },
677
678 merge: function( first, second ) {
679 var l = second.length,
680 i = first.length,
681 j = 0;
682
683 if ( typeof l === "number" ) {
684 for ( ; j < l; j++ ) {
685 first[ i++ ] = second[ j ];
686 }
687
688 } else {
689 while ( second[j] !== undefined ) {
690 first[ i++ ] = second[ j++ ];
691 }
692 }
693
694 first.length = i;
695
696 return first;
697 },
698
699 grep: function( elems, callback, inv ) {
700 var retVal,
701 ret = [],
702 i = 0,
703 length = elems.length;
704 inv = !!inv;
705
706 // Go through the array, only saving the items
707 // that pass the validator function
708 for ( ; i < length; i++ ) {
709 retVal = !!callback( elems[ i ], i );
710 if ( inv !== retVal ) {
711 ret.push( elems[ i ] );
712 }
713 }
714
715 return ret;
716 },
717
718 // arg is for internal usage only
719 map: function( elems, callback, arg ) {
720 var value, key,
721 ret = [],
722 i = 0,
723 length = elems.length,
724 // jquery objects are treated as arrays
725 isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
726
727 // Go through the array, translating each of the items to their
728 if ( isArray ) {
729 for ( ; i < length; i++ ) {
730 value = callback( elems[ i ], i, arg );
731
732 if ( value != null ) {
733 ret[ ret.length ] = value;
734 }
735 }
736
737 // Go through every key on the object,
738 } else {
739 for ( key in elems ) {
740 value = callback( elems[ key ], key, arg );
741
742 if ( value != null ) {
743 ret[ ret.length ] = value;
744 }
745 }
746 }
747
748 // Flatten any nested arrays
749 return ret.concat.apply( [], ret );
750 },
751
752 // A global GUID counter for objects
753 guid: 1,
754
755 // Bind a function to a context, optionally partially applying any
756 // arguments.
757 proxy: function( fn, context ) {
758 var tmp, args, proxy;
759
760 if ( typeof context === "string" ) {
761 tmp = fn[ context ];
762 context = fn;
763 fn = tmp;
764 }
765
766 // Quick check to determine if target is callable, in the spec
767 // this throws a TypeError, but we will just return undefined.
768 if ( !jQuery.isFunction( fn ) ) {
769 return undefined;
770 }
771
772 // Simulated bind
773 args = core_slice.call( arguments, 2 );
774 proxy = function() {
775 return fn.apply( context, args.concat( core_slice.call( arguments ) ) );
776 };
777
778 // Set the guid of unique handler to the same of original handler, so it can be removed
779 proxy.guid = fn.guid = fn.guid || jQuery.guid++;
780
781 return proxy;
782 },
783
784 // Multifunctional method to get and set values of a collection
785 // The value/s can optionally be executed if it's a function
786 access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
787 var exec,
788 bulk = key == null,
789 i = 0,
790 length = elems.length;
791
792 // Sets many values
793 if ( key && typeof key === "object" ) {
794 for ( i in key ) {
795 jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
796 }
797 chainable = 1;
798
799 // Sets one value
800 } else if ( value !== undefined ) {
801 // Optionally, function values get executed if exec is true
802 exec = pass === undefined && jQuery.isFunction( value );
803
804 if ( bulk ) {
805 // Bulk operations only iterate when executing function values
806 if ( exec ) {
807 exec = fn;
808 fn = function( elem, key, value ) {
809 return exec.call( jQuery( elem ), value );
810 };
811
812 // Otherwise they run against the entire set
813 } else {
814 fn.call( elems, value );
815 fn = null;
816 }
817 }
818
819 if ( fn ) {
820 for (; i < length; i++ ) {
821 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
822 }
823 }
824
825 chainable = 1;
826 }
827
828 return chainable ?
829 elems :
830
831 // Gets
832 bulk ?
833 fn.call( elems ) :
834 length ? fn( elems[0], key ) : emptyGet;
835 },
836
837 now: function() {
838 return ( new Date() ).getTime();
839 }
840 });
841
842 jQuery.ready.promise = function( obj ) {
843 if ( !readyList ) {
844
845 readyList = jQuery.Deferred();
846
847 // Catch cases where $(document).ready() is called after the browser event has already occurred.
848 // we once tried to use readyState "interactive" here, but it caused issues like the one
849 // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
850 if ( document.readyState === "complete" ) {
851 // Handle it asynchronously to allow scripts the opportunity to delay ready
852 setTimeout( jQuery.ready, 1 );
853
854 // Standards-based browsers support DOMContentLoaded
855 } else if ( document.addEventListener ) {
856 // Use the handy event callback
857 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
858
859 // A fallback to window.onload, that will always work
860 window.addEventListener( "load", jQuery.ready, false );
861
862 // If IE event model is used
863 } else {
864 // Ensure firing before onload, maybe late but safe also for iframes
865 document.attachEvent( "onreadystatechange", DOMContentLoaded );
866
867 // A fallback to window.onload, that will always work
868 window.attachEvent( "onload", jQuery.ready );
869
870 // If IE and not a frame
871 // continually check to see if the document is ready
872 var top = false;
873
874 try {
875 top = window.frameElement == null && document.documentElement;
876 } catch(e) {}
877
878 if ( top && top.doScroll ) {
879 (function doScrollCheck() {
880 if ( !jQuery.isReady ) {
881
882 try {
883 // Use the trick by Diego Perini
884 // http://javascript.nwbox.com/IEContentLoaded/
885 top.doScroll("left");
886 } catch(e) {
887 return setTimeout( doScrollCheck, 50 );
888 }
889
890 // and execute any waiting functions
891 jQuery.ready();
892 }
893 })();
894 }
895 }
896 }
897 return readyList.promise( obj );
898 };
899
900 // Populate the class2type map
901 jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
902 class2type[ "[object " + name + "]" ] = name.toLowerCase();
903 });
904
905 // All jQuery objects should point back to these
906 rootjQuery = jQuery(document);
907 // String to Object options format cache
908 var optionsCache = {};
909
910 // Convert String-formatted options into Object-formatted ones and store in cache
911 function createOptions( options ) {
912 var object = optionsCache[ options ] = {};
913 jQuery.each( options.split( core_rspace ), function( _, flag ) {
914 object[ flag ] = true;
915 });
916 return object;
917 }
918
919 /*
920 * Create a callback list using the following parameters:
921 *
922 * options: an optional list of space-separated options that will change how
923 * the callback list behaves or a more traditional option object
924 *
925 * By default a callback list will act like an event callback list and can be
926 * "fired" multiple times.
927 *
928 * Possible options:
929 *
930 * once: will ensure the callback list can only be fired once (like a Deferred)
931 *
932 * memory: will keep track of previous values and will call any callback added
933 * after the list has been fired right away with the latest "memorized"
934 * values (like a Deferred)
935 *
936 * unique: will ensure a callback can only be added once (no duplicate in the list)
937 *
938 * stopOnFalse: interrupt callings when a callback returns false
939 *
940 */
941 jQuery.Callbacks = function( options ) {
942
943 // Convert options from String-formatted to Object-formatted if needed
944 // (we check in cache first)
945 options = typeof options === "string" ?
946 ( optionsCache[ options ] || createOptions( options ) ) :
947 jQuery.extend( {}, options );
948
949 var // Last fire value (for non-forgettable lists)
950 memory,
951 // Flag to know if list was already fired
952 fired,
953 // Flag to know if list is currently firing
954 firing,
955 // First callback to fire (used internally by add and fireWith)
956 firingStart,
957 // End of the loop when firing
958 firingLength,
959 // Index of currently firing callback (modified by remove if needed)
960 firingIndex,
961 // Actual callback list
962 list = [],
963 // Stack of fire calls for repeatable lists
964 stack = !options.once && [],
965 // Fire callbacks
966 fire = function( data ) {
967 memory = options.memory && data;
968 fired = true;
969 firingIndex = firingStart || 0;
970 firingStart = 0;
971 firingLength = list.length;
972 firing = true;
973 for ( ; list && firingIndex < firingLength; firingIndex++ ) {
974 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
975 memory = false; // To prevent further calls using add
976 break;
977 }
978 }
979 firing = false;
980 if ( list ) {
981 if ( stack ) {
982 if ( stack.length ) {
983 fire( stack.shift() );
984 }
985 } else if ( memory ) {
986 list = [];
987 } else {
988 self.disable();
989 }
990 }
991 },
992 // Actual Callbacks object
993 self = {
994 // Add a callback or a collection of callbacks to the list
995 add: function() {
996 if ( list ) {
997 // First, we save the current length
998 var start = list.length;
999 (function add( args ) {
1000 jQuery.each( args, function( _, arg ) {
1001 var type = jQuery.type( arg );
1002 if ( type === "function" ) {
1003 if ( !options.unique || !self.has( arg ) ) {
1004 list.push( arg );
1005 }
1006 } else if ( arg && arg.length && type !== "string" ) {
1007 // Inspect recursively
1008 add( arg );
1009 }
1010 });
1011 })( arguments );
1012 // Do we need to add the callbacks to the
1013 // current firing batch?
1014 if ( firing ) {
1015 firingLength = list.length;
1016 // With memory, if we're not firing then
1017 // we should call right away
1018 } else if ( memory ) {
1019 firingStart = start;
1020 fire( memory );
1021 }
1022 }
1023 return this;
1024 },
1025 // Remove a callback from the list
1026 remove: function() {
1027 if ( list ) {
1028 jQuery.each( arguments, function( _, arg ) {
1029 var index;
1030 while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
1031 list.splice( index, 1 );
1032 // Handle firing indexes
1033 if ( firing ) {
1034 if ( index <= firingLength ) {
1035 firingLength--;
1036 }
1037 if ( index <= firingIndex ) {
1038 firingIndex--;
1039 }
1040 }
1041 }
1042 });
1043 }
1044 return this;
1045 },
1046 // Control if a given callback is in the list
1047 has: function( fn ) {
1048 return jQuery.inArray( fn, list ) > -1;
1049 },
1050 // Remove all callbacks from the list
1051 empty: function() {
1052 list = [];
1053 return this;
1054 },
1055 // Have the list do nothing anymore
1056 disable: function() {
1057 list = stack = memory = undefined;
1058 return this;
1059 },
1060 // Is it disabled?
1061 disabled: function() {
1062 return !list;
1063 },
1064 // Lock the list in its current state
1065 lock: function() {
1066 stack = undefined;
1067 if ( !memory ) {
1068 self.disable();
1069 }
1070 return this;
1071 },
1072 // Is it locked?
1073 locked: function() {
1074 return !stack;
1075 },
1076 // Call all callbacks with the given context and arguments
1077 fireWith: function( context, args ) {
1078 args = args || [];
1079 args = [ context, args.slice ? args.slice() : args ];
1080 if ( list && ( !fired || stack ) ) {
1081 if ( firing ) {
1082 stack.push( args );
1083 } else {
1084 fire( args );
1085 }
1086 }
1087 return this;
1088 },
1089 // Call all the callbacks with the given arguments
1090 fire: function() {
1091 self.fireWith( this, arguments );
1092 return this;
1093 },
1094 // To know if the callbacks have already been called at least once
1095 fired: function() {
1096 return !!fired;
1097 }
1098 };
1099
1100 return self;
1101 };
1102 jQuery.extend({
1103
1104 Deferred: function( func ) {
1105 var tuples = [
1106 // action, add listener, listener list, final state
1107 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
1108 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
1109 [ "notify", "progress", jQuery.Callbacks("memory") ]
1110 ],
1111 state = "pending",
1112 promise = {
1113 state: function() {
1114 return state;
1115 },
1116 always: function() {
1117 deferred.done( arguments ).fail( arguments );
1118 return this;
1119 },
1120 then: function( /* fnDone, fnFail, fnProgress */ ) {
1121 var fns = arguments;
1122 return jQuery.Deferred(function( newDefer ) {
1123 jQuery.each( tuples, function( i, tuple ) {
1124 var action = tuple[ 0 ],
1125 fn = fns[ i ];
1126 // deferred[ done | fail | progress ] for forwarding actions to newDefer
1127 deferred[ tuple[1] ]( jQuery.isFunction( fn ) ?
1128 function() {
1129 var returned = fn.apply( this, arguments );
1130 if ( returned && jQuery.isFunction( returned.promise ) ) {
1131 returned.promise()
1132 .done( newDefer.resolve )
1133 .fail( newDefer.reject )
1134 .progress( newDefer.notify );
1135 } else {
1136 newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
1137 }
1138 } :
1139 newDefer[ action ]
1140 );
1141 });
1142 fns = null;
1143 }).promise();
1144 },
1145 // Get a promise for this deferred
1146 // If obj is provided, the promise aspect is added to the object
1147 promise: function( obj ) {
1148 return obj != null ? jQuery.extend( obj, promise ) : promise;
1149 }
1150 },
1151 deferred = {};
1152
1153 // Keep pipe for back-compat
1154 promise.pipe = promise.then;
1155
1156 // Add list-specific methods
1157 jQuery.each( tuples, function( i, tuple ) {
1158 var list = tuple[ 2 ],
1159 stateString = tuple[ 3 ];
1160
1161 // promise[ done | fail | progress ] = list.add
1162 promise[ tuple[1] ] = list.add;
1163
1164 // Handle state
1165 if ( stateString ) {
1166 list.add(function() {
1167 // state = [ resolved | rejected ]
1168 state = stateString;
1169
1170 // [ reject_list | resolve_list ].disable; progress_list.lock
1171 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
1172 }
1173
1174 // deferred[ resolve | reject | notify ] = list.fire
1175 deferred[ tuple[0] ] = list.fire;
1176 deferred[ tuple[0] + "With" ] = list.fireWith;
1177 });
1178
1179 // Make the deferred a promise
1180 promise.promise( deferred );
1181
1182 // Call given func if any
1183 if ( func ) {
1184 func.call( deferred, deferred );
1185 }
1186
1187 // All done!
1188 return deferred;
1189 },
1190
1191 // Deferred helper
1192 when: function( subordinate /* , ..., subordinateN */ ) {
1193 var i = 0,
1194 resolveValues = core_slice.call( arguments ),
1195 length = resolveValues.length,
1196
1197 // the count of uncompleted subordinates
1198 remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
1199
1200 // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
1201 deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
1202
1203 // Update function for both resolve and progress values
1204 updateFunc = function( i, contexts, values ) {
1205 return function( value ) {
1206 contexts[ i ] = this;
1207 values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
1208 if( values === progressValues ) {
1209 deferred.notifyWith( contexts, values );
1210 } else if ( !( --remaining ) ) {
1211 deferred.resolveWith( contexts, values );
1212 }
1213 };
1214 },
1215
1216 progressValues, progressContexts, resolveContexts;
1217
1218 // add listeners to Deferred subordinates; treat others as resolved
1219 if ( length > 1 ) {
1220 progressValues = new Array( length );
1221 progressContexts = new Array( length );
1222 resolveContexts = new Array( length );
1223 for ( ; i < length; i++ ) {
1224 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
1225 resolveValues[ i ].promise()
1226 .done( updateFunc( i, resolveContexts, resolveValues ) )
1227 .fail( deferred.reject )
1228 .progress( updateFunc( i, progressContexts, progressValues ) );
1229 } else {
1230 --remaining;
1231 }
1232 }
1233 }
1234
1235 // if we're not waiting on anything, resolve the master
1236 if ( !remaining ) {
1237 deferred.resolveWith( resolveContexts, resolveValues );
1238 }
1239
1240 return deferred.promise();
1241 }
1242 });
1243 jQuery.support = (function() {
1244
1245 var support,
1246 all,
1247 a,
1248 select,
1249 opt,
1250 input,
1251 fragment,
1252 eventName,
1253 i,
1254 isSupported,
1255 clickFn,
1256 div = document.createElement("div");
1257
1258 // Setup
1259 div.setAttribute( "className", "t" );
1260 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
1261
1262 // Support tests won't run in some limited or non-browser environments
1263 all = div.getElementsByTagName("*");
1264 a = div.getElementsByTagName("a")[ 0 ];
1265 if ( !all || !a || !all.length ) {
1266 return {};
1267 }
1268
1269 // First batch of tests
1270 select = document.createElement("select");
1271 opt = select.appendChild( document.createElement("option") );
1272 input = div.getElementsByTagName("input")[ 0 ];
1273
1274 a.style.cssText = "top:1px;float:left;opacity:.5";
1275 support = {
1276 // IE strips leading whitespace when .innerHTML is used
1277 leadingWhitespace: ( div.firstChild.nodeType === 3 ),
1278
1279 // Make sure that tbody elements aren't automatically inserted
1280 // IE will insert them into empty tables
1281 tbody: !div.getElementsByTagName("tbody").length,
1282
1283 // Make sure that link elements get serialized correctly by innerHTML
1284 // This requires a wrapper element in IE
1285 htmlSerialize: !!div.getElementsByTagName("link").length,
1286
1287 // Get the style information from getAttribute
1288 // (IE uses .cssText instead)
1289 style: /top/.test( a.getAttribute("style") ),
1290
1291 // Make sure that URLs aren't manipulated
1292 // (IE normalizes it by default)
1293 hrefNormalized: ( a.getAttribute("href") === "/a" ),
1294
1295 // Make sure that element opacity exists
1296 // (IE uses filter instead)
1297 // Use a regex to work around a WebKit issue. See #5145
1298 opacity: /^0.5/.test( a.style.opacity ),
1299
1300 // Verify style float existence
1301 // (IE uses styleFloat instead of cssFloat)
1302 cssFloat: !!a.style.cssFloat,
1303
1304 // Make sure that if no value is specified for a checkbox
1305 // that it defaults to "on".
1306 // (WebKit defaults to "" instead)
1307 checkOn: ( input.value === "on" ),
1308
1309 // Make sure that a selected-by-default option has a working selected property.
1310 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1311 optSelected: opt.selected,
1312
1313 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
1314 getSetAttribute: div.className !== "t",
1315
1316 // Tests for enctype support on a form (#6743)
1317 enctype: !!document.createElement("form").enctype,
1318
1319 // Makes sure cloning an html5 element does not cause problems
1320 // Where outerHTML is undefined, this still works
1321 html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
1322
1323 // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
1324 boxModel: ( document.compatMode === "CSS1Compat" ),
1325
1326 // Will be defined later
1327 submitBubbles: true,
1328 changeBubbles: true,
1329 focusinBubbles: false,
1330 deleteExpando: true,
1331 noCloneEvent: true,
1332 inlineBlockNeedsLayout: false,
1333 shrinkWrapBlocks: false,
1334 reliableMarginRight: true,
1335 boxSizingReliable: true,
1336 pixelPosition: false
1337 };
1338
1339 // Make sure checked status is properly cloned
1340 input.checked = true;
1341 support.noCloneChecked = input.cloneNode( true ).checked;
1342
1343 // Make sure that the options inside disabled selects aren't marked as disabled
1344 // (WebKit marks them as disabled)
1345 select.disabled = true;
1346 support.optDisabled = !opt.disabled;
1347
1348 // Test to see if it's possible to delete an expando from an element
1349 // Fails in Internet Explorer
1350 try {
1351 delete div.test;
1352 } catch( e ) {
1353 support.deleteExpando = false;
1354 }
1355
1356 if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
1357 div.attachEvent( "onclick", clickFn = function() {
1358 // Cloning a node shouldn't copy over any
1359 // bound event handlers (IE does this)
1360 support.noCloneEvent = false;
1361 });
1362 div.cloneNode( true ).fireEvent("onclick");
1363 div.detachEvent( "onclick", clickFn );
1364 }
1365
1366 // Check if a radio maintains its value
1367 // after being appended to the DOM
1368 input = document.createElement("input");
1369 input.value = "t";
1370 input.setAttribute( "type", "radio" );
1371 support.radioValue = input.value === "t";
1372
1373 input.setAttribute( "checked", "checked" );
1374
1375 // #11217 - WebKit loses check when the name is after the checked attribute
1376 input.setAttribute( "name", "t" );
1377
1378 div.appendChild( input );
1379 fragment = document.createDocumentFragment();
1380 fragment.appendChild( div.lastChild );
1381
1382 // WebKit doesn't clone checked state correctly in fragments
1383 support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
1384
1385 // Check if a disconnected checkbox will retain its checked
1386 // value of true after appended to the DOM (IE6/7)
1387 support.appendChecked = input.checked;
1388
1389 fragment.removeChild( input );
1390 fragment.appendChild( div );
1391
1392 // Technique from Juriy Zaytsev
1393 // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
1394 // We only care about the case where non-standard event systems
1395 // are used, namely in IE. Short-circuiting here helps us to
1396 // avoid an eval call (in setAttribute) which can cause CSP
1397 // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
1398 if ( div.attachEvent ) {
1399 for ( i in {
1400 submit: true,
1401 change: true,
1402 focusin: true
1403 }) {
1404 eventName = "on" + i;
1405 isSupported = ( eventName in div );
1406 if ( !isSupported ) {
1407 div.setAttribute( eventName, "return;" );
1408 isSupported = ( typeof div[ eventName ] === "function" );
1409 }
1410 support[ i + "Bubbles" ] = isSupported;
1411 }
1412 }
1413
1414 // Run tests that need a body at doc ready
1415 jQuery(function() {
1416 var container, div, tds, marginDiv,
1417 divReset = "padding:0;margin:0;border:0;display:block;overflow:hidden;",
1418 body = document.getElementsByTagName("body")[0];
1419
1420 if ( !body ) {
1421 // Return for frameset docs that don't have a body
1422 return;
1423 }
1424
1425 container = document.createElement("div");
1426 container.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px";
1427 body.insertBefore( container, body.firstChild );
1428
1429 // Construct the test element
1430 div = document.createElement("div");
1431 container.appendChild( div );
1432
1433 // Check if table cells still have offsetWidth/Height when they are set
1434 // to display:none and there are still other visible table cells in a
1435 // table row; if so, offsetWidth/Height are not reliable for use when
1436 // determining if an element has been hidden directly using
1437 // display:none (it is still safe to use offsets if a parent element is
1438 // hidden; don safety goggles and see bug #4512 for more information).
1439 // (only IE 8 fails this test)
1440 div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
1441 tds = div.getElementsByTagName("td");
1442 tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
1443 isSupported = ( tds[ 0 ].offsetHeight === 0 );
1444
1445 tds[ 0 ].style.display = "";
1446 tds[ 1 ].style.display = "none";
1447
1448 // Check if empty table cells still have offsetWidth/Height
1449 // (IE <= 8 fail this test)
1450 support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
1451
1452 // Check box-sizing and margin behavior
1453 div.innerHTML = "";
1454 div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
1455 support.boxSizing = ( div.offsetWidth === 4 );
1456 support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
1457
1458 // NOTE: To any future maintainer, we've window.getComputedStyle
1459 // because jsdom on node.js will break without it.
1460 if ( window.getComputedStyle ) {
1461 support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
1462 support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
1463
1464 // Check if div with explicit width and no margin-right incorrectly
1465 // gets computed margin-right based on width of container. For more
1466 // info see bug #3333
1467 // Fails in WebKit before Feb 2011 nightlies
1468 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
1469 marginDiv = document.createElement("div");
1470 marginDiv.style.cssText = div.style.cssText = divReset;
1471 marginDiv.style.marginRight = marginDiv.style.width = "0";
1472 div.style.width = "1px";
1473 div.appendChild( marginDiv );
1474 support.reliableMarginRight =
1475 !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
1476 }
1477
1478 if ( typeof div.style.zoom !== "undefined" ) {
1479 // Check if natively block-level elements act like inline-block
1480 // elements when setting their display to 'inline' and giving
1481 // them layout
1482 // (IE < 8 does this)
1483 div.innerHTML = "";
1484 div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
1485 support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
1486
1487 // Check if elements with layout shrink-wrap their children
1488 // (IE 6 does this)
1489 div.style.display = "block";
1490 div.style.overflow = "visible";
1491 div.innerHTML = "<div></div>";
1492 div.firstChild.style.width = "5px";
1493 support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
1494
1495 container.style.zoom = 1;
1496 }
1497
1498 // Null elements to avoid leaks in IE
1499 body.removeChild( container );
1500 container = div = tds = marginDiv = null;
1501 });
1502
1503 // Null elements to avoid leaks in IE
1504 fragment.removeChild( div );
1505 all = a = select = opt = input = fragment = div = null;
1506
1507 return support;
1508 })();
1509 var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
1510 rmultiDash = /([A-Z])/g;
1511
1512 jQuery.extend({
1513 cache: {},
1514
1515 deletedIds: [],
1516
1517 // Remove at next major release (1.9/2.0)
1518 uuid: 0,
1519
1520 // Unique for each copy of jQuery on the page
1521 // Non-digits removed to match rinlinejQuery
1522 expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
1523
1524 // The following elements throw uncatchable exceptions if you
1525 // attempt to add expando properties to them.
1526 noData: {
1527 "embed": true,
1528 // Ban all objects except for Flash (which handle expandos)
1529 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
1530 "applet": true
1531 },
1532
1533 hasData: function( elem ) {
1534 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
1535 return !!elem && !isEmptyDataObject( elem );
1536 },
1537
1538 data: function( elem, name, data, pvt /* Internal Use Only */ ) {
1539 if ( !jQuery.acceptData( elem ) ) {
1540 return;
1541 }
1542
1543 var thisCache, ret,
1544 internalKey = jQuery.expando,
1545 getByName = typeof name === "string",
1546
1547 // We have to handle DOM nodes and JS objects differently because IE6-7
1548 // can't GC object references properly across the DOM-JS boundary
1549 isNode = elem.nodeType,
1550
1551 // Only DOM nodes need the global jQuery cache; JS object data is
1552 // attached directly to the object so GC can occur automatically
1553 cache = isNode ? jQuery.cache : elem,
1554
1555 // Only defining an ID for JS objects if its cache already exists allows
1556 // the code to shortcut on the same path as a DOM node with no cache
1557 id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
1558
1559 // Avoid doing any more work than we need to when trying to get data on an
1560 // object that has no data at all
1561 if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
1562 return;
1563 }
1564
1565 if ( !id ) {
1566 // Only DOM nodes need a new unique ID for each element since their data
1567 // ends up in the global cache
1568 if ( isNode ) {
1569 elem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++;
1570 } else {
1571 id = internalKey;
1572 }
1573 }
1574
1575 if ( !cache[ id ] ) {
1576 cache[ id ] = {};
1577
1578 // Avoids exposing jQuery metadata on plain JS objects when the object
1579 // is serialized using JSON.stringify
1580 if ( !isNode ) {
1581 cache[ id ].toJSON = jQuery.noop;
1582 }
1583 }
1584
1585 // An object can be passed to jQuery.data instead of a key/value pair; this gets
1586 // shallow copied over onto the existing cache
1587 if ( typeof name === "object" || typeof name === "function" ) {
1588 if ( pvt ) {
1589 cache[ id ] = jQuery.extend( cache[ id ], name );
1590 } else {
1591 cache[ id ].data = jQuery.extend( cache[ id ].data, name );
1592 }
1593 }
1594
1595 thisCache = cache[ id ];
1596
1597 // jQuery data() is stored in a separate object inside the object's internal data
1598 // cache in order to avoid key collisions between internal data and user-defined
1599 // data.
1600 if ( !pvt ) {
1601 if ( !thisCache.data ) {
1602 thisCache.data = {};
1603 }
1604
1605 thisCache = thisCache.data;
1606 }
1607
1608 if ( data !== undefined ) {
1609 thisCache[ jQuery.camelCase( name ) ] = data;
1610 }
1611
1612 // Check for both converted-to-camel and non-converted data property names
1613 // If a data property was specified
1614 if ( getByName ) {
1615
1616 // First Try to find as-is property data
1617 ret = thisCache[ name ];
1618
1619 // Test for null|undefined property data
1620 if ( ret == null ) {
1621
1622 // Try to find the camelCased property
1623 ret = thisCache[ jQuery.camelCase( name ) ];
1624 }
1625 } else {
1626 ret = thisCache;
1627 }
1628
1629 return ret;
1630 },
1631
1632 removeData: function( elem, name, pvt /* Internal Use Only */ ) {
1633 if ( !jQuery.acceptData( elem ) ) {
1634 return;
1635 }
1636
1637 var thisCache, i, l,
1638
1639 isNode = elem.nodeType,
1640
1641 // See jQuery.data for more information
1642 cache = isNode ? jQuery.cache : elem,
1643 id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
1644
1645 // If there is already no cache entry for this object, there is no
1646 // purpose in continuing
1647 if ( !cache[ id ] ) {
1648 return;
1649 }
1650
1651 if ( name ) {
1652
1653 thisCache = pvt ? cache[ id ] : cache[ id ].data;
1654
1655 if ( thisCache ) {
1656
1657 // Support array or space separated string names for data keys
1658 if ( !jQuery.isArray( name ) ) {
1659
1660 // try the string as a key before any manipulation
1661 if ( name in thisCache ) {
1662 name = [ name ];
1663 } else {
1664
1665 // split the camel cased version by spaces unless a key with the spaces exists
1666 name = jQuery.camelCase( name );
1667 if ( name in thisCache ) {
1668 name = [ name ];
1669 } else {
1670 name = name.split(" ");
1671 }
1672 }
1673 }
1674
1675 for ( i = 0, l = name.length; i < l; i++ ) {
1676 delete thisCache[ name[i] ];
1677 }
1678
1679 // If there is no data left in the cache, we want to continue
1680 // and let the cache object itself get destroyed
1681 if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
1682 return;
1683 }
1684 }
1685 }
1686
1687 // See jQuery.data for more information
1688 if ( !pvt ) {
1689 delete cache[ id ].data;
1690
1691 // Don't destroy the parent cache unless the internal data object
1692 // had been the only thing left in it
1693 if ( !isEmptyDataObject( cache[ id ] ) ) {
1694 return;
1695 }
1696 }
1697
1698 // Destroy the cache
1699 if ( isNode ) {
1700 jQuery.cleanData( [ elem ], true );
1701
1702 // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
1703 } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
1704 delete cache[ id ];
1705
1706 // When all else fails, null
1707 } else {
1708 cache[ id ] = null;
1709 }
1710 },
1711
1712 // For internal use only.
1713 _data: function( elem, name, data ) {
1714 return jQuery.data( elem, name, data, true );
1715 },
1716
1717 // A method for determining if a DOM node can handle the data expando
1718 acceptData: function( elem ) {
1719 var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
1720
1721 // nodes accept data unless otherwise specified; rejection can be conditional
1722 return !noData || noData !== true && elem.getAttribute("classid") === noData;
1723 }
1724 });
1725
1726 jQuery.fn.extend({
1727 data: function( key, value ) {
1728 var parts, part, attr, name, l,
1729 elem = this[0],
1730 i = 0,
1731 data = null;
1732
1733 // Gets all values
1734 if ( key === undefined ) {
1735 if ( this.length ) {
1736 data = jQuery.data( elem );
1737
1738 if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
1739 attr = elem.attributes;
1740 for ( l = attr.length; i < l; i++ ) {
1741 name = attr[i].name;
1742
1743 if ( !name.indexOf( "data-" ) ) {
1744 name = jQuery.camelCase( name.substring(5) );
1745
1746 dataAttr( elem, name, data[ name ] );
1747 }
1748 }
1749 jQuery._data( elem, "parsedAttrs", true );
1750 }
1751 }
1752
1753 return data;
1754 }
1755
1756 // Sets multiple values
1757 if ( typeof key === "object" ) {
1758 return this.each(function() {
1759 jQuery.data( this, key );
1760 });
1761 }
1762
1763 parts = key.split( ".", 2 );
1764 parts[1] = parts[1] ? "." + parts[1] : "";
1765 part = parts[1] + "!";
1766
1767 return jQuery.access( this, function( value ) {
1768
1769 if ( value === undefined ) {
1770 data = this.triggerHandler( "getData" + part, [ parts[0] ] );
1771
1772 // Try to fetch any internally stored data first
1773 if ( data === undefined && elem ) {
1774 data = jQuery.data( elem, key );
1775 data = dataAttr( elem, key, data );
1776 }
1777
1778 return data === undefined && parts[1] ?
1779 this.data( parts[0] ) :
1780 data;
1781 }
1782
1783 parts[1] = value;
1784 this.each(function() {
1785 var self = jQuery( this );
1786
1787 self.triggerHandler( "setData" + part, parts );
1788 jQuery.data( this, key, value );
1789 self.triggerHandler( "changeData" + part, parts );
1790 });
1791 }, null, value, arguments.length > 1, null, false );
1792 },
1793
1794 removeData: function( key ) {
1795 return this.each(function() {
1796 jQuery.removeData( this, key );
1797 });
1798 }
1799 });
1800
1801 function dataAttr( elem, key, data ) {
1802 // If nothing was found internally, try to fetch any
1803 // data from the HTML5 data-* attribute
1804 if ( data === undefined && elem.nodeType === 1 ) {
1805
1806 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
1807
1808 data = elem.getAttribute( name );
1809
1810 if ( typeof data === "string" ) {
1811 try {
1812 data = data === "true" ? true :
1813 data === "false" ? false :
1814 data === "null" ? null :
1815 // Only convert to a number if it doesn't change the string
1816 +data + "" === data ? +data :
1817 rbrace.test( data ) ? jQuery.parseJSON( data ) :
1818 data;
1819 } catch( e ) {}
1820
1821 // Make sure we set the data so it isn't changed later
1822 jQuery.data( elem, key, data );
1823
1824 } else {
1825 data = undefined;
1826 }
1827 }
1828
1829 return data;
1830 }
1831
1832 // checks a cache object for emptiness
1833 function isEmptyDataObject( obj ) {
1834 var name;
1835 for ( name in obj ) {
1836
1837 // if the public data object is empty, the private is still empty
1838 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
1839 continue;
1840 }
1841 if ( name !== "toJSON" ) {
1842 return false;
1843 }
1844 }
1845
1846 return true;
1847 }
1848 jQuery.extend({
1849 queue: function( elem, type, data ) {
1850 var queue;
1851
1852 if ( elem ) {
1853 type = ( type || "fx" ) + "queue";
1854 queue = jQuery._data( elem, type );
1855
1856 // Speed up dequeue by getting out quickly if this is just a lookup
1857 if ( data ) {
1858 if ( !queue || jQuery.isArray(data) ) {
1859 queue = jQuery._data( elem, type, jQuery.makeArray(data) );
1860 } else {
1861 queue.push( data );
1862 }
1863 }
1864 return queue || [];
1865 }
1866 },
1867
1868 dequeue: function( elem, type ) {
1869 type = type || "fx";
1870
1871 var queue = jQuery.queue( elem, type ),
1872 startLength = queue.length,
1873 fn = queue.shift(),
1874 hooks = jQuery._queueHooks( elem, type ),
1875 next = function() {
1876 jQuery.dequeue( elem, type );
1877 };
1878
1879 // If the fx queue is dequeued, always remove the progress sentinel
1880 if ( fn === "inprogress" ) {
1881 fn = queue.shift();
1882 startLength--;
1883 }
1884
1885 if ( fn ) {
1886
1887 // Add a progress sentinel to prevent the fx queue from being
1888 // automatically dequeued
1889 if ( type === "fx" ) {
1890 queue.unshift( "inprogress" );
1891 }
1892
1893 // clear up the last queue stop function
1894 delete hooks.stop;
1895 fn.call( elem, next, hooks );
1896 }
1897
1898 if ( !startLength && hooks ) {
1899 hooks.empty.fire();
1900 }
1901 },
1902
1903 // not intended for public consumption - generates a queueHooks object, or returns the current one
1904 _queueHooks: function( elem, type ) {
1905 var key = type + "queueHooks";
1906 return jQuery._data( elem, key ) || jQuery._data( elem, key, {
1907 empty: jQuery.Callbacks("once memory").add(function() {
1908 jQuery.removeData( elem, type + "queue", true );
1909 jQuery.removeData( elem, key, true );
1910 })
1911 });
1912 }
1913 });
1914
1915 jQuery.fn.extend({
1916 queue: function( type, data ) {
1917 var setter = 2;
1918
1919 if ( typeof type !== "string" ) {
1920 data = type;
1921 type = "fx";
1922 setter--;
1923 }
1924
1925 if ( arguments.length < setter ) {
1926 return jQuery.queue( this[0], type );
1927 }
1928
1929 return data === undefined ?
1930 this :
1931 this.each(function() {
1932 var queue = jQuery.queue( this, type, data );
1933
1934 // ensure a hooks for this queue
1935 jQuery._queueHooks( this, type );
1936
1937 if ( type === "fx" && queue[0] !== "inprogress" ) {
1938 jQuery.dequeue( this, type );
1939 }
1940 });
1941 },
1942 dequeue: function( type ) {
1943 return this.each(function() {
1944 jQuery.dequeue( this, type );
1945 });
1946 },
1947 // Based off of the plugin by Clint Helfers, with permission.
1948 // http://blindsignals.com/index.php/2009/07/jquery-delay/
1949 delay: function( time, type ) {
1950 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
1951 type = type || "fx";
1952
1953 return this.queue( type, function( next, hooks ) {
1954 var timeout = setTimeout( next, time );
1955 hooks.stop = function() {
1956 clearTimeout( timeout );
1957 };
1958 });
1959 },
1960 clearQueue: function( type ) {
1961 return this.queue( type || "fx", [] );
1962 },
1963 // Get a promise resolved when queues of a certain type
1964 // are emptied (fx is the type by default)
1965 promise: function( type, obj ) {
1966 var tmp,
1967 count = 1,
1968 defer = jQuery.Deferred(),
1969 elements = this,
1970 i = this.length,
1971 resolve = function() {
1972 if ( !( --count ) ) {
1973 defer.resolveWith( elements, [ elements ] );
1974 }
1975 };
1976
1977 if ( typeof type !== "string" ) {
1978 obj = type;
1979 type = undefined;
1980 }
1981 type = type || "fx";
1982
1983 while( i-- ) {
1984 tmp = jQuery._data( elements[ i ], type + "queueHooks" );
1985 if ( tmp && tmp.empty ) {
1986 count++;
1987 tmp.empty.add( resolve );
1988 }
1989 }
1990 resolve();
1991 return defer.promise( obj );
1992 }
1993 });
1994 var nodeHook, boolHook, fixSpecified,
1995 rclass = /[\t\r\n]/g,
1996 rreturn = /\r/g,
1997 rtype = /^(?:button|input)$/i,
1998 rfocusable = /^(?:button|input|object|select|textarea)$/i,
1999 rclickable = /^a(?:rea|)$/i,
2000 rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
2001 getSetAttribute = jQuery.support.getSetAttribute;
2002
2003 jQuery.fn.extend({
2004 attr: function( name, value ) {
2005 return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
2006 },
2007
2008 removeAttr: function( name ) {
2009 return this.each(function() {
2010 jQuery.removeAttr( this, name );
2011 });
2012 },
2013
2014 prop: function( name, value ) {
2015 return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
2016 },
2017
2018 removeProp: function( name ) {
2019 name = jQuery.propFix[ name ] || name;
2020 return this.each(function() {
2021 // try/catch handles cases where IE balks (such as removing a property on window)
2022 try {
2023 this[ name ] = undefined;
2024 delete this[ name ];
2025 } catch( e ) {}
2026 });
2027 },
2028
2029 addClass: function( value ) {
2030 var classNames, i, l, elem,
2031 setClass, c, cl;
2032
2033 if ( jQuery.isFunction( value ) ) {
2034 return this.each(function( j ) {
2035 jQuery( this ).addClass( value.call(this, j, this.className) );
2036 });
2037 }
2038
2039 if ( value && typeof value === "string" ) {
2040 classNames = value.split( core_rspace );
2041
2042 for ( i = 0, l = this.length; i < l; i++ ) {
2043 elem = this[ i ];
2044
2045 if ( elem.nodeType === 1 ) {
2046 if ( !elem.className && classNames.length === 1 ) {
2047 elem.className = value;
2048
2049 } else {
2050 setClass = " " + elem.className + " ";
2051
2052 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
2053 if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) {
2054 setClass += classNames[ c ] + " ";
2055 }
2056 }
2057 elem.className = jQuery.trim( setClass );
2058 }
2059 }
2060 }
2061 }
2062
2063 return this;
2064 },
2065
2066 removeClass: function( value ) {
2067 var removes, className, elem, c, cl, i, l;
2068
2069 if ( jQuery.isFunction( value ) ) {
2070 return this.each(function( j ) {
2071 jQuery( this ).removeClass( value.call(this, j, this.className) );
2072 });
2073 }
2074 if ( (value && typeof value === "string") || value === undefined ) {
2075 removes = ( value || "" ).split( core_rspace );
2076
2077 for ( i = 0, l = this.length; i < l; i++ ) {
2078 elem = this[ i ];
2079 if ( elem.nodeType === 1 && elem.className ) {
2080
2081 className = (" " + elem.className + " ").replace( rclass, " " );
2082
2083 // loop over each item in the removal list
2084 for ( c = 0, cl = removes.length; c < cl; c++ ) {
2085 // Remove until there is nothing to remove,
2086 while ( className.indexOf(" " + removes[ c ] + " ") >= 0 ) {
2087 className = className.replace( " " + removes[ c ] + " " , " " );
2088 }
2089 }
2090 elem.className = value ? jQuery.trim( className ) : "";
2091 }
2092 }
2093 }
2094
2095 return this;
2096 },
2097
2098 toggleClass: function( value, stateVal ) {
2099 var type = typeof value,
2100 isBool = typeof stateVal === "boolean";
2101
2102 if ( jQuery.isFunction( value ) ) {
2103 return this.each(function( i ) {
2104 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
2105 });
2106 }
2107
2108 return this.each(function() {
2109 if ( type === "string" ) {
2110 // toggle individual class names
2111 var className,
2112 i = 0,
2113 self = jQuery( this ),
2114 state = stateVal,
2115 classNames = value.split( core_rspace );
2116
2117 while ( (className = classNames[ i++ ]) ) {
2118 // check each className given, space separated list
2119 state = isBool ? state : !self.hasClass( className );
2120 self[ state ? "addClass" : "removeClass" ]( className );
2121 }
2122
2123 } else if ( type === "undefined" || type === "boolean" ) {
2124 if ( this.className ) {
2125 // store className if set
2126 jQuery._data( this, "__className__", this.className );
2127 }
2128
2129 // toggle whole className
2130 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2131 }
2132 });
2133 },
2134
2135 hasClass: function( selector ) {
2136 var className = " " + selector + " ",
2137 i = 0,
2138 l = this.length;
2139 for ( ; i < l; i++ ) {
2140 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
2141 return true;
2142 }
2143 }
2144
2145 return false;
2146 },
2147
2148 val: function( value ) {
2149 var hooks, ret, isFunction,
2150 elem = this[0];
2151
2152 if ( !arguments.length ) {
2153 if ( elem ) {
2154 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
2155
2156 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
2157 return ret;
2158 }
2159
2160 ret = elem.value;
2161
2162 return typeof ret === "string" ?
2163 // handle most common string cases
2164 ret.replace(rreturn, "") :
2165 // handle cases where value is null/undef or number
2166 ret == null ? "" : ret;
2167 }
2168
2169 return;
2170 }
2171
2172 isFunction = jQuery.isFunction( value );
2173
2174 return this.each(function( i ) {
2175 var val,
2176 self = jQuery(this);
2177
2178 if ( this.nodeType !== 1 ) {
2179 return;
2180 }
2181
2182 if ( isFunction ) {
2183 val = value.call( this, i, self.val() );
2184 } else {
2185 val = value;
2186 }
2187
2188 // Treat null/undefined as ""; convert numbers to string
2189 if ( val == null ) {
2190 val = "";
2191 } else if ( typeof val === "number" ) {
2192 val += "";
2193 } else if ( jQuery.isArray( val ) ) {
2194 val = jQuery.map(val, function ( value ) {
2195 return value == null ? "" : value + "";
2196 });
2197 }
2198
2199 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
2200
2201 // If set returns undefined, fall back to normal setting
2202 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
2203 this.value = val;
2204 }
2205 });
2206 }
2207 });
2208
2209 jQuery.extend({
2210 valHooks: {
2211 option: {
2212 get: function( elem ) {
2213 // attributes.value is undefined in Blackberry 4.7 but
2214 // uses .value. See #6932
2215 var val = elem.attributes.value;
2216 return !val || val.specified ? elem.value : elem.text;
2217 }
2218 },
2219 select: {
2220 get: function( elem ) {
2221 var value, option,
2222 options = elem.options,
2223 index = elem.selectedIndex,
2224 one = elem.type === "select-one" || index < 0,
2225 values = one ? null : [],
2226 max = one ? index + 1 : options.length,
2227 i = index < 0 ?
2228 max :
2229 one ? index : 0;
2230
2231 // Loop through all the selected options
2232 for ( ; i < max; i++ ) {
2233 option = options[ i ];
2234
2235 // oldIE doesn't update selected after form reset (#2551)
2236 if ( ( option.selected || i === index ) &&
2237 // Don't return options that are disabled or in a disabled optgroup
2238 ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
2239 ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
2240
2241 // Get the specific value for the option
2242 value = jQuery( option ).val();
2243
2244 // We don't need an array for one selects
2245 if ( one ) {
2246 return value;
2247 }
2248
2249 // Multi-Selects return an array
2250 values.push( value );
2251 }
2252 }
2253
2254 return values;
2255 },
2256
2257 set: function( elem, value ) {
2258 var values = jQuery.makeArray( value );
2259
2260 jQuery(elem).find("option").each(function() {
2261 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
2262 });
2263
2264 if ( !values.length ) {
2265 elem.selectedIndex = -1;
2266 }
2267 return values;
2268 }
2269 }
2270 },
2271
2272 // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9
2273 attrFn: {},
2274
2275 attr: function( elem, name, value, pass ) {
2276 var ret, hooks, notxml,
2277 nType = elem.nodeType;
2278
2279 // don't get/set attributes on text, comment and attribute nodes
2280 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2281 return;
2282 }
2283
2284 if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {
2285 return jQuery( elem )[ name ]( value );
2286 }
2287
2288 // Fallback to prop when attributes are not supported
2289 if ( typeof elem.getAttribute === "undefined" ) {
2290 return jQuery.prop( elem, name, value );
2291 }
2292
2293 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2294
2295 // All attributes are lowercase
2296 // Grab necessary hook if one is defined
2297 if ( notxml ) {
2298 name = name.toLowerCase();
2299 hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
2300 }
2301
2302 if ( value !== undefined ) {
2303
2304 if ( value === null ) {
2305 jQuery.removeAttr( elem, name );
2306 return;
2307
2308 } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
2309 return ret;
2310
2311 } else {
2312 elem.setAttribute( name, value + "" );
2313 return value;
2314 }
2315
2316 } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
2317 return ret;
2318
2319 } else {
2320
2321 ret = elem.getAttribute( name );
2322
2323 // Non-existent attributes return null, we normalize to undefined
2324 return ret === null ?
2325 undefined :
2326 ret;
2327 }
2328 },
2329
2330 removeAttr: function( elem, value ) {
2331 var propName, attrNames, name, isBool,
2332 i = 0;
2333
2334 if ( value && elem.nodeType === 1 ) {
2335
2336 attrNames = value.split( core_rspace );
2337
2338 for ( ; i < attrNames.length; i++ ) {
2339 name = attrNames[ i ];
2340
2341 if ( name ) {
2342 propName = jQuery.propFix[ name ] || name;
2343 isBool = rboolean.test( name );
2344
2345 // See #9699 for explanation of this approach (setting first, then removal)
2346 // Do not do this for boolean attributes (see #10870)
2347 if ( !isBool ) {
2348 jQuery.attr( elem, name, "" );
2349 }
2350 elem.removeAttribute( getSetAttribute ? name : propName );
2351
2352 // Set corresponding property to false for boolean attributes
2353 if ( isBool && propName in elem ) {
2354 elem[ propName ] = false;
2355 }
2356 }
2357 }
2358 }
2359 },
2360
2361 attrHooks: {
2362 type: {
2363 set: function( elem, value ) {
2364 // We can't allow the type property to be changed (since it causes problems in IE)
2365 if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
2366 jQuery.error( "type property can't be changed" );
2367 } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
2368 // Setting the type on a radio button after the value resets the value in IE6-9
2369 // Reset value to it's default in case type is set after value
2370 // This is for element creation
2371 var val = elem.value;
2372 elem.setAttribute( "type", value );
2373 if ( val ) {
2374 elem.value = val;
2375 }
2376 return value;
2377 }
2378 }
2379 },
2380 // Use the value property for back compat
2381 // Use the nodeHook for button elements in IE6/7 (#1954)
2382 value: {
2383 get: function( elem, name ) {
2384 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
2385 return nodeHook.get( elem, name );
2386 }
2387 return name in elem ?
2388 elem.value :
2389 null;
2390 },
2391 set: function( elem, value, name ) {
2392 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
2393 return nodeHook.set( elem, value, name );
2394 }
2395 // Does not return so that setAttribute is also used
2396 elem.value = value;
2397 }
2398 }
2399 },
2400
2401 propFix: {
2402 tabindex: "tabIndex",
2403 readonly: "readOnly",
2404 "for": "htmlFor",
2405 "class": "className",
2406 maxlength: "maxLength",
2407 cellspacing: "cellSpacing",
2408 cellpadding: "cellPadding",
2409 rowspan: "rowSpan",
2410 colspan: "colSpan",
2411 usemap: "useMap",
2412 frameborder: "frameBorder",
2413 contenteditable: "contentEditable"
2414 },
2415
2416 prop: function( elem, name, value ) {
2417 var ret, hooks, notxml,
2418 nType = elem.nodeType;
2419
2420 // don't get/set properties on text, comment and attribute nodes
2421 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2422 return;
2423 }
2424
2425 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2426
2427 if ( notxml ) {
2428 // Fix name and attach hooks
2429 name = jQuery.propFix[ name ] || name;
2430 hooks = jQuery.propHooks[ name ];
2431 }
2432
2433 if ( value !== undefined ) {
2434 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2435 return ret;
2436
2437 } else {
2438 return ( elem[ name ] = value );
2439 }
2440
2441 } else {
2442 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2443 return ret;
2444
2445 } else {
2446 return elem[ name ];
2447 }
2448 }
2449 },
2450
2451 propHooks: {
2452 tabIndex: {
2453 get: function( elem ) {
2454 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
2455 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
2456 var attributeNode = elem.getAttributeNode("tabindex");
2457
2458 return attributeNode && attributeNode.specified ?
2459 parseInt( attributeNode.value, 10 ) :
2460 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
2461 0 :
2462 undefined;
2463 }
2464 }
2465 }
2466 });
2467
2468 // Hook for boolean attributes
2469 boolHook = {
2470 get: function( elem, name ) {
2471 // Align boolean attributes with corresponding properties
2472 // Fall back to attribute presence where some booleans are not supported
2473 var attrNode,
2474 property = jQuery.prop( elem, name );
2475 return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
2476 name.toLowerCase() :
2477 undefined;
2478 },
2479 set: function( elem, value, name ) {
2480 var propName;
2481 if ( value === false ) {
2482 // Remove boolean attributes when set to false
2483 jQuery.removeAttr( elem, name );
2484 } else {
2485 // value is true since we know at this point it's type boolean and not false
2486 // Set boolean attributes to the same name and set the DOM property
2487 propName = jQuery.propFix[ name ] || name;
2488 if ( propName in elem ) {
2489 // Only set the IDL specifically if it already exists on the element
2490 elem[ propName ] = true;
2491 }
2492
2493 elem.setAttribute( name, name.toLowerCase() );
2494 }
2495 return name;
2496 }
2497 };
2498
2499 // IE6/7 do not support getting/setting some attributes with get/setAttribute
2500 if ( !getSetAttribute ) {
2501
2502 fixSpecified = {
2503 name: true,
2504 id: true,
2505 coords: true
2506 };
2507
2508 // Use this for any attribute in IE6/7
2509 // This fixes almost every IE6/7 issue
2510 nodeHook = jQuery.valHooks.button = {
2511 get: function( elem, name ) {
2512 var ret;
2513 ret = elem.getAttributeNode( name );
2514 return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ?
2515 ret.value :
2516 undefined;
2517 },
2518 set: function( elem, value, name ) {
2519 // Set the existing or create a new attribute node
2520 var ret = elem.getAttributeNode( name );
2521 if ( !ret ) {
2522 ret = document.createAttribute( name );
2523 elem.setAttributeNode( ret );
2524 }
2525 return ( ret.value = value + "" );
2526 }
2527 };
2528
2529 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
2530 // This is for removals
2531 jQuery.each([ "width", "height" ], function( i, name ) {
2532 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2533 set: function( elem, value ) {
2534 if ( value === "" ) {
2535 elem.setAttribute( name, "auto" );
2536 return value;
2537 }
2538 }
2539 });
2540 });
2541
2542 // Set contenteditable to false on removals(#10429)
2543 // Setting to empty string throws an error as an invalid value
2544 jQuery.attrHooks.contenteditable = {
2545 get: nodeHook.get,
2546 set: function( elem, value, name ) {
2547 if ( value === "" ) {
2548 value = "false";
2549 }
2550 nodeHook.set( elem, value, name );
2551 }
2552 };
2553 }
2554
2555
2556 // Some attributes require a special call on IE
2557 if ( !jQuery.support.hrefNormalized ) {
2558 jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
2559 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2560 get: function( elem ) {
2561 var ret = elem.getAttribute( name, 2 );
2562 return ret === null ? undefined : ret;
2563 }
2564 });
2565 });
2566 }
2567
2568 if ( !jQuery.support.style ) {
2569 jQuery.attrHooks.style = {
2570 get: function( elem ) {
2571 // Return undefined in the case of empty string
2572 // Normalize to lowercase since IE uppercases css property names
2573 return elem.style.cssText.toLowerCase() || undefined;
2574 },
2575 set: function( elem, value ) {
2576 return ( elem.style.cssText = value + "" );
2577 }
2578 };
2579 }
2580
2581 // Safari mis-reports the default selected property of an option
2582 // Accessing the parent's selectedIndex property fixes it
2583 if ( !jQuery.support.optSelected ) {
2584 jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
2585 get: function( elem ) {
2586 var parent = elem.parentNode;
2587
2588 if ( parent ) {
2589 parent.selectedIndex;
2590
2591 // Make sure that it also works with optgroups, see #5701
2592 if ( parent.parentNode ) {
2593 parent.parentNode.selectedIndex;
2594 }
2595 }
2596 return null;
2597 }
2598 });
2599 }
2600
2601 // IE6/7 call enctype encoding
2602 if ( !jQuery.support.enctype ) {
2603 jQuery.propFix.enctype = "encoding";
2604 }
2605
2606 // Radios and checkboxes getter/setter
2607 if ( !jQuery.support.checkOn ) {
2608 jQuery.each([ "radio", "checkbox" ], function() {
2609 jQuery.valHooks[ this ] = {
2610 get: function( elem ) {
2611 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
2612 return elem.getAttribute("value") === null ? "on" : elem.value;
2613 }
2614 };
2615 });
2616 }
2617 jQuery.each([ "radio", "checkbox" ], function() {
2618 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
2619 set: function( elem, value ) {
2620 if ( jQuery.isArray( value ) ) {
2621 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
2622 }
2623 }
2624 });
2625 });
2626 var rformElems = /^(?:textarea|input|select)$/i,
2627 rtypenamespace = /^([^\.]*|)(?:\.(.+)|)$/,
2628 rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
2629 rkeyEvent = /^key/,
2630 rmouseEvent = /^(?:mouse|contextmenu)|click/,
2631 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
2632 hoverHack = function( events ) {
2633 return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
2634 };
2635
2636 /*
2637 * Helper functions for managing events -- not part of the public interface.
2638 * Props to Dean Edwards' addEvent library for many of the ideas.
2639 */
2640 jQuery.event = {
2641
2642 add: function( elem, types, handler, data, selector ) {
2643
2644 var elemData, eventHandle, events,
2645 t, tns, type, namespaces, handleObj,
2646 handleObjIn, handlers, special;
2647
2648 // Don't attach events to noData or text/comment nodes (allow plain objects tho)
2649 if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
2650 return;
2651 }
2652
2653 // Caller can pass in an object of custom data in lieu of the handler
2654 if ( handler.handler ) {
2655 handleObjIn = handler;
2656 handler = handleObjIn.handler;
2657 selector = handleObjIn.selector;
2658 }
2659
2660 // Make sure that the handler has a unique ID, used to find/remove it later
2661 if ( !handler.guid ) {
2662 handler.guid = jQuery.guid++;
2663 }
2664
2665 // Init the element's event structure and main handler, if this is the first
2666 events = elemData.events;
2667 if ( !events ) {
2668 elemData.events = events = {};
2669 }
2670 eventHandle = elemData.handle;
2671 if ( !eventHandle ) {
2672 elemData.handle = eventHandle = function( e ) {
2673 // Discard the second event of a jQuery.event.trigger() and
2674 // when an event is called after a page has unloaded
2675 return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
2676 jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
2677 undefined;
2678 };
2679 // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
2680 eventHandle.elem = elem;
2681 }
2682
2683 // Handle multiple events separated by a space
2684 // jQuery(...).bind("mouseover mouseout", fn);
2685 types = jQuery.trim( hoverHack(types) ).split( " " );
2686 for ( t = 0; t < types.length; t++ ) {
2687
2688 tns = rtypenamespace.exec( types[t] ) || [];
2689 type = tns[1];
2690 namespaces = ( tns[2] || "" ).split( "." ).sort();
2691
2692 // If event changes its type, use the special event handlers for the changed type
2693 special = jQuery.event.special[ type ] || {};
2694
2695 // If selector defined, determine special event api type, otherwise given type
2696 type = ( selector ? special.delegateType : special.bindType ) || type;
2697
2698 // Update special based on newly reset type
2699 special = jQuery.event.special[ type ] || {};
2700
2701 // handleObj is passed to all event handlers
2702 handleObj = jQuery.extend({
2703 type: type,
2704 origType: tns[1],
2705 data: data,
2706 handler: handler,
2707 guid: handler.guid,
2708 selector: selector,
2709 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
2710 namespace: namespaces.join(".")
2711 }, handleObjIn );
2712
2713 // Init the event handler queue if we're the first
2714 handlers = events[ type ];
2715 if ( !handlers ) {
2716 handlers = events[ type ] = [];
2717 handlers.delegateCount = 0;
2718
2719 // Only use addEventListener/attachEvent if the special events handler returns false
2720 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
2721 // Bind the global event handler to the element
2722 if ( elem.addEventListener ) {
2723 elem.addEventListener( type, eventHandle, false );
2724
2725 } else if ( elem.attachEvent ) {
2726 elem.attachEvent( "on" + type, eventHandle );
2727 }
2728 }
2729 }
2730
2731 if ( special.add ) {
2732 special.add.call( elem, handleObj );
2733
2734 if ( !handleObj.handler.guid ) {
2735 handleObj.handler.guid = handler.guid;
2736 }
2737 }
2738
2739 // Add to the element's handler list, delegates in front
2740 if ( selector ) {
2741 handlers.splice( handlers.delegateCount++, 0, handleObj );
2742 } else {
2743 handlers.push( handleObj );
2744 }
2745
2746 // Keep track of which events have ever been used, for event optimization
2747 jQuery.event.global[ type ] = true;
2748 }
2749
2750 // Nullify elem to prevent memory leaks in IE
2751 elem = null;
2752 },
2753
2754 global: {},
2755
2756 // Detach an event or set of events from an element
2757 remove: function( elem, types, handler, selector, mappedTypes ) {
2758
2759 var t, tns, type, origType, namespaces, origCount,
2760 j, events, special, eventType, handleObj,
2761 elemData = jQuery.hasData( elem ) && jQuery._data( elem );
2762
2763 if ( !elemData || !(events = elemData.events) ) {
2764 return;
2765 }
2766
2767 // Once for each type.namespace in types; type may be omitted
2768 types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
2769 for ( t = 0; t < types.length; t++ ) {
2770 tns = rtypenamespace.exec( types[t] ) || [];
2771 type = origType = tns[1];
2772 namespaces = tns[2];
2773
2774 // Unbind all events (on this namespace, if provided) for the element
2775 if ( !type ) {
2776 for ( type in events ) {
2777 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
2778 }
2779 continue;
2780 }
2781
2782 special = jQuery.event.special[ type ] || {};
2783 type = ( selector? special.delegateType : special.bindType ) || type;
2784 eventType = events[ type ] || [];
2785 origCount = eventType.length;
2786 namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
2787
2788 // Remove matching events
2789 for ( j = 0; j < eventType.length; j++ ) {
2790 handleObj = eventType[ j ];
2791
2792 if ( ( mappedTypes || origType === handleObj.origType ) &&
2793 ( !handler || handler.guid === handleObj.guid ) &&
2794 ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
2795 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
2796 eventType.splice( j--, 1 );
2797
2798 if ( handleObj.selector ) {
2799 eventType.delegateCount--;
2800 }
2801 if ( special.remove ) {
2802 special.remove.call( elem, handleObj );
2803 }
2804 }
2805 }
2806
2807 // Remove generic event handler if we removed something and no more handlers exist
2808 // (avoids potential for endless recursion during removal of special event handlers)
2809 if ( eventType.length === 0 && origCount !== eventType.length ) {
2810 if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
2811 jQuery.removeEvent( elem, type, elemData.handle );
2812 }
2813
2814 delete events[ type ];
2815 }
2816 }
2817
2818 // Remove the expando if it's no longer used
2819 if ( jQuery.isEmptyObject( events ) ) {
2820 delete elemData.handle;
2821
2822 // removeData also checks for emptiness and clears the expando if empty
2823 // so use it instead of delete
2824 jQuery.removeData( elem, "events", true );
2825 }
2826 },
2827
2828 // Events that are safe to short-circuit if no handlers are attached.
2829 // Native DOM events should not be added, they may have inline handlers.
2830 customEvent: {
2831 "getData": true,
2832 "setData": true,
2833 "changeData": true
2834 },
2835
2836 trigger: function( event, data, elem, onlyHandlers ) {
2837 // Don't do events on text and comment nodes
2838 if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
2839 return;
2840 }
2841
2842 // Event object or event type
2843 var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType,
2844 type = event.type || event,
2845 namespaces = [];
2846
2847 // focus/blur morphs to focusin/out; ensure we're not firing them right now
2848 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
2849 return;
2850 }
2851
2852 if ( type.indexOf( "!" ) >= 0 ) {
2853 // Exclusive events trigger only for the exact event (no namespaces)
2854 type = type.slice(0, -1);
2855 exclusive = true;
2856 }
2857
2858 if ( type.indexOf( "." ) >= 0 ) {
2859 // Namespaced trigger; create a regexp to match event type in handle()
2860 namespaces = type.split(".");
2861 type = namespaces.shift();
2862 namespaces.sort();
2863 }
2864
2865 if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
2866 // No jQuery handlers for this event type, and it can't have inline handlers
2867 return;
2868 }
2869
2870 // Caller can pass in an Event, Object, or just an event type string
2871 event = typeof event === "object" ?
2872 // jQuery.Event object
2873 event[ jQuery.expando ] ? event :
2874 // Object literal
2875 new jQuery.Event( type, event ) :
2876 // Just the event type (string)
2877 new jQuery.Event( type );
2878
2879 event.type = type;
2880 event.isTrigger = true;
2881 event.exclusive = exclusive;
2882 event.namespace = namespaces.join( "." );
2883 event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
2884 ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
2885
2886 // Handle a global trigger
2887 if ( !elem ) {
2888
2889 // TODO: Stop taunting the data cache; remove global events and always attach to document
2890 cache = jQuery.cache;
2891 for ( i in cache ) {
2892 if ( cache[ i ].events && cache[ i ].events[ type ] ) {
2893 jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
2894 }
2895 }
2896 return;
2897 }
2898
2899 // Clean up the event in case it is being reused
2900 event.result = undefined;
2901 if ( !event.target ) {
2902 event.target = elem;
2903 }
2904
2905 // Clone any incoming data and prepend the event, creating the handler arg list
2906 data = data != null ? jQuery.makeArray( data ) : [];
2907 data.unshift( event );
2908
2909 // Allow special events to draw outside the lines
2910 special = jQuery.event.special[ type ] || {};
2911 if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
2912 return;
2913 }
2914
2915 // Determine event propagation path in advance, per W3C events spec (#9951)
2916 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
2917 eventPath = [[ elem, special.bindType || type ]];
2918 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
2919
2920 bubbleType = special.delegateType || type;
2921 cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
2922 for ( old = elem; cur; cur = cur.parentNode ) {
2923 eventPath.push([ cur, bubbleType ]);
2924 old = cur;
2925 }
2926
2927 // Only add window if we got to document (e.g., not plain obj or detached DOM)
2928 if ( old === (elem.ownerDocument || document) ) {
2929 eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
2930 }
2931 }
2932
2933 // Fire handlers on the event path
2934 for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
2935
2936 cur = eventPath[i