Home > Javascript AJAX CSS > JS Code Archive

JS Code Archive

Javascript Code prettifier - Highlight Syntax (JS Code Pro.)

this gadget (upgrade version of code prettifier) highlights syntax code of javascript just copy and paste, and RegExp in a code will be highlighted by midnight Blue. font-size, font-family are changeable. As additional option, text view and print view button will highlight and show source code to new window. print view is for color print. it's not necessary to set up js file. it's easy to use and very accurate.

ガジェットの貼り付けコード


このガジェットは前回紹介した Javascript の Syntax Highlighter ガジェット(JS Code)に機能を追加したものです。

このツールの特徴は、外部 js ファイルなどのセッティングなどを必要とせず、Javascript のコードをコピーして貼り付けるだけです。グローバル変数、ファンクション名、CSSのクラス名なども毎回違う名前になるようにしてますので、ブログなどに何ヶ所もソースコードを貼り付けても名前がかぶることがありません。

正規表現(RegExp)の部分が青(midnightBlue)でハイライトされます。他にあまり見られないものです。

追加機能は、Text view ボタンを追加しています。IE7, FireFox3, Safari, Google Chrome でテストしています。 Opera でテキストエリアの表示(text view)がうまくいきません。Operaはとても優秀なブラウザなので文字化け等への対応がされているためだと思います。文字コードは、現時点ではUnicode のみになります。ガジェットの charset は UTF-8 で設定してます。print view でソースコードをそのままカラープリントが出来ます。

font (font-family)は前のガジェットと変わらず以下の4種類のタイプに変更できます。
  1. "Arial,Helvetica,sans-serif"
  2. "Comic Sans MS"
  3. "Trebuchet MS,sans-serif"
  4. "Georgia,Times,sans-serif"


Last Modified : 26 Sep. 2008

1    /****************************************************************
2    
3     23 Sep. 2008 (C)samurai-logic.com
4    
5    
6     Code Prettifier
7    
8     Modified on 26 Sep. 2008
9    
10   /****************************************************************/
11   
12   function $code(str,rnd){
13   
14   /*--------------------------------------------------------------
15    str = string of javascript code
16    rnd = random 5 digits number for
17    name of temporary var, class,id and function name
18   /*---------------------------------------------------------------*/
19   
20   js_key=/\b(?=(alert|array|arguments|Boolean|break|caller|callee|case|catch|class|confirm|const|constructor|continue|Date|default|delete|do|else|eval|false|final|finally|for|function|if|isFinite|isNaN|Math|NaN|new|null|Number|Object|parseFloat|parseInt|prompt|prototype|return|String|switch|this|throw|throws|toString|toExponential|toFixed|toPrecision|true|try|typeof|value|valueOf|var|void|while|with)(\W))/g;
21   
22   var key="";
23   
24   //replace \b to key()just before keywords of javascript 
25   
26   str=str.replace(/\t/g,"      ").replace(js_key,key).replace(/&/g,"&")+"\n";
27   
28   var CODE  = '';            //CODE is string to modify code 
29   var arg   = -1;            //arg is selectors of key 
30   var pos = end = 0;      //pos = end = position of slice str 
31   var last=" ";            //last is char. before pos 
32   var temp="";            //temp 
33   var LEN=str.length;      //LEN is for end of ' and " 
34   
35   var spn ="<span style='color:";
36   var spn_c="<span class='";
37   var _col = "green;'>";
38   
39   var code_e='<br /></span>';
40   
41   var retrn = false; // for regexp "return /pat/.test()" 
42   
43   chr=/(\(|\=|\[|\:|\||\&|\!|\,)/; // RegExp in front of /pattern/ 
44   
45   d_q=/([^\\]\"[^\"]*[^\:]|[^\"]\"[\s]*[\:\,\}\]\)\;\.])/;  //RegExp of double quot. case "\\"", "\":,;.)}] 
46   s_q=/([^\\]\'[^\']*[^\:]|[^\']\'[\s]*[\:\,\}\]\)\;\.])/;  //RegExp of single quot 
47   
48   Exp=/\/[^\/]*([\s\,\;]*)((\,\s*(\"|\')|(e|h|t)\s*\(\s*\/)[\s\S]+|\/\/[\s\S]+|\/\*[\s\S]+|\s{2,}[\s\S]+|\s)\n*/;
49   
50       while (pos >= 0){
51         var cls = "</span>";
52         var key_q = str.charAt(pos);
53         var key_c = str.substr(pos,2);
54         var key_r = last + key_c;
55         var key_w = str.substr(pos,7);
56         
57         if (key_q=="'")            { arg = 0; pos++; }     //find pos of keyword ' 
58         elseif (key_q=='"')  { arg = 1; pos++; }     //find pos of keyword " 
59         elseif ((key_q=='/') && (key_c!="//") && (key_c!="/*") && ((chr.test(last) || (retrn))))
60                           { arg = 4; pos++; }     //find pos of keyword / 
61         elseif (key_c=="//") { arg = 2; pos+=2; }    //find pos of keyword // 
62         elseif (key_c=="/*") { arg = 3; pos+=2; }    //find pos of keyword /* 
63         elseif (key_w==key)  { arg = 5; pos+=8; }    // find pos of js_key (//.test(key_w)) 
64         else                   { arg =-1; pos++; }
65   
66         if (arg>=0){      //if keyword is found 
67            if (arg==0)      { temp=(str.substring(pos-1, LEN)); 
68                           end = temp.search(s_q)+pos; _col = spn+"#DC143C;'>";}//s_q=2char 
69   
70            elseif (arg==1) { temp=(str.substring(pos-1, LEN)); 
71                           end = temp.search(d_q)+pos; _col = spn+"#DC143C;'>";}
72   
73            elseif (arg==4) { end = str.indexOf("\n", pos);      // find end of line 
74                           temp=(str.substring(pos,end+2));      //temp start from pos to EOL(\n) or use LEN 
75                           end = temp.search(Exp)+pos;  _col = spn+"#0000CD;'>"; //midnightblue 
76                           retrn=false;      //set retrn false 
77                          }
78            elseif (arg==2) { end = str.indexOf("\n", pos); pos--; 
79                          _col = spn+"green;'><small>";
80                            cls+="</small>\n";
81                         }
82            else      if (arg==3) { end = str.indexOf("*/", pos); pos--; end++; _col = spn+"green;'><small>";
83                           /*if(end==0)*/ cls+="</small>";
84                         }
85            else/*if(arg==5)*/{ end = str.indexOf("\n", pos);            //find EOL 
86                            temp=str.substring(pos,end+2);            //+"\n"; 
87                            end = eval(temp.search(/[^\w\d]/)+pos-1); //search \W 
88                           _col = spn_c+"c5"+rnd+"'>"; 
89                            retrn = ((/return/.test(str.substring(pos-1,end+1))))? true:false;      
90                          } //if found keyword "return" then retrn is true 
91            temp=null; // release memory  
92   
93            if (end <= 0) end=str.length-1;  end++; //in case end=-1 : end is length of str 
94   
95            var tmp=str.charAt(end-1); // store last char if code is not comments (except comments from code) 
96   
97            if((/[^\s\n]/.test(tmp)) && (arg>=5 || arg<=1)) { last=tmp;}
98   
99            if ((arg==3)) CODE+=_col + (str.substring(pos-1,end).replace(//g,"").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\n/g,"</small></span>\n<span style='color:green;'><small>"))+cls;
100  
101           else CODE += _col + (str.substring(pos-1,end).replace(//g,"").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\s/g,"&ensp;")) + cls;
102  
103           pos=end; cmt=false;  //at last, end up with pos=0 
104  
105        }else{ // else keyword is not found  
106  
107            if      (/\n/.test(key_q)) CODE += "\n"; 
108            elseif (/\s/.test(key_q)) CODE += "&ensp;";
109            elseif (/\t/.test(key_q)) CODE += "&ensp;&ensp;&ensp;&ensp;";
110            elseif (/</.test(key_q))  CODE += "&lt;";
111            elseif (/>/.test(key_q))  CODE += "&gt;";
112            else CODE += key_q; 
113  
114            if(/[^\s\n]/.test(key_q))last=key_q; //if key_q isn't \s nor \n then last=key_q 
115  
116            if(pos>=str.length) pos=-1; //if pos rearch eof 
117        }
118     }
119  
120    delete str;
121  
122    return(CODE);
123  }
124  

Javascript Code Prettifier (Google Gadget)

this gadget highlights syntax code of javascript just copy and paste. no necessary to set up js file. it's easy to use.

ガジェットの貼り付けコード(Upgraded version)


Javascript の Syntax Highlighter ガジェットが完成しました。

このツールの特徴は、外部 js ファイルなどのセッティングなどを必要とせず、Javascript のコードをコピーして貼り付けるだけです。グローバル変数、ファンクション名、CSSのクラス名なども毎回違う名前になるようにしてますので、ブログなどに何ヶ所もソースコードを貼り付けても名前がかぶることがありません。

正規表現がなければ大きな問題もなくソースコードはもっとコンパクトで解りやすく書けたのですが、複雑で少々粗めになってしまいました。いろんなタイプの正規表現が見られる prototype.js , jQuery.js でテストしてクリアしましたので綺麗に使えると思います。(下にサンプルページのリンクがあります)

Scroll Width & Height の初期設定値は600px、250px になっています。これはスクロールさせる範囲の大きさです。ページのサイズに合わせて変更できます。使用できる単位は、px, in, %, cm, mm, pc, pt です。

font ボタンで以下のfont-family に変更できます。
  1. "Arial,Helvetica,sans-serif"
  2. "Comic Sans MS"
  3. "Trebuchet MS,sans-serif"
  4. "Georgia,Times,sans-serif"


prototype.js(1.5.1)

jQuery.js(1.2.6)

ソースコードは「CONTINUE READING」の下に紹介しています。このソースコードはこのガジェットで作ったものです。スクロールサイズは、Scroll Width = 850px Height = 400px で設定しています。

Continue reading

Javascript code prettify - Highlight Syntax (JS Code)

Next google gadget project is Highlight Syntax of JavaScript and etc.

次に公開予定のガジェットは "JS Code" (仮名)です。現在このブログで使っているのがSyntaxHighlighter 1.5.1なんですが、コードの行数が1000行を超えるとかなり読み込み処理に時間がかかります。prototype.js 1.5.1 はファイルを3分割して見れるようにしてますが、IEでの読み込みは少しきついです。

それをガジェットという便利なツールを使って、簡単にコードをブログに貼り付けられるようにしようとしています。コードをコピーしてガジェットのテキストエリアに貼り付けて、ボタンを押すだけでコードをすべて作ってしまえるようにします。javascript ファイル等の のセットアップする必要はありません。グローバル変数、function 名はすべて変えるように設定します。 Javascript の部分はだいたい仕上がってきてます。

また、Javascript Compressor の性能もアップさせる予定です。

jQuery.js をガジェットに貼り付けてコピペするだけでこんな感じになります。3500行以上ありますので、フォントサイズ size(小), SIZE(大), F(フォント), 等を変更する際は処理時間がかかる場合があります。i (italic) は、Class で設定してるので今のところボタンをクリックしても反映されません。

こちらはウェブページです。jQuery.js

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