2 * jQuery JavaScript Library v1.3.1
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-21 20:42:16 -0500 (Wed, 21 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 // Handle the case where IE and Opera return items
64 // by name instead of ID
65 if ( elem && elem.id != match[3] )
66 return jQuery().find( selector );
68 // Otherwise, we inject the element directly into the jQuery object
69 var ret = jQuery( elem || [] );
70 ret.context = document;
71 ret.selector = selector;
75 // HANDLE: $(expr, [context])
76 // (which is just equivalent to: $(content).find(expr)
78 return jQuery( context ).find( selector );
80 // HANDLE: $(function)
81 // Shortcut for document ready
82 } else if ( jQuery.isFunction( selector ) )
83 return jQuery( document ).ready( selector );
85 // Make sure that old selector state is passed along
86 if ( selector.selector && selector.context ) {
87 this.selector = selector.selector;
88 this.context = selector.context;
91 return this.setArray(jQuery.makeArray(selector));
94 // Start with an empty selector
97 // The current version of jQuery being used
100 // The number of elements contained in the matched element set
105 // Get the Nth element in the matched element set OR
106 // Get the whole matched element set as a clean array
107 get: function( num ) {
108 return num === undefined ?
110 // Return a 'clean' array
111 jQuery.makeArray( this ) :
113 // Return just the object
117 // Take an array of elements and push it onto the stack
118 // (returning the new matched element set)
119 pushStack: function( elems, name, selector ) {
120 // Build a new jQuery matched element set
121 var ret = jQuery( elems );
123 // Add the old object onto the stack (as a reference)
124 ret.prevObject = this;
126 ret.context = this.context;
128 if ( name === "find" )
129 ret.selector = this.selector + (this.selector ? " " : "") + selector;
131 ret.selector = this.selector + "." + name + "(" + selector + ")";
133 // Return the newly-formed element set
137 // Force the current matched set of elements to become
138 // the specified array of elements (destroying the stack in the process)
139 // You should use pushStack() in order to do this, but maintain the stack
140 setArray: function( elems ) {
141 // Resetting the length to 0, then using the native Array push
142 // is a super-fast way to populate an object with array-like properties
144 Array.prototype.push.apply( this, elems );
149 // Execute a callback for every element in the matched set.
150 // (You can seed the arguments with an array of args, but this is
151 // only used internally.)
152 each: function( callback, args ) {
153 return jQuery.each( this, callback, args );
156 // Determine the position of an element within
157 // the matched set of elements
158 index: function( elem ) {
159 // Locate the position of the desired element
160 return jQuery.inArray(
161 // If it receives a jQuery object, the first element is used
162 elem && elem.jquery ? elem[0] : elem
166 attr: function( name, value, type ) {
169 // Look for the case where we're accessing a style value
170 if ( typeof name === "string" )
171 if ( value === undefined )
172 return this[0] && jQuery[ type || "attr" ]( this[0], name );
176 options[ name ] = value;
179 // Check to see if we're setting style values
180 return this.each(function(i){
181 // Set all the styles
182 for ( name in options )
187 name, jQuery.prop( this, options[ name ], type, i, name )
192 css: function( key, value ) {
193 // ignore negative width and height values
194 if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
196 return this.attr( key, value, "curCSS" );
199 text: function( text ) {
200 if ( typeof text !== "object" && text != null )
201 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
205 jQuery.each( text || this, function(){
206 jQuery.each( this.childNodes, function(){
207 if ( this.nodeType != 8 )
208 ret += this.nodeType != 1 ?
210 jQuery.fn.text( [ this ] );
217 wrapAll: function( html ) {
219 // The elements to wrap the target around
220 var wrap = jQuery( html, this[0].ownerDocument ).clone();
222 if ( this[0].parentNode )
223 wrap.insertBefore( this[0] );
228 while ( elem.firstChild )
229 elem = elem.firstChild;
238 wrapInner: function( html ) {
239 return this.each(function(){
240 jQuery( this ).contents().wrapAll( html );
244 wrap: function( html ) {
245 return this.each(function(){
246 jQuery( this ).wrapAll( html );
251 return this.domManip(arguments, true, function(elem){
252 if (this.nodeType == 1)
253 this.appendChild( elem );
257 prepend: function() {
258 return this.domManip(arguments, true, function(elem){
259 if (this.nodeType == 1)
260 this.insertBefore( elem, this.firstChild );
265 return this.domManip(arguments, false, function(elem){
266 this.parentNode.insertBefore( elem, this );
271 return this.domManip(arguments, false, function(elem){
272 this.parentNode.insertBefore( elem, this.nextSibling );
277 return this.prevObject || jQuery( [] );
280 // For internal use only.
281 // Behaves like an Array's .push method, not like a jQuery method.
284 find: function( selector ) {
285 if ( this.length === 1 && !/,/.test(selector) ) {
286 var ret = this.pushStack( [], "find", selector );
288 jQuery.find( selector, this[0], ret );
291 var elems = jQuery.map(this, function(elem){
292 return jQuery.find( selector, elem );
295 return this.pushStack( /[^+>] [^+>]/.test( selector ) ?
296 jQuery.unique( elems ) :
297 elems, "find", selector );
301 clone: function( events ) {
303 var ret = this.map(function(){
304 if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
305 // IE copies events bound via attachEvent when
306 // using cloneNode. Calling detachEvent on the
307 // clone will also remove the events from the orignal
308 // In order to get around this, we use innerHTML.
309 // Unfortunately, this means some modifications to
310 // attributes in IE that are actually only stored
311 // as properties will not be copied (such as the
312 // the name attribute on an input).
313 var clone = this.cloneNode(true),
314 container = document.createElement("div");
315 container.appendChild(clone);
316 return jQuery.clean([container.innerHTML])[0];
318 return this.cloneNode(true);
321 // Need to set the expando to null on the cloned set if it exists
322 // removeData doesn't work here, IE removes it from the original as well
323 // this is primarily for IE but the data expando shouldn't be copied over in any browser
324 var clone = ret.find("*").andSelf().each(function(){
325 if ( this[ expando ] !== undefined )
326 this[ expando ] = null;
329 // Copy the events from the original to the clone
330 if ( events === true )
331 this.find("*").andSelf().each(function(i){
332 if (this.nodeType == 3)
334 var events = jQuery.data( this, "events" );
336 for ( var type in events )
337 for ( var handler in events[ type ] )
338 jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
341 // Return the cloned set
345 filter: function( selector ) {
346 return this.pushStack(
347 jQuery.isFunction( selector ) &&
348 jQuery.grep(this, function(elem, i){
349 return selector.call( elem, i );
352 jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
353 return elem.nodeType === 1;
354 }) ), "filter", selector );
357 closest: function( selector ) {
358 var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null;
360 return this.map(function(){
362 while ( cur && cur.ownerDocument ) {
363 if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) )
365 cur = cur.parentNode;
370 not: function( selector ) {
371 if ( typeof selector === "string" )
372 // test special case where just one selector is passed in
373 if ( isSimple.test( selector ) )
374 return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
376 selector = jQuery.multiFilter( selector, this );
378 var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
379 return this.filter(function() {
380 return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
384 add: function( selector ) {
385 return this.pushStack( jQuery.unique( jQuery.merge(
387 typeof selector === "string" ?
389 jQuery.makeArray( selector )
393 is: function( selector ) {
394 return !!selector && jQuery.multiFilter( selector, this ).length > 0;
397 hasClass: function( selector ) {
398 return !!selector && this.is( "." + selector );
401 val: function( value ) {
402 if ( value === undefined ) {
406 if( jQuery.nodeName( elem, 'option' ) )
407 return (elem.attributes.value || {}).specified ? elem.value : elem.text;
409 // We need to handle select boxes special
410 if ( jQuery.nodeName( elem, "select" ) ) {
411 var index = elem.selectedIndex,
413 options = elem.options,
414 one = elem.type == "select-one";
416 // Nothing was selected
420 // Loop through all the selected options
421 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
422 var option = options[ i ];
424 if ( option.selected ) {
425 // Get the specifc value for the option
426 value = jQuery(option).val();
428 // We don't need an array for one selects
432 // Multi-Selects return an array
433 values.push( value );
440 // Everything else, we just grab the value
441 return (elem.value || "").replace(/\r/g, "");
448 if ( typeof value === "number" )
451 return this.each(function(){
452 if ( this.nodeType != 1 )
455 if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
456 this.checked = (jQuery.inArray(this.value, value) >= 0 ||
457 jQuery.inArray(this.name, value) >= 0);
459 else if ( jQuery.nodeName( this, "select" ) ) {
460 var values = jQuery.makeArray(value);
462 jQuery( "option", this ).each(function(){
463 this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
464 jQuery.inArray( this.text, values ) >= 0);
467 if ( !values.length )
468 this.selectedIndex = -1;
475 html: function( value ) {
476 return value === undefined ?
480 this.empty().append( value );
483 replaceWith: function( value ) {
484 return this.after( value ).remove();
488 return this.slice( i, +i + 1 );
492 return this.pushStack( Array.prototype.slice.apply( this, arguments ),
493 "slice", Array.prototype.slice.call(arguments).join(",") );
496 map: function( callback ) {
497 return this.pushStack( jQuery.map(this, function(elem, i){
498 return callback.call( elem, i, elem );
502 andSelf: function() {
503 return this.add( this.prevObject );
506 domManip: function( args, table, callback ) {
508 var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
509 scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
510 first = fragment.firstChild,
511 extra = this.length > 1 ? fragment.cloneNode(true) : fragment;
514 for ( var i = 0, l = this.length; i < l; i++ )
515 callback.call( root(this[i], first), i > 0 ? extra.cloneNode(true) : fragment );
518 jQuery.each( scripts, evalScript );
523 function root( elem, cur ) {
524 return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
525 (elem.getElementsByTagName("tbody")[0] ||
526 elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
532 // Give the init function the jQuery prototype for later instantiation
533 jQuery.fn.init.prototype = jQuery.fn;
535 function evalScript( i, elem ) {
544 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
546 if ( elem.parentNode )
547 elem.parentNode.removeChild( elem );
554 jQuery.extend = jQuery.fn.extend = function() {
555 // copy reference to target object
556 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
558 // Handle a deep copy situation
559 if ( typeof target === "boolean" ) {
561 target = arguments[1] || {};
562 // skip the boolean and the target
566 // Handle case when target is a string or something (possible in deep copy)
567 if ( typeof target !== "object" && !jQuery.isFunction(target) )
570 // extend jQuery itself if only one argument is passed
576 for ( ; i < length; i++ )
577 // Only deal with non-null/undefined values
578 if ( (options = arguments[ i ]) != null )
579 // Extend the base object
580 for ( var name in options ) {
581 var src = target[ name ], copy = options[ name ];
583 // Prevent never-ending loop
584 if ( target === copy )
587 // Recurse if we're merging object values
588 if ( deep && copy && typeof copy === "object" && !copy.nodeType )
589 target[ name ] = jQuery.extend( deep,
590 // Never move original objects, clone them
591 src || ( copy.length != null ? [ ] : { } )
594 // Don't bring in undefined values
595 else if ( copy !== undefined )
596 target[ name ] = copy;
600 // Return the modified object
604 // exclude the following css properties to add px
605 var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
607 defaultView = document.defaultView || {},
608 toString = Object.prototype.toString;
611 noConflict: function( deep ) {
615 window.jQuery = _jQuery;
620 // See test/unit/core.js for details concerning isFunction.
621 // Since version 1.3, DOM methods and functions like alert
622 // aren't supported. They return false on IE (#2968).
623 isFunction: function( obj ) {
624 return toString.call(obj) === "[object Function]";
627 isArray: function( obj ) {
628 return toString.call(obj) === "[object Array]";
631 // check if an element is in a (or is an) XML document
632 isXMLDoc: function( elem ) {
633 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
634 !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
637 // Evalulates a script in a global context
638 globalEval: function( data ) {
639 data = jQuery.trim( data );
642 // Inspired by code by Andrea Giammarchi
643 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
644 var head = document.getElementsByTagName("head")[0] || document.documentElement,
645 script = document.createElement("script");
647 script.type = "text/javascript";
648 if ( jQuery.support.scriptEval )
649 script.appendChild( document.createTextNode( data ) );
653 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
654 // This arises when a base node is used (#2709).
655 head.insertBefore( script, head.firstChild );
656 head.removeChild( script );
660 nodeName: function( elem, name ) {
661 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
664 // args is for internal usage only
665 each: function( object, callback, args ) {
666 var name, i = 0, length = object.length;
669 if ( length === undefined ) {
670 for ( name in object )
671 if ( callback.apply( object[ name ], args ) === false )
674 for ( ; i < length; )
675 if ( callback.apply( object[ i++ ], args ) === false )
678 // A special, fast, case for the most common use of each
680 if ( length === undefined ) {
681 for ( name in object )
682 if ( callback.call( object[ name ], name, object[ name ] ) === false )
685 for ( var value = object[0];
686 i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
692 prop: function( elem, value, type, i, name ) {
693 // Handle executable functions
694 if ( jQuery.isFunction( value ) )
695 value = value.call( elem, i );
697 // Handle passing in a number to a CSS property
698 return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
704 // internal only, use addClass("class")
705 add: function( elem, classNames ) {
706 jQuery.each((classNames || "").split(/\s+/), function(i, className){
707 if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
708 elem.className += (elem.className ? " " : "") + className;
712 // internal only, use removeClass("class")
713 remove: function( elem, classNames ) {
714 if (elem.nodeType == 1)
715 elem.className = classNames !== undefined ?
716 jQuery.grep(elem.className.split(/\s+/), function(className){
717 return !jQuery.className.has( classNames, className );
722 // internal only, use hasClass("class")
723 has: function( elem, className ) {
724 return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
728 // A method for quickly swapping in/out CSS properties to get correct calculations
729 swap: function( elem, options, callback ) {
731 // Remember the old values, and insert the new ones
732 for ( var name in options ) {
733 old[ name ] = elem.style[ name ];
734 elem.style[ name ] = options[ name ];
737 callback.call( elem );
739 // Revert the old values
740 for ( var name in options )
741 elem.style[ name ] = old[ name ];
744 css: function( elem, name, force ) {
745 if ( name == "width" || name == "height" ) {
746 var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
749 val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
750 var padding = 0, border = 0;
751 jQuery.each( which, function() {
752 padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
753 border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
755 val -= Math.round(padding + border);
758 if ( jQuery(elem).is(":visible") )
761 jQuery.swap( elem, props, getWH );
763 return Math.max(0, val);
766 return jQuery.curCSS( elem, name, force );
769 curCSS: function( elem, name, force ) {
770 var ret, style = elem.style;
772 // We need to handle opacity special in IE
773 if ( name == "opacity" && !jQuery.support.opacity ) {
774 ret = jQuery.attr( style, "opacity" );
781 // Make sure we're using the right name for getting the float value
782 if ( name.match( /float/i ) )
785 if ( !force && style && style[ name ] )
788 else if ( defaultView.getComputedStyle ) {
790 // Only "float" is needed here
791 if ( name.match( /float/i ) )
794 name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
796 var computedStyle = defaultView.getComputedStyle( elem, null );
799 ret = computedStyle.getPropertyValue( name );
801 // We should always get a number back from opacity
802 if ( name == "opacity" && ret == "" )
805 } else if ( elem.currentStyle ) {
806 var camelCase = name.replace(/\-(\w)/g, function(all, letter){
807 return letter.toUpperCase();
810 ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
812 // From the awesome hack by Dean Edwards
813 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
815 // If we're not dealing with a regular pixel number
816 // but a number that has a weird ending, we need to convert it to pixels
817 if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
818 // Remember the original values
819 var left = style.left, rsLeft = elem.runtimeStyle.left;
821 // Put in the new values to get a computed value out
822 elem.runtimeStyle.left = elem.currentStyle.left;
823 style.left = ret || 0;
824 ret = style.pixelLeft + "px";
826 // Revert the changed values
828 elem.runtimeStyle.left = rsLeft;
835 clean: function( elems, context, fragment ) {
836 context = context || document;
838 // !context.createElement fails in IE with an error but returns typeof 'object'
839 if ( typeof context.createElement === "undefined" )
840 context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
842 // If a single string is passed in and it's a single tag
843 // just do a createElement and skip the rest
844 if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
845 var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
847 return [ context.createElement( match[1] ) ];
850 var ret = [], scripts = [], div = context.createElement("div");
852 jQuery.each(elems, function(i, elem){
853 if ( typeof elem === "number" )
859 // Convert html string into DOM nodes
860 if ( typeof elem === "string" ) {
861 // Fix "XHTML"-style tags in all browsers
862 elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
863 return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
865 front + "></" + tag + ">";
868 // Trim whitespace, otherwise indexOf won't work as expected
869 var tags = jQuery.trim( elem ).toLowerCase();
872 // option or optgroup
873 !tags.indexOf("<opt") &&
874 [ 1, "<select multiple='multiple'>", "</select>" ] ||
876 !tags.indexOf("<leg") &&
877 [ 1, "<fieldset>", "</fieldset>" ] ||
879 tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
880 [ 1, "<table>", "</table>" ] ||
882 !tags.indexOf("<tr") &&
883 [ 2, "<table><tbody>", "</tbody></table>" ] ||
885 // <thead> matched above
886 (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
887 [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
889 !tags.indexOf("<col") &&
890 [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
892 // IE can't serialize <link> and <script> tags normally
893 !jQuery.support.htmlSerialize &&
894 [ 1, "div<div>", "</div>" ] ||
898 // Go to html and back, then peel off extra wrappers
899 div.innerHTML = wrap[1] + elem + wrap[2];
901 // Move to the right depth
905 // Remove IE's autoinserted <tbody> from table fragments
906 if ( !jQuery.support.tbody ) {
908 // String was a <table>, *may* have spurious <tbody>
909 var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
910 div.firstChild && div.firstChild.childNodes :
912 // String was a bare <thead> or <tfoot>
913 wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
917 for ( var j = tbody.length - 1; j >= 0 ; --j )
918 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
919 tbody[ j ].parentNode.removeChild( tbody[ j ] );
923 // IE completely kills leading whitespace when innerHTML is used
924 if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
925 div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
927 elem = jQuery.makeArray( div.childNodes );
933 ret = jQuery.merge( ret, elem );
938 for ( var i = 0; ret[i]; i++ ) {
939 if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
940 scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
942 if ( ret[i].nodeType === 1 )
943 ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
944 fragment.appendChild( ret[i] );
954 attr: function( elem, name, value ) {
955 // don't set attributes on text and comment nodes
956 if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
959 var notxml = !jQuery.isXMLDoc( elem ),
960 // Whether we are setting (or getting)
961 set = value !== undefined;
963 // Try to normalize/fix the name
964 name = notxml && jQuery.props[ name ] || name;
966 // Only do all the following if this is a node (faster for style)
967 // IE elem.getAttribute passes even for style
968 if ( elem.tagName ) {
970 // These attributes require special treatment
971 var special = /href|src|style/.test( name );
973 // Safari mis-reports the default selected property of a hidden option
974 // Accessing the parent's selectedIndex property fixes it
975 if ( name == "selected" && elem.parentNode )
976 elem.parentNode.selectedIndex;
978 // If applicable, access the attribute via the DOM 0 way
979 if ( name in elem && notxml && !special ) {
981 // We can't allow the type property to be changed (since it causes problems in IE)
982 if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
983 throw "type property can't be changed";
985 elem[ name ] = value;
988 // browsers index elements by id/name on forms, give priority to attributes.
989 if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
990 return elem.getAttributeNode( name ).nodeValue;
992 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
993 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
994 if ( name == "tabIndex" ) {
995 var attributeNode = elem.getAttributeNode( "tabIndex" );
996 return attributeNode && attributeNode.specified
997 ? attributeNode.value
998 : elem.nodeName.match(/(button|input|object|select|textarea)/i)
1000 : elem.nodeName.match(/^(a|area)$/i) && elem.href
1005 return elem[ name ];
1008 if ( !jQuery.support.style && notxml && name == "style" )
1009 return jQuery.attr( elem.style, "cssText", value );
1012 // convert the value to a string (all browsers do this but IE) see #1070
1013 elem.setAttribute( name, "" + value );
1015 var attr = !jQuery.support.hrefNormalized && notxml && special
1016 // Some attributes require a special call on IE
1017 ? elem.getAttribute( name, 2 )
1018 : elem.getAttribute( name );
1020 // Non-existent attributes return null, we normalize to undefined
1021 return attr === null ? undefined : attr;
1024 // elem is actually elem.style ... set the style
1026 // IE uses filters for opacity
1027 if ( !jQuery.support.opacity && name == "opacity" ) {
1029 // IE has trouble with opacity if it does not have layout
1030 // Force it by setting the zoom level
1033 // Set the alpha filter to set the opacity
1034 elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
1035 (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
1038 return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
1039 (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
1043 name = name.replace(/-([a-z])/ig, function(all, letter){
1044 return letter.toUpperCase();
1048 elem[ name ] = value;
1050 return elem[ name ];
1053 trim: function( text ) {
1054 return (text || "").replace( /^\s+|\s+$/g, "" );
1057 makeArray: function( array ) {
1060 if( array != null ){
1061 var i = array.length;
1062 // The window, strings (and functions) also have 'length'
1063 if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
1067 ret[--i] = array[i];
1073 inArray: function( elem, array ) {
1074 for ( var i = 0, length = array.length; i < length; i++ )
1075 // Use === because on IE, window == document
1076 if ( array[ i ] === elem )
1082 merge: function( first, second ) {
1083 // We have to loop this way because IE & Opera overwrite the length
1084 // expando of getElementsByTagName
1085 var i = 0, elem, pos = first.length;
1086 // Also, we need to make sure that the correct elements are being returned
1087 // (IE returns comment nodes in a '*' query)
1088 if ( !jQuery.support.getAll ) {
1089 while ( (elem = second[ i++ ]) != null )
1090 if ( elem.nodeType != 8 )
1091 first[ pos++ ] = elem;
1094 while ( (elem = second[ i++ ]) != null )
1095 first[ pos++ ] = elem;
1100 unique: function( array ) {
1101 var ret = [], done = {};
1105 for ( var i = 0, length = array.length; i < length; i++ ) {
1106 var id = jQuery.data( array[ i ] );
1108 if ( !done[ id ] ) {
1110 ret.push( array[ i ] );
1121 grep: function( elems, callback, inv ) {
1124 // Go through the array, only saving the items
1125 // that pass the validator function
1126 for ( var i = 0, length = elems.length; i < length; i++ )
1127 if ( !inv != !callback( elems[ i ], i ) )
1128 ret.push( elems[ i ] );
1133 map: function( elems, callback ) {
1136 // Go through the array, translating each of the items to their
1137 // new value (or values).
1138 for ( var i = 0, length = elems.length; i < length; i++ ) {
1139 var value = callback( elems[ i ], i );
1141 if ( value != null )
1142 ret[ ret.length ] = value;
1145 return ret.concat.apply( [], ret );
1149 // Use of jQuery.browser is deprecated.
1150 // It's included for backwards compatibility and plugins,
1151 // although they should work to migrate away.
1153 var userAgent = navigator.userAgent.toLowerCase();
1155 // Figure out what browser is being used
1157 version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
1158 safari: /webkit/.test( userAgent ),
1159 opera: /opera/.test( userAgent ),
1160 msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
1161 mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
1165 parent: function(elem){return elem.parentNode;},
1166 parents: function(elem){return jQuery.dir(elem,"parentNode");},
1167 next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
1168 prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
1169 nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
1170 prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
1171 siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
1172 children: function(elem){return jQuery.sibling(elem.firstChild);},
1173 contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
1174 }, function(name, fn){
1175 jQuery.fn[ name ] = function( selector ) {
1176 var ret = jQuery.map( this, fn );
1178 if ( selector && typeof selector == "string" )
1179 ret = jQuery.multiFilter( selector, ret );
1181 return this.pushStack( jQuery.unique( ret ), name, selector );
1187 prependTo: "prepend",
1188 insertBefore: "before",
1189 insertAfter: "after",
1190 replaceAll: "replaceWith"
1191 }, function(name, original){
1192 jQuery.fn[ name ] = function() {
1193 var args = arguments;
1195 return this.each(function(){
1196 for ( var i = 0, length = args.length; i < length; i++ )
1197 jQuery( args[ i ] )[ original ]( this );
1203 removeAttr: function( name ) {
1204 jQuery.attr( this, name, "" );
1205 if (this.nodeType == 1)
1206 this.removeAttribute( name );
1209 addClass: function( classNames ) {
1210 jQuery.className.add( this, classNames );
1213 removeClass: function( classNames ) {
1214 jQuery.className.remove( this, classNames );
1217 toggleClass: function( classNames, state ) {
1218 if( typeof state !== "boolean" )
1219 state = !jQuery.className.has( this, classNames );
1220 jQuery.className[ state ? "add" : "remove" ]( this, classNames );
1223 remove: function( selector ) {
1224 if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
1225 // Prevent memory leaks
1226 jQuery( "*", this ).add([this]).each(function(){
1227 jQuery.event.remove(this);
1228 jQuery.removeData(this);
1230 if (this.parentNode)
1231 this.parentNode.removeChild( this );
1236 // Remove element nodes and prevent memory leaks
1237 jQuery( ">*", this ).remove();
1239 // Remove any remaining nodes
1240 while ( this.firstChild )
1241 this.removeChild( this.firstChild );
1243 }, function(name, fn){
1244 jQuery.fn[ name ] = function(){
1245 return this.each( fn, arguments );
1249 // Helper function used by the dimensions and offset modules
1250 function num(elem, prop) {
1251 return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
1253 var expando = "jQuery" + now(), uuid = 0, windowData = {};
\r
1258 data: function( elem, name, data ) {
\r
1259 elem = elem == window ?
\r
1263 var id = elem[ expando ];
\r
1265 // Compute a unique ID for the element
\r
1267 id = elem[ expando ] = ++uuid;
\r
1269 // Only generate the data cache if we're
\r
1270 // trying to access or manipulate it
\r
1271 if ( name && !jQuery.cache[ id ] )
\r
1272 jQuery.cache[ id ] = {};
\r
1274 // Prevent overriding the named cache with undefined values
\r
1275 if ( data !== undefined )
\r
1276 jQuery.cache[ id ][ name ] = data;
\r
1278 // Return the named cache data, or the ID for the element
\r
1280 jQuery.cache[ id ][ name ] :
\r
1284 removeData: function( elem, name ) {
\r
1285 elem = elem == window ?
\r
1289 var id = elem[ expando ];
\r
1291 // If we want to remove a specific section of the element's data
\r
1293 if ( jQuery.cache[ id ] ) {
\r
1294 // Remove the section of cache data
\r
1295 delete jQuery.cache[ id ][ name ];
\r
1297 // If we've removed all the data, remove the element's cache
\r
1300 for ( name in jQuery.cache[ id ] )
\r
1304 jQuery.removeData( elem );
\r
1307 // Otherwise, we want to remove all of the element's data
\r
1309 // Clean up the element expando
\r
1311 delete elem[ expando ];
\r
1313 // IE has trouble directly removing the expando
\r
1314 // but it's ok with using removeAttribute
\r
1315 if ( elem.removeAttribute )
\r
1316 elem.removeAttribute( expando );
\r
1319 // Completely remove the data cache
\r
1320 delete jQuery.cache[ id ];
\r
1323 queue: function( elem, type, data ) {
\r
1326 type = (type || "fx") + "queue";
\r
1328 var q = jQuery.data( elem, type );
\r
1330 if ( !q || jQuery.isArray(data) )
\r
1331 q = jQuery.data( elem, type, jQuery.makeArray(data) );
\r
1339 dequeue: function( elem, type ){
\r
1340 var queue = jQuery.queue( elem, type ),
\r
1341 fn = queue.shift();
\r
1343 if( !type || type === "fx" )
\r
1346 if( fn !== undefined )
\r
1351 jQuery.fn.extend({
\r
1352 data: function( key, value ){
\r
1353 var parts = key.split(".");
\r
1354 parts[1] = parts[1] ? "." + parts[1] : "";
\r
1356 if ( value === undefined ) {
\r
1357 var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
\r
1359 if ( data === undefined && this.length )
\r
1360 data = jQuery.data( this[0], key );
\r
1362 return data === undefined && parts[1] ?
\r
1363 this.data( parts[0] ) :
\r
1366 return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
\r
1367 jQuery.data( this, key, value );
\r
1371 removeData: function( key ){
\r
1372 return this.each(function(){
\r
1373 jQuery.removeData( this, key );
\r
1376 queue: function(type, data){
\r
1377 if ( typeof type !== "string" ) {
\r
1382 if ( data === undefined )
\r
1383 return jQuery.queue( this[0], type );
\r
1385 return this.each(function(){
\r
1386 var queue = jQuery.queue( this, type, data );
\r
1388 if( type == "fx" && queue.length == 1 )
\r
1389 queue[0].call(this);
\r
1392 dequeue: function(type){
\r
1393 return this.each(function(){
\r
1394 jQuery.dequeue( this, type );
\r
1398 * Sizzle CSS Selector Engine - v0.9.3
1399 * Copyright 2009, The Dojo Foundation
1400 * Released under the MIT, BSD, and GPL Licenses.
1401 * More information: http://sizzlejs.com/
1405 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]+['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,
1407 toString = Object.prototype.toString;
1409 var Sizzle = function(selector, context, results, seed) {
1410 results = results || [];
1411 context = context || document;
1413 if ( context.nodeType !== 1 && context.nodeType !== 9 )
1416 if ( !selector || typeof selector !== "string" ) {
1420 var parts = [], m, set, checkSet, check, mode, extra, prune = true;
1422 // Reset the position of the chunker regexp (start from head)
1423 chunker.lastIndex = 0;
1425 while ( (m = chunker.exec(selector)) !== null ) {
1429 extra = RegExp.rightContext;
1434 if ( parts.length > 1 && origPOS.exec( selector ) ) {
1435 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
1436 set = posProcess( parts[0] + parts[1], context );
1438 set = Expr.relative[ parts[0] ] ?
1440 Sizzle( parts.shift(), context );
1442 while ( parts.length ) {
1443 selector = parts.shift();
1445 if ( Expr.relative[ selector ] )
1446 selector += parts.shift();
1448 set = posProcess( selector, set );
1453 { expr: parts.pop(), set: makeArray(seed) } :
1454 Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
1455 set = Sizzle.filter( ret.expr, ret.set );
1457 if ( parts.length > 0 ) {
1458 checkSet = makeArray(set);
1463 while ( parts.length ) {
1464 var cur = parts.pop(), pop = cur;
1466 if ( !Expr.relative[ cur ] ) {
1472 if ( pop == null ) {
1476 Expr.relative[ cur ]( checkSet, pop, isXML(context) );
1485 throw "Syntax error, unrecognized expression: " + (cur || selector);
1488 if ( toString.call(checkSet) === "[object Array]" ) {
1490 results.push.apply( results, checkSet );
1491 } else if ( context.nodeType === 1 ) {
1492 for ( var i = 0; checkSet[i] != null; i++ ) {
1493 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
1494 results.push( set[i] );
1498 for ( var i = 0; checkSet[i] != null; i++ ) {
1499 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
1500 results.push( set[i] );
1505 makeArray( checkSet, results );
1509 Sizzle( extra, context, results, seed );
1515 Sizzle.matches = function(expr, set){
1516 return Sizzle(expr, null, null, set);
1519 Sizzle.find = function(expr, context, isXML){
1526 for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
1527 var type = Expr.order[i], match;
1529 if ( (match = Expr.match[ type ].exec( expr )) ) {
1530 var left = RegExp.leftContext;
1532 if ( left.substr( left.length - 1 ) !== "\\" ) {
1533 match[1] = (match[1] || "").replace(/\\/g, "");
1534 set = Expr.find[ type ]( match, context, isXML );
1535 if ( set != null ) {
1536 expr = expr.replace( Expr.match[ type ], "" );
1544 set = context.getElementsByTagName("*");
1547 return {set: set, expr: expr};
1550 Sizzle.filter = function(expr, set, inplace, not){
1551 var old = expr, result = [], curLoop = set, match, anyFound;
1553 while ( expr && set.length ) {
1554 for ( var type in Expr.filter ) {
1555 if ( (match = Expr.match[ type ].exec( expr )) != null ) {
1556 var filter = Expr.filter[ type ], found, item;
1559 if ( curLoop == result ) {
1563 if ( Expr.preFilter[ type ] ) {
1564 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not );
1567 anyFound = found = true;
1568 } else if ( match === true ) {
1574 for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
1576 found = filter( item, match, i, curLoop );
1577 var pass = not ^ !!found;
1579 if ( inplace && found != null ) {
1585 } else if ( pass ) {
1586 result.push( item );
1593 if ( found !== undefined ) {
1598 expr = expr.replace( Expr.match[ type ], "" );
1609 expr = expr.replace(/\s*,\s*/, "");
1611 // Improper expression
1612 if ( expr == old ) {
1613 if ( anyFound == null ) {
1614 throw "Syntax error, unrecognized expression: " + expr;
1626 var Expr = Sizzle.selectors = {
1627 order: [ "ID", "NAME", "TAG" ],
1629 ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
1630 CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
1631 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
1632 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
1633 TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
1634 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
1635 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
1636 PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
1639 "class": "className",
1643 href: function(elem){
1644 return elem.getAttribute("href");
1648 "+": function(checkSet, part){
1649 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1650 var elem = checkSet[i];
1652 var cur = elem.previousSibling;
1653 while ( cur && cur.nodeType !== 1 ) {
1654 cur = cur.previousSibling;
1656 checkSet[i] = typeof part === "string" ?
1662 if ( typeof part === "string" ) {
1663 Sizzle.filter( part, checkSet, true );
1666 ">": function(checkSet, part, isXML){
1667 if ( typeof part === "string" && !/\W/.test(part) ) {
1668 part = isXML ? part : part.toUpperCase();
1670 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1671 var elem = checkSet[i];
1673 var parent = elem.parentNode;
1674 checkSet[i] = parent.nodeName === part ? parent : false;
1678 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1679 var elem = checkSet[i];
1681 checkSet[i] = typeof part === "string" ?
1683 elem.parentNode === part;
1687 if ( typeof part === "string" ) {
1688 Sizzle.filter( part, checkSet, true );
1692 "": function(checkSet, part, isXML){
1693 var doneName = "done" + (done++), checkFn = dirCheck;
1695 if ( !part.match(/\W/) ) {
1696 var nodeCheck = part = isXML ? part : part.toUpperCase();
1697 checkFn = dirNodeCheck;
1700 checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
1702 "~": function(checkSet, part, isXML){
1703 var doneName = "done" + (done++), checkFn = dirCheck;
1705 if ( typeof part === "string" && !part.match(/\W/) ) {
1706 var nodeCheck = part = isXML ? part : part.toUpperCase();
1707 checkFn = dirNodeCheck;
1710 checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
1714 ID: function(match, context, isXML){
1715 if ( typeof context.getElementById !== "undefined" && !isXML ) {
1716 var m = context.getElementById(match[1]);
1717 return m ? [m] : [];
1720 NAME: function(match, context, isXML){
1721 if ( typeof context.getElementsByName !== "undefined" && !isXML ) {
1722 return context.getElementsByName(match[1]);
1725 TAG: function(match, context){
1726 return context.getElementsByTagName(match[1]);
1730 CLASS: function(match, curLoop, inplace, result, not){
1731 match = " " + match[1].replace(/\\/g, "") + " ";
1734 for ( var i = 0; (elem = curLoop[i]) != null; i++ ) {
1736 if ( not ^ (" " + elem.className + " ").indexOf(match) >= 0 ) {
1738 result.push( elem );
1739 } else if ( inplace ) {
1747 ID: function(match){
1748 return match[1].replace(/\\/g, "");
1750 TAG: function(match, curLoop){
1751 for ( var i = 0; curLoop[i] === false; i++ ){}
1752 return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
1754 CHILD: function(match){
1755 if ( match[1] == "nth" ) {
1756 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
1757 var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
1758 match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
1759 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
1761 // calculate the numbers (first)n+(last) including if they are negative
1762 match[2] = (test[1] + (test[2] || 1)) - 0;
1763 match[3] = test[3] - 0;
1766 // TODO: Move to normal caching system
1767 match[0] = "done" + (done++);
1771 ATTR: function(match){
1772 var name = match[1].replace(/\\/g, "");
1774 if ( Expr.attrMap[name] ) {
1775 match[1] = Expr.attrMap[name];
1778 if ( match[2] === "~=" ) {
1779 match[4] = " " + match[4] + " ";
1784 PSEUDO: function(match, curLoop, inplace, result, not){
1785 if ( match[1] === "not" ) {
1786 // If we're dealing with a complex expression, or a simple one
1787 if ( match[3].match(chunker).length > 1 ) {
1788 match[3] = Sizzle(match[3], null, null, curLoop);
1790 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
1792 result.push.apply( result, ret );
1796 } else if ( Expr.match.POS.test( match[0] ) ) {
1802 POS: function(match){
1803 match.unshift( true );
1808 enabled: function(elem){
1809 return elem.disabled === false && elem.type !== "hidden";
1811 disabled: function(elem){
1812 return elem.disabled === true;
1814 checked: function(elem){
1815 return elem.checked === true;
1817 selected: function(elem){
1818 // Accessing this property makes selected-by-default
1819 // options in Safari work properly
1820 elem.parentNode.selectedIndex;
1821 return elem.selected === true;
1823 parent: function(elem){
1824 return !!elem.firstChild;
1826 empty: function(elem){
1827 return !elem.firstChild;
1829 has: function(elem, i, match){
1830 return !!Sizzle( match[3], elem ).length;
1832 header: function(elem){
1833 return /h\d/i.test( elem.nodeName );
1835 text: function(elem){
1836 return "text" === elem.type;
1838 radio: function(elem){
1839 return "radio" === elem.type;
1841 checkbox: function(elem){
1842 return "checkbox" === elem.type;
1844 file: function(elem){
1845 return "file" === elem.type;
1847 password: function(elem){
1848 return "password" === elem.type;
1850 submit: function(elem){
1851 return "submit" === elem.type;
1853 image: function(elem){
1854 return "image" === elem.type;
1856 reset: function(elem){
1857 return "reset" === elem.type;
1859 button: function(elem){
1860 return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
1862 input: function(elem){
1863 return /input|select|textarea|button/i.test(elem.nodeName);
1867 first: function(elem, i){
1870 last: function(elem, i, match, array){
1871 return i === array.length - 1;
1873 even: function(elem, i){
1876 odd: function(elem, i){
1879 lt: function(elem, i, match){
1880 return i < match[3] - 0;
1882 gt: function(elem, i, match){
1883 return i > match[3] - 0;
1885 nth: function(elem, i, match){
1886 return match[3] - 0 == i;
1888 eq: function(elem, i, match){
1889 return match[3] - 0 == i;
1893 CHILD: function(elem, match){
1894 var type = match[1], parent = elem.parentNode;
1896 var doneName = match[0];
1898 if ( parent && (!parent[ doneName ] || !elem.nodeIndex) ) {
1901 for ( var node = parent.firstChild; node; node = node.nextSibling ) {
1902 if ( node.nodeType == 1 ) {
1903 node.nodeIndex = count++;
1907 parent[ doneName ] = count - 1;
1910 if ( type == "first" ) {
1911 return elem.nodeIndex == 1;
1912 } else if ( type == "last" ) {
1913 return elem.nodeIndex == parent[ doneName ];
1914 } else if ( type == "only" ) {
1915 return parent[ doneName ] == 1;
1916 } else if ( type == "nth" ) {
1917 var add = false, first = match[2], last = match[3];
1919 if ( first == 1 && last == 0 ) {
1924 if ( elem.nodeIndex == last ) {
1927 } else if ( (elem.nodeIndex - last) % first == 0 && (elem.nodeIndex - last) / first >= 0 ) {
1934 PSEUDO: function(elem, match, i, array){
1935 var name = match[1], filter = Expr.filters[ name ];
1938 return filter( elem, i, match, array );
1939 } else if ( name === "contains" ) {
1940 return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
1941 } else if ( name === "not" ) {
1944 for ( var i = 0, l = not.length; i < l; i++ ) {
1945 if ( not[i] === elem ) {
1953 ID: function(elem, match){
1954 return elem.nodeType === 1 && elem.getAttribute("id") === match;
1956 TAG: function(elem, match){
1957 return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
1959 CLASS: function(elem, match){
1960 return match.test( elem.className );
1962 ATTR: function(elem, match){
1963 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];
1964 return result == null ?
1969 value.indexOf(check) >= 0 :
1971 (" " + value + " ").indexOf(check) >= 0 :
1977 value.indexOf(check) === 0 :
1979 value.substr(value.length - check.length) === check :
1981 value === check || value.substr(0, check.length + 1) === check + "-" :
1984 POS: function(elem, match, i, array){
1985 var name = match[2], filter = Expr.setFilters[ name ];
1988 return filter( elem, i, match, array );
1994 var origPOS = Expr.match.POS;
1996 for ( var type in Expr.match ) {
1997 Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
2000 var makeArray = function(array, results) {
2001 array = Array.prototype.slice.call( array );
2004 results.push.apply( results, array );
2011 // Perform a simple check to determine if the browser is capable of
2012 // converting a NodeList to an array using builtin methods.
2014 Array.prototype.slice.call( document.documentElement.childNodes );
2016 // Provide a fallback method if it does not work
2018 makeArray = function(array, results) {
2019 var ret = results || [];
2021 if ( toString.call(array) === "[object Array]" ) {
2022 Array.prototype.push.apply( ret, array );
2024 if ( typeof array.length === "number" ) {
2025 for ( var i = 0, l = array.length; i < l; i++ ) {
2026 ret.push( array[i] );
2029 for ( var i = 0; array[i]; i++ ) {
2030 ret.push( array[i] );
2039 // Check to see if the browser returns elements by name when
2040 // querying by getElementById (and provide a workaround)
2042 // We're going to inject a fake input element with a specified name
2043 var form = document.createElement("form"),
2044 id = "script" + (new Date).getTime();
2045 form.innerHTML = "<input name='" + id + "'/>";
2047 // Inject it into the root element, check its status, and remove it quickly
2048 var root = document.documentElement;
2049 root.insertBefore( form, root.firstChild );
2051 // The workaround has to do additional checks after a getElementById
2052 // Which slows things down for other browsers (hence the branching)
2053 if ( !!document.getElementById( id ) ) {
2054 Expr.find.ID = function(match, context, isXML){
2055 if ( typeof context.getElementById !== "undefined" && !isXML ) {
2056 var m = context.getElementById(match[1]);
2057 return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
2061 Expr.filter.ID = function(elem, match){
2062 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
2063 return elem.nodeType === 1 && node && node.nodeValue === match;
2067 root.removeChild( form );
2071 // Check to see if the browser returns only elements
2072 // when doing getElementsByTagName("*")
2074 // Create a fake element
2075 var div = document.createElement("div");
2076 div.appendChild( document.createComment("") );
2078 // Make sure no comments are found
2079 if ( div.getElementsByTagName("*").length > 0 ) {
2080 Expr.find.TAG = function(match, context){
2081 var results = context.getElementsByTagName(match[1]);
2083 // Filter out possible comments
2084 if ( match[1] === "*" ) {
2087 for ( var i = 0; results[i]; i++ ) {
2088 if ( results[i].nodeType === 1 ) {
2089 tmp.push( results[i] );
2100 // Check to see if an attribute returns normalized href attributes
2101 div.innerHTML = "<a href='#'></a>";
2102 if ( div.firstChild && div.firstChild.getAttribute("href") !== "#" ) {
2103 Expr.attrHandle.href = function(elem){
2104 return elem.getAttribute("href", 2);
2109 if ( document.querySelectorAll ) (function(){
2110 var oldSizzle = Sizzle, div = document.createElement("div");
2111 div.innerHTML = "<p class='TEST'></p>";
2113 // Safari can't handle uppercase or unicode characters when
2115 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
2119 Sizzle = function(query, context, extra, seed){
2120 context = context || document;
2122 // Only use querySelectorAll on non-XML documents
2123 // (ID selectors don't work in non-HTML documents)
2124 if ( !seed && context.nodeType === 9 && !isXML(context) ) {
2126 return makeArray( context.querySelectorAll(query), extra );
2130 return oldSizzle(query, context, extra, seed);
2133 Sizzle.find = oldSizzle.find;
2134 Sizzle.filter = oldSizzle.filter;
2135 Sizzle.selectors = oldSizzle.selectors;
2136 Sizzle.matches = oldSizzle.matches;
2139 if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) {
2140 Expr.order.splice(1, 0, "CLASS");
2141 Expr.find.CLASS = function(match, context) {
2142 return context.getElementsByClassName(match[1]);
2146 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
2147 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2148 var elem = checkSet[i];
2153 while ( elem && elem.nodeType ) {
2154 var done = elem[doneName];
2156 match = checkSet[ done ];
2160 if ( elem.nodeType === 1 && !isXML )
2163 if ( elem.nodeName === cur ) {
2171 checkSet[i] = match;
2176 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
2177 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
2178 var elem = checkSet[i];
2183 while ( elem && elem.nodeType ) {
2184 if ( elem[doneName] ) {
2185 match = checkSet[ elem[doneName] ];
2189 if ( elem.nodeType === 1 ) {
2193 if ( typeof cur !== "string" ) {
2194 if ( elem === cur ) {
2199 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
2208 checkSet[i] = match;
2213 var contains = document.compareDocumentPosition ? function(a, b){
2214 return a.compareDocumentPosition(b) & 16;
2216 return a !== b && (a.contains ? a.contains(b) : true);
2219 var isXML = function(elem){
2220 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
2221 !!elem.ownerDocument && isXML( elem.ownerDocument );
2224 var posProcess = function(selector, context){
2225 var tmpSet = [], later = "", match,
2226 root = context.nodeType ? [context] : context;
2228 // Position selectors must be done after the filter
2229 // And so must :not(positional) so we move all PSEUDOs to the end
2230 while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
2232 selector = selector.replace( Expr.match.PSEUDO, "" );
2235 selector = Expr.relative[selector] ? selector + "*" : selector;
2237 for ( var i = 0, l = root.length; i < l; i++ ) {
2238 Sizzle( selector, root[i], tmpSet );
2241 return Sizzle.filter( later, tmpSet );
2245 jQuery.find = Sizzle;
2246 jQuery.filter = Sizzle.filter;
2247 jQuery.expr = Sizzle.selectors;
2248 jQuery.expr[":"] = jQuery.expr.filters;
2250 Sizzle.selectors.filters.hidden = function(elem){
2251 return "hidden" === elem.type ||
2252 jQuery.css(elem, "display") === "none" ||
2253 jQuery.css(elem, "visibility") === "hidden";
2256 Sizzle.selectors.filters.visible = function(elem){
2257 return "hidden" !== elem.type &&
2258 jQuery.css(elem, "display") !== "none" &&
2259 jQuery.css(elem, "visibility") !== "hidden";
2262 Sizzle.selectors.filters.animated = function(elem){
2263 return jQuery.grep(jQuery.timers, function(fn){
2264 return elem === fn.elem;
2268 jQuery.multiFilter = function( expr, elems, not ) {
2270 expr = ":not(" + expr + ")";
2273 return Sizzle.matches(expr, elems);
2276 jQuery.dir = function( elem, dir ){
2277 var matched = [], cur = elem[dir];
2278 while ( cur && cur != document ) {
2279 if ( cur.nodeType == 1 )
2280 matched.push( cur );
2286 jQuery.nth = function(cur, result, dir, elem){
2287 result = result || 1;
2290 for ( ; cur; cur = cur[dir] )
2291 if ( cur.nodeType == 1 && ++num == result )
2297 jQuery.sibling = function(n, elem){
2300 for ( ; n; n = n.nextSibling ) {
2301 if ( n.nodeType == 1 && n != elem )
2310 window.Sizzle = Sizzle;
2314 * A number of helper functions used for managing events.
2315 * Many of the ideas behind this code originated from
2316 * Dean Edwards' addEvent library.
2320 // Bind an event to an element
2321 // Original by Dean Edwards
2322 add: function(elem, types, handler, data) {
2323 if ( elem.nodeType == 3 || elem.nodeType == 8 )
2326 // For whatever reason, IE has trouble passing the window object
2327 // around, causing it to be cloned in the process
2328 if ( elem.setInterval && elem != window )
2331 // Make sure that the function being executed has a unique ID
2332 if ( !handler.guid )
2333 handler.guid = this.guid++;
2335 // if data is passed, bind to handler
2336 if ( data !== undefined ) {
2337 // Create temporary function pointer to original handler
2340 // Create unique handler function, wrapped around original handler
2341 handler = this.proxy( fn );
2343 // Store data in unique handler
2344 handler.data = data;
2347 // Init the element's event structure
2348 var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
2349 handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
2350 // Handle the second event of a trigger and when
2351 // an event is called after a page has unloaded
2352 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
2353 jQuery.event.handle.apply(arguments.callee.elem, arguments) :
2356 // Add elem as a property of the handle function
2357 // This is to prevent a memory leak with non-native
2361 // Handle multiple events separated by a space
2362 // jQuery(...).bind("mouseover mouseout", fn);
2363 jQuery.each(types.split(/\s+/), function(index, type) {
2364 // Namespaced event handlers
2365 var namespaces = type.split(".");
2366 type = namespaces.shift();
2367 handler.type = namespaces.slice().sort().join(".");
2369 // Get the current list of functions bound to this event
2370 var handlers = events[type];
2372 if ( jQuery.event.specialAll[type] )
2373 jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
2375 // Init the event handler queue
2377 handlers = events[type] = {};
2379 // Check for a special event handler
2380 // Only use addEventListener/attachEvent if the special
2381 // events handler returns false
2382 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
2383 // Bind the global event handler to the element
2384 if (elem.addEventListener)
2385 elem.addEventListener(type, handle, false);
2386 else if (elem.attachEvent)
2387 elem.attachEvent("on" + type, handle);
2391 // Add the function to the element's handler list
2392 handlers[handler.guid] = handler;
2394 // Keep track of which events have been used, for global triggering
2395 jQuery.event.global[type] = true;
2398 // Nullify elem to prevent memory leaks in IE
2405 // Detach an event or set of events from an element
2406 remove: function(elem, types, handler) {
2407 // don't do events on text and comment nodes
2408 if ( elem.nodeType == 3 || elem.nodeType == 8 )
2411 var events = jQuery.data(elem, "events"), ret, index;
2414 // Unbind all events for the element
2415 if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
2416 for ( var type in events )
2417 this.remove( elem, type + (types || "") );
2419 // types is actually an event object here
2421 handler = types.handler;
2425 // Handle multiple events seperated by a space
2426 // jQuery(...).unbind("mouseover mouseout", fn);
2427 jQuery.each(types.split(/\s+/), function(index, type){
2428 // Namespaced event handlers
2429 var namespaces = type.split(".");
2430 type = namespaces.shift();
2431 var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
2433 if ( events[type] ) {
2434 // remove the given handler for the given type
2436 delete events[type][handler.guid];
2438 // remove all handlers for the given type
2440 for ( var handle in events[type] )
2441 // Handle the removal of namespaced events
2442 if ( namespace.test(events[type][handle].type) )
2443 delete events[type][handle];
2445 if ( jQuery.event.specialAll[type] )
2446 jQuery.event.specialAll[type].teardown.call(elem, namespaces);
2448 // remove generic event handler if no more handlers exist
2449 for ( ret in events[type] ) break;
2451 if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
2452 if (elem.removeEventListener)
2453 elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
2454 else if (elem.detachEvent)
2455 elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
2458 delete events[type];
2464 // Remove the expando if it's no longer used
2465 for ( ret in events ) break;
2467 var handle = jQuery.data( elem, "handle" );
2468 if ( handle ) handle.elem = null;
2469 jQuery.removeData( elem, "events" );
2470 jQuery.removeData( elem, "handle" );
2475 // bubbling is internal
2476 trigger: function( event, data, elem, bubbling ) {
2477 // Event object or event type
2478 var type = event.type || event;
2481 event = typeof event === "object" ?
2482 // jQuery.Event object
2483 event[expando] ? event :
2485 jQuery.extend( jQuery.Event(type), event ) :
2486 // Just the event type (string)
2489 if ( type.indexOf("!") >= 0 ) {
2490 event.type = type = type.slice(0, -1);
2491 event.exclusive = true;
2494 // Handle a global trigger
2496 // Don't bubble custom events when global (to avoid too much overhead)
2497 event.stopPropagation();
2498 // Only trigger if we've ever bound an event for it
2499 if ( this.global[type] )
2500 jQuery.each( jQuery.cache, function(){
2501 if ( this.events && this.events[type] )
2502 jQuery.event.trigger( event, data, this.handle.elem );
2506 // Handle triggering a single element
2508 // don't do events on text and comment nodes
2509 if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
2512 // Clean up in case it is reused
2513 event.result = undefined;
2514 event.target = elem;
2516 // Clone the incoming data, if any
2517 data = jQuery.makeArray(data);
2518 data.unshift( event );
2521 event.currentTarget = elem;
2523 // Trigger the event, it is assumed that "handle" is a function
2524 var handle = jQuery.data(elem, "handle");
2526 handle.apply( elem, data );
2528 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
2529 if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
2530 event.result = false;
2532 // Trigger the native events (except for clicks on links)
2533 if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
2534 this.triggered = true;
2537 // prevent IE from throwing an error for some hidden elements
2541 this.triggered = false;
2543 if ( !event.isPropagationStopped() ) {
2544 var parent = elem.parentNode || elem.ownerDocument;
2546 jQuery.event.trigger(event, data, parent, true);
2550 handle: function(event) {
2551 // returned undefined or false
2554 event = arguments[0] = jQuery.event.fix( event || window.event );
2556 // Namespaced event handlers
2557 var namespaces = event.type.split(".");
2558 event.type = namespaces.shift();
2560 // Cache this now, all = true means, any handler
2561 all = !namespaces.length && !event.exclusive;
2563 var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
2565 handlers = ( jQuery.data(this, "events") || {} )[event.type];
2567 for ( var j in handlers ) {
2568 var handler = handlers[j];
2570 // Filter the functions by class
2571 if ( all || namespace.test(handler.type) ) {
2572 // Pass in a reference to the handler function itself
2573 // So that we can later remove it
2574 event.handler = handler;
2575 event.data = handler.data;
2577 var ret = handler.apply(this, arguments);
2579 if( ret !== undefined ){
2581 if ( ret === false ) {
2582 event.preventDefault();
2583 event.stopPropagation();
2587 if( event.isImmediatePropagationStopped() )
2594 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(" "),
2596 fix: function(event) {
2597 if ( event[expando] )
2600 // store a copy of the original event object
2601 // and "clone" to set read-only properties
2602 var originalEvent = event;
2603 event = jQuery.Event( originalEvent );
2605 for ( var i = this.props.length, prop; i; ){
2606 prop = this.props[ --i ];
2607 event[ prop ] = originalEvent[ prop ];
2610 // Fix target property, if necessary
2611 if ( !event.target )
2612 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
2614 // check if target is a textnode (safari)
2615 if ( event.target.nodeType == 3 )
2616 event.target = event.target.parentNode;
2618 // Add relatedTarget, if necessary
2619 if ( !event.relatedTarget && event.fromElement )
2620 event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
2622 // Calculate pageX/Y if missing and clientX/Y available
2623 if ( event.pageX == null && event.clientX != null ) {
2624 var doc = document.documentElement, body = document.body;
2625 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
2626 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
2629 // Add which for key events
2630 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
2631 event.which = event.charCode || event.keyCode;
2633 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
2634 if ( !event.metaKey && event.ctrlKey )
2635 event.metaKey = event.ctrlKey;
2637 // Add which for click: 1 == left; 2 == middle; 3 == right
2638 // Note: button is not normalized, so don't use it
2639 if ( !event.which && event.button )
2640 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2645 proxy: function( fn, proxy ){
2646 proxy = proxy || function(){ return fn.apply(this, arguments); };
2647 // Set the guid of unique handler to the same of original handler, so it can be removed
2648 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
2649 // So proxy can be declared as an argument
2655 // Make sure the ready event is setup
2657 teardown: function() {}
2663 setup: function( selector, namespaces ){
2664 jQuery.event.add( this, namespaces[0], liveHandler );
2666 teardown: function( namespaces ){
2667 if ( namespaces.length ) {
2668 var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
2670 jQuery.each( (jQuery.data(this, "events").live || {}), function(){
2671 if ( name.test(this.type) )
2676 jQuery.event.remove( this, namespaces[0], liveHandler );
2683 jQuery.Event = function( src ){
2684 // Allow instantiation without the 'new' keyword
2685 if( !this.preventDefault )
2686 return new jQuery.Event(src);
2689 if( src && src.type ){
2690 this.originalEvent = src;
2691 this.type = src.type;
2696 // timeStamp is buggy for some events on Firefox(#3843)
2697 // So we won't rely on the native value
2698 this.timeStamp = now();
2701 this[expando] = true;
2704 function returnFalse(){
2707 function returnTrue(){
2711 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
2712 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
2713 jQuery.Event.prototype = {
2714 preventDefault: function() {
2715 this.isDefaultPrevented = returnTrue;
2717 var e = this.originalEvent;
2720 // if preventDefault exists run it on the original event
2721 if (e.preventDefault)
2723 // otherwise set the returnValue property of the original event to false (IE)
2724 e.returnValue = false;
2726 stopPropagation: function() {
2727 this.isPropagationStopped = returnTrue;
2729 var e = this.originalEvent;
2732 // if stopPropagation exists run it on the original event
2733 if (e.stopPropagation)
2734 e.stopPropagation();
2735 // otherwise set the cancelBubble property of the original event to true (IE)
2736 e.cancelBubble = true;
2738 stopImmediatePropagation:function(){
2739 this.isImmediatePropagationStopped = returnTrue;
2740 this.stopPropagation();
2742 isDefaultPrevented: returnFalse,
2743 isPropagationStopped: returnFalse,
2744 isImmediatePropagationStopped: returnFalse
2746 // Checks if an event happened on an element within another element
2747 // Used in jQuery.event.special.mouseenter and mouseleave handlers
2748 var withinElement = function(event) {
2749 // Check if mouse(over|out) are still within the same parent element
2750 var parent = event.relatedTarget;
2751 // Traverse up the tree
2752 while ( parent && parent != this )
2753 try { parent = parent.parentNode; }
2754 catch(e) { parent = this; }
2756 if( parent != this ){
2757 // set the correct event type
2758 event.type = event.data;
2759 // handle event if we actually just moused on to a non sub-element
2760 jQuery.event.handle.apply( this, arguments );
2765 mouseover: 'mouseenter',
2766 mouseout: 'mouseleave'
2767 }, function( orig, fix ){
2768 jQuery.event.special[ fix ] = {
2770 jQuery.event.add( this, orig, withinElement, fix );
2772 teardown: function(){
2773 jQuery.event.remove( this, orig, withinElement );
2779 bind: function( type, data, fn ) {
2780 return type == "unload" ? this.one(type, data, fn) : this.each(function(){
2781 jQuery.event.add( this, type, fn || data, fn && data );
2785 one: function( type, data, fn ) {
2786 var one = jQuery.event.proxy( fn || data, function(event) {
2787 jQuery(this).unbind(event, one);
2788 return (fn || data).apply( this, arguments );
2790 return this.each(function(){
2791 jQuery.event.add( this, type, one, fn && data);
2795 unbind: function( type, fn ) {
2796 return this.each(function(){
2797 jQuery.event.remove( this, type, fn );
2801 trigger: function( type, data ) {
2802 return this.each(function(){
2803 jQuery.event.trigger( type, data, this );
2807 triggerHandler: function( type, data ) {
2809 var event = jQuery.Event(type);
2810 event.preventDefault();
2811 event.stopPropagation();
2812 jQuery.event.trigger( event, data, this[0] );
2813 return event.result;
2817 toggle: function( fn ) {
2818 // Save reference to arguments for access in closure
2819 var args = arguments, i = 1;
2821 // link all the functions, so any of them can unbind this click handler
2822 while( i < args.length )
2823 jQuery.event.proxy( fn, args[i++] );
2825 return this.click( jQuery.event.proxy( fn, function(event) {
2826 // Figure out which function to execute
2827 this.lastToggle = ( this.lastToggle || 0 ) % i;
2829 // Make sure that clicks stop
2830 event.preventDefault();
2832 // and execute the function
2833 return args[ this.lastToggle++ ].apply( this, arguments ) || false;
2837 hover: function(fnOver, fnOut) {
2838 return this.mouseenter(fnOver).mouseleave(fnOut);
2841 ready: function(fn) {
2842 // Attach the listeners
2845 // If the DOM is already ready
2846 if ( jQuery.isReady )
2847 // Execute the function immediately
2848 fn.call( document, jQuery );
2850 // Otherwise, remember the function for later
2852 // Add the function to the wait list
2853 jQuery.readyList.push( fn );
2858 live: function( type, fn ){
2859 var proxy = jQuery.event.proxy( fn );
2860 proxy.guid += this.selector + type;
2862 jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
2867 die: function( type, fn ){
2868 jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
2873 function liveHandler( event ){
2874 var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
2878 jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
2879 if ( check.test(fn.type) ) {
2880 var elem = jQuery(event.target).closest(fn.data)[0];
2882 elems.push({ elem: elem, fn: fn });
2886 jQuery.each(elems, function(){
2887 if ( this.fn.call(this.elem, event, this.fn.data) === false )
2894 function liveConvert(type, selector){
2895 return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
2901 // Handle when the DOM is ready
2903 // Make sure that the DOM is not already loaded
2904 if ( !jQuery.isReady ) {
2905 // Remember that the DOM is ready
2906 jQuery.isReady = true;
2908 // If there are functions bound, to execute
2909 if ( jQuery.readyList ) {
2910 // Execute all of them
2911 jQuery.each( jQuery.readyList, function(){
2912 this.call( document, jQuery );
2915 // Reset the list of functions
2916 jQuery.readyList = null;
2919 // Trigger any bound ready events
2920 jQuery(document).triggerHandler("ready");
2925 var readyBound = false;
2927 function bindReady(){
2928 if ( readyBound ) return;
2931 // Mozilla, Opera and webkit nightlies currently support this event
2932 if ( document.addEventListener ) {
2933 // Use the handy event callback
2934 document.addEventListener( "DOMContentLoaded", function(){
2935 document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
2939 // If IE event model is used
2940 } else if ( document.attachEvent ) {
2941 // ensure firing before onload,
2942 // maybe late but safe also for iframes
2943 document.attachEvent("onreadystatechange", function(){
2944 if ( document.readyState === "complete" ) {
2945 document.detachEvent( "onreadystatechange", arguments.callee );
2950 // If IE and not an iframe
2951 // continually check to see if the document is ready
2952 if ( document.documentElement.doScroll && typeof window.frameElement === "undefined" ) (function(){
2953 if ( jQuery.isReady ) return;
2956 // If IE is used, use the trick by Diego Perini
2957 // http://javascript.nwbox.com/IEContentLoaded/
2958 document.documentElement.doScroll("left");
2960 setTimeout( arguments.callee, 0 );
2964 // and execute any waiting functions
2969 // A fallback to window.onload, that will always work
2970 jQuery.event.add( window, "load", jQuery.ready );
2973 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
2974 "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
2975 "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
2977 // Handle event binding
2978 jQuery.fn[name] = function(fn){
2979 return fn ? this.bind(name, fn) : this.trigger(name);
2983 // Prevent memory leaks in IE
2984 // And prevent errors on refresh with events like mouseover in other browsers
2985 // Window isn't included so as not to unbind existing unload events
2986 jQuery( window ).bind( 'unload', function(){
2987 for ( var id in jQuery.cache )
2989 if ( id != 1 && jQuery.cache[ id ].handle )
2990 jQuery.event.remove( jQuery.cache[ id ].handle.elem );
2994 jQuery.support = {};
2996 var root = document.documentElement,
2997 script = document.createElement("script"),
2998 div = document.createElement("div"),
2999 id = "script" + (new Date).getTime();
3001 div.style.display = "none";
3002 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>';
3004 var all = div.getElementsByTagName("*"),
3005 a = div.getElementsByTagName("a")[0];
3007 // Can't get basic test support
3008 if ( !all || !all.length || !a ) {
3013 // IE strips leading whitespace when .innerHTML is used
3014 leadingWhitespace: div.firstChild.nodeType == 3,
3016 // Make sure that tbody elements aren't automatically inserted
3017 // IE will insert them into empty tables
3018 tbody: !div.getElementsByTagName("tbody").length,
3020 // Make sure that you can get all elements in an <object> element
3021 // IE 7 always returns no results
3022 objectAll: !!div.getElementsByTagName("object")[0]
3023 .getElementsByTagName("*").length,
3025 // Make sure that link elements get serialized correctly by innerHTML
3026 // This requires a wrapper element in IE
3027 htmlSerialize: !!div.getElementsByTagName("link").length,
3029 // Get the style information from getAttribute
3030 // (IE uses .cssText insted)
3031 style: /red/.test( a.getAttribute("style") ),
3033 // Make sure that URLs aren't manipulated
3034 // (IE normalizes it by default)
3035 hrefNormalized: a.getAttribute("href") === "/a",
3037 // Make sure that element opacity exists
3038 // (IE uses filter instead)
3039 opacity: a.style.opacity === "0.5",
3041 // Verify style float existence
3042 // (IE uses styleFloat instead of cssFloat)
3043 cssFloat: !!a.style.cssFloat,
3045 // Will be defined later
3051 script.type = "text/javascript";
3053 script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
3056 root.insertBefore( script, root.firstChild );
3058 // Make sure that the execution of code works by injecting a script
3059 // tag with appendChild/createTextNode
3060 // (IE doesn't support this, fails, and uses .text instead)
3061 if ( window[ id ] ) {
3062 jQuery.support.scriptEval = true;
3063 delete window[ id ];
3066 root.removeChild( script );
3068 if ( div.attachEvent && div.fireEvent ) {
3069 div.attachEvent("onclick", function(){
3070 // Cloning a node shouldn't copy over any
3071 // bound event handlers (IE does this)
3072 jQuery.support.noCloneEvent = false;
3073 div.detachEvent("onclick", arguments.callee);
3075 div.cloneNode(true).fireEvent("onclick");
3078 // Figure out if the W3C box model works as expected
3079 // document.body must exist before we can do this
3081 var div = document.createElement("div");
3082 div.style.width = "1px";
3083 div.style.paddingLeft = "1px";
3085 document.body.appendChild( div );
3086 jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
3087 document.body.removeChild( div );
3091 var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
3095 "class": "className",
3096 "float": styleFloat,
3097 cssFloat: styleFloat,
3098 styleFloat: styleFloat,
3099 readonly: "readOnly",
3100 maxlength: "maxLength",
3101 cellspacing: "cellSpacing",
3103 tabindex: "tabIndex"
3106 // Keep a copy of the old load
3107 _load: jQuery.fn.load,
3109 load: function( url, params, callback ) {
3110 if ( typeof url !== "string" )
3111 return this._load( url );
3113 var off = url.indexOf(" ");
3115 var selector = url.slice(off, url.length);
3116 url = url.slice(0, off);
3119 // Default to a GET request
3122 // If the second parameter was provided
3124 // If it's a function
3125 if ( jQuery.isFunction( params ) ) {
3126 // We assume that it's the callback
3130 // Otherwise, build a param string
3131 } else if( typeof params === "object" ) {
3132 params = jQuery.param( params );
3138 // Request the remote document
3144 complete: function(res, status){
3145 // If successful, inject the HTML into all the matched elements
3146 if ( status == "success" || status == "notmodified" )
3147 // See if a selector was specified
3148 self.html( selector ?
3149 // Create a dummy div to hold the results
3151 // inject the contents of the document in, removing the scripts
3152 // to avoid any 'Permission Denied' errors in IE
3153 .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
3155 // Locate the specified elements
3158 // If not, just inject the full result
3162 self.each( callback, [res.responseText, status, res] );
3168 serialize: function() {
3169 return jQuery.param(this.serializeArray());
3171 serializeArray: function() {
3172 return this.map(function(){
3173 return this.elements ? jQuery.makeArray(this.elements) : this;
3176 return this.name && !this.disabled &&
3177 (this.checked || /select|textarea/i.test(this.nodeName) ||
3178 /text|hidden|password/i.test(this.type));
3180 .map(function(i, elem){
3181 var val = jQuery(this).val();
3182 return val == null ? null :
3183 jQuery.isArray(val) ?
3184 jQuery.map( val, function(val, i){
3185 return {name: elem.name, value: val};
3187 {name: elem.name, value: val};
3192 // Attach a bunch of functions for handling common AJAX events
3193 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
3194 jQuery.fn[o] = function(f){
3195 return this.bind(o, f);
3203 get: function( url, data, callback, type ) {
3204 // shift arguments if data argument was ommited
3205 if ( jQuery.isFunction( data ) ) {
3210 return jQuery.ajax({
3219 getScript: function( url, callback ) {
3220 return jQuery.get(url, null, callback, "script");
3223 getJSON: function( url, data, callback ) {
3224 return jQuery.get(url, data, callback, "json");
3227 post: function( url, data, callback, type ) {
3228 if ( jQuery.isFunction( data ) ) {
3233 return jQuery.ajax({
3242 ajaxSetup: function( settings ) {
3243 jQuery.extend( jQuery.ajaxSettings, settings );
3250 contentType: "application/x-www-form-urlencoded",
3259 // Create the request object; Microsoft failed to properly
3260 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
3261 // This function can be overriden by calling jQuery.ajaxSetup
3263 return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
3266 xml: "application/xml, text/xml",
3268 script: "text/javascript, application/javascript",
3269 json: "application/json, text/javascript",
3275 // Last-Modified header cache for next request
3278 ajax: function( s ) {
3279 // Extend the settings, but re-extend 's' so that it can be
3280 // checked again later (in the test suite, specifically)
3281 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
3283 var jsonp, jsre = /=\?(&|$)/g, status, data,
3284 type = s.type.toUpperCase();
3286 // convert data if not already a string
3287 if ( s.data && s.processData && typeof s.data !== "string" )
3288 s.data = jQuery.param(s.data);
3290 // Handle JSONP Parameter Callbacks
3291 if ( s.dataType == "jsonp" ) {
3292 if ( type == "GET" ) {
3293 if ( !s.url.match(jsre) )
3294 s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
3295 } else if ( !s.data || !s.data.match(jsre) )
3296 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
3297 s.dataType = "json";
3300 // Build temporary JSONP function
3301 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
3302 jsonp = "jsonp" + jsc++;
3304 // Replace the =? sequence both in the query string and the data
3306 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
3307 s.url = s.url.replace(jsre, "=" + jsonp + "$1");
3309 // We need to make sure
3310 // that a JSONP style response is executed properly
3311 s.dataType = "script";
3313 // Handle JSONP-style loading
3314 window[ jsonp ] = function(tmp){
3319 window[ jsonp ] = undefined;
3320 try{ delete window[ jsonp ]; } catch(e){}
3322 head.removeChild( script );
3326 if ( s.dataType == "script" && s.cache == null )
3329 if ( s.cache === false && type == "GET" ) {
3331 // try replacing _= if it is there
3332 var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
3333 // if nothing was replaced, add timestamp to the end
3334 s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
3337 // If data is available, append data to url for get requests
3338 if ( s.data && type == "GET" ) {
3339 s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
3341 // IE likes to send both get and post data, prevent this
3345 // Watch for a new set of requests
3346 if ( s.global && ! jQuery.active++ )
3347 jQuery.event.trigger( "ajaxStart" );
3349 // Matches an absolute URL, and saves the domain
3350 var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
3352 // If we're requesting a remote document
3353 // and trying to load JSON or Script with a GET
3354 if ( s.dataType == "script" && type == "GET" && parts
3355 && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
3357 var head = document.getElementsByTagName("head")[0];
3358 var script = document.createElement("script");
3360 if (s.scriptCharset)
3361 script.charset = s.scriptCharset;
3363 // Handle Script loading
3367 // Attach handlers for all browsers
3368 script.onload = script.onreadystatechange = function(){
3369 if ( !done && (!this.readyState ||
3370 this.readyState == "loaded" || this.readyState == "complete") ) {
3374 head.removeChild( script );
3379 head.appendChild(script);
3381 // We handle everything using the script element injection
3385 var requestDone = false;
3387 // Create the request object
3391 // Passing null username, generates a login popup on Opera (#2865)
3393 xhr.open(type, s.url, s.async, s.username, s.password);
3395 xhr.open(type, s.url, s.async);
3397 // Need an extra try/catch for cross domain requests in Firefox 3
3399 // Set the correct header, if data is being sent
3401 xhr.setRequestHeader("Content-Type", s.contentType);
3403 // Set the If-Modified-Since header, if ifModified mode.
3405 xhr.setRequestHeader("If-Modified-Since",
3406 jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
3408 // Set header so the called script knows that it's an XMLHttpRequest
3409 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
3411 // Set the Accepts header for the server, depending on the dataType
3412 xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
3413 s.accepts[ s.dataType ] + ", */*" :
3414 s.accepts._default );
3417 // Allow custom headers/mimetypes and early abort
3418 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
3419 // Handle the global AJAX counter
3420 if ( s.global && ! --jQuery.active )
3421 jQuery.event.trigger( "ajaxStop" );
3422 // close opended socket
3428 jQuery.event.trigger("ajaxSend", [xhr, s]);
3430 // Wait for a response to come back
3431 var onreadystatechange = function(isTimeout){
3432 // The request was aborted, clear the interval and decrement jQuery.active
3433 if (xhr.readyState == 0) {
3435 // clear poll interval
3436 clearInterval(ival);
3438 // Handle the global AJAX counter
3439 if ( s.global && ! --jQuery.active )
3440 jQuery.event.trigger( "ajaxStop" );
3442 // The transfer is complete and the data is available, or the request timed out
3443 } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
3446 // clear poll interval
3448 clearInterval(ival);
3452 status = isTimeout == "timeout" ? "timeout" :
3453 !jQuery.httpSuccess( xhr ) ? "error" :
3454 s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
3457 if ( status == "success" ) {
3458 // Watch for, and catch, XML document parse errors
3460 // process the data (runs the xml through httpData regardless of callback)
3461 data = jQuery.httpData( xhr, s.dataType, s );
3463 status = "parsererror";
3467 // Make sure that the request was successful or notmodified
3468 if ( status == "success" ) {
3469 // Cache Last-Modified header, if ifModified mode.
3472 modRes = xhr.getResponseHeader("Last-Modified");
3473 } catch(e) {} // swallow exception thrown by FF if header is not available
3475 if ( s.ifModified && modRes )
3476 jQuery.lastModified[s.url] = modRes;
3478 // JSONP handles its own success callback
3482 jQuery.handleError(s, xhr, status);
3484 // Fire the complete handlers
3490 // Stop memory leaks
3497 // don't attach the handler to the request, just poll it instead
3498 var ival = setInterval(onreadystatechange, 13);
3501 if ( s.timeout > 0 )
3502 setTimeout(function(){
3503 // Check to see if the request is still happening
3504 if ( xhr && !requestDone )
3505 onreadystatechange( "timeout" );
3513 jQuery.handleError(s, xhr, null, e);
3516 // firefox 1.5 doesn't fire statechange for sync requests
3518 onreadystatechange();
3521 // If a local callback was specified, fire it and pass it the data
3523 s.success( data, status );
3525 // Fire the global callback
3527 jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
3530 function complete(){
3533 s.complete(xhr, status);
3535 // The request was completed
3537 jQuery.event.trigger( "ajaxComplete", [xhr, s] );
3539 // Handle the global AJAX counter
3540 if ( s.global && ! --jQuery.active )
3541 jQuery.event.trigger( "ajaxStop" );
3544 // return XMLHttpRequest to allow aborting the request etc.
3548 handleError: function( s, xhr, status, e ) {
3549 // If a local callback was specified, fire it
3550 if ( s.error ) s.error( xhr, status, e );
3552 // Fire the global callback
3554 jQuery.event.trigger( "ajaxError", [xhr, s, e] );
3557 // Counter for holding the number of active queries
3560 // Determines if an XMLHttpRequest was successful or not
3561 httpSuccess: function( xhr ) {
3563 // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
3564 return !xhr.status && location.protocol == "file:" ||
3565 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
3570 // Determines if an XMLHttpRequest returns NotModified
3571 httpNotModified: function( xhr, url ) {
3573 var xhrRes = xhr.getResponseHeader("Last-Modified");
3575 // Firefox always returns 200. check Last-Modified date
3576 return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
3581 httpData: function( xhr, type, s ) {
3582 var ct = xhr.getResponseHeader("content-type"),
3583 xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
3584 data = xml ? xhr.responseXML : xhr.responseText;
3586 if ( xml && data.documentElement.tagName == "parsererror" )
3587 throw "parsererror";
3589 // Allow a pre-filtering function to sanitize the response
3590 // s != null is checked to keep backwards compatibility
3591 if( s && s.dataFilter )
3592 data = s.dataFilter( data, type );
3594 // The filter can actually parse the response
3595 if( typeof data === "string" ){
3597 // If the type is "script", eval it in global context
3598 if ( type == "script" )
3599 jQuery.globalEval( data );
3601 // Get the JavaScript object, if JSON is used.
3602 if ( type == "json" )
3603 data = window["eval"]("(" + data + ")");
3609 // Serialize an array of form elements or a set of
3610 // key/values into a query string
3611 param: function( a ) {
3614 function add( key, value ){
3615 s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
3618 // If an array was passed in, assume that it is an array
3620 if ( jQuery.isArray(a) || a.jquery )
3621 // Serialize the form elements
3622 jQuery.each( a, function(){
3623 add( this.name, this.value );
3626 // Otherwise, assume that it's an object of key/value pairs
3628 // Serialize the key/values
3630 // If the value is an array then the key names need to be repeated
3631 if ( jQuery.isArray(a[j]) )
3632 jQuery.each( a[j], function(){
3636 add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
3638 // Return the resulting serialization
3639 return s.join("&").replace(/%20/g, "+");
3643 var elemdisplay = {},
3646 // height animations
3647 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
3649 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
3650 // opacity animations
3654 function genFx( type, num ){
3656 jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
3663 show: function(speed,callback){
3665 return this.animate( genFx("show", 3), speed, callback);
3667 for ( var i = 0, l = this.length; i < l; i++ ){
3668 var old = jQuery.data(this[i], "olddisplay");
3670 this[i].style.display = old || "";
3672 if ( jQuery.css(this[i], "display") === "none" ) {
3673 var tagName = this[i].tagName, display;
3675 if ( elemdisplay[ tagName ] ) {
3676 display = elemdisplay[ tagName ];
3678 var elem = jQuery("<" + tagName + " />").appendTo("body");
3680 display = elem.css("display");
3681 if ( display === "none" )
3686 elemdisplay[ tagName ] = display;
3689 this[i].style.display = jQuery.data(this[i], "olddisplay", display);
3697 hide: function(speed,callback){
3699 return this.animate( genFx("hide", 3), speed, callback);
3701 for ( var i = 0, l = this.length; i < l; i++ ){
3702 var old = jQuery.data(this[i], "olddisplay");
3703 if ( !old && old !== "none" )
3704 jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
3705 this[i].style.display = "none";
3711 // Save the old toggle function
3712 _toggle: jQuery.fn.toggle,
3714 toggle: function( fn, fn2 ){
3715 var bool = typeof fn === "boolean";
3717 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
3718 this._toggle.apply( this, arguments ) :
3719 fn == null || bool ?
3720 this.each(function(){
3721 var state = bool ? fn : jQuery(this).is(":hidden");
3722 jQuery(this)[ state ? "show" : "hide" ]();
3724 this.animate(genFx("toggle", 3), fn, fn2);
3727 fadeTo: function(speed,to,callback){
3728 return this.animate({opacity: to}, speed, callback);
3731 animate: function( prop, speed, easing, callback ) {
3732 var optall = jQuery.speed(speed, easing, callback);
3734 return this[ optall.queue === false ? "each" : "queue" ](function(){
3736 var opt = jQuery.extend({}, optall), p,
3737 hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
3741 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
3742 return opt.complete.call(this);
3744 if ( ( p == "height" || p == "width" ) && this.style ) {
3745 // Store display property
3746 opt.display = jQuery.css(this, "display");
3748 // Make sure that nothing sneaks out
3749 opt.overflow = this.style.overflow;
3753 if ( opt.overflow != null )
3754 this.style.overflow = "hidden";
3756 opt.curAnim = jQuery.extend({}, prop);
3758 jQuery.each( prop, function(name, val){
3759 var e = new jQuery.fx( self, opt, name );
3761 if ( /toggle|show|hide/.test(val) )
3762 e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
3764 var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
3765 start = e.cur(true) || 0;
3768 var end = parseFloat(parts[2]),
3769 unit = parts[3] || "px";
3771 // We need to compute starting value
3772 if ( unit != "px" ) {
3773 self.style[ name ] = (end || 1) + unit;
3774 start = ((end || 1) / e.cur(true)) * start;
3775 self.style[ name ] = start + unit;
3778 // If a +=/-= token was provided, we're doing a relative animation
3780 end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
3782 e.custom( start, end, unit );
3784 e.custom( start, val, "" );
3788 // For JS strict compliance
3793 stop: function(clearQueue, gotoEnd){
3794 var timers = jQuery.timers;
3799 this.each(function(){
3800 // go in reverse order so anything added to the queue during the loop is ignored
3801 for ( var i = timers.length - 1; i >= 0; i-- )
3802 if ( timers[i].elem == this ) {
3804 // force the next step to be the last
3806 timers.splice(i, 1);
3810 // start the next in the queue if the last step wasn't forced
3819 // Generate shortcuts for custom animations
3821 slideDown: genFx("show", 1),
3822 slideUp: genFx("hide", 1),
3823 slideToggle: genFx("toggle", 1),
3824 fadeIn: { opacity: "show" },
3825 fadeOut: { opacity: "hide" }
3826 }, function( name, props ){
3827 jQuery.fn[ name ] = function( speed, callback ){
3828 return this.animate( props, speed, callback );
3834 speed: function(speed, easing, fn) {
3835 var opt = typeof speed === "object" ? speed : {
3836 complete: fn || !fn && easing ||
3837 jQuery.isFunction( speed ) && speed,
3839 easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
3842 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
3843 jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
3846 opt.old = opt.complete;
3847 opt.complete = function(){
3848 if ( opt.queue !== false )
3849 jQuery(this).dequeue();
3850 if ( jQuery.isFunction( opt.old ) )
3851 opt.old.call( this );
3858 linear: function( p, n, firstNum, diff ) {
3859 return firstNum + diff * p;
3861 swing: function( p, n, firstNum, diff ) {
3862 return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
3868 fx: function( elem, options, prop ){
3869 this.options = options;
3873 if ( !options.orig )
3879 jQuery.fx.prototype = {
3881 // Simple function for setting a style value
3883 if ( this.options.step )
3884 this.options.step.call( this.elem, this.now, this );
3886 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
3888 // Set display property to block for height/width animations
3889 if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
3890 this.elem.style.display = "block";
3893 // Get the current size
3894 cur: function(force){
3895 if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
3896 return this.elem[ this.prop ];
3898 var r = parseFloat(jQuery.css(this.elem, this.prop, force));
3899 return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
3902 // Start an animation from one number to another
3903 custom: function(from, to, unit){
3904 this.startTime = now();
3907 this.unit = unit || this.unit || "px";
3908 this.now = this.start;
3909 this.pos = this.state = 0;
3912 function t(gotoEnd){
3913 return self.step(gotoEnd);
3918 if ( t() && jQuery.timers.push(t) == 1 ) {
3919 timerId = setInterval(function(){
3920 var timers = jQuery.timers;
3922 for ( var i = 0; i < timers.length; i++ )
3924 timers.splice(i--, 1);
3926 if ( !timers.length ) {
3927 clearInterval( timerId );
3933 // Simple 'show' function
3935 // Remember where we started, so that we can go back to it later
3936 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
3937 this.options.show = true;
3939 // Begin the animation
3940 // Make sure that we start at a small width/height to avoid any
3942 this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
3944 // Start by showing the element
3945 jQuery(this.elem).show();
3948 // Simple 'hide' function
3950 // Remember where we started, so that we can go back to it later
3951 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
3952 this.options.hide = true;
3954 // Begin the animation
3955 this.custom(this.cur(), 0);
3958 // Each step of an animation
3959 step: function(gotoEnd){
3962 if ( gotoEnd || t >= this.options.duration + this.startTime ) {
3963 this.now = this.end;
3964 this.pos = this.state = 1;
3967 this.options.curAnim[ this.prop ] = true;
3970 for ( var i in this.options.curAnim )
3971 if ( this.options.curAnim[i] !== true )
3975 if ( this.options.display != null ) {
3976 // Reset the overflow
3977 this.elem.style.overflow = this.options.overflow;
3979 // Reset the display
3980 this.elem.style.display = this.options.display;
3981 if ( jQuery.css(this.elem, "display") == "none" )
3982 this.elem.style.display = "block";
3985 // Hide the element if the "hide" operation was done
3986 if ( this.options.hide )
3987 jQuery(this.elem).hide();
3989 // Reset the properties, if the item has been hidden or shown
3990 if ( this.options.hide || this.options.show )
3991 for ( var p in this.options.curAnim )
3992 jQuery.attr(this.elem.style, p, this.options.orig[p]);
3994 // Execute the complete function
3995 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" );