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