Added document.ready shortcut to $().
[jquery.git] / jquery / jquery.js
1 /*
2  * jQuery - New Wave Javascript
3  *
4  * Copyright (c) 2006 John Resig (jquery.com)
5  * Licensed under the MIT License:
6  *   http://www.opensource.org/licenses/mit-license.php
7  *
8  * $Date$
9  * $Rev$
10  */
11
12 // Global undefined variable
13 window.undefined = window.undefined;
14
15 /**
16  * Create a new jQuery Object
17  * @constructor
18  */
19 function jQuery(a,c) {
20
21         // Shortcut for document ready (because $(document).each() is silly)
22         if ( a && a.constructor == Function )
23                 return $(document).ready(a);
24
25         // Make sure t hat a selection was provided
26         a = a || jQuery.context || document;
27
28         /*
29          * Handle support for overriding other $() functions. Way too many libraries
30          * provide this function to simply ignore it and overwrite it.
31          */
32
33         // Check to see if this is a possible collision case
34         if ( jQuery._$ && !c && a.constructor == String && 
35       
36                 // Make sure that the expression is a colliding one
37                 !/[^a-zA-Z0-9_-]/.test(a) &&
38         
39                 // and that there are no elements that match it
40                 // (this is the one truly ambiguous case)
41                 !document.getElementsByTagName(a).length )
42
43                         // Use the default method, in case it works some voodoo
44                         return jQuery._$( a );
45
46         // Watch for when a jQuery object is passed as the selector
47         if ( a.jquery )
48                 return a;
49
50         // Watch for when a jQuery object is passed at the context
51         if ( c && c.jquery )
52                 return $(c.get()).find(a);
53         
54         // If the context is global, return a new object
55         if ( window == this )
56                 return new jQuery(a,c);
57
58         // Watch for when an array is passed in
59         this.get( a.constructor == Array ?
60                 // Assume that it's an array of DOM Elements
61                 a :
62
63                 // Find the matching elements and save them for later
64                 jQuery.Select( a, c ) );
65
66         var fn = arguments[ arguments.length - 1 ];
67         if ( fn && fn.constructor == Function )
68                 this.each(fn);
69 }
70
71 // Map over the $ in case of overwrite
72 if ( $ )
73         jQuery._$ = $;
74
75 // Map the jQuery namespace to the '$' one
76 var $ = jQuery;
77
78 jQuery.fn = jQuery.prototype = {
79         /**
80          * The current SVN version of jQuery.
81          *
82          * @private
83          * @type String
84          */
85         jquery: "$Rev$",
86         
87         /**
88          * The number of elements currently matched.
89          *
90          * @type Number
91          */
92         size: function() {
93                 return this.length;
94         },
95         
96         /**
97          * Access the elements matched. If a number is provided,
98          * the Nth element is returned, otherwise, an array of all
99          * matched items is returned.
100          *
101          * @type Array,DOMElement
102          */
103         get: function(num) {
104                 if ( num && num.constructor == Array ) {
105                         this.length = 0;
106                         [].push.apply( this, num );
107                 } else
108                         return num == undefined ?
109
110                                 // Return a 'clean' array
111                                 $.map( this, function(a){ return a } ) :
112
113                                 // Return just the object
114                                 this[num];
115         },
116         
117         each: function(f) {
118                 for ( var i = 0; i < this.size(); i++ )
119                         f.apply( this[i], [i] );
120                 return this;
121         },
122         set: function(a,b) {
123                 return this.each(function(){
124                         if ( b === undefined )
125                                 for ( var j in a )
126                                         jQuery.attr(this,j,a[j]);
127                         else
128                                 jQuery.attr(this,a,b);
129                 });
130         },
131         html: function(h) {
132                 return h == undefined && this.size() ?
133                         this[0].innerHTML : this.set( "innerHTML", h );
134         },
135         val: function(h) {
136                 return h == undefined && this.size() ?
137                         this[0].value : this.set( "value", h );
138         },
139         text: function(e) {
140                 e = e || this;
141                 var t = "";
142                 for ( var j = 0; j < e.length; j++ ) {
143                         var r = e[j].childNodes;
144                         for ( var i = 0; i < r.length; i++ )
145                                 t += r[i].nodeType != 1 ?
146                                         r[i].nodeValue : jQuery.fn.text([ r[i] ]);
147                 }
148                 return t;
149         },
150         
151         css: function(a,b) {
152                 return a.constructor != String || b ?
153                         this.each(function(){
154                                 if ( b === undefined )
155                                         for ( var j in a )
156                                                 jQuery.attr(this.style,j,a[j]);
157                                 else
158                                         jQuery.attr(this.style,a,b);
159                         }) : jQuery.css( this[0], a );
160         },
161         toggle: function() {
162                 return this.each(function(){
163                         var d = jQuery.css(this,"display");
164                         if ( !d || d == "none" )
165                                 $(this).show();
166                         else
167                                 $(this).hide();
168                 });
169         },
170         show: function() {
171                 return this.each(function(){
172                         this.style.display = this.oldblock ? this.oldblock : "";
173                         if ( jQuery.css(this,"display") == "none" )
174                                 this.style.display = "block";
175                 });
176         },
177         hide: function() {
178                 return this.each(function(){
179                         this.oldblock = jQuery.css(this,"display");
180                         if ( this.oldblock == "none" )
181                                 this.oldblock = "block";
182                         this.style.display = "none";
183                 });
184         },
185         addClass: function(c) {
186                 return this.each(function(){
187                         jQuery.className.add(this,c);
188                 });
189         },
190         removeClass: function(c) {
191                 return this.each(function(){
192                         jQuery.className.remove(this,c);
193                 });
194         },
195
196         toggleClass: function(c) {
197                 return this.each(function(){
198                         if (jQuery.hasWord(this,c))
199                                 jQuery.className.remove(this,c);
200                         else
201                                 jQuery.className.add(this,c);
202                 });
203         },
204         remove: function() {
205                 return this.each(function(){
206                         this.parentNode.removeChild( this );
207                 });
208         },
209         
210         wrap: function() {
211                 var a = jQuery.clean(arguments);
212                 return this.each(function(){
213                         var b = a[0].cloneNode(true);
214                         this.parentNode.insertBefore( b, this );
215                         while ( b.firstChild )
216                                 b = b.firstChild;
217                         b.appendChild( this );
218                 });
219         },
220         
221         append: function() {
222                 var clone = this.size() > 1;
223                 var a = jQuery.clean(arguments);
224                 return this.domManip(function(){
225                         for ( var i = 0; i < a.length; i++ )
226                                 this.appendChild( clone ? a[i].cloneNode(true) : a[i] );
227                 });
228         },
229         
230         appendTo: function() {
231                 var a = arguments;
232                 return this.each(function(){
233                         for ( var i = 0; i < a.length; i++ )
234                                 $(a[i]).append( this );
235                 });
236         },
237         
238         prepend: function() {
239                 var clone = this.size() > 1;
240                 var a = jQuery.clean(arguments);
241                 return this.domManip(function(){
242                         for ( var i = a.length - 1; i >= 0; i-- )
243                                 this.insertBefore( clone ? a[i].cloneNode(true) : a[i], this.firstChild );
244                 });
245         },
246         
247         before: function() {
248                 var clone = this.size() > 1;
249                 var a = jQuery.clean(arguments);
250                 return this.each(function(){
251                         for ( var i = 0; i < a.length; i++ )
252                                 this.parentNode.insertBefore( clone ? a[i].cloneNode(true) : a[i], this );
253                 });
254         },
255         
256         after: function() {
257                 var clone = this.size() > 1;
258                 var a = jQuery.clean(arguments);
259                 return this.each(function(){
260                         for ( var i = a.length - 1; i >= 0; i-- )
261                                 this.parentNode.insertBefore( clone ? a[i].cloneNode(true) : a[i], this.nextSibling );
262                 });
263         },
264         
265         empty: function() {
266                 return this.each(function(){
267                         while ( this.firstChild )
268                                 this.removeChild( this.firstChild );
269                 });
270         },
271         
272         bind: function(t,f) {
273                 return this.each(function(){jQuery.event.add(this,t,f);});
274         },
275         unbind: function(t,f) {
276                 return this.each(function(){jQuery.event.remove(this,t,f);});
277         },
278         trigger: function(t) {
279                 return this.each(function(){jQuery.event.trigger(this,t);});
280         },
281         
282         pushStack: function(a,args) {
283                 var fn = args[args.length-1];
284
285                 if ( !fn || fn.constructor != Function ) {
286                         if ( !this.stack ) this.stack = [];
287                         this.stack.push( this.get() );
288                         this.get( a );
289                 } else {
290                         var old = this.get();
291                         this.get( a );
292                         if ( fn.constructor == Function )
293                                 return this.each( fn );
294                         this.get( old );
295                 }
296
297                 return this;
298         },
299
300         end: function() {
301                 this.get( this.stack.pop() );
302                 return this;
303         },
304         
305         find: function(t) {
306                 return this.pushStack( $.map( this, function(a){
307                         return jQuery.Select(t,a);
308                 }), arguments );
309         },
310         
311         parent: function(a) {
312                 var ret = jQuery.map(this,"a.parentNode");
313                 if ( a ) ret = jQuery.filter(a,ret).r;
314                 return this.pushStack( ret, arguments );
315         },
316         
317         parents: function(a) {
318                 var ret = jQuery.map(this,jQuery.parents);
319                 if ( a ) ret = jQuery.filter(a,ret).r;
320                 return this.pushStack( ret, arguments );
321         },
322         
323         siblings: function(a) {
324                 // Incorrect, need to exclude current element
325                 var ret = jQuery.map(this,jQuery.sibling);
326                 if ( a ) ret = jQuery.filter(a,ret).r;
327                 return this.pushStack( ret, arguments );
328         },
329         
330         filter: function(t) {
331                 if ( /,/.test(t) ) {
332                         var p = t.split(/\s*,\s*/);
333                         return this.pushStack( $.map(this,function(a){
334                                 for ( var i = 0; i < p.length; i++ )
335                                         if ( jQuery.filter(p[i],[a]).r.length )
336                                                 return a;
337                         }), arguments );
338                 } else
339                         return this.pushStack( jQuery.filter(t,this).r, arguments );
340         },
341         not: function(t) {
342                 return this.pushStack( t.constructor == String ?
343                         jQuery.filter(t,this,false).r :
344                         jQuery.grep(this,function(a){ return a != t; }), arguments );
345         },
346         add: function(t) {
347                 return this.pushStack( jQuery.merge( this, t.constructor == String ?
348                         jQuery.Select(t) : t.constructor == Array ? t : [t] ), arguments );
349         },
350         
351         /**
352          * A wrapper function for each() to be used by append and prepend.
353          * Handles cases where you're trying to modify the inner contents of
354          * a table, when you actually need to work with the tbody.
355          *
356          * @member jQuery
357          * @param {String} expr The expression with which to filter
358          * @type Boolean
359          */
360         is: function(expr) {
361                 return jQuery.filter(expr,this).r.length > 0;
362         },
363         
364         /**
365          * A wrapper function for each() to be used by append and prepend.
366          * Handles cases where you're trying to modify the inner contents of
367          * a table, when you actually need to work with the tbody.
368          *
369          * @private
370          * @member jQuery
371          * @param {Function} fn The function doing the DOM manipulation.
372          * @type jQuery
373          */
374         domManip: function(fn){
375                 return this.each(function(){
376                         var obj = this;
377                         
378                         if ( this.nodeName == "TABLE" ) {
379                                 var tbody = this.getElementsByTagName("tbody");
380
381                                 if ( !tbody.length ) {
382                                         obj = document.createElement("tbody");
383                                         this.appendChild( obj );
384                                 } else
385                                         obj = tbody[0];
386                         }
387         
388                         fn.apply( obj );
389                 });
390         }
391 };
392
393 /**
394  * Similar to the Prototype $A() function, only it allows you to
395  * forcefully pass array-like structures into $().
396  */
397 jQuery.A = function(a){
398         // Create a temporary, clean, array
399         var r = [];
400
401         // and copy the old array contents over to it
402         for ( var i = 0; i < a.length; i++ )
403                 r.push( a[i] );
404
405         // Return the sane jQuery object
406         return $(r);
407 };
408
409 jQuery.className = {
410         add: function(o,c){
411                 if (jQuery.hasWord(o,c)) return;
412                 o.className += ( o.className ? " " : "" ) + c;
413         },
414         remove: function(o,c){
415                 o.className = !c ? "" :
416                         o.className.replace(
417                                 new RegExp("(^|\\s*\\b[^-])"+c+"($|\\b(?=[^-]))", "g"), "");
418         }
419 };
420
421 (function(){
422         var b = navigator.userAgent.toLowerCase();
423
424         // Figure out what browser is being used
425         jQuery.browser =
426                 ( /webkit/.test(b) && "safari" ) ||
427                 ( /opera/.test(b) && "opera" ) ||
428                 ( /msie/.test(b) && "msie" ) ||
429                 ( !/compatible/.test(b) && "mozilla" ) ||
430                 "other";
431
432         // Check to see if the W3C box model is being used
433         jQuery.boxModel = ( jQuery.browser != "msie" || document.compatMode == "CSS1Compat" );
434 })();
435
436 $.swap = function(e,o,f) {
437         for ( var i in o ) {
438                 e.style["old"+i] = e.style[i];
439                 e.style[i] = o[i];
440         }
441         f.apply( e, [] );
442         for ( var i in o )
443                 e.style[i] = e.style["old"+i];
444 };
445
446 jQuery.css = function(e,p) {
447         // Adapted from Prototype 1.4.0
448         if ( p == "height" || p == "width" ) {
449                 var old = {}, oHeight, oWidth, d = ["Top","Bottom","Right","Left"];
450
451                 for ( var i in d ) {
452                         old["padding" + d[i]] = 0;
453                         old["border" + d[i] + "Width"] = 0;
454                 }
455
456                 $.swap( e, old, function() {
457                         if (jQuery.css(e,"display") != 'none') {
458                                 oHeight = e.offsetHeight;
459                                 oWidth = e.offsetWidth;
460                         } else
461                                 $.swap( e, { visibility: 'hidden', position: 'absolute', display: '' },
462                                         function(){
463                                                 oHeight = e.clientHeight;
464                                                 oWidth = e.clientWidth;
465                                         });
466                 });
467
468                 return p == "height" ? oHeight : oWidth;
469         }
470         
471         var r;
472
473         if (e.style[p])
474                 r = e.style[p];
475         else if (e.currentStyle)
476                 r = e.currentStyle[p];
477         else if (document.defaultView && document.defaultView.getComputedStyle) {
478                 p = p.replace(/([A-Z])/g,"-$1").toLowerCase();
479                 var s = document.defaultView.getComputedStyle(e,"");
480                 r = s ? s.getPropertyValue(p) : null;
481         }
482         
483         return r;
484 };
485
486 jQuery.clean = function(a) {
487         var r = [];
488         for ( var i = 0; i < a.length; i++ ) {
489                 if ( a[i].constructor == String ) {
490
491                         if ( !a[i].indexOf("<tr") ) {
492                                 var tr = true;
493                                 a[i] = "<table>" + a[i] + "</table>";
494                         } else if ( !a[i].indexOf("<td") || !a[i].indexOf("<th") ) {
495                                 var td = true;
496                                 a[i] = "<table><tbody><tr>" + a[i] + "</tr></tbody></table>";
497                         }
498
499                         var div = document.createElement("div");
500                         div.innerHTML = a[i];
501
502                         if ( tr || td ) {
503                                 div = div.firstChild.firstChild;
504                                 if ( td ) div = div.firstChild;
505                         }
506
507                         for ( var j = 0; j < div.childNodes.length; j++ )
508                                 r[r.length] = div.childNodes[j];
509                 } else if ( a[i].length && !a[i].nodeType )
510                         for ( var k = 0; k < a[i].length; k++ )
511                                 r[r.length] = a[i][k];
512                 else if ( a[i] !== null )
513                         r[r.length] =
514                                 a[i].nodeType ? a[i] : document.createTextNode(a[i].toString());
515         }
516         return r;
517 };
518
519 jQuery.g = {
520         "": "m[2]== '*'||a.nodeName.toUpperCase()==m[2].toUpperCase()",
521         "#": "a.getAttribute('id')&&a.getAttribute('id')==m[2]",
522         ":": {
523                 lt: "i<m[3]-0",
524                 gt: "i>m[3]-0",
525                 nth: "m[3]-0==i",
526                 eq: "m[3]-0==i",
527                 first: "i==0",
528                 last: "i==r.length-1",
529                 even: "i%2==0",
530                 odd: "i%2==1",
531                 "first-child": "jQuery.sibling(a,0).cur",
532                 "nth-child": "(m[3]=='even'?jQuery.sibling(a,m[3]).n%2==0:(m[3]=='odd'?jQuery.sibling(a,m[3]).n%2==1:jQuery.sibling(a,m[3]).cur))",
533                 "last-child": "jQuery.sibling(a,0,true).cur",
534                 "nth-last-child": "jQuery.sibling(a,m[3],true).cur",
535                 "first-of-type": "jQuery.ofType(a,0)",
536                 "nth-of-type": "jQuery.ofType(a,m[3])",
537                 "last-of-type": "jQuery.ofType(a,0,true)",
538                 "nth-last-of-type": "jQuery.ofType(a,m[3],true)",
539                 "only-of-type": "jQuery.ofType(a)==1",
540                 "only-child": "jQuery.sibling(a).length==1",
541                 parent: "a.childNodes.length",
542                 empty: "!a.childNodes.length",
543                 root: "a==(a.ownerDocument||document).documentElement",
544                 contains: "(a.innerText||a.innerHTML).indexOf(m[3])!=-1",
545                 visible: "(!a.type||a.type!='hidden')&&(jQuery.css(a,'display')!='none'&&jQuery.css(a,'visibility')!= 'hidden')",
546                 hidden: "(a.type&&a.type=='hidden')||jQuery.css(a,'display')=='none'||jQuery.css(a,'visibility')== 'hidden'",
547                 enabled: "!a.disabled",
548                 disabled: "a.disabled",
549                 checked: "a.checked"
550         },
551         ".": "jQuery.hasWord(a,m[2])",
552         "@": {
553                 "=": "jQuery.attr(a,m[3])==m[4]",
554                 "!=": "jQuery.attr(a,m[3])!=m[4]",
555                 "~=": "jQuery.hasWord(jQuery.attr(a,m[3]),m[4])",
556                 "|=": "!jQuery.attr(a,m[3]).indexOf(m[4])",
557                 "^=": "!jQuery.attr(a,m[3]).indexOf(m[4])",
558                 "$=": "jQuery.attr(a,m[3]).substr( jQuery.attr(a,m[3]).length - m[4].length,m[4].length )==m[4]",
559                 "*=": "jQuery.attr(a,m[3]).indexOf(m[4])>=0",
560                 "": "m[3]=='*'?a.attributes.length>0:jQuery.attr(a,m[3])"
561         },
562         "[": "jQuery.Select(m[2],a).length"
563 };
564
565 jQuery.token = [
566         "\\.\\.|/\\.\\.", "a.parentNode",
567         ">|/", "jQuery.sibling(a.firstChild)",
568         "\\+", "jQuery.sibling(a).next",
569         "~", function(a){
570                 var r = [];
571                 var s = jQuery.sibling(a);
572                 if ( s.n > 0 )
573                         for ( var i = s.n; i < s.length; i++ )
574                                 r[r.length] = s[i];
575                 return r;
576         }
577 ];
578
579 jQuery.Select = function( t, context ) {
580         // Make sure that the context is a DOM Element
581         if ( context && context.getElementsByTagName == undefined )
582                 context = null;
583
584         // Set the correct context (if none is provided)
585         context = context || jQuery.context || document;
586
587         if ( t.constructor != String ) return [t];
588
589         if ( !t.indexOf("//") ) {
590                 context = context.documentElement;
591                 t = t.substr(2,t.length);
592         } else if ( !t.indexOf("/") ) {
593                 context = context.documentElement;
594                 t = t.substr(1,t.length);
595                 // FIX Assume the root element is right :(
596                 if ( t.indexOf("/") >= 1 )
597                         t = t.substr(t.indexOf("/"),t.length);
598         }
599
600         var ret = [context];
601         var done = [];
602         var last = null;
603
604         while ( t.length > 0 && last != t ) {
605                 var r = [];
606                 last = t;
607
608                 t = jQuery.cleanSpaces(t).replace( /^\/\//i, "" );
609                 
610                 var foundToken = false;
611                 
612                 for ( var i = 0; i < jQuery.token.length; i += 2 ) {
613                         var re = new RegExp("^(" + jQuery.token[i] + ")");
614                         var m = re.exec(t);
615                         
616                         if ( m ) {
617                                 r = ret = jQuery.map( ret, jQuery.token[i+1] );
618                                 t = jQuery.cleanSpaces( t.replace( re, "" ) );
619                                 foundToken = true;
620                         }
621                 }
622                 
623                 if ( !foundToken ) {
624
625                         if ( !t.indexOf(",") || !t.indexOf("|") ) {
626                                 if ( ret[0] == context ) ret.shift();
627                                 done = jQuery.merge( done, ret );
628                                 r = ret = [context];
629                                 t = " " + t.substr(1,t.length);
630                         } else {
631                                 var re2 = /^([#.]?)([a-z0-9\\*_-]*)/i;
632                                 var m = re2.exec(t);
633         
634                                 if ( m[1] == "#" ) {
635                                         // Ummm, should make this work in all XML docs
636                                         var oid = document.getElementById(m[2]);
637                                         r = ret = oid ? [oid] : [];
638                                         t = t.replace( re2, "" );
639                                 } else {
640                                         if ( !m[2] || m[1] == "." ) m[2] = "*";
641         
642                                         for ( var i = 0; i < ret.length; i++ )
643                                                 r = jQuery.merge( r,
644                                                         m[2] == "*" ?
645                                                                 jQuery.getAll(ret[i]) :
646                                                                 ret[i].getElementsByTagName(m[2])
647                                                 );
648                                 }
649                         }
650                         
651                 }
652
653                 if ( t ) {
654                         var val = jQuery.filter(t,r);
655                         ret = r = val.r;
656                         t = jQuery.cleanSpaces(val.t);
657                 }
658         }
659
660         if ( ret && ret[0] == context ) ret.shift();
661         done = jQuery.merge( done, ret );
662
663         return done;
664 };
665
666 jQuery.getAll = function(o,r) {
667         r = r || [];
668         var s = o.childNodes;
669         for ( var i = 0; i < s.length; i++ )
670                 if ( s[i].nodeType == 1 ) {
671                         r[r.length] = s[i];
672                         jQuery.getAll( s[i], r );
673                 }
674         return r;
675 };
676
677 jQuery.attr = function(o,a,v){
678         if ( a && a.constructor == String ) {
679                 var fix = {
680                         "for": "htmlFor",
681                         "class": "className",
682                         "float": "cssFloat"
683                 };
684                 a = (fix[a] && fix[a].replace && fix[a]) || a;
685                 var r = /-([a-z])/ig;
686                 a = a.replace(r,function(z,b){return b.toUpperCase();});
687                 if ( v != undefined ) {
688                         o[a] = v;
689                         if ( o.setAttribute && a != "disabled" )
690                                 o.setAttribute(a,v);
691                 }
692                 return o[a] || o.getAttribute(a) || "";
693         } else
694                 return "";
695 };
696
697 jQuery.filter = function(t,r,not) {
698         var g = jQuery.grep;
699         if ( not === false )
700                 g = function(a,f) {return jQuery.grep(a,f,true);};
701
702         while ( t && t.match(/^[:\\.#\\[a-zA-Z\\*]/) ) {
703                 var re = /^\[ *@([a-z*_-][a-z0-9()_-]*) *([~!|*$^=]*) *'?"?([^'"]*)'?"? *\]/i;
704                 var m = re.exec(t);
705
706                 if ( m )
707                         m = ["", "@", m[2], m[1], m[3]];
708                 else {
709                         re = /^(\[) *([^\]]*) *\]/i;
710                         m = re.exec(t);
711
712                         if ( !m ) {
713                                 re = /^(:)([a-z0-9*_-]*)\( *["']?([^ \)'"]*)['"]? *\)/i;
714                                 m = re.exec(t);
715
716                                 if ( !m ) {
717                                         re = /^([:\.#]*)([a-z0-9*_-]*)/i;
718                                         m = re.exec(t);
719                                 }
720                         }
721                 }
722                 t = t.replace( re, "" );
723
724                 if ( m[1] == ":" && m[2] == "not" )
725                         r = jQuery.filter(m[3],r,false).r;
726                 else {
727                         var f = null;
728
729                         if ( jQuery.g[m[1]].constructor == String )
730                                 f = jQuery.g[m[1]];
731                         else if ( jQuery.g[m[1]][m[2]] )
732                                 f = jQuery.g[m[1]][m[2]];
733
734                         if ( f ) {
735                                 eval("f = function(a,i){return " + f + "}");
736                                 r = g( r, f );
737                         }
738                 }
739         }
740
741         return { r: r, t: t };
742 };
743
744 jQuery.parents = function(a){
745         var b = [];
746         var c = a.parentNode;
747         while ( c && c != document ) {
748                 b[b.length] = c;
749                 c = c.parentNode;
750         }
751         return b;
752 };
753
754 jQuery.cleanSpaces = function(t){
755         return t.replace(/^\s+|\s+$/g, "");
756 };
757
758 jQuery.ofType = function(a,n,e) {
759         var t = jQuery.grep(jQuery.sibling(a),function(b){ return b.nodeName == a.nodeName; });
760         if ( e ) n = t.length - n - 1;
761         return n != undefined ? t[n] == a : t.length;
762 };
763
764 jQuery.sibling = function(a,n,e) {
765         var type = [];
766         var tmp = a.parentNode.childNodes;
767         for ( var i = 0; i < tmp.length; i++ ) {
768                 if ( tmp[i].nodeType == 1 )
769                         type[type.length] = tmp[i];
770                 if ( tmp[i] == a )
771                         type.n = type.length - 1;
772         }
773         if ( e ) n = type.length - n - 1;
774         type.cur = ( type[n] == a );
775         type.prev = ( type.n > 0 ? type[type.n - 1] : null );
776         type.next = ( type.n < type.length - 1 ? type[type.n + 1] : null );
777         return type;
778 };
779
780 jQuery.hasWord = function(e,a) {
781         if ( e == undefined ) return;
782         if ( e.className ) e = e.className;
783         return new RegExp("(^|\\s)" + a + "(\\s|$)").test(e);
784 };
785
786 jQuery.merge = function(a,b) {
787         var d = [];
788         for ( var k = 0; k < b.length; k++ ) d[k] = b[k];
789
790         for ( var i = 0; i < a.length; i++ ) {
791                 var c = true;
792                 for ( var j = 0; j < b.length; j++ )
793                         if ( a[i] == b[j] )
794                                 c = false;
795                 if ( c ) d[d.length] = a[i];
796         }
797
798         return d;
799 };
800
801 jQuery.grep = function(a,f,s) {
802         if ( f.constructor == String )
803                 f = new Function("a","i","return " + f);
804         var r = [];
805         if ( a )
806                 for ( var i = 0; i < a.length; i++ )
807                         if ( (!s && f(a[i],i)) || (s && !f(a[i],i)) )
808                                 r[r.length] = a[i];
809         return r;
810 };
811
812 jQuery.map = function(a,f) {
813         if ( f.constructor == String )
814                 f = new Function("a","return " + f);
815         
816         var r = [];
817         for ( var i = 0; i < a.length; i++ ) {
818                 var t = f(a[i],i);
819                 if ( t !== null && t != undefined ) {
820                         if ( t.constructor != Array ) t = [t];
821                         r = jQuery.merge( t, r );
822                 }
823         }
824         return r;
825 };
826
827 jQuery.event = {
828
829         // Bind an event to an element
830         // Original by Dean Edwards
831         add: function(element, type, handler) {
832                 // For whatever reason, IE has trouble passing the window object
833                 // around, causing it to be cloned in the process
834                 if ( jQuery.browser == "msie" && element.setInterval != undefined )
835                         element = window;
836         
837                 if (!handler.guid) handler.guid = jQuery.event.guid++;
838                 if (!element.events) element.events = {};
839                 var handlers = element.events[type];
840                 if (!handlers) {
841                         handlers = element.events[type] = {};
842                         if (element["on" + type])
843                                 handlers[0] = element["on" + type];
844                 }
845                 handlers[handler.guid] = handler;
846                 element["on" + type] = this.handle;
847
848                 if (!this.global[type])
849                         this.global[type] = [];
850                 this.global[type].push( element );
851         },
852         
853         guid: 1,
854         global: {},
855         
856         // Detach an event or set of events from an element
857         remove: function(element, type, handler) {
858                 if (element.events)
859                         if (type && element.events[type])
860                                 if ( handler )
861                                         delete element.events[type][handler.guid];
862                                 else
863                                         for ( var i in element.events[type] )
864                                                 delete element.events[type][i];
865                         else
866                                 for ( var j in element.events )
867                                         this.remove( element, j );
868         },
869         
870         trigger: function(type,data,element) {
871                 // Touch up the incoming data
872                 data = data || [];
873
874                 // Handle a global trigger
875                 if ( !element ) {
876                         var g = this.global[type];
877                         if ( g )
878                                 for ( var i = 0; i < g.length; i++ )
879                                         this.trigger( type, data, g[i] );
880
881                 // Handle triggering a single element
882                 } else if ( element["on" + type] ) {
883                         // Pass along a fake event
884                         data.unshift( this.fix({ type: type, target: element }) );
885
886                         // Trigger the event
887                         element["on" + type].apply( element, data );
888                 }
889         },
890         
891         handle: function(event) {
892                 // Handle adding events to items in IFrames, in IE
893                 event = event ||
894                         jQuery.event.fix( ((this.ownerDocument || this.document || 
895                                 this).parentWindow || window).event );
896
897                 // If no correct event was found, fail
898                 if ( !event ) return;
899         
900                 var returnValue = true, handlers = [];
901         
902                 for ( var j in this.events[event.type] )
903                         handlers[handlers.length] = this.events[event.type][j];
904         
905                 for ( var i = 0; i < handlers.length; i++ )
906                         if ( handlers[i].constructor == Function ) {
907                                 this.handleEvent = handlers[i];
908                                 if (this.handleEvent(event) === false) {
909                                         event.preventDefault();
910                                         event.stopPropagation();
911                                         returnValue = false;
912                                 }
913                         }
914                 return returnValue;
915         },
916         
917         fix: function(event) {
918                 if ( event ) {
919                         event.preventDefault = function() {
920                                 this.returnValue = false;
921                         };
922                 
923                         event.stopPropagation = function() {
924                                 this.cancelBubble = true;
925                         };
926                 }
927                 
928                 return event;
929         }
930
931 };