2 * jQuery JavaScript Library v1.3
5 * Copyright (c) 2009 John Resig
6 * Dual licensed under the MIT and GPL licenses.
7 * http://docs.jquery.com/License
9 * Date: 2009-01-13 12:50:31 -0500 (Tue, 13 Jan 2009)
15 // Will speed up references to window, and allows munging its name.
17 // Will speed up references to undefined, and allows munging its name.
19 // Map over jQuery in case of overwrite
20 _jQuery = window.jQuery,
21 // Map over the $ in case of overwrite
24 jQuery = window.jQuery = window.$ = function( selector, context ) {
25 // The jQuery object is actually just the init constructor 'enhanced'
26 return new jQuery.fn.init( selector, context );
29 // A simple way to check for HTML strings or ID strings
30 // (both of which we optimize for)
31 quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
32 // Is it a simple selector
33 isSimple = /^.[^:#\[\.,]*$/;
35 jQuery.fn = jQuery.prototype = {
36 init: function( selector, context ) {
37 // Make sure that a selection was provided
38 selector = selector || document;
40 // Handle $(DOMElement)
41 if ( selector.nodeType ) {
44 this.context = selector;
47 // Handle HTML strings
48 if ( typeof selector === "string" ) {
49 // Are we dealing with HTML string or an ID?
50 var match = quickExpr.exec( selector );
52 // Verify a match, and that no context was specified for #id
53 if ( match && (match[1] || !context) ) {
55 // HANDLE: $(html) -> $(array)
57 selector = jQuery.clean( [ match[1] ], context );
61 var elem = document.getElementById( match[3] );
63 // Make sure an element was located
65 // Handle the case where IE and Opera return items
66 // by name instead of ID
67 if ( elem.id != match[3] )
68 return jQuery().find( selector );
70 // Otherwise, we inject the element directly into the jQuery object
71 var ret = jQuery( elem );
72 ret.context = document;
73 ret.selector = selector;
79 // HANDLE: $(expr, [context])
80 // (which is just equivalent to: $(content).find(expr)
82 return jQuery( context ).find( selector );
84 // HANDLE: $(function)
85 // Shortcut for document ready
86 } else if ( jQuery.isFunction( selector ) )
87 return jQuery( document ).ready( selector );
89 // Make sure that old selector state is passed along
90 if ( selector.selector && selector.context ) {
91 this.selector = selector.selector;
92 this.context = selector.context;
95 return this.setArray(jQuery.makeArray(selector));
98 // Start with an empty selector
101 // The current version of jQuery being used
104 // The number of elements contained in the matched element set
109 // Get the Nth element in the matched element set OR
110 // Get the whole matched element set as a clean array
111 get: function( num ) {
112 return num === undefined ?
114 // Return a 'clean' array
115 jQuery.makeArray( this ) :
117 // Return just the object
121 // Take an array of elements and push it onto the stack
122 // (returning the new matched element set)
123 pushStack: function( elems, name, selector ) {
124 // Build a new jQuery matched element set
125 var ret = jQuery( elems );
127 // Add the old object onto the stack (as a reference)
128 ret.prevObject = this;
130 ret.context = this.context;
132 if ( name === "find" )
133 ret.selector = this.selector + (this.selector ? " " : "") + selector;
135 ret.selector = this.selector + "." + name + "(" + selector + ")";
137 // Return the newly-formed element set
141 // Force the current matched set of elements to become
142 // the specified array of elements (destroying the stack in the process)
143 // You should use pushStack() in order to do this, but maintain the stack
144 setArray: function( elems ) {
145 // Resetting the length to 0, then using the native Array push
146 // is a super-fast way to populate an object with array-like properties
148 Array.prototype.push.apply( this, elems );
153 // Execute a callback for every element in the matched set.
154 // (You can seed the arguments with an array of args, but this is
155 // only used internally.)
156 each: function( callback, args ) {
157 return jQuery.each( this, callback, args );
160 // Determine the position of an element within
161 // the matched set of elements
162 index: function( elem ) {
163 // Locate the position of the desired element
164 return jQuery.inArray(
165 // If it receives a jQuery object, the first element is used
166 elem && elem.jquery ? elem[0] : elem
170 attr: function( name, value, type ) {
173 // Look for the case where we're accessing a style value
174 if ( typeof name === "string" )
175 if ( value === undefined )
176 return this[0] && jQuery[ type || "attr" ]( this[0], name );
180 options[ name ] = value;
183 // Check to see if we're setting style values
184 return this.each(function(i){
185 // Set all the styles
186 for ( name in options )
191 name, jQuery.prop( this, options[ name ], type, i, name )
196 css: function( key, value ) {
197 // ignore negative width and height values
198 if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
200 return this.attr( key, value, "curCSS" );
203 text: function( text ) {
204 if ( typeof text !== "object" && text != null )
205 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
209 jQuery.each( text || this, function(){
210 jQuery.each( this.childNodes, function(){
211 if ( this.nodeType != 8 )
212 ret += this.nodeType != 1 ?
214 jQuery.fn.text( [ this ] );
221 wrapAll: function( html ) {
223 // The elements to wrap the target around
224 var wrap = jQuery( html, this[0].ownerDocument ).clone();
226 if ( this[0].parentNode )
227 wrap.insertBefore( this[0] );
232 while ( elem.firstChild )
233 elem = elem.firstChild;
242 wrapInner: function( html ) {
243 return this.each(function(){
244 jQuery( this ).contents().wrapAll( html );
248 wrap: function( html ) {
249 return this.each(function(){
250 jQuery( this ).wrapAll( html );
255 return this.domManip(arguments, true, function(elem){
256 if (this.nodeType == 1)
257 this.appendChild( elem );
261 prepend: function() {
262 return this.domManip(arguments, true, function(elem){
263 if (this.nodeType == 1)
264 this.insertBefore( elem, this.firstChild );
269 return this.domManip(arguments, false, function(elem){
270 this.parentNode.insertBefore( elem, this );
275 return this.domManip(arguments, false, function(elem){
276 this.parentNode.insertBefore( elem, this.nextSibling );
281 return this.prevObject || jQuery( [] );
284 // For internal use only.
285 // Behaves like an Array's .push method, not like a jQuery method.
288 find: function( selector ) {
289 if ( this.length === 1 && !/,/.test(selector) ) {
290 var ret = this.pushStack( [], "find", selector );
292 jQuery.find( selector, this[0], ret );
295 var elems = jQuery.map(this, function(elem){
296 return jQuery.find( selector, elem );
299 return this.pushStack( /[^+>] [^+>]/.test( selector ) ?
300 jQuery.unique( elems ) :
301 elems, "find", selector );
305 clone: function( events ) {
307 var ret = this.map(function(){
308 if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
309 // IE copies events bound via attachEvent when
310 // using cloneNode. Calling detachEvent on the
311 // clone will also remove the events from the orignal
312 // In order to get around this, we use innerHTML.
313 // Unfortunately, this means some modifications to
314 // attributes in IE that are actually only stored
315 // as properties will not be copied (such as the
316 // the name attribute on an input).
317 var clone = this.cloneNode(true),
318 container = document.createElement("div");
319 container.appendChild(clone);
320 return jQuery.clean([container.innerHTML])[0];
322 return this.cloneNode(true);
325 // Need to set the expando to null on the cloned set if it exists
326 // removeData doesn't work here, IE removes it from the original as well
327 // this is primarily for IE but the data expando shouldn't be copied over in any browser
328 var clone = ret.find("*").andSelf().each(function(){
329 if ( this[ expando ] !== undefined )
330 this[ expando ] = null;
333 // Copy the events from the original to the clone
334 if ( events === true )
335 this.find("*").andSelf().each(function(i){
336 if (this.nodeType == 3)
338 var events = jQuery.data( this, "events" );
340 for ( var type in events )
341 for ( var handler in events[ type ] )
342 jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
345 // Return the cloned set
349 filter: function( selector ) {
350 return this.pushStack(
351 jQuery.isFunction( selector ) &&
352 jQuery.grep(this, function(elem, i){
353 return selector.call( elem, i );
356 jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
357 return elem.nodeType === 1;
358 }) ), "filter", selector );
361 closest: function( selector ) {
362 var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null;
364 return this.map(function(){
366 while ( cur && cur.ownerDocument ) {
367 if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) )
369 cur = cur.parentNode;
374 not: function( selector ) {
375 if ( typeof selector === "string" )
376 // test special case where just one selector is passed in
377 if ( isSimple.test( selector ) )
378 return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
380 selector = jQuery.multiFilter( selector, this );
382 var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
383 return this.filter(function() {
384 return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
388 add: function( selector ) {
389 return this.pushStack( jQuery.unique( jQuery.merge(
391 typeof selector === "string" ?
393 jQuery.makeArray( selector )
397 is: function( selector ) {
398 return !!selector && jQuery.multiFilter( selector, this ).length > 0;
401 hasClass: function( selector ) {
402 return !!selector && this.is( "." + selector );
405 val: function( value ) {
406 if ( value === undefined ) {
410 if( jQuery.nodeName( elem, 'option' ) )
411 return (elem.attributes.value || {}).specified ? elem.value : elem.text;
413 // We need to handle select boxes special
414 if ( jQuery.nodeName( elem, "select" ) ) {
415 var index = elem.selectedIndex,
417 options = elem.options,
418 one = elem.type == "select-one";
420 // Nothing was selected
424 // Loop through all the selected options
425 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
426 var option = options[ i ];
428 if ( option.selected ) {
429 // Get the specifc value for the option
430 value = jQuery(option).val();
432 // We don't need an array for one selects
436 // Multi-Selects return an array
437 values.push( value );
444 // Everything else, we just grab the value
445 return (elem.value || "").replace(/\r/g, "");
452 if ( typeof value === "number" )
455 return this.each(function(){
456 if ( this.nodeType != 1 )
459 if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
460 this.checked = (jQuery.inArray(this.value, value) >= 0 ||
461 jQuery.inArray(this.name, value) >= 0);
463 else if ( jQuery.nodeName( this, "select" ) ) {
464 var values = jQuery.makeArray(value);
466 jQuery( "option", this ).each(function(){
467 this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
468 jQuery.inArray( this.text, values ) >= 0);
471 if ( !values.length )
472 this.selectedIndex = -1;
479 html: function( value ) {
480 return value === undefined ?
484 this.empty().append( value );
487 replaceWith: function( value ) {
488 return this.after( value ).remove();
492 return this.slice( i, +i + 1 );
496 return this.pushStack( Array.prototype.slice.apply( this, arguments ),
497 "slice", Array.prototype.slice.call(arguments).join(",") );
500 map: function( callback ) {
501 return this.pushStack( jQuery.map(this, function(elem, i){
502 return callback.call( elem, i, elem );
506 andSelf: function() {
507 return this.add( this.prevObject );
510 domManip: function( args, table, callback ) {
512 var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
513 scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
514 first = fragment.firstChild,
515 extra = this.length > 1 ? fragment.cloneNode(true) : fragment;
518 for ( var i = 0, l = this.length; i < l; i++ )
519 callback.call( root(this[i], first), i > 0 ? extra.cloneNode(true) : fragment );
522 jQuery.each( scripts, evalScript );
527 function root( elem, cur ) {
528 return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
529 (elem.getElementsByTagName("tbody")[0] ||
530 elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
536 // Give the init function the jQuery prototype for later instantiation
537 jQuery.fn.init.prototype = jQuery.fn;
539 function evalScript( i, elem ) {
548 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
550 if ( elem.parentNode )
551 elem.parentNode.removeChild( elem );
558 jQuery.extend = jQuery.fn.extend = function() {
559 // copy reference to target object
560 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
562 // Handle a deep copy situation
563 if ( typeof target === "boolean" ) {
565 target = arguments[1] || {};
566 // skip the boolean and the target
570 // Handle case when target is a string or something (possible in deep copy)
571 if ( typeof target !== "object" && !jQuery.isFunction(target) )
574 // extend jQuery itself if only one argument is passed
580 for ( ; i < length; i++ )
581 // Only deal with non-null/undefined values
582 if ( (options = arguments[ i ]) != null )
583 // Extend the base object
584 for ( var name in options ) {
585 var src = target[ name ], copy = options[ name ];
587 // Prevent never-ending loop
588 if ( target === copy )
591 // Recurse if we're merging object values
592 if ( deep && copy && typeof copy === "object" && !copy.nodeType )
593 target[ name ] = jQuery.extend( deep,
594 // Never move original objects, clone them
595 src || ( copy.length != null ? [ ] : { } )
598 // Don't bring in undefined values
599 else if ( copy !== undefined )
600 target[ name ] = copy;
604 // Return the modified object
608 // exclude the following css properties to add px
609 var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
611 defaultView = document.defaultView || {},
612 toString = Object.prototype.toString;
615 noConflict: function( deep ) {
619 window.jQuery = _jQuery;
624 // See test/unit/core.js for details concerning isFunction.
625 // Since version 1.3, DOM methods and functions like alert
626 // aren't supported. They return false on IE (#2968).
627 isFunction: function( obj ) {
628 return toString.call(obj) === "[object Function]";
631 isArray: function( obj ) {
632 return toString.call(obj) === "[object Array]";
635 // check if an element is in a (or is an) XML document
636 isXMLDoc: function( elem ) {
637 return elem.documentElement && !elem.body ||
638 elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
641 // Evalulates a script in a global context
642 globalEval: function( data ) {
643 data = jQuery.trim( data );
646 // Inspired by code by Andrea Giammarchi
647 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
648 var head = document.getElementsByTagName("head")[0] || document.documentElement,
649 script = document.createElement("script");
651 script.type = "text/javascript";
652 if ( jQuery.support.scriptEval )
653 script.appendChild( document.createTextNode( data ) );
657 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
658 // This arises when a base node is used (#2709).
659 head.insertBefore( script, head.firstChild );
660 head.removeChild( script );
664 nodeName: function( elem, name ) {
665 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
668 // args is for internal usage only
669 each: function( object, callback, args ) {
670 var name, i = 0, length = object.length;
673 if ( length === undefined ) {
674 for ( name in object )
675 if ( callback.apply( object[ name ], args ) === false )
678 for ( ; i < length; )
679 if ( callback.apply( object[ i++ ], args ) === false )
682 // A special, fast, case for the most common use of each
684 if ( length === undefined ) {
685 for ( name in object )
686 if ( callback.call( object[ name ], name, object[ name ] ) === false )
689 for ( var value = object[0];
690 i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
696 prop: function( elem, value, type, i, name ) {
697 // Handle executable functions
698 if ( jQuery.isFunction( value ) )
699 value = value.call( elem, i );
701 // Handle passing in a number to a CSS property
702 return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
708 // internal only, use addClass("class")
709 add: function( elem, classNames ) {
710 jQuery.each((classNames || "").split(/\s+/), function(i, className){
711 if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
712 elem.className += (elem.className ? " " : "") + className;
716 // internal only, use removeClass("class")
717 remove: function( elem, classNames ) {
718 if (elem.nodeType == 1)
719 elem.className = classNames !== undefined ?
720 jQuery.grep(elem.className.split(/\s+/), function(className){
721 return !jQuery.className.has( classNames, className );
726 // internal only, use hasClass("class")
727 has: function( elem, className ) {
728 return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
732 // A method for quickly swapping in/out CSS properties to get correct calculations
733 swap: function( elem, options, callback ) {
735 // Remember the old values, and insert the new ones
736 for ( var name in options ) {
737 old[ name ] = elem.style[ name ];
738 elem.style[ name ] = options[ name ];
741 callback.call( elem );
743 // Revert the old values
744 for ( var name in options )
745 elem.style[ name ] = old[ name ];
748 css: function( elem, name, force ) {
749 if ( name == "width" || name == "height" ) {
750 var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
753 val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
754 var padding = 0, border = 0;
755 jQuery.each( which, function() {
756 padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
757 border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
759 val -= Math.round(padding + border);
762 if ( jQuery(elem).is(":visible") )
765 jQuery.swap( elem, props, getWH );
767 return Math.max(0, val);
770 return jQuery.curCSS( elem, name, force );
773 curCSS: function( elem, name, force ) {
774 var ret, style = elem.style;
776 // We need to handle opacity special in IE
777 if ( name == "opacity" && !jQuery.support.opacity ) {
778 ret = jQuery.attr( style, "opacity" );
785 // Make sure we're using the right name for getting the float value
786 if ( name.match( /float/i ) )
789 if ( !force && style && style[ name ] )
792 else if ( defaultView.getComputedStyle ) {
794 // Only "float" is needed here
795 if ( name.match( /float/i ) )
798 name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
800 var computedStyle = defaultView.getComputedStyle( elem, null );
803 ret = computedStyle.getPropertyValue( name );
805 // We should always get a number back from opacity
806 if ( name == "opacity" && ret == "" )
809 } else if ( elem.currentStyle ) {
810 var camelCase = name.replace(/\-(\w)/g, function(all, letter){
811 return letter.toUpperCase();
814 ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
816 // From the awesome hack by Dean Edwards
817 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
819 // If we're not dealing with a regular pixel number
820 // but a number that has a weird ending, we need to convert it to pixels
821 if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
822 // Remember the original values
823 var left = style.left, rsLeft = elem.runtimeStyle.left;
825 // Put in the new values to get a computed value out
826 elem.runtimeStyle.left = elem.currentStyle.left;
827 style.left = ret || 0;
828 ret = style.pixelLeft + "px";
830 // Revert the changed values
832 elem.runtimeStyle.left = rsLeft;
839 clean: function( elems, context, fragment ) {
840 context = context || document;
842 // !context.createElement fails in IE with an error but returns typeof 'object'
843 if ( typeof context.createElement === "undefined" )
844 context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
846 // If a single string is passed in and it's a single tag
847 // just do a createElement and skip the rest
848 if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
849 var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
851 return [ context.createElement( match[1] ) ];
854 var ret = [], scripts = [], div = context.createElement("div");
856 jQuery.each(elems, function(i, elem){
857 if ( typeof elem === "number" )
863 // Convert html string into DOM nodes
864 if ( typeof elem === "string" ) {
865 // Fix "XHTML"-style tags in all browsers
866 elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
867 return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
869 front + "></" + tag + ">";
872 // Trim whitespace, otherwise indexOf won't work as expected
873 var tags = jQuery.trim( elem ).toLowerCase();
876 // option or optgroup
877 !tags.indexOf("<opt") &&
878 [ 1, "<select multiple='multiple'>", "</select>" ] ||
880 !tags.indexOf("<leg") &&
881 [ 1, "<fieldset>", "</fieldset>" ] ||
883 tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
884 [ 1, "<table>", "</table>" ] ||
886 !tags.indexOf("<tr") &&
887 [ 2, "<table><tbody>", "</tbody></table>" ] ||
889 // <thead> matched above
890 (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
891 [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
893 !tags.indexOf("<col") &&
894 [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
896 // IE can't serialize <link> and <script> tags normally
897 !jQuery.support.htmlSerialize &&
898 [ 1, "div<div>", "</div>" ] ||
902 // Go to html and back, then peel off extra wrappers
903 div.innerHTML = wrap[1] + elem + wrap[2];
905 // Move to the right depth
909 // Remove IE's autoinserted <tbody> from table fragments
910 if ( !jQuery.support.tbody ) {
912 // String was a <table>, *may* have spurious <tbody>
913 var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
914 div.firstChild && div.firstChild.childNodes :
916 // String was a bare <thead> or <tfoot>
917 wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
921 for ( var j = tbody.length - 1; j >= 0 ; --j )
922 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
923 tbody[ j ].parentNode.removeChild( tbody[ j ] );
927 // IE completely kills leading whitespace when innerHTML is used
928 if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
929 div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
931 elem = jQuery.makeArray( div.childNodes );
937 ret = jQuery.merge( ret, elem );
942 for ( var i = 0; ret[i]; i++ ) {
943 if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
944 scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
946 if ( ret[i].nodeType === 1 )
947 ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
948 fragment.appendChild( ret[i] );
958 attr: function( elem, name, value ) {
959 // don't set attributes on text and comment nodes
960 if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
963 var notxml = !jQuery.isXMLDoc( elem ),
964 // Whether we are setting (or getting)
965 set = value !== undefined;
967 // Try to normalize/fix the name
968 name = notxml && jQuery.props[ name ] || name;
970 // Only do all the following if this is a node (faster for style)
971 // IE elem.getAttribute passes even for style
972 if ( elem.tagName ) {
974 // These attributes require special treatment
975 var special = /href|src|style/.test( name );
977 // Safari mis-reports the default selected property of a hidden option
978 // Accessing the parent's selectedIndex property fixes it
979 if ( name == "selected" && elem.parentNode )
980 elem.parentNode.selectedIndex;
982 // If applicable, access the attribute via the DOM 0 way
983 if ( name in elem && notxml && !special ) {
985 // We can't allow the type property to be changed (since it causes problems in IE)
986 if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
987 throw "type property can't be changed";
989 elem[ name ] = value;
992 // browsers index elements by id/name on forms, give priority to attributes.
993 if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
994 return elem.getAttributeNode( name ).nodeValue;
996 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
997 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
998 if ( name == "tabIndex" ) {
999 var attributeNode = elem.getAttributeNode( "tabIndex" );
1000 return attributeNode && attributeNode.specified
1001 ? attributeNode.value
1002 : elem.nodeName.match(/^(a|area|button|input|object|select|textarea)$/i)
1007 return elem[ name ];
1010 if ( !jQuery.support.style && notxml && name == "style" )
1011 return jQuery.attr( elem.style, "cssText", value );
1014 // convert the value to a string (all browsers do this but IE) see #1070
1015 elem.setAttribute( name, "" + value );
1017 var attr = !jQuery.support.hrefNormalized && notxml && special
1018 // Some attributes require a special call on IE
1019 ? elem.getAttribute( name, 2 )
1020 : elem.getAttribute( name );
1022 // Non-existent attributes return null, we normalize to undefined
1023 return attr === null ? undefined : attr;
1026 // elem is actually elem.style ... set the style
1028 // IE uses filters for opacity
1029 if ( !jQuery.support.opacity && name == "opacity" ) {
1031 // IE has trouble with opacity if it does not have layout
1032 // Force it by setting the zoom level
1035 // Set the alpha filter to set the opacity
1036 elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
1037 (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
1040 return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
1041 (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
1045 name = name.replace(/-([a-z])/ig, function(all, letter){
1046 return letter.toUpperCase();
1050 elem[ name ] = value;
1052 return elem[ name ];
1055 trim: function( text ) {
1056 return (text || "").replace( /^\s+|\s+$/g, "" );
1059 makeArray: function( array ) {
1062 if( array != null ){
1063 var i = array.length;
1064 // The window, strings (and functions) also have 'length'
1065 if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
1069 ret[--i] = array[i];
1075 inArray: function( elem, array ) {
1076 for ( var i = 0, length = array.length; i < length; i++ )
1077 // Use === because on IE, window == document
1078 if ( array[ i ] === elem )
1084 merge: function( first, second ) {
1085 // We have to loop this way because IE & Opera overwrite the length
1086 // expando of getElementsByTagName
1087 var i = 0, elem, pos = first.length;
1088 // Also, we need to make sure that the correct elements are being returned
1089 // (IE returns comment nodes in a '*' query)
1090 if ( !jQuery.support.getAll ) {
1091 while ( (elem = second[ i++ ]) != null )
1092 if ( elem.nodeType != 8 )
1093 first[ pos++ ] = elem;
1096 while ( (elem = second[ i++ ]) != null )
1097 first[ pos++ ] = elem;
1102 unique: function( array ) {
1103 var ret = [], done = {};
1107 for ( var i = 0, length = array.length; i < length; i++ ) {
1108 var id = jQuery.data( array[ i ] );
1110 if ( !done[ id ] ) {
1112 ret.push( array[ i ] );
1123 grep: function( elems, callback, inv ) {
1126 // Go through the array, only saving the items
1127 // that pass the validator function
1128 for ( var i = 0, length = elems.length; i < length; i++ )
1129 if ( !inv != !callback( elems[ i ], i ) )
1130 ret.push( elems[ i ] );
1135 map: function( elems, callback ) {
1138 // Go through the array, translating each of the items to their
1139 // new value (or values).
1140 for ( var i = 0, length = elems.length; i < length; i++ ) {
1141 var value = callback( elems[ i ], i );
1143 if ( value != null )
1144 ret[ ret.length ] = value;
1147 return ret.concat.apply( [], ret );
1151 // Use of jQuery.browser is deprecated.
1152 // It's included for backwards compatibility and plugins,
1153 // although they should work to migrate away.
1155 var userAgent = navigator.userAgent.toLowerCase();
1157 // Figure out what browser is being used
1159 version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
1160 safari: /webkit/.test( userAgent ),
1161 opera: /opera/.test( userAgent ),
1162 msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
1163 mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
1167 parent: function(elem){return elem.parentNode;},
1168 parents: function(elem){return jQuery.dir(elem,"parentNode");},
1169 next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
1170 prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
1171 nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
1172 prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
1173 siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
1174 children: function(elem){return jQuery.sibling(elem.firstChild);},
1175 contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
1176 }, function(name, fn){
1177 jQuery.fn[ name ] = function( selector ) {
1178 var ret = jQuery.map( this, fn );
1180 if ( selector && typeof selector == "string" )
1181 ret = jQuery.multiFilter( selector, ret );
1183 return this.pushStack( jQuery.unique( ret ), name, selector );
1189 prependTo: "prepend",
1190 insertBefore: "before",
1191 insertAfter: "after",
1192 replaceAll: "replaceWith"
1193 }, function(name, original){
1194 jQuery.fn[ name ] = function() {
1195 var args = arguments;
1197 return this.each(function(){
1198 for ( var i = 0, length = args.length; i < length; i++ )
1199 jQuery( args[ i ] )[ original ]( this );
1205 removeAttr: function( name ) {
1206 jQuery.attr( this, name, "" );
1207 if (this.nodeType == 1)
1208 this.removeAttribute( name );
1211 addClass: function( classNames ) {
1212 jQuery.className.add( this, classNames );
1215 removeClass: function( classNames ) {
1216 jQuery.className.remove( this, classNames );
1219 toggleClass: function( classNames, state ) {
1220 if( typeof state !== "boolean" )
1221 state = !jQuery.className.has( this, classNames );
1222 jQuery.className[ state ? "add" : "remove" ]( this, classNames );
1225 remove: function( selector ) {
1226 if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
1227 // Prevent memory leaks
1228 jQuery( "*", this ).add([this]).each(function(){
1229 jQuery.event.remove(this);
1230 jQuery.removeData(this);
1232 if (this.parentNode)
1233 this.parentNode.removeChild( this );
1238 // Remove element nodes and prevent memory leaks
1239 jQuery( ">*", this ).remove();
1241 // Remove any remaining nodes
1242 while ( this.firstChild )
1243 this.removeChild( this.firstChild );
1245 }, function(name, fn){
1246 jQuery.fn[ name ] = function(){
1247 return this.each( fn, arguments );
1251 // Helper function used by the dimensions and offset modules
1252 function num(elem, prop) {
1253 return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
1255 var expando = "jQuery" + now(), uuid = 0, windowData = {};
\r
1260 data: function( elem, name, data ) {
\r
1261 elem = elem == window ?
\r
1265 var id = elem[ expando ];
\r
1267 // Compute a unique ID for the element
\r
1269 id = elem[ expando ] = ++uuid;
\r
1271 // Only generate the data cache if we're
\r
1272 // trying to access or manipulate it
\r
1273 if ( name && !jQuery.cache[ id ] )
\r
1274 jQuery.cache[ id ] = {};
\r
1276 // Prevent overriding the named cache with undefined values
\r
1277 if ( data !== undefined )
\r
1278 jQuery.cache[ id ][ name ] = data;
\r
1280 // Return the named cache data, or the ID for the element
\r
1282 jQuery.cache[ id ][ name ] :
\r
1286 removeData: function( elem, name ) {
\r
1287 elem = elem == window ?
\r
1291 var id = elem[ expando ];
\r
1293 // If we want to remove a specific section of the element's data
\r
1295 if ( jQuery.cache[ id ] ) {
\r
1296 // Remove the section of cache data
\r
1297 delete jQuery.cache[ id ][ name ];
\r
1299 // If we've removed all the data, remove the element's cache
\r
1302 for ( name in jQuery.cache[ id ] )
\r
1306 jQuery.removeData( elem );
\r
1309 // Otherwise, we want to remove all of the element's data
\r
1311 // Clean up the element expando
\r
1313 delete elem[ expando ];
\r
1315 // IE has trouble directly removing the expando
\r
1316 // but it's ok with using removeAttribute
\r
1317 if ( elem.removeAttribute )
\r
1318 elem.removeAttribute( expando );
\r
1321 // Completely remove the data cache
\r
1322 delete jQuery.cache[ id ];
\r
1325 queue: function( elem, type, data ) {
\r
1328 type = (type || "fx") + "queue";
\r
1330 var q = jQuery.data( elem, type );
\r
1332 if ( !q || jQuery.isArray(data) )
\r
1333 q = jQuery.data( elem, type, jQuery.makeArray(data) );
\r
1341 dequeue: function( elem, type ){
\r
1342 var queue = jQuery.queue( elem, type ),
\r
1343 fn = queue.shift();
\r
1345 if( !type || type === "fx" )
\r
1348 if( fn !== undefined )
\r
1353 jQuery.fn.extend({
\r
1354 data: function( key, value ){
\r
1355 var parts = key.split(".");
\r
1356 parts[1] = parts[1] ? "." + parts[1] : "";
\r
1358 if ( value === undefined ) {
\r
1359 var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
\r
1361 if ( data === undefined && this.length )
\r
1362 data = jQuery.data( this[0], key );
\r
1364 return data === undefined && parts[1] ?
\r
1365 this.data( parts[0] ) :
\r
1368 return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
\r
1369 jQuery.data( this, key, value );
\r
1373 removeData: function( key ){
\r
1374 return this.each(function(){
\r
1375 jQuery.removeData( this, key );
\r
1378 queue: function(type, data){
\r
1379 if ( typeof type !== "string" ) {
\r
1384 if ( data === undefined )
\r
1385 return jQuery.queue( this[0], type );
\r
1387 return this.each(function(){
\r
1388 var queue = jQuery.queue( this, type, data );
\r
1390 if( type == "fx" && queue.length == 1 )
\r
1391 queue[0].call(this);
\r
1394 dequeue: function(type){
\r
1395 return this.each(function(){
\r
1396 jQuery.dequeue( this, type );
\r
1400 * Sizzle CSS Selector Engine - v0.9.1
1401 * Copyright 2009, The Dojo Foundation
1402 * Released under the MIT, BSD, and GPL Licenses.
1403 * More information: http://sizzlejs.com/
1407 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|[^[\]]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,
1409 toString = Object.prototype.toString;
1411 var Sizzle = function(selector, context, results, seed) {
1412 results = results || [];
1413 context = context || document;
1415 if ( context.nodeType !== 1 && context.nodeType !== 9 )
1418 if ( !selector || typeof selector !== "string" ) {
1422 var parts = [], m, set, checkSet, check, mode, extra, prune = true;
1424 // Reset the position of the chunker regexp (start from head)
1425 chunker.lastIndex = 0;
1427 while ( (m = chunker.exec(selector)) !== null ) {
1431 extra = RegExp.rightContext;
1436 if ( parts.length > 1 && Expr.match.POS.exec( selector ) ) {
1437 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
1438 var later = "", match;
1440 // Position selectors must be done after the filter
1441 while ( (match = Expr.match.POS.exec( selector )) ) {
1443 selector = selector.replace( Expr.match.POS, "" );
1446 set = Sizzle.filter( later, Sizzle( /\s$/.test(selector) ? selector + "*" : selector, context ) );
1448 set = Expr.relative[ parts[0] ] ?
1450 Sizzle( parts.shift(), context );
1452 while ( parts.length ) {
1455 selector = parts.shift();
1456 if ( Expr.relative[ selector ] )
1457 selector += parts.shift();
1459 for ( var i = 0, l = set.length; i < l; i++ ) {
1460 Sizzle( selector, set[i], tmpSet );
1468 { expr: parts.pop(), set: makeArray(seed) } :
1469 Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context );
1470 set = Sizzle.filter( ret.expr, ret.set );
1472 if ( parts.length > 0 ) {
1473 checkSet = makeArray(set);
1478 while ( parts.length ) {
1479 var cur = parts.pop(), pop = cur;
1481 if ( !Expr.relative[ cur ] ) {
1487 if ( pop == null ) {
1491 Expr.relative[ cur ]( checkSet, pop, isXML(context) );
1500 throw "Syntax error, unrecognized expression: " + (cur || selector);
1503 if ( toString.call(checkSet) === "[object Array]" ) {
1505 results.push.apply( results, checkSet );
1506 } else if ( context.nodeType === 1 ) {
1507 for ( var i = 0; checkSet[i] != null; i++ ) {
1508 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
1509 results.push( set[i] );
1513 for ( var i = 0; checkSet[i] != null; i++ ) {
1514 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
1515 results.push( set[i] );
1520 makeArray( checkSet, results );
1524 Sizzle( extra, context, results, seed );
1530 Sizzle.matches = function(expr, set){
1531 return Sizzle(expr, null, null, set);
1534 Sizzle.find = function(expr, context){
1541 for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
1542 var type = Expr.order[i], match;
1544 if ( (match = Expr.match[ type ].exec( expr )) ) {
1545 var left = RegExp.leftContext;
1547 if ( left.substr( left.length - 1 ) !== "\\" ) {
1548 match[1] = (match[1] || "").replace(/\\/g, "");
1549 set = Expr.find[ type ]( match, context );
1550 if ( set != null ) {
1551 expr = expr.replace( Expr.match[ type ], "" );
1559 set = context.getElementsByTagName("*");
1562 return {set: set, expr: expr};
1565 Sizzle.filter = function(expr, set, inplace, not){
1566 var old = expr, result = [], curLoop = set, match, anyFound;
1568 while ( expr && set.length ) {
1569 for ( var type in Expr.filter ) {
1570 if ( (match = Expr.match[ type ].exec( expr )) != null ) {
1571 var filter = Expr.filter[ type ], goodArray = null, goodPos = 0, found, item;
1574 if ( curLoop == result ) {
1578 if ( Expr.preFilter[ type ] ) {
1579 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not );
1582 anyFound = found = true;
1583 } else if ( match === true ) {
1585 } else if ( match[0] === true ) {
1587 var last = null, elem;
1588 for ( var i = 0; (elem = curLoop[i]) !== undefined; i++ ) {
1589 if ( elem && last !== elem ) {
1590 goodArray.push( elem );
1598 for ( var i = 0; (item = curLoop[i]) !== undefined; i++ ) {
1600 if ( goodArray && item != goodArray[goodPos] ) {
1604 found = filter( item, match, goodPos, goodArray );
1605 var pass = not ^ !!found;
1607 if ( inplace && found != null ) {
1613 } else if ( pass ) {
1614 result.push( item );
1621 if ( found !== undefined ) {
1626 expr = expr.replace( Expr.match[ type ], "" );
1637 expr = expr.replace(/\s*,\s*/, "");
1639 // Improper expression
1640 if ( expr == old ) {
1641 if ( anyFound == null ) {
1642 throw "Syntax error, unrecognized expression: " + expr;
1654 var Expr = Sizzle.selectors = {
1655 order: [ "ID", "NAME", "TAG" ],
1657 ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
1658 CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
1659 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
1660 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
1661 TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
1662 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
1663 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
1664 PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
1667 "class": "className",
1671 href: function(elem){
1672 return elem.getAttribute("href");
1676 "+": function(checkSet, part){
1677 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1678 var elem = checkSet[i];
1680 var cur = elem.previousSibling;
1681 while ( cur && cur.nodeType !== 1 ) {
1682 cur = cur.previousSibling;
1684 checkSet[i] = typeof part === "string" ?
1690 if ( typeof part === "string" ) {
1691 Sizzle.filter( part, checkSet, true );
1694 ">": function(checkSet, part, isXML){
1695 if ( typeof part === "string" && !/\W/.test(part) ) {
1696 part = isXML ? part : part.toUpperCase();
1698 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1699 var elem = checkSet[i];
1701 var parent = elem.parentNode;
1702 checkSet[i] = parent.nodeName === part ? parent : false;
1706 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1707 var elem = checkSet[i];
1709 checkSet[i] = typeof part === "string" ?
1711 elem.parentNode === part;
1715 if ( typeof part === "string" ) {
1716 Sizzle.filter( part, checkSet, true );
1720 "": function(checkSet, part, isXML){
1721 var doneName = "done" + (done++), checkFn = dirCheck;
1723 if ( !part.match(/\W/) ) {
1724 var nodeCheck = part = isXML ? part : part.toUpperCase();
1725 checkFn = dirNodeCheck;
1728 checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
1730 "~": function(checkSet, part, isXML){
1731 var doneName = "done" + (done++), checkFn = dirCheck;
1733 if ( typeof part === "string" && !part.match(/\W/) ) {
1734 var nodeCheck = part = isXML ? part : part.toUpperCase();
1735 checkFn = dirNodeCheck;
1738 checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
1742 ID: function(match, context){
1743 if ( context.getElementById ) {
1744 var m = context.getElementById(match[1]);
1745 return m ? [m] : [];
1748 NAME: function(match, context){
1749 return context.getElementsByName ? context.getElementsByName(match[1]) : null;
1751 TAG: function(match, context){
1752 return context.getElementsByTagName(match[1]);
1756 CLASS: function(match, curLoop, inplace, result, not){
1757 match = " " + match[1].replace(/\\/g, "") + " ";
1759 for ( var i = 0; curLoop[i]; i++ ) {
1760 if ( not ^ (" " + curLoop[i].className + " ").indexOf(match) >= 0 ) {
1762 result.push( curLoop[i] );
1763 } else if ( inplace ) {
1770 ID: function(match){
1771 return match[1].replace(/\\/g, "");
1773 TAG: function(match, curLoop){
1774 for ( var i = 0; !curLoop[i]; i++ ){}
1775 return isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
1777 CHILD: function(match){
1778 if ( match[1] == "nth" ) {
1779 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
1780 var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
1781 match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
1782 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
1784 // calculate the numbers (first)n+(last) including if they are negative
1785 match[2] = (test[1] + (test[2] || 1)) - 0;
1786 match[3] = test[3] - 0;
1789 // TODO: Move to normal caching system
1790 match[0] = "done" + (done++);
1794 ATTR: function(match){
1795 var name = match[1];
1797 if ( Expr.attrMap[name] ) {
1798 match[1] = Expr.attrMap[name];
1801 if ( match[2] === "~=" ) {
1802 match[4] = " " + match[4] + " ";
1807 PSEUDO: function(match, curLoop, inplace, result, not){
1808 if ( match[1] === "not" ) {
1809 // If we're dealing with a complex expression, or a simple one
1810 if ( match[3].match(chunker).length > 1 ) {
1811 match[3] = Sizzle(match[3], null, null, curLoop);
1813 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
1815 result.push.apply( result, ret );
1819 } else if ( Expr.match.POS.test( match[0] ) ) {
1825 POS: function(match){
1826 match.unshift( true );
1831 enabled: function(elem){
1832 return elem.disabled === false && elem.type !== "hidden";
1834 disabled: function(elem){
1835 return elem.disabled === true;
1837 checked: function(elem){
1838 return elem.checked === true;
1840 selected: function(elem){
1841 // Accessing this property makes selected-by-default
1842 // options in Safari work properly
1843 elem.parentNode.selectedIndex;
1844 return elem.selected === true;
1846 parent: function(elem){
1847 return !!elem.firstChild;
1849 empty: function(elem){
1850 return !elem.firstChild;
1852 has: function(elem, i, match){
1853 return !!Sizzle( match[3], elem ).length;
1855 header: function(elem){
1856 return /h\d/i.test( elem.nodeName );
1858 text: function(elem){
1859 return "text" === elem.type;
1861 radio: function(elem){
1862 return "radio" === elem.type;
1864 checkbox: function(elem){
1865 return "checkbox" === elem.type;
1867 file: function(elem){
1868 return "file" === elem.type;
1870 password: function(elem){
1871 return "password" === elem.type;
1873 submit: function(elem){
1874 return "submit" === elem.type;
1876 image: function(elem){
1877 return "image" === elem.type;
1879 reset: function(elem){
1880 return "reset" === elem.type;
1882 button: function(elem){
1883 return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
1885 input: function(elem){
1886 return /input|select|textarea|button/i.test(elem.nodeName);
1890 first: function(elem, i){
1893 last: function(elem, i, match, array){
1894 return i === array.length - 1;
1896 even: function(elem, i){
1899 odd: function(elem, i){
1902 lt: function(elem, i, match){
1903 return i < match[3] - 0;
1905 gt: function(elem, i, match){
1906 return i > match[3] - 0;
1908 nth: function(elem, i, match){
1909 return match[3] - 0 == i;
1911 eq: function(elem, i, match){
1912 return match[3] - 0 == i;
1916 CHILD: function(elem, match){
1917 var type = match[1], parent = elem.parentNode;
1919 var doneName = "child" + parent.childNodes.length;
1921 if ( parent && (!parent[ doneName ] || !elem.nodeIndex) ) {
1924 for ( var node = parent.firstChild; node; node = node.nextSibling ) {
1925 if ( node.nodeType == 1 ) {
1926 node.nodeIndex = count++;
1930 parent[ doneName ] = count - 1;
1933 if ( type == "first" ) {
1934 return elem.nodeIndex == 1;
1935 } else if ( type == "last" ) {
1936 return elem.nodeIndex == parent[ doneName ];
1937 } else if ( type == "only" ) {
1938 return parent[ doneName ] == 1;
1939 } else if ( type == "nth" ) {
1940 var add = false, first = match[2], last = match[3];
1942 if ( first == 1 && last == 0 ) {
1947 if ( elem.nodeIndex == last ) {
1950 } else if ( (elem.nodeIndex - last) % first == 0 && (elem.nodeIndex - last) / first >= 0 ) {
1957 PSEUDO: function(elem, match, i, array){
1958 var name = match[1], filter = Expr.filters[ name ];
1961 return filter( elem, i, match, array );
1962 } else if ( name === "contains" ) {
1963 return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
1964 } else if ( name === "not" ) {
1967 for ( var i = 0, l = not.length; i < l; i++ ) {
1968 if ( not[i] === elem ) {
1976 ID: function(elem, match){
1977 return elem.nodeType === 1 && elem.getAttribute("id") === match;
1979 TAG: function(elem, match){
1980 return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
1982 CLASS: function(elem, match){
1983 return match.test( elem.className );
1985 ATTR: function(elem, match){
1986 var result = Expr.attrHandle[ match[1] ] ? Expr.attrHandle[ match[1] ]( elem ) : elem[ match[1] ] || elem.getAttribute( match[1] ), value = result + "", type = match[2], check = match[4];
1987 return result == null ?
1992 value.indexOf(check) >= 0 :
1994 (" " + value + " ").indexOf(check) >= 0 :
2000 value.indexOf(check) === 0 :
2002 value.substr(value.length - check.length) === check :
2004 value === check || value.substr(0, check.length + 1) === check + "-" :
2007 POS: function(elem, match, i, array){
2008 var name = match[2], filter = Expr.setFilters[ name ];
2011 return filter( elem, i, match, array );
2017 for ( var type in Expr.match ) {
2018 Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
2021 var makeArray = function(array, results) {
2022 array = Array.prototype.slice.call( array );
2025 results.push.apply( results, array );
2032 // Perform a simple check to determine if the browser is capable of
2033 // converting a NodeList to an array using builtin methods.
2035 Array.prototype.slice.call( document.documentElement.childNodes );
2037 // Provide a fallback method if it does not work
2039 makeArray = function(array, results) {
2040 var ret = results || [];
2042 if ( toString.call(array) === "[object Array]" ) {
2043 Array.prototype.push.apply( ret, array );
2045 if ( typeof array.length === "number" ) {
2046 for ( var i = 0, l = array.length; i < l; i++ ) {
2047 ret.push( array[i] );
2050 for ( var i = 0; array[i]; i++ ) {
2051 ret.push( array[i] );
2060 // Check to see if the browser returns elements by name when
2061 // querying by getElementById (and provide a workaround)
2063 // We're going to inject a fake input element with a specified name
2064 var form = document.createElement("form"),
2065 id = "script" + (new Date).getTime();
2066 form.innerHTML = "<input name='" + id + "'/>";
2068 // Inject it into the root element, check its status, and remove it quickly
2069 var root = document.documentElement;
2070 root.insertBefore( form, root.firstChild );
2072 // The workaround has to do additional checks after a getElementById
2073 // Which slows things down for other browsers (hence the branching)
2074 if ( !!document.getElementById( id ) ) {
2075 Expr.find.ID = function(match, context){
2076 if ( context.getElementById ) {
2077 var m = context.getElementById(match[1]);
2078 return m ? m.id === match[1] || m.getAttributeNode && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
2082 Expr.filter.ID = function(elem, match){
2083 var node = elem.getAttributeNode && elem.getAttributeNode("id");
2084 return elem.nodeType === 1 && node && node.nodeValue === match;
2088 root.removeChild( form );
2092 // Check to see if the browser returns only elements
2093 // when doing getElementsByTagName("*")
2095 // Create a fake element
2096 var div = document.createElement("div");
2097 div.appendChild( document.createComment("") );
2099 // Make sure no comments are found
2100 if ( div.getElementsByTagName("*").length > 0 ) {
2101 Expr.find.TAG = function(match, context){
2102 var results = context.getElementsByTagName(match[1]);
2104 // Filter out possible comments
2105 if ( match[1] === "*" ) {
2108 for ( var i = 0; results[i]; i++ ) {
2109 if ( results[i].nodeType === 1 ) {
2110 tmp.push( results[i] );
2121 // Check to see if an attribute returns normalized href attributes
2122 div.innerHTML = "<a href='#'></a>";
2123 if ( div.firstChild.getAttribute("href") !== "#" ) {
2124 Expr.attrHandle.href = function(elem){
2125 return elem.getAttribute("href", 2);
2130 if ( document.querySelectorAll ) (function(){
2131 var oldSizzle = Sizzle;
2133 Sizzle = function(query, context, extra, seed){
2134 context = context || document;
2136 if ( !seed && context.nodeType === 9 ) {
2138 return makeArray( context.querySelectorAll(query), extra );
2142 return oldSizzle(query, context, extra, seed);
2145 Sizzle.find = oldSizzle.find;
2146 Sizzle.filter = oldSizzle.filter;
2147 Sizzle.selectors = oldSizzle.selectors;
2148 Sizzle.matches = oldSizzle.matches;
2151 if ( document.documentElement.getElementsByClassName ) {
2152 Expr.order.splice(1, 0, "CLASS");
2153 Expr.find.CLASS = function(match, context) {
2154 return context.getElementsByClassName(match[1]);
2158 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
2159 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2160 var elem = checkSet[i];
2165 while ( elem && elem.nodeType ) {
2166 var done = elem[doneName];
2168 match = checkSet[ done ];
2172 if ( elem.nodeType === 1 && !isXML )
2175 if ( elem.nodeName === cur ) {
2183 checkSet[i] = match;
2188 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
2189 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2190 var elem = checkSet[i];
2195 while ( elem && elem.nodeType ) {
2196 if ( elem[doneName] ) {
2197 match = checkSet[ elem[doneName] ];
2201 if ( elem.nodeType === 1 ) {
2205 if ( typeof cur !== "string" ) {
2206 if ( elem === cur ) {
2211 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
2220 checkSet[i] = match;
2225 var contains = document.compareDocumentPosition ? function(a, b){
2226 return a.compareDocumentPosition(b) & 16;
2228 return a !== b && (a.contains ? a.contains(b) : true);
2231 var isXML = function(elem){
2232 return elem.documentElement && !elem.body ||
2233 elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
2237 jQuery.find = Sizzle;
2238 jQuery.filter = Sizzle.filter;
2239 jQuery.expr = Sizzle.selectors;
2240 jQuery.expr[":"] = jQuery.expr.filters;
2242 Sizzle.selectors.filters.hidden = function(elem){
2243 return "hidden" === elem.type ||
2244 jQuery.css(elem, "display") === "none" ||
2245 jQuery.css(elem, "visibility") === "hidden";
2248 Sizzle.selectors.filters.visible = function(elem){
2249 return "hidden" !== elem.type &&
2250 jQuery.css(elem, "display") !== "none" &&
2251 jQuery.css(elem, "visibility") !== "hidden";
2254 Sizzle.selectors.filters.animated = function(elem){
2255 return jQuery.grep(jQuery.timers, function(fn){
2256 return elem === fn.elem;
2260 jQuery.multiFilter = function( expr, elems, not ) {
2262 expr = ":not(" + expr + ")";
2265 return Sizzle.matches(expr, elems);
2268 jQuery.dir = function( elem, dir ){
2269 var matched = [], cur = elem[dir];
2270 while ( cur && cur != document ) {
2271 if ( cur.nodeType == 1 )
2272 matched.push( cur );
2278 jQuery.nth = function(cur, result, dir, elem){
2279 result = result || 1;
2282 for ( ; cur; cur = cur[dir] )
2283 if ( cur.nodeType == 1 && ++num == result )
2289 jQuery.sibling = function(n, elem){
2292 for ( ; n; n = n.nextSibling ) {
2293 if ( n.nodeType == 1 && n != elem )
2302 window.Sizzle = Sizzle;
2306 * A number of helper functions used for managing events.
2307 * Many of the ideas behind this code originated from
2308 * Dean Edwards' addEvent library.
2312 // Bind an event to an element
2313 // Original by Dean Edwards
2314 add: function(elem, types, handler, data) {
2315 if ( elem.nodeType == 3 || elem.nodeType == 8 )
2318 // For whatever reason, IE has trouble passing the window object
2319 // around, causing it to be cloned in the process
2320 if ( elem.setInterval && elem != window )
2323 // Make sure that the function being executed has a unique ID
2324 if ( !handler.guid )
2325 handler.guid = this.guid++;
2327 // if data is passed, bind to handler
2328 if ( data !== undefined ) {
2329 // Create temporary function pointer to original handler
2332 // Create unique handler function, wrapped around original handler
2333 handler = this.proxy( fn );
2335 // Store data in unique handler
2336 handler.data = data;
2339 // Init the element's event structure
2340 var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
2341 handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
2342 // Handle the second event of a trigger and when
2343 // an event is called after a page has unloaded
2344 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
2345 jQuery.event.handle.apply(arguments.callee.elem, arguments) :
2348 // Add elem as a property of the handle function
2349 // This is to prevent a memory leak with non-native
2353 // Handle multiple events separated by a space
2354 // jQuery(...).bind("mouseover mouseout", fn);
2355 jQuery.each(types.split(/\s+/), function(index, type) {
2356 // Namespaced event handlers
2357 var namespaces = type.split(".");
2358 type = namespaces.shift();
2359 handler.type = namespaces.slice().sort().join(".");
2361 // Get the current list of functions bound to this event
2362 var handlers = events[type];
2364 if ( jQuery.event.specialAll[type] )
2365 jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
2367 // Init the event handler queue
2369 handlers = events[type] = {};
2371 // Check for a special event handler
2372 // Only use addEventListener/attachEvent if the special
2373 // events handler returns false
2374 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
2375 // Bind the global event handler to the element
2376 if (elem.addEventListener)
2377 elem.addEventListener(type, handle, false);
2378 else if (elem.attachEvent)
2379 elem.attachEvent("on" + type, handle);
2383 // Add the function to the element's handler list
2384 handlers[handler.guid] = handler;
2386 // Keep track of which events have been used, for global triggering
2387 jQuery.event.global[type] = true;
2390 // Nullify elem to prevent memory leaks in IE
2397 // Detach an event or set of events from an element
2398 remove: function(elem, types, handler) {
2399 // don't do events on text and comment nodes
2400 if ( elem.nodeType == 3 || elem.nodeType == 8 )
2403 var events = jQuery.data(elem, "events"), ret, index;
2406 // Unbind all events for the element
2407 if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
2408 for ( var type in events )
2409 this.remove( elem, type + (types || "") );
2411 // types is actually an event object here
2413 handler = types.handler;
2417 // Handle multiple events seperated by a space
2418 // jQuery(...).unbind("mouseover mouseout", fn);
2419 jQuery.each(types.split(/\s+/), function(index, type){
2420 // Namespaced event handlers
2421 var namespaces = type.split(".");
2422 type = namespaces.shift();
2423 var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
2425 if ( events[type] ) {
2426 // remove the given handler for the given type
2428 delete events[type][handler.guid];
2430 // remove all handlers for the given type
2432 for ( var handle in events[type] )
2433 // Handle the removal of namespaced events
2434 if ( namespace.test(events[type][handle].type) )
2435 delete events[type][handle];
2437 if ( jQuery.event.specialAll[type] )
2438 jQuery.event.specialAll[type].teardown.call(elem, namespaces);
2440 // remove generic event handler if no more handlers exist
2441 for ( ret in events[type] ) break;
2443 if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
2444 if (elem.removeEventListener)
2445 elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
2446 else if (elem.detachEvent)
2447 elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
2450 delete events[type];
2456 // Remove the expando if it's no longer used
2457 for ( ret in events ) break;
2459 var handle = jQuery.data( elem, "handle" );
2460 if ( handle ) handle.elem = null;
2461 jQuery.removeData( elem, "events" );
2462 jQuery.removeData( elem, "handle" );
2467 // bubbling is internal
2468 trigger: function( event, data, elem, bubbling ) {
2469 // Event object or event type
2470 var type = event.type || event;
2473 event = typeof event === "object" ?
2474 // jQuery.Event object
2475 event[expando] ? event :
2477 jQuery.extend( jQuery.Event(type), event ) :
2478 // Just the event type (string)
2481 if ( type.indexOf("!") >= 0 ) {
2482 event.type = type = type.slice(0, -1);
2483 event.exclusive = true;
2486 // Handle a global trigger
2488 // Don't bubble custom events when global (to avoid too much overhead)
2489 event.stopPropagation();
2490 // Only trigger if we've ever bound an event for it
2491 if ( this.global[type] )
2492 jQuery.each( jQuery.cache, function(){
2493 if ( this.events && this.events[type] )
2494 jQuery.event.trigger( event, data, this.handle.elem );
2498 // Handle triggering a single element
2500 // don't do events on text and comment nodes
2501 if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
2504 // Clean up in case it is reused
2505 event.result = undefined;
2506 event.target = elem;
2508 // Clone the incoming data, if any
2509 data = jQuery.makeArray(data);
2510 data.unshift( event );
2513 event.currentTarget = elem;
2515 // Trigger the event, it is assumed that "handle" is a function
2516 var handle = jQuery.data(elem, "handle");
2518 handle.apply( elem, data );
2520 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
2521 if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
2522 event.result = false;
2524 // Trigger the native events (except for clicks on links)
2525 if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
2526 this.triggered = true;
2529 // prevent IE from throwing an error for some hidden elements
2533 this.triggered = false;
2535 if ( !event.isPropagationStopped() ) {
2536 var parent = elem.parentNode || elem.ownerDocument;
2538 jQuery.event.trigger(event, data, parent, true);
2542 handle: function(event) {
2543 // returned undefined or false
2546 event = arguments[0] = jQuery.event.fix( event || window.event );
2548 // Namespaced event handlers
2549 var namespaces = event.type.split(".");
2550 event.type = namespaces.shift();
2552 // Cache this now, all = true means, any handler
2553 all = !namespaces.length && !event.exclusive;
2555 var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
2557 handlers = ( jQuery.data(this, "events") || {} )[event.type];
2559 for ( var j in handlers ) {
2560 var handler = handlers[j];
2562 // Filter the functions by class
2563 if ( all || namespace.test(handler.type) ) {
2564 // Pass in a reference to the handler function itself
2565 // So that we can later remove it
2566 event.handler = handler;
2567 event.data = handler.data;
2569 var ret = handler.apply(this, arguments);
2571 if( ret !== undefined ){
2573 if ( ret === false ) {
2574 event.preventDefault();
2575 event.stopPropagation();
2579 if( event.isImmediatePropagationStopped() )
2586 props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
2588 fix: function(event) {
2589 if ( event[expando] )
2592 // store a copy of the original event object
2593 // and "clone" to set read-only properties
2594 var originalEvent = event;
2595 event = jQuery.Event( originalEvent );
2597 for ( var i = this.props.length, prop; i; ){
2598 prop = this.props[ --i ];
2599 event[ prop ] = originalEvent[ prop ];
2602 // Fix target property, if necessary
2603 if ( !event.target )
2604 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
2606 // check if target is a textnode (safari)
2607 if ( event.target.nodeType == 3 )
2608 event.target = event.target.parentNode;
2610 // Add relatedTarget, if necessary
2611 if ( !event.relatedTarget && event.fromElement )
2612 event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
2614 // Calculate pageX/Y if missing and clientX/Y available
2615 if ( event.pageX == null && event.clientX != null ) {
2616 var doc = document.documentElement, body = document.body;
2617 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
2618 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
2621 // Add which for key events
2622 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
2623 event.which = event.charCode || event.keyCode;
2625 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
2626 if ( !event.metaKey && event.ctrlKey )
2627 event.metaKey = event.ctrlKey;
2629 // Add which for click: 1 == left; 2 == middle; 3 == right
2630 // Note: button is not normalized, so don't use it
2631 if ( !event.which && event.button )
2632 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2637 proxy: function( fn, proxy ){
2638 proxy = proxy || function(){ return fn.apply(this, arguments); };
2639 // Set the guid of unique handler to the same of original handler, so it can be removed
2640 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
2641 // So proxy can be declared as an argument
2647 // Make sure the ready event is setup
2649 teardown: function() {}
2655 setup: function( selector, namespaces ){
2656 jQuery.event.add( this, namespaces[0], liveHandler );
2658 teardown: function( namespaces ){
2659 if ( namespaces.length ) {
2660 var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
2662 jQuery.each( (jQuery.data(this, "events").live || {}), function(){
2663 if ( name.test(this.type) )
2668 jQuery.event.remove( this, namespaces[0], liveHandler );
2675 jQuery.Event = function( src ){
2676 // Allow instantiation without the 'new' keyword
2677 if( !this.preventDefault )
2678 return new jQuery.Event(src);
2681 if( src && src.type ){
2682 this.originalEvent = src;
2683 this.type = src.type;
2684 this.timeStamp = src.timeStamp;
2689 if( !this.timeStamp )
2690 this.timeStamp = now();
2693 this[expando] = true;
2696 function returnFalse(){
2699 function returnTrue(){
2703 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
2704 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
2705 jQuery.Event.prototype = {
2706 preventDefault: function() {
2707 this.isDefaultPrevented = returnTrue;
2709 var e = this.originalEvent;
2712 // if preventDefault exists run it on the original event
2713 if (e.preventDefault)
2715 // otherwise set the returnValue property of the original event to false (IE)
2716 e.returnValue = false;
2718 stopPropagation: function() {
2719 this.isPropagationStopped = returnTrue;
2721 var e = this.originalEvent;
2724 // if stopPropagation exists run it on the original event
2725 if (e.stopPropagation)
2726 e.stopPropagation();
2727 // otherwise set the cancelBubble property of the original event to true (IE)
2728 e.cancelBubble = true;
2730 stopImmediatePropagation:function(){
2731 this.isImmediatePropagationStopped = returnTrue;
2732 this.stopPropagation();
2734 isDefaultPrevented: returnFalse,
2735 isPropagationStopped: returnFalse,
2736 isImmediatePropagationStopped: returnFalse
2738 // Checks if an event happened on an element within another element
2739 // Used in jQuery.event.special.mouseenter and mouseleave handlers
2740 var withinElement = function(event) {
2741 // Check if mouse(over|out) are still within the same parent element
2742 var parent = event.relatedTarget;
2743 // Traverse up the tree
2744 while ( parent && parent != this )
2745 try { parent = parent.parentNode; }
2746 catch(e) { parent = this; }
2748 if( parent != this ){
2749 // set the correct event type
2750 event.type = event.data;
2751 // handle event if we actually just moused on to a non sub-element
2752 jQuery.event.handle.apply( this, arguments );
2757 mouseover: 'mouseenter',
2758 mouseout: 'mouseleave'
2759 }, function( orig, fix ){
2760 jQuery.event.special[ fix ] = {
2762 jQuery.event.add( this, orig, withinElement, fix );
2764 teardown: function(){
2765 jQuery.event.remove( this, orig, withinElement );
2771 bind: function( type, data, fn ) {
2772 return type == "unload" ? this.one(type, data, fn) : this.each(function(){
2773 jQuery.event.add( this, type, fn || data, fn && data );
2777 one: function( type, data, fn ) {
2778 var one = jQuery.event.proxy( fn || data, function(event) {
2779 jQuery(this).unbind(event, one);
2780 return (fn || data).apply( this, arguments );
2782 return this.each(function(){
2783 jQuery.event.add( this, type, one, fn && data);
2787 unbind: function( type, fn ) {
2788 return this.each(function(){
2789 jQuery.event.remove( this, type, fn );
2793 trigger: function( type, data ) {
2794 return this.each(function(){
2795 jQuery.event.trigger( type, data, this );
2799 triggerHandler: function( type, data ) {
2801 var event = jQuery.Event(type);
2802 event.preventDefault();
2803 event.stopPropagation();
2804 jQuery.event.trigger( event, data, this[0] );
2805 return event.result;
2809 toggle: function( fn ) {
2810 // Save reference to arguments for access in closure
2811 var args = arguments, i = 1;
2813 // link all the functions, so any of them can unbind this click handler
2814 while( i < args.length )
2815 jQuery.event.proxy( fn, args[i++] );
2817 return this.click( jQuery.event.proxy( fn, function(event) {
2818 // Figure out which function to execute
2819 this.lastToggle = ( this.lastToggle || 0 ) % i;
2821 // Make sure that clicks stop
2822 event.preventDefault();
2824 // and execute the function
2825 return args[ this.lastToggle++ ].apply( this, arguments ) || false;
2829 hover: function(fnOver, fnOut) {
2830 return this.mouseenter(fnOver).mouseleave(fnOut);
2833 ready: function(fn) {
2834 // Attach the listeners
2837 // If the DOM is already ready
2838 if ( jQuery.isReady )
2839 // Execute the function immediately
2840 fn.call( document, jQuery );
2842 // Otherwise, remember the function for later
2844 // Add the function to the wait list
2845 jQuery.readyList.push( fn );
2850 live: function( type, fn ){
2851 var proxy = jQuery.event.proxy( fn );
2852 proxy.guid += this.selector + type;
2854 jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
2859 die: function( type, fn ){
2860 jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
2865 function liveHandler( event ){
2866 var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
2870 jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
2871 if ( check.test(fn.type) ) {
2872 var elem = jQuery(event.target).closest(fn.data)[0];
2874 elems.push({ elem: elem, fn: fn });
2878 jQuery.each(elems, function(){
2879 if ( !event.isImmediatePropagationStopped() &&
2880 this.fn.call(this.elem, event, this.fn.data) === false )
2887 function liveConvert(type, selector){
2888 return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
2894 // Handle when the DOM is ready
2896 // Make sure that the DOM is not already loaded
2897 if ( !jQuery.isReady ) {
2898 // Remember that the DOM is ready
2899 jQuery.isReady = true;
2901 // If there are functions bound, to execute
2902 if ( jQuery.readyList ) {
2903 // Execute all of them
2904 jQuery.each( jQuery.readyList, function(){
2905 this.call( document, jQuery );
2908 // Reset the list of functions
2909 jQuery.readyList = null;
2912 // Trigger any bound ready events
2913 jQuery(document).triggerHandler("ready");
2918 var readyBound = false;
2920 function bindReady(){
2921 if ( readyBound ) return;
2924 // Mozilla, Opera and webkit nightlies currently support this event
2925 if ( document.addEventListener ) {
2926 // Use the handy event callback
2927 document.addEventListener( "DOMContentLoaded", function(){
2928 document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
2932 // If IE event model is used
2933 } else if ( document.attachEvent ) {
2934 // ensure firing before onload,
2935 // maybe late but safe also for iframes
2936 document.attachEvent("onreadystatechange", function(){
2937 if ( document.readyState === "complete" ) {
2938 document.detachEvent( "onreadystatechange", arguments.callee );
2943 // If IE and not an iframe
2944 // continually check to see if the document is ready
2945 if ( document.documentElement.doScroll && !window.frameElement ) (function(){
2946 if ( jQuery.isReady ) return;
2949 // If IE is used, use the trick by Diego Perini
2950 // http://javascript.nwbox.com/IEContentLoaded/
2951 document.documentElement.doScroll("left");
2953 setTimeout( arguments.callee, 0 );
2957 // and execute any waiting functions
2962 // A fallback to window.onload, that will always work
2963 jQuery.event.add( window, "load", jQuery.ready );
2966 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
2967 "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
2968 "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
2970 // Handle event binding
2971 jQuery.fn[name] = function(fn){
2972 return fn ? this.bind(name, fn) : this.trigger(name);
2976 // Prevent memory leaks in IE
2977 // And prevent errors on refresh with events like mouseover in other browsers
2978 // Window isn't included so as not to unbind existing unload events
2979 jQuery( window ).bind( 'unload', function(){
2980 for ( var id in jQuery.cache )
2982 if ( id != 1 && jQuery.cache[ id ].handle )
2983 jQuery.event.remove( jQuery.cache[ id ].handle.elem );
2987 jQuery.support = {};
2989 var root = document.documentElement,
2990 script = document.createElement("script"),
2991 div = document.createElement("div"),
2992 id = "script" + (new Date).getTime();
2994 div.style.display = "none";
2995 div.innerHTML = ' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
2997 var all = div.getElementsByTagName("*"),
2998 a = div.getElementsByTagName("a")[0];
3000 // Can't get basic test support
3001 if ( !all || !all.length || !a ) {
3006 // IE strips leading whitespace when .innerHTML is used
3007 leadingWhitespace: div.firstChild.nodeType == 3,
3009 // Make sure that tbody elements aren't automatically inserted
3010 // IE will insert them into empty tables
3011 tbody: !div.getElementsByTagName("tbody").length,
3013 // Make sure that you can get all elements in an <object> element
3014 // IE 7 always returns no results
3015 objectAll: !!div.getElementsByTagName("object")[0]
3016 .getElementsByTagName("*").length,
3018 // Make sure that link elements get serialized correctly by innerHTML
3019 // This requires a wrapper element in IE
3020 htmlSerialize: !!div.getElementsByTagName("link").length,
3022 // Get the style information from getAttribute
3023 // (IE uses .cssText insted)
3024 style: /red/.test( a.getAttribute("style") ),
3026 // Make sure that URLs aren't manipulated
3027 // (IE normalizes it by default)
3028 hrefNormalized: a.getAttribute("href") === "/a",
3030 // Make sure that element opacity exists
3031 // (IE uses filter instead)
3032 opacity: a.style.opacity === "0.5",
3034 // Verify style float existence
3035 // (IE uses styleFloat instead of cssFloat)
3036 cssFloat: !!a.style.cssFloat,
3038 // Will be defined later
3044 script.type = "text/javascript";
3046 script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
3049 root.insertBefore( script, root.firstChild );
3051 // Make sure that the execution of code works by injecting a script
3052 // tag with appendChild/createTextNode
3053 // (IE doesn't support this, fails, and uses .text instead)
3054 if ( window[ id ] ) {
3055 jQuery.support.scriptEval = true;
3056 delete window[ id ];
3059 root.removeChild( script );
3061 if ( div.attachEvent && div.fireEvent ) {
3062 div.attachEvent("onclick", function(){
3063 // Cloning a node shouldn't copy over any
3064 // bound event handlers (IE does this)
3065 jQuery.support.noCloneEvent = false;
3066 div.detachEvent("onclick", arguments.callee);
3068 div.cloneNode(true).fireEvent("onclick");
3071 // Figure out if the W3C box model works as expected
3072 // document.body must exist before we can do this
3074 var div = document.createElement("div");
3075 div.style.width = "1px";
3076 div.style.paddingLeft = "1px";
3078 document.body.appendChild( div );
3079 jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
3080 document.body.removeChild( div );
3084 var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
3088 "class": "className",
3089 "float": styleFloat,
3090 cssFloat: styleFloat,
3091 styleFloat: styleFloat,
3092 readonly: "readOnly",
3093 maxlength: "maxLength",
3094 cellspacing: "cellSpacing",
3096 tabindex: "tabIndex"
3099 // Keep a copy of the old load
3100 _load: jQuery.fn.load,
3102 load: function( url, params, callback ) {
3103 if ( typeof url !== "string" )
3104 return this._load( url );
3106 var off = url.indexOf(" ");
3108 var selector = url.slice(off, url.length);
3109 url = url.slice(0, off);
3112 // Default to a GET request
3115 // If the second parameter was provided
3117 // If it's a function
3118 if ( jQuery.isFunction( params ) ) {
3119 // We assume that it's the callback
3123 // Otherwise, build a param string
3124 } else if( typeof params === "object" ) {
3125 params = jQuery.param( params );
3131 // Request the remote document
3137 complete: function(res, status){
3138 // If successful, inject the HTML into all the matched elements
3139 if ( status == "success" || status == "notmodified" )
3140 // See if a selector was specified
3141 self.html( selector ?
3142 // Create a dummy div to hold the results
3144 // inject the contents of the document in, removing the scripts
3145 // to avoid any 'Permission Denied' errors in IE
3146 .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
3148 // Locate the specified elements
3151 // If not, just inject the full result
3155 self.each( callback, [res.responseText, status, res] );
3161 serialize: function() {
3162 return jQuery.param(this.serializeArray());
3164 serializeArray: function() {
3165 return this.map(function(){
3166 return this.elements ? jQuery.makeArray(this.elements) : this;
3169 return this.name && !this.disabled &&
3170 (this.checked || /select|textarea/i.test(this.nodeName) ||
3171 /text|hidden|password/i.test(this.type));
3173 .map(function(i, elem){
3174 var val = jQuery(this).val();
3175 return val == null ? null :
3176 jQuery.isArray(val) ?
3177 jQuery.map( val, function(val, i){
3178 return {name: elem.name, value: val};
3180 {name: elem.name, value: val};
3185 // Attach a bunch of functions for handling common AJAX events
3186 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
3187 jQuery.fn[o] = function(f){
3188 return this.bind(o, f);
3196 get: function( url, data, callback, type ) {
3197 // shift arguments if data argument was ommited
3198 if ( jQuery.isFunction( data ) ) {
3203 return jQuery.ajax({
3212 getScript: function( url, callback ) {
3213 return jQuery.get(url, null, callback, "script");
3216 getJSON: function( url, data, callback ) {
3217 return jQuery.get(url, data, callback, "json");
3220 post: function( url, data, callback, type ) {
3221 if ( jQuery.isFunction( data ) ) {
3226 return jQuery.ajax({
3235 ajaxSetup: function( settings ) {
3236 jQuery.extend( jQuery.ajaxSettings, settings );
3243 contentType: "application/x-www-form-urlencoded",
3252 // Create the request object; Microsoft failed to properly
3253 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
3254 // This function can be overriden by calling jQuery.ajaxSetup
3256 return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
3259 xml: "application/xml, text/xml",
3261 script: "text/javascript, application/javascript",
3262 json: "application/json, text/javascript",
3268 // Last-Modified header cache for next request
3271 ajax: function( s ) {
3272 // Extend the settings, but re-extend 's' so that it can be
3273 // checked again later (in the test suite, specifically)
3274 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
3276 var jsonp, jsre = /=\?(&|$)/g, status, data,
3277 type = s.type.toUpperCase();
3279 // convert data if not already a string
3280 if ( s.data && s.processData && typeof s.data !== "string" )
3281 s.data = jQuery.param(s.data);
3283 // Handle JSONP Parameter Callbacks
3284 if ( s.dataType == "jsonp" ) {
3285 if ( type == "GET" ) {
3286 if ( !s.url.match(jsre) )
3287 s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
3288 } else if ( !s.data || !s.data.match(jsre) )
3289 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
3290 s.dataType = "json";
3293 // Build temporary JSONP function
3294 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
3295 jsonp = "jsonp" + jsc++;
3297 // Replace the =? sequence both in the query string and the data
3299 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
3300 s.url = s.url.replace(jsre, "=" + jsonp + "$1");
3302 // We need to make sure
3303 // that a JSONP style response is executed properly
3304 s.dataType = "script";
3306 // Handle JSONP-style loading
3307 window[ jsonp ] = function(tmp){
3312 window[ jsonp ] = undefined;
3313 try{ delete window[ jsonp ]; } catch(e){}
3315 head.removeChild( script );
3319 if ( s.dataType == "script" && s.cache == null )
3322 if ( s.cache === false && type == "GET" ) {
3324 // try replacing _= if it is there
3325 var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
3326 // if nothing was replaced, add timestamp to the end
3327 s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
3330 // If data is available, append data to url for get requests
3331 if ( s.data && type == "GET" ) {
3332 s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
3334 // IE likes to send both get and post data, prevent this
3338 // Watch for a new set of requests
3339 if ( s.global && ! jQuery.active++ )
3340 jQuery.event.trigger( "ajaxStart" );
3342 // Matches an absolute URL, and saves the domain
3343 var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
3345 // If we're requesting a remote document
3346 // and trying to load JSON or Script with a GET
3347 if ( s.dataType == "script" && type == "GET" && parts
3348 && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
3350 var head = document.getElementsByTagName("head")[0];
3351 var script = document.createElement("script");
3353 if (s.scriptCharset)
3354 script.charset = s.scriptCharset;
3356 // Handle Script loading
3360 // Attach handlers for all browsers
3361 script.onload = script.onreadystatechange = function(){
3362 if ( !done && (!this.readyState ||
3363 this.readyState == "loaded" || this.readyState == "complete") ) {
3367 head.removeChild( script );
3372 head.appendChild(script);
3374 // We handle everything using the script element injection
3378 var requestDone = false;
3380 // Create the request object
3384 // Passing null username, generates a login popup on Opera (#2865)
3386 xhr.open(type, s.url, s.async, s.username, s.password);
3388 xhr.open(type, s.url, s.async);
3390 // Need an extra try/catch for cross domain requests in Firefox 3
3392 // Set the correct header, if data is being sent
3394 xhr.setRequestHeader("Content-Type", s.contentType);
3396 // Set the If-Modified-Since header, if ifModified mode.
3398 xhr.setRequestHeader("If-Modified-Since",
3399 jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
3401 // Set header so the called script knows that it's an XMLHttpRequest
3402 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
3404 // Set the Accepts header for the server, depending on the dataType
3405 xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
3406 s.accepts[ s.dataType ] + ", */*" :
3407 s.accepts._default );
3410 // Allow custom headers/mimetypes and early abort
3411 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
3412 // Handle the global AJAX counter
3413 if ( s.global && ! --jQuery.active )
3414 jQuery.event.trigger( "ajaxStop" );
3415 // close opended socket
3421 jQuery.event.trigger("ajaxSend", [xhr, s]);
3423 // Wait for a response to come back
3424 var onreadystatechange = function(isTimeout){
3425 // The request was aborted, clear the interval and decrement jQuery.active
3426 if (xhr.readyState == 0) {
3428 // clear poll interval
3429 clearInterval(ival);
3431 // Handle the global AJAX counter
3432 if ( s.global && ! --jQuery.active )
3433 jQuery.event.trigger( "ajaxStop" );
3435 // The transfer is complete and the data is available, or the request timed out
3436 } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
3439 // clear poll interval
3441 clearInterval(ival);
3445 status = isTimeout == "timeout" ? "timeout" :
3446 !jQuery.httpSuccess( xhr ) ? "error" :
3447 s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
3450 if ( status == "success" ) {
3451 // Watch for, and catch, XML document parse errors
3453 // process the data (runs the xml through httpData regardless of callback)
3454 data = jQuery.httpData( xhr, s.dataType, s );
3456 status = "parsererror";
3460 // Make sure that the request was successful or notmodified
3461 if ( status == "success" ) {
3462 // Cache Last-Modified header, if ifModified mode.
3465 modRes = xhr.getResponseHeader("Last-Modified");
3466 } catch(e) {} // swallow exception thrown by FF if header is not available
3468 if ( s.ifModified && modRes )
3469 jQuery.lastModified[s.url] = modRes;
3471 // JSONP handles its own success callback
3475 jQuery.handleError(s, xhr, status);
3477 // Fire the complete handlers
3480 // Stop memory leaks
3487 // don't attach the handler to the request, just poll it instead
3488 var ival = setInterval(onreadystatechange, 13);
3491 if ( s.timeout > 0 )
3492 setTimeout(function(){
3493 // Check to see if the request is still happening
3496 onreadystatechange( "timeout" );
3498 // Cancel the request
3509 jQuery.handleError(s, xhr, null, e);
3512 // firefox 1.5 doesn't fire statechange for sync requests
3514 onreadystatechange();
3517 // If a local callback was specified, fire it and pass it the data
3519 s.success( data, status );
3521 // Fire the global callback
3523 jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
3526 function complete(){
3529 s.complete(xhr, status);
3531 // The request was completed
3533 jQuery.event.trigger( "ajaxComplete", [xhr, s] );
3535 // Handle the global AJAX counter
3536 if ( s.global && ! --jQuery.active )
3537 jQuery.event.trigger( "ajaxStop" );
3540 // return XMLHttpRequest to allow aborting the request etc.
3544 handleError: function( s, xhr, status, e ) {
3545 // If a local callback was specified, fire it
3546 if ( s.error ) s.error( xhr, status, e );
3548 // Fire the global callback
3550 jQuery.event.trigger( "ajaxError", [xhr, s, e] );
3553 // Counter for holding the number of active queries
3556 // Determines if an XMLHttpRequest was successful or not
3557 httpSuccess: function( xhr ) {
3559 // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
3560 return !xhr.status && location.protocol == "file:" ||
3561 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
3566 // Determines if an XMLHttpRequest returns NotModified
3567 httpNotModified: function( xhr, url ) {
3569 var xhrRes = xhr.getResponseHeader("Last-Modified");
3571 // Firefox always returns 200. check Last-Modified date
3572 return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
3577 httpData: function( xhr, type, s ) {
3578 var ct = xhr.getResponseHeader("content-type"),
3579 xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
3580 data = xml ? xhr.responseXML : xhr.responseText;
3582 if ( xml && data.documentElement.tagName == "parsererror" )
3583 throw "parsererror";
3585 // Allow a pre-filtering function to sanitize the response
3586 // s != null is checked to keep backwards compatibility
3587 if( s && s.dataFilter )
3588 data = s.dataFilter( data, type );
3590 // The filter can actually parse the response
3591 if( typeof data === "string" ){
3593 // If the type is "script", eval it in global context
3594 if ( type == "script" )
3595 jQuery.globalEval( data );
3597 // Get the JavaScript object, if JSON is used.
3598 if ( type == "json" )
3599 data = window["eval"]("(" + data + ")");
3605 // Serialize an array of form elements or a set of
3606 // key/values into a query string
3607 param: function( a ) {
3610 function add( key, value ){
3611 s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
3614 // If an array was passed in, assume that it is an array
3616 if ( jQuery.isArray(a) || a.jquery )
3617 // Serialize the form elements
3618 jQuery.each( a, function(){
3619 add( this.name, this.value );
3622 // Otherwise, assume that it's an object of key/value pairs
3624 // Serialize the key/values
3626 // If the value is an array then the key names need to be repeated
3627 if ( jQuery.isArray(a[j]) )
3628 jQuery.each( a[j], function(){
3632 add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
3634 // Return the resulting serialization
3635 return s.join("&").replace(/%20/g, "+");
3639 var elemdisplay = {},
3641 // height animations
3642 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
3644 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
3645 // opacity animations
3649 function genFx( type, num ){
3651 jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
3658 show: function(speed,callback){
3660 return this.animate( genFx("show", 3), speed, callback);
3662 for ( var i = 0, l = this.length; i < l; i++ ){
3663 var old = jQuery.data(this[i], "olddisplay");
3665 this[i].style.display = old || "";
3667 if ( jQuery.css(this[i], "display") === "none" ) {
3668 var tagName = this[i].tagName, display;
3670 if ( elemdisplay[ tagName ] ) {
3671 display = elemdisplay[ tagName ];
3673 var elem = jQuery("<" + tagName + " />").appendTo("body");
3675 display = elem.css("display");
3676 if ( display === "none" )
3681 elemdisplay[ tagName ] = display;
3684 this[i].style.display = jQuery.data(this[i], "olddisplay", display);
3692 hide: function(speed,callback){
3694 return this.animate( genFx("hide", 3), speed, callback);
3696 for ( var i = 0, l = this.length; i < l; i++ ){
3697 var old = jQuery.data(this[i], "olddisplay");
3698 if ( !old && old !== "none" )
3699 jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
3700 this[i].style.display = "none";
3706 // Save the old toggle function
3707 _toggle: jQuery.fn.toggle,
3709 toggle: function( fn, fn2 ){
3710 var bool = typeof fn === "boolean";
3712 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
3713 this._toggle.apply( this, arguments ) :
3714 fn == null || bool ?
3715 this.each(function(){
3716 var state = bool ? fn : jQuery(this).is(":hidden");
3717 jQuery(this)[ state ? "show" : "hide" ]();
3719 this.animate(genFx("toggle", 3), fn, fn2);
3722 fadeTo: function(speed,to,callback){
3723 return this.animate({opacity: to}, speed, callback);
3726 animate: function( prop, speed, easing, callback ) {
3727 var optall = jQuery.speed(speed, easing, callback);
3729 return this[ optall.queue === false ? "each" : "queue" ](function(){
3731 var opt = jQuery.extend({}, optall), p,
3732 hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
3736 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
3737 return opt.complete.call(this);
3739 if ( ( p == "height" || p == "width" ) && this.style ) {
3740 // Store display property
3741 opt.display = jQuery.css(this, "display");
3743 // Make sure that nothing sneaks out
3744 opt.overflow = this.style.overflow;
3748 if ( opt.overflow != null )
3749 this.style.overflow = "hidden";
3751 opt.curAnim = jQuery.extend({}, prop);
3753 jQuery.each( prop, function(name, val){
3754 var e = new jQuery.fx( self, opt, name );
3756 if ( /toggle|show|hide/.test(val) )
3757 e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
3759 var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
3760 start = e.cur(true) || 0;
3763 var end = parseFloat(parts[2]),
3764 unit = parts[3] || "px";
3766 // We need to compute starting value
3767 if ( unit != "px" ) {
3768 self.style[ name ] = (end || 1) + unit;
3769 start = ((end || 1) / e.cur(true)) * start;
3770 self.style[ name ] = start + unit;
3773 // If a +=/-= token was provided, we're doing a relative animation
3775 end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
3777 e.custom( start, end, unit );
3779 e.custom( start, val, "" );
3783 // For JS strict compliance
3788 stop: function(clearQueue, gotoEnd){
3789 var timers = jQuery.timers;
3794 this.each(function(){
3795 // go in reverse order so anything added to the queue during the loop is ignored
3796 for ( var i = timers.length - 1; i >= 0; i-- )
3797 if ( timers[i].elem == this ) {
3799 // force the next step to be the last
3801 timers.splice(i, 1);
3805 // start the next in the queue if the last step wasn't forced
3814 // Generate shortcuts for custom animations
3816 slideDown: genFx("show", 1),
3817 slideUp: genFx("hide", 1),
3818 slideToggle: genFx("toggle", 1),
3819 fadeIn: { opacity: "show" },
3820 fadeOut: { opacity: "hide" }
3821 }, function( name, props ){
3822 jQuery.fn[ name ] = function( speed, callback ){
3823 return this.animate( props, speed, callback );
3829 speed: function(speed, easing, fn) {
3830 var opt = typeof speed === "object" ? speed : {
3831 complete: fn || !fn && easing ||
3832 jQuery.isFunction( speed ) && speed,
3834 easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
3837 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
3838 jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
3841 opt.old = opt.complete;
3842 opt.complete = function(){
3843 if ( opt.queue !== false )
3844 jQuery(this).dequeue();
3845 if ( jQuery.isFunction( opt.old ) )
3846 opt.old.call( this );
3853 linear: function( p, n, firstNum, diff ) {
3854 return firstNum + diff * p;
3856 swing: function( p, n, firstNum, diff ) {
3857 return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
3864 fx: function( elem, options, prop ){
3865 this.options = options;
3869 if ( !options.orig )
3875 jQuery.fx.prototype = {
3877 // Simple function for setting a style value
3879 if ( this.options.step )
3880 this.options.step.call( this.elem, this.now, this );
3882 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
3884 // Set display property to block for height/width animations
3885 if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
3886 this.elem.style.display = "block";
3889 // Get the current size
3890 cur: function(force){
3891 if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
3892 return this.elem[ this.prop ];
3894 var r = parseFloat(jQuery.css(this.elem, this.prop, force));
3895 return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
3898 // Start an animation from one number to another
3899 custom: function(from, to, unit){
3900 this.startTime = now();
3903 this.unit = unit || this.unit || "px";
3904 this.now = this.start;
3905 this.pos = this.state = 0;
3908 function t(gotoEnd){
3909 return self.step(gotoEnd);
3914 jQuery.timers.push(t);
3916 if ( t() && jQuery.timerId == null ) {
3917 jQuery.timerId = setInterval(function(){
3918 var timers = jQuery.timers;
3920 for ( var i = 0; i < timers.length; i++ )
3922 timers.splice(i--, 1);
3924 if ( !timers.length ) {
3925 clearInterval( jQuery.timerId );
3926 jQuery.timerId = null;
3932 // Simple 'show' function
3934 // Remember where we started, so that we can go back to it later
3935 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
3936 this.options.show = true;
3938 // Begin the animation
3939 // Make sure that we start at a small width/height to avoid any
3941 this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
3943 // Start by showing the element
3944 jQuery(this.elem).show();
3947 // Simple 'hide' function
3949 // Remember where we started, so that we can go back to it later
3950 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
3951 this.options.hide = true;
3953 // Begin the animation
3954 this.custom(this.cur(), 0);
3957 // Each step of an animation
3958 step: function(gotoEnd){
3961 if ( gotoEnd || t >= this.options.duration + this.startTime ) {
3962 this.now = this.end;
3963 this.pos = this.state = 1;
3966 this.options.curAnim[ this.prop ] = true;
3969 for ( var i in this.options.curAnim )
3970 if ( this.options.curAnim[i] !== true )
3974 if ( this.options.display != null ) {
3975 // Reset the overflow
3976 this.elem.style.overflow = this.options.overflow;
3978 // Reset the display
3979 this.elem.style.display = this.options.display;
3980 if ( jQuery.css(this.elem, "display") == "none" )
3981 this.elem.style.display = "block";
3984 // Hide the element if the "hide" operation was done
3985 if ( this.options.hide )
3986 jQuery(this.elem).hide();
3988 // Reset the properties, if the item has been hidden or shown
3989 if ( this.options.hide || this.options.show )
3990 for ( var p in this.options.curAnim )
3991 jQuery.attr(this.elem.style, p, this.options.orig[p]);
3995 // Execute the complete function
3996 this.options.complete.call( this.elem );
4000 var n = t - this.startTime;
4001 this.state = n / this.options.duration;
4003 // Perform the easing function, defaults to swing
4004 this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
4005 this.now = this.start + ((this.end - this.start) * this.pos);
4007 // Perform the next step of the animation
4016 jQuery.extend( jQuery.fx, {
4025 opacity: function(fx){
4026 jQuery.attr(fx.elem.style, "opacity", fx.now);
4029 _default: function(fx){
4030 if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
4031 fx.elem.style[ fx.prop ] = fx.now + fx.unit;
4033 fx.elem[ fx.prop ] = fx.now;
4037 if ( document.documentElement["getBoundingClientRect"] )
4038 jQuery.fn.offset = function() {
4039 if ( !this[0] ) return { top: 0, left: 0 };
4040 if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
4041 var box = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
4042 clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
4043 top = box.top + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop,
4044 left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
4045 return { top: top, left: left };
4048 jQuery.fn.offset = function() {
4049 if ( !this[0] ) return { top: 0, left: 0 };
4050 if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
4051 jQuery.offset.initialized || jQuery.offset.initialize();
4053 var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
4054 doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
4055 body = doc.body, defaultView = doc.defaultView,
4056 prevComputedStyle = defaultView.getComputedStyle(elem, null),
4057 top = elem.offsetTop, left = elem.offsetLeft;
4059 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
4060 computedStyle = defaultView.getComputedStyle(elem, null);
4061 top -= elem.scrollTop, left -= elem.scrollLeft;
4062 if ( elem === offsetParent ) {
4063 top += elem.offsetTop, left += elem.offsetLeft;
4064 if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
4065 top += parseInt( computedStyle.borderTopWidth, 10) || 0,
4066 left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
4067 prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
4069 if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
4070 top += parseInt( computedStyle.borderTopWidth, 10) || 0,
4071 left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
4072 prevComputedStyle = computedStyle;
4075 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
4076 top += body.offsetTop,
4077 left += body.offsetLeft;
4079 if ( prevComputedStyle.position === "fixed" )
4080 top += Math.max(docElem.scrollTop, body.scrollTop),
4081 left += Math.max(docElem.scrollLeft, body.scrollLeft);
4083 return { top: top, left: left };
4087 initialize: function() {
4088 if ( this.initialized ) return;
4089 var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
4090 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>';
4092 rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
4093 for ( prop in rules ) container.style[prop] = rules[prop];
4095 container.innerHTML = html;
4096 body.insertBefore(container, body.firstChild);
4097 innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
4099 this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
4100 this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
4102 innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
4103 this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
4105 body.style.marginTop = '1px';
4106 this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
4107 body.style.marginTop = bodyMarginTop;
4109 body.removeChild(container);
4110 this.initialized = true;
4113 bodyOffset: function(body) {
4114 jQuery.offset.initialized || jQuery.offset.initialize();
4115 var top = body.offsetTop, left = body.offsetLeft;
4116 if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
4117 top += parseInt( jQuery.curCSS(body, 'marginTop', true), 10 ) || 0,
4118 left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
4119 return { top: top, left: left };
4125 position: function() {
4126 var left = 0, top = 0, results;
4129 // Get *real* offsetParent
4130 var offsetParent = this.offsetParent(),
4132 // Get correct offsets
4133 offset = this.offset(),
4134 parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
4136 // Subtract element margins
4137 // note: when an element has margin: auto the offsetLeft and marginLeft
4138 // are the same in Safari causing offset.left to incorrectly be 0
4139 offset.top -= num( this, 'marginTop' );
4140 offset.left -= num( this, 'marginLeft' );
4142 // Add offsetParent borders
4143 parentOffset.top += num( offsetParent, 'borderTopWidth' );
4144 parentOffset.left += num( offsetParent, 'borderLeftWidth' );
4146 // Subtract the two offsets
4148 top: offset.top - parentOffset.top,
4149 left: offset.left - parentOffset.left
4156 offsetParent: function() {
4157 var offsetParent = this[0].offsetParent || document.body;
4158 while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
4159 offsetParent = offsetParent.offsetParent;
4160 return jQuery(offsetParent);
4165 // Create scrollLeft and scrollTop methods
4166 jQuery.each( ['Left', 'Top'], function(i, name) {
4167 var method = 'scroll' + name;
4169 jQuery.fn[ method ] = function(val) {
4170 if (!this[0]) return null;
4172 return val !== undefined ?
4174 // Set the scroll offset
4175 this.each(function() {
4176 this == window || this == document ?
4178 !i ? val : jQuery(window).scrollLeft(),
4179 i ? val : jQuery(window).scrollTop()
4181 this[ method ] = val;
4184 // Return the scroll offset
4185 this[0] == window || this[0] == document ?
4186 self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
4187 jQuery.boxModel && document.documentElement[ method ] ||
4188 document.body[ method ] :
4192 // Create innerHeight, innerWidth, outerHeight and outerWidth methods
4193 jQuery.each([ "Height", "Width" ], function(i, name){
4195 var tl = i ? "Left" : "Top", // top or left
4196 br = i ? "Right" : "Bottom"; // bottom or right
4198 // innerHeight and innerWidth
4199 jQuery.fn["inner" + name] = function(){
4200 return this[ name.toLowerCase() ]() +
4201 num(this, "padding" + tl) +
4202 num(this, "padding" + br);
4205 // outerHeight and outerWidth
4206 jQuery.fn["outer" + name] = function(margin) {
4207 return this["inner" + name]() +
4208 num(this, "border" + tl + "Width") +
4209 num(this, "border" + br + "Width") +
4211 num(this, "margin" + tl) + num(this, "margin" + br) : 0);
4214 var type = name.toLowerCase();
4216 jQuery.fn[ type ] = function( size ) {
4217 // Get window width or height
4218 return this[0] == window ?
4219 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
4220 document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
4221 document.body[ "client" + name ] :
4223 // Get document width or height
4224 this[0] == document ?
4225 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
4227 document.documentElement["client" + name],
4228 document.body["scroll" + name], document.documentElement["scroll" + name],
4229 document.body["offset" + name], document.documentElement["offset" + name]
4232 // Get or set width or height on the element
4233 size === undefined ?
4234 // Get width or height on the element
4235 (this.length ? jQuery.css( this[0], type ) : null) :
4237 // Set the width or height on the element (default to pixels if value is unitless)
4238 this.css( type, typeof size === "string" ? size : size + "px" );