importing greclusters into git
[greclusters.git] / jquery.js
blob760b1841fd239f5bf913ec2bab2ac9ea286e5fab
1 // prevent execution of jQuery if included more than once
2 if(typeof window.jQuery == "undefined") {
3 /*
4  * jQuery 1.1.3 - New Wave Javascript
5  *
6  * Copyright (c) 2007 John Resig (jquery.com)
7  * Dual licensed under the MIT (MIT-LICENSE.txt)
8  * and GPL (GPL-LICENSE.txt) licenses.
9  *
10  * $Date: 2007-07-01 08:54:38 -0400 (Sun, 01 Jul 2007) $
11  * $Rev: 2200 $
12  */
14 // Global undefined variable
15 window.undefined = window.undefined;
16 var jQuery = function(a,c) {
17         // If the context is global, return a new object
18         if ( window == this || !this.init )
19                 return new jQuery(a,c);
20         
21         return this.init(a,c);
24 // Map over the $ in case of overwrite
25 if ( typeof $ != "undefined" )
26         jQuery._$ = $;
27         
28 // Map the jQuery namespace to the '$' one
29 var $ = jQuery;
31 jQuery.fn = jQuery.prototype = {
32         init: function(a,c) {
33                 // Make sure that a selection was provided
34                 a = a || document;
36                 // HANDLE: $(function)
37                 // Shortcut for document ready
38                 if ( jQuery.isFunction(a) )
39                         return new jQuery(document)[ jQuery.fn.ready ? "ready" : "load" ]( a );
41                 // Handle HTML strings
42                 if ( typeof a  == "string" ) {
43                         // HANDLE: $(html) -> $(array)
44                         var m = /^[^<]*(<(.|\s)+>)[^>]*$/.exec(a);
45                         if ( m )
46                                 a = jQuery.clean( [ m[1] ] );
48                         // HANDLE: $(expr)
49                         else
50                                 return new jQuery( c ).find( a );
51                 }
53                 return this.setArray(
54                         // HANDLE: $(array)
55                         a.constructor == Array && a ||
57                         // HANDLE: $(arraylike)
58                         // Watch for when an array-like object is passed as the selector
59                         (a.jquery || a.length && a != window && !a.nodeType && a[0] != undefined && a[0].nodeType) && jQuery.makeArray( a ) ||
61                         // HANDLE: $(*)
62                         [ a ] );
63         },
64         jquery: "1.1.3",
66         size: function() {
67                 return this.length;
68         },
69         
70         length: 0,
72         get: function( num ) {
73                 return num == undefined ?
75                         // Return a 'clean' array
76                         jQuery.makeArray( this ) :
78                         // Return just the object
79                         this[num];
80         },
81         pushStack: function( a ) {
82                 var ret = jQuery(a);
83                 ret.prevObject = this;
84                 return ret;
85         },
86         setArray: function( a ) {
87                 this.length = 0;
88                 [].push.apply( this, a );
89                 return this;
90         },
91         each: function( fn, args ) {
92                 return jQuery.each( this, fn, args );
93         },
94         index: function( obj ) {
95                 var pos = -1;
96                 this.each(function(i){
97                         if ( this == obj ) pos = i;
98                 });
99                 return pos;
100         },
102         attr: function( key, value, type ) {
103                 var obj = key;
104                 
105                 // Look for the case where we're accessing a style value
106                 if ( key.constructor == String )
107                         if ( value == undefined )
108                                 return this.length && jQuery[ type || "attr" ]( this[0], key ) || undefined;
109                         else {
110                                 obj = {};
111                                 obj[ key ] = value;
112                         }
113                 
114                 // Check to see if we're setting style values
115                 return this.each(function(index){
116                         // Set all the styles
117                         for ( var prop in obj )
118                                 jQuery.attr(
119                                         type ? this.style : this,
120                                         prop, jQuery.prop(this, obj[prop], type, index, prop)
121                                 );
122                 });
123         },
125         css: function( key, value ) {
126                 return this.attr( key, value, "curCSS" );
127         },
129         text: function(e) {
130                 if ( typeof e == "string" )
131                         return this.empty().append( document.createTextNode( e ) );
133                 var t = "";
134                 jQuery.each( e || this, function(){
135                         jQuery.each( this.childNodes, function(){
136                                 if ( this.nodeType != 8 )
137                                         t += this.nodeType != 1 ?
138                                                 this.nodeValue : jQuery.fn.text([ this ]);
139                         });
140                 });
141                 return t;
142         },
144         wrap: function() {
145                 // The elements to wrap the target around
146                 var a, args = arguments;
148                 // Wrap each of the matched elements individually
149                 return this.each(function(){
150                         if ( !a )
151                                 a = jQuery.clean(args, this.ownerDocument);
153                         // Clone the structure that we're using to wrap
154                         var b = a[0].cloneNode(true);
156                         // Insert it before the element to be wrapped
157                         this.parentNode.insertBefore( b, this );
159                         // Find the deepest point in the wrap structure
160                         while ( b.firstChild )
161                                 b = b.firstChild;
163                         // Move the matched element to within the wrap structure
164                         b.appendChild( this );
165                 });
166         },
167         append: function() {
168                 return this.domManip(arguments, true, 1, function(a){
169                         this.appendChild( a );
170                 });
171         },
172         prepend: function() {
173                 return this.domManip(arguments, true, -1, function(a){
174                         this.insertBefore( a, this.firstChild );
175                 });
176         },
177         before: function() {
178                 return this.domManip(arguments, false, 1, function(a){
179                         this.parentNode.insertBefore( a, this );
180                 });
181         },
182         after: function() {
183                 return this.domManip(arguments, false, -1, function(a){
184                         this.parentNode.insertBefore( a, this.nextSibling );
185                 });
186         },
187         end: function() {
188                 return this.prevObject || jQuery([]);
189         },
190         find: function(t) {
191                 var data = jQuery.map(this, function(a){ return jQuery.find(t,a); });
192                 return this.pushStack( /[^+>] [^+>]/.test( t ) || t.indexOf("..") > -1 ?
193                         jQuery.unique( data ) : data );
194         },
195         clone: function(deep) {
196                 // Need to remove events on the element and its descendants
197                 var $this = this.add(this.find("*"));
198                 $this.each(function() {
199                         this._$events = {};
200                         for (var type in this.$events)
201                                 this._$events[type] = jQuery.extend({},this.$events[type]);
202                 }).unbind();
204                 // Do the clone
205                 var r = this.pushStack( jQuery.map( this, function(a){
206                         return a.cloneNode( deep != undefined ? deep : true );
207                 }) );
209                 // Add the events back to the original and its descendants
210                 $this.each(function() {
211                         var events = this._$events;
212                         for (var type in events)
213                                 for (var handler in events[type])
214                                         jQuery.event.add(this, type, events[type][handler], events[type][handler].data);
215                         this._$events = null;
216                 });
218                 // Return the cloned set
219                 return r;
220         },
222         filter: function(t) {
223                 return this.pushStack(
224                         jQuery.isFunction( t ) &&
225                         jQuery.grep(this, function(el, index){
226                                 return t.apply(el, [index])
227                         }) ||
229                         jQuery.multiFilter(t,this) );
230         },
232         not: function(t) {
233                 return this.pushStack(
234                         t.constructor == String &&
235                         jQuery.multiFilter(t, this, true) ||
237                         jQuery.grep(this, function(a) {
238                                 return ( t.constructor == Array || t.jquery )
239                                         ? jQuery.inArray( a, t ) < 0
240                                         : a != t;
241                         })
242                 );
243         },
245         add: function(t) {
246                 return this.pushStack( jQuery.merge(
247                         this.get(),
248                         t.constructor == String ?
249                                 jQuery(t).get() :
250                                 t.length != undefined && (!t.nodeName || t.nodeName == "FORM") ?
251                                         t : [t] )
252                 );
253         },
254         is: function(expr) {
255                 return expr ? jQuery.multiFilter(expr,this).length > 0 : false;
256         },
258         val: function( val ) {
259                 return val == undefined ?
260                         ( this.length ? this[0].value : null ) :
261                         this.attr( "value", val );
262         },
264         html: function( val ) {
265                 return val == undefined ?
266                         ( this.length ? this[0].innerHTML : null ) :
267                         this.empty().append( val );
268         },
269         domManip: function(args, table, dir, fn){
270                 var clone = this.length > 1, a; 
272                 return this.each(function(){
273                         if ( !a ) {
274                                 a = jQuery.clean(args, this.ownerDocument);
275                                 if ( dir < 0 )
276                                         a.reverse();
277                         }
279                         var obj = this;
281                         if ( table && jQuery.nodeName(this, "table") && jQuery.nodeName(a[0], "tr") )
282                                 obj = this.getElementsByTagName("tbody")[0] || this.appendChild(document.createElement("tbody"));
284                         jQuery.each( a, function(){
285                                 fn.apply( obj, [ clone ? this.cloneNode(true) : this ] );
286                         });
288                 });
289         }
292 jQuery.extend = jQuery.fn.extend = function() {
293         // copy reference to target object
294         var target = arguments[0], a = 1;
296         // extend jQuery itself if only one argument is passed
297         if ( arguments.length == 1 ) {
298                 target = this;
299                 a = 0;
300         }
301         var prop;
302         while ( (prop = arguments[a++]) != null )
303                 // Extend the base object
304                 for ( var i in prop ) target[i] = prop[i];
306         // Return the modified object
307         return target;
310 jQuery.extend({
311         noConflict: function() {
312                 if ( jQuery._$ )
313                         $ = jQuery._$;
314                 return jQuery;
315         },
317         // This may seem like some crazy code, but trust me when I say that this
318         // is the only cross-browser way to do this. --John
319         isFunction: function( fn ) {
320                 return !!fn && typeof fn != "string" && !fn.nodeName && 
321                         fn.constructor != Array && /function/i.test( fn + "" );
322         },
323         
324         // check if an element is in a XML document
325         isXMLDoc: function(elem) {
326                 return elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
327         },
329         nodeName: function( elem, name ) {
330                 return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
331         },
332         // args is for internal usage only
333         each: function( obj, fn, args ) {
334                 if ( obj.length == undefined )
335                         for ( var i in obj )
336                                 fn.apply( obj[i], args || [i, obj[i]] );
337                 else
338                         for ( var i = 0, ol = obj.length; i < ol; i++ )
339                                 if ( fn.apply( obj[i], args || [i, obj[i]] ) === false ) break;
340                 return obj;
341         },
342         
343         prop: function(elem, value, type, index, prop){
344                         // Handle executable functions
345                         if ( jQuery.isFunction( value ) )
346                                 value = value.call( elem, [index] );
347                                 
348                         // exclude the following css properties to add px
349                         var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
351                         // Handle passing in a number to a CSS property
352                         return value && value.constructor == Number && type == "curCSS" && !exclude.test(prop) ?
353                                 value + "px" :
354                                 value;
355         },
357         className: {
358                 // internal only, use addClass("class")
359                 add: function( elem, c ){
360                         jQuery.each( c.split(/\s+/), function(i, cur){
361                                 if ( !jQuery.className.has( elem.className, cur ) )
362                                         elem.className += ( elem.className ? " " : "" ) + cur;
363                         });
364                 },
366                 // internal only, use removeClass("class")
367                 remove: function( elem, c ){
368                         elem.className = c != undefined ?
369                                 jQuery.grep( elem.className.split(/\s+/), function(cur){
370                                         return !jQuery.className.has( c, cur ); 
371                                 }).join(" ") : "";
372                 },
374                 // internal only, use is(".class")
375                 has: function( t, c ) {
376                         return jQuery.inArray( c, (t.className || t).toString().split(/\s+/) ) > -1;
377                 }
378         },
379         swap: function(e,o,f) {
380                 for ( var i in o ) {
381                         e.style["old"+i] = e.style[i];
382                         e.style[i] = o[i];
383                 }
384                 f.apply( e, [] );
385                 for ( var i in o )
386                         e.style[i] = e.style["old"+i];
387         },
389         css: function(e,p) {
390                 if ( p == "height" || p == "width" ) {
391                         var old = {}, oHeight, oWidth, d = ["Top","Bottom","Right","Left"];
393                         jQuery.each( d, function(){
394                                 old["padding" + this] = 0;
395                                 old["border" + this + "Width"] = 0;
396                         });
398                         jQuery.swap( e, old, function() {
399                                 if ( jQuery(e).is(':visible') ) {
400                                         oHeight = e.offsetHeight;
401                                         oWidth = e.offsetWidth;
402                                 } else {
403                                         e = jQuery(e.cloneNode(true))
404                                                 .find(":radio").removeAttr("checked").end()
405                                                 .css({
406                                                         visibility: "hidden", position: "absolute", display: "block", right: "0", left: "0"
407                                                 }).appendTo(e.parentNode)[0];
409                                         var parPos = jQuery.css(e.parentNode,"position") || "static";
410                                         if ( parPos == "static" )
411                                                 e.parentNode.style.position = "relative";
413                                         oHeight = e.clientHeight;
414                                         oWidth = e.clientWidth;
416                                         if ( parPos == "static" )
417                                                 e.parentNode.style.position = "static";
419                                         e.parentNode.removeChild(e);
420                                 }
421                         });
423                         return p == "height" ? oHeight : oWidth;
424                 }
426                 return jQuery.curCSS( e, p );
427         },
429         curCSS: function(elem, prop, force) {
430                 var ret;
432                 if (prop == "opacity" && jQuery.browser.msie) {
433                         ret = jQuery.attr(elem.style, "opacity");
434                         return ret == "" ? "1" : ret;
435                 }
436                 
437                 if (prop.match(/float/i))
438                         prop = jQuery.styleFloat;
440                 if (!force && elem.style[prop])
441                         ret = elem.style[prop];
443                 else if (document.defaultView && document.defaultView.getComputedStyle) {
445                         if (prop.match(/float/i))
446                                 prop = "float";
448                         prop = prop.replace(/([A-Z])/g,"-$1").toLowerCase();
449                         var cur = document.defaultView.getComputedStyle(elem, null);
451                         if ( cur )
452                                 ret = cur.getPropertyValue(prop);
453                         else if ( prop == "display" )
454                                 ret = "none";
455                         else
456                                 jQuery.swap(elem, { display: "block" }, function() {
457                                     var c = document.defaultView.getComputedStyle(this, "");
458                                     ret = c && c.getPropertyValue(prop) || "";
459                                 });
461                 } else if (elem.currentStyle) {
462                         var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase();});
463                         ret = elem.currentStyle[prop] || elem.currentStyle[newProp];
464                 }
466                 return ret;
467         },
468         
469         clean: function(a, doc) {
470                 var r = [];
471                 doc = doc || document;
473                 jQuery.each( a, function(i,arg){
474                         if ( !arg ) return;
476                         if ( arg.constructor == Number )
477                                 arg = arg.toString();
478                         
479                         // Convert html string into DOM nodes
480                         if ( typeof arg == "string" ) {
481                                 // Trim whitespace, otherwise indexOf won't work as expected
482                                 var s = jQuery.trim(arg).toLowerCase(), div = doc.createElement("div"), tb = [];
484                                 var wrap =
485                                         // option or optgroup
486                                         !s.indexOf("<opt") &&
487                                         [1, "<select>", "</select>"] ||
488                                         
489                                         !s.indexOf("<leg") &&
490                                         [1, "<fieldset>", "</fieldset>"] ||
491                                         
492                                         (!s.indexOf("<thead") || !s.indexOf("<tbody") || !s.indexOf("<tfoot") || !s.indexOf("<colg")) &&
493                                         [1, "<table>", "</table>"] ||
494                                         
495                                         !s.indexOf("<tr") &&
496                                         [2, "<table><tbody>", "</tbody></table>"] ||
497                                         
498                                         // <thead> matched above
499                                         (!s.indexOf("<td") || !s.indexOf("<th")) &&
500                                         [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
501                                         
502                                         !s.indexOf("<col") &&
503                                         [2, "<table><colgroup>", "</colgroup></table>"] ||
504                                         
505                                         [0,"",""];
507                                 // Go to html and back, then peel off extra wrappers
508                                 div.innerHTML = wrap[1] + arg + wrap[2];
509                                 
510                                 // Move to the right depth
511                                 while ( wrap[0]-- )
512                                         div = div.firstChild;
513                                 
514                                 // Remove IE's autoinserted <tbody> from table fragments
515                                 if ( jQuery.browser.msie ) {
516                                         
517                                         // String was a <table>, *may* have spurious <tbody>
518                                         if ( !s.indexOf("<table") && s.indexOf("<tbody") < 0 ) 
519                                                 tb = div.firstChild && div.firstChild.childNodes;
520                                                 
521                                         // String was a bare <thead> or <tfoot>
522                                         else if ( wrap[1] == "<table>" && s.indexOf("<tbody") < 0 )
523                                                 tb = div.childNodes;
525                                         for ( var n = tb.length-1; n >= 0 ; --n )
526                                                 if ( jQuery.nodeName(tb[n], "tbody") && !tb[n].childNodes.length )
527                                                         tb[n].parentNode.removeChild(tb[n]);
528                                         
529                                 }
530                                 
531                                 arg = jQuery.makeArray( div.childNodes );
532                         }
534                         if ( 0 === arg.length && (!jQuery.nodeName(arg, "form") && !jQuery.nodeName(arg, "select")) )
535                                 return;
537                         if ( arg[0] == undefined || jQuery.nodeName(arg, "form") || arg.options )
538                                 r.push( arg );
539                         else
540                                 r = jQuery.merge( r, arg );
542                 });
544                 return r;
545         },
546         
547         attr: function(elem, name, value){
548                 var fix = jQuery.isXMLDoc(elem) ? {} : jQuery.props;
549                 
550                 // Certain attributes only work when accessed via the old DOM 0 way
551                 if ( fix[name] ) {
552                         if ( value != undefined ) elem[fix[name]] = value;
553                         return elem[fix[name]];
555                 } else if ( value == undefined && jQuery.browser.msie && jQuery.nodeName(elem, "form") && (name == "action" || name == "method") )
556                         return elem.getAttributeNode(name).nodeValue;
558                 // IE elem.getAttribute passes even for style
559                 else if ( elem.tagName ) {
560                         // IE actually uses filters for opacity ... elem is actually elem.style
561                         if ( name == "opacity" && jQuery.browser.msie ) {
562                                 if ( value != undefined ) {
563                                         // IE has trouble with opacity if it does not have layout
564                                         // Force it by setting the zoom level
565                                         elem.zoom = 1; 
566         
567                                         // Set the alpha filter to set the opacity
568                                         elem.filter = (elem.filter || "").replace(/alpha\([^)]*\)/,"") +
569                                                 (parseFloat(value).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
570                                 }
571         
572                                 return elem.filter ? 
573                                         (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() : "";
574                         }
576                         if ( value != undefined ) elem.setAttribute( name, value );
577                         if ( jQuery.browser.msie && /href|src/.test(name) && !jQuery.isXMLDoc(elem) ) 
578                                 return elem.getAttribute( name, 2 );
579                         return elem.getAttribute( name );
581                 // elem is actually elem.style ... set the style
582                 } else {
583                         name = name.replace(/-([a-z])/ig,function(z,b){return b.toUpperCase();});
584                         if ( value != undefined ) elem[name] = value;
585                         return elem[name];
586                 }
587         },
588         trim: function(t){
589                 return t.replace(/^\s+|\s+$/g, "");
590         },
592         makeArray: function( a ) {
593                 var r = [];
595                 // Need to use typeof to fight Safari childNodes crashes
596                 if ( typeof a != "array" )
597                         for ( var i = 0, al = a.length; i < al; i++ )
598                                 r.push( a[i] );
599                 else
600                         r = a.slice( 0 );
602                 return r;
603         },
605         inArray: function( b, a ) {
606                 for ( var i = 0, al = a.length; i < al; i++ )
607                         if ( a[i] == b )
608                                 return i;
609                 return -1;
610         },
611         merge: function(first, second) {
612                 // We have to loop this way because IE & Opera overwrite the length
613                 // expando of getElementsByTagName
614                 for ( var i = 0; second[i]; i++ )
615                         first.push(second[i]);
616                 return first;
617         },
618         unique: function(first) {
619                 var r = [], num = jQuery.mergeNum++;
621                 for ( var i = 0, fl = first.length; i < fl; i++ )
622                         if ( num != first[i].mergeNum ) {
623                                 first[i].mergeNum = num;
624                                 r.push(first[i]);
625                         }
627                 return r;
628         },
630         mergeNum: 0,
631         grep: function(elems, fn, inv) {
632                 // If a string is passed in for the function, make a function
633                 // for it (a handy shortcut)
634                 if ( typeof fn == "string" )
635                         fn = new Function("a","i","return " + fn);
637                 var result = [];
639                 // Go through the array, only saving the items
640                 // that pass the validator function
641                 for ( var i = 0, el = elems.length; i < el; i++ )
642                         if ( !inv && fn(elems[i],i) || inv && !fn(elems[i],i) )
643                                 result.push( elems[i] );
645                 return result;
646         },
647         map: function(elems, fn) {
648                 // If a string is passed in for the function, make a function
649                 // for it (a handy shortcut)
650                 if ( typeof fn == "string" )
651                         fn = new Function("a","return " + fn);
653                 var result = [];
655                 // Go through the array, translating each of the items to their
656                 // new value (or values).
657                 for ( var i = 0, el = elems.length; i < el; i++ ) {
658                         var val = fn(elems[i],i);
660                         if ( val !== null && val != undefined ) {
661                                 if ( val.constructor != Array ) val = [val];
662                                 result = result.concat( val );
663                         }
664                 }
666                 return result;
667         }
671  * Whether the W3C compliant box model is being used.
673  * @property
674  * @name $.boxModel
675  * @type Boolean
676  * @cat JavaScript
677  */
678 new function() {
679         var b = navigator.userAgent.toLowerCase();
681         // Figure out what browser is being used
682         jQuery.browser = {
683                 version: b.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)[1],
684                 safari: /webkit/.test(b),
685                 opera: /opera/.test(b),
686                 msie: /msie/.test(b) && !/opera/.test(b),
687                 mozilla: /mozilla/.test(b) && !/(compatible|webkit)/.test(b)
688         };
690         // Check to see if the W3C box model is being used
691         jQuery.boxModel = !jQuery.browser.msie || document.compatMode == "CSS1Compat";
693         jQuery.styleFloat = jQuery.browser.msie ? "styleFloat" : "cssFloat",
695         jQuery.props = {
696                 "for": "htmlFor",
697                 "class": "className",
698                 "float": jQuery.styleFloat,
699                 cssFloat: jQuery.styleFloat,
700                 styleFloat: jQuery.styleFloat,
701                 innerHTML: "innerHTML",
702                 className: "className",
703                 value: "value",
704                 disabled: "disabled",
705                 checked: "checked",
706                 readonly: "readOnly",
707                 selected: "selected",
708                 maxlength: "maxLength"
709         };
712 jQuery.each({
713         parent: "a.parentNode",
714         parents: "jQuery.parents(a)",
715         next: "jQuery.nth(a,2,'nextSibling')",
716         prev: "jQuery.nth(a,2,'previousSibling')",
717         siblings: "jQuery.sibling(a.parentNode.firstChild,a)",
718         children: "jQuery.sibling(a.firstChild)"
719 }, function(i,n){
720         jQuery.fn[ i ] = function(a) {
721                 var ret = jQuery.map(this,n);
722                 if ( a && typeof a == "string" )
723                         ret = jQuery.multiFilter(a,ret);
724                 return this.pushStack( ret );
725         };
728 jQuery.each({
729         appendTo: "append",
730         prependTo: "prepend",
731         insertBefore: "before",
732         insertAfter: "after"
733 }, function(i,n){
734         jQuery.fn[ i ] = function(){
735                 var a = arguments;
736                 return this.each(function(){
737                         for ( var j = 0, al = a.length; j < al; j++ )
738                                 jQuery(a[j])[n]( this );
739                 });
740         };
743 jQuery.each( {
744         removeAttr: function( key ) {
745                 jQuery.attr( this, key, "" );
746                 this.removeAttribute( key );
747         },
748         addClass: function(c){
749                 jQuery.className.add(this,c);
750         },
751         removeClass: function(c){
752                 jQuery.className.remove(this,c);
753         },
754         toggleClass: function( c ){
755                 jQuery.className[ jQuery.className.has(this,c) ? "remove" : "add" ](this, c);
756         },
757         remove: function(a){
758                 if ( !a || jQuery.filter( a, [this] ).r.length )
759                         this.parentNode.removeChild( this );
760         },
761         empty: function() {
762                 while ( this.firstChild )
763                         this.removeChild( this.firstChild );
764         }
765 }, function(i,n){
766         jQuery.fn[ i ] = function() {
767                 return this.each( n, arguments );
768         };
771 jQuery.each( [ "eq", "lt", "gt", "contains" ], function(i,n){
772         jQuery.fn[ n ] = function(num,fn) {
773                 return this.filter( ":" + n + "(" + num + ")", fn );
774         };
777 jQuery.each( [ "height", "width" ], function(i,n){
778         jQuery.fn[ n ] = function(h) {
779                 return h == undefined ?
780                         ( this.length ? jQuery.css( this[0], n ) : null ) :
781                         this.css( n, h.constructor == String ? h : h + "px" );
782         };
784 jQuery.extend({
785         expr: {
786                 "": "m[2]=='*'||jQuery.nodeName(a,m[2])",
787                 "#": "a.getAttribute('id')==m[2]",
788                 ":": {
789                         // Position Checks
790                         lt: "i<m[3]-0",
791                         gt: "i>m[3]-0",
792                         nth: "m[3]-0==i",
793                         eq: "m[3]-0==i",
794                         first: "i==0",
795                         last: "i==r.length-1",
796                         even: "i%2==0",
797                         odd: "i%2",
799                         // Child Checks
800                         "first-child": "a.parentNode.getElementsByTagName('*')[0]==a",
801                         "last-child": "jQuery.nth(a.parentNode.lastChild,1,'previousSibling')==a",
802                         "only-child": "!jQuery.nth(a.parentNode.lastChild,2,'previousSibling')",
804                         // Parent Checks
805                         parent: "a.firstChild",
806                         empty: "!a.firstChild",
808                         // Text Check
809                         contains: "(a.textContent||a.innerText||'').indexOf(m[3])>=0",
811                         // Visibility
812                         visible: '"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden"',
813                         hidden: '"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden"',
815                         // Form attributes
816                         enabled: "!a.disabled",
817                         disabled: "a.disabled",
818                         checked: "a.checked",
819                         selected: "a.selected||jQuery.attr(a,'selected')",
821                         // Form elements
822                         text: "'text'==a.type",
823                         radio: "'radio'==a.type",
824                         checkbox: "'checkbox'==a.type",
825                         file: "'file'==a.type",
826                         password: "'password'==a.type",
827                         submit: "'submit'==a.type",
828                         image: "'image'==a.type",
829                         reset: "'reset'==a.type",
830                         button: '"button"==a.type||jQuery.nodeName(a,"button")',
831                         input: "/input|select|textarea|button/i.test(a.nodeName)"
832                 },
833                 "[": "jQuery.find(m[2],a).length"
834         },
835         
836         // The regular expressions that power the parsing engine
837         parse: [
838                 // Match: [@value='test'], [@foo]
839                 /^\[ *(@)([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
841                 // Match: [div], [div p]
842                 /^(\[)\s*(.*?(\[.*?\])?[^[]*?)\s*\]/,
844                 // Match: :contains('foo')
845                 /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
847                 // Match: :even, :last-chlid, #id, .class
848                 new RegExp("^([:.#]*)(" + 
849                         ( jQuery.chars = "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)" ) + "+)")
850         ],
852         multiFilter: function( expr, elems, not ) {
853                 var old, cur = [];
855                 while ( expr && expr != old ) {
856                         old = expr;
857                         var f = jQuery.filter( expr, elems, not );
858                         expr = f.t.replace(/^\s*,\s*/, "" );
859                         cur = not ? elems = f.r : jQuery.merge( cur, f.r );
860                 }
862                 return cur;
863         },
864         find: function( t, context ) {
865                 // Quickly handle non-string expressions
866                 if ( typeof t != "string" )
867                         return [ t ];
869                 // Make sure that the context is a DOM Element
870                 if ( context && !context.nodeType )
871                         context = null;
873                 // Set the correct context (if none is provided)
874                 context = context || document;
876                 // Handle the common XPath // expression
877                 if ( !t.indexOf("//") ) {
878                         context = context.documentElement;
879                         t = t.substr(2,t.length);
881                 // And the / root expression
882                 } else if ( !t.indexOf("/") && !context.ownerDocument ) {
883                         context = context.documentElement;
884                         t = t.substr(1,t.length);
885                         if ( t.indexOf("/") >= 1 )
886                                 t = t.substr(t.indexOf("/"),t.length);
887                 }
889                 // Initialize the search
890                 var ret = [context], done = [], last;
892                 // Continue while a selector expression exists, and while
893                 // we're no longer looping upon ourselves
894                 while ( t && last != t ) {
895                         var r = [];
896                         last = t;
898                         t = jQuery.trim(t).replace( /^\/\//, "" );
900                         var foundToken = false;
902                         // An attempt at speeding up child selectors that
903                         // point to a specific element tag
904                         var re = new RegExp("^[/>]\\s*(" + jQuery.chars + "+)");
905                         var m = re.exec(t);
907                         if ( m ) {
908                                 var nodeName = m[1].toUpperCase();
910                                 // Perform our own iteration and filter
911                                 for ( var i = 0; ret[i]; i++ )
912                                         for ( var c = ret[i].firstChild; c; c = c.nextSibling )
913                                                 if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName == nodeName.toUpperCase()) )
914                                                         r.push( c );
916                                 ret = r;
917                                 t = t.replace( re, "" );
918                                 if ( t.indexOf(" ") == 0 ) continue;
919                                 foundToken = true;
920                         } else {
921                                 re = /^((\/?\.\.)|([>\/+~]))\s*([a-z]*)/i;
923                                 if ( (m = re.exec(t)) != null ) {
924                                         r = [];
926                                         var nodeName = m[4], mergeNum = jQuery.mergeNum++;
927                                         m = m[1];
929                                         for ( var j = 0, rl = ret.length; j < rl; j++ )
930                                                 if ( m.indexOf("..") < 0 ) {
931                                                         var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
932                                                         for ( ; n; n = n.nextSibling )
933                                                                 if ( n.nodeType == 1 ) {
934                                                                         if ( m == "~" && n.mergeNum == mergeNum ) break;
935                                                                         
936                                                                         if (!nodeName || n.nodeName == nodeName.toUpperCase() ) {
937                                                                                 if ( m == "~" ) n.mergeNum = mergeNum;
938                                                                                 r.push( n );
939                                                                         }
940                                                                         
941                                                                         if ( m == "+" ) break;
942                                                                 }
943                                                 } else
944                                                         r.push( ret[j].parentNode );
946                                         ret = r;
948                                         // And remove the token
949                                         t = jQuery.trim( t.replace( re, "" ) );
950                                         foundToken = true;
951                                 }
952                         }
954                         // See if there's still an expression, and that we haven't already
955                         // matched a token
956                         if ( t && !foundToken ) {
957                                 // Handle multiple expressions
958                                 if ( !t.indexOf(",") ) {
959                                         // Clean the result set
960                                         if ( context == ret[0] ) ret.shift();
962                                         // Merge the result sets
963                                         done = jQuery.merge( done, ret );
965                                         // Reset the context
966                                         r = ret = [context];
968                                         // Touch up the selector string
969                                         t = " " + t.substr(1,t.length);
971                                 } else {
972                                         // Optomize for the case nodeName#idName
973                                         var re2 = new RegExp("^(" + jQuery.chars + "+)(#)(" + jQuery.chars + "+)");
974                                         var m = re2.exec(t);
975                                         
976                                         // Re-organize the results, so that they're consistent
977                                         if ( m ) {
978                                            m = [ 0, m[2], m[3], m[1] ];
980                                         } else {
981                                                 // Otherwise, do a traditional filter check for
982                                                 // ID, class, and element selectors
983                                                 re2 = new RegExp("^([#.]?)(" + jQuery.chars + "*)");
984                                                 m = re2.exec(t);
985                                         }
987                                         m[2] = m[2].replace(/\\/g, "");
989                                         var elem = ret[ret.length-1];
991                                         // Try to do a global search by ID, where we can
992                                         if ( m[1] == "#" && elem && elem.getElementById ) {
993                                                 // Optimization for HTML document case
994                                                 var oid = elem.getElementById(m[2]);
995                                                 
996                                                 // Do a quick check for the existence of the actual ID attribute
997                                                 // to avoid selecting by the name attribute in IE
998                                                 // also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
999                                                 if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
1000                                                         oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
1002                                                 // Do a quick check for node name (where applicable) so
1003                                                 // that div#foo searches will be really fast
1004                                                 ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
1005                                         } else {
1006                                                 // We need to find all descendant elements
1007                                                 for ( var i = 0; ret[i]; i++ ) {
1008                                                         // Grab the tag name being searched for
1009                                                         var tag = m[1] != "" || m[0] == "" ? "*" : m[2];
1011                                                         // Handle IE7 being really dumb about <object>s
1012                                                         if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
1013                                                                 tag = "param";
1015                                                         r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
1016                                                 }
1018                                                 // It's faster to filter by class and be done with it
1019                                                 if ( m[1] == "." )
1020                                                         r = jQuery.classFilter( r, m[2] );
1022                                                 // Same with ID filtering
1023                                                 if ( m[1] == "#" ) {
1024                                                         var tmp = [];
1026                                                         // Try to find the element with the ID
1027                                                         for ( var i = 0; r[i]; i++ )
1028                                                                 if ( r[i].getAttribute("id") == m[2] ) {
1029                                                                         tmp = [ r[i] ];
1030                                                                         break;
1031                                                                 }
1033                                                         r = tmp;
1034                                                 }
1036                                                 ret = r;
1037                                         }
1039                                         t = t.replace( re2, "" );
1040                                 }
1042                         }
1044                         // If a selector string still exists
1045                         if ( t ) {
1046                                 // Attempt to filter it
1047                                 var val = jQuery.filter(t,r);
1048                                 ret = r = val.r;
1049                                 t = jQuery.trim(val.t);
1050                         }
1051                 }
1053                 // An error occurred with the selector;
1054                 // just return an empty set instead
1055                 if ( t )
1056                         ret = [];
1058                 // Remove the root context
1059                 if ( ret && context == ret[0] )
1060                         ret.shift();
1062                 // And combine the results
1063                 done = jQuery.merge( done, ret );
1065                 return done;
1066         },
1068         classFilter: function(r,m,not){
1069                 m = " " + m + " ";
1070                 var tmp = [];
1071                 for ( var i = 0; r[i]; i++ ) {
1072                         var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
1073                         if ( !not && pass || not && !pass )
1074                                 tmp.push( r[i] );
1075                 }
1076                 return tmp;
1077         },
1079         filter: function(t,r,not) {
1080                 var last;
1082                 // Look for common filter expressions
1083                 while ( t  && t != last ) {
1084                         last = t;
1086                         var p = jQuery.parse, m;
1088                         for ( var i = 0; p[i]; i++ ) {
1089                                 m = p[i].exec( t );
1091                                 if ( m ) {
1092                                         // Remove what we just matched
1093                                         t = t.substring( m[0].length );
1095                                         m[2] = m[2].replace(/\\/g, "");
1096                                         break;
1097                                 }
1098                         }
1100                         if ( !m )
1101                                 break;
1103                         // :not() is a special case that can be optimized by
1104                         // keeping it out of the expression list
1105                         if ( m[1] == ":" && m[2] == "not" )
1106                                 r = jQuery.filter(m[3], r, true).r;
1108                         // We can get a big speed boost by filtering by class here
1109                         else if ( m[1] == "." )
1110                                 r = jQuery.classFilter(r, m[2], not);
1112                         else if ( m[1] == "@" ) {
1113                                 var tmp = [], type = m[3];
1114                                 
1115                                 for ( var i = 0, rl = r.length; i < rl; i++ ) {
1116                                         var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
1117                                         
1118                                         if ( z == null || /href|src/.test(m[2]) )
1119                                                 z = jQuery.attr(a,m[2]);
1121                                         if ( (type == "" && !!z ||
1122                                                  type == "=" && z == m[5] ||
1123                                                  type == "!=" && z != m[5] ||
1124                                                  type == "^=" && z && !z.indexOf(m[5]) ||
1125                                                  type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
1126                                                  (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
1127                                                         tmp.push( a );
1128                                 }
1129                                 
1130                                 r = tmp;
1132                         // We can get a speed boost by handling nth-child here
1133                         } else if ( m[1] == ":" && m[2] == "nth-child" ) {
1134                                 var num = jQuery.mergeNum++, tmp = [],
1135                                         test = /(\d*)n\+?(\d*)/.exec(
1136                                                 m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
1137                                                 !/\D/.test(m[3]) && "n+" + m[3] || m[3]),
1138                                         first = (test[1] || 1) - 0, last = test[2] - 0;
1140                                 for ( var i = 0, rl = r.length; i < rl; i++ ) {
1141                                         var node = r[i], parentNode = node.parentNode;
1143                                         if ( num != parentNode.mergeNum ) {
1144                                                 var c = 1;
1146                                                 for ( var n = parentNode.firstChild; n; n = n.nextSibling )
1147                                                         if ( n.nodeType == 1 )
1148                                                                 n.nodeIndex = c++;
1150                                                 parentNode.mergeNum = num;
1151                                         }
1153                                         var add = false;
1155                                         if ( first == 1 ) {
1156                                                 if ( last == 0 || node.nodeIndex == last )
1157                                                         add = true;
1158                                         } else if ( (node.nodeIndex + last) % first == 0 )
1159                                                 add = true;
1161                                         if ( add ^ not )
1162                                                 tmp.push( node );
1163                                 }
1165                                 r = tmp;
1167                         // Otherwise, find the expression to execute
1168                         } else {
1169                                 var f = jQuery.expr[m[1]];
1170                                 if ( typeof f != "string" )
1171                                         f = jQuery.expr[m[1]][m[2]];
1173                                 // Build a custom macro to enclose it
1174                                 eval("f = function(a,i){return " + f + "}");
1176                                 // Execute it against the current filter
1177                                 r = jQuery.grep( r, f, not );
1178                         }
1179                 }
1181                 // Return an array of filtered elements (r)
1182                 // and the modified expression string (t)
1183                 return { r: r, t: t };
1184         },
1185         parents: function( elem ){
1186                 var matched = [];
1187                 var cur = elem.parentNode;
1188                 while ( cur && cur != document ) {
1189                         matched.push( cur );
1190                         cur = cur.parentNode;
1191                 }
1192                 return matched;
1193         },
1194         nth: function(cur,result,dir,elem){
1195                 result = result || 1;
1196                 var num = 0;
1198                 for ( ; cur; cur = cur[dir] )
1199                         if ( cur.nodeType == 1 && ++num == result )
1200                                 break;
1202                 return cur;
1203         },
1204         sibling: function( n, elem ) {
1205                 var r = [];
1207                 for ( ; n; n = n.nextSibling ) {
1208                         if ( n.nodeType == 1 && (!elem || n != elem) )
1209                                 r.push( n );
1210                 }
1212                 return r;
1213         }
1216  * A number of helper functions used for managing events.
1217  * Many of the ideas behind this code orignated from 
1218  * Dean Edwards' addEvent library.
1219  */
1220 jQuery.event = {
1222         // Bind an event to an element
1223         // Original by Dean Edwards
1224         add: function(element, type, handler, data) {
1225                 // For whatever reason, IE has trouble passing the window object
1226                 // around, causing it to be cloned in the process
1227                 if ( jQuery.browser.msie && element.setInterval != undefined )
1228                         element = window;
1229                 
1230                 // Make sure that the function being executed has a unique ID
1231                 if ( !handler.guid )
1232                         handler.guid = this.guid++;
1233                         
1234                 // if data is passed, bind to handler 
1235                 if( data != undefined ) { 
1236                 // Create temporary function pointer to original handler 
1237                         var fn = handler; 
1239                         // Create unique handler function, wrapped around original handler 
1240                         handler = function() { 
1241                                 // Pass arguments and context to original handler 
1242                                 return fn.apply(this, arguments); 
1243                         };
1245                         // Store data in unique handler 
1246                         handler.data = data;
1248                         // Set the guid of unique handler to the same of original handler, so it can be removed 
1249                         handler.guid = fn.guid;
1250                 }
1252                 // Init the element's event structure
1253                 if (!element.$events)
1254                         element.$events = {};
1255                 
1256                 if (!element.$handle)
1257                         element.$handle = function() {
1258                                 // returned undefined or false
1259                                 var val;
1261                                 // Handle the second event of a trigger and when
1262                                 // an event is called after a page has unloaded
1263                                 if ( typeof jQuery == "undefined" || jQuery.event.triggered )
1264                                   return val;
1265                                 
1266                                 val = jQuery.event.handle.apply(element, arguments);
1267                                 
1268                                 return val;
1269                         };
1271                 // Get the current list of functions bound to this event
1272                 var handlers = element.$events[type];
1274                 // Init the event handler queue
1275                 if (!handlers) {
1276                         handlers = element.$events[type] = {};  
1277                         
1278                         // And bind the global event handler to the element
1279                         if (element.addEventListener)
1280                                 element.addEventListener(type, element.$handle, false);
1281                         else
1282                                 element.attachEvent("on" + type, element.$handle);
1283                 }
1285                 // Add the function to the element's handler list
1286                 handlers[handler.guid] = handler;
1288                 // Remember the function in a global list (for triggering)
1289                 if (!this.global[type])
1290                         this.global[type] = [];
1291                 // Only add the element to the global list once
1292                 if (jQuery.inArray(element, this.global[type]) == -1)
1293                         this.global[type].push( element );
1294         },
1296         guid: 1,
1297         global: {},
1299         // Detach an event or set of events from an element
1300         remove: function(element, type, handler) {
1301                 var events = element.$events, ret, index;
1303                 if ( events ) {
1304                         // type is actually an event object here
1305                         if ( type && type.type ) {
1306                                 handler = type.handler;
1307                                 type = type.type;
1308                         }
1309                         
1310                         if ( !type ) {
1311                                 for ( type in events )
1312                                         this.remove( element, type );
1314                         } else if ( events[type] ) {
1315                                 // remove the given handler for the given type
1316                                 if ( handler )
1317                                         delete events[type][handler.guid];
1318                                 
1319                                 // remove all handlers for the given type
1320                                 else
1321                                         for ( handler in element.$events[type] )
1322                                                 delete events[type][handler];
1324                                 // remove generic event handler if no more handlers exist
1325                                 for ( ret in events[type] ) break;
1326                                 if ( !ret ) {
1327                                         if (element.removeEventListener)
1328                                                 element.removeEventListener(type, element.$handle, false);
1329                                         else
1330                                                 element.detachEvent("on" + type, element.$handle);
1331                                         ret = null;
1332                                         delete events[type];
1333                                         
1334                                         // Remove element from the global event type cache
1335                                         while ( this.global[type] && ( (index = jQuery.inArray(element, this.global[type])) >= 0 ) )
1336                                                 delete this.global[type][index];
1337                                 }
1338                         }
1340                         // Remove the expando if it's no longer used
1341                         for ( ret in events ) break;
1342                         if ( !ret )
1343                                 element.$handle = element.$events = null;
1344                 }
1345         },
1347         trigger: function(type, data, element) {
1348                 // Clone the incoming data, if any
1349                 data = jQuery.makeArray(data || []);
1351                 // Handle a global trigger
1352                 if ( !element )
1353                         jQuery.each( this.global[type] || [], function(){
1354                                 jQuery.event.trigger( type, data, this );
1355                         });
1357                 // Handle triggering a single element
1358                 else {
1359                         var val, ret, fn = jQuery.isFunction( element[ type ] || null );
1360                         
1361                         // Pass along a fake event
1362                         data.unshift( this.fix({ type: type, target: element }) );
1364                         // Trigger the event
1365                         if ( jQuery.isFunction(element.$handle) && (val = element.$handle.apply( element, data )) !== false )
1366                                 this.triggered = true;
1368                         if ( fn && val !== false && !jQuery.nodeName(element, 'a') )
1369                                 element[ type ]();
1371                         this.triggered = false;
1372                 }
1373         },
1375         handle: function(event) {
1376                 // returned undefined or false
1377                 var val;
1379                 // Empty object is for triggered events with no data
1380                 event = jQuery.event.fix( event || window.event || {} ); 
1382                 var c = this.$events && this.$events[event.type], args = [].slice.call( arguments, 1 );
1383                 args.unshift( event );
1385                 for ( var j in c ) {
1386                         // Pass in a reference to the handler function itself
1387                         // So that we can later remove it
1388                         args[0].handler = c[j];
1389                         args[0].data = c[j].data;
1391                         if ( c[j].apply( this, args ) === false ) {
1392                                 event.preventDefault();
1393                                 event.stopPropagation();
1394                                 val = false;
1395                         }
1396                 }
1398                 // Clean up added properties in IE to prevent memory leak
1399                 if (jQuery.browser.msie)
1400                         event.target = event.preventDefault = event.stopPropagation =
1401                                 event.handler = event.data = null;
1403                 return val;
1404         },
1406         fix: function(event) {
1407                 // store a copy of the original event object 
1408                 // and clone to set read-only properties
1409                 var originalEvent = event;
1410                 event = jQuery.extend({}, originalEvent);
1411                 
1412                 // add preventDefault and stopPropagation since 
1413                 // they will not work on the clone
1414                 event.preventDefault = function() {
1415                         // if preventDefault exists run it on the original event
1416                         if (originalEvent.preventDefault)
1417                                 return originalEvent.preventDefault();
1418                         // otherwise set the returnValue property of the original event to false (IE)
1419                         originalEvent.returnValue = false;
1420                 };
1421                 event.stopPropagation = function() {
1422                         // if stopPropagation exists run it on the original event
1423                         if (originalEvent.stopPropagation)
1424                                 return originalEvent.stopPropagation();
1425                         // otherwise set the cancelBubble property of the original event to true (IE)
1426                         originalEvent.cancelBubble = true;
1427                 };
1428                 
1429                 // Fix target property, if necessary
1430                 if ( !event.target && event.srcElement )
1431                         event.target = event.srcElement;
1432                                 
1433                 // check if target is a textnode (safari)
1434                 if (jQuery.browser.safari && event.target.nodeType == 3)
1435                         event.target = originalEvent.target.parentNode;
1437                 // Add relatedTarget, if necessary
1438                 if ( !event.relatedTarget && event.fromElement )
1439                         event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
1441                 // Calculate pageX/Y if missing and clientX/Y available
1442                 if ( event.pageX == null && event.clientX != null ) {
1443                         var e = document.documentElement, b = document.body;
1444                         event.pageX = event.clientX + (e && e.scrollLeft || b.scrollLeft);
1445                         event.pageY = event.clientY + (e && e.scrollTop || b.scrollTop);
1446                 }
1447                         
1448                 // Add which for key events
1449                 if ( !event.which && (event.charCode || event.keyCode) )
1450                         event.which = event.charCode || event.keyCode;
1451                 
1452                 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
1453                 if ( !event.metaKey && event.ctrlKey )
1454                         event.metaKey = event.ctrlKey;
1456                 // Add which for click: 1 == left; 2 == middle; 3 == right
1457                 // Note: button is not normalized, so don't use it
1458                 if ( !event.which && event.button )
1459                         event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
1460                         
1461                 return event;
1462         }
1465 jQuery.fn.extend({
1466         bind: function( type, data, fn ) {
1467                 return type == "unload" ? this.one(type, data, fn) : this.each(function(){
1468                         jQuery.event.add( this, type, fn || data, fn && data );
1469                 });
1470         },
1471         one: function( type, data, fn ) {
1472                 return this.each(function(){
1473                         jQuery.event.add( this, type, function(event) {
1474                                 jQuery(this).unbind(event);
1475                                 return (fn || data).apply( this, arguments);
1476                         }, fn && data);
1477                 });
1478         },
1479         unbind: function( type, fn ) {
1480                 return this.each(function(){
1481                         jQuery.event.remove( this, type, fn );
1482                 });
1483         },
1484         trigger: function( type, data ) {
1485                 return this.each(function(){
1486                         jQuery.event.trigger( type, data, this );
1487                 });
1488         },
1489         toggle: function() {
1490                 // Save reference to arguments for access in closure
1491                 var a = arguments;
1493                 return this.click(function(e) {
1494                         // Figure out which function to execute
1495                         this.lastToggle = 0 == this.lastToggle ? 1 : 0;
1496                         
1497                         // Make sure that clicks stop
1498                         e.preventDefault();
1499                         
1500                         // and execute the function
1501                         return a[this.lastToggle].apply( this, [e] ) || false;
1502                 });
1503         },
1504         hover: function(f,g) {
1505                 
1506                 // A private function for handling mouse 'hovering'
1507                 function handleHover(e) {
1508                         // Check if mouse(over|out) are still within the same parent element
1509                         var p = e.relatedTarget;
1510         
1511                         // Traverse up the tree
1512                         while ( p && p != this ) try { p = p.parentNode } catch(e) { p = this; };
1513                         
1514                         // If we actually just moused on to a sub-element, ignore it
1515                         if ( p == this ) return false;
1516                         
1517                         // Execute the right function
1518                         return (e.type == "mouseover" ? f : g).apply(this, [e]);
1519                 }
1520                 
1521                 // Bind the function to the two event listeners
1522                 return this.mouseover(handleHover).mouseout(handleHover);
1523         },
1524         ready: function(f) {
1525                 // If the DOM is already ready
1526                 if ( jQuery.isReady )
1527                         // Execute the function immediately
1528                         f.apply( document, [jQuery] );
1529                         
1530                 // Otherwise, remember the function for later
1531                 else
1532                         // Add the function to the wait list
1533                         jQuery.readyList.push( function() { return f.apply(this, [jQuery]) } );
1534         
1535                 return this;
1536         }
1539 jQuery.extend({
1540         /*
1541          * All the code that makes DOM Ready work nicely.
1542          */
1543         isReady: false,
1544         readyList: [],
1545         
1546         // Handle when the DOM is ready
1547         ready: function() {
1548                 // Make sure that the DOM is not already loaded
1549                 if ( !jQuery.isReady ) {
1550                         // Remember that the DOM is ready
1551                         jQuery.isReady = true;
1552                         
1553                         // If there are functions bound, to execute
1554                         if ( jQuery.readyList ) {
1555                                 // Execute all of them
1556                                 jQuery.each( jQuery.readyList, function(){
1557                                         this.apply( document );
1558                                 });
1559                                 
1560                                 // Reset the list of functions
1561                                 jQuery.readyList = null;
1562                         }
1563                         // Remove event listener to avoid memory leak
1564                         if ( jQuery.browser.mozilla || jQuery.browser.opera )
1565                                 document.removeEventListener( "DOMContentLoaded", jQuery.ready, false );
1566                         
1567                         // Remove script element used by IE hack
1568                         if( !window.frames.length ) // don't remove if frames are present (#1187)
1569                                 jQuery(window).load(function(){ jQuery("#__ie_init").remove(); });
1570                 }
1571         }
1574 new function(){
1576         jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
1577                 "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + 
1578                 "submit,keydown,keypress,keyup,error").split(","), function(i,o){
1579                 
1580                 // Handle event binding
1581                 jQuery.fn[o] = function(f){
1582                         return f ? this.bind(o, f) : this.trigger(o);
1583                 };
1584                         
1585         });
1586         
1587         // If Mozilla is used
1588         if ( jQuery.browser.mozilla || jQuery.browser.opera )
1589                 // Use the handy event callback
1590                 document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
1591         
1592         // If IE is used, use the excellent hack by Matthias Miller
1593         // http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited
1594         else if ( jQuery.browser.msie ) {
1595         
1596                 // Only works if you document.write() it
1597                 document.write("<scr" + "ipt id=__ie_init defer=true " + 
1598                         "src=//:><\/script>");
1599         
1600                 // Use the defer script hack
1601                 var script = document.getElementById("__ie_init");
1602                 
1603                 // script does not exist if jQuery is loaded dynamically
1604                 if ( script ) 
1605                         script.onreadystatechange = function() {
1606                                 if ( this.readyState != "complete" ) return;
1607                                 jQuery.ready();
1608                         };
1609         
1610                 // Clear from memory
1611                 script = null;
1612         
1613         // If Safari  is used
1614         } else if ( jQuery.browser.safari )
1615                 // Continually check to see if the document.readyState is valid
1616                 jQuery.safariTimer = setInterval(function(){
1617                         // loaded and complete are both valid states
1618                         if ( document.readyState == "loaded" || 
1619                                 document.readyState == "complete" ) {
1620         
1621                                 // If either one are found, remove the timer
1622                                 clearInterval( jQuery.safariTimer );
1623                                 jQuery.safariTimer = null;
1624         
1625                                 // and execute any waiting functions
1626                                 jQuery.ready();
1627                         }
1628                 }, 10); 
1630         // A fallback to window.onload, that will always work
1631         jQuery.event.add( window, "load", jQuery.ready );
1632         
1635 // Clean up after IE to avoid memory leaks
1636 if (jQuery.browser.msie)
1637         jQuery(window).one("unload", function() {
1638                 var global = jQuery.event.global;
1639                 for ( var type in global ) {
1640                         var els = global[type], i = els.length;
1641                         if ( i && type != 'unload' )
1642                                 do
1643                                         els[i-1] && jQuery.event.remove(els[i-1], type);
1644                                 while (--i);
1645                 }
1646         });
1647 jQuery.fn.extend({
1648         loadIfModified: function( url, params, callback ) {
1649                 this.load( url, params, callback, 1 );
1650         },
1651         load: function( url, params, callback, ifModified ) {
1652                 if ( jQuery.isFunction( url ) )
1653                         return this.bind("load", url);
1655                 callback = callback || function(){};
1657                 // Default to a GET request
1658                 var type = "GET";
1660                 // If the second parameter was provided
1661                 if ( params )
1662                         // If it's a function
1663                         if ( jQuery.isFunction( params ) ) {
1664                                 // We assume that it's the callback
1665                                 callback = params;
1666                                 params = null;
1668                         // Otherwise, build a param string
1669                         } else {
1670                                 params = jQuery.param( params );
1671                                 type = "POST";
1672                         }
1674                 var self = this;
1676                 // Request the remote document
1677                 jQuery.ajax({
1678                         url: url,
1679                         type: type,
1680                         data: params,
1681                         ifModified: ifModified,
1682                         complete: function(res, status){
1683                                 if ( status == "success" || !ifModified && status == "notmodified" )
1684                                         // Inject the HTML into all the matched elements
1685                                         self.attr("innerHTML", res.responseText)
1686                                           // Execute all the scripts inside of the newly-injected HTML
1687                                           .evalScripts()
1688                                           // Execute callback
1689                                           .each( callback, [res.responseText, status, res] );
1690                                 else
1691                                         callback.apply( self, [res.responseText, status, res] );
1692                         }
1693                 });
1694                 return this;
1695         },
1696         serialize: function() {
1697                 return jQuery.param( this );
1698         },
1699         evalScripts: function() {
1700                 return this.find("script").each(function(){
1701                         if ( this.src )
1702                                 jQuery.getScript( this.src );
1703                         else
1704                                 jQuery.globalEval( this.text || this.textContent || this.innerHTML || "" );
1705                 }).end();
1706         }
1710 // Attach a bunch of functions for handling common AJAX events
1712 jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
1713         jQuery.fn[o] = function(f){
1714                 return this.bind(o, f);
1715         };
1718 jQuery.extend({
1719         get: function( url, data, callback, type, ifModified ) {
1720                 // shift arguments if data argument was ommited
1721                 if ( jQuery.isFunction( data ) ) {
1722                         callback = data;
1723                         data = null;
1724                 }
1725                 
1726                 return jQuery.ajax({
1727                         type: "GET",
1728                         url: url,
1729                         data: data,
1730                         success: callback,
1731                         dataType: type,
1732                         ifModified: ifModified
1733                 });
1734         },
1735         getIfModified: function( url, data, callback, type ) {
1736                 return jQuery.get(url, data, callback, type, 1);
1737         },
1738         getScript: function( url, callback ) {
1739                 return jQuery.get(url, null, callback, "script");
1740         },
1741         getJSON: function( url, data, callback ) {
1742                 return jQuery.get(url, data, callback, "json");
1743         },
1744         post: function( url, data, callback, type ) {
1745                 if ( jQuery.isFunction( data ) ) {
1746                         callback = data;
1747                         data = {};
1748                 }
1750                 return jQuery.ajax({
1751                         type: "POST",
1752                         url: url,
1753                         data: data,
1754                         success: callback,
1755                         dataType: type
1756                 });
1757         },
1758         ajaxTimeout: function( timeout ) {
1759                 jQuery.ajaxSettings.timeout = timeout;
1760         },
1761         ajaxSetup: function( settings ) {
1762                 jQuery.extend( jQuery.ajaxSettings, settings );
1763         },
1765         ajaxSettings: {
1766                 global: true,
1767                 type: "GET",
1768                 timeout: 0,
1769                 contentType: "application/x-www-form-urlencoded",
1770                 processData: true,
1771                 async: true,
1772                 data: null
1773         },
1774         
1775         // Last-Modified header cache for next request
1776         lastModified: {},
1777         ajax: function( s ) {
1778                 // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
1779                 s = jQuery.extend({}, jQuery.ajaxSettings, s);
1781                 // if data available
1782                 if ( s.data ) {
1783                         // convert data if not already a string
1784                         if (s.processData && typeof s.data != "string")
1785                         s.data = jQuery.param(s.data);
1786                         // append data to url for get requests
1787                         if( s.type.toLowerCase() == "get" ) {
1788                                 // "?" + data or "&" + data (in case there are already params)
1789                                 s.url += ((s.url.indexOf("?") > -1) ? "&" : "?") + s.data;
1790                                 // IE likes to send both get and post data, prevent this
1791                                 s.data = null;
1792                         }
1793                 }
1795                 // Watch for a new set of requests
1796                 if ( s.global && ! jQuery.active++ )
1797                         jQuery.event.trigger( "ajaxStart" );
1799                 var requestDone = false;
1801                 // Create the request object; Microsoft failed to properly
1802                 // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
1803                 var xml = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
1805                 // Open the socket
1806                 xml.open(s.type, s.url, s.async);
1808                 // Set the correct header, if data is being sent
1809                 if ( s.data )
1810                         xml.setRequestHeader("Content-Type", s.contentType);
1812                 // Set the If-Modified-Since header, if ifModified mode.
1813                 if ( s.ifModified )
1814                         xml.setRequestHeader("If-Modified-Since",
1815                                 jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
1817                 // Set header so the called script knows that it's an XMLHttpRequest
1818                 xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");
1820                 // Allow custom headers/mimetypes
1821                 if( s.beforeSend )
1822                         s.beforeSend(xml);
1823                         
1824                 if ( s.global )
1825                     jQuery.event.trigger("ajaxSend", [xml, s]);
1827                 // Wait for a response to come back
1828                 var onreadystatechange = function(isTimeout){
1829                         // The transfer is complete and the data is available, or the request timed out
1830                         if ( xml && (xml.readyState == 4 || isTimeout == "timeout") ) {
1831                                 requestDone = true;
1832                                 
1833                                 // clear poll interval
1834                                 if (ival) {
1835                                         clearInterval(ival);
1836                                         ival = null;
1837                                 }
1838                                 
1839                                 var status;
1840                                 try {
1841                                         status = jQuery.httpSuccess( xml ) && isTimeout != "timeout" ?
1842                                                 s.ifModified && jQuery.httpNotModified( xml, s.url ) ? "notmodified" : "success" : "error";
1843                                         // Make sure that the request was successful or notmodified
1844                                         if ( status != "error" ) {
1845                                                 // Cache Last-Modified header, if ifModified mode.
1846                                                 var modRes;
1847                                                 try {
1848                                                         modRes = xml.getResponseHeader("Last-Modified");
1849                                                 } catch(e) {} // swallow exception thrown by FF if header is not available
1850         
1851                                                 if ( s.ifModified && modRes )
1852                                                         jQuery.lastModified[s.url] = modRes;
1853         
1854                                                 // process the data (runs the xml through httpData regardless of callback)
1855                                                 var data = jQuery.httpData( xml, s.dataType );
1856         
1857                                                 // If a local callback was specified, fire it and pass it the data
1858                                                 if ( s.success )
1859                                                         s.success( data, status );
1860         
1861                                                 // Fire the global callback
1862                                                 if( s.global )
1863                                                         jQuery.event.trigger( "ajaxSuccess", [xml, s] );
1864                                         } else
1865                                                 jQuery.handleError(s, xml, status);
1866                                 } catch(e) {
1867                                         status = "error";
1868                                         jQuery.handleError(s, xml, status, e);
1869                                 }
1871                                 // The request was completed
1872                                 if( s.global )
1873                                         jQuery.event.trigger( "ajaxComplete", [xml, s] );
1875                                 // Handle the global AJAX counter
1876                                 if ( s.global && ! --jQuery.active )
1877                                         jQuery.event.trigger( "ajaxStop" );
1879                                 // Process result
1880                                 if ( s.complete )
1881                                         s.complete(xml, status);
1883                                 // Stop memory leaks
1884                                 if(s.async)
1885                                         xml = null;
1886                         }
1887                 };
1888                 
1889                 // don't attach the handler to the request, just poll it instead
1890                 var ival = setInterval(onreadystatechange, 13); 
1892                 // Timeout checker
1893                 if ( s.timeout > 0 )
1894                         setTimeout(function(){
1895                                 // Check to see if the request is still happening
1896                                 if ( xml ) {
1897                                         // Cancel the request
1898                                         xml.abort();
1900                                         if( !requestDone )
1901                                                 onreadystatechange( "timeout" );
1902                                 }
1903                         }, s.timeout);
1904                         
1905                 // Send the data
1906                 try {
1907                         xml.send(s.data);
1908                 } catch(e) {
1909                         jQuery.handleError(s, xml, null, e);
1910                 }
1911                 
1912                 // firefox 1.5 doesn't fire statechange for sync requests
1913                 if ( !s.async )
1914                         onreadystatechange();
1915                 
1916                 // return XMLHttpRequest to allow aborting the request etc.
1917                 return xml;
1918         },
1920         handleError: function( s, xml, status, e ) {
1921                 // If a local callback was specified, fire it
1922                 if ( s.error ) s.error( xml, status, e );
1924                 // Fire the global callback
1925                 if ( s.global )
1926                         jQuery.event.trigger( "ajaxError", [xml, s, e] );
1927         },
1929         // Counter for holding the number of active queries
1930         active: 0,
1932         // Determines if an XMLHttpRequest was successful or not
1933         httpSuccess: function( r ) {
1934                 try {
1935                         return !r.status && location.protocol == "file:" ||
1936                                 ( r.status >= 200 && r.status < 300 ) || r.status == 304 ||
1937                                 jQuery.browser.safari && r.status == undefined;
1938                 } catch(e){}
1939                 return false;
1940         },
1942         // Determines if an XMLHttpRequest returns NotModified
1943         httpNotModified: function( xml, url ) {
1944                 try {
1945                         var xmlRes = xml.getResponseHeader("Last-Modified");
1947                         // Firefox always returns 200. check Last-Modified date
1948                         return xml.status == 304 || xmlRes == jQuery.lastModified[url] ||
1949                                 jQuery.browser.safari && xml.status == undefined;
1950                 } catch(e){}
1951                 return false;
1952         },
1954         /* Get the data out of an XMLHttpRequest.
1955          * Return parsed XML if content-type header is "xml" and type is "xml" or omitted,
1956          * otherwise return plain text.
1957          * (String) data - The type of data that you're expecting back,
1958          * (e.g. "xml", "html", "script")
1959          */
1960         httpData: function( r, type ) {
1961                 var ct = r.getResponseHeader("content-type");
1962                 var data = !type && ct && ct.indexOf("xml") >= 0;
1963                 data = type == "xml" || data ? r.responseXML : r.responseText;
1965                 // If the type is "script", eval it in global context
1966                 if ( type == "script" )
1967                         jQuery.globalEval( data );
1969                 // Get the JavaScript object, if JSON is used.
1970                 if ( type == "json" )
1971                         data = eval("(" + data + ")");
1973                 // evaluate scripts within html
1974                 if ( type == "html" )
1975                         jQuery("<div>").html(data).evalScripts();
1977                 return data;
1978         },
1980         // Serialize an array of form elements or a set of
1981         // key/values into a query string
1982         param: function( a ) {
1983                 var s = [];
1985                 // If an array was passed in, assume that it is an array
1986                 // of form elements
1987                 if ( a.constructor == Array || a.jquery )
1988                         // Serialize the form elements
1989                         jQuery.each( a, function(){
1990                                 s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
1991                         });
1993                 // Otherwise, assume that it's an object of key/value pairs
1994                 else
1995                         // Serialize the key/values
1996                         for ( var j in a )
1997                                 // If the value is an array then the key names need to be repeated
1998                                 if ( a[j] && a[j].constructor == Array )
1999                                         jQuery.each( a[j], function(){
2000                                                 s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
2001                                         });
2002                                 else
2003                                         s.push( encodeURIComponent(j) + "=" + encodeURIComponent( a[j] ) );
2005                 // Return the resulting serialization
2006                 return s.join("&");
2007         },
2008         
2009         // evalulates a script in global context
2010         // not reliable for safari
2011         globalEval: function( data ) {
2012                 if ( window.execScript )
2013                         window.execScript( data );
2014                 else if ( jQuery.browser.safari )
2015                         // safari doesn't provide a synchronous global eval
2016                         window.setTimeout( data, 0 );
2017                 else
2018                         eval.call( window, data );
2019         }
2022 jQuery.fn.extend({
2024         show: function(speed,callback){
2025                 return speed ?
2026                         this.animate({
2027                                 height: "show", width: "show", opacity: "show"
2028                         }, speed, callback) :
2029                         
2030                         this.filter(":hidden").each(function(){
2031                                 this.style.display = this.oldblock ? this.oldblock : "";
2032                                 if ( jQuery.css(this,"display") == "none" )
2033                                         this.style.display = "block";
2034                         }).end();
2035         },
2037         hide: function(speed,callback){
2038                 return speed ?
2039                         this.animate({
2040                                 height: "hide", width: "hide", opacity: "hide"
2041                         }, speed, callback) :
2042                         
2043                         this.filter(":visible").each(function(){
2044                                 this.oldblock = this.oldblock || jQuery.css(this,"display");
2045                                 if ( this.oldblock == "none" )
2046                                         this.oldblock = "block";
2047                                 this.style.display = "none";
2048                         }).end();
2049         },
2051         // Save the old toggle function
2052         _toggle: jQuery.fn.toggle,
2053         toggle: function( fn, fn2 ){
2054                 return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
2055                         this._toggle( fn, fn2 ) :
2056                         fn ?
2057                                 this.animate({
2058                                         height: "toggle", width: "toggle", opacity: "toggle"
2059                                 }, fn, fn2) :
2060                                 this.each(function(){
2061                                         jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
2062                                 });
2063         },
2064         slideDown: function(speed,callback){
2065                 return this.animate({height: "show"}, speed, callback);
2066         },
2067         slideUp: function(speed,callback){
2068                 return this.animate({height: "hide"}, speed, callback);
2069         },
2070         slideToggle: function(speed, callback){
2071                 return this.animate({height: "toggle"}, speed, callback);
2072         },
2073         fadeIn: function(speed, callback){
2074                 return this.animate({opacity: "show"}, speed, callback);
2075         },
2076         fadeOut: function(speed, callback){
2077                 return this.animate({opacity: "hide"}, speed, callback);
2078         },
2079         fadeTo: function(speed,to,callback){
2080                 return this.animate({opacity: to}, speed, callback);
2081         },
2082         animate: function( prop, speed, easing, callback ) {
2083                 return this.queue(function(){
2084                         var hidden = jQuery(this).is(":hidden"),
2085                                 opt = jQuery.speed(speed, easing, callback),
2086                                 self = this;
2087                         
2088                         for ( var p in prop )
2089                                 if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
2090                                         return jQuery.isFunction(opt.complete) && opt.complete.apply(this);
2092                         this.curAnim = jQuery.extend({}, prop);
2093                         
2094                         jQuery.each( prop, function(name, val){
2095                                 var e = new jQuery.fx( self, opt, name );
2096                                 if ( val.constructor == Number )
2097                                         e.custom( e.cur(), val );
2098                                 else
2099                                         e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
2100                         });
2101                 });
2102         },
2103         queue: function(type,fn){
2104                 if ( !fn ) {
2105                         fn = type;
2106                         type = "fx";
2107                 }
2108         
2109                 return this.each(function(){
2110                         if ( !this.queue )
2111                                 this.queue = {};
2112         
2113                         if ( !this.queue[type] )
2114                                 this.queue[type] = [];
2115         
2116                         this.queue[type].push( fn );
2117                 
2118                         if ( this.queue[type].length == 1 )
2119                                 fn.apply(this);
2120                 });
2121         }
2125 jQuery.extend({
2126         
2127         speed: function(speed, easing, fn) {
2128                 var opt = speed && speed.constructor == Object ? speed : {
2129                         complete: fn || !fn && easing || 
2130                                 jQuery.isFunction( speed ) && speed,
2131                         duration: speed,
2132                         easing: fn && easing || easing && easing.constructor != Function && easing || (jQuery.easing.swing ? "swing" : "linear")
2133                 };
2135                 opt.duration = (opt.duration && opt.duration.constructor == Number ? 
2136                         opt.duration : 
2137                         { slow: 600, fast: 200 }[opt.duration]) || 400;
2138         
2139                 // Queueing
2140                 opt.old = opt.complete;
2141                 opt.complete = function(){
2142                         jQuery.dequeue(this, "fx");
2143                         if ( jQuery.isFunction( opt.old ) )
2144                                 opt.old.apply( this );
2145                 };
2146         
2147                 return opt;
2148         },
2149         
2150         easing: {
2151                 linear: function( p, n, firstNum, diff ) {
2152                         return firstNum + diff * p;
2153                 },
2154                 swing: function( p, n, firstNum, diff ) {
2155                         return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
2156                 }
2157         },
2158         
2159         queue: {},
2160         
2161         dequeue: function(elem,type){
2162                 type = type || "fx";
2163         
2164                 if ( elem.queue && elem.queue[type] ) {
2165                         // Remove self
2166                         elem.queue[type].shift();
2167         
2168                         // Get next function
2169                         var f = elem.queue[type][0];
2170                 
2171                         if ( f ) f.apply( elem );
2172                 }
2173         },
2175         timers: [],
2177         /*
2178          * I originally wrote fx() as a clone of moo.fx and in the process
2179          * of making it small in size the code became illegible to sane
2180          * people. You've been warned.
2181          */
2182         
2183         fx: function( elem, options, prop ){
2185                 var z = this;
2187                 // The styles
2188                 var y = elem.style;
2189                 
2190                 if ( prop == "height" || prop == "width" ) {
2191                         // Store display property
2192                         var oldDisplay = jQuery.css(elem, "display");
2194                         // Make sure that nothing sneaks out
2195                         var oldOverflow = y.overflow;
2196                         y.overflow = "hidden";
2197                 }
2199                 // Simple function for setting a style value
2200                 z.a = function(){
2201                         if ( options.step )
2202                                 options.step.apply( elem, [ z.now ] );
2204                         if ( prop == "opacity" )
2205                                 jQuery.attr(y, "opacity", z.now); // Let attr handle opacity
2206                         else {
2207                                 y[prop] = parseInt(z.now) + "px";
2208                                 y.display = "block"; // Set display property to block for animation
2209                         }
2210                 };
2212                 // Figure out the maximum number to run to
2213                 z.max = function(){
2214                         return parseFloat( jQuery.css(elem,prop) );
2215                 };
2217                 // Get the current size
2218                 z.cur = function(){
2219                         var r = parseFloat( jQuery.curCSS(elem, prop) );
2220                         return r && r > -10000 ? r : z.max();
2221                 };
2223                 // Start an animation from one number to another
2224                 z.custom = function(from,to){
2225                         z.startTime = (new Date()).getTime();
2226                         z.now = from;
2227                         z.a();
2229                         jQuery.timers.push(function(){
2230                                 return z.step(from, to);
2231                         });
2233                         if ( jQuery.timers.length == 1 ) {
2234                                 var timer = setInterval(function(){
2235                                         var timers = jQuery.timers;
2236                                         
2237                                         for ( var i = 0; i < timers.length; i++ )
2238                                                 if ( !timers[i]() )
2239                                                         timers.splice(i--, 1);
2241                                         if ( !timers.length )
2242                                                 clearInterval( timer );
2243                                 }, 13);
2244                         }
2245                 };
2247                 // Simple 'show' function
2248                 z.show = function(){
2249                         if ( !elem.orig ) elem.orig = {};
2251                         // Remember where we started, so that we can go back to it later
2252                         elem.orig[prop] = jQuery.attr( elem.style, prop );
2254                         options.show = true;
2256                         // Begin the animation
2257                         z.custom(0, this.cur());
2259                         // Make sure that we start at a small width/height to avoid any
2260                         // flash of content
2261                         if ( prop != "opacity" )
2262                                 y[prop] = "1px";
2263                         
2264                         // Start by showing the element
2265                         jQuery(elem).show();
2266                 };
2268                 // Simple 'hide' function
2269                 z.hide = function(){
2270                         if ( !elem.orig ) elem.orig = {};
2272                         // Remember where we started, so that we can go back to it later
2273                         elem.orig[prop] = jQuery.attr( elem.style, prop );
2275                         options.hide = true;
2277                         // Begin the animation
2278                         z.custom(this.cur(), 0);
2279                 };
2281                 // Each step of an animation
2282                 z.step = function(firstNum, lastNum){
2283                         var t = (new Date()).getTime();
2285                         if (t > options.duration + z.startTime) {
2286                                 z.now = lastNum;
2287                                 z.a();
2289                                 if (elem.curAnim) elem.curAnim[ prop ] = true;
2291                                 var done = true;
2292                                 for ( var i in elem.curAnim )
2293                                         if ( elem.curAnim[i] !== true )
2294                                                 done = false;
2296                                 if ( done ) {
2297                                         if ( oldDisplay != null ) {
2298                                                 // Reset the overflow
2299                                                 y.overflow = oldOverflow;
2300                                         
2301                                                 // Reset the display
2302                                                 y.display = oldDisplay;
2303                                                 if ( jQuery.css(elem, "display") == "none" )
2304                                                         y.display = "block";
2305                                         }
2307                                         // Hide the element if the "hide" operation was done
2308                                         if ( options.hide )
2309                                                 y.display = "none";
2311                                         // Reset the properties, if the item has been hidden or shown
2312                                         if ( options.hide || options.show )
2313                                                 for ( var p in elem.curAnim )
2314                                                         jQuery.attr(y, p, elem.orig[p]);
2315                                 }
2317                                 // If a callback was provided, execute it
2318                                 if ( done && jQuery.isFunction( options.complete ) )
2319                                         // Execute the complete function
2320                                         options.complete.apply( elem );
2322                                 return false;
2323                         } else {
2324                                 var n = t - this.startTime;
2325                                 // Figure out where in the animation we are and set the number
2326                                 var p = n / options.duration;
2327                                 
2328                                 // Perform the easing function, defaults to swing
2329                                 z.now = jQuery.easing[options.easing](p, n, firstNum, (lastNum-firstNum), options.duration);
2331                                 // Perform the next step of the animation
2332                                 z.a();
2333                         }
2335                         return true;
2336                 };
2337         
2338         }