Merge remote branch 'origin/master' into mlewandow-branch01
[phpmyadmin/mlewandow.git] / js / jquery / jquery-1.4.4.js
bloba9f2ec7d2d2fecb8b3eb10d5901ca08b8ee03b7c
1 /*!
2 * jQuery JavaScript Library v1.4.4
3 * http://jquery.com/
5 * Copyright 2010, John Resig
6 * Dual licensed under the MIT or GPL Version 2 licenses.
7 * http://jquery.org/license
9 * Includes Sizzle.js
10 * http://sizzlejs.com/
11 * Copyright 2010, The Dojo Foundation
12 * Released under the MIT, BSD, and GPL Licenses.
14 * Date: Thu Nov 11 19:04:53 2010 -0500
16 (function( window, undefined ) {
18 // Use the correct document accordingly with window argument (sandbox)
19 var document = window.document;
20 var jQuery = (function() {
22 // Define a local copy of jQuery
23 var jQuery = function( selector, context ) {
24 // The jQuery object is actually just the init constructor 'enhanced'
25 return new jQuery.fn.init( selector, context );
28 // Map over jQuery in case of overwrite
29 _jQuery = window.jQuery,
31 // Map over the $ in case of overwrite
32 _$ = window.$,
34 // A central reference to the root jQuery(document)
35 rootjQuery,
37 // A simple way to check for HTML strings or ID strings
38 // (both of which we optimize for)
39 quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
41 // Is it a simple selector
42 isSimple = /^.[^:#\[\.,]*$/,
44 // Check if a string has a non-whitespace character in it
45 rnotwhite = /\S/,
46 rwhite = /\s/,
48 // Used for trimming whitespace
49 trimLeft = /^\s+/,
50 trimRight = /\s+$/,
52 // Check for non-word characters
53 rnonword = /\W/,
55 // Check for digits
56 rdigit = /\d/,
58 // Match a standalone tag
59 rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
61 // JSON RegExp
62 rvalidchars = /^[\],:{}\s]*$/,
63 rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
64 rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
65 rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
67 // Useragent RegExp
68 rwebkit = /(webkit)[ \/]([\w.]+)/,
69 ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
70 rmsie = /(msie) ([\w.]+)/,
71 rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
73 // Keep a UserAgent string for use with jQuery.browser
74 userAgent = navigator.userAgent,
76 // For matching the engine and version of the browser
77 browserMatch,
79 // Has the ready events already been bound?
80 readyBound = false,
82 // The functions to execute on DOM ready
83 readyList = [],
85 // The ready event handler
86 DOMContentLoaded,
88 // Save a reference to some core methods
89 toString = Object.prototype.toString,
90 hasOwn = Object.prototype.hasOwnProperty,
91 push = Array.prototype.push,
92 slice = Array.prototype.slice,
93 trim = String.prototype.trim,
94 indexOf = Array.prototype.indexOf,
96 // [[Class]] -> type pairs
97 class2type = {};
99 jQuery.fn = jQuery.prototype = {
100 init: function( selector, context ) {
101 var match, elem, ret, doc;
103 // Handle $(""), $(null), or $(undefined)
104 if ( !selector ) {
105 return this;
108 // Handle $(DOMElement)
109 if ( selector.nodeType ) {
110 this.context = this[0] = selector;
111 this.length = 1;
112 return this;
115 // The body element only exists once, optimize finding it
116 if ( selector === "body" && !context && document.body ) {
117 this.context = document;
118 this[0] = document.body;
119 this.selector = "body";
120 this.length = 1;
121 return this;
124 // Handle HTML strings
125 if ( typeof selector === "string" ) {
126 // Are we dealing with HTML string or an ID?
127 match = quickExpr.exec( selector );
129 // Verify a match, and that no context was specified for #id
130 if ( match && (match[1] || !context) ) {
132 // HANDLE: $(html) -> $(array)
133 if ( match[1] ) {
134 doc = (context ? context.ownerDocument || context : document);
136 // If a single string is passed in and it's a single tag
137 // just do a createElement and skip the rest
138 ret = rsingleTag.exec( selector );
140 if ( ret ) {
141 if ( jQuery.isPlainObject( context ) ) {
142 selector = [ document.createElement( ret[1] ) ];
143 jQuery.fn.attr.call( selector, context, true );
145 } else {
146 selector = [ doc.createElement( ret[1] ) ];
149 } else {
150 ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
151 selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
154 return jQuery.merge( this, selector );
156 // HANDLE: $("#id")
157 } else {
158 elem = document.getElementById( match[2] );
160 // Check parentNode to catch when Blackberry 4.6 returns
161 // nodes that are no longer in the document #6963
162 if ( elem && elem.parentNode ) {
163 // Handle the case where IE and Opera return items
164 // by name instead of ID
165 if ( elem.id !== match[2] ) {
166 return rootjQuery.find( selector );
169 // Otherwise, we inject the element directly into the jQuery object
170 this.length = 1;
171 this[0] = elem;
174 this.context = document;
175 this.selector = selector;
176 return this;
179 // HANDLE: $("TAG")
180 } else if ( !context && !rnonword.test( selector ) ) {
181 this.selector = selector;
182 this.context = document;
183 selector = document.getElementsByTagName( selector );
184 return jQuery.merge( this, selector );
186 // HANDLE: $(expr, $(...))
187 } else if ( !context || context.jquery ) {
188 return (context || rootjQuery).find( selector );
190 // HANDLE: $(expr, context)
191 // (which is just equivalent to: $(context).find(expr)
192 } else {
193 return jQuery( context ).find( selector );
196 // HANDLE: $(function)
197 // Shortcut for document ready
198 } else if ( jQuery.isFunction( selector ) ) {
199 return rootjQuery.ready( selector );
202 if (selector.selector !== undefined) {
203 this.selector = selector.selector;
204 this.context = selector.context;
207 return jQuery.makeArray( selector, this );
210 // Start with an empty selector
211 selector: "",
213 // The current version of jQuery being used
214 jquery: "1.4.4",
216 // The default length of a jQuery object is 0
217 length: 0,
219 // The number of elements contained in the matched element set
220 size: function() {
221 return this.length;
224 toArray: function() {
225 return slice.call( this, 0 );
228 // Get the Nth element in the matched element set OR
229 // Get the whole matched element set as a clean array
230 get: function( num ) {
231 return num == null ?
233 // Return a 'clean' array
234 this.toArray() :
236 // Return just the object
237 ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
240 // Take an array of elements and push it onto the stack
241 // (returning the new matched element set)
242 pushStack: function( elems, name, selector ) {
243 // Build a new jQuery matched element set
244 var ret = jQuery();
246 if ( jQuery.isArray( elems ) ) {
247 push.apply( ret, elems );
249 } else {
250 jQuery.merge( ret, elems );
253 // Add the old object onto the stack (as a reference)
254 ret.prevObject = this;
256 ret.context = this.context;
258 if ( name === "find" ) {
259 ret.selector = this.selector + (this.selector ? " " : "") + selector;
260 } else if ( name ) {
261 ret.selector = this.selector + "." + name + "(" + selector + ")";
264 // Return the newly-formed element set
265 return ret;
268 // Execute a callback for every element in the matched set.
269 // (You can seed the arguments with an array of args, but this is
270 // only used internally.)
271 each: function( callback, args ) {
272 return jQuery.each( this, callback, args );
275 ready: function( fn ) {
276 // Attach the listeners
277 jQuery.bindReady();
279 // If the DOM is already ready
280 if ( jQuery.isReady ) {
281 // Execute the function immediately
282 fn.call( document, jQuery );
284 // Otherwise, remember the function for later
285 } else if ( readyList ) {
286 // Add the function to the wait list
287 readyList.push( fn );
290 return this;
293 eq: function( i ) {
294 return i === -1 ?
295 this.slice( i ) :
296 this.slice( i, +i + 1 );
299 first: function() {
300 return this.eq( 0 );
303 last: function() {
304 return this.eq( -1 );
307 slice: function() {
308 return this.pushStack( slice.apply( this, arguments ),
309 "slice", slice.call(arguments).join(",") );
312 map: function( callback ) {
313 return this.pushStack( jQuery.map(this, function( elem, i ) {
314 return callback.call( elem, i, elem );
315 }));
318 end: function() {
319 return this.prevObject || jQuery(null);
322 // For internal use only.
323 // Behaves like an Array's method, not like a jQuery method.
324 push: push,
325 sort: [].sort,
326 splice: [].splice
329 // Give the init function the jQuery prototype for later instantiation
330 jQuery.fn.init.prototype = jQuery.fn;
332 jQuery.extend = jQuery.fn.extend = function() {
333 var options, name, src, copy, copyIsArray, clone,
334 target = arguments[0] || {},
335 i = 1,
336 length = arguments.length,
337 deep = false;
339 // Handle a deep copy situation
340 if ( typeof target === "boolean" ) {
341 deep = target;
342 target = arguments[1] || {};
343 // skip the boolean and the target
344 i = 2;
347 // Handle case when target is a string or something (possible in deep copy)
348 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
349 target = {};
352 // extend jQuery itself if only one argument is passed
353 if ( length === i ) {
354 target = this;
355 --i;
358 for ( ; i < length; i++ ) {
359 // Only deal with non-null/undefined values
360 if ( (options = arguments[ i ]) != null ) {
361 // Extend the base object
362 for ( name in options ) {
363 src = target[ name ];
364 copy = options[ name ];
366 // Prevent never-ending loop
367 if ( target === copy ) {
368 continue;
371 // Recurse if we're merging plain objects or arrays
372 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
373 if ( copyIsArray ) {
374 copyIsArray = false;
375 clone = src && jQuery.isArray(src) ? src : [];
377 } else {
378 clone = src && jQuery.isPlainObject(src) ? src : {};
381 // Never move original objects, clone them
382 target[ name ] = jQuery.extend( deep, clone, copy );
384 // Don't bring in undefined values
385 } else if ( copy !== undefined ) {
386 target[ name ] = copy;
392 // Return the modified object
393 return target;
396 jQuery.extend({
397 noConflict: function( deep ) {
398 window.$ = _$;
400 if ( deep ) {
401 window.jQuery = _jQuery;
404 return jQuery;
407 // Is the DOM ready to be used? Set to true once it occurs.
408 isReady: false,
410 // A counter to track how many items to wait for before
411 // the ready event fires. See #6781
412 readyWait: 1,
414 // Handle when the DOM is ready
415 ready: function( wait ) {
416 // A third-party is pushing the ready event forwards
417 if ( wait === true ) {
418 jQuery.readyWait--;
421 // Make sure that the DOM is not already loaded
422 if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) {
423 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
424 if ( !document.body ) {
425 return setTimeout( jQuery.ready, 1 );
428 // Remember that the DOM is ready
429 jQuery.isReady = true;
431 // If a normal DOM Ready event fired, decrement, and wait if need be
432 if ( wait !== true && --jQuery.readyWait > 0 ) {
433 return;
436 // If there are functions bound, to execute
437 if ( readyList ) {
438 // Execute all of them
439 var fn,
440 i = 0,
441 ready = readyList;
443 // Reset the list of functions
444 readyList = null;
446 while ( (fn = ready[ i++ ]) ) {
447 fn.call( document, jQuery );
450 // Trigger any bound ready events
451 if ( jQuery.fn.trigger ) {
452 jQuery( document ).trigger( "ready" ).unbind( "ready" );
458 bindReady: function() {
459 if ( readyBound ) {
460 return;
463 readyBound = true;
465 // Catch cases where $(document).ready() is called after the
466 // browser event has already occurred.
467 if ( document.readyState === "complete" ) {
468 // Handle it asynchronously to allow scripts the opportunity to delay ready
469 return setTimeout( jQuery.ready, 1 );
472 // Mozilla, Opera and webkit nightlies currently support this event
473 if ( document.addEventListener ) {
474 // Use the handy event callback
475 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
477 // A fallback to window.onload, that will always work
478 window.addEventListener( "load", jQuery.ready, false );
480 // If IE event model is used
481 } else if ( document.attachEvent ) {
482 // ensure firing before onload,
483 // maybe late but safe also for iframes
484 document.attachEvent("onreadystatechange", DOMContentLoaded);
486 // A fallback to window.onload, that will always work
487 window.attachEvent( "onload", jQuery.ready );
489 // If IE and not a frame
490 // continually check to see if the document is ready
491 var toplevel = false;
493 try {
494 toplevel = window.frameElement == null;
495 } catch(e) {}
497 if ( document.documentElement.doScroll && toplevel ) {
498 doScrollCheck();
503 // See test/unit/core.js for details concerning isFunction.
504 // Since version 1.3, DOM methods and functions like alert
505 // aren't supported. They return false on IE (#2968).
506 isFunction: function( obj ) {
507 return jQuery.type(obj) === "function";
510 isArray: Array.isArray || function( obj ) {
511 return jQuery.type(obj) === "array";
514 // A crude way of determining if an object is a window
515 isWindow: function( obj ) {
516 return obj && typeof obj === "object" && "setInterval" in obj;
519 isNaN: function( obj ) {
520 return obj == null || !rdigit.test( obj ) || isNaN( obj );
523 type: function( obj ) {
524 return obj == null ?
525 String( obj ) :
526 class2type[ toString.call(obj) ] || "object";
529 isPlainObject: function( obj ) {
530 // Must be an Object.
531 // Because of IE, we also have to check the presence of the constructor property.
532 // Make sure that DOM nodes and window objects don't pass through, as well
533 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
534 return false;
537 // Not own constructor property must be Object
538 if ( obj.constructor &&
539 !hasOwn.call(obj, "constructor") &&
540 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
541 return false;
544 // Own properties are enumerated firstly, so to speed up,
545 // if last one is own, then all properties are own.
547 var key;
548 for ( key in obj ) {}
550 return key === undefined || hasOwn.call( obj, key );
553 isEmptyObject: function( obj ) {
554 for ( var name in obj ) {
555 return false;
557 return true;
560 error: function( msg ) {
561 throw msg;
564 parseJSON: function( data ) {
565 if ( typeof data !== "string" || !data ) {
566 return null;
569 // Make sure leading/trailing whitespace is removed (IE can't handle it)
570 data = jQuery.trim( data );
572 // Make sure the incoming data is actual JSON
573 // Logic borrowed from http://json.org/json2.js
574 if ( rvalidchars.test(data.replace(rvalidescape, "@")
575 .replace(rvalidtokens, "]")
576 .replace(rvalidbraces, "")) ) {
578 // Try to use the native JSON parser first
579 return window.JSON && window.JSON.parse ?
580 window.JSON.parse( data ) :
581 (new Function("return " + data))();
583 } else {
584 jQuery.error( "Invalid JSON: " + data );
588 noop: function() {},
590 // Evalulates a script in a global context
591 globalEval: function( data ) {
592 if ( data && rnotwhite.test(data) ) {
593 // Inspired by code by Andrea Giammarchi
594 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
595 var head = document.getElementsByTagName("head")[0] || document.documentElement,
596 script = document.createElement("script");
598 script.type = "text/javascript";
600 if ( jQuery.support.scriptEval ) {
601 script.appendChild( document.createTextNode( data ) );
602 } else {
603 script.text = data;
606 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
607 // This arises when a base node is used (#2709).
608 head.insertBefore( script, head.firstChild );
609 head.removeChild( script );
613 nodeName: function( elem, name ) {
614 return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
617 // args is for internal usage only
618 each: function( object, callback, args ) {
619 var name, i = 0,
620 length = object.length,
621 isObj = length === undefined || jQuery.isFunction(object);
623 if ( args ) {
624 if ( isObj ) {
625 for ( name in object ) {
626 if ( callback.apply( object[ name ], args ) === false ) {
627 break;
630 } else {
631 for ( ; i < length; ) {
632 if ( callback.apply( object[ i++ ], args ) === false ) {
633 break;
638 // A special, fast, case for the most common use of each
639 } else {
640 if ( isObj ) {
641 for ( name in object ) {
642 if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
643 break;
646 } else {
647 for ( var value = object[0];
648 i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
652 return object;
655 // Use native String.trim function wherever possible
656 trim: trim ?
657 function( text ) {
658 return text == null ?
659 "" :
660 trim.call( text );
663 // Otherwise use our own trimming functionality
664 function( text ) {
665 return text == null ?
666 "" :
667 text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
670 // results is for internal usage only
671 makeArray: function( array, results ) {
672 var ret = results || [];
674 if ( array != null ) {
675 // The window, strings (and functions) also have 'length'
676 // The extra typeof function check is to prevent crashes
677 // in Safari 2 (See: #3039)
678 // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
679 var type = jQuery.type(array);
681 if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
682 push.call( ret, array );
683 } else {
684 jQuery.merge( ret, array );
688 return ret;
691 inArray: function( elem, array ) {
692 if ( array.indexOf ) {
693 return array.indexOf( elem );
696 for ( var i = 0, length = array.length; i < length; i++ ) {
697 if ( array[ i ] === elem ) {
698 return i;
702 return -1;
705 merge: function( first, second ) {
706 var i = first.length,
707 j = 0;
709 if ( typeof second.length === "number" ) {
710 for ( var l = second.length; j < l; j++ ) {
711 first[ i++ ] = second[ j ];
714 } else {
715 while ( second[j] !== undefined ) {
716 first[ i++ ] = second[ j++ ];
720 first.length = i;
722 return first;
725 grep: function( elems, callback, inv ) {
726 var ret = [], retVal;
727 inv = !!inv;
729 // Go through the array, only saving the items
730 // that pass the validator function
731 for ( var i = 0, length = elems.length; i < length; i++ ) {
732 retVal = !!callback( elems[ i ], i );
733 if ( inv !== retVal ) {
734 ret.push( elems[ i ] );
738 return ret;
741 // arg is for internal usage only
742 map: function( elems, callback, arg ) {
743 var ret = [], value;
745 // Go through the array, translating each of the items to their
746 // new value (or values).
747 for ( var i = 0, length = elems.length; i < length; i++ ) {
748 value = callback( elems[ i ], i, arg );
750 if ( value != null ) {
751 ret[ ret.length ] = value;
755 return ret.concat.apply( [], ret );
758 // A global GUID counter for objects
759 guid: 1,
761 proxy: function( fn, proxy, thisObject ) {
762 if ( arguments.length === 2 ) {
763 if ( typeof proxy === "string" ) {
764 thisObject = fn;
765 fn = thisObject[ proxy ];
766 proxy = undefined;
768 } else if ( proxy && !jQuery.isFunction( proxy ) ) {
769 thisObject = proxy;
770 proxy = undefined;
774 if ( !proxy && fn ) {
775 proxy = function() {
776 return fn.apply( thisObject || this, arguments );
780 // Set the guid of unique handler to the same of original handler, so it can be removed
781 if ( fn ) {
782 proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
785 // So proxy can be declared as an argument
786 return proxy;
789 // Mutifunctional method to get and set values to a collection
790 // The value/s can be optionally by executed if its a function
791 access: function( elems, key, value, exec, fn, pass ) {
792 var length = elems.length;
794 // Setting many attributes
795 if ( typeof key === "object" ) {
796 for ( var k in key ) {
797 jQuery.access( elems, k, key[k], exec, fn, value );
799 return elems;
802 // Setting one attribute
803 if ( value !== undefined ) {
804 // Optionally, function values get executed if exec is true
805 exec = !pass && exec && jQuery.isFunction(value);
807 for ( var i = 0; i < length; i++ ) {
808 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
811 return elems;
814 // Getting an attribute
815 return length ? fn( elems[0], key ) : undefined;
818 now: function() {
819 return (new Date()).getTime();
822 // Use of jQuery.browser is frowned upon.
823 // More details: http://docs.jquery.com/Utilities/jQuery.browser
824 uaMatch: function( ua ) {
825 ua = ua.toLowerCase();
827 var match = rwebkit.exec( ua ) ||
828 ropera.exec( ua ) ||
829 rmsie.exec( ua ) ||
830 ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
833 return { browser: match[1] || "", version: match[2] || "0" };
836 browser: {}
839 // Populate the class2type map
840 jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
841 class2type[ "[object " + name + "]" ] = name.toLowerCase();
844 browserMatch = jQuery.uaMatch( userAgent );
845 if ( browserMatch.browser ) {
846 jQuery.browser[ browserMatch.browser ] = true;
847 jQuery.browser.version = browserMatch.version;
850 // Deprecated, use jQuery.browser.webkit instead
851 if ( jQuery.browser.webkit ) {
852 jQuery.browser.safari = true;
855 if ( indexOf ) {
856 jQuery.inArray = function( elem, array ) {
857 return indexOf.call( array, elem );
861 // Verify that \s matches non-breaking spaces
862 // (IE fails on this test)
863 if ( !rwhite.test( "\xA0" ) ) {
864 trimLeft = /^[\s\xA0]+/;
865 trimRight = /[\s\xA0]+$/;
868 // All jQuery objects should point back to these
869 rootjQuery = jQuery(document);
871 // Cleanup functions for the document ready method
872 if ( document.addEventListener ) {
873 DOMContentLoaded = function() {
874 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
875 jQuery.ready();
878 } else if ( document.attachEvent ) {
879 DOMContentLoaded = function() {
880 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
881 if ( document.readyState === "complete" ) {
882 document.detachEvent( "onreadystatechange", DOMContentLoaded );
883 jQuery.ready();
888 // The DOM ready check for Internet Explorer
889 function doScrollCheck() {
890 if ( jQuery.isReady ) {
891 return;
894 try {
895 // If IE is used, use the trick by Diego Perini
896 // http://javascript.nwbox.com/IEContentLoaded/
897 document.documentElement.doScroll("left");
898 } catch(e) {
899 setTimeout( doScrollCheck, 1 );
900 return;
903 // and execute any waiting functions
904 jQuery.ready();
907 // Expose jQuery to the global object
908 return (window.jQuery = window.$ = jQuery);
910 })();
913 (function() {
915 jQuery.support = {};
917 var root = document.documentElement,
918 script = document.createElement("script"),
919 div = document.createElement("div"),
920 id = "script" + jQuery.now();
922 div.style.display = "none";
923 div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
925 var all = div.getElementsByTagName("*"),
926 a = div.getElementsByTagName("a")[0],
927 select = document.createElement("select"),
928 opt = select.appendChild( document.createElement("option") );
930 // Can't get basic test support
931 if ( !all || !all.length || !a ) {
932 return;
935 jQuery.support = {
936 // IE strips leading whitespace when .innerHTML is used
937 leadingWhitespace: div.firstChild.nodeType === 3,
939 // Make sure that tbody elements aren't automatically inserted
940 // IE will insert them into empty tables
941 tbody: !div.getElementsByTagName("tbody").length,
943 // Make sure that link elements get serialized correctly by innerHTML
944 // This requires a wrapper element in IE
945 htmlSerialize: !!div.getElementsByTagName("link").length,
947 // Get the style information from getAttribute
948 // (IE uses .cssText insted)
949 style: /red/.test( a.getAttribute("style") ),
951 // Make sure that URLs aren't manipulated
952 // (IE normalizes it by default)
953 hrefNormalized: a.getAttribute("href") === "/a",
955 // Make sure that element opacity exists
956 // (IE uses filter instead)
957 // Use a regex to work around a WebKit issue. See #5145
958 opacity: /^0.55$/.test( a.style.opacity ),
960 // Verify style float existence
961 // (IE uses styleFloat instead of cssFloat)
962 cssFloat: !!a.style.cssFloat,
964 // Make sure that if no value is specified for a checkbox
965 // that it defaults to "on".
966 // (WebKit defaults to "" instead)
967 checkOn: div.getElementsByTagName("input")[0].value === "on",
969 // Make sure that a selected-by-default option has a working selected property.
970 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
971 optSelected: opt.selected,
973 // Will be defined later
974 deleteExpando: true,
975 optDisabled: false,
976 checkClone: false,
977 scriptEval: false,
978 noCloneEvent: true,
979 boxModel: null,
980 inlineBlockNeedsLayout: false,
981 shrinkWrapBlocks: false,
982 reliableHiddenOffsets: true
985 // Make sure that the options inside disabled selects aren't marked as disabled
986 // (WebKit marks them as diabled)
987 select.disabled = true;
988 jQuery.support.optDisabled = !opt.disabled;
990 script.type = "text/javascript";
991 try {
992 script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
993 } catch(e) {}
995 root.insertBefore( script, root.firstChild );
997 // Make sure that the execution of code works by injecting a script
998 // tag with appendChild/createTextNode
999 // (IE doesn't support this, fails, and uses .text instead)
1000 if ( window[ id ] ) {
1001 jQuery.support.scriptEval = true;
1002 delete window[ id ];
1005 // Test to see if it's possible to delete an expando from an element
1006 // Fails in Internet Explorer
1007 try {
1008 delete script.test;
1010 } catch(e) {
1011 jQuery.support.deleteExpando = false;
1014 root.removeChild( script );
1016 if ( div.attachEvent && div.fireEvent ) {
1017 div.attachEvent("onclick", function click() {
1018 // Cloning a node shouldn't copy over any
1019 // bound event handlers (IE does this)
1020 jQuery.support.noCloneEvent = false;
1021 div.detachEvent("onclick", click);
1023 div.cloneNode(true).fireEvent("onclick");
1026 div = document.createElement("div");
1027 div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
1029 var fragment = document.createDocumentFragment();
1030 fragment.appendChild( div.firstChild );
1032 // WebKit doesn't clone checked state correctly in fragments
1033 jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
1035 // Figure out if the W3C box model works as expected
1036 // document.body must exist before we can do this
1037 jQuery(function() {
1038 var div = document.createElement("div"),
1039 body = document.getElementsByTagName("body")[0];
1041 // Frameset documents with no body should not run this code
1042 if ( !body ) {
1043 return;
1046 div.style.width = div.style.paddingLeft = "1px";
1047 body.appendChild( div );
1048 jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
1050 if ( "zoom" in div.style ) {
1051 // Check if natively block-level elements act like inline-block
1052 // elements when setting their display to 'inline' and giving
1053 // them layout
1054 // (IE < 8 does this)
1055 div.style.display = "inline";
1056 div.style.zoom = 1;
1057 jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2;
1059 // Check if elements with layout shrink-wrap their children
1060 // (IE 6 does this)
1061 div.style.display = "";
1062 div.innerHTML = "<div style='width:4px;'></div>";
1063 jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;
1066 div.innerHTML = "<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";
1067 var tds = div.getElementsByTagName("td");
1069 // Check if table cells still have offsetWidth/Height when they are set
1070 // to display:none and there are still other visible table cells in a
1071 // table row; if so, offsetWidth/Height are not reliable for use when
1072 // determining if an element has been hidden directly using
1073 // display:none (it is still safe to use offsets if a parent element is
1074 // hidden; don safety goggles and see bug #4512 for more information).
1075 // (only IE 8 fails this test)
1076 jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0;
1078 tds[0].style.display = "";
1079 tds[1].style.display = "none";
1081 // Check if empty table cells still have offsetWidth/Height
1082 // (IE < 8 fail this test)
1083 jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0;
1084 div.innerHTML = "";
1086 body.removeChild( div ).style.display = "none";
1087 div = tds = null;
1090 // Technique from Juriy Zaytsev
1091 // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
1092 var eventSupported = function( eventName ) {
1093 var el = document.createElement("div");
1094 eventName = "on" + eventName;
1096 var isSupported = (eventName in el);
1097 if ( !isSupported ) {
1098 el.setAttribute(eventName, "return;");
1099 isSupported = typeof el[eventName] === "function";
1101 el = null;
1103 return isSupported;
1106 jQuery.support.submitBubbles = eventSupported("submit");
1107 jQuery.support.changeBubbles = eventSupported("change");
1109 // release memory in IE
1110 root = script = div = all = a = null;
1111 })();
1115 var windowData = {},
1116 rbrace = /^(?:\{.*\}|\[.*\])$/;
1118 jQuery.extend({
1119 cache: {},
1121 // Please use with caution
1122 uuid: 0,
1124 // Unique for each copy of jQuery on the page
1125 expando: "jQuery" + jQuery.now(),
1127 // The following elements throw uncatchable exceptions if you
1128 // attempt to add expando properties to them.
1129 noData: {
1130 "embed": true,
1131 // Ban all objects except for Flash (which handle expandos)
1132 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
1133 "applet": true
1136 data: function( elem, name, data ) {
1137 if ( !jQuery.acceptData( elem ) ) {
1138 return;
1141 elem = elem == window ?
1142 windowData :
1143 elem;
1145 var isNode = elem.nodeType,
1146 id = isNode ? elem[ jQuery.expando ] : null,
1147 cache = jQuery.cache, thisCache;
1149 if ( isNode && !id && typeof name === "string" && data === undefined ) {
1150 return;
1153 // Get the data from the object directly
1154 if ( !isNode ) {
1155 cache = elem;
1157 // Compute a unique ID for the element
1158 } else if ( !id ) {
1159 elem[ jQuery.expando ] = id = ++jQuery.uuid;
1162 // Avoid generating a new cache unless none exists and we
1163 // want to manipulate it.
1164 if ( typeof name === "object" ) {
1165 if ( isNode ) {
1166 cache[ id ] = jQuery.extend(cache[ id ], name);
1168 } else {
1169 jQuery.extend( cache, name );
1172 } else if ( isNode && !cache[ id ] ) {
1173 cache[ id ] = {};
1176 thisCache = isNode ? cache[ id ] : cache;
1178 // Prevent overriding the named cache with undefined values
1179 if ( data !== undefined ) {
1180 thisCache[ name ] = data;
1183 return typeof name === "string" ? thisCache[ name ] : thisCache;
1186 removeData: function( elem, name ) {
1187 if ( !jQuery.acceptData( elem ) ) {
1188 return;
1191 elem = elem == window ?
1192 windowData :
1193 elem;
1195 var isNode = elem.nodeType,
1196 id = isNode ? elem[ jQuery.expando ] : elem,
1197 cache = jQuery.cache,
1198 thisCache = isNode ? cache[ id ] : id;
1200 // If we want to remove a specific section of the element's data
1201 if ( name ) {
1202 if ( thisCache ) {
1203 // Remove the section of cache data
1204 delete thisCache[ name ];
1206 // If we've removed all the data, remove the element's cache
1207 if ( isNode && jQuery.isEmptyObject(thisCache) ) {
1208 jQuery.removeData( elem );
1212 // Otherwise, we want to remove all of the element's data
1213 } else {
1214 if ( isNode && jQuery.support.deleteExpando ) {
1215 delete elem[ jQuery.expando ];
1217 } else if ( elem.removeAttribute ) {
1218 elem.removeAttribute( jQuery.expando );
1220 // Completely remove the data cache
1221 } else if ( isNode ) {
1222 delete cache[ id ];
1224 // Remove all fields from the object
1225 } else {
1226 for ( var n in elem ) {
1227 delete elem[ n ];
1233 // A method for determining if a DOM node can handle the data expando
1234 acceptData: function( elem ) {
1235 if ( elem.nodeName ) {
1236 var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
1238 if ( match ) {
1239 return !(match === true || elem.getAttribute("classid") !== match);
1243 return true;
1247 jQuery.fn.extend({
1248 data: function( key, value ) {
1249 var data = null;
1251 if ( typeof key === "undefined" ) {
1252 if ( this.length ) {
1253 var attr = this[0].attributes, name;
1254 data = jQuery.data( this[0] );
1256 for ( var i = 0, l = attr.length; i < l; i++ ) {
1257 name = attr[i].name;
1259 if ( name.indexOf( "data-" ) === 0 ) {
1260 name = name.substr( 5 );
1261 dataAttr( this[0], name, data[ name ] );
1266 return data;
1268 } else if ( typeof key === "object" ) {
1269 return this.each(function() {
1270 jQuery.data( this, key );
1274 var parts = key.split(".");
1275 parts[1] = parts[1] ? "." + parts[1] : "";
1277 if ( value === undefined ) {
1278 data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
1280 // Try to fetch any internally stored data first
1281 if ( data === undefined && this.length ) {
1282 data = jQuery.data( this[0], key );
1283 data = dataAttr( this[0], key, data );
1286 return data === undefined && parts[1] ?
1287 this.data( parts[0] ) :
1288 data;
1290 } else {
1291 return this.each(function() {
1292 var $this = jQuery( this ),
1293 args = [ parts[0], value ];
1295 $this.triggerHandler( "setData" + parts[1] + "!", args );
1296 jQuery.data( this, key, value );
1297 $this.triggerHandler( "changeData" + parts[1] + "!", args );
1302 removeData: function( key ) {
1303 return this.each(function() {
1304 jQuery.removeData( this, key );
1309 function dataAttr( elem, key, data ) {
1310 // If nothing was found internally, try to fetch any
1311 // data from the HTML5 data-* attribute
1312 if ( data === undefined && elem.nodeType === 1 ) {
1313 data = elem.getAttribute( "data-" + key );
1315 if ( typeof data === "string" ) {
1316 try {
1317 data = data === "true" ? true :
1318 data === "false" ? false :
1319 data === "null" ? null :
1320 !jQuery.isNaN( data ) ? parseFloat( data ) :
1321 rbrace.test( data ) ? jQuery.parseJSON( data ) :
1322 data;
1323 } catch( e ) {}
1325 // Make sure we set the data so it isn't changed later
1326 jQuery.data( elem, key, data );
1328 } else {
1329 data = undefined;
1333 return data;
1339 jQuery.extend({
1340 queue: function( elem, type, data ) {
1341 if ( !elem ) {
1342 return;
1345 type = (type || "fx") + "queue";
1346 var q = jQuery.data( elem, type );
1348 // Speed up dequeue by getting out quickly if this is just a lookup
1349 if ( !data ) {
1350 return q || [];
1353 if ( !q || jQuery.isArray(data) ) {
1354 q = jQuery.data( elem, type, jQuery.makeArray(data) );
1356 } else {
1357 q.push( data );
1360 return q;
1363 dequeue: function( elem, type ) {
1364 type = type || "fx";
1366 var queue = jQuery.queue( elem, type ),
1367 fn = queue.shift();
1369 // If the fx queue is dequeued, always remove the progress sentinel
1370 if ( fn === "inprogress" ) {
1371 fn = queue.shift();
1374 if ( fn ) {
1375 // Add a progress sentinel to prevent the fx queue from being
1376 // automatically dequeued
1377 if ( type === "fx" ) {
1378 queue.unshift("inprogress");
1381 fn.call(elem, function() {
1382 jQuery.dequeue(elem, type);
1388 jQuery.fn.extend({
1389 queue: function( type, data ) {
1390 if ( typeof type !== "string" ) {
1391 data = type;
1392 type = "fx";
1395 if ( data === undefined ) {
1396 return jQuery.queue( this[0], type );
1398 return this.each(function( i ) {
1399 var queue = jQuery.queue( this, type, data );
1401 if ( type === "fx" && queue[0] !== "inprogress" ) {
1402 jQuery.dequeue( this, type );
1406 dequeue: function( type ) {
1407 return this.each(function() {
1408 jQuery.dequeue( this, type );
1412 // Based off of the plugin by Clint Helfers, with permission.
1413 // http://blindsignals.com/index.php/2009/07/jquery-delay/
1414 delay: function( time, type ) {
1415 time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
1416 type = type || "fx";
1418 return this.queue( type, function() {
1419 var elem = this;
1420 setTimeout(function() {
1421 jQuery.dequeue( elem, type );
1422 }, time );
1426 clearQueue: function( type ) {
1427 return this.queue( type || "fx", [] );
1434 var rclass = /[\n\t]/g,
1435 rspaces = /\s+/,
1436 rreturn = /\r/g,
1437 rspecialurl = /^(?:href|src|style)$/,
1438 rtype = /^(?:button|input)$/i,
1439 rfocusable = /^(?:button|input|object|select|textarea)$/i,
1440 rclickable = /^a(?:rea)?$/i,
1441 rradiocheck = /^(?:radio|checkbox)$/i;
1443 jQuery.props = {
1444 "for": "htmlFor",
1445 "class": "className",
1446 readonly: "readOnly",
1447 maxlength: "maxLength",
1448 cellspacing: "cellSpacing",
1449 rowspan: "rowSpan",
1450 colspan: "colSpan",
1451 tabindex: "tabIndex",
1452 usemap: "useMap",
1453 frameborder: "frameBorder"
1456 jQuery.fn.extend({
1457 attr: function( name, value ) {
1458 return jQuery.access( this, name, value, true, jQuery.attr );
1461 removeAttr: function( name, fn ) {
1462 return this.each(function(){
1463 jQuery.attr( this, name, "" );
1464 if ( this.nodeType === 1 ) {
1465 this.removeAttribute( name );
1470 addClass: function( value ) {
1471 if ( jQuery.isFunction(value) ) {
1472 return this.each(function(i) {
1473 var self = jQuery(this);
1474 self.addClass( value.call(this, i, self.attr("class")) );
1478 if ( value && typeof value === "string" ) {
1479 var classNames = (value || "").split( rspaces );
1481 for ( var i = 0, l = this.length; i < l; i++ ) {
1482 var elem = this[i];
1484 if ( elem.nodeType === 1 ) {
1485 if ( !elem.className ) {
1486 elem.className = value;
1488 } else {
1489 var className = " " + elem.className + " ",
1490 setClass = elem.className;
1492 for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
1493 if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
1494 setClass += " " + classNames[c];
1497 elem.className = jQuery.trim( setClass );
1503 return this;
1506 removeClass: function( value ) {
1507 if ( jQuery.isFunction(value) ) {
1508 return this.each(function(i) {
1509 var self = jQuery(this);
1510 self.removeClass( value.call(this, i, self.attr("class")) );
1514 if ( (value && typeof value === "string") || value === undefined ) {
1515 var classNames = (value || "").split( rspaces );
1517 for ( var i = 0, l = this.length; i < l; i++ ) {
1518 var elem = this[i];
1520 if ( elem.nodeType === 1 && elem.className ) {
1521 if ( value ) {
1522 var className = (" " + elem.className + " ").replace(rclass, " ");
1523 for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
1524 className = className.replace(" " + classNames[c] + " ", " ");
1526 elem.className = jQuery.trim( className );
1528 } else {
1529 elem.className = "";
1535 return this;
1538 toggleClass: function( value, stateVal ) {
1539 var type = typeof value,
1540 isBool = typeof stateVal === "boolean";
1542 if ( jQuery.isFunction( value ) ) {
1543 return this.each(function(i) {
1544 var self = jQuery(this);
1545 self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
1549 return this.each(function() {
1550 if ( type === "string" ) {
1551 // toggle individual class names
1552 var className,
1553 i = 0,
1554 self = jQuery( this ),
1555 state = stateVal,
1556 classNames = value.split( rspaces );
1558 while ( (className = classNames[ i++ ]) ) {
1559 // check each className given, space seperated list
1560 state = isBool ? state : !self.hasClass( className );
1561 self[ state ? "addClass" : "removeClass" ]( className );
1564 } else if ( type === "undefined" || type === "boolean" ) {
1565 if ( this.className ) {
1566 // store className if set
1567 jQuery.data( this, "__className__", this.className );
1570 // toggle whole className
1571 this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
1576 hasClass: function( selector ) {
1577 var className = " " + selector + " ";
1578 for ( var i = 0, l = this.length; i < l; i++ ) {
1579 if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
1580 return true;
1584 return false;
1587 val: function( value ) {
1588 if ( !arguments.length ) {
1589 var elem = this[0];
1591 if ( elem ) {
1592 if ( jQuery.nodeName( elem, "option" ) ) {
1593 // attributes.value is undefined in Blackberry 4.7 but
1594 // uses .value. See #6932
1595 var val = elem.attributes.value;
1596 return !val || val.specified ? elem.value : elem.text;
1599 // We need to handle select boxes special
1600 if ( jQuery.nodeName( elem, "select" ) ) {
1601 var index = elem.selectedIndex,
1602 values = [],
1603 options = elem.options,
1604 one = elem.type === "select-one";
1606 // Nothing was selected
1607 if ( index < 0 ) {
1608 return null;
1611 // Loop through all the selected options
1612 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
1613 var option = options[ i ];
1615 // Don't return options that are disabled or in a disabled optgroup
1616 if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
1617 (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
1619 // Get the specific value for the option
1620 value = jQuery(option).val();
1622 // We don't need an array for one selects
1623 if ( one ) {
1624 return value;
1627 // Multi-Selects return an array
1628 values.push( value );
1632 return values;
1635 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
1636 if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
1637 return elem.getAttribute("value") === null ? "on" : elem.value;
1641 // Everything else, we just grab the value
1642 return (elem.value || "").replace(rreturn, "");
1646 return undefined;
1649 var isFunction = jQuery.isFunction(value);
1651 return this.each(function(i) {
1652 var self = jQuery(this), val = value;
1654 if ( this.nodeType !== 1 ) {
1655 return;
1658 if ( isFunction ) {
1659 val = value.call(this, i, self.val());
1662 // Treat null/undefined as ""; convert numbers to string
1663 if ( val == null ) {
1664 val = "";
1665 } else if ( typeof val === "number" ) {
1666 val += "";
1667 } else if ( jQuery.isArray(val) ) {
1668 val = jQuery.map(val, function (value) {
1669 return value == null ? "" : value + "";
1673 if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
1674 this.checked = jQuery.inArray( self.val(), val ) >= 0;
1676 } else if ( jQuery.nodeName( this, "select" ) ) {
1677 var values = jQuery.makeArray(val);
1679 jQuery( "option", this ).each(function() {
1680 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
1683 if ( !values.length ) {
1684 this.selectedIndex = -1;
1687 } else {
1688 this.value = val;
1694 jQuery.extend({
1695 attrFn: {
1696 val: true,
1697 css: true,
1698 html: true,
1699 text: true,
1700 data: true,
1701 width: true,
1702 height: true,
1703 offset: true
1706 attr: function( elem, name, value, pass ) {
1707 // don't set attributes on text and comment nodes
1708 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
1709 return undefined;
1712 if ( pass && name in jQuery.attrFn ) {
1713 return jQuery(elem)[name](value);
1716 var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
1717 // Whether we are setting (or getting)
1718 set = value !== undefined;
1720 // Try to normalize/fix the name
1721 name = notxml && jQuery.props[ name ] || name;
1723 // These attributes require special treatment
1724 var special = rspecialurl.test( name );
1726 // Safari mis-reports the default selected property of an option
1727 // Accessing the parent's selectedIndex property fixes it
1728 if ( name === "selected" && !jQuery.support.optSelected ) {
1729 var parent = elem.parentNode;
1730 if ( parent ) {
1731 parent.selectedIndex;
1733 // Make sure that it also works with optgroups, see #5701
1734 if ( parent.parentNode ) {
1735 parent.parentNode.selectedIndex;
1740 // If applicable, access the attribute via the DOM 0 way
1741 // 'in' checks fail in Blackberry 4.7 #6931
1742 if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) {
1743 if ( set ) {
1744 // We can't allow the type property to be changed (since it causes problems in IE)
1745 if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
1746 jQuery.error( "type property can't be changed" );
1749 if ( value === null ) {
1750 if ( elem.nodeType === 1 ) {
1751 elem.removeAttribute( name );
1754 } else {
1755 elem[ name ] = value;
1759 // browsers index elements by id/name on forms, give priority to attributes.
1760 if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
1761 return elem.getAttributeNode( name ).nodeValue;
1764 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
1765 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
1766 if ( name === "tabIndex" ) {
1767 var attributeNode = elem.getAttributeNode( "tabIndex" );
1769 return attributeNode && attributeNode.specified ?
1770 attributeNode.value :
1771 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
1773 undefined;
1776 return elem[ name ];
1779 if ( !jQuery.support.style && notxml && name === "style" ) {
1780 if ( set ) {
1781 elem.style.cssText = "" + value;
1784 return elem.style.cssText;
1787 if ( set ) {
1788 // convert the value to a string (all browsers do this but IE) see #1070
1789 elem.setAttribute( name, "" + value );
1792 // Ensure that missing attributes return undefined
1793 // Blackberry 4.7 returns "" from getAttribute #6938
1794 if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) {
1795 return undefined;
1798 var attr = !jQuery.support.hrefNormalized && notxml && special ?
1799 // Some attributes require a special call on IE
1800 elem.getAttribute( name, 2 ) :
1801 elem.getAttribute( name );
1803 // Non-existent attributes return null, we normalize to undefined
1804 return attr === null ? undefined : attr;
1811 var rnamespaces = /\.(.*)$/,
1812 rformElems = /^(?:textarea|input|select)$/i,
1813 rperiod = /\./g,
1814 rspace = / /g,
1815 rescape = /[^\w\s.|`]/g,
1816 fcleanup = function( nm ) {
1817 return nm.replace(rescape, "\\$&");
1819 focusCounts = { focusin: 0, focusout: 0 };
1822 * A number of helper functions used for managing events.
1823 * Many of the ideas behind this code originated from
1824 * Dean Edwards' addEvent library.
1826 jQuery.event = {
1828 // Bind an event to an element
1829 // Original by Dean Edwards
1830 add: function( elem, types, handler, data ) {
1831 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
1832 return;
1835 // For whatever reason, IE has trouble passing the window object
1836 // around, causing it to be cloned in the process
1837 if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
1838 elem = window;
1841 if ( handler === false ) {
1842 handler = returnFalse;
1843 } else if ( !handler ) {
1844 // Fixes bug #7229. Fix recommended by jdalton
1845 return;
1848 var handleObjIn, handleObj;
1850 if ( handler.handler ) {
1851 handleObjIn = handler;
1852 handler = handleObjIn.handler;
1855 // Make sure that the function being executed has a unique ID
1856 if ( !handler.guid ) {
1857 handler.guid = jQuery.guid++;
1860 // Init the element's event structure
1861 var elemData = jQuery.data( elem );
1863 // If no elemData is found then we must be trying to bind to one of the
1864 // banned noData elements
1865 if ( !elemData ) {
1866 return;
1869 // Use a key less likely to result in collisions for plain JS objects.
1870 // Fixes bug #7150.
1871 var eventKey = elem.nodeType ? "events" : "__events__",
1872 events = elemData[ eventKey ],
1873 eventHandle = elemData.handle;
1875 if ( typeof events === "function" ) {
1876 // On plain objects events is a fn that holds the the data
1877 // which prevents this data from being JSON serialized
1878 // the function does not need to be called, it just contains the data
1879 eventHandle = events.handle;
1880 events = events.events;
1882 } else if ( !events ) {
1883 if ( !elem.nodeType ) {
1884 // On plain objects, create a fn that acts as the holder
1885 // of the values to avoid JSON serialization of event data
1886 elemData[ eventKey ] = elemData = function(){};
1889 elemData.events = events = {};
1892 if ( !eventHandle ) {
1893 elemData.handle = eventHandle = function() {
1894 // Handle the second event of a trigger and when
1895 // an event is called after a page has unloaded
1896 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
1897 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
1898 undefined;
1902 // Add elem as a property of the handle function
1903 // This is to prevent a memory leak with non-native events in IE.
1904 eventHandle.elem = elem;
1906 // Handle multiple events separated by a space
1907 // jQuery(...).bind("mouseover mouseout", fn);
1908 types = types.split(" ");
1910 var type, i = 0, namespaces;
1912 while ( (type = types[ i++ ]) ) {
1913 handleObj = handleObjIn ?
1914 jQuery.extend({}, handleObjIn) :
1915 { handler: handler, data: data };
1917 // Namespaced event handlers
1918 if ( type.indexOf(".") > -1 ) {
1919 namespaces = type.split(".");
1920 type = namespaces.shift();
1921 handleObj.namespace = namespaces.slice(0).sort().join(".");
1923 } else {
1924 namespaces = [];
1925 handleObj.namespace = "";
1928 handleObj.type = type;
1929 if ( !handleObj.guid ) {
1930 handleObj.guid = handler.guid;
1933 // Get the current list of functions bound to this event
1934 var handlers = events[ type ],
1935 special = jQuery.event.special[ type ] || {};
1937 // Init the event handler queue
1938 if ( !handlers ) {
1939 handlers = events[ type ] = [];
1941 // Check for a special event handler
1942 // Only use addEventListener/attachEvent if the special
1943 // events handler returns false
1944 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
1945 // Bind the global event handler to the element
1946 if ( elem.addEventListener ) {
1947 elem.addEventListener( type, eventHandle, false );
1949 } else if ( elem.attachEvent ) {
1950 elem.attachEvent( "on" + type, eventHandle );
1955 if ( special.add ) {
1956 special.add.call( elem, handleObj );
1958 if ( !handleObj.handler.guid ) {
1959 handleObj.handler.guid = handler.guid;
1963 // Add the function to the element's handler list
1964 handlers.push( handleObj );
1966 // Keep track of which events have been used, for global triggering
1967 jQuery.event.global[ type ] = true;
1970 // Nullify elem to prevent memory leaks in IE
1971 elem = null;
1974 global: {},
1976 // Detach an event or set of events from an element
1977 remove: function( elem, types, handler, pos ) {
1978 // don't do events on text and comment nodes
1979 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
1980 return;
1983 if ( handler === false ) {
1984 handler = returnFalse;
1987 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
1988 eventKey = elem.nodeType ? "events" : "__events__",
1989 elemData = jQuery.data( elem ),
1990 events = elemData && elemData[ eventKey ];
1992 if ( !elemData || !events ) {
1993 return;
1996 if ( typeof events === "function" ) {
1997 elemData = events;
1998 events = events.events;
2001 // types is actually an event object here
2002 if ( types && types.type ) {
2003 handler = types.handler;
2004 types = types.type;
2007 // Unbind all events for the element
2008 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
2009 types = types || "";
2011 for ( type in events ) {
2012 jQuery.event.remove( elem, type + types );
2015 return;
2018 // Handle multiple events separated by a space
2019 // jQuery(...).unbind("mouseover mouseout", fn);
2020 types = types.split(" ");
2022 while ( (type = types[ i++ ]) ) {
2023 origType = type;
2024 handleObj = null;
2025 all = type.indexOf(".") < 0;
2026 namespaces = [];
2028 if ( !all ) {
2029 // Namespaced event handlers
2030 namespaces = type.split(".");
2031 type = namespaces.shift();
2033 namespace = new RegExp("(^|\\.)" +
2034 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
2037 eventType = events[ type ];
2039 if ( !eventType ) {
2040 continue;
2043 if ( !handler ) {
2044 for ( j = 0; j < eventType.length; j++ ) {
2045 handleObj = eventType[ j ];
2047 if ( all || namespace.test( handleObj.namespace ) ) {
2048 jQuery.event.remove( elem, origType, handleObj.handler, j );
2049 eventType.splice( j--, 1 );
2053 continue;
2056 special = jQuery.event.special[ type ] || {};
2058 for ( j = pos || 0; j < eventType.length; j++ ) {
2059 handleObj = eventType[ j ];
2061 if ( handler.guid === handleObj.guid ) {
2062 // remove the given handler for the given type
2063 if ( all || namespace.test( handleObj.namespace ) ) {
2064 if ( pos == null ) {
2065 eventType.splice( j--, 1 );
2068 if ( special.remove ) {
2069 special.remove.call( elem, handleObj );
2073 if ( pos != null ) {
2074 break;
2079 // remove generic event handler if no more handlers exist
2080 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
2081 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
2082 jQuery.removeEvent( elem, type, elemData.handle );
2085 ret = null;
2086 delete events[ type ];
2090 // Remove the expando if it's no longer used
2091 if ( jQuery.isEmptyObject( events ) ) {
2092 var handle = elemData.handle;
2093 if ( handle ) {
2094 handle.elem = null;
2097 delete elemData.events;
2098 delete elemData.handle;
2100 if ( typeof elemData === "function" ) {
2101 jQuery.removeData( elem, eventKey );
2103 } else if ( jQuery.isEmptyObject( elemData ) ) {
2104 jQuery.removeData( elem );
2109 // bubbling is internal
2110 trigger: function( event, data, elem /*, bubbling */ ) {
2111 // Event object or event type
2112 var type = event.type || event,
2113 bubbling = arguments[3];
2115 if ( !bubbling ) {
2116 event = typeof event === "object" ?
2117 // jQuery.Event object
2118 event[ jQuery.expando ] ? event :
2119 // Object literal
2120 jQuery.extend( jQuery.Event(type), event ) :
2121 // Just the event type (string)
2122 jQuery.Event(type);
2124 if ( type.indexOf("!") >= 0 ) {
2125 event.type = type = type.slice(0, -1);
2126 event.exclusive = true;
2129 // Handle a global trigger
2130 if ( !elem ) {
2131 // Don't bubble custom events when global (to avoid too much overhead)
2132 event.stopPropagation();
2134 // Only trigger if we've ever bound an event for it
2135 if ( jQuery.event.global[ type ] ) {
2136 jQuery.each( jQuery.cache, function() {
2137 if ( this.events && this.events[type] ) {
2138 jQuery.event.trigger( event, data, this.handle.elem );
2144 // Handle triggering a single element
2146 // don't do events on text and comment nodes
2147 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
2148 return undefined;
2151 // Clean up in case it is reused
2152 event.result = undefined;
2153 event.target = elem;
2155 // Clone the incoming data, if any
2156 data = jQuery.makeArray( data );
2157 data.unshift( event );
2160 event.currentTarget = elem;
2162 // Trigger the event, it is assumed that "handle" is a function
2163 var handle = elem.nodeType ?
2164 jQuery.data( elem, "handle" ) :
2165 (jQuery.data( elem, "__events__" ) || {}).handle;
2167 if ( handle ) {
2168 handle.apply( elem, data );
2171 var parent = elem.parentNode || elem.ownerDocument;
2173 // Trigger an inline bound script
2174 try {
2175 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
2176 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
2177 event.result = false;
2178 event.preventDefault();
2182 // prevent IE from throwing an error for some elements with some event types, see #3533
2183 } catch (inlineError) {}
2185 if ( !event.isPropagationStopped() && parent ) {
2186 jQuery.event.trigger( event, data, parent, true );
2188 } else if ( !event.isDefaultPrevented() ) {
2189 var old,
2190 target = event.target,
2191 targetType = type.replace( rnamespaces, "" ),
2192 isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
2193 special = jQuery.event.special[ targetType ] || {};
2195 if ( (!special._default || special._default.call( elem, event ) === false) &&
2196 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
2198 try {
2199 if ( target[ targetType ] ) {
2200 // Make sure that we don't accidentally re-trigger the onFOO events
2201 old = target[ "on" + targetType ];
2203 if ( old ) {
2204 target[ "on" + targetType ] = null;
2207 jQuery.event.triggered = true;
2208 target[ targetType ]();
2211 // prevent IE from throwing an error for some elements with some event types, see #3533
2212 } catch (triggerError) {}
2214 if ( old ) {
2215 target[ "on" + targetType ] = old;
2218 jQuery.event.triggered = false;
2223 handle: function( event ) {
2224 var all, handlers, namespaces, namespace_re, events,
2225 namespace_sort = [],
2226 args = jQuery.makeArray( arguments );
2228 event = args[0] = jQuery.event.fix( event || window.event );
2229 event.currentTarget = this;
2231 // Namespaced event handlers
2232 all = event.type.indexOf(".") < 0 && !event.exclusive;
2234 if ( !all ) {
2235 namespaces = event.type.split(".");
2236 event.type = namespaces.shift();
2237 namespace_sort = namespaces.slice(0).sort();
2238 namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
2241 event.namespace = event.namespace || namespace_sort.join(".");
2243 events = jQuery.data(this, this.nodeType ? "events" : "__events__");
2245 if ( typeof events === "function" ) {
2246 events = events.events;
2249 handlers = (events || {})[ event.type ];
2251 if ( events && handlers ) {
2252 // Clone the handlers to prevent manipulation
2253 handlers = handlers.slice(0);
2255 for ( var j = 0, l = handlers.length; j < l; j++ ) {
2256 var handleObj = handlers[ j ];
2258 // Filter the functions by class
2259 if ( all || namespace_re.test( handleObj.namespace ) ) {
2260 // Pass in a reference to the handler function itself
2261 // So that we can later remove it
2262 event.handler = handleObj.handler;
2263 event.data = handleObj.data;
2264 event.handleObj = handleObj;
2266 var ret = handleObj.handler.apply( this, args );
2268 if ( ret !== undefined ) {
2269 event.result = ret;
2270 if ( ret === false ) {
2271 event.preventDefault();
2272 event.stopPropagation();
2276 if ( event.isImmediatePropagationStopped() ) {
2277 break;
2283 return event.result;
2286 props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
2288 fix: function( event ) {
2289 if ( event[ jQuery.expando ] ) {
2290 return event;
2293 // store a copy of the original event object
2294 // and "clone" to set read-only properties
2295 var originalEvent = event;
2296 event = jQuery.Event( originalEvent );
2298 for ( var i = this.props.length, prop; i; ) {
2299 prop = this.props[ --i ];
2300 event[ prop ] = originalEvent[ prop ];
2303 // Fix target property, if necessary
2304 if ( !event.target ) {
2305 // Fixes #1925 where srcElement might not be defined either
2306 event.target = event.srcElement || document;
2309 // check if target is a textnode (safari)
2310 if ( event.target.nodeType === 3 ) {
2311 event.target = event.target.parentNode;
2314 // Add relatedTarget, if necessary
2315 if ( !event.relatedTarget && event.fromElement ) {
2316 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
2319 // Calculate pageX/Y if missing and clientX/Y available
2320 if ( event.pageX == null && event.clientX != null ) {
2321 var doc = document.documentElement,
2322 body = document.body;
2324 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
2325 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
2328 // Add which for key events
2329 if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
2330 event.which = event.charCode != null ? event.charCode : event.keyCode;
2333 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
2334 if ( !event.metaKey && event.ctrlKey ) {
2335 event.metaKey = event.ctrlKey;
2338 // Add which for click: 1 === left; 2 === middle; 3 === right
2339 // Note: button is not normalized, so don't use it
2340 if ( !event.which && event.button !== undefined ) {
2341 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2344 return event;
2347 // Deprecated, use jQuery.guid instead
2348 guid: 1E8,
2350 // Deprecated, use jQuery.proxy instead
2351 proxy: jQuery.proxy,
2353 special: {
2354 ready: {
2355 // Make sure the ready event is setup
2356 setup: jQuery.bindReady,
2357 teardown: jQuery.noop
2360 live: {
2361 add: function( handleObj ) {
2362 jQuery.event.add( this,
2363 liveConvert( handleObj.origType, handleObj.selector ),
2364 jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
2367 remove: function( handleObj ) {
2368 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
2372 beforeunload: {
2373 setup: function( data, namespaces, eventHandle ) {
2374 // We only want to do this special case on windows
2375 if ( jQuery.isWindow( this ) ) {
2376 this.onbeforeunload = eventHandle;
2380 teardown: function( namespaces, eventHandle ) {
2381 if ( this.onbeforeunload === eventHandle ) {
2382 this.onbeforeunload = null;
2389 jQuery.removeEvent = document.removeEventListener ?
2390 function( elem, type, handle ) {
2391 if ( elem.removeEventListener ) {
2392 elem.removeEventListener( type, handle, false );
2394 } :
2395 function( elem, type, handle ) {
2396 if ( elem.detachEvent ) {
2397 elem.detachEvent( "on" + type, handle );
2401 jQuery.Event = function( src ) {
2402 // Allow instantiation without the 'new' keyword
2403 if ( !this.preventDefault ) {
2404 return new jQuery.Event( src );
2407 // Event object
2408 if ( src && src.type ) {
2409 this.originalEvent = src;
2410 this.type = src.type;
2411 // Event type
2412 } else {
2413 this.type = src;
2416 // timeStamp is buggy for some events on Firefox(#3843)
2417 // So we won't rely on the native value
2418 this.timeStamp = jQuery.now();
2420 // Mark it as fixed
2421 this[ jQuery.expando ] = true;
2424 function returnFalse() {
2425 return false;
2427 function returnTrue() {
2428 return true;
2431 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
2432 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
2433 jQuery.Event.prototype = {
2434 preventDefault: function() {
2435 this.isDefaultPrevented = returnTrue;
2437 var e = this.originalEvent;
2438 if ( !e ) {
2439 return;
2442 // if preventDefault exists run it on the original event
2443 if ( e.preventDefault ) {
2444 e.preventDefault();
2446 // otherwise set the returnValue property of the original event to false (IE)
2447 } else {
2448 e.returnValue = false;
2451 stopPropagation: function() {
2452 this.isPropagationStopped = returnTrue;
2454 var e = this.originalEvent;
2455 if ( !e ) {
2456 return;
2458 // if stopPropagation exists run it on the original event
2459 if ( e.stopPropagation ) {
2460 e.stopPropagation();
2462 // otherwise set the cancelBubble property of the original event to true (IE)
2463 e.cancelBubble = true;
2465 stopImmediatePropagation: function() {
2466 this.isImmediatePropagationStopped = returnTrue;
2467 this.stopPropagation();
2469 isDefaultPrevented: returnFalse,
2470 isPropagationStopped: returnFalse,
2471 isImmediatePropagationStopped: returnFalse
2474 // Checks if an event happened on an element within another element
2475 // Used in jQuery.event.special.mouseenter and mouseleave handlers
2476 var withinElement = function( event ) {
2477 // Check if mouse(over|out) are still within the same parent element
2478 var parent = event.relatedTarget;
2480 // Firefox sometimes assigns relatedTarget a XUL element
2481 // which we cannot access the parentNode property of
2482 try {
2483 // Traverse up the tree
2484 while ( parent && parent !== this ) {
2485 parent = parent.parentNode;
2488 if ( parent !== this ) {
2489 // set the correct event type
2490 event.type = event.data;
2492 // handle event if we actually just moused on to a non sub-element
2493 jQuery.event.handle.apply( this, arguments );
2496 // assuming we've left the element since we most likely mousedover a xul element
2497 } catch(e) { }
2500 // In case of event delegation, we only need to rename the event.type,
2501 // liveHandler will take care of the rest.
2502 delegate = function( event ) {
2503 event.type = event.data;
2504 jQuery.event.handle.apply( this, arguments );
2507 // Create mouseenter and mouseleave events
2508 jQuery.each({
2509 mouseenter: "mouseover",
2510 mouseleave: "mouseout"
2511 }, function( orig, fix ) {
2512 jQuery.event.special[ orig ] = {
2513 setup: function( data ) {
2514 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
2516 teardown: function( data ) {
2517 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
2522 // submit delegation
2523 if ( !jQuery.support.submitBubbles ) {
2525 jQuery.event.special.submit = {
2526 setup: function( data, namespaces ) {
2527 if ( this.nodeName.toLowerCase() !== "form" ) {
2528 jQuery.event.add(this, "click.specialSubmit", function( e ) {
2529 var elem = e.target,
2530 type = elem.type;
2532 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
2533 e.liveFired = undefined;
2534 return trigger( "submit", this, arguments );
2538 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
2539 var elem = e.target,
2540 type = elem.type;
2542 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
2543 e.liveFired = undefined;
2544 return trigger( "submit", this, arguments );
2548 } else {
2549 return false;
2553 teardown: function( namespaces ) {
2554 jQuery.event.remove( this, ".specialSubmit" );
2560 // change delegation, happens here so we have bind.
2561 if ( !jQuery.support.changeBubbles ) {
2563 var changeFilters,
2565 getVal = function( elem ) {
2566 var type = elem.type, val = elem.value;
2568 if ( type === "radio" || type === "checkbox" ) {
2569 val = elem.checked;
2571 } else if ( type === "select-multiple" ) {
2572 val = elem.selectedIndex > -1 ?
2573 jQuery.map( elem.options, function( elem ) {
2574 return elem.selected;
2575 }).join("-") :
2578 } else if ( elem.nodeName.toLowerCase() === "select" ) {
2579 val = elem.selectedIndex;
2582 return val;
2585 testChange = function testChange( e ) {
2586 var elem = e.target, data, val;
2588 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
2589 return;
2592 data = jQuery.data( elem, "_change_data" );
2593 val = getVal(elem);
2595 // the current data will be also retrieved by beforeactivate
2596 if ( e.type !== "focusout" || elem.type !== "radio" ) {
2597 jQuery.data( elem, "_change_data", val );
2600 if ( data === undefined || val === data ) {
2601 return;
2604 if ( data != null || val ) {
2605 e.type = "change";
2606 e.liveFired = undefined;
2607 return jQuery.event.trigger( e, arguments[1], elem );
2611 jQuery.event.special.change = {
2612 filters: {
2613 focusout: testChange,
2615 beforedeactivate: testChange,
2617 click: function( e ) {
2618 var elem = e.target, type = elem.type;
2620 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
2621 return testChange.call( this, e );
2625 // Change has to be called before submit
2626 // Keydown will be called before keypress, which is used in submit-event delegation
2627 keydown: function( e ) {
2628 var elem = e.target, type = elem.type;
2630 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
2631 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
2632 type === "select-multiple" ) {
2633 return testChange.call( this, e );
2637 // Beforeactivate happens also before the previous element is blurred
2638 // with this event you can't trigger a change event, but you can store
2639 // information
2640 beforeactivate: function( e ) {
2641 var elem = e.target;
2642 jQuery.data( elem, "_change_data", getVal(elem) );
2646 setup: function( data, namespaces ) {
2647 if ( this.type === "file" ) {
2648 return false;
2651 for ( var type in changeFilters ) {
2652 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
2655 return rformElems.test( this.nodeName );
2658 teardown: function( namespaces ) {
2659 jQuery.event.remove( this, ".specialChange" );
2661 return rformElems.test( this.nodeName );
2665 changeFilters = jQuery.event.special.change.filters;
2667 // Handle when the input is .focus()'d
2668 changeFilters.focus = changeFilters.beforeactivate;
2671 function trigger( type, elem, args ) {
2672 args[0].type = type;
2673 return jQuery.event.handle.apply( elem, args );
2676 // Create "bubbling" focus and blur events
2677 if ( document.addEventListener ) {
2678 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
2679 jQuery.event.special[ fix ] = {
2680 setup: function() {
2681 if ( focusCounts[fix]++ === 0 ) {
2682 document.addEventListener( orig, handler, true );
2685 teardown: function() {
2686 if ( --focusCounts[fix] === 0 ) {
2687 document.removeEventListener( orig, handler, true );
2692 function handler( e ) {
2693 e = jQuery.event.fix( e );
2694 e.type = fix;
2695 return jQuery.event.trigger( e, null, e.target );
2700 jQuery.each(["bind", "one"], function( i, name ) {
2701 jQuery.fn[ name ] = function( type, data, fn ) {
2702 // Handle object literals
2703 if ( typeof type === "object" ) {
2704 for ( var key in type ) {
2705 this[ name ](key, data, type[key], fn);
2707 return this;
2710 if ( jQuery.isFunction( data ) || data === false ) {
2711 fn = data;
2712 data = undefined;
2715 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
2716 jQuery( this ).unbind( event, handler );
2717 return fn.apply( this, arguments );
2718 }) : fn;
2720 if ( type === "unload" && name !== "one" ) {
2721 this.one( type, data, fn );
2723 } else {
2724 for ( var i = 0, l = this.length; i < l; i++ ) {
2725 jQuery.event.add( this[i], type, handler, data );
2729 return this;
2733 jQuery.fn.extend({
2734 unbind: function( type, fn ) {
2735 // Handle object literals
2736 if ( typeof type === "object" && !type.preventDefault ) {
2737 for ( var key in type ) {
2738 this.unbind(key, type[key]);
2741 } else {
2742 for ( var i = 0, l = this.length; i < l; i++ ) {
2743 jQuery.event.remove( this[i], type, fn );
2747 return this;
2750 delegate: function( selector, types, data, fn ) {
2751 return this.live( types, data, fn, selector );
2754 undelegate: function( selector, types, fn ) {
2755 if ( arguments.length === 0 ) {
2756 return this.unbind( "live" );
2758 } else {
2759 return this.die( types, null, fn, selector );
2763 trigger: function( type, data ) {
2764 return this.each(function() {
2765 jQuery.event.trigger( type, data, this );
2769 triggerHandler: function( type, data ) {
2770 if ( this[0] ) {
2771 var event = jQuery.Event( type );
2772 event.preventDefault();
2773 event.stopPropagation();
2774 jQuery.event.trigger( event, data, this[0] );
2775 return event.result;
2779 toggle: function( fn ) {
2780 // Save reference to arguments for access in closure
2781 var args = arguments,
2782 i = 1;
2784 // link all the functions, so any of them can unbind this click handler
2785 while ( i < args.length ) {
2786 jQuery.proxy( fn, args[ i++ ] );
2789 return this.click( jQuery.proxy( fn, function( event ) {
2790 // Figure out which function to execute
2791 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
2792 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
2794 // Make sure that clicks stop
2795 event.preventDefault();
2797 // and execute the function
2798 return args[ lastToggle ].apply( this, arguments ) || false;
2799 }));
2802 hover: function( fnOver, fnOut ) {
2803 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
2807 var liveMap = {
2808 focus: "focusin",
2809 blur: "focusout",
2810 mouseenter: "mouseover",
2811 mouseleave: "mouseout"
2814 jQuery.each(["live", "die"], function( i, name ) {
2815 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
2816 var type, i = 0, match, namespaces, preType,
2817 selector = origSelector || this.selector,
2818 context = origSelector ? this : jQuery( this.context );
2820 if ( typeof types === "object" && !types.preventDefault ) {
2821 for ( var key in types ) {
2822 context[ name ]( key, data, types[key], selector );
2825 return this;
2828 if ( jQuery.isFunction( data ) ) {
2829 fn = data;
2830 data = undefined;
2833 types = (types || "").split(" ");
2835 while ( (type = types[ i++ ]) != null ) {
2836 match = rnamespaces.exec( type );
2837 namespaces = "";
2839 if ( match ) {
2840 namespaces = match[0];
2841 type = type.replace( rnamespaces, "" );
2844 if ( type === "hover" ) {
2845 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
2846 continue;
2849 preType = type;
2851 if ( type === "focus" || type === "blur" ) {
2852 types.push( liveMap[ type ] + namespaces );
2853 type = type + namespaces;
2855 } else {
2856 type = (liveMap[ type ] || type) + namespaces;
2859 if ( name === "live" ) {
2860 // bind live handler
2861 for ( var j = 0, l = context.length; j < l; j++ ) {
2862 jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
2863 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
2866 } else {
2867 // unbind live handler
2868 context.unbind( "live." + liveConvert( type, selector ), fn );
2872 return this;
2876 function liveHandler( event ) {
2877 var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
2878 elems = [],
2879 selectors = [],
2880 events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
2882 if ( typeof events === "function" ) {
2883 events = events.events;
2886 // Make sure we avoid non-left-click bubbling in Firefox (#3861)
2887 if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
2888 return;
2891 if ( event.namespace ) {
2892 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
2895 event.liveFired = this;
2897 var live = events.live.slice(0);
2899 for ( j = 0; j < live.length; j++ ) {
2900 handleObj = live[j];
2902 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
2903 selectors.push( handleObj.selector );
2905 } else {
2906 live.splice( j--, 1 );
2910 match = jQuery( event.target ).closest( selectors, event.currentTarget );
2912 for ( i = 0, l = match.length; i < l; i++ ) {
2913 close = match[i];
2915 for ( j = 0; j < live.length; j++ ) {
2916 handleObj = live[j];
2918 if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
2919 elem = close.elem;
2920 related = null;
2922 // Those two events require additional checking
2923 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
2924 event.type = handleObj.preType;
2925 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
2928 if ( !related || related !== elem ) {
2929 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
2935 for ( i = 0, l = elems.length; i < l; i++ ) {
2936 match = elems[i];
2938 if ( maxLevel && match.level > maxLevel ) {
2939 break;
2942 event.currentTarget = match.elem;
2943 event.data = match.handleObj.data;
2944 event.handleObj = match.handleObj;
2946 ret = match.handleObj.origHandler.apply( match.elem, arguments );
2948 if ( ret === false || event.isPropagationStopped() ) {
2949 maxLevel = match.level;
2951 if ( ret === false ) {
2952 stop = false;
2954 if ( event.isImmediatePropagationStopped() ) {
2955 break;
2960 return stop;
2963 function liveConvert( type, selector ) {
2964 return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
2967 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
2968 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
2969 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
2971 // Handle event binding
2972 jQuery.fn[ name ] = function( data, fn ) {
2973 if ( fn == null ) {
2974 fn = data;
2975 data = null;
2978 return arguments.length > 0 ?
2979 this.bind( name, data, fn ) :
2980 this.trigger( name );
2983 if ( jQuery.attrFn ) {
2984 jQuery.attrFn[ name ] = true;
2988 // Prevent memory leaks in IE
2989 // Window isn't included so as not to unbind existing unload events
2990 // More info:
2991 // - http://isaacschlueter.com/2006/10/msie-memory-leaks/
2992 if ( window.attachEvent && !window.addEventListener ) {
2993 jQuery(window).bind("unload", function() {
2994 for ( var id in jQuery.cache ) {
2995 if ( jQuery.cache[ id ].handle ) {
2996 // Try/Catch is to handle iframes being unloaded, see #4280
2997 try {
2998 jQuery.event.remove( jQuery.cache[ id ].handle.elem );
2999 } catch(e) {}
3007 * Sizzle CSS Selector Engine - v1.0
3008 * Copyright 2009, The Dojo Foundation
3009 * Released under the MIT, BSD, and GPL Licenses.
3010 * More information: http://sizzlejs.com/
3012 (function(){
3014 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
3015 done = 0,
3016 toString = Object.prototype.toString,
3017 hasDuplicate = false,
3018 baseHasDuplicate = true;
3020 // Here we check if the JavaScript engine is using some sort of
3021 // optimization where it does not always call our comparision
3022 // function. If that is the case, discard the hasDuplicate value.
3023 // Thus far that includes Google Chrome.
3024 [0, 0].sort(function() {
3025 baseHasDuplicate = false;
3026 return 0;
3029 var Sizzle = function( selector, context, results, seed ) {
3030 results = results || [];
3031 context = context || document;
3033 var origContext = context;
3035 if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
3036 return [];
3039 if ( !selector || typeof selector !== "string" ) {
3040 return results;
3043 var m, set, checkSet, extra, ret, cur, pop, i,
3044 prune = true,
3045 contextXML = Sizzle.isXML( context ),
3046 parts = [],
3047 soFar = selector;
3049 // Reset the position of the chunker regexp (start from head)
3050 do {
3051 chunker.exec( "" );
3052 m = chunker.exec( soFar );
3054 if ( m ) {
3055 soFar = m[3];
3057 parts.push( m[1] );
3059 if ( m[2] ) {
3060 extra = m[3];
3061 break;
3064 } while ( m );
3066 if ( parts.length > 1 && origPOS.exec( selector ) ) {
3068 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
3069 set = posProcess( parts[0] + parts[1], context );
3071 } else {
3072 set = Expr.relative[ parts[0] ] ?
3073 [ context ] :
3074 Sizzle( parts.shift(), context );
3076 while ( parts.length ) {
3077 selector = parts.shift();
3079 if ( Expr.relative[ selector ] ) {
3080 selector += parts.shift();
3083 set = posProcess( selector, set );
3087 } else {
3088 // Take a shortcut and set the context if the root selector is an ID
3089 // (but not if it'll be faster if the inner selector is an ID)
3090 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
3091 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
3093 ret = Sizzle.find( parts.shift(), context, contextXML );
3094 context = ret.expr ?
3095 Sizzle.filter( ret.expr, ret.set )[0] :
3096 ret.set[0];
3099 if ( context ) {
3100 ret = seed ?
3101 { expr: parts.pop(), set: makeArray(seed) } :
3102 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
3104 set = ret.expr ?
3105 Sizzle.filter( ret.expr, ret.set ) :
3106 ret.set;
3108 if ( parts.length > 0 ) {
3109 checkSet = makeArray( set );
3111 } else {
3112 prune = false;
3115 while ( parts.length ) {
3116 cur = parts.pop();
3117 pop = cur;
3119 if ( !Expr.relative[ cur ] ) {
3120 cur = "";
3121 } else {
3122 pop = parts.pop();
3125 if ( pop == null ) {
3126 pop = context;
3129 Expr.relative[ cur ]( checkSet, pop, contextXML );
3132 } else {
3133 checkSet = parts = [];
3137 if ( !checkSet ) {
3138 checkSet = set;
3141 if ( !checkSet ) {
3142 Sizzle.error( cur || selector );
3145 if ( toString.call(checkSet) === "[object Array]" ) {
3146 if ( !prune ) {
3147 results.push.apply( results, checkSet );
3149 } else if ( context && context.nodeType === 1 ) {
3150 for ( i = 0; checkSet[i] != null; i++ ) {
3151 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
3152 results.push( set[i] );
3156 } else {
3157 for ( i = 0; checkSet[i] != null; i++ ) {
3158 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
3159 results.push( set[i] );
3164 } else {
3165 makeArray( checkSet, results );
3168 if ( extra ) {
3169 Sizzle( extra, origContext, results, seed );
3170 Sizzle.uniqueSort( results );
3173 return results;
3176 Sizzle.uniqueSort = function( results ) {
3177 if ( sortOrder ) {
3178 hasDuplicate = baseHasDuplicate;
3179 results.sort( sortOrder );
3181 if ( hasDuplicate ) {
3182 for ( var i = 1; i < results.length; i++ ) {
3183 if ( results[i] === results[ i - 1 ] ) {
3184 results.splice( i--, 1 );
3190 return results;
3193 Sizzle.matches = function( expr, set ) {
3194 return Sizzle( expr, null, null, set );
3197 Sizzle.matchesSelector = function( node, expr ) {
3198 return Sizzle( expr, null, null, [node] ).length > 0;
3201 Sizzle.find = function( expr, context, isXML ) {
3202 var set;
3204 if ( !expr ) {
3205 return [];
3208 for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
3209 var match,
3210 type = Expr.order[i];
3212 if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
3213 var left = match[1];
3214 match.splice( 1, 1 );
3216 if ( left.substr( left.length - 1 ) !== "\\" ) {
3217 match[1] = (match[1] || "").replace(/\\/g, "");
3218 set = Expr.find[ type ]( match, context, isXML );
3220 if ( set != null ) {
3221 expr = expr.replace( Expr.match[ type ], "" );
3222 break;
3228 if ( !set ) {
3229 set = context.getElementsByTagName( "*" );
3232 return { set: set, expr: expr };
3235 Sizzle.filter = function( expr, set, inplace, not ) {
3236 var match, anyFound,
3237 old = expr,
3238 result = [],
3239 curLoop = set,
3240 isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
3242 while ( expr && set.length ) {
3243 for ( var type in Expr.filter ) {
3244 if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
3245 var found, item,
3246 filter = Expr.filter[ type ],
3247 left = match[1];
3249 anyFound = false;
3251 match.splice(1,1);
3253 if ( left.substr( left.length - 1 ) === "\\" ) {
3254 continue;
3257 if ( curLoop === result ) {
3258 result = [];
3261 if ( Expr.preFilter[ type ] ) {
3262 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
3264 if ( !match ) {
3265 anyFound = found = true;
3267 } else if ( match === true ) {
3268 continue;
3272 if ( match ) {
3273 for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
3274 if ( item ) {
3275 found = filter( item, match, i, curLoop );
3276 var pass = not ^ !!found;
3278 if ( inplace && found != null ) {
3279 if ( pass ) {
3280 anyFound = true;
3282 } else {
3283 curLoop[i] = false;
3286 } else if ( pass ) {
3287 result.push( item );
3288 anyFound = true;
3294 if ( found !== undefined ) {
3295 if ( !inplace ) {
3296 curLoop = result;
3299 expr = expr.replace( Expr.match[ type ], "" );
3301 if ( !anyFound ) {
3302 return [];
3305 break;
3310 // Improper expression
3311 if ( expr === old ) {
3312 if ( anyFound == null ) {
3313 Sizzle.error( expr );
3315 } else {
3316 break;
3320 old = expr;
3323 return curLoop;
3326 Sizzle.error = function( msg ) {
3327 throw "Syntax error, unrecognized expression: " + msg;
3330 var Expr = Sizzle.selectors = {
3331 order: [ "ID", "NAME", "TAG" ],
3333 match: {
3334 ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
3335 CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
3336 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
3337 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
3338 TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
3339 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,
3340 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
3341 PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
3344 leftMatch: {},
3346 attrMap: {
3347 "class": "className",
3348 "for": "htmlFor"
3351 attrHandle: {
3352 href: function( elem ) {
3353 return elem.getAttribute( "href" );
3357 relative: {
3358 "+": function(checkSet, part){
3359 var isPartStr = typeof part === "string",
3360 isTag = isPartStr && !/\W/.test( part ),
3361 isPartStrNotTag = isPartStr && !isTag;
3363 if ( isTag ) {
3364 part = part.toLowerCase();
3367 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
3368 if ( (elem = checkSet[i]) ) {
3369 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
3371 checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
3372 elem || false :
3373 elem === part;
3377 if ( isPartStrNotTag ) {
3378 Sizzle.filter( part, checkSet, true );
3382 ">": function( checkSet, part ) {
3383 var elem,
3384 isPartStr = typeof part === "string",
3385 i = 0,
3386 l = checkSet.length;
3388 if ( isPartStr && !/\W/.test( part ) ) {
3389 part = part.toLowerCase();
3391 for ( ; i < l; i++ ) {
3392 elem = checkSet[i];
3394 if ( elem ) {
3395 var parent = elem.parentNode;
3396 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
3400 } else {
3401 for ( ; i < l; i++ ) {
3402 elem = checkSet[i];
3404 if ( elem ) {
3405 checkSet[i] = isPartStr ?
3406 elem.parentNode :
3407 elem.parentNode === part;
3411 if ( isPartStr ) {
3412 Sizzle.filter( part, checkSet, true );
3417 "": function(checkSet, part, isXML){
3418 var nodeCheck,
3419 doneName = done++,
3420 checkFn = dirCheck;
3422 if ( typeof part === "string" && !/\W/.test(part) ) {
3423 part = part.toLowerCase();
3424 nodeCheck = part;
3425 checkFn = dirNodeCheck;
3428 checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
3431 "~": function( checkSet, part, isXML ) {
3432 var nodeCheck,
3433 doneName = done++,
3434 checkFn = dirCheck;
3436 if ( typeof part === "string" && !/\W/.test( part ) ) {
3437 part = part.toLowerCase();
3438 nodeCheck = part;
3439 checkFn = dirNodeCheck;
3442 checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
3446 find: {
3447 ID: function( match, context, isXML ) {
3448 if ( typeof context.getElementById !== "undefined" && !isXML ) {
3449 var m = context.getElementById(match[1]);
3450 // Check parentNode to catch when Blackberry 4.6 returns
3451 // nodes that are no longer in the document #6963
3452 return m && m.parentNode ? [m] : [];
3456 NAME: function( match, context ) {
3457 if ( typeof context.getElementsByName !== "undefined" ) {
3458 var ret = [],
3459 results = context.getElementsByName( match[1] );
3461 for ( var i = 0, l = results.length; i < l; i++ ) {
3462 if ( results[i].getAttribute("name") === match[1] ) {
3463 ret.push( results[i] );
3467 return ret.length === 0 ? null : ret;
3471 TAG: function( match, context ) {
3472 return context.getElementsByTagName( match[1] );
3475 preFilter: {
3476 CLASS: function( match, curLoop, inplace, result, not, isXML ) {
3477 match = " " + match[1].replace(/\\/g, "") + " ";
3479 if ( isXML ) {
3480 return match;
3483 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
3484 if ( elem ) {
3485 if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
3486 if ( !inplace ) {
3487 result.push( elem );
3490 } else if ( inplace ) {
3491 curLoop[i] = false;
3496 return false;
3499 ID: function( match ) {
3500 return match[1].replace(/\\/g, "");
3503 TAG: function( match, curLoop ) {
3504 return match[1].toLowerCase();
3507 CHILD: function( match ) {
3508 if ( match[1] === "nth" ) {
3509 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
3510 var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
3511 match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
3512 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
3514 // calculate the numbers (first)n+(last) including if they are negative
3515 match[2] = (test[1] + (test[2] || 1)) - 0;
3516 match[3] = test[3] - 0;
3519 // TODO: Move to normal caching system
3520 match[0] = done++;
3522 return match;
3525 ATTR: function( match, curLoop, inplace, result, not, isXML ) {
3526 var name = match[1].replace(/\\/g, "");
3528 if ( !isXML && Expr.attrMap[name] ) {
3529 match[1] = Expr.attrMap[name];
3532 if ( match[2] === "~=" ) {
3533 match[4] = " " + match[4] + " ";
3536 return match;
3539 PSEUDO: function( match, curLoop, inplace, result, not ) {
3540 if ( match[1] === "not" ) {
3541 // If we're dealing with a complex expression, or a simple one
3542 if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
3543 match[3] = Sizzle(match[3], null, null, curLoop);
3545 } else {
3546 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
3548 if ( !inplace ) {
3549 result.push.apply( result, ret );
3552 return false;
3555 } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
3556 return true;
3559 return match;
3562 POS: function( match ) {
3563 match.unshift( true );
3565 return match;
3569 filters: {
3570 enabled: function( elem ) {
3571 return elem.disabled === false && elem.type !== "hidden";
3574 disabled: function( elem ) {
3575 return elem.disabled === true;
3578 checked: function( elem ) {
3579 return elem.checked === true;
3582 selected: function( elem ) {
3583 // Accessing this property makes selected-by-default
3584 // options in Safari work properly
3585 elem.parentNode.selectedIndex;
3587 return elem.selected === true;
3590 parent: function( elem ) {
3591 return !!elem.firstChild;
3594 empty: function( elem ) {
3595 return !elem.firstChild;
3598 has: function( elem, i, match ) {
3599 return !!Sizzle( match[3], elem ).length;
3602 header: function( elem ) {
3603 return (/h\d/i).test( elem.nodeName );
3606 text: function( elem ) {
3607 return "text" === elem.type;
3609 radio: function( elem ) {
3610 return "radio" === elem.type;
3613 checkbox: function( elem ) {
3614 return "checkbox" === elem.type;
3617 file: function( elem ) {
3618 return "file" === elem.type;
3620 password: function( elem ) {
3621 return "password" === elem.type;
3624 submit: function( elem ) {
3625 return "submit" === elem.type;
3628 image: function( elem ) {
3629 return "image" === elem.type;
3632 reset: function( elem ) {
3633 return "reset" === elem.type;
3636 button: function( elem ) {
3637 return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
3640 input: function( elem ) {
3641 return (/input|select|textarea|button/i).test( elem.nodeName );
3644 setFilters: {
3645 first: function( elem, i ) {
3646 return i === 0;
3649 last: function( elem, i, match, array ) {
3650 return i === array.length - 1;
3653 even: function( elem, i ) {
3654 return i % 2 === 0;
3657 odd: function( elem, i ) {
3658 return i % 2 === 1;
3661 lt: function( elem, i, match ) {
3662 return i < match[3] - 0;
3665 gt: function( elem, i, match ) {
3666 return i > match[3] - 0;
3669 nth: function( elem, i, match ) {
3670 return match[3] - 0 === i;
3673 eq: function( elem, i, match ) {
3674 return match[3] - 0 === i;
3677 filter: {
3678 PSEUDO: function( elem, match, i, array ) {
3679 var name = match[1],
3680 filter = Expr.filters[ name ];
3682 if ( filter ) {
3683 return filter( elem, i, match, array );
3685 } else if ( name === "contains" ) {
3686 return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;
3688 } else if ( name === "not" ) {
3689 var not = match[3];
3691 for ( var j = 0, l = not.length; j < l; j++ ) {
3692 if ( not[j] === elem ) {
3693 return false;
3697 return true;
3699 } else {
3700 Sizzle.error( "Syntax error, unrecognized expression: " + name );
3704 CHILD: function( elem, match ) {
3705 var type = match[1],
3706 node = elem;
3708 switch ( type ) {
3709 case "only":
3710 case "first":
3711 while ( (node = node.previousSibling) ) {
3712 if ( node.nodeType === 1 ) {
3713 return false;
3717 if ( type === "first" ) {
3718 return true;
3721 node = elem;
3723 case "last":
3724 while ( (node = node.nextSibling) ) {
3725 if ( node.nodeType === 1 ) {
3726 return false;
3730 return true;
3732 case "nth":
3733 var first = match[2],
3734 last = match[3];
3736 if ( first === 1 && last === 0 ) {
3737 return true;
3740 var doneName = match[0],
3741 parent = elem.parentNode;
3743 if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
3744 var count = 0;
3746 for ( node = parent.firstChild; node; node = node.nextSibling ) {
3747 if ( node.nodeType === 1 ) {
3748 node.nodeIndex = ++count;
3752 parent.sizcache = doneName;
3755 var diff = elem.nodeIndex - last;
3757 if ( first === 0 ) {
3758 return diff === 0;
3760 } else {
3761 return ( diff % first === 0 && diff / first >= 0 );
3766 ID: function( elem, match ) {
3767 return elem.nodeType === 1 && elem.getAttribute("id") === match;
3770 TAG: function( elem, match ) {
3771 return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
3774 CLASS: function( elem, match ) {
3775 return (" " + (elem.className || elem.getAttribute("class")) + " ")
3776 .indexOf( match ) > -1;
3779 ATTR: function( elem, match ) {
3780 var name = match[1],
3781 result = Expr.attrHandle[ name ] ?
3782 Expr.attrHandle[ name ]( elem ) :
3783 elem[ name ] != null ?
3784 elem[ name ] :
3785 elem.getAttribute( name ),
3786 value = result + "",
3787 type = match[2],
3788 check = match[4];
3790 return result == null ?
3791 type === "!=" :
3792 type === "=" ?
3793 value === check :
3794 type === "*=" ?
3795 value.indexOf(check) >= 0 :
3796 type === "~=" ?
3797 (" " + value + " ").indexOf(check) >= 0 :
3798 !check ?
3799 value && result !== false :
3800 type === "!=" ?
3801 value !== check :
3802 type === "^=" ?
3803 value.indexOf(check) === 0 :
3804 type === "$=" ?
3805 value.substr(value.length - check.length) === check :
3806 type === "|=" ?
3807 value === check || value.substr(0, check.length + 1) === check + "-" :
3808 false;
3811 POS: function( elem, match, i, array ) {
3812 var name = match[2],
3813 filter = Expr.setFilters[ name ];
3815 if ( filter ) {
3816 return filter( elem, i, match, array );
3822 var origPOS = Expr.match.POS,
3823 fescape = function(all, num){
3824 return "\\" + (num - 0 + 1);
3827 for ( var type in Expr.match ) {
3828 Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
3829 Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
3832 var makeArray = function( array, results ) {
3833 array = Array.prototype.slice.call( array, 0 );
3835 if ( results ) {
3836 results.push.apply( results, array );
3837 return results;
3840 return array;
3843 // Perform a simple check to determine if the browser is capable of
3844 // converting a NodeList to an array using builtin methods.
3845 // Also verifies that the returned array holds DOM nodes
3846 // (which is not the case in the Blackberry browser)
3847 try {
3848 Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
3850 // Provide a fallback method if it does not work
3851 } catch( e ) {
3852 makeArray = function( array, results ) {
3853 var i = 0,
3854 ret = results || [];
3856 if ( toString.call(array) === "[object Array]" ) {
3857 Array.prototype.push.apply( ret, array );
3859 } else {
3860 if ( typeof array.length === "number" ) {
3861 for ( var l = array.length; i < l; i++ ) {
3862 ret.push( array[i] );
3865 } else {
3866 for ( ; array[i]; i++ ) {
3867 ret.push( array[i] );
3872 return ret;
3876 var sortOrder, siblingCheck;
3878 if ( document.documentElement.compareDocumentPosition ) {
3879 sortOrder = function( a, b ) {
3880 if ( a === b ) {
3881 hasDuplicate = true;
3882 return 0;
3885 if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
3886 return a.compareDocumentPosition ? -1 : 1;
3889 return a.compareDocumentPosition(b) & 4 ? -1 : 1;
3892 } else {
3893 sortOrder = function( a, b ) {
3894 var al, bl,
3895 ap = [],
3896 bp = [],
3897 aup = a.parentNode,
3898 bup = b.parentNode,
3899 cur = aup;
3901 // The nodes are identical, we can exit early
3902 if ( a === b ) {
3903 hasDuplicate = true;
3904 return 0;
3906 // If the nodes are siblings (or identical) we can do a quick check
3907 } else if ( aup === bup ) {
3908 return siblingCheck( a, b );
3910 // If no parents were found then the nodes are disconnected
3911 } else if ( !aup ) {
3912 return -1;
3914 } else if ( !bup ) {
3915 return 1;
3918 // Otherwise they're somewhere else in the tree so we need
3919 // to build up a full list of the parentNodes for comparison
3920 while ( cur ) {
3921 ap.unshift( cur );
3922 cur = cur.parentNode;
3925 cur = bup;
3927 while ( cur ) {
3928 bp.unshift( cur );
3929 cur = cur.parentNode;
3932 al = ap.length;
3933 bl = bp.length;
3935 // Start walking down the tree looking for a discrepancy
3936 for ( var i = 0; i < al && i < bl; i++ ) {
3937 if ( ap[i] !== bp[i] ) {
3938 return siblingCheck( ap[i], bp[i] );
3942 // We ended someplace up the tree so do a sibling check
3943 return i === al ?
3944 siblingCheck( a, bp[i], -1 ) :
3945 siblingCheck( ap[i], b, 1 );
3948 siblingCheck = function( a, b, ret ) {
3949 if ( a === b ) {
3950 return ret;
3953 var cur = a.nextSibling;
3955 while ( cur ) {
3956 if ( cur === b ) {
3957 return -1;
3960 cur = cur.nextSibling;
3963 return 1;
3967 // Utility function for retreiving the text value of an array of DOM nodes
3968 Sizzle.getText = function( elems ) {
3969 var ret = "", elem;
3971 for ( var i = 0; elems[i]; i++ ) {
3972 elem = elems[i];
3974 // Get the text from text nodes and CDATA nodes
3975 if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
3976 ret += elem.nodeValue;
3978 // Traverse everything else, except comment nodes
3979 } else if ( elem.nodeType !== 8 ) {
3980 ret += Sizzle.getText( elem.childNodes );
3984 return ret;
3987 // Check to see if the browser returns elements by name when
3988 // querying by getElementById (and provide a workaround)
3989 (function(){
3990 // We're going to inject a fake input element with a specified name
3991 var form = document.createElement("div"),
3992 id = "script" + (new Date()).getTime(),
3993 root = document.documentElement;
3995 form.innerHTML = "<a name='" + id + "'/>";
3997 // Inject it into the root element, check its status, and remove it quickly
3998 root.insertBefore( form, root.firstChild );
4000 // The workaround has to do additional checks after a getElementById
4001 // Which slows things down for other browsers (hence the branching)
4002 if ( document.getElementById( id ) ) {
4003 Expr.find.ID = function( match, context, isXML ) {
4004 if ( typeof context.getElementById !== "undefined" && !isXML ) {
4005 var m = context.getElementById(match[1]);
4007 return m ?
4008 m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
4009 [m] :
4010 undefined :
4015 Expr.filter.ID = function( elem, match ) {
4016 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
4018 return elem.nodeType === 1 && node && node.nodeValue === match;
4022 root.removeChild( form );
4024 // release memory in IE
4025 root = form = null;
4026 })();
4028 (function(){
4029 // Check to see if the browser returns only elements
4030 // when doing getElementsByTagName("*")
4032 // Create a fake element
4033 var div = document.createElement("div");
4034 div.appendChild( document.createComment("") );
4036 // Make sure no comments are found
4037 if ( div.getElementsByTagName("*").length > 0 ) {
4038 Expr.find.TAG = function( match, context ) {
4039 var results = context.getElementsByTagName( match[1] );
4041 // Filter out possible comments
4042 if ( match[1] === "*" ) {
4043 var tmp = [];
4045 for ( var i = 0; results[i]; i++ ) {
4046 if ( results[i].nodeType === 1 ) {
4047 tmp.push( results[i] );
4051 results = tmp;
4054 return results;
4058 // Check to see if an attribute returns normalized href attributes
4059 div.innerHTML = "<a href='#'></a>";
4061 if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
4062 div.firstChild.getAttribute("href") !== "#" ) {
4064 Expr.attrHandle.href = function( elem ) {
4065 return elem.getAttribute( "href", 2 );
4069 // release memory in IE
4070 div = null;
4071 })();
4073 if ( document.querySelectorAll ) {
4074 (function(){
4075 var oldSizzle = Sizzle,
4076 div = document.createElement("div"),
4077 id = "__sizzle__";
4079 div.innerHTML = "<p class='TEST'></p>";
4081 // Safari can't handle uppercase or unicode characters when
4082 // in quirks mode.
4083 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
4084 return;
4087 Sizzle = function( query, context, extra, seed ) {
4088 context = context || document;
4090 // Make sure that attribute selectors are quoted
4091 query = query.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
4093 // Only use querySelectorAll on non-XML documents
4094 // (ID selectors don't work in non-HTML documents)
4095 if ( !seed && !Sizzle.isXML(context) ) {
4096 if ( context.nodeType === 9 ) {
4097 try {
4098 return makeArray( context.querySelectorAll(query), extra );
4099 } catch(qsaError) {}
4101 // qSA works strangely on Element-rooted queries
4102 // We can work around this by specifying an extra ID on the root
4103 // and working up from there (Thanks to Andrew Dupont for the technique)
4104 // IE 8 doesn't work on object elements
4105 } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
4106 var old = context.getAttribute( "id" ),
4107 nid = old || id;
4109 if ( !old ) {
4110 context.setAttribute( "id", nid );
4113 try {
4114 return makeArray( context.querySelectorAll( "#" + nid + " " + query ), extra );
4116 } catch(pseudoError) {
4117 } finally {
4118 if ( !old ) {
4119 context.removeAttribute( "id" );
4125 return oldSizzle(query, context, extra, seed);
4128 for ( var prop in oldSizzle ) {
4129 Sizzle[ prop ] = oldSizzle[ prop ];
4132 // release memory in IE
4133 div = null;
4134 })();
4137 (function(){
4138 var html = document.documentElement,
4139 matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector,
4140 pseudoWorks = false;
4142 try {
4143 // This should fail with an exception
4144 // Gecko does not error, returns false instead
4145 matches.call( document.documentElement, "[test!='']:sizzle" );
4147 } catch( pseudoError ) {
4148 pseudoWorks = true;
4151 if ( matches ) {
4152 Sizzle.matchesSelector = function( node, expr ) {
4153 // Make sure that attribute selectors are quoted
4154 expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
4156 if ( !Sizzle.isXML( node ) ) {
4157 try {
4158 if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
4159 return matches.call( node, expr );
4161 } catch(e) {}
4164 return Sizzle(expr, null, null, [node]).length > 0;
4167 })();
4169 (function(){
4170 var div = document.createElement("div");
4172 div.innerHTML = "<div class='test e'></div><div class='test'></div>";
4174 // Opera can't find a second classname (in 9.6)
4175 // Also, make sure that getElementsByClassName actually exists
4176 if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
4177 return;
4180 // Safari caches class attributes, doesn't catch changes (in 3.2)
4181 div.lastChild.className = "e";
4183 if ( div.getElementsByClassName("e").length === 1 ) {
4184 return;
4187 Expr.order.splice(1, 0, "CLASS");
4188 Expr.find.CLASS = function( match, context, isXML ) {
4189 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
4190 return context.getElementsByClassName(match[1]);
4194 // release memory in IE
4195 div = null;
4196 })();
4198 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
4199 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
4200 var elem = checkSet[i];
4202 if ( elem ) {
4203 var match = false;
4205 elem = elem[dir];
4207 while ( elem ) {
4208 if ( elem.sizcache === doneName ) {
4209 match = checkSet[elem.sizset];
4210 break;
4213 if ( elem.nodeType === 1 && !isXML ){
4214 elem.sizcache = doneName;
4215 elem.sizset = i;
4218 if ( elem.nodeName.toLowerCase() === cur ) {
4219 match = elem;
4220 break;
4223 elem = elem[dir];
4226 checkSet[i] = match;
4231 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
4232 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
4233 var elem = checkSet[i];
4235 if ( elem ) {
4236 var match = false;
4238 elem = elem[dir];
4240 while ( elem ) {
4241 if ( elem.sizcache === doneName ) {
4242 match = checkSet[elem.sizset];
4243 break;
4246 if ( elem.nodeType === 1 ) {
4247 if ( !isXML ) {
4248 elem.sizcache = doneName;
4249 elem.sizset = i;
4252 if ( typeof cur !== "string" ) {
4253 if ( elem === cur ) {
4254 match = true;
4255 break;
4258 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
4259 match = elem;
4260 break;
4264 elem = elem[dir];
4267 checkSet[i] = match;
4272 if ( document.documentElement.contains ) {
4273 Sizzle.contains = function( a, b ) {
4274 return a !== b && (a.contains ? a.contains(b) : true);
4277 } else if ( document.documentElement.compareDocumentPosition ) {
4278 Sizzle.contains = function( a, b ) {
4279 return !!(a.compareDocumentPosition(b) & 16);
4282 } else {
4283 Sizzle.contains = function() {
4284 return false;
4288 Sizzle.isXML = function( elem ) {
4289 // documentElement is verified for cases where it doesn't yet exist
4290 // (such as loading iframes in IE - #4833)
4291 var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
4293 return documentElement ? documentElement.nodeName !== "HTML" : false;
4296 var posProcess = function( selector, context ) {
4297 var match,
4298 tmpSet = [],
4299 later = "",
4300 root = context.nodeType ? [context] : context;
4302 // Position selectors must be done after the filter
4303 // And so must :not(positional) so we move all PSEUDOs to the end
4304 while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
4305 later += match[0];
4306 selector = selector.replace( Expr.match.PSEUDO, "" );
4309 selector = Expr.relative[selector] ? selector + "*" : selector;
4311 for ( var i = 0, l = root.length; i < l; i++ ) {
4312 Sizzle( selector, root[i], tmpSet );
4315 return Sizzle.filter( later, tmpSet );
4318 // EXPOSE
4319 jQuery.find = Sizzle;
4320 jQuery.expr = Sizzle.selectors;
4321 jQuery.expr[":"] = jQuery.expr.filters;
4322 jQuery.unique = Sizzle.uniqueSort;
4323 jQuery.text = Sizzle.getText;
4324 jQuery.isXMLDoc = Sizzle.isXML;
4325 jQuery.contains = Sizzle.contains;
4328 })();
4331 var runtil = /Until$/,
4332 rparentsprev = /^(?:parents|prevUntil|prevAll)/,
4333 // Note: This RegExp should be improved, or likely pulled from Sizzle
4334 rmultiselector = /,/,
4335 isSimple = /^.[^:#\[\.,]*$/,
4336 slice = Array.prototype.slice,
4337 POS = jQuery.expr.match.POS;
4339 jQuery.fn.extend({
4340 find: function( selector ) {
4341 var ret = this.pushStack( "", "find", selector ),
4342 length = 0;
4344 for ( var i = 0, l = this.length; i < l; i++ ) {
4345 length = ret.length;
4346 jQuery.find( selector, this[i], ret );
4348 if ( i > 0 ) {
4349 // Make sure that the results are unique
4350 for ( var n = length; n < ret.length; n++ ) {
4351 for ( var r = 0; r < length; r++ ) {
4352 if ( ret[r] === ret[n] ) {
4353 ret.splice(n--, 1);
4354 break;
4361 return ret;
4364 has: function( target ) {
4365 var targets = jQuery( target );
4366 return this.filter(function() {
4367 for ( var i = 0, l = targets.length; i < l; i++ ) {
4368 if ( jQuery.contains( this, targets[i] ) ) {
4369 return true;
4375 not: function( selector ) {
4376 return this.pushStack( winnow(this, selector, false), "not", selector);
4379 filter: function( selector ) {
4380 return this.pushStack( winnow(this, selector, true), "filter", selector );
4383 is: function( selector ) {
4384 return !!selector && jQuery.filter( selector, this ).length > 0;
4387 closest: function( selectors, context ) {
4388 var ret = [], i, l, cur = this[0];
4390 if ( jQuery.isArray( selectors ) ) {
4391 var match, selector,
4392 matches = {},
4393 level = 1;
4395 if ( cur && selectors.length ) {
4396 for ( i = 0, l = selectors.length; i < l; i++ ) {
4397 selector = selectors[i];
4399 if ( !matches[selector] ) {
4400 matches[selector] = jQuery.expr.match.POS.test( selector ) ?
4401 jQuery( selector, context || this.context ) :
4402 selector;
4406 while ( cur && cur.ownerDocument && cur !== context ) {
4407 for ( selector in matches ) {
4408 match = matches[selector];
4410 if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
4411 ret.push({ selector: selector, elem: cur, level: level });
4415 cur = cur.parentNode;
4416 level++;
4420 return ret;
4423 var pos = POS.test( selectors ) ?
4424 jQuery( selectors, context || this.context ) : null;
4426 for ( i = 0, l = this.length; i < l; i++ ) {
4427 cur = this[i];
4429 while ( cur ) {
4430 if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
4431 ret.push( cur );
4432 break;
4434 } else {
4435 cur = cur.parentNode;
4436 if ( !cur || !cur.ownerDocument || cur === context ) {
4437 break;
4443 ret = ret.length > 1 ? jQuery.unique(ret) : ret;
4445 return this.pushStack( ret, "closest", selectors );
4448 // Determine the position of an element within
4449 // the matched set of elements
4450 index: function( elem ) {
4451 if ( !elem || typeof elem === "string" ) {
4452 return jQuery.inArray( this[0],
4453 // If it receives a string, the selector is used
4454 // If it receives nothing, the siblings are used
4455 elem ? jQuery( elem ) : this.parent().children() );
4457 // Locate the position of the desired element
4458 return jQuery.inArray(
4459 // If it receives a jQuery object, the first element is used
4460 elem.jquery ? elem[0] : elem, this );
4463 add: function( selector, context ) {
4464 var set = typeof selector === "string" ?
4465 jQuery( selector, context || this.context ) :
4466 jQuery.makeArray( selector ),
4467 all = jQuery.merge( this.get(), set );
4469 return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
4470 all :
4471 jQuery.unique( all ) );
4474 andSelf: function() {
4475 return this.add( this.prevObject );
4479 // A painfully simple check to see if an element is disconnected
4480 // from a document (should be improved, where feasible).
4481 function isDisconnected( node ) {
4482 return !node || !node.parentNode || node.parentNode.nodeType === 11;
4485 jQuery.each({
4486 parent: function( elem ) {
4487 var parent = elem.parentNode;
4488 return parent && parent.nodeType !== 11 ? parent : null;
4490 parents: function( elem ) {
4491 return jQuery.dir( elem, "parentNode" );
4493 parentsUntil: function( elem, i, until ) {
4494 return jQuery.dir( elem, "parentNode", until );
4496 next: function( elem ) {
4497 return jQuery.nth( elem, 2, "nextSibling" );
4499 prev: function( elem ) {
4500 return jQuery.nth( elem, 2, "previousSibling" );
4502 nextAll: function( elem ) {
4503 return jQuery.dir( elem, "nextSibling" );
4505 prevAll: function( elem ) {
4506 return jQuery.dir( elem, "previousSibling" );
4508 nextUntil: function( elem, i, until ) {
4509 return jQuery.dir( elem, "nextSibling", until );
4511 prevUntil: function( elem, i, until ) {
4512 return jQuery.dir( elem, "previousSibling", until );
4514 siblings: function( elem ) {
4515 return jQuery.sibling( elem.parentNode.firstChild, elem );
4517 children: function( elem ) {
4518 return jQuery.sibling( elem.firstChild );
4520 contents: function( elem ) {
4521 return jQuery.nodeName( elem, "iframe" ) ?
4522 elem.contentDocument || elem.contentWindow.document :
4523 jQuery.makeArray( elem.childNodes );
4525 }, function( name, fn ) {
4526 jQuery.fn[ name ] = function( until, selector ) {
4527 var ret = jQuery.map( this, fn, until );
4529 if ( !runtil.test( name ) ) {
4530 selector = until;
4533 if ( selector && typeof selector === "string" ) {
4534 ret = jQuery.filter( selector, ret );
4537 ret = this.length > 1 ? jQuery.unique( ret ) : ret;
4539 if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
4540 ret = ret.reverse();
4543 return this.pushStack( ret, name, slice.call(arguments).join(",") );
4547 jQuery.extend({
4548 filter: function( expr, elems, not ) {
4549 if ( not ) {
4550 expr = ":not(" + expr + ")";
4553 return elems.length === 1 ?
4554 jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
4555 jQuery.find.matches(expr, elems);
4558 dir: function( elem, dir, until ) {
4559 var matched = [],
4560 cur = elem[ dir ];
4562 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
4563 if ( cur.nodeType === 1 ) {
4564 matched.push( cur );
4566 cur = cur[dir];
4568 return matched;
4571 nth: function( cur, result, dir, elem ) {
4572 result = result || 1;
4573 var num = 0;
4575 for ( ; cur; cur = cur[dir] ) {
4576 if ( cur.nodeType === 1 && ++num === result ) {
4577 break;
4581 return cur;
4584 sibling: function( n, elem ) {
4585 var r = [];
4587 for ( ; n; n = n.nextSibling ) {
4588 if ( n.nodeType === 1 && n !== elem ) {
4589 r.push( n );
4593 return r;
4597 // Implement the identical functionality for filter and not
4598 function winnow( elements, qualifier, keep ) {
4599 if ( jQuery.isFunction( qualifier ) ) {
4600 return jQuery.grep(elements, function( elem, i ) {
4601 var retVal = !!qualifier.call( elem, i, elem );
4602 return retVal === keep;
4605 } else if ( qualifier.nodeType ) {
4606 return jQuery.grep(elements, function( elem, i ) {
4607 return (elem === qualifier) === keep;
4610 } else if ( typeof qualifier === "string" ) {
4611 var filtered = jQuery.grep(elements, function( elem ) {
4612 return elem.nodeType === 1;
4615 if ( isSimple.test( qualifier ) ) {
4616 return jQuery.filter(qualifier, filtered, !keep);
4617 } else {
4618 qualifier = jQuery.filter( qualifier, filtered );
4622 return jQuery.grep(elements, function( elem, i ) {
4623 return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
4630 var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
4631 rleadingWhitespace = /^\s+/,
4632 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
4633 rtagName = /<([\w:]+)/,
4634 rtbody = /<tbody/i,
4635 rhtml = /<|&#?\w+;/,
4636 rnocache = /<(?:script|object|embed|option|style)/i,
4637 // checked="checked" or checked (html5)
4638 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
4639 raction = /\=([^="'>\s]+\/)>/g,
4640 wrapMap = {
4641 option: [ 1, "<select multiple='multiple'>", "</select>" ],
4642 legend: [ 1, "<fieldset>", "</fieldset>" ],
4643 thead: [ 1, "<table>", "</table>" ],
4644 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
4645 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
4646 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
4647 area: [ 1, "<map>", "</map>" ],
4648 _default: [ 0, "", "" ]
4651 wrapMap.optgroup = wrapMap.option;
4652 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
4653 wrapMap.th = wrapMap.td;
4655 // IE can't serialize <link> and <script> tags normally
4656 if ( !jQuery.support.htmlSerialize ) {
4657 wrapMap._default = [ 1, "div<div>", "</div>" ];
4660 jQuery.fn.extend({
4661 text: function( text ) {
4662 if ( jQuery.isFunction(text) ) {
4663 return this.each(function(i) {
4664 var self = jQuery( this );
4666 self.text( text.call(this, i, self.text()) );
4670 if ( typeof text !== "object" && text !== undefined ) {
4671 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
4674 return jQuery.text( this );
4677 wrapAll: function( html ) {
4678 if ( jQuery.isFunction( html ) ) {
4679 return this.each(function(i) {
4680 jQuery(this).wrapAll( html.call(this, i) );
4684 if ( this[0] ) {
4685 // The elements to wrap the target around
4686 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
4688 if ( this[0].parentNode ) {
4689 wrap.insertBefore( this[0] );
4692 wrap.map(function() {
4693 var elem = this;
4695 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
4696 elem = elem.firstChild;
4699 return elem;
4700 }).append(this);
4703 return this;
4706 wrapInner: function( html ) {
4707 if ( jQuery.isFunction( html ) ) {
4708 return this.each(function(i) {
4709 jQuery(this).wrapInner( html.call(this, i) );
4713 return this.each(function() {
4714 var self = jQuery( this ),
4715 contents = self.contents();
4717 if ( contents.length ) {
4718 contents.wrapAll( html );
4720 } else {
4721 self.append( html );
4726 wrap: function( html ) {
4727 return this.each(function() {
4728 jQuery( this ).wrapAll( html );
4732 unwrap: function() {
4733 return this.parent().each(function() {
4734 if ( !jQuery.nodeName( this, "body" ) ) {
4735 jQuery( this ).replaceWith( this.childNodes );
4737 }).end();
4740 append: function() {
4741 return this.domManip(arguments, true, function( elem ) {
4742 if ( this.nodeType === 1 ) {
4743 this.appendChild( elem );
4748 prepend: function() {
4749 return this.domManip(arguments, true, function( elem ) {
4750 if ( this.nodeType === 1 ) {
4751 this.insertBefore( elem, this.firstChild );
4756 before: function() {
4757 if ( this[0] && this[0].parentNode ) {
4758 return this.domManip(arguments, false, function( elem ) {
4759 this.parentNode.insertBefore( elem, this );
4761 } else if ( arguments.length ) {
4762 var set = jQuery(arguments[0]);
4763 set.push.apply( set, this.toArray() );
4764 return this.pushStack( set, "before", arguments );
4768 after: function() {
4769 if ( this[0] && this[0].parentNode ) {
4770 return this.domManip(arguments, false, function( elem ) {
4771 this.parentNode.insertBefore( elem, this.nextSibling );
4773 } else if ( arguments.length ) {
4774 var set = this.pushStack( this, "after", arguments );
4775 set.push.apply( set, jQuery(arguments[0]).toArray() );
4776 return set;
4780 // keepData is for internal use only--do not document
4781 remove: function( selector, keepData ) {
4782 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
4783 if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
4784 if ( !keepData && elem.nodeType === 1 ) {
4785 jQuery.cleanData( elem.getElementsByTagName("*") );
4786 jQuery.cleanData( [ elem ] );
4789 if ( elem.parentNode ) {
4790 elem.parentNode.removeChild( elem );
4795 return this;
4798 empty: function() {
4799 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
4800 // Remove element nodes and prevent memory leaks
4801 if ( elem.nodeType === 1 ) {
4802 jQuery.cleanData( elem.getElementsByTagName("*") );
4805 // Remove any remaining nodes
4806 while ( elem.firstChild ) {
4807 elem.removeChild( elem.firstChild );
4811 return this;
4814 clone: function( events ) {
4815 // Do the clone
4816 var ret = this.map(function() {
4817 if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
4818 // IE copies events bound via attachEvent when
4819 // using cloneNode. Calling detachEvent on the
4820 // clone will also remove the events from the orignal
4821 // In order to get around this, we use innerHTML.
4822 // Unfortunately, this means some modifications to
4823 // attributes in IE that are actually only stored
4824 // as properties will not be copied (such as the
4825 // the name attribute on an input).
4826 var html = this.outerHTML,
4827 ownerDocument = this.ownerDocument;
4829 if ( !html ) {
4830 var div = ownerDocument.createElement("div");
4831 div.appendChild( this.cloneNode(true) );
4832 html = div.innerHTML;
4835 return jQuery.clean([html.replace(rinlinejQuery, "")
4836 // Handle the case in IE 8 where action=/test/> self-closes a tag
4837 .replace(raction, '="$1">')
4838 .replace(rleadingWhitespace, "")], ownerDocument)[0];
4839 } else {
4840 return this.cloneNode(true);
4844 // Copy the events from the original to the clone
4845 if ( events === true ) {
4846 cloneCopyEvent( this, ret );
4847 cloneCopyEvent( this.find("*"), ret.find("*") );
4850 // Return the cloned set
4851 return ret;
4854 html: function( value ) {
4855 if ( value === undefined ) {
4856 return this[0] && this[0].nodeType === 1 ?
4857 this[0].innerHTML.replace(rinlinejQuery, "") :
4858 null;
4860 // See if we can take a shortcut and just use innerHTML
4861 } else if ( typeof value === "string" && !rnocache.test( value ) &&
4862 (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
4863 !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
4865 value = value.replace(rxhtmlTag, "<$1></$2>");
4867 try {
4868 for ( var i = 0, l = this.length; i < l; i++ ) {
4869 // Remove element nodes and prevent memory leaks
4870 if ( this[i].nodeType === 1 ) {
4871 jQuery.cleanData( this[i].getElementsByTagName("*") );
4872 this[i].innerHTML = value;
4876 // If using innerHTML throws an exception, use the fallback method
4877 } catch(e) {
4878 this.empty().append( value );
4881 } else if ( jQuery.isFunction( value ) ) {
4882 this.each(function(i){
4883 var self = jQuery( this );
4885 self.html( value.call(this, i, self.html()) );
4888 } else {
4889 this.empty().append( value );
4892 return this;
4895 replaceWith: function( value ) {
4896 if ( this[0] && this[0].parentNode ) {
4897 // Make sure that the elements are removed from the DOM before they are inserted
4898 // this can help fix replacing a parent with child elements
4899 if ( jQuery.isFunction( value ) ) {
4900 return this.each(function(i) {
4901 var self = jQuery(this), old = self.html();
4902 self.replaceWith( value.call( this, i, old ) );
4906 if ( typeof value !== "string" ) {
4907 value = jQuery( value ).detach();
4910 return this.each(function() {
4911 var next = this.nextSibling,
4912 parent = this.parentNode;
4914 jQuery( this ).remove();
4916 if ( next ) {
4917 jQuery(next).before( value );
4918 } else {
4919 jQuery(parent).append( value );
4922 } else {
4923 return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
4927 detach: function( selector ) {
4928 return this.remove( selector, true );
4931 domManip: function( args, table, callback ) {
4932 var results, first, fragment, parent,
4933 value = args[0],
4934 scripts = [];
4936 // We can't cloneNode fragments that contain checked, in WebKit
4937 if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
4938 return this.each(function() {
4939 jQuery(this).domManip( args, table, callback, true );
4943 if ( jQuery.isFunction(value) ) {
4944 return this.each(function(i) {
4945 var self = jQuery(this);
4946 args[0] = value.call(this, i, table ? self.html() : undefined);
4947 self.domManip( args, table, callback );
4951 if ( this[0] ) {
4952 parent = value && value.parentNode;
4954 // If we're in a fragment, just use that instead of building a new one
4955 if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
4956 results = { fragment: parent };
4958 } else {
4959 results = jQuery.buildFragment( args, this, scripts );
4962 fragment = results.fragment;
4964 if ( fragment.childNodes.length === 1 ) {
4965 first = fragment = fragment.firstChild;
4966 } else {
4967 first = fragment.firstChild;
4970 if ( first ) {
4971 table = table && jQuery.nodeName( first, "tr" );
4973 for ( var i = 0, l = this.length; i < l; i++ ) {
4974 callback.call(
4975 table ?
4976 root(this[i], first) :
4977 this[i],
4978 i > 0 || results.cacheable || this.length > 1 ?
4979 fragment.cloneNode(true) :
4980 fragment
4985 if ( scripts.length ) {
4986 jQuery.each( scripts, evalScript );
4990 return this;
4994 function root( elem, cur ) {
4995 return jQuery.nodeName(elem, "table") ?
4996 (elem.getElementsByTagName("tbody")[0] ||
4997 elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
4998 elem;
5001 function cloneCopyEvent(orig, ret) {
5002 var i = 0;
5004 ret.each(function() {
5005 if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
5006 return;
5009 var oldData = jQuery.data( orig[i++] ),
5010 curData = jQuery.data( this, oldData ),
5011 events = oldData && oldData.events;
5013 if ( events ) {
5014 delete curData.handle;
5015 curData.events = {};
5017 for ( var type in events ) {
5018 for ( var handler in events[ type ] ) {
5019 jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
5026 jQuery.buildFragment = function( args, nodes, scripts ) {
5027 var fragment, cacheable, cacheresults,
5028 doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
5030 // Only cache "small" (1/2 KB) strings that are associated with the main document
5031 // Cloning options loses the selected state, so don't cache them
5032 // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
5033 // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
5034 if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
5035 !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
5037 cacheable = true;
5038 cacheresults = jQuery.fragments[ args[0] ];
5039 if ( cacheresults ) {
5040 if ( cacheresults !== 1 ) {
5041 fragment = cacheresults;
5046 if ( !fragment ) {
5047 fragment = doc.createDocumentFragment();
5048 jQuery.clean( args, doc, fragment, scripts );
5051 if ( cacheable ) {
5052 jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
5055 return { fragment: fragment, cacheable: cacheable };
5058 jQuery.fragments = {};
5060 jQuery.each({
5061 appendTo: "append",
5062 prependTo: "prepend",
5063 insertBefore: "before",
5064 insertAfter: "after",
5065 replaceAll: "replaceWith"
5066 }, function( name, original ) {
5067 jQuery.fn[ name ] = function( selector ) {
5068 var ret = [],
5069 insert = jQuery( selector ),
5070 parent = this.length === 1 && this[0].parentNode;
5072 if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
5073 insert[ original ]( this[0] );
5074 return this;
5076 } else {
5077 for ( var i = 0, l = insert.length; i < l; i++ ) {
5078 var elems = (i > 0 ? this.clone(true) : this).get();
5079 jQuery( insert[i] )[ original ]( elems );
5080 ret = ret.concat( elems );
5083 return this.pushStack( ret, name, insert.selector );
5088 jQuery.extend({
5089 clean: function( elems, context, fragment, scripts ) {
5090 context = context || document;
5092 // !context.createElement fails in IE with an error but returns typeof 'object'
5093 if ( typeof context.createElement === "undefined" ) {
5094 context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
5097 var ret = [];
5099 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
5100 if ( typeof elem === "number" ) {
5101 elem += "";
5104 if ( !elem ) {
5105 continue;
5108 // Convert html string into DOM nodes
5109 if ( typeof elem === "string" && !rhtml.test( elem ) ) {
5110 elem = context.createTextNode( elem );
5112 } else if ( typeof elem === "string" ) {
5113 // Fix "XHTML"-style tags in all browsers
5114 elem = elem.replace(rxhtmlTag, "<$1></$2>");
5116 // Trim whitespace, otherwise indexOf won't work as expected
5117 var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
5118 wrap = wrapMap[ tag ] || wrapMap._default,
5119 depth = wrap[0],
5120 div = context.createElement("div");
5122 // Go to html and back, then peel off extra wrappers
5123 div.innerHTML = wrap[1] + elem + wrap[2];
5125 // Move to the right depth
5126 while ( depth-- ) {
5127 div = div.lastChild;
5130 // Remove IE's autoinserted <tbody> from table fragments
5131 if ( !jQuery.support.tbody ) {
5133 // String was a <table>, *may* have spurious <tbody>
5134 var hasBody = rtbody.test(elem),
5135 tbody = tag === "table" && !hasBody ?
5136 div.firstChild && div.firstChild.childNodes :
5138 // String was a bare <thead> or <tfoot>
5139 wrap[1] === "<table>" && !hasBody ?
5140 div.childNodes :
5143 for ( var j = tbody.length - 1; j >= 0 ; --j ) {
5144 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
5145 tbody[ j ].parentNode.removeChild( tbody[ j ] );
5151 // IE completely kills leading whitespace when innerHTML is used
5152 if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
5153 div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
5156 elem = div.childNodes;
5159 if ( elem.nodeType ) {
5160 ret.push( elem );
5161 } else {
5162 ret = jQuery.merge( ret, elem );
5166 if ( fragment ) {
5167 for ( i = 0; ret[i]; i++ ) {
5168 if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
5169 scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
5171 } else {
5172 if ( ret[i].nodeType === 1 ) {
5173 ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
5175 fragment.appendChild( ret[i] );
5180 return ret;
5183 cleanData: function( elems ) {
5184 var data, id, cache = jQuery.cache,
5185 special = jQuery.event.special,
5186 deleteExpando = jQuery.support.deleteExpando;
5188 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
5189 if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
5190 continue;
5193 id = elem[ jQuery.expando ];
5195 if ( id ) {
5196 data = cache[ id ];
5198 if ( data && data.events ) {
5199 for ( var type in data.events ) {
5200 if ( special[ type ] ) {
5201 jQuery.event.remove( elem, type );
5203 } else {
5204 jQuery.removeEvent( elem, type, data.handle );
5209 if ( deleteExpando ) {
5210 delete elem[ jQuery.expando ];
5212 } else if ( elem.removeAttribute ) {
5213 elem.removeAttribute( jQuery.expando );
5216 delete cache[ id ];
5222 function evalScript( i, elem ) {
5223 if ( elem.src ) {
5224 jQuery.ajax({
5225 url: elem.src,
5226 async: false,
5227 dataType: "script"
5229 } else {
5230 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
5233 if ( elem.parentNode ) {
5234 elem.parentNode.removeChild( elem );
5241 var ralpha = /alpha\([^)]*\)/i,
5242 ropacity = /opacity=([^)]*)/,
5243 rdashAlpha = /-([a-z])/ig,
5244 rupper = /([A-Z])/g,
5245 rnumpx = /^-?\d+(?:px)?$/i,
5246 rnum = /^-?\d/,
5248 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
5249 cssWidth = [ "Left", "Right" ],
5250 cssHeight = [ "Top", "Bottom" ],
5251 curCSS,
5253 getComputedStyle,
5254 currentStyle,
5256 fcamelCase = function( all, letter ) {
5257 return letter.toUpperCase();
5260 jQuery.fn.css = function( name, value ) {
5261 // Setting 'undefined' is a no-op
5262 if ( arguments.length === 2 && value === undefined ) {
5263 return this;
5266 return jQuery.access( this, name, value, true, function( elem, name, value ) {
5267 return value !== undefined ?
5268 jQuery.style( elem, name, value ) :
5269 jQuery.css( elem, name );
5273 jQuery.extend({
5274 // Add in style property hooks for overriding the default
5275 // behavior of getting and setting a style property
5276 cssHooks: {
5277 opacity: {
5278 get: function( elem, computed ) {
5279 if ( computed ) {
5280 // We should always get a number back from opacity
5281 var ret = curCSS( elem, "opacity", "opacity" );
5282 return ret === "" ? "1" : ret;
5284 } else {
5285 return elem.style.opacity;
5291 // Exclude the following css properties to add px
5292 cssNumber: {
5293 "zIndex": true,
5294 "fontWeight": true,
5295 "opacity": true,
5296 "zoom": true,
5297 "lineHeight": true
5300 // Add in properties whose names you wish to fix before
5301 // setting or getting the value
5302 cssProps: {
5303 // normalize float css property
5304 "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
5307 // Get and set the style property on a DOM Node
5308 style: function( elem, name, value, extra ) {
5309 // Don't set styles on text and comment nodes
5310 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
5311 return;
5314 // Make sure that we're working with the right name
5315 var ret, origName = jQuery.camelCase( name ),
5316 style = elem.style, hooks = jQuery.cssHooks[ origName ];
5318 name = jQuery.cssProps[ origName ] || origName;
5320 // Check if we're setting a value
5321 if ( value !== undefined ) {
5322 // Make sure that NaN and null values aren't set. See: #7116
5323 if ( typeof value === "number" && isNaN( value ) || value == null ) {
5324 return;
5327 // If a number was passed in, add 'px' to the (except for certain CSS properties)
5328 if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) {
5329 value += "px";
5332 // If a hook was provided, use that value, otherwise just set the specified value
5333 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
5334 // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
5335 // Fixes bug #5509
5336 try {
5337 style[ name ] = value;
5338 } catch(e) {}
5341 } else {
5342 // If a hook was provided get the non-computed value from there
5343 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
5344 return ret;
5347 // Otherwise just get the value from the style object
5348 return style[ name ];
5352 css: function( elem, name, extra ) {
5353 // Make sure that we're working with the right name
5354 var ret, origName = jQuery.camelCase( name ),
5355 hooks = jQuery.cssHooks[ origName ];
5357 name = jQuery.cssProps[ origName ] || origName;
5359 // If a hook was provided get the computed value from there
5360 if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
5361 return ret;
5363 // Otherwise, if a way to get the computed value exists, use that
5364 } else if ( curCSS ) {
5365 return curCSS( elem, name, origName );
5369 // A method for quickly swapping in/out CSS properties to get correct calculations
5370 swap: function( elem, options, callback ) {
5371 var old = {};
5373 // Remember the old values, and insert the new ones
5374 for ( var name in options ) {
5375 old[ name ] = elem.style[ name ];
5376 elem.style[ name ] = options[ name ];
5379 callback.call( elem );
5381 // Revert the old values
5382 for ( name in options ) {
5383 elem.style[ name ] = old[ name ];
5387 camelCase: function( string ) {
5388 return string.replace( rdashAlpha, fcamelCase );
5392 // DEPRECATED, Use jQuery.css() instead
5393 jQuery.curCSS = jQuery.css;
5395 jQuery.each(["height", "width"], function( i, name ) {
5396 jQuery.cssHooks[ name ] = {
5397 get: function( elem, computed, extra ) {
5398 var val;
5400 if ( computed ) {
5401 if ( elem.offsetWidth !== 0 ) {
5402 val = getWH( elem, name, extra );
5404 } else {
5405 jQuery.swap( elem, cssShow, function() {
5406 val = getWH( elem, name, extra );
5410 if ( val <= 0 ) {
5411 val = curCSS( elem, name, name );
5413 if ( val === "0px" && currentStyle ) {
5414 val = currentStyle( elem, name, name );
5417 if ( val != null ) {
5418 // Should return "auto" instead of 0, use 0 for
5419 // temporary backwards-compat
5420 return val === "" || val === "auto" ? "0px" : val;
5424 if ( val < 0 || val == null ) {
5425 val = elem.style[ name ];
5427 // Should return "auto" instead of 0, use 0 for
5428 // temporary backwards-compat
5429 return val === "" || val === "auto" ? "0px" : val;
5432 return typeof val === "string" ? val : val + "px";
5436 set: function( elem, value ) {
5437 if ( rnumpx.test( value ) ) {
5438 // ignore negative width and height values #1599
5439 value = parseFloat(value);
5441 if ( value >= 0 ) {
5442 return value + "px";
5445 } else {
5446 return value;
5452 if ( !jQuery.support.opacity ) {
5453 jQuery.cssHooks.opacity = {
5454 get: function( elem, computed ) {
5455 // IE uses filters for opacity
5456 return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ?
5457 (parseFloat(RegExp.$1) / 100) + "" :
5458 computed ? "1" : "";
5461 set: function( elem, value ) {
5462 var style = elem.style;
5464 // IE has trouble with opacity if it does not have layout
5465 // Force it by setting the zoom level
5466 style.zoom = 1;
5468 // Set the alpha filter to set the opacity
5469 var opacity = jQuery.isNaN(value) ?
5470 "" :
5471 "alpha(opacity=" + value * 100 + ")",
5472 filter = style.filter || "";
5474 style.filter = ralpha.test(filter) ?
5475 filter.replace(ralpha, opacity) :
5476 style.filter + ' ' + opacity;
5481 if ( document.defaultView && document.defaultView.getComputedStyle ) {
5482 getComputedStyle = function( elem, newName, name ) {
5483 var ret, defaultView, computedStyle;
5485 name = name.replace( rupper, "-$1" ).toLowerCase();
5487 if ( !(defaultView = elem.ownerDocument.defaultView) ) {
5488 return undefined;
5491 if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
5492 ret = computedStyle.getPropertyValue( name );
5493 if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
5494 ret = jQuery.style( elem, name );
5498 return ret;
5502 if ( document.documentElement.currentStyle ) {
5503 currentStyle = function( elem, name ) {
5504 var left, rsLeft,
5505 ret = elem.currentStyle && elem.currentStyle[ name ],
5506 style = elem.style;
5508 // From the awesome hack by Dean Edwards
5509 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
5511 // If we're not dealing with a regular pixel number
5512 // but a number that has a weird ending, we need to convert it to pixels
5513 if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
5514 // Remember the original values
5515 left = style.left;
5516 rsLeft = elem.runtimeStyle.left;
5518 // Put in the new values to get a computed value out
5519 elem.runtimeStyle.left = elem.currentStyle.left;
5520 style.left = name === "fontSize" ? "1em" : (ret || 0);
5521 ret = style.pixelLeft + "px";
5523 // Revert the changed values
5524 style.left = left;
5525 elem.runtimeStyle.left = rsLeft;
5528 return ret === "" ? "auto" : ret;
5532 curCSS = getComputedStyle || currentStyle;
5534 function getWH( elem, name, extra ) {
5535 var which = name === "width" ? cssWidth : cssHeight,
5536 val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
5538 if ( extra === "border" ) {
5539 return val;
5542 jQuery.each( which, function() {
5543 if ( !extra ) {
5544 val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0;
5547 if ( extra === "margin" ) {
5548 val += parseFloat(jQuery.css( elem, "margin" + this )) || 0;
5550 } else {
5551 val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0;
5555 return val;
5558 if ( jQuery.expr && jQuery.expr.filters ) {
5559 jQuery.expr.filters.hidden = function( elem ) {
5560 var width = elem.offsetWidth,
5561 height = elem.offsetHeight;
5563 return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none");
5566 jQuery.expr.filters.visible = function( elem ) {
5567 return !jQuery.expr.filters.hidden( elem );
5574 var jsc = jQuery.now(),
5575 rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
5576 rselectTextarea = /^(?:select|textarea)/i,
5577 rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
5578 rnoContent = /^(?:GET|HEAD)$/,
5579 rbracket = /\[\]$/,
5580 jsre = /\=\?(&|$)/,
5581 rquery = /\?/,
5582 rts = /([?&])_=[^&]*/,
5583 rurl = /^(\w+:)?\/\/([^\/?#]+)/,
5584 r20 = /%20/g,
5585 rhash = /#.*$/,
5587 // Keep a copy of the old load method
5588 _load = jQuery.fn.load;
5590 jQuery.fn.extend({
5591 load: function( url, params, callback ) {
5592 if ( typeof url !== "string" && _load ) {
5593 return _load.apply( this, arguments );
5595 // Don't do a request if no elements are being requested
5596 } else if ( !this.length ) {
5597 return this;
5600 var off = url.indexOf(" ");
5601 if ( off >= 0 ) {
5602 var selector = url.slice(off, url.length);
5603 url = url.slice(0, off);
5606 // Default to a GET request
5607 var type = "GET";
5609 // If the second parameter was provided
5610 if ( params ) {
5611 // If it's a function
5612 if ( jQuery.isFunction( params ) ) {
5613 // We assume that it's the callback
5614 callback = params;
5615 params = null;
5617 // Otherwise, build a param string
5618 } else if ( typeof params === "object" ) {
5619 params = jQuery.param( params, jQuery.ajaxSettings.traditional );
5620 type = "POST";
5624 var self = this;
5626 // Request the remote document
5627 jQuery.ajax({
5628 url: url,
5629 type: type,
5630 dataType: "html",
5631 data: params,
5632 complete: function( res, status ) {
5633 // If successful, inject the HTML into all the matched elements
5634 if ( status === "success" || status === "notmodified" ) {
5635 // See if a selector was specified
5636 self.html( selector ?
5637 // Create a dummy div to hold the results
5638 jQuery("<div>")
5639 // inject the contents of the document in, removing the scripts
5640 // to avoid any 'Permission Denied' errors in IE
5641 .append(res.responseText.replace(rscript, ""))
5643 // Locate the specified elements
5644 .find(selector) :
5646 // If not, just inject the full result
5647 res.responseText );
5650 if ( callback ) {
5651 self.each( callback, [res.responseText, status, res] );
5656 return this;
5659 serialize: function() {
5660 return jQuery.param(this.serializeArray());
5663 serializeArray: function() {
5664 return this.map(function() {
5665 return this.elements ? jQuery.makeArray(this.elements) : this;
5667 .filter(function() {
5668 return this.name && !this.disabled &&
5669 (this.checked || rselectTextarea.test(this.nodeName) ||
5670 rinput.test(this.type));
5672 .map(function( i, elem ) {
5673 var val = jQuery(this).val();
5675 return val == null ?
5676 null :
5677 jQuery.isArray(val) ?
5678 jQuery.map( val, function( val, i ) {
5679 return { name: elem.name, value: val };
5680 }) :
5681 { name: elem.name, value: val };
5682 }).get();
5686 // Attach a bunch of functions for handling common AJAX events
5687 jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
5688 jQuery.fn[o] = function( f ) {
5689 return this.bind(o, f);
5693 jQuery.extend({
5694 get: function( url, data, callback, type ) {
5695 // shift arguments if data argument was omited
5696 if ( jQuery.isFunction( data ) ) {
5697 type = type || callback;
5698 callback = data;
5699 data = null;
5702 return jQuery.ajax({
5703 type: "GET",
5704 url: url,
5705 data: data,
5706 success: callback,
5707 dataType: type
5711 getScript: function( url, callback ) {
5712 return jQuery.get(url, null, callback, "script");
5715 getJSON: function( url, data, callback ) {
5716 return jQuery.get(url, data, callback, "json");
5719 post: function( url, data, callback, type ) {
5720 // shift arguments if data argument was omited
5721 if ( jQuery.isFunction( data ) ) {
5722 type = type || callback;
5723 callback = data;
5724 data = {};
5727 return jQuery.ajax({
5728 type: "POST",
5729 url: url,
5730 data: data,
5731 success: callback,
5732 dataType: type
5736 ajaxSetup: function( settings ) {
5737 jQuery.extend( jQuery.ajaxSettings, settings );
5740 ajaxSettings: {
5741 url: location.href,
5742 global: true,
5743 type: "GET",
5744 contentType: "application/x-www-form-urlencoded",
5745 processData: true,
5746 async: true,
5748 timeout: 0,
5749 data: null,
5750 username: null,
5751 password: null,
5752 traditional: false,
5754 // This function can be overriden by calling jQuery.ajaxSetup
5755 xhr: function() {
5756 return new window.XMLHttpRequest();
5758 accepts: {
5759 xml: "application/xml, text/xml",
5760 html: "text/html",
5761 script: "text/javascript, application/javascript",
5762 json: "application/json, text/javascript",
5763 text: "text/plain",
5764 _default: "*/*"
5768 ajax: function( origSettings ) {
5769 var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings),
5770 jsonp, status, data, type = s.type.toUpperCase(), noContent = rnoContent.test(type);
5772 s.url = s.url.replace( rhash, "" );
5774 // Use original (not extended) context object if it was provided
5775 s.context = origSettings && origSettings.context != null ? origSettings.context : s;
5777 // convert data if not already a string
5778 if ( s.data && s.processData && typeof s.data !== "string" ) {
5779 s.data = jQuery.param( s.data, s.traditional );
5782 // Handle JSONP Parameter Callbacks
5783 if ( s.dataType === "jsonp" ) {
5784 if ( type === "GET" ) {
5785 if ( !jsre.test( s.url ) ) {
5786 s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
5788 } else if ( !s.data || !jsre.test(s.data) ) {
5789 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
5791 s.dataType = "json";
5794 // Build temporary JSONP function
5795 if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
5796 jsonp = s.jsonpCallback || ("jsonp" + jsc++);
5798 // Replace the =? sequence both in the query string and the data
5799 if ( s.data ) {
5800 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
5803 s.url = s.url.replace(jsre, "=" + jsonp + "$1");
5805 // We need to make sure
5806 // that a JSONP style response is executed properly
5807 s.dataType = "script";
5809 // Handle JSONP-style loading
5810 var customJsonp = window[ jsonp ];
5812 window[ jsonp ] = function( tmp ) {
5813 if ( jQuery.isFunction( customJsonp ) ) {
5814 customJsonp( tmp );
5816 } else {
5817 // Garbage collect
5818 window[ jsonp ] = undefined;
5820 try {
5821 delete window[ jsonp ];
5822 } catch( jsonpError ) {}
5825 data = tmp;
5826 jQuery.handleSuccess( s, xhr, status, data );
5827 jQuery.handleComplete( s, xhr, status, data );
5829 if ( head ) {
5830 head.removeChild( script );
5835 if ( s.dataType === "script" && s.cache === null ) {
5836 s.cache = false;
5839 if ( s.cache === false && noContent ) {
5840 var ts = jQuery.now();
5842 // try replacing _= if it is there
5843 var ret = s.url.replace(rts, "$1_=" + ts);
5845 // if nothing was replaced, add timestamp to the end
5846 s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
5849 // If data is available, append data to url for GET/HEAD requests
5850 if ( s.data && noContent ) {
5851 s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
5854 // Watch for a new set of requests
5855 if ( s.global && jQuery.active++ === 0 ) {
5856 jQuery.event.trigger( "ajaxStart" );
5859 // Matches an absolute URL, and saves the domain
5860 var parts = rurl.exec( s.url ),
5861 remote = parts && (parts[1] && parts[1].toLowerCase() !== location.protocol || parts[2].toLowerCase() !== location.host);
5863 // If we're requesting a remote document
5864 // and trying to load JSON or Script with a GET
5865 if ( s.dataType === "script" && type === "GET" && remote ) {
5866 var head = document.getElementsByTagName("head")[0] || document.documentElement;
5867 var script = document.createElement("script");
5868 if ( s.scriptCharset ) {
5869 script.charset = s.scriptCharset;
5871 script.src = s.url;
5873 // Handle Script loading
5874 if ( !jsonp ) {
5875 var done = false;
5877 // Attach handlers for all browsers
5878 script.onload = script.onreadystatechange = function() {
5879 if ( !done && (!this.readyState ||
5880 this.readyState === "loaded" || this.readyState === "complete") ) {
5881 done = true;
5882 jQuery.handleSuccess( s, xhr, status, data );
5883 jQuery.handleComplete( s, xhr, status, data );
5885 // Handle memory leak in IE
5886 script.onload = script.onreadystatechange = null;
5887 if ( head && script.parentNode ) {
5888 head.removeChild( script );
5894 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
5895 // This arises when a base node is used (#2709 and #4378).
5896 head.insertBefore( script, head.firstChild );
5898 // We handle everything using the script element injection
5899 return undefined;
5902 var requestDone = false;
5904 // Create the request object
5905 var xhr = s.xhr();
5907 if ( !xhr ) {
5908 return;
5911 // Open the socket
5912 // Passing null username, generates a login popup on Opera (#2865)
5913 if ( s.username ) {
5914 xhr.open(type, s.url, s.async, s.username, s.password);
5915 } else {
5916 xhr.open(type, s.url, s.async);
5919 // Need an extra try/catch for cross domain requests in Firefox 3
5920 try {
5921 // Set content-type if data specified and content-body is valid for this type
5922 if ( (s.data != null && !noContent) || (origSettings && origSettings.contentType) ) {
5923 xhr.setRequestHeader("Content-Type", s.contentType);
5926 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
5927 if ( s.ifModified ) {
5928 if ( jQuery.lastModified[s.url] ) {
5929 xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
5932 if ( jQuery.etag[s.url] ) {
5933 xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
5937 // Set header so the called script knows that it's an XMLHttpRequest
5938 // Only send the header if it's not a remote XHR
5939 if ( !remote ) {
5940 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
5943 // Set the Accepts header for the server, depending on the dataType
5944 xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
5945 s.accepts[ s.dataType ] + ", */*; q=0.01" :
5946 s.accepts._default );
5947 } catch( headerError ) {}
5949 // Allow custom headers/mimetypes and early abort
5950 if ( s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false ) {
5951 // Handle the global AJAX counter
5952 if ( s.global && jQuery.active-- === 1 ) {
5953 jQuery.event.trigger( "ajaxStop" );
5956 // close opended socket
5957 xhr.abort();
5958 return false;
5961 if ( s.global ) {
5962 jQuery.triggerGlobal( s, "ajaxSend", [xhr, s] );
5965 // Wait for a response to come back
5966 var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
5967 // The request was aborted
5968 if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
5969 // Opera doesn't call onreadystatechange before this point
5970 // so we simulate the call
5971 if ( !requestDone ) {
5972 jQuery.handleComplete( s, xhr, status, data );
5975 requestDone = true;
5976 if ( xhr ) {
5977 xhr.onreadystatechange = jQuery.noop;
5980 // The transfer is complete and the data is available, or the request timed out
5981 } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
5982 requestDone = true;
5983 xhr.onreadystatechange = jQuery.noop;
5985 status = isTimeout === "timeout" ?
5986 "timeout" :
5987 !jQuery.httpSuccess( xhr ) ?
5988 "error" :
5989 s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
5990 "notmodified" :
5991 "success";
5993 var errMsg;
5995 if ( status === "success" ) {
5996 // Watch for, and catch, XML document parse errors
5997 try {
5998 // process the data (runs the xml through httpData regardless of callback)
5999 data = jQuery.httpData( xhr, s.dataType, s );
6000 } catch( parserError ) {
6001 status = "parsererror";
6002 errMsg = parserError;
6006 // Make sure that the request was successful or notmodified
6007 if ( status === "success" || status === "notmodified" ) {
6008 // JSONP handles its own success callback
6009 if ( !jsonp ) {
6010 jQuery.handleSuccess( s, xhr, status, data );
6012 } else {
6013 jQuery.handleError( s, xhr, status, errMsg );
6016 // Fire the complete handlers
6017 if ( !jsonp ) {
6018 jQuery.handleComplete( s, xhr, status, data );
6021 if ( isTimeout === "timeout" ) {
6022 xhr.abort();
6025 // Stop memory leaks
6026 if ( s.async ) {
6027 xhr = null;
6032 // Override the abort handler, if we can (IE 6 doesn't allow it, but that's OK)
6033 // Opera doesn't fire onreadystatechange at all on abort
6034 try {
6035 var oldAbort = xhr.abort;
6036 xhr.abort = function() {
6037 if ( xhr ) {
6038 // oldAbort has no call property in IE7 so
6039 // just do it this way, which works in all
6040 // browsers
6041 Function.prototype.call.call( oldAbort, xhr );
6044 onreadystatechange( "abort" );
6046 } catch( abortError ) {}
6048 // Timeout checker
6049 if ( s.async && s.timeout > 0 ) {
6050 setTimeout(function() {
6051 // Check to see if the request is still happening
6052 if ( xhr && !requestDone ) {
6053 onreadystatechange( "timeout" );
6055 }, s.timeout);
6058 // Send the data
6059 try {
6060 xhr.send( noContent || s.data == null ? null : s.data );
6062 } catch( sendError ) {
6063 jQuery.handleError( s, xhr, null, sendError );
6065 // Fire the complete handlers
6066 jQuery.handleComplete( s, xhr, status, data );
6069 // firefox 1.5 doesn't fire statechange for sync requests
6070 if ( !s.async ) {
6071 onreadystatechange();
6074 // return XMLHttpRequest to allow aborting the request etc.
6075 return xhr;
6078 // Serialize an array of form elements or a set of
6079 // key/values into a query string
6080 param: function( a, traditional ) {
6081 var s = [],
6082 add = function( key, value ) {
6083 // If value is a function, invoke it and return its value
6084 value = jQuery.isFunction(value) ? value() : value;
6085 s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
6088 // Set traditional to true for jQuery <= 1.3.2 behavior.
6089 if ( traditional === undefined ) {
6090 traditional = jQuery.ajaxSettings.traditional;
6093 // If an array was passed in, assume that it is an array of form elements.
6094 if ( jQuery.isArray(a) || a.jquery ) {
6095 // Serialize the form elements
6096 jQuery.each( a, function() {
6097 add( this.name, this.value );
6100 } else {
6101 // If traditional, encode the "old" way (the way 1.3.2 or older
6102 // did it), otherwise encode params recursively.
6103 for ( var prefix in a ) {
6104 buildParams( prefix, a[prefix], traditional, add );
6108 // Return the resulting serialization
6109 return s.join("&").replace(r20, "+");
6113 function buildParams( prefix, obj, traditional, add ) {
6114 if ( jQuery.isArray(obj) && obj.length ) {
6115 // Serialize array item.
6116 jQuery.each( obj, function( i, v ) {
6117 if ( traditional || rbracket.test( prefix ) ) {
6118 // Treat each array item as a scalar.
6119 add( prefix, v );
6121 } else {
6122 // If array item is non-scalar (array or object), encode its
6123 // numeric index to resolve deserialization ambiguity issues.
6124 // Note that rack (as of 1.0.0) can't currently deserialize
6125 // nested arrays properly, and attempting to do so may cause
6126 // a server error. Possible fixes are to modify rack's
6127 // deserialization algorithm or to provide an option or flag
6128 // to force array serialization to be shallow.
6129 buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
6133 } else if ( !traditional && obj != null && typeof obj === "object" ) {
6134 if ( jQuery.isEmptyObject( obj ) ) {
6135 add( prefix, "" );
6137 // Serialize object item.
6138 } else {
6139 jQuery.each( obj, function( k, v ) {
6140 buildParams( prefix + "[" + k + "]", v, traditional, add );
6144 } else {
6145 // Serialize scalar item.
6146 add( prefix, obj );
6150 // This is still on the jQuery object... for now
6151 // Want to move this to jQuery.ajax some day
6152 jQuery.extend({
6154 // Counter for holding the number of active queries
6155 active: 0,
6157 // Last-Modified header cache for next request
6158 lastModified: {},
6159 etag: {},
6161 handleError: function( s, xhr, status, e ) {
6162 // If a local callback was specified, fire it
6163 if ( s.error ) {
6164 s.error.call( s.context, xhr, status, e );
6167 // Fire the global callback
6168 if ( s.global ) {
6169 jQuery.triggerGlobal( s, "ajaxError", [xhr, s, e] );
6173 handleSuccess: function( s, xhr, status, data ) {
6174 // If a local callback was specified, fire it and pass it the data
6175 if ( s.success ) {
6176 s.success.call( s.context, data, status, xhr );
6179 // Fire the global callback
6180 if ( s.global ) {
6181 jQuery.triggerGlobal( s, "ajaxSuccess", [xhr, s] );
6185 handleComplete: function( s, xhr, status ) {
6186 // Process result
6187 if ( s.complete ) {
6188 s.complete.call( s.context, xhr, status );
6191 // The request was completed
6192 if ( s.global ) {
6193 jQuery.triggerGlobal( s, "ajaxComplete", [xhr, s] );
6196 // Handle the global AJAX counter
6197 if ( s.global && jQuery.active-- === 1 ) {
6198 jQuery.event.trigger( "ajaxStop" );
6202 triggerGlobal: function( s, type, args ) {
6203 (s.context && s.context.url == null ? jQuery(s.context) : jQuery.event).trigger(type, args);
6206 // Determines if an XMLHttpRequest was successful or not
6207 httpSuccess: function( xhr ) {
6208 try {
6209 // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
6210 return !xhr.status && location.protocol === "file:" ||
6211 xhr.status >= 200 && xhr.status < 300 ||
6212 xhr.status === 304 || xhr.status === 1223;
6213 } catch(e) {}
6215 return false;
6218 // Determines if an XMLHttpRequest returns NotModified
6219 httpNotModified: function( xhr, url ) {
6220 var lastModified = xhr.getResponseHeader("Last-Modified"),
6221 etag = xhr.getResponseHeader("Etag");
6223 if ( lastModified ) {
6224 jQuery.lastModified[url] = lastModified;
6227 if ( etag ) {
6228 jQuery.etag[url] = etag;
6231 return xhr.status === 304;
6234 httpData: function( xhr, type, s ) {
6235 var ct = xhr.getResponseHeader("content-type") || "",
6236 xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
6237 data = xml ? xhr.responseXML : xhr.responseText;
6239 if ( xml && data.documentElement.nodeName === "parsererror" ) {
6240 jQuery.error( "parsererror" );
6243 // Allow a pre-filtering function to sanitize the response
6244 // s is checked to keep backwards compatibility
6245 if ( s && s.dataFilter ) {
6246 data = s.dataFilter( data, type );
6249 // The filter can actually parse the response
6250 if ( typeof data === "string" ) {
6251 // Get the JavaScript object, if JSON is used.
6252 if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
6253 data = jQuery.parseJSON( data );
6255 // If the type is "script", eval it in global context
6256 } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
6257 jQuery.globalEval( data );
6261 return data;
6267 * Create the request object; Microsoft failed to properly
6268 * implement the XMLHttpRequest in IE7 (can't request local files),
6269 * so we use the ActiveXObject when it is available
6270 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
6271 * we need a fallback.
6273 if ( window.ActiveXObject ) {
6274 jQuery.ajaxSettings.xhr = function() {
6275 if ( window.location.protocol !== "file:" ) {
6276 try {
6277 return new window.XMLHttpRequest();
6278 } catch(xhrError) {}
6281 try {
6282 return new window.ActiveXObject("Microsoft.XMLHTTP");
6283 } catch(activeError) {}
6287 // Does this browser support XHR requests?
6288 jQuery.support.ajax = !!jQuery.ajaxSettings.xhr();
6293 var elemdisplay = {},
6294 rfxtypes = /^(?:toggle|show|hide)$/,
6295 rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/,
6296 timerId,
6297 fxAttrs = [
6298 // height animations
6299 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
6300 // width animations
6301 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
6302 // opacity animations
6303 [ "opacity" ]
6306 jQuery.fn.extend({
6307 show: function( speed, easing, callback ) {
6308 var elem, display;
6310 if ( speed || speed === 0 ) {
6311 return this.animate( genFx("show", 3), speed, easing, callback);
6313 } else {
6314 for ( var i = 0, j = this.length; i < j; i++ ) {
6315 elem = this[i];
6316 display = elem.style.display;
6318 // Reset the inline display of this element to learn if it is
6319 // being hidden by cascaded rules or not
6320 if ( !jQuery.data(elem, "olddisplay") && display === "none" ) {
6321 display = elem.style.display = "";
6324 // Set elements which have been overridden with display: none
6325 // in a stylesheet to whatever the default browser style is
6326 // for such an element
6327 if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
6328 jQuery.data(elem, "olddisplay", defaultDisplay(elem.nodeName));
6332 // Set the display of most of the elements in a second loop
6333 // to avoid the constant reflow
6334 for ( i = 0; i < j; i++ ) {
6335 elem = this[i];
6336 display = elem.style.display;
6338 if ( display === "" || display === "none" ) {
6339 elem.style.display = jQuery.data(elem, "olddisplay") || "";
6343 return this;
6347 hide: function( speed, easing, callback ) {
6348 if ( speed || speed === 0 ) {
6349 return this.animate( genFx("hide", 3), speed, easing, callback);
6351 } else {
6352 for ( var i = 0, j = this.length; i < j; i++ ) {
6353 var display = jQuery.css( this[i], "display" );
6355 if ( display !== "none" ) {
6356 jQuery.data( this[i], "olddisplay", display );
6360 // Set the display of the elements in a second loop
6361 // to avoid the constant reflow
6362 for ( i = 0; i < j; i++ ) {
6363 this[i].style.display = "none";
6366 return this;
6370 // Save the old toggle function
6371 _toggle: jQuery.fn.toggle,
6373 toggle: function( fn, fn2, callback ) {
6374 var bool = typeof fn === "boolean";
6376 if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
6377 this._toggle.apply( this, arguments );
6379 } else if ( fn == null || bool ) {
6380 this.each(function() {
6381 var state = bool ? fn : jQuery(this).is(":hidden");
6382 jQuery(this)[ state ? "show" : "hide" ]();
6385 } else {
6386 this.animate(genFx("toggle", 3), fn, fn2, callback);
6389 return this;
6392 fadeTo: function( speed, to, easing, callback ) {
6393 return this.filter(":hidden").css("opacity", 0).show().end()
6394 .animate({opacity: to}, speed, easing, callback);
6397 animate: function( prop, speed, easing, callback ) {
6398 var optall = jQuery.speed(speed, easing, callback);
6400 if ( jQuery.isEmptyObject( prop ) ) {
6401 return this.each( optall.complete );
6404 return this[ optall.queue === false ? "each" : "queue" ](function() {
6405 // XXX 'this' does not always have a nodeName when running the
6406 // test suite
6408 var opt = jQuery.extend({}, optall), p,
6409 isElement = this.nodeType === 1,
6410 hidden = isElement && jQuery(this).is(":hidden"),
6411 self = this;
6413 for ( p in prop ) {
6414 var name = jQuery.camelCase( p );
6416 if ( p !== name ) {
6417 prop[ name ] = prop[ p ];
6418 delete prop[ p ];
6419 p = name;
6422 if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
6423 return opt.complete.call(this);
6426 if ( isElement && ( p === "height" || p === "width" ) ) {
6427 // Make sure that nothing sneaks out
6428 // Record all 3 overflow attributes because IE does not
6429 // change the overflow attribute when overflowX and
6430 // overflowY are set to the same value
6431 opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
6433 // Set display property to inline-block for height/width
6434 // animations on inline elements that are having width/height
6435 // animated
6436 if ( jQuery.css( this, "display" ) === "inline" &&
6437 jQuery.css( this, "float" ) === "none" ) {
6438 if ( !jQuery.support.inlineBlockNeedsLayout ) {
6439 this.style.display = "inline-block";
6441 } else {
6442 var display = defaultDisplay(this.nodeName);
6444 // inline-level elements accept inline-block;
6445 // block-level elements need to be inline with layout
6446 if ( display === "inline" ) {
6447 this.style.display = "inline-block";
6449 } else {
6450 this.style.display = "inline";
6451 this.style.zoom = 1;
6457 if ( jQuery.isArray( prop[p] ) ) {
6458 // Create (if needed) and add to specialEasing
6459 (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
6460 prop[p] = prop[p][0];
6464 if ( opt.overflow != null ) {
6465 this.style.overflow = "hidden";
6468 opt.curAnim = jQuery.extend({}, prop);
6470 jQuery.each( prop, function( name, val ) {
6471 var e = new jQuery.fx( self, opt, name );
6473 if ( rfxtypes.test(val) ) {
6474 e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
6476 } else {
6477 var parts = rfxnum.exec(val),
6478 start = e.cur() || 0;
6480 if ( parts ) {
6481 var end = parseFloat( parts[2] ),
6482 unit = parts[3] || "px";
6484 // We need to compute starting value
6485 if ( unit !== "px" ) {
6486 jQuery.style( self, name, (end || 1) + unit);
6487 start = ((end || 1) / e.cur()) * start;
6488 jQuery.style( self, name, start + unit);
6491 // If a +=/-= token was provided, we're doing a relative animation
6492 if ( parts[1] ) {
6493 end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
6496 e.custom( start, end, unit );
6498 } else {
6499 e.custom( start, val, "" );
6504 // For JS strict compliance
6505 return true;
6509 stop: function( clearQueue, gotoEnd ) {
6510 var timers = jQuery.timers;
6512 if ( clearQueue ) {
6513 this.queue([]);
6516 this.each(function() {
6517 // go in reverse order so anything added to the queue during the loop is ignored
6518 for ( var i = timers.length - 1; i >= 0; i-- ) {
6519 if ( timers[i].elem === this ) {
6520 if (gotoEnd) {
6521 // force the next step to be the last
6522 timers[i](true);
6525 timers.splice(i, 1);
6530 // start the next in the queue if the last step wasn't forced
6531 if ( !gotoEnd ) {
6532 this.dequeue();
6535 return this;
6540 function genFx( type, num ) {
6541 var obj = {};
6543 jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
6544 obj[ this ] = type;
6547 return obj;
6550 // Generate shortcuts for custom animations
6551 jQuery.each({
6552 slideDown: genFx("show", 1),
6553 slideUp: genFx("hide", 1),
6554 slideToggle: genFx("toggle", 1),
6555 fadeIn: { opacity: "show" },
6556 fadeOut: { opacity: "hide" },
6557 fadeToggle: { opacity: "toggle" }
6558 }, function( name, props ) {
6559 jQuery.fn[ name ] = function( speed, easing, callback ) {
6560 return this.animate( props, speed, easing, callback );
6564 jQuery.extend({
6565 speed: function( speed, easing, fn ) {
6566 var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
6567 complete: fn || !fn && easing ||
6568 jQuery.isFunction( speed ) && speed,
6569 duration: speed,
6570 easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
6573 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
6574 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;
6576 // Queueing
6577 opt.old = opt.complete;
6578 opt.complete = function() {
6579 if ( opt.queue !== false ) {
6580 jQuery(this).dequeue();
6582 if ( jQuery.isFunction( opt.old ) ) {
6583 opt.old.call( this );
6587 return opt;
6590 easing: {
6591 linear: function( p, n, firstNum, diff ) {
6592 return firstNum + diff * p;
6594 swing: function( p, n, firstNum, diff ) {
6595 return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
6599 timers: [],
6601 fx: function( elem, options, prop ) {
6602 this.options = options;
6603 this.elem = elem;
6604 this.prop = prop;
6606 if ( !options.orig ) {
6607 options.orig = {};
6613 jQuery.fx.prototype = {
6614 // Simple function for setting a style value
6615 update: function() {
6616 if ( this.options.step ) {
6617 this.options.step.call( this.elem, this.now, this );
6620 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
6623 // Get the current size
6624 cur: function() {
6625 if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
6626 return this.elem[ this.prop ];
6629 var r = parseFloat( jQuery.css( this.elem, this.prop ) );
6630 return r && r > -10000 ? r : 0;
6633 // Start an animation from one number to another
6634 custom: function( from, to, unit ) {
6635 var self = this,
6636 fx = jQuery.fx;
6638 this.startTime = jQuery.now();
6639 this.start = from;
6640 this.end = to;
6641 this.unit = unit || this.unit || "px";
6642 this.now = this.start;
6643 this.pos = this.state = 0;
6645 function t( gotoEnd ) {
6646 return self.step(gotoEnd);
6649 t.elem = this.elem;
6651 if ( t() && jQuery.timers.push(t) && !timerId ) {
6652 timerId = setInterval(fx.tick, fx.interval);
6656 // Simple 'show' function
6657 show: function() {
6658 // Remember where we started, so that we can go back to it later
6659 this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
6660 this.options.show = true;
6662 // Begin the animation
6663 // Make sure that we start at a small width/height to avoid any
6664 // flash of content
6665 this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
6667 // Start by showing the element
6668 jQuery( this.elem ).show();
6671 // Simple 'hide' function
6672 hide: function() {
6673 // Remember where we started, so that we can go back to it later
6674 this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
6675 this.options.hide = true;
6677 // Begin the animation
6678 this.custom(this.cur(), 0);
6681 // Each step of an animation
6682 step: function( gotoEnd ) {
6683 var t = jQuery.now(), done = true;
6685 if ( gotoEnd || t >= this.options.duration + this.startTime ) {
6686 this.now = this.end;
6687 this.pos = this.state = 1;
6688 this.update();
6690 this.options.curAnim[ this.prop ] = true;
6692 for ( var i in this.options.curAnim ) {
6693 if ( this.options.curAnim[i] !== true ) {
6694 done = false;
6698 if ( done ) {
6699 // Reset the overflow
6700 if ( this.options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
6701 var elem = this.elem,
6702 options = this.options;
6704 jQuery.each( [ "", "X", "Y" ], function (index, value) {
6705 elem.style[ "overflow" + value ] = options.overflow[index];
6706 } );
6709 // Hide the element if the "hide" operation was done
6710 if ( this.options.hide ) {
6711 jQuery(this.elem).hide();
6714 // Reset the properties, if the item has been hidden or shown
6715 if ( this.options.hide || this.options.show ) {
6716 for ( var p in this.options.curAnim ) {
6717 jQuery.style( this.elem, p, this.options.orig[p] );
6721 // Execute the complete function
6722 this.options.complete.call( this.elem );
6725 return false;
6727 } else {
6728 var n = t - this.startTime;
6729 this.state = n / this.options.duration;
6731 // Perform the easing function, defaults to swing
6732 var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
6733 var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
6734 this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
6735 this.now = this.start + ((this.end - this.start) * this.pos);
6737 // Perform the next step of the animation
6738 this.update();
6741 return true;
6745 jQuery.extend( jQuery.fx, {
6746 tick: function() {
6747 var timers = jQuery.timers;
6749 for ( var i = 0; i < timers.length; i++ ) {
6750 if ( !timers[i]() ) {
6751 timers.splice(i--, 1);
6755 if ( !timers.length ) {
6756 jQuery.fx.stop();
6760 interval: 13,
6762 stop: function() {
6763 clearInterval( timerId );
6764 timerId = null;
6767 speeds: {
6768 slow: 600,
6769 fast: 200,
6770 // Default speed
6771 _default: 400
6774 step: {
6775 opacity: function( fx ) {
6776 jQuery.style( fx.elem, "opacity", fx.now );
6779 _default: function( fx ) {
6780 if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
6781 fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
6782 } else {
6783 fx.elem[ fx.prop ] = fx.now;
6789 if ( jQuery.expr && jQuery.expr.filters ) {
6790 jQuery.expr.filters.animated = function( elem ) {
6791 return jQuery.grep(jQuery.timers, function( fn ) {
6792 return elem === fn.elem;
6793 }).length;
6797 function defaultDisplay( nodeName ) {
6798 if ( !elemdisplay[ nodeName ] ) {
6799 var elem = jQuery("<" + nodeName + ">").appendTo("body"),
6800 display = elem.css("display");
6802 elem.remove();
6804 if ( display === "none" || display === "" ) {
6805 display = "block";
6808 elemdisplay[ nodeName ] = display;
6811 return elemdisplay[ nodeName ];
6817 var rtable = /^t(?:able|d|h)$/i,
6818 rroot = /^(?:body|html)$/i;
6820 if ( "getBoundingClientRect" in document.documentElement ) {
6821 jQuery.fn.offset = function( options ) {
6822 var elem = this[0], box;
6824 if ( options ) {
6825 return this.each(function( i ) {
6826 jQuery.offset.setOffset( this, options, i );
6830 if ( !elem || !elem.ownerDocument ) {
6831 return null;
6834 if ( elem === elem.ownerDocument.body ) {
6835 return jQuery.offset.bodyOffset( elem );
6838 try {
6839 box = elem.getBoundingClientRect();
6840 } catch(e) {}
6842 var doc = elem.ownerDocument,
6843 docElem = doc.documentElement;
6845 // Make sure we're not dealing with a disconnected DOM node
6846 if ( !box || !jQuery.contains( docElem, elem ) ) {
6847 return box || { top: 0, left: 0 };
6850 var body = doc.body,
6851 win = getWindow(doc),
6852 clientTop = docElem.clientTop || body.clientTop || 0,
6853 clientLeft = docElem.clientLeft || body.clientLeft || 0,
6854 scrollTop = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ),
6855 scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft),
6856 top = box.top + scrollTop - clientTop,
6857 left = box.left + scrollLeft - clientLeft;
6859 return { top: top, left: left };
6862 } else {
6863 jQuery.fn.offset = function( options ) {
6864 var elem = this[0];
6866 if ( options ) {
6867 return this.each(function( i ) {
6868 jQuery.offset.setOffset( this, options, i );
6872 if ( !elem || !elem.ownerDocument ) {
6873 return null;
6876 if ( elem === elem.ownerDocument.body ) {
6877 return jQuery.offset.bodyOffset( elem );
6880 jQuery.offset.initialize();
6882 var computedStyle,
6883 offsetParent = elem.offsetParent,
6884 prevOffsetParent = elem,
6885 doc = elem.ownerDocument,
6886 docElem = doc.documentElement,
6887 body = doc.body,
6888 defaultView = doc.defaultView,
6889 prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
6890 top = elem.offsetTop,
6891 left = elem.offsetLeft;
6893 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
6894 if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
6895 break;
6898 computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
6899 top -= elem.scrollTop;
6900 left -= elem.scrollLeft;
6902 if ( elem === offsetParent ) {
6903 top += elem.offsetTop;
6904 left += elem.offsetLeft;
6906 if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
6907 top += parseFloat( computedStyle.borderTopWidth ) || 0;
6908 left += parseFloat( computedStyle.borderLeftWidth ) || 0;
6911 prevOffsetParent = offsetParent;
6912 offsetParent = elem.offsetParent;
6915 if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
6916 top += parseFloat( computedStyle.borderTopWidth ) || 0;
6917 left += parseFloat( computedStyle.borderLeftWidth ) || 0;
6920 prevComputedStyle = computedStyle;
6923 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
6924 top += body.offsetTop;
6925 left += body.offsetLeft;
6928 if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
6929 top += Math.max( docElem.scrollTop, body.scrollTop );
6930 left += Math.max( docElem.scrollLeft, body.scrollLeft );
6933 return { top: top, left: left };
6937 jQuery.offset = {
6938 initialize: function() {
6939 var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0,
6940 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>";
6942 jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
6944 container.innerHTML = html;
6945 body.insertBefore( container, body.firstChild );
6946 innerDiv = container.firstChild;
6947 checkDiv = innerDiv.firstChild;
6948 td = innerDiv.nextSibling.firstChild.firstChild;
6950 this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
6951 this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
6953 checkDiv.style.position = "fixed";
6954 checkDiv.style.top = "20px";
6956 // safari subtracts parent border width here which is 5px
6957 this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
6958 checkDiv.style.position = checkDiv.style.top = "";
6960 innerDiv.style.overflow = "hidden";
6961 innerDiv.style.position = "relative";
6963 this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
6965 this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
6967 body.removeChild( container );
6968 body = container = innerDiv = checkDiv = table = td = null;
6969 jQuery.offset.initialize = jQuery.noop;
6972 bodyOffset: function( body ) {
6973 var top = body.offsetTop,
6974 left = body.offsetLeft;
6976 jQuery.offset.initialize();
6978 if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
6979 top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
6980 left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
6983 return { top: top, left: left };
6986 setOffset: function( elem, options, i ) {
6987 var position = jQuery.css( elem, "position" );
6989 // set position first, in-case top/left are set even on static elem
6990 if ( position === "static" ) {
6991 elem.style.position = "relative";
6994 var curElem = jQuery( elem ),
6995 curOffset = curElem.offset(),
6996 curCSSTop = jQuery.css( elem, "top" ),
6997 curCSSLeft = jQuery.css( elem, "left" ),
6998 calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1),
6999 props = {}, curPosition = {}, curTop, curLeft;
7001 // need to be able to calculate position if either top or left is auto and position is absolute
7002 if ( calculatePosition ) {
7003 curPosition = curElem.position();
7006 curTop = calculatePosition ? curPosition.top : parseInt( curCSSTop, 10 ) || 0;
7007 curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0;
7009 if ( jQuery.isFunction( options ) ) {
7010 options = options.call( elem, i, curOffset );
7013 if (options.top != null) {
7014 props.top = (options.top - curOffset.top) + curTop;
7016 if (options.left != null) {
7017 props.left = (options.left - curOffset.left) + curLeft;
7020 if ( "using" in options ) {
7021 options.using.call( elem, props );
7022 } else {
7023 curElem.css( props );
7029 jQuery.fn.extend({
7030 position: function() {
7031 if ( !this[0] ) {
7032 return null;
7035 var elem = this[0],
7037 // Get *real* offsetParent
7038 offsetParent = this.offsetParent(),
7040 // Get correct offsets
7041 offset = this.offset(),
7042 parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
7044 // Subtract element margins
7045 // note: when an element has margin: auto the offsetLeft and marginLeft
7046 // are the same in Safari causing offset.left to incorrectly be 0
7047 offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
7048 offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
7050 // Add offsetParent borders
7051 parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
7052 parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
7054 // Subtract the two offsets
7055 return {
7056 top: offset.top - parentOffset.top,
7057 left: offset.left - parentOffset.left
7061 offsetParent: function() {
7062 return this.map(function() {
7063 var offsetParent = this.offsetParent || document.body;
7064 while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
7065 offsetParent = offsetParent.offsetParent;
7067 return offsetParent;
7073 // Create scrollLeft and scrollTop methods
7074 jQuery.each( ["Left", "Top"], function( i, name ) {
7075 var method = "scroll" + name;
7077 jQuery.fn[ method ] = function(val) {
7078 var elem = this[0], win;
7080 if ( !elem ) {
7081 return null;
7084 if ( val !== undefined ) {
7085 // Set the scroll offset
7086 return this.each(function() {
7087 win = getWindow( this );
7089 if ( win ) {
7090 win.scrollTo(
7091 !i ? val : jQuery(win).scrollLeft(),
7092 i ? val : jQuery(win).scrollTop()
7095 } else {
7096 this[ method ] = val;
7099 } else {
7100 win = getWindow( elem );
7102 // Return the scroll offset
7103 return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
7104 jQuery.support.boxModel && win.document.documentElement[ method ] ||
7105 win.document.body[ method ] :
7106 elem[ method ];
7111 function getWindow( elem ) {
7112 return jQuery.isWindow( elem ) ?
7113 elem :
7114 elem.nodeType === 9 ?
7115 elem.defaultView || elem.parentWindow :
7116 false;
7122 // Create innerHeight, innerWidth, outerHeight and outerWidth methods
7123 jQuery.each([ "Height", "Width" ], function( i, name ) {
7125 var type = name.toLowerCase();
7127 // innerHeight and innerWidth
7128 jQuery.fn["inner" + name] = function() {
7129 return this[0] ?
7130 parseFloat( jQuery.css( this[0], type, "padding" ) ) :
7131 null;
7134 // outerHeight and outerWidth
7135 jQuery.fn["outer" + name] = function( margin ) {
7136 return this[0] ?
7137 parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) :
7138 null;
7141 jQuery.fn[ type ] = function( size ) {
7142 // Get window width or height
7143 var elem = this[0];
7144 if ( !elem ) {
7145 return size == null ? null : this;
7148 if ( jQuery.isFunction( size ) ) {
7149 return this.each(function( i ) {
7150 var self = jQuery( this );
7151 self[ type ]( size.call( this, i, self[ type ]() ) );
7155 if ( jQuery.isWindow( elem ) ) {
7156 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
7157 return elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
7158 elem.document.body[ "client" + name ];
7160 // Get document width or height
7161 } else if ( elem.nodeType === 9 ) {
7162 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
7163 return Math.max(
7164 elem.documentElement["client" + name],
7165 elem.body["scroll" + name], elem.documentElement["scroll" + name],
7166 elem.body["offset" + name], elem.documentElement["offset" + name]
7169 // Get or set width or height on the element
7170 } else if ( size === undefined ) {
7171 var orig = jQuery.css( elem, type ),
7172 ret = parseFloat( orig );
7174 return jQuery.isNaN( ret ) ? orig : ret;
7176 // Set the width or height on the element (default to pixels if value is unitless)
7177 } else {
7178 return this.css( type, typeof size === "string" ? size : size + "px" );
7185 })(window);