Home > Javascript AJAX CSS Archive

Javascript AJAX CSS Archive

Google Gadget : File Document Extractor

このガジェットはGoogle Gadget を利用してWeb から非同期通信でデータを読み込むガジェットです。prototype.jsなどで非同期通信を使う場合では同じサーバーのみという制限があって、他のサーバーにはアクセスは出来ませんが、Google Gadget は_IG_FetchContent を使うことで他のサーバーへのアクセス&データダウンロードが可能になります。

このガジェットはデータをDocumentタブにダウンロードして、イメージタグ<img>とリンクタグ<a href="address"を抽出します。また下のRegExpのテキストボックスに抽出したい文字列の正規表現を書き込むとマッチした文字列が"other" タブに書き込まれます。

ガジェットのコードです(コピペ用)。

Search Gadget (Google Ajax Search API)

ブログやウェブサイトの狭いスペースでも設置できる検索ガジェットです。小さくてもウェブ検索、イメージ検索、ビデオ検索、本の検索などが出来る優れものです。幅は290px、高さは180px に設定しています。高さは調整可能です。 ガジェットのコードです(コピペ用)。

Google Map and Ajax API Search Gadget

何らかの変更があったためコントロールが表示されなくなっていました。
11月3日 : 地図タイプをノーマルに設定したら回復しました。
Google Map と Ajax API Search 兼ねたガジェットです。左のガジェットはシンプル(Simple version)な方のガジェットです。クリックすると移動可能なマーカーが表示されます。ドラッグズームや経度、緯度などがクリックで表示されるFull option バージョンもあります。 地図の左下の方にある小さいボタンを押すと上に検索ボックスが表示されます。もう一度押すと非表示になります。このガジェット一つで地図検索からウェブ、画像、動画、ブログ、本などのあらゆる検索が可能です。

下にある検索はグーグルローカルマップ検索です。地図上のレストラン、ホテルなどを様々な検索が出来ます。検索ボックスに「東京 ホテル」と書き込めば地域のホテルのマップ、住所等の情報が表示されます。

Full Option version:

Simple version:



これらのコードの幅は、420px と設定されています。大きさはブログやサイトのスペースに応じて設定してください。(w=420 の部分を変更すればOKです。)
このガジェットはiframeで生成されています。グーグルでカスタマイズした場合は、IEでY軸のスクロールが出来なくなります。

JS Text Translation - Google gadget (翻訳ガジェット)

Google の提供している Google Ajax Language API を利用した翻訳ガジェットです。現在35カ国語の言語の翻訳が出来ます。

Google Codeページ

言語選択はセレクトメニューのオプションが35 (言語)もあるので、マウスホイールで選択出来るようにしました。一応クッキーを使って最後に翻訳した言語を次回読み出したときに表示できるようにしてます。長い文章の翻訳はまだ出来ませんが、日本語で200文字程度まで翻訳できます。英語は1000文字程度可能です。下のテキストエリアは翻訳した文章を再変換して文章の意味合いに違いがないか確認するためのものです。素早くできるので忙しい方は重宝すると思います。

Continue reading

Javascript Base64 encoder & decoder(Google Gadget)

Javascript base64 encoder and decoder.

手軽に Base64 エンコード(暗号化) & デコード(解読)ができる Google gadget を作りました。

使い方は、上のテキストエリアに貼り付けてボタンを押すだけです。貼り付けるエリアは、data1,data2, data3, data4 の4ヶ所あります。ソースコードもBase64 function の中に文字コード変換のスクリプトを書いてます。下に書いている Javascript のソースコードもシンプルにしましたので(120行くらい)、少しは分かりやすいと思います。対応文字コードは1~3バイトまでです。4バイト以上はまず使うことはないので一般的にテキストエリアに貼り付ける範囲内のものはBase64暗号化・解読が可能です。

    1バイト
  • ASCIIの全て(実装系によりJIS X 0201/Windows-31Jの当該エリアの場合あり)
    • 2バイト
  • JIS X 0208の非漢字の一部
    • 3バイト
  • JIS X 0201の8ビット文字(半角カタカナ)
  • JIS X 0208の漢字エリアの全て
  • JIS X 0212の漢字エリアの全て
  • JIS X 0213の第3・4水準漢字の一部
  • Windows-31Jの拡張文字エリア全て
  • 『ウィキペディア(Wikipedia)』

    Google Gadget の貼り付けコードです。ブログやウェブページに貼り付けられます。

    Source code of Base64_encode, Base64_decode Javascript function.

    1    /****************************************************************************
    2     Javascript Base64 encoder and decoder
    3    
    4     4 Oct. 2008 Samurai-Logic.com
    5    ****************************************************************************/
    6    
    7    var chrs="ABCDEFGHIJKLMNOPQRSTUVWXYZ";    //grobal variable 
    8    
    9    function Base64_encode(str2){
    10   
    11   chrs+=chrs.toLowerCase()+"0123456789+/";
    12   
    13   str2=str2.replace(/\n/g,""); 
    14   
    15   str=[];
    16   var out="";
    17   var j=str2.length;
    18   var z=0;
    19   /*---------------------------------------------------------
    20    In case char is more than 2 bite
    21   ----------------------------------------------------------*/
    22       for (var i=0; z<j;i++) {
    23          var x=str2.charCodeAt(z);
    24   
    25           if(x<128) str[i]=str2.charCodeAt(z);    //  1 Bite(0x00-0x7f) 
    26   
    27           elseif(x<2048) {            //  2 Bites(0x80-0x7ff) 
    28           str[i++] = ((192) | (x >> 6));
    29           str[i] = ((128) | (x & 63));
    30   
    31               }elseif (x < 65536){        //  3 Bites(0x800-0xffff)=2sup16 
    32                   str[i++] = ((224) | ( x >> 12 ));
    33                   str[i++] = ((128) | ((x >> 6 ) & 63)); //3f=63 
    34                   str[i] = ((128) | ( x & 63));
    35   
    36               }else{                // 4 Bites return; 
    37           out=("4 Bites character is not suported"); return; //will never happen here 
    38               }
    39       z++;
    40       }
    41   
    42   /*------------------------------------------------------
    43    Base64 encode
    44   -------------------------------------------------------*/
    45   
    46       var temp=str.length;
    47   
    48       for (var i = 0; i < temp; i += 3){
    49   
    50       var len = ((temp-i)>=3)? 3 : temp-i;
    51   
    52           out += chrs.charAt((str[i] >> 2))
    53   
    54           if (len == 1){        //1 bite 
    55               out += chrs.charAt((str[i] & 3) << 4) + "==";
    56   
    57           } elseif (len == 2) {    //2 bites 
    58               out    += chrs.charAt(((str[i] & 3) << 4) | (str[i+1] >> 4))
    59                   +  chrs.charAt ((str[i+1] & 15) << 2) + "=";
    60   
    61           } else {        //3 bites 
    62               out    += chrs.charAt(((str[i] & 3) << 4) | (str[i+1] >> 4))
    63                   +  chrs.charAt(((str[i+1] & 15) << 2) | (str[i+2] >> 6))
    64                   +  chrs.charAt ((str[i+2] & 63));    /* NOTE:63=0x3f, 15=0xf . */
    65           }
    66       }
    67   return out;
    68   }
    69   

    Javascript Compressor (Modified 1 Oct. 2008)

    Javascript Compressor がほぼ完成しました。正規表現のエラーチェックと括弧の数を数えてエラーがある場合に表示されます。Compression Ratio も表示させるようにしました。

    以前の記事を改良しました。

    正規表現部分の[ ] 内の"/" とスペースがあった場合に圧縮時に(スペースがある場合のみ)スペースが消てしまうので今回は、ループさせてRegExp をecmascript 評価 (eval)してチェックするようにしました。
    例: exp=/[ / ]/;
    通常は、exp=/[ \/ ]/; と書くのですが、実際に正規表現の [ ] 内に"/" があってもjavascript ではエラーになりません。普通に書くと、/ ==> \/, space ==> \s となるのですが、文字コードなどが絡んでどうしても特殊な書き方が必要な例もあるかもしれないのでそれに対応しました。Javascript のコードはとても柔軟性が高いのでまだ100%とは言えないかもしれませんが、一般的なJavascriptのコードではエラーはないと思います。

    また今回、Javascript Code Prettifier もセレクトメニューに追加しました。

    こちらの記事に詳細があります。使い方はただ貼り付けるだけなので簡単です。(js ファイルなどのセットアップせずに何ヶ所でも貼り付けられます。)

    見た目は下にあるJavascript compressor のソースコードのようになります。

    Google Gadget の貼り付けコードです。ブログやウェブページに貼り付けられます。

    Source code of modified Javascript Compressor function.

    Modified on 1 Oct. 2008

    1    /****************************************************************
    2     2008 (C)samurai-logic.com
    3    
    4     Javascript Compressor
    5    
    6     Last Modified 1 Oct. 2008
    7    ****************************************************************/
    8    function $compress(str){
    9    
    10   var Size=str.length;
    11   
    12   //if(/\n/g.test(str)) return("no end of line"); 
    13   
    14   str=str.replace(/\t+/g," ");
    15   
    16   Reg=/([^\d\w]\n[^\d\w]|[^\d\w]\s[^\d\w]|[\d\w]\s[^\d\w\$\_\#]|[^\d\w]\s[\d\w])/;
    17   
    18   //Exp=/[^\\]\/[^\/]*([\s\,\;]*)((\,\s*(\"|\')|(\w+)\s*\(\s*\/*)[\s\S]+|\/\/[\s\S]+|\/\*[\s\S]+|\s{2,}[\s\S]+|\s*)\n*/; 
    19   //Exp=/[^\\]\/([^\/])?(\s)*(([\,\s]*(\"|\')|(\w+)\s*\(\s*\/*)[\s\S]+|\/\/[\s\S]+|\/\*[\s\S]+|\s{2,}[\s\S]+|\s*)\n*/; 
    20   
    21   //Basic Exp 
    22   Exp=/[^\\]\/([^\/])/;
    23   
    24   chr=/(\(|\=|\[|\:|\||\&|\!|\,)/; // new reg 
    25   
    26   //d_q=/([^\\]\"[^\"]*[^\:]|[^\"]\"[\s]*[\:\,\}\]\)\;\.])/; 
    27   //s_q=/([^\\]\'[^\']*[^\:]|[^\']\'[\s]*[\:\,\}\]\)\;\.])/; 
    28   //d_q=/([^\\]\"|[^\"]\")/; 
    29   //s_q=/([^\\]\'|[^\']\')/; 
    30   
    31   //modified 1 Oct. 2008  don't need to replace \\\" and \\\'... 
    32   d_q=/[^\\]\"/; //replace(/\\\\|\\\"/g,"xx") temp before search(d_q) 
    33   s_q=/[^\\]\'/; //replace(/\\\\|\\\'/g,"xx") temp before search(s_q) 
    34   
    35   bracket=new Array();
    36   
    37   bracket[0]=0; bracket[1]=0; bracket[2]=0; bracket[3]="";
    38   
    39   var CODE  = "";  
    40   var cmt   = false;
    41   var arg   = -1;
    42   var pos = end = 0;
    43   var last=" ";
    44   var temp="";
    45   var LEN=str.length;
    46   var retrn = false; // for regexp "return /pat/.test()" 
    47   
    48       while (pos >= 0){
    49       var key_q = str.charAt(pos);
    50       var key_c = str.substr(pos,2);
    51       var key_r = last + key_c;
    52   
    53       if((pos>6)&&(str.substr(pos-6,6)=="return")&&(/^[\s\n]*\/[^\/\*]/.test(str.substring(pos,LEN))))retrn=true;
    54   
    55       if (key_q=="'")          { arg = 0; pos++; }     //find pos of keyword ' 
    56       elseif (key_q=='"')  { arg = 1; pos++; }     //find pos of keyword " 
    57       elseif ((key_q=='/') && (key_c!="//") && (key_c!="/*") && ((chr.test(last) || (retrn))))
    58                     { arg = 4; pos++;  }     //find pos of keyword / 
    59       elseif (key_c=="//") { arg = 2; pos+=2; }    //find pos of keyword // 
    60       elseif (key_c=="/*") { arg = 3; pos+=2; }    //find pos of keyword /* 
    61       else              { arg =-1; pos++; }
    62   
    63       if (arg>=0){    //if keyword is found 
    64   
    65          if      (arg==0) { temp=(str.substring(pos-1, LEN).replace(/\\\\|\\\"/g,"xx")); end = temp.search(s_q)+pos; temp=null;}
    66          elseif (arg==1) { temp=(str.substring(pos-1, LEN).replace(/\\\\|\\\'/g,"xx")); end = temp.search(d_q)+pos; temp=null;}
    67   
    68          elseif (arg==4) { var eol  = str.indexOf("\n", pos);    // find end of line 
    69                     if(eol==-1){return(CODE+"\nerror : no end of line");}
    70                     var temp = next = (str.substring(pos-1,eol+2).replace(/\\\\/g,"xx"));    // end+2 ==> \n 
    71                     end = 0;    var t_l=temp.length-2; retrn=false; 
    72   
    73                   while(end<t_l-1){ //(str.substring(pos-1,end+1))==> /pat/ 
    74               
    75                      var isReg=true;
    76   
    77                      next=(temp.substring(end,t_l+1)); // store temp to next 
    78   
    79                        end=parseInt(end+next.search(Exp)+2); //alert("next="+next); //find next key / 
    80   
    81                      try{ eval(temp.substring(0,end));}catch(e){isReg=false; var err=(e);}
    82   
    83                      if(isReg) break;
    84                   }
    85   
    86                   end=parseInt(end+pos-2); temp=null; next=null;
    87   
    88                     if(!(isReg)){bracket[3]+=err+" : "+(str.substring(pos-1,end+1))+" pos ="+pos;}
    89                    }
    90       
    91          elseif (arg==2) { end = str.indexOf("\n", pos);   pos--; cmt = true; }
    92   
    93          else    /*arg==3*/  { end = str.indexOf("*/", pos); pos--; end++; //pos-- because 2 char "/*" 
    94                          if (end == 0) cmt = false; //if not found(avoid error) 
    95                          else         cmt = true; }
    96   
    97          if (end <= 0) end=str.length-1; end++;
    98   
    99          if (cmt==false) CODE += str.substring(pos-1,end);//alert(str.substring(pos-1,end+1)); 
    100  
    101         pos=end; //if(arg==4) pos++; // end=pos at "/" so add 1 
    102  
    103         cmt=false;  //at last, end up with pos=0  
    104  
    105      }else{ // else keyword is not found 
    106  
    107        if((last==";") && (key_q=="}")){ key_q="/**/"; bracket[1]--;} //replace(/\;\}/g,"}"); 
    108  
    109         if (!(Reg.test(key_r))) { CODE += key_q; last=key_q;}
    110  
    111         switch(key_q){
    112          case"(" : bracket[0]++; break;
    113          case")" : bracket[0]--; break;
    114          case"{" : bracket[1]++; break;
    115          case"}" : bracket[1]--; break;
    116          case"[" : bracket[2]++; break;
    117          case"]" : bracket[2]--; 
    118         }
    119          if(pos>=str.length) pos=-1;
    120      } 
    121     }
    122    str=null;
    123  
    124    CODE=CODE.replace(/^\s+/,"").replace(/[\s\n]*$/,"").replace(/\;\/\*\*\//g,"}");
    125  
    126    var j=CODE.length;
    127    var el=$id("ratio");//el.style.backgroundColor="#000"; 
    128    el.innerHTML="Compression Ratio:"+j+"/"+Size+"="+eval(j/Size).toFixed(5);
    129  
    130    var hr ="\n/*------------------------------------\n";
    131    var hr2="\n------------------------------------*/\n";
    132  
    133    if (eval(bracket[0]+bracket[1]+bracket[2])!=0) 
    134      CODE+=hr+"Check pair of brackets. \n () :"+bracket[0]+"; {} :"+bracket[1]+"; [] : "+bracket[2]+hr2;
    135    if (bracket[3]!="")
    136      CODE+=hr+"Check Syntax of RegExp. \n"+(bracket[3]).replace(/xx/g,"\\\\")+hr2;
    137  
    138    return(CODE);
    139  }
    140  

    Modified on 29 Sep. 2008

    1    /****************************************************************
    2     2008 (C)samurai-logic.com
    3    
    4    
    5     Javascript Compressor
    6    
    7     Last Modified 29 Sep. 2008
    8    ****************************************************************/
    9    function $compress(str){
    10   
    11   var Size=str.length;
    12   
    13   //if(/\n/g.test(str)) return("no end of line"); 
    14   
    15   str=str.replace(/\t+/g," ");
    16   
    17   Reg=/([^\d\w]\n[^\d\w]|[^\d\w]\s[^\d\w]|[\d\w]\s[^\d\w\$\_\#]|[^\d\w]\s[\d\w])/;
    18   
    19   //Exp=/[^\\]\/[^\/]*([\s\,\;]*)((\,\s*(\"|\')|(\w+)\s*\(\s*\/*)[\s\S]+|\/\/[\s\S]+|\/\*[\s\S]+|\s{2,}[\s\S]+|\s*)\n*/; 
    20   //Exp=/[^\\]\/([^\/])?(\s)*(([\,\s]*(\"|\')|(\w+)\s*\(\s*\/*)[\s\S]+|\/\/[\s\S]+|\/\*[\s\S]+|\s{2,}[\s\S]+|\s*)\n*/; 
    21   
    22   //Basic Exp 
    23   Exp=/[^\\]\/([^\/])/;
    24   
    25   chr=/(\(|\=|\[|\:|\||\&|\!|\,)/; // new reg 
    26   
    27   //these RegExp don't need to replace(/\\\\/g,"xx")...but just in case. 
    28   d_q=/([^\\]\"[^\"]*[^\:]|[^\"]\"[\s]*[\:\,\}\]\)\;\.])/;
    29   s_q=/([^\\]\'[^\']*[^\:]|[^\']\'[\s]*[\:\,\}\]\)\;\.])/;
    30   
    31   // Basic RegExp 
    32   //d_q=/([^\\]\"|[^\"]\")/; 
    33   //s_q=/([^\\]\'|[^\']\')/; 
    34   
    35   bracket=new Array();
    36   
    37   bracket[0]=0; bracket[1]=0; bracket[2]=0; bracket[3]="";
    38   
    39   var CODE  = "";        //new string for compressed code 
    40   var cmt   = false;    //cmt=true, char is comment.< -- > cmt=false, char is code. 
    41   var arg   = -1;        //arg decide the keyword to find 
    42   var pos = end = 0;    //pos = postion of open keyword, end = postion of close keyword 
    43   var last=" ";        //last is last char which store to CODE 
    44   var temp="";        //temp is to find another keyword 
    45   var LEN=str.length;
    46   var retrn = false;    // for regexp "return /pat/.test()" 
    47   
    48      /*-----------------------------------------------
    49    While loop begin. check each char in string
    50    ------------------------------------------------*/
    51       while (pos >= 0){
    52       var key_q = str.charAt(pos);    //keyword quot 
    53       var key_c = str.substr(pos,2);    //keyword comment 
    54       var key_r = last + key_c;    //keyword to test key_q is necessary 
    55   
    56       if((pos>6)&&(str.substr(pos-6,6)=="return")&&(/^[\s\n]*\/[^\/\*]/.test(str.substring(pos,LEN))))retrn=true;
    57   
    58       if (key_q=="'")          { arg = 0; pos++; }     //find pos of keyword ' 
    59       elseif (key_q=='"')  { arg = 1; pos++; }     //find pos of keyword " 
    60       elseif ((key_q=='/') && (key_c!="//") && (key_c!="/*") && ((chr.test(last) || (retrn))))
    61                     { arg = 4; pos++;  }     //find pos of keyword / 
    62       elseif (key_c=="//") { arg = 2; pos+=2; }    //find pos of keyword // 
    63       elseif (key_c=="/*") { arg = 3; pos+=2; }    //find pos of keyword /* 
    64       else              { arg =-1; pos++; }
    65   
    66       if (arg>=0){    //if keyword is found 
    67   
    68          if      (arg==0) { temp=(str.substring(pos-1, LEN)); end = temp.search(s_q)+pos; temp=null;}
    69          elseif (arg==1) { temp=(str.substring(pos-1, LEN)); end = temp.search(d_q)+pos; temp=null;}
    70   
    71          elseif (arg==4) { var eol  = str.indexOf("\n", pos);    // find end of line 
    72                     if(eol==-1){return(CODE+"\nerror : no end of line");}
    73                     var temp = next = (str.substring(pos-1,eol+2).replace(/\\\\/g,"xx"));    // end+2 ==> \n 
    74                     end = 0;    var t_l=temp.length-2; retrn=false; 
    75   
    76           /*---------------------------------------------------------------
    77    loop to find next keyword "/" and evaluate Regular Expression
    78    and if RegExp is NG, store error message to var err.
    79    ----------------------------------------------------------------*/
    80   
    81                   while(end<t_l-1){
    82               
    83                      var isReg=true;
    84   
    85                      next=(temp.substring(end,t_l+1));      // store temp to next 
    86   
    87                        end=parseInt(end+next.search(Exp)+2);  //alert("next="+next); //find next key / 
    88   
    89                      try{ eval(temp.substring(0,end));}       //evaluate RegExp 
    90                       catch(e){isReg=false; var err=(e);}// store error msg to err 
    91   
    92                      if(isReg) break;//if RegExp is OK, then break 
    93                   }
    94   
    95                   end=parseInt(end+pos-2); temp=null; next=null; //add pos to end, and release memory 
    96   
    97                     if(!(isReg)){bracket[3]+=err+" : "+(str.substring(pos-1,end+1))+" pos ="+pos;}
    98                    }
    99       
    100         elseif (arg==2) { end = str.indexOf("\n", pos);   pos--; cmt = true; }
    101  
    102         else    /*arg==3*/  { end = str.indexOf("*/", pos); pos--; end++; //pos-- because 2 char "/*" 
    103                         if (end == 0) cmt = false; //if not found(avoid error) 
    104                         else         cmt = true; }
    105  
    106         if (end <= 0) end=str.length-1; end++;
    107  
    108         if (cmt==false) CODE += str.substring(pos-1,end);//alert(str.substring(pos-1,end+1)); 
    109  
    110         pos=end; //if(arg==4) pos++; // end=pos at "/" so add 1 
    111  
    112         cmt=false;  //at last, end up with pos=0  
    113  
    114      }else{ // else keyword is not found 
    115  
    116        if((last==";") && (key_q=="}")){ key_q="/**/"; bracket[1]--;} //replace(/\;\}/g,"}"); 
    117  
    118         if (!(Reg.test(key_r))) { CODE += key_q; last=key_q;}
    119  
    120         switch(key_q){
    121          case"(" : bracket[0]++; break;//in case ( is found then count one 
    122          case")" : bracket[0]--; break;
    123          case"{" : bracket[1]++; break;
    124          case"}" : bracket[1]--; break;
    125          case"[" : bracket[2]++; break;
    126          case"]" : bracket[2]--; 
    127         }
    128          if(pos>=str.length) pos=-1;
    129      } 
    130     } //while loop 
    131    str=null;
    132  
    133    CODE=CODE.replace(/^\s+/,"").replace(/[\s\n]*$/,"").replace(/\;\/\*\*\//g,"}");
    134  
    135    var j=CODE.length;
    136    var el=$id("ratio");//el.style.backgroundColor="#000"; 
    137    el.innerHTML="Compression Ratio:"+j+"/"+Size+"="+eval(j/Size).toFixed(5);
    138  
    139    var hr ="\n/*------------------------------------\n";
    140    var hr2="\n------------------------------------*/\n";
    141  
    142    if (eval(bracket[0]+bracket[1]+bracket[2])!=0) 
    143      CODE+=hr+"Check pair of brackets. \n () :"+bracket[0]+"; {} :"+bracket[1]+"; [] : "+bracket[2]+hr2;
    144    if (bracket[3]!="")
    145      CODE+=hr+"Check Syntax of RegExp. \n"+(bracket[3]).replace(/xx/g,"\\\\")+hr2;
    146  
    147    return(CODE);
    148  }
    149  

    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,"&amp;")+"\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 th