(no commit message)
[euphorik.git] / js / jquery.js
1 (function(){
2 /*
3 * jQuery 1.2.7pre - New Wave Javascript
4 *
5 * Copyright (c) 2008 John Resig (jquery.com)
6 * Dual licensed under the MIT (MIT-LICENSE.txt)
7 * and GPL (GPL-LICENSE.txt) licenses.
8 *
9 * $Date: 2008-06-30 12:17:44 -0400 (Mon, 30 Jun 2008) $
10 * $Rev: 5754 $
11 */
12
13 // Map over jQuery in case of overwrite
14 var _jQuery = window.jQuery,
15 // Map over the $ in case of overwrite
16 _$ = window.$;
17
18 var jQuery = window.jQuery = window.$ = function( selector, context ) {
19 // The jQuery object is actually just the init constructor 'enhanced'
20 return new jQuery.fn.init( selector, context );
21 };
22
23 // A simple way to check for HTML strings or ID strings
24 // (both of which we optimize for)
25 var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
26
27 // Is it a simple selector
28 isSimple = /^.[^:#\[\.]*$/,
29
30 // Will speed up references to undefined, and allows munging its name.
31 undefined;
32
33 jQuery.fn = jQuery.prototype = {
34 init: function( selector, context ) {
35 // Make sure that a selection was provided
36 selector = selector || document;
37
38 // Handle $(DOMElement)
39 if ( selector.nodeType ) {
40 this[0] = selector;
41 this.length = 1;
42 return this;
43 }
44 // Handle HTML strings
45 if ( typeof selector == "string" ) {
46 // Are we dealing with HTML string or an ID?
47 var match = quickExpr.exec( selector );
48
49 // Verify a match, and that no context was specified for #id
50 if ( match && (match[1] || !context) ) {
51
52 // HANDLE: $(html) -> $(array)
53 if ( match[1] )
54 selector = jQuery.clean( [ match[1] ], context );
55
56 // HANDLE: $("#id")
57 else {
58 var elem = document.getElementById( match[3] );
59
60 // Make sure an element was located
61 if ( elem ){
62 // Handle the case where IE and Opera return items
63 // by name instead of ID
64 if ( elem.id != match[3] )
65 return jQuery().find( selector );
66
67 // Otherwise, we inject the element directly into the jQuery object
68 return jQuery( elem );
69 }
70 selector = [];
71 }
72
73 // HANDLE: $(expr, [context])
74 // (which is just equivalent to: $(content).find(expr)
75 } else
76 return jQuery( context ).find( selector );
77
78 // HANDLE: $(function)
79 // Shortcut for document ready
80 } else if ( jQuery.isFunction( selector ) )
81 return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
82
83 return this.setArray(jQuery.makeArray(selector));
84 },
85
86 // The current version of jQuery being used
87 jquery: "1.2.7pre",
88
89 // The number of elements contained in the matched element set
90 size: function() {
91 return this.length;
92 },
93
94 // The number of elements contained in the matched element set
95 length: 0,
96
97 // Get the Nth element in the matched element set OR
98 // Get the whole matched element set as a clean array
99 get: function( num ) {
100 return num == undefined ?
101
102 // Return a 'clean' array
103 jQuery.makeArray( this ) :
104
105 // Return just the object
106 this[ num ];
107 },
108
109 // Take an array of elements and push it onto the stack
110 // (returning the new matched element set)
111 pushStack: function( elems ) {
112 // Build a new jQuery matched element set
113 var ret = jQuery( elems );
114
115 // Add the old object onto the stack (as a reference)
116 ret.prevObject = this;
117
118 // Return the newly-formed element set
119 return ret;
120 },
121
122 // Force the current matched set of elements to become
123 // the specified array of elements (destroying the stack in the process)
124 // You should use pushStack() in order to do this, but maintain the stack
125 setArray: function( elems ) {
126 // Resetting the length to 0, then using the native Array push
127 // is a super-fast way to populate an object with array-like properties
128 this.length = 0;
129 Array.prototype.push.apply( this, elems );
130
131 return this;
132 },
133
134 // Execute a callback for every element in the matched set.
135 // (You can seed the arguments with an array of args, but this is
136 // only used internally.)
137 each: function( callback, args ) {
138 return jQuery.each( this, callback, args );
139 },
140
141 // Determine the position of an element within
142 // the matched set of elements
143 index: function( elem ) {
144 var ret = -1;
145
146 // Locate the position of the desired element
147 return jQuery.inArray(
148 // If it receives a jQuery object, the first element is used
149 elem && elem.jquery ? elem[0] : elem
150 , this );
151 },
152
153 attr: function( name, value, type ) {
154 var options = name;
155
156 // Look for the case where we're accessing a style value
157 if ( name.constructor == String )
158 if ( value === undefined )
159 return this[0] && jQuery[ type || "attr" ]( this[0], name );
160
161 else {
162 options = {};
163 options[ name ] = value;
164 }
165
166 // Check to see if we're setting style values
167 return this.each(function(i){
168 // Set all the styles
169 for ( name in options )
170 jQuery.attr(
171 type ?
172 this.style :
173 this,
174 name, jQuery.prop( this, options[ name ], type, i, name )
175 );
176 });
177 },
178
179 css: function( key, value ) {
180 // ignore negative width and height values
181 if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
182 value = undefined;
183 return this.attr( key, value, "curCSS" );
184 },
185
186 text: function( text ) {
187 if ( typeof text != "object" && text != null )
188 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
189
190 var ret = "";
191
192 jQuery.each( text || this, function(){
193 jQuery.each( this.childNodes, function(){
194 if ( this.nodeType != 8 )
195 ret += this.nodeType != 1 ?
196 this.nodeValue :
197 jQuery.fn.text( [ this ] );
198 });
199 });
200
201 return ret;
202 },
203
204 wrapAll: function( html ) {
205 if ( this[0] )
206 // The elements to wrap the target around
207 jQuery( html, this[0].ownerDocument )
208 .clone()
209 .insertBefore( this[0] )
210 .map(function(){
211 var elem = this;
212
213 while ( elem.firstChild )
214 elem = elem.firstChild;
215
216 return elem;
217 })
218 .append(this);
219
220 return this;
221 },
222
223 wrapInner: function( html ) {
224 return this.each(function(){
225 jQuery( this ).contents().wrapAll( html );
226 });
227 },
228
229 wrap: function( html ) {
230 return this.each(function(){
231 jQuery( this ).wrapAll( html );
232 });
233 },
234
235 append: function() {
236 return this.domManip(arguments, true, false, function(elem){
237 if (this.nodeType == 1)
238 this.appendChild( elem );
239 });
240 },
241
242 prepend: function() {
243 return this.domManip(arguments, true, true, function(elem){
244 if (this.nodeType == 1)
245 this.insertBefore( elem, this.firstChild );
246 });
247 },
248
249 before: function() {
250 return this.domManip(arguments, false, false, function(elem){
251 this.parentNode.insertBefore( elem, this );
252 });
253 },
254
255 after: function() {
256 return this.domManip(arguments, false, true, function(elem){
257 this.parentNode.insertBefore( elem, this.nextSibling );
258 });
259 },
260
261 end: function() {
262 return this.prevObject || jQuery( [] );
263 },
264
265 find: function( selector ) {
266 var elems = jQuery.map(this, function(elem){
267 return jQuery.find( selector, elem );
268 });
269
270 return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
271 jQuery.unique( elems ) :
272 elems );
273 },
274
275 clone: function( events ) {
276 // Do the clone
277 var ret = this.map(function(){
278 if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
279 // IE copies events bound via attachEvent when
280 // using cloneNode. Calling detachEvent on the
281 // clone will also remove the events from the orignal
282 // In order to get around this, we use innerHTML.
283 // Unfortunately, this means some modifications to
284 // attributes in IE that are actually only stored
285 // as properties will not be copied (such as the
286 // the name attribute on an input).
287 var clone = this.cloneNode(true),
288 container = document.createElement("div");
289 container.appendChild(clone);
290 return jQuery.clean([container.innerHTML])[0];
291 } else
292 return this.cloneNode(true);
293 });
294
295 // Need to set the expando to null on the cloned set if it exists
296 // removeData doesn't work here, IE removes it from the original as well
297 // this is primarily for IE but the data expando shouldn't be copied over in any browser
298 var clone = ret.find("*").andSelf().each(function(){
299 if ( this[ expando ] != undefined )
300 this[ expando ] = null;
301 });
302
303 // Copy the events from the original to the clone
304 if ( events === true )
305 this.find("*").andSelf().each(function(i){
306 if (this.nodeType == 3)
307 return;
308 var events = jQuery.data( this, "events" );
309
310 for ( var type in events )
311 for ( var handler in events[ type ] )
312 jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
313 });
314
315 // Return the cloned set
316 return ret;
317 },
318
319 filter: function( selector ) {
320 return this.pushStack(
321 jQuery.isFunction( selector ) &&
322 jQuery.grep(this, function(elem, i){
323 return selector.call( elem, i );
324 }) ||
325
326 jQuery.multiFilter( selector, this ) );
327 },
328
329 not: function( selector ) {
330 if ( selector.constructor == String )
331 // test special case where just one selector is passed in
332 if ( isSimple.test( selector ) )
333 return this.pushStack( jQuery.multiFilter( selector, this, true ) );
334 else
335 selector = jQuery.multiFilter( selector, this );
336
337 var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
338 return this.filter(function() {
339 return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
340 });
341 },
342
343 add: function( selector ) {
344 return this.pushStack( jQuery.unique( jQuery.merge(
345 this.get(),
346 typeof selector == 'string' ?
347 jQuery( selector ) :
348 jQuery.makeArray( selector )
349 )));
350 },
351
352 is: function( selector ) {
353 return !!selector && jQuery.multiFilter( selector, this ).length > 0;
354 },
355
356 hasClass: function( selector ) {
357 return this.is( "." + selector );
358 },
359
360 val: function( value ) {
361 if ( value == undefined ) {
362
363 if ( this.length ) {
364 var elem = this[0];
365
366 // We need to handle select boxes special
367 if ( jQuery.nodeName( elem, "select" ) ) {
368 var index = elem.selectedIndex,
369 values = [],
370 options = elem.options,
371 one = elem.type == "select-one";
372
373 // Nothing was selected
374 if ( index < 0 )
375 return null;
376
377 // Loop through all the selected options
378 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
379 var option = options[ i ];
380
381 if ( option.selected ) {
382 // Get the specifc value for the option
383 value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
384
385 // We don't need an array for one selects
386 if ( one )
387 return value;
388
389 // Multi-Selects return an array
390 values.push( value );
391 }
392 }
393
394 return values;
395
396 // Everything else, we just grab the value
397 } else
398 return (this[0].value || "").replace(/\r/g, "");
399
400 }
401
402 return undefined;
403 }
404
405 if( value.constructor == Number )
406 value += '';
407
408 return this.each(function(){
409 if ( this.nodeType != 1 )
410 return;
411
412 if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
413 this.checked = (jQuery.inArray(this.value, value) >= 0 ||
414 jQuery.inArray(this.name, value) >= 0);
415
416 else if ( jQuery.nodeName( this, "select" ) ) {
417 var values = jQuery.makeArray(value);
418
419 jQuery( "option", this ).each(function(){
420 this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
421 jQuery.inArray( this.text, values ) >= 0);
422 });
423
424 if ( !values.length )
425 this.selectedIndex = -1;
426
427 } else
428 this.value = value;
429 });
430 },
431
432 html: function( value ) {
433 return value == undefined ?
434 (this[0] ?
435 this[0].innerHTML :
436 null) :
437 this.empty().append( value );
438 },
439
440 replaceWith: function( value ) {
441 return this.after( value ).remove();
442 },
443
444 eq: function( i ) {
445 return this.slice( i, +i + 1 );
446 },
447
448 slice: function() {
449 return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
450 },
451
452 map: function( callback ) {
453 return this.pushStack( jQuery.map(this, function(elem, i){
454 return callback.call( elem, i, elem );
455 }));
456 },
457
458 andSelf: function() {
459 return this.add( this.prevObject );
460 },
461
462 data: function( key, value ){
463 var parts = key.split(".");
464 parts[1] = parts[1] ? "." + parts[1] : "";
465
466 if ( value === undefined ) {
467 var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
468
469 if ( data === undefined && this.length )
470 data = jQuery.data( this[0], key );
471
472 return data === undefined && parts[1] ?
473 this.data( parts[0] ) :
474 data;
475 } else
476 return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
477 jQuery.data( this, key, value );
478 });
479 },
480
481 removeData: function( key ){
482 return this.each(function(){
483 jQuery.removeData( this, key );
484 });
485 },
486
487 domManip: function( args, table, reverse, callback ) {
488 var clone = this.length > 1, elems;
489
490 return this.each(function(){
491 if ( !elems ) {
492 elems = jQuery.clean( args, this.ownerDocument );
493
494 if ( reverse )
495 elems.reverse();
496 }
497
498 var obj = this;
499
500 if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
501 obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
502
503 var scripts = jQuery( [] );
504
505 jQuery.each(elems, function(){
506 var elem = clone ?
507 jQuery( this ).clone( true )[0] :
508 this;
509
510 // execute all scripts after the elements have been injected
511 if ( jQuery.nodeName( elem, "script" ) )
512 scripts = scripts.add( elem );
513 else {
514 // Remove any inner scripts for later evaluation
515 if ( elem.nodeType == 1 )
516 scripts = scripts.add( jQuery( "script", elem ).remove() );
517
518 // Inject the elements into the document
519 callback.call( obj, elem );
520 }
521 });
522
523 scripts.each( evalScript );
524 });
525 }
526 };
527
528 // Give the init function the jQuery prototype for later instantiation
529 jQuery.fn.init.prototype = jQuery.fn;
530
531 function evalScript( i, elem ) {
532 if ( elem.src )
533 jQuery.ajax({
534 url: elem.src,
535 async: false,
536 dataType: "script"
537 });
538
539 else
540 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
541
542 if ( elem.parentNode )
543 elem.parentNode.removeChild( elem );
544 }
545
546 function now(){
547 return +new Date;
548 }
549
550 jQuery.extend = jQuery.fn.extend = function() {
551 // copy reference to target object
552 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
553
554 // Handle a deep copy situation
555 if ( target.constructor == Boolean ) {
556 deep = target;
557 target = arguments[1] || {};
558 // skip the boolean and the target
559 i = 2;
560 }
561
562 // Handle case when target is a string or something (possible in deep copy)
563 if ( typeof target != "object" && typeof target != "function" )
564 target = {};
565
566 // extend jQuery itself if only one argument is passed
567 if ( length == i ) {
568 target = this;
569 --i;
570 }
571
572 for ( ; i < length; i++ )
573 // Only deal with non-null/undefined values
574 if ( (options = arguments[ i ]) != null )
575 // Extend the base object
576 for ( var name in options ) {
577 var src = target[ name ], copy = options[ name ];
578
579 // Prevent never-ending loop
580 if ( target === copy )
581 continue;
582
583 // Recurse if we're merging object values
584 if ( deep && copy && typeof copy == "object" && !copy.nodeType )
585 target[ name ] = jQuery.extend( deep,
586 // Never move original objects, clone them
587 src || ( copy.length != null ? [ ] : { } )
588 , copy );
589
590 // Don't bring in undefined values
591 else if ( copy !== undefined )
592 target[ name ] = copy;
593
594 }
595
596 // Return the modified object
597 return target;
598 };
599
600 var expando = "jQuery" + now(), uuid = 0, windowData = {},
601 // exclude the following css properties to add px
602 exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
603 // cache defaultView
604 defaultView = document.defaultView || {};
605
606 jQuery.extend({
607 noConflict: function( deep ) {
608 window.$ = _$;
609
610 if ( deep )
611 window.jQuery = _jQuery;
612
613 return jQuery;
614 },
615
616 // See test/unit/core.js for details concerning this function.
617 isFunction: function( fn ) {
618 return !!fn && typeof fn != "string" && !fn.nodeName &&
619 fn.constructor != Array && /^[\s[]?function/.test( fn + "" );
620 },
621
622 // check if an element is in a (or is an) XML document
623 isXMLDoc: function( elem ) {
624 return elem.documentElement && !elem.body ||
625 elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
626 },
627
628 // Evalulates a script in a global context
629 globalEval: function( data ) {
630 data = jQuery.trim( data );
631
632 if ( data ) {
633 // Inspired by code by Andrea Giammarchi
634 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
635 var head = document.getElementsByTagName("head")[0] || document.documentElement,
636 script = document.createElement("script");
637
638 script.type = "text/javascript";
639 if ( jQuery.browser.msie )
640 script.text = data;
641 else
642 script.appendChild( document.createTextNode( data ) );
643
644 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
645 // This arises when a base node is used (#2709).
646 head.insertBefore( script, head.firstChild );
647 head.removeChild( script );
648 }
649 },
650
651 nodeName: function( elem, name ) {
652 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
653 },
654
655 cache: {},
656
657 data: function( elem, name, data ) {
658 elem = elem == window ?
659 windowData :
660 elem;
661
662 var id = elem[ expando ];
663
664 // Compute a unique ID for the element
665 if ( !id )
666 id = elem[ expando ] = ++uuid;
667
668 // Only generate the data cache if we're
669 // trying to access or manipulate it
670 if ( name && !jQuery.cache[ id ] )
671 jQuery.cache[ id ] = {};
672
673 // Prevent overriding the named cache with undefined values
674 if ( data !== undefined )
675 jQuery.cache[ id ][ name ] = data;
676
677 // Return the named cache data, or the ID for the element
678 return name ?
679 jQuery.cache[ id ][ name ] :
680 id;
681 },
682
683 removeData: function( elem, name ) {
684 elem = elem == window ?
685 windowData :
686 elem;
687
688 var id = elem[ expando ];
689
690 // If we want to remove a specific section of the element's data
691 if ( name ) {
692 if ( jQuery.cache[ id ] ) {
693 // Remove the section of cache data
694 delete jQuery.cache[ id ][ name ];
695
696 // If we've removed all the data, remove the element's cache
697 name = "";
698
699 for ( name in jQuery.cache[ id ] )
700 break;
701
702 if ( !name )
703 jQuery.removeData( elem );
704 }
705
706 // Otherwise, we want to remove all of the element's data
707 } else {
708 // Clean up the element expando
709 try {
710 delete elem[ expando ];
711 } catch(e){
712 // IE has trouble directly removing the expando
713 // but it's ok with using removeAttribute
714 if ( elem.removeAttribute )
715 elem.removeAttribute( expando );
716 }
717
718 // Completely remove the data cache
719 delete jQuery.cache[ id ];
720 }
721 },
722
723 // args is for internal usage only
724 each: function( object, callback, args ) {
725 var name, i = 0, length = object.length;
726
727 if ( args ) {
728 if ( length == undefined ) {
729 for ( name in object )
730 if ( callback.apply( object[ name ], args ) === false )
731 break;
732 } else
733 for ( ; i < length; )
734 if ( callback.apply( object[ i++ ], args ) === false )
735 break;
736
737 // A special, fast, case for the most common use of each
738 } else {
739 if ( length == undefined ) {
740 for ( name in object )
741 if ( callback.call( object[ name ], name, object[ name ] ) === false )
742 break;
743 } else
744 for ( var value = object[0];
745 i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
746 }
747
748 return object;
749 },
750
751 prop: function( elem, value, type, i, name ) {
752 // Handle executable functions
753 if ( jQuery.isFunction( value ) )
754 value = value.call( elem, i );
755
756 // Handle passing in a number to a CSS property
757 return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
758 value + "px" :
759 value;
760 },
761
762 className: {
763 // internal only, use addClass("class")
764 add: function( elem, classNames ) {
765 jQuery.each((classNames || "").split(/\s+/), function(i, className){
766 if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
767 elem.className += (elem.className ? " " : "") + className;
768 });
769 },
770
771 // internal only, use removeClass("class")
772 remove: function( elem, classNames ) {
773 if (elem.nodeType == 1)
774 elem.className = classNames != undefined ?
775 jQuery.grep(elem.className.split(/\s+/), function(className){
776 return !jQuery.className.has( classNames, className );
777 }).join(" ") :
778 "";
779 },
780
781 // internal only, use hasClass("class")
782 has: function( elem, className ) {
783 return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
784 }
785 },
786
787 // A method for quickly swapping in/out CSS properties to get correct calculations
788 swap: function( elem, options, callback ) {
789 var old = {};
790 // Remember the old values, and insert the new ones
791 for ( var name in options ) {
792 old[ name ] = elem.style[ name ];
793 elem.style[ name ] = options[ name ];
794 }
795
796 callback.call( elem );
797
798 // Revert the old values
799 for ( var name in options )
800 elem.style[ name ] = old[ name ];
801 },
802
803 css: function( elem, name, force ) {
804 if ( name == "width" || name == "height" ) {
805 var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
806
807 function getWH() {
808 val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
809 var padding = 0, border = 0;
810 jQuery.each( which, function() {
811 padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
812 border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
813 });
814 val -= Math.round(padding + border);
815 }
816
817 if ( jQuery(elem).is(":visible") )
818 getWH();
819 else
820 jQuery.swap( elem, props, getWH );
821
822 return Math.max(0, val);
823 }
824
825 return jQuery.curCSS( elem, name, force );
826 },
827
828 curCSS: function( elem, name, force ) {
829 var ret, style = elem.style;
830
831 // A helper method for determining if an element's values are broken
832 function color( elem ) {
833 if ( !jQuery.browser.safari )
834 return false;
835
836 // defaultView is cached
837 var ret = defaultView.getComputedStyle( elem, null );
838 return !ret || ret.getPropertyValue("color") == "";
839 }
840
841 // We need to handle opacity special in IE
842 if ( name == "opacity" && jQuery.browser.msie ) {
843 ret = jQuery.attr( style, "opacity" );
844
845 return ret == "" ?
846 "1" :
847 ret;
848 }
849 // Opera sometimes will give the wrong display answer, this fixes it, see #2037
850 if ( jQuery.browser.opera && name == "display" ) {
851 var save = style.outline;
852 style.outline = "0 solid black";
853 style.outline = save;
854 }
855
856 // Make sure we're using the right name for getting the float value
857 if ( name.match( /float/i ) )
858 name = styleFloat;
859
860 if ( !force && style && style[ name ] )
861 ret = style[ name ];
862
863 else if ( defaultView.getComputedStyle ) {
864
865 // Only "float" is needed here
866 if ( name.match( /float/i ) )
867 name = "float";
868
869 name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
870
871 var computedStyle = defaultView.getComputedStyle( elem, null );
872
873 if ( computedStyle && !color( elem ) )
874 ret = computedStyle.getPropertyValue( name );
875
876 // If the element isn't reporting its values properly in Safari
877 // then some display: none elements are involved
878 else {
879 var swap = [], stack = [], a = elem, i = 0;
880
881 // Locate all of the parent display: none elements
882 for ( ; a && color(a); a = a.parentNode )
883 stack.unshift(a);
884
885 // Go through and make them visible, but in reverse
886 // (It would be better if we knew the exact display type that they had)
887 for ( ; i < stack.length; i++ )
888 if ( color( stack[ i ] ) ) {
889 swap[ i ] = stack[ i ].style.display;
890 stack[ i ].style.display = "block";
891 }
892
893 // Since we flip the display style, we have to handle that
894 // one special, otherwise get the value
895 ret = name == "display" && swap[ stack.length - 1 ] != null ?
896 "none" :
897 ( computedStyle && computedStyle.getPropertyValue( name ) ) || "";
898
899 // Finally, revert the display styles back
900 for ( i = 0; i < swap.length; i++ )
901 if ( swap[ i ] != null )
902 stack[ i ].style.display = swap[ i ];
903 }
904
905 // We should always get a number back from opacity
906 if ( name == "opacity" && ret == "" )
907 ret = "1";
908
909 } else if ( elem.currentStyle ) {
910 var camelCase = name.replace(/\-(\w)/g, function(all, letter){
911 return letter.toUpperCase();
912 });
913
914 ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
915
916 // From the awesome hack by Dean Edwards
917 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
918
919 // If we're not dealing with a regular pixel number
920 // but a number that has a weird ending, we need to convert it to pixels
921 if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
922 // Remember the original values
923 var left = style.left, rsLeft = elem.runtimeStyle.left;
924
925 // Put in the new values to get a computed value out
926 elem.runtimeStyle.left = elem.currentStyle.left;
927 style.left = ret || 0;
928 ret = style.pixelLeft + "px";
929
930 // Revert the changed values
931 style.left = left;
932 elem.runtimeStyle.left = rsLeft;
933 }
934 }
935
936 return ret;
937 },
938
939 clean: function( elems, context ) {
940 var ret = [];
941 context = context || document;
942 // !context.createElement fails in IE with an error but returns typeof 'object'
943 if (typeof context.createElement == 'undefined')
944 context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
945
946 jQuery.each(elems, function(i, elem){
947 if ( typeof elem == 'number' )
948 elem += '';
949
950 if ( !elem )
951 return;
952
953 // Convert html string into DOM nodes
954 if ( typeof elem == "string" ) {
955 // Fix "XHTML"-style tags in all browsers
956 elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
957 return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
958 all :
959 front + "></" + tag + ">";
960 });
961
962 // Trim whitespace, otherwise indexOf won't work as expected
963 var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
964
965 var wrap =
966 // option or optgroup
967 !tags.indexOf("<opt") &&
968 [ 1, "<select multiple='multiple'>", "</select>" ] ||
969
970 !tags.indexOf("<leg") &&
971 [ 1, "<fieldset>", "</fieldset>" ] ||
972
973 tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
974 [ 1, "<table>", "</table>" ] ||
975
976 !tags.indexOf("<tr") &&
977 [ 2, "<table><tbody>", "</tbody></table>" ] ||
978
979 // <thead> matched above
980 (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
981 [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
982
983 !tags.indexOf("<col") &&
984 [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
985
986 // IE can't serialize <link> and <script> tags normally
987 jQuery.browser.msie &&
988 [ 1, "div<div>", "</div>" ] ||
989
990 [ 0, "", "" ];
991
992 // Go to html and back, then peel off extra wrappers
993 div.innerHTML = wrap[1] + elem + wrap[2];
994
995 // Move to the right depth
996 while ( wrap[0]-- )
997 div = div.lastChild;
998
999 // Remove IE's autoinserted <tbody> from table fragments
1000 if ( jQuery.browser.msie ) {
1001
1002 // String was a <table>, *may* have spurious <tbody>
1003 var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
1004 div.firstChild && div.firstChild.childNodes :
1005
1006 // String was a bare <thead> or <tfoot>
1007 wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
1008 div.childNodes :
1009 [];
1010
1011 for ( var j = tbody.length - 1; j >= 0 ; --j )
1012 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
1013 tbody[ j ].parentNode.removeChild( tbody[ j ] );
1014
1015 // IE completely kills leading whitespace when innerHTML is used
1016 if ( /^\s/.test( elem ) )
1017 div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
1018
1019 }
1020
1021 elem = jQuery.makeArray( div.childNodes );
1022 }
1023
1024 if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
1025 return;
1026
1027 if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
1028 ret.push( elem );
1029
1030 else
1031 ret = jQuery.merge( ret, elem );
1032
1033 });
1034
1035 return ret;
1036 },
1037
1038 attr: function( elem, name, value ) {
1039 // don't set attributes on text and comment nodes
1040 if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
1041 return undefined;
1042
1043 var notxml = !jQuery.isXMLDoc( elem ),
1044 // Whether we are setting (or getting)
1045 set = value !== undefined,
1046 msie = jQuery.browser.msie;
1047
1048 // Try to normalize/fix the name
1049 name = notxml && jQuery.props[ name ] || name;
1050
1051 // Only do all the following if this is a node (faster for style)
1052 // IE elem.getAttribute passes even for style
1053 if ( elem.tagName ) {
1054
1055 // These attributes require special treatment
1056 var special = /href|src|style/.test( name );
1057
1058 // Safari mis-reports the default selected property of a hidden option
1059 // Accessing the parent's selectedIndex property fixes it
1060 if ( name == "selected" && jQuery.browser.safari )
1061 elem.parentNode.selectedIndex;
1062
1063 // If applicable, access the attribute via the DOM 0 way
1064 if ( name in elem && notxml && !special ) {
1065 if ( set ){
1066 // We can't allow the type property to be changed (since it causes problems in IE)
1067 if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
1068 throw "type property can't be changed";
1069
1070 elem[ name ] = value;
1071 }
1072
1073 // browsers index elements by id/name on forms, give priority to attributes.
1074 if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
1075 return elem.getAttributeNode( name ).nodeValue;
1076
1077 return elem[ name ];
1078 }
1079
1080 if ( msie && notxml && name == "style" )
1081 return jQuery.attr( elem.style, "cssText", value );
1082
1083 if ( set )
1084 // convert the value to a string (all browsers do this but IE) see #1070
1085 elem.setAttribute( name, "" + value );
1086
1087 var attr = msie && notxml && special
1088 // Some attributes require a special call on IE
1089 ? elem.getAttribute( name, 2 )
1090 : elem.getAttribute( name );
1091
1092 // Non-existent attributes return null, we normalize to undefined
1093 return attr === null ? undefined : attr;
1094 }
1095
1096 // elem is actually elem.style ... set the style
1097
1098 // IE uses filters for opacity
1099 if ( msie && name == "opacity" ) {
1100 if ( set ) {
1101 // IE has trouble with opacity if it does not have layout
1102 // Force it by setting the zoom level
1103 elem.zoom = 1;
1104
1105 // Set the alpha filter to set the opacity
1106 elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
1107 (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
1108 }
1109
1110 return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
1111 (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
1112 "";
1113 }
1114
1115 name = name.replace(/-([a-z])/ig, function(all, letter){
1116 return letter.toUpperCase();
1117 });
1118
1119 if ( set )
1120 elem[ name ] = value;
1121
1122 return elem[ name ];
1123 },
1124
1125 trim: function( text ) {
1126 return (text || "").replace( /^\s+|\s+$/g, "" );
1127 },
1128
1129 makeArray: function( array ) {
1130 var ret = [];
1131
1132 if( array != null ){
1133 var i = array.length;
1134 //the window, strings and functions also have 'length'
1135 if( i == null || array.split || array.setInterval || array.call )
1136 ret[0] = array;
1137 else
1138 while( i )
1139 ret[--i] = array[i];
1140 }
1141
1142 return ret;
1143 },
1144
1145 inArray: function( elem, array ) {
1146 for ( var i = 0, length = array.length; i < length; i++ )
1147 // Use === because on IE, window == document
1148 if ( array[ i ] === elem )
1149 return i;
1150
1151 return -1;
1152 },
1153
1154 merge: function( first, second ) {
1155 // We have to loop this way because IE & Opera overwrite the length
1156 // expando of getElementsByTagName
1157 var i = 0, elem, pos = first.length;
1158 // Also, we need to make sure that the correct elements are being returned
1159 // (IE returns comment nodes in a '*' query)
1160 if ( jQuery.browser.msie ) {
1161 while ( elem = second[ i++ ] )
1162 if ( elem.nodeType != 8 )
1163 first[ pos++ ] = elem;
1164
1165 } else
1166 while ( elem = second[ i++ ] )
1167 first[ pos++ ] = elem;
1168
1169 return first;
1170 },
1171
1172 unique: function( array ) {
1173 var ret = [], done = {};
1174
1175 try {
1176
1177 for ( var i = 0, length = array.length; i < length; i++ ) {
1178 var id = jQuery.data( array[ i ] );
1179
1180 if ( !done[ id ] ) {
1181 done[ id ] = true;
1182 ret.push( array[ i ] );
1183 }
1184 }
1185
1186 } catch( e ) {
1187 ret = array;
1188 }
1189
1190 return ret;
1191 },
1192
1193 grep: function( elems, callback, inv ) {
1194 var ret = [];
1195
1196 // Go through the array, only saving the items
1197 // that pass the validator function
1198 for ( var i = 0, length = elems.length; i < length; i++ )
1199 if ( !inv != !callback( elems[ i ], i ) )
1200 ret.push( elems[ i ] );
1201
1202 return ret;
1203 },
1204
1205 map: function( elems, callback ) {
1206 var ret = [];
1207
1208 // Go through the array, translating each of the items to their
1209 // new value (or values).
1210 for ( var i = 0, length = elems.length; i < length; i++ ) {
1211 var value = callback( elems[ i ], i );
1212
1213 if ( value != null )
1214 ret[ ret.length ] = value;
1215 }
1216
1217 return ret.concat.apply( [], ret );
1218 }
1219 });
1220
1221 var userAgent = navigator.userAgent.toLowerCase();
1222
1223 // Figure out what browser is being used
1224 jQuery.browser = {
1225 version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
1226 safari: /webkit/.test( userAgent ),
1227 opera: /opera/.test( userAgent ),
1228 msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
1229 mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
1230 };
1231
1232 var styleFloat = jQuery.browser.msie ?
1233 "styleFloat" :
1234 "cssFloat";
1235
1236 jQuery.extend({
1237 // Check to see if the W3C box model is being used
1238 boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
1239
1240 props: {
1241 "for": "htmlFor",
1242 "class": "className",
1243 "float": styleFloat,
1244 cssFloat: styleFloat,
1245 styleFloat: styleFloat,
1246 readonly: "readOnly",
1247 maxlength: "maxLength",
1248 cellspacing: "cellSpacing",
1249 rowspan: "rowSpan"
1250 }
1251 });
1252
1253 jQuery.each({
1254 parent: function(elem){return elem.parentNode;},
1255 parents: function(elem){return jQuery.dir(elem,"parentNode");},
1256 next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
1257 prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
1258 nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
1259 prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
1260 siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
1261 children: function(elem){return jQuery.sibling(elem.firstChild);},
1262 contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
1263 }, function(name, fn){
1264 jQuery.fn[ name ] = function( selector ) {
1265 var ret = jQuery.map( this, fn );
1266
1267 if ( selector && typeof selector == "string" )
1268 ret = jQuery.multiFilter( selector, ret );
1269
1270 return this.pushStack( jQuery.unique( ret ) );
1271 };
1272 });
1273
1274 jQuery.each({
1275 appendTo: "append",
1276 prependTo: "prepend",
1277 insertBefore: "before",
1278 insertAfter: "after",
1279 replaceAll: "replaceWith"
1280 }, function(name, original){
1281 jQuery.fn[ name ] = function() {
1282 var args = arguments;
1283
1284 return this.each(function(){
1285 for ( var i = 0, length = args.length; i < length; i++ )
1286 jQuery( args[ i ] )[ original ]( this );
1287 });
1288 };
1289 });
1290
1291 jQuery.each({
1292 removeAttr: function( name ) {
1293 jQuery.attr( this, name, "" );
1294 if (this.nodeType == 1)
1295 this.removeAttribute( name );
1296 },
1297
1298 addClass: function( classNames ) {
1299 jQuery.className.add( this, classNames );
1300 },
1301
1302 removeClass: function( classNames ) {
1303 jQuery.className.remove( this, classNames );
1304 },
1305
1306 toggleClass: function( classNames ) {
1307 jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
1308 },
1309
1310 remove: function( selector ) {
1311 if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
1312 // Prevent memory leaks
1313 jQuery( "*", this ).add(this).each(function(){
1314 jQuery.event.remove(this);
1315 jQuery.removeData(this);
1316 });
1317 if (this.parentNode)
1318 this.parentNode.removeChild( this );
1319 }
1320 },
1321
1322 empty: function() {
1323 // Remove element nodes and prevent memory leaks
1324 jQuery( ">*", this ).remove();
1325
1326 // Remove any remaining nodes
1327 while ( this.firstChild )
1328 this.removeChild( this.firstChild );
1329 }
1330 }, function(name, fn){
1331 jQuery.fn[ name ] = function(){
1332 return this.each( fn, arguments );
1333 };
1334 });
1335
1336 jQuery.each([ "Height", "Width" ], function(i, name){
1337 var type = name.toLowerCase();
1338
1339 jQuery.fn[ type ] = function( size ) {
1340 // Get window width or height
1341 return this[0] == window ?
1342 // Opera reports document.body.client[Width/Height] properly in both quirks and standards
1343 jQuery.browser.opera && document.body[ "client" + name ] ||
1344
1345 // Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
1346 jQuery.browser.safari && window[ "inner" + name ] ||
1347
1348 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
1349 document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
1350
1351 // Get document width or height
1352 this[0] == document ?
1353 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
1354 Math.max(
1355 Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]),
1356 Math.max(document.body["offset" + name], document.documentElement["offset" + name])
1357 ) :
1358
1359 // Get or set width or height on the element
1360 size == undefined ?
1361 // Get width or height on the element
1362 (this.length ? jQuery.css( this[0], type ) : null) :
1363
1364 // Set the width or height on the element (default to pixels if value is unitless)
1365 this.css( type, size.constructor == String ? size : size + "px" );
1366 };
1367 });
1368
1369 // Helper function used by the dimensions and offset modules
1370 function num(elem, prop) {
1371 return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
1372 }
1373 var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
1374 "(?:[\\w*_-]|\\\\.)" :
1375 "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
1376 quickChild = new RegExp("^>\\s*(" + chars + "+)"),
1377 quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
1378 quickClass = new RegExp("^([#.]?)(" + chars + "*)");
1379
1380 jQuery.extend({
1381 expr: {
1382 "": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
1383 "#": function(a,i,m){return a.getAttribute("id")==m[2];},
1384 ":": {
1385 // Position Checks
1386 lt: function(a,i,m){return i<m[3]-0;},
1387 gt: function(a,i,m){return i>m[3]-0;},
1388 nth: function(a,i,m){return m[3]-0==i;},
1389 eq: function(a,i,m){return m[3]-0==i;},
1390 first: function(a,i){return i==0;},
1391 last: function(a,i,m,r){return i==r.length-1;},
1392 even: function(a,i){return i%2==0;},
1393 odd: function(a,i){return i%2;},
1394
1395 // Child Checks
1396 "first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
1397 "last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
1398 "only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
1399
1400 // Parent Checks
1401 parent: function(a){return a.firstChild;},
1402 empty: function(a){return !a.firstChild;},
1403
1404 // Text Check
1405 contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
1406
1407 // Visibility
1408 visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
1409 hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
1410
1411 // Form attributes
1412 enabled: function(a){return !a.disabled;},
1413 disabled: function(a){return a.disabled;},
1414 checked: function(a){return a.checked;},
1415 selected: function(a){return a.selected||jQuery.attr(a,"selected");},
1416
1417 // Form elements
1418 text: function(a){return "text"==a.type;},
1419 radio: function(a){return "radio"==a.type;},
1420 checkbox: function(a){return "checkbox"==a.type;},
1421 file: function(a){return "file"==a.type;},
1422 password: function(a){return "password"==a.type;},
1423 submit: function(a){return "submit"==a.type;},
1424 image: function(a){return "image"==a.type;},
1425 reset: function(a){return "reset"==a.type;},
1426 button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
1427 input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
1428
1429 // :has()
1430 has: function(a,i,m){return jQuery.find(m[3],a).length;},
1431
1432 // :header
1433 header: function(a){return /h\d/i.test(a.nodeName);},
1434
1435 // :animated
1436 animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
1437 }
1438 },
1439
1440 // The regular expressions that power the parsing engine
1441 parse: [
1442 // Match: [@value='test'], [@foo]
1443 /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
1444
1445 // Match: :contains('foo')
1446 /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
1447
1448 // Match: :even, :last-child, #id, .class
1449 new RegExp("^([:.#]*)(" + chars + "+)")
1450 ],
1451
1452 multiFilter: function( expr, elems, not ) {
1453 var old, cur = [];
1454
1455 while ( expr && expr != old ) {
1456 old = expr;
1457 var f = jQuery.filter( expr, elems, not );
1458 expr = f.t.replace(/^\s*,\s*/, "" );
1459 cur = not ? elems = f.r : jQuery.merge( cur, f.r );
1460 }
1461
1462 return cur;
1463 },
1464
1465 find: function( t, context ) {
1466 // Quickly handle non-string expressions
1467 if ( typeof t != "string" )
1468 return [ t ];
1469
1470 // check to make sure context is a DOM element or a document
1471 if ( context && context.nodeType != 1 && context.nodeType != 9)
1472 return [ ];
1473
1474 // Set the correct context (if none is provided)
1475 context = context || document;
1476
1477 // Initialize the search
1478 var ret = [context], done = [], last, nodeName;
1479
1480 // Continue while a selector expression exists, and while
1481 // we're no longer looping upon ourselves
1482 while ( t && last != t ) {
1483 var r = [];
1484 last = t;
1485
1486 t = jQuery.trim(t);
1487
1488 var foundToken = false,
1489
1490 // An attempt at speeding up child selectors that
1491 // point to a specific element tag
1492 re = quickChild,
1493
1494 m = re.exec(t);
1495
1496 if ( m ) {
1497 nodeName = m[1].toUpperCase();
1498
1499 // Perform our own iteration and filter
1500 for ( var i = 0; ret[i]; i++ )
1501 for ( var c = ret[i].firstChild; c; c = c.nextSibling )
1502 if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
1503 r.push( c );
1504
1505 ret = r;
1506 t = t.replace( re, "" );
1507 if ( t.indexOf(" ") == 0 ) continue;
1508 foundToken = true;
1509 } else {
1510 re = /^([>+~])\s*(\w*)/i;
1511
1512 if ( (m = re.exec(t)) != null ) {
1513 r = [];
1514
1515 var merge = {};
1516 nodeName = m[2].toUpperCase();
1517 m = m[1];
1518
1519 for ( var j = 0, rl = ret.length; j < rl; j++ ) {
1520 var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
1521 for ( ; n; n = n.nextSibling )
1522 if ( n.nodeType == 1 ) {
1523 var id = jQuery.data(n);
1524
1525 if ( m == "~" && merge[id] ) break;
1526
1527 if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
1528 if ( m == "~" ) merge[id] = true;
1529 r.push( n );
1530 }
1531
1532 if ( m == "+" ) break;
1533 }
1534 }
1535
1536 ret = r;
1537
1538 // And remove the token
1539 t = jQuery.trim( t.replace( re, "" ) );
1540 foundToken = true;
1541 }
1542 }
1543
1544 // See if there's still an expression, and that we haven't already
1545 // matched a token
1546 if ( t && !foundToken ) {
1547 // Handle multiple expressions
1548 if ( !t.indexOf(",") ) {
1549 // Clean the result set
1550 if ( context == ret[0] ) ret.shift();
1551
1552 // Merge the result sets
1553 done = jQuery.merge( done, ret );
1554
1555 // Reset the context
1556 r = ret = [context];
1557
1558 // Touch up the selector string
1559 t = " " + t.substr(1,t.length);
1560
1561 } else {
1562 // Optimize for the case nodeName#idName
1563 var re2 = quickID;
1564 var m = re2.exec(t);
1565
1566 // Re-organize the results, so that they're consistent
1567 if ( m ) {
1568 m = [ 0, m[2], m[3], m[1] ];
1569
1570 } else {
1571 // Otherwise, do a traditional filter check for
1572 // ID, class, and element selectors
1573 re2 = quickClass;
1574 m = re2.exec(t);
1575 }
1576
1577 m[2] = m[2].replace(/\\/g, "");
1578
1579 var elem = ret[ret.length-1];
1580
1581 // Try to do a global search by ID, where we can
1582 if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
1583 // Optimization for HTML document case
1584 var oid = elem.getElementById(m[2]);
1585
1586 // Do a quick check for the existence of the actual ID attribute
1587 // to avoid selecting by the name attribute in IE
1588 // also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
1589 if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
1590 oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
1591
1592 // Do a quick check for node name (where applicable) so
1593 // that div#foo searches will be really fast
1594 ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
1595 } else {
1596 // We need to find all descendant elements
1597 for ( var i = 0; ret[i]; i++ ) {
1598 // Grab the tag name being searched for
1599 var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
1600
1601 // Handle IE7 being really dumb about <object>s
1602 if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
1603 tag = "param";
1604
1605 r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
1606 }
1607
1608 // It's faster to filter by class and be done with it
1609 if ( m[1] == "." )
1610 r = jQuery.classFilter( r, m[2] );
1611
1612 // Same with ID filtering
1613 if ( m[1] == "#" ) {
1614 var tmp = [];
1615
1616 // Try to find the element with the ID
1617 for ( var i = 0; r[i]; i++ )
1618 if ( r[i].getAttribute("id") == m[2] ) {
1619 tmp = [ r[i] ];
1620 break;
1621 }
1622
1623 r = tmp;
1624 }
1625
1626 ret = r;
1627 }
1628
1629 t = t.replace( re2, "" );
1630 }
1631
1632 }
1633
1634 // If a selector string still exists
1635 if ( t ) {
1636 // Attempt to filter it
1637 var val = jQuery.filter(t,r);
1638 ret = r = val.r;
1639 t = jQuery.trim(val.t);
1640 }
1641 }
1642
1643 // An error occurred with the selector;
1644 // just return an empty set instead
1645 if ( t )
1646 ret = [];
1647
1648 // Remove the root context
1649 if ( ret && context == ret[0] )
1650 ret.shift();
1651
1652 // And combine the results
1653 done = jQuery.merge( done, ret );
1654
1655 return done;
1656 },
1657
1658 classFilter: function(r,m,not){
1659 m = " " + m + " ";
1660 var tmp = [];
1661 for ( var i = 0; r[i]; i++ ) {
1662 var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
1663 if ( !not && pass || not && !pass )
1664 tmp.push( r[i] );
1665 }
1666 return tmp;
1667 },
1668
1669 filter: function(t,r,not) {
1670 var last;
1671
1672 // Look for common filter expressions
1673 while ( t && t != last ) {
1674 last = t;
1675
1676 var p = jQuery.parse, m;
1677
1678 for ( var i = 0; p[i]; i++ ) {
1679 m = p[i].exec( t );
1680
1681 if ( m ) {
1682 // Remove what we just matched
1683 t = t.substring( m[0].length );
1684
1685 m[2] = m[2].replace(/\\/g, "");
1686 break;
1687 }
1688 }
1689
1690 if ( !m )
1691 break;
1692
1693 // :not() is a special case that can be optimized by
1694 // keeping it out of the expression list
1695 if ( m[1] == ":" && m[2] == "not" )
1696 // optimize if only one selector found (most common case)
1697 r = isSimple.test( m[3] ) ?
1698 jQuery.filter(m[3], r, true).r :
1699 jQuery( r ).not( m[3] );
1700
1701 // We can get a big speed boost by filtering by class here
1702 else if ( m[1] == "." )
1703 r = jQuery.classFilter(r, m[2], not);
1704
1705 else if ( m[1] == "[" ) {
1706 var tmp = [], type = m[3];
1707
1708 for ( var i = 0, rl = r.length; i < rl; i++ ) {
1709 var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
1710
1711 if ( z == null || /href|src|selected/.test(m[2]) )
1712 z = jQuery.attr(a,m[2]) || '';
1713
1714 if ( (type == "" && !!z ||
1715 type == "=" && z == m[5] ||
1716 type == "!=" && z != m[5] ||
1717 type == "^=" && z && !z.indexOf(m[5]) ||
1718 type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
1719 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
1720 tmp.push( a );
1721 }
1722
1723 r = tmp;
1724
1725 // We can get a speed boost by handling nth-child here
1726 } else if ( m[1] == ":" && m[2] == "nth-child" ) {
1727 var merge = {}, tmp = [],
1728 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
1729 test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
1730 m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
1731 !/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
1732 // calculate the numbers (first)n+(last) including if they are negative
1733 first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
1734
1735 // loop through all the elements left in the jQuery object
1736 for ( var i = 0, rl = r.length; i < rl; i++ ) {
1737 var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
1738
1739 if ( !merge[id] ) {
1740 var c = 1;
1741
1742 for ( var n = parentNode.firstChild; n; n = n.nextSibling )
1743 if ( n.nodeType == 1 )
1744 n.nodeIndex = c++;
1745
1746 merge[id] = true;
1747 }
1748
1749 var add = false;
1750
1751 if ( first == 0 ) {
1752 if ( node.nodeIndex == last )
1753 add = true;
1754 } else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
1755 add = true;
1756
1757 if ( add ^ not )
1758 tmp.push( node );
1759 }
1760
1761 r = tmp;
1762
1763 // Otherwise, find the expression to execute
1764 } else {
1765 var fn = jQuery.expr[ m[1] ];
1766 if ( typeof fn == "object" )
1767 fn = fn[ m[2] ];
1768
1769 if ( typeof fn == "string" )
1770 fn = eval("false||function(a,i){return " + fn + ";}");
1771
1772 // Execute it against the current filter
1773 r = jQuery.grep( r, function(elem, i){
1774 return fn(elem, i, m, r);
1775 }, not );
1776 }
1777 }
1778
1779 // Return an array of filtered elements (r)
1780 // and the modified expression string (t)
1781 return { r: r, t: t };
1782 },
1783
1784 dir: function( elem, dir ){
1785 var matched = [],
1786 cur = elem[dir];
1787 while ( cur && cur != document ) {
1788 if ( cur.nodeType == 1 )
1789 matched.push( cur );
1790 cur = cur[dir];
1791 }
1792 return matched;
1793 },
1794
1795 nth: function(cur,result,dir,elem){
1796 result = result || 1;
1797 var num = 0;
1798
1799 for ( ; cur; cur = cur[dir] )
1800 if ( cur.nodeType == 1 && ++num == result )
1801 break;
1802
1803 return cur;
1804 },
1805
1806 sibling: function( n, elem ) {
1807 var r = [];
1808
1809 for ( ; n; n = n.nextSibling ) {
1810 if ( n.nodeType == 1 && n != elem )
1811 r.push( n );
1812 }
1813
1814 return r;
1815 }
1816 });
1817 /*
1818 * A number of helper functions used for managing events.
1819 * Many of the ideas behind this code originated from
1820 * Dean Edwards' addEvent library.
1821 */
1822 jQuery.event = {
1823
1824 // Bind an event to an element
1825 // Original by Dean Edwards
1826 add: function(elem, types, handler, data) {
1827 if ( elem.nodeType == 3 || elem.nodeType == 8 )
1828 return;
1829
1830 // For whatever reason, IE has trouble passing the window object
1831 // around, causing it to be cloned in the process
1832 if ( jQuery.browser.msie && elem.setInterval )
1833 elem = window;
1834
1835 // Make sure that the function being executed has a unique ID
1836 if ( !handler.guid )
1837 handler.guid = this.guid++;
1838
1839 // if data is passed, bind to handler
1840 if( data != undefined ) {
1841 // Create temporary function pointer to original handler
1842 var fn = handler;
1843
1844 // Create unique handler function, wrapped around original handler
1845 handler = this.proxy( fn, function() {
1846 // Pass arguments and context to original handler
1847 return fn.apply(this, arguments);
1848 });
1849
1850 // Store data in unique handler
1851 handler.data = data;
1852 }
1853
1854 // Init the element's event structure
1855 var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
1856 handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
1857 // Handle the second event of a trigger and when
1858 // an event is called after a page has unloaded
1859 if ( typeof jQuery != "undefined" && !jQuery.event.triggered )
1860 return jQuery.event.handle.apply(arguments.callee.elem, arguments);
1861 });
1862 // Add elem as a property of the handle function
1863 // This is to prevent a memory leak with non-native
1864 // event in IE.
1865 handle.elem = elem;
1866
1867 // Handle multiple events separated by a space
1868 // jQuery(...).bind("mouseover mouseout", fn);
1869 jQuery.each(types.split(/\s+/), function(index, type) {
1870 // Namespaced event handlers
1871 var parts = type.split(".");
1872 type = parts[0];
1873 handler.type = parts[1];
1874
1875 // Get the current list of functions bound to this event
1876 var handlers = events[type];
1877
1878 // Init the event handler queue
1879 if (!handlers) {
1880 handlers = events[type] = {};
1881
1882 // Check for a special event handler
1883 // Only use addEventListener/attachEvent if the special
1884 // events handler returns false
1885 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
1886 // Bind the global event handler to the element
1887 if (elem.addEventListener)
1888 elem.addEventListener(type, handle, false);
1889 else if (elem.attachEvent)
1890 elem.attachEvent("on" + type, handle);
1891 }
1892 }
1893
1894 // Add the function to the element's handler list
1895 handlers[handler.guid] = handler;
1896
1897 // Keep track of which events have been used, for global triggering
1898 jQuery.event.global[type] = true;
1899 });
1900
1901 // Nullify elem to prevent memory leaks in IE
1902 elem = null;
1903 },
1904
1905 guid: 1,
1906 global: {},
1907
1908 // Detach an event or set of events from an element
1909 remove: function(elem, types, handler) {
1910 // don't do events on text and comment nodes
1911 if ( elem.nodeType == 3 || elem.nodeType == 8 )
1912 return;
1913
1914 var events = jQuery.data(elem, "events"), ret, index;
1915
1916 if ( events ) {
1917 // Unbind all events for the element
1918 if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
1919 for ( var type in events )
1920 this.remove( elem, type + (types || "") );
1921 else {
1922 // types is actually an event object here
1923 if ( types.type ) {
1924 handler = types.handler;
1925 types = types.type;
1926 }
1927
1928 // Handle multiple events seperated by a space
1929 // jQuery(...).unbind("mouseover mouseout", fn);
1930 jQuery.each(types.split(/\s+/), function(index, type){
1931 // Namespaced event handlers
1932 var parts = type.split(".");
1933 type = parts[0];
1934
1935 if ( events[type] ) {
1936 // remove the given handler for the given type
1937 if ( handler )
1938 delete events[type][handler.guid];
1939
1940 // remove all handlers for the given type
1941 else
1942 for ( handler in events[type] )
1943 // Handle the removal of namespaced events
1944 if ( !parts[1] || events[type][handler].type == parts[1] )
1945 delete events[type][handler];
1946
1947 // remove generic event handler if no more handlers exist
1948 for ( ret in events[type] ) break;
1949 if ( !ret ) {
1950 if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
1951 if (elem.removeEventListener)
1952 elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
1953 else if (elem.detachEvent)
1954 elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
1955 }
1956 ret = null;
1957 delete events[type];
1958 }
1959 }
1960 });
1961 }
1962
1963 // Remove the expando if it's no longer used
1964 for ( ret in events ) break;
1965 if ( !ret ) {
1966 var handle = jQuery.data( elem, "handle" );
1967 if ( handle ) handle.elem = null;
1968 jQuery.removeData( elem, "events" );
1969 jQuery.removeData( elem, "handle" );
1970 }
1971 }
1972 },
1973
1974 trigger: function(type, data, elem, donative, extra) {
1975 // Clone the incoming data, if any
1976 data = jQuery.makeArray(data);
1977
1978 if ( type.indexOf("!") >= 0 ) {
1979 type = type.slice(0, -1);
1980 var exclusive = true;
1981 }
1982
1983 // Handle a global trigger
1984 if ( !elem ) {
1985 // Only trigger if we've ever bound an event for it
1986 if ( this.global[type] )
1987 jQuery.each( jQuery.cache, function(){
1988 if ( this.events && this.events[type] )
1989 jQuery.event.trigger( type, data, this.handle.elem );
1990 });
1991
1992 // Handle triggering a single element
1993 } else {
1994 // don't do events on text and comment nodes
1995 if ( elem.nodeType == 3 || elem.nodeType == 8 )
1996 return undefined;
1997
1998 var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
1999 // Check to see if we need to provide a fake event, or not
2000 event = !data[0] || !data[0].preventDefault;
2001
2002 // Pass along a fake event
2003 if ( event ) {
2004 data.unshift({
2005 type: type,
2006 target: elem,
2007 preventDefault: function(){},
2008 stopPropagation: function(){},
2009 timeStamp: now()
2010 });
2011 data[0][expando] = true; // no need to fix fake event
2012 }
2013
2014 // Enforce the right trigger type
2015 data[0].type = type;
2016 if ( exclusive )
2017 data[0].exclusive = true;
2018
2019 // Trigger the event, it is assumed that "handle" is a function
2020 var handle = jQuery.data(elem, "handle");
2021 if ( handle )
2022 val = handle.apply( elem, data );
2023
2024 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
2025 if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
2026 val = false;
2027
2028 // Extra functions don't get the custom event object
2029 if ( event )
2030 data.shift();
2031
2032 // Handle triggering of extra function
2033 if ( extra && jQuery.isFunction( extra ) ) {
2034 // call the extra function and tack the current return value on the end for possible inspection
2035 ret = extra.apply( elem, val == null ? data : data.concat( val ) );
2036 // if anything is returned, give it precedence and have it overwrite the previous value
2037 if (ret !== undefined)
2038 val = ret;
2039 }
2040
2041 // Trigger the native events (except for clicks on links)
2042 if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
2043 this.triggered = true;
2044 try {
2045 elem[ type ]();
2046 // prevent IE from throwing an error for some hidden elements
2047 } catch (e) {}
2048 }
2049
2050 this.triggered = false;
2051 }
2052
2053 return val;
2054 },
2055
2056 handle: function(event) {
2057 // returned undefined or false
2058 var val, ret, namespace, all, handlers;
2059
2060 event = arguments[0] = jQuery.event.fix( event || window.event );
2061
2062 // Namespaced event handlers
2063 namespace = event.type.split(".");
2064 event.type = namespace[0];
2065 namespace = namespace[1];
2066 // Cache this now, all = true means, any handler
2067 all = !namespace && !event.exclusive;
2068
2069 handlers = ( jQuery.data(this, "events") || {} )[event.type];
2070
2071 for ( var j in handlers ) {
2072 var handler = handlers[j];
2073
2074 // Filter the functions by class
2075 if ( all || handler.type == namespace ) {
2076 // Pass in a reference to the handler function itself
2077 // So that we can later remove it
2078 event.handler = handler;
2079 event.data = handler.data;
2080
2081 ret = handler.apply( this, arguments );
2082
2083 if ( val !== false )
2084 val = ret;
2085
2086 if ( ret === false ) {
2087 event.preventDefault();
2088 event.stopPropagation();
2089 }
2090 }
2091 }
2092
2093 return val;
2094 },
2095
2096 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 timeStamp toElement type view wheelDelta which".split(" "),
2097
2098 fix: function(event) {
2099 if ( event[expando] == true )
2100 return event;
2101
2102 // store a copy of the original event object
2103 // and "clone" to set read-only properties
2104 var originalEvent = event;
2105 event = { originalEvent: originalEvent };
2106
2107 for ( var i = this.props.length, prop; i; ){
2108 prop = this.props[ --i ];
2109 event[ prop ] = originalEvent[ prop ];
2110 }
2111
2112 // Mark it as fixed
2113 event[expando] = true;
2114
2115 // add preventDefault and stopPropagation since
2116 // they will not work on the clone
2117 event.preventDefault = function() {
2118 // if preventDefault exists run it on the original event
2119 if (originalEvent.preventDefault)
2120 originalEvent.preventDefault();
2121 // otherwise set the returnValue property of the original event to false (IE)
2122 originalEvent.returnValue = false;
2123 };
2124 event.stopPropagation = function() {
2125 // if stopPropagation exists run it on the original event
2126 if (originalEvent.stopPropagation)
2127 originalEvent.stopPropagation();
2128 // otherwise set the cancelBubble property of the original event to true (IE)
2129 originalEvent.cancelBubble = true;
2130 };
2131
2132 // Fix timeStamp
2133 event.timeStamp = event.timeStamp || now();
2134
2135 // Fix target property, if necessary
2136 if ( !event.target )
2137 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
2138
2139 // check if target is a textnode (safari)
2140 if ( event.target.nodeType == 3 )
2141 event.target = event.target.parentNode;
2142
2143 // Add relatedTarget, if necessary
2144 if ( !event.relatedTarget && event.fromElement )
2145 event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
2146
2147 // Calculate pageX/Y if missing and clientX/Y available
2148 if ( event.pageX == null && event.clientX != null ) {
2149 var doc = document.documentElement, body = document.body;
2150 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
2151 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
2152 }
2153
2154 // Add which for key events
2155 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
2156 event.which = event.charCode || event.keyCode;
2157
2158 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
2159 if ( !event.metaKey && event.ctrlKey )
2160 event.metaKey = event.ctrlKey;
2161
2162 // Add which for click: 1 == left; 2 == middle; 3 == right
2163 // Note: button is not normalized, so don't use it
2164 if ( !event.which && event.button )
2165 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2166
2167 return event;
2168 },
2169
2170 proxy: function( fn, proxy ){
2171 // Set the guid of unique handler to the same of original handler, so it can be removed
2172 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
2173 // So proxy can be declared as an argument
2174 return proxy;
2175 },
2176
2177 special: {
2178 ready: {
2179 setup: function() {
2180 // Make sure the ready event is setup
2181 bindReady();
2182 return;
2183 },
2184
2185 teardown: function() { return; }
2186 },
2187
2188 mouseenter: {
2189 setup: function() {
2190 if ( jQuery.browser.msie ) return false;
2191 jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
2192 return true;
2193 },
2194
2195 teardown: function() {
2196 if ( jQuery.browser.msie ) return false;
2197 jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
2198 return true;
2199 },
2200
2201 handler: function(event) {
2202 // If we actually just moused on to a sub-element, ignore it
2203 if ( withinElement(event, this) ) return true;
2204 // Execute the right handlers by setting the event type to mouseenter
2205 event.type = "mouseenter";
2206 return jQuery.event.handle.apply(this, arguments);
2207 }
2208 },
2209
2210 mouseleave: {
2211 setup: function() {
2212 if ( jQuery.browser.msie ) return false;
2213 jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
2214 return true;
2215 },
2216
2217 teardown: function() {
2218 if ( jQuery.browser.msie ) return false;
2219 jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
2220 return true;
2221 },
2222
2223 handler: function(event) {
2224 // If we actually just moused on to a sub-element, ignore it
2225 if ( withinElement(event, this) ) return true;
2226 // Execute the right handlers by setting the event type to mouseleave
2227 event.type = "mouseleave";
2228 return jQuery.event.handle.apply(this, arguments);
2229 }
2230 }
2231 }
2232 };
2233
2234 jQuery.fn.extend({
2235 bind: function( type, data, fn ) {
2236 return type == "unload" ? this.one(type, data, fn) : this.each(function(){
2237 jQuery.event.add( this, type, fn || data, fn && data );
2238 });
2239 },
2240
2241 one: function( type, data, fn ) {
2242 var one = jQuery.event.proxy( fn || data, function(event) {
2243 jQuery(this).unbind(event, one);
2244 return (fn || data).apply( this, arguments );
2245 });
2246 return this.each(function(){
2247 jQuery.event.add( this, type, one, fn && data);
2248 });
2249 },
2250
2251 unbind: function( type, fn ) {
2252 return this.each(function(){
2253 jQuery.event.remove( this, type, fn );
2254 });
2255 },
2256
2257 trigger: function( type, data, fn ) {
2258 return this.each(function(){
2259 jQuery.event.trigger( type, data, this, true, fn );
2260 });
2261 },
2262
2263 triggerHandler: function( type, data, fn ) {
2264 return this[0] && jQuery.event.trigger( type, data, this[0], false, fn );
2265 },
2266
2267 toggle: function( fn ) {
2268 // Save reference to arguments for access in closure
2269 var args = arguments, i = 1;
2270
2271 // link all the functions, so any of them can unbind this click handler
2272 while( i < args.length )
2273 jQuery.event.proxy( fn, args[i++] );
2274
2275 return this.click( jQuery.event.proxy( fn, function(event) {
2276 // Figure out which function to execute
2277 this.lastToggle = ( this.lastToggle || 0 ) % i;
2278
2279 // Make sure that clicks stop
2280 event.preventDefault();
2281
2282 // and execute the function
2283 return args[ this.lastToggle++ ].apply( this, arguments ) || false;
2284 }));
2285 },
2286
2287 hover: function(fnOver, fnOut) {
2288 return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
2289 },
2290
2291 ready: function(fn) {
2292 // Attach the listeners
2293 bindReady();
2294
2295 // If the DOM is already ready
2296 if ( jQuery.isReady )
2297 // Execute the function immediately
2298 fn.call( document, jQuery );
2299
2300 // Otherwise, remember the function for later
2301 else
2302 // Add the function to the wait list
2303 jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
2304
2305 return this;
2306 }
2307 });
2308
2309 jQuery.extend({
2310 isReady: false,
2311 readyList: [],
2312 // Handle when the DOM is ready
2313 ready: function() {
2314 // Make sure that the DOM is not already loaded
2315 if ( !jQuery.isReady ) {
2316 // Remember that the DOM is ready
2317 jQuery.isReady = true;
2318
2319 // If there are functions bound, to execute
2320 if ( jQuery.readyList ) {
2321 // Execute all of them
2322 jQuery.each( jQuery.readyList, function(){
2323 this.call( document );
2324 });
2325
2326 // Reset the list of functions
2327 jQuery.readyList = null;
2328 }
2329
2330 // Trigger any bound ready events
2331 jQuery(document).triggerHandler("ready");
2332 }
2333 }
2334 });
2335
2336 var readyBound = false;
2337
2338 function bindReady(){
2339 if ( readyBound ) return;
2340 readyBound = true;
2341
2342 // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
2343 if ( document.addEventListener && !jQuery.browser.opera)
2344 // Use the handy event callback
2345 document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
2346
2347 // If IE is used and is not in a frame
2348 // Continually check to see if the document is ready
2349 if ( jQuery.browser.msie && window == top ) (function(){
2350 if (jQuery.isReady) return;
2351 try {
2352 // If IE is used, use the trick by Diego Perini
2353 // http://javascript.nwbox.com/IEContentLoaded/
2354 document.documentElement.doScroll("left");
2355 } catch( error ) {
2356 setTimeout( arguments.callee, 0 );
2357 return;
2358 }
2359 // and execute any waiting functions
2360 jQuery.ready();
2361 })();
2362
2363 if ( jQuery.browser.opera )
2364 document.addEventListener( "DOMContentLoaded", function () {
2365 if (jQuery.isReady) return;
2366 for (var i = 0; i < document.styleSheets.length; i++)
2367 if (document.styleSheets[i].disabled) {
2368 setTimeout( arguments.callee, 0 );
2369 return;
2370 }
2371 // and execute any waiting functions
2372 jQuery.ready();
2373 }, false);
2374
2375 if ( jQuery.browser.safari ) {
2376 var numStyles;
2377 (function(){
2378 if (jQuery.isReady) return;
2379 if ( document.readyState != "loaded" && document.readyState != "complete" ) {
2380 setTimeout( arguments.callee, 0 );
2381 return;
2382 }
2383 if ( numStyles === undefined )
2384 numStyles = jQuery("style, link[rel=stylesheet]").length;
2385 if ( document.styleSheets.length != numStyles ) {
2386 setTimeout( arguments.callee, 0 );
2387 return;
2388 }
2389 // and execute any waiting functions
2390 jQuery.ready();
2391 })();
2392 }
2393
2394 // A fallback to window.onload, that will always work
2395 jQuery.event.add( window, "load", jQuery.ready );
2396 }
2397
2398 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
2399 "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
2400 "submit,keydown,keypress,keyup,error").split(","), function(i, name){
2401
2402 // Handle event binding
2403 jQuery.fn[name] = function(fn){
2404 return fn ? this.bind(name, fn) : this.trigger(name);
2405 };
2406 });
2407
2408 // Checks if an event happened on an element within another element
2409 // Used in jQuery.event.special.mouseenter and mouseleave handlers
2410 var withinElement = function(event, elem) {
2411 // Check if mouse(over|out) are still within the same parent element
2412 var parent = event.relatedTarget;
2413 // Traverse up the tree
2414 while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
2415 // Return true if we actually just moused on to a sub-element
2416 return parent == elem;
2417 };
2418
2419 // Prevent memory leaks in IE
2420 // And prevent errors on refresh with events like mouseover in other browsers
2421 // Window isn't included so as not to unbind existing unload events
2422 jQuery( window ).bind( 'unload', function(){
2423 for ( var id in jQuery.cache )
2424 // Skip the window
2425 if ( id != 1 && jQuery.cache[ id ].handle )
2426 jQuery.event.remove( jQuery.cache[ id ].handle.elem );
2427 });
2428 jQuery.fn.extend({
2429 // Keep a copy of the old load
2430 _load: jQuery.fn.load,
2431
2432 load: function( url, params, callback ) {
2433 if ( typeof url != 'string' )
2434 return this._load( url );
2435
2436 var off = url.indexOf(" ");
2437 if ( off >= 0 ) {
2438 var selector = url.slice(off, url.length);
2439 url = url.slice(0, off);
2440 }
2441
2442 callback = callback || function(){};
2443
2444 // Default to a GET request
2445 var type = "GET";
2446
2447 // If the second parameter was provided
2448 if ( params )
2449 // If it's a function
2450 if ( jQuery.isFunction( params ) ) {
2451 // We assume that it's the callback
2452 callback = params;
2453 params = null;
2454
2455 // Otherwise, build a param string
2456 } else if( typeof params == 'object' ) {
2457 params = jQuery.param( params );
2458 type = "POST";
2459 }
2460
2461 var self = this;
2462
2463 // Request the remote document
2464 jQuery.ajax({
2465 url: url,
2466 type: type,
2467 dataType: "html",
2468 data: params,
2469 complete: function(res, status){
2470 // If successful, inject the HTML into all the matched elements
2471 if ( status == "success" || status == "notmodified" )
2472 // See if a selector was specified
2473 self.html( selector ?
2474 // Create a dummy div to hold the results
2475 jQuery("<div/>")
2476 // inject the contents of the document in, removing the scripts
2477 // to avoid any 'Permission Denied' errors in IE
2478 .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
2479
2480 // Locate the specified elements
2481 .find(selector) :
2482
2483 // If not, just inject the full result
2484 res.responseText );
2485
2486 self.each( callback, [res.responseText, status, res] );
2487 }
2488 });
2489 return this;
2490 },
2491
2492 serialize: function() {
2493 return jQuery.param(this.serializeArray());
2494 },
2495 serializeArray: function() {
2496 return this.map(function(){
2497 return jQuery.nodeName(this, "form") ?
2498 jQuery.makeArray(this.elements) : this;
2499 })
2500 .filter(function(){
2501 return this.name && !this.disabled &&
2502 (this.checked || /select|textarea/i.test(this.nodeName) ||
2503 /text|hidden|password/i.test(this.type));
2504 })
2505 .map(function(i, elem){
2506 var val = jQuery(this).val();
2507 return val == null ? null :
2508 val.constructor == Array ?
2509 jQuery.map( val, function(val, i){
2510 return {name: elem.name, value: val};
2511 }) :
2512 {name: elem.name, value: val};
2513 }).get();
2514 }
2515 });
2516
2517 // Attach a bunch of functions for handling common AJAX events
2518 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
2519 jQuery.fn[o] = function(f){
2520 return this.bind(o, f);
2521 };
2522 });
2523
2524 var jsc = now();
2525
2526 jQuery.extend({
2527 get: function( url, data, callback, type ) {
2528 // shift arguments if data argument was ommited
2529 if ( jQuery.isFunction( data ) ) {
2530 callback = data;
2531 data = null;
2532 }
2533
2534 return jQuery.ajax({
2535 type: "GET",
2536 url: url,
2537 data: data,
2538 success: callback,
2539 dataType: type
2540 });
2541 },
2542
2543 getScript: function( url, callback ) {
2544 return jQuery.get(url, null, callback, "script");
2545 },
2546
2547 getJSON: function( url, data, callback ) {
2548 return jQuery.get(url, data, callback, "json");
2549 },
2550
2551 post: function( url, data, callback, type ) {
2552 if ( jQuery.isFunction( data ) ) {
2553 callback = data;
2554 data = {};
2555 }
2556
2557 return jQuery.ajax({
2558 type: "POST",
2559 url: url,
2560 data: data,
2561 success: callback,
2562 dataType: type
2563 });
2564 },
2565
2566 ajaxSetup: function( settings ) {
2567 jQuery.extend( jQuery.ajaxSettings, settings );
2568 },
2569
2570 ajaxSettings: {
2571 url: location.href,
2572 global: true,
2573 type: "GET",
2574 timeout: 0,
2575 contentType: "application/x-www-form-urlencoded",
2576 processData: true,
2577 async: true,
2578 data: null,
2579 username: null,
2580 password: null,
2581 accepts: {
2582 xml: "application/xml, text/xml",
2583 html: "text/html",
2584 script: "text/javascript, application/javascript",
2585 json: "application/json, text/javascript",
2586 text: "text/plain",
2587 _default: "*/*"
2588 }
2589 },
2590
2591 // Last-Modified header cache for next request
2592 lastModified: {},
2593
2594 ajax: function( s ) {
2595 // Extend the settings, but re-extend 's' so that it can be
2596 // checked again later (in the test suite, specifically)
2597 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
2598
2599 var jsonp, jsre = /=\?(&|$)/g, status, data,
2600 type = s.type.toUpperCase();
2601
2602 // convert data if not already a string
2603 if ( s.data && s.processData && typeof s.data != "string" )
2604 s.data = jQuery.param(s.data);
2605
2606 // Handle JSONP Parameter Callbacks
2607 if ( s.dataType == "jsonp" ) {
2608 if ( type == "GET" ) {
2609 if ( !s.url.match(jsre) )
2610 s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
2611 } else if ( !s.data || !s.data.match(jsre) )
2612 s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
2613 s.dataType = "json";
2614 }
2615
2616 // Build temporary JSONP function
2617 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
2618 jsonp = "jsonp" + jsc++;
2619
2620 // Replace the =? sequence both in the query string and the data
2621 if ( s.data )
2622 s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
2623 s.url = s.url.replace(jsre, "=" + jsonp + "$1");
2624
2625 // We need to make sure
2626 // that a JSONP style response is executed properly
2627 s.dataType = "script";
2628
2629 // Handle JSONP-style loading
2630 window[ jsonp ] = function(tmp){
2631 data = tmp;
2632 success();
2633 complete();
2634 // Garbage collect
2635 window[ jsonp ] = undefined;
2636 try{ delete window[ jsonp ]; } catch(e){}
2637 if ( head )
2638 head.removeChild( script );
2639 };
2640 }
2641
2642 if ( s.dataType == "script" && s.cache == null )
2643 s.cache = false;
2644
2645 if ( s.cache === false && type == "GET" ) {
2646 var ts = now();
2647 // try replacing _= if it is there
2648 var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
2649 // if nothing was replaced, add timestamp to the end
2650 s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
2651 }
2652
2653 // If data is available, append data to url for get requests
2654 if ( s.data && type == "GET" ) {
2655 s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
2656
2657 // IE likes to send both get and post data, prevent this
2658 s.data = null;
2659 }
2660
2661 // Watch for a new set of requests
2662 if ( s.global && ! jQuery.active++ )
2663 jQuery.event.trigger( "ajaxStart" );
2664
2665 // Matches an absolute URL, and saves the domain
2666 var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
2667
2668 // If we're requesting a remote document
2669 // and trying to load JSON or Script with a GET
2670 if ( s.dataType == "script" && type == "GET" && parts
2671 && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
2672
2673 var head = document.getElementsByTagName("head")[0];
2674 var script = document.createElement("script");
2675 script.src = s.url;
2676 if (s.scriptCharset)
2677 script.charset = s.scriptCharset;
2678
2679 // Handle Script loading
2680 if ( !jsonp ) {
2681 var done = false;
2682
2683 // Attach handlers for all browsers
2684 script.onload = script.onreadystatechange = function(){
2685 if ( !done && (!this.readyState ||
2686 this.readyState == "loaded" || this.readyState == "complete") ) {
2687 done = true;
2688 success();
2689 complete();
2690 head.removeChild( script );
2691 }
2692 };
2693 }
2694
2695 head.appendChild(script);
2696
2697 // We handle everything using the script element injection
2698 return undefined;
2699 }
2700
2701 var requestDone = false;
2702
2703 // Create the request object; Microsoft failed to properly
2704 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
2705 var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
2706
2707 // Open the socket
2708 // Passing null username, generates a login popup on Opera (#2865)
2709 if( s.username )
2710 xhr.open(type, s.url, s.async, s.username, s.password);
2711 else
2712 xhr.open(type, s.url, s.async);
2713
2714 // Need an extra try/catch for cross domain requests in Firefox 3
2715 try {
2716 // Set the correct header, if data is being sent
2717 if ( s.data )
2718 xhr.setRequestHeader("Content-Type", s.contentType);
2719
2720 // Set the If-Modified-Since header, if ifModified mode.
2721 if ( s.ifModified )
2722 xhr.setRequestHeader("If-Modified-Since",
2723 jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
2724
2725 // Set header so the called script knows that it's an XMLHttpRequest
2726 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
2727
2728 // Set the Accepts header for the server, depending on the dataType
2729 xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
2730 s.accepts[ s.dataType ] + ", */*" :
2731 s.accepts._default );
2732 } catch(e){}
2733
2734 // Allow custom headers/mimetypes
2735 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
2736 // cleanup active request counter
2737 s.global && jQuery.active--;
2738 // close opended socket
2739 xhr.abort();
2740 return false;
2741 }
2742
2743 if ( s.global )
2744 jQuery.event.trigger("ajaxSend", [xhr, s]);
2745
2746 // Wait for a response to come back
2747 var onreadystatechange = function(isTimeout){
2748 // The transfer is complete and the data is available, or the request timed out
2749 if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
2750 requestDone = true;
2751
2752 // clear poll interval
2753 if (ival) {
2754 clearInterval(ival);
2755 ival = null;
2756 }
2757
2758 status = isTimeout == "timeout" ? "timeout" :
2759 !jQuery.httpSuccess( xhr ) ? "error" :
2760 s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
2761 "success";
2762
2763 if ( status == "success" ) {
2764 // Watch for, and catch, XML document parse errors
2765 try {
2766 // process the data (runs the xml through httpData regardless of callback)
2767 data = jQuery.httpData( xhr, s.dataType, s );
2768 } catch(e) {
2769 status = "parsererror";
2770 }
2771 }
2772
2773 // Make sure that the request was successful or notmodified
2774 if ( status == "success" ) {
2775 // Cache Last-Modified header, if ifModified mode.
2776 var modRes;
2777 try {
2778 modRes = xhr.getResponseHeader("Last-Modified");
2779 } catch(e) {} // swallow exception thrown by FF if header is not available
2780
2781 if ( s.ifModified && modRes )
2782 jQuery.lastModified[s.url] = modRes;
2783
2784 // JSONP handles its own success callback
2785 if ( !jsonp )
2786 success();
2787 } else
2788 jQuery.handleError(s, xhr, status);
2789
2790 // Fire the complete handlers
2791 complete();
2792
2793 // Stop memory leaks
2794 if ( s.async )
2795 xhr = null;
2796 }
2797 };
2798
2799 if ( s.async ) {
2800 // don't attach the handler to the request, just poll it instead
2801 var ival = setInterval(onreadystatechange, 13);
2802
2803 // Timeout checker
2804 if ( s.timeout > 0 )
2805 setTimeout(function(){
2806 // Check to see if the request is still happening
2807 if ( xhr ) {
2808 // Cancel the request
2809 xhr.abort();
2810
2811 if( !requestDone )
2812 onreadystatechange( "timeout" );
2813 }
2814 }, s.timeout);
2815 }
2816
2817 // Send the data
2818 try {
2819 xhr.send(s.data);
2820 } catch(e) {
2821 jQuery.handleError(s, xhr, null, e);
2822 }
2823
2824 // firefox 1.5 doesn't fire statechange for sync requests
2825 if ( !s.async )
2826 onreadystatechange();
2827
2828 function success(){
2829 // If a local callback was specified, fire it and pass it the data
2830 if ( s.success )
2831 s.success( data, status );
2832
2833 // Fire the global callback
2834 if ( s.global )
2835 jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
2836 }
2837
2838 function complete(){
2839 // Process result
2840 if ( s.complete )
2841 s.complete(xhr, status);
2842
2843 // The request was completed
2844 if ( s.global )
2845 jQuery.event.trigger( "ajaxComplete", [xhr, s] );
2846
2847 // Handle the global AJAX counter
2848 if ( s.global && ! --jQuery.active )
2849 jQuery.event.trigger( "ajaxStop" );
2850 }
2851
2852 // return XMLHttpRequest to allow aborting the request etc.
2853 return xhr;
2854 },
2855
2856 handleError: function( s, xhr, status, e ) {
2857 // If a local callback was specified, fire it
2858 if ( s.error ) s.error( xhr, status, e );
2859
2860 // Fire the global callback
2861 if ( s.global )
2862 jQuery.event.trigger( "ajaxError", [xhr, s, e] );
2863 },
2864
2865 // Counter for holding the number of active queries
2866 active: 0,
2867
2868 // Determines if an XMLHttpRequest was successful or not
2869 httpSuccess: function( xhr ) {
2870 try {
2871 // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
2872 return !xhr.status && location.protocol == "file:" ||
2873 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223 ||
2874 jQuery.browser.safari && xhr.status == undefined;
2875 } catch(e){}
2876 return false;
2877 },
2878
2879 // Determines if an XMLHttpRequest returns NotModified
2880 httpNotModified: function( xhr, url ) {
2881 try {
2882 var xhrRes = xhr.getResponseHeader("Last-Modified");
2883
2884 // Firefox always returns 200. check Last-Modified date
2885 return xhr.status == 304 || xhrRes == jQuery.lastModified[url] ||
2886 jQuery.browser.safari && xhr.status == undefined;
2887 } catch(e){}
2888 return false;
2889 },
2890
2891 httpData: function( xhr, type, s ) {
2892 var ct = xhr.getResponseHeader("content-type"),
2893 xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
2894 data = xml ? xhr.responseXML : xhr.responseText;
2895
2896 if ( xml && data.documentElement.tagName == "parsererror" )
2897 throw "parsererror";
2898
2899 // Allow a pre-filtering function to sanitize the response
2900 // s != null is checked to keep backwards compatibility
2901 if( s && s.dataFilter )
2902 data = s.dataFilter( data, type );
2903
2904 // If the type is "script", eval it in global context
2905 if ( type == "script" )
2906 jQuery.globalEval( data );
2907
2908 // Get the JavaScript object, if JSON is used.
2909 if ( type == "json" )
2910 data = eval("(" + data + ")");
2911
2912 return data;
2913 },
2914
2915 // Serialize an array of form elements or a set of
2916 // key/values into a query string
2917 param: function( a ) {
2918 var s = [ ];
2919
2920 function add( key, value ){
2921 s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
2922 };
2923
2924 // If an array was passed in, assume that it is an array
2925 // of form elements
2926 if ( a.constructor == Array || a.jquery )
2927 // Serialize the form elements
2928 jQuery.each( a, function(){
2929 add( this.name, this.value );
2930 });
2931
2932 // Otherwise, assume that it's an object of key/value pairs
2933 else
2934 // Serialize the key/values
2935 for ( var j in a )
2936 // If the value is an array then the key names need to be repeated
2937 if ( a[j] && a[j].constructor == Array )
2938 jQuery.each( a[j], function(){
2939 add( j, this );
2940 });
2941 else
2942 add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
2943
2944 // Return the resulting serialization
2945 return s.join("&").replace(/%20/g, "+");
2946 }
2947
2948 });
2949 jQuery.fn.extend({
2950 show: function(speed,callback){
2951 return speed ?
2952 this.animate({
2953 height: "show", width: "show", opacity: "show"
2954 }, speed, callback) :
2955
2956 this.filter(":hidden").each(function(){
2957 this.style.display = this.oldblock || "";
2958 if ( jQuery.css(this,"display") == "none" ) {
2959 var elem = jQuery("<" + this.tagName + " />").appendTo("body");
2960 this.style.display = elem.css("display");
2961 // handle an edge condition where css is - div { display:none; } or similar
2962 if (this.style.display == "none")
2963 this.style.display = "block";
2964 elem.remove();
2965 }
2966 }).end();
2967 },
2968
2969 hide: function(speed,callback){
2970 return speed ?
2971 this.animate({
2972 height: "hide", width: "hide", opacity: "hide"
2973 }, speed, callback) :
2974
2975 this.filter(":visible").each(function(){
2976 this.oldblock = this.oldblock || jQuery.css(this,"display");
2977 this.style.display = "none";
2978 }).end();
2979 },
2980
2981 // Save the old toggle function
2982 _toggle: jQuery.fn.toggle,
2983
2984 toggle: function( fn, fn2 ){
2985 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
2986 this._toggle.apply( this, arguments ) :
2987 fn ?
2988 this.animate({
2989 height: "toggle", width: "toggle", opacity: "toggle"
2990 }, fn, fn2) :
2991 this.each(function(){
2992 jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
2993 });
2994 },
2995
2996 fadeTo: function(speed,to,callback){
2997 return this.animate({opacity: to}, speed, callback);
2998 },
2999
3000 animate: function( prop, speed, easing, callback ) {
3001 var optall = jQuery.speed(speed, easing, callback);
3002
3003 return this[ optall.queue === false ? "each" : "queue" ](function(){
3004
3005 var opt = jQuery.extend({}, optall), p,
3006 hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
3007 self = this;
3008
3009 for ( p in prop ) {
3010 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
3011 return opt.complete.call(this);
3012
3013 if ( ( p == "height" || p == "width" ) && this.style ) {
3014 // Store display property
3015 opt.display = jQuery.css(this, "display");
3016
3017 // Make sure that nothing sneaks out
3018 opt.overflow = this.style.overflow;
3019 }
3020 }
3021
3022 if ( opt.overflow != null )
3023 this.style.overflow = "hidden";
3024
3025 opt.curAnim = jQuery.extend({}, prop);
3026
3027 jQuery.each( prop, function(name, val){
3028 var e = new jQuery.fx( self, opt, name );
3029
3030 if ( /toggle|show|hide/.test(val) )
3031 e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
3032 else {
3033 var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
3034 start = e.cur(true) || 0;
3035
3036 if ( parts ) {
3037 var end = parseFloat(parts[2]),
3038 unit = parts[3] || "px";
3039
3040 // We need to compute starting value
3041 if ( unit != "px" ) {
3042 self.style[ name ] = (end || 1) + unit;
3043 start = ((end || 1) / e.cur(true)) * start;
3044 self.style[ name ] = start + unit;
3045 }
3046
3047 // If a +=/-= token was provided, we're doing a relative animation
3048 if ( parts[1] )
3049 end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
3050
3051 e.custom( start, end, unit );
3052 } else
3053 e.custom( start, val, "" );
3054 }
3055 });
3056
3057 // For JS strict compliance
3058 return true;
3059 });
3060 },
3061
3062 queue: function(type, fn){
3063 if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
3064 fn = type;
3065 type = "fx";
3066 }
3067
3068 if ( !type || (typeof type == "string" && !fn) )
3069 return queue( this[0], type );
3070
3071 return this.each(function(){
3072 if ( fn.constructor == Array )
3073 queue(this, type, fn);
3074 else {
3075 queue(this, type).push( fn );
3076
3077 if ( queue(this, type).length == 1 )
3078 fn.call(this);
3079 }
3080 });
3081 },
3082
3083 stop: function(clearQueue, gotoEnd){
3084 var timers = jQuery.timers;
3085
3086 if (clearQueue)
3087 this.queue([]);
3088
3089 this.each(function(){
3090 // go in reverse order so anything added to the queue during the loop is ignored
3091 for ( var i = timers.length - 1; i >= 0; i-- )
3092 if ( timers[i].elem == this ) {
3093 if (gotoEnd)
3094 // force the next step to be the last
3095 timers[i](true);
3096 timers.splice(i, 1);
3097 }
3098 });
3099
3100 // start the next in the queue if the last step wasn't forced
3101 if (!gotoEnd)
3102 this.dequeue();
3103
3104 return this;
3105 }
3106
3107 });
3108
3109 // Generate shortcuts for custom animations
3110 jQuery.each({
3111 slideDown: { height:"show" },
3112 slideUp: { height: "hide" },
3113 slideToggle: { height: "toggle" },
3114 fadeIn: { opacity: "show" },
3115 fadeOut: { opacity: "hide" }
3116 }, function( name, props ){
3117 jQuery.fn[ name ] = function( speed, callback ){
3118 return this.animate( props, speed, callback );
3119 };
3120 });
3121
3122 var queue = function( elem, type, array ) {
3123 if ( elem ){
3124
3125 type = type || "fx";
3126
3127 var q = jQuery.data( elem, type + "queue" );
3128
3129 if ( !q || array )
3130 q = jQuery.data( elem, type + "queue", jQuery.makeArray(array) );
3131
3132 }
3133 return q;
3134 };
3135
3136 jQuery.fn.dequeue = function(type){
3137 type = type || "fx";
3138
3139 return this.each(function(){
3140 var q = queue(this, type);
3141
3142 q.shift();
3143
3144 if ( q.length )
3145 q[0].call( this );
3146 });
3147 };
3148
3149 jQuery.extend({
3150
3151 speed: function(speed, easing, fn) {
3152 var opt = speed && speed.constructor == Object ? speed : {
3153 complete: fn || !fn && easing ||
3154 jQuery.isFunction( speed ) && speed,
3155 duration: speed,
3156 easing: fn && easing || easing && easing.constructor != Function && easing
3157 };
3158
3159 opt.duration = (opt.duration && opt.duration.constructor == Number ?
3160 opt.duration :
3161 jQuery.fx.speeds[opt.duration]) || jQuery.fx.speeds._default;
3162
3163 // Queueing
3164 opt.old = opt.complete;
3165 opt.complete = function(){
3166 if ( opt.queue !== false )
3167 jQuery(this).dequeue();
3168 if ( jQuery.isFunction( opt.old ) )
3169 opt.old.call( this );
3170 };
3171
3172 return opt;
3173 },
3174
3175 easing: {
3176 linear: function( p, n, firstNum, diff ) {
3177 return firstNum + diff * p;
3178 },
3179 swing: function( p, n, firstNum, diff ) {
3180 return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
3181 }
3182 },
3183
3184 timers: [],
3185 timerId: null,
3186
3187 fx: function( elem, options, prop ){
3188 this.options = options;
3189 this.elem = elem;
3190 this.prop = prop;
3191
3192 if ( !options.orig )
3193 options.orig = {};
3194 }
3195
3196 });
3197
3198 jQuery.fx.prototype = {
3199
3200 // Simple function for setting a style value
3201 update: function(){
3202 if ( this.options.step )
3203 this.options.step.call( this.elem, this.now, this );
3204
3205 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
3206
3207 // Set display property to block for height/width animations
3208 if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
3209 this.elem.style.display = "block";
3210 },
3211
3212 // Get the current size
3213 cur: function(force){
3214 if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
3215 return this.elem[ this.prop ];
3216
3217 var r = parseFloat(jQuery.css(this.elem, this.prop, force));
3218 return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
3219 },
3220
3221 // Start an animation from one number to another
3222 custom: function(from, to, unit){
3223 this.startTime = now();
3224 this.start = from;
3225 this.end = to;
3226 this.unit = unit || this.unit || "px";
3227 this.now = this.start;
3228 this.pos = this.state = 0;
3229 this.update();
3230
3231 var self = this;
3232 function t(gotoEnd){
3233 return self.step(gotoEnd);
3234 }
3235
3236 t.elem = this.elem;
3237
3238 jQuery.timers.push(t);
3239
3240 if ( jQuery.timerId == null ) {
3241 jQuery.timerId = setInterval(function(){
3242 var timers = jQuery.timers;
3243
3244 for ( var i = 0; i < timers.length; i++ )
3245 if ( !timers[i]() )
3246 timers.splice(i--, 1);
3247
3248 if ( !timers.length ) {
3249 clearInterval( jQuery.timerId );
3250 jQuery.timerId = null;
3251 }
3252 }, 13);
3253 }
3254 },
3255
3256 // Simple 'show' function
3257 show: function(){
3258 // Remember where we started, so that we can go back to it later
3259 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
3260 this.options.show = true;
3261
3262 // Begin the animation
3263 this.custom(0, this.cur());
3264
3265 // Make sure that we start at a small width/height to avoid any
3266 // flash of content
3267 if ( this.prop == "width" || this.prop == "height" )
3268 this.elem.style[this.prop] = "1px";
3269
3270 // Start by showing the element
3271 jQuery(this.elem).show();
3272 },
3273
3274 // Simple 'hide' function
3275 hide: function(){
3276 // Remember where we started, so that we can go back to it later
3277 this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
3278 this.options.hide = true;
3279
3280 // Begin the animation
3281 this.custom(this.cur(), 0);
3282 },
3283
3284 // Each step of an animation
3285 step: function(gotoEnd){
3286 var t = now();
3287
3288 if ( gotoEnd || t > this.options.duration + this.startTime ) {
3289 this.now = this.end;
3290 this.pos = this.state = 1;
3291 this.update();
3292
3293 this.options.curAnim[ this.prop ] = true;
3294
3295 var done = true;
3296 for ( var i in this.options.curAnim )
3297 if ( this.options.curAnim[i] !== true )
3298 done = false;
3299
3300 if ( done ) {
3301 if ( this.options.display != null ) {
3302 // Reset the overflow
3303 this.elem.style.overflow = this.options.overflow;
3304
3305 // Reset the display
3306 this.elem.style.display = this.options.display;
3307 if ( jQuery.css(this.elem, "display") == "none" )
3308 this.elem.style.display = "block";
3309 }
3310
3311 // Hide the element if the "hide" operation was done
3312 if ( this.options.hide )
3313 this.elem.style.display = "none";
3314
3315 // Reset the properties, if the item has been hidden or shown
3316 if ( this.options.hide || this.options.show )
3317 for ( var p in this.options.curAnim )
3318 jQuery.attr(this.elem.style, p, this.options.orig[p]);
3319 }
3320
3321 if ( done )
3322 // Execute the complete function
3323 this.options.complete.call( this.elem );
3324
3325 return false;
3326 } else {
3327 var n = t - this.startTime;
3328 this.state = n / this.options.duration;
3329
3330 // Perform the easing function, defaults to swing
3331 this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
3332 this.now = this.start + ((this.end - this.start) * this.pos);
3333
3334 // Perform the next step of the animation
3335 this.update();
3336 }
3337
3338 return true;
3339 }
3340
3341 };
3342
3343 jQuery.extend( jQuery.fx, {
3344 speeds:{
3345 slow: 600,
3346 fast: 200,
3347 // Default speed
3348 _default: 400
3349 },
3350 step: {
3351
3352 opacity: function(fx){
3353 jQuery.attr(fx.elem.style, "opacity", fx.now);
3354 },
3355
3356 _default: function(fx){
3357 if( fx.prop in fx.elem )
3358 fx.elem[ fx.prop ] = fx.now;
3359 else if( fx.elem.style )
3360 fx.elem.style[ fx.prop ] = fx.now + fx.unit;
3361 }
3362 }
3363 });
3364 // The Offset Method
3365 // Originally By Brandon Aaron, part of the Dimension Plugin
3366 // http://jquery.com/plugins/project/dimensions
3367 jQuery.fn.offset = function() {
3368 var left = 0, top = 0, elem = this[0], results;
3369
3370 if ( elem ) with ( jQuery.browser ) {
3371 var parent = elem.parentNode,
3372 offsetChild = elem,
3373 offsetParent = elem.offsetParent,
3374 doc = elem.ownerDocument,
3375 safari2 = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
3376 css = jQuery.curCSS,
3377 fixed = css(elem, "position") == "fixed";
3378
3379 // Use getBoundingClientRect if available
3380 if ( !(mozilla && elem == document.body) && elem.getBoundingClientRect ) {
3381 var box = elem.getBoundingClientRect();
3382
3383 // Add the document scroll offsets
3384 add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
3385 box.top + Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
3386
3387 // IE adds the HTML element's border, by default it is medium which is 2px
3388 // IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
3389 // IE 7 standards mode, the border is always 2px
3390 // This border/offset is typically represented by the clientLeft and clientTop properties
3391 // However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
3392 // Therefore this method will be off by 2px in IE while in quirksmode
3393 add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
3394
3395 // Otherwise loop through the offsetParents and parentNodes
3396 } else {
3397
3398 // Initial element offsets
3399 add( elem.offsetLeft, elem.offsetTop );
3400
3401 // Get parent offsets
3402 while ( offsetParent ) {
3403 // Add offsetParent offsets
3404 add( offsetParent.offsetLeft, offsetParent.offsetTop );
3405
3406 // Mozilla and Safari > 2 does not include the border on offset parents
3407 // However Mozilla adds the border for table or table cells
3408 if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
3409 border( offsetParent );
3410
3411 // Add the document scroll offsets if position is fixed on any offsetParent
3412 if ( !fixed && css(offsetParent, "position") == "fixed" )
3413 fixed = true;
3414
3415 // Set offsetChild to previous offsetParent unless it is the body element
3416 offsetChild = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
3417 // Get next offsetParent
3418 offsetParent = offsetParent.offsetParent;
3419 }
3420
3421 // Get parent scroll offsets
3422 while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
3423 // Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
3424 if ( !/^inline|table.*$/i.test(css(parent, "display")) )
3425 // Subtract parent scroll offsets
3426 add( -parent.scrollLeft, -parent.scrollTop );
3427
3428 // Mozilla does not add the border for a parent that has overflow != visible
3429 if ( mozilla && css(parent, "overflow") != "visible" )
3430 border( parent );
3431
3432 // Get next parent
3433 parent = parent.parentNode;
3434 }
3435
3436 // Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
3437 // Mozilla doubles body offsets with a non-absolutely positioned offsetChild
3438 if ( (safari2 && (fixed || css(offsetChild, "position") == "absolute")) ||
3439 (mozilla && css(offsetChild, "position") != "absolute") )
3440 add( -doc.body.offsetLeft, -doc.body.offsetTop );
3441
3442 // Add the document scroll offsets if position is fixed
3443 if ( fixed )
3444 add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
3445 Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
3446 }
3447
3448 // Return an object with top and left properties
3449 results = { top: top, left: left };
3450 }
3451
3452 function border(elem) {
3453 add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
3454 }
3455
3456 function add(l, t) {
3457 left += parseInt(l, 10) || 0;
3458 top += parseInt(t, 10) || 0;
3459 }
3460
3461 return results;
3462 };
3463
3464
3465 jQuery.fn.extend({
3466 position: function() {
3467 var left = 0, top = 0, results;
3468
3469 if ( this[0] ) {
3470 // Get *real* offsetParent
3471 var offsetParent = this.offsetParent(),
3472
3473 // Get correct offsets
3474 offset = this.offset(),
3475 parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
3476
3477 // Subtract element margins
3478 // note: when an element has margin: auto the offsetLeft and marginLeft
3479 // are the same in Safari causing offset.left to incorrectly be 0
3480 offset.top -= num( this, 'marginTop' );
3481 offset.left -= num( this, 'marginLeft' );
3482
3483 // Add offsetParent borders
3484 parentOffset.top += num( offsetParent, 'borderTopWidth' );
3485 parentOffset.left += num( offsetParent, 'borderLeftWidth' );
3486
3487 // Subtract the two offsets
3488 results = {
3489 top: offset.top - parentOffset.top,
3490 left: offset.left - parentOffset.left
3491 };
3492 }
3493
3494 return results;
3495 },
3496
3497 offsetParent: function() {
3498 var offsetParent = this[0].offsetParent || document.body;
3499 while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
3500 offsetParent = offsetParent.offsetParent;
3501 return jQuery(offsetParent);
3502 }
3503 });
3504
3505
3506 // Create scrollLeft and scrollTop methods
3507 jQuery.each( ['Left', 'Top'], function(i, name) {
3508 var method = 'scroll' + name;
3509
3510 jQuery.fn[ method ] = function(val) {
3511 if (!this[0]) return;
3512
3513 return val != undefined ?
3514
3515 // Set the scroll offset
3516 this.each(function() {
3517 this == window || this == document ?
3518 window.scrollTo(
3519 !i ? val : jQuery(window).scrollLeft(),
3520 i ? val : jQuery(window).scrollTop()
3521 ) :
3522 this[ method ] = val;
3523 }) :
3524
3525 // Return the scroll offset
3526 this[0] == window || this[0] == document ?
3527 self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
3528 jQuery.boxModel && document.documentElement[ method ] ||
3529 document.body[ method ] :
3530 this[0][ method ];
3531 };
3532 });
3533 // Create innerHeight, innerWidth, outerHeight and outerWidth methods
3534 jQuery.each([ "Height", "Width" ], function(i, name){
3535
3536 var tl = i ? "Left" : "Top", // top or left
3537 br = i ? "Right" : "Bottom"; // bottom or right
3538
3539 // innerHeight and innerWidth
3540 jQuery.fn["inner" + name] = function(){
3541 return this[ name.toLowerCase() ]() +
3542 num(this, "padding" + tl) +
3543 num(this, "padding" + br);
3544 };
3545
3546 // outerHeight and outerWidth
3547 jQuery.fn["outer" + name] = function(margin) {
3548 return this["inner" + name]() +
3549 num(this, "border" + tl + "Width") +
3550 num(this, "border" + br + "Width") +
3551 (margin ?
3552 num(this, "margin" + tl) + num(this, "margin" + br) : 0);
3553 };
3554
3555 });})();