/*
 * jQuery 1.1.3 - New Wave Javascript
 *
 * Copyright (c) 2007 John Resig (jquery.com)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * $Date: 2007-07-01 08:54:38 -0400 (Sun, 01 Jul 2007) $
 * $Rev: 2200 $
 */
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('7(1e 12.6=="J"){12.J=12.J;u 6=q(a,c){7(12==9||!9.3Z)v 17 6(a,c);v 9.3Z(a,c)};7(1e $!="J")6.1I$=$;u $=6;6.11=6.8r={3Z:q(a,c){a=a||P;7(6.14(a))v 17 6(P)[6.11.1D?"1D":"1X"](a);7(1e a=="1v"){u m=/^[^<]*(<(.|\\s)+>)[^>]*$/.1Q(a);7(m)a=6.2Y([m[1]]);B v 17 6(c).1H(a)}v 9.4A(a.18==23&&a||(a.3B||a.C&&a!=12&&!a.1r&&a[0]!=J&&a[0].1r)&&6.2K(a)||[a])},3B:"1.1.3",7Y:q(){v 9.C},C:0,1L:q(a){v a==J?6.2K(9):9[a]},1W:q(a){u b=6(a);b.5l=9;v b},4A:q(a){9.C=0;[].R.O(9,a);v 9},F:q(a,b){v 6.F(9,a,b)},2m:q(a){u b=-1;9.F(q(i){7(9==a)b=i});v b},1b:q(f,d,e){u c=f;7(f.18==31)7(d==J)v 9.C&&6[e||"1b"](9[0],f)||J;B{c={};c[f]=d}v 9.F(q(a){E(u b T c)6.1b(e?9.Y:9,b,6.4D(9,c[b],e,a,b))})},1c:q(b,a){v 9.1b(b,a,"2q")},2R:q(e){7(1e e=="1v")v 9.2V().3m(P.67(e));u t="";6.F(e||9,q(){6.F(9.2S,q(){7(9.1r!=8)t+=9.1r!=1?9.5R:6.11.2R([9])})});v t},8c:q(){u a,1Z=1g;v 9.F(q(){7(!a)a=6.2Y(1Z,9.2N);u b=a[0].3r(K);9.L.2J(b,9);1q(b.1a)b=b.1a;b.4h(9)})},3m:q(){v 9.2F(1g,K,1,q(a){9.4h(a)})},5s:q(){v 9.2F(1g,K,-1,q(a){9.2J(a,9.1a)})},5p:q(){v 9.2F(1g,M,1,q(a){9.L.2J(a,9)})},5n:q(){v 9.2F(1g,M,-1,q(a){9.L.2J(a,9.1U)})},2E:q(){v 9.5l||6([])},1H:q(t){u b=6.3h(9,q(a){v 6.1H(t,a)});v 9.1W(/[^+>] [^+>]/.16(t)||t.I("..")>-1?6.5c(b):b)},7z:q(e){u d=9.1A(9.1H("*"));d.F(q(){9.1I$19={};E(u a T 9.$19)9.1I$19[a]=6.1f({},9.$19[a])}).3C();u r=9.1W(6.3h(9,q(a){v a.3r(e!=J?e:K)}));d.F(q(){u b=9.1I$19;E(u a T b)E(u c T b[a])6.S.1A(9,a,b[a][c],b[a][c].W);9.1I$19=H});v r},1j:q(t){v 9.1W(6.14(t)&&6.2x(9,q(b,a){v t.O(b,[a])})||6.2w(t,9))},4V:q(t){v 9.1W(t.18==31&&6.2w(t,9,K)||6.2x(9,q(a){v(t.18==23||t.3B)?6.2s(a,t)<0:a!=t}))},1A:q(t){v 9.1W(6.1R(9.1L(),t.18==31?6(t).1L():t.C!=J&&(!t.Q||t.Q=="71")?t:[t]))},33:q(a){v a?6.2w(a,9).C>0:M},6T:q(a){v a==J?(9.C?9[0].2t:H):9.1b("2t",a)},3K:q(a){v a==J?(9.C?9[0].26:H):9.2V().3m(a)},2F:q(f,d,g,e){u c=9.C>1,a;v 9.F(q(){7(!a){a=6.2Y(f,9.2N);7(g<0)a.6G()}u b=9;7(d&&6.Q(9,"1s")&&6.Q(a[0],"3k"))b=9.3V("1x")[0]||9.4h(P.55("1x"));6.F(a,q(){e.O(b,[c?9.3r(K):9])})})}};6.1f=6.11.1f=q(){u c=1g[0],a=1;7(1g.C==1){c=9;a=0}u b;1q((b=1g[a++])!=H)E(u i T b)c[i]=b[i];v c};6.1f({6o:q(){7(6.1I$)$=6.1I$;v 6},14:q(a){v!!a&&1e a!="1v"&&!a.Q&&a.18!=23&&/q/i.16(a+"")},43:q(a){v a.4x&&a.2N&&!a.2N.4w},Q:q(b,a){v b.Q&&b.Q.1S()==a.1S()},F:q(a,b,c){7(a.C==J)E(u i T a)b.O(a[i],c||[i,a[i]]);B E(u i=0,4v=a.C;i<4v;i++)7(b.O(a[i],c||[i,a[i]])===M)1E;v a},4D:q(c,b,d,e,a){7(6.14(b))b=b.3D(c,[e]);u f=/z-?2m|5Y-?8p|1d|5U|8i-?1u/i;v b&&b.18==3x&&d=="2q"&&!f.16(a)?b+"4p":b},V:{1A:q(b,c){6.F(c.2Q(/\\s+/),q(i,a){7(!6.V.3v(b.V,a))b.V+=(b.V?" ":"")+a})},1B:q(b,c){b.V=c!=J?6.2x(b.V.2Q(/\\s+/),q(a){v!6.V.3v(c,a)}).5K(" "):""},3v:q(t,c){v 6.2s(c,(t.V||t).3s().2Q(/\\s+/))>-1}},4n:q(e,o,f){E(u i T o){e.Y["2M"+i]=e.Y[i];e.Y[i]=o[i]}f.O(e,[]);E(u i T o)e.Y[i]=e.Y["2M"+i]},1c:q(e,p){7(p=="1u"||p=="28"){u b={},3q,3p,d=["85","83","82","80"];6.F(d,q(){b["7X"+9]=0;b["7W"+9+"7V"]=0});6.4n(e,b,q(){7(6(e).33(\':4g\')){3q=e.7S;3p=e.7Q}B{e=6(e.3r(K)).1H(":4c").5r("2D").2E().1c({49:"1y",3i:"7N",15:"2j",7M:"0",7K:"0"}).5j(e.L)[0];u a=6.1c(e.L,"3i")||"3n";7(a=="3n")e.L.Y.3i="7I";3q=e.7G;3p=e.7F;7(a=="3n")e.L.Y.3i="3n";e.L.3t(e)}});v p=="1u"?3q:3p}v 6.2q(e,p)},2q:q(e,a,d){u g;7(a=="1d"&&6.N.1h){g=6.1b(e.Y,"1d");v g==""?"1":g}7(a.3w(/3u/i))a=6.1T;7(!d&&e.Y[a])g=e.Y[a];B 7(P.3d&&P.3d.40){7(a.3w(/3u/i))a="3u";a=a.1o(/([A-Z])/g,"-$1").2T();u b=P.3d.40(e,H);7(b)g=b.52(a);B 7(a=="15")g="1G";B 6.4n(e,{15:"2j"},q(){u c=P.3d.40(9,"");g=c&&c.52(a)||""})}B 7(e.3U){u f=a.1o(/\\-(\\w)/g,q(m,c){v c.1S()});g=e.3U[a]||e.3U[f]}v g},2Y:q(a,c){u r=[];c=c||P;6.F(a,q(i,b){7(!b)v;7(b.18==3x)b=b.3s();7(1e b=="1v"){u s=6.2p(b).2T(),1z=c.55("1z"),1K=[];u a=!s.I("<2z")&&[1,"<2y>","</2y>"]||!s.I("<7i")&&[1,"<4Y>","</4Y>"]||(!s.I("<7e")||!s.I("<1x")||!s.I("<7d")||!s.I("<7a"))&&[1,"<1s>","</1s>"]||!s.I("<3k")&&[2,"<1s><1x>","</1x></1s>"]||(!s.I("<77")||!s.I("<76"))&&[3,"<1s><1x><3k>","</3k></1x></1s>"]||!s.I("<75")&&[2,"<1s><4U>","</4U></1s>"]||[0,"",""];1z.26=a[1]+b+a[2];1q(a[0]--)1z=1z.1a;7(6.N.1h){7(!s.I("<1s")&&s.I("<1x")<0)1K=1z.1a&&1z.1a.2S;B 7(a[1]=="<1s>"&&s.I("<1x")<0)1K=1z.2S;E(u n=1K.C-1;n>=0;--n)7(6.Q(1K[n],"1x")&&!1K[n].2S.C)1K[n].L.3t(1K[n])}b=6.2K(1z.2S)}7(0===b.C&&(!6.Q(b,"35")&&!6.Q(b,"2y")))v;7(b[0]==J||6.Q(b,"35")||b.73)r.R(b);B r=6.1R(r,b)});v r},1b:q(c,d,a){u e=6.43(c)?{}:6.3J;7(e[d]){7(a!=J)c[e[d]]=a;v c[e[d]]}B 7(a==J&&6.N.1h&&6.Q(c,"35")&&(d=="72"||d=="70"))v c.6X(d).5R;B 7(c.4x){7(d=="1d"&&6.N.1h){7(a!=J){c.5U=1;c.1j=(c.1j||"").1o(/4J\\([^)]*\\)/,"")+(34(a).3s()=="6S"?"":"4J(1d="+a*4Q+")")}v c.1j?(34(c.1j.3w(/1d=([^)]*)/)[1])/4Q).3s():""}7(a!=J)c.6Q(d,a);7(6.N.1h&&/4I|2r/.16(d)&&!6.43(c))v c.2Z(d,2);v c.2Z(d)}B{d=d.1o(/-([a-z])/6M,q(z,b){v b.1S()});7(a!=J)c[d]=a;v c[d]}},2p:q(t){v t.1o(/^\\s+|\\s+$/g,"")},2K:q(a){u r=[];7(1e a!="6K")E(u i=0,25=a.C;i<25;i++)r.R(a[i]);B r=a.4X(0);v r},2s:q(b,a){E(u i=0,25=a.C;i<25;i++)7(a[i]==b)v i;v-1},1R:q(a,b){E(u i=0;b[i];i++)a.R(b[i]);v a},5c:q(a){u r=[],3F=6.1m++;E(u i=0,4C=a.C;i<4C;i++)7(3F!=a[i].1m){a[i].1m=3F;r.R(a[i])}v r},1m:0,2x:q(c,b,d){7(1e b=="1v")b=17 3S("a","i","v "+b);u a=[];E(u i=0,30=c.C;i<30;i++)7(!d&&b(c[i],i)||d&&!b(c[i],i))a.R(c[i]);v a},3h:q(c,b){7(1e b=="1v")b=17 3S("a","v "+b);u d=[];E(u i=0,30=c.C;i<30;i++){u a=b(c[i],i);7(a!==H&&a!=J){7(a.18!=23)a=[a];d=d.6x(a)}}v d}});17 q(){u b=6w.6v.2T();6.N={6u:b.3w(/.+(?:6t|6r|6p|6n)[\\/: ]([\\d.]+)/)[1],2g:/5g/.16(b),2k:/2k/.16(b),1h:/1h/.16(b)&&!/2k/.16(b),3g:/3g/.16(b)&&!/(6i|5g)/.16(b)};6.6h=!6.N.1h||P.6g=="6d";6.1T=6.N.1h?"1T":"5t",6.3J={"E":"69","68":"V","3u":6.1T,5t:6.1T,1T:6.1T,26:"26",V:"V",2t:"2t",2B:"2B",2D:"2D",66:"64",2H:"2H",62:"5Z"}};6.F({5E:"a.L",4r:"6.4r(a)",8o:"6.21(a,2,\'1U\')",8n:"6.21(a,2,\'4t\')",8k:"6.4q(a.L.1a,a)",8h:"6.4q(a.1a)"},q(i,n){6.11[i]=q(a){u b=6.3h(9,n);7(a&&1e a=="1v")b=6.2w(a,b);v 9.1W(b)}});6.F({5j:"3m",8g:"5s",2J:"5p",8f:"5n"},q(i,n){6.11[i]=q(){u a=1g;v 9.F(q(){E(u j=0,25=a.C;j<25;j++)6(a[j])[n](9)})}});6.F({5r:q(a){6.1b(9,a,"");9.8e(a)},8d:q(c){6.V.1A(9,c)},8b:q(c){6.V.1B(9,c)},8a:q(c){6.V[6.V.3v(9,c)?"1B":"1A"](9,c)},1B:q(a){7(!a||6.1j(a,[9]).r.C)9.L.3t(9)},2V:q(){1q(9.1a)9.3t(9.1a)}},q(i,n){6.11[i]=q(){v 9.F(n,1g)}});6.F(["5Q","5P","5M","5L"],q(i,n){6.11[n]=q(a,b){v 9.1j(":"+n+"("+a+")",b)}});6.F(["1u","28"],q(i,n){6.11[n]=q(h){v h==J?(9.C?6.1c(9[0],n):H):9.1c(n,h.18==31?h:h+"4p")}});6.1f({4o:{"":"m[2]==\'*\'||6.Q(a,m[2])","#":"a.2Z(\'24\')==m[2]",":":{5P:"i<m[3]-0",5M:"i>m[3]-0",21:"m[3]-0==i",5Q:"m[3]-0==i",2P:"i==0",2O:"i==r.C-1",5J:"i%2==0",5G:"i%2","2P-2X":"a.L.3V(\'*\')[0]==a","2O-2X":"6.21(a.L.5F,1,\'4t\')==a","88-2X":"!6.21(a.L.5F,2,\'4t\')",5E:"a.1a",2V:"!a.1a",5L:"(a.5D||a.87||\'\').I(m[3])>=0",4g:\'"1y"!=a.G&&6.1c(a,"15")!="1G"&&6.1c(a,"49")!="1y"\',1y:\'"1y"==a.G||6.1c(a,"15")=="1G"||6.1c(a,"49")=="1y"\',86:"!a.2B",2B:"a.2B",2D:"a.2D",2H:"a.2H||6.1b(a,\'2H\')",2R:"\'2R\'==a.G",4c:"\'4c\'==a.G",5C:"\'5C\'==a.G",4m:"\'4m\'==a.G",5B:"\'5B\'==a.G",4l:"\'4l\'==a.G",5A:"\'5A\'==a.G",5z:"\'5z\'==a.G",1J:\'"1J"==a.G||6.Q(a,"1J")\',5y:"/5y|2y|84|1J/i.16(a.Q)"},"[":"6.1H(m[2],a).C"},5x:[/^\\[ *(@)([\\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\\4 *\\]/,/^(\\[)\\s*(.*?(\\[.*?\\])?[^[]*?)\\s*\\]/,/^(:)([\\w-]+)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/,17 3o("^([:.#]*)("+(6.2I="(?:[\\\\w\\81-\\7Z*1I-]|\\\\\\\\.)")+"+)")],2w:q(a,c,b){u d,1O=[];1q(a&&a!=d){d=a;u f=6.1j(a,c,b);a=f.t.1o(/^\\s*,\\s*/,"");1O=b?c=f.r:6.1R(1O,f.r)}v 1O},1H:q(t,l){7(1e t!="1v")v[t];7(l&&!l.1r)l=H;l=l||P;7(!t.I("//")){l=l.4i;t=t.2G(2,t.C)}B 7(!t.I("/")&&!l.2N){l=l.4i;t=t.2G(1,t.C);7(t.I("/")>=1)t=t.2G(t.I("/"),t.C)}u b=[l],2a=[],2O;1q(t&&2O!=t){u r=[];2O=t;t=6.2p(t).1o(/^\\/\\//,"");u k=M;u g=17 3o("^[/>]\\\\s*("+6.2I+"+)");u m=g.1Q(t);7(m){u o=m[1].1S();E(u i=0;b[i];i++)E(u c=b[i].1a;c;c=c.1U)7(c.1r==1&&(o=="*"||c.Q==o.1S()))r.R(c);b=r;t=t.1o(g,"");7(t.I(" ")==0)7T;k=K}B{g=/^((\\/?\\.\\.)|([>\\/+~]))\\s*([a-z]*)/i;7((m=g.1Q(t))!=H){r=[];u o=m[4],1m=6.1m++;m=m[1];E(u j=0,2b=b.C;j<2b;j++)7(m.I("..")<0){u n=m=="~"||m=="+"?b[j].1U:b[j].1a;E(;n;n=n.1U)7(n.1r==1){7(m=="~"&&n.1m==1m)1E;7(!o||n.Q==o.1S()){7(m=="~")n.1m=1m;r.R(n)}7(m=="+")1E}}B r.R(b[j].L);b=r;t=6.2p(t.1o(g,""));k=K}}7(t&&!k){7(!t.I(",")){7(l==b[0])b.4f();2a=6.1R(2a,b);r=b=[l];t=" "+t.2G(1,t.C)}B{u h=17 3o("^("+6.2I+"+)(#)("+6.2I+"+)");u m=h.1Q(t);7(m){m=[0,m[2],m[3],m[1]]}B{h=17 3o("^([#.]?)("+6.2I+"*)");m=h.1Q(t)}m[2]=m[2].1o(/\\\\/g,"");u f=b[b.C-1];7(m[1]=="#"&&f&&f.4e){u p=f.4e(m[2]);7((6.N.1h||6.N.2k)&&p&&1e p.24=="1v"&&p.24!=m[2])p=6(\'[@24="\'+m[2]+\'"]\',f)[0];b=r=p&&(!m[3]||6.Q(p,m[3]))?[p]:[]}B{E(u i=0;b[i];i++){u a=m[1]!=""||m[0]==""?"*":m[2];7(a=="*"&&b[i].Q.2T()=="7R")a="2C";r=6.1R(r,b[i].3V(a))}7(m[1]==".")r=6.4d(r,m[2]);7(m[1]=="#"){u e=[];E(u i=0;r[i];i++)7(r[i].2Z("24")==m[2]){e=[r[i]];1E}r=e}b=r}t=t.1o(h,"")}}7(t){u d=6.1j(t,r);b=r=d.r;t=6.2p(d.t)}}7(t)b=[];7(b&&l==b[0])b.4f();2a=6.1R(2a,b);v 2a},4d:q(r,m,a){m=" "+m+" ";u b=[];E(u i=0;r[i];i++){u c=(" "+r[i].V+" ").I(m)>=0;7(!a&&c||a&&!c)b.R(r[i])}v b},1j:q(t,r,h){u d;1q(t&&t!=d){d=t;u p=6.5x,m;E(u i=0;p[i];i++){m=p[i].1Q(t);7(m){t=t.7P(m[0].C);m[2]=m[2].1o(/\\\\/g,"");1E}}7(!m)1E;7(m[1]==":"&&m[2]=="4V")r=6.1j(m[3],r,K).r;B 7(m[1]==".")r=6.4d(r,m[2],h);B 7(m[1]=="@"){u g=[],G=m[3];E(u i=0,2b=r.C;i<2b;i++){u a=r[i],z=a[6.3J[m[2]]||m[2]];7(z==H||/4I|2r/.16(m[2]))z=6.1b(a,m[2]);7((G==""&&!!z||G=="="&&z==m[5]||G=="!="&&z!=m[5]||G=="^="&&z&&!z.I(m[5])||G=="$="&&z.2G(z.C-m[5].C)==m[5]||(G=="*="||G=="~=")&&z.I(m[5])>=0)^h)g.R(a)}r=g}B 7(m[1]==":"&&m[2]=="21-2X"){u e=6.1m++,g=[],16=/(\\d*)n\\+?(\\d*)/.1Q(m[3]=="5J"&&"2n"||m[3]=="5G"&&"2n+1"||!/\\D/.16(m[3])&&"n+"+m[3]||m[3]),2P=(16[1]||1)-0,d=16[2]-0;E(u i=0,2b=r.C;i<2b;i++){u j=r[i],L=j.L;7(e!=L.1m){u c=1;E(u n=L.1a;n;n=n.1U)7(n.1r==1)n.4b=c++;L.1m=e}u b=M;7(2P==1){7(d==0||j.4b==d)b=K}B 7((j.4b+d)%2P==0)b=K;7(b^h)g.R(j)}r=g}B{u f=6.4o[m[1]];7(1e f!="1v")f=6.4o[m[1]][m[2]];4a("f = q(a,i){v "+f+"}");r=6.2x(r,f,h)}}v{r:r,t:t}},4r:q(c){u b=[];u a=c.L;1q(a&&a!=P){b.R(a);a=a.L}v b},21:q(a,e,c,b){e=e||1;u d=0;E(;a;a=a[c])7(a.1r==1&&++d==e)1E;v a},4q:q(n,a){u r=[];E(;n;n=n.1U){7(n.1r==1&&(!a||n!=a))r.R(n)}v r}});6.S={1A:q(d,e,c,b){7(6.N.1h&&d.3l!=J)d=12;7(!c.1M)c.1M=9.1M++;7(b!=J){u f=c;c=q(){v f.O(9,1g)};c.W=b;c.1M=f.1M}7(!d.$19)d.$19={};7(!d.$1p)d.$1p=q(){u a;7(1e 6=="J"||6.S.48)v a;a=6.S.1p.O(d,1g);v a};u g=d.$19[e];7(!g){g=d.$19[e]={};7(d.47)d.47(e,d.$1p,M);B d.7O("5m"+e,d.$1p)}g[c.1M]=c;7(!9.U[e])9.U[e]=[];7(6.2s(d,9.U[e])==-1)9.U[e].R(d)},1M:1,U:{},1B:q(b,c,a){u d=b.$19,1V,2m;7(d){7(c&&c.G){a=c.46;c=c.G}7(!c){E(c T d)9.1B(b,c)}B 7(d[c]){7(a)3j d[c][a.1M];B E(a T b.$19[c])3j d[c][a];E(1V T d[c])1E;7(!1V){7(b.45)b.45(c,b.$1p,M);B b.7L("5m"+c,b.$1p);1V=H;3j d[c];1q(9.U[c]&&((2m=6.2s(b,9.U[c]))>=0))3j 9.U[c][2m]}}E(1V T d)1E;7(!1V)b.$1p=b.$19=H}},1t:q(c,b,d){b=6.2K(b||[]);7(!d)6.F(9.U[c]||[],q(){6.S.1t(c,b,9)});B{u a,1V,11=6.14(d[c]||H);b.5k(9.44({G:c,1N:d}));7(6.14(d.$1p)&&(a=d.$1p.O(d,b))!==M)9.48=K;7(11&&a!==M&&!6.Q(d,\'a\'))d[c]();9.48=M}},1p:q(b){u a;b=6.S.44(b||12.S||{});u c=9.$19&&9.$19[b.G],1Z=[].4X.3D(1g,1);1Z.5k(b);E(u j T c){1Z[0].46=c[j];1Z[0].W=c[j].W;7(c[j].O(9,1Z)===M){b.2d();b.2L();a=M}}7(6.N.1h)b.1N=b.2d=b.2L=b.46=b.W=H;v a},44:q(c){u a=c;c=6.1f({},a);c.2d=q(){7(a.2d)v a.2d();a.7J=M};c.2L=q(){7(a.2L)v a.2L();a.7H=K};7(!c.1N&&c.5i)c.1N=c.5i;7(6.N.2g&&c.1N.1r==3)c.1N=a.1N.L;7(!c.42&&c.4k)c.42=c.4k==c.1N?c.7E:c.4k;7(c.5h==H&&c.5f!=H){u e=P.4i,b=P.4w;c.5h=c.5f+(e&&e.5I||b.5I);c.7D=c.7C+(e&&e.5b||b.5b)}7(!c.3f&&(c.5a||c.5O))c.3f=c.5a||c.5O;7(!c.59&&c.58)c.59=c.58;7(!c.3f&&c.1J)c.3f=(c.1J&1?1:(c.1J&2?3:(c.1J&4?2:0)));v c}};6.11.1f({3e:q(c,a,b){v c=="3z"?9.41(c,a,b):9.F(q(){6.S.1A(9,c,b||a,b&&a)})},41:q(d,b,c){v 9.F(q(){6.S.1A(9,d,q(a){6(9).3C(a);v(c||b).O(9,1g)},c&&b)})},3C:q(a,b){v 9.F(q(){6.S.1B(9,a,b)})},1t:q(a,b){v 9.F(q(){6.S.1t(a,b,9)})},1P:q(){u a=1g;v 9.57(q(e){9.3O=0==9.3O?1:0;e.2d();v a[9.3O].O(9,[e])||M})},7y:q(f,g){q 3Y(e){u p=e.42;1q(p&&p!=9)2c{p=p.L}2h(e){p=9};7(p==9)v M;v(e.G=="3X"?f:g).O(9,[e])}v 9.3X(3Y).54(3Y)},1D:q(f){7(6.3c)f.O(P,[6]);B 6.2o.R(q(){v f.O(9,[6])});v 9}});6.1f({3c:M,2o:[],1D:q(){7(!6.3c){6.3c=K;7(6.2o){6.F(6.2o,q(){9.O(P)});6.2o=H}7(6.N.3g||6.N.2k)P.45("53",6.1D,M);7(!12.7x.C)6(12).1X(q(){6("#3W").1B()})}}});17 q(){6.F(("7w,7v,1X,7u,7t,3z,57,7s,"+"7r,7q,7p,3X,54,7o,2y,"+"4l,7n,7m,7l,29").2Q(","),q(i,o){6.11[o]=q(f){v f?9.3e(o,f):9.1t(o)}});7(6.N.3g||6.N.2k)P.47("53",6.1D,M);B 7(6.N.1h){P.7k("<7j"+"7h 24=3W 7g=K "+"2r=//:><\\/3a>");u a=P.4e("3W");7(a)a.7f=q(){7(9.39!="1n")v;6.1D()};a=H}B 7(6.N.2g)6.3R=3l(q(){7(P.39=="7c"||P.39=="1n"){3P(6.3R);6.3R=H;6.1D()}},10);6.S.1A(12,"1X",6.1D)};7(6.N.1h)6(12).41("3z",q(){u a=6.S.U;E(u b T a){u c=a[b],i=c.C;7(i&&b!=\'3z\')79 c[i-1]&&6.S.1B(c[i-1],b);1q(--i)}});6.11.1f({78:q(c,b,a){9.1X(c,b,a,1)},1X:q(g,d,c,e){7(6.14(g))v 9.3e("1X",g);c=c||q(){};u f="3M";7(d)7(6.14(d)){c=d;d=H}B{d=6.2C(d);f="4W"}u h=9;6.37({1C:g,G:f,W:d,2v:e,1n:q(a,b){7(b=="27"||!e&&b=="4T")h.1b("26",a.36).3L().F(c,[a.36,b,a]);B c.O(h,[a.36,b,a])}});v 9},74:q(){v 6.2C(9)},3L:q(){v 9.1H("3a").F(q(){7(9.2r)6.4S(9.2r);B 6.3H(9.2R||9.5D||9.26||"")}).2E()}});6.F("4R,4E,4P,4O,4N,4F".2Q(","),q(i,o){6.11[o]=q(f){v 9.3e(o,f)}});6.1f({1L:q(e,c,a,d,b){7(6.14(c)){a=c;c=H}v 6.37({G:"3M",1C:e,W:c,27:a,3I:d,2v:b})},6Y:q(d,b,a,c){v 6.1L(d,b,a,c,1)},4S:q(b,a){v 6.1L(b,H,a,"3a")},6W:q(c,b,a){v 6.1L(c,b,a,"4L")},6V:q(d,b,a,c){7(6.14(b)){a=b;b={}}v 6.37({G:"4W",1C:d,W:b,27:a,3I:c})},6U:q(a){6.32.20=a},6Z:q(a){6.1f(6.32,a)},32:{U:K,G:"3M",20:0,4K:"6R/x-6P-35-6O",4M:K,2W:K,W:H},38:{},37:q(s){s=6.1f({},6.32,s);7(s.W){7(s.4M&&1e s.W!="1v")s.W=6.2C(s.W);7(s.G.2T()=="1L"){s.1C+=((s.1C.I("?")>-1)?"&":"?")+s.W;s.W=H}}7(s.U&&!6.3G++)6.S.1t("4R");u f=M;u h=12.4H?17 4H("6N.6L"):17 4G();h.7b(s.G,s.1C,s.2W);7(s.W)h.3N("6J-6I",s.4K);7(s.2v)h.3N("6H-3Q-6F",6.38[s.1C]||"6E, 6D 6C 6B 3T:3T:3T 6A");h.3N("X-6z-6y","4G");7(s.5e)s.5e(h);7(s.U)6.S.1t("4F",[h,s]);u g=q(d){7(h&&(h.39==4||d=="20")){f=K;7(i){3P(i);i=H}u c;2c{c=6.56(h)&&d!="20"?s.2v&&6.4B(h,s.1C)?"4T":"27":"29";7(c!="29"){u b;2c{b=h.3E("50-3Q")}2h(e){}7(s.2v&&b)6.38[s.1C]=b;u a=6.4Z(h,s.3I);7(s.27)s.27(a,c);7(s.U)6.S.1t("4N",[h,s])}B 6.3b(s,h,c)}2h(e){c="29";6.3b(s,h,c,e)}7(s.U)6.S.1t("4P",[h,s]);7(s.U&&!--6.3G)6.S.1t("4E");7(s.1n)s.1n(h,c);7(s.2W)h=H}};u i=3l(g,13);7(s.20>0)51(q(){7(h){h.6s();7(!f)g("20")}},s.20);2c{h.6q(s.W)}2h(e){6.3b(s,h,H,e)}7(!s.2W)g();v h},3b:q(s,a,b,e){7(s.29)s.29(a,b,e);7(s.U)6.S.1t("4O",[a,s,e])},3G:0,56:q(r){2c{v!r.1Y&&7A.7B=="4m:"||(r.1Y>=5d&&r.1Y<6m)||r.1Y==5q||6.N.2g&&r.1Y==J}2h(e){}v M},4B:q(a,c){2c{u b=a.3E("50-3Q");v a.1Y==5q||b==6.38[c]||6.N.2g&&a.1Y==J}2h(e){}v M},4Z:q(r,b){u c=r.3E("6l-G");u a=!b&&c&&c.I("4z")>=0;a=b=="4z"||a?r.6k:r.36;7(b=="3a")6.3H(a);7(b=="4L")a=4a("("+a+")");7(b=="3K")6("<1z>").3K(a).3L();v a},2C:q(a){u s=[];7(a.18==23||a.3B)6.F(a,q(){s.R(2e(9.6j)+"="+2e(9.2t))});B E(u j T a)7(a[j]&&a[j].18==23)6.F(a[j],q(){s.R(2e(j)+"="+2e(9))});B s.R(2e(j)+"="+2e(a[j]));v s.5K("&")},3H:q(a){7(12.4y)12.4y(a);B 7(6.N.2g)12.51(a,0);B 4a.3D(12,a)}});6.11.1f({1k:q(b,a){v b?9.1w({1u:"1k",28:"1k",1d:"1k"},b,a):9.1j(":1y").F(q(){9.Y.15=9.2f?9.2f:"";7(6.1c(9,"15")=="1G")9.Y.15="2j"}).2E()},1i:q(b,a){v b?9.1w({1u:"1i",28:"1i",1d:"1i"},b,a):9.1j(":4g").F(q(){9.2f=9.2f||6.1c(9,"15");7(9.2f=="1G")9.2f="2j";9.Y.15="1G"}).2E()},5o:6.11.1P,1P:q(a,b){v 6.14(a)&&6.14(b)?9.5o(a,b):a?9.1w({1u:"1P",28:"1P",1d:"1P"},a,b):9.F(q(){6(9)[6(9).33(":1y")?"1k":"1i"]()})},6f:q(b,a){v 9.1w({1u:"1k"},b,a)},6e:q(b,a){v 9.1w({1u:"1i"},b,a)},6c:q(b,a){v 9.1w({1u:"1P"},b,a)},6b:q(b,a){v 9.1w({1d:"1k"},b,a)},6a:q(b,a){v 9.1w({1d:"1i"},b,a)},7U:q(c,a,b){v 9.1w({1d:a},c,b)},1w:q(d,h,f,g){v 9.1l(q(){u c=6(9).33(":1y"),2z=6.5v(h,f,g),5u=9;E(u p T d)7(d[p]=="1i"&&c||d[p]=="1k"&&!c)v 6.14(2z.1n)&&2z.1n.O(9);9.2i=6.1f({},d);6.F(d,q(a,b){u e=17 6.2A(5u,2z,a);7(b.18==3x)e.2U(e.1O(),b);B e[b=="1P"?c?"1k":"1i":b](d)})})},1l:q(a,b){7(!b){b=a;a="2A"}v 9.F(q(){7(!9.1l)9.1l={};7(!9.1l[a])9.1l[a]=[];9.1l[a].R(b);7(9.1l[a].C==1)b.O(9)})}});6.1f({5v:q(b,a,c){u d=b&&b.18==65?b:{1n:c||!c&&a||6.14(b)&&b,1F:b,2u:c&&a||a&&a.18!=3S&&a||(6.2u.4j?"4j":"5w")};d.1F=(d.1F&&d.1F.18==3x?d.1F:{63:61,60:5d}[d.1F])||89;d.2M=d.1n;d.1n=q(){6.5N(9,"2A");7(6.14(d.2M))d.2M.O(9)};v d},2u:{5w:q(p,n,b,a){v b+a*p},4j:q(p,n,b,a){v((-5H.5X(p*5H.5W)/2)+0.5)*a+b}},1l:{},5N:q(b,a){a=a||"2A";7(b.1l&&b.1l[a]){b.1l[a].4f();u f=b.1l[a][0];7(f)f.O(b)}},3y:[],2A:q(h,e,j){u z=9;u y=h.Y;7(j=="1u"||j=="28"){u f=6.1c(h,"15");u g=y.4u;y.4u="1y"}z.a=q(){7(e.3A)e.3A.O(h,[z.2l]);7(j=="1d")6.1b(y,"1d",z.2l);B{y[j]=8m(z.2l)+"4p";y.15="2j"}};z.5V=q(){v 34(6.1c(h,j))};z.1O=q(){u r=34(6.2q(h,j));v r&&r>-8l?r:z.5V()};z.2U=q(c,b){z.4s=(17 5T()).5S();z.2l=c;z.a();6.3y.R(q(){v z.3A(c,b)});7(6.3y.C==1){u d=3l(q(){u a=6.3y;E(u i=0;i<a.C;i++)7(!a[i]())a.8j(i--,1);7(!a.C)3P(d)},13)}};z.1k=q(){7(!h.22)h.22={};h.22[j]=6.1b(h.Y,j);e.1k=K;z.2U(0,9.1O());7(j!="1d")y[j]="8q";6(h).1k()};z.1i=q(){7(!h.22)h.22={};h.22[j]=6.1b(h.Y,j);e.1i=K;z.2U(9.1O(),0)};z.3A=q(a,c){u t=(17 5T()).5S();7(t>e.1F+z.4s){z.2l=c;z.a();7(h.2i)h.2i[j]=K;u b=K;E(u i T h.2i)7(h.2i[i]!==K)b=M;7(b){7(f!=H){y.4u=g;y.15=f;7(6.1c(h,"15")=="1G")y.15="2j"}7(e.1i)y.15="1G";7(e.1i||e.1k)E(u p T h.2i)6.1b(y,p,h.22[p])}7(b&&6.14(e.1n))e.1n.O(h);v M}B{u n=t-9.4s;u p=n/e.1F;z.2l=6.2u[e.2u](p,n,a,(c-a),e.1F);z.a()}v K}}})}',62,524,'||||||jQuery|if||this|||||||||||||||||function||||var|return||||||else|length||for|each|type|null|indexOf|undefined|true|parentNode|false|browser|apply|document|nodeName|push|event|in|global|className|data||style|||fn|window||isFunction|display|test|new|constructor|events|firstChild|attr|css|opacity|typeof|extend|arguments|msie|hide|filter|show|queue|mergeNum|complete|replace|handle|while|nodeType|table|trigger|height|string|animate|tbody|hidden|div|add|remove|url|ready|break|duration|none|find|_|button|tb|get|guid|target|cur|toggle|exec|merge|toUpperCase|styleFloat|nextSibling|ret|pushStack|load|status|args|timeout|nth|orig|Array|id|al|innerHTML|success|width|error|done|rl|try|preventDefault|encodeURIComponent|oldblock|safari|catch|curAnim|block|opera|now|index||readyList|trim|curCSS|src|inArray|value|easing|ifModified|multiFilter|grep|select|opt|fx|disabled|param|checked|end|domManip|substr|selected|chars|insertBefore|makeArray|stopPropagation|old|ownerDocument|last|first|split|text|childNodes|toLowerCase|custom|empty|async|child|clean|getAttribute|el|String|ajaxSettings|is|parseFloat|form|responseText|ajax|lastModified|readyState|script|handleError|isReady|defaultView|bind|which|mozilla|map|position|delete|tr|setInterval|append|static|RegExp|oWidth|oHeight|cloneNode|toString|removeChild|float|has|match|Number|timers|unload|step|jquery|unbind|call|getResponseHeader|num|active|globalEval|dataType|props|html|evalScripts|GET|setRequestHeader|lastToggle|clearInterval|Modified|safariTimer|Function|00|currentStyle|getElementsByTagName|__ie_init|mouseover|handleHover|init|getComputedStyle|one|relatedTarget|isXMLDoc|fix|removeEventListener|handler|addEventListener|triggered|visibility|eval|nodeIndex|radio|classFilter|getElementById|shift|visible|appendChild|documentElement|swing|fromElement|submit|file|swap|expr|px|sibling|parents|startTime|previousSibling|overflow|ol|body|tagName|execScript|xml|setArray|httpNotModified|fl|prop|ajaxStop|ajaxSend|XMLHttpRequest|ActiveXObject|href|alpha|contentType|json|processData|ajaxSuccess|ajaxError|ajaxComplete|100|ajaxStart|getScript|notmodified|colgroup|not|POST|slice|fieldset|httpData|Last|setTimeout|getPropertyValue|DOMContentLoaded|mouseout|createElement|httpSuccess|click|ctrlKey|metaKey|charCode|scrollTop|unique|200|beforeSend|clientX|webkit|pageX|srcElement|appendTo|unshift|prevObject|on|after|_toggle|before|304|removeAttr|prepend|cssFloat|self|speed|linear|parse|input|reset|image|password|checkbox|textContent|parent|lastChild|odd|Math|scrollLeft|even|join|contains|gt|dequeue|keyCode|lt|eq|nodeValue|getTime|Date|zoom|max|PI|cos|font|maxLength|fast|600|maxlength|slow|readOnly|Object|readonly|createTextNode|class|htmlFor|fadeOut|fadeIn|slideToggle|CSS1Compat|slideUp|slideDown|compatMode|boxModel|compatible|name|responseXML|content|300|ie|noConflict|ra|send|it|abort|rv|version|userAgent|navigator|concat|With|Requested|GMT|1970|Jan|01|Thu|Since|reverse|If|Type|Content|array|XMLHTTP|ig|Microsoft|urlencoded|www|setAttribute|application|NaN|val|ajaxTimeout|post|getJSON|getAttributeNode|getIfModified|ajaxSetup|method|FORM|action|options|serialize|col|th|td|loadIfModified|do|colg|open|loaded|tfoot|thead|onreadystatechange|defer|ipt|leg|scr|write|keyup|keypress|keydown|change|mousemove|mouseup|mousedown|dblclick|scroll|resize|focus|blur|frames|hover|clone|location|protocol|clientY|pageY|toElement|clientWidth|clientHeight|cancelBubble|relative|returnValue|left|detachEvent|right|absolute|attachEvent|substring|offsetWidth|object|offsetHeight|continue|fadeTo|Width|border|padding|size|uFFFF|Left|u0128|Right|Bottom|textarea|Top|enabled|innerText|only|400|toggleClass|removeClass|wrap|addClass|removeAttribute|insertAfter|prependTo|children|line|splice|siblings|10000|parseInt|prev|next|weight|1px|prototype'.split('|'),0,{}))/*
 * Interface elements for jQuery - http://interface.eyecon.ro
 *
 * Copyright (c) 2006 Stefan Petre
 * Dual licensed under the MIT (MIT-LICENSE.txt) 
 * and GPL (GPL-LICENSE.txt) licenses.
 */
 eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('4.1e={3Y:7(e){6 x=0;6 y=0;6 1Z=17;6 E=e.1k;d(4(e).D(\'P\')==\'S\'){25=E.1i;2A=E.Q;E.1i=\'2a\';E.P=\'1S\';E.Q=\'2n\';1Z=2s}6 8=e;2S(8){x+=8.4t+(8.21&&!4.35.3X?H(8.21.3i)||0:0);y+=8.4o+(8.21&&!4.35.3X?H(8.21.3b)||0:0);8=8.4C}8=e;2S(8&&8.3Z&&8.3Z.3r()!=\'W\'){x-=8.1R||0;y-=8.1G||0;8=8.2x}d(1Z){E.P=\'S\';E.Q=2A;E.1i=25}u{x:x,y:y}},56:7(8){6 x=0,y=0;2S(8){x+=8.4t||0;y+=8.4o||0;8=8.4C}u{x:x,y:y}},2Z:7(e){6 w=4.D(e,\'1Y\');6 h=4.D(e,\'1W\');6 1d=0;6 1b=0;6 E=e.1k;d(4(e).D(\'P\')!=\'S\'){1d=e.3t;1b=e.3v}B{25=E.1i;2A=E.Q;E.1i=\'2a\';E.P=\'1S\';E.Q=\'2n\';1d=e.3t;1b=e.3v;E.P=\'S\';E.Q=2A;E.1i=25}u{w:w,h:h,1d:1d,1b:1b}},4Y:7(8){u{1d:8.3t||0,1b:8.3v||0}},4F:7(e){6 h,w,1T;d(e){w=e.2o;h=e.2m}B{1T=J.15;w=2z.3n||30.3n||(1T&&1T.2o)||J.W.2o;h=2z.3l||30.3l||(1T&&1T.2m)||J.W.2m}u{w:w,h:h}},3q:7(e){6 t,l,w,h,1u,1q;d(e&&e.2v.3r()!=\'W\'){t=e.1G;l=e.1R;w=e.3h;h=e.3d;1u=0;1q=0}B{d(J.15&&J.15.1G){t=J.15.1G;l=J.15.1R;w=J.15.3h;h=J.15.3d}B d(J.W){t=J.W.1G;l=J.W.1R;w=J.W.3h;h=J.W.3d}1u=30.3n||J.15.2o||J.W.2o||0;1q=30.3l||J.15.2m||J.W.2m||0}u{t:t,l:l,w:w,h:h,1u:1u,1q:1q}},3N:7(e,1U){6 8=4(e);6 t=8.D(\'2t\')||\'\';6 r=8.D(\'2q\')||\'\';6 b=8.D(\'2k\')||\'\';6 l=8.D(\'2l\')||\'\';d(1U)u{t:H(t)||0,r:H(r)||0,b:H(b)||0,l:H(l)};B u{t:t,r:r,b:b,l:l}},4Z:7(e,1U){6 8=4(e);6 t=8.D(\'3G\')||\'\';6 r=8.D(\'3O\')||\'\';6 b=8.D(\'3H\')||\'\';6 l=8.D(\'4d\')||\'\';d(1U)u{t:H(t)||0,r:H(r)||0,b:H(b)||0,l:H(l)};B u{t:t,r:r,b:b,l:l}},5R:7(e,1U){6 8=4(e);6 t=8.D(\'3b\')||\'\';6 r=8.D(\'3P\')||\'\';6 b=8.D(\'3F\')||\'\';6 l=8.D(\'3i\')||\'\';d(1U)u{t:H(t)||0,r:H(r)||0,b:H(b)||0,l:H(l)||0};B u{t:t,r:r,b:b,l:l}},4U:7(2f){6 x=2f.4K||(2f.4H+(J.15.1R||J.W.1R))||0;6 y=2f.4G||(2f.5b+(J.15.1G||J.W.1G))||0;u{x:x,y:y}},3E:7(1a,3p){3p(1a);1a=1a.3I;2S(1a){4.1e.3E(1a,3p);1a=1a.54}},53:7(1a){4.1e.3E(1a,7(8){V(6 1t 1F 8){d(29 8[1t]===\'7\'){8[1t]=1l}}})},5a:7(8,R){6 1j=$.1e.3q();6 34=$.1e.2Z(8);d(!R||R==\'59\')$(8).D({12:1j.t+((1h.4u(1j.h,1j.1q)-1j.t-34.1b)/2)+\'16\'});d(!R||R==\'4V\')$(8).D({T:1j.l+((1h.4u(1j.w,1j.1u)-1j.l-34.1d)/2)+\'16\'})},4O:7(8,4p){6 4r=$(\'46[@2O*="2B"]\',8||J),2B;4r.2Q(7(){2B=q.2O;q.2O=4p;q.1k.5I="5O:5K.5y.5k(2O=\'"+2B+"\')"})}};[].4E||(5l.5j.4E=7(v,n){n=(n==1l)?0:n;6 m=q.1y;V(6 i=n;i<m;i++)d(q[i]==v)u i;u-1});4.2H=7(e){d(/^5i$|^5e$|^5u$|^5v$|^5w$|^5t$|^5p$|^5r$|^5z$|^W$|^5q$|^5s$|^5o$|^5n$|^5h$|^5g$|^5f$/i.2p(e.2v))u 17;B u 2s};4.f.4f=7(e,1x){6 c=e.3I;6 1r=c.1k;1r.Q=1x.Q;1r.2t=1x.1g.t;1r.2l=1x.1g.l;1r.2k=1x.1g.b;1r.2q=1x.1g.r;1r.12=1x.12+\'16\';1r.T=1x.T+\'16\';e.2x.3V(c,e);e.2x.5m(e)};4.f.4g=7(e){d(!4.2H(e))u 17;6 t=4(e);6 E=e.1k;6 1Z=17;6 K={};K.Q=t.D(\'Q\');d(t.D(\'P\')==\'S\'){25=t.D(\'1i\');E.1i=\'2a\';E.P=\'\';1Z=2s}K.1D=4.1e.2Z(e);K.1g=4.1e.3N(e);6 3A=e.21?e.21.3S:t.D(\'5x\');K.12=H(t.D(\'12\'))||0;K.T=H(t.D(\'T\'))||0;6 49=\'5M\'+H(1h.5L()*4i);6 1J=J.5N(/^46$|^5Q$|^5P$|^5J$|^5C$|^5B$|^36$|^5A$|^5d$|^5D$|^5E$|^5H$|^5G$|^5F$/i.2p(e.2v)?\'5S\':e.2v);4.1t(1J,\'4N\',49);1J.4w=\'4M\';6 U=1J.1k;6 12=0;6 T=0;d(K.Q==\'3c\'||K.Q==\'2n\'){12=K.12;T=K.T}U.P=\'S\';U.12=12+\'16\';U.T=T+\'16\';U.Q=K.Q!=\'3c\'&&K.Q!=\'2n\'?\'3c\':K.Q;U.2u=\'2a\';U.1W=K.1D.1b+\'16\';U.1Y=K.1D.1d+\'16\';U.2t=K.1g.t;U.2q=K.1g.r;U.2k=K.1g.b;U.2l=K.1g.l;d(4.35.4I){U.3S=3A}B{U.4J=3A}e.2x.3V(1J,e);E.2t=\'20\';E.2q=\'20\';E.2k=\'20\';E.2l=\'20\';E.Q=\'2n\';E.58=\'S\';E.12=\'20\';E.T=\'20\';d(1Z){E.P=\'S\';E.1i=25}1J.51(e);U.P=\'1S\';u{K:K,1z:4(1J)}};4.f.2j={52:[0,F,F],4W:[3T,F,F],4X:[4b,4b,57],5c:[0,0,0],4R:[0,0,F],4L:[48,42,42],4S:[0,F,F],4T:[0,0,24],4Q:[0,24,24],4P:[3s,3s,3s],6f:[0,73,0],72:[71,6Z,43],70:[24,0,24],74:[76,43,47],7a:[F,3U,0],79:[78,50,77],6Y:[24,0,0],6X:[6Q,6P,6O],6M:[6N,0,2C],6R:[F,0,F],6S:[F,6W,0],7c:[0,1H,0],6V:[75,0,6U],6T:[3T,41,3U],7b:[7e,7t,41],7s:[3Q,F,F],7q:[4a,7u,4a],7x:[2C,2C,2C],7v:[F,7y,7w],7o:[F,F,3Q],7p:[0,F,0],7h:[F,0,F],7g:[1H,0,0],7f:[0,0,1H],7i:[1H,1H,0],7n:[F,48,0],7k:[F,2E,7l],7m:[1H,0,1H],7j:[F,0,0],7d:[2E,2E,2E],7r:[F,F,F],6K:[F,F,0]};4.f.1I=7(19,4c){d(4.f.2j[19])u{r:4.f.2j[19][0],g:4.f.2j[19][1],b:4.f.2j[19][2]};B d(O=/^22\\(\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*\\)$/.2L(19))u{r:H(O[1]),g:H(O[2]),b:H(O[3])};B d(O=/22\\(\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*\\)$/.2L(19))u{r:14(O[1])*2.55,g:14(O[2])*2.55,b:14(O[3])*2.55};B d(O=/^#([a-2b-28-9])([a-2b-28-9])([a-2b-28-9])$/.2L(19))u{r:H("1Q"+O[1]+O[1]),g:H("1Q"+O[2]+O[2]),b:H("1Q"+O[3]+O[3])};B d(O=/^#([a-2b-28-9]{2})([a-2b-28-9]{2})([a-2b-28-9]{2})$/.2L(19))u{r:H("1Q"+O[1]),g:H("1Q"+O[2]),b:H("1Q"+O[3])};B u 4c==2s?17:{r:F,g:F,b:F}};4.f.4j={3F:1,3i:1,3P:1,3b:1,6c:1,6b:1,1W:1,T:1,6L:1,6a:1,2k:1,2l:1,2q:1,2t:1,68:1,69:1,6d:1,6e:1,1c:1,6i:1,6h:1,3H:1,4d:1,3O:1,3G:1,2r:1,6g:1,12:1,1Y:1,2K:1};4.f.4y={5T:1,67:1,66:1,5Y:1,5X:1,19:1,5W:1};4.f.2g=[\'5U\',\'5V\',\'5Z\',\'60\'];4.f.3j={\'3e\':[\'2e\',\'4n\'],\'2J\':[\'2e\',\'39\'],\'2w\':[\'2w\',\'\'],\'2y\':[\'2y\',\'\']};4.2F.2P({65:7(1A,A,k,C){u q.Y(7(){6 2G=4.A(A,k,C);6 e=N 4.4k(q,2G,1A)})},37:7(A,C){u q.Y(7(){6 2G=4.A(A,C);6 e=N 4.37(q,2G)})},63:7(11){u q.2Q(7(){d(q.1s)4.3m(q,11)})},61:7(11){u q.2Q(7(){d(q.1s)4.3m(q,11);d(q.Y&&q.Y[\'f\'])q.Y.f=[]})}});4.2P({37:7(G,L){6 z=q,4l;z.11=7(){d(4.4z(L.1f))L.1f.2M(G)};z.1B=3B(7(){z.11()},L.10);G.1s=z},k:{4m:7(p,n,4A,4D,10){u((-1h.3a(p*1h.3f)/2)+0.5)*4D+4A}},4k:7(G,L,1A){6 z=q,4l;6 y=G.1k;6 4x=4.D(G,"2u");6 26=4.D(G,"P");6 I={};z.31=(N 2T()).2U();L.k=L.k&&4.k[L.k]?L.k:\'4m\';z.2N=7(M,X){d(4.f.4j[M]){d(X==\'1C\'||X==\'2i\'||X==\'4e\'){d(!G.1M)G.1M={};6 r=14(4.1E(G,M));G.1M[M]=r&&r>-4i?r:(14(4.D(G,M))||0);X=X==\'4e\'?(26==\'S\'?\'1C\':\'2i\'):X;L[X]=2s;I[M]=X==\'1C\'?[0,G.1M[M]]:[G.1M[M],0];d(M!=\'1c\')y[M]=I[M][0]+(M!=\'2K\'&&M!=\'3C\'?\'16\':\'\');B 4.1t(y,"1c",I[M][0])}B{I[M]=[14(4.1E(G,M)),14(X)||0]}}B d(4.f.4y[M])I[M]=[4.f.1I(4.1E(G,M)),4.f.1I(X)];B d(/^2w$|2y$|2e$|2J$|3e$/i.2p(M)){6 m=X.1K(/\\s+/g,\' \').1K(/22\\s*\\(\\s*/g,\'22(\').1K(/\\s*,\\s*/g,\',\').1K(/\\s*\\)/g,\')\').62(/([^\\s]+)/g);4B(M){1m\'2w\':1m\'2y\':1m\'3e\':1m\'2J\':m[3]=m[3]||m[1]||m[0];m[2]=m[2]||m[0];m[1]=m[1]||m[0];V(6 i=0;i<4.f.2g.1y;i++){6 1v=4.f.3j[M][0]+4.f.2g[i]+4.f.3j[M][1];I[1v]=M==\'2J\'?[4.f.1I(4.1E(G,1v)),4.f.1I(m[i])]:[14(4.1E(G,1v)),14(m[i])]}2d;1m\'2e\':V(6 i=0;i<m.1y;i++){6 3k=14(m[i]);6 2D=!6j(3k)?\'4n\':(!/6k|S|2a|6D|6C|6B|6z|6A|6E|6F|6J/i.2p(m[i])?\'39\':17);d(2D){V(6 j=0;j<4.f.2g.1y;j++){1v=\'2e\'+4.f.2g[j]+2D;I[1v]=2D==\'39\'?[4.f.1I(4.1E(G,1v)),4.f.1I(m[i])]:[14(4.1E(G,1v)),3k]}}B{y[\'6I\']=m[i]}}2d}}B{y[M]=X}u 17};V(p 1F 1A){d(p==\'1k\'){6 1o=4.3y(1A[p]);V(2c 1F 1o){q.2N(2c,1o[2c])}}B d(p==\'4w\'){d(J.2I)V(6 i=0;i<J.2I.1y;i++){6 1N=J.2I[i].1N||J.2I[i].6H||1l;d(1N){V(6 j=0;j<1N.1y;j++){d(1N[j].6G==\'.\'+1A[p]){6 1P=N 6y(\'\\.\'+1A[p]+\' {\');6 1w=1N[j].1k.6x;6 1o=4.3y(1w.1K(1P,\'\').1K(/}/g,\'\'));V(2c 1F 1o){q.2N(2c,1o[2c])}}}}}}B{q.2N(p,1A[p])}}y.P=26==\'S\'?\'1S\':26;y.2u=\'2a\';z.11=7(){6 t=(N 2T()).2U();d(t>L.10+z.31){3w(z.1B);z.1B=1l;V(p 1F I){d(p=="1c")4.1t(y,"1c",I[p][1]);B d(29 I[p][1]==\'36\')y[p]=\'22(\'+I[p][1].r+\',\'+I[p][1].g+\',\'+I[p][1].b+\')\';B y[p]=I[p][1]+(p!=\'2K\'&&p!=\'3C\'?\'16\':\'\')}d(L.2i||L.1C)V(6 p 1F G.1M)d(p=="1c")4.1t(y,p,G.1M[p]);B y[p]="";y.P=L.2i?\'S\':(26!=\'S\'?26:\'1S\');y.2u=4x;G.1s=1l;d(4.4z(L.1f))L.1f.2M(G)}B{6 n=t-q.31;6 2h=n/L.10;V(p 1F I){d(29 I[p][1]==\'36\'){y[p]=\'22(\'+H(4.k[L.k](2h,n,I[p][0].r,(I[p][1].r-I[p][0].r),L.10))+\',\'+H(4.k[L.k](2h,n,I[p][0].g,(I[p][1].g-I[p][0].g),L.10))+\',\'+H(4.k[L.k](2h,n,I[p][0].b,(I[p][1].b-I[p][0].b),L.10))+\')\'}B{6 38=4.k[L.k](2h,n,I[p][0],(I[p][1]-I[p][0]),L.10);d(p=="1c")4.1t(y,"1c",38);B y[p]=38+(p!=\'2K\'&&p!=\'3C\'?\'16\':\'\')}}}};z.1B=3B(7(){z.11()},13);G.1s=z},3m:7(G,11){d(11)G.1s.31-=6p;B{2z.3w(G.1s.1B);G.1s=1l;4.1O(G,"f")}}});4.3y=7(1w){6 1o={};d(29 1w==\'4s\'){1w=1w.3r().3x(\';\');V(6 i=0;i<1w.1y;i++){1P=1w[i].3x(\':\');d(1P.1y==2){1o[4.4v(1P[0].1K(/\\-(\\w)/g,7(m,c){u c.6n()}))]=4.4v(1P[1])}}}u 1o};4.2F.2P({6l:7(A,C,k){u q.Y(\'Z\',7(){N 4.f.1L(q,A,C,\'3z\',k)})},6m:7(A,C,k){u q.Y(\'Z\',7(){N 4.f.1L(q,A,C,\'2V\',k)})},6q:7(A,C,k){u q.Y(\'Z\',7(){N 4.f.1L(q,A,C,\'4q\',k)})},6r:7(A,C,k){u q.Y(\'Z\',7(){N 4.f.1L(q,A,C,\'T\',k)})},6w:7(A,C,k){u q.Y(\'Z\',7(){N 4.f.1L(q,A,C,\'2r\',k)})},6v:7(A,C,k){u q.Y(\'Z\',7(){N 4.f.1L(q,A,C,\'4h\',k)})}});4.f.1L=7(e,A,C,18,k){d(!4.2H(e)){4.1O(e,\'Z\');u 17}6 z=q;z.8=4(e);z.6u=4.1e.2Z(e);z.k=29 C==\'4s\'?C:k||1l;d(!e.2X)e.2X=z.8.D(\'P\');d(18==\'4q\'){18=z.8.D(\'P\')==\'S\'?\'2V\':\'3z\'}B d(18==\'4h\'){18=z.8.D(\'P\')==\'S\'?\'2r\':\'T\'}z.8.1C();z.A=A;z.C=29 C==\'7\'?C:1l;z.f=4.f.4g(e);z.18=18;z.1f=7(){d(z.C&&z.C.3L==3M){z.C.2M(z.8.1n(0))}d(z.18==\'2V\'||z.18==\'2r\'){z.8.D(\'P\',z.8.1n(0).2X==\'S\'?\'1S\':z.8.1n(0).2X)}B{z.8.2i()}4.f.4f(z.f.1z.1n(0),z.f.K);4.1O(z.8.1n(0),\'Z\')};4B(z.18){1m\'3z\':1p=N 4.f(z.f.1z.1n(0),4.A(z.A,z.k,z.1f),\'1W\');1p.23(z.f.K.1D.1b,0);2d;1m\'2V\':z.f.1z.D(\'1W\',\'45\');z.8.1C();1p=N 4.f(z.f.1z.1n(0),4.A(z.A,z.k,z.1f),\'1W\');1p.23(0,z.f.K.1D.1b);2d;1m\'T\':1p=N 4.f(z.f.1z.1n(0),4.A(z.A,z.k,z.1f),\'1Y\');1p.23(z.f.K.1D.1d,0);2d;1m\'2r\':z.f.1z.D(\'1Y\',\'45\');z.8.1C();1p=N 4.f(z.f.1z.1n(0),4.A(z.A,z.k,z.1f),\'1Y\');1p.23(0,z.f.K.1D.1d);2d}};4.2F.2P({2R:7(A,R,k){o=4.A(A);u q.Y(\'Z\',7(){N 4.f.2R(q,o,R,k)})},6s:7(A,R,k){u q.2Q(7(){4(\'a[@3R*="#"]\',q).6t(7(e){3W=q.3R.3x(\'#\');4(\'#\'+3W[1]).2R(A,R,k);u 17})})}});4.f.2R=7(e,o,R,k){6 z=q;z.o=o;z.e=e;z.R=/3K|3J/.2p(R)?R:17;z.k=k;p=4.1e.3Y(e);s=4.1e.3q();z.44=7(){3w(z.1B);z.1B=1l;4.1O(z.e,\'Z\')};z.t=(N 2T).2U();s.h=s.h>s.1q?(s.h-s.1q):s.h;s.w=s.w>s.1u?(s.w-s.1u):s.w;z.2W=p.y>s.h?s.h:p.y;z.2Y=p.x>s.w?s.w:p.x;z.1X=s.t;z.27=s.l;z.11=7(){6 t=(N 2T).2U();6 n=t-z.t;6 p=n/z.o.10;d(t>=z.o.10+z.t){z.44();6o(7(){z.3g(z.2W,z.2Y)},13)}B{d(!z.R||z.R==\'3K\'){d(!4.k||!4.k[z.k]){32=((-1h.3a(p*1h.3f)/2)+0.5)*(z.2W-z.1X)+z.1X}B{32=4.k[z.k](p,n,z.1X,(z.2W-z.1X),z.o.10)}}B{32=z.1X}d(!z.R||z.R==\'3J\'){d(!4.k||!4.k[z.k]){33=((-1h.3a(p*1h.3f)/2)+0.5)*(z.2Y-z.27)+z.27}B{33=4.k[z.k](p,n,z.27,(z.2Y-z.27),z.o.10)}}B{33=z.27}z.3g(32,33)}};z.3g=7(t,l){2z.64(l,t)};z.1B=3B(7(){z.11()},13)};4.2F.3o=7(A,1V,C){u q.Y(\'Z\',7(){d(!4.2H(q)){4.1O(q,\'Z\');u 17}6 f=N 4.f.3o(q,A,1V,C);f.3D()})};4.f.3o=7(8,A,1V,C){6 z=q;z.1V=1V;z.3u=1;z.8=8;z.A=A;z.C=C;4(z.8).1C();z.3D=7(){z.3u++;z.e=N 4.f(z.8,4.A(z.A,7(){z.40=N 4.f(z.8,4.A(z.A,7(){d(z.3u<=z.1V)z.3D();B{4.1O(z.8,\'Z\');d(z.C&&z.C.3L==3M){z.C.2M(z.8)}}}),\'1c\');z.40.23(0,1)}),\'1c\');z.e.23(1,0)}};',62,469,'||||jQuery||var|function|el|||||if||fx|||||easing||||||this||||return||||||speed|else|callback|css|es|255|elem|parseInt|props|document|oldStyle|options|tp|new|result|display|position|axis|none|left|wrs|for|body|vp|queue|interfaceFX|duration|step|top||parseFloat|documentElement|px|false|direction|color|nodeEl|hb|opacity|wb|iUtil|complete|margins|Math|visibility|clientScroll|style|null|case|get|newStyles|fxh|ih|cs|animationHandler|attr|iw|nmp|styles|old|length|wrapper|prop|timer|show|sizes|curCSS|in|scrollTop|128|parseColor|wr|replace|BlindDirection|orig|cssRules|dequeue|rule|0x|scrollLeft|block|de|toInteger|times|height|startTop|width|restoreStyle|0px|currentStyle|rgb|custom|139|oldVisibility|oldDisplay|startLeft|F0|typeof|hidden|fA|np|break|border|event|cssSides|pr|hide|namedColors|marginBottom|marginLeft|clientHeight|absolute|clientWidth|test|marginRight|right|true|marginTop|overflow|nodeName|margin|parentNode|padding|window|oldPosition|png|211|sideEnd|192|fn|opt|fxCheckTag|styleSheets|borderColor|zIndex|exec|apply|getValues|src|extend|each|ScrollTo|while|Date|getTime|down|endTop|ifxFirstDisplay|endLeft|getSize|self|startTime|st|sl|windowSize|browser|object|pause|pValue|Color|cos|borderTopWidth|relative|scrollHeight|borderWidth|PI|scroll|scrollWidth|borderLeftWidth|cssSidesEnd|floatVal|innerHeight|stopAnim|innerWidth|Pulsate|func|getScroll|toLowerCase|169|offsetWidth|cnt|offsetHeight|clearInterval|split|parseStyle|up|oldFloat|setInterval|fontWeight|pulse|traverseDOM|borderBottomWidth|paddingTop|paddingBottom|firstChild|horizontal|vertical|constructor|Function|getMargins|paddingRight|borderRightWidth|224|href|styleFloat|240|140|insertBefore|parts|opera|getPosition|tagName|ef|230||107|clear|1px|img||165|wid|144|245|notColor|paddingLeft|toggle|destroyWrapper|buildWrapper|togglehor|10000|cssProps|fxe|values|linear|Width|offsetTop|emptyGIF|togglever|images|string|offsetLeft|max|trim|className|oldOverflow|colorCssProps|isFunction|firstNum|switch|offsetParent|delta|indexOf|getClient|pageY|clientX|msie|cssFloat|pageX|brown|fxWrapper|id|fixPNG|darkgrey|darkcyan|blue|cyan|darkblue|getPointer|horizontally|azure|beige|getSizeLite|getPadding||appendChild|aqua|purgeEvents|nextSibling||getPositionLite|220|listStyle|vertically|centerEl|clientY|black|button|td|meta|optgroup|option|tr|prototype|AlphaImageLoader|Array|removeChild|frameset|frame|col|header|colgroup|script|tfoot|tbody|caption|thead|float|Microsoft|th|iframe|textarea|select|form|table|ol|dl|ul|filter|hr|DXImageTransform|random|w_|createElement|progid|input|br|getBorder|div|backgroundColor|Top|Right|outlineColor|borderTopColor|borderRightColor|Bottom|Left|stopAll|match|stop|scrollTo|animate|borderLeftColor|borderBottomColor|maxHeight|maxWidth|lineHeight|fontSize|bottom|minHeight|minWidth|darkgreen|textIndent|outlineWidth|outlineOffset|isNaN|transparent|BlindUp|BlindDown|toUpperCase|setTimeout|100000000|BlindToggleVertically|BlindLeft|ScrollToAnchors|click|size|BlindToggleHorizontally|BlindRight|cssText|RegExp|double|groove|solid|dashed|dotted|ridge|inset|selectorText|rules|borderStyle|outset|yellow|letterSpacing|darkviolet|148|122|150|233|fuchsia|gold|khaki|130|indigo|215|darksalmon|darkred|183|darkmagenta|189|darkkhaki|100|darkolivegreen||85|204|153|darkorchid|darkorange|lightblue|green|silver|173|navy|maroon|magenta|olive|red|pink|203|purple|orange|lightyellow|lime|lightgreen|white|lightcyan|216|238|lightpink|193|lightgrey|182'.split('|'),0,{}))

jQuery.noConflict()
/*
 * Version patched with http://logan.mediaisotope.com/patches/prototype_ajax_bug_setRequestHeaders.patch
 * for AJAX and toJSON functions to work properly.
 * <mcv>
 */

/*  Prototype JavaScript framework, version 1.5.2_pre0
 *  (c) 2005-2007 Sam Stephenson
 *
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the Prototype web site: http://www.prototypejs.org/
 *
/*--------------------------------------------------------------------------*/

var Prototype = {
  Version: '1.5.2_pre0',

  Browser: {
    IE:     !!(window.attachEvent && !window.opera),
    Opera:  !!window.opera,
    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
  },

  BrowserFeatures: {
    XPath: !!document.evaluate,
    ElementExtensions: !!window.HTMLElement,
    SpecificElementExtensions:
      (document.createElement('div').__proto__ !==
       document.createElement('form').__proto__)
  },

  ScriptFragment: '<script[^>]*>([\u0001-\uFFFF]*?)<\/script>',
  JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/,

  emptyFunction: function() { },
  K: function(x) { return x }
}

var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}

var Abstract = new Object();

Object.extend = function(destination, source) {
  for (var property in source) {
    destination[property] = source[property];
  }
  return destination;
}

Object.extend(Object, {
  inspect: function(object) {
    try {
      if (object === undefined) return 'undefined';
      if (object === null) return 'null';
      return object.inspect ? object.inspect() : object.toString();
    } catch (e) {
      if (e instanceof RangeError) return '...';
      throw e;
    }
  },

  toJSON: function(object) {
    var type = typeof object;
    switch(type) {
      case 'undefined':
      case 'function':
      case 'unknown': return;
      case 'boolean': return object.toString();
    }
    if (object === null) return 'null';
    if (object.toJSON) return object.toJSON();
    if (object.ownerDocument === document) return;
    var results = [];
    for (var property in object) {
      var value = Object.toJSON(object[property]);
      if (value !== undefined)
        results.push(property.toJSON() + ': ' + value);
    }
    return '{' + results.join(', ') + '}';
  },

  keys: function(object) {
    var keys = [];
    for (var property in object)
      keys.push(property);
    return keys;
  },

  values: function(object) {
    var values = [];
    for (var property in object)
      values.push(object[property]);
    return values;
  },

  clone: function(object) {
    return Object.extend({}, object);
  }
});

Object.extend(Function.prototype, {
  bind: function() {
    var __method = this, args = $A(arguments), object = args.shift();
    return function() {
      return __method.apply(object, args.concat($A(arguments)));
    }
  },

  bindAsEventListener: function() {
    var __method = this, args = $A(arguments), object = args.shift();
    return function(event) {
      return __method.apply(object, [event || window.event].concat(args));
    }
  },

  curry: function() {
    var __method = this, args = $A(arguments);
    return function() {
      return __method.apply(this, args.concat($A(arguments)));
    }
  },

  delay: function() {
    var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
    return window.setTimeout(function() {
      return __method.apply(__method, args);
    }, timeout);
  },

  wrap: function(wrapper) {
    var __method = this;
    return function() {
      return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
    }
  },

  methodize: function() {
    if (this._methodized) return this._methodized;
    var __method = this;
    return this._methodized = function() {
      return __method.apply(null, [this].concat($A(arguments)));
    };
  }
});

Function.prototype.defer = Function.prototype.delay.curry(0.01);

Object.extend(Number.prototype, {
  toColorPart: function() {
    return this.toPaddedString(2, 16);
  },

  succ: function() {
    return this + 1;
  },

  times: function(iterator) {
    $R(0, this, true).each(iterator);
    return this;
  },

  toPaddedString: function(length, radix) {
    var string = this.toString(radix || 10);
    return '0'.times(length - string.length) + string;
  },

  toJSON: function() {
    return isFinite(this) ? this.toString() : 'null';
  }
});

Date.prototype.toJSON = function() {
  return '"' + this.getFullYear() + '-' +
    (this.getMonth() + 1).toPaddedString(2) + '-' +
    this.getDate().toPaddedString(2) + 'T' +
    this.getHours().toPaddedString(2) + ':' +
    this.getMinutes().toPaddedString(2) + ':' +
    this.getSeconds().toPaddedString(2) + '"';
};

var Try = {
  these: function() {
    var returnValue;

    for (var i = 0, length = arguments.length; i < length; i++) {
      var lambda = arguments[i];
      try {
        returnValue = lambda();
        break;
      } catch (e) {}
    }

    return returnValue;
  }
}

/*--------------------------------------------------------------------------*/

var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

  registerCallback: function() {
    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  stop: function() {
    if (!this.timer) return;
    clearInterval(this.timer);
    this.timer = null;
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.callback(this);
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
}
Object.extend(String, {
  interpret: function(value) {
    return value == null ? '' : String(value);
  },
  specialChar: {
    '\b': '\\b',
    '\t': '\\t',
    '\n': '\\n',
    '\f': '\\f',
    '\r': '\\r',
    '\\': '\\\\'
  }
});

Object.extend(String.prototype, {
  gsub: function(pattern, replacement) {
    var result = '', source = this, match;
    replacement = arguments.callee.prepareReplacement(replacement);

    while (source.length > 0) {
      if (match = source.match(pattern)) {
        result += source.slice(0, match.index);
        result += String.interpret(replacement(match));
        source  = source.slice(match.index + match[0].length);
      } else {
        result += source, source = '';
      }
    }
    return result;
  },

  sub: function(pattern, replacement, count) {
    replacement = this.gsub.prepareReplacement(replacement);
    count = count === undefined ? 1 : count;

    return this.gsub(pattern, function(match) {
      if (--count < 0) return match[0];
      return replacement(match);
    });
  },

  scan: function(pattern, iterator) {
    this.gsub(pattern, iterator);
    return this;
  },

  truncate: function(length, truncation) {
    length = length || 30;
    truncation = truncation === undefined ? '...' : truncation;
    return this.length > length ?
      this.slice(0, length - truncation.length) + truncation : this;
  },

  strip: function() {
    return this.replace(/^\s+/, '').replace(/\s+$/, '');
  },

  stripTags: function() {
    return this.replace(/<\/?[^>]+>/gi, '');
  },

  stripScripts: function() {
    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
  },

  extractScripts: function() {
    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
    return (this.match(matchAll) || []).map(function(scriptTag) {
      return (scriptTag.match(matchOne) || ['', ''])[1];
    });
  },

  evalScripts: function() {
    return this.extractScripts().map(function(script) { return eval(script) });
  },

  escapeHTML: function() {
    var self = arguments.callee;
    self.text.data = this;
    return self.div.innerHTML;
  },

  unescapeHTML: function() {
    var div = new Element('div');
    div.innerHTML = this.stripTags();
    return div.childNodes[0] ? (div.childNodes.length > 1 ?
      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
      div.childNodes[0].nodeValue) : '';
  },

  toQueryParams: function(separator) {
    var match = this.strip().match(/([^?#]*)(#.*)?$/);
    if (!match) return {};

    return match[1].split(separator || '&').inject({}, function(hash, pair) {
      if ((pair = pair.split('='))[0]) {
        var key = decodeURIComponent(pair.shift());
        var value = pair.length > 1 ? pair.join('=') : pair[0];
        if (value != undefined) value = decodeURIComponent(value);

        if (key in hash) {
          if (hash[key].constructor != Array) hash[key] = [hash[key]];
          hash[key].push(value);
        }
        else hash[key] = value;
      }
      return hash;
    });
  },

  toArray: function() {
    return this.split('');
  },

  succ: function() {
    return this.slice(0, this.length - 1) +
      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
  },

  times: function(count) {
    var result = '';
    for (var i = 0; i < count; i++) result += this;
    return result;
  },

  camelize: function() {
    var parts = this.split('-'), len = parts.length;
    if (len == 1) return parts[0];

    var camelized = this.charAt(0) == '-'
      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
      : parts[0];

    for (var i = 1; i < len; i++)
      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

    return camelized;
  },

  capitalize: function() {
    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
  },

  underscore: function() {
    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
  },

  dasherize: function() {
    return this.gsub(/_/,'-');
  },

  inspect: function(useDoubleQuotes) {
    var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
      var character = String.specialChar[match[0]];
      return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
    });
    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
  },

  toJSON: function() {
    return this.inspect(true);
  },

  unfilterJSON: function(filter) {
    return this.sub(filter || Prototype.JSONFilter, '#{1}');
  },

  evalJSON: function(sanitize) {
    var json = this.unfilterJSON();
    try {
      if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json)))
        return eval('(' + json + ')');
    } catch (e) { }
    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
  },

  include: function(pattern) {
    return this.indexOf(pattern) > -1;
  },

  startsWith: function(pattern) {
    return this.indexOf(pattern) === 0;
  },

  endsWith: function(pattern) {
    var d = this.length - pattern.length;
    return d >= 0 && this.lastIndexOf(pattern) === d;
  },

  empty: function() {
    return this == '';
  },

  blank: function() {
    return /^\s*$/.test(this);
  }
});

if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
  escapeHTML: function() {
    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
  },
  unescapeHTML: function() {
    return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
  }
});

String.prototype.gsub.prepareReplacement = function(replacement) {
  if (typeof replacement == 'function') return replacement;
  var template = new Template(replacement);
  return function(match) { return template.evaluate(match) };
}

String.prototype.parseQuery = String.prototype.toQueryParams;

Object.extend(String.prototype.escapeHTML, {
  div:  document.createElement('div'),
  text: document.createTextNode('')
});

with (String.prototype.escapeHTML) div.appendChild(text);

var Template = Class.create();
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
Template.prototype = {
  initialize: function(template, pattern) {
    this.template = template.toString();
    this.pattern  = pattern || Template.Pattern;
  },

  evaluate: function(object) {
    return this.template.gsub(this.pattern, function(match) {
      var before = match[1];
      if (before == '\\') return match[2];
      return before + String.interpret(object[match[3]]);
    });
  }
}

var $break = {};

var Enumerable = {
  each: function(iterator) {
    var index = 0;
    try {
      this._each(function(value) {
        iterator(value, index++);
      });
    } catch (e) {
      if (e != $break) throw e;
    }
    return this;
  },

  eachSlice: function(number, iterator) {
    var index = -number, slices = [], array = this.toArray();
    while ((index += number) < array.length)
      slices.push(array.slice(index, index+number));
    return slices.map(iterator);
  },

  all: function(iterator) {
    var result = true;
    this.each(function(value, index) {
      result = result && !!(iterator || Prototype.K)(value, index);
      if (!result) throw $break;
    });
    return result;
  },

  any: function(iterator) {
    var result = false;
    this.each(function(value, index) {
      if (result = !!(iterator || Prototype.K)(value, index))
        throw $break;
    });
    return result;
  },

  collect: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      results.push((iterator || Prototype.K)(value, index));
    });
    return results;
  },

  detect: function(iterator) {
    var result;
    this.each(function(value, index) {
      if (iterator(value, index)) {
        result = value;
        throw $break;
      }
    });
    return result;
  },

  findAll: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (iterator(value, index))
        results.push(value);
    });
    return results;
  },

  grep: function(pattern, iterator) {
    var results = [];
    this.each(function(value, index) {
      var stringValue = value.toString();
      if (stringValue.match(pattern))
        results.push((iterator || Prototype.K)(value, index));
    })
    return results;
  },

  include: function(object) {
    var found = false;
    this.each(function(value) {
      if (value == object) {
        found = true;
        throw $break;
      }
    });
    return found;
  },

  inGroupsOf: function(number, fillWith) {
    fillWith = fillWith === undefined ? null : fillWith;
    return this.eachSlice(number, function(slice) {
      while(slice.length < number) slice.push(fillWith);
      return slice;
    });
  },

  inject: function(memo, iterator) {
    this.each(function(value, index) {
      memo = iterator(memo, value, index);
    });
    return memo;
  },

  invoke: function(method) {
    var args = $A(arguments).slice(1);
    return this.map(function(value) {
      return value[method].apply(value, args);
    });
  },

  max: function(iterator) {
    var result;
    this.each(function(value, index) {
      value = (iterator || Prototype.K)(value, index);
      if (result == undefined || value >= result)
        result = value;
    });
    return result;
  },

  min: function(iterator) {
    var result;
    this.each(function(value, index) {
      value = (iterator || Prototype.K)(value, index);
      if (result == undefined || value < result)
        result = value;
    });
    return result;
  },

  partition: function(iterator) {
    var trues = [], falses = [];
    this.each(function(value, index) {
      ((iterator || Prototype.K)(value, index) ?
        trues : falses).push(value);
    });
    return [trues, falses];
  },

  pluck: function(property) {
    var results = [];
    this.each(function(value, index) {
      results.push(value[property]);
    });
    return results;
  },

  reject: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (!iterator(value, index))
        results.push(value);
    });
    return results;
  },

  sortBy: function(iterator) {
    return this.map(function(value, index) {
      return {value: value, criteria: iterator(value, index)};
    }).sort(function(left, right) {
      var a = left.criteria, b = right.criteria;
      return a < b ? -1 : a > b ? 1 : 0;
    }).pluck('value');
  },

  toArray: function() {
    return this.map();
  },

  zip: function() {
    var iterator = Prototype.K, args = $A(arguments);
    if (typeof args.last() == 'function')
      iterator = args.pop();

    var collections = [this].concat(args).map($A);
    return this.map(function(value, index) {
      return iterator(collections.pluck(index));
    });
  },

  size: function() {
    return this.toArray().length;
  },

  inspect: function() {
    return '#<Enumerable:' + this.toArray().inspect() + '>';
  }
}

Object.extend(Enumerable, {
  map:     Enumerable.collect,
  find:    Enumerable.detect,
  select:  Enumerable.findAll,
  member:  Enumerable.include,
  entries: Enumerable.toArray
});
function $A(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}

if (Prototype.Browser.WebKit) {
  function $A(iterable) {
    if (!iterable) return [];
    if (!(typeof iterable == 'function' && iterable == '[object NodeList]') &&
      iterable.toArray) {
      return iterable.toArray();
    } else {
      var results = [];
      for (var i = 0, length = iterable.length; i < length; i++)
        results.push(iterable[i]);
      return results;
    }
  }
}

Array.from = $A;

Object.extend(Array.prototype, Enumerable);

if (!Array.prototype._reverse)
  Array.prototype._reverse = Array.prototype.reverse;

Object.extend(Array.prototype, {
  _each: function(iterator) {
    for (var i = 0, length = this.length; i < length; i++)
      iterator(this[i]);
  },

  clear: function() {
    this.length = 0;
    return this;
  },

  first: function() {
    return this[0];
  },

  last: function() {
    return this[this.length - 1];
  },

  compact: function() {
    return this.select(function(value) {
      return value != null;
    });
  },

  flatten: function() {
    return this.inject([], function(array, value) {
      return array.concat(value && value.constructor == Array ?
        value.flatten() : [value]);
    });
  },

  without: function() {
    var values = $A(arguments);
    return this.select(function(value) {
      return !values.include(value);
    });
  },

  indexOf: function(object) {
    for (var i = 0, length = this.length; i < length; i++)
      if (this[i] == object) return i;
    return -1;
  },

  reverse: function(inline) {
    return (inline !== false ? this : this.toArray())._reverse();
  },

  reduce: function() {
    return this.length > 1 ? this : this[0];
  },

  uniq: function(sorted) {
    return this.inject([], function(array, value, index) {
      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
        array.push(value);
      return array;
    });
  },

  clone: function() {
    return [].concat(this);
  },

  size: function() {
    return this.length;
  },

  inspect: function() {
    return '[' + this.map(Object.inspect).join(', ') + ']';
  },

  toJSON: function() {
    var results = [];
    this.each(function(object) {
      var value = Object.toJSON(object);
      if (value !== undefined) results.push(value);
    });
    return '[' + results.join(', ') + ']';
  }
});

Array.prototype.toArray = Array.prototype.clone;

function $w(string) {
  string = string.strip();
  return string ? string.split(/\s+/) : [];
}

if (Prototype.Browser.Opera){
  Array.prototype.concat = function() {
    var array = [];
    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
    for (var i = 0, length = arguments.length; i < length; i++) {
      if (arguments[i].constructor == Array) {
        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
          array.push(arguments[i][j]);
      } else {
        array.push(arguments[i]);
      }
    }
    return array;
  }
}
var Hash = function(object) {
  if (object instanceof Hash) this.merge(object);
  else Object.extend(this, object || {});
};

Object.extend(Hash, {
  toQueryString: function(obj) {
    var parts = [];
    parts.add = arguments.callee.addPair;

    this.prototype._each.call(obj, function(pair) {
      if (!pair.key) return;
      var value = pair.value;

      if (value && typeof value == 'object') {
        if (value.constructor == Array) value.each(function(value) {
          parts.add(pair.key, value);
        });
        return;
      }
      parts.add(pair.key, value);
    });

    return parts.join('&');
  },

  toJSON: function(object) {
    var results = [];
    this.prototype._each.call(object, function(pair) {
      var value = Object.toJSON(pair.value);
      if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value);
    });
    return '{' + results.join(', ') + '}';
  }
});

Hash.toQueryString.addPair = function(key, value, prefix) {
  key = encodeURIComponent(key);
  if (value === undefined) this.push(key);
  else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value)));
}

Object.extend(Hash.prototype, Enumerable);
Object.extend(Hash.prototype, {
  _each: function(iterator) {
    for (var key in this) {
      var value = this[key];
      if (value && value == Hash.prototype[key]) continue;

      var pair = [key, value];
      pair.key = key;
      pair.value = value;
      iterator(pair);
    }
  },

  keys: function() {
    return this.pluck('key');
  },

  values: function() {
    return this.pluck('value');
  },

  merge: function(hash) {
    return $H(hash).inject(this, function(mergedHash, pair) {
      mergedHash[pair.key] = pair.value;
      return mergedHash;
    });
  },

  remove: function() {
    var result;
    for(var i = 0, length = arguments.length; i < length; i++) {
      var value = this[arguments[i]];
      if (value !== undefined){
        if (result === undefined) result = value;
        else {
          if (result.constructor != Array) result = [result];
          result.push(value)
        }
      }
      delete this[arguments[i]];
    }
    return result;
  },

  toQueryString: function() {
    return Hash.toQueryString(this);
  },

  inspect: function() {
    return '#<Hash:{' + this.map(function(pair) {
      return pair.map(Object.inspect).join(': ');
    }).join(', ') + '}>';
  },

  toJSON: function() {
    return Hash.toJSON(this);
  }
});

function $H(object) {
  if (object instanceof Hash) return object;
  return new Hash(object);
};

// Safari iterates over shadowed properties
if (function() {
  var i = 0, Test = function(value) { this.key = value };
  Test.prototype.key = 'foo';
  for (var property in new Test('bar')) i++;
  return i > 1;
}()) Hash.prototype._each = function(iterator) {
  var cache = [];
  for (var key in this) {
    var value = this[key];
    if ((value && value == Hash.prototype[key]) || cache.include(key)) continue;
    cache.push(key);
    var pair = [key, value];
    pair.key = key;
    pair.value = value;
    iterator(pair);
  }
};
ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
  initialize: function(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  },

  _each: function(iterator) {
    var value = this.start;
    while (this.include(value)) {
      iterator(value);
      value = value.succ();
    }
  },

  include: function(value) {
    if (value < this.start)
      return false;
    if (this.exclusive)
      return value < this.end;
    return value <= this.end;
  }
});

var $R = function(start, end, exclusive) {
  return new ObjectRange(start, end, exclusive);
}

var Ajax = {
  getTransport: function() {
    return Try.these(
      function() {return new XMLHttpRequest()},
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
    ) || false;
  },

  activeRequestCount: 0
}

Ajax.Responders = {
  responders: [],

  _each: function(iterator) {
    this.responders._each(iterator);
  },

  register: function(responder) {
    if (!this.include(responder))
      this.responders.push(responder);
  },

  unregister: function(responder) {
    this.responders = this.responders.without(responder);
  },

  dispatch: function(callback, request, transport, json) {
    this.each(function(responder) {
      if (typeof responder[callback] == 'function') {
        try {
          responder[callback].apply(responder, [request, transport, json]);
        } catch (e) {}
      }
    });
  }
};

Object.extend(Ajax.Responders, Enumerable);

Ajax.Responders.register({
  onCreate: function() {
    Ajax.activeRequestCount++;
  },
  onComplete: function() {
    Ajax.activeRequestCount--;
  }
});

Ajax.Base = function() {};
Ajax.Base.prototype = {
  setOptions: function(options) {
    this.options = {
      method:       'post',
      asynchronous: true,
      contentType:  'application/x-www-form-urlencoded',
      encoding:     'UTF-8',
      parameters:   ''
    }
    Object.extend(this.options, options || {});

    this.options.method = this.options.method.toLowerCase();
    if (typeof this.options.parameters == 'string')
      this.options.parameters = this.options.parameters.toQueryParams();
  }
}

Ajax.Request = Class.create();
Ajax.Request.Events =
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];

Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
  _complete: false,

  initialize: function(url, options) {
    this.transport = Ajax.getTransport();
    this.setOptions(options);
    this.request(url);
  },

  request: function(url) {
    this.url = url;
    this.method = this.options.method;
    var params = Object.clone(this.options.parameters);

    if (!['get', 'post'].include(this.method)) {
      // simulate other verbs over post
      params['_method'] = this.method;
      this.method = 'post';
    }

    this.parameters = params;

    if (params = Hash.toQueryString(params)) {
      // when GET, append parameters to URL
      if (this.method == 'get')
        this.url += (this.url.include('?') ? '&' : '?') + params;
      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
        params += '&_=';
    }

    try {
      if (this.options.onCreate) this.options.onCreate(this.transport);
      Ajax.Responders.dispatch('onCreate', this, this.transport);

      this.transport.open(this.method.toUpperCase(), this.url,
        this.options.asynchronous);

      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);

      this.transport.onreadystatechange = this.onStateChange.bind(this);
      this.setRequestHeaders();

      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
      this.transport.send(this.body);

      /* Force Firefox to handle ready state 4 for synchronous requests */
      if (!this.options.asynchronous && this.transport.overrideMimeType)
        this.onStateChange();

    }
    catch (e) {
      this.dispatchException(e);
    }
  },

  onStateChange: function() {
    var readyState = this.transport.readyState;
    if (readyState > 1 && !((readyState == 4) && this._complete))
      this.respondToReadyState(this.transport.readyState);
  },

  setRequestHeaders: function() {
    var headers = {
      'X-Requested-With': 'XMLHttpRequest',
      'X-Prototype-Version': Prototype.Version,
      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
    };

    if (this.method == 'post') {
      headers['Content-type'] = this.options.contentType +
        (this.options.encoding ? '; charset=' + this.options.encoding : '');

      /* Force "Connection: close" for older Mozilla browsers to work
       * around a bug where XMLHttpRequest sends an incorrect
       * Content-length header. See Mozilla Bugzilla #246651.
       */
      if (this.transport.overrideMimeType &&
          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
            headers['Connection'] = 'close';
    }

    // user-defined headers
    if (typeof this.options.requestHeaders == 'object') {
      var extras = this.options.requestHeaders;

      if (typeof extras.push == 'function')
        for (var i = 0, length = extras.length; i < length; i += 2)
          headers[extras[i]] = extras[i+1];
      else
        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
    }

    for (var name in headers)
	  (typeof headers[name] != 'function') && this.transport.setRequestHeader(name, headers[name]);
  },

  success: function() {
    return !this.transport.status
        || (this.transport.status >= 200 && this.transport.status < 300);
  },

  respondToReadyState: function(readyState) {
    var state = Ajax.Request.Events[readyState];
    var transport = this.transport, json = this.evalJSON();

    if (state == 'Complete') {
      try {
        this._complete = true;
        (this.options['on' + this.transport.status]
         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
         || Prototype.emptyFunction)(transport, json);
      } catch (e) {
        this.dispatchException(e);
      }

      var contentType = this.getHeader('Content-type');
      if (contentType && contentType.strip().
        match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
          this.evalResponse();
    }

    try {
      (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
      Ajax.Responders.dispatch('on' + state, this, transport, json);
    } catch (e) {
      this.dispatchException(e);
    }

    if (state == 'Complete') {
      // avoid memory leak in MSIE: clean up
      this.transport.onreadystatechange = Prototype.emptyFunction;
    }
  },

  getHeader: function(name) {
    try {
      return this.transport.getResponseHeader(name);
    } catch (e) { return null }
  },

  evalJSON: function() {
    try {
      var json = this.getHeader('X-JSON');
      return json ? json.evalJSON() : null;
    } catch (e) { return null }
  },

  evalResponse: function() {
    try {
      return eval((this.transport.responseText || '').unfilterJSON());
    } catch (e) {
      this.dispatchException(e);
    }
  },

  dispatchException: function(exception) {
    (this.options.onException || Prototype.emptyFunction)(this, exception);
    Ajax.Responders.dispatch('onException', this, exception);
  }
});

Ajax.Updater = Class.create();

Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
  initialize: function(container, url, options) {
    this.container = {
      success: (container.success || container),
      failure: (container.failure || (container.success ? null : container))
    }

    this.transport = Ajax.getTransport();
    this.setOptions(options);

    var onComplete = this.options.onComplete || Prototype.emptyFunction;
    this.options.onComplete = (function(transport, param) {
      this.updateContent();
      onComplete(transport, param);
    }).bind(this);

    this.request(url);
  },

  updateContent: function() {
    var receiver = this.container[this.success() ? 'success' : 'failure'];
    var response = this.transport.responseText, options = this.options;

    if (!options.evalScripts) response = response.stripScripts();

    if (receiver = $(receiver)) {
      if (options.insertion) {
        if (typeof options.insertion == 'string')
          receiver.insert(response, options.insertion);
        else options.insertion(receiver, response);
      }
      else receiver.update(response);
    }

    if (this.success()) {
      if (this.onComplete) this.onComplete.bind(this).defer();
    }
  }
});

Ajax.PeriodicalUpdater = Class.create();
Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
  initialize: function(container, url, options) {
    this.setOptions(options);
    this.onComplete = this.options.onComplete;

    this.frequency = (this.options.frequency || 2);
    this.decay = (this.options.decay || 1);

    this.updater = {};
    this.container = container;
    this.url = url;

    this.start();
  },

  start: function() {
    this.options.onComplete = this.updateComplete.bind(this);
    this.onTimerEvent();
  },

  stop: function() {
    this.updater.options.onComplete = undefined;
    clearTimeout(this.timer);
    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
  },

  updateComplete: function(request) {
    if (this.options.decay) {
      this.decay = (request.responseText == this.lastText ?
        this.decay * this.options.decay : 1);

      this.lastText = request.responseText;
    }
    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
  },

  onTimerEvent: function() {
    this.updater = new Ajax.Updater(this.container, this.url, this.options);
  }
});
function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (typeof element == 'string')
    element = document.getElementById(element);
  return Element.extend(element);
}

if (Prototype.BrowserFeatures.XPath) {
  document._getElementsByXPath = function(expression, parentElement) {
    var results = [];
    var query = document.evaluate(expression, $(parentElement) || document,
      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    for (var i = 0, length = query.snapshotLength; i < length; i++)
      results.push(query.snapshotItem(i));
    return results;
  };

  document.getElementsByClassName = function(className, parentElement) {
    var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
    return document._getElementsByXPath(q, parentElement);
  }

} else document.getElementsByClassName = function(className, parentElement) {
  var children = ($(parentElement) || document.body).getElementsByTagName('*');
  var elements = [], child;
  for (var i = 0, length = children.length; i < length; i++) {
    child = children[i];
    if (Element.hasClassName(child, className))
      elements.push(Element.extend(child));
  }
  return elements;
};

/*--------------------------------------------------------------------------*/

(function() {
  var element = this.Element;
  this.Element = function(tagName, attributes) {
    attributes = attributes || {};
    tagName = tagName.toLowerCase();
    var cache = Element.cache;
    if (Prototype.Browser.IE && attributes.name) {
      tagName = '<' + tagName + ' name="' + attributes.name + '">';
      delete attributes.name;
      return Element.writeAttribute(document.createElement(tagName), attributes);
    }
    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
    return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
  };
  Object.extend(this.Element, element || {});
}).call(window);

Element.cache = {};

Element.Methods = {
  visible: function(element) {
    return $(element).style.display != 'none';
  },

  toggle: function(element) {
    element = $(element);
    Element[Element.visible(element) ? 'hide' : 'show'](element);
    return element;
  },

  hide: function(element) {
    $(element).style.display = 'none';
    return element;
  },

  show: function(element) {
    $(element).style.display = '';
    return element;
  },

  remove: function(element) {
    element = $(element);
    element.parentNode.removeChild(element);
    return element;
  },

  update: function(element, html) {
    html = typeof html == 'undefined' ? '' : html.toString();
    $(element).innerHTML = html.stripScripts();
    html.evalScripts.bind(html).defer();
    return element;
  },

  replace: function(element, html) {
    element = $(element);
    html = typeof html == 'undefined' ? '' : html.toString();
    if (element.outerHTML) {
      element.outerHTML = html.stripScripts();
    } else {
      var range = element.ownerDocument.createRange();
      range.selectNode(element);
      element.parentNode.replaceChild(
        range.createContextualFragment(html.stripScripts()), element);
    }
    html.evalScripts.bind(html).defer();
    return element;
  },

  insert: function(element, content, position) {
    element = $(element);
    position = (position || 'bottom').toLowerCase();
    var t = Element._insertionTranslations[position], range;

    if (content && content.ownerDocument === document) {
      t.insert(element, content);
      return element;
    }

    content = content.toString();

    range = element.ownerDocument.createRange();
    t.initializeRange(element, range);
    t.insert(element, range.createContextualFragment(content.stripScripts()));

    content.evalScripts.bind(content).defer();
    return element;
  },

  wrap: function(element, wrapper) {
    element = $(element);
    wrapper = wrapper || 'div';
    if (typeof wrapper == 'string') wrapper = new Element(wrapper);
    else Element.extend(wrapper);
    element.parentNode.replaceChild(wrapper, element);
    wrapper.appendChild(element);
    return element;
  },

  inspect: function(element) {
    element = $(element);
    var result = '<' + element.tagName.toLowerCase();
    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
      var property = pair.first(), attribute = pair.last();
      var value = (element[property] || '').toString();
      if (value) result += ' ' + attribute + '=' + value.inspect(true);
    });
    return result + '>';
  },

  recursivelyCollect: function(element, property) {
    element = $(element);
    var elements = [];
    while (element = element[property])
      if (element.nodeType == 1)
        elements.push(Element.extend(element));
    return elements;
  },

  ancestors: function(element) {
    return $(element).recursivelyCollect('parentNode');
  },

  descendants: function(element) {
    return $A($(element).getElementsByTagName('*')).each(Element.extend);
  },

  firstDescendant: function(element) {
    element = $(element).firstChild;
    while (element && element.nodeType != 1) element = element.nextSibling;
    return $(element);
  },

  immediateDescendants: function(element) {
    if (!(element = $(element).firstChild)) return [];
    while (element && element.nodeType != 1) element = element.nextSibling;
    if (element) return [element].concat($(element).nextSiblings());
    return [];
  },

  previousSiblings: function(element) {
    return $(element).recursivelyCollect('previousSibling');
  },

  nextSiblings: function(element) {
    return $(element).recursivelyCollect('nextSibling');
  },

  siblings: function(element) {
    element = $(element);
    return element.previousSiblings().reverse().concat(element.nextSiblings());
  },

  match: function(element, selector) {
    if (typeof selector == 'string')
      selector = new Selector(selector);
    return selector.match($(element));
  },

  up: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return $(element.parentNode);
    var ancestors = element.ancestors();
    return expression ? Selector.findElement(ancestors, expression, index) :
      ancestors[index || 0];
  },

  down: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return element.firstDescendant();
    var descendants = element.descendants();
    return expression ? Selector.findElement(descendants, expression, index) :
      descendants[index || 0];
  },

  previous: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
    var previousSiblings = element.previousSiblings();
    return expression ? Selector.findElement(previousSiblings, expression, index) :
      previousSiblings[index || 0];
  },

  next: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
    var nextSiblings = element.nextSiblings();
    return expression ? Selector.findElement(nextSiblings, expression, index) :
      nextSiblings[index || 0];
  },

  getElementsBySelector: function() {
    var args = $A(arguments), element = $(args.shift());
    return Selector.findChildElements(element, args);
  },

  getElementsByClassName: function(element, className) {
    return document.getElementsByClassName(className, element);
  },

  readAttribute: function(element, name) {
    element = $(element);
    if (Prototype.Browser.IE) {
      if (!element.attributes) return null;
      var t = Element._attributeTranslations.read;
      if (t.values[name]) return t.values[name](element, name);
      if (t.names[name])  name = t.names[name];
      var attribute = element.attributes[name];
      return attribute ? attribute.nodeValue : null;
    }
    return element.getAttribute(name);
  },

  writeAttribute: function(element, name, value) {
    element = $(element);
    var attributes = {}, t = Element._attributeTranslations.write;

    if (typeof name == 'object') attributes = name;
    else attributes[name] = value === undefined ? true : value;

    for (var attr in attributes) {
      var name = t.names[attr] || attr, value = attributes[attr];
      if (t.values[attr]) name = t.values[attr](element, value);
      if (value === false || value === null)
        element.removeAttribute(name);
      else if (value === true)
        element.setAttribute(name, name);
      else element.setAttribute(name, value);
    }
    return element;
  },

  getHeight: function(element) {
    return $(element).getDimensions().height;
  },

  getWidth: function(element) {
    return $(element).getDimensions().width;
  },

  classNames: function(element) {
    return new Element.ClassNames(element);
  },

  hasClassName: function(element, className) {
    if (!(element = $(element))) return;
    var elementClassName = element.className;
    if (elementClassName.length == 0) return false;
    if (elementClassName == className ||
        elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
      return true;
    return false;
  },

  addClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element).add(className);
    return element;
  },

  removeClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element).remove(className);
    return element;
  },

  toggleClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
    return element;
  },

  observe: function() {
    Event.observe.apply(Event, arguments);
    return $A(arguments).first();
  },

  stopObserving: function() {
    Event.stopObserving.apply(Event, arguments);
    return $A(arguments).first();
  },

  // removes whitespace-only text node children
  cleanWhitespace: function(element) {
    element = $(element);
    var node = element.firstChild;
    while (node) {
      var nextNode = node.nextSibling;
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
        element.removeChild(node);
      node = nextNode;
    }
    return element;
  },

  empty: function(element) {
    return $(element).innerHTML.blank();
  },

  descendantOf: function(element, ancestor) {
    element = $(element), ancestor = $(ancestor);
    while (element = element.parentNode)
      if (element == ancestor) return true;
    return false;
  },

  scrollTo: function(element) {
    element = $(element);
    var pos = Position.cumulativeOffset(element);
    window.scrollTo(pos[0], pos[1]);
    return element;
  },

  getStyle: function(element, style) {
    element = $(element);
    style = style == 'float' ? 'cssFloat' : style.camelize();
    var value = element.style[style];
    if (!value) {
      var css = document.defaultView.getComputedStyle(element, null);
      value = css ? css[style] : null;
    }
    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
    return value == 'auto' ? null : value;
  },

  getOpacity: function(element) {
    return $(element).getStyle('opacity');
  },

  setStyle: function(element, styles, camelized) {
    element = $(element);
    var elementStyle = element.style;

    for (var property in styles)
      if (property == 'opacity') element.setOpacity(styles[property])
      else
        elementStyle[(property == 'float' || property == 'cssFloat') ?
          (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
          (camelized ? property : property.camelize())] = styles[property];

    return element;
  },

  setOpacity: function(element, value) {
    element = $(element);
    element.style.opacity = (value == 1 || value === '') ? '' :
      (value < 0.00001) ? 0 : value;
    return element;
  },

  getDimensions: function(element) {
    element = $(element);
    var display = $(element).getStyle('display');
    if (display != 'none' && display != null) // Safari bug
      return {width: element.offsetWidth, height: element.offsetHeight};

    // All *Width and *Height properties give 0 on elements with display none,
    // so enable the element temporarily
    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    var originalDisplay = els.display;
    els.visibility = 'hidden';
    els.position = 'absolute';
    els.display = 'block';
    var originalWidth = element.clientWidth;
    var originalHeight = element.clientHeight;
    els.display = originalDisplay;
    els.position = originalPosition;
    els.visibility = originalVisibility;
    return {width: originalWidth, height: originalHeight};
  },

  makePositioned: function(element) {
    element = $(element);
    var pos = Element.getStyle(element, 'position');
    if (pos == 'static' || !pos) {
      element._madePositioned = true;
      element.style.position = 'relative';
      // Opera returns the offset relative to the positioning context, when an
      // element is position relative but top and left have not been defined
      if (window.opera) {
        element.style.top = 0;
        element.style.left = 0;
      }
    }
    return element;
  },

  undoPositioned: function(element) {
    element = $(element);
    if (element._madePositioned) {
      element._madePositioned = undefined;
      element.style.position =
        element.style.top =
        element.style.left =
        element.style.bottom =
        element.style.right = '';
    }
    return element;
  },

  makeClipping: function(element) {
    element = $(element);
    if (element._overflow) return element;
    element._overflow = element.style.overflow || 'auto';
    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
      element.style.overflow = 'hidden';
    return element;
  },

  undoClipping: function(element) {
    element = $(element);
    if (!element._overflow) return element;
    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
    element._overflow = null;
    return element;
  },

  cumulativeOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
    } while (element);
    return Element._returnOffset(valueL, valueT);
  },

  positionedOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
      if (element) {
        if (element.tagName == 'BODY') break;
        var p = Element.getStyle(element, 'position');
        if (p == 'relative' || p == 'absolute') break;
      }
    } while (element);
    return Element._returnOffset(valueL, valueT);
  },

  absolutize: function(element) {
    element = $(element);
    if (element.style.position == 'absolute') return;
    // Position.prepare(); // To be done manually by Scripty when it needs it.

    var offsets = element.positionedOffset();
    var top     = offsets[1];
    var left    = offsets[0];
    var width   = element.clientWidth;
    var height  = element.clientHeight;

    element._originalLeft   = left - parseFloat(element.style.left  || 0);
    element._originalTop    = top  - parseFloat(element.style.top || 0);
    element._originalWidth  = element.style.width;
    element._originalHeight = element.style.height;

    element.style.position = 'absolute';
    element.style.top    = top + 'px';
    element.style.left   = left + 'px';
    element.style.width  = width + 'px';
    element.style.height = height + 'px';
    return element;
  },

  relativize: function(element) {
    element = $(element);
    if (element.style.position == 'relative') return;
    // Position.prepare(); // To be done manually by Scripty when it needs it.

    element.style.position = 'relative';
    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);

    element.style.top    = top + 'px';
    element.style.left   = left + 'px';
    element.style.height = element._originalHeight;
    element.style.width  = element._originalWidth;
    return element;
  },

  cumulativeScrollOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.scrollTop  || 0;
      valueL += element.scrollLeft || 0;
      element = element.parentNode;
    } while (element);
    return Element._returnOffset(valueL, valueT);
  },

  getOffsetParent: function(element) {
    if (element.offsetParent) return $(element.offsetParent);
    if (element == document.body) return $(element);

    while ((element = element.parentNode) && element != document.body)
      if (Element.getStyle(element, 'position') != 'static')
        return $(element);

    return $(document.body);
  },

  viewportOffset: function(forElement) {
    var valueT = 0, valueL = 0;

    var element = forElement;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;

      // Safari fix
      if (element.offsetParent == document.body &&
        Element.getStyle(element, 'position') == 'absolute') break;

    } while (element = element.offsetParent);

    element = forElement;
    do {
      if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
        valueT -= element.scrollTop  || 0;
        valueL -= element.scrollLeft || 0;
      }
    } while (element = element.parentNode);

    return Element._returnOffset(valueL, valueT);
  },

  clonePosition: function(element, source) {
    var options = Object.extend({
      setLeft:    true,
      setTop:     true,
      setWidth:   true,
      setHeight:  true,
      offsetTop:  0,
      offsetLeft: 0
    }, arguments[2] || {});

    // find page position of source
    source = $(source);
    var p = source.viewportOffset();

    // find coordinate system to use
    element = $(element);
    var delta = [0, 0];
    var parent = null;
    // delta [0,0] will do fine with position: fixed elements,
    // position:absolute needs offsetParent deltas
    if (Element.getStyle(element, 'position') == 'absolute') {
      parent = element.getOffsetParent();
      delta = parent.viewportOffset();
    }

    // correct by body offsets (fixes Safari)
    if (parent == document.body) {
      delta[0] -= document.body.offsetLeft;
      delta[1] -= document.body.offsetTop;
    }

    // set position
    if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
    if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
    if (options.setWidth)  element.style.width = source.offsetWidth + 'px';
    if (options.setHeight) element.style.height = source.offsetHeight + 'px';
    return element;
  }
};

Object.extend(Element.Methods, {
  childElements: Element.Methods.immediateDescendants
});

Element._attributeTranslations = {
  write: {
    names: {
      className: 'class',
      htmlFor:   'for'
    },
    values: {}
  }
};


if (!document.createRange || Prototype.Browser.Opera) {
  Element.Methods.insert = function(element, content, position) {
    element = $(element);
    position = (position || 'bottom').toLowerCase();
    var t = Element._insertionTranslations, pos = t[position], tagName;

    if (content && content.ownerDocument === document) {
      pos.insert(element, content);
      return element;
    }

    content = content.toString();
    tagName = ((position == 'before' || position == 'after')
      ? element.parentNode : element).tagName.toUpperCase();

    if (t.tags[tagName]) {
      var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
      if (position == 'top' || position == 'after') fragments.reverse();
      fragments.each(pos.insert.curry(element));
    }
    else element.insertAdjacentHTML(pos.adjacency, content.stripScripts());

    content.evalScripts.bind(content).defer();
    return element;
  }
}

if (Prototype.Browser.Opera) {
  Element.Methods._getStyle = Element.Methods.getStyle;
  Element.Methods.getStyle = function(element, style) {
    switch(style) {
      case 'left':
      case 'top':
      case 'right':
      case 'bottom':
        if (Element._getStyle(element, 'position') == 'static') return null;
      default: return Element._getStyle(element, style);
    }
  };
  Element.Methods._readAttribute = Element.Methods.readAttribute;
  Element.Methods.readAttribute = function(element, attribute) {
    if (attribute == 'title') return element.title;
    return Element._readAttribute(element, attribute);
  };
}

else if (Prototype.Browser.IE) {
  Element.Methods.getStyle = function(element, style) {
    element = $(element);
    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
    var value = element.style[style];
    if (!value && element.currentStyle) value = element.currentStyle[style];

    if (style == 'opacity') {
      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
        if (value[1]) return parseFloat(value[1]) / 100;
      return 1.0;
    }

    if (value == 'auto') {
      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
        return element['offset' + style.capitalize()] + 'px';
      return null;
    }
    return value;
  };

  Element.Methods.setOpacity = function(element, value) {
    function stripAlpha(filter){
      return filter.replace(/alpha\([^\)]*\)/gi,'');
    }
    element = $(element);
    var filter = element.getStyle('filter'), style = element.style;
    if (value == 1 || value === '') {
      (filter = stripAlpha(filter)) ?
        style.filter = filter : style.removeAttribute('filter');
      return element;
    } else if (value < 0.00001) value = 0;
    style.filter = stripAlpha(filter) +
      'alpha(opacity=' + (value * 100) + ')';
    return element;
  };

  Element._attributeTranslations = {
    read: {
      names: {
        colspan:   "colSpan",
        rowspan:   "rowSpan",
        valign:    "vAlign",
        datetime:  "dateTime",
        accesskey: "accessKey",
        tabindex:  "tabIndex",
        enctype:   "encType",
        maxlength: "maxLength",
        readonly:  "readOnly",
        longdesc:  "longDesc"
      },
      values: {
        _getAttr: function(element, attribute) {
          return element.getAttribute(attribute, 2);
        },
        _flag: function(element, attribute) {
          return $(element).hasAttribute(attribute) ? attribute : null;
        },
        style: function(element) {
          return element.style.cssText.toLowerCase();
        },
        title: function(element) {
          var node = element.getAttributeNode('title');
          return node.specified ? node.nodeValue : null;
        }
      }
    }
  };

  Element._attributeTranslations.write = {
    names: Object.extend({
        'class': 'className',
        'for':   'htmlFor'
      }, Element._attributeTranslations.read.names),
    values: {
      checked: function(element, value) {
        element.checked = !!value;
      },

      style: function(element, value) {
        element.style.cssText = value ? value : '';
      }
    }
  };

  (function() {
    Object.extend(this, {
      href: this._getAttr,
      src:  this._getAttr,
      type: this._getAttr,
      disabled: this._flag,
      checked:  this._flag,
      readonly: this._flag,
      multiple: this._flag
    });
  }).call(Element._attributeTranslations.read.values);
}

else if (Prototype.Browser.Gecko) {
  Element.Methods.setOpacity = function(element, value) {
    element = $(element);
    element.style.opacity = (value == 1) ? 0.999999 :
      (value === '') ? '' : (value < 0.00001) ? 0 : value;
    return element;
  };
}

else if (Prototype.Browser.WebKit) {
  // Safari returns margins on body which is incorrect if the child is absolutely
  // positioned.  For performance reasons, redefine Position.cumulativeOffset for
  // KHTML/WebKit only.
  Element.Methods.cumulativeOffset = function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      if (element.offsetParent == document.body)
        if (Element.getStyle(element, 'position') == 'absolute') break;

      element = element.offsetParent;
    } while (element);

    return [valueL, valueT];
  }
}

if (Prototype.Browser.IE || Prototype.Browser.Opera) {
  // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
  Element.Methods.update = function(element, html) {
    element = $(element);
    html = typeof html == 'undefined' ? '' : html.toString();
    var tagName = element.tagName.toUpperCase();

    if (Element._insertionTranslations.tags[tagName]) {
      $A(element.childNodes).each(function(node) { element.removeChild(node) });
      Element._getContentFromAnonymousElement(tagName, html.stripScripts())
        .each(function(node) { element.appendChild(node) });
    }
    else element.innerHTML = html.stripScripts();

    html.evalScripts.bind(html).defer();
    return element;
  };
}

Element._returnOffset = function(l, t) {
  var result = [l, t];
  result.left = l;
  result.top = t;
  return result;
};

Element._getContentFromAnonymousElement = function(tagName, html) {
  var div = new Element('div'); t = Element._insertionTranslations.tags[tagName]
  div.innerHTML = t[0] + html + t[1];
  t[2].times(function() { div = div.firstChild });
  return $A(div.childNodes);
};

Element._insertionTranslations = {
  before: {
    adjacency: 'beforeBegin',
    insert: function(element, node) {
      element.parentNode.insertBefore(node, element);
    },
    initializeRange: function(element, range) {
      range.setStartBefore(element);
    }
  },
  top: {
    adjacency: 'afterBegin',
    insert: function(element, node) {
      element.insertBefore(node, element.firstChild);
    },
    initializeRange: function(element, range) {
      range.selectNodeContents(element);
      range.collapse(true);
    }
  },
  bottom: {
    adjacency: 'beforeEnd',
    insert: function(element, node) {
      element.appendChild(node);
    }
  },
  after: {
    adjacency: 'afterEnd',
    insert: function(element, node) {
      element.parentNode.insertBefore(node, element.nextSibling);
    },
    initializeRange: function(element, range) {
      range.setStartAfter(element);
    }
  },
  tags: {
    TABLE:  ['<table>',                '</table>',                   1],
    TBODY:  ['<table><tbody>',         '</tbody></table>',           2],
    TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],
    TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
    SELECT: ['<select>',               '</select>',                  1]
  }
};

(function() {
  this.bottom.initializeRange = this.top.initializeRange;
  Object.extend(this.tags, {
    THEAD: this.tags.TBODY,
    TFOOT: this.tags.TBODY,
    TH:    this.tags.TD
  });
}).call(Element._insertionTranslations);

Element.Methods.Simulated = {
  hasAttribute: function(element, attribute) {
    var t = Element._attributeTranslations.read, node;
    attribute = t.names[attribute] || attribute;
    node = $(element).getAttributeNode(attribute);
    return node && node.specified;
  }
};

Element.Methods.ByTag = {};

Object.extend(Element, Element.Methods);

Element.extend = (function() {
  if (Prototype.BrowserFeatures.SpecificElementExtensions)
    return Prototype.K;

  var Methods = {}, ByTag = Element.Methods.ByTag;

  var extend = Object.extend(function(element) {
    if (!element || element._extendedByPrototype ||
        element.nodeType != 1 || element == window) return element;

    var methods = Object.clone(Methods),
      tagName = element.tagName, property, value;

    // extend methods for specific tags
    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);

    for (property in methods) {
      value = methods[property];
      if (typeof value == 'function' && !(property in element))
        element[property] = value.methodize();
    }

    element._extendedByPrototype = Prototype.emptyFunction;
    return element;

  }, {
    refresh: function() {
      // extend methods for all tags (Safari doesn't need this)
      if (!Prototype.BrowserFeatures.ElementExtensions) {
        Object.extend(Methods, Element.Methods);
        Object.extend(Methods, Element.Methods.Simulated);
      }
    }
  });

  extend.refresh();
  return extend;
})();

if (!Prototype.BrowserFeatures.ElementExtensions &&
    document.createElement('div').__proto__) {
  window.HTMLElement = {};
  window.HTMLElement.prototype = document.createElement('div').__proto__;
  Prototype.BrowserFeatures.ElementExtensions = true;
}

Element.hasAttribute = function(element, attribute) {
  if (element.hasAttribute) return element.hasAttribute(attribute);
  return Element.Methods.Simulated.hasAttribute(element, attribute);
};

Element.addMethods = function(methods) {
  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;

  if (!methods) {
    Object.extend(Form, Form.Methods);
    Object.extend(Form.Element, Form.Element.Methods);
    Object.extend(Element.Methods.ByTag, {
      "FORM":     Object.clone(Form.Methods),
      "INPUT":    Object.clone(Form.Element.Methods),
      "SELECT":   Object.clone(Form.Element.Methods),
      "TEXTAREA": Object.clone(Form.Element.Methods)
    });
  }

  if (arguments.length == 2) {
    var tagName = methods;
    methods = arguments[1];
  }

  if (!tagName) Object.extend(Element.Methods, methods || {});
  else {
    if (tagName.constructor == Array) tagName.each(extend);
    else extend(tagName);
  }

  function extend(tagName) {
    tagName = tagName.toUpperCase();
    if (!Element.Methods.ByTag[tagName])
      Element.Methods.ByTag[tagName] = {};
    Object.extend(Element.Methods.ByTag[tagName], methods);
  }

  function copy(methods, destination, onlyIfAbsent) {
    onlyIfAbsent = onlyIfAbsent || false;
    for (var property in methods) {
      var value = methods[property];
      if (typeof value != 'function') continue;
      if (!onlyIfAbsent || !(property in destination))
        destination[property] = value.methodize();
    }
  }

  function findDOMClass(tagName) {
    var klass;
    var trans = {
      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
      "FrameSet", "IFRAME": "IFrame"
    };
    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
    if (window[klass]) return window[klass];
    klass = 'HTML' + tagName + 'Element';
    if (window[klass]) return window[klass];
    klass = 'HTML' + tagName.capitalize() + 'Element';
    if (window[klass]) return window[klass];

    window[klass] = {};
    window[klass].prototype = document.createElement(tagName).__proto__;
    return window[klass];
  }

  if (F.ElementExtensions) {
    copy(Element.Methods, HTMLElement.prototype);
    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
  }

  if (F.SpecificElementExtensions) {
    for (var tag in Element.Methods.ByTag) {
      var klass = findDOMClass(tag);
      if (typeof klass == "undefined") continue;
      copy(T[tag], klass.prototype);
    }
  }

  Object.extend(Element, Element.Methods);
  delete Element.ByTag;

  if (Element.extend.refresh) Element.extend.refresh();
  Element.cache = {};
};

/*--------------------------------------------------------------------------*/

Element.ClassNames = Class.create();
Element.ClassNames.prototype = {
  initialize: function(element) {
    this.element = $(element);
  },

  _each: function(iterator) {
    this.element.className.split(/\s+/).select(function(name) {
      return name.length > 0;
    })._each(iterator);
  },

  set: function(className) {
    this.element.className = className;
  },

  add: function(classNameToAdd) {
    if (this.include(classNameToAdd)) return;
    this.set($A(this).concat(classNameToAdd).join(' '));
  },

  remove: function(classNameToRemove) {
    if (!this.include(classNameToRemove)) return;
    this.set($A(this).without(classNameToRemove).join(' '));
  },

  toString: function() {
    return $A(this).join(' ');
  }
};

Object.extend(Element.ClassNames.prototype, Enumerable);
/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
 * license.  Please see http://www.yui-ext.com/ for more information. */

var Selector = Class.create();

Selector.prototype = {
  initialize: function(expression) {
    this.expression = expression.strip();
    this.compileMatcher();
  },

  compileMatcher: function() {
    // Selectors with namespaced attributes can't use the XPath version
    if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression))
      return this.compileXPathMatcher();

    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
        c = Selector.criteria, le, p, m;

    if (Selector._cache[e]) {
      this.matcher = Selector._cache[e]; return;
    }
    this.matcher = ["this.matcher = function(root) {",
                    "var r = root, h = Selector.handlers, c = false, n;"];

    while (e && le != e && (/\S/).test(e)) {
      le = e;
      for (var i in ps) {
        p = ps[i];
        if (m = e.match(p)) {
          this.matcher.push(typeof c[i] == 'function' ? c[i](m) :
    	      new Template(c[i]).evaluate(m));
          e = e.replace(m[0], '');
          break;
        }
      }
    }

    this.matcher.push("return h.unique(n);\n}");
    eval(this.matcher.join('\n'));
    Selector._cache[this.expression] = this.matcher;
  },

  compileXPathMatcher: function() {
    var e = this.expression, ps = Selector.patterns,
        x = Selector.xpath, le,  m;

    if (Selector._cache[e]) {
      this.xpath = Selector._cache[e]; return;
    }

    this.matcher = ['.//*'];
    while (e && le != e && (/\S/).test(e)) {
      le = e;
      for (var i in ps) {
        if (m = e.match(ps[i])) {
          this.matcher.push(typeof x[i] == 'function' ? x[i](m) :
            new Template(x[i]).evaluate(m));
          e = e.replace(m[0], '');
          break;
        }
      }
    }

    this.xpath = this.matcher.join('');
    Selector._cache[this.expression] = this.xpath;
  },

  findElements: function(root) {
    root = root || document;
    if (this.xpath) return document._getElementsByXPath(this.xpath, root);
    return this.matcher(root);
  },

  match: function(element) {
    return this.findElements(document).include(element);
  },

  toString: function() {
    return this.expression;
  },

  inspect: function() {
    return "#<Selector:" + this.expression.inspect() + ">";
  }
};

Object.extend(Selector, {
  _cache: {},

  xpath: {
    descendant:   "//*",
    child:        "/*",
    adjacent:     "/following-sibling::*[1]",
    laterSibling: '/following-sibling::*',
    tagName:      function(m) {
      if (m[1] == '*') return '';
      return "[local-name()='" + m[1].toLowerCase() +
             "' or local-name()='" + m[1].toUpperCase() + "']";
    },
    className:    "[contains(concat(' ', @class, ' '), ' #{1} ')]",
    id:           "[@id='#{1}']",
    attrPresence: "[@#{1}]",
    attr: function(m) {
      m[3] = m[5] || m[6];
      return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
    },
    pseudo: function(m) {
      var h = Selector.xpath.pseudos[m[1]];
      if (!h) return '';
      if (typeof h === 'function') return h(m);
      return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
    },
    operators: {
      '=':  "[@#{1}='#{3}']",
      '!=': "[@#{1}!='#{3}']",
      '^=': "[starts-with(@#{1}, '#{3}')]",
      '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
      '*=': "[contains(@#{1}, '#{3}')]",
      '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
      '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
    },
    pseudos: {
      'first-child': '[not(preceding-sibling::*)]',
      'last-child':  '[not(following-sibling::*)]',
      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]',
      'empty':       "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
      'checked':     "[@checked]",
      'disabled':    "[@disabled]",
      'enabled':     "[not(@disabled)]",
      'not': function(m) {
        var e = m[6], p = Selector.patterns,
            x = Selector.xpath, le, m, v;

        var exclusion = [];
        while (e && le != e && (/\S/).test(e)) {
          le = e;
          for (var i in p) {
            if (m = e.match(p[i])) {
              v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m);
              exclusion.push("(" + v.substring(1, v.length - 1) + ")");
              e = e.replace(m[0], '');
              break;
            }
          }
        }
        return "[not(" + exclusion.join(" and ") + ")]";
      },
      'nth-child':      function(m) {
        return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
      },
      'nth-last-child': function(m) {
        return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
      },
      'nth-of-type':    function(m) {
        return Selector.xpath.pseudos.nth("position() ", m);
      },
      'nth-last-of-type': function(m) {
        return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
      },
      'first-of-type':  function(m) {
        m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
      },
      'last-of-type':   function(m) {
        m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
      },
      'only-of-type':   function(m) {
        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
      },
      nth: function(fragment, m) {
        var mm, formula = m[6], predicate;
        if (formula == 'even') formula = '2n+0';
        if (formula == 'odd')  formula = '2n+1';
        if (mm = formula.match(/^(\d+)$/)) // digit only
          return '[' + fragment + "= " + mm[1] + ']';
        if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
          if (mm[1] == "-") mm[1] = -1;
          var a = mm[1] ? Number(mm[1]) : 1;
          var b = mm[2] ? Number(mm[2]) : 0;
          predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
          "((#{fragment} - #{b}) div #{a} >= 0)]";
          return new Template(predicate).evaluate({
            fragment: fragment, a: a, b: b });
        }
      }
    }
  },

  criteria: {
    tagName:      'n = h.tagName(n, r, "#{1}", c);   c = false;',
    className:    'n = h.className(n, r, "#{1}", c); c = false;',
    id:           'n = h.id(n, r, "#{1}", c);        c = false;',
    attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',
    attr: function(m) {
      m[3] = (m[5] || m[6]);
      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);
    },
    pseudo:       function(m) {
      if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
      return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
    },
    descendant:   'c = "descendant";',
    child:        'c = "child";',
    adjacent:     'c = "adjacent";',
    laterSibling: 'c = "laterSibling";'
  },

  patterns: {
    // combinators must be listed first
    // (and descendant needs to be last combinator)
    laterSibling: /^\s*~\s*/,
    child:        /^\s*>\s*/,
    adjacent:     /^\s*\+\s*/,
    descendant:   /^\s/,

    // selectors follow
    tagName:      /^\s*(\*|[\w\-]+)(\b|$)?/,
    id:           /^#([\w\-\*]+)(\b|$)/,
    className:    /^\.([\w\-\*]+)(\b|$)/,
    pseudo:       /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/,
    attrPresence: /^\[([\w]+)\]/,
    attr:         /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/
  },

  handlers: {
    // UTILITY FUNCTIONS
    // joins two collections
    concat: function(a, b) {
      for (var i = 0, node; node = b[i]; i++)
        a.push(node);
      return a;
    },

    // marks an array of nodes for counting
    mark: function(nodes) {
      for (var i = 0, node; node = nodes[i]; i++)
        node._counted = true;
      return nodes;
    },

    unmark: function(nodes) {
      for (var i = 0, node; node = nodes[i]; i++)
        node._counted = undefined;
      return nodes;
    },

    // mark each child node with its position (for nth calls)
    // "ofType" flag indicates whether we're indexing for nth-of-type
    // rather than nth-child
    index: function(parentNode, reverse, ofType) {
      parentNode._counted = true;
      if (reverse) {
        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
          node = nodes[i];
          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
        }
      } else {
        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
      }
    },

    // filters out duplicates and extends all nodes
    unique: function(nodes) {
      if (nodes.length == 0) return nodes;
      var results = [], n;
      for (var i = 0, l = nodes.length; i < l; i++)
        if (!(n = nodes[i])._counted) {
          n._counted = true;
          results.push(Element.extend(n));
        }
      return Selector.handlers.unmark(results);
    },

    // COMBINATOR FUNCTIONS
    descendant: function(nodes) {
      var h = Selector.handlers;
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        h.concat(results, node.getElementsByTagName('*'));
      return results;
    },

    child: function(nodes) {
      var h = Selector.handlers;
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        for (var j = 0, children = [], child; child = node.childNodes[j]; j++)
          if (child.nodeType == 1 && child.tagName != '!') results.push(child);
      }
      return results;
    },

    adjacent: function(nodes) {
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        var next = this.nextElementSibling(node);
        if (next) results.push(next);
      }
      return results;
    },

    laterSibling: function(nodes) {
      var h = Selector.handlers;
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        h.concat(results, Element.nextSiblings(node));
      return results;
    },

    nextElementSibling: function(node) {
      while (node = node.nextSibling)
	      if (node.nodeType == 1) return node;
      return null;
    },

    previousElementSibling: function(node) {
      while (node = node.previousSibling)
        if (node.nodeType == 1) return node;
      return null;
    },

    // TOKEN FUNCTIONS
    tagName: function(nodes, root, tagName, combinator) {
      tagName = tagName.toUpperCase();
      var results = [], h = Selector.handlers;
      if (nodes) {
        if (combinator) {
          // fastlane for ordinary descendant combinators
          if (combinator == "descendant") {
            for (var i = 0, node; node = nodes[i]; i++)
              h.concat(results, node.getElementsByTagName(tagName));
            return results;
          } else nodes = this[combinator](nodes);
          if (tagName == "*") return nodes;
        }
        for (var i = 0, node; node = nodes[i]; i++)
          if (node.tagName.toUpperCase() == tagName) results.push(node);
        return results;
      } else return root.getElementsByTagName(tagName);
    },

    id: function(nodes, root, id, combinator) {
      var targetNode = $(id), h = Selector.handlers;
      if (!targetNode) return [];
      if (!nodes && root == document) return [targetNode];
      if (nodes) {
        if (combinator) {
          if (combinator == 'child') {
            for (var i = 0, node; node = nodes[i]; i++)
              if (targetNode.parentNode == node) return [targetNode];
          } else if (combinator == 'descendant') {
            for (var i = 0, node; node = nodes[i]; i++)
              if (Element.descendantOf(targetNode, node)) return [targetNode];
          } else if (combinator == 'adjacent') {
            for (var i = 0, node; node = nodes[i]; i++)
              if (Selector.handlers.previousElementSibling(targetNode) == node)
                return [targetNode];
          } else nodes = h[combinator](nodes);
        }
        for (var i = 0, node; node = nodes[i]; i++)
          if (node == targetNode) return [targetNode];
        return [];
      }
      return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
    },

    className: function(nodes, root, className, combinator) {
      if (nodes && combinator) nodes = this[combinator](nodes);
      return Selector.handlers.byClassName(nodes, root, className);
    },

    byClassName: function(nodes, root, className) {
      if (!nodes) nodes = Selector.handlers.descendant([root]);
      var needle = ' ' + className + ' ';
      for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
        nodeClassName = node.className;
        if (nodeClassName.length == 0) continue;
        if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
          results.push(node);
      }
      return results;
    },

    attrPresence: function(nodes, root, attr) {
      var results = [];
      for (var i = 0, node; node = nodes[i]; i++)
        if (Element.hasAttribute(node, attr)) results.push(node);
      return results;
    },

    attr: function(nodes, root, attr, value, operator) {
      if (!nodes) nodes = root.getElementsByTagName("*");
      var handler = Selector.operators[operator], results = [];
      for (var i = 0, node; node = nodes[i]; i++) {
        var nodeValue = Element.readAttribute(node, attr);
        if (nodeValue === null) continue;
        if (handler(nodeValue, value)) results.push(node);
      }
      return results;
    },

    pseudo: function(nodes, name, value, root, combinator) {
      if (nodes && combinator) nodes = this[combinator](nodes);
      if (!nodes) nodes = root.getElementsByTagName("*");
      return Selector.pseudos[name](nodes, value, root);
    }
  },

  pseudos: {
    'first-child': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        if (Selector.handlers.previousElementSibling(node)) continue;
          results.push(node);
      }
      return results;
    },
    'last-child': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        if (Selector.handlers.nextElementSibling(node)) continue;
          results.push(node);
      }
      return results;
    },
    'only-child': function(nodes, value, root) {
      var h = Selector.handlers;
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
          results.push(node);
      return results;
    },
    'nth-child':        function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, formula, root);
    },
    'nth-last-child':   function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, formula, root, true);
    },
    'nth-of-type':      function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, formula, root, false, true);
    },
    'nth-last-of-type': function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, formula, root, true, true);
    },
    'first-of-type':    function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, "1", root, false, true);
    },
    'last-of-type':     function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, "1", root, true, true);
    },
    'only-of-type':     function(nodes, formula, root) {
      var p = Selector.pseudos;
      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
    },

    // handles the an+b logic
    getIndices: function(a, b, total) {
      if (a == 0) return b > 0 ? [b] : [];
      return $R(1, total).inject([], function(memo, i) {
        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
        return memo;
      });
    },

    // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
    nth: function(nodes, formula, root, reverse, ofType) {
      if (nodes.length == 0) return [];
      if (formula == 'even') formula = '2n+0';
      if (formula == 'odd')  formula = '2n+1';
      var h = Selector.handlers, results = [], indexed = [], m;
      h.mark(nodes);
      for (var i = 0, node; node = nodes[i]; i++) {
        if (!node.parentNode._counted) {
          h.index(node.parentNode, reverse, ofType);
          indexed.push(node.parentNode);
        }
      }
      if (formula.match(/^\d+$/)) { // just a number
        formula = Number(formula);
        for (var i = 0, node; node = nodes[i]; i++)
          if (node.nodeIndex == formula) results.push(node);
      } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
        if (m[1] == "-") m[1] = -1;
        var a = m[1] ? Number(m[1]) : 1;
        var b = m[2] ? Number(m[2]) : 0;
        var indices = Selector.pseudos.getIndices(a, b, nodes.length);
        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
          for (var j = 0; j < l; j++)
            if (node.nodeIndex == indices[j]) results.push(node);
        }
      }
      h.unmark(nodes);
      h.unmark(indexed);
      return results;
    },

    'empty': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        // IE treats comments as element nodes
        if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
        results.push(node);
      }
      return results;
    },

    'not': function(nodes, selector, root) {
      var h = Selector.handlers, selectorType, m;
      var exclusions = new Selector(selector).findElements(root);
      h.mark(exclusions);
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (!node._counted) results.push(node);
      h.unmark(exclusions);
      return results;
    },

    'enabled': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (!node.disabled) results.push(node);
      return results;
    },

    'disabled': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (node.disabled) results.push(node);
      return results;
    },

    'checked': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (node.checked) results.push(node);
      return results;
    }
  },

  operators: {
    '=':  function(nv, v) { return nv == v; },
    '!=': function(nv, v) { return nv != v; },
    '^=': function(nv, v) { return nv.startsWith(v); },
    '$=': function(nv, v) { return nv.endsWith(v); },
    '*=': function(nv, v) { return nv.include(v); },
    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
    '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
  },

  matchElements: function(elements, expression) {
    var matches = new Selector(expression).findElements(), h = Selector.handlers;
    h.mark(matches);
    for (var i = 0, results = [], element; element = elements[i]; i++)
      if (element._counted) results.push(element);
    h.unmark(matches);
    return results;
  },

  findElement: function(elements, expression, index) {
    if (typeof expression == 'number') {
      index = expression; expression = false;
    }
    return Selector.matchElements(elements, expression || '*')[index || 0];
  },

  findChildElements: function(element, expressions) {
    var exprs = expressions.join(','), expressions = [];
    exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
      expressions.push(m[1].strip());
    });
    var results = [], h = Selector.handlers;
    for (var i = 0, l = expressions.length, selector; i < l; i++) {
      selector = new Selector(expressions[i].strip());
      h.concat(results, selector.findElements(element));
    }
    return (l > 1) ? h.unique(results) : results;
  }
});

function $$() {
  return Selector.findChildElements(document, $A(arguments));
}
var Form = {
  reset: function(form) {
    $(form).reset();
    return form;
  },

  serializeElements: function(elements, getHash) {
    var data = elements.inject({}, function(result, element) {
      if (!element.disabled && element.name) {
        var key = element.name, value = $(element).getValue();
        if (value != null) {
         	if (key in result) {
            if (result[key].constructor != Array) result[key] = [result[key]];
            result[key].push(value);
          }
          else result[key] = value;
        }
      }
      return result;
    });

    return getHash ? data : Hash.toQueryString(data);
  }
};

Form.Methods = {
  serialize: function(form, getHash) {
    return Form.serializeElements(Form.getElements(form), getHash);
  },

  getElements: function(form) {
    return $A($(form).getElementsByTagName('*')).inject([],
      function(elements, child) {
        if (Form.Element.Serializers[child.tagName.toLowerCase()])
          elements.push(Element.extend(child));
        return elements;
      }
    );
  },

  getInputs: function(form, typeName, name) {
    form = $(form);
    var inputs = form.getElementsByTagName('input');

    if (!typeName && !name) return $A(inputs).map(Element.extend);

    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
      var input = inputs[i];
      if ((typeName && input.type != typeName) || (name && input.name != name))
        continue;
      matchingInputs.push(Element.extend(input));
    }

    return matchingInputs;
  },

  disable: function(form) {
    form = $(form);
    Form.getElements(form).invoke('disable');
    return form;
  },

  enable: function(form) {
    form = $(form);
    Form.getElements(form).invoke('enable');
    return form;
  },

  findFirstElement: function(form) {
    return $(form).getElements().find(function(element) {
      return element.type != 'hidden' && !element.disabled &&
        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
    });
  },

  focusFirstElement: function(form) {
    form = $(form);
    form.findFirstElement().activate();
    return form;
  },

  request: function(form, options) {
    form = $(form), options = Object.clone(options || {});

    var params = options.parameters;
    options.parameters = form.serialize(true);

    if (params) {
      if (typeof params == 'string') params = params.toQueryParams();
      Object.extend(options.parameters, params);
    }

    if (form.hasAttribute('method') && !options.method)
      options.method = form.method;

    return new Ajax.Request(form.readAttribute('action'), options);
  }
}

/*--------------------------------------------------------------------------*/

Form.Element = {
  focus: function(element) {
    $(element).focus();
    return element;
  },

  select: function(element) {
    $(element).select();
    return element;
  }
}

Form.Element.Methods = {
  serialize: function(element) {
    element = $(element);
    if (!element.disabled && element.name) {
      var value = element.getValue();
      if (value != undefined) {
        var pair = {};
        pair[element.name] = value;
        return Hash.toQueryString(pair);
      }
    }
    return '';
  },

  getValue: function(element) {
    element = $(element);
    var method = element.tagName.toLowerCase();
    return Form.Element.Serializers[method](element);
  },

  clear: function(element) {
    $(element).value = '';
    return element;
  },

  present: function(element) {
    return $(element).value != '';
  },

  activate: function(element) {
    element = $(element);
    try {
      element.focus();
      if (element.select && (element.tagName.toLowerCase() != 'input' ||
        !['button', 'reset', 'submit'].include(element.type)))
        element.select();
    } catch (e) {}
    return element;
  },

  disable: function(element) {
    element = $(element);
    element.blur();
    element.disabled = true;
    return element;
  },

  enable: function(element) {
    element = $(element);
    element.disabled = false;
    return element;
  }
}

/*--------------------------------------------------------------------------*/

var Field = Form.Element;
var $F = Form.Element.Methods.getValue;

/*--------------------------------------------------------------------------*/

Form.Element.Serializers = {
  input: function(element) {
    switch (element.type.toLowerCase()) {
      case 'checkbox':
      case 'radio':
        return Form.Element.Serializers.inputSelector(element);
      default:
        return Form.Element.Serializers.textarea(element);
    }
  },

  inputSelector: function(element) {
    return element.checked ? element.value : null;
  },

  textarea: function(element) {
    return element.value;
  },

  select: function(element) {
    return this[element.type == 'select-one' ?
      'selectOne' : 'selectMany'](element);
  },

  selectOne: function(element) {
    var index = element.selectedIndex;
    return index >= 0 ? this.optionValue(element.options[index]) : null;
  },

  selectMany: function(element) {
    var values, length = element.length;
    if (!length) return null;

    for (var i = 0, values = []; i < length; i++) {
      var opt = element.options[i];
      if (opt.selected) values.push(this.optionValue(opt));
    }
    return values;
  },

  optionValue: function(opt) {
    // extend element because hasAttribute may not be native
    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
  }
}

/*--------------------------------------------------------------------------*/

Abstract.TimedObserver = function() {}
Abstract.TimedObserver.prototype = {
  initialize: function(element, frequency, callback) {
    this.frequency = frequency;
    this.element   = $(element);
    this.callback  = callback;

    this.lastValue = this.getValue();
    this.registerCallback();
  },

  registerCallback: function() {
    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  onTimerEvent: function() {
    var value = this.getValue();
    var changed = ('string' == typeof this.lastValue && 'string' == typeof value
      ? this.lastValue != value : String(this.lastValue) != String(value));
    if (changed) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  }
}

Form.Element.Observer = Class.create();
Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.Observer = Class.create();
Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  getValue: function() {
    return Form.serialize(this.element);
  }
});

/*--------------------------------------------------------------------------*/

Abstract.EventObserver = function() {}
Abstract.EventObserver.prototype = {
  initialize: function(element, callback) {
    this.element  = $(element);
    this.callback = callback;

    this.lastValue = this.getValue();
    if (this.element.tagName.toLowerCase() == 'form')
      this.registerFormCallbacks();
    else
      this.registerCallback(this.element);
  },

  onElementEvent: function() {
    var value = this.getValue();
    if (this.lastValue != value) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  },

  registerFormCallbacks: function() {
    Form.getElements(this.element).each(this.registerCallback.bind(this));
  },

  registerCallback: function(element) {
    if (element.type) {
      switch (element.type.toLowerCase()) {
        case 'checkbox':
        case 'radio':
          Event.observe(element, 'click', this.onElementEvent.bind(this));
          break;
        default:
          Event.observe(element, 'change', this.onElementEvent.bind(this));
          break;
      }
    }
  }
}

Form.Element.EventObserver = Class.create();
Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.EventObserver = Class.create();
Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  getValue: function() {
    return Form.serialize(this.element);
  }
});
if (!window.Event) {
  var Event = new Object();
}

Object.extend(Event, {
  KEY_BACKSPACE: 8,
  KEY_TAB:       9,
  KEY_RETURN:   13,
  KEY_ESC:      27,
  KEY_LEFT:     37,
  KEY_UP:       38,
  KEY_RIGHT:    39,
  KEY_DOWN:     40,
  KEY_DELETE:   46,
  KEY_HOME:     36,
  KEY_END:      35,
  KEY_PAGEUP:   33,
  KEY_PAGEDOWN: 34,

  element: function(event) {
    return $(event.target || event.srcElement);
  },

  isLeftClick: function(event) {
    return (((event.which) && (event.which == 1)) ||
            ((event.button) && (event.button == 1)));
  },

  pointerX: function(event) {
    return event.pageX || (event.clientX +
      (document.documentElement.scrollLeft || document.body.scrollLeft));
  },

  pointerY: function(event) {
    return event.pageY || (event.clientY +
      (document.documentElement.scrollTop || document.body.scrollTop));
  },

  stop: function(event) {
    if (event.preventDefault) {
      event.preventDefault();
      event.stopPropagation();
    } else {
      event.returnValue = false;
      event.cancelBubble = true;
    }
  },

  findElement: function(event, expression) {
    var element = Event.element(event);
    return element.match(expression) ? element : element.up(expression);
  },

  observers: false,

  _observeAndCache: function(element, name, observer, useCapture) {
    if (!this.observers) this.observers = [];
    if (element.addEventListener) {
      this.observers.push([element, name, observer, useCapture]);
      element.addEventListener(name, observer, useCapture);
    } else if (element.attachEvent) {
      this.observers.push([element, name, observer, useCapture]);
      element.attachEvent('on' + name, observer);
    }
  },

  unloadCache: function() {
    if (!Event.observers) return;
    for (var i = 0, length = Event.observers.length; i < length; i++) {
      Event.stopObserving.apply(this, Event.observers[i]);
      Event.observers[i][0] = null;
    }
    Event.observers = false;
  },

  observe: function(element, name, observer, useCapture) {
    element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
      (Prototype.Browser.WebKit || element.attachEvent))
      name = 'keydown';

    Event._observeAndCache(element, name, observer, useCapture);
  },

  stopObserving: function(element, name, observer, useCapture) {
    element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (Prototype.Browser.WebKit || element.attachEvent))
      name = 'keydown';

    if (element.removeEventListener) {
      element.removeEventListener(name, observer, useCapture);
    } else if (element.detachEvent) {
      try {
        element.detachEvent('on' + name, observer);
      } catch (e) {}
    }
  }
});

/* prevent memory leaks in IE */
if (Prototype.Browser.IE)
  Event.observe(window, 'unload', Event.unloadCache, false);
/*------------------------------- DEPRECATED -------------------------------*/

var Toggle = { display: Element.toggle };

Element.Methods.childOf = Element.Methods.descendantOf;

var Insertion = {
  Before: function(element, content) {
    return Element.insert(element, content, 'before');
  },

  Top: function(element, content) {
    return Element.insert(element, content, 'top');
  },

  Bottom: function(element, content) {
    return Element.insert(element, content, 'bottom');
  },

  After: function(element, content) {
    return Element.insert(element, content, 'after');
  }
}

var $continue = new Error('"throw $continue" is deprecated, use "return" instead');

// This should be moved to script.aculo.us; notice the deprecated methods
// further below, that map to the newer Element methods.
var Position = {
  // set to true if needed, warning: firefox performance problems
  // NOT neeeded for page scrolling, only if draggable contained in
  // scrollable elements
  includeScrollOffsets: false,

  // must be called before calling withinIncludingScrolloffset, every time the
  // page is scrolled
  prepare: function() {
    this.deltaX =  window.pageXOffset
                || document.documentElement.scrollLeft
                || document.body.scrollLeft
                || 0;
    this.deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
  },

  // caches x/y coordinate pair to use with overlap
  within: function(element, x, y) {
    if (this.includeScrollOffsets)
      return this.withinIncludingScrolloffsets(element, x, y);
    this.xcomp = x;
    this.ycomp = y;
    this.offset = Element.cumulativeOffset(element);

    return (y >= this.offset[1] &&
            y <  this.offset[1] + element.offsetHeight &&
            x >= this.offset[0] &&
            x <  this.offset[0] + element.offsetWidth);
  },

  withinIncludingScrolloffsets: function(element, x, y) {
    var offsetcache = Element.cumulativeScrollOffset(element);

    this.xcomp = x + offsetcache[0] - this.deltaX;
    this.ycomp = y + offsetcache[1] - this.deltaY;
    this.offset = Element.cumulativeOffset(element);

    return (this.ycomp >= this.offset[1] &&
            this.ycomp <  this.offset[1] + element.offsetHeight &&
            this.xcomp >= this.offset[0] &&
            this.xcomp <  this.offset[0] + element.offsetWidth);
  },

  // within must be called directly before
  overlap: function(mode, element) {
    if (!mode) return 0;
    if (mode == 'vertical')
      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
        element.offsetHeight;
    if (mode == 'horizontal')
      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
        element.offsetWidth;
  },

  // Deprecation layer -- use newer Element methods now (1.5.2).

  cumulativeOffset: Element.Methods.cumulativeOffset,

  positionedOffset: Element.Methods.positionedOffset,

  absolutize: function(element) {
    Position.prepare();
    return Element.absolutize(element);
  },

  relativize: function(element) {
    Position.prepare();
    return Element.relativize(element);
  },

  realOffset: Element.Methods.cumulativeScrollOffset,

  offsetParent: Element.Methods.getOffsetParent,

  page: Element.Methods.viewportOffset,

  clone: function(source, target, options) {
    options = options || {};
    return Element.clonePosition(target, source, options);
  }
}
/*--------------------------------------------------------------------------*/

Element.addMethods();
function add_click_confirmations()
{
	var els = document.getElementsByTagName ('*');
	for (var i in els)
	{
		if (!els[i].getAttribute)
			continue;
		var v = els[i].getAttribute ('confirm')
		if ((v != '') && (v != null))
		{
			els[i].onclick = function (event) {
				return confirm (this.getAttribute ('confirm'));
			}
		}
	}
}

jQuery (add_click_confirmations)

