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