· 9 years ago · Sep 22, 2016, 05:32 PM
1/*
2* jQuery JavaScript Library v1.4.2
3* Copyright 2010, John Resig, http://jquery.com/
4* Distributed in whole under the terms of the MIT license
5* http://www.opensource.org/licenses/mit-license.php
6*
7* Includes Sizzle.js
8* http://sizzlejs.com/
9* Copyright 2010, The Dojo Foundation
10* Released under the MIT, BSD, and GPL Licenses.
11*/
12(function( window, undefined ) {
13
14// Define a local copy of jQuery
15var jQuery = function( selector, context ) {
16 // The jQuery object is actually just the init constructor 'enhanced'
17 return new jQuery.fn.init( selector, context );
18 },
19
20 // Map over jQuery in case of overwrite
21 _jQuery = window.jQuery,
22
23 // Map over the $ in case of overwrite
24 _$ = window.$,
25
26 // Use the correct document accordingly with window argument (sandbox)
27 document = window.document,
28
29 // A central reference to the root jQuery(document)
30 rootjQuery,
31
32 // A simple way to check for HTML strings or ID strings
33 // (both of which we optimize for)
34 quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,
35
36 // Is it a simple selector
37 isSimple = /^.[^:#\[\.,]*$/,
38
39 // Check if a string has a non-whitespace character in it
40 rnotwhite = /\S/,
41
42 // Used for trimming whitespace
43 rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g,
44
45 // Match a standalone tag
46 rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
47
48 // Keep a UserAgent string for use with jQuery.browser
49 userAgent = navigator.userAgent,
50
51 // For matching the engine and version of the browser
52 browserMatch,
53
54 // Has the ready events already been bound?
55 readyBound = false,
56
57 // The functions to execute on DOM ready
58 readyList = [],
59
60 // The ready event handler
61 DOMContentLoaded,
62
63 // Save a reference to some core methods
64 toString = Object.prototype.toString,
65 hasOwnProperty = Object.prototype.hasOwnProperty,
66 push = Array.prototype.push,
67 slice = Array.prototype.slice,
68 indexOf = Array.prototype.indexOf;
69
70jQuery.fn = jQuery.prototype = {
71 init: function( selector, context ) {
72 var match, elem, ret, doc;
73
74 // Handle $(""), $(null), or $(undefined)
75 if ( !selector ) {
76 return this;
77 }
78
79 // Handle $(DOMElement)
80 if ( selector.nodeType ) {
81 this.context = this[0] = selector;
82 this.length = 1;
83 return this;
84 }
85
86 // The body element only exists once, optimize finding it
87 if ( selector === "body" && !context ) {
88 this.context = document;
89 this[0] = document.body;
90 this.selector = "body";
91 this.length = 1;
92 return this;
93 }
94
95 // Handle HTML strings
96 if ( typeof selector === "string" ) {
97 // Are we dealing with HTML string or an ID?
98 match = quickExpr.exec( selector );
99
100 // Verify a match, and that no context was specified for #id
101 if ( match && (match[1] || !context) ) {
102
103 // HANDLE: $(html) -> $(array)
104 if ( match[1] ) {
105 doc = (context ? context.ownerDocument || context : document);
106
107 // If a single string is passed in and it's a single tag
108 // just do a createElement and skip the rest
109 ret = rsingleTag.exec( selector );
110
111 if ( ret ) {
112 if ( jQuery.isPlainObject( context ) ) {
113 selector = [ document.createElement( ret[1] ) ];
114 jQuery.fn.attr.call( selector, context, true );
115
116 } else {
117 selector = [ doc.createElement( ret[1] ) ];
118 }
119
120 } else {
121 ret = buildFragment( [ match[1] ], [ doc ] );
122 selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
123 }
124
125 return jQuery.merge( this, selector );
126
127 // HANDLE: $("#id")
128 } else {
129 elem = document.getElementById( match[2] );
130
131 if ( elem ) {
132 // Handle the case where IE and Opera return items
133 // by name instead of ID
134 if ( elem.id !== match[2] ) {
135 return rootjQuery.find( selector );
136 }
137
138 // Otherwise, we inject the element directly into the jQuery object
139 this.length = 1;
140 this[0] = elem;
141 }
142
143 this.context = document;
144 this.selector = selector;
145 return this;
146 }
147
148 // HANDLE: $("TAG")
149 } else if ( !context && /^\w+$/.test( selector ) ) {
150 this.selector = selector;
151 this.context = document;
152 selector = document.getElementsByTagName( selector );
153 return jQuery.merge( this, selector );
154
155 // HANDLE: $(expr, $(...))
156 } else if ( !context || context.jquery ) {
157 return (context || rootjQuery).find( selector );
158
159 // HANDLE: $(expr, context)
160 // (which is just equivalent to: $(context).find(expr)
161 } else {
162 return jQuery( context ).find( selector );
163 }
164
165 // HANDLE: $(function)
166 // Shortcut for document ready
167 } else if ( jQuery.isFunction( selector ) ) {
168 return rootjQuery.ready( selector );
169 }
170
171 if (selector.selector !== undefined) {
172 this.selector = selector.selector;
173 this.context = selector.context;
174 }
175
176 return jQuery.makeArray( selector, this );
177 },
178
179 // Start with an empty selector
180 selector: "",
181
182 // The current version of jQuery being used
183 jquery: "1.4.2",
184
185 // The default length of a jQuery object is 0
186 length: 0,
187
188 // The number of elements contained in the matched element set
189 size: function() {
190 return this.length;
191 },
192
193 toArray: function() {
194 return slice.call( this, 0 );
195 },
196
197 // Get the Nth element in the matched element set OR
198 // Get the whole matched element set as a clean array
199 get: function( num ) {
200 return num == null ?
201
202 // Return a 'clean' array
203 this.toArray() :
204
205 // Return just the object
206 ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
207 },
208
209 // Take an array of elements and push it onto the stack
210 // (returning the new matched element set)
211 pushStack: function( elems, name, selector ) {
212 // Build a new jQuery matched element set
213 var ret = jQuery();
214
215 if ( jQuery.isArray( elems ) ) {
216 push.apply( ret, elems );
217
218 } else {
219 jQuery.merge( ret, elems );
220 }
221
222 // Add the old object onto the stack (as a reference)
223 ret.prevObject = this;
224
225 ret.context = this.context;
226
227 if ( name === "find" ) {
228 ret.selector = this.selector + (this.selector ? " " : "") + selector;
229 } else if ( name ) {
230 ret.selector = this.selector + "." + name + "(" + selector + ")";
231 }
232
233 // Return the newly-formed element set
234 return ret;
235 },
236
237 // Execute a callback for every element in the matched set.
238 // (You can seed the arguments with an array of args, but this is
239 // only used internally.)
240 each: function( callback, args ) {
241 return jQuery.each( this, callback, args );
242 },
243
244 ready: function( fn ) {
245 // Attach the listeners
246 jQuery.bindReady();
247
248 // If the DOM is already ready
249 if ( jQuery.isReady ) {
250 // Execute the function immediately
251 fn.call( document, jQuery );
252
253 // Otherwise, remember the function for later
254 } else if ( readyList ) {
255 // Add the function to the wait list
256 readyList.push( fn );
257 }
258
259 return this;
260 },
261
262 eq: function( i ) {
263 return i === -1 ?
264 this.slice( i ) :
265 this.slice( i, +i + 1 );
266 },
267
268 first: function() {
269 return this.eq( 0 );
270 },
271
272 last: function() {
273 return this.eq( -1 );
274 },
275
276 slice: function() {
277 return this.pushStack( slice.apply( this, arguments ),
278 "slice", slice.call(arguments).join(",") );
279 },
280
281 map: function( callback ) {
282 return this.pushStack( jQuery.map(this, function( elem, i ) {
283 return callback.call( elem, i, elem );
284 }));
285 },
286
287 end: function() {
288 return this.prevObject || jQuery(null);
289 },
290
291 // For internal use only.
292 // Behaves like an Array's method, not like a jQuery method.
293 push: push,
294 sort: [].sort,
295 splice: [].splice
296};
297
298// Give the init function the jQuery prototype for later instantiation
299jQuery.fn.init.prototype = jQuery.fn;
300
301jQuery.extend = jQuery.fn.extend = function() {
302 // copy reference to target object
303 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;
304
305 // Handle a deep copy situation
306 if ( typeof target === "boolean" ) {
307 deep = target;
308 target = arguments[1] || {};
309 // skip the boolean and the target
310 i = 2;
311 }
312
313 // Handle case when target is a string or something (possible in deep copy)
314 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
315 target = {};
316 }
317
318 // extend jQuery itself if only one argument is passed
319 if ( length === i ) {
320 target = this;
321 --i;
322 }
323
324 for ( ; i < length; i++ ) {
325 // Only deal with non-null/undefined values
326 if ( (options = arguments[ i ]) != null ) {
327 // Extend the base object
328 for ( name in options ) {
329 src = target[ name ];
330 copy = options[ name ];
331
332 // Prevent never-ending loop
333 if ( target === copy ) {
334 continue;
335 }
336
337 // Recurse if we're merging object literal values or arrays
338 if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) {
339 var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src
340 : jQuery.isArray(copy) ? [] : {};
341
342 // Never move original objects, clone them
343 target[ name ] = jQuery.extend( deep, clone, copy );
344
345 // Don't bring in undefined values
346 } else if ( copy !== undefined ) {
347 target[ name ] = copy;
348 }
349 }
350 }
351 }
352
353 // Return the modified object
354 return target;
355};
356
357jQuery.extend({
358 noConflict: function( deep ) {
359 window.$ = _$;
360
361 if ( deep ) {
362 window.jQuery = _jQuery;
363 }
364
365 return jQuery;
366 },
367
368 // Is the DOM ready to be used? Set to true once it occurs.
369 isReady: false,
370
371 // Handle when the DOM is ready
372 ready: function() {
373 // Make sure that the DOM is not already loaded
374 if ( !jQuery.isReady ) {
375 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
376 if ( !document.body ) {
377 return setTimeout( jQuery.ready, 13 );
378 }
379
380 // Remember that the DOM is ready
381 jQuery.isReady = true;
382
383 // If there are functions bound, to execute
384 if ( readyList ) {
385 // Execute all of them
386 var fn, i = 0;
387 while ( (fn = readyList[ i++ ]) ) {
388 fn.call( document, jQuery );
389 }
390
391 // Reset the list of functions
392 readyList = null;
393 }
394
395 // Trigger any bound ready events
396 if ( jQuery.fn.triggerHandler ) {
397 jQuery( document ).triggerHandler( "ready" );
398 }
399 }
400 },
401
402 bindReady: function() {
403 if ( readyBound ) {
404 return;
405 }
406
407 readyBound = true;
408
409 // Catch cases where $(document).ready() is called after the
410 // browser event has already occurred.
411 if ( document.readyState === "complete" ) {
412 return jQuery.ready();
413 }
414
415 // Mozilla, Opera and webkit nightlies currently support this event
416 if ( document.addEventListener ) {
417 // Use the handy event callback
418 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
419
420 // A fallback to window.onload, that will always work
421 window.addEventListener( "load", jQuery.ready, false );
422
423 // If IE event model is used
424 } else if ( document.attachEvent ) {
425 // ensure firing before onload,
426 // maybe late but safe also for iframes
427 document.attachEvent("onreadystatechange", DOMContentLoaded);
428
429 // A fallback to window.onload, that will always work
430 window.attachEvent( "onload", jQuery.ready );
431
432 // If IE and not a frame
433 // continually check to see if the document is ready
434 var toplevel = false;
435
436 try {
437 toplevel = window.frameElement == null;
438 } catch(e) {}
439
440 if ( document.documentElement.doScroll && toplevel ) {
441 doScrollCheck();
442 }
443 }
444 },
445
446 // See test/unit/core.js for details concerning isFunction.
447 // Since version 1.3, DOM methods and functions like alert
448 // aren't supported. They return false on IE (#2968).
449 isFunction: function( obj ) {
450 return toString.call(obj) === "[object Function]";
451 },
452
453 isArray: function( obj ) {
454 return toString.call(obj) === "[object Array]";
455 },
456
457 isPlainObject: function( obj ) {
458 // Must be an Object.
459 // Because of IE, we also have to check the presence of the constructor property.
460 // Make sure that DOM nodes and window objects don't pass through, as well
461 if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
462 return false;
463 }
464
465 // Not own constructor property must be Object
466 if ( obj.constructor
467 && !hasOwnProperty.call(obj, "constructor")
468 && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) {
469 return false;
470 }
471
472 // Own properties are enumerated firstly, so to speed up,
473 // if last one is own, then all properties are own.
474
475 var key;
476 for ( key in obj ) {}
477
478 return key === undefined || hasOwnProperty.call( obj, key );
479 },
480
481 isEmptyObject: function( obj ) {
482 for ( var name in obj ) {
483 return false;
484 }
485 return true;
486 },
487
488 error: function( msg ) {
489 throw msg;
490 },
491
492 parseJSON: function( data ) {
493 if ( typeof data !== "string" || !data ) {
494 return null;
495 }
496
497 // Make sure leading/trailing whitespace is removed (IE can't handle it)
498 data = jQuery.trim( data );
499
500 // Make sure the incoming data is actual JSON
501 // Logic borrowed from http://json.org/json2.js
502 if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
503 .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
504 .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) {
505
506 // Try to use the native JSON parser first
507 return window.JSON && window.JSON.parse ?
508 window.JSON.parse( data ) :
509 (new Function("return " + data))();
510
511 } else {
512 jQuery.error( "Invalid JSON: " + data );
513 }
514 },
515
516 noop: function() {},
517
518 // Evalulates a script in a global context
519 globalEval: function( data ) {
520 if ( data && rnotwhite.test(data) ) {
521 // Inspired by code by Andrea Giammarchi
522 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
523 var head = document.getElementsByTagName("head")[0] || document.documentElement,
524 script = document.createElement("script");
525
526 script.type = "text/javascript";
527
528 if ( jQuery.support.scriptEval ) {
529 script.appendChild( document.createTextNode( data ) );
530 } else {
531 script.text = data;
532 }
533
534 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
535 // This arises when a base node is used (#2709).
536 head.insertBefore( script, head.firstChild );
537 head.removeChild( script );
538 }
539 },
540
541 nodeName: function( elem, name ) {
542 return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
543 },
544
545 // args is for internal usage only
546 each: function( object, callback, args ) {
547 var name, i = 0,
548 length = object.length,
549 isObj = length === undefined || jQuery.isFunction(object);
550
551 if ( args ) {
552 if ( isObj ) {
553 for ( name in object ) {
554 if ( callback.apply( object[ name ], args ) === false ) {
555 break;
556 }
557 }
558 } else {
559 for ( ; i < length; ) {
560 if ( callback.apply( object[ i++ ], args ) === false ) {
561 break;
562 }
563 }
564 }
565
566 // A special, fast, case for the most common use of each
567 } else {
568 if ( isObj ) {
569 for ( name in object ) {
570 if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
571 break;
572 }
573 }
574 } else {
575 for ( var value = object[0];
576 i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
577 }
578 }
579
580 return object;
581 },
582
583 trim: function( text ) {
584 return (text || "").replace( rtrim, "" );
585 },
586
587 // results is for internal usage only
588 makeArray: function( array, results ) {
589 var ret = results || [];
590
591 if ( array != null ) {
592 // The window, strings (and functions) also have 'length'
593 // The extra typeof function check is to prevent crashes
594 // in Safari 2 (See: #3039)
595 if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {
596 push.call( ret, array );
597 } else {
598 jQuery.merge( ret, array );
599 }
600 }
601
602 return ret;
603 },
604
605 inArray: function( elem, array ) {
606 if ( array.indexOf ) {
607 return array.indexOf( elem );
608 }
609
610 for ( var i = 0, length = array.length; i < length; i++ ) {
611 if ( array[ i ] === elem ) {
612 return i;
613 }
614 }
615
616 return -1;
617 },
618
619 merge: function( first, second ) {
620 var i = first.length, j = 0;
621
622 if ( typeof second.length === "number" ) {
623 for ( var l = second.length; j < l; j++ ) {
624 first[ i++ ] = second[ j ];
625 }
626
627 } else {
628 while ( second[j] !== undefined ) {
629 first[ i++ ] = second[ j++ ];
630 }
631 }
632
633 first.length = i;
634
635 return first;
636 },
637
638 grep: function( elems, callback, inv ) {
639 var ret = [];
640
641 // Go through the array, only saving the items
642 // that pass the validator function
643 for ( var i = 0, length = elems.length; i < length; i++ ) {
644 if ( !inv !== !callback( elems[ i ], i ) ) {
645 ret.push( elems[ i ] );
646 }
647 }
648
649 return ret;
650 },
651
652 // arg is for internal usage only
653 map: function( elems, callback, arg ) {
654 var ret = [], value;
655
656 // Go through the array, translating each of the items to their
657 // new value (or values).
658 for ( var i = 0, length = elems.length; i < length; i++ ) {
659 value = callback( elems[ i ], i, arg );
660
661 if ( value != null ) {
662 ret[ ret.length ] = value;
663 }
664 }
665
666 return ret.concat.apply( [], ret );
667 },
668
669 // A global GUID counter for objects
670 guid: 1,
671
672 proxy: function( fn, proxy, thisObject ) {
673 if ( arguments.length === 2 ) {
674 if ( typeof proxy === "string" ) {
675 thisObject = fn;
676 fn = thisObject[ proxy ];
677 proxy = undefined;
678
679 } else if ( proxy && !jQuery.isFunction( proxy ) ) {
680 thisObject = proxy;
681 proxy = undefined;
682 }
683 }
684
685 if ( !proxy && fn ) {
686 proxy = function() {
687 return fn.apply( thisObject || this, arguments );
688 };
689 }
690
691 // Set the guid of unique handler to the same of original handler, so it can be removed
692 if ( fn ) {
693 proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
694 }
695
696 // So proxy can be declared as an argument
697 return proxy;
698 },
699
700 // Use of jQuery.browser is frowned upon.
701 // More details: http://docs.jquery.com/Utilities/jQuery.browser
702 uaMatch: function( ua ) {
703 ua = ua.toLowerCase();
704
705 var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
706 /(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) ||
707 /(msie) ([\w.]+)/.exec( ua ) ||
708 !/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) ||
709 [];
710
711 return { browser: match[1] || "", version: match[2] || "0" };
712 },
713
714 browser: {}
715});
716
717browserMatch = jQuery.uaMatch( userAgent );
718if ( browserMatch.browser ) {
719 jQuery.browser[ browserMatch.browser ] = true;
720 jQuery.browser.version = browserMatch.version;
721}
722
723// Deprecated, use jQuery.browser.webkit instead
724if ( jQuery.browser.webkit ) {
725 jQuery.browser.safari = true;
726}
727
728if ( indexOf ) {
729 jQuery.inArray = function( elem, array ) {
730 return indexOf.call( array, elem );
731 };
732}
733
734// All jQuery objects should point back to these
735rootjQuery = jQuery(document);
736
737// Cleanup functions for the document ready method
738if ( document.addEventListener ) {
739 DOMContentLoaded = function() {
740 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
741 jQuery.ready();
742 };
743
744} else if ( document.attachEvent ) {
745 DOMContentLoaded = function() {
746 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
747 if ( document.readyState === "complete" ) {
748 document.detachEvent( "onreadystatechange", DOMContentLoaded );
749 jQuery.ready();
750 }
751 };
752}
753
754// The DOM ready check for Internet Explorer
755function doScrollCheck() {
756 if ( jQuery.isReady ) {
757 return;
758 }
759
760 try {
761 // If IE is used, use the trick by Diego Perini
762 // http://javascript.nwbox.com/IEContentLoaded/
763 document.documentElement.doScroll("left");
764 } catch( error ) {
765 setTimeout( doScrollCheck, 1 );
766 return;
767 }
768
769 // and execute any waiting functions
770 jQuery.ready();
771}
772
773function evalScript( i, elem ) {
774 if ( elem.src ) {
775 jQuery.ajax({
776 url: elem.src,
777 async: false,
778 dataType: "script"
779 });
780 } else {
781 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
782 }
783
784 if ( elem.parentNode ) {
785 elem.parentNode.removeChild( elem );
786 }
787}
788
789// Mutifunctional method to get and set values to a collection
790// The value/s can be optionally by executed if its a function
791function access( elems, key, value, exec, fn, pass ) {
792 var length = elems.length;
793
794 // Setting many attributes
795 if ( typeof key === "object" ) {
796 for ( var k in key ) {
797 access( elems, k, key[k], exec, fn, value );
798 }
799 return elems;
800 }
801
802 // Setting one attribute
803 if ( value !== undefined ) {
804 // Optionally, function values get executed if exec is true
805 exec = !pass && exec && jQuery.isFunction(value);
806
807 for ( var i = 0; i < length; i++ ) {
808 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
809 }
810
811 return elems;
812 }
813
814 // Getting an attribute
815 return length ? fn( elems[0], key ) : undefined;
816}
817
818function now() {
819 return (new Date).getTime();
820}
821(function() {
822
823 jQuery.support = {};
824
825 var root = document.documentElement,
826 script = document.createElement("script"),
827 div = document.createElement("div"),
828 id = "script" + now();
829
830 div.style.display = "none";
831 div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
832
833 var all = div.getElementsByTagName("*"),
834 a = div.getElementsByTagName("a")[0];
835
836 // Can't get basic test support
837 if ( !all || !all.length || !a ) {
838 return;
839 }
840
841 jQuery.support = {
842 // IE strips leading whitespace when .innerHTML is used
843 leadingWhitespace: div.firstChild.nodeType === 3,
844
845 // Make sure that tbody elements aren't automatically inserted
846 // IE will insert them into empty tables
847 tbody: !div.getElementsByTagName("tbody").length,
848
849 // Make sure that link elements get serialized correctly by innerHTML
850 // This requires a wrapper element in IE
851 htmlSerialize: !!div.getElementsByTagName("link").length,
852
853 // Get the style information from getAttribute
854 // (IE uses .cssText insted)
855 style: /red/.test( a.getAttribute("style") ),
856
857 // Make sure that URLs aren't manipulated
858 // (IE normalizes it by default)
859 hrefNormalized: a.getAttribute("href") === "/a",
860
861 // Make sure that element opacity exists
862 // (IE uses filter instead)
863 // Use a regex to work around a WebKit issue. See #5145
864 opacity: /^0.55$/.test( a.style.opacity ),
865
866 // Verify style float existence
867 // (IE uses styleFloat instead of cssFloat)
868 cssFloat: !!a.style.cssFloat,
869
870 // Make sure that if no value is specified for a checkbox
871 // that it defaults to "on".
872 // (WebKit defaults to "" instead)
873 checkOn: div.getElementsByTagName("input")[0].value === "on",
874
875 // Make sure that a selected-by-default option has a working selected property.
876 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
877 optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected,
878
879 parentNode: div.removeChild( div.appendChild( document.createElement("div") ) ).parentNode === null,
880
881 // Will be defined later
882 deleteExpando: true,
883 checkClone: false,
884 scriptEval: false,
885 noCloneEvent: true,
886 boxModel: null
887 };
888
889 script.type = "text/javascript";
890 try {
891 script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
892 } catch(e) {}
893
894 root.insertBefore( script, root.firstChild );
895
896 // Make sure that the execution of code works by injecting a script
897 // tag with appendChild/createTextNode
898 // (IE doesn't support this, fails, and uses .text instead)
899 if ( window[ id ] ) {
900 jQuery.support.scriptEval = true;
901 delete window[ id ];
902 }
903
904 // Test to see if it's possible to delete an expando from an element
905 // Fails in Internet Explorer
906 try {
907 delete script.test;
908
909 } catch(e) {
910 jQuery.support.deleteExpando = false;
911 }
912
913 root.removeChild( script );
914
915 if ( div.attachEvent && div.fireEvent ) {
916 div.attachEvent("onclick", function click() {
917 // Cloning a node shouldn't copy over any
918 // bound event handlers (IE does this)
919 jQuery.support.noCloneEvent = false;
920 div.detachEvent("onclick", click);
921 });
922 div.cloneNode(true).fireEvent("onclick");
923 }
924
925 div = document.createElement("div");
926 div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
927
928 var fragment = document.createDocumentFragment();
929 fragment.appendChild( div.firstChild );
930
931 // WebKit doesn't clone checked state correctly in fragments
932 jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
933
934 // Figure out if the W3C box model works as expected
935 // document.body must exist before we can do this
936 jQuery(function() {
937 var div = document.createElement("div");
938 div.style.width = div.style.paddingLeft = "1px";
939
940 document.body.appendChild( div );
941 jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
942 document.body.removeChild( div ).style.display = 'none';
943
944 div = null;
945 });
946
947 // Technique from Juriy Zaytsev
948 // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
949 var eventSupported = function( eventName ) {
950 var el = document.createElement("div");
951 eventName = "on" + eventName;
952
953 var isSupported = (eventName in el);
954 if ( !isSupported ) {
955 el.setAttribute(eventName, "return;");
956 isSupported = typeof el[eventName] === "function";
957 }
958 el = null;
959
960 return isSupported;
961 };
962
963 jQuery.support.submitBubbles = eventSupported("submit");
964 jQuery.support.changeBubbles = eventSupported("change");
965
966 // release memory in IE
967 root = script = div = all = a = null;
968})();
969
970jQuery.props = {
971 "for": "htmlFor",
972 "class": "className",
973 readonly: "readOnly",
974 maxlength: "maxLength",
975 cellspacing: "cellSpacing",
976 rowspan: "rowSpan",
977 colspan: "colSpan",
978 tabindex: "tabIndex",
979 usemap: "useMap",
980 frameborder: "frameBorder"
981};
982var expando = "jQuery" + now(), uuid = 0, windowData = {};
983
984jQuery.extend({
985 cache: {},
986
987 expando:expando,
988
989 // The following elements throw uncatchable exceptions if you
990 // attempt to add expando properties to them.
991 noData: {
992 "embed": true,
993 "object": true,
994 "applet": true
995 },
996
997 data: function( elem, name, data ) {
998 if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
999 return;
1000 }
1001
1002 elem = elem == window ?
1003 windowData :
1004 elem;
1005
1006 var id = elem[ expando ], cache = jQuery.cache, thisCache;
1007
1008 if ( !id && typeof name === "string" && data === undefined ) {
1009 return null;
1010 }
1011
1012 // Compute a unique ID for the element
1013 if ( !id ) {
1014 id = ++uuid;
1015 }
1016
1017 // Avoid generating a new cache unless none exists and we
1018 // want to manipulate it.
1019 if ( typeof name === "object" ) {
1020 elem[ expando ] = id;
1021 thisCache = cache[ id ] = jQuery.extend(true, {}, name);
1022
1023 } else if ( !cache[ id ] ) {
1024 elem[ expando ] = id;
1025 cache[ id ] = {};
1026 }
1027
1028 thisCache = cache[ id ];
1029
1030 // Prevent overriding the named cache with undefined values
1031 if ( data !== undefined ) {
1032 thisCache[ name ] = data;
1033 }
1034
1035 return typeof name === "string" ? thisCache[ name ] : thisCache;
1036 },
1037
1038 removeData: function( elem, name ) {
1039 if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
1040 return;
1041 }
1042
1043 elem = elem == window ?
1044 windowData :
1045 elem;
1046
1047 var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ];
1048
1049 // If we want to remove a specific section of the element's data
1050 if ( name ) {
1051 if ( thisCache ) {
1052 // Remove the section of cache data
1053 delete thisCache[ name ];
1054
1055 // If we've removed all the data, remove the element's cache
1056 if ( jQuery.isEmptyObject(thisCache) ) {
1057 jQuery.removeData( elem );
1058 }
1059 }
1060
1061 // Otherwise, we want to remove all of the element's data
1062 } else {
1063 if ( jQuery.support.deleteExpando ) {
1064 delete elem[ jQuery.expando ];
1065
1066 } else if ( elem.removeAttribute ) {
1067 elem.removeAttribute( jQuery.expando );
1068 }
1069
1070 // Completely remove the data cache
1071 delete cache[ id ];
1072 }
1073 }
1074});
1075
1076jQuery.fn.extend({
1077 data: function( key, value ) {
1078 if ( typeof key === "undefined" && this.length ) {
1079 return jQuery.data( this[0] );
1080
1081 } else if ( typeof key === "object" ) {
1082 return this.each(function() {
1083 jQuery.data( this, key );
1084 });
1085 }
1086
1087 var parts = key.split(".");
1088 parts[1] = parts[1] ? "." + parts[1] : "";
1089
1090 if ( value === undefined ) {
1091 var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
1092
1093 if ( data === undefined && this.length ) {
1094 data = jQuery.data( this[0], key );
1095 }
1096 return data === undefined && parts[1] ?
1097 this.data( parts[0] ) :
1098 data;
1099 } else {
1100 return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() {
1101 jQuery.data( this, key, value );
1102 });
1103 }
1104 },
1105
1106 removeData: function( key ) {
1107 return this.each(function() {
1108 jQuery.removeData( this, key );
1109 });
1110 }
1111});
1112jQuery.extend({
1113 queue: function( elem, type, data ) {
1114 if ( !elem ) {
1115 return;
1116 }
1117
1118 type = (type || "fx") + "queue";
1119 var q = jQuery.data( elem, type );
1120
1121 // Speed up dequeue by getting out quickly if this is just a lookup
1122 if ( !data ) {
1123 return q || [];
1124 }
1125
1126 if ( !q || jQuery.isArray(data) ) {
1127 q = jQuery.data( elem, type, jQuery.makeArray(data) );
1128
1129 } else {
1130 q.push( data );
1131 }
1132
1133 return q;
1134 },
1135
1136 dequeue: function( elem, type ) {
1137 type = type || "fx";
1138
1139 var queue = jQuery.queue( elem, type ), fn = queue.shift();
1140
1141 // If the fx queue is dequeued, always remove the progress sentinel
1142 if ( fn === "inprogress" ) {
1143 fn = queue.shift();
1144 }
1145
1146 if ( fn ) {
1147 // Add a progress sentinel to prevent the fx queue from being
1148 // automatically dequeued
1149 if ( type === "fx" ) {
1150 queue.unshift("inprogress");
1151 }
1152
1153 fn.call(elem, function() {
1154 jQuery.dequeue(elem, type);
1155 });
1156 }
1157 }
1158});
1159
1160jQuery.fn.extend({
1161 queue: function( type, data ) {
1162 if ( typeof type !== "string" ) {
1163 data = type;
1164 type = "fx";
1165 }
1166
1167 if ( data === undefined ) {
1168 return jQuery.queue( this[0], type );
1169 }
1170 return this.each(function( i, elem ) {
1171 var queue = jQuery.queue( this, type, data );
1172
1173 if ( type === "fx" && queue[0] !== "inprogress" ) {
1174 jQuery.dequeue( this, type );
1175 }
1176 });
1177 },
1178 dequeue: function( type ) {
1179 return this.each(function() {
1180 jQuery.dequeue( this, type );
1181 });
1182 },
1183
1184 // Based off of the plugin by Clint Helfers, with permission.
1185 // http://blindsignals.com/index.php/2009/07/jquery-delay/
1186 delay: function( time, type ) {
1187 time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
1188 type = type || "fx";
1189
1190 return this.queue( type, function() {
1191 var elem = this;
1192 setTimeout(function() {
1193 jQuery.dequeue( elem, type );
1194 }, time );
1195 });
1196 },
1197
1198 clearQueue: function( type ) {
1199 return this.queue( type || "fx", [] );
1200 }
1201});
1202var rclass = /[\n\t]/g,
1203 rspace = /\s+/,
1204 rreturn = /\r/g,
1205 rspecialurl = /href|src|style/,
1206 rtype = /(button|input)/i,
1207 rfocusable = /(button|input|object|select|textarea)/i,
1208 rclickable = /^(a|area)$/i,
1209 rradiocheck = /radio|checkbox/;
1210
1211jQuery.fn.extend({
1212 attr: function( name, value ) {
1213 return access( this, name, value, true, jQuery.attr );
1214 },
1215
1216 removeAttr: function( name, fn ) {
1217 return this.each(function(){
1218 jQuery.attr( this, name, "" );
1219 if ( this.nodeType === 1 ) {
1220 this.removeAttribute( name );
1221 }
1222 });
1223 },
1224
1225 addClass: function( value ) {
1226 if ( jQuery.isFunction(value) ) {
1227 return this.each(function(i) {
1228 var self = jQuery(this);
1229 self.addClass( value.call(this, i, self.attr("class")) );
1230 });
1231 }
1232
1233 if ( value && typeof value === "string" ) {
1234 var classNames = (value || "").split( rspace );
1235
1236 for ( var i = 0, l = this.length; i < l; i++ ) {
1237 var elem = this[i];
1238
1239 if ( elem.nodeType === 1 ) {
1240 if ( !elem.className ) {
1241 elem.className = value;
1242
1243 } else {
1244 var className = " " + elem.className + " ", setClass = elem.className;
1245 for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
1246 if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
1247 setClass += " " + classNames[c];
1248 }
1249 }
1250 elem.className = jQuery.trim( setClass );
1251 }
1252 }
1253 }
1254 }
1255
1256 return this;
1257 },
1258
1259 removeClass: function( value ) {
1260 if ( jQuery.isFunction(value) ) {
1261 return this.each(function(i) {
1262 var self = jQuery(this);
1263 self.removeClass( value.call(this, i, self.attr("class")) );
1264 });
1265 }
1266
1267 if ( (value && typeof value === "string") || value === undefined ) {
1268 var classNames = (value || "").split(rspace);
1269
1270 for ( var i = 0, l = this.length; i < l; i++ ) {
1271 var elem = this[i];
1272
1273 if ( elem.nodeType === 1 && elem.className ) {
1274 if ( value ) {
1275 var className = (" " + elem.className + " ").replace(rclass, " ");
1276 for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
1277 className = className.replace(" " + classNames[c] + " ", " ");
1278 }
1279 elem.className = jQuery.trim( className );
1280
1281 } else {
1282 elem.className = "";
1283 }
1284 }
1285 }
1286 }
1287
1288 return this;
1289 },
1290
1291 toggleClass: function( value, stateVal ) {
1292 var type = typeof value, isBool = typeof stateVal === "boolean";
1293
1294 if ( jQuery.isFunction( value ) ) {
1295 return this.each(function(i) {
1296 var self = jQuery(this);
1297 self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
1298 });
1299 }
1300
1301 return this.each(function() {
1302 if ( type === "string" ) {
1303 // toggle individual class names
1304 var className, i = 0, self = jQuery(this),
1305 state = stateVal,
1306 classNames = value.split( rspace );
1307
1308 while ( (className = classNames[ i++ ]) ) {
1309 // check each className given, space seperated list
1310 state = isBool ? state : !self.hasClass( className );
1311 self[ state ? "addClass" : "removeClass" ]( className );
1312 }
1313
1314 } else if ( type === "undefined" || type === "boolean" ) {
1315 if ( this.className ) {
1316 // store className if set
1317 jQuery.data( this, "__className__", this.className );
1318 }
1319
1320 // toggle whole className
1321 this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
1322 }
1323 });
1324 },
1325
1326 hasClass: function( selector ) {
1327 var className = " " + selector + " ";
1328 for ( var i = 0, l = this.length; i < l; i++ ) {
1329 if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
1330 return true;
1331 }
1332 }
1333
1334 return false;
1335 },
1336
1337 val: function( value ) {
1338 if ( value === undefined ) {
1339 var elem = this[0];
1340
1341 if ( elem ) {
1342 if ( jQuery.nodeName( elem, "option" ) ) {
1343 return (elem.attributes.value || {}).specified ? elem.value : elem.text;
1344 }
1345
1346 // We need to handle select boxes special
1347 if ( jQuery.nodeName( elem, "select" ) ) {
1348 var index = elem.selectedIndex,
1349 values = [],
1350 options = elem.options,
1351 one = elem.type === "select-one";
1352
1353 // Nothing was selected
1354 if ( index < 0 ) {
1355 return null;
1356 }
1357
1358 // Loop through all the selected options
1359 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
1360 var option = options[ i ];
1361
1362 if ( option.selected ) {
1363 // Get the specifc value for the option
1364 value = jQuery(option).val();
1365
1366 // We don't need an array for one selects
1367 if ( one ) {
1368 return value;
1369 }
1370
1371 // Multi-Selects return an array
1372 values.push( value );
1373 }
1374 }
1375
1376 return values;
1377 }
1378
1379 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
1380 if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
1381 return elem.getAttribute("value") === null ? "on" : elem.value;
1382 }
1383
1384
1385 // Everything else, we just grab the value
1386 return (elem.value || "").replace(rreturn, "");
1387
1388 }
1389
1390 return undefined;
1391 }
1392
1393 var isFunction = jQuery.isFunction(value);
1394
1395 return this.each(function(i) {
1396 var self = jQuery(this), val = value;
1397
1398 if ( this.nodeType !== 1 ) {
1399 return;
1400 }
1401
1402 if ( isFunction ) {
1403 val = value.call(this, i, self.val());
1404 }
1405
1406 // Typecast each time if the value is a Function and the appended
1407 // value is therefore different each time.
1408 if ( typeof val === "number" ) {
1409 val += "";
1410 }
1411
1412 if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
1413 this.checked = jQuery.inArray( self.val(), val ) >= 0;
1414
1415 } else if ( jQuery.nodeName( this, "select" ) ) {
1416 var values = jQuery.makeArray(val);
1417
1418 jQuery( "option", this ).each(function() {
1419 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
1420 });
1421
1422 if ( !values.length ) {
1423 this.selectedIndex = -1;
1424 }
1425
1426 } else {
1427 this.value = val;
1428 }
1429 });
1430 }
1431});
1432
1433jQuery.extend({
1434 attrFn: {
1435 val: true,
1436 css: true,
1437 html: true,
1438 text: true,
1439 data: true,
1440 width: true,
1441 height: true,
1442 offset: true
1443 },
1444
1445 attr: function( elem, name, value, pass ) {
1446 // don't set attributes on text and comment nodes
1447 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
1448 return undefined;
1449 }
1450
1451 if ( pass && name in jQuery.attrFn ) {
1452 return jQuery(elem)[name](value);
1453 }
1454
1455 var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
1456 // Whether we are setting (or getting)
1457 set = value !== undefined;
1458
1459 // Try to normalize/fix the name
1460 name = notxml && jQuery.props[ name ] || name;
1461
1462 // Only do all the following if this is a node (faster for style)
1463 if ( elem.nodeType === 1 ) {
1464 // These attributes require special treatment
1465 var special = rspecialurl.test( name );
1466
1467 // Safari mis-reports the default selected property of an option
1468 // Accessing the parent's selectedIndex property fixes it
1469 if ( name === "selected" && !jQuery.support.optSelected ) {
1470 var parent = elem.parentNode;
1471 if ( parent ) {
1472 parent.selectedIndex;
1473
1474 // Make sure that it also works with optgroups, see #5701
1475 if ( parent.parentNode ) {
1476 parent.parentNode.selectedIndex;
1477 }
1478 }
1479 }
1480
1481 // If applicable, access the attribute via the DOM 0 way
1482 if ( name in elem && notxml && !special ) {
1483 if ( set ) {
1484 // We can't allow the type property to be changed (since it causes problems in IE)
1485 if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
1486 jQuery.error( "type property can't be changed" );
1487 }
1488
1489 elem[ name ] = value;
1490 }
1491
1492 // browsers index elements by id/name on forms, give priority to attributes.
1493 if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
1494 return elem.getAttributeNode( name ).nodeValue;
1495 }
1496
1497 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
1498 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
1499 if ( name === "tabIndex" ) {
1500 var attributeNode = elem.getAttributeNode( "tabIndex" );
1501
1502 return attributeNode && attributeNode.specified ?
1503 attributeNode.value :
1504 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
1505 0 :
1506 undefined;
1507 }
1508
1509 return elem[ name ];
1510 }
1511
1512 if ( !jQuery.support.style && notxml && name === "style" ) {
1513 if ( set ) {
1514 elem.style.cssText = "" + value;
1515 }
1516
1517 return elem.style.cssText;
1518 }
1519
1520 if ( set ) {
1521 // convert the value to a string (all browsers do this but IE) see #1070
1522 elem.setAttribute( name, "" + value );
1523 }
1524
1525 var attr = !jQuery.support.hrefNormalized && notxml && special ?
1526 // Some attributes require a special call on IE
1527 elem.getAttribute( name, 2 ) :
1528 elem.getAttribute( name );
1529
1530 // Non-existent attributes return null, we normalize to undefined
1531 return attr === null ? undefined : attr;
1532 }
1533
1534 // elem is actually elem.style ... set the style
1535 // Using attr for specific style information is now deprecated. Use style instead.
1536 return jQuery.style( elem, name, value );
1537 }
1538});
1539var rnamespaces = /\.(.*)$/,
1540 fcleanup = function( nm ) {
1541 return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
1542 return "\\" + ch;
1543 });
1544 };
1545
1546/*
1547 * A number of helper functions used for managing events.
1548 * Many of the ideas behind this code originated from
1549 * Dean Edwards' addEvent library.
1550 */
1551jQuery.event = {
1552
1553 // Bind an event to an element
1554 // Original by Dean Edwards
1555 add: function( elem, types, handler, data ) {
1556 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
1557 return;
1558 }
1559
1560 // For whatever reason, IE has trouble passing the window object
1561 // around, causing it to be cloned in the process
1562 if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {
1563 elem = window;
1564 }
1565
1566 var handleObjIn, handleObj;
1567
1568 if ( handler.handler ) {
1569 handleObjIn = handler;
1570 handler = handleObjIn.handler;
1571 }
1572
1573 // Make sure that the function being executed has a unique ID
1574 if ( !handler.guid ) {
1575 handler.guid = jQuery.guid++;
1576 }
1577
1578 // Init the element's event structure
1579 var elemData = jQuery.data( elem );
1580
1581 // If no elemData is found then we must be trying to bind to one of the
1582 // banned noData elements
1583 if ( !elemData ) {
1584 return;
1585 }
1586
1587 var events = elemData.events = elemData.events || {},
1588 eventHandle = elemData.handle, eventHandle;
1589
1590 if ( !eventHandle ) {
1591 elemData.handle = eventHandle = function() {
1592 // Handle the second event of a trigger and when
1593 // an event is called after a page has unloaded
1594 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
1595 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
1596 undefined;
1597 };
1598 }
1599
1600 // Add elem as a property of the handle function
1601 // This is to prevent a memory leak with non-native events in IE.
1602 eventHandle.elem = elem;
1603
1604 // Handle multiple events separated by a space
1605 // jQuery(...).bind("mouseover mouseout", fn);
1606 types = types.split(" ");
1607
1608 var type, i = 0, namespaces;
1609
1610 while ( (type = types[ i++ ]) ) {
1611 handleObj = handleObjIn ?
1612 jQuery.extend({}, handleObjIn) :
1613 { handler: handler, data: data };
1614
1615 // Namespaced event handlers
1616 if ( type.indexOf(".") > -1 ) {
1617 namespaces = type.split(".");
1618 type = namespaces.shift();
1619 handleObj.namespace = namespaces.slice(0).sort().join(".");
1620
1621 } else {
1622 namespaces = [];
1623 handleObj.namespace = "";
1624 }
1625
1626 handleObj.type = type;
1627 handleObj.guid = handler.guid;
1628
1629 // Get the current list of functions bound to this event
1630 var handlers = events[ type ],
1631 special = jQuery.event.special[ type ] || {};
1632
1633 // Init the event handler queue
1634 if ( !handlers ) {
1635 handlers = events[ type ] = [];
1636
1637 // Check for a special event handler
1638 // Only use addEventListener/attachEvent if the special
1639 // events handler returns false
1640 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
1641 // Bind the global event handler to the element
1642 if ( elem.addEventListener ) {
1643 elem.addEventListener( type, eventHandle, false );
1644
1645 } else if ( elem.attachEvent ) {
1646 elem.attachEvent( "on" + type, eventHandle );
1647 }
1648 }
1649 }
1650
1651 if ( special.add ) {
1652 special.add.call( elem, handleObj );
1653
1654 if ( !handleObj.handler.guid ) {
1655 handleObj.handler.guid = handler.guid;
1656 }
1657 }
1658
1659 // Add the function to the element's handler list
1660 handlers.push( handleObj );
1661
1662 // Keep track of which events have been used, for global triggering
1663 jQuery.event.global[ type ] = true;
1664 }
1665
1666 // Nullify elem to prevent memory leaks in IE
1667 elem = null;
1668 },
1669
1670 global: {},
1671
1672 // Detach an event or set of events from an element
1673 remove: function( elem, types, handler, pos ) {
1674 // don't do events on text and comment nodes
1675 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
1676 return;
1677 }
1678
1679 var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
1680 elemData = jQuery.data( elem ),
1681 events = elemData && elemData.events;
1682
1683 if ( !elemData || !events ) {
1684 return;
1685 }
1686
1687 // types is actually an event object here
1688 if ( types && types.type ) {
1689 handler = types.handler;
1690 types = types.type;
1691 }
1692
1693 // Unbind all events for the element
1694 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
1695 types = types || "";
1696
1697 for ( type in events ) {
1698 jQuery.event.remove( elem, type + types );
1699 }
1700
1701 return;
1702 }
1703
1704 // Handle multiple events separated by a space
1705 // jQuery(...).unbind("mouseover mouseout", fn);
1706 types = types.split(" ");
1707
1708 while ( (type = types[ i++ ]) ) {
1709 origType = type;
1710 handleObj = null;
1711 all = type.indexOf(".") < 0;
1712 namespaces = [];
1713
1714 if ( !all ) {
1715 // Namespaced event handlers
1716 namespaces = type.split(".");
1717 type = namespaces.shift();
1718
1719 namespace = new RegExp("(^|\\.)" +
1720 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)")
1721 }
1722
1723 eventType = events[ type ];
1724
1725 if ( !eventType ) {
1726 continue;
1727 }
1728
1729 if ( !handler ) {
1730 for ( var j = 0; j < eventType.length; j++ ) {
1731 handleObj = eventType[ j ];
1732
1733 if ( all || namespace.test( handleObj.namespace ) ) {
1734 jQuery.event.remove( elem, origType, handleObj.handler, j );
1735 eventType.splice( j--, 1 );
1736 }
1737 }
1738
1739 continue;
1740 }
1741
1742 special = jQuery.event.special[ type ] || {};
1743
1744 for ( var j = pos || 0; j < eventType.length; j++ ) {
1745 handleObj = eventType[ j ];
1746
1747 if ( handler.guid === handleObj.guid ) {
1748 // remove the given handler for the given type
1749 if ( all || namespace.test( handleObj.namespace ) ) {
1750 if ( pos == null ) {
1751 eventType.splice( j--, 1 );
1752 }
1753
1754 if ( special.remove ) {
1755 special.remove.call( elem, handleObj );
1756 }
1757 }
1758
1759 if ( pos != null ) {
1760 break;
1761 }
1762 }
1763 }
1764
1765 // remove generic event handler if no more handlers exist
1766 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
1767 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
1768 removeEvent( elem, type, elemData.handle );
1769 }
1770
1771 ret = null;
1772 delete events[ type ];
1773 }
1774 }
1775
1776 // Remove the expando if it's no longer used
1777 if ( jQuery.isEmptyObject( events ) ) {
1778 var handle = elemData.handle;
1779 if ( handle ) {
1780 handle.elem = null;
1781 }
1782
1783 delete elemData.events;
1784 delete elemData.handle;
1785
1786 if ( jQuery.isEmptyObject( elemData ) ) {
1787 jQuery.removeData( elem );
1788 }
1789 }
1790 },
1791
1792 // bubbling is internal
1793 trigger: function( event, data, elem /*, bubbling */ ) {
1794 // Event object or event type
1795 var type = event.type || event,
1796 bubbling = arguments[3];
1797
1798 if ( !bubbling ) {
1799 event = typeof event === "object" ?
1800 // jQuery.Event object
1801 event[expando] ? event :
1802 // Object literal
1803 jQuery.extend( jQuery.Event(type), event ) :
1804 // Just the event type (string)
1805 jQuery.Event(type);
1806
1807 if ( type.indexOf("!") >= 0 ) {
1808 event.type = type = type.slice(0, -1);
1809 event.exclusive = true;
1810 }
1811
1812 // Handle a global trigger
1813 if ( !elem ) {
1814 // Don't bubble custom events when global (to avoid too much overhead)
1815 event.stopPropagation();
1816
1817 // Only trigger if we've ever bound an event for it
1818 if ( jQuery.event.global[ type ] ) {
1819 jQuery.each( jQuery.cache, function() {
1820 if ( this.events && this.events[type] ) {
1821 jQuery.event.trigger( event, data, this.handle.elem );
1822 }
1823 });
1824 }
1825 }
1826
1827 // Handle triggering a single element
1828
1829 // don't do events on text and comment nodes
1830 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
1831 return undefined;
1832 }
1833
1834 // Clean up in case it is reused
1835 event.result = undefined;
1836 event.target = elem;
1837
1838 // Clone the incoming data, if any
1839 data = jQuery.makeArray( data );
1840 data.unshift( event );
1841 }
1842
1843 event.currentTarget = elem;
1844
1845 // Trigger the event, it is assumed that "handle" is a function
1846 var handle = jQuery.data( elem, "handle" );
1847 if ( handle ) {
1848 handle.apply( elem, data );
1849 }
1850
1851 var parent = elem.parentNode || elem.ownerDocument;
1852
1853 // Trigger an inline bound script
1854 try {
1855 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
1856 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
1857 event.result = false;
1858 }
1859 }
1860
1861 // prevent IE from throwing an error for some elements with some event types, see #3533
1862 } catch (e) {}
1863
1864 if ( !event.isPropagationStopped() && parent ) {
1865 jQuery.event.trigger( event, data, parent, true );
1866
1867 } else if ( !event.isDefaultPrevented() ) {
1868 var target = event.target, old,
1869 isClick = jQuery.nodeName(target, "a") && type === "click",
1870 special = jQuery.event.special[ type ] || {};
1871
1872 if ( (!special._default || special._default.call( elem, event ) === false) &&
1873 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
1874
1875 try {
1876 if ( target[ type ] ) {
1877 // Make sure that we don't accidentally re-trigger the onFOO events
1878 old = target[ "on" + type ];
1879
1880 if ( old ) {
1881 target[ "on" + type ] = null;
1882 }
1883
1884 jQuery.event.triggered = true;
1885 target[ type ]();
1886 }
1887
1888 // prevent IE from throwing an error for some elements with some event types, see #3533
1889 } catch (e) {}
1890
1891 if ( old ) {
1892 target[ "on" + type ] = old;
1893 }
1894
1895 jQuery.event.triggered = false;
1896 }
1897 }
1898 },
1899
1900 handle: function( event ) {
1901 var all, handlers, namespaces, namespace, events;
1902
1903 event = arguments[0] = jQuery.event.fix( event || window.event );
1904 event.currentTarget = this;
1905
1906 // Namespaced event handlers
1907 all = event.type.indexOf(".") < 0 && !event.exclusive;
1908
1909 if ( !all ) {
1910 namespaces = event.type.split(".");
1911 event.type = namespaces.shift();
1912 namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
1913 }
1914
1915 var events = jQuery.data(this, "events"), handlers = events[ event.type ];
1916
1917 if ( events && handlers ) {
1918 // Clone the handlers to prevent manipulation
1919 handlers = handlers.slice(0);
1920
1921 for ( var j = 0, l = handlers.length; j < l; j++ ) {
1922 var handleObj = handlers[ j ];
1923
1924 // Filter the functions by class
1925 if ( all || namespace.test( handleObj.namespace ) ) {
1926 // Pass in a reference to the handler function itself
1927 // So that we can later remove it
1928 event.handler = handleObj.handler;
1929 event.data = handleObj.data;
1930 event.handleObj = handleObj;
1931
1932 var ret = handleObj.handler.apply( this, arguments );
1933
1934 if ( ret !== undefined ) {
1935 event.result = ret;
1936 if ( ret === false ) {
1937 event.preventDefault();
1938 event.stopPropagation();
1939 }
1940 }
1941
1942 if ( event.isImmediatePropagationStopped() ) {
1943 break;
1944 }
1945 }
1946 }
1947 }
1948
1949 return event.result;
1950 },
1951
1952 props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
1953
1954 fix: function( event ) {
1955 if ( event[ expando ] ) {
1956 return event;
1957 }
1958
1959 // store a copy of the original event object
1960 // and "clone" to set read-only properties
1961 var originalEvent = event;
1962 event = jQuery.Event( originalEvent );
1963
1964 for ( var i = this.props.length, prop; i; ) {
1965 prop = this.props[ --i ];
1966 event[ prop ] = originalEvent[ prop ];
1967 }
1968
1969 // Fix target property, if necessary
1970 if ( !event.target ) {
1971 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
1972 }
1973
1974 // check if target is a textnode (safari)
1975 if ( event.target.nodeType === 3 ) {
1976 event.target = event.target.parentNode;
1977 }
1978
1979 // Add relatedTarget, if necessary
1980 if ( !event.relatedTarget && event.fromElement ) {
1981 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
1982 }
1983
1984 // Calculate pageX/Y if missing and clientX/Y available
1985 if ( event.pageX == null && event.clientX != null ) {
1986 var doc = document.documentElement, body = document.body;
1987 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
1988 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
1989 }
1990
1991 // Add which for key events
1992 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
1993 event.which = event.charCode || event.keyCode;
1994 }
1995
1996 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
1997 if ( !event.metaKey && event.ctrlKey ) {
1998 event.metaKey = event.ctrlKey;
1999 }
2000
2001 // Add which for click: 1 === left; 2 === middle; 3 === right
2002 // Note: button is not normalized, so don't use it
2003 if ( !event.which && event.button !== undefined ) {
2004 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2005 }
2006
2007 return event;
2008 },
2009
2010 // Deprecated, use jQuery.guid instead
2011 guid: 1E8,
2012
2013 // Deprecated, use jQuery.proxy instead
2014 proxy: jQuery.proxy,
2015
2016 special: {
2017 ready: {
2018 // Make sure the ready event is setup
2019 setup: jQuery.bindReady,
2020 teardown: jQuery.noop
2021 },
2022
2023 live: {
2024 add: function( handleObj ) {
2025 jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) );
2026 },
2027
2028 remove: function( handleObj ) {
2029 var remove = true,
2030 type = handleObj.origType.replace(rnamespaces, "");
2031
2032 jQuery.each( jQuery.data(this, "events").live || [], function() {
2033 if ( type === this.origType.replace(rnamespaces, "") ) {
2034 remove = false;
2035 return false;
2036 }
2037 });
2038
2039 if ( remove ) {
2040 jQuery.event.remove( this, handleObj.origType, liveHandler );
2041 }
2042 }
2043
2044 },
2045
2046 beforeunload: {
2047 setup: function( data, namespaces, eventHandle ) {
2048 // We only want to do this special case on windows
2049 if ( this.setInterval ) {
2050 this.onbeforeunload = eventHandle;
2051 }
2052
2053 return false;
2054 },
2055 teardown: function( namespaces, eventHandle ) {
2056 if ( this.onbeforeunload === eventHandle ) {
2057 this.onbeforeunload = null;
2058 }
2059 }
2060 }
2061 }
2062};
2063
2064var removeEvent = document.removeEventListener ?
2065 function( elem, type, handle ) {
2066 elem.removeEventListener( type, handle, false );
2067 } :
2068 function( elem, type, handle ) {
2069 elem.detachEvent( "on" + type, handle );
2070 };
2071
2072jQuery.Event = function( src ) {
2073 // Allow instantiation without the 'new' keyword
2074 if ( !this.preventDefault ) {
2075 return new jQuery.Event( src );
2076 }
2077
2078 // Event object
2079 if ( src && src.type ) {
2080 this.originalEvent = src;
2081 this.type = src.type;
2082 // Event type
2083 } else {
2084 this.type = src;
2085 }
2086
2087 // timeStamp is buggy for some events on Firefox(#3843)
2088 // So we won't rely on the native value
2089 this.timeStamp = now();
2090
2091 // Mark it as fixed
2092 this[ expando ] = true;
2093};
2094
2095function returnFalse() {
2096 return false;
2097}
2098function returnTrue() {
2099 return true;
2100}
2101
2102// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
2103// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
2104jQuery.Event.prototype = {
2105 preventDefault: function() {
2106 this.isDefaultPrevented = returnTrue;
2107
2108 var e = this.originalEvent;
2109 if ( !e ) {
2110 return;
2111 }
2112
2113 // if preventDefault exists run it on the original event
2114 if ( e.preventDefault ) {
2115 e.preventDefault();
2116 }
2117 // otherwise set the returnValue property of the original event to false (IE)
2118 e.returnValue = false;
2119 },
2120 stopPropagation: function() {
2121 this.isPropagationStopped = returnTrue;
2122
2123 var e = this.originalEvent;
2124 if ( !e ) {
2125 return;
2126 }
2127 // if stopPropagation exists run it on the original event
2128 if ( e.stopPropagation ) {
2129 e.stopPropagation();
2130 }
2131 // otherwise set the cancelBubble property of the original event to true (IE)
2132 e.cancelBubble = true;
2133 },
2134 stopImmediatePropagation: function() {
2135 this.isImmediatePropagationStopped = returnTrue;
2136 this.stopPropagation();
2137 },
2138 isDefaultPrevented: returnFalse,
2139 isPropagationStopped: returnFalse,
2140 isImmediatePropagationStopped: returnFalse
2141};
2142
2143// Checks if an event happened on an element within another element
2144// Used in jQuery.event.special.mouseenter and mouseleave handlers
2145var withinElement = function( event ) {
2146 // Check if mouse(over|out) are still within the same parent element
2147 var parent = event.relatedTarget;
2148
2149 // Firefox sometimes assigns relatedTarget a XUL element
2150 // which we cannot access the parentNode property of
2151 try {
2152 // Traverse up the tree
2153 while ( parent && parent !== this ) {
2154 parent = parent.parentNode;
2155 }
2156
2157 if ( parent !== this ) {
2158 // set the correct event type
2159 event.type = event.data;
2160
2161 // handle event if we actually just moused on to a non sub-element
2162 jQuery.event.handle.apply( this, arguments );
2163 }
2164
2165 // assuming we've left the element since we most likely mousedover a xul element
2166 } catch(e) { }
2167},
2168
2169// In case of event delegation, we only need to rename the event.type,
2170// liveHandler will take care of the rest.
2171delegate = function( event ) {
2172 event.type = event.data;
2173 jQuery.event.handle.apply( this, arguments );
2174};
2175
2176// Create mouseenter and mouseleave events
2177jQuery.each({
2178 mouseenter: "mouseover",
2179 mouseleave: "mouseout"
2180}, function( orig, fix ) {
2181 jQuery.event.special[ orig ] = {
2182 setup: function( data ) {
2183 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
2184 },
2185 teardown: function( data ) {
2186 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
2187 }
2188 };
2189});
2190
2191// submit delegation
2192if ( !jQuery.support.submitBubbles ) {
2193
2194 jQuery.event.special.submit = {
2195 setup: function( data, namespaces ) {
2196 if ( this.nodeName.toLowerCase() !== "form" ) {
2197 jQuery.event.add(this, "click.specialSubmit", function( e ) {
2198 var elem = e.target, type = elem.type;
2199
2200 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
2201 return trigger( "submit", this, arguments );
2202 }
2203 });
2204
2205 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
2206 var elem = e.target, type = elem.type;
2207
2208 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
2209 return trigger( "submit", this, arguments );
2210 }
2211 });
2212
2213 } else {
2214 return false;
2215 }
2216 },
2217
2218 teardown: function( namespaces ) {
2219 jQuery.event.remove( this, ".specialSubmit" );
2220 }
2221 };
2222
2223}
2224
2225// change delegation, happens here so we have bind.
2226if ( !jQuery.support.changeBubbles ) {
2227
2228 var formElems = /textarea|input|select/i,
2229
2230 changeFilters,
2231
2232 getVal = function( elem ) {
2233 var type = elem.type, val = elem.value;
2234
2235 if ( type === "radio" || type === "checkbox" ) {
2236 val = elem.checked;
2237
2238 } else if ( type === "select-multiple" ) {
2239 val = elem.selectedIndex > -1 ?
2240 jQuery.map( elem.options, function( elem ) {
2241 return elem.selected;
2242 }).join("-") :
2243 "";
2244
2245 } else if ( elem.nodeName.toLowerCase() === "select" ) {
2246 val = elem.selectedIndex;
2247 }
2248
2249 return val;
2250 },
2251
2252 testChange = function testChange( e ) {
2253 var elem = e.target, data, val;
2254
2255 if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
2256 return;
2257 }
2258
2259 data = jQuery.data( elem, "_change_data" );
2260 val = getVal(elem);
2261
2262 // the current data will be also retrieved by beforeactivate
2263 if ( e.type !== "focusout" || elem.type !== "radio" ) {
2264 jQuery.data( elem, "_change_data", val );
2265 }
2266
2267 if ( data === undefined || val === data ) {
2268 return;
2269 }
2270
2271 if ( data != null || val ) {
2272 e.type = "change";
2273 return jQuery.event.trigger( e, arguments[1], elem );
2274 }
2275 };
2276
2277 jQuery.event.special.change = {
2278 filters: {
2279 focusout: testChange,
2280
2281 click: function( e ) {
2282 var elem = e.target, type = elem.type;
2283
2284 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
2285 return testChange.call( this, e );
2286 }
2287 },
2288
2289 // Change has to be called before submit
2290 // Keydown will be called before keypress, which is used in submit-event delegation
2291 keydown: function( e ) {
2292 var elem = e.target, type = elem.type;
2293
2294 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
2295 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
2296 type === "select-multiple" ) {
2297 return testChange.call( this, e );
2298 }
2299 },
2300
2301 // Beforeactivate happens also before the previous element is blurred
2302 // with this event you can't trigger a change event, but you can store
2303 // information/focus[in] is not needed anymore
2304 beforeactivate: function( e ) {
2305 var elem = e.target;
2306 jQuery.data( elem, "_change_data", getVal(elem) );
2307 }
2308 },
2309
2310 setup: function( data, namespaces ) {
2311 if ( this.type === "file" ) {
2312 return false;
2313 }
2314
2315 for ( var type in changeFilters ) {
2316 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
2317 }
2318
2319 return formElems.test( this.nodeName );
2320 },
2321
2322 teardown: function( namespaces ) {
2323 jQuery.event.remove( this, ".specialChange" );
2324
2325 return formElems.test( this.nodeName );
2326 }
2327 };
2328
2329 changeFilters = jQuery.event.special.change.filters;
2330}
2331
2332function trigger( type, elem, args ) {
2333 args[0].type = type;
2334 return jQuery.event.handle.apply( elem, args );
2335}
2336
2337// Create "bubbling" focus and blur events
2338if ( document.addEventListener ) {
2339 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
2340 jQuery.event.special[ fix ] = {
2341 setup: function() {
2342 this.addEventListener( orig, handler, true );
2343 },
2344 teardown: function() {
2345 this.removeEventListener( orig, handler, true );
2346 }
2347 };
2348
2349 function handler( e ) {
2350 e = jQuery.event.fix( e );
2351 e.type = fix;
2352 return jQuery.event.handle.call( this, e );
2353 }
2354 });
2355}
2356
2357jQuery.each(["bind", "one"], function( i, name ) {
2358 jQuery.fn[ name ] = function( type, data, fn ) {
2359 // Handle object literals
2360 if ( typeof type === "object" ) {
2361 for ( var key in type ) {
2362 this[ name ](key, data, type[key], fn);
2363 }
2364 return this;
2365 }
2366
2367 if ( jQuery.isFunction( data ) ) {
2368 fn = data;
2369 data = undefined;
2370 }
2371
2372 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
2373 jQuery( this ).unbind( event, handler );
2374 return fn.apply( this, arguments );
2375 }) : fn;
2376
2377 if ( type === "unload" && name !== "one" ) {
2378 this.one( type, data, fn );
2379
2380 } else {
2381 for ( var i = 0, l = this.length; i < l; i++ ) {
2382 jQuery.event.add( this[i], type, handler, data );
2383 }
2384 }
2385
2386 return this;
2387 };
2388});
2389
2390jQuery.fn.extend({
2391 unbind: function( type, fn ) {
2392 // Handle object literals
2393 if ( typeof type === "object" && !type.preventDefault ) {
2394 for ( var key in type ) {
2395 this.unbind(key, type[key]);
2396 }
2397
2398 } else {
2399 for ( var i = 0, l = this.length; i < l; i++ ) {
2400 jQuery.event.remove( this[i], type, fn );
2401 }
2402 }
2403
2404 return this;
2405 },
2406
2407 delegate: function( selector, types, data, fn ) {
2408 return this.live( types, data, fn, selector );
2409 },
2410
2411 undelegate: function( selector, types, fn ) {
2412 if ( arguments.length === 0 ) {
2413 return this.unbind( "live" );
2414
2415 } else {
2416 return this.die( types, null, fn, selector );
2417 }
2418 },
2419
2420 trigger: function( type, data ) {
2421 return this.each(function() {
2422 jQuery.event.trigger( type, data, this );
2423 });
2424 },
2425
2426 triggerHandler: function( type, data ) {
2427 if ( this[0] ) {
2428 var event = jQuery.Event( type );
2429 event.preventDefault();
2430 event.stopPropagation();
2431 jQuery.event.trigger( event, data, this[0] );
2432 return event.result;
2433 }
2434 },
2435
2436 toggle: function( fn ) {
2437 // Save reference to arguments for access in closure
2438 var args = arguments, i = 1;
2439
2440 // link all the functions, so any of them can unbind this click handler
2441 while ( i < args.length ) {
2442 jQuery.proxy( fn, args[ i++ ] );
2443 }
2444
2445 return this.click( jQuery.proxy( fn, function( event ) {
2446 // Figure out which function to execute
2447 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
2448 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
2449
2450 // Make sure that clicks stop
2451 event.preventDefault();
2452
2453 // and execute the function
2454 return args[ lastToggle ].apply( this, arguments ) || false;
2455 }));
2456 },
2457
2458 hover: function( fnOver, fnOut ) {
2459 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
2460 }
2461});
2462
2463var liveMap = {
2464 focus: "focusin",
2465 blur: "focusout",
2466 mouseenter: "mouseover",
2467 mouseleave: "mouseout"
2468};
2469
2470jQuery.each(["live", "die"], function( i, name ) {
2471 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
2472 var type, i = 0, match, namespaces, preType,
2473 selector = origSelector || this.selector,
2474 context = origSelector ? this : jQuery( this.context );
2475
2476 if ( jQuery.isFunction( data ) ) {
2477 fn = data;
2478 data = undefined;
2479 }
2480
2481 types = (types || "").split(" ");
2482
2483 while ( (type = types[ i++ ]) != null ) {
2484 match = rnamespaces.exec( type );
2485 namespaces = "";
2486
2487 if ( match ) {
2488 namespaces = match[0];
2489 type = type.replace( rnamespaces, "" );
2490 }
2491
2492 if ( type === "hover" ) {
2493 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
2494 continue;
2495 }
2496
2497 preType = type;
2498
2499 if ( type === "focus" || type === "blur" ) {
2500 types.push( liveMap[ type ] + namespaces );
2501 type = type + namespaces;
2502
2503 } else {
2504 type = (liveMap[ type ] || type) + namespaces;
2505 }
2506
2507 if ( name === "live" ) {
2508 // bind live handler
2509 context.each(function(){
2510 jQuery.event.add( this, liveConvert( type, selector ),
2511 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
2512 });
2513
2514 } else {
2515 // unbind live handler
2516 context.unbind( liveConvert( type, selector ), fn );
2517 }
2518 }
2519
2520 return this;
2521 }
2522});
2523
2524function liveHandler( event ) {
2525 var stop, elems = [], selectors = [], args = arguments,
2526 related, match, handleObj, elem, j, i, l, data,
2527 events = jQuery.data( this, "events" );
2528
2529 // Make sure we avoid non-left-click bubbling in Firefox (#3861)
2530 if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
2531 return;
2532 }
2533
2534 event.liveFired = this;
2535
2536 var live = events.live.slice(0);
2537
2538 for ( j = 0; j < live.length; j++ ) {
2539 handleObj = live[j];
2540
2541 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
2542 selectors.push( handleObj.selector );
2543
2544 } else {
2545 live.splice( j--, 1 );
2546 }
2547 }
2548
2549 match = jQuery( event.target ).closest( selectors, event.currentTarget );
2550
2551 for ( i = 0, l = match.length; i < l; i++ ) {
2552 for ( j = 0; j < live.length; j++ ) {
2553 handleObj = live[j];
2554
2555 if ( match[i].selector === handleObj.selector ) {
2556 elem = match[i].elem;
2557 related = null;
2558
2559 // Those two events require additional checking
2560 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
2561 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
2562 }
2563
2564 if ( !related || related !== elem ) {
2565 elems.push({ elem: elem, handleObj: handleObj });
2566 }
2567 }
2568 }
2569 }
2570
2571 for ( i = 0, l = elems.length; i < l; i++ ) {
2572 match = elems[i];
2573 event.currentTarget = match.elem;
2574 event.data = match.handleObj.data;
2575 event.handleObj = match.handleObj;
2576
2577 if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) {
2578 stop = false;
2579 break;
2580 }
2581 }
2582
2583 return stop;
2584}
2585
2586function liveConvert( type, selector ) {
2587 return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
2588}
2589
2590jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
2591 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
2592 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
2593
2594 // Handle event binding
2595 jQuery.fn[ name ] = function( fn ) {
2596 return fn ? this.bind( name, fn ) : this.trigger( name );
2597 };
2598
2599 if ( jQuery.attrFn ) {
2600 jQuery.attrFn[ name ] = true;
2601 }
2602});
2603
2604// Prevent memory leaks in IE
2605// Window isn't included so as not to unbind existing unload events
2606// More info:
2607// - http://isaacschlueter.com/2006/10/msie-memory-leaks/
2608if ( window.attachEvent && !window.addEventListener ) {
2609 window.attachEvent("onunload", function() {
2610 for ( var id in jQuery.cache ) {
2611 if ( jQuery.cache[ id ].handle ) {
2612 // Try/Catch is to handle iframes being unloaded, see #4280
2613 try {
2614 jQuery.event.remove( jQuery.cache[ id ].handle.elem );
2615 } catch(e) {}
2616 }
2617 }
2618 });
2619}
2620/*!
2621 * Sizzle CSS Selector Engine - v1.0
2622 * Copyright 2009, The Dojo Foundation
2623 * Released under the MIT, BSD, and GPL Licenses.
2624 * More information: http://sizzlejs.com/
2625 */
2626(function(){
2627
2628var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
2629 done = 0,
2630 toString = Object.prototype.toString,
2631 hasDuplicate = false,
2632 baseHasDuplicate = true;
2633
2634// Here we check if the JavaScript engine is using some sort of
2635// optimization where it does not always call our comparision
2636// function. If that is the case, discard the hasDuplicate value.
2637// Thus far that includes Google Chrome.
2638[0, 0].sort(function(){
2639 baseHasDuplicate = false;
2640 return 0;
2641});
2642
2643var Sizzle = function(selector, context, results, seed) {
2644 results = results || [];
2645 var origContext = context = context || document;
2646
2647 if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
2648 return [];
2649 }
2650
2651 if ( !selector || typeof selector !== "string" ) {
2652 return results;
2653 }
2654
2655 var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context),
2656 soFar = selector;
2657
2658 // Reset the position of the chunker regexp (start from head)
2659 while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
2660 soFar = m[3];
2661
2662 parts.push( m[1] );
2663
2664 if ( m[2] ) {
2665 extra = m[3];
2666 break;
2667 }
2668 }
2669
2670 if ( parts.length > 1 && origPOS.exec( selector ) ) {
2671 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
2672 set = posProcess( parts[0] + parts[1], context );
2673 } else {
2674 set = Expr.relative[ parts[0] ] ?
2675 [ context ] :
2676 Sizzle( parts.shift(), context );
2677
2678 while ( parts.length ) {
2679 selector = parts.shift();
2680
2681 if ( Expr.relative[ selector ] ) {
2682 selector += parts.shift();
2683 }
2684
2685 set = posProcess( selector, set );
2686 }
2687 }
2688 } else {
2689 // Take a shortcut and set the context if the root selector is an ID
2690 // (but not if it'll be faster if the inner selector is an ID)
2691 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
2692 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
2693 var ret = Sizzle.find( parts.shift(), context, contextXML );
2694 context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
2695 }
2696
2697 if ( context ) {
2698 var ret = seed ?
2699 { expr: parts.pop(), set: makeArray(seed) } :
2700 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
2701 set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
2702
2703 if ( parts.length > 0 ) {
2704 checkSet = makeArray(set);
2705 } else {
2706 prune = false;
2707 }
2708
2709 while ( parts.length ) {
2710 var cur = parts.pop(), pop = cur;
2711
2712 if ( !Expr.relative[ cur ] ) {
2713 cur = "";
2714 } else {
2715 pop = parts.pop();
2716 }
2717
2718 if ( pop == null ) {
2719 pop = context;
2720 }
2721
2722 Expr.relative[ cur ]( checkSet, pop, contextXML );
2723 }
2724 } else {
2725 checkSet = parts = [];
2726 }
2727 }
2728
2729 if ( !checkSet ) {
2730 checkSet = set;
2731 }
2732
2733 if ( !checkSet ) {
2734 Sizzle.error( cur || selector );
2735 }
2736
2737 if ( toString.call(checkSet) === "[object Array]" ) {
2738 if ( !prune ) {
2739 results.push.apply( results, checkSet );
2740 } else if ( context && context.nodeType === 1 ) {
2741 for ( var i = 0; checkSet[i] != null; i++ ) {
2742 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
2743 results.push( set[i] );
2744 }
2745 }
2746 } else {
2747 for ( var i = 0; checkSet[i] != null; i++ ) {
2748 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
2749 results.push( set[i] );
2750 }
2751 }
2752 }
2753 } else {
2754 makeArray( checkSet, results );
2755 }
2756
2757 if ( extra ) {
2758 Sizzle( extra, origContext, results, seed );
2759 Sizzle.uniqueSort( results );
2760 }
2761
2762 return results;
2763};
2764
2765Sizzle.uniqueSort = function(results){
2766 if ( sortOrder ) {
2767 hasDuplicate = baseHasDuplicate;
2768 results.sort(sortOrder);
2769
2770 if ( hasDuplicate ) {
2771 for ( var i = 1; i < results.length; i++ ) {
2772 if ( results[i] === results[i-1] ) {
2773 results.splice(i--, 1);
2774 }
2775 }
2776 }
2777 }
2778
2779 return results;
2780};
2781
2782Sizzle.matches = function(expr, set){
2783 return Sizzle(expr, null, null, set);
2784};
2785
2786Sizzle.find = function(expr, context, isXML){
2787 var set, match;
2788
2789 if ( !expr ) {
2790 return [];
2791 }
2792
2793 for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
2794 var type = Expr.order[i], match;
2795
2796 if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
2797 var left = match[1];
2798 match.splice(1,1);
2799
2800 if ( left.substr( left.length - 1 ) !== "\\" ) {
2801 match[1] = (match[1] || "").replace(/\\/g, "");
2802 set = Expr.find[ type ]( match, context, isXML );
2803 if ( set != null ) {
2804 expr = expr.replace( Expr.match[ type ], "" );
2805 break;
2806 }
2807 }
2808 }
2809 }
2810
2811 if ( !set ) {
2812 set = context.getElementsByTagName("*");
2813 }
2814
2815 return {set: set, expr: expr};
2816};
2817
2818Sizzle.filter = function(expr, set, inplace, not){
2819 var old = expr, result = [], curLoop = set, match, anyFound,
2820 isXMLFilter = set && set[0] && isXML(set[0]);
2821
2822 while ( expr && set.length ) {
2823 for ( var type in Expr.filter ) {
2824 if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
2825 var filter = Expr.filter[ type ], found, item, left = match[1];
2826 anyFound = false;
2827
2828 match.splice(1,1);
2829
2830 if ( left.substr( left.length - 1 ) === "\\" ) {
2831 continue;
2832 }
2833
2834 if ( curLoop === result ) {
2835 result = [];
2836 }
2837
2838 if ( Expr.preFilter[ type ] ) {
2839 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
2840
2841 if ( !match ) {
2842 anyFound = found = true;
2843 } else if ( match === true ) {
2844 continue;
2845 }
2846 }
2847
2848 if ( match ) {
2849 for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
2850 if ( item ) {
2851 found = filter( item, match, i, curLoop );
2852 var pass = not ^ !!found;
2853
2854 if ( inplace && found != null ) {
2855 if ( pass ) {
2856 anyFound = true;
2857 } else {
2858 curLoop[i] = false;
2859 }
2860 } else if ( pass ) {
2861 result.push( item );
2862 anyFound = true;
2863 }
2864 }
2865 }
2866 }
2867
2868 if ( found !== undefined ) {
2869 if ( !inplace ) {
2870 curLoop = result;
2871 }
2872
2873 expr = expr.replace( Expr.match[ type ], "" );
2874
2875 if ( !anyFound ) {
2876 return [];
2877 }
2878
2879 break;
2880 }
2881 }
2882 }
2883
2884 // Improper expression
2885 if ( expr === old ) {
2886 if ( anyFound == null ) {
2887 Sizzle.error( expr );
2888 } else {
2889 break;
2890 }
2891 }
2892
2893 old = expr;
2894 }
2895
2896 return curLoop;
2897};
2898
2899Sizzle.error = function( msg ) {
2900 throw "Syntax error, unrecognized expression: " + msg;
2901};
2902
2903var Expr = Sizzle.selectors = {
2904 order: [ "ID", "NAME", "TAG" ],
2905 match: {
2906 ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
2907 CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
2908 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
2909 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
2910 TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
2911 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
2912 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
2913 PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
2914 },
2915 leftMatch: {},
2916 attrMap: {
2917 "class": "className",
2918 "for": "htmlFor"
2919 },
2920 attrHandle: {
2921 href: function(elem){
2922 return elem.getAttribute("href");
2923 }
2924 },
2925 relative: {
2926 "+": function(checkSet, part){
2927 var isPartStr = typeof part === "string",
2928 isTag = isPartStr && !/\W/.test(part),
2929 isPartStrNotTag = isPartStr && !isTag;
2930
2931 if ( isTag ) {
2932 part = part.toLowerCase();
2933 }
2934
2935 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
2936 if ( (elem = checkSet[i]) ) {
2937 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
2938
2939 checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
2940 elem || false :
2941 elem === part;
2942 }
2943 }
2944
2945 if ( isPartStrNotTag ) {
2946 Sizzle.filter( part, checkSet, true );
2947 }
2948 },
2949 ">": function(checkSet, part){
2950 var isPartStr = typeof part === "string";
2951
2952 if ( isPartStr && !/\W/.test(part) ) {
2953 part = part.toLowerCase();
2954
2955 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2956 var elem = checkSet[i];
2957 if ( elem ) {
2958 var parent = elem.parentNode;
2959 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
2960 }
2961 }
2962 } else {
2963 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2964 var elem = checkSet[i];
2965 if ( elem ) {
2966 checkSet[i] = isPartStr ?
2967 elem.parentNode :
2968 elem.parentNode === part;
2969 }
2970 }
2971
2972 if ( isPartStr ) {
2973 Sizzle.filter( part, checkSet, true );
2974 }
2975 }
2976 },
2977 "": function(checkSet, part, isXML){
2978 var doneName = done++, checkFn = dirCheck;
2979
2980 if ( typeof part === "string" && !/\W/.test(part) ) {
2981 var nodeCheck = part = part.toLowerCase();
2982 checkFn = dirNodeCheck;
2983 }
2984
2985 checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
2986 },
2987 "~": function(checkSet, part, isXML){
2988 var doneName = done++, checkFn = dirCheck;
2989
2990 if ( typeof part === "string" && !/\W/.test(part) ) {
2991 var nodeCheck = part = part.toLowerCase();
2992 checkFn = dirNodeCheck;
2993 }
2994
2995 checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
2996 }
2997 },
2998 find: {
2999 ID: function(match, context, isXML){
3000 if ( typeof context.getElementById !== "undefined" && !isXML ) {
3001 var m = context.getElementById(match[1]);
3002 return m ? [m] : [];
3003 }
3004 },
3005 NAME: function(match, context){
3006 if ( typeof context.getElementsByName !== "undefined" ) {
3007 var ret = [], results = context.getElementsByName(match[1]);
3008
3009 for ( var i = 0, l = results.length; i < l; i++ ) {
3010 if ( results[i].getAttribute("name") === match[1] ) {
3011 ret.push( results[i] );
3012 }
3013 }
3014
3015 return ret.length === 0 ? null : ret;
3016 }
3017 },
3018 TAG: function(match, context){
3019 return context.getElementsByTagName(match[1]);
3020 }
3021 },
3022 preFilter: {
3023 CLASS: function(match, curLoop, inplace, result, not, isXML){
3024 match = " " + match[1].replace(/\\/g, "") + " ";
3025
3026 if ( isXML ) {
3027 return match;
3028 }
3029
3030 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
3031 if ( elem ) {
3032 if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
3033 if ( !inplace ) {
3034 result.push( elem );
3035 }
3036 } else if ( inplace ) {
3037 curLoop[i] = false;
3038 }
3039 }
3040 }
3041
3042 return false;
3043 },
3044 ID: function(match){
3045 return match[1].replace(/\\/g, "");
3046 },
3047 TAG: function(match, curLoop){
3048 return match[1].toLowerCase();
3049 },
3050 CHILD: function(match){
3051 if ( match[1] === "nth" ) {
3052 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
3053 var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
3054 match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
3055 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
3056
3057 // calculate the numbers (first)n+(last) including if they are negative
3058 match[2] = (test[1] + (test[2] || 1)) - 0;
3059 match[3] = test[3] - 0;
3060 }
3061
3062 // TODO: Move to normal caching system
3063 match[0] = done++;
3064
3065 return match;
3066 },
3067 ATTR: function(match, curLoop, inplace, result, not, isXML){
3068 var name = match[1].replace(/\\/g, "");
3069
3070 if ( !isXML && Expr.attrMap[name] ) {
3071 match[1] = Expr.attrMap[name];
3072 }
3073
3074 if ( match[2] === "~=" ) {
3075 match[4] = " " + match[4] + " ";
3076 }
3077
3078 return match;
3079 },
3080 PSEUDO: function(match, curLoop, inplace, result, not){
3081 if ( match[1] === "not" ) {
3082 // If we're dealing with a complex expression, or a simple one
3083 if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
3084 match[3] = Sizzle(match[3], null, null, curLoop);
3085 } else {
3086 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
3087 if ( !inplace ) {
3088 result.push.apply( result, ret );
3089 }
3090 return false;
3091 }
3092 } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
3093 return true;
3094 }
3095
3096 return match;
3097 },
3098 POS: function(match){
3099 match.unshift( true );
3100 return match;
3101 }
3102 },
3103 filters: {
3104 enabled: function(elem){
3105 return elem.disabled === false && elem.type !== "hidden";
3106 },
3107 disabled: function(elem){
3108 return elem.disabled === true;
3109 },
3110 checked: function(elem){
3111 return elem.checked === true;
3112 },
3113 selected: function(elem){
3114 // Accessing this property makes selected-by-default
3115 // options in Safari work properly
3116 elem.parentNode.selectedIndex;
3117 return elem.selected === true;
3118 },
3119 parent: function(elem){
3120 return !!elem.firstChild;
3121 },
3122 empty: function(elem){
3123 return !elem.firstChild;
3124 },
3125 has: function(elem, i, match){
3126 return !!Sizzle( match[3], elem ).length;
3127 },
3128 header: function(elem){
3129 return /h\d/i.test( elem.nodeName );
3130 },
3131 text: function(elem){
3132 return "text" === elem.type;
3133 },
3134 radio: function(elem){
3135 return "radio" === elem.type;
3136 },
3137 checkbox: function(elem){
3138 return "checkbox" === elem.type;
3139 },
3140 file: function(elem){
3141 return "file" === elem.type;
3142 },
3143 password: function(elem){
3144 return "password" === elem.type;
3145 },
3146 submit: function(elem){
3147 return "submit" === elem.type;
3148 },
3149 image: function(elem){
3150 return "image" === elem.type;
3151 },
3152 reset: function(elem){
3153 return "reset" === elem.type;
3154 },
3155 button: function(elem){
3156 return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
3157 },
3158 input: function(elem){
3159 return /input|select|textarea|button/i.test(elem.nodeName);
3160 }
3161 },
3162 setFilters: {
3163 first: function(elem, i){
3164 return i === 0;
3165 },
3166 last: function(elem, i, match, array){
3167 return i === array.length - 1;
3168 },
3169 even: function(elem, i){
3170 return i % 2 === 0;
3171 },
3172 odd: function(elem, i){
3173 return i % 2 === 1;
3174 },
3175 lt: function(elem, i, match){
3176 return i < match[3] - 0;
3177 },
3178 gt: function(elem, i, match){
3179 return i > match[3] - 0;
3180 },
3181 nth: function(elem, i, match){
3182 return match[3] - 0 === i;
3183 },
3184 eq: function(elem, i, match){
3185 return match[3] - 0 === i;
3186 }
3187 },
3188 filter: {
3189 PSEUDO: function(elem, match, i, array){
3190 var name = match[1], filter = Expr.filters[ name ];
3191
3192 if ( filter ) {
3193 return filter( elem, i, match, array );
3194 } else if ( name === "contains" ) {
3195 return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
3196 } else if ( name === "not" ) {
3197 var not = match[3];
3198
3199 for ( var i = 0, l = not.length; i < l; i++ ) {
3200 if ( not[i] === elem ) {
3201 return false;
3202 }
3203 }
3204
3205 return true;
3206 } else {
3207 Sizzle.error( "Syntax error, unrecognized expression: " + name );
3208 }
3209 },
3210 CHILD: function(elem, match){
3211 var type = match[1], node = elem;
3212 switch (type) {
3213 case 'only':
3214 case 'first':
3215 while ( (node = node.previousSibling) ) {
3216 if ( node.nodeType === 1 ) {
3217 return false;
3218 }
3219 }
3220 if ( type === "first" ) {
3221 return true;
3222 }
3223 node = elem;
3224 case 'last':
3225 while ( (node = node.nextSibling) ) {
3226 if ( node.nodeType === 1 ) {
3227 return false;
3228 }
3229 }
3230 return true;
3231 case 'nth':
3232 var first = match[2], last = match[3];
3233
3234 if ( first === 1 && last === 0 ) {
3235 return true;
3236 }
3237
3238 var doneName = match[0],
3239 parent = elem.parentNode;
3240
3241 if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
3242 var count = 0;
3243 for ( node = parent.firstChild; node; node = node.nextSibling ) {
3244 if ( node.nodeType === 1 ) {
3245 node.nodeIndex = ++count;
3246 }
3247 }
3248 parent.sizcache = doneName;
3249 }
3250
3251 var diff = elem.nodeIndex - last;
3252 if ( first === 0 ) {
3253 return diff === 0;
3254 } else {
3255 return ( diff % first === 0 && diff / first >= 0 );
3256 }
3257 }
3258 },
3259 ID: function(elem, match){
3260 return elem.nodeType === 1 && elem.getAttribute("id") === match;
3261 },
3262 TAG: function(elem, match){
3263 return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
3264 },
3265 CLASS: function(elem, match){
3266 return (" " + (elem.className || elem.getAttribute("class")) + " ")
3267 .indexOf( match ) > -1;
3268 },
3269 ATTR: function(elem, match){
3270 var name = match[1],
3271 result = Expr.attrHandle[ name ] ?
3272 Expr.attrHandle[ name ]( elem ) :
3273 elem[ name ] != null ?
3274 elem[ name ] :
3275 elem.getAttribute( name ),
3276 value = result + "",
3277 type = match[2],
3278 check = match[4];
3279
3280 return result == null ?
3281 type === "!=" :
3282 type === "=" ?
3283 value === check :
3284 type === "*=" ?
3285 value.indexOf(check) >= 0 :
3286 type === "~=" ?
3287 (" " + value + " ").indexOf(check) >= 0 :
3288 !check ?
3289 value && result !== false :
3290 type === "!=" ?
3291 value !== check :
3292 type === "^=" ?
3293 value.indexOf(check) === 0 :
3294 type === "$=" ?
3295 value.substr(value.length - check.length) === check :
3296 type === "|=" ?
3297 value === check || value.substr(0, check.length + 1) === check + "-" :
3298 false;
3299 },
3300 POS: function(elem, match, i, array){
3301 var name = match[2], filter = Expr.setFilters[ name ];
3302
3303 if ( filter ) {
3304 return filter( elem, i, match, array );
3305 }
3306 }
3307 }
3308};
3309
3310var origPOS = Expr.match.POS;
3311
3312for ( var type in Expr.match ) {
3313 Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
3314 Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){
3315 return "\\" + (num - 0 + 1);
3316 }));
3317}
3318
3319var makeArray = function(array, results) {
3320 array = Array.prototype.slice.call( array, 0 );
3321
3322 if ( results ) {
3323 results.push.apply( results, array );
3324 return results;
3325 }
3326
3327 return array;
3328};
3329
3330// Perform a simple check to determine if the browser is capable of
3331// converting a NodeList to an array using builtin methods.
3332// Also verifies that the returned array holds DOM nodes
3333// (which is not the case in the Blackberry browser)
3334try {
3335 Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
3336
3337// Provide a fallback method if it does not work
3338} catch(e){
3339 makeArray = function(array, results) {
3340 var ret = results || [];
3341
3342 if ( toString.call(array) === "[object Array]" ) {
3343 Array.prototype.push.apply( ret, array );
3344 } else {
3345 if ( typeof array.length === "number" ) {
3346 for ( var i = 0, l = array.length; i < l; i++ ) {
3347 ret.push( array[i] );
3348 }
3349 } else {
3350 for ( var i = 0; array[i]; i++ ) {
3351 ret.push( array[i] );
3352 }
3353 }
3354 }
3355
3356 return ret;
3357 };
3358}
3359
3360var sortOrder;
3361
3362if ( document.documentElement.compareDocumentPosition ) {
3363 sortOrder = function( a, b ) {
3364 if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
3365 if ( a == b ) {
3366 hasDuplicate = true;
3367 }
3368 return a.compareDocumentPosition ? -1 : 1;
3369 }
3370
3371 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
3372 if ( ret === 0 ) {
3373 hasDuplicate = true;
3374 }
3375 return ret;
3376 };
3377} else if ( "sourceIndex" in document.documentElement ) {
3378 sortOrder = function( a, b ) {
3379 if ( !a.sourceIndex || !b.sourceIndex ) {
3380 if ( a == b ) {
3381 hasDuplicate = true;
3382 }
3383 return a.sourceIndex ? -1 : 1;
3384 }
3385
3386 var ret = a.sourceIndex - b.sourceIndex;
3387 if ( ret === 0 ) {
3388 hasDuplicate = true;
3389 }
3390 return ret;
3391 };
3392} else if ( document.createRange ) {
3393 sortOrder = function( a, b ) {
3394 if ( !a.ownerDocument || !b.ownerDocument ) {
3395 if ( a == b ) {
3396 hasDuplicate = true;
3397 }
3398 return a.ownerDocument ? -1 : 1;
3399 }
3400
3401 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
3402 aRange.setStart(a, 0);
3403 aRange.setEnd(a, 0);
3404 bRange.setStart(b, 0);
3405 bRange.setEnd(b, 0);
3406 var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
3407 if ( ret === 0 ) {
3408 hasDuplicate = true;
3409 }
3410 return ret;
3411 };
3412}
3413
3414// Utility function for retreiving the text value of an array of DOM nodes
3415function getText( elems ) {
3416 var ret = "", elem;
3417
3418 for ( var i = 0; elems[i]; i++ ) {
3419 elem = elems[i];
3420
3421 // Get the text from text nodes and CDATA nodes
3422 if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
3423 ret += elem.nodeValue;
3424
3425 // Traverse everything else, except comment nodes
3426 } else if ( elem.nodeType !== 8 ) {
3427 ret += getText( elem.childNodes );
3428 }
3429 }
3430
3431 return ret;
3432}
3433
3434// Check to see if the browser returns elements by name when
3435// querying by getElementById (and provide a workaround)
3436(function(){
3437 // We're going to inject a fake input element with a specified name
3438 var form = document.createElement("div"),
3439 id = "script" + (new Date).getTime();
3440 form.innerHTML = "<a name='" + id + "'/>";
3441
3442 // Inject it into the root element, check its status, and remove it quickly
3443 var root = document.documentElement;
3444 root.insertBefore( form, root.firstChild );
3445
3446 // The workaround has to do additional checks after a getElementById
3447 // Which slows things down for other browsers (hence the branching)
3448 if ( document.getElementById( id ) ) {
3449 Expr.find.ID = function(match, context, isXML){
3450 if ( typeof context.getElementById !== "undefined" && !isXML ) {
3451 var m = context.getElementById(match[1]);
3452 return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
3453 }
3454 };
3455
3456 Expr.filter.ID = function(elem, match){
3457 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
3458 return elem.nodeType === 1 && node && node.nodeValue === match;
3459 };
3460 }
3461
3462 root.removeChild( form );
3463 root = form = null; // release memory in IE
3464})();
3465
3466(function(){
3467 // Check to see if the browser returns only elements
3468 // when doing getElementsByTagName("*")
3469
3470 // Create a fake element
3471 var div = document.createElement("div");
3472 div.appendChild( document.createComment("") );
3473
3474 // Make sure no comments are found
3475 if ( div.getElementsByTagName("*").length > 0 ) {
3476 Expr.find.TAG = function(match, context){
3477 var results = context.getElementsByTagName(match[1]);
3478
3479 // Filter out possible comments
3480 if ( match[1] === "*" ) {
3481 var tmp = [];
3482
3483 for ( var i = 0; results[i]; i++ ) {
3484 if ( results[i].nodeType === 1 ) {
3485 tmp.push( results[i] );
3486 }
3487 }
3488
3489 results = tmp;
3490 }
3491
3492 return results;
3493 };
3494 }
3495
3496 // Check to see if an attribute returns normalized href attributes
3497 div.innerHTML = "<a href='#'></a>";
3498 if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
3499 div.firstChild.getAttribute("href") !== "#" ) {
3500 Expr.attrHandle.href = function(elem){
3501 return elem.getAttribute("href", 2);
3502 };
3503 }
3504
3505 div = null; // release memory in IE
3506})();
3507
3508if ( document.querySelectorAll ) {
3509 (function(){
3510 var oldSizzle = Sizzle, div = document.createElement("div");
3511 div.innerHTML = "<p class='TEST'></p>";
3512
3513 // Safari can't handle uppercase or unicode characters when
3514 // in quirks mode.
3515 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
3516 return;
3517 }
3518
3519 Sizzle = function(query, context, extra, seed){
3520 context = context || document;
3521
3522 // Only use querySelectorAll on non-XML documents
3523 // (ID selectors don't work in non-HTML documents)
3524 if ( !seed && context.nodeType === 9 && !isXML(context) ) {
3525 try {
3526 return makeArray( context.querySelectorAll(query), extra );
3527 } catch(e){}
3528 }
3529
3530 return oldSizzle(query, context, extra, seed);
3531 };
3532
3533 for ( var prop in oldSizzle ) {
3534 Sizzle[ prop ] = oldSizzle[ prop ];
3535 }
3536
3537 div = null; // release memory in IE
3538 })();
3539}
3540
3541(function(){
3542 var div = document.createElement("div");
3543
3544 div.innerHTML = "<div class='test e'></div><div class='test'></div>";
3545
3546 // Opera can't find a second classname (in 9.6)
3547 // Also, make sure that getElementsByClassName actually exists
3548 if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
3549 return;
3550 }
3551
3552 // Safari caches class attributes, doesn't catch changes (in 3.2)
3553 div.lastChild.className = "e";
3554
3555 if ( div.getElementsByClassName("e").length === 1 ) {
3556 return;
3557 }
3558
3559 Expr.order.splice(1, 0, "CLASS");
3560 Expr.find.CLASS = function(match, context, isXML) {
3561 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
3562 return context.getElementsByClassName(match[1]);
3563 }
3564 };
3565
3566 div = null; // release memory in IE
3567})();
3568
3569function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
3570 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
3571 var elem = checkSet[i];
3572 if ( elem ) {
3573 elem = elem[dir];
3574 var match = false;
3575
3576 while ( elem ) {
3577 if ( elem.sizcache === doneName ) {
3578 match = checkSet[elem.sizset];
3579 break;
3580 }
3581
3582 if ( elem.nodeType === 1 && !isXML ){
3583 elem.sizcache = doneName;
3584 elem.sizset = i;
3585 }
3586
3587 if ( elem.nodeName.toLowerCase() === cur ) {
3588 match = elem;
3589 break;
3590 }
3591
3592 elem = elem[dir];
3593 }
3594
3595 checkSet[i] = match;
3596 }
3597 }
3598}
3599
3600function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
3601 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
3602 var elem = checkSet[i];
3603 if ( elem ) {
3604 elem = elem[dir];
3605 var match = false;
3606
3607 while ( elem ) {
3608 if ( elem.sizcache === doneName ) {
3609 match = checkSet[elem.sizset];
3610 break;
3611 }
3612
3613 if ( elem.nodeType === 1 ) {
3614 if ( !isXML ) {
3615 elem.sizcache = doneName;
3616 elem.sizset = i;
3617 }
3618 if ( typeof cur !== "string" ) {
3619 if ( elem === cur ) {
3620 match = true;
3621 break;
3622 }
3623
3624 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
3625 match = elem;
3626 break;
3627 }
3628 }
3629
3630 elem = elem[dir];
3631 }
3632
3633 checkSet[i] = match;
3634 }
3635 }
3636}
3637
3638var contains = document.compareDocumentPosition ? function(a, b){
3639 return !!(a.compareDocumentPosition(b) & 16);
3640} : function(a, b){
3641 return a !== b && (a.contains ? a.contains(b) : true);
3642};
3643
3644var isXML = function(elem){
3645 // documentElement is verified for cases where it doesn't yet exist
3646 // (such as loading iframes in IE - #4833)
3647 var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
3648 return documentElement ? documentElement.nodeName !== "HTML" : false;
3649};
3650
3651var posProcess = function(selector, context){
3652 var tmpSet = [], later = "", match,
3653 root = context.nodeType ? [context] : context;
3654
3655 // Position selectors must be done after the filter
3656 // And so must :not(positional) so we move all PSEUDOs to the end
3657 while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
3658 later += match[0];
3659 selector = selector.replace( Expr.match.PSEUDO, "" );
3660 }
3661
3662 selector = Expr.relative[selector] ? selector + "*" : selector;
3663
3664 for ( var i = 0, l = root.length; i < l; i++ ) {
3665 Sizzle( selector, root[i], tmpSet );
3666 }
3667
3668 return Sizzle.filter( later, tmpSet );
3669};
3670
3671// EXPOSE
3672jQuery.find = Sizzle;
3673jQuery.expr = Sizzle.selectors;
3674jQuery.expr[":"] = jQuery.expr.filters;
3675jQuery.unique = Sizzle.uniqueSort;
3676jQuery.text = getText;
3677jQuery.isXMLDoc = isXML;
3678jQuery.contains = contains;
3679
3680return;
3681
3682window.Sizzle = Sizzle;
3683
3684})();
3685var runtil = /Until$/,
3686 rparentsprev = /^(?:parents|prevUntil|prevAll)/,
3687 // Note: This RegExp should be improved, or likely pulled from Sizzle
3688 rmultiselector = /,/,
3689 slice = Array.prototype.slice;
3690
3691// Implement the identical functionality for filter and not
3692var winnow = function( elements, qualifier, keep ) {
3693 if ( jQuery.isFunction( qualifier ) ) {
3694 return jQuery.grep(elements, function( elem, i ) {
3695 return !!qualifier.call( elem, i, elem ) === keep;
3696 });
3697
3698 } else if ( qualifier.nodeType ) {
3699 return jQuery.grep(elements, function( elem, i ) {
3700 return (elem === qualifier) === keep;
3701 });
3702
3703 } else if ( typeof qualifier === "string" ) {
3704 var filtered = jQuery.grep(elements, function( elem ) {
3705 return elem.nodeType === 1;
3706 });
3707
3708 if ( isSimple.test( qualifier ) ) {
3709 return jQuery.filter(qualifier, filtered, !keep);
3710 } else {
3711 qualifier = jQuery.filter( qualifier, filtered );
3712 }
3713 }
3714
3715 return jQuery.grep(elements, function( elem, i ) {
3716 return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
3717 });
3718};
3719
3720jQuery.fn.extend({
3721 find: function( selector ) {
3722 var ret = this.pushStack( "", "find", selector ), length = 0;
3723
3724 for ( var i = 0, l = this.length; i < l; i++ ) {
3725 length = ret.length;
3726 jQuery.find( selector, this[i], ret );
3727
3728 if ( i > 0 ) {
3729 // Make sure that the results are unique
3730 for ( var n = length; n < ret.length; n++ ) {
3731 for ( var r = 0; r < length; r++ ) {
3732 if ( ret[r] === ret[n] ) {
3733 ret.splice(n--, 1);
3734 break;
3735 }
3736 }
3737 }
3738 }
3739 }
3740
3741 return ret;
3742 },
3743
3744 has: function( target ) {
3745 var targets = jQuery( target );
3746 return this.filter(function() {
3747 for ( var i = 0, l = targets.length; i < l; i++ ) {
3748 if ( jQuery.contains( this, targets[i] ) ) {
3749 return true;
3750 }
3751 }
3752 });
3753 },
3754
3755 not: function( selector ) {
3756 return this.pushStack( winnow(this, selector, false), "not", selector);
3757 },
3758
3759 filter: function( selector ) {
3760 return this.pushStack( winnow(this, selector, true), "filter", selector );
3761 },
3762
3763 is: function( selector ) {
3764 return !!selector && jQuery.filter( selector, this ).length > 0;
3765 },
3766
3767 closest: function( selectors, context ) {
3768 if ( jQuery.isArray( selectors ) ) {
3769 var ret = [], cur = this[0], match, matches = {}, selector;
3770
3771 if ( cur && selectors.length ) {
3772 for ( var i = 0, l = selectors.length; i < l; i++ ) {
3773 selector = selectors[i];
3774
3775 if ( !matches[selector] ) {
3776 matches[selector] = jQuery.expr.match.POS.test( selector ) ?
3777 jQuery( selector, context || this.context ) :
3778 selector;
3779 }
3780 }
3781
3782 while ( cur && cur.ownerDocument && cur !== context ) {
3783 for ( selector in matches ) {
3784 match = matches[selector];
3785
3786 if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
3787 ret.push({ selector: selector, elem: cur });
3788 delete matches[selector];
3789 }
3790 }
3791 cur = cur.parentNode;
3792 }
3793 }
3794
3795 return ret;
3796 }
3797
3798 var pos = jQuery.expr.match.POS.test( selectors ) ?
3799 jQuery( selectors, context || this.context ) : null;
3800
3801 return this.map(function( i, cur ) {
3802 while ( cur && cur.ownerDocument && cur !== context ) {
3803 if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) {
3804 return cur;
3805 }
3806 cur = cur.parentNode;
3807 }
3808 return null;
3809 });
3810 },
3811
3812 // Determine the position of an element within
3813 // the matched set of elements
3814 index: function( elem ) {
3815 if ( !elem || typeof elem === "string" ) {
3816 return jQuery.inArray( this[0],
3817 // If it receives a string, the selector is used
3818 // If it receives nothing, the siblings are used
3819 elem ? jQuery( elem ) : this.parent().children() );
3820 }
3821 // Locate the position of the desired element
3822 return jQuery.inArray(
3823 // If it receives a jQuery object, the first element is used
3824 elem.jquery ? elem[0] : elem, this );
3825 },
3826
3827 add: function( selector, context ) {
3828 var set = typeof selector === "string" ?
3829 jQuery( selector, context || this.context ) :
3830 jQuery.makeArray( selector ),
3831 all = jQuery.merge( this.get(), set );
3832
3833 return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
3834 all :
3835 jQuery.unique( all ) );
3836 },
3837
3838 andSelf: function() {
3839 return this.add( this.prevObject );
3840 }
3841});
3842
3843// A painfully simple check to see if an element is disconnected
3844// from a document (should be improved, where feasible).
3845function isDisconnected( node ) {
3846 return !node || !node.parentNode || node.parentNode.nodeType === 11;
3847}
3848
3849jQuery.each({
3850 parent: function( elem ) {
3851 var parent = elem.parentNode;
3852 return parent && parent.nodeType !== 11 ? parent : null;
3853 },
3854 parents: function( elem ) {
3855 return jQuery.dir( elem, "parentNode" );
3856 },
3857 parentsUntil: function( elem, i, until ) {
3858 return jQuery.dir( elem, "parentNode", until );
3859 },
3860 next: function( elem ) {
3861 return jQuery.nth( elem, 2, "nextSibling" );
3862 },
3863 prev: function( elem ) {
3864 return jQuery.nth( elem, 2, "previousSibling" );
3865 },
3866 nextAll: function( elem ) {
3867 return jQuery.dir( elem, "nextSibling" );
3868 },
3869 prevAll: function( elem ) {
3870 return jQuery.dir( elem, "previousSibling" );
3871 },
3872 nextUntil: function( elem, i, until ) {
3873 return jQuery.dir( elem, "nextSibling", until );
3874 },
3875 prevUntil: function( elem, i, until ) {
3876 return jQuery.dir( elem, "previousSibling", until );
3877 },
3878 siblings: function( elem ) {
3879 return jQuery.sibling( elem.parentNode.firstChild, elem );
3880 },
3881 children: function( elem ) {
3882 return jQuery.sibling( elem.firstChild );
3883 },
3884 contents: function( elem ) {
3885 return jQuery.nodeName( elem, "iframe" ) ?
3886 elem.contentDocument || elem.contentWindow.document :
3887 jQuery.makeArray( elem.childNodes );
3888 }
3889}, function( name, fn ) {
3890 jQuery.fn[ name ] = function( until, selector ) {
3891 var ret = jQuery.map( this, fn, until );
3892
3893 if ( !runtil.test( name ) ) {
3894 selector = until;
3895 }
3896
3897 if ( selector && typeof selector === "string" ) {
3898 ret = jQuery.filter( selector, ret );
3899 }
3900
3901 ret = this.length > 1 ? jQuery.unique( ret ) : ret;
3902
3903 if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
3904 ret = ret.reverse();
3905 }
3906
3907 return this.pushStack( ret, name, slice.call(arguments).join(",") );
3908 };
3909});
3910
3911jQuery.extend({
3912 filter: function( expr, elems, not ) {
3913 if ( not ) {
3914 expr = ":not(" + expr + ")";
3915 }
3916
3917 return jQuery.find.matches(expr, elems);
3918 },
3919
3920 dir: function( elem, dir, until ) {
3921 var matched = [], cur = elem[dir];
3922 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
3923 if ( cur.nodeType === 1 ) {
3924 matched.push( cur );
3925 }
3926 cur = cur[dir];
3927 }
3928 return matched;
3929 },
3930
3931 nth: function( cur, result, dir, elem ) {
3932 result = result || 1;
3933 var num = 0;
3934
3935 for ( ; cur; cur = cur[dir] ) {
3936 if ( cur.nodeType === 1 && ++num === result ) {
3937 break;
3938 }
3939 }
3940
3941 return cur;
3942 },
3943
3944 sibling: function( n, elem ) {
3945 var r = [];
3946
3947 for ( ; n; n = n.nextSibling ) {
3948 if ( n.nodeType === 1 && n !== elem ) {
3949 r.push( n );
3950 }
3951 }
3952
3953 return r;
3954 }
3955});
3956var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
3957 rleadingWhitespace = /^\s+/,
3958 rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g,
3959 rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,
3960 rtagName = /<([\w:]+)/,
3961 rtbody = /<tbody/i,
3962 rhtml = /<|&#?\w+;/,
3963 rnocache = /<script|<object|<embed|<option|<style/i,
3964 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, // checked="checked" or checked (html5)
3965 fcloseTag = function( all, front, tag ) {
3966 return rselfClosing.test( tag ) ?
3967 all :
3968 front + "></" + tag + ">";
3969 },
3970 wrapMap = {
3971 option: [ 1, "<select multiple='multiple'>", "</select>" ],
3972 legend: [ 1, "<fieldset>", "</fieldset>" ],
3973 thead: [ 1, "<table>", "</table>" ],
3974 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
3975 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
3976 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
3977 area: [ 1, "<map>", "</map>" ],
3978 _default: [ 0, "", "" ]
3979 };
3980
3981wrapMap.optgroup = wrapMap.option;
3982wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
3983wrapMap.th = wrapMap.td;
3984
3985// IE can't serialize <link> and <script> tags normally
3986if ( !jQuery.support.htmlSerialize ) {
3987 wrapMap._default = [ 1, "div<div>", "</div>" ];
3988}
3989
3990jQuery.fn.extend({
3991 text: function( text ) {
3992 if ( jQuery.isFunction(text) ) {
3993 return this.each(function(i) {
3994 var self = jQuery(this);
3995 self.text( text.call(this, i, self.text()) );
3996 });
3997 }
3998
3999 if ( typeof text !== "object" && text !== undefined ) {
4000 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
4001 }
4002
4003 return jQuery.text( this );
4004 },
4005
4006 wrapAll: function( html ) {
4007 if ( jQuery.isFunction( html ) ) {
4008 return this.each(function(i) {
4009 jQuery(this).wrapAll( html.call(this, i) );
4010 });
4011 }
4012
4013 if ( this[0] ) {
4014 // The elements to wrap the target around
4015 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
4016
4017 if ( this[0].parentNode ) {
4018 wrap.insertBefore( this[0] );
4019 }
4020
4021 wrap.map(function() {
4022 var elem = this;
4023
4024 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
4025 elem = elem.firstChild;
4026 }
4027
4028 return elem;
4029 }).append(this);
4030 }
4031
4032 return this;
4033 },
4034
4035 wrapInner: function( html ) {
4036 if ( jQuery.isFunction( html ) ) {
4037 return this.each(function(i) {
4038 jQuery(this).wrapInner( html.call(this, i) );
4039 });
4040 }
4041
4042 return this.each(function() {
4043 var self = jQuery( this ), contents = self.contents();
4044
4045 if ( contents.length ) {
4046 contents.wrapAll( html );
4047
4048 } else {
4049 self.append( html );
4050 }
4051 });
4052 },
4053
4054 wrap: function( html ) {
4055 return this.each(function() {
4056 jQuery( this ).wrapAll( html );
4057 });
4058 },
4059
4060 unwrap: function() {
4061 return this.parent().each(function() {
4062 if ( !jQuery.nodeName( this, "body" ) ) {
4063 jQuery( this ).replaceWith( this.childNodes );
4064 }
4065 }).end();
4066 },
4067
4068 append: function() {
4069 return this.domManip(arguments, true, function( elem ) {
4070 if ( this.nodeType === 1 ) {
4071 this.appendChild( elem );
4072 }
4073 });
4074 },
4075
4076 prepend: function() {
4077 return this.domManip(arguments, true, function( elem ) {
4078 if ( this.nodeType === 1 ) {
4079 this.insertBefore( elem, this.firstChild );
4080 }
4081 });
4082 },
4083
4084 before: function() {
4085 if ( this[0] && this[0].parentNode ) {
4086 return this.domManip(arguments, false, function( elem ) {
4087 this.parentNode.insertBefore( elem, this );
4088 });
4089 } else if ( arguments.length ) {
4090 var set = jQuery(arguments[0]);
4091 set.push.apply( set, this.toArray() );
4092 return this.pushStack( set, "before", arguments );
4093 }
4094 },
4095
4096 after: function() {
4097 if ( this[0] && this[0].parentNode ) {
4098 return this.domManip(arguments, false, function( elem ) {
4099 this.parentNode.insertBefore( elem, this.nextSibling );
4100 });
4101 } else if ( arguments.length ) {
4102 var set = this.pushStack( this, "after", arguments );
4103 set.push.apply( set, jQuery(arguments[0]).toArray() );
4104 return set;
4105 }
4106 },
4107
4108 // keepData is for internal use only--do not document
4109 remove: function( selector, keepData ) {
4110 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
4111 if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
4112 if ( !keepData && elem.nodeType === 1 ) {
4113 jQuery.cleanData( elem.getElementsByTagName("*") );
4114 jQuery.cleanData( [ elem ] );
4115 }
4116
4117 if ( elem.parentNode ) {
4118 elem.parentNode.removeChild( elem );
4119 }
4120 }
4121 }
4122
4123 return this;
4124 },
4125
4126 empty: function() {
4127 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
4128 // Remove element nodes and prevent memory leaks
4129 if ( elem.nodeType === 1 ) {
4130 jQuery.cleanData( elem.getElementsByTagName("*") );
4131 }
4132
4133 // Remove any remaining nodes
4134 while ( elem.firstChild ) {
4135 elem.removeChild( elem.firstChild );
4136 }
4137 }
4138
4139 return this;
4140 },
4141
4142 clone: function( events ) {
4143 // Do the clone
4144 var ret = this.map(function() {
4145 if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
4146 // IE copies events bound via attachEvent when
4147 // using cloneNode. Calling detachEvent on the
4148 // clone will also remove the events from the orignal
4149 // In order to get around this, we use innerHTML.
4150 // Unfortunately, this means some modifications to
4151 // attributes in IE that are actually only stored
4152 // as properties will not be copied (such as the
4153 // the name attribute on an input).
4154 var html = this.outerHTML, ownerDocument = this.ownerDocument;
4155 if ( !html ) {
4156 var div = ownerDocument.createElement("div");
4157 div.appendChild( this.cloneNode(true) );
4158 html = div.innerHTML;
4159 }
4160
4161 return jQuery.clean([html.replace(rinlinejQuery, "")
4162 // Handle the case in IE 8 where action=/test/> self-closes a tag
4163 .replace(/=([^="'>\s]+\/)>/g, '="$1">')
4164 .replace(rleadingWhitespace, "")], ownerDocument)[0];
4165 } else {
4166 return this.cloneNode(true);
4167 }
4168 });
4169
4170 // Copy the events from the original to the clone
4171 if ( events === true ) {
4172 cloneCopyEvent( this, ret );
4173 cloneCopyEvent( this.find("*"), ret.find("*") );
4174 }
4175
4176 // Return the cloned set
4177 return ret;
4178 },
4179
4180 html: function( value ) {
4181 if ( value === undefined ) {
4182 return this[0] && this[0].nodeType === 1 ?
4183 this[0].innerHTML.replace(rinlinejQuery, "") :
4184 null;
4185
4186 // See if we can take a shortcut and just use innerHTML
4187 } else if ( typeof value === "string" && !rnocache.test( value ) &&
4188 (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
4189 !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
4190
4191 value = value.replace(rxhtmlTag, fcloseTag);
4192
4193 try {
4194 for ( var i = 0, l = this.length; i < l; i++ ) {
4195 // Remove element nodes and prevent memory leaks
4196 if ( this[i].nodeType === 1 ) {
4197 jQuery.cleanData( this[i].getElementsByTagName("*") );
4198 this[i].innerHTML = value;
4199 }
4200 }
4201
4202 // If using innerHTML throws an exception, use the fallback method
4203 } catch(e) {
4204 this.empty().append( value );
4205 }
4206
4207 } else if ( jQuery.isFunction( value ) ) {
4208 this.each(function(i){
4209 var self = jQuery(this), old = self.html();
4210 self.empty().append(function(){
4211 return value.call( this, i, old );
4212 });
4213 });
4214
4215 } else {
4216 this.empty().append( value );
4217 }
4218
4219 return this;
4220 },
4221
4222 replaceWith: function( value ) {
4223 if ( this[0] && this[0].parentNode ) {
4224 // Make sure that the elements are removed from the DOM before they are inserted
4225 // this can help fix replacing a parent with child elements
4226 if ( jQuery.isFunction( value ) ) {
4227 return this.each(function(i) {
4228 var self = jQuery(this), old = self.html();
4229 self.replaceWith( value.call( this, i, old ) );
4230 });
4231 }
4232
4233 if ( typeof value !== "string" ) {
4234 value = jQuery(value).detach();
4235 }
4236
4237 return this.each(function() {
4238 var next = this.nextSibling, parent = this.parentNode;
4239
4240 jQuery(this).remove();
4241
4242 if ( next ) {
4243 jQuery(next).before( value );
4244 } else {
4245 jQuery(parent).append( value );
4246 }
4247 });
4248 } else {
4249 return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
4250 }
4251 },
4252
4253 detach: function( selector ) {
4254 return this.remove( selector, true );
4255 },
4256
4257 domManip: function( args, table, callback ) {
4258 var results, first, value = args[0], scripts = [], fragment, parent;
4259
4260 // We can't cloneNode fragments that contain checked, in WebKit
4261 if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
4262 return this.each(function() {
4263 jQuery(this).domManip( args, table, callback, true );
4264 });
4265 }
4266
4267 if ( jQuery.isFunction(value) ) {
4268 return this.each(function(i) {
4269 var self = jQuery(this);
4270 args[0] = value.call(this, i, table ? self.html() : undefined);
4271 self.domManip( args, table, callback );
4272 });
4273 }
4274
4275 if ( this[0] ) {
4276 parent = value && value.parentNode;
4277
4278 // If we're in a fragment, just use that instead of building a new one
4279 if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
4280 results = { fragment: parent };
4281
4282 } else {
4283 results = buildFragment( args, this, scripts );
4284 }
4285
4286 fragment = results.fragment;
4287
4288 if ( fragment.childNodes.length === 1 ) {
4289 first = fragment = fragment.firstChild;
4290 } else {
4291 first = fragment.firstChild;
4292 }
4293
4294 if ( first ) {
4295 table = table && jQuery.nodeName( first, "tr" );
4296
4297 for ( var i = 0, l = this.length; i < l; i++ ) {
4298 callback.call(
4299 table ?
4300 root(this[i], first) :
4301 this[i],
4302 i > 0 || results.cacheable || this.length > 1 ?
4303 fragment.cloneNode(true) :
4304 fragment
4305 );
4306 }
4307 }
4308
4309 if ( scripts.length ) {
4310 jQuery.each( scripts, evalScript );
4311 }
4312 }
4313
4314 return this;
4315
4316 function root( elem, cur ) {
4317 return jQuery.nodeName(elem, "table") ?
4318 (elem.getElementsByTagName("tbody")[0] ||
4319 elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
4320 elem;
4321 }
4322 }
4323});
4324
4325function cloneCopyEvent(orig, ret) {
4326 var i = 0;
4327
4328 ret.each(function() {
4329 if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
4330 return;
4331 }
4332
4333 var oldData = jQuery.data( orig[i++] ), curData = jQuery.data( this, oldData ), events = oldData && oldData.events;
4334
4335 if ( events ) {
4336 delete curData.handle;
4337 curData.events = {};
4338
4339 for ( var type in events ) {
4340 for ( var handler in events[ type ] ) {
4341 jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
4342 }
4343 }
4344 }
4345 });
4346}
4347
4348function buildFragment( args, nodes, scripts ) {
4349 var fragment, cacheable, cacheresults,
4350 doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
4351
4352 // Only cache "small" (1/2 KB) strings that are associated with the main document
4353 // Cloning options loses the selected state, so don't cache them
4354 // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
4355 // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
4356 if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
4357 !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
4358
4359 cacheable = true;
4360 cacheresults = jQuery.fragments[ args[0] ];
4361 if ( cacheresults ) {
4362 if ( cacheresults !== 1 ) {
4363 fragment = cacheresults;
4364 }
4365 }
4366 }
4367
4368 if ( !fragment ) {
4369 fragment = doc.createDocumentFragment();
4370 jQuery.clean( args, doc, fragment, scripts );
4371 }
4372
4373 if ( cacheable ) {
4374 jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
4375 }
4376
4377 return { fragment: fragment, cacheable: cacheable };
4378}
4379
4380jQuery.fragments = {};
4381
4382jQuery.each({
4383 appendTo: "append",
4384 prependTo: "prepend",
4385 insertBefore: "before",
4386 insertAfter: "after",
4387 replaceAll: "replaceWith"
4388}, function( name, original ) {
4389 jQuery.fn[ name ] = function( selector ) {
4390 var ret = [], insert = jQuery( selector ),
4391 parent = this.length === 1 && this[0].parentNode;
4392
4393 if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
4394 insert[ original ]( this[0] );
4395 return this;
4396
4397 } else {
4398 for ( var i = 0, l = insert.length; i < l; i++ ) {
4399 var elems = (i > 0 ? this.clone(true) : this).get();
4400 jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
4401 ret = ret.concat( elems );
4402 }
4403
4404 return this.pushStack( ret, name, insert.selector );
4405 }
4406 };
4407});
4408
4409jQuery.extend({
4410 clean: function( elems, context, fragment, scripts ) {
4411 context = context || document;
4412
4413 // !context.createElement fails in IE with an error but returns typeof 'object'
4414 if ( typeof context.createElement === "undefined" ) {
4415 context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
4416 }
4417
4418 var ret = [];
4419
4420 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
4421 if ( typeof elem === "number" ) {
4422 elem += "";
4423 }
4424
4425 if ( !elem ) {
4426 continue;
4427 }
4428
4429 // Convert html string into DOM nodes
4430 if ( typeof elem === "string" && !rhtml.test( elem ) ) {
4431 elem = context.createTextNode( elem );
4432
4433 } else if ( typeof elem === "string" ) {
4434 // Fix "XHTML"-style tags in all browsers
4435 elem = elem.replace(rxhtmlTag, fcloseTag);
4436
4437 // Trim whitespace, otherwise indexOf won't work as expected
4438 var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
4439 wrap = wrapMap[ tag ] || wrapMap._default,
4440 depth = wrap[0],
4441 div = context.createElement("div");
4442
4443 // Go to html and back, then peel off extra wrappers
4444 div.innerHTML = wrap[1] + elem + wrap[2];
4445
4446 // Move to the right depth
4447 while ( depth-- ) {
4448 div = div.lastChild;
4449 }
4450
4451 // Remove IE's autoinserted <tbody> from table fragments
4452 if ( !jQuery.support.tbody ) {
4453
4454 // String was a <table>, *may* have spurious <tbody>
4455 var hasBody = rtbody.test(elem),
4456 tbody = tag === "table" && !hasBody ?
4457 div.firstChild && div.firstChild.childNodes :
4458
4459 // String was a bare <thead> or <tfoot>
4460 wrap[1] === "<table>" && !hasBody ?
4461 div.childNodes :
4462 [];
4463
4464 for ( var j = tbody.length - 1; j >= 0 ; --j ) {
4465 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
4466 tbody[ j ].parentNode.removeChild( tbody[ j ] );
4467 }
4468 }
4469
4470 }
4471
4472 // IE completely kills leading whitespace when innerHTML is used
4473 if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
4474 div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
4475 }
4476
4477 elem = div.childNodes;
4478 }
4479
4480 if ( elem.nodeType ) {
4481 ret.push( elem );
4482 } else {
4483 ret = jQuery.merge( ret, elem );
4484 }
4485 }
4486
4487 if ( fragment ) {
4488 for ( var i = 0; ret[i]; i++ ) {
4489 if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
4490 scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
4491
4492 } else {
4493 if ( ret[i].nodeType === 1 ) {
4494 ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
4495 }
4496 fragment.appendChild( ret[i] );
4497 }
4498 }
4499 }
4500
4501 return ret;
4502 },
4503
4504 cleanData: function( elems ) {
4505 var data, id, cache = jQuery.cache,
4506 special = jQuery.event.special,
4507 deleteExpando = jQuery.support.deleteExpando;
4508
4509 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
4510 id = elem[ jQuery.expando ];
4511
4512 if ( id ) {
4513 data = cache[ id ];
4514
4515 if ( data.events ) {
4516 for ( var type in data.events ) {
4517 if ( special[ type ] ) {
4518 jQuery.event.remove( elem, type );
4519
4520 } else {
4521 removeEvent( elem, type, data.handle );
4522 }
4523 }
4524 }
4525
4526 if ( deleteExpando ) {
4527 delete elem[ jQuery.expando ];
4528
4529 } else if ( elem.removeAttribute ) {
4530 elem.removeAttribute( jQuery.expando );
4531 }
4532
4533 delete cache[ id ];
4534 }
4535 }
4536 }
4537});
4538// exclude the following css properties to add px
4539var rexclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
4540 ralpha = /alpha\([^)]*\)/,
4541 ropacity = /opacity=([^)]*)/,
4542 rfloat = /float/i,
4543 rdashAlpha = /-([a-z])/ig,
4544 rupper = /([A-Z])/g,
4545 rnumpx = /^-?\d+(?:px)?$/i,
4546 rnum = /^-?\d/,
4547
4548 cssShow = { position: "absolute", visibility: "hidden", display:"block" },
4549 cssWidth = [ "Left", "Right" ],
4550 cssHeight = [ "Top", "Bottom" ],
4551
4552 // cache check for defaultView.getComputedStyle
4553 getComputedStyle = document.defaultView && document.defaultView.getComputedStyle,
4554 // normalize float css property
4555 styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat",
4556 fcamelCase = function( all, letter ) {
4557 return letter.toUpperCase();
4558 };
4559
4560jQuery.fn.css = function( name, value ) {
4561 return access( this, name, value, true, function( elem, name, value ) {
4562 if ( value === undefined ) {
4563 return jQuery.curCSS( elem, name );
4564 }
4565
4566 if ( typeof value === "number" && !rexclude.test(name) ) {
4567 value += "px";
4568 }
4569
4570 jQuery.style( elem, name, value );
4571 });
4572};
4573
4574jQuery.extend({
4575 style: function( elem, name, value ) {
4576 // don't set styles on text and comment nodes
4577 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
4578 return undefined;
4579 }
4580
4581 // ignore negative width and height values #1599
4582 if ( (name === "width" || name === "height") && parseFloat(value) < 0 ) {
4583 value = undefined;
4584 }
4585
4586 var style = elem.style || elem, set = value !== undefined;
4587
4588 // IE uses filters for opacity
4589 if ( !jQuery.support.opacity && name === "opacity" ) {
4590 if ( set ) {
4591 // IE has trouble with opacity if it does not have layout
4592 // Force it by setting the zoom level
4593 style.zoom = 1;
4594
4595 // Set the alpha filter to set the opacity
4596 var opacity = parseInt( value, 10 ) + "" === "NaN" ? "" : "alpha(opacity=" + value * 100 + ")";
4597 var filter = style.filter || jQuery.curCSS( elem, "filter" ) || "";
4598 style.filter = ralpha.test(filter) ? filter.replace(ralpha, opacity) : opacity;
4599 }
4600
4601 return style.filter && style.filter.indexOf("opacity=") >= 0 ?
4602 (parseFloat( ropacity.exec(style.filter)[1] ) / 100) + "":
4603 "";
4604 }
4605
4606 // Make sure we're using the right name for getting the float value
4607 if ( rfloat.test( name ) ) {
4608 name = styleFloat;
4609 }
4610
4611 name = name.replace(rdashAlpha, fcamelCase);
4612
4613 if ( set ) {
4614 style[ name ] = value;
4615 }
4616
4617 return style[ name ];
4618 },
4619
4620 css: function( elem, name, force, extra ) {
4621 if ( name === "width" || name === "height" ) {
4622 var val, props = cssShow, which = name === "width" ? cssWidth : cssHeight;
4623
4624 function getWH() {
4625 val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
4626
4627 if ( extra === "border" ) {
4628 return;
4629 }
4630
4631 jQuery.each( which, function() {
4632 if ( !extra ) {
4633 val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
4634 }
4635
4636 if ( extra === "margin" ) {
4637 val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
4638 } else {
4639 val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
4640 }
4641 });
4642 }
4643
4644 if ( elem.offsetWidth !== 0 ) {
4645 getWH();
4646 } else {
4647 jQuery.swap( elem, props, getWH );
4648 }
4649
4650 return Math.max(0, Math.round(val));
4651 }
4652
4653 return jQuery.curCSS( elem, name, force );
4654 },
4655
4656 curCSS: function( elem, name, force ) {
4657 var ret, style = elem.style, filter;
4658
4659 // IE uses filters for opacity
4660 if ( !jQuery.support.opacity && name === "opacity" && elem.currentStyle ) {
4661 ret = ropacity.test(elem.currentStyle.filter || "") ?
4662 (parseFloat(RegExp.$1) / 100) + "" :
4663 "";
4664
4665 return ret === "" ?
4666 "1" :
4667 ret;
4668 }
4669
4670 // Make sure we're using the right name for getting the float value
4671 if ( rfloat.test( name ) ) {
4672 name = styleFloat;
4673 }
4674
4675 if ( !force && style && style[ name ] ) {
4676 ret = style[ name ];
4677
4678 } else if ( getComputedStyle ) {
4679
4680 // Only "float" is needed here
4681 if ( rfloat.test( name ) ) {
4682 name = "float";
4683 }
4684
4685 name = name.replace( rupper, "-$1" ).toLowerCase();
4686
4687 var defaultView = elem.ownerDocument.defaultView;
4688
4689 if ( !defaultView ) {
4690 return null;
4691 }
4692
4693 var computedStyle = defaultView.getComputedStyle( elem, null );
4694
4695 if ( computedStyle ) {
4696 ret = computedStyle.getPropertyValue( name );
4697 }
4698
4699 // We should always get a number back from opacity
4700 if ( name === "opacity" && ret === "" ) {
4701 ret = "1";
4702 }
4703
4704 } else if ( elem.currentStyle ) {
4705 var camelCase = name.replace(rdashAlpha, fcamelCase);
4706
4707 ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
4708
4709 // From the awesome hack by Dean Edwards
4710 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
4711
4712 // If we're not dealing with a regular pixel number
4713 // but a number that has a weird ending, we need to convert it to pixels
4714 if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
4715 // Remember the original values
4716 var left = style.left, rsLeft = elem.runtimeStyle.left;
4717
4718 // Put in the new values to get a computed value out
4719 elem.runtimeStyle.left = elem.currentStyle.left;
4720 style.left = camelCase === "fontSize" ? "1em" : (ret || 0);
4721 ret = style.pixelLeft + "px";
4722
4723 // Revert the changed values
4724 style.left = left;
4725 elem.runtimeStyle.left = rsLeft;
4726 }
4727 }
4728
4729 return ret;
4730 },
4731
4732 // A method for quickly swapping in/out CSS properties to get correct calculations
4733 swap: function( elem, options, callback ) {
4734 var old = {};
4735
4736 // Remember the old values, and insert the new ones
4737 for ( var name in options ) {
4738 old[ name ] = elem.style[ name ];
4739 elem.style[ name ] = options[ name ];
4740 }
4741
4742 callback.call( elem );
4743
4744 // Revert the old values
4745 for ( var name in options ) {
4746 elem.style[ name ] = old[ name ];
4747 }
4748 }
4749});
4750
4751if ( jQuery.expr && jQuery.expr.filters ) {
4752 jQuery.expr.filters.hidden = function( elem ) {
4753 var width = elem.offsetWidth, height = elem.offsetHeight,
4754 skip = elem.nodeName.toLowerCase() === "tr";
4755
4756 return width === 0 && height === 0 && !skip ?
4757 true :
4758 width > 0 && height > 0 && !skip ?
4759 false :
4760 jQuery.curCSS(elem, "display") === "none";
4761 };
4762
4763 jQuery.expr.filters.visible = function( elem ) {
4764 return !jQuery.expr.filters.hidden( elem );
4765 };
4766}
4767var jsc = now(),
4768 rscript = /<script(.|\s)*?\/script>/gi,
4769 rselectTextarea = /select|textarea/i,
4770 rinput = /color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,
4771 jsre = /=\?(&|$)/,
4772 rquery = /\?/,
4773 rts = /(\?|&)_=.*?(&|$)/,
4774 rurl = /^(\w+:)?\/\/([^\/?#]+)/,
4775 r20 = /%20/g,
4776
4777 // Keep a copy of the old load method
4778 _load = jQuery.fn.load;
4779
4780jQuery.fn.extend({
4781 load: function( url, params, callback ) {
4782 if ( typeof url !== "string" ) {
4783 return _load.call( this, url );
4784
4785 // Don't do a request if no elements are being requested
4786 } else if ( !this.length ) {
4787 return this;
4788 }
4789
4790 var off = url.indexOf(" ");
4791 if ( off >= 0 ) {
4792 var selector = url.slice(off, url.length);
4793 url = url.slice(0, off);
4794 }
4795
4796 // Default to a GET request
4797 var type = "GET";
4798
4799 // If the second parameter was provided
4800 if ( params ) {
4801 // If it's a function
4802 if ( jQuery.isFunction( params ) ) {
4803 // We assume that it's the callback
4804 callback = params;
4805 params = null;
4806
4807 // Otherwise, build a param string
4808 } else if ( typeof params === "object" ) {
4809 params = jQuery.param( params, jQuery.ajaxSettings.traditional );
4810 type = "POST";
4811 }
4812 }
4813
4814 var self = this;
4815
4816 // Request the remote document
4817 jQuery.ajax({
4818 url: url,
4819 type: type,
4820 dataType: "html",
4821 data: params,
4822 complete: function( res, status ) {
4823 // If successful, inject the HTML into all the matched elements
4824 if ( status === "success" || status === "notmodified" ) {
4825 // See if a selector was specified
4826 self.html( selector ?
4827 // Create a dummy div to hold the results
4828 jQuery("<div />")
4829 // inject the contents of the document in, removing the scripts
4830 // to avoid any 'Permission Denied' errors in IE
4831 .append(res.responseText.replace(rscript, ""))
4832
4833 // Locate the specified elements
4834 .find(selector) :
4835
4836 // If not, just inject the full result
4837 res.responseText );
4838 }
4839
4840 if ( callback ) {
4841 self.each( callback, [res.responseText, status, res] );
4842 }
4843 }
4844 });
4845
4846 return this;
4847 },
4848
4849 serialize: function() {
4850 return jQuery.param(this.serializeArray());
4851 },
4852 serializeArray: function() {
4853 return this.map(function() {
4854 return this.elements ? jQuery.makeArray(this.elements) : this;
4855 })
4856 .filter(function() {
4857 return this.name && !this.disabled &&
4858 (this.checked || rselectTextarea.test(this.nodeName) ||
4859 rinput.test(this.type));
4860 })
4861 .map(function( i, elem ) {
4862 var val = jQuery(this).val();
4863
4864 return val == null ?
4865 null :
4866 jQuery.isArray(val) ?
4867 jQuery.map( val, function( val, i ) {
4868 return { name: elem.name, value: val };
4869 }) :
4870 { name: elem.name, value: val };
4871 }).get();
4872 }
4873});
4874
4875// Attach a bunch of functions for handling common AJAX events
4876jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
4877 jQuery.fn[o] = function( f ) {
4878 return this.bind(o, f);
4879 };
4880});
4881
4882jQuery.extend({
4883
4884 get: function( url, data, callback, type ) {
4885 // shift arguments if data argument was omited
4886 if ( jQuery.isFunction( data ) ) {
4887 type = type || callback;
4888 callback = data;
4889 data = null;
4890 }
4891
4892 return jQuery.ajax({
4893 type: "GET",
4894 url: url,
4895 data: data,
4896 success: callback,
4897 dataType: type
4898 });
4899 },
4900
4901 getScript: function( url, callback ) {
4902 return jQuery.get(url, null, callback, "script");
4903 },
4904
4905 getJSON: function( url, data, callback ) {
4906 return jQuery.get(url, data, callback, "json");
4907 },
4908
4909 post: function( url, data, callback, type ) {
4910 // shift arguments if data argument was omited
4911 if ( jQuery.isFunction( data ) ) {
4912 type = type || callback;
4913 callback = data;
4914 data = {};
4915 }
4916
4917 return jQuery.ajax({
4918 type: "POST",
4919 url: url,
4920 data: data,
4921 success: callback,
4922 dataType: type
4923 });
4924 },
4925
4926 ajaxSetup: function( settings ) {
4927 jQuery.extend( jQuery.ajaxSettings, settings );
4928 },
4929
4930 ajaxSettings: {
4931 url: location.href,
4932 global: true,
4933 type: "GET",
4934 contentType: "application/x-www-form-urlencoded",
4935 processData: true,
4936 async: true,
4937 /*
4938 timeout: 0,
4939 data: null,
4940 username: null,
4941 password: null,
4942 traditional: false,
4943 */
4944 // Create the request object; Microsoft failed to properly
4945 // implement the XMLHttpRequest in IE7 (can't request local files),
4946 // so we use the ActiveXObject when it is available
4947 // This function can be overriden by calling jQuery.ajaxSetup
4948 xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?
4949 function() {
4950 return new window.XMLHttpRequest();
4951 } :
4952 function() {
4953 try {
4954 return new window.ActiveXObject("Microsoft.XMLHTTP");
4955 } catch(e) {}
4956 },
4957 accepts: {
4958 xml: "application/xml, text/xml",
4959 html: "text/html",
4960 script: "text/javascript, application/javascript",
4961 json: "application/json, text/javascript",
4962 text: "text/plain",
4963 _default: "*/*"
4964 }
4965 },
4966
4967 // Last-Modified header cache for next request
4968 lastModified: {},
4969 etag: {},
4970
4971 ajax: function( origSettings ) {
4972 var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
4973
4974 var jsonp, status, data,
4975 callbackContext = origSettings && origSettings.context || s,
4976 type = s.type.toUpperCase();
4977
4978 // convert data if not already a string
4979 if ( s.data && s.processData && typeof s.data !== "string" ) {
4980 s.data = jQuery.param( s.data, s.traditional );
4981 }
4982
4983 // Handle JSONP Parameter Callbacks
4984 if ( s.dataType === "jsonp" ) {
4985 if ( type === "GET" ) {
4986 if ( !jsre.test( s.url ) ) {
4987 s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
4988 }
4989 } else if ( !s.data || !jsre.test(s.data) ) {
4990 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
4991 }
4992 s.dataType = "json";
4993 }
4994
4995 // Build temporary JSONP function
4996 if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
4997 jsonp = s.jsonpCallback || ("jsonp" + jsc++);
4998
4999 // Replace the =? sequence both in the query string and the data
5000 if ( s.data ) {
5001 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
5002 }
5003
5004 s.url = s.url.replace(jsre, "=" + jsonp + "$1");
5005
5006 // We need to make sure
5007 // that a JSONP style response is executed properly
5008 s.dataType = "script";
5009
5010 // Handle JSONP-style loading
5011 window[ jsonp ] = window[ jsonp ] || function( tmp ) {
5012 data = tmp;
5013 success();
5014 complete();
5015 // Garbage collect
5016 window[ jsonp ] = undefined;
5017
5018 try {
5019 delete window[ jsonp ];
5020 } catch(e) {}
5021
5022 if ( head ) {
5023 head.removeChild( script );
5024 }
5025 };
5026 }
5027
5028 if ( s.dataType === "script" && s.cache === null ) {
5029 s.cache = false;
5030 }
5031
5032 if ( s.cache === false && type === "GET" ) {
5033 var ts = now();
5034
5035 // try replacing _= if it is there
5036 var ret = s.url.replace(rts, "$1_=" + ts + "$2");
5037
5038 // if nothing was replaced, add timestamp to the end
5039 s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
5040 }
5041
5042 // If data is available, append data to url for get requests
5043 if ( s.data && type === "GET" ) {
5044 s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
5045 }
5046
5047 // Watch for a new set of requests
5048 if ( s.global && ! jQuery.active++ ) {
5049 jQuery.event.trigger( "ajaxStart" );
5050 }
5051
5052 // Matches an absolute URL, and saves the domain
5053 var parts = rurl.exec( s.url ),
5054 remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
5055
5056 // If we're requesting a remote document
5057 // and trying to load JSON or Script with a GET
5058 if ( s.dataType === "script" && type === "GET" && remote ) {
5059 var head = document.getElementsByTagName("head")[0] || document.documentElement;
5060 var script = document.createElement("script");
5061 script.src = s.url;
5062 if ( s.scriptCharset ) {
5063 script.charset = s.scriptCharset;
5064 }
5065
5066 // Handle Script loading
5067 if ( !jsonp ) {
5068 var done = false;
5069
5070 // Attach handlers for all browsers
5071 script.onload = script.onreadystatechange = function() {
5072 if ( !done && (!this.readyState ||
5073 this.readyState === "loaded" || this.readyState === "complete") ) {
5074 done = true;
5075 success();
5076 complete();
5077
5078 // Handle memory leak in IE
5079 script.onload = script.onreadystatechange = null;
5080 if ( head && script.parentNode ) {
5081 head.removeChild( script );
5082 }
5083 }
5084 };
5085 }
5086
5087 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
5088 // This arises when a base node is used (#2709 and #4378).
5089 head.insertBefore( script, head.firstChild );
5090
5091 // We handle everything using the script element injection
5092 return undefined;
5093 }
5094
5095 var requestDone = false;
5096
5097 // Create the request object
5098 var xhr = s.xhr();
5099
5100 if ( !xhr ) {
5101 return;
5102 }
5103
5104 // Open the socket
5105 // Passing null username, generates a login popup on Opera (#2865)
5106 if ( s.username ) {
5107 xhr.open(type, s.url, s.async, s.username, s.password);
5108 } else {
5109 xhr.open(type, s.url, s.async);
5110 }
5111
5112 // Need an extra try/catch for cross domain requests in Firefox 3
5113 try {
5114 // Set the correct header, if data is being sent
5115 if ( s.data || origSettings && origSettings.contentType ) {
5116 xhr.setRequestHeader("Content-Type", s.contentType);
5117 }
5118
5119 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
5120 if ( s.ifModified ) {
5121 if ( jQuery.lastModified[s.url] ) {
5122 xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
5123 }
5124
5125 if ( jQuery.etag[s.url] ) {
5126 xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
5127 }
5128 }
5129
5130 // Set header so the called script knows that it's an XMLHttpRequest
5131 // Only send the header if it's not a remote XHR
5132 if ( !remote ) {
5133 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
5134 }
5135
5136 // Set the Accepts header for the server, depending on the dataType
5137 xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
5138 s.accepts[ s.dataType ] + ", */*" :
5139 s.accepts._default );
5140 } catch(e) {}
5141
5142 // Allow custom headers/mimetypes and early abort
5143 if ( s.beforeSend && s.beforeSend.call(callbackContext, xhr, s) === false ) {
5144 // Handle the global AJAX counter
5145 if ( s.global && ! --jQuery.active ) {
5146 jQuery.event.trigger( "ajaxStop" );
5147 }
5148
5149 // close opended socket
5150 xhr.abort();
5151 return false;
5152 }
5153
5154 if ( s.global ) {
5155 trigger("ajaxSend", [xhr, s]);
5156 }
5157
5158 // Wait for a response to come back
5159 var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
5160 // The request was aborted
5161 if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
5162 // Opera doesn't call onreadystatechange before this point
5163 // so we simulate the call
5164 if ( !requestDone ) {
5165 complete();
5166 }
5167
5168 requestDone = true;
5169 if ( xhr ) {
5170 xhr.onreadystatechange = jQuery.noop;
5171 }
5172
5173 // The transfer is complete and the data is available, or the request timed out
5174 } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
5175 requestDone = true;
5176 xhr.onreadystatechange = jQuery.noop;
5177
5178 status = isTimeout === "timeout" ?
5179 "timeout" :
5180 !jQuery.httpSuccess( xhr ) ?
5181 "error" :
5182 s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
5183 "notmodified" :
5184 "success";
5185
5186 var errMsg;
5187
5188 if ( status === "success" ) {
5189 // Watch for, and catch, XML document parse errors
5190 try {
5191 // process the data (runs the xml through httpData regardless of callback)
5192 data = jQuery.httpData( xhr, s.dataType, s );
5193 } catch(err) {
5194 status = "parsererror";
5195 errMsg = err;
5196 }
5197 }
5198
5199 // Make sure that the request was successful or notmodified
5200 if ( status === "success" || status === "notmodified" ) {
5201 // JSONP handles its own success callback
5202 if ( !jsonp ) {
5203 success();
5204 }
5205 } else {
5206 jQuery.handleError(s, xhr, status, errMsg);
5207 }
5208
5209 // Fire the complete handlers
5210 complete();
5211
5212 if ( isTimeout === "timeout" ) {
5213 xhr.abort();
5214 }
5215
5216 // Stop memory leaks
5217 if ( s.async ) {
5218 xhr = null;
5219 }
5220 }
5221 };
5222
5223 // Override the abort handler, if we can (IE doesn't allow it, but that's OK)
5224 // Opera doesn't fire onreadystatechange at all on abort
5225 try {
5226 var oldAbort = xhr.abort;
5227 xhr.abort = function() {
5228 if ( xhr ) {
5229 oldAbort.call( xhr );
5230 }
5231
5232 onreadystatechange( "abort" );
5233 };
5234 } catch(e) { }
5235
5236 // Timeout checker
5237 if ( s.async && s.timeout > 0 ) {
5238 setTimeout(function() {
5239 // Check to see if the request is still happening
5240 if ( xhr && !requestDone ) {
5241 onreadystatechange( "timeout" );
5242 }
5243 }, s.timeout);
5244 }
5245
5246 // Send the data
5247 try {
5248 xhr.send( type === "POST" || type === "PUT" || type === "DELETE" ? s.data : null );
5249 } catch(e) {
5250 jQuery.handleError(s, xhr, null, e);
5251 // Fire the complete handlers
5252 complete();
5253 }
5254
5255 // firefox 1.5 doesn't fire statechange for sync requests
5256 if ( !s.async ) {
5257 onreadystatechange();
5258 }
5259
5260 function success() {
5261 // If a local callback was specified, fire it and pass it the data
5262 if ( s.success ) {
5263 s.success.call( callbackContext, data, status, xhr );
5264 }
5265
5266 // Fire the global callback
5267 if ( s.global ) {
5268 trigger( "ajaxSuccess", [xhr, s] );
5269 }
5270 }
5271
5272 function complete() {
5273 // Process result
5274 if ( s.complete ) {
5275 s.complete.call( callbackContext, xhr, status);
5276 }
5277
5278 // The request was completed
5279 if ( s.global ) {
5280 trigger( "ajaxComplete", [xhr, s] );
5281 }
5282
5283 // Handle the global AJAX counter
5284 if ( s.global && ! --jQuery.active ) {
5285 jQuery.event.trigger( "ajaxStop" );
5286 }
5287 }
5288
5289 function trigger(type, args) {
5290 (s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
5291 }
5292
5293 // return XMLHttpRequest to allow aborting the request etc.
5294 return xhr;
5295 },
5296
5297 handleError: function( s, xhr, status, e ) {
5298 // If a local callback was specified, fire it
5299 if ( s.error ) {
5300 s.error.call( s.context || s, xhr, status, e );
5301 }
5302
5303 // Fire the global callback
5304 if ( s.global ) {
5305 (s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
5306 }
5307 },
5308
5309 // Counter for holding the number of active queries
5310 active: 0,
5311
5312 // Determines if an XMLHttpRequest was successful or not
5313 httpSuccess: function( xhr ) {
5314 try {
5315 // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
5316 return !xhr.status && location.protocol === "file:" ||
5317 // Opera returns 0 when status is 304
5318 ( xhr.status >= 200 && xhr.status < 300 ) ||
5319 xhr.status === 304 || xhr.status === 1223 || xhr.status === 0;
5320 } catch(e) {}
5321
5322 return false;
5323 },
5324
5325 // Determines if an XMLHttpRequest returns NotModified
5326 httpNotModified: function( xhr, url ) {
5327 var lastModified = xhr.getResponseHeader("Last-Modified"),
5328 etag = xhr.getResponseHeader("Etag");
5329
5330 if ( lastModified ) {
5331 jQuery.lastModified[url] = lastModified;
5332 }
5333
5334 if ( etag ) {
5335 jQuery.etag[url] = etag;
5336 }
5337
5338 // Opera returns 0 when status is 304
5339 return xhr.status === 304 || xhr.status === 0;
5340 },
5341
5342 httpData: function( xhr, type, s ) {
5343 var ct = xhr.getResponseHeader("content-type") || "",
5344 xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
5345 data = xml ? xhr.responseXML : xhr.responseText;
5346
5347 if ( xml && data.documentElement.nodeName === "parsererror" ) {
5348 jQuery.error( "parsererror" );
5349 }
5350
5351 // Allow a pre-filtering function to sanitize the response
5352 // s is checked to keep backwards compatibility
5353 if ( s && s.dataFilter ) {
5354 data = s.dataFilter( data, type );
5355 }
5356
5357 // The filter can actually parse the response
5358 if ( typeof data === "string" ) {
5359 // Get the JavaScript object, if JSON is used.
5360 if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
5361 data = jQuery.parseJSON( data );
5362
5363 // If the type is "script", eval it in global context
5364 } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
5365 jQuery.globalEval( data );
5366 }
5367 }
5368
5369 return data;
5370 },
5371
5372 // Serialize an array of form elements or a set of
5373 // key/values into a query string
5374 param: function( a, traditional ) {
5375 var s = [];
5376
5377 // Set traditional to true for jQuery <= 1.3.2 behavior.
5378 if ( traditional === undefined ) {
5379 traditional = jQuery.ajaxSettings.traditional;
5380 }
5381
5382 // If an array was passed in, assume that it is an array of form elements.
5383 if ( jQuery.isArray(a) || a.jquery ) {
5384 // Serialize the form elements
5385 jQuery.each( a, function() {
5386 add( this.name, this.value );
5387 });
5388
5389 } else {
5390 // If traditional, encode the "old" way (the way 1.3.2 or older
5391 // did it), otherwise encode params recursively.
5392 for ( var prefix in a ) {
5393 buildParams( prefix, a[prefix] );
5394 }
5395 }
5396
5397 // Return the resulting serialization
5398 return s.join("&").replace(r20, "+");
5399
5400 function buildParams( prefix, obj ) {
5401 if ( jQuery.isArray(obj) ) {
5402 // Serialize array item.
5403 jQuery.each( obj, function( i, v ) {
5404 if ( traditional || /\[\]$/.test( prefix ) ) {
5405 // Treat each array item as a scalar.
5406 add( prefix, v );
5407 } else {
5408 // If array item is non-scalar (array or object), encode its
5409 // numeric index to resolve deserialization ambiguity issues.
5410 // Note that rack (as of 1.0.0) can't currently deserialize
5411 // nested arrays properly, and attempting to do so may cause
5412 // a server error. Possible fixes are to modify rack's
5413 // deserialization algorithm or to provide an option or flag
5414 // to force array serialization to be shallow.
5415 buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v );
5416 }
5417 });
5418
5419 } else if ( !traditional && obj != null && typeof obj === "object" ) {
5420 // Serialize object item.
5421 jQuery.each( obj, function( k, v ) {
5422 buildParams( prefix + "[" + k + "]", v );
5423 });
5424
5425 } else {
5426 // Serialize scalar item.
5427 add( prefix, obj );
5428 }
5429 }
5430
5431 function add( key, value ) {
5432 // If value is a function, invoke it and return its value
5433 value = jQuery.isFunction(value) ? value() : value;
5434 s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
5435 }
5436 }
5437});
5438var elemdisplay = {},
5439 rfxtypes = /toggle|show|hide/,
5440 rfxnum = /^([+-]=)?([\d+-.]+)(.*)$/,
5441 timerId,
5442 fxAttrs = [
5443 // height animations
5444 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
5445 // width animations
5446 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
5447 // opacity animations
5448 [ "opacity" ]
5449 ];
5450
5451jQuery.fn.extend({
5452 show: function( speed, callback ) {
5453 if ( speed || speed === 0) {
5454 return this.animate( genFx("show", 3), speed, callback);
5455
5456 } else {
5457 for ( var i = 0, l = this.length; i < l; i++ ) {
5458 var old = jQuery.data(this[i], "olddisplay");
5459
5460 this[i].style.display = old || "";
5461
5462 if ( jQuery.css(this[i], "display") === "none" ) {
5463 var nodeName = this[i].nodeName, display;
5464
5465 if ( elemdisplay[ nodeName ] ) {
5466 display = elemdisplay[ nodeName ];
5467
5468 } else {
5469 var elem = jQuery("<" + nodeName + " />").appendTo("body");
5470
5471 display = elem.css("display");
5472
5473 if ( display === "none" ) {
5474 display = "block";
5475 }
5476
5477 elem.remove();
5478
5479 elemdisplay[ nodeName ] = display;
5480 }
5481
5482 jQuery.data(this[i], "olddisplay", display);
5483 }
5484 }
5485
5486 // Set the display of the elements in a second loop
5487 // to avoid the constant reflow
5488 for ( var j = 0, k = this.length; j < k; j++ ) {
5489 this[j].style.display = jQuery.data(this[j], "olddisplay") || "";
5490 }
5491
5492 return this;
5493 }
5494 },
5495
5496 hide: function( speed, callback ) {
5497 if ( speed || speed === 0 ) {
5498 return this.animate( genFx("hide", 3), speed, callback);
5499
5500 } else {
5501 for ( var i = 0, l = this.length; i < l; i++ ) {
5502 var old = jQuery.data(this[i], "olddisplay");
5503 if ( !old && old !== "none" ) {
5504 jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
5505 }
5506 }
5507
5508 // Set the display of the elements in a second loop
5509 // to avoid the constant reflow
5510 for ( var j = 0, k = this.length; j < k; j++ ) {
5511 this[j].style.display = "none";
5512 }
5513
5514 return this;
5515 }
5516 },
5517
5518 // Save the old toggle function
5519 _toggle: jQuery.fn.toggle,
5520
5521 toggle: function( fn, fn2 ) {
5522 var bool = typeof fn === "boolean";
5523
5524 if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
5525 this._toggle.apply( this, arguments );
5526
5527 } else if ( fn == null || bool ) {
5528 this.each(function() {
5529 var state = bool ? fn : jQuery(this).is(":hidden");
5530 jQuery(this)[ state ? "show" : "hide" ]();
5531 });
5532
5533 } else {
5534 this.animate(genFx("toggle", 3), fn, fn2);
5535 }
5536
5537 return this;
5538 },
5539
5540 fadeTo: function( speed, to, callback ) {
5541 return this.filter(":hidden").css("opacity", 0).show().end()
5542 .animate({opacity: to}, speed, callback);
5543 },
5544
5545 animate: function( prop, speed, easing, callback ) {
5546 var optall = jQuery.speed(speed, easing, callback);
5547
5548 if ( jQuery.isEmptyObject( prop ) ) {
5549 return this.each( optall.complete );
5550 }
5551
5552 return this[ optall.queue === false ? "each" : "queue" ](function() {
5553 var opt = jQuery.extend({}, optall), p,
5554 hidden = this.nodeType === 1 && jQuery(this).is(":hidden"),
5555 self = this;
5556
5557 for ( p in prop ) {
5558 var name = p.replace(rdashAlpha, fcamelCase);
5559
5560 if ( p !== name ) {
5561 prop[ name ] = prop[ p ];
5562 delete prop[ p ];
5563 p = name;
5564 }
5565
5566 if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
5567 return opt.complete.call(this);
5568 }
5569
5570 if ( ( p === "height" || p === "width" ) && this.style ) {
5571 // Store display property
5572 opt.display = jQuery.css(this, "display");
5573
5574 // Make sure that nothing sneaks out
5575 opt.overflow = this.style.overflow;
5576 }
5577
5578 if ( jQuery.isArray( prop[p] ) ) {
5579 // Create (if needed) and add to specialEasing
5580 (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
5581 prop[p] = prop[p][0];
5582 }
5583 }
5584
5585 if ( opt.overflow != null ) {
5586 this.style.overflow = "hidden";
5587 }
5588
5589 opt.curAnim = jQuery.extend({}, prop);
5590
5591 jQuery.each( prop, function( name, val ) {
5592 var e = new jQuery.fx( self, opt, name );
5593
5594 if ( rfxtypes.test(val) ) {
5595 e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
5596
5597 } else {
5598 var parts = rfxnum.exec(val),
5599 start = e.cur(true) || 0;
5600
5601 if ( parts ) {
5602 var end = parseFloat( parts[2] ),
5603 unit = parts[3] || "px";
5604
5605 // We need to compute starting value
5606 if ( unit !== "px" ) {
5607 self.style[ name ] = (end || 1) + unit;
5608 start = ((end || 1) / e.cur(true)) * start;
5609 self.style[ name ] = start + unit;
5610 }
5611
5612 // If a +=/-= token was provided, we're doing a relative animation
5613 if ( parts[1] ) {
5614 end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
5615 }
5616
5617 e.custom( start, end, unit );
5618
5619 } else {
5620 e.custom( start, val, "" );
5621 }
5622 }
5623 });
5624
5625 // For JS strict compliance
5626 return true;
5627 });
5628 },
5629
5630 stop: function( clearQueue, gotoEnd ) {
5631 var timers = jQuery.timers;
5632
5633 if ( clearQueue ) {
5634 this.queue([]);
5635 }
5636
5637 this.each(function() {
5638 // go in reverse order so anything added to the queue during the loop is ignored
5639 for ( var i = timers.length - 1; i >= 0; i-- ) {
5640 if ( timers[i].elem === this ) {
5641 if (gotoEnd) {
5642 // force the next step to be the last
5643 timers[i](true);
5644 }
5645
5646 timers.splice(i, 1);
5647 }
5648 }
5649 });
5650
5651 // start the next in the queue if the last step wasn't forced
5652 if ( !gotoEnd ) {
5653 this.dequeue();
5654 }
5655
5656 return this;
5657 }
5658
5659});
5660
5661// Generate shortcuts for custom animations
5662jQuery.each({
5663 slideDown: genFx("show", 1),
5664 slideUp: genFx("hide", 1),
5665 slideToggle: genFx("toggle", 1),
5666 fadeIn: { opacity: "show" },
5667 fadeOut: { opacity: "hide" }
5668}, function( name, props ) {
5669 jQuery.fn[ name ] = function( speed, callback ) {
5670 return this.animate( props, speed, callback );
5671 };
5672});
5673
5674jQuery.extend({
5675 speed: function( speed, easing, fn ) {
5676 var opt = speed && typeof speed === "object" ? speed : {
5677 complete: fn || !fn && easing ||
5678 jQuery.isFunction( speed ) && speed,
5679 duration: speed,
5680 easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
5681 };
5682
5683 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
5684 jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
5685
5686 // Queueing
5687 opt.old = opt.complete;
5688 opt.complete = function() {
5689 if ( opt.queue !== false ) {
5690 jQuery(this).dequeue();
5691 }
5692 if ( jQuery.isFunction( opt.old ) ) {
5693 opt.old.call( this );
5694 }
5695 };
5696
5697 return opt;
5698 },
5699
5700 easing: {
5701 linear: function( p, n, firstNum, diff ) {
5702 return firstNum + diff * p;
5703 },
5704 swing: function( p, n, firstNum, diff ) {
5705 return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
5706 }
5707 },
5708
5709 timers: [],
5710
5711 fx: function( elem, options, prop ) {
5712 this.options = options;
5713 this.elem = elem;
5714 this.prop = prop;
5715
5716 if ( !options.orig ) {
5717 options.orig = {};
5718 }
5719 }
5720
5721});
5722
5723jQuery.fx.prototype = {
5724 // Simple function for setting a style value
5725 update: function() {
5726 if ( this.options.step ) {
5727 this.options.step.call( this.elem, this.now, this );
5728 }
5729
5730 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
5731
5732 // Set display property to block for height/width animations
5733 if ( ( this.prop === "height" || this.prop === "width" ) && this.elem.style ) {
5734 this.elem.style.display = "block";
5735 }
5736 },
5737
5738 // Get the current size
5739 cur: function( force ) {
5740 if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
5741 return this.elem[ this.prop ];
5742 }
5743
5744 var r = parseFloat(jQuery.css(this.elem, this.prop, force));
5745 return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
5746 },
5747
5748 // Start an animation from one number to another
5749 custom: function( from, to, unit ) {
5750 this.startTime = now();
5751 this.start = from;
5752 this.end = to;
5753 this.unit = unit || this.unit || "px";
5754 this.now = this.start;
5755 this.pos = this.state = 0;
5756
5757 var self = this;
5758 function t( gotoEnd ) {
5759 return self.step(gotoEnd);
5760 }
5761
5762 t.elem = this.elem;
5763
5764 if ( t() && jQuery.timers.push(t) && !timerId ) {
5765 timerId = setInterval(jQuery.fx.tick, 13);
5766 }
5767 },
5768
5769 // Simple 'show' function
5770 show: function() {
5771 // Remember where we started, so that we can go back to it later
5772 this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
5773 this.options.show = true;
5774
5775 // Begin the animation
5776 // Make sure that we start at a small width/height to avoid any
5777 // flash of content
5778 this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
5779
5780 // Start by showing the element
5781 jQuery( this.elem ).show();
5782 },
5783
5784 // Simple 'hide' function
5785 hide: function() {
5786 // Remember where we started, so that we can go back to it later
5787 this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
5788 this.options.hide = true;
5789
5790 // Begin the animation
5791 this.custom(this.cur(), 0);
5792 },
5793
5794 // Each step of an animation
5795 step: function( gotoEnd ) {
5796 var t = now(), done = true;
5797
5798 if ( gotoEnd || t >= this.options.duration + this.startTime ) {
5799 this.now = this.end;
5800 this.pos = this.state = 1;
5801 this.update();
5802
5803 this.options.curAnim[ this.prop ] = true;
5804
5805 for ( var i in this.options.curAnim ) {
5806 if ( this.options.curAnim[i] !== true ) {
5807 done = false;
5808 }
5809 }
5810
5811 if ( done ) {
5812 if ( this.options.display != null ) {
5813 // Reset the overflow
5814 this.elem.style.overflow = this.options.overflow;
5815
5816 // Reset the display
5817 var old = jQuery.data(this.elem, "olddisplay");
5818 this.elem.style.display = old ? old : this.options.display;
5819
5820 if ( jQuery.css(this.elem, "display") === "none" ) {
5821 this.elem.style.display = "block";
5822 }
5823 }
5824
5825 // Hide the element if the "hide" operation was done
5826 if ( this.options.hide ) {
5827 jQuery(this.elem).hide();
5828 }
5829
5830 // Reset the properties, if the item has been hidden or shown
5831 if ( this.options.hide || this.options.show ) {
5832 for ( var p in this.options.curAnim ) {
5833 jQuery.style(this.elem, p, this.options.orig[p]);
5834 }
5835 }
5836
5837 // Execute the complete function
5838 this.options.complete.call( this.elem );
5839 }
5840
5841 return false;
5842
5843 } else {
5844 var n = t - this.startTime;
5845 this.state = n / this.options.duration;
5846
5847 // Perform the easing function, defaults to swing
5848 var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
5849 var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
5850 this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
5851 this.now = this.start + ((this.end - this.start) * this.pos);
5852
5853 // Perform the next step of the animation
5854 this.update();
5855 }
5856
5857 return true;
5858 }
5859};
5860
5861jQuery.extend( jQuery.fx, {
5862 tick: function() {
5863 var timers = jQuery.timers;
5864
5865 for ( var i = 0; i < timers.length; i++ ) {
5866 if ( !timers[i]() ) {
5867 timers.splice(i--, 1);
5868 }
5869 }
5870
5871 if ( !timers.length ) {
5872 jQuery.fx.stop();
5873 }
5874 },
5875
5876 stop: function() {
5877 clearInterval( timerId );
5878 timerId = null;
5879 },
5880
5881 speeds: {
5882 slow: 600,
5883 fast: 200,
5884 // Default speed
5885 _default: 400
5886 },
5887
5888 step: {
5889 opacity: function( fx ) {
5890 jQuery.style(fx.elem, "opacity", fx.now);
5891 },
5892
5893 _default: function( fx ) {
5894 if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
5895 fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
5896 } else {
5897 fx.elem[ fx.prop ] = fx.now;
5898 }
5899 }
5900 }
5901});
5902
5903if ( jQuery.expr && jQuery.expr.filters ) {
5904 jQuery.expr.filters.animated = function( elem ) {
5905 return jQuery.grep(jQuery.timers, function( fn ) {
5906 return elem === fn.elem;
5907 }).length;
5908 };
5909}
5910
5911function genFx( type, num ) {
5912 var obj = {};
5913
5914 jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
5915 obj[ this ] = type;
5916 });
5917
5918 return obj;
5919}
5920if ( "getBoundingClientRect" in document.documentElement ) {
5921 jQuery.fn.offset = function( options ) {
5922 var elem = this[0];
5923
5924 if ( options ) {
5925 return this.each(function( i ) {
5926 jQuery.offset.setOffset( this, options, i );
5927 });
5928 }
5929
5930 if ( !elem || !elem.ownerDocument ) {
5931 return null;
5932 }
5933
5934 if ( elem === elem.ownerDocument.body ) {
5935 return jQuery.offset.bodyOffset( elem );
5936 }
5937
5938 var box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement,
5939 clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
5940 top = box.top + (self.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop,
5941 left = box.left + (self.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
5942
5943 return { top: top, left: left };
5944 };
5945
5946} else {
5947 jQuery.fn.offset = function( options ) {
5948 var elem = this[0];
5949
5950 if ( options ) {
5951 return this.each(function( i ) {
5952 jQuery.offset.setOffset( this, options, i );
5953 });
5954 }
5955
5956 if ( !elem || !elem.ownerDocument ) {
5957 return null;
5958 }
5959
5960 if ( elem === elem.ownerDocument.body ) {
5961 return jQuery.offset.bodyOffset( elem );
5962 }
5963
5964 jQuery.offset.initialize();
5965
5966 var offsetParent = elem.offsetParent, prevOffsetParent = elem,
5967 doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
5968 body = doc.body, defaultView = doc.defaultView,
5969 prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
5970 top = elem.offsetTop, left = elem.offsetLeft;
5971
5972 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
5973 if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
5974 break;
5975 }
5976
5977 computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
5978 top -= elem.scrollTop;
5979 left -= elem.scrollLeft;
5980
5981 if ( elem === offsetParent ) {
5982 top += elem.offsetTop;
5983 left += elem.offsetLeft;
5984
5985 if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.nodeName)) ) {
5986 top += parseFloat( computedStyle.borderTopWidth ) || 0;
5987 left += parseFloat( computedStyle.borderLeftWidth ) || 0;
5988 }
5989
5990 prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
5991 }
5992
5993 if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
5994 top += parseFloat( computedStyle.borderTopWidth ) || 0;
5995 left += parseFloat( computedStyle.borderLeftWidth ) || 0;
5996 }
5997
5998 prevComputedStyle = computedStyle;
5999 }
6000
6001 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
6002 top += body.offsetTop;
6003 left += body.offsetLeft;
6004 }
6005
6006 if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
6007 top += Math.max( docElem.scrollTop, body.scrollTop );
6008 left += Math.max( docElem.scrollLeft, body.scrollLeft );
6009 }
6010
6011 return { top: top, left: left };
6012 };
6013}
6014
6015jQuery.offset = {
6016 initialize: function() {
6017 var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0,
6018 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>";
6019
6020 jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
6021
6022 container.innerHTML = html;
6023 body.insertBefore( container, body.firstChild );
6024 innerDiv = container.firstChild;
6025 checkDiv = innerDiv.firstChild;
6026 td = innerDiv.nextSibling.firstChild.firstChild;
6027
6028 this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
6029 this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
6030
6031 checkDiv.style.position = "fixed", checkDiv.style.top = "20px";
6032 // safari subtracts parent border width here which is 5px
6033 this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
6034 checkDiv.style.position = checkDiv.style.top = "";
6035
6036 innerDiv.style.overflow = "hidden", innerDiv.style.position = "relative";
6037 this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
6038
6039 this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
6040
6041 body.removeChild( container );
6042 body = container = innerDiv = checkDiv = table = td = null;
6043 jQuery.offset.initialize = jQuery.noop;
6044 },
6045
6046 bodyOffset: function( body ) {
6047 var top = body.offsetTop, left = body.offsetLeft;
6048
6049 jQuery.offset.initialize();
6050
6051 if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
6052 top += parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0;
6053 left += parseFloat( jQuery.curCSS(body, "marginLeft", true) ) || 0;
6054 }
6055
6056 return { top: top, left: left };
6057 },
6058
6059 setOffset: function( elem, options, i ) {
6060 // set position first, in-case top/left are set even on static elem
6061 if ( /static/.test( jQuery.curCSS( elem, "position" ) ) ) {
6062 elem.style.position = "relative";
6063 }
6064 var curElem = jQuery( elem ),
6065 curOffset = curElem.offset(),
6066 curTop = parseInt( jQuery.curCSS( elem, "top", true ), 10 ) || 0,
6067 curLeft = parseInt( jQuery.curCSS( elem, "left", true ), 10 ) || 0;
6068
6069 if ( jQuery.isFunction( options ) ) {
6070 options = options.call( elem, i, curOffset );
6071 }
6072
6073 var props = {
6074 top: (options.top - curOffset.top) + curTop,
6075 left: (options.left - curOffset.left) + curLeft
6076 };
6077
6078 if ( "using" in options ) {
6079 options.using.call( elem, props );
6080 } else {
6081 curElem.css( props );
6082 }
6083 }
6084};
6085
6086
6087jQuery.fn.extend({
6088 position: function() {
6089 if ( !this[0] ) {
6090 return null;
6091 }
6092
6093 var elem = this[0],
6094
6095 // Get *real* offsetParent
6096 offsetParent = this.offsetParent(),
6097
6098 // Get correct offsets
6099 offset = this.offset(),
6100 parentOffset = /^body|html$/i.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
6101
6102 // Subtract element margins
6103 // note: when an element has margin: auto the offsetLeft and marginLeft
6104 // are the same in Safari causing offset.left to incorrectly be 0
6105 offset.top -= parseFloat( jQuery.curCSS(elem, "marginTop", true) ) || 0;
6106 offset.left -= parseFloat( jQuery.curCSS(elem, "marginLeft", true) ) || 0;
6107
6108 // Add offsetParent borders
6109 parentOffset.top += parseFloat( jQuery.curCSS(offsetParent[0], "borderTopWidth", true) ) || 0;
6110 parentOffset.left += parseFloat( jQuery.curCSS(offsetParent[0], "borderLeftWidth", true) ) || 0;
6111
6112 // Subtract the two offsets
6113 return {
6114 top: offset.top - parentOffset.top,
6115 left: offset.left - parentOffset.left
6116 };
6117 },
6118
6119 offsetParent: function() {
6120 return this.map(function() {
6121 var offsetParent = this.offsetParent || document.body;
6122 while ( offsetParent && (!/^body|html$/i.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
6123 offsetParent = offsetParent.offsetParent;
6124 }
6125 return offsetParent;
6126 });
6127 }
6128});
6129
6130
6131// Create scrollLeft and scrollTop methods
6132jQuery.each( ["Left", "Top"], function( i, name ) {
6133 var method = "scroll" + name;
6134
6135 jQuery.fn[ method ] = function(val) {
6136 var elem = this[0], win;
6137
6138 if ( !elem ) {
6139 return null;
6140 }
6141
6142 if ( val !== undefined ) {
6143 // Set the scroll offset
6144 return this.each(function() {
6145 win = getWindow( this );
6146
6147 if ( win ) {
6148 win.scrollTo(
6149 !i ? val : jQuery(win).scrollLeft(),
6150 i ? val : jQuery(win).scrollTop()
6151 );
6152
6153 } else {
6154 this[ method ] = val;
6155 }
6156 });
6157 } else {
6158 win = getWindow( elem );
6159
6160 // Return the scroll offset
6161 return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
6162 jQuery.support.boxModel && win.document.documentElement[ method ] ||
6163 win.document.body[ method ] :
6164 elem[ method ];
6165 }
6166 };
6167});
6168
6169function getWindow( elem ) {
6170 return ("scrollTo" in elem && elem.document) ?
6171 elem :
6172 elem.nodeType === 9 ?
6173 elem.defaultView || elem.parentWindow :
6174 false;
6175}
6176// Create innerHeight, innerWidth, outerHeight and outerWidth methods
6177jQuery.each([ "Height", "Width" ], function( i, name ) {
6178
6179 var type = name.toLowerCase();
6180
6181 // innerHeight and innerWidth
6182 jQuery.fn["inner" + name] = function() {
6183 return this[0] ?
6184 jQuery.css( this[0], type, false, "padding" ) :
6185 null;
6186 };
6187
6188 // outerHeight and outerWidth
6189 jQuery.fn["outer" + name] = function( margin ) {
6190 return this[0] ?
6191 jQuery.css( this[0], type, false, margin ? "margin" : "border" ) :
6192 null;
6193 };
6194
6195 jQuery.fn[ type ] = function( size ) {
6196 // Get window width or height
6197 var elem = this[0];
6198 if ( !elem ) {
6199 return size == null ? null : this;
6200 }
6201
6202 if ( jQuery.isFunction( size ) ) {
6203 return this.each(function( i ) {
6204 var self = jQuery( this );
6205 self[ type ]( size.call( this, i, self[ type ]() ) );
6206 });
6207 }
6208
6209 return ("scrollTo" in elem && elem.document) ? // does it walk and quack like a window?
6210 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
6211 elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
6212 elem.document.body[ "client" + name ] :
6213
6214 // Get document width or height
6215 (elem.nodeType === 9) ? // is it a document
6216 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
6217 Math.max(
6218 elem.documentElement["client" + name],
6219 elem.body["scroll" + name], elem.documentElement["scroll" + name],
6220 elem.body["offset" + name], elem.documentElement["offset" + name]
6221 ) :
6222
6223 // Get or set width or height on the element
6224 size === undefined ?
6225 // Get width or height on the element
6226 jQuery.css( elem, type ) :
6227
6228 // Set the width or height on the element (default to pixels if value is unitless)
6229 this.css( type, typeof size === "string" ? size : size + "px" );
6230 };
6231
6232});
6233// Expose jQuery to the global object
6234window.jQuery = window.$ = jQuery;
6235
6236})(window);