07706829477ba50051cef233232023adec461e07
[Packages/TYPO3.CMS.git] / typo3 / contrib / jquery / jquery-1.8.0.js
1 /*!
2 * jQuery JavaScript Library v1.8.0
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: Thu Aug 09 2012 16:24:48 GMT-0400 (Eastern Daylight 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 // IE doesn't match non-breaking spaces with \s
55 rtrim = core_rnotwhite.test("\xA0") ? (/^[\s\xA0]+|[\s\xA0]+$/g) : /^\s+|\s+$/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.0",
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.toUpperCase() === name.toUpperCase();
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 ?
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.toString().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 || proxy.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
848 // browser event has already occurred.
849 if ( document.readyState === "complete" || ( document.readyState !== "loading" && document.addEventListener ) ) {
850 // Handle it asynchronously to allow scripts the opportunity to delay ready
851 setTimeout( jQuery.ready, 1 );
852
853 // Standards-based browsers support DOMContentLoaded
854 } else if ( document.addEventListener ) {
855 // Use the handy event callback
856 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
857
858 // A fallback to window.onload, that will always work
859 window.addEventListener( "load", jQuery.ready, false );
860
861 // If IE event model is used
862 } else {
863 // Ensure firing before onload, maybe late but safe also for iframes
864 document.attachEvent( "onreadystatechange", DOMContentLoaded );
865
866 // A fallback to window.onload, that will always work
867 window.attachEvent( "onload", jQuery.ready );
868
869 // If IE and not a frame
870 // continually check to see if the document is ready
871 var top = false;
872
873 try {
874 top = window.frameElement == null && document.documentElement;
875 } catch(e) {}
876
877 if ( top && top.doScroll ) {
878 (function doScrollCheck() {
879 if ( !jQuery.isReady ) {
880
881 try {
882 // Use the trick by Diego Perini
883 // http://javascript.nwbox.com/IEContentLoaded/
884 top.doScroll("left");
885 } catch(e) {
886 return setTimeout( doScrollCheck, 50 );
887 }
888
889 // and execute any waiting functions
890 jQuery.ready();
891 }
892 })();
893 }
894 }
895 }
896 return readyList.promise( obj );
897 };
898
899 // Populate the class2type map
900 jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
901 class2type[ "[object " + name + "]" ] = name.toLowerCase();
902 });
903
904 // All jQuery objects should point back to these
905 rootjQuery = jQuery(document);
906 // String to Object options format cache
907 var optionsCache = {};
908
909 // Convert String-formatted options into Object-formatted ones and store in cache
910 function createOptions( options ) {
911 var object = optionsCache[ options ] = {};
912 jQuery.each( options.split( core_rspace ), function( _, flag ) {
913 object[ flag ] = true;
914 });
915 return object;
916 }
917
918 /*
919 * Create a callback list using the following parameters:
920 *
921 * options: an optional list of space-separated options that will change how
922 * the callback list behaves or a more traditional option object
923 *
924 * By default a callback list will act like an event callback list and can be
925 * "fired" multiple times.
926 *
927 * Possible options:
928 *
929 * once: will ensure the callback list can only be fired once (like a Deferred)
930 *
931 * memory: will keep track of previous values and will call any callback added
932 * after the list has been fired right away with the latest "memorized"
933 * values (like a Deferred)
934 *
935 * unique: will ensure a callback can only be added once (no duplicate in the list)
936 *
937 * stopOnFalse: interrupt callings when a callback returns false
938 *
939 */
940 jQuery.Callbacks = function( options ) {
941
942 // Convert options from String-formatted to Object-formatted if needed
943 // (we check in cache first)
944 options = typeof options === "string" ?
945 ( optionsCache[ options ] || createOptions( options ) ) :
946 jQuery.extend( {}, options );
947
948 var // Last fire value (for non-forgettable lists)
949 memory,
950 // Flag to know if list was already fired
951 fired,
952 // Flag to know if list is currently firing
953 firing,
954 // First callback to fire (used internally by add and fireWith)
955 firingStart,
956 // End of the loop when firing
957 firingLength,
958 // Index of currently firing callback (modified by remove if needed)
959 firingIndex,
960 // Actual callback list
961 list = [],
962 // Stack of fire calls for repeatable lists
963 stack = !options.once && [],
964 // Fire callbacks
965 fire = function( data ) {
966 memory = options.memory && data;
967 fired = true;
968 firingIndex = firingStart || 0;
969 firingStart = 0;
970 firingLength = list.length;
971 firing = true;
972 for ( ; list && firingIndex < firingLength; firingIndex++ ) {
973 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
974 memory = false; // To prevent further calls using add
975 break;
976 }
977 }
978 firing = false;
979 if ( list ) {
980 if ( stack ) {
981 if ( stack.length ) {
982 fire( stack.shift() );
983 }
984 } else if ( memory ) {
985 list = [];
986 } else {
987 self.disable();
988 }
989 }
990 },
991 // Actual Callbacks object
992 self = {
993 // Add a callback or a collection of callbacks to the list
994 add: function() {
995 if ( list ) {
996 // First, we save the current length
997 var start = list.length;
998 (function add( args ) {
999 jQuery.each( args, function( _, arg ) {
1000 if ( jQuery.isFunction( arg ) && ( !options.unique || !self.has( arg ) ) ) {
1001 list.push( arg );
1002 } else if ( arg && arg.length ) {
1003 // Inspect recursively
1004 add( arg );
1005 }
1006 });
1007 })( arguments );
1008 // Do we need to add the callbacks to the
1009 // current firing batch?
1010 if ( firing ) {
1011 firingLength = list.length;
1012 // With memory, if we're not firing then
1013 // we should call right away
1014 } else if ( memory ) {
1015 firingStart = start;
1016 fire( memory );
1017 }
1018 }
1019 return this;
1020 },
1021 // Remove a callback from the list
1022 remove: function() {
1023 if ( list ) {
1024 jQuery.each( arguments, function( _, arg ) {
1025 var index;
1026 while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
1027 list.splice( index, 1 );
1028 // Handle firing indexes
1029 if ( firing ) {
1030 if ( index <= firingLength ) {
1031 firingLength--;
1032 }
1033 if ( index <= firingIndex ) {
1034 firingIndex--;
1035 }
1036 }
1037 }
1038 });
1039 }
1040 return this;
1041 },
1042 // Control if a given callback is in the list
1043 has: function( fn ) {
1044 return jQuery.inArray( fn, list ) > -1;
1045 },
1046 // Remove all callbacks from the list
1047 empty: function() {
1048 list = [];
1049 return this;
1050 },
1051 // Have the list do nothing anymore
1052 disable: function() {
1053 list = stack = memory = undefined;
1054 return this;
1055 },
1056 // Is it disabled?
1057 disabled: function() {
1058 return !list;
1059 },
1060 // Lock the list in its current state
1061 lock: function() {
1062 stack = undefined;
1063 if ( !memory ) {
1064 self.disable();
1065 }
1066 return this;
1067 },
1068 // Is it locked?
1069 locked: function() {
1070 return !stack;
1071 },
1072 // Call all callbacks with the given context and arguments
1073 fireWith: function( context, args ) {
1074 args = args || [];
1075 args = [ context, args.slice ? args.slice() : args ];
1076 if ( list && ( !fired || stack ) ) {
1077 if ( firing ) {
1078 stack.push( args );
1079 } else {
1080 fire( args );
1081 }
1082 }
1083 return this;
1084 },
1085 // Call all the callbacks with the given arguments
1086 fire: function() {
1087 self.fireWith( this, arguments );
1088 return this;
1089 },
1090 // To know if the callbacks have already been called at least once
1091 fired: function() {
1092 return !!fired;
1093 }
1094 };
1095
1096 return self;
1097 };
1098 jQuery.extend({
1099
1100 Deferred: function( func ) {
1101 var tuples = [
1102 // action, add listener, listener list, final state
1103 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
1104 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
1105 [ "notify", "progress", jQuery.Callbacks("memory") ]
1106 ],
1107 state = "pending",
1108 promise = {
1109 state: function() {
1110 return state;
1111 },
1112 always: function() {
1113 deferred.done( arguments ).fail( arguments );
1114 return this;
1115 },
1116 then: function( /* fnDone, fnFail, fnProgress */ ) {
1117 var fns = arguments;
1118 return jQuery.Deferred(function( newDefer ) {
1119 jQuery.each( tuples, function( i, tuple ) {
1120 var action = tuple[ 0 ],
1121 fn = fns[ i ];
1122 // deferred[ done | fail | progress ] for forwarding actions to newDefer
1123 deferred[ tuple[1] ]( jQuery.isFunction( fn ) ?
1124 function() {
1125 var returned = fn.apply( this, arguments );
1126 if ( returned && jQuery.isFunction( returned.promise ) ) {
1127 returned.promise()
1128 .done( newDefer.resolve )
1129 .fail( newDefer.reject )
1130 .progress( newDefer.notify );
1131 } else {
1132 newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
1133 }
1134 } :
1135 newDefer[ action ]
1136 );
1137 });
1138 fns = null;
1139 }).promise();
1140 },
1141 // Get a promise for this deferred
1142 // If obj is provided, the promise aspect is added to the object
1143 promise: function( obj ) {
1144 return typeof obj === "object" ? jQuery.extend( obj, promise ) : promise;
1145 }
1146 },
1147 deferred = {};
1148
1149 // Keep pipe for back-compat
1150 promise.pipe = promise.then;
1151
1152 // Add list-specific methods
1153 jQuery.each( tuples, function( i, tuple ) {
1154 var list = tuple[ 2 ],
1155 stateString = tuple[ 3 ];
1156
1157 // promise[ done | fail | progress ] = list.add
1158 promise[ tuple[1] ] = list.add;
1159
1160 // Handle state
1161 if ( stateString ) {
1162 list.add(function() {
1163 // state = [ resolved | rejected ]
1164 state = stateString;
1165
1166 // [ reject_list | resolve_list ].disable; progress_list.lock
1167 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
1168 }
1169
1170 // deferred[ resolve | reject | notify ] = list.fire
1171 deferred[ tuple[0] ] = list.fire;
1172 deferred[ tuple[0] + "With" ] = list.fireWith;
1173 });
1174
1175 // Make the deferred a promise
1176 promise.promise( deferred );
1177
1178 // Call given func if any
1179 if ( func ) {
1180 func.call( deferred, deferred );
1181 }
1182
1183 // All done!
1184 return deferred;
1185 },
1186
1187 // Deferred helper
1188 when: function( subordinate /* , ..., subordinateN */ ) {
1189 var i = 0,
1190 resolveValues = core_slice.call( arguments ),
1191 length = resolveValues.length,
1192
1193 // the count of uncompleted subordinates
1194 remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
1195
1196 // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
1197 deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
1198
1199 // Update function for both resolve and progress values
1200 updateFunc = function( i, contexts, values ) {
1201 return function( value ) {
1202 contexts[ i ] = this;
1203 values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
1204 if( values === progressValues ) {
1205 deferred.notifyWith( contexts, values );
1206 } else if ( !( --remaining ) ) {
1207 deferred.resolveWith( contexts, values );
1208 }
1209 };
1210 },
1211
1212 progressValues, progressContexts, resolveContexts;
1213
1214 // add listeners to Deferred subordinates; treat others as resolved
1215 if ( length > 1 ) {
1216 progressValues = new Array( length );
1217 progressContexts = new Array( length );
1218 resolveContexts = new Array( length );
1219 for ( ; i < length; i++ ) {
1220 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
1221 resolveValues[ i ].promise()
1222 .done( updateFunc( i, resolveContexts, resolveValues ) )
1223 .fail( deferred.reject )
1224 .progress( updateFunc( i, progressContexts, progressValues ) );
1225 } else {
1226 --remaining;
1227 }
1228 }
1229 }
1230
1231 // if we're not waiting on anything, resolve the master
1232 if ( !remaining ) {
1233 deferred.resolveWith( resolveContexts, resolveValues );
1234 }
1235
1236 return deferred.promise();
1237 }
1238 });
1239 jQuery.support = (function() {
1240
1241 var support,
1242 all,
1243 a,
1244 select,
1245 opt,
1246 input,
1247 fragment,
1248 eventName,
1249 i,
1250 isSupported,
1251 clickFn,
1252 div = document.createElement("div");
1253
1254 // Preliminary tests
1255 div.setAttribute( "className", "t" );
1256 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
1257
1258 all = div.getElementsByTagName("*");
1259 a = div.getElementsByTagName("a")[ 0 ];
1260 a.style.cssText = "top:1px;float:left;opacity:.5";
1261
1262 // Can't get basic test support
1263 if ( !all || !all.length || !a ) {
1264 return {};
1265 }
1266
1267 // First batch of supports tests
1268 select = document.createElement("select");
1269 opt = select.appendChild( document.createElement("option") );
1270 input = div.getElementsByTagName("input")[ 0 ];
1271
1272 support = {
1273 // IE strips leading whitespace when .innerHTML is used
1274 leadingWhitespace: ( div.firstChild.nodeType === 3 ),
1275
1276 // Make sure that tbody elements aren't automatically inserted
1277 // IE will insert them into empty tables
1278 tbody: !div.getElementsByTagName("tbody").length,
1279
1280 // Make sure that link elements get serialized correctly by innerHTML
1281 // This requires a wrapper element in IE
1282 htmlSerialize: !!div.getElementsByTagName("link").length,
1283
1284 // Get the style information from getAttribute
1285 // (IE uses .cssText instead)
1286 style: /top/.test( a.getAttribute("style") ),
1287
1288 // Make sure that URLs aren't manipulated
1289 // (IE normalizes it by default)
1290 hrefNormalized: ( a.getAttribute("href") === "/a" ),
1291
1292 // Make sure that element opacity exists
1293 // (IE uses filter instead)
1294 // Use a regex to work around a WebKit issue. See #5145
1295 opacity: /^0.5/.test( a.style.opacity ),
1296
1297 // Verify style float existence
1298 // (IE uses styleFloat instead of cssFloat)
1299 cssFloat: !!a.style.cssFloat,
1300
1301 // Make sure that if no value is specified for a checkbox
1302 // that it defaults to "on".
1303 // (WebKit defaults to "" instead)
1304 checkOn: ( input.value === "on" ),
1305
1306 // Make sure that a selected-by-default option has a working selected property.
1307 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1308 optSelected: opt.selected,
1309
1310 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
1311 getSetAttribute: div.className !== "t",
1312
1313 // Tests for enctype support on a form(#6743)
1314 enctype: !!document.createElement("form").enctype,
1315
1316 // Makes sure cloning an html5 element does not cause problems
1317 // Where outerHTML is undefined, this still works
1318 html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
1319
1320 // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
1321 boxModel: ( document.compatMode === "CSS1Compat" ),
1322
1323 // Will be defined later
1324 submitBubbles: true,
1325 changeBubbles: true,
1326 focusinBubbles: false,
1327 deleteExpando: true,
1328 noCloneEvent: true,
1329 inlineBlockNeedsLayout: false,
1330 shrinkWrapBlocks: false,
1331 reliableMarginRight: true,
1332 boxSizingReliable: true,
1333 pixelPosition: false
1334 };
1335
1336 // Make sure checked status is properly cloned
1337 input.checked = true;
1338 support.noCloneChecked = input.cloneNode( true ).checked;
1339
1340 // Make sure that the options inside disabled selects aren't marked as disabled
1341 // (WebKit marks them as disabled)
1342 select.disabled = true;
1343 support.optDisabled = !opt.disabled;
1344
1345 // Test to see if it's possible to delete an expando from an element
1346 // Fails in Internet Explorer
1347 try {
1348 delete div.test;
1349 } catch( e ) {
1350 support.deleteExpando = false;
1351 }
1352
1353 if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
1354 div.attachEvent( "onclick", clickFn = function() {
1355 // Cloning a node shouldn't copy over any
1356 // bound event handlers (IE does this)
1357 support.noCloneEvent = false;
1358 });
1359 div.cloneNode( true ).fireEvent("onclick");
1360 div.detachEvent( "onclick", clickFn );
1361 }
1362
1363 // Check if a radio maintains its value
1364 // after being appended to the DOM
1365 input = document.createElement("input");
1366 input.value = "t";
1367 input.setAttribute( "type", "radio" );
1368 support.radioValue = input.value === "t";
1369
1370 input.setAttribute( "checked", "checked" );
1371
1372 // #11217 - WebKit loses check when the name is after the checked attribute
1373 input.setAttribute( "name", "t" );
1374
1375 div.appendChild( input );
1376 fragment = document.createDocumentFragment();
1377 fragment.appendChild( div.lastChild );
1378
1379 // WebKit doesn't clone checked state correctly in fragments
1380 support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
1381
1382 // Check if a disconnected checkbox will retain its checked
1383 // value of true after appended to the DOM (IE6/7)
1384 support.appendChecked = input.checked;
1385
1386 fragment.removeChild( input );
1387 fragment.appendChild( div );
1388
1389 // Technique from Juriy Zaytsev
1390 // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
1391 // We only care about the case where non-standard event systems
1392 // are used, namely in IE. Short-circuiting here helps us to
1393 // avoid an eval call (in setAttribute) which can cause CSP
1394 // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
1395 if ( div.attachEvent ) {
1396 for ( i in {
1397 submit: true,
1398 change: true,
1399 focusin: true
1400 }) {
1401 eventName = "on" + i;
1402 isSupported = ( eventName in div );
1403 if ( !isSupported ) {
1404 div.setAttribute( eventName, "return;" );
1405 isSupported = ( typeof div[ eventName ] === "function" );
1406 }
1407 support[ i + "Bubbles" ] = isSupported;
1408 }
1409 }
1410
1411 // Run tests that need a body at doc ready
1412 jQuery(function() {
1413 var container, div, tds, marginDiv,
1414 divReset = "padding:0;margin:0;border:0;display:block;overflow:hidden;",
1415 body = document.getElementsByTagName("body")[0];
1416
1417 if ( !body ) {
1418 // Return for frameset docs that don't have a body
1419 return;
1420 }
1421
1422 container = document.createElement("div");
1423 container.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px";
1424 body.insertBefore( container, body.firstChild );
1425
1426 // Construct the test element
1427 div = document.createElement("div");
1428 container.appendChild( div );
1429
1430 // Check if table cells still have offsetWidth/Height when they are set
1431 // to display:none and there are still other visible table cells in a
1432 // table row; if so, offsetWidth/Height are not reliable for use when
1433 // determining if an element has been hidden directly using
1434 // display:none (it is still safe to use offsets if a parent element is
1435 // hidden; don safety goggles and see bug #4512 for more information).
1436 // (only IE 8 fails this test)
1437 div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
1438 tds = div.getElementsByTagName("td");
1439 tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
1440 isSupported = ( tds[ 0 ].offsetHeight === 0 );
1441
1442 tds[ 0 ].style.display = "";
1443 tds[ 1 ].style.display = "none";
1444
1445 // Check if empty table cells still have offsetWidth/Height
1446 // (IE <= 8 fail this test)
1447 support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
1448
1449 // Check box-sizing and margin behavior
1450 div.innerHTML = "";
1451 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%;";
1452 support.boxSizing = ( div.offsetWidth === 4 );
1453 support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
1454
1455 // NOTE: To any future maintainer, window.getComputedStyle was used here
1456 // instead of getComputedStyle because it gave a better gzip size.
1457 // The difference between window.getComputedStyle and getComputedStyle is
1458 // 7 bytes
1459 if ( window.getComputedStyle ) {
1460 support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
1461 support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
1462
1463 // Check if div with explicit width and no margin-right incorrectly
1464 // gets computed margin-right based on width of container. For more
1465 // info see bug #3333
1466 // Fails in WebKit before Feb 2011 nightlies
1467 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
1468 marginDiv = document.createElement("div");
1469 marginDiv.style.cssText = div.style.cssText = divReset;
1470 marginDiv.style.marginRight = marginDiv.style.width = "0";
1471 div.style.width = "1px";
1472 div.appendChild( marginDiv );
1473 support.reliableMarginRight =
1474 !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
1475 }
1476
1477 if ( typeof div.style.zoom !== "undefined" ) {
1478 // Check if natively block-level elements act like inline-block
1479 // elements when setting their display to 'inline' and giving
1480 // them layout
1481 // (IE < 8 does this)
1482 div.innerHTML = "";
1483 div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
1484 support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
1485
1486 // Check if elements with layout shrink-wrap their children
1487 // (IE 6 does this)
1488 div.style.display = "block";
1489 div.style.overflow = "visible";
1490 div.innerHTML = "<div></div>";
1491 div.firstChild.style.width = "5px";
1492 support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
1493
1494 container.style.zoom = 1;
1495 }
1496
1497 // Null elements to avoid leaks in IE
1498 body.removeChild( container );
1499 container = div = tds = marginDiv = null;
1500 });
1501
1502 // Null elements to avoid leaks in IE
1503 fragment.removeChild( div );
1504 all = a = select = opt = input = fragment = div = null;
1505
1506 return support;
1507 })();
1508 var rbrace = /^(?:\{.*\}|\[.*\])$/,
1509 rmultiDash = /([A-Z])/g;
1510
1511 jQuery.extend({
1512 cache: {},
1513
1514 deletedIds: [],
1515
1516 // Please use with caution
1517 uuid: 0,
1518
1519 // Unique for each copy of jQuery on the page
1520 // Non-digits removed to match rinlinejQuery
1521 expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
1522
1523 // The following elements throw uncatchable exceptions if you
1524 // attempt to add expando properties to them.
1525 noData: {
1526 "embed": true,
1527 // Ban all objects except for Flash (which handle expandos)
1528 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
1529 "applet": true
1530 },
1531
1532 hasData: function( elem ) {
1533 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
1534 return !!elem && !isEmptyDataObject( elem );
1535 },
1536
1537 data: function( elem, name, data, pvt /* Internal Use Only */ ) {
1538 if ( !jQuery.acceptData( elem ) ) {
1539 return;
1540 }
1541
1542 var thisCache, ret,
1543 internalKey = jQuery.expando,
1544 getByName = typeof name === "string",
1545
1546 // We have to handle DOM nodes and JS objects differently because IE6-7
1547 // can't GC object references properly across the DOM-JS boundary
1548 isNode = elem.nodeType,
1549
1550 // Only DOM nodes need the global jQuery cache; JS object data is
1551 // attached directly to the object so GC can occur automatically
1552 cache = isNode ? jQuery.cache : elem,
1553
1554 // Only defining an ID for JS objects if its cache already exists allows
1555 // the code to shortcut on the same path as a DOM node with no cache
1556 id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
1557
1558 // Avoid doing any more work than we need to when trying to get data on an
1559 // object that has no data at all
1560 if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
1561 return;
1562 }
1563
1564 if ( !id ) {
1565 // Only DOM nodes need a new unique ID for each element since their data
1566 // ends up in the global cache
1567 if ( isNode ) {
1568 elem[ internalKey ] = id = jQuery.deletedIds.pop() || ++jQuery.uuid;
1569 } else {
1570 id = internalKey;
1571 }
1572 }
1573
1574 if ( !cache[ id ] ) {
1575 cache[ id ] = {};
1576
1577 // Avoids exposing jQuery metadata on plain JS objects when the object
1578 // is serialized using JSON.stringify
1579 if ( !isNode ) {
1580 cache[ id ].toJSON = jQuery.noop;
1581 }
1582 }
1583
1584 // An object can be passed to jQuery.data instead of a key/value pair; this gets
1585 // shallow copied over onto the existing cache
1586 if ( typeof name === "object" || typeof name === "function" ) {
1587 if ( pvt ) {
1588 cache[ id ] = jQuery.extend( cache[ id ], name );
1589 } else {
1590 cache[ id ].data = jQuery.extend( cache[ id ].data, name );
1591 }
1592 }
1593
1594 thisCache = cache[ id ];
1595
1596 // jQuery data() is stored in a separate object inside the object's internal data
1597 // cache in order to avoid key collisions between internal data and user-defined
1598 // data.
1599 if ( !pvt ) {
1600 if ( !thisCache.data ) {
1601 thisCache.data = {};
1602 }
1603
1604 thisCache = thisCache.data;
1605 }
1606
1607 if ( data !== undefined ) {
1608 thisCache[ jQuery.camelCase( name ) ] = data;
1609 }
1610
1611 // Check for both converted-to-camel and non-converted data property names
1612 // If a data property was specified
1613 if ( getByName ) {
1614
1615 // First Try to find as-is property data
1616 ret = thisCache[ name ];
1617
1618 // Test for null|undefined property data
1619 if ( ret == null ) {
1620
1621 // Try to find the camelCased property
1622 ret = thisCache[ jQuery.camelCase( name ) ];
1623 }
1624 } else {
1625 ret = thisCache;
1626 }
1627
1628 return ret;
1629 },
1630
1631 removeData: function( elem, name, pvt /* Internal Use Only */ ) {
1632 if ( !jQuery.acceptData( elem ) ) {
1633 return;
1634 }
1635
1636 var thisCache, i, l,
1637
1638 isNode = elem.nodeType,
1639
1640 // See jQuery.data for more information
1641 cache = isNode ? jQuery.cache : elem,
1642 id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
1643
1644 // If there is already no cache entry for this object, there is no
1645 // purpose in continuing
1646 if ( !cache[ id ] ) {
1647 return;
1648 }
1649
1650 if ( name ) {
1651
1652 thisCache = pvt ? cache[ id ] : cache[ id ].data;
1653
1654 if ( thisCache ) {
1655
1656 // Support array or space separated string names for data keys
1657 if ( !jQuery.isArray( name ) ) {
1658
1659 // try the string as a key before any manipulation
1660 if ( name in thisCache ) {
1661 name = [ name ];
1662 } else {
1663
1664 // split the camel cased version by spaces unless a key with the spaces exists
1665 name = jQuery.camelCase( name );
1666 if ( name in thisCache ) {
1667 name = [ name ];
1668 } else {
1669 name = name.split(" ");
1670 }
1671 }
1672 }
1673
1674 for ( i = 0, l = name.length; i < l; i++ ) {
1675 delete thisCache[ name[i] ];
1676 }
1677
1678 // If there is no data left in the cache, we want to continue
1679 // and let the cache object itself get destroyed
1680 if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
1681 return;
1682 }
1683 }
1684 }
1685
1686 // See jQuery.data for more information
1687 if ( !pvt ) {
1688 delete cache[ id ].data;
1689
1690 // Don't destroy the parent cache unless the internal data object
1691 // had been the only thing left in it
1692 if ( !isEmptyDataObject( cache[ id ] ) ) {
1693 return;
1694 }
1695 }
1696
1697 // Destroy the cache
1698 if ( isNode ) {
1699 jQuery.cleanData( [ elem ], true );
1700
1701 // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
1702 } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
1703 delete cache[ id ];
1704
1705 // When all else fails, null
1706 } else {
1707 cache[ id ] = null;
1708 }
1709 },
1710
1711 // For internal use only.
1712 _data: function( elem, name, data ) {
1713 return jQuery.data( elem, name, data, true );
1714 },
1715
1716 // A method for determining if a DOM node can handle the data expando
1717 acceptData: function( elem ) {
1718 var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
1719
1720 // nodes accept data unless otherwise specified; rejection can be conditional
1721 return !noData || noData !== true && elem.getAttribute("classid") === noData;
1722 }
1723 });
1724
1725 jQuery.fn.extend({
1726 data: function( key, value ) {
1727 var parts, part, attr, name, l,
1728 elem = this[0],
1729 i = 0,
1730 data = null;
1731
1732 // Gets all values
1733 if ( key === undefined ) {
1734 if ( this.length ) {
1735 data = jQuery.data( elem );
1736
1737 if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
1738 attr = elem.attributes;
1739 for ( l = attr.length; i < l; i++ ) {
1740 name = attr[i].name;
1741
1742 if ( name.indexOf( "data-" ) === 0 ) {
1743 name = jQuery.camelCase( name.substring(5) );
1744
1745 dataAttr( elem, name, data[ name ] );
1746 }
1747 }
1748 jQuery._data( elem, "parsedAttrs", true );
1749 }
1750 }
1751
1752 return data;
1753 }
1754
1755 // Sets multiple values
1756 if ( typeof key === "object" ) {
1757 return this.each(function() {
1758 jQuery.data( this, key );
1759 });
1760 }
1761
1762 parts = key.split( ".", 2 );
1763 parts[1] = parts[1] ? "." + parts[1] : "";
1764 part = parts[1] + "!";
1765
1766 return jQuery.access( this, function( value ) {
1767
1768 if ( value === undefined ) {
1769 data = this.triggerHandler( "getData" + part, [ parts[0] ] );
1770
1771 // Try to fetch any internally stored data first
1772 if ( data === undefined && elem ) {
1773 data = jQuery.data( elem, key );
1774 data = dataAttr( elem, key, data );
1775 }
1776
1777 return data === undefined && parts[1] ?
1778 this.data( parts[0] ) :
1779 data;
1780 }
1781
1782 parts[1] = value;
1783 this.each(function() {
1784 var self = jQuery( this );
1785
1786 self.triggerHandler( "setData" + part, parts );
1787 jQuery.data( this, key, value );
1788 self.triggerHandler( "changeData" + part, parts );
1789 });
1790 }, null, value, arguments.length > 1, null, false );
1791 },
1792
1793 removeData: function( key ) {
1794 return this.each(function() {
1795 jQuery.removeData( this, key );
1796 });
1797 }
1798 });
1799
1800 function dataAttr( elem, key, data ) {
1801 // If nothing was found internally, try to fetch any
1802 // data from the HTML5 data-* attribute
1803 if ( data === undefined && elem.nodeType === 1 ) {
1804
1805 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
1806
1807 data = elem.getAttribute( name );
1808
1809 if ( typeof data === "string" ) {
1810 try {
1811 data = data === "true" ? true :
1812 data === "false" ? false :
1813 data === "null" ? null :
1814 // Only convert to a number if it doesn't change the string
1815 +data + "" === data ? +data :
1816 rbrace.test( data ) ? jQuery.parseJSON( data ) :
1817 data;
1818 } catch( e ) {}
1819
1820 // Make sure we set the data so it isn't changed later
1821 jQuery.data( elem, key, data );
1822
1823 } else {
1824 data = undefined;
1825 }
1826 }
1827
1828 return data;
1829 }
1830
1831 // checks a cache object for emptiness
1832 function isEmptyDataObject( obj ) {
1833 var name;
1834 for ( name in obj ) {
1835
1836 // if the public data object is empty, the private is still empty
1837 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
1838 continue;
1839 }
1840 if ( name !== "toJSON" ) {
1841 return false;
1842 }
1843 }
1844
1845 return true;
1846 }
1847 jQuery.extend({
1848 queue: function( elem, type, data ) {
1849 var queue;
1850
1851 if ( elem ) {
1852 type = ( type || "fx" ) + "queue";
1853 queue = jQuery._data( elem, type );
1854
1855 // Speed up dequeue by getting out quickly if this is just a lookup
1856 if ( data ) {
1857 if ( !queue || jQuery.isArray(data) ) {
1858 queue = jQuery._data( elem, type, jQuery.makeArray(data) );
1859 } else {
1860 queue.push( data );
1861 }
1862 }
1863 return queue || [];
1864 }
1865 },
1866
1867 dequeue: function( elem, type ) {
1868 type = type || "fx";
1869
1870 var queue = jQuery.queue( elem, type ),
1871 fn = queue.shift(),
1872 hooks = jQuery._queueHooks( elem, type ),
1873 next = function() {
1874 jQuery.dequeue( elem, type );
1875 };
1876
1877 // If the fx queue is dequeued, always remove the progress sentinel
1878 if ( fn === "inprogress" ) {
1879 fn = queue.shift();
1880 }
1881
1882 if ( fn ) {
1883
1884 // Add a progress sentinel to prevent the fx queue from being
1885 // automatically dequeued
1886 if ( type === "fx" ) {
1887 queue.unshift( "inprogress" );
1888 }
1889
1890 // clear up the last queue stop function
1891 delete hooks.stop;
1892 fn.call( elem, next, hooks );
1893 }
1894 if ( !queue.length && hooks ) {
1895 hooks.empty.fire();
1896 }
1897 },
1898
1899 // not intended for public consumption - generates a queueHooks object, or returns the current one
1900 _queueHooks: function( elem, type ) {
1901 var key = type + "queueHooks";
1902 return jQuery._data( elem, key ) || jQuery._data( elem, key, {
1903 empty: jQuery.Callbacks("once memory").add(function() {
1904 jQuery.removeData( elem, type + "queue", true );
1905 jQuery.removeData( elem, key, true );
1906 })
1907 });
1908 }
1909 });
1910
1911 jQuery.fn.extend({
1912 queue: function( type, data ) {
1913 var setter = 2;
1914
1915 if ( typeof type !== "string" ) {
1916 data = type;
1917 type = "fx";
1918 setter--;
1919 }
1920
1921 if ( arguments.length < setter ) {
1922 return jQuery.queue( this[0], type );
1923 }
1924
1925 return data === undefined ?
1926 this :
1927 this.each(function() {
1928 var queue = jQuery.queue( this, type, data );
1929
1930 // ensure a hooks for this queue
1931 jQuery._queueHooks( this, type );
1932
1933 if ( type === "fx" && queue[0] !== "inprogress" ) {
1934 jQuery.dequeue( this, type );
1935 }
1936 });
1937 },
1938 dequeue: function( type ) {
1939 return this.each(function() {
1940 jQuery.dequeue( this, type );
1941 });
1942 },
1943 // Based off of the plugin by Clint Helfers, with permission.
1944 // http://blindsignals.com/index.php/2009/07/jquery-delay/
1945 delay: function( time, type ) {
1946 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
1947 type = type || "fx";
1948
1949 return this.queue( type, function( next, hooks ) {
1950 var timeout = setTimeout( next, time );
1951 hooks.stop = function() {
1952 clearTimeout( timeout );
1953 };
1954 });
1955 },
1956 clearQueue: function( type ) {
1957 return this.queue( type || "fx", [] );
1958 },
1959 // Get a promise resolved when queues of a certain type
1960 // are emptied (fx is the type by default)
1961 promise: function( type, obj ) {
1962 var tmp,
1963 count = 1,
1964 defer = jQuery.Deferred(),
1965 elements = this,
1966 i = this.length,
1967 resolve = function() {
1968 if ( !( --count ) ) {
1969 defer.resolveWith( elements, [ elements ] );
1970 }
1971 };
1972
1973 if ( typeof type !== "string" ) {
1974 obj = type;
1975 type = undefined;
1976 }
1977 type = type || "fx";
1978
1979 while( i-- ) {
1980 if ( (tmp = jQuery._data( elements[ i ], type + "queueHooks" )) && tmp.empty ) {
1981 count++;
1982 tmp.empty.add( resolve );
1983 }
1984 }
1985 resolve();
1986 return defer.promise( obj );
1987 }
1988 });
1989 var nodeHook, boolHook, fixSpecified,
1990 rclass = /[\t\r\n]/g,
1991 rreturn = /\r/g,
1992 rtype = /^(?:button|input)$/i,
1993 rfocusable = /^(?:button|input|object|select|textarea)$/i,
1994 rclickable = /^a(?:rea|)$/i,
1995 rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
1996 getSetAttribute = jQuery.support.getSetAttribute;
1997
1998 jQuery.fn.extend({
1999 attr: function( name, value ) {
2000 return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
2001 },
2002
2003 removeAttr: function( name ) {
2004 return this.each(function() {
2005 jQuery.removeAttr( this, name );
2006 });
2007 },
2008
2009 prop: function( name, value ) {
2010 return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
2011 },
2012
2013 removeProp: function( name ) {
2014 name = jQuery.propFix[ name ] || name;
2015 return this.each(function() {
2016 // try/catch handles cases where IE balks (such as removing a property on window)
2017 try {
2018 this[ name ] = undefined;
2019 delete this[ name ];
2020 } catch( e ) {}
2021 });
2022 },
2023
2024 addClass: function( value ) {
2025 var classNames, i, l, elem,
2026 setClass, c, cl;
2027
2028 if ( jQuery.isFunction( value ) ) {
2029 return this.each(function( j ) {
2030 jQuery( this ).addClass( value.call(this, j, this.className) );
2031 });
2032 }
2033
2034 if ( value && typeof value === "string" ) {
2035 classNames = value.split( core_rspace );
2036
2037 for ( i = 0, l = this.length; i < l; i++ ) {
2038 elem = this[ i ];
2039
2040 if ( elem.nodeType === 1 ) {
2041 if ( !elem.className && classNames.length === 1 ) {
2042 elem.className = value;
2043
2044 } else {
2045 setClass = " " + elem.className + " ";
2046
2047 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
2048 if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
2049 setClass += classNames[ c ] + " ";
2050 }
2051 }
2052 elem.className = jQuery.trim( setClass );
2053 }
2054 }
2055 }
2056 }
2057
2058 return this;
2059 },
2060
2061 removeClass: function( value ) {
2062 var removes, className, elem, c, cl, i, l;
2063
2064 if ( jQuery.isFunction( value ) ) {
2065 return this.each(function( j ) {
2066 jQuery( this ).removeClass( value.call(this, j, this.className) );
2067 });
2068 }
2069 if ( (value && typeof value === "string") || value === undefined ) {
2070 removes = ( value || "" ).split( core_rspace );
2071
2072 for ( i = 0, l = this.length; i < l; i++ ) {
2073 elem = this[ i ];
2074 if ( elem.nodeType === 1 && elem.className ) {
2075
2076 className = (" " + elem.className + " ").replace( rclass, " " );
2077
2078 // loop over each item in the removal list
2079 for ( c = 0, cl = removes.length; c < cl; c++ ) {
2080 // Remove until there is nothing to remove,
2081 while ( className.indexOf(" " + removes[ c ] + " ") > -1 ) {
2082 className = className.replace( " " + removes[ c ] + " " , " " );
2083 }
2084 }
2085 elem.className = value ? jQuery.trim( className ) : "";
2086 }
2087 }
2088 }
2089
2090 return this;
2091 },
2092
2093 toggleClass: function( value, stateVal ) {
2094 var type = typeof value,
2095 isBool = typeof stateVal === "boolean";
2096
2097 if ( jQuery.isFunction( value ) ) {
2098 return this.each(function( i ) {
2099 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
2100 });
2101 }
2102
2103 return this.each(function() {
2104 if ( type === "string" ) {
2105 // toggle individual class names
2106 var className,
2107 i = 0,
2108 self = jQuery( this ),
2109 state = stateVal,
2110 classNames = value.split( core_rspace );
2111
2112 while ( (className = classNames[ i++ ]) ) {
2113 // check each className given, space separated list
2114 state = isBool ? state : !self.hasClass( className );
2115 self[ state ? "addClass" : "removeClass" ]( className );
2116 }
2117
2118 } else if ( type === "undefined" || type === "boolean" ) {
2119 if ( this.className ) {
2120 // store className if set
2121 jQuery._data( this, "__className__", this.className );
2122 }
2123
2124 // toggle whole className
2125 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2126 }
2127 });
2128 },
2129
2130 hasClass: function( selector ) {
2131 var className = " " + selector + " ",
2132 i = 0,
2133 l = this.length;
2134 for ( ; i < l; i++ ) {
2135 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
2136 return true;
2137 }
2138 }
2139
2140 return false;
2141 },
2142
2143 val: function( value ) {
2144 var hooks, ret, isFunction,
2145 elem = this[0];
2146
2147 if ( !arguments.length ) {
2148 if ( elem ) {
2149 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
2150
2151 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
2152 return ret;
2153 }
2154
2155 ret = elem.value;
2156
2157 return typeof ret === "string" ?
2158 // handle most common string cases
2159 ret.replace(rreturn, "") :
2160 // handle cases where value is null/undef or number
2161 ret == null ? "" : ret;
2162 }
2163
2164 return;
2165 }
2166
2167 isFunction = jQuery.isFunction( value );
2168
2169 return this.each(function( i ) {
2170 var val,
2171 self = jQuery(this);
2172
2173 if ( this.nodeType !== 1 ) {
2174 return;
2175 }
2176
2177 if ( isFunction ) {
2178 val = value.call( this, i, self.val() );
2179 } else {
2180 val = value;
2181 }
2182
2183 // Treat null/undefined as ""; convert numbers to string
2184 if ( val == null ) {
2185 val = "";
2186 } else if ( typeof val === "number" ) {
2187 val += "";
2188 } else if ( jQuery.isArray( val ) ) {
2189 val = jQuery.map(val, function ( value ) {
2190 return value == null ? "" : value + "";
2191 });
2192 }
2193
2194 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
2195
2196 // If set returns undefined, fall back to normal setting
2197 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
2198 this.value = val;
2199 }
2200 });
2201 }
2202 });
2203
2204 jQuery.extend({
2205 valHooks: {
2206 option: {
2207 get: function( elem ) {
2208 // attributes.value is undefined in Blackberry 4.7 but
2209 // uses .value. See #6932
2210 var val = elem.attributes.value;
2211 return !val || val.specified ? elem.value : elem.text;
2212 }
2213 },
2214 select: {
2215 get: function( elem ) {
2216 var value, i, max, option,
2217 index = elem.selectedIndex,
2218 values = [],
2219 options = elem.options,
2220 one = elem.type === "select-one";
2221
2222 // Nothing was selected
2223 if ( index < 0 ) {
2224 return null;
2225 }
2226
2227 // Loop through all the selected options
2228 i = one ? index : 0;
2229 max = one ? index + 1 : options.length;
2230 for ( ; i < max; i++ ) {
2231 option = options[ i ];
2232
2233 // Don't return options that are disabled or in a disabled optgroup
2234 if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
2235 (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
2236
2237 // Get the specific value for the option
2238 value = jQuery( option ).val();
2239
2240 // We don't need an array for one selects
2241 if ( one ) {
2242 return value;
2243 }
2244
2245 // Multi-Selects return an array
2246 values.push( value );
2247 }
2248 }
2249
2250 // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
2251 if ( one && !values.length && options.length ) {
2252 return jQuery( options[ index ] ).val();
2253 }
2254
2255 return values;
2256 },
2257
2258 set: function( elem, value ) {
2259 var values = jQuery.makeArray( value );
2260
2261 jQuery(elem).find("option").each(function() {
2262 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
2263 });
2264
2265 if ( !values.length ) {
2266 elem.selectedIndex = -1;
2267 }
2268 return values;
2269 }
2270 }
2271 },
2272
2273 // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9
2274 attrFn: {},
2275
2276 attr: function( elem, name, value, pass ) {
2277 var ret, hooks, notxml,
2278 nType = elem.nodeType;
2279
2280 // don't get/set attributes on text, comment and attribute nodes
2281 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2282 return;
2283 }
2284
2285 if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {
2286 return jQuery( elem )[ name ]( value );
2287 }
2288
2289 // Fallback to prop when attributes are not supported
2290 if ( typeof elem.getAttribute === "undefined" ) {
2291 return jQuery.prop( elem, name, value );
2292 }
2293
2294 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2295
2296 // All attributes are lowercase
2297 // Grab necessary hook if one is defined
2298 if ( notxml ) {
2299 name = name.toLowerCase();
2300 hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
2301 }
2302
2303 if ( value !== undefined ) {
2304
2305 if ( value === null ) {
2306 jQuery.removeAttr( elem, name );
2307 return;
2308
2309 } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
2310 return ret;
2311
2312 } else {
2313 elem.setAttribute( name, "" + value );
2314 return value;
2315 }
2316
2317 } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
2318 return ret;
2319
2320 } else {
2321
2322 ret = elem.getAttribute( name );
2323
2324 // Non-existent attributes return null, we normalize to undefined
2325 return ret === null ?
2326 undefined :
2327 ret;
2328 }
2329 },
2330
2331 removeAttr: function( elem, value ) {
2332 var propName, attrNames, name, isBool,
2333 i = 0;
2334
2335 if ( value && elem.nodeType === 1 ) {
2336
2337 attrNames = value.split( core_rspace );
2338
2339 for ( ; i < attrNames.length; i++ ) {
2340 name = attrNames[ i ];
2341
2342 if ( name ) {
2343 propName = jQuery.propFix[ name ] || name;
2344 isBool = rboolean.test( name );
2345
2346 // See #9699 for explanation of this approach (setting first, then removal)
2347 // Do not do this for boolean attributes (see #10870)
2348 if ( !isBool ) {
2349 jQuery.attr( elem, name, "" );
2350 }
2351 elem.removeAttribute( getSetAttribute ? name : propName );
2352
2353 // Set corresponding property to false for boolean attributes
2354 if ( isBool && propName in elem ) {
2355 elem[ propName ] = false;
2356 }
2357 }
2358 }
2359 }
2360 },
2361
2362 attrHooks: {
2363 type: {
2364 set: function( elem, value ) {
2365 // We can't allow the type property to be changed (since it causes problems in IE)
2366 if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
2367 jQuery.error( "type property can't be changed" );
2368 } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
2369 // Setting the type on a radio button after the value resets the value in IE6-9
2370 // Reset value to it's default in case type is set after value
2371 // This is for element creation
2372 var val = elem.value;
2373 elem.setAttribute( "type", value );
2374 if ( val ) {
2375 elem.value = val;
2376 }
2377 return value;
2378 }
2379 }
2380 },
2381 // Use the value property for back compat
2382 // Use the nodeHook for button elements in IE6/7 (#1954)
2383 value: {
2384 get: function( elem, name ) {
2385 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
2386 return nodeHook.get( elem, name );
2387 }
2388 return name in elem ?
2389 elem.value :
2390 null;
2391 },
2392 set: function( elem, value, name ) {
2393 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
2394 return nodeHook.set( elem, value, name );
2395 }
2396 // Does not return so that setAttribute is also used
2397 elem.value = value;
2398 }
2399 }
2400 },
2401
2402 propFix: {
2403 tabindex: "tabIndex",
2404 readonly: "readOnly",
2405 "for": "htmlFor",
2406 "class": "className",
2407 maxlength: "maxLength",
2408 cellspacing: "cellSpacing",
2409 cellpadding: "cellPadding",
2410 rowspan: "rowSpan",
2411 colspan: "colSpan",
2412 usemap: "useMap",
2413 frameborder: "frameBorder",
2414 contenteditable: "contentEditable"
2415 },
2416
2417 prop: function( elem, name, value ) {
2418 var ret, hooks, notxml,
2419 nType = elem.nodeType;
2420
2421 // don't get/set properties on text, comment and attribute nodes
2422 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2423 return;
2424 }
2425
2426 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2427
2428 if ( notxml ) {
2429 // Fix name and attach hooks
2430 name = jQuery.propFix[ name ] || name;
2431 hooks = jQuery.propHooks[ name ];
2432 }
2433
2434 if ( value !== undefined ) {
2435 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2436 return ret;
2437
2438 } else {
2439 return ( elem[ name ] = value );
2440 }
2441
2442 } else {
2443 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2444 return ret;
2445
2446 } else {
2447 return elem[ name ];
2448 }
2449 }
2450 },
2451
2452 propHooks: {
2453 tabIndex: {
2454 get: function( elem ) {
2455 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
2456 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
2457 var attributeNode = elem.getAttributeNode("tabindex");
2458
2459 return attributeNode && attributeNode.specified ?
2460 parseInt( attributeNode.value, 10 ) :
2461 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
2462 0 :
2463 undefined;
2464 }
2465 }
2466 }
2467 });
2468
2469 // Hook for boolean attributes
2470 boolHook = {
2471 get: function( elem, name ) {
2472 // Align boolean attributes with corresponding properties
2473 // Fall back to attribute presence where some booleans are not supported
2474 var attrNode,
2475 property = jQuery.prop( elem, name );
2476 return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
2477 name.toLowerCase() :
2478 undefined;
2479 },
2480 set: function( elem, value, name ) {
2481 var propName;
2482 if ( value === false ) {
2483 // Remove boolean attributes when set to false
2484 jQuery.removeAttr( elem, name );
2485 } else {
2486 // value is true since we know at this point it's type boolean and not false
2487 // Set boolean attributes to the same name and set the DOM property
2488 propName = jQuery.propFix[ name ] || name;
2489 if ( propName in elem ) {
2490 // Only set the IDL specifically if it already exists on the element
2491 elem[ propName ] = true;
2492 }
2493
2494 elem.setAttribute( name, name.toLowerCase() );
2495 }
2496 return name;
2497 }
2498 };
2499
2500 // IE6/7 do not support getting/setting some attributes with get/setAttribute
2501 if ( !getSetAttribute ) {
2502
2503 fixSpecified = {
2504 name: true,
2505 id: true,
2506 coords: true
2507 };
2508
2509 // Use this for any attribute in IE6/7
2510 // This fixes almost every IE6/7 issue
2511 nodeHook = jQuery.valHooks.button = {
2512 get: function( elem, name ) {
2513 var ret;
2514 ret = elem.getAttributeNode( name );
2515 return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ?
2516 ret.value :
2517 undefined;
2518 },
2519 set: function( elem, value, name ) {
2520 // Set the existing or create a new attribute node
2521 var ret = elem.getAttributeNode( name );
2522 if ( !ret ) {
2523 ret = document.createAttribute( name );
2524 elem.setAttributeNode( ret );
2525 }
2526 return ( ret.value = value + "" );
2527 }
2528 };
2529
2530 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
2531 // This is for removals
2532 jQuery.each([ "width", "height" ], function( i, name ) {
2533 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2534 set: function( elem, value ) {
2535 if ( value === "" ) {
2536 elem.setAttribute( name, "auto" );
2537 return value;
2538 }
2539 }
2540 });
2541 });
2542
2543 // Set contenteditable to false on removals(#10429)
2544 // Setting to empty string throws an error as an invalid value
2545 jQuery.attrHooks.contenteditable = {
2546 get: nodeHook.get,
2547 set: function( elem, value, name ) {
2548 if ( value === "" ) {
2549 value = "false";
2550 }
2551 nodeHook.set( elem, value, name );
2552 }
2553 };
2554 }
2555
2556
2557 // Some attributes require a special call on IE
2558 if ( !jQuery.support.hrefNormalized ) {
2559 jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
2560 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2561 get: function( elem ) {
2562 var ret = elem.getAttribute( name, 2 );
2563 return ret === null ? undefined : ret;
2564 }
2565 });
2566 });
2567 }
2568
2569 if ( !jQuery.support.style ) {
2570 jQuery.attrHooks.style = {
2571 get: function( elem ) {
2572 // Return undefined in the case of empty string
2573 // Normalize to lowercase since IE uppercases css property names
2574 return elem.style.cssText.toLowerCase() || undefined;
2575 },
2576 set: function( elem, value ) {
2577 return ( elem.style.cssText = "" + value );
2578 }
2579 };
2580 }
2581
2582 // Safari mis-reports the default selected property of an option
2583 // Accessing the parent's selectedIndex property fixes it
2584 if ( !jQuery.support.optSelected ) {
2585 jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
2586 get: function( elem ) {
2587 var parent = elem.parentNode;
2588
2589 if ( parent ) {
2590 parent.selectedIndex;
2591
2592 // Make sure that it also works with optgroups, see #5701
2593 if ( parent.parentNode ) {
2594 parent.parentNode.selectedIndex;
2595 }
2596 }
2597 return null;
2598 }
2599 });
2600 }
2601
2602 // IE6/7 call enctype encoding
2603 if ( !jQuery.support.enctype ) {
2604 jQuery.propFix.enctype = "encoding";
2605 }
2606
2607 // Radios and checkboxes getter/setter
2608 if ( !jQuery.support.checkOn ) {
2609 jQuery.each([ "radio", "checkbox" ], function() {
2610 jQuery.valHooks[ this ] = {
2611 get: function( elem ) {
2612 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
2613 return elem.getAttribute("value") === null ? "on" : elem.value;
2614 }
2615 };
2616 });
2617 }
2618 jQuery.each([ "radio", "checkbox" ], function() {
2619 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
2620 set: function( elem, value ) {
2621 if ( jQuery.isArray( value ) ) {
2622 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
2623 }
2624 }
2625 });
2626 });
2627 var rformElems = /^(?:textarea|input|select)$/i,
2628 rtypenamespace = /^([^\.]*|)(?:\.(.+)|)$/,
2629 rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
2630 rkeyEvent = /^key/,
2631 rmouseEvent = /^(?:mouse|contextmenu)|click/,
2632 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
2633 hoverHack = function( events ) {
2634 return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
2635 };
2636
2637 /*
2638 * Helper functions for managing events -- not part of the public interface.
2639 * Props to Dean Edwards' addEvent library for many of the ideas.
2640 */
2641 jQuery.event = {
2642
2643 add: function( elem, types, handler, data, selector ) {
2644
2645 var elemData, eventHandle, events,
2646 t, tns, type, namespaces, handleObj,
2647 handleObjIn, handlers, special;
2648
2649 // Don't attach events to noData or text/comment nodes (allow plain objects tho)
2650 if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
2651 return;
2652 }
2653
2654 // Caller can pass in an object of custom data in lieu of the handler
2655 if ( handler.handler ) {
2656 handleObjIn = handler;
2657 handler = handleObjIn.handler;
2658 selector = handleObjIn.selector;
2659 }
2660
2661 // Make sure that the handler has a unique ID, used to find/remove it later
2662 if ( !handler.guid ) {
2663 handler.guid = jQuery.guid++;
2664 }
2665
2666 // Init the element's event structure and main handler, if this is the first
2667 events = elemData.events;
2668 if ( !events ) {
2669 elemData.events = events = {};
2670 }
2671 eventHandle = elemData.handle;
2672 if ( !eventHandle ) {
2673 elemData.handle = eventHandle = function( e ) {
2674 // Discard the second event of a jQuery.event.trigger() and
2675 // when an event is called after a page has unloaded
2676 return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
2677 jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
2678 undefined;
2679 };
2680 // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
2681 eventHandle.elem = elem;
2682 }
2683
2684 // Handle multiple events separated by a space
2685 // jQuery(...).bind("mouseover mouseout", fn);
2686 types = jQuery.trim( hoverHack(types) ).split( " " );
2687 for ( t = 0; t < types.length; t++ ) {
2688
2689 tns = rtypenamespace.exec( types[t] ) || [];
2690 type = tns[1];
2691 namespaces = ( tns[2] || "" ).split( "." ).sort();
2692
2693 // If event changes its type, use the special event handlers for the changed type
2694 special = jQuery.event.special[ type ] || {};
2695
2696 // If selector defined, determine special event api type, otherwise given type
2697 type = ( selector ? special.delegateType : special.bindType ) || type;
2698
2699 // Update special based on newly reset type
2700 special = jQuery.event.special[ type ] || {};
2701
2702 // handleObj is passed to all event handlers
2703 handleObj = jQuery.extend({
2704 type: type,
2705 origType: tns[1],
2706 data: data,
2707 handler: handler,
2708 guid: handler.guid,
2709 selector: 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][0];
2937 event.type = eventPath[i][1];
2938
2939 handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
2940 if ( handle ) {
2941 handle.apply( cur, data );
2942 }
2943 // Note that this is a bare JS function and not a jQuery handler
2944 handle = ontype && cur[ ontype ];
2945 if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
2946 event.preventDefault();
2947 }
2948 }
2949 event.type = type;
2950
2951 // If nobody prevented the default action, do it now
2952 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
2953
2954 if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
2955 !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
2956
2957 // Call a native DOM method on the target with the same name name as the event.
2958 // Can't use an .isFunction() check here because IE6/7 fails that test.
2959 // Don't do default actions on window, that's where global variables be (#6170)
2960 // IE<9 dies on focus/blur to hidden element (#1486)
2961 if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
2962
2963 // Don't re-trigger an onFOO event when we call its FOO() method
2964 old = elem[ ontype ];
2965
2966 if ( old ) {
2967 elem[ ontype ] = null;
2968 }
2969
2970 // Prevent re-triggering of the same event, since we already bubbled it above
2971 jQuery.event.triggered = type;
2972 elem[ type ]();
2973 jQuery.event.triggered = undefined;
2974
2975 if ( old ) {
2976 elem[ ontype ] = old;
2977 }
2978 }
2979 }
2980 }
2981
2982 return event.result;
2983 },
2984
2985 dispatch: function( event ) {
2986
2987 // Make a writable jQuery.Event from the native event object
2988 event = jQuery.event.fix( event || window.event );
2989
2990 var i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related,
2991 handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
2992 delegateCount = handlers.delegateCount,
2993 args = [].slice.call( arguments ),
2994 run_all = !event.exclusive && !event.namespace,
2995 special = jQuery.event.special[ event.type ] || {},
2996 handlerQueue = [];
2997
2998 // Use the fix-ed jQuery.Event rather than the (read-only) native event
2999 args[0] = event;
3000 event.delegateTarget = this;
3001
3002 // Call the preDispatch hook for the mapped type, and let it bail if desired
3003 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
3004 return;
3005 }
3006
3007 // Determine handlers that should run if there are delegated events
3008 // Avoid non-left-click bubbling in Firefox (#3861)
3009 if ( delegateCount && !(event.button && event.type === "click") ) {
3010
3011 // Pregenerate a single jQuery object for reuse with .is()
3012 jqcur = jQuery(this);
3013 jqcur.context = this;
3014
3015 for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
3016
3017 // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #xxxx)
3018 if ( cur.disabled !== true || event.type !== "click" ) {
3019 selMatch = {};
3020 matches = [];
3021 jqcur[0] = cur;
3022 for ( i = 0; i < delegateCount; i++ ) {
3023 handleObj = handlers[ i ];
3024 sel = handleObj.selector;
3025
3026 if ( selMatch[ sel ] === undefined ) {
3027 selMatch[ sel ] = jqcur.is( sel );
3028 }
3029 if ( selMatch[ sel ] ) {
3030 matches.push( handleObj );
3031 }
3032 }
3033 if ( matches.length ) {
3034 handlerQueue.push({ elem: cur, matches: matches });
3035 }
3036 }
3037 }
3038 }
3039
3040 // Add the remaining (directly-bound) handlers
3041 if ( handlers.length > delegateCount ) {
3042 handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
3043 }
3044
3045 // Run delegates first; they may want to stop propagation beneath us
3046 for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
3047 matched = handlerQueue[ i ];
3048 event.currentTarget = matched.elem;
3049
3050 for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
3051 handleObj = matched.matches[ j ];
3052
3053 // Triggered event must either 1) be non-exclusive and have no namespace, or
3054 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
3055 if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
3056
3057 event.data = handleObj.data;
3058 event.handleObj = handleObj;
3059
3060 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
3061 .apply( matched.elem, args );
3062
3063 if ( ret !== undefined ) {
3064 event.result = ret;
3065 if ( ret === false ) {
3066 event.preventDefault();
3067 event.stopPropagation();
3068 }
3069 }
3070 }
3071 }
3072 }
3073
3074 // Call the postDispatch hook for the mapped type
3075 if ( special.postDispatch ) {
3076 special.postDispatch.call( this, event );
3077 }
3078
3079 return event.result;
3080 },
3081
3082 // Includes some event props shared by KeyEvent and MouseEvent
3083 // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
3084 props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
3085
3086 fixHooks: {},
3087
3088 keyHooks: {
3089 props: "char charCode key keyCode".split(" "),
3090 filter: function( event, original ) {
3091
3092 // Add which for key events
3093 if ( event.which == null ) {
3094 event.which = original.charCode != null ? original.charCode : original.keyCode;
3095 }
3096
3097 return event;
3098 }
3099 },
3100
3101 mouseHooks: {
3102 props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
3103 filter: function( event, original ) {
3104 var eventDoc, doc, body,
3105 button = original.button,
3106 fromElement = original.fromElement;
3107
3108 // Calculate pageX/Y if missing and clientX/Y available
3109 if ( event.pageX == null && original.clientX != null ) {
3110 eventDoc = event.target.ownerDocument || document;
3111 doc = eventDoc.documentElement;
3112 body = eventDoc.body;
3113
3114 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
3115 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
3116 }
3117
3118 // Add relatedTarget, if necessary
3119 if ( !event.relatedTarget && fromElement ) {
3120 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
3121 }
3122
3123 // Add which for click: 1 === left; 2 === middle; 3 === right
3124 // Note: button is not normalized, so don't use it
3125 if ( !event.which && button !== undefined ) {
3126 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
3127 }
3128
3129 return event;
3130 }
3131 },
3132
3133 fix: function( event ) {
3134 if ( event[ jQuery.expando ] ) {
3135 return event;
3136 }
3137
3138 // Create a writable copy of the event object and normalize some properties
3139 var i, prop,
3140 originalEvent = event,
3141 fixHook = jQuery.event.fixHooks[ event.type ] || {},
3142 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
3143
3144 event = jQuery.Event( originalEvent );
3145
3146 for ( i = copy.length; i; ) {
3147 prop = copy[ --i ];
3148 event[ prop ] = originalEvent[ prop ];
3149 }
3150
3151 // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
3152 if ( !event.target ) {
3153 event.target = originalEvent.srcElement || document;
3154 }
3155
3156 // Target should not be a text node (#504, Safari)
3157 if ( event.target.nodeType === 3 ) {
3158 event.target = event.target.parentNode;
3159 }
3160
3161 // For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8)
3162 event.metaKey = !!event.metaKey;
3163
3164 return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
3165 },
3166
3167 special: {
3168 ready: {
3169 // Make sure the ready event is setup
3170 setup: jQuery.bindReady
3171 },
3172
3173 load: {
3174 // Prevent triggered image.load events from bubbling to window.load
3175 noBubble: true
3176 },
3177
3178 focus: {
3179 delegateType: "focusin"
3180 },
3181 blur: {
3182 delegateType: "focusout"
3183 },
3184
3185 beforeunload: {
3186 setup: function( data, namespaces, eventHandle ) {
3187 // We only want to do this special case on windows
3188 if ( jQuery.isWindow( this ) ) {
3189 this.onbeforeunload = eventHandle;
3190 }
3191 },
3192
3193 teardown: function( namespaces, eventHandle ) {
3194 if ( this.onbeforeunload === eventHandle ) {
3195 this.onbeforeunload = null;
3196 }
3197 }
3198 }
3199 },
3200
3201 simulate: function( type, elem, event, bubble ) {
3202 // Piggyback on a donor event to simulate a different one.
3203 // Fake originalEvent to avoid donor's stopPropagation, but if the
3204 // simulated event prevents default then we do the same on the donor.
3205 var e = jQuery.extend(
3206 new jQuery.Event(),
3207 event,
3208 { type: type,
3209 isSimulated: true,
3210 originalEvent: {}
3211 }
3212 );
3213 if ( bubble ) {
3214 jQuery.event.trigger( e, null, elem );
3215 } else {
3216 jQuery.event.dispatch.call( elem, e );
3217 }
3218 if ( e.isDefaultPrevented() ) {
3219 event.preventDefault();
3220 }
3221 }
3222 };
3223
3224 // Some plugins are using, but it's undocumented/deprecated and will be removed.
3225 // The 1.7 special event interface should provide all the hooks needed now.
3226 jQuery.event.handle = jQuery.event.dispatch;
3227
3228 jQuery.removeEvent = document.removeEventListener ?
3229 function( elem, type, handle ) {
3230 if ( elem.removeEventListener ) {
3231 elem.removeEventListener( type, handle, false );
3232 }
3233 } :
3234 function( elem, type, handle ) {
3235 var name = "on" + type;
3236
3237 if ( elem.detachEvent ) {
3238
3239 // #8545, #7054, preventing memory leaks for custom events in IE6-8 –
3240 // detachEvent needed property on element, by name of that event, to properly expose it to GC
3241 if ( typeof elem[ name ] === "undefined" ) {
3242 elem[ name ] = null;
3243 }
3244
3245 elem.detachEvent( name, handle );
3246 }
3247 };
3248
3249 jQuery.Event = function( src, props ) {
3250 // Allow instantiation without the 'new' keyword
3251 if ( !(this instanceof jQuery.Event) ) {
3252 return new jQuery.Event( src, props );
3253 }
3254
3255 // Event object
3256 if ( src && src.type ) {
3257 this.originalEvent = src;
3258 this.type = src.type;
3259
3260 // Events bubbling up the document may have been marked as prevented
3261 // by a handler lower down the tree; reflect the correct value.
3262 this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
3263 src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
3264
3265 // Event type
3266 } else {
3267 this.type = src;
3268 }
3269
3270 // Put explicitly provided properties onto the event object
3271 if ( props ) {
3272 jQuery.extend( this, props );
3273 }
3274
3275 // Create a timestamp if incoming event doesn't have one
3276 this.timeStamp = src && src.timeStamp || jQuery.now();
3277
3278 // Mark it as fixed
3279 this[ jQuery.expando ] = true;
3280 };
3281
3282 function returnFalse() {
3283 return false;
3284 }
3285 function returnTrue() {
3286 return true;
3287 }
3288
3289 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
3290 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
3291 jQuery.Event.prototype = {
3292 preventDefault: function() {
3293 this.isDefaultPrevented = returnTrue;
3294
3295 var e = this.originalEvent;
3296 if ( !e ) {
3297 return;
3298 }
3299
3300 // if preventDefault exists run it on the original event
3301 if ( e.preventDefault ) {
3302 e.preventDefault();
3303
3304 // otherwise set the returnValue property of the original event to false (IE)
3305 } else {
3306 e.returnValue = false;
3307 }
3308 },
3309 stopPropagation: function() {
3310 this.isPropagationStopped = returnTrue;
3311
3312 var e = this.originalEvent;
3313 if ( !e ) {
3314 return;
3315 }
3316 // if stopPropagation exists run it on the original event
3317 if ( e.stopPropagation ) {
3318 e.stopPropagation();
3319 }
3320 // otherwise set the cancelBubble property of the original event to true (IE)
3321 e.cancelBubble = true;
3322 },
3323 stopImmediatePropagation: function() {
3324 this.isImmediatePropagationStopped = returnTrue;
3325 this.stopPropagation();
3326 },
3327 isDefaultPrevented: returnFalse,
3328 isPropagationStopped: returnFalse,
3329 isImmediatePropagationStopped: returnFalse
3330 };
3331
3332 // Create mouseenter/leave events using mouseover/out and event-time checks
3333 jQuery.each({
3334 mouseenter: "mouseover",
3335 mouseleave: "mouseout"
3336 }, function( orig, fix ) {
3337 jQuery.event.special[ orig ] = {
3338 delegateType: fix,
3339 bindType: fix,
3340
3341 handle: function( event ) {
3342 var ret,
3343 target = this,
3344 related = event.relatedTarget,
3345 handleObj = event.handleObj,
3346 selector = handleObj.selector;
3347
3348 // For mousenter/leave call the handler if related is outside the target.
3349 // NB: No relatedTarget if the mouse left/entered the browser window
3350 if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
3351 event.type = handleObj.origType;
3352 ret = handleObj.handler.apply( this, arguments );
3353 event.type = fix;
3354 }
3355 return ret;
3356 }
3357 };
3358 });
3359
3360 // IE submit delegation
3361 if ( !jQuery.support.submitBubbles ) {
3362
3363 jQuery.event.special.submit = {
3364 setup: function() {
3365 // Only need this for delegated form submit events
3366 if ( jQuery.nodeName( this, "form" ) ) {