source: main/trunk/greenstone3/web/interfaces/oran/js/jquery-ui-1.8rc1/jquery-1.4.1.js@ 24245

Last change on this file since 24245 was 24245, checked in by sjb48, 13 years ago

Oran code for supporting format changes to document.

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