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