1 (function(){
2 /*
3 * jQuery 1.2.6 - 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-05-24 14:22:17 -0400 (Sat, 24 May 2008) $
10 * $Rev: 5685 $
11 */
12
13
14 // Map over jQuery in case of overwrite
15 var _jQuery = window.jQuery,
16 // Map over the $ in case of overwrite
17 _$ = window.$;
18
19 var jQuery = window.jQuery = window.$ = function( selector, context ) {
20 // The jQuery object is actually just the init constructor 'enhanced'
21 return new jQuery.fn.init( selector, context );
22 };
23
24 // A simple way to check for HTML strings or ID strings
25 // (both of which we optimize for)
26 var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,
27
28 // Is it a simple selector
29 isSimple = /^.[^:#\[\.]*$/,
30
31 // Will speed up references to undefined, and allows munging its name.
32 undefined;
33
34 jQuery.fn = jQuery.prototype = {
35 init: function( selector, context ) {
36 // Make sure that a selection was provided
37 selector = selector || document;
38
39 // Handle $(DOMElement)
40 if ( selector.nodeType ) {
41 this[0] = selector;
42 this.length = 1;
43 return this;
44 }
45 // Handle HTML strings
46 if ( typeof selector == "string" ) {
47 // Are we dealing with HTML string or an ID?
48 var match = quickExpr.exec( selector );
49
50 // Verify a match, and that no context was specified for #id
51 if ( match && (match[1] || !context) ) {
52
53 // HANDLE: $(html) -> $(array)
54 if ( match[1] )
55 selector = jQuery.clean( [ match[1] ], context );
56
57 // HANDLE: $("#id")
58 else {
59 var elem = document.getElementById( match[3] );
60
61 // Make sure an element was located
62 if ( elem ){
63 // Handle the case where IE and Opera return items
64 // by name instead of ID
65 if ( elem.id != match[3] )
66 return jQuery().find( selector );
67
68 // Otherwise, we inject the element directly into the jQuery object
69 return jQuery( elem );
70 }
71 selector = [];
72 }
73
74 // HANDLE: $(expr, [context])
75 // (which is just equivalent to: $(content).find(expr)
76 } else
77 return jQuery( context ).find( selector );
78
79 // HANDLE: $(function)
80 // Shortcut for document ready
81 } else if ( jQuery.isFunction( selector ) )
82 return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
83
84 return this.setArray(jQuery.makeArray(selector));
85 },
86
87 // The current version of jQuery being used
88 jquery: "1.2.6",
89
90 // The number of elements contained in the matched element set
91 size: function() {
92 return this.length;
93 },
94
95 // The number of elements contained in the matched element set
96 length: 0,
97
98 // Get the Nth element in the matched element set OR
99 // Get the whole matched element set as a clean array
100 get: function( num ) {
101 return num == undefined ?
102
103 // Return a 'clean' array
104 jQuery.makeArray( this ) :
105
106 // Return just the object
107 this[ num ];
108 },
109
110 // Take an array of elements and push it onto the stack
111 // (returning the new matched element set)
112 pushStack: function( elems ) {
113 // Build a new jQuery matched element set
114 var ret = jQuery( elems );
115
116 // Add the old object onto the stack (as a reference)
117 ret.prevObject = this;
118
119 // Return the newly-formed element set
120 return ret;
121 },
122
123 // Force the current matched set of elements to become
124 // the specified array of elements (destroying the stack in the process)
125 // You should use pushStack() in order to do this, but maintain the stack
126 setArray: function( elems ) {
127 // Resetting the length to 0, then using the native Array push
128 // is a super-fast way to populate an object with array-like properties
129 this.length = 0;
130 Array.prototype.push.apply( this, elems );
131
132 return this;
133 },
134
135 // Execute a callback for every element in the matched set.
136 // (You can seed the arguments with an array of args, but this is
137 // only used internally.)
138 each: function( callback, args ) {
139 return jQuery.each( this, callback, args );
140 },
141
142 // Determine the position of an element within
143 // the matched set of elements
144 index: function( elem ) {
145 var ret = -1;
146
147 // Locate the position of the desired element
148 return jQuery.inArray(
149 // If it receives a jQuery object, the first element is used
150 elem && elem.jquery ? elem[0] : elem
151 , this );
152 },
153
154 attr: function( name, value, type ) {
155 var options = name;
156
157 // Look for the case where we're accessing a style value
158 if ( name.constructor == String )
159 if ( value === undefined )
160 return this[0] && jQuery[ type || "attr" ]( this[0], name );
161
162 else {
163 options = {};
164 options[ name ] = value;
165 }
166
167 // Check to see if we're setting style values
168 return this.each(function(i){
169 // Set all the styles
170 for ( name in options )
171 jQuery.attr(
172 type ?
173 this.style :
174 this,
175 name, jQuery.prop( this, options[ name ], type, i, name )
176 );
177 });
178 },
179
180 css: function( key, value ) {
181 // ignore negative width and height values
182 if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
183 value = undefined;
184 return this.attr( key, value, "curCSS" );
185 },
186
187 text: function( text ) {
188 if ( typeof text != "object" && text != null )
189 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
190
191 var ret = "";
192
193 jQuery.each( text || this, function(){
194 jQuery.each( this.childNodes, function(){
195 if ( this.nodeType != 8 )
196 ret += this.nodeType != 1 ?
197 this.nodeValue :
198 jQuery.fn.text( [ this ] );
199 });
200 });
201
202 return ret;
203 },
204
205 wrapAll: function( html ) {
206 if ( this[0] )
207 // The elements to wrap the target around
208 jQuery( html, this[0].ownerDocument )
209 .clone()
210 .insertBefore( this[0] )
211 .map(function(){
212 var elem = this;
213
214 while ( elem.firstChild )
215 elem = elem.firstChild;
216
217 return elem;
218 })
219 .append(this);
220
221 return this;
222 },
223
224 wrapInner: function( html ) {
225 return this.each(function(){
226 jQuery( this ).contents().wrapAll( html );
227 });
228 },
229
230 wrap: function( html ) {
231 return this.each(function(){
232 jQuery( this ).wrapAll( html );
233 });
234 },
235
236 append: function() {
237 return this.domManip(arguments, true, false, function(elem){
238 if (this.nodeType == 1)
239 this.appendChild( elem );
240 });
241 },
242
243 prepend: function() {
244 return this.domManip(arguments, true, true, function(elem){
245 if (this.nodeType == 1)
246 this.insertBefore( elem, this.firstChild );
247 });
248 },
249
250 before: function() {
251 return this.domManip(arguments, false, false, function(elem){
252 this.parentNode.insertBefore( elem, this );
253 });
254 },
255
256 after: function() {
257 return this.domManip(arguments, false, true, function(elem){
258 this.parentNode.insertBefore( elem, this.nextSibling );
259 });
260 },
261
262 end: function() {
263 return this.prevObject || jQuery( [] );
264 },
265
266 find: function( selector ) {
267 var elems = jQuery.map(this, function(elem){
268 return jQuery.find( selector, elem );
269 });
270
271 return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
272 jQuery.unique( elems ) :
273 elems );
274 },
275
276 clone: function( events ) {
277 // Do the clone
278 var ret = this.map(function(){
279 if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
280 // IE copies events bound via attachEvent when
281 // using cloneNode. Calling detachEvent on the
282 // clone will also remove the events from the orignal
283 // In order to get around this, we use innerHTML.
284 // Unfortunately, this means some modifications to
285 // attributes in IE that are actually only stored
286 // as properties will not be copied (such as the
287 // the name attribute on an input).
288 var clone = this.cloneNode(true),
289 container = document.createElement("div");
290 container.appendChild(clone);
291 return jQuery.clean([container.innerHTML])[0];
292 } else
293 return this.cloneNode(true);
294 });
295
296 // Need to set the expando to null on the cloned set if it exists
297 // removeData doesn't work here, IE removes it from the original as well
298 // this is primarily for IE but the data expando shouldn't be copied over in any browser
299 var clone = ret.find("*").andSelf().each(function(){
300 if ( this[ expando ] != undefined )
301 this[ expando ] = null;
302 });
303
304 // Copy the events from the original to the clone
305 if ( events === true )
306 this.find("*").andSelf().each(function(i){
307 if (this.nodeType == 3)
308 return;
309 var events = jQuery.data( this, "events" );
310
311 for ( var type in events )
312 for ( var handler in events[ type ] )
313 jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
314 });
315
316 // Return the cloned set
317 return ret;
318 },
319
320 filter: function( selector ) {
321 return this.pushStack(
322 jQuery.isFunction( selector ) &&
323 jQuery.grep(this, function(elem, i){
324 return selector.call( elem, i );
325 }) ||
326
327 jQuery.multiFilter( selector, this ) );
328 },
329
330 not: function( selector ) {
331 if ( selector.constructor == String )
332 // test special case where just one selector is passed in
333 if ( isSimple.test( selector ) )
334 return this.pushStack( jQuery.multiFilter( selector, this, true ) );
335 else
336 selector = jQuery.multiFilter( selector, this );
337
338 var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
339 return this.filter(function() {
340 return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
341 });
342 },
343
344 add: function( selector ) {
345 return this.pushStack( jQuery.unique( jQuery.merge(
346 this.get(),
347 typeof selector == 'string' ?
348 jQuery( selector ) :
349 jQuery.makeArray( selector )
350 )));
351 },
352
353 is: function( selector ) {
354 return !!selector && jQuery.multiFilter( selector, this ).length > 0;
355 },
356
357 hasClass: function( selector ) {
358 return this.is( "." + selector );
359 },
360
361 val: function( value ) {
362 if ( value == undefined ) {
363
364 if ( this.length ) {
365 var elem = this[0];
366
367 // We need to handle select boxes special
368 if ( jQuery.nodeName( elem, "select" ) ) {
369 var index = elem.selectedIndex,
370 values = [],
371 options = elem.options,
372 one = elem.type == "select-one";
373
374 // Nothing was selected
375 if ( index < 0 )
376 return null;
377
378 // Loop through all the selected options
379 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
380 var option = options[ i ];
381
382 if ( option.selected ) {
383 // Get the specifc value for the option
384 value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
385
386 // We don't need an array for one selects
387 if ( one )
388 return value;
389
390 // Multi-Selects return an array
391 values.push( value );
392 }
393 }
394
395 return values;
396
397 // Everything else, we just grab the value
398 } else
399 return (this[0].value || "").replace(/\r/g, "");
400
401 }
402
403 return undefined;
404 }
405
406 if( value.constructor == Number )
407 value += '';
408
409 return this.each(function(){
410 if ( this.nodeType != 1 )
411 return;
412
413 if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
414 this.checked = (jQuery.inArray(this.value, value) >= 0 ||
415 jQuery.inArray(this.name, value) >= 0);
416
417 else if ( jQuery.nodeName( this, "select" ) ) {
418 var values = jQuery.makeArray(value);
419
420 jQuery( "option", this ).each(function(){
421 this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
422 jQuery.inArray( this.text, values ) >= 0);
423 });
424
425 if ( !values.length )
426 this.selectedIndex = -1;
427
428 } else
429 this.value = value;
430 });
431 },
432
433 html: function( value ) {
434 return value == undefined ?
435 (this[0] ?
436 this[0].innerHTML :
437 null) :
438 this.empty().append( value );
439 },
440
441 replaceWith: function( value ) {
442 return this.after( value ).remove();
443 },
444
445 eq: function( i ) {
446 return this.slice( i, i + 1 );
447 },
448
449 slice: function() {
450 return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
451 },
452
453 map: function( callback ) {
454 return this.pushStack( jQuery.map(this, function(elem, i){
455 return callback.call( elem, i, elem );
456 }));
457 },
458
459 andSelf: function() {
460 return this.add( this.prevObject );
461 },
462
463 data: function( key, value ){
464 var parts = key.split(".");
465 parts[1] = parts[1] ? "." + parts[1] : "";
466
467 if ( value === undefined ) {
468 var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
469
470 if ( data === undefined && this.length )
471 data = jQuery.data( this[0], key );
472
473 return data === undefined && parts[1] ?
474 this.data( parts[0] ) :
475 data;
476 } else
477 return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
478 jQuery.data( this, key, value );
479 });
480 },
481
482 removeData: function( key ){
483 return this.each(function(){
484 jQuery.removeData( this, key );
485 });
486 },
487
488 domManip: function( args, table, reverse, callback ) {
489 var clone = this.length > 1, elems;
490
491 return this.each(function(){
492 if ( !elems ) {
493 elems = jQuery.clean( args, this.ownerDocument );
494
495 if ( reverse )
496 elems.reverse();
497 }
498
499 var obj = this;
500
501 if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
502 obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
503
504 var scripts = jQuery( [] );
505
506 jQuery.each(elems, function(){
507 var elem = clone ?
508 jQuery( this ).clone( true )[0] :
509 this;
510
511 // execute all scripts after the elements have been injected
512 if ( jQuery.nodeName( elem, "script" ) )
513 scripts = scripts.add( elem );
514 else {
515 // Remove any inner scripts for later evaluation
516 if ( elem.nodeType == 1 )
517 scripts = scripts.add( jQuery( "script", elem ).remove() );
518
519 // Inject the elements into the document
520 callback.call( obj, elem );
521 }
522 });
523
524 scripts.each( evalScript );
525 });
526 }
527 };
528
529 // Give the init function the jQuery prototype for later instantiation
530 jQuery.fn.init.prototype = jQuery.fn;
531
532 function evalScript( i, elem ) {
533 if ( elem.src )
534 jQuery.ajax({
535 url: elem.src,
536 async: false,
537 dataType: "script"
538 });
539
540 else
541 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
542
543 if ( elem.parentNode )
544 elem.parentNode.removeChild( elem );
545 }
546
547 function now(){
548 return +new Date;
549 }
550
551 jQuery.extend = jQuery.fn.extend = function() {
552 // copy reference to target object
553 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
554
555 // Handle a deep copy situation
556 if ( target.constructor == Boolean ) {
557 deep = target;
558 target = arguments[1] || {};
559 // skip the boolean and the target
560 i = 2;
561 }
562
563 // Handle case when target is a string or something (possible in deep copy)
564 if ( typeof target != "object" && typeof target != "function" )
565 target = {};
566
567 // extend jQuery itself if only one argument is passed
568 if ( length == i ) {
569 target = this;
570 --i;
571 }
572
573 for ( ; i < length; i++ )
574 // Only deal with non-null/undefined values
575 if ( (options = arguments[ i ]) != null )
576 // Extend the base object
577 for ( var name in options ) {
578 var src = target[ name ], copy = options[ name ];
579
580 // Prevent never-ending loop
581 if ( target === copy )
582 continue;
583
584 // Recurse if we're merging object values
585 if ( deep && copy && typeof copy == "object" && !copy.nodeType )
586 target[ name ] = jQuery.extend( deep,
587 // Never move original objects, clone them
588 src || ( copy.length != null ? [ ] : { } )
589 , copy );
590
591 // Don't bring in undefined values
592 else if ( copy !== undefined )
593 target[ name ] = copy;
594
595 }
596
597 // Return the modified object
598 return target;
599 };
600
601 var expando = "jQuery" + now(), uuid = 0, windowData = {},
602 // exclude the following css properties to add px
603 exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
604 // cache defaultView
605 defaultView = document.defaultView || {};
606
607 jQuery.extend({
608 noConflict: function( deep ) {
609 window.$ = _$;
610
611 if ( deep )
612 window.jQuery = _jQuery;
613
614 return jQuery;
615 },
616
617 // See test/unit/core.js for details concerning this function.
618 isFunction: function( fn ) {
619 return !!fn && typeof fn != "string" && !fn.nodeName &&
620 fn.constructor != Array && /^[\s[]?function/.test( fn + "" );
621 },
622
623 // check if an element is in a (or is an) XML document
624 isXMLDoc: function( elem ) {
625 return elem.documentElement && !elem.body ||
626 elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
627 },
628
629 // Evalulates a script in a global context
630 globalEval: function( data ) {
631 data = jQuery.trim( data );
632
633 if ( data ) {
634 // Inspired by code by Andrea Giammarchi
635 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
636 var head = document.getElementsByTagName("head")[0] || document.documentElement,
637 script = document.createElement("script");
638
639 script.type = "text/javascript";
640 if ( jQuery.browser.msie )
641 script.text = data;
642 else
643 script.appendChild( document.createTextNode( data ) );
644
645 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
646 // This arises when a base node is used (#2709).
647 head.insertBefore( script, head.firstChild );
648 head.removeChild( script );
649 }
650 },
651
652 nodeName: function( elem, name ) {
653 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
654 },
655
656 cache: {},
657
658 data: function( elem, name, data ) {
659 elem = elem == window ?
660 windowData :
661 elem;
662
663 var id = elem[ expando ];
664
665 // Compute a unique ID for the element
666 if ( !id )
667 id = elem[ expando ] = ++uuid;
668
669 // Only generate the data cache if we're
670 // trying to access or manipulate it
671 if ( name && !jQuery.cache[ id ] )
672 jQuery.cache[ id ] = {};
673
674 // Prevent overriding the named cache with undefined values
675 if ( data !== undefined )
676 jQuery.cache[ id ][ name ] = data;
677
678 // Return the named cache data, or the ID for the element
679 return name ?
680 jQuery.cache[ id ][ name ] :
681 id;
682 },
683
684 removeData: function( elem, name ) {
685 elem = elem == window ?
686 windowData :
687 elem;
688
689 var id = elem[ expando ];
690
691 // If we want to remove a specific section of the element's data
692 if ( name ) {
693 if ( jQuery.cache[ id ] ) {
694 // Remove the section of cache data
695 delete jQuery.cache[ id ][ name ];
696
697 // If we've removed all the data, remove the element's cache
698 name = "";
699
700 for ( name in jQuery.cache[ id ] )
701 break;
702
703 if ( !name )
704 jQuery.removeData( elem );
705 }
706
707 // Otherwise, we want to remove all of the element's data
708 } else {
709 // Clean up the element expando
710 try {
711 delete elem[ expando ];
712 } catch(e){
713 // IE has trouble directly removing the expando
714 // but it's ok with using removeAttribute
715 if ( elem.removeAttribute )
716 elem.removeAttribute( expando );
717 }
718
719 // Completely remove the data cache
720 delete jQuery.cache[ id ];
721 }
722 },
723
724 // args is for internal usage only
725 each: function( object, callback, args ) {
726 var name, i = 0, length = object.length;
727
728 if ( args ) {
729 if ( length == undefined ) {
730 for ( name in object )
731 if ( callback.apply( object[ name ], args ) === false )
732 break;
733 } else
734 for ( ; i < length; )
735 if ( callback.apply( object[ i++ ], args ) === false )
736 break;
737
738 // A special, fast, case for the most common use of each
739 } else {
740 if ( length == undefined ) {
741 for ( name in object )
742 if ( callback.call( object[ name ], name, object[ name ] ) === false )
743 break;
744 } else
745 for ( var value = object[0];
746 i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
747 }
748
749 return object;
750 },
751
752 prop: function( elem, value, type, i, name ) {
753 // Handle executable functions
754 if ( jQuery.isFunction( value ) )
755 value = value.call( elem, i );
756
757 // Handle passing in a number to a CSS property
758 return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
759 value + "px" :
760 value;
761 },
762
763 className: {
764 // internal only, use addClass("class")
765 add: function( elem, classNames ) {
766 jQuery.each((classNames || "").split(/\s+/), function(i, className){
767 if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
768 elem.className += (elem.className ? " " : "") + className;
769 });
770 },
771
772 // internal only, use removeClass("class")
773 remove: function( elem, classNames ) {
774 if (elem.nodeType == 1)
775 elem.className = classNames != undefined ?
776 jQuery.grep(elem.className.split(/\s+/), function(className){
777 return !jQuery.className.has( classNames, className );
778 }).join(" ") :
779 "";
780 },
781
782 // internal only, use hasClass("class")
783 has: function( elem, className ) {
784 return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
785 }
786 },
787
788 // A method for quickly swapping in/out CSS properties to get correct calculations
789 swap: function( elem, options, callback ) {
790 var old = {};
791 // Remember the old values, and insert the new ones
792 for ( var name in options ) {
793 old[ name ] = elem.style[ name ];
794 elem.style[ name ] = options[ name ];
795 }
796
797 callback.call( elem );
798
799 // Revert the old values
800 for ( var name in options )
801 elem.style[ name ] = old[ name ];
802 },
803
804 css: function( elem, name, force ) {
805 if ( name == "width" || name == "height" ) {
806 var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
807
808 function getWH() {
809 val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
810 var padding = 0, border = 0;
811 jQuery.each( which, function() {
812 padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
813 border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
814 });
815 val -= Math.round(padding + border);
816 }
817
818 if ( jQuery(elem).is(":visible") )
819 getWH();
820 else
821 jQuery.swap( elem, props, getWH );
822
823 return Math.max(0, val);
824 }
825
826 return jQuery.curCSS( elem, name, force );
827 },
828
829 curCSS: function( elem, name, force ) {
830 var ret, style = elem.style;
831
832 // A helper method for determining if an element's values are broken
833 function color( elem ) {
834 if ( !jQuery.browser.safari )
835 return false;
836
837 // defaultView is cached
838 var ret = defaultView.getComputedStyle( elem, null );
839 return !ret || ret.getPropertyValue("color") == "";
840 }
841
842 // We need to handle opacity special in IE
843 if ( name == "opacity" && jQuery.browser.msie ) {
844 ret = jQuery.attr( style, "opacity" );
845
846 return ret == "" ?
847 "1" :
848 ret;
849 }
850 // Opera sometimes will give the wrong display answer, this fixes it, see #2037
851 if ( jQuery.browser.opera && name == "display" ) {
852 var save = style.outline;
853 style.outline = "0 solid black";
854 style.outline = save;
855 }
856
857 // Make sure we're using the right name for getting the float value
858 if ( name.match( /float/i ) )
859 name = styleFloat;
860
861 if ( !force && style && style[ name ] )
862 ret = style[ name ];
863
864 else if ( defaultView.getComputedStyle ) {
865
866 // Only "float" is needed here
867 if ( name.match( /float/i ) )
868 name = "float";
869
870 name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
871
872 var computedStyle = defaultView.getComputedStyle( elem, null );
873
874 if ( computedStyle && !color( elem ) )
875 ret = computedStyle.getPropertyValue( name );
876
877 // If the element isn't reporting its values properly in Safari
878 // then some display: none elements are involved
879 else {
880 var swap = [], stack = [], a = elem, i = 0;
881
882 // Locate all of the parent display: none elements
883 for ( ; a && color(a); a = a.parentNode )
884 stack.unshift(a);
885
886 // Go through and make them visible, but in reverse
887 // (It would be better if we knew the exact display type that they had)
888 for ( ; i < stack.length; i++ )
889 if ( color( stack[ i ] ) ) {
890 swap[ i ] = stack[ i ].style.display;
891 stack[ i ].style.display = "block";
892 }
893
894 // Since we flip the display style, we have to handle that
895 // one special, otherwise get the value
896 ret = name == "display" && swap[ stack.length - 1 ] != null ?
897 "none" :
898 ( computedStyle && computedStyle.getPropertyValue( name ) ) || "";
899
900 // Finally, revert the display styles back
901 for ( i = 0; i < swap.length; i++ )
902 if ( swap[ i ] != null )
903 stack[ i ].style.display = swap[ i ];
904 }
905
906 // We should always get a number back from opacity
907 if ( name == "opacity" && ret == "" )
908 ret = "1";
909
910 } else if ( elem.currentStyle ) {
911 var camelCase = name.replace(/\-(\w)/g, function(all, letter){
912 return letter.toUpperCase();
913 });
914
915 ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
916
917 // From the awesome hack by Dean Edwards
918 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
919
920 // If we're not dealing with a regular pixel number
921 // but a number that has a weird ending, we need to convert it to pixels
922 if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
923 // Remember the original values
924 var left = style.left, rsLeft = elem.runtimeStyle.left;
925
926 // Put in the new values to get a computed value out
927 elem.runtimeStyle.left = elem.currentStyle.left;
928 style.left = ret || 0;
929 ret = style.pixelLeft + "px";
930
931 // Revert the changed values
932 style.left = left;
933 elem.runtimeStyle.left = rsLeft;
934 }
935 }
936
937 return ret;
938 },
939
940 clean: function( elems, context ) {
941 var ret = [];
942 context = context || document;
943 // !context.createElement fails in IE with an error but returns typeof 'object'
944 if (typeof context.createElement == 'undefined')
945 context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
946
947 jQuery.each(elems, function(i, elem){
948 if ( !elem )
949 return;
950
951 if ( elem.constructor == Number )
952 elem += '';
953
954 // Convert html string into DOM nodes
955 if ( typeof elem == "string" ) {
956 // Fix "XHTML"-style tags in all browsers
957 elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
958 return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
959 all :
960 front + "></" + tag + ">";
961 });
962
963 // Trim whitespace, otherwise indexOf won't work as expected
964 var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
965
966 var wrap =
967 // option or optgroup
968 !tags.indexOf("<opt") &&
969 [ 1, "<select multiple='multiple'>", "</select>" ] ||
970
971 !tags.indexOf("<leg") &&
972 [ 1, "<fieldset>", "</fieldset>" ] ||
973
974 tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
975 [ 1, "<table>", "</table>" ] ||
976
977 !tags.indexOf("<tr") &&
978 [ 2, "<table><tbody>", "</tbody></table>" ] ||
979
980 // <thead> matched above
981 (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
982 [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
983
984 !tags.indexOf("<col") &&
985 [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
986
987 // IE can't serialize <link> and <script> tags normally
988 jQuery.browser.msie &&
989 [ 1, "div<div>", "</div>" ] ||
990
991 [ 0, "", "" ];
992
993 // Go to html and back, then peel off extra wrappers
994 div.innerHTML = wrap[1] + elem + wrap[2];
995
996 // Move to the right depth
997 while ( wrap[0]-- )
998 div = div.lastChild;
999
1000 // Remove IE's autoinserted <tbody> from table fragments
1001 if ( jQuery.browser.msie ) {
1002
1003 // String was a <table>, *may* have spurious <tbody>
1004 var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
1005 div.firstChild && div.firstChild.childNodes :
1006
1007 // String was a bare <thead> or <tfoot>
1008 wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
1009 div.childNodes :
1010 [];
1011
1012 for ( var j = tbody.length - 1; j >= 0 ; --j )
1013 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
1014 tbody[ j ].parentNode.removeChild( tbody[ j ] );
1015
1016 // IE completely kills leading whitespace when innerHTML is used
1017 if ( /^\s/.test( elem ) )
1018 div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
1019
1020 }
1021
1022 elem = jQuery.makeArray( div.childNodes );
1023 }
1024
1025 if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
1026 return;
1027
1028 if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
1029 ret.push( elem );
1030
1031 else
1032 ret = jQuery.merge( ret, elem );
1033
1034 });
1035
1036 return ret;
1037 },
1038
1039 attr: function( elem, name, value ) {
1040 // don't set attributes on text and comment nodes
1041 if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
1042 return undefined;
1043
1044 var notxml = !jQuery.isXMLDoc( elem ),
1045 // Whether we are setting (or getting)
1046 set = value !== undefined,
1047 msie = jQuery.browser.msie;
1048
1049 // Try to normalize/fix the name
1050 name = notxml && jQuery.props[ name ] || name;
1051
1052 // Only do all the following if this is a node (faster for style)
1053 // IE elem.getAttribute passes even for style
1054 if ( elem.tagName ) {
1055
1056 // These attributes require special treatment
1057 var special = /href|src|style/.test( name );
1058
1059 // Safari mis-reports the default selected property of a hidden option
1060 // Accessing the parent's selectedIndex property fixes it
1061 if ( name == "selected" && jQuery.browser.safari )
1062 elem.parentNode.selectedIndex;
1063
1064 // If applicable, access the attribute via the DOM 0 way
1065 if ( name in elem && notxml && !special ) {
1066 if ( set ){
1067 // We can't allow the type property to be changed (since it causes problems in IE)
1068 if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
1069 throw "type property can't be changed";
1070
1071 elem[ name ] = value;
1072 }
1073
1074 // browsers index elements by id/name on forms, give priority to attributes.
1075 if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
1076 return elem.getAttributeNode( name ).nodeValue;
1077
1078 return elem[ name ];
1079 }
1080
1081 if ( msie && notxml && name == "style" )
1082 return jQuery.attr( elem.style, "cssText", value );
1083
1084 if ( set )
1085 // convert the value to a string (all browsers do this but IE) see #1070
1086 elem.setAttribute( name, "" + value );
1087
1088 var attr = msie && notxml && special
1089 // Some attributes require a special call on IE
1090 ? elem.getAttribute( name, 2 )
1091 : elem.getAttribute( name );
1092
1093 // Non-existent attributes return null, we normalize to undefined
1094 return attr === null ? undefined : attr;
1095 }
1096
1097 // elem is actually elem.style ... set the style
1098
1099 // IE uses filters for opacity
1100 if ( msie && name == "opacity" ) {
1101 if ( set ) {
1102 // IE has trouble with opacity if it does not have layout
1103 // Force it by setting the zoom level
1104 elem.zoom = 1;
1105
1106 // Set the alpha filter to set the opacity
1107 elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
1108 (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
1109 }
1110
1111 return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
1112 (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
1113 "";
1114 }
1115
1116 name = name.replace(/-([a-z])/ig, function(all, letter){
1117 return letter.toUpperCase();
1118 });
1119
1120 if ( set )
1121 elem[ name ] = value;
1122
1123 return elem[ name ];
1124 },
1125
1126 trim: function( text ) {
1127 return (text || "").replace( /^\s+|\s+$/g, "" );
1128 },
1129
1130 makeArray: function( array ) {
1131 var ret = [];
1132
1133 if( array != null ){
1134 var i = array.length;
1135 //the window, strings and functions also have 'length'
1136 if( i == null || array.split || array.setInterval || array.call )
1137 ret[0] = array;
1138 else
1139 while( i )
1140 ret[--i] = array[i];
1141 }
1142
1143 return ret;
1144 },
1145
1146 inArray: function( elem, array ) {
1147 for ( var i = 0, length = array.length; i < length; i++ )
1148 // Use === because on IE, window == document
1149 if ( array[ i ] === elem )
1150 return i;
1151
1152 return -1;
1153 },
1154
1155 merge: function( first, second ) {
1156 // We have to loop this way because IE & Opera overwrite the length
1157 // expando of getElementsByTagName
1158 var i = 0, elem, pos = first.length;
1159 // Also, we need to make sure that the correct elements are being returned
1160 // (IE returns comment nodes in a '*' query)
1161 if ( jQuery.browser.msie ) {
1162 while ( elem = second[ i++ ] )
1163 if ( elem.nodeType != 8 )
1164 first[ pos++ ] = elem;
1165
1166 } else
1167 while ( elem = second[ i++ ] )
1168 first[ pos++ ] = elem;
1169
1170 return first;
1171 },
1172
1173 unique: function( array ) {
1174 var ret = [], done = {};
1175
1176 try {
1177
1178 for ( var i = 0, length = array.length; i < length; i++ ) {
1179 var id = jQuery.data( array[ i ] );
1180
1181 if ( !done[ id ] ) {
1182 done[ id ] = true;
1183 ret.push( array[ i ] );
1184 }
1185 }
1186
1187 } catch( e ) {
1188 ret = array;
1189 }
1190
1191 return ret;
1192 },
1193
1194 grep: function( elems, callback, inv ) {
1195 var ret = [];
1196
1197 // Go through the array, only saving the items
1198 // that pass the validator function
1199 for ( var i = 0, length = elems.length; i < length; i++ )
1200 if ( !inv != !callback( elems[ i ], i ) )
1201 ret.push( elems[ i ] );
1202
1203 return ret;
1204 },
1205
1206 map: function( elems, callback ) {
1207 var ret = [];
1208
1209 // Go through the array, translating each of the items to their
1210 // new value (or values).
1211 for ( var i = 0, length = elems.length; i < length; i++ ) {
1212 var value = callback( elems[ i ], i );
1213
1214 if ( value != null )
1215 ret[ ret.length ] = value;
1216 }
1217
1218 return ret.concat.apply( [], ret );
1219 }
1220 });
1221
1222 var userAgent = navigator.userAgent.toLowerCase();
1223
1224 // Figure out what browser is being used
1225 jQuery.browser = {
1226 version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
1227 safari: /webkit/.test( userAgent ),
1228 opera: /opera/.test( userAgent ),
1229 msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
1230 mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
1231 };
1232
1233 var styleFloat = jQuery.browser.msie ?
1234 "styleFloat" :
1235 "cssFloat";
1236
1237 jQuery.extend({
1238 // Check to see if the W3C box model is being used
1239 boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
1240
1241 props: {
1242 "for": "htmlFor",
1243 "class": "className",
1244 "float": styleFloat,
1245 cssFloat: styleFloat,
1246 styleFloat: styleFloat,
1247 readonly: "readOnly",
1248 maxlength: "maxLength",
1249 cellspacing: "cellSpacing"
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 }var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
1373 "(?:[\\w*_-]|\\\\.)" :
1374 "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
1375 quickChild = new RegExp("^>\\s*(" + chars + "+)"),
1376 quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
1377 quickClass = new RegExp("^([#.]?)(" + chars + "*)");
1378
1379 jQuery.extend({
1380 expr: {
1381 "": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
1382 "#": function(a,i,m){return a.getAttribute("id")==m[2];},
1383 ":": {
1384 // Position Checks
1385 lt: function(a,i,m){return i<m[3]-0;},
1386 gt: function(a,i,m){return i>m[3]-0;},
1387 nth: function(a,i,m){return m[3]-0==i;},
1388 eq: function(a,i,m){return m[3]-0==i;},
1389 first: function(a,i){return i==0;},
1390 last: function(a,i,m,r){return i==r.length-1;},
1391 even: function(a,i){return i%2==0;},
1392 odd: function(a,i){return i%2;},
1393
1394 // Child Checks
1395 "first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
1396 "last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
1397 "only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
1398
1399 // Parent Checks
1400 parent: function(a){return a.firstChild;},
1401 empty: function(a){return !a.firstChild;},
1402
1403 // Text Check
1404 contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
1405
1406 // Visibility
1407 visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
1408 hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
1409
1410 // Form attributes
1411 enabled: function(a){return !a.disabled;},
1412 disabled: function(a){return a.disabled;},
1413 checked: function(a){return a.checked;},
1414 selected: function(a){return a.selected||jQuery.attr(a,"selected");},
1415
1416 // Form elements
1417 text: function(a){return "text"==a.type;},
1418 radio: function(a){return "radio"==a.type;},
1419 checkbox: function(a){return "checkbox"==a.type;},
1420 file: function(a){return "file"==a.type;},
1421 password: function(a){return "password"==a.type;},
1422 submit: function(a){return "submit"==a.type;},
1423 image: function(a){return "image"==a.type;},
1424 reset: function(a){return "reset"==a.type;},
1425 button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
1426 input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
1427
1428 // :has()
1429 has: function(a,i,m){return jQuery.find(m[3],a).length;},
1430
1431 // :header
1432 header: function(a){return /h\d/i.test(a.nodeName);},
1433
1434 // :animated
1435 animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
1436 }
1437 },
1438
1439 // The regular expressions that power the parsing engine
1440 parse: [
1441 // Match: [@value='test'], [@foo]
1442 /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
1443
1444 // Match: :contains('foo')
1445 /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
1446
1447 // Match: :even, :last-child, #id, .class
1448 new RegExp("^([:.#]*)(" + chars + "+)")
1449 ],
1450
1451 multiFilter: function( expr, elems, not ) {
1452 var old, cur = [];
1453
1454 while ( expr && expr != old ) {
1455 old = expr;
1456 var f = jQuery.filter( expr, elems, not );
1457 expr = f.t.replace(/^\s*,\s*/, "" );
1458 cur = not ? elems = f.r : jQuery.merge( cur, f.r );
1459 }
1460
1461 return cur;
1462 },
1463
1464 find: function( t, context ) {
1465 // Quickly handle non-string expressions
1466 if ( typeof t != "string" )
1467 return [ t ];
1468
1469 // check to make sure context is a DOM element or a document
1470 if ( context && context.nodeType != 1 && context.nodeType != 9)
1471 return [ ];
1472
1473 // Set the correct context (if none is provided)
1474 context = context || document;
1475
1476 // Initialize the search
1477 var ret = [context], done = [], last, nodeName;
1478
1479 // Continue while a selector expression exists, and while
1480 // we're no longer looping upon ourselves
1481 while ( t && last != t ) {
1482 var r = [];
1483 last = t;
1484
1485 t = jQuery.trim(t);
1486
1487 var foundToken = false,
1488
1489 // An attempt at speeding up child selectors that
1490 // point to a specific element tag
1491 re = quickChild,
1492
1493 m = re.exec(t);
1494
1495 if ( m ) {
1496 nodeName = m[1].toUpperCase();
1497
1498 // Perform our own iteration and filter
1499 for ( var i = 0; ret[i]; i++ )
1500 for ( var c = ret[i].firstChild; c; c = c.nextSibling )
1501 if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
1502 r.push( c );
1503
1504 ret = r;
1505 t = t.replace( re, "" );
1506 if ( t.indexOf(" ") == 0 ) continue;
1507 foundToken = true;
1508 } else {
1509 re = /^([>+~])\s*(\w*)/i;
1510
1511 if ( (m = re.exec(t)) != null ) {
1512 r = [];
1513
1514 var merge = {};
1515 nodeName = m[2].toUpperCase();
1516 m = m[1];
1517
1518 for ( var j = 0, rl = ret.length; j < rl; j++ ) {
1519 var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
1520 for ( ; n; n = n.nextSibling )
1521 if ( n.nodeType == 1 ) {
1522 var id = jQuery.data(n);
1523
1524 if ( m == "~" && merge[id] ) break;
1525
1526 if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
1527 if ( m == "~" ) merge[id] = true;
1528 r.push( n );
1529 }
1530
1531 if ( m == "+" ) break;
1532 }
1533 }
1534
1535 ret = r;
1536
1537 // And remove the token
1538 t = jQuery.trim( t.replace( re, "" ) );
1539 foundToken = true;
1540 }
1541 }
1542
1543 // See if there's still an expression, and that we haven't already
1544 // matched a token
1545 if ( t && !foundToken ) {
1546 // Handle multiple expressions
1547 if ( !t.indexOf(",") ) {
1548 // Clean the result set
1549 if ( context == ret[0] ) ret.shift();
1550
1551 // Merge the result sets
1552 done = jQuery.merge( done, ret );
1553
1554 // Reset the context
1555 r = ret = [context];
1556
1557 // Touch up the selector string
1558 t = " " + t.substr(1,t.length);
1559
1560 } else {
1561 // Optimize for the case nodeName#idName
1562 var re2 = quickID;
1563 var m = re2.exec(t);
1564
1565 // Re-organize the results, so that they're consistent
1566 if ( m ) {
1567 m = [ 0, m[2], m[3], m[1] ];
1568
1569 } else {
1570 // Otherwise, do a traditional filter check for
1571 // ID, class, and element selectors
1572 re2 = quickClass;
1573 m = re2.exec(t);
1574 }
1575
1576 m[2] = m[2].replace(/\\/g, "");
1577
1578 var elem = ret[ret.length-1];
1579
1580 // Try to do a global search by ID, where we can
1581 if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
1582 // Optimization for HTML document case
1583 var oid = elem.getElementById(m[2]);
1584
1585 // Do a quick check for the existence of the actual ID attribute
1586 // to avoid selecting by the name attribute in IE
1587 // also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
1588 if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
1589 oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
1590
1591 // Do a quick check for node name (where applicable) so
1592 // that div#foo searches will be really fast
1593 ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
1594 } else {
1595 // We need to find all descendant elements
1596 for ( var i = 0; ret[i]; i++ ) {
1597 // Grab the tag name being searched for
1598 var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
1599
1600 // Handle IE7 being really dumb about <object>s
1601 if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
1602 tag = "param";
1603
1604 r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
1605 }
1606
1607 // It's faster to filter by class and be done with it
1608 if ( m[1] == "." )
1609 r = jQuery.classFilter( r, m[2] );
1610
1611 // Same with ID filtering
1612 if ( m[1] == "#" ) {
1613 var tmp = [];
1614
1615 // Try to find the element with the ID
1616 for ( var i = 0; r[i]; i++ )
1617 if ( r[i].getAttribute("id") == m[2] ) {
1618 tmp = [ r[i] ];
1619 break;
1620 }
1621
1622 r = tmp;
1623 }
1624
1625 ret = r;
1626 }
1627
1628 t = t.replace( re2, "" );
1629 }
1630
1631 }
1632
1633 // If a selector string still exists
1634 if ( t ) {
1635 // Attempt to filter it
1636 var val = jQuery.filter(t,r);
1637 ret = r = val.r;
1638 t = jQuery.trim(val.t);
1639 }
1640 }
1641
1642 // An error occurred with the selector;
1643 // just return an empty set instead
1644 if ( t )
1645 ret = [];
1646
1647 // Remove the root context
1648 if ( ret && context == ret[0] )
1649 ret.shift();
1650
1651 // And combine the results
1652 done = jQuery.merge( done, ret );
1653
1654 return done;
1655 },
1656
1657 classFilter: function(r,m,not){
1658 m = " " + m + " ";
1659 var tmp = [];
1660 for ( var i = 0; r[i]; i++ ) {
1661 var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
1662 if ( !not && pass || not && !pass )
1663 tmp.push( r[i] );
1664 }
1665 return tmp;
1666 },
1667
1668 filter: function(t,r,not) {
1669 var last;
1670
1671 // Look for common filter expressions
1672 while ( t && t != last ) {
1673 last = t;
1674
1675 var p = jQuery.parse, m;
1676
1677 for ( var i = 0; p[i]; i++ ) {
1678 m = p[i].exec( t );
1679
1680 if ( m ) {
1681 // Remove what we just matched
1682 t = t.substring( m[0].length );
1683
1684 m[2] = m[2].replace(/\\/g, "");
1685 break;
1686 }
1687 }
1688
1689 if ( !m )
1690 break;
1691
1692 // :not() is a special case that can be optimized by
1693 // keeping it out of the expression list
1694 if ( m[1] == ":" && m[2] == "not" )
1695 // optimize if only one selector found (most common case)
1696 r = isSimple.test( m[3] ) ?
1697 jQuery.filter(m[3], r, true).r :
1698 jQuery( r ).not( m[3] );
1699
1700 // We can get a big speed boost by filtering by class here
1701 else if ( m[1] == "." )
1702 r = jQuery.classFilter(r, m[2], not);
1703
1704 else if ( m[1] == "[" ) {
1705 var tmp = [], type = m[3];
1706
1707 for ( var i = 0, rl = r.length; i < rl; i++ ) {
1708 var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
1709
1710 if ( z == null || /href|src|selected/.test(m[2]) )
1711 z = jQuery.attr(a,m[2]) || '';
1712
1713 if ( (type == "" && !!z ||
1714 type == "=" && z == m[5] ||
1715 type == "!=" && z != m[5] ||
1716 type == "^=" && z && !z.indexOf(m[5]) ||
1717 type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
1718 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
1719 tmp.push( a );
1720 }
1721
1722 r = tmp;
1723
1724 // We can get a speed boost by handling nth-child here
1725 } else if ( m[1] == ":" && m[2] == "nth-child" ) {
1726 var merge = {}, tmp = [],
1727 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
1728 test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
1729 m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
1730 !/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
1731 // calculate the numbers (first)n+(last) including if they are negative
1732 first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
1733
1734 // loop through all the elements left in the jQuery object
1735 for ( var i = 0, rl = r.length; i < rl; i++ ) {
1736 var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
1737
1738 if ( !merge[id] ) {
1739 var c = 1;
1740
1741 for ( var n = parentNode.firstChild; n; n = n.nextSibling )
1742 if ( n.nodeType == 1 )
1743 n.nodeIndex = c++;
1744
1745 merge[id] = true;
1746 }
1747
1748 var add = false;
1749
1750 if ( first == 0 ) {
1751 if ( node.nodeIndex == last )
1752 add = true;
1753 } else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
1754 add = true;
1755
1756 if ( add ^ not )
1757 tmp.push( node );
1758 }
1759
1760 r = tmp;
1761
1762 // Otherwise, find the expression to execute
1763 } else {
1764 var fn = jQuery.expr[ m[1] ];
1765 if ( typeof fn == "object" )
1766 fn = fn[ m[2] ];
1767
1768 if ( typeof fn == "string" )
1769 fn = eval("false||function(a,i){return " + fn + ";}");
1770
1771 // Execute it against the current filter
1772 r = jQuery.grep( r, function(elem, i){
1773 return fn(elem, i, m, r);
1774 }, not );
1775 }
1776 }
1777
1778 // Return an array of filtered elements (r)
1779 // and the modified expression string (t)
1780 return { r: r, t: t };
1781 },
1782
1783 dir: function( elem, dir ){
1784 var matched = [],
1785 cur = elem[dir];
1786 while ( cur && cur != document ) {
1787 if ( cur.nodeType == 1 )
1788 matched.push( cur );
1789 cur = cur[dir];
1790 }
1791 return matched;
1792 },
1793
1794 nth: function(cur,result,dir,elem){
1795 result = result || 1;
1796 var num = 0;
1797
1798 for ( ; cur; cur = cur[dir] )
1799 if ( cur.nodeType == 1 && ++num == result )
1800 break;
1801
1802 return cur;
1803 },
1804
1805 sibling: function( n, elem ) {
1806 var r = [];
1807
1808 for ( ; n; n = n.nextSibling ) {
1809 if ( n.nodeType == 1 && n != elem )
1810 r.push( n );
1811 }
1812
1813 return r;
1814 }
1815 });
1816 /*
1817 * A number of helper functions used for managing events.
1818 * Many of the ideas behind this code orignated from
1819 * Dean Edwards' addEvent library.
1820 */
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("*").add([window, document]).trigger(type, data);
1988
1989 // Handle triggering a single element
1990 } else {
1991 // don't do events on text and comment nodes
1992 if ( elem.nodeType == 3 || elem.nodeType == 8 )
1993 return undefined;
1994
1995 var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
1996 // Check to see if we need to provide a fake event, or not
1997 event = !data[0] || !data[0].preventDefault;
1998
1999 // Pass along a fake event
2000 if ( event ) {
2001 data.unshift({
2002 type: type,
2003 target: elem,
2004 preventDefault: function(){},
2005 stopPropagation: function(){},
2006 timeStamp: now()
2007 });
2008 data[0][expando] = true; // no need to fix fake event
2009 }
2010
2011 // Enforce the right trigger type
2012 data[0].type = type;
2013 if ( exclusive )
2014 data[0].exclusive = true;
2015
2016 // Trigger the event, it is assumed that "handle" is a function
2017 var handle = jQuery.data(elem, "handle");
2018 if ( handle )
2019 val = handle.apply( elem, data );
2020
2021 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
2022 if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
2023 val = false;
2024
2025 // Extra functions don't get the custom event object
2026 if ( event )
2027 data.shift();
2028
2029 // Handle triggering of extra function
2030 if ( extra && jQuery.isFunction( extra ) ) {
2031 // call the extra function and tack the current return value on the end for possible inspection
2032 ret = extra.apply( elem, val == null ? data : data.concat( val ) );
2033 // if anything is returned, give it precedence and have it overwrite the previous value
2034 if (ret !== undefined)
2035 val = ret;
2036 }
2037
2038 // Trigger the native events (except for clicks on links)
2039 if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
2040 this.triggered = true;
2041 try {
2042 elem[ type ]();
2043 // prevent IE from throwing an error for some hidden elements
2044 } catch (e) {}
2045 }
2046
2047 this.triggered = false;
2048 }
2049
2050 return val;
2051 },
2052
2053 handle: function(event) {
2054 // returned undefined or false
2055 var val, ret, namespace, all, handlers;
2056
2057 event = arguments[0] = jQuery.event.fix( event || window.event );
2058
2059 // Namespaced event handlers
2060 namespace = event.type.split(".");
2061 event.type = namespace[0];
2062 namespace = namespace[1];
2063 // Cache this now, all = true means, any handler
2064 all = !namespace && !event.exclusive;
2065
2066 handlers = ( jQuery.data(this, "events") || {} )[event.type];
2067
2068 for ( var j in handlers ) {
2069 var handler = handlers[j];
2070
2071 // Filter the functions by class
2072 if ( all || handler.type == namespace ) {
2073 // Pass in a reference to the handler function itself
2074 // So that we can later remove it
2075 event.handler = handler;
2076 event.data = handler.data;
2077
2078 ret = handler.apply( this, arguments );
2079
2080 if ( val !== false )
2081 val = ret;
2082
2083 if ( ret === false ) {
2084 event.preventDefault();
2085 event.stopPropagation();
2086 }
2087 }
2088 }
2089
2090 return val;
2091 },
2092
2093 fix: function(event) {
2094 if ( event[expando] == true )
2095 return event;
2096
2097 // store a copy of the original event object
2098 // and "clone" to set read-only properties
2099 var originalEvent = event;
2100 event = { originalEvent: originalEvent };
2101 var 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(" ");
2102 for ( var i=props.length; i; i-- )
2103 event[ props[i] ] = originalEvent[ props[i] ];
2104
2105 // Mark it as fixed
2106 event[expando] = true;
2107
2108 // add preventDefault and stopPropagation since
2109 // they will not work on the clone
2110 event.preventDefault = function() {
2111 // if preventDefault exists run it on the original event
2112 if (originalEvent.preventDefault)
2113 originalEvent.preventDefault();
2114 // otherwise set the returnValue property of the original event to false (IE)
2115 originalEvent.returnValue = false;
2116 };
2117 event.stopPropagation = function() {
2118 // if stopPropagation exists run it on the original event
2119 if (originalEvent.stopPropagation)
2120 originalEvent.stopPropagation();
2121 // otherwise set the cancelBubble property of the original event to true (IE)
2122 originalEvent.cancelBubble = true;
2123 };
2124
2125 // Fix timeStamp
2126 event.timeStamp = event.timeStamp || now();
2127
2128 // Fix target property, if necessary
2129 if ( !event.target )
2130 event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
2131
2132 // check if target is a textnode (safari)
2133 if ( event.target.nodeType == 3 )
2134 event.target = event.target.parentNode;
2135
2136 // Add relatedTarget, if necessary
2137 if ( !event.relatedTarget && event.fromElement )
2138 event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
2139
2140 // Calculate pageX/Y if missing and clientX/Y available
2141 if ( event.pageX == null && event.clientX != null ) {
2142 var doc = document.documentElement, body = document.body;
2143 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
2144 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
2145 }
2146
2147 // Add which for key events
2148 if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
2149 event.which = event.charCode || event.keyCode;
2150
2151 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
2152 if ( !event.metaKey && event.ctrlKey )
2153 event.metaKey = event.ctrlKey;
2154
2155 // Add which for click: 1 == left; 2 == middle; 3 == right
2156 // Note: button is not normalized, so don't use it
2157 if ( !event.which && event.button )
2158 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2159
2160 return event;
2161 },
2162
2163 proxy: function( fn, proxy ){
2164 // Set the guid of unique handler to the same of original handler, so it can be removed
2165 proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
2166 // So proxy can be declared as an argument
2167 return proxy;
2168 },
2169
2170 special: {
2171 ready: {
2172 setup: function() {
2173 // Make sure the ready event is setup
2174 bindReady();
2175 return;
2176 },
2177
2178 teardown: function() { return; }
2179 },
2180
2181 mouseenter: {
2182 setup: function() {
2183 if ( jQuery.browser.msie ) return false;
2184 jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
2185 return true;
2186 },
2187
2188 teardown: function() {
2189 if ( jQuery.browser.msie ) return false;
2190 jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
2191 return true;
2192 },
2193
2194 handler: function(event) {
2195 // If we actually just moused on to a sub-element, ignore it
2196 if ( withinElement(event, this) ) return true;
2197 // Execute the right handlers by setting the event type to mouseenter
2198 event.type = "mouseenter";
2199 return jQuery.event.handle.apply(this, arguments);
2200 }
2201 },
2202
2203 mouseleave: {
2204 setup: function() {
2205 if ( jQuery.browser.msie ) return false;
2206 jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
2207 return true;
2208 },
2209
2210 teardown: function() {
2211 if ( jQuery.browser.msie ) return false;
2212 jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
2213 return true;
2214 },
2215
2216 handler: function(event) {
2217 // If we actually just moused on to a sub-element, ignore it
2218 if ( withinElement(event, this) ) return true;
2219 // Execute the right handlers by setting the event type to mouseleave
2220 event.type = "mouseleave";
2221 return jQuery.event.handle.apply(this, arguments);
2222 }
2223 }
2224 }
2225 };
2226
2227 jQuery.fn.extend({
2228 bind: function( type, data, fn ) {
2229 return type == "unload" ? this.one(type, data, fn) : this.each(function(){
2230 jQuery.event.add( this, type, fn || data, fn && data );
2231 });
2232 },
2233
2234 one: function( type, data, fn ) {
2235 var one = jQuery.event.proxy( fn || data, function(event) {
2236 jQuery(this).unbind(event, one);
2237 return (fn || data).apply( this, arguments );
2238 });
2239 return this.each(function(){
2240 jQuery.event.add( this, type, one, fn && data);
2241 });
2242 },
2243
2244 unbind: function( type, fn ) {
2245 return this.each(function(){
2246 jQuery.event.remove( this, type, fn );
2247 });
2248 },
2249
2250 trigger: function( type, data, fn ) {
2251 return this.each(function(){
2252 jQuery.event.trigger( type, data, this, true, fn );
2253 });
2254 },
2255
2256 triggerHandler: function( type, data, fn ) {
2257 return this[0] && jQuery.event.trigger( type, data, this[0], false, fn );
2258 },
2259
2260 toggle: function( fn ) {
2261 // Save reference to arguments for access in closure
2262 var args = arguments, i = 1;
2263
2264 // link all the functions, so any of them can unbind this click handler
2265 while( i < args.length )
2266 jQuery.event.proxy( fn, args[i++] );
2267
2268 return this.click( jQuery.event.proxy( fn, function(event) {
2269 // Figure out which function to execute
2270 this.lastToggle = ( this.lastToggle || 0 ) % i;
2271
2272 // Make sure that clicks stop
2273 event.preventDefault();
2274
2275 // and execute the function
2276 return args[ this.lastToggle++ ].apply( this, arguments ) || false;
2277 }));
2278 },
2279
2280 hover: function(fnOver, fnOut) {
2281 return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
2282 },
2283
2284 ready: function(fn) {
2285 // Attach the listeners
2286 bindReady();
2287
2288 // If the DOM is already ready
2289 if ( jQuery.isReady )
2290 // Execute the function immediately
2291 fn.call( document, jQuery );
2292
2293 // Otherwise, remember the function for later
2294 else
2295 // Add the function to the wait list
2296 jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
2297
2298 return this;
2299 }
2300 });
2301
2302 jQuery.extend({
2303 isReady: false,
2304 readyList: [],
2305 // Handle when the DOM is ready
2306 ready: function() {
2307 // Make sure that the DOM is not already loaded
2308 if ( !jQuery.isReady ) {
2309 // Remember that the DOM is ready
2310 jQuery.isReady = true;
2311
2312 // If there are functions bound, to execute
2313 if ( jQuery.readyList ) {
2314 // Execute all of them
2315 jQuery.each( jQuery.readyList, function(){
2316 this.call( document );
2317 });
2318
2319 // Reset the list of functions
2320 jQuery.readyList = null;
2321 }
2322
2323 // Trigger any bound ready events
2324 jQuery(document).triggerHandler("ready");
2325 }
2326 }
2327 });
2328
2329 var readyBound = false;
2330
2331 function bindReady(){
2332 if ( readyBound ) return;
2333 readyBound = true;
2334
2335 // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
2336 if ( document.addEventListener && !jQuery.browser.opera)
2337 // Use the handy event callback
2338 document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
2339
2340 // If IE is used and is not in a frame
2341 // Continually check to see if the document is ready
2342 if ( jQuery.browser.msie && window == top ) (function(){
2343 if (jQuery.isReady) return;
2344 try {
2345 // If IE is used, use the trick by Diego Perini
2346 // http://javascript.nwbox.com/IEContentLoaded/
2347 document.documentElement.doScroll("left");
2348 } catch( error ) {
2349 setTimeout( arguments.callee, 0 );
2350 return;
2351 }
2352 // and execute any waiting functions
2353 jQuery.ready();
2354 })();
2355
2356 if ( jQuery.browser.opera )
2357 document.addEventListener( "DOMContentLoaded", function () {
2358 if (jQuery.isReady) return;
2359 for (var i = 0; i < document.styleSheets.length; i++)
2360 if (document.styleSheets[i].disabled) {
2361 setTimeout( arguments.callee, 0 );
2362 return;
2363 }
2364 // and execute any waiting functions
2365 jQuery.ready();
2366 }, false);
2367
2368 if ( jQuery.browser.safari ) {
2369 var numStyles;
2370 (function(){
2371 if (jQuery.isReady) return;
2372 if ( document.readyState != "loaded" && document.readyState != "complete" ) {
2373 setTimeout( arguments.callee, 0 );
2374 return;
2375 }
2376 if ( numStyles === undefined )
2377 numStyles = jQuery("style, link[rel=stylesheet]").length;
2378 if ( document.styleSheets.length != numStyles ) {
2379 setTimeout( arguments.callee, 0 );
2380 return;
2381 }
2382 // and execute any waiting functions
2383 jQuery.ready();
2384 })();
2385 }
2386
2387 // A fallback to window.onload, that will always work
2388 jQuery.event.add( window, "load", jQuery.ready );
2389 }
2390
2391 jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
2392 "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
2393 "submit,keydown,keypress,keyup,error").split(","), function(i, name){
2394
2395 // Handle event binding
2396 jQuery.fn[name] = function(fn){
2397 return fn ? this.bind(name, fn) : this.trigger(name);
2398 };
2399 });
2400
2401 // Checks if an event happened on an element within another element
2402 // Used in jQuery.event.special.mouseenter and mouseleave handlers
2403 var withinElement = function(event, elem) {
2404 // Check if mouse(over|out) are still within the same parent element
2405 var parent = event.relatedTarget;
2406 // Traverse up the tree
2407 while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
2408 // Return true if we actually just moused on to a sub-element
2409 return parent == elem;
2410 };
2411
2412 // Prevent memory leaks in IE
2413 // And prevent errors on refresh with events like mouseover in other browsers
2414 // Window isn't included so as not to unbind existing unload events
2415 jQuery(window).bind("unload", function() {
2416 jQuery("*").add(document).unbind();
2417 });
2418 jQuery.fn.extend({
2419 // Keep a copy of the old load
2420 _load: jQuery.fn.load,
2421
2422 load: function( url, params, callback ) {
2423 if ( typeof url != 'string' )
2424 return this._load( url );
2425
2426 var off = url.indexOf(" ");
2427 if ( off >= 0 ) {
2428 var selector = url.slice(off, url.length);
2429 url = url.slice(0, off);
2430 }
2431
2432 callback = callback || function(){};
2433
2434 // Default to a GET request
2435 var type = "GET";
2436
2437 // If the second parameter was provided
2438 if ( params )
2439 // If it's a function
2440 if ( jQuery.isFunction( params ) ) {
2441 // We assume that it's the callback
2442 callback = params;
2443 params = null;
2444
2445 // Otherwise, build a param string
2446 } else {
2447 params = jQuery.param( params );
2448 type = "POST";
2449 }
2450
2451 var self = this;
2452
2453 // Request the remote document
2454 jQuery.ajax({
2455 url: url,
2456 type: type,
2457 dataType: "html",
2458 data: params,
2459 complete: function(res, status){
2460 // If successful, inject the HTML into all the matched elements
2461 if ( status == "success" || status == "notmodified" )
2462 // See if a selector was specified
2463 self.html( selector ?
2464 // Create a dummy div to hold the results
2465 jQuery("<div/>")
2466 // inject the contents of the document in, removing the scripts
2467 // to avoid any 'Permission Denied' errors in IE
2468 .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
2469
2470 // Locate th