2 * jQuery JavaScript Library v1.3.2
5 * Copyright (c) 2009 John Resig
6 * Dual licensed under the MIT and GPL licenses.
7 * http://docs.jquery.com/License
9 * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
14 // Will speed up references to window, and allows munging its name.
16 // Will speed up references to undefined, and allows munging its name.
18 // Map over jQuery in case of overwrite
19 _jQuery = window.jQuery,
20 // Map over the $ in case of overwrite
22 jQuery = window.jQuery = window.$ = function( selector, context ) {
23 // The jQuery object is actually just the init constructor 'enhanced'
24 return new jQuery.fn.init( selector, context );
26 // A simple way to check for HTML strings or ID strings
27 // (both of which we optimize for)
28 quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
29 // Is it a simple selector
30 isSimple = /^.[^:#\[\.,]*$/;
31 jQuery.fn = jQuery.prototype = {
32 init: function( selector, context ) {
33 // Make sure that a selection was provided
34 selector = selector || document;
35 // Handle $(DOMElement)
36 if ( selector.nodeType ) {
39 this.context = selector;
42 // Handle HTML strings
43 if ( typeof selector === "string" ) {
44 // Are we dealing with HTML string or an ID?
45 var match = quickExpr.exec( selector );
46 // Verify a match, and that no context was specified for #id
47 if ( match && (match[1] || !context) ) {
48 // HANDLE: $(html) -> $(array)
50 selector = jQuery.clean( [ match[1] ], context );
53 var elem = document.getElementById( match[3] );
54 // Handle the case where IE and Opera return items
55 // by name instead of ID
56 if ( elem && elem.id != match[3] )
57 return jQuery().find( selector );
58 // Otherwise, we inject the element directly into the jQuery object
59 var ret = jQuery( elem || [] );
60 ret.context = document;
61 ret.selector = selector;
64 // HANDLE: $(expr, [context])
65 // (which is just equivalent to: $(content).find(expr)
67 return jQuery( context ).find( selector );
68 // HANDLE: $(function)
69 // Shortcut for document ready
70 } else if ( jQuery.isFunction( selector ) )
71 return jQuery( document ).ready( selector );
72 // Make sure that old selector state is passed along
73 if ( selector.selector && selector.context ) {
74 this.selector = selector.selector;
75 this.context = selector.context;
77 return this.setArray(jQuery.isArray( selector ) ?
79 jQuery.makeArray(selector));
81 // Start with an empty selector
83 // The current version of jQuery being used
85 // The number of elements contained in the matched element set
89 // Get the Nth element in the matched element set OR
90 // Get the whole matched element set as a clean array
91 get: function( num ) {
92 return num === undefined ?
93 // Return a 'clean' array
94 Array.prototype.slice.call( this ) :
95 // Return just the object
98 // Take an array of elements and push it onto the stack
99 // (returning the new matched element set)
100 pushStack: function( elems, name, selector ) {
101 // Build a new jQuery matched element set
102 var ret = jQuery( elems );
103 // Add the old object onto the stack (as a reference)
104 ret.prevObject = this;
105 ret.context = this.context;
106 if ( name === "find" )
107 ret.selector = this.selector + (this.selector ? " " : "") + selector;
109 ret.selector = this.selector + "." + name + "(" + selector + ")";
110 // Return the newly-formed element set
113 // Force the current matched set of elements to become
114 // the specified array of elements (destroying the stack in the process)
115 // You should use pushStack() in order to do this, but maintain the stack
116 setArray: function( elems ) {
117 // Resetting the length to 0, then using the native Array push
118 // is a super-fast way to populate an object with array-like properties
120 Array.prototype.push.apply( this, elems );
123 // Execute a callback for every element in the matched set.
124 // (You can seed the arguments with an array of args, but this is
125 // only used internally.)
126 each: function( callback, args ) {
127 return jQuery.each( this, callback, args );
129 // Determine the position of an element within
130 // the matched set of elements
131 index: function( elem ) {
132 // Locate the position of the desired element
133 return jQuery.inArray(
134 // If it receives a jQuery object, the first element is used
135 elem && elem.jquery ? elem[0] : elem
138 attr: function( name, value, type ) {
140 // Look for the case where we're accessing a style value
141 if ( typeof name === "string" )
142 if ( value === undefined )
143 return this[0] && jQuery[ type || "attr" ]( this[0], name );
146 options[ name ] = value;
148 // Check to see if we're setting style values
149 return this.each(function(i){
150 // Set all the styles
151 for ( name in options )
156 name, jQuery.prop( this, options[ name ], type, i, name )
160 css: function( key, value ) {
161 // ignore negative width and height values
162 if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
164 return this.attr( key, value, "curCSS" );
166 text: function( text ) {
167 if ( typeof text !== "object" && text != null )
168 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
170 jQuery.each( text || this, function(){
171 jQuery.each( this.childNodes, function(){
172 if ( this.nodeType != 8 )
173 ret += this.nodeType != 1 ?
175 jQuery.fn.text( [ this ] );
180 wrapAll: function( html ) {
182 // The elements to wrap the target around
183 var wrap = jQuery( html, this[0].ownerDocument ).clone();
184 if ( this[0].parentNode )
185 wrap.insertBefore( this[0] );
188 while ( elem.firstChild )
189 elem = elem.firstChild;
195 wrapInner: function( html ) {
196 return this.each(function(){
197 jQuery( this ).contents().wrapAll( html );
200 wrap: function( html ) {
201 return this.each(function(){
202 jQuery( this ).wrapAll( html );
206 return this.domManip(arguments, true, function(elem){
207 if (this.nodeType == 1)
208 this.appendChild( elem );
211 prepend: function() {
212 return this.domManip(arguments, true, function(elem){
213 if (this.nodeType == 1)
214 this.insertBefore( elem, this.firstChild );
218 return this.domManip(arguments, false, function(elem){
219 this.parentNode.insertBefore( elem, this );
223 return this.domManip(arguments, false, function(elem){
224 this.parentNode.insertBefore( elem, this.nextSibling );
228 return this.prevObject || jQuery( [] );
230 // For internal use only.
231 // Behaves like an Array's method, not like a jQuery method.
235 find: function( selector ) {
236 if ( this.length === 1 ) {
237 var ret = this.pushStack( [], "find", selector );
239 jQuery.find( selector, this[0], ret );
242 return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
243 return jQuery.find( selector, elem );
244 })), "find", selector );
247 clone: function( events ) {
249 var ret = this.map(function(){
250 if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
251 // IE copies events bound via attachEvent when
252 // using cloneNode. Calling detachEvent on the
253 // clone will also remove the events from the orignal
254 // In order to get around this, we use innerHTML.
255 // Unfortunately, this means some modifications to
256 // attributes in IE that are actually only stored
257 // as properties will not be copied (such as the
258 // the name attribute on an input).
259 var html = this.outerHTML;
261 var div = this.ownerDocument.createElement("div");
262 div.appendChild( this.cloneNode(true) );
263 html = div.innerHTML;
265 return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
267 return this.cloneNode(true);
269 // Copy the events from the original to the clone
270 if ( events === true ) {
271 var orig = this.find("*").andSelf(), i = 0;
272 ret.find("*").andSelf().each(function(){
273 if ( this.nodeName !== orig[i].nodeName )
275 var events = jQuery.data( orig[i], "events" );
276 for ( var type in events ) {
277 for ( var handler in events[ type ] ) {
278 jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
284 // Return the cloned set
287 filter: function( selector ) {
288 return this.pushStack(
289 jQuery.isFunction( selector ) &&
290 jQuery.grep(this, function(elem, i){
291 return selector.call( elem, i );
293 jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
294 return elem.nodeType === 1;
295 }) ), "filter", selector );
297 closest: function( selector ) {
298 var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
300 return this.map(function(){
302 while ( cur && cur.ownerDocument ) {
303 if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
304 jQuery.data(cur, "closest", closer);
307 cur = cur.parentNode;
312 not: function( selector ) {
313 if ( typeof selector === "string" )
314 // test special case where just one selector is passed in
315 if ( isSimple.test( selector ) )
316 return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
318 selector = jQuery.multiFilter( selector, this );
319 var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
320 return this.filter(function() {
321 return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
324 add: function( selector ) {
325 return this.pushStack( jQuery.unique( jQuery.merge(
327 typeof selector === "string" ?
329 jQuery.makeArray( selector )
332 is: function( selector ) {
333 return !!selector && jQuery.multiFilter( selector, this ).length > 0;
335 hasClass: function( selector ) {
336 return !!selector && this.is( "." + selector );
338 val: function( value ) {
339 if ( value === undefined ) {
342 if( jQuery.nodeName( elem, 'option' ) )
343 return (elem.attributes.value || {}).specified ? elem.value : elem.text;
345 // We need to handle select boxes special
346 if ( jQuery.nodeName( elem, "select" ) ) {
347 var index = elem.selectedIndex,
349 options = elem.options,
350 one = elem.type == "select-one";
351 // Nothing was selected
354 // Loop through all the selected options
355 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
356 var option = options[ i ];
357 if ( option.selected ) {
358 // Get the specifc value for the option
359 value = jQuery(option).val();
360 // We don't need an array for one selects
363 // Multi-Selects return an array
364 values.push( value );
369 // Everything else, we just grab the value
370 return (elem.value || "").replace(/\r/g, "");
374 if ( typeof value === "number" )
376 return this.each(function(){
377 if ( this.nodeType != 1 )
379 if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
380 this.checked = (jQuery.inArray(this.value, value) >= 0 ||
381 jQuery.inArray(this.name, value) >= 0);
382 else if ( jQuery.nodeName( this, "select" ) ) {
383 var values = jQuery.makeArray(value);
384 jQuery( "option", this ).each(function(){
385 this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
386 jQuery.inArray( this.text, values ) >= 0);
388 if ( !values.length )
389 this.selectedIndex = -1;
394 html: function( value ) {
395 return value === undefined ?
397 this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
399 this.empty().append( value );
401 replaceWith: function( value ) {
402 return this.after( value ).remove();
405 return this.slice( i, +i + 1 );
408 return this.pushStack( Array.prototype.slice.apply( this, arguments ),
409 "slice", Array.prototype.slice.call(arguments).join(",") );
411 map: function( callback ) {
412 return this.pushStack( jQuery.map(this, function(elem, i){
413 return callback.call( elem, i, elem );
416 andSelf: function() {
417 return this.add( this.prevObject );
419 domManip: function( args, table, callback ) {
421 var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
422 scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
423 first = fragment.firstChild;
425 for ( var i = 0, l = this.length; i < l; i++ )
426 callback.call( root(this[i], first), this.length > 1 || i > 0 ?
427 fragment.cloneNode(true) : fragment );
430 jQuery.each( scripts, evalScript );
434 function root( elem, cur ) {
435 return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
436 (elem.getElementsByTagName("tbody")[0] ||
437 elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
442 // Give the init function the jQuery prototype for later instantiation
443 jQuery.fn.init.prototype = jQuery.fn;
444 function evalScript( i, elem ) {
452 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
453 if ( elem.parentNode )
454 elem.parentNode.removeChild( elem );
459 jQuery.extend = jQuery.fn.extend = function() {
460 // copy reference to target object
461 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
462 // Handle a deep copy situation
463 if ( typeof target === "boolean" ) {
465 target = arguments[1] || {};
466 // skip the boolean and the target
469 // Handle case when target is a string or something (possible in deep copy)
470 if ( typeof target !== "object" && !jQuery.isFunction(target) )
472 // extend jQuery itself if only one argument is passed
477 for ( ; i < length; i++ )
478 // Only deal with non-null/undefined values
479 if ( (options = arguments[ i ]) != null )
480 // Extend the base object
481 for ( var name in options ) {
482 var src = target[ name ], copy = options[ name ];
483 // Prevent never-ending loop
484 if ( target === copy )
486 // Recurse if we're merging object values
487 if ( deep && copy && typeof copy === "object" && !copy.nodeType )
488 target[ name ] = jQuery.extend( deep,
489 // Never move original objects, clone them
490 src || ( copy.length != null ? [ ] : { } )
492 // Don't bring in undefined values
493 else if ( copy !== undefined )
494 target[ name ] = copy;
496 // Return the modified object
499 // exclude the following css properties to add px
500 var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
502 defaultView = document.defaultView || {},
503 toString = Object.prototype.toString;
505 noConflict: function( deep ) {
508 window.jQuery = _jQuery;
511 // See test/unit/core.js for details concerning isFunction.
512 // Since version 1.3, DOM methods and functions like alert
513 // aren't supported. They return false on IE (#2968).
514 isFunction: function( obj ) {
515 return toString.call(obj) === "[object Function]";
517 isArray: function( obj ) {
518 return toString.call(obj) === "[object Array]";
520 // check if an element is in a (or is an) XML document
521 isXMLDoc: function( elem ) {
522 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
523 !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
525 // Evalulates a script in a global context
526 globalEval: function( data ) {
527 if ( data && /\S/.test(data) ) {
528 // Inspired by code by Andrea Giammarchi
529 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
530 var head = document.getElementsByTagName("head")[0] || document.documentElement,
531 script = document.createElement("script");
532 script.type = "text/javascript";
533 if ( jQuery.support.scriptEval )
534 script.appendChild( document.createTextNode( data ) );
537 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
538 // This arises when a base node is used (#2709).
539 head.insertBefore( script, head.firstChild );
540 head.removeChild( script );
543 nodeName: function( elem, name ) {
544 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
546 // args is for internal usage only
547 each: function( object, callback, args ) {
548 var name, i = 0, length = object.length;
550 if ( length === undefined ) {
551 for ( name in object )
552 if ( callback.apply( object[ name ], args ) === false )
555 for ( ; i < length; )
556 if ( callback.apply( object[ i++ ], args ) === false )
558 // A special, fast, case for the most common use of each
560 if ( length === undefined ) {
561 for ( name in object )
562 if ( callback.call( object[ name ], name, object[ name ] ) === false )
565 for ( var value = object[0];
566 i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
570 prop: function( elem, value, type, i, name ) {
571 // Handle executable functions
572 if ( jQuery.isFunction( value ) )
573 value = value.call( elem, i );
574 // Handle passing in a number to a CSS property
575 return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
580 // internal only, use addClass("class")
581 add: function( elem, classNames ) {
582 jQuery.each((classNames || "").split(/\s+/), function(i, className){
583 if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
584 elem.className += (elem.className ? " " : "") + className;
587 // internal only, use removeClass("class")
588 remove: function( elem, classNames ) {
589 if (elem.nodeType == 1)
590 elem.className = classNames !== undefined ?
591 jQuery.grep(elem.className.split(/\s+/), function(className){
592 return !jQuery.className.has( classNames, className );
596 // internal only, use hasClass("class")
597 has: function( elem, className ) {
598 return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
601 // A method for quickly swapping in/out CSS properties to get correct calculations
602 swap: function( elem, options, callback ) {
604 // Remember the old values, and insert the new ones
605 for ( var name in options ) {
606 old[ name ] = elem.style[ name ];
607 elem.style[ name ] = options[ name ];
609 callback.call( elem );
610 // Revert the old values
611 for ( var name in options )
612 elem.style[ name ] = old[ name ];
614 css: function( elem, name, force, extra ) {
615 if ( name == "width" || name == "height" ) {
616 var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
618 val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
619 if ( extra === "border" )
621 jQuery.each( which, function() {
623 val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
624 if ( extra === "margin" )
625 val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
627 val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
630 if ( elem.offsetWidth !== 0 )
633 jQuery.swap( elem, props, getWH );
634 return Math.max(0, Math.round(val));
636 return jQuery.curCSS( elem, name, force );
638 curCSS: function( elem, name, force ) {
639 var ret, style = elem.style;
640 // We need to handle opacity special in IE
641 if ( name == "opacity" && !jQuery.support.opacity ) {
642 ret = jQuery.attr( style, "opacity" );
647 // Make sure we're using the right name for getting the float value
648 if ( name.match( /float/i ) )
650 if ( !force && style && style[ name ] )
652 else if ( defaultView.getComputedStyle ) {
653 // Only "float" is needed here
654 if ( name.match( /float/i ) )
656 name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
657 var computedStyle = defaultView.getComputedStyle( elem, null );
659 ret = computedStyle.getPropertyValue( name );
660 // We should always get a number back from opacity
661 if ( name == "opacity" && ret == "" )
663 } else if ( elem.currentStyle ) {
664 var camelCase = name.replace(/\-(\w)/g, function(all, letter){
665 return letter.toUpperCase();
667 ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
668 // From the awesome hack by Dean Edwards
669 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
670 // If we're not dealing with a regular pixel number
671 // but a number that has a weird ending, we need to convert it to pixels
672 if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
673 // Remember the original values
674 var left = style.left, rsLeft = elem.runtimeStyle.left;
675 // Put in the new values to get a computed value out
676 elem.runtimeStyle.left = elem.currentStyle.left;
677 style.left = ret || 0;
678 ret = style.pixelLeft + "px";
679 // Revert the changed values
681 elem.runtimeStyle.left = rsLeft;
686 clean: function( elems, context, fragment ) {
687 context = context || document;
688 // !context.createElement fails in IE with an error but returns typeof 'object'
689 if ( typeof context.createElement === "undefined" )
690 context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
691 // If a single string is passed in and it's a single tag
692 // just do a createElement and skip the rest
693 if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
694 var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
696 return [ context.createElement( match[1] ) ];
698 var ret = [], scripts = [], div = context.createElement("div");
699 jQuery.each(elems, function(i, elem){
700 if ( typeof elem === "number" )
704 // Convert html string into DOM nodes
705 if ( typeof elem === "string" ) {
706 // Fix "XHTML"-style tags in all browsers
707 elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
708 return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
710 front + "></" + tag + ">";
712 // Trim whitespace, otherwise indexOf won't work as expected
713 var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
715 // option or optgroup
716 !tags.indexOf("<opt") &&
717 [ 1, "<select multiple='multiple'>", "</select>" ] ||
718 !tags.indexOf("<leg") &&
719 [ 1, "<fieldset>", "</fieldset>" ] ||
720 tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
721 [ 1, "<table>", "</table>" ] ||
722 !tags.indexOf("<tr") &&
723 [ 2, "<table><tbody>", "</tbody></table>" ] ||
724 // <thead> matched above
725 (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
726 [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
727 !tags.indexOf("<col") &&
728 [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
729 // IE can't serialize <link> and <script> tags normally
730 !jQuery.support.htmlSerialize &&
731 [ 1, "div<div>", "</div>" ] ||
733 // Go to html and back, then peel off extra wrappers
734 div.innerHTML = wrap[1] + elem + wrap[2];
735 // Move to the right depth
738 // Remove IE's autoinserted <tbody> from table fragments
739 if ( !jQuery.support.tbody ) {
740 // String was a <table>, *may* have spurious <tbody>
741 var hasBody = /<tbody/i.test(elem),
742 tbody = !tags.indexOf("<table") && !hasBody ?
743 div.firstChild && div.firstChild.childNodes :
744 // String was a bare <thead> or <tfoot>
745 wrap[1] == "<table>" && !hasBody ?
748 for ( var j = tbody.length - 1; j >= 0 ; --j )
749 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
750 tbody[ j ].parentNode.removeChild( tbody[ j ] );
752 // IE completely kills leading whitespace when innerHTML is used
753 if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
754 div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
756 elem = jQuery.makeArray( div.childNodes );
761 ret = jQuery.merge( ret, elem );
764 for ( var i = 0; ret[i]; i++ ) {
765 if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
766 scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
768 if ( ret[i].nodeType === 1 )
769 ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
770 fragment.appendChild( ret[i] );
778 attr: function( elem, name, value ) {
779 // don't set attributes on text and comment nodes
780 if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
782 var notxml = !jQuery.isXMLDoc( elem ),
783 // Whether we are setting (or getting)
784 set = value !== undefined;
785 // Try to normalize/fix the name
786 name = notxml && jQuery.props[ name ] || name;
787 // Only do all the following if this is a node (faster for style)
788 // IE elem.getAttribute passes even for style
789 if ( elem.tagName ) {
790 // These attributes require special treatment
791 var special = /href|src|style/.test( name );
792 // Safari mis-reports the default selected property of a hidden option
793 // Accessing the parent's selectedIndex property fixes it
794 if ( name == "selected" && elem.parentNode )
795 elem.parentNode.selectedIndex;
796 // If applicable, access the attribute via the DOM 0 way
797 if ( name in elem && notxml && !special ) {
799 // We can't allow the type property to be changed (since it causes problems in IE)
800 if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
801 throw "type property can't be changed";
802 elem[ name ] = value;
804 // browsers index elements by id/name on forms, give priority to attributes.
805 if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
806 return elem.getAttributeNode( name ).nodeValue;
807 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
808 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
809 if ( name == "tabIndex" ) {
810 var attributeNode = elem.getAttributeNode( "tabIndex" );
811 return attributeNode && attributeNode.specified
812 ? attributeNode.value
813 : elem.nodeName.match(/(button|input|object|select|textarea)/i)
815 : elem.nodeName.match(/^(a|area)$/i) && elem.href
821 if ( !jQuery.support.style && notxml && name == "style" )
822 return jQuery.attr( elem.style, "cssText", value );
824 // convert the value to a string (all browsers do this but IE) see #1070
825 elem.setAttribute( name, "" + value );
826 var attr = !jQuery.support.hrefNormalized && notxml && special
827 // Some attributes require a special call on IE
828 ? elem.getAttribute( name, 2 )
829 : elem.getAttribute( name );
830 // Non-existent attributes return null, we normalize to undefined
831 return attr === null ? undefined : attr;
833 // elem is actually elem.style ... set the style
834 // IE uses filters for opacity
835 if ( !jQuery.support.opacity && name == "opacity" ) {
837 // IE has trouble with opacity if it does not have layout
838 // Force it by setting the zoom level
840 // Set the alpha filter to set the opacity
841 elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
842 (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
844 return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
845 (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
848 name = name.replace(/-([a-z])/ig, function(all, letter){
849 return letter.toUpperCase();
852 elem[ name ] = value;
855 trim: function( text ) {
856 return (text || "").replace( /^\s+|\s+$/g, "" );
858 makeArray: function( array ) {
861 var i = array.length;
862 // The window, strings (and functions) also have 'length'
863 if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
871 inArray: function( elem, array ) {
872 for ( var i = 0, length = array.length; i < length; i++ )
873 // Use === because on IE, window == document
874 if ( array[ i ] === elem )
878 merge: function( first, second ) {
879 // We have to loop this way because IE & Opera overwrite the length
880 // expando of getElementsByTagName
881 var i = 0, elem, pos = first.length;
882 // Also, we need to make sure that the correct elements are being returned
883 // (IE returns comment nodes in a '*' query)
884 if ( !jQuery.support.getAll ) {
885 while ( (elem = second[ i++ ]) != null )
886 if ( elem.nodeType != 8 )
887 first[ pos++ ] = elem;
889 while ( (elem = second[ i++ ]) != null )
890 first[ pos++ ] = elem;
893 unique: function( array ) {
894 var ret = [], done = {};
896 for ( var i = 0, length = array.length; i < length; i++ ) {
897 var id = jQuery.data( array[ i ] );
900 ret.push( array[ i ] );
908 grep: function( elems, callback, inv ) {
910 // Go through the array, only saving the items
911 // that pass the validator function
912 for ( var i = 0, length = elems.length; i < length; i++ )
913 if ( !inv != !callback( elems[ i ], i ) )
914 ret.push( elems[ i ] );
917 map: function( elems, callback ) {
919 // Go through the array, translating each of the items to their
920 // new value (or values).
921 for ( var i = 0, length = elems.length; i < length; i++ ) {
922 var value = callback( elems[ i ], i );
924 ret[ ret.length ] = value;
926 return ret.concat.apply( [], ret );
929 // Use of jQuery.browser is deprecated.
930 // It's included for backwards compatibility and plugins,
931 // although they should work to migrate away.
932 var userAgent = navigator.userAgent.toLowerCase();
933 // Figure out what browser is being used
935 version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
936 safari: /webkit/.test( userAgent ),
937 opera: /opera/.test( userAgent ),
938 msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
939 mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
942 parent: function(elem){return elem.parentNode;},
943 parents: function(elem){return jQuery.dir(elem,"parentNode");},
944 next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
945 prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
946 nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
947 prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
948 siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
949 children: function(elem){return jQuery.sibling(elem.firstChild);},
950 contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
951 }, function(name, fn){
952 jQuery.fn[ name ] = function( selector ) {
953 var ret = jQuery.map( this, fn );
954 if ( selector && typeof selector == "string" )
955 ret = jQuery.multiFilter( selector, ret );
956 return this.pushStack( jQuery.unique( ret ), name, selector );
961 prependTo: "prepend",
962 insertBefore: "before",
963 insertAfter: "after",
964 replaceAll: "replaceWith"
965 }, function(name, original){
966 jQuery.fn[ name ] = function( selector ) {
967 var ret = [], insert = jQuery( selector );
968 for ( var i = 0, l = insert.length; i < l; i++ ) {
969 var elems = (i > 0 ? this.clone(true) : this).get();
970 jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
971 ret = ret.concat( elems );
973 return this.pushStack( ret, name, selector );
977 removeAttr: function( name ) {
978 jQuery.attr( this, name, "" );
979 if (this.nodeType == 1)
980 this.removeAttribute( name );
982 addClass: function( classNames ) {
983 jQuery.className.add( this, classNames );
985 removeClass: function( classNames ) {
986 jQuery.className.remove( this, classNames );
988 toggleClass: function( classNames, state ) {
989 if( typeof state !== "boolean" )
990 state = !jQuery.className.has( this, classNames );
991 jQuery.className[ state ? "add" : "remove" ]( this, classNames );
993 remove: function( selector ) {
994 if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
995 // Prevent memory leaks
996 jQuery( "*", this ).add([this]).each(function(){
997 jQuery.event.remove(this);
998 jQuery.removeData(this);
1000 if (this.parentNode)
1001 this.parentNode.removeChild( this );
1005 // Remove element nodes and prevent memory leaks
1006 jQuery(this).children().remove();
1007 // Remove any remaining nodes
1008 while ( this.firstChild )
1009 this.removeChild( this.firstChild );
1011 }, function(name, fn){
1012 jQuery.fn[ name ] = function(){
1013 return this.each( fn, arguments );
1016 // Helper function used by the dimensions and offset modules
1017 function num(elem, prop) {
1018 return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
1020 var expando = "jQuery" + now(), uuid = 0, windowData = {};
1023 data: function( elem, name, data ) {
1024 elem = elem == window ?
1027 var id = elem[ expando ];
1028 // Compute a unique ID for the element
1030 id = elem[ expando ] = ++uuid;
1031 // Only generate the data cache if we're
1032 // trying to access or manipulate it
1033 if ( name && !jQuery.cache[ id ] )
1034 jQuery.cache[ id ] = {};
1035 // Prevent overriding the named cache with undefined values
1036 if ( data !== undefined )
1037 jQuery.cache[ id ][ name ] = data;
1038 // Return the named cache data, or the ID for the element
1040 jQuery.cache[ id ][ name ] :
1043 removeData: function( elem, name ) {
1044 elem = elem == window ?
1047 var id = elem[ expando ];
1048 // If we want to remove a specific section of the element's data
1050 if ( jQuery.cache[ id ] ) {
1051 // Remove the section of cache data
1052 delete jQuery.cache[ id ][ name ];
1053 // If we've removed all the data, remove the element's cache
1055 for ( name in jQuery.cache[ id ] )
1058 jQuery.removeData( elem );
1060 // Otherwise, we want to remove all of the element's data
1062 // Clean up the element expando
1064 delete elem[ expando ];
1066 // IE has trouble directly removing the expando
1067 // but it's ok with using removeAttribute
1068 if ( elem.removeAttribute )
1069 elem.removeAttribute( expando );
1071 // Completely remove the data cache
1072 delete jQuery.cache[ id ];
1075 queue: function( elem, type, data ) {
1078 type = (type || "fx") + "queue";
1080 var q = jQuery.data( elem, type );
1082 if ( !q || jQuery.isArray(data) )
1083 q = jQuery.data( elem, type, jQuery.makeArray(data) );
1090 dequeue: function( elem, type ){
1091 var queue = jQuery.queue( elem, type ),
1094 if( !type || type === "fx" )
1097 if( fn !== undefined )
1102 data: function( key, value ){
1103 var parts = key.split(".");
1104 parts[1] = parts[1] ? "." + parts[1] : "";
1105 if ( value === undefined ) {
1106 var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
1107 if ( data === undefined && this.length )
1108 data = jQuery.data( this[0], key );
1109 return data === undefined && parts[1] ?
1110 this.data( parts[0] ) :
1113 return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
1114 jQuery.data( this, key, value );
1117 removeData: function( key ){
1118 return this.each(function(){
1119 jQuery.removeData( this, key );
1122 queue: function(type, data){
1123 if ( typeof type !== "string" ) {
1127 if ( data === undefined )
1128 return jQuery.queue( this[0], type );
1129 return this.each(function(){
1130 var queue = jQuery.queue( this, type, data );
1132 if( type == "fx" && queue.length == 1 )
1133 queue[0].call(this);
1136 dequeue: function(type){
1137 return this.each(function(){
1138 jQuery.dequeue( this, type );
1142 * Sizzle CSS Selector Engine - v0.9.3
1143 * Copyright 2009, The Dojo Foundation
1144 * Released under the MIT, BSD, and GPL Licenses.
1145 * More information: http://sizzlejs.com/
1148 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
1150 toString = Object.prototype.toString;
1151 var Sizzle = function(selector, context, results, seed) {
1152 results = results || [];
1153 context = context || document;
1154 if ( context.nodeType !== 1 && context.nodeType !== 9 )
1157 if ( !selector || typeof selector !== "string" ) {
1160 var parts = [], m, set, checkSet, check, mode, extra, prune = true;
1162 // Reset the position of the chunker regexp (start from head)
1163 chunker.lastIndex = 0;
1165 while ( (m = chunker.exec(selector)) !== null ) {
1169 extra = RegExp.rightContext;
1173 if ( parts.length > 1 && origPOS.exec( selector ) ) {
1174 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
1175 set = posProcess( parts[0] + parts[1], context );
1177 set = Expr.relative[ parts[0] ] ?
1179 Sizzle( parts.shift(), context );
1180 while ( parts.length ) {
1181 selector = parts.shift();
1182 if ( Expr.relative[ selector ] )
1183 selector += parts.shift();
1184 set = posProcess( selector, set );
1189 { expr: parts.pop(), set: makeArray(seed) } :
1190 Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
1191 set = Sizzle.filter( ret.expr, ret.set );
1192 if ( parts.length > 0 ) {
1193 checkSet = makeArray(set);
1197 while ( parts.length ) {
1198 var cur = parts.pop(), pop = cur;
1199 if ( !Expr.relative[ cur ] ) {
1204 if ( pop == null ) {
1207 Expr.relative[ cur ]( checkSet, pop, isXML(context) );
1214 throw "Syntax error, unrecognized expression: " + (cur || selector);
1216 if ( toString.call(checkSet) === "[object Array]" ) {
1218 results.push.apply( results, checkSet );
1219 } else if ( context.nodeType === 1 ) {
1220 for ( var i = 0; checkSet[i] != null; i++ ) {
1221 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
1222 results.push( set[i] );
1226 for ( var i = 0; checkSet[i] != null; i++ ) {
1227 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
1228 results.push( set[i] );
1233 makeArray( checkSet, results );
1236 Sizzle( extra, context, results, seed );
1238 hasDuplicate = false;
1239 results.sort(sortOrder);
1240 if ( hasDuplicate ) {
1241 for ( var i = 1; i < results.length; i++ ) {
1242 if ( results[i] === results[i-1] ) {
1243 results.splice(i--, 1);
1251 Sizzle.matches = function(expr, set){
1252 return Sizzle(expr, null, null, set);
1254 Sizzle.find = function(expr, context, isXML){
1259 for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
1260 var type = Expr.order[i], match;
1262 if ( (match = Expr.match[ type ].exec( expr )) ) {
1263 var left = RegExp.leftContext;
1264 if ( left.substr( left.length - 1 ) !== "\\" ) {
1265 match[1] = (match[1] || "").replace(/\\/g, "");
1266 set = Expr.find[ type ]( match, context, isXML );
1267 if ( set != null ) {
1268 expr = expr.replace( Expr.match[ type ], "" );
1275 set = context.getElementsByTagName("*");
1277 return {set: set, expr: expr};
1279 Sizzle.filter = function(expr, set, inplace, not){
1280 var old = expr, result = [], curLoop = set, match, anyFound,
1281 isXMLFilter = set && set[0] && isXML(set[0]);
1282 while ( expr && set.length ) {
1283 for ( var type in Expr.filter ) {
1284 if ( (match = Expr.match[ type ].exec( expr )) != null ) {
1285 var filter = Expr.filter[ type ], found, item;
1287 if ( curLoop == result ) {
1290 if ( Expr.preFilter[ type ] ) {
1291 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
1293 anyFound = found = true;
1294 } else if ( match === true ) {
1299 for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
1301 found = filter( item, match, i, curLoop );
1302 var pass = not ^ !!found;
1303 if ( inplace && found != null ) {
1309 } else if ( pass ) {
1310 result.push( item );
1316 if ( found !== undefined ) {
1320 expr = expr.replace( Expr.match[ type ], "" );
1328 // Improper expression
1329 if ( expr == old ) {
1330 if ( anyFound == null ) {
1331 throw "Syntax error, unrecognized expression: " + expr;
1340 var Expr = Sizzle.selectors = {
1341 order: [ "ID", "NAME", "TAG" ],
1343 ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
1344 CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
1345 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
1346 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
1347 TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
1348 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
1349 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
1350 PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
1353 "class": "className",
1357 href: function(elem){
1358 return elem.getAttribute("href");
1362 "+": function(checkSet, part, isXML){
1363 var isPartStr = typeof part === "string",
1364 isTag = isPartStr && !/\W/.test(part),
1365 isPartStrNotTag = isPartStr && !isTag;
1366 if ( isTag && !isXML ) {
1367 part = part.toUpperCase();
1369 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
1370 if ( (elem = checkSet[i]) ) {
1371 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
1372 checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
1377 if ( isPartStrNotTag ) {
1378 Sizzle.filter( part, checkSet, true );
1381 ">": function(checkSet, part, isXML){
1382 var isPartStr = typeof part === "string";
1383 if ( isPartStr && !/\W/.test(part) ) {
1384 part = isXML ? part : part.toUpperCase();
1385 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1386 var elem = checkSet[i];
1388 var parent = elem.parentNode;
1389 checkSet[i] = parent.nodeName === part ? parent : false;
1393 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1394 var elem = checkSet[i];
1396 checkSet[i] = isPartStr ?
1398 elem.parentNode === part;
1402 Sizzle.filter( part, checkSet, true );
1406 "": function(checkSet, part, isXML){
1407 var doneName = done++, checkFn = dirCheck;
1408 if ( !part.match(/\W/) ) {
1409 var nodeCheck = part = isXML ? part : part.toUpperCase();
1410 checkFn = dirNodeCheck;
1412 checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
1414 "~": function(checkSet, part, isXML){
1415 var doneName = done++, checkFn = dirCheck;
1416 if ( typeof part === "string" && !part.match(/\W/) ) {
1417 var nodeCheck = part = isXML ? part : part.toUpperCase();
1418 checkFn = dirNodeCheck;
1420 checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
1424 ID: function(match, context, isXML){
1425 if ( typeof context.getElementById !== "undefined" && !isXML ) {
1426 var m = context.getElementById(match[1]);
1427 return m ? [m] : [];
1430 NAME: function(match, context, isXML){
1431 if ( typeof context.getElementsByName !== "undefined" ) {
1432 var ret = [], results = context.getElementsByName(match[1]);
1433 for ( var i = 0, l = results.length; i < l; i++ ) {
1434 if ( results[i].getAttribute("name") === match[1] ) {
1435 ret.push( results[i] );
1438 return ret.length === 0 ? null : ret;
1441 TAG: function(match, context){
1442 return context.getElementsByTagName(match[1]);
1446 CLASS: function(match, curLoop, inplace, result, not, isXML){
1447 match = " " + match[1].replace(/\\/g, "") + " ";
1451 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
1453 if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
1455 result.push( elem );
1456 } else if ( inplace ) {
1463 ID: function(match){
1464 return match[1].replace(/\\/g, "");
1466 TAG: function(match, curLoop){
1467 for ( var i = 0; curLoop[i] === false; i++ ){}
1468 return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
1470 CHILD: function(match){
1471 if ( match[1] == "nth" ) {
1472 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
1473 var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
1474 match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
1475 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
1476 // calculate the numbers (first)n+(last) including if they are negative
1477 match[2] = (test[1] + (test[2] || 1)) - 0;
1478 match[3] = test[3] - 0;
1480 // TODO: Move to normal caching system
1484 ATTR: function(match, curLoop, inplace, result, not, isXML){
1485 var name = match[1].replace(/\\/g, "");
1487 if ( !isXML && Expr.attrMap[name] ) {
1488 match[1] = Expr.attrMap[name];
1490 if ( match[2] === "~=" ) {
1491 match[4] = " " + match[4] + " ";
1495 PSEUDO: function(match, curLoop, inplace, result, not){
1496 if ( match[1] === "not" ) {
1497 // If we're dealing with a complex expression, or a simple one
1498 if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
1499 match[3] = Sizzle(match[3], null, null, curLoop);
1501 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
1503 result.push.apply( result, ret );
1507 } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
1513 POS: function(match){
1514 match.unshift( true );
1519 enabled: function(elem){
1520 return elem.disabled === false && elem.type !== "hidden";
1522 disabled: function(elem){
1523 return elem.disabled === true;
1525 checked: function(elem){
1526 return elem.checked === true;
1528 selected: function(elem){
1529 // Accessing this property makes selected-by-default
1530 // options in Safari work properly
1531 elem.parentNode.selectedIndex;
1532 return elem.selected === true;
1534 parent: function(elem){
1535 return !!elem.firstChild;
1537 empty: function(elem){
1538 return !elem.firstChild;
1540 has: function(elem, i, match){
1541 return !!Sizzle( match[3], elem ).length;
1543 header: function(elem){
1544 return /h\d/i.test( elem.nodeName );
1546 text: function(elem){
1547 return "text" === elem.type;
1549 radio: function(elem){
1550 return "radio" === elem.type;
1552 checkbox: function(elem){
1553 return "checkbox" === elem.type;
1555 file: function(elem){
1556 return "file" === elem.type;
1558 password: function(elem){
1559 return "password" === elem.type;
1561 submit: function(elem){
1562 return "submit" === elem.type;
1564 image: function(elem){
1565 return "image" === elem.type;
1567 reset: function(elem){
1568 return "reset" === elem.type;
1570 button: function(elem){
1571 return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
1573 input: function(elem){
1574 return /input|select|textarea|button/i.test(elem.nodeName);
1578 first: function(elem, i){
1581 last: function(elem, i, match, array){
1582 return i === array.length - 1;
1584 even: function(elem, i){
1587 odd: function(elem, i){
1590 lt: function(elem, i, match){
1591 return i < match[3] - 0;
1593 gt: function(elem, i, match){
1594 return i > match[3] - 0;
1596 nth: function(elem, i, match){
1597 return match[3] - 0 == i;
1599 eq: function(elem, i, match){
1600 return match[3] - 0 == i;
1604 PSEUDO: function(elem, match, i, array){
1605 var name = match[1], filter = Expr.filters[ name ];
1607 return filter( elem, i, match, array );
1608 } else if ( name === "contains" ) {
1609 return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
1610 } else if ( name === "not" ) {
1612 for ( var i = 0, l = not.length; i < l; i++ ) {
1613 if ( not[i] === elem ) {
1620 CHILD: function(elem, match){
1621 var type = match[1], node = elem;
1625 while (node = node.previousSibling) {
1626 if ( node.nodeType === 1 ) return false;
1628 if ( type == 'first') return true;
1631 while (node = node.nextSibling) {
1632 if ( node.nodeType === 1 ) return false;
1636 var first = match[2], last = match[3];
1637 if ( first == 1 && last == 0 ) {
1641 var doneName = match[0],
1642 parent = elem.parentNode;
1644 if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
1646 for ( node = parent.firstChild; node; node = node.nextSibling ) {
1647 if ( node.nodeType === 1 ) {
1648 node.nodeIndex = ++count;
1651 parent.sizcache = doneName;
1654 var diff = elem.nodeIndex - last;
1658 return ( diff % first == 0 && diff / first >= 0 );
1662 ID: function(elem, match){
1663 return elem.nodeType === 1 && elem.getAttribute("id") === match;
1665 TAG: function(elem, match){
1666 return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
1668 CLASS: function(elem, match){
1669 return (" " + (elem.className || elem.getAttribute("class")) + " ")
1670 .indexOf( match ) > -1;
1672 ATTR: function(elem, match){
1673 var name = match[1],
1674 result = Expr.attrHandle[ name ] ?
1675 Expr.attrHandle[ name ]( elem ) :
1676 elem[ name ] != null ?
1678 elem.getAttribute( name ),
1679 value = result + "",
1682 return result == null ?
1687 value.indexOf(check) >= 0 :
1689 (" " + value + " ").indexOf(check) >= 0 :
1691 value && result !== false :
1695 value.indexOf(check) === 0 :
1697 value.substr(value.length - check.length) === check :
1699 value === check || value.substr(0, check.length + 1) === check + "-" :
1702 POS: function(elem, match, i, array){
1703 var name = match[2], filter = Expr.setFilters[ name ];
1705 return filter( elem, i, match, array );
1710 var origPOS = Expr.match.POS;
1711 for ( var type in Expr.match ) {
1712 Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
1714 var makeArray = function(array, results) {
1715 array = Array.prototype.slice.call( array );
1717 results.push.apply( results, array );
1723 // Perform a simple check to determine if the browser is capable of
1724 // converting a NodeList to an array using builtin methods.
1726 Array.prototype.slice.call( document.documentElement.childNodes );
1727 // Provide a fallback method if it does not work
1729 makeArray = function(array, results) {
1730 var ret = results || [];
1731 if ( toString.call(array) === "[object Array]" ) {
1732 Array.prototype.push.apply( ret, array );
1734 if ( typeof array.length === "number" ) {
1735 for ( var i = 0, l = array.length; i < l; i++ ) {
1736 ret.push( array[i] );
1739 for ( var i = 0; array[i]; i++ ) {
1740 ret.push( array[i] );
1748 if ( document.documentElement.compareDocumentPosition ) {
1749 sortOrder = function( a, b ) {
1750 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
1752 hasDuplicate = true;
1756 } else if ( "sourceIndex" in document.documentElement ) {
1757 sortOrder = function( a, b ) {
1758 var ret = a.sourceIndex - b.sourceIndex;
1760 hasDuplicate = true;
1764 } else if ( document.createRange ) {
1765 sortOrder = function( a, b ) {
1766 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
1767 aRange.selectNode(a);
1768 aRange.collapse(true);
1769 bRange.selectNode(b);
1770 bRange.collapse(true);
1771 var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
1773 hasDuplicate = true;
1778 // Check to see if the browser returns elements by name when
1779 // querying by getElementById (and provide a workaround)
1781 // We're going to inject a fake input element with a specified name
1782 var form = document.createElement("form"),
1783 id = "script" + (new Date).getTime();
1784 form.innerHTML = "<input name='" + id + "'/>";
1785 // Inject it into the root element, check its status, and remove it quickly
1786 var root = document.documentElement;
1787 root.insertBefore( form, root.firstChild );
1788 // The workaround has to do additional checks after a getElementById
1789 // Which slows things down for other browsers (hence the branching)
1790 if ( !!document.getElementById( id ) ) {
1791 Expr.find.ID = function(match, context, isXML){
1792 if ( typeof context.getElementById !== "undefined" && !isXML ) {
1793 var m = context.getElementById(match[1]);
1794 return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
1797 Expr.filter.ID = function(elem, match){
1798 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
1799 return elem.nodeType === 1 && node && node.nodeValue === match;
1802 root.removeChild( form );
1805 // Check to see if the browser returns only elements
1806 // when doing getElementsByTagName("*")
1807 // Create a fake element
1808 var div = document.createElement("div");
1809 div.appendChild( document.createComment("") );
1810 // Make sure no comments are found
1811 if ( div.getElementsByTagName("*").length > 0 ) {
1812 Expr.find.TAG = function(match, context){
1813 var results = context.getElementsByTagName(match[1]);
1814 // Filter out possible comments
1815 if ( match[1] === "*" ) {
1817 for ( var i = 0; results[i]; i++ ) {
1818 if ( results[i].nodeType === 1 ) {
1819 tmp.push( results[i] );
1827 // Check to see if an attribute returns normalized href attributes
1828 div.innerHTML = "<a href='#'></a>";
1829 if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
1830 div.firstChild.getAttribute("href") !== "#" ) {
1831 Expr.attrHandle.href = function(elem){
1832 return elem.getAttribute("href", 2);
1836 if ( document.querySelectorAll ) (function(){
1837 var oldSizzle = Sizzle, div = document.createElement("div");
1838 div.innerHTML = "<p class='TEST'></p>";
1839 // Safari can't handle uppercase or unicode characters when
1841 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
1845 Sizzle = function(query, context, extra, seed){
1846 context = context || document;
1847 // Only use querySelectorAll on non-XML documents
1848 // (ID selectors don't work in non-HTML documents)
1849 if ( !seed && context.nodeType === 9 && !isXML(context) ) {
1851 return makeArray( context.querySelectorAll(query), extra );
1855 return oldSizzle(query, context, extra, seed);
1857 Sizzle.find = oldSizzle.find;
1858 Sizzle.filter = oldSizzle.filter;
1859 Sizzle.selectors = oldSizzle.selectors;
1860 Sizzle.matches = oldSizzle.matches;
1862 if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
1863 var div = document.createElement("div");
1864 div.innerHTML = "<div class='test e'></div><div class='test'></div>";
1865 // Opera can't find a second classname (in 9.6)
1866 if ( div.getElementsByClassName("e").length === 0 )
1868 // Safari caches class attributes, doesn't catch changes (in 3.2)
1869 div.lastChild.className = "e";
1870 if ( div.getElementsByClassName("e").length === 1 )
1872 Expr.order.splice(1, 0, "CLASS");
1873 Expr.find.CLASS = function(match, context, isXML) {
1874 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
1875 return context.getElementsByClassName(match[1]);
1879 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
1880 var sibDir = dir == "previousSibling" && !isXML;
1881 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1882 var elem = checkSet[i];
1884 if ( sibDir && elem.nodeType === 1 ){
1885 elem.sizcache = doneName;
1891 if ( elem.sizcache === doneName ) {
1892 match = checkSet[elem.sizset];
1895 if ( elem.nodeType === 1 && !isXML ){
1896 elem.sizcache = doneName;
1899 if ( elem.nodeName === cur ) {
1905 checkSet[i] = match;
1909 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
1910 var sibDir = dir == "previousSibling" && !isXML;
1911 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
1912 var elem = checkSet[i];
1914 if ( sibDir && elem.nodeType === 1 ) {
1915 elem.sizcache = doneName;
1921 if ( elem.sizcache === doneName ) {
1922 match = checkSet[elem.sizset];
1925 if ( elem.nodeType === 1 ) {
1927 elem.sizcache = doneName;
1930 if ( typeof cur !== "string" ) {
1931 if ( elem === cur ) {
1935 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
1942 checkSet[i] = match;
1946 var contains = document.compareDocumentPosition ? function(a, b){
1947 return a.compareDocumentPosition(b) & 16;
1949 return a !== b && (a.contains ? a.contains(b) : true);
1951 var isXML = function(elem){
1952 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
1953 !!elem.ownerDocument && isXML( elem.ownerDocument );
1955 var posProcess = function(selector, context){
1956 var tmpSet = [], later = "", match,
1957 root = context.nodeType ? [context] : context;
1958 // Position selectors must be done after the filter
1959 // And so must :not(positional) so we move all PSEUDOs to the end
1960 while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
1962 selector = selector.replace( Expr.match.PSEUDO, "" );
1964 selector = Expr.relative[selector] ? selector + "*" : selector;
1965 for ( var i = 0, l = root.length; i < l; i++ ) {
1966 Sizzle( selector, root[i], tmpSet );
1968 return Sizzle.filter( later, tmpSet );
1971 jQuery.find = Sizzle;
1972 jQuery.filter = Sizzle.filter;
1973 jQuery.expr = Sizzle.selectors;
1974 jQuery.expr[":"] = jQuery.expr.filters;
1975 Sizzle.selectors.filters.hidden = function(elem){
1976 return elem.offsetWidth === 0 || elem.offsetHeight === 0;
1978 Sizzle.selectors.filters.visible = function(elem){
1979 return elem.offsetWidth > 0 || elem.offsetHeight > 0;
1981 Sizzle.selectors.filters.animated = function(elem){
1982 return jQuery.grep(jQuery.timers, function(fn){
1983 return elem === fn.elem;
1986 jQuery.multiFilter = function( expr, elems, not ) {
1988 expr = ":not(" + expr + ")";
1990 return Sizzle.matches(expr, elems);
1992 jQuery.dir = function( elem, dir ){
1993 var matched = [], cur = elem[dir];
1994 while ( cur && cur != document ) {
1995 if ( cur.nodeType == 1 )
1996 matched.push( cur );
2001 jQuery.nth = function(cur, result, dir, elem){
2002 result = result || 1;
2004 for ( ; cur; cur = cur[dir] )
2005 if ( cur.nodeType == 1 && ++num == result )
2009 jQuery.sibling = function(n, elem){
2011 for ( ; n; n = n.nextSibling ) {
2012 if ( n.nodeType == 1 && n != elem )
2018 window.Sizzle = Sizzle;
2021 * A number of helper functions used for managing events.
2022 * Many of the ideas behind this code originated from
2023 * Dean Edwards' addEvent library.
2026 // Bind an event to an element
2027 // Original by Dean Edwards
2028 add: function(elem, types, handler, data) {
2029 if ( elem.nodeType == 3 || elem.nodeType == 8 )
2031 // For whatever reason, IE has trouble passing the window object
2032 // around, causing it to be cloned in the process
2033 if ( elem.setInterval && elem != window )
2035 // Make sure that the function being executed has a unique ID
2036 if ( !handler.guid )
2037 handler.guid = this.guid++;
2038 // if data is passed, bind to handler
2039 if ( data !== undefined ) {
2040 // Create temporary function pointer to original handler
2042 // Create unique handler function, wrapped around original handler
2043 handler = this.proxy( fn );
2044 // Store data in unique handler
2045 handler.data = data;
2047 // Init the element's event structure
2048 var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
2049 handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
2050 // Handle the second event of a trigger and when
2051 // an event is called after a page has unloaded
2052 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
2053 jQuery.event.handle.apply(arguments.callee.elem, arguments) :
2056 // Add elem as a property of the handle function
2057 // This is to prevent a memory leak with non-native
2060 // Handle multiple events separated by a space
2061 // jQuery(...).bind("mouseover mouseout", fn);
2062 jQuery.each(types.split(/\s+/), function(index, type) {
2063 // Namespaced event handlers
2064 var namespaces = type.split(".");
2065 type = namespaces.shift();
2066 handler.type = namespaces.slice().sort().join(".");
2067 // Get the current list of functions bound to this event
2068 var handlers = events[type];
2070 if ( jQuery.event.specialAll[type] )
2071 jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
2072 // Init the event handler queue
2074 handlers = events[type] = {};
2075 // Check for a special event handler
2076 // Only use addEventListener/attachEvent if the special
2077 // events handler returns false
2078 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
2079 // Bind the global event handler to the element
2080 if (elem.addEventListener)
2081 elem.addEventListener(type, handle, false);
2082 else if (elem.attachEvent)
2083 elem.attachEvent("on" + type, handle);
2086 // Add the function to the element's handler list
2087 handlers[handler.guid] = handler;
2088 // Keep track of which events have been used, for global triggering
2089 jQuery.event.global[type] = true;
2091 // Nullify elem to prevent memory leaks in IE
2096 // Detach an event or set of events from an element
2097 remove: function(elem, types, handler) {
2098 // don't do events on text and comment nodes
2099 if ( elem.nodeType == 3 || elem.nodeType == 8 )
2101 var events = jQuery.data(elem, "events"), ret, index;
2103 // Unbind all events for the element
2104 if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
2105 for ( var type in events )
2106 this.remove( elem, type + (types || "") );
2108 // types is actually an event object here
2110 handler = types.handler;
2113 // Handle multiple events seperated by a space
2114 // jQuery(...).unbind("mouseover mouseout", fn);
2115 jQuery.each(types.split(/\s+/), function(index, type){
2116 // Namespaced event handlers
2117 var namespaces = type.split(".");
2118 type = namespaces.shift();
2119 var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
2120 if ( events[type] ) {
2121 // remove the given handler for the given type
2123 delete events[type][handler.guid];
2124 // remove all handlers for the given type
2126 for ( var handle in events[type] )
2127 // Handle the removal of namespaced events
2128 if ( namespace.test(events[type][handle].type) )
2129 delete events[type][handle];
2131 if ( jQuery.event.specialAll[type] )
2132 jQuery.event.specialAll[type].teardown.call(elem, namespaces);
2133 // remove generic event handler if no more handlers exist
2134 for ( ret in events[type] ) break;
2136 if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
2137 if (elem.removeEventListener)
2138 elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
2139 else if (elem.detachEvent)
2140 elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
2143 delete events[type];
2148 // Remove the expando if it's no longer used
2149 for ( ret in events ) break;
2151 var handle = jQuery.data( elem, "handle" );
2152 if ( handle ) handle.elem = null;
2153 jQuery.removeData( elem, "events" );
2154 jQuery.removeData( elem, "handle" );
2158 // bubbling is internal
2159 trigger: function( event, data, elem, bubbling ) {
2160 // Event object or event type
2161 var type = event.type || event;
2163 event = typeof event === "object" ?
2164 // jQuery.Event object
2165 event[expando] ? event :
2167 jQuery.extend( jQuery.Event(type), event ) :
2168 // Just the event type (string)
2170 if ( type.indexOf("!") >= 0 ) {
2171 event.type = type = type.slice(0, -1);
2172 event.exclusive = true;
2174 // Handle a global trigger
2176 // Don't bubble custom events when global (to avoid too much overhead)
2177 event.stopPropagation();
2178 // Only trigger if we've ever bound an event for it
2179 if ( this.global[type] )
2180 jQuery.each( jQuery.cache, function(){
2181 if ( this.events && this.events[type] )
2182 jQuery.event.trigger( event, data, this.handle.elem );
2185 // Handle triggering a single element
2186 // don't do events on text and comment nodes
2187 if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
2190 // Clean up in case it is reused
2191 event.result = undefined;
2192 event.target = elem;
2194 // Clone the incoming data, if any
2195 data = jQuery.makeArray(data);
2196 data.unshift( event );
2198 event.currentTarget = elem;
2199 // Trigger the event, it is assumed that "handle" is a function
2200 var handle = jQuery.data(elem, "handle");
2202 handle.apply( elem, data );
2203 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
2204 if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
2205 event.result = false;
2206 // Trigger the native events (except for clicks on links)
2207 if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
2208 this.triggered = true;
2211 // prevent IE from throwing an error for some hidden elements
2214 this.triggered = false;
2215 if ( !event.isPropagationStopped() ) {
2216 var parent = elem.parentNode || elem.ownerDocument;
2218 jQuery.event.trigger(event, data, parent, true);
2221 handle: function(event) {
2222 // returned undefined or false
2224 event = arguments[0] = jQuery.event.fix( event || window.event );
2225 event.currentTarget = this;
2227 // Namespaced event handlers
2228 var namespaces = event.type.split(".");
2229 event.type = namespaces.shift();
2230 // Cache this now, all = true means, any handler
2231 all = !namespaces.length && !event.exclusive;
2233 var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
2234 handlers = ( jQuery.data(this, "events") || {} )[event.type];
2235 for ( var j in handlers ) {
2236 var handler = handlers[j];
2237 // Filter the functions by class
2238 if ( all || namespace.test(handler.type) ) {
2239 // Pass in a reference to the handler function itself
2240 // So that we can later remove it
2241 event.handler = handler;
2242 event.data = handler.data;
2243 var ret = handler.apply(this, arguments);
2244 if( ret !== undefined ){
2246 if ( ret === false ) {
2247 event.preventDefault();
2248 event.stopPropagation();
2251 if( event.isImmediatePropagationStopped() )
2256 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(" "),
2257 fix: function(event) {
2258 if ( event[expando] )
2260 // store a copy of the original event object
2261 // and "clone" to set read-only properties
2262 var originalEvent = event;
2263 event = jQuery.Event( originalEvent );
2264 for ( var i = this.props.length, prop; i; ){
2265 prop = this.props[ --i ];
2266 event[ prop ] = originalEvent[ prop ];
2268 // Fix target property, if necessary
2269 if ( !event.target )
2270 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
2271 // check if target is a textnode (safari)
2272 if ( event.target.nodeType == 3 )
2273 event.target = event.target.parentNode;
2274 // Add relatedTarget, if necessary
2275 if ( !event.relatedTarget && event.fromElement )
2276 event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
2277 // Calculate pageX/Y if missing and clientX/Y available
2278 if ( event.pageX == null && event.clientX != null ) {
2279 var doc = document.documentElement, body = document.body;
2280 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
2281 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
2283 // Add which for key events
2284 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
2285 event.which = event.charCode || event.keyCode;
2286 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
2287 if ( !event.metaKey && event.ctrlKey )
2288 event.metaKey = event.ctrlKey;
2289 // Add which for click: 1 == left; 2 == middle; 3 == right
2290 // Note: button is not normalized, so don't use it
2291 if ( !event.which && event.button )
2292 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2295 proxy: function( fn, proxy ){
2296 proxy = proxy || function(){ return fn.apply(this, arguments); };
2297 // Set the guid of unique handler to the same of original handler, so it can be removed
2298 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
2299 // So proxy can be declared as an argument
2304 // Make sure the ready event is setup
2306 teardown: function() {}
2312 setup: function( selector, namespaces ){
2313 jQuery.event.add( this, namespaces[0], liveHandler );
2315 teardown: function( namespaces ){
2316 if ( namespaces.length ) {
2317 var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
2319 jQuery.each( (jQuery.data(this, "events").live || {}), function(){
2320 if ( name.test(this.type) )
2325 jQuery.event.remove( this, namespaces[0], liveHandler );
2331 jQuery.Event = function( src ){
2332 // Allow instantiation without the 'new' keyword
2333 if( !this.preventDefault )
2334 return new jQuery.Event(src);
2337 if( src && src.type ){
2338 this.originalEvent = src;
2339 this.type = src.type;
2343 // timeStamp is buggy for some events on Firefox(#3843)
2344 // So we won't rely on the native value
2345 this.timeStamp = now();
2348 this[expando] = true;
2350 function returnFalse(){
2353 function returnTrue(){
2356 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
2357 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
2358 jQuery.Event.prototype = {
2359 preventDefault: function() {
2360 this.isDefaultPrevented = returnTrue;
2361 var e = this.originalEvent;
2364 // if preventDefault exists run it on the original event
2365 if (e.preventDefault)
2367 // otherwise set the returnValue property of the original event to false (IE)
2368 e.returnValue = false;
2370 stopPropagation: function() {
2371 this.isPropagationStopped = returnTrue;
2372 var e = this.originalEvent;
2375 // if stopPropagation exists run it on the original event
2376 if (e.stopPropagation)
2377 e.stopPropagation();
2378 // otherwise set the cancelBubble property of the original event to true (IE)
2379 e.cancelBubble = true;
2381 stopImmediatePropagation:function(){
2382 this.isImmediatePropagationStopped = returnTrue;
2383 this.stopPropagation();
2385 isDefaultPrevented: returnFalse,
2386 isPropagationStopped: returnFalse,
2387 isImmediatePropagationStopped: returnFalse
2389 // Checks if an event happened on an element within another element
2390 // Used in jQuery.event.special.mouseenter and mouseleave handlers
2391 var withinElement = function(event) {
2392 // Check if mouse(over|out) are still within the same parent element
2393 var parent = event.relatedTarget;
2394 // Traverse up the tree
2395 while ( parent && parent != this )
2396 try { parent = parent.parentNode; }
2397 catch(e) { parent = this; }
2399 if( parent != this ){
2400 // set the correct event type
2401 event.type = event.data;
2402 // handle event if we actually just moused on to a non sub-element
2403 jQuery.event.handle.apply( this, arguments );
2408 mouseover: 'mouseenter',
2409 mouseout: 'mouseleave'
2410 }, function( orig, fix ){
2411 jQuery.event.special[ fix ] = {
2413 jQuery.event.add( this, orig, withinElement, fix );
2415 teardown: function(){
2416 jQuery.event.remove( this, orig, withinElement );
2421 bind: function( type, data, fn ) {
2422 return type == "unload" ? this.one(type, data, fn) : this.each(function(){
2423 jQuery.event.add( this, type, fn || data, fn && data );
2426 one: function( type, data, fn ) {
2427 var one = jQuery.event.proxy( fn || data, function(event) {
2428 jQuery(this).unbind(event, one);
2429 return (fn || data).apply( this, arguments );
2431 return this.each(function(){
2432 jQuery.event.add( this, type, one, fn && data);
2435 unbind: function( type, fn ) {
2436 return this.each(function(){
2437 jQuery.event.remove( this, type, fn );
2440 trigger: function( type, data ) {
2441 return this.each(function(){
2442 jQuery.event.trigger( type, data, this );
2445 triggerHandler: function( type, data ) {
2447 var event = jQuery.Event(type);
2448 event.preventDefault();
2449 event.stopPropagation();
2450 jQuery.event.trigger( event, data, this[0] );
2451 return event.result;
2454 toggle: function( fn ) {
2455 // Save reference to arguments for access in closure
2456 var args = arguments, i = 1;
2457 // link all the functions, so any of them can unbind this click handler
2458 while( i < args.length )
2459 jQuery.event.proxy( fn, args[i++] );
2460 return this.click( jQuery.event.proxy( fn, function(event) {
2461 // Figure out which function to execute
2462 this.lastToggle = ( this.lastToggle || 0 ) % i;
2463 // Make sure that clicks stop
2464 event.preventDefault();
2465 // and execute the function
2466 return args[ this.lastToggle++ ].apply( this, arguments ) || false;
2469 hover: function(fnOver, fnOut) {
2470 return this.mouseenter(fnOver).mouseleave(fnOut);
2472 ready: function(fn) {
2473 // Attach the listeners
2475 // If the DOM is already ready
2476 if ( jQuery.isReady )
2477 // Execute the function immediately
2478 fn.call( document, jQuery );
2479 // Otherwise, remember the function for later
2481 // Add the function to the wait list
2482 jQuery.readyList.push( fn );
2486 live: function( type, fn ){
2487 var proxy = jQuery.event.proxy( fn );
2488 proxy.guid += this.selector + type;
2489 jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
2493 die: function( type, fn ){
2494 jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
2498 function liveHandler( event ){
2499 var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
2502 jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
2503 if ( check.test(fn.type) ) {
2504 var elem = jQuery(event.target).closest(fn.data)[0];
2506 elems.push({ elem: elem, fn: fn });
2509 elems.sort(function(a,b) {
2510 return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
2513 jQuery.each(elems, function(){
2514 if ( this.fn.call(this.elem, event, this.fn.data) === false )
2515 return (stop = false);
2519 function liveConvert(type, selector){
2520 return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
2525 // Handle when the DOM is ready
2527 // Make sure that the DOM is not already loaded
2528 if ( !jQuery.isReady ) {
2529 // Remember that the DOM is ready
2530 jQuery.isReady = true;
2531 // If there are functions bound, to execute
2532 if ( jQuery.readyList ) {
2533 // Execute all of them
2534 jQuery.each( jQuery.readyList, function(){
2535 this.call( document, jQuery );
2537 // Reset the list of functions
2538 jQuery.readyList = null;
2540 // Trigger any bound ready events
2541 jQuery(document).triggerHandler("ready");
2545 var readyBound = false;
2546 function bindReady(){
2547 if ( readyBound ) return;
2549 // Mozilla, Opera and webkit nightlies currently support this event
2550 if ( document.addEventListener ) {
2551 // Use the handy event callback
2552 document.addEventListener( "DOMContentLoaded", function(){
2553 document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
2556 // If IE event model is used
2557 } else if ( document.attachEvent ) {
2558 // ensure firing before onload,
2559 // maybe late but safe also for iframes
2560 document.attachEvent("onreadystatechange", function(){
2561 if ( document.readyState === "complete" ) {
2562 document.detachEvent( "onreadystatechange", arguments.callee );
2566 // If IE and not an iframe
2567 // continually check to see if the document is ready
2568 if ( document.documentElement.doScroll && window == window.top ) (function(){
2569 if ( jQuery.isReady ) return;
2571 // If IE is used, use the trick by Diego Perini
2572 // http://javascript.nwbox.com/IEContentLoaded/
2573 document.documentElement.doScroll("left");
2575 setTimeout( arguments.callee, 0 );
2578 // and execute any waiting functions
2582 // A fallback to window.onload, that will always work
2583 jQuery.event.add( window, "load", jQuery.ready );
2585 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
2586 "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
2587 "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
2588 // Handle event binding
2589 jQuery.fn[name] = function(fn){
2590 return fn ? this.bind(name, fn) : this.trigger(name);
2593 // Prevent memory leaks in IE
2594 // And prevent errors on refresh with events like mouseover in other browsers
2595 // Window isn't included so as not to unbind existing unload events
2596 jQuery( window ).bind( 'unload', function(){
2597 for ( var id in jQuery.cache )
2599 if ( id != 1 && jQuery.cache[ id ].handle )
2600 jQuery.event.remove( jQuery.cache[ id ].handle.elem );
2603 jQuery.support = {};
2604 var root = document.documentElement,
2605 script = document.createElement("script"),
2606 div = document.createElement("div"),
2607 id = "script" + (new Date).getTime();
2608 div.style.display = "none";
2609 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>';
2610 var all = div.getElementsByTagName("*"),
2611 a = div.getElementsByTagName("a")[0];
2612 // Can't get basic test support
2613 if ( !all || !all.length || !a ) {
2617 // IE strips leading whitespace when .innerHTML is used
2618 leadingWhitespace: div.firstChild.nodeType == 3,
2620 // Make sure that tbody elements aren't automatically inserted
2621 // IE will insert them into empty tables
2622 tbody: !div.getElementsByTagName("tbody").length,
2624 // Make sure that you can get all elements in an <object> element
2625 // IE 7 always returns no results
2626 objectAll: !!div.getElementsByTagName("object")[0]
2627 .getElementsByTagName("*").length,
2629 // Make sure that link elements get serialized correctly by innerHTML
2630 // This requires a wrapper element in IE
2631 htmlSerialize: !!div.getElementsByTagName("link").length,
2633 // Get the style information from getAttribute
2634 // (IE uses .cssText insted)
2635 style: /red/.test( a.getAttribute("style") ),
2637 // Make sure that URLs aren't manipulated
2638 // (IE normalizes it by default)
2639 hrefNormalized: a.getAttribute("href") === "/a",
2641 // Make sure that element opacity exists
2642 // (IE uses filter instead)
2643 opacity: a.style.opacity === "0.5",
2645 // Verify style float existence
2646 // (IE uses styleFloat instead of cssFloat)
2647 cssFloat: !!a.style.cssFloat,
2648 // Will be defined later
2654 script.type = "text/javascript";
2656 script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
2658 root.insertBefore( script, root.firstChild );
2660 // Make sure that the execution of code works by injecting a script
2661 // tag with appendChild/createTextNode
2662 // (IE doesn't support this, fails, and uses .text instead)
2663 if ( window[ id ] ) {
2664 jQuery.support.scriptEval = true;
2665 delete window[ id ];
2667 root.removeChild( script );
2668 if ( div.attachEvent && div.fireEvent ) {
2669 div.attachEvent("onclick", function(){
2670 // Cloning a node shouldn't copy over any
2671 // bound event handlers (IE does this)
2672 jQuery.support.noCloneEvent = false;
2673 div.detachEvent("onclick", arguments.callee);
2675 div.cloneNode(true).fireEvent("onclick");
2677 // Figure out if the W3C box model works as expected
2678 // document.body must exist before we can do this
2680 var div = document.createElement("div");
2681 div.style.width = div.style.paddingLeft = "1px";
2682 document.body.appendChild( div );
2683 jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
2684 document.body.removeChild( div ).style.display = 'none';
2687 var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
2690 "class": "className",
2691 "float": styleFloat,
2692 cssFloat: styleFloat,
2693 styleFloat: styleFloat,
2694 readonly: "readOnly",
2695 maxlength: "maxLength",
2696 cellspacing: "cellSpacing",
2698 tabindex: "tabIndex"
2701 // Keep a copy of the old load
2702 _load: jQuery.fn.load,
2703 load: function( url, params, callback ) {
2704 if ( typeof url !== "string" )
2705 return this._load( url );
2706 var off = url.indexOf(" ");
2708 var selector = url.slice(off, url.length);
2709 url = url.slice(0, off);
2711 // Default to a GET request
2713 // If the second parameter was provided
2715 // If it's a function
2716 if ( jQuery.isFunction( params ) ) {
2717 // We assume that it's the callback
2720 // Otherwise, build a param string
2721 } else if( typeof params === "object" ) {
2722 params = jQuery.param( params );
2726 // Request the remote document
2732 complete: function(res, status){
2733 // If successful, inject the HTML into all the matched elements
2734 if ( status == "success" || status == "notmodified" )
2735 // See if a selector was specified
2736 self.html( selector ?
2737 // Create a dummy div to hold the results
2739 // inject the contents of the document in, removing the scripts
2740 // to avoid any 'Permission Denied' errors in IE
2741 .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
2742 // Locate the specified elements
2744 // If not, just inject the full result
2747 self.each( callback, [res.responseText, status, res] );
2752 serialize: function() {
2753 return jQuery.param(this.serializeArray());
2755 serializeArray: function() {
2756 return this.map(function(){
2757 return this.elements ? jQuery.makeArray(this.elements) : this;
2760 return this.name && !this.disabled &&
2761 (this.checked || /select|textarea/i.test(this.nodeName) ||
2762 /text|hidden|password|search/i.test(this.type));
2764 .map(function(i, elem){
2765 var val = jQuery(this).val();
2766 return val == null ? null :
2767 jQuery.isArray(val) ?
2768 jQuery.map( val, function(val, i){
2769 return {name: elem.name, value: val};
2771 {name: elem.name, value: val};
2775 // Attach a bunch of functions for handling common AJAX events
2776 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
2777 jQuery.fn[o] = function(f){
2778 return this.bind(o, f);
2784 get: function( url, data, callback, type ) {
2785 // shift arguments if data argument was ommited
2786 if ( jQuery.isFunction( data ) ) {
2790 return jQuery.ajax({
2798 getScript: function( url, callback ) {
2799 return jQuery.get(url, null, callback, "script");
2801 getJSON: function( url, data, callback ) {
2802 return jQuery.get(url, data, callback, "json");
2804 post: function( url, data, callback, type ) {
2805 if ( jQuery.isFunction( data ) ) {
2809 return jQuery.ajax({
2817 ajaxSetup: function( settings ) {
2818 jQuery.extend( jQuery.ajaxSettings, settings );
2824 contentType: "application/x-www-form-urlencoded",
2833 // Create the request object; Microsoft failed to properly
2834 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
2835 // This function can be overriden by calling jQuery.ajaxSetup
2837 return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
2840 xml: "application/xml, text/xml",
2842 script: "text/javascript, application/javascript",
2843 json: "application/json, text/javascript",
2848 // Last-Modified header cache for next request
2850 ajax: function( s ) {
2851 // Extend the settings, but re-extend 's' so that it can be
2852 // checked again later (in the test suite, specifically)
2853 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
2854 var jsonp, jsre = /=\?(&|$)/g, status, data,
2855 type = s.type.toUpperCase();
2856 // convert data if not already a string
2857 if ( s.data && s.processData && typeof s.data !== "string" )
2858 s.data = jQuery.param(s.data);
2859 // Handle JSONP Parameter Callbacks
2860 if ( s.dataType == "jsonp" ) {
2861 if ( type == "GET" ) {
2862 if ( !s.url.match(jsre) )
2863 s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
2864 } else if ( !s.data || !s.data.match(jsre) )
2865 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
2866 s.dataType = "json";
2868 // Build temporary JSONP function
2869 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
2870 jsonp = "jsonp" + jsc++;
2871 // Replace the =? sequence both in the query string and the data
2873 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
2874 s.url = s.url.replace(jsre, "=" + jsonp + "$1");
2875 // We need to make sure
2876 // that a JSONP style response is executed properly
2877 s.dataType = "script";
2878 // Handle JSONP-style loading
2879 window[ jsonp ] = function(tmp){
2884 window[ jsonp ] = undefined;
2885 try{ delete window[ jsonp ]; } catch(e){}
2887 head.removeChild( script );
2890 if ( s.dataType == "script" && s.cache == null )
2892 if ( s.cache === false && type == "GET" ) {
2894 // try replacing _= if it is there
2895 var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
2896 // if nothing was replaced, add timestamp to the end
2897 s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
2899 // If data is available, append data to url for get requests
2900 if ( s.data && type == "GET" ) {
2901 s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
2902 // IE likes to send both get and post data, prevent this
2905 // Watch for a new set of requests
2906 if ( s.global && ! jQuery.active++ )
2907 jQuery.event.trigger( "ajaxStart" );
2908 // Matches an absolute URL, and saves the domain
2909 var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
2910 // If we're requesting a remote document
2911 // and trying to load JSON or Script with a GET
2912 if ( s.dataType == "script" && type == "GET" && parts
2913 && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
2914 var head = document.getElementsByTagName("head")[0];
2915 var script = document.createElement("script");
2917 if (s.scriptCharset)
2918 script.charset = s.scriptCharset;
2919 // Handle Script loading
2922 // Attach handlers for all browsers
2923 script.onload = script.onreadystatechange = function(){
2924 if ( !done && (!this.readyState ||
2925 this.readyState == "loaded" || this.readyState == "complete") ) {
2929 // Handle memory leak in IE
2930 script.onload = script.onreadystatechange = null;
2931 head.removeChild( script );
2935 head.appendChild(script);
2936 // We handle everything using the script element injection
2939 var requestDone = false;
2940 // Create the request object
2943 // Passing null username, generates a login popup on Opera (#2865)
2945 xhr.open(type, s.url, s.async, s.username, s.password);
2947 xhr.open(type, s.url, s.async);
2948 // Need an extra try/catch for cross domain requests in Firefox 3
2950 // Set the correct header, if data is being sent
2952 xhr.setRequestHeader("Content-Type", s.contentType);
2953 // Set the If-Modified-Since header, if ifModified mode.
2955 xhr.setRequestHeader("If-Modified-Since",
2956 jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
2957 // Set header so the called script knows that it's an XMLHttpRequest
2958 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
2959 // Set the Accepts header for the server, depending on the dataType
2960 xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
2961 s.accepts[ s.dataType ] + ", */*" :
2962 s.accepts._default );
2964 // Allow custom headers/mimetypes and early abort
2965 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
2966 // Handle the global AJAX counter
2967 if ( s.global && ! --jQuery.active )
2968 jQuery.event.trigger( "ajaxStop" );
2969 // close opended socket
2974 jQuery.event.trigger("ajaxSend", [xhr, s]);
2975 // Wait for a response to come back
2976 var onreadystatechange = function(isTimeout){
2977 // The request was aborted, clear the interval and decrement jQuery.active
2978 if (xhr.readyState == 0) {
2980 // clear poll interval
2981 clearInterval(ival);
2983 // Handle the global AJAX counter
2984 if ( s.global && ! --jQuery.active )
2985 jQuery.event.trigger( "ajaxStop" );
2987 // The transfer is complete and the data is available, or the request timed out
2988 } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
2990 // clear poll interval
2992 clearInterval(ival);
2995 status = isTimeout == "timeout" ? "timeout" :
2996 !jQuery.httpSuccess( xhr ) ? "error" :
2997 s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
2999 if ( status == "success" ) {
3000 // Watch for, and catch, XML document parse errors
3002 // process the data (runs the xml through httpData regardless of callback)
3003 data = jQuery.httpData( xhr, s.dataType, s );
3005 status = "parsererror";
3008 // Make sure that the request was successful or notmodified
3009 if ( status == "success" ) {
3010 // Cache Last-Modified header, if ifModified mode.
3013 modRes = xhr.getResponseHeader("Last-Modified");
3014 } catch(e) {} // swallow exception thrown by FF if header is not available
3015 if ( s.ifModified && modRes )
3016 jQuery.lastModified[s.url] = modRes;
3017 // JSONP handles its own success callback
3021 jQuery.handleError(s, xhr, status);
3022 // Fire the complete handlers
3026 // Stop memory leaks
3032 // don't attach the handler to the request, just poll it instead
3033 var ival = setInterval(onreadystatechange, 13);
3035 if ( s.timeout > 0 )
3036 setTimeout(function(){
3037 // Check to see if the request is still happening
3038 if ( xhr && !requestDone )
3039 onreadystatechange( "timeout" );
3046 jQuery.handleError(s, xhr, null, e);
3048 // firefox 1.5 doesn't fire statechange for sync requests
3050 onreadystatechange();
3052 // If a local callback was specified, fire it and pass it the data
3054 s.success( data, status );
3055 // Fire the global callback
3057 jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
3059 function complete(){
3062 s.complete(xhr, status);
3063 // The request was completed
3065 jQuery.event.trigger( "ajaxComplete", [xhr, s] );
3066 // Handle the global AJAX counter
3067 if ( s.global && ! --jQuery.active )
3068 jQuery.event.trigger( "ajaxStop" );
3070 // return XMLHttpRequest to allow aborting the request etc.
3073 handleError: function( s, xhr, status, e ) {
3074 // If a local callback was specified, fire it
3075 if ( s.error ) s.error( xhr, status, e );
3076 // Fire the global callback
3078 jQuery.event.trigger( "ajaxError", [xhr, s, e] );
3080 // Counter for holding the number of active queries
3082 // Determines if an XMLHttpRequest was successful or not
3083 httpSuccess: function( xhr ) {
3085 // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
3086 return !xhr.status && location.protocol == "file:" ||
3087 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
3091 // Determines if an XMLHttpRequest returns NotModified
3092 httpNotModified: function( xhr, url ) {
3094 var xhrRes = xhr.getResponseHeader("Last-Modified");
3095 // Firefox always returns 200. check Last-Modified date
3096 return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
3100 httpData: function( xhr, type, s ) {
3101 var ct = xhr.getResponseHeader("content-type"),
3102 xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
3103 data = xml ? xhr.responseXML : xhr.responseText;
3104 if ( xml && data.documentElement.tagName == "parsererror" )
3105 throw "parsererror";
3107 // Allow a pre-filtering function to sanitize the response
3108 // s != null is checked to keep backwards compatibility
3109 if( s && s.dataFilter )
3110 data = s.dataFilter( data, type );
3111 // The filter can actually parse the response
3112 if( typeof data === "string" ){
3113 // If the type is "script", eval it in global context
3114 if ( type == "script" )
3115 jQuery.globalEval( data );
3116 // Get the JavaScript object, if JSON is used.
3117 if ( type == "json" )
3118 data = window["eval"]("(" + data + ")");
3123 // Serialize an array of form elements or a set of
3124 // key/values into a query string
3125 param: function( a ) {
3127 function add( key, value ){
3128 s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
3130 // If an array was passed in, assume that it is an array
3132 if ( jQuery.isArray(a) || a.jquery )
3133 // Serialize the form elements
3134 jQuery.each( a, function(){
3135 add( this.name, this.value );
3137 // Otherwise, assume that it's an object of key/value pairs
3139 // Serialize the key/values
3141 // If the value is an array then the key names need to be repeated
3142 if ( jQuery.isArray(a[j]) )
3143 jQuery.each( a[j], function(){
3147 add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
3148 // Return the resulting serialization
3149 return s.join("&").replace(/%20/g, "+");
3152 var elemdisplay = {},
3155 // height animations
3156 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
3158 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
3159 // opacity animations
3162 function genFx( type, num ){
3164 jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
3170 show: function(speed,callback){
3172 return this.animate( genFx("show", 3), speed, callback);
3174 for ( var i = 0, l = this.length; i < l; i++ ){
3175 var old = jQuery.data(this[i], "olddisplay");
3177 this[i].style.display = old || "";
3179 if ( jQuery.css(this[i], "display") === "none" ) {
3180 var tagName = this[i].tagName, display;
3182 if ( elemdisplay[ tagName ] ) {
3183 display = elemdisplay[ tagName ];
3185 var elem = jQuery("<" + tagName + " />").appendTo("body");
3187 display = elem.css("display");
3188 if ( display === "none" )
3193 elemdisplay[ tagName ] = display;
3196 jQuery.data(this[i], "olddisplay", display);
3199 // Set the display of the elements in a second loop
3200 // to avoid the constant reflow
3201 for ( var i = 0, l = this.length; i < l; i++ ){
3202 this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
3208 hide: function(speed,callback){
3210 return this.animate( genFx("hide", 3), speed, callback);
3212 for ( var i = 0, l = this.length; i < l; i++ ){
3213 var old = jQuery.data(this[i], "olddisplay");
3214 if ( !old && old !== "none" )
3215 jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
3217 // Set the display of the elements in a second loop
3218 // to avoid the constant reflow
3219 for ( var i = 0, l = this.length; i < l; i++ ){
3220 this[i].style.display = "none";
3225 // Save the old toggle function
3226 _toggle: jQuery.fn.toggle,
3227 toggle: function( fn, fn2 ){
3228 var bool = typeof fn === "boolean";
3229 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
3230 this._toggle.apply( this, arguments ) :
3231 fn == null || bool ?
3232 this.each(function(){
3233 var state = bool ? fn : jQuery(this).is(":hidden");
3234 jQuery(this)[ state ? "show" : "hide" ]();
3236 this.animate(genFx("toggle", 3), fn, fn2);
3238 fadeTo: function(speed,to,callback){
3239 return this.animate({opacity: to}, speed, callback);
3241 animate: function( prop, speed, easing, callback ) {
3242 var optall = jQuery.speed(speed, easing, callback);
3243 return this[ optall.queue === false ? "each" : "queue" ](function(){
3245 var opt = jQuery.extend({}, optall), p,
3246 hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
3250 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
3251 return opt.complete.call(this);
3252 if ( ( p == "height" || p == "width" ) && this.style ) {
3253 // Store display property
3254 opt.display = jQuery.css(this, "display");
3255 // Make sure that nothing sneaks out
3256 opt.overflow = this.style.overflow;
3259 if ( opt.overflow != null )
3260 this.style.overflow = "hidden";
3261 opt.curAnim = jQuery.extend({}, prop);
3262 jQuery.each( prop, function(name, val){
3263 var e = new jQuery.fx( self, opt, name );
3264 if ( /toggle|show|hide/.test(val) )
3265 e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
3267 var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
3268 start = e.cur(true) || 0;
3270 var end = parseFloat(parts[2]),
3271 unit = parts[3] || "px";
3272 // We need to compute starting value
3273 if ( unit != "px" ) {
3274 self.style[ name ] = (end || 1) + unit;
3275 start = ((end || 1) / e.cur(true)) * start;
3276 self.style[ name ] = start + unit;
3278 // If a +=/-= token was provided, we're doing a relative animation
3280 end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
3281 e.custom( start, end, unit );
3283 e.custom( start, val, "" );
3286 // For JS strict compliance
3290 stop: function(clearQueue, gotoEnd){
3291 var timers = jQuery.timers;
3294 this.each(function(){
3295 // go in reverse order so anything added to the queue during the loop is ignored
3296 for ( var i = timers.length - 1; i >= 0; i-- )
3297 if ( timers[i].elem == this ) {
3299 // force the next step to be the last
3301 timers.splice(i, 1);
3304 // start the next in the queue if the last step wasn't forced
3310 // Generate shortcuts for custom animations
3312 slideDown: genFx("show", 1),
3313 slideUp: genFx("hide", 1),
3314 slideToggle: genFx("toggle", 1),
3315 fadeIn: { opacity: "show" },
3316 fadeOut: { opacity: "hide" }
3317 }, function( name, props ){
3318 jQuery.fn[ name ] = function( speed, callback ){
3319 return this.animate( props, speed, callback );
3323 speed: function(speed, easing, fn) {
3324 var opt = typeof speed === "object" ? speed : {
3325 complete: fn || !fn && easing ||
3326 jQuery.isFunction( speed ) && speed,
3328 easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
3330 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
3331 jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
3333 opt.old = opt.complete;
3334 opt.complete = function(){
3335 if ( opt.queue !== false )
3336 jQuery(this).dequeue();
3337 if ( jQuery.isFunction( opt.old ) )
3338 opt.old.call( this );
3343 linear: function( p, n, firstNum, diff ) {
3344 return firstNum + diff * p;
3346 swing: function( p, n, firstNum, diff ) {
3347 return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
3351 fx: function( elem, options, prop ){
3352 this.options = options;
3355 if ( !options.orig )
3359 jQuery.fx.prototype = {
3360 // Simple function for setting a style value
3362 if ( this.options.step )
3363 this.options.step.call( this.elem, this.now, this );
3364 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
3365 // Set display property to block for height/width animations
3366 if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
3367 this.elem.style.display = "block";
3369 // Get the current size
3370 cur: function(force){
3371 if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
3372 return this.elem[ this.prop ];
3373 var r = parseFloat(jQuery.css(this.elem, this.prop, force));
3374 return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
3376 // Start an animation from one number to another
3377 custom: function(from, to, unit){
3378 this.startTime = now();
3381 this.unit = unit || this.unit || "px";
3382 this.now = this.start;
3383 this.pos = this.state = 0;
3385 function t(gotoEnd){
3386 return self.step(gotoEnd);
3389 if ( t() && jQuery.timers.push(t) && !timerId ) {
3390 timerId = setInterval(function(){
3391 var timers = jQuery.timers;
3392 for ( var i = 0; i < timers.length; i++ )
3394 timers.splice(i--, 1);
3395 if ( !timers.length ) {
3396 clearInterval( timerId );
3397 timerId = undefined;
3402 // Simple 'show' function
3404 // Remember where we started, so that we can go back to it later
3405 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
3406 this.options.show = true;
3407 // Begin the animation
3408 // Make sure that we start at a small width/height to avoid any
3410 this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
3411 // Start by showing the element
3412 jQuery(this.elem).show();
3414 // Simple 'hide' function
3416 // Remember where we started, so that we can go back to it later
3417 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
3418 this.options.hide = true;
3419 // Begin the animation
3420 this.custom(this.cur(), 0);
3422 // Each step of an animation
3423 step: function(gotoEnd){
3425 if ( gotoEnd || t >= this.options.duration + this.startTime ) {
3426 this.now = this.end;
3427 this.pos = this.state = 1;
3429 this.options.curAnim[ this.prop ] = true;
3431 for ( var i in this.options.curAnim )
3432 if ( this.options.curAnim[i] !== true )
3435 if ( this.options.display != null ) {
3436 // Reset the overflow
3437 this.elem.style.overflow = this.options.overflow;
3438 // Reset the display
3439 this.elem.style.display = this.options.display;
3440 if ( jQuery.css(this.elem, "display") == "none" )
3441 this.elem.style.display = "block";
3443 // Hide the element if the "hide" operation was done
3444 if ( this.options.hide )
3445 jQuery(this.elem).hide();
3446 // Reset the properties, if the item has been hidden or shown
3447 if ( this.options.hide || this.options.show )
3448 for ( var p in this.options.curAnim )
3449 jQuery.attr(this.elem.style, p, this.options.orig[p]);
3451 // Execute the complete function
3452 this.options.complete.call( this.elem );
3456 var n = t - this.startTime;
3457 this.state = n / this.options.duration;
3458 // Perform the easing function, defaults to swing
3459 this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
3460 this.now = this.start + ((this.end - this.start) * this.pos);
3461 // Perform the next step of the animation
3467 jQuery.extend( jQuery.fx, {
3475 opacity: function(fx){
3476 jQuery.attr(fx.elem.style, "opacity", fx.now);
3478 _default: function(fx){
3479 if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
3480 fx.elem.style[ fx.prop ] = fx.now + fx.unit;
3482 fx.elem[ fx.prop ] = fx.now;
3486 if ( document.documentElement["getBoundingClientRect"] )
3487 jQuery.fn.offset = function() {
3488 if ( !this[0] ) return { top: 0, left: 0 };
3489 if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
3490 var box = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
3491 clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
3492 top = box.top + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop,
3493 left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
3494 return { top: top, left: left };
3497 jQuery.fn.offset = function() {
3498 if ( !this[0] ) return { top: 0, left: 0 };
3499 if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
3500 jQuery.offset.initialized || jQuery.offset.initialize();
3501 var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
3502 doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
3503 body = doc.body, defaultView = doc.defaultView,
3504 prevComputedStyle = defaultView.getComputedStyle(elem, null),
3505 top = elem.offsetTop, left = elem.offsetLeft;
3506 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
3507 computedStyle = defaultView.getComputedStyle(elem, null);
3508 top -= elem.scrollTop, left -= elem.scrollLeft;
3509 if ( elem === offsetParent ) {
3510 top += elem.offsetTop, left += elem.offsetLeft;
3511 if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
3512 top += parseInt( computedStyle.borderTopWidth, 10) || 0,
3513 left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
3514 prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
3516 if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
3517 top += parseInt( computedStyle.borderTopWidth, 10) || 0,
3518 left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
3519 prevComputedStyle = computedStyle;
3521 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
3522 top += body.offsetTop,
3523 left += body.offsetLeft;
3524 if ( prevComputedStyle.position === "fixed" )
3525 top += Math.max(docElem.scrollTop, body.scrollTop),
3526 left += Math.max(docElem.scrollLeft, body.scrollLeft);
3527 return { top: top, left: left };
3530 initialize: function() {
3531 if ( this.initialized ) return;
3532 var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
3533 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>';
3534 rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
3535 for ( prop in rules ) container.style[prop] = rules[prop];
3536 container.innerHTML = html;
3537 body.insertBefore(container, body.firstChild);
3538 innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
3539 this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
3540 this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
3541 innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
3542 this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
3543 body.style.marginTop = '1px';
3544 this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
3545 body.style.marginTop = bodyMarginTop;
3546 body.removeChild(container);
3547 this.initialized = true;
3549 bodyOffset: function(body) {
3550 jQuery.offset.initialized || jQuery.offset.initialize();
3551 var top = body.offsetTop, left = body.offsetLeft;
3552 if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
3553 top += parseInt( jQuery.curCSS(body, 'marginTop', true), 10 ) || 0,
3554 left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
3555 return { top: top, left: left };
3560 position: function() {
3561 var left = 0, top = 0, results;
3563 // Get *real* offsetParent
3564 var offsetParent = this.offsetParent(),
3565 // Get correct offsets
3566 offset = this.offset(),
3567 parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
3568 // Subtract element margins
3569 // note: when an element has margin: auto the offsetLeft and marginLeft
3570 // are the same in Safari causing offset.left to incorrectly be 0
3571 offset.top -= num( this, 'marginTop' );
3572 offset.left -= num( this, 'marginLeft' );
3573 // Add offsetParent borders
3574 parentOffset.top += num( offsetParent, 'borderTopWidth' );
3575 parentOffset.left += num( offsetParent, 'borderLeftWidth' );
3576 // Subtract the two offsets
3578 top: offset.top - parentOffset.top,
3579 left: offset.left - parentOffset.left
3584 offsetParent: function() {
3585 var offsetParent = this[0].offsetParent || document.body;
3586 while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
3587 offsetParent = offsetParent.offsetParent;
3588 return jQuery(offsetParent);
3592 // Create scrollLeft and scrollTop methods
3593 jQuery.each( ['Left', 'Top'], function(i, name) {
3594 var method = 'scroll' + name;
3596 jQuery.fn[ method ] = function(val) {
3597 if (!this[0]) return null;
3598 return val !== undefined ?
3599 // Set the scroll offset
3600 this.each(function() {
3601 this == window || this == document ?
3603 !i ? val : jQuery(window).scrollLeft(),
3604 i ? val : jQuery(window).scrollTop()
3606 this[ method ] = val;
3608 // Return the scroll offset
3609 this[0] == window || this[0] == document ?
3610 self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
3611 jQuery.boxModel && document.documentElement[ method ] ||
3612 document.body[ method ] :
3616 // Create innerHeight, innerWidth, outerHeight and outerWidth methods
3617 jQuery.each([ "Height", "Width" ], function(i, name){
3618 var tl = i ? "Left" : "Top", // top or left
3619 br = i ? "Right" : "Bottom", // bottom or right
3620 lower = name.toLowerCase();
3621 // innerHeight and innerWidth
3622 jQuery.fn["inner" + name] = function(){
3624 jQuery.css( this[0], lower, false, "padding" ) :
3627 // outerHeight and outerWidth
3628 jQuery.fn["outer" + name] = function(margin) {
3630 jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
3634 var type = name.toLowerCase();
3635 jQuery.fn[ type ] = function( size ) {
3636 // Get window width or height
3637 return this[0] == window ?
3638 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
3639 document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
3640 document.body[ "client" + name ] :
3641 // Get document width or height
3642 this[0] == document ?
3643 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
3645 document.documentElement["client" + name],
3646 document.body["scroll" + name], document.documentElement["scroll" + name],
3647 document.body["offset" + name], document.documentElement["offset" + name]
3649 // Get or set width or height on the element
3650 size === undefined ?
3651 // Get width or height on the element
3652 (this.length ? jQuery.css( this[0], type ) : null) :
3653 // Set the width or height on the element (default to pixels if value is unitless)
3654 this.css( type, typeof size === "string" ? size : size + "px" );