

/*--------------------------------------------------------------------------
 /ext/jquery/_firebugx.js
--------------------------------------------------------------------------*/
if (!("console" in window) || !("firebug" in console))
{
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
    "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];

    window.console = {};
    for (var i = 0; i < names.length; ++i)
        window.console[names[i]] = function() {}
};

/*--------------------------------------------------------------------------
 /ext/jquery/_jquery-1.1.4.js
--------------------------------------------------------------------------*/
/*
 * jQuery 1.1.4 - 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-08-23 21:49:27 -0400 (Thu, 23 Aug 2007) $
 * $Rev: 2862 $
 */
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}('(9(){6(1f C!="Q")E v=C;E C=19.16=9(a,c){6(19==7||!7.4a)F 1s C(a,c);F 7.4a(a,c)};6(1f $!="Q")E B=$;19.$=C;E q=/^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$/;C.15=C.3v={4a:9(a,c){a=a||R;6(1f a=="1E"){E m=q.2d(a);6(m&&(m[1]||!c)){6(m[1])a=C.3c([m[1]]);G{E b=R.37(m[3]);6(b)6(b.2j!=m[3])F C().1F(a);G{7[0]=b;7.H=1;F 7}G a=[]}}G F 1s C(c).1F(a)}G 6(C.1g(a))F 1s C(R)[C.15.1L?"1L":"2f"](a);F 7.5J(a.1b==1K&&a||(a.3w||a.H&&a!=19&&!a.1t&&a[0]!=Q&&a[0].1t)&&C.2V(a)||[a])},3w:"1.1.4",7K:9(){F 7.H},H:0,21:9(a){F a==Q?C.2V(7):7[a]},1O:9(a){E b=C(a);b.5c=7;F b},5J:9(a){7.H=0;1K.3v.Y.T(7,a);F 7},J:9(a,b){F C.J(7,a,b)},45:9(a){E b=-1;7.J(9(i){6(7==a)b=i});F b},1j:9(f,d,e){E c=f;6(f.1b==3n)6(d==Q)F 7.H&&C[e||"1j"](7[0],f)||Q;G{c={};c[f]=d}F 7.J(9(a){I(E b 17 c)C.1j(e?7.S:7,b,C.4Q(7,c[b],e,a,b))})},1h:9(b,a){F 7.1j(b,a,"34")},2Q:9(e){6(1f e!="4P"&&e!=K)F 7.3K().3H(R.60(e));E t="";C.J(e||7,9(){C.J(7.2Z,9(){6(7.1t!=8)t+=7.1t!=1?7.5S:C.15.2Q([7])})});F t},82:9(){E a,2e=1a;F 7.J(9(){6(!a)a=C.3c(2e,7.2I);E b=a[0].3B(O);7.P.2p(b,7);20(b.1k)b=b.1k;b.4p(7)})},3H:9(){F 7.2J(1a,O,1,9(a){7.4p(a)})},5v:9(){F 7.2J(1a,O,-1,9(a){7.2p(a,7.1k)})},5u:9(){F 7.2J(1a,M,1,9(a){7.P.2p(a,7)})},5t:9(){F 7.2J(1a,M,-1,9(a){7.P.2p(a,7.2a)})},3L:9(){F 7.5c||C([])},1F:9(t){E b=C.3M(7,9(a){F C.1F(t,a)});F 7.1O(/[^+>] [^+>]/.1d(t)||t.U("..")>-1?C.4d(b):b)},7o:9(e){e=e!=Q?e:O;E d=7.1r(7.1F("*"));6(C.N.12){d.J(9(){7.2l$1i={};I(E a 17 7.$1i)7.2l$1i[a]=C.14({},7.$1i[a])}).49()}E r=7.1O(C.3M(7,9(a){F a.3B(e)}));6(C.N.12){d.J(9(){E c=7.2l$1i;I(E a 17 c)I(E b 17 c[a])C.1c.1r(7,a,c[a][b],c[a][b].V);7.2l$1i=K})}6(e){E f=r.1r(r.1F(\'*\')).1l(\'2b,39[@L=3i]\');d.1l(\'2b,39[@L=3i]\').J(9(i){6(7.3j)f[i].3j=7.3j;6(7.27)f[i].27=O})}F r},1l:9(t){F 7.1O(C.1g(t)&&C.2B(7,9(b,a){F t.T(b,[a])})||C.2R(t,7))},5l:9(t){F 7.1O(t.1b==3n&&C.2R(t,7,O)||C.2B(7,9(a){F(t.1b==1K||t.3w)?C.4K(a,t)<0:a!=t}))},1r:9(t){F 7.1O(C.29(7.21(),t.1b==3n?C(t).21():t.H!=Q&&(!t.W||t.W=="6s")?t:[t]))},3y:9(a){F a?C.2R(a,7).H>0:M},2G:9(a){F a==Q?(7.H?7[0].2A:K):7.1j("2A",a)},5W:9(a){F a==Q?(7.H?7[0].2W:K):7.3K().3H(a)},3S:9(){F 7.1O(1K.3v.3S.T(7,1a))},2J:9(f,d,g,e){E c=7.H>1,a;F 7.J(9(){6(!a){a=C.3c(f,7.2I);6(g<0)a.8E()}E b=7;6(d&&C.W(7,"1A")&&C.W(a[0],"3O"))b=7.4L("1w")[0]||7.4p(R.6a("1w"));C.J(a,9(){6(C.W(7,"33")){6(7.32)C.31({1G:7.32,2w:M,3G:"33"});G C.4E(7.2Q||7.5Z||7.2W||"")}G e.T(b,[c?7.3B(O):7])})})}};C.14=C.15.14=9(){E c=1a[0]||{},a=1,1M=1a.H,4D=M;6(c.1b==8d){4D=c;c=1a[1]||{}}6(1M==1){c=7;a=0}E b;I(;a<1M;a++)6((b=1a[a])!=K)I(E i 17 b){6(c==b[i])5X;6(4D&&1f b[i]==\'4P\'&&c[i])C.14(c[i],b[i]);G 6(b[i]!=Q)c[i]=b[i]}F c};C.14({8a:9(a){19.$=B;6(a)19.16=v;F C},1g:9(a){F!!a&&1f a!="1E"&&!a.W&&a.1b!=1K&&/9/i.1d(a+"")},3E:9(a){F a.3D&&!a.4z||a.4y&&a.2I&&!a.2I.4z},4E:9(a){a=C.2s(a);6(a){6(19.5N)19.5N(a);G 6(C.N.1H)19.4x(a,0);G 2T.2S(19,a)}},W:9(b,a){F b.W&&b.W.1I()==a.1I()},J:9(a,b,c){6(c){6(a.H==Q)I(E i 17 a)b.T(a[i],c);G I(E i=0,3A=a.H;i<3A;i++)6(b.T(a[i],c)===M)1J}G{6(a.H==Q)I(E i 17 a)b.2S(a[i],i,a[i]);G I(E i=0,3A=a.H,2G=a[0];i<3A&&b.2S(2G,i,2G)!==M;2G=a[++i]){}}F a},4Q:9(c,b,d,e,a){6(C.1g(b))b=b.2S(c,[e]);E f=/z-?45|7S-?7Q|1e|5y|7O-?1u/i;F b&&b.1b==3x&&d=="34"&&!f.1d(a)?b+"4t":b},18:{1r:9(b,c){C.J((c||"").2M(/\\s+/),9(i,a){6(!C.18.2N(b.18,a))b.18+=(b.18?" ":"")+a})},23:9(b,c){b.18=c!=Q?C.2B(b.18.2M(/\\s+/),9(a){F!C.18.2N(c,a)}).5w(" "):""},2N:9(t,c){F C.4K(c,(t.18||t).3s().2M(/\\s+/))>-1}},1V:9(e,o,f){I(E i 17 o){e.S["2U"+i]=e.S[i];e.S[i]=o[i]}f.T(e,[]);I(E i 17 o)e.S[i]=e.S["2U"+i]},1h:9(e,p){6(p=="1u"||p=="24"){E b={},3p,3o,d=["7J","7G","7F","7B"];C.J(d,9(){b["7A"+7]=0;b["7x"+7+"7u"]=0});C.1V(e,b,9(){6(C(e).3y(\':4N\')){3p=e.7t;3o=e.7q}G{e=C(e.3B(O)).1F(":4e").5d("27").3L().1h({3V:"1C",3k:"7n",11:"2m",7h:"0",7e:"0"}).57(e.P)[0];E a=C.1h(e.P,"3k")||"3g";6(a=="3g")e.P.S.3k="76";3p=e.74;3o=e.71;6(a=="3g")e.P.S.3k="3g";e.P.3e(e)}});F p=="1u"?3p:3o}F C.34(e,p)},34:9(h,d,g){E i,1R=[],1V=[];9 2E(a){6(!C.N.1H)F M;E b=R.2L.3b(a,K);F!b||b.44("2E")==""}6(d=="1e"&&C.N.12){i=C.1j(h.S,"1e");F i==""?"1":i}6(d.2k(/3a/i))d=x;6(!g&&h.S[d])i=h.S[d];G 6(R.2L&&R.2L.3b){6(d.2k(/3a/i))d="3a";d=d.1v(/([A-Z])/g,"-$1").2D();E e=R.2L.3b(h,K);6(e&&!2E(h))i=e.44(d);G{I(E a=h;a&&2E(a);a=a.P)1R.42(a);I(a=0;a<1R.H;a++)6(2E(1R[a])){1V[a]=1R[a].S.11;1R[a].S.11="2m"}i=d=="11"&&1V[1R.H-1]!=K?"1T":R.2L.3b(h,K).44(d)||"";I(a=0;a<1V.H;a++)6(1V[a]!=K)1R[a].S.11=1V[a]}6(d=="1e"&&i=="")i="1"}G 6(h.41){E f=d.1v(/\\-(\\w)/g,9(m,c){F c.1I()});i=h.41[d]||h.41[f]}F i},3c:9(a,c){E r=[];c=c||R;C.J(a,9(i,b){6(!b)F;6(b.1b==3x)b=b.3s();6(1f b=="1E"){E s=C.2s(b).2D(),1m=c.6a("1m"),1P=[];E a=!s.U("<1Z")&&[1,"<2b>","</2b>"]||!s.U("<6L")&&[1,"<4V>","</4V>"]||s.2k(/^<(6I|1w|6H|6F|6D)/)&&[1,"<1A>","</1A>"]||!s.U("<3O")&&[2,"<1A><1w>","</1w></1A>"]||(!s.U("<6A")||!s.U("<6y"))&&[3,"<1A><1w><3O>","</3O></1w></1A>"]||!s.U("<6x")&&[2,"<1A><1w></1w><4T>","</4T></1A>"]||C.N.12&&[1,"1m<1m>","</1m>"]||[0,"",""];1m.2W=a[1]+b+a[2];20(a[0]--)1m=1m.3Y;6(C.N.12){6(!s.U("<1A")&&s.U("<1w")<0)1P=1m.1k&&1m.1k.2Z;G 6(a[1]=="<1A>"&&s.U("<1w")<0)1P=1m.2Z;I(E n=1P.H-1;n>=0;--n)6(C.W(1P[n],"1w")&&!1P[n].2Z.H)1P[n].P.3e(1P[n]);6(/^\\s/.1d(b))1m.2p(c.60(b.2k(/^\\s*/)[0]),1m.1k)}b=C.2V(1m.2Z)}6(0===b.H&&(!C.W(b,"38")&&!C.W(b,"2b")))F;6(b[0]==Q||C.W(b,"38")||b.6u)r.Y(b);G r=C.29(r,b)});F r},1j:9(c,d,a){E e=C.3E(c)?{}:C.4q;6(d=="28"&&C.N.1H)c.P.3j;6(e[d]){6(a!=Q)c[e[d]]=a;F c[e[d]]}G 6(C.N.12&&d=="S")F C.1j(c.S,"6p",a);G 6(a==Q&&C.N.12&&C.W(c,"38")&&(d=="6n"||d=="6m"))F c.6k(d).5S;G 6(c.4y){6(a!=Q)c.6j(d,a);6(C.N.12&&/5R|32/.1d(d)&&!C.3E(c))F c.3F(d,2);F c.3F(d)}G{6(d=="1e"&&C.N.12){6(a!=Q){c.5y=1;c.1l=(c.1l||"").1v(/5T\\([^)]*\\)/,"")+(3m(a).3s()=="6d"?"":"5T(1e="+a*6c+")")}F c.1l?(3m(c.1l.2k(/1e=([^)]*)/)[1])/6c).3s():""}d=d.1v(/-([a-z])/8I,9(z,b){F b.1I()});6(a!=Q)c[d]=a;F c[d]}},2s:9(t){F(t||"").1v(/^\\s+|\\s+$/g,"")},2V:9(a){E r=[];6(1f a!="8H")I(E i=0,1M=a.H;i<1M;i++)r.Y(a[i]);G r=a.3S(0);F r},4K:9(b,a){I(E i=0,1M=a.H;i<1M;i++)6(a[i]==b)F i;F-1},29:9(a,b){6(C.N.12){I(E i=0;b[i];i++)6(b[i].1t!=8)a.Y(b[i])}G I(E i=0;b[i];i++)a.Y(b[i]);F a},4d:9(a){E r=[],4O=C.1q++;2g{I(E i=0,69=a.H;i<69;i++)6(4O!=a[i].1q){a[i].1q=4O;r.Y(a[i])}}2h(e){r=a}F r},1q:0,2B:9(b,a,c){6(1f a=="1E")a=2T("M||9(a,i){F "+a+"}");E d=[];I(E i=0,3P=b.H;i<3P;i++)6(!c&&a(b[i],i)||c&&!a(b[i],i))d.Y(b[i]);F d},3M:9(c,b){6(1f b=="1E")b=2T("M||9(a){F "+b+"}");E d=[];I(E i=0,3P=c.H;i<3P;i++){E a=b(c[i],i);6(a!==K&&a!=Q){6(a.1b!=1K)a=[a];d=d.8x(a)}}F d}});E u=8w.8u.2D();C.N={6b:(u.2k(/.+(?:8s|8q|8p|8o)[\\/: ]([\\d.]+)/)||[])[1],1H:/61/.1d(u),2t:/2t/.1d(u),12:/12/.1d(u)&&!/2t/.1d(u),3J:/3J/.1d(u)&&!/(8n|61)/.1d(u)};E x=C.N.12?"3I":"4G";C.14({8m:!C.N.12||R.8l=="8k",3I:C.N.12?"3I":"4G",4q:{"I":"8j","8i":"18","3a":x,4G:x,3I:x,2W:"2W",18:"18",2A:"2A",30:"30",27:"27",8h:"8g",28:"28",8f:"8e"}});C.J({5Y:"a.P",4C:"16.4C(a)",8c:"16.25(a,2,\'2a\')",8b:"16.25(a,2,\'4B\')",88:"16.4A(a.P.1k,a)",87:"16.4A(a.1k)"},9(i,n){C.15[i]=9(a){E b=C.3M(7,n);6(a&&1f a=="1E")b=C.2R(a,b);F 7.1O(C.4d(b))}});C.J({57:"3H",86:"5v",2p:"5u",85:"5t"},9(i,n){C.15[i]=9(){E a=1a;F 7.J(9(){I(E j=0,1M=a.H;j<1M;j++)C(a[j])[n](7)})}});C.J({5d:9(a){C.1j(7,a,"");7.84(a)},83:9(c){C.18.1r(7,c)},81:9(c){C.18.23(7,c)},80:9(c){C.18[C.18.2N(7,c)?"23":"1r"](7,c)},23:9(a){6(!a||C.1l(a,[7]).r.H)7.P.3e(7)},3K:9(){20(7.1k)7.3e(7.1k)}},9(i,n){C.15[i]=9(){F 7.J(n,1a)}});C.J(["5Q","5P","5M","5L"],9(i,n){C.15[n]=9(a,b){F 7.1l(":"+n+"("+a+")",b)}});C.J(["1u","24"],9(i,n){C.15[n]=9(h){F h==Q?(7.H?C.1h(7[0],n):K):7.1h(n,h.1b==3n?h:h+"4t")}});E A=C.N.1H&&5K(C.N.6b)<7Z?"(?:[\\\\w*2l-]|\\\\\\\\.)":"(?:[\\\\w\\7Y-\\7V*2l-]|\\\\\\\\.)",5I=1s 3C("^[/>]\\\\s*("+A+"+)"),5H=1s 3C("^("+A+"+)(#)("+A+"+)"),5G=1s 3C("^([#.]?)("+A+"*)");C.14({4w:{"":"m[2]==\'*\'||16.W(a,m[2])","#":"a.3F(\'2j\')==m[2]",":":{5P:"i<m[3]-0",5M:"i>m[3]-0",25:"m[3]-0==i",5Q:"m[3]-0==i",2H:"i==0",2P:"i==r.H-1",5E:"i%2==0",5D:"i%2","2H-3z":"a.P.4L(\'*\')[0]==a","2P-3z":"16.25(a.P.3Y,1,\'4B\')==a","7U-3z":"!16.25(a.P.3Y,2,\'4B\')",5Y:"a.1k",3K:"!a.1k",5L:"(a.5Z||a.7T||\'\').U(m[3])>=0",4N:\'"1C"!=a.L&&16.1h(a,"11")!="1T"&&16.1h(a,"3V")!="1C"\',1C:\'"1C"==a.L||16.1h(a,"11")=="1T"||16.1h(a,"3V")=="1C"\',7R:"!a.30",30:"a.30",27:"a.27",28:"a.28||16.1j(a,\'28\')",2Q:"\'2Q\'==a.L",4e:"\'4e\'==a.L",3i:"\'3i\'==a.L",4v:"\'4v\'==a.L",5C:"\'5C\'==a.L",4u:"\'4u\'==a.L",5B:"\'5B\'==a.L",5A:"\'5A\'==a.L",1X:\'"1X"==a.L||16.W(a,"1X")\',39:"/39|2b|7P|1X/i.1d(a.W)",2N:"16.1F(m[3],a).H"},"[":"16.1F(m[2],a).H"},5x:[/^\\[ *(@)([\\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\\4 *\\]/,/^(\\[)\\s*(.*?(\\[.*?\\])?[^[]*?)\\s*\\]/,/^(:)([\\w-]+)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/,1s 3C("^([:.#]*)("+A+"+)")],2R:9(a,c,b){E d,1Y=[];20(a&&a!=d){d=a;E f=C.1l(a,c,b);a=f.t.1v(/^\\s*,\\s*/,"");1Y=b?c=f.r:C.29(1Y,f.r)}F 1Y},1F:9(t,l){6(1f t!="1E")F[t];6(l&&!l.1t)l=K;l=l||R;6(!t.U("//")){t=t.2K(2,t.H)}G 6(!t.U("/")&&!l.2I){l=l.3D;t=t.2K(1,t.H);6(t.U("/")>=1)t=t.2K(t.U("/"),t.H)}E d=[l],2q=[],2P;20(t&&2P!=t){E r=[];2P=t;t=C.2s(t).1v(/^\\/\\//,"");E k=M;E g=5I;E m=g.2d(t);6(m){E o=m[1].1I();I(E i=0;d[i];i++)I(E c=d[i].1k;c;c=c.2a)6(c.1t==1&&(o=="*"||c.W.1I()==o.1I()))r.Y(c);d=r;t=t.1v(g,"");6(t.U(" ")==0)5X;k=O}G{g=/^((\\/?\\.\\.)|([>\\/+~]))\\s*(\\w*)/i;6((m=g.2d(t))!=K){r=[];E o=m[4],1q=C.1q++;m=m[1];I(E j=0,2o=d.H;j<2o;j++)6(m.U("..")<0){E n=m=="~"||m=="+"?d[j].2a:d[j].1k;I(;n;n=n.2a)6(n.1t==1){6(m=="~"&&n.1q==1q)1J;6(!o||n.W.1I()==o.1I()){6(m=="~")n.1q=1q;r.Y(n)}6(m=="+")1J}}G r.Y(d[j].P);d=r;t=C.2s(t.1v(g,""));k=O}}6(t&&!k){6(!t.U(",")){6(l==d[0])d.4s();2q=C.29(2q,d);r=d=[l];t=" "+t.2K(1,t.H)}G{E h=5H;E m=h.2d(t);6(m){m=[0,m[2],m[3],m[1]]}G{h=5G;m=h.2d(t)}m[2]=m[2].1v(/\\\\/g,"");E f=d[d.H-1];6(m[1]=="#"&&f&&f.37&&!C.3E(f)){E p=f.37(m[2]);6((C.N.12||C.N.2t)&&p&&1f p.2j=="1E"&&p.2j!=m[2])p=C(\'[@2j="\'+m[2]+\'"]\',f)[0];d=r=p&&(!m[3]||C.W(p,m[3]))?[p]:[]}G{I(E i=0;d[i];i++){E a=m[1]!=""||m[0]==""?"*":m[2];6(a=="*"&&d[i].W.2D()=="4P")a="2O";r=C.29(r,d[i].4L(a))}6(m[1]==".")r=C.4r(r,m[2]);6(m[1]=="#"){E e=[];I(E i=0;r[i];i++)6(r[i].3F("2j")==m[2]){e=[r[i]];1J}r=e}d=r}t=t.1v(h,"")}}6(t){E b=C.1l(t,r);d=r=b.r;t=C.2s(b.t)}}6(t)d=[];6(d&&l==d[0])d.4s();2q=C.29(2q,d);F 2q},4r:9(r,m,a){m=" "+m+" ";E c=[];I(E i=0;r[i];i++){E b=(" "+r[i].18+" ").U(m)>=0;6(!a&&b||a&&!b)c.Y(r[i])}F c},1l:9(t,r,h){E d;20(t&&t!=d){d=t;E p=C.5x,m;I(E i=0;p[i];i++){m=p[i].2d(t);6(m){t=t.7N(m[0].H);m[2]=m[2].1v(/\\\\/g,"");1J}}6(!m)1J;6(m[1]==":"&&m[2]=="5l")r=C.1l(m[3],r,O).r;G 6(m[1]==".")r=C.4r(r,m[2],h);G 6(m[1]=="@"){E g=[],L=m[3];I(E i=0,2o=r.H;i<2o;i++){E a=r[i],z=a[C.4q[m[2]]||m[2]];6(z==K||/5R|32|28/.1d(m[2]))z=C.1j(a,m[2])||\'\';6((L==""&&!!z||L=="="&&z==m[5]||L=="!="&&z!=m[5]||L=="^="&&z&&!z.U(m[5])||L=="$="&&z.2K(z.H-m[5].H)==m[5]||(L=="*="||L=="~=")&&z.U(m[5])>=0)^h)g.Y(a)}r=g}G 6(m[1]==":"&&m[2]=="25-3z"){E e=C.1q++,g=[],1d=/(\\d*)n\\+?(\\d*)/.2d(m[3]=="5E"&&"2n"||m[3]=="5D"&&"2n+1"||!/\\D/.1d(m[3])&&"n+"+m[3]||m[3]),2H=(1d[1]||1)-0,d=1d[2]-0;I(E i=0,2o=r.H;i<2o;i++){E j=r[i],P=j.P;6(e!=P.1q){E c=1;I(E n=P.1k;n;n=n.2a)6(n.1t==1)n.4o=c++;P.1q=e}E b=M;6(2H==1){6(d==0||j.4o==d)b=O}G 6((j.4o+d)%2H==0)b=O;6(b^h)g.Y(j)}r=g}G{E f=C.4w[m[1]];6(1f f!="1E")f=C.4w[m[1]][m[2]];f=2T("M||9(a,i){F "+f+"}");r=C.2B(r,f,h)}}F{r:r,t:t}},4C:9(c){E b=[];E a=c.P;20(a&&a!=R){b.Y(a);a=a.P}F b},25:9(a,e,c,b){e=e||1;E d=0;I(;a;a=a[c])6(a.1t==1&&++d==e)1J;F a},4A:9(n,a){E r=[];I(;n;n=n.2a){6(n.1t==1&&(!a||n!=a))r.Y(n)}F r}});C.1c={1r:9(f,d,c,b){6(C.N.12&&f.3t!=Q)f=19;6(!c.22)c.22=7.22++;6(b!=Q){E e=c;c=9(){F e.T(7,1a)};c.V=b;c.22=e.22}6(!f.$1i)f.$1i={};6(!f.$1y)f.$1y=9(){E a;6(1f C=="Q"||C.1c.4n)F a;a=C.1c.1y.T(f,1a);F a};E g=f.$1i[d];6(!g){g=f.$1i[d]={};6(f.4m)f.4m(d,f.$1y,M);G f.7M("3r"+d,f.$1y)}g[c.22]=c;7.1D[d]=O},22:1,1D:{},23:9(c,b,a){E d=c.$1i,2c,45;6(d){6(b&&b.L){a=b.4l;b=b.L}6(!b){I(b 17 d)7.23(c,b)}G 6(d[b]){6(a)4k d[b][a.22];G I(a 17 c.$1i[b])4k d[b][a];I(2c 17 d[b])1J;6(!2c){6(c.4j)c.4j(b,c.$1y,M);G c.7L("3r"+b,c.$1y);2c=K;4k d[b]}}I(2c 17 d)1J;6(!2c)c.$1y=c.$1i=K}},1z:9(c,b,d){b=C.2V(b||[]);6(!d){6(7.1D[c])C("*").1r([19,R]).1z(c,b)}G{E a,2c,15=C.1g(d[c]||K);b.42(7.4i({L:c,1S:d}));6(C.1g(d.$1y))a=d.$1y.T(d,b);6(!15&&d["3r"+c]&&d["3r"+c].T(d,b)===M)a=M;6(15&&a!==M&&!(C.W(d,\'a\')&&c=="4h")){7.4n=O;d[c]()}7.4n=M}},1y:9(b){E a;b=C.1c.4i(b||19.1c||{});E c=7.$1i&&7.$1i[b.L],2e=1K.3v.3S.2S(1a,1);2e.42(b);I(E j 17 c){2e[0].4l=c[j];2e[0].V=c[j].V;6(c[j].T(7,2e)===M){b.2u();b.2X();a=M}}6(C.N.12)b.1S=b.2u=b.2X=b.4l=b.V=K;F a},4i:9(c){E a=c;c=C.14({},a);c.2u=9(){6(a.2u)a.2u();a.7I=M};c.2X=9(){6(a.2X)a.2X();a.7H=O};6(!c.1S&&c.5r)c.1S=c.5r;6(C.N.1H&&c.1S.1t==3)c.1S=a.1S.P;6(!c.4g&&c.4F)c.4g=c.4F==c.1S?c.7C:c.4F;6(c.5p==K&&c.66!=K){E e=R.3D,b=R.4z;c.5p=c.66+(e&&e.5o||b.5o||0);c.7z=c.7v+(e&&e.5m||b.5m||0)}6(!c.3Q&&(c.5k||c.5j))c.3Q=c.5k||c.5j;6(!c.5i&&c.5g)c.5i=c.5g;6(!c.3Q&&c.1X)c.3Q=(c.1X&1?1:(c.1X&2?3:(c.1X&4?2:0)));F c}};C.15.14({3l:9(c,a,b){F c=="5f"?7.5e(c,a,b):7.J(9(){C.1c.1r(7,c,b||a,b&&a)})},5e:9(d,b,c){F 7.J(9(){C.1c.1r(7,d,9(a){C(7).49(a);F(c||b).T(7,1a)},c&&b)})},49:9(a,b){F 7.J(9(){C.1c.23(7,a,b)})},1z:9(a,b){F 7.J(9(){C.1c.1z(a,b,7)})},1W:9(){E a=1a;F 7.4h(9(e){7.3T=0==7.3T?1:0;e.2u();F a[7.3T].T(7,[e])||M})},7p:9(f,g){9 3U(e){E p=e.4g;20(p&&p!=7)2g{p=p.P}2h(e){p=7};6(p==7)F M;F(e.L=="3W"?f:g).T(7,[e])}F 7.3W(3U).5b(3U)},1L:9(f){5a();6(C.36)f.T(R,[C]);G C.2C.Y(9(){F f.T(7,[C])});F 7}});C.14({36:M,2C:[],1L:9(){6(!C.36){C.36=O;6(C.2C){C.J(C.2C,9(){7.T(R)});C.2C=K}6(C.N.3J||C.N.2t)R.4j("59",C.1L,M);6(!19.7m.H)C(19).2f(9(){C("#4b").23()})}}});C.J(("7l,7k,2f,7j,7i,5f,4h,7g,"+"7f,7d,7c,3W,5b,7b,2b,"+"4u,7a,79,78,3f").2M(","),9(i,o){C.15[o]=9(f){F f?7.3l(o,f):7.1z(o)}});E w=M;9 5a(){6(w)F;w=O;6(C.N.3J||C.N.2t)R.4m("59",C.1L,M);G 6(C.N.12){R.75("<73"+"72 2j=4b 70=O "+"32=//:><\\/33>");E a=R.37("4b");6(a)a.6Z=9(){6(R.3d!="1x")F;C.1L()};a=K}G 6(C.N.1H)C.48=3t(9(){6(R.3d=="6Y"||R.3d=="1x"){47(C.48);C.48=K;C.1L()}},10);C.1c.1r(19,"2f",C.1L)}C.15.14({6X:9(c,b,a){7.2f(c,b,a,1)},2f:9(g,e,c,d){6(C.1g(g))F 7.3l("2f",g);c=c||9(){};E f="46";6(e)6(C.1g(e)){c=e;e=K}G{e=C.2O(e);f="55"}E h=7;C.31({1G:g,L:f,V:e,2F:d,1x:9(a,b){6(b=="1U"||!d&&b=="54")h.5W(a.43);4x(9(){h.J(c,[a.43,b,a])},13)}});F 7},6W:9(){F C.2O(7)},6V:9(){}});C.J("53,52,51,50,4Z,5h".2M(","),9(i,o){C.15[o]=9(f){F 7.3l(o,f)}});C.14({21:9(e,c,a,d,b){6(C.1g(c)){a=c;c=K}F C.31({L:"46",1G:e,V:c,1U:a,3G:d,2F:b})},6U:9(d,b,a,c){F C.21(d,b,a,c,1)},6T:9(b,a){F C.21(b,K,a,"33")},77:9(c,b,a){F C.21(c,b,a,"56")},6S:9(d,b,a,c){6(C.1g(b)){a=b;b={}}F C.31({L:"55",1G:d,V:b,1U:a,3G:c})},6R:9(a){C.3u.1Q=a},6Q:9(a){C.14(C.3u,a)},3u:{1D:O,L:"46",1Q:0,4Y:"6P/x-6O-38-6N",4X:O,2w:O,V:K},3h:{},31:9(s){s=C.14(O,s,C.14(O,{},C.3u,s));6(s.V){6(s.4X&&1f s.V!="1E")s.V=C.2O(s.V);6(s.L.2D()=="21"){s.1G+=(s.1G.U("?")>-1?"&":"?")+s.V;s.V=K}}6(s.1D&&!C.40++)C.1c.1z("53");E f=M;E h=19.4W?1s 4W("6M.6K"):1s 58();h.6J(s.L,s.1G,s.2w);6(s.V)h.4c("7r-7s",s.4Y);6(s.2F)h.4c("6G-3Z-6E",C.3h[s.1G]||"7w, 6C 7y 6B 4J:4J:4J 6z");h.4c("X-7D-7E","58");6(s.4U)s.4U(h);6(s.1D)C.1c.1z("5h",[h,s]);E g=9(d){6(!f&&h&&(h.3d==4||d=="1Q")){f=O;6(i){47(i);i=K}E c=d=="1Q"&&"1Q"||!C.5n(h)&&"3f"||s.2F&&C.5s(h,s.1G)&&"54"||"1U";6(c=="1U"){2g{E a=C.5q(h,s.3G)}2h(e){c="4I"}}6(c=="1U"){E b;2g{b=h.4f("4S-3Z")}2h(e){}6(s.2F&&b)C.3h[s.1G]=b;6(s.1U)s.1U(a,c);6(s.1D)C.1c.1z("4Z",[h,s])}G C.3X(s,h,c);6(s.1D)C.1c.1z("51",[h,s]);6(s.1D&&!--C.40)C.1c.1z("52");6(s.1x)s.1x(h,c);6(s.2w)h=K}};6(s.2w){E i=3t(g,13);6(s.1Q>0)4x(9(){6(h){h.6w();6(!f)g("1Q")}},s.1Q)}2g{h.6v(s.V)}2h(e){C.3X(s,h,K,e)}6(!s.2w)g();F h},3X:9(s,a,b,e){6(s.3f)s.3f(a,b,e);6(s.1D)C.1c.1z("50",[a,s,e])},40:0,5n:9(r){2g{F!r.26&&6t.6r=="4v:"||(r.26>=4R&&r.26<6q)||r.26==5z||C.N.1H&&r.26==Q}2h(e){}F M},5s:9(a,c){2g{E b=a.4f("4S-3Z");F a.26==5z||b==C.3h[c]||C.N.1H&&a.26==Q}2h(e){}F M},5q:9(r,a){E b=r.4f("6o-L");E c=a=="5F"||!a&&b&&b.U("5F")>=0;V=c?r.7W:r.43;6(c&&V.3D.4y=="4I")7X"4I";6(a=="33")C.4E(V);6(a=="56")V=2T("("+V+")");F V},2O:9(a){E s=[];6(a.1b==1K||a.3w)C.J(a,9(){s.Y(2y(7.6l)+"="+2y(7.2A))});G I(E j 17 a)6(a[j]&&a[j].1b==1K)C.J(a[j],9(){s.Y(2y(j)+"="+2y(7))});G s.Y(2y(j)+"="+2y(a[j]));F s.5w("&")}});C.15.14({1o:9(b,a){F b?7.1B({1u:"1o",24:"1o",1e:"1o"},b,a):7.1l(":1C").J(9(){7.S.11=7.2r?7.2r:"";6(C.1h(7,"11")=="1T")7.S.11="2m"}).3L()},1p:9(b,a){F b?7.1B({1u:"1p",24:"1p",1e:"1p"},b,a):7.1l(":4N").J(9(){7.2r=7.2r||C.1h(7,"11");6(7.2r=="1T")7.2r="2m";7.S.11="1T"}).3L()},5O:C.15.1W,1W:9(a,b){F C.1g(a)&&C.1g(b)?7.5O(a,b):a?7.1B({1u:"1W",24:"1W",1e:"1W"},a,b):7.J(9(){C(7)[C(7).3y(":1C")?"1o":"1p"]()})},6i:9(b,a){F 7.1B({1u:"1o"},b,a)},6h:9(b,a){F 7.1B({1u:"1p"},b,a)},6g:9(b,a){F 7.1B({1u:"1W"},b,a)},6f:9(b,a){F 7.1B({1e:"1o"},b,a)},89:9(b,a){F 7.1B({1e:"1p"},b,a)},6e:9(c,a,b){F 7.1B({1e:a},c,b)},1B:9(d,h,f,g){F 7.1n(9(){E c=C(7).3y(":1C"),1Z=C.5V(h,f,g),5U=7;I(E p 17 d){6(d[p]=="1p"&&c||d[p]=="1o"&&!c)F C.1g(1Z.1x)&&1Z.1x.T(7);6(p=="1u"||p=="24"){1Z.11=C.1h(7,"11");1Z.2z=7.S.2z}}6(1Z.2z!=K)7.S.2z="1C";7.2v=C.14({},d);C.J(d,9(a,b){E e=1s C.2Y(5U,1Z,a);6(b.1b==3x)e.3R(e.1Y()||0,b);G e[b=="1W"?c?"1o":"1p":b](d)});F O})},1n:9(a,b){6(!b){b=a;a="2Y"}F 7.J(9(){6(!7.1n)7.1n={};6(!7.1n[a])7.1n[a]=[];7.1n[a].Y(b);6(7.1n[a].H==1)b.T(7)})}});C.14({5V:9(b,a,c){E d=b&&b.1b==8G?b:{1x:c||!c&&a||C.1g(b)&&b,1N:b,35:c&&a||a&&a.1b!=8F&&a};d.1N=(d.1N&&d.1N.1b==3x?d.1N:{8D:8C,8B:4R}[d.1N])||8A;d.2U=d.1x;d.1x=9(){C.68(7,"2Y");6(C.1g(d.2U))d.2U.T(7)};F d},35:{62:9(p,n,b,a){F b+a*p},4H:9(p,n,b,a){F((-67.8z(p*67.8y)/2)+0.5)*a+b}},1n:{},68:9(b,a){a=a||"2Y";6(b.1n&&b.1n[a]){b.1n[a].4s();E f=b.1n[a][0];6(f)f.T(b)}},3N:[],2Y:9(f,e,g){E z=7;E y=f.S;z.a=9(){6(e.3q)e.3q.T(f,[z.2x]);6(g=="1e")C.1j(y,"1e",z.2x);G{y[g]=5K(z.2x)+"4t";6(g=="1u"||g=="24")y.11="2m"}};z.65=9(){F 3m(C.1h(f,g))};z.1Y=9(){E r=3m(C.34(f,g));F r&&r>-8v?r:z.65()};z.3R=9(c,b){z.4M=(1s 64()).63();z.2x=c;z.a();C.3N.Y(9(){F z.3q(c,b)});6(C.3N.H==1){E d=3t(9(){E a=C.3N;I(E i=0;i<a.H;i++)6(!a[i]())a.8t(i--,1);6(!a.H)47(d)},13)}};z.1o=9(){6(!f.2i)f.2i={};f.2i[g]=C.1j(f.S,g);e.1o=O;z.3R(0,7.1Y());6(g!="1e")y[g]="8r";C(f).1o()};z.1p=9(){6(!f.2i)f.2i={};f.2i[g]=C.1j(f.S,g);e.1p=O;z.3R(7.1Y(),0)};z.3q=9(a,c){E t=(1s 64()).63();6(t>e.1N+z.4M){z.2x=c;z.a();6(f.2v)f.2v[g]=O;E b=O;I(E i 17 f.2v)6(f.2v[i]!==O)b=M;6(b){6(e.11!=K){y.2z=e.2z;y.11=e.11;6(C.1h(f,"11")=="1T")y.11="2m"}6(e.1p)y.11="1T";6(e.1p||e.1o)I(E p 17 f.2v)C.1j(y,p,f.2i[p])}6(b&&C.1g(e.1x))e.1x.T(f);F M}G{E n=t-7.4M;E p=n/e.1N;z.2x=C.35[e.35||(C.35.4H?"4H":"62")](p,n,a,(c-a),e.1N);z.a()}F O}}})})();',62,541,'||||||if|this||function|||||||||||||||||||||||||||||||var|return|else|length|for|each|null|type|false|browser|true|parentNode|undefined|document|style|apply|indexOf|data|nodeName||push|||display|msie||extend|fn|jQuery|in|className|window|arguments|constructor|event|test|opacity|typeof|isFunction|css|events|attr|firstChild|filter|div|queue|show|hide|mergeNum|add|new|nodeType|height|replace|tbody|complete|handle|trigger|table|animate|hidden|global|string|find|url|safari|toUpperCase|break|Array|ready|al|duration|pushStack|tb|timeout|stack|target|none|success|swap|toggle|button|cur|opt|while|get|guid|remove|width|nth|status|checked|selected|merge|nextSibling|select|ret|exec|args|load|try|catch|orig|id|match|_|block||rl|insertBefore|done|oldblock|trim|opera|preventDefault|curAnim|async|now|encodeURIComponent|overflow|value|grep|readyList|toLowerCase|color|ifModified|val|first|ownerDocument|domManip|substr|defaultView|split|has|param|last|text|multiFilter|call|eval|old|makeArray|innerHTML|stopPropagation|fx|childNodes|disabled|ajax|src|script|curCSS|easing|isReady|getElementById|form|input|float|getComputedStyle|clean|readyState|removeChild|error|static|lastModified|checkbox|selectedIndex|position|bind|parseFloat|String|oWidth|oHeight|step|on|toString|setInterval|ajaxSettings|prototype|jquery|Number|is|child|ol|cloneNode|RegExp|documentElement|isXMLDoc|getAttribute|dataType|append|styleFloat|mozilla|empty|end|map|timers|tr|el|which|custom|slice|lastToggle|handleHover|visibility|mouseover|handleError|lastChild|Modified|active|currentStyle|unshift|responseText|getPropertyValue|index|GET|clearInterval|safariTimer|unbind|init|__ie_init|setRequestHeader|unique|radio|getResponseHeader|relatedTarget|click|fix|removeEventListener|delete|handler|addEventListener|triggered|nodeIndex|appendChild|props|classFilter|shift|px|submit|file|expr|setTimeout|tagName|body|sibling|previousSibling|parents|deep|globalEval|fromElement|cssFloat|swing|parsererror|00|inArray|getElementsByTagName|startTime|visible|num|object|prop|200|Last|colgroup|beforeSend|fieldset|ActiveXObject|processData|contentType|ajaxSuccess|ajaxError|ajaxComplete|ajaxStop|ajaxStart|notmodified|POST|json|appendTo|XMLHttpRequest|DOMContentLoaded|bindReady|mouseout|prevObject|removeAttr|one|unload|ctrlKey|ajaxSend|metaKey|keyCode|charCode|not|scrollTop|httpSuccess|scrollLeft|pageX|httpData|srcElement|httpNotModified|after|before|prepend|join|parse|zoom|304|reset|image|password|odd|even|xml|quickClass|quickID|quickChild|setArray|parseInt|contains|gt|execScript|_toggle|lt|eq|href|nodeValue|alpha|self|speed|html|continue|parent|textContent|createTextNode|webkit|linear|getTime|Date|max|clientX|Math|dequeue|fl|createElement|version|100|NaN|fadeTo|fadeIn|slideToggle|slideUp|slideDown|setAttribute|getAttributeNode|name|method|action|content|cssText|300|protocol|FORM|location|options|send|abort|col|th|GMT|td|1970|01|cap|Since|colg|If|tfoot|thead|open|XMLHTTP|leg|Microsoft|urlencoded|www|application|ajaxSetup|ajaxTimeout|post|getScript|getIfModified|evalScripts|serialize|loadIfModified|loaded|onreadystatechange|defer|clientWidth|ipt|scr|clientHeight|write|relative|getJSON|keyup|keypress|keydown|change|mousemove|mouseup|left|mousedown|dblclick|right|scroll|resize|focus|blur|frames|absolute|clone|hover|offsetWidth|Content|Type|offsetHeight|Width|clientY|Thu|border|Jan|pageY|padding|Left|toElement|Requested|With|Right|Bottom|cancelBubble|returnValue|Top|size|detachEvent|attachEvent|substring|line|textarea|weight|enabled|font|innerText|only|uFFFF|responseXML|throw|u0128|417|toggleClass|removeClass|wrap|addClass|removeAttribute|insertAfter|prependTo|children|siblings|fadeOut|noConflict|prev|next|Boolean|maxLength|maxlength|readOnly|readonly|class|htmlFor|CSS1Compat|compatMode|boxModel|compatible|ie|ra|it|1px|rv|splice|userAgent|10000|navigator|concat|PI|cos|400|fast|600|slow|reverse|Function|Object|array|ig'.split('|'),0,{}));

/*--------------------------------------------------------------------------
 /ext/jquery/cmxforms.js
--------------------------------------------------------------------------*/
// apply inline-box only for mozilla
if( jQuery.browser.mozilla ) {
	// do when DOM is ready
	$( function() {
		// search form, hide it, search labels to modify, filter classes nocmx and error
		$( 'form.cmxform' ).hide().find( 'p/label:not(.nocmx):not(.error)' ).each( function() {
			var $this = $(this);
			var labelContent = $this.html();
			var labelWidth = document.defaultView.getComputedStyle( this, '' ).getPropertyValue( 'width' );
			// create block element with width of label
			var labelSpan = $("<span>")
				.css("display", "block")
				.width(labelWidth)
				.html(labelContent);
			// change display to mozilla specific inline-box
			$this.css("display", "-moz-inline-box")
				// remove children
				.empty()
				// add span element
				.append(labelSpan);
		// show form again
		}).end().show();
	});
};;

/*--------------------------------------------------------------------------
 /ext/jquery/jquery.array.js
--------------------------------------------------------------------------*/
/*
 * Array prototype extensions. Doesn't depend on any
 * other code. Doens't overwrite existing methods.
 *
 * Adds forEach, every, some, map, filter, indexOf and unique.
 *
 * Copyright (c) 2006 Jörn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 */

(function() {
	
	/**
	 * Adds a given method under the given name 
	 * to the Array prototype if it doesn't
	 * currently exist.
	 *
	 * @private
	 */
	function add(name, method) {
		if( !Array.prototype[name] ) {
			Array.prototype[name] = method;
		}
	};
	
	/**
	 * Executes a provided function once per array element.
	 *
	 * @example var stuff = "";
	 * ["foo", "bar"].forEach(function(element, index, array) {
	 *   stuff += element;
	 * });
	 * @result "foobar";
	 *
	 * @param Function handler Function to execute for each element.
	 * @param Object scope (optional) Object to use as 'this' when executing handler.
	 * @name forEach
	 * @type undefined
	 * @cat Plugins/Methods/Array
	 */
	add("forEach", function(handler, scope) {
		scope = scope || window;
		for( var i = 0; i < this.length; i++)
			handler.call(scope, this[i], i, this);
	});
	
	/**
	 * Tests whether all elements in the array pass the test
	 * implemented by the provided function.
	 *
	 * @example [12, 54, 18, 130, 44].every(function(element, index, array) {
	 *   return element >= 10;
	 * });
	 * @result true;
	 *
	 * @example [12, 5, 8, 130, 44].every(function(element, index, array) {
	 *   return element >= 10;
	 * });
	 * @result false;
	 *
	 * @param Function handler Function to execute for each element.
	 * @param Object scope (optional) Object to use as 'this' when executing handler.
	 * @name every
	 * @type Boolean
	 * @cat Plugins/Methods/Array
	 */
	add("every", function(handler, scope) {
		scope = scope || window;
		for( var i = 0; i < this.length; i++)
			if( !handler.call(scope, this[i], i, this) )
				return false;
		return true;
	});
	
	/**
	 * Tests whether at least one element in the array passes the test
	 * implemented by the provided function.
	 *
	 * @example [12, 5, 8, 1, 44].some(function(element, index, array) {
	 *   return element >= 10;
	 * });
	 * @result true;
	 *
	 * @example [2, 5, 8, 1, 4].some(function(element, index, array) {
	 *   return element >= 10;
	 * });
	 * @result false;
	 *
	 * @param Function handler Function to execute for each element.
	 * @param Object scope (optional) Object to use as 'this' when executing handler.
	 * @name some
	 * @type Boolean
	 * @cat Plugins/Methods/Array
	 */
	add("some", function(handler, scope) {
		scope = scope || window;
		for( var i = 0; i < this.length; i++)
			if( handler.call(scope, this[i], i, this) )
				return true;
		return false;
	});
	
	/**
	 * Creates a new array with the results of
	 * calling a provided function on every element in this array.
	 *
	 * @example ["hello", "Array", "WORLD"].map(function(element, index, array) {
	 *   return element.toUpperCase();
	 * });
	 * @result ["HELLO", "ARRAY", "WORLD"];
	 *
	 * @example [1, 4, 9].map(Math.sqrt);
	 * @result [1, 2, 3];
	 *
	 * @param Function handler Function to execute for each element.
	 * @param Object scope (optional) Object to use as 'this' when executing handler.
	 * @name map
	 * @type Array
	 * @cat Plugins/Methods/Array
	 */
	add("map", function(handler, scope) {
		scope = scope || window;
		var r = [];
		for( var i = 0; i < this.length; i++)
			r[r.length] = handler.call(scope, this[i], i, this);
		return r;
	});
	
	/**
	 * Creates a new array with all elements that pass
	 * the test implemented by the provided function.
	 *
	 * @example [12, 5, 8, 1, 44].filter(function(element, index, array) {
	 *   return element >= 10;
	 * });
	 * @result [12, 44];
	 *
	 * @param Function handler Function to execute for each element.
	 * @param Object scope (optional) Object to use as 'this' when executing handler.
	 * @name filter
	 * @type Array
	 * @cat Plugins/Methods/Array
	 */
	add("filter", function(handler, scope) {
		scope = scope || window;
		var r = [];
		for( var i = 0; i < this.length; i++)
			if( handler.call(scope, this[i], i, this) )
				r[r.length] = this[i];
		return r;
	});
	
	/**
	 * Returns the first index at which a given element can
	 * be found in the array, or -1 if it is not present.
	 *
	 * @example [12, 5, 8, 5, 44].indexOf(5);
	 * @result 1;
	 *
	 * @example [12, 5, 8, 5, 44].indexOf(5, 2);
	 * @result 3;
	 *
	 * @param Object subject Object to search for
	 * @param Number offset (optional) Index at which to start searching
	 * @name filter
	 * @type Array
	 * @cat Plugins/Methods/Array
	 */
	add("indexOf", function(subject, offset) {
		for( var i = offset || 0; i < this.length; i++)
			if ( this[i] === subject )
	            return i;
		return -1;
	});
	
	/**
	 * Returns a new array that contains all unique elements
	 * of this array.
	 *
	 * @example [1, 2, 1, 4, 5, 4].unique();
	 * @result [1, 2, 4, 5]
	 *
	 * @name unique
	 * @type Array
	 * @cat Plugins/Methods/Array
	 */
	add("unique", function() {
		return this.filter(function(element, index, array) {
			return array.indexOf(element) >= index;
		});
	});
	
})();;

/*--------------------------------------------------------------------------
 /ext/jquery/jquery.autocomplete.js
--------------------------------------------------------------------------*/
/*
 * Autocomplete - jQuery plugin 1.0 Alpha
 *
 * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, Jörn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id$
 *
 */

/*
TODO
- allow users to keep their incomplete value when pressing tab, just mimic the default-browser-autocomplete: tab doesn't select any proposed value
- small bug in your autocomplete,  When setting autoFill:true I would expect formatResult to be called on autofill, it seems not to be the case.
- add a callback to allow decoding the response
- add scrollbars and page down/up, option for height or number of items to be visible without scrolling
- allow modification of not-last value in multiple-fields
@option Number size Limit the number of items to show at once. Default: 
@option Function parse - TEST AND DOCUMENT ME
- add option to display selectbox on focus

$input.bind("show", function() {
	if ( !select.visible() ) {
		onChange(0, true);
	}
});

- reference: http://capxous.com/
  - add "try ..." hints to demo
  - check out demos
*/

/**
 * Provide autocomplete for text-inputs or textareas.
 *
 * Depends on dimensions plugin's offset method for correct positioning of the select box and bgiframe plugin
 * to fix IE's problem with selects.
 *
 * @example $("#input_box").autocomplete("my_autocomplete_backend.php");
 * @before <input id="input_box" />
 * @desc Autocomplete a text-input with remote data. For small to giant datasets.
 *
 * When the user starts typing, a request is send to the specified backend ("my_autocomplete_backend.php"),
 * with a GET parameter named q that contains the current value of the input box and a paremeter "limit" with
 * the value specified for the max option.
 *
 * A value of "foo" would result in this request url: my_autocomplete_backend.php?q=foo&limit=10
 *
 * The result must return with one value on each line. The result is presented in the order
 * the backend sends it.
 *
 * @example $("#input_box").autocomplete(["Cologne", "Berlin", "Munich"]);
 * @before <input id="input_box" />
 * @desc Autcomplete a text-input with local data. For small datasets.
 *
 * @example $.getJSON("my_backend.php", function(data) {
 *   $("#input_box").autocomplete(data);
 * });
 * @before <input id="input_box" />
 * @desc Autcomplete a text-input with data received via AJAX. For small to medium sized datasets.
 *
 * @example $("#mytextarea").autocomplete(["Cologne", "Berlin", "Munich"], {
 *  multiple: true
 * });
 * @before <textarea id="mytextarea" />
 * @desc Autcomplete a textarea with local data (for small datasets). Once the user chooses one
 * value, a separator is appended (by default a comma, see multipleSeparator option) and more values
 * are autocompleted.
 *
 * @name autocomplete
 * @cat Plugins/Autocomplete
 * @type jQuery
 * @param String|Array urlOrData Pass either an URL for remote-autocompletion or an array of data for local auto-completion
 * @param Map options Optional settings
 * @option String inputClass This class will be added to the input box. Default: "ac_input"
 * @option String resultsClass The class for the UL that will contain the result items (result items are LI elements). Default: "ac_results"
 * @option String loadingClass The class for the input box while results are being fetched from the server. Default: "ac_loading"
 * @option Number minChars The minimum number of characters a user has to type before the autocompleter activates. Default: 1
 * @option Number delay The delay in milliseconds the autocompleter waits after a keystroke to activate itself. Default: 400 for remote, 10 for local
 * @option Number cacheLength The number of backend query results to store in cache. If set to 1 (the current result), no caching will happen. Do not set below 1. Default: 10
 * @option Boolean matchSubset Whether or not the autocompleter can use a cache for more specific queries. This means that all matches of "foot" are a subset of all matches for "foo". Usually this is true, and using this options decreases server load and increases performance. Only useful with cacheLength settings bigger than one, like 10. Default: true
 * @option Boolean matchCase Whether or not the comparison is case sensitive. Only important only if you use caching. Default: false
 * @option Boolean matchContains Whether or not the comparison looks inside (i.e. does "ba" match "foo bar") the search results. Only important if you use caching. Don't mix with autofill. Default: false
 * @option Booolean mustMatch If set to true, the autocompleter will only allow results that are presented by the backend. Note that illegal values result in an empty input box. Default: false
 * @option Object extraParams Extra parameters for the backend. If you were to specify { bar:4 }, the autocompleter would call my_autocomplete_backend.php?q=foo&bar=4 (assuming the input box contains "foo"). Default: {}
 * @option Boolean selectFirst If this is set to true, the first autocomplete value will be automatically selected on tab/return, even if it has not been handpicked by keyboard or mouse action. If there is a handpicked (highlighted) result, that result will take precedence. Default: true
 * @option Function|Boolean formatItem Provides advanced markup for an item. For each row of results, this function will be called. If false is returned, the row is skipped. Otherwise the returned value will be displayed inside an LI element in the results list. Autocompleter will provide 3 parameters: the results row, the position of the row in the list of results (starting at 1), and the number of items in the list of results. Default: none, assumes that a single row contains a single value.
 * @option Function formatResult Similar to formatResult, but provides the formatting for the value to be put into the input field. Again three arguments: Data, position (starting with one) and total number of data. Default: none, assumes either plain data to use as result or uses the same value as provided by formatItem.
 * @option Boolean multiple Whether to allow more than one autocomplted-value to enter. Default: false
 * @option String multipleSeparator Seperator to put between values when using multiple option. Default: ", "
 * @option Number width Specify a custom width for the select box. Default: width of the input element
 * @option Boolean autoFill Fill the textinput while still selecting a value, replacing the value if more is type or something else is selected. Default: false
 * @option Number max Limit the number of items in the select box. Is also send as a "limit" parameter with a remote request. Default: 10
 * @option Boolean|Function highlight Whether and how to highlight matches in the select box. Set to false to disable. Set to a function to customize. The function gets the value as the first argument and the search term as the second and must return the formatted value. Default: Wraps the search term in a <strong> element 
 * @option Boolean|String moreItems Whether or not to show the "more items" text if there are more items than are currently be displayed. Set to false to disable. Set to a string to customize the html. Default: Displays "more", surrounded with three arrows.
 */

/**
 * Handle the result of a search event. Is executed when the user selects a value or a
 * programmatic search event is triggered (see search()).
 *
 * You can add and remove (using unbind("result")) this event at any time.
 *
 * @example jQuery('input#suggest').result(function(event, data, formatted) {
 *   jQuery("#result").html( !data ? "No match!" : "Selected: " + formatted);
 * });
 * @desc Bind a handler to the result event to display the selected value in a #result element.
 *    The first argument is a generic event object, in this case with type "result".
 *    The second argument refers to the selected data, which can be a plain string value or an array or object.
 *    The third argument is the formatted value that is inserted into the input field.
 *
 * @param Function handler The event handler, gets a default event object as first and
 * 		the selected list item as second argument.
 * @name result
 * @cat Plugins/Autocomplete
 * @type jQuery
 */

/**
 * Trigger a search event. See result(Function) for binding to that event.
 *
 * A search event mimics the same behaviour as when the user selects a value from
 * the list of autocomplete items. You can use it to execute anything that does something
 * with the selected value, beyond simply putting the value into the input and submitting it.
 *
 * @example jQuery('input#suggest').search();
 * @desc Triggers a search event.
 *
 * @name search
 * @cat Plugins/Autocomplete
 * @type jQuery
 */
 
/**
 * Flush (empty) the cache of matched input's autocompleters.
 *
 * @example jQuery('input#suggest').flushCache();
 *
 * @name flushCache
 * @cat Plugins/Autocomplete
 * @type jQuery
 */

/**
 * Updates the options for the current autocomplete field. This allows 
 * you to change things like the URL, max items to display, etc. If you're
 * changing the URL, be sure to remember to call the flushCache() method.
 *
 * @example jQuery('input#suggest').setOptions({
 *  max: 15
 * });
 * @desc Changes the maximum number of items to display to 15.
 *
 * @name setOptions
 * @cat Plugins/Autocomplete
 * @type jQuery
 */
 
jQuery.fn.extend({
	autocomplete: function(urlOrData, options) {
		var isUrl = typeof urlOrData == "string";
		options = jQuery.extend({}, jQuery.Autocompleter.defaults, {
			url: isUrl ? urlOrData : null,
			data: isUrl ? null : urlOrData,
			delay: isUrl ? jQuery.Autocompleter.defaults.delay : 10
		}, options);
		
		// if highlight is set to false, replace it with a do-nothing function
		options.highlight = options.highlight || function(value) { return value; };
		// if moreItems is false, replace it w/empty string
		options.moreItems = options.moreItems || "";
		
		return this.each(function() {
			new jQuery.Autocompleter(this, options);
		});
	},
	result: function(handler) {
		return this.bind("result", handler);
	},
	search: function(handler) {
		return this.trigger("search", [handler]);
	},
	flushCache: function() {
		return this.trigger("flushCache");
	},
	setOptions: function(options){
		return this.trigger("setOptions", [options]);
	}
});

jQuery.Autocompleter = function(input, options) {

	var KEY = {
		UP: 38,
		DOWN: 40,
		DEL: 46,
		TAB: 9,
		RETURN: 13,
		ESC: 27,
		COMMA: 188
	};

	// Create jQuery object for input element
	var $input = jQuery(input).attr("autocomplete", "off").addClass(options.inputClass);

	var timeout;
	var previousValue = "";
	var cache = jQuery.Autocompleter.Cache(options);
	var hasFocus = 0;
	var lastKeyPressCode;
	var select = jQuery.Autocompleter.Select(options, input, selectCurrent);
	
	$input.keydown(function(event) {
		// track last key pressed
		lastKeyPressCode = event.keyCode;
		switch(event.keyCode) {
		
			case KEY.UP:
				event.preventDefault();
				if ( select.visible() ) {
					select.prev();
				} else {
					onChange(0, true);
				}
				break;
				
			case KEY.DOWN:
				event.preventDefault();
				if ( select.visible() ) {
					select.next();
				} else {
					onChange(0, true);
				}
				break;
			
			// matches also semicolon
			case options.multiple && jQuery.trim(options.multipleSeparator) == "," && KEY.COMMA:
			case KEY.TAB:
			case KEY.RETURN:
				if( selectCurrent() ){
					// make sure to blur off the current field
					if( !options.multiple )
						$input.blur();
					event.preventDefault();
				}
				break;
				
			case KEY.ESC:
				select.hide();
				break;
				
			default:
				clearTimeout(timeout);
				timeout = setTimeout(onChange, options.delay);
				break;
		}
	}).keypress(function() {
		// having fun with opera - remove this binding and Opera submits the form when we select an entry via return
	}).focus(function(){
	  /*----------------------------------------
	   by Stephan Baumeister
	  ----------------------------------------*/
    if (hasFocus == 0)
		{
			var doc = $.browser.msie ? document.body : document;
			$(doc).bind("mousedown", mimicBlur);
		}
		/*--------------------------------------*/		
		
		// track whether the field has focus, we shouldn't process any
		// results if the field no longer has focus
		hasFocus++;				
	})
	/*
  .blur(function() {		
		hasFocus = 0;
		hideResults();		
	})
	*/
	.click(function() {
		// show select when clicking in a focused field
		if ( hasFocus++ > 1 && !select.visible() ) {
			onChange(0, true);
		}
	}).bind("search", function() {
		var fn = (arguments.length > 1) ? arguments[1] : null;
		function findValueCallback(q, data) {
			var result;
			if( data && data.length ) {
				for (var i=0; i < data.length; i++) {
					if( data[i].result.toLowerCase() == q.toLowerCase() ) {
						result = data[i];
						break;
					}
				}
			}
			if( typeof fn == "function" ) fn(result);
			else $input.trigger("result", result && [result.data, result.value]);
		}
		jQuery.each(trimWords($input.val()), function(i, value) {
			request(value, findValueCallback, findValueCallback);
		});
	}).bind("flushCache", function() {
		cache.flush();
	}).bind("setOptions", function() {
		// overwrite the options
		for( var k in arguments[1] ){
			// update the options
			options[k] = arguments[1][k];
			// if we've updated the data, repopulate
			if( k == "data" ) cache.populate();
		}
	});
	
	hideResultsNow();
	
  /*----------------------------------------
   by Stephan Baumeister
  ----------------------------------------*/
	function mimicBlur(evt)
	{
    var target = $(evt.target);
		
		//console.log
		
		if (!target.is(".ac_results") && !target.is(".ac_input"))
		{
			$(this).unbind("mousedown", evt.handler);
			
			hasFocus = 0;
	    hideResults();
		}		
	};
	/*--------------------------------------*/
	
	function selectCurrent() {
		var selected = select.selected();
		if( !selected )
			return false;
		
		var v = selected.result;
		previousValue = v;
		
		if ( options.multiple ) {
			var words = trimWords($input.val());
			if ( words.length > 1 ) {
				v = words.slice(0, words.length - 1).join( options.multipleSeparator ) + options.multipleSeparator + v;
			}
			v += options.multipleSeparator;
		}
		
		$input.val(v);
		hideResultsNow();
		$input.trigger("result", [selected.data, selected.value]);
		return true;
	}
	
	function onChange(crap, skipPrevCheck) {
		if( lastKeyPressCode == KEY.DEL ) {
			select.hide();
			return;
		}
		
		var currentValue = $input.val();
		
		if ( !skipPrevCheck && currentValue == previousValue )
			return;
		
		previousValue = currentValue;
		
		currentValue = lastWord(currentValue);
		if ( currentValue.length >= options.minChars) {
			$input.addClass(options.loadingClass);
			if (!options.matchCase)
				currentValue = currentValue.toLowerCase();
			request(currentValue, receiveData, hideResultsNow);
		} else {
			stopLoading();
			select.hide();
		}
	};
	
	function trimWords(value) {
		if ( !value ) {
			return [""];
		}
		var words = value.split( jQuery.trim( options.multipleSeparator ) );
		var result = [];
		jQuery.each(words, function(i, value) {
			if ( jQuery.trim(value) )
				result[i] = jQuery.trim(value);
		});
		return result;
	}
	
	function lastWord(value) {
		if ( !options.multiple )
			return value;
		var words = trimWords(value);
		return words[words.length - 1];
	}
	
	// fills in the input box w/the first match (assumed to be the best match)
	function autoFill(q, sValue){
		// autofill in the complete box w/the first match as long as the user hasn't entered in more data
		// if the last user key pressed was backspace, don't autofill
		if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != 8 ) {
			// fill in the value (keep the case the user has typed)
			$input.val($input.val() + sValue.substring(lastWord(previousValue).length));
			// select the portion of the value not typed by the user (so the next character will erase)
			jQuery.Autocompleter.Selection(input, previousValue.length, previousValue.length + sValue.length);
		}
	};

	function hideResults() {
		clearTimeout(timeout);
		timeout = setTimeout(hideResultsNow, 200);
	};

	function hideResultsNow() {
		select.hide();
		clearTimeout(timeout);
		stopLoading();
		if (options.mustMatch) {
			// call search and run callback
			$input.search(
				function (result){
					// if no value found, clear the input box
					if( !result ) $input.val("");
				}
			);
		}
	};

	function receiveData(q, data) {
		if ( data && data.length && hasFocus ) {
			stopLoading();
			select.display(data, q);
			autoFill(q, data[0].value);
			select.show();
		} else {
			hideResultsNow();
		}
	};

	function request(term, success, failure) {
		if (!options.matchCase)
			term = term.toLowerCase();
		var data = cache.load(term);
		// recieve the cached data
		if (data && data.length) {
			success(term, data);
		// if an AJAX url has been supplied, try loading the data now
		} else if( (typeof options.url == "string") && (options.url.length > 0) ){
			jQuery.ajax({
				url: options.url,
				global: false,
				data: jQuery.extend({
					q: lastWord(term),
					limit: options.max
				}, options.extraParams),
				success: function(data) {
					var parsed = options.parse && options.parse(data) || parse(data);
					cache.add(term, parsed);
					success(term, parsed);
				}
			});
		} else {
			failure(term);
		}
	}
	
	function parse(data) {
		var parsed = [];
		var rows = data.split("\n");
		for (var i=0; i < rows.length; i++) {
			var row = jQuery.trim(rows[i]);
			if (row) {
				row = row.split("|");
				parsed[parsed.length] = {
					data: row,
					value: row[0],
					result: options.formatResult && options.formatResult(row, row[0]) || row[0]
				};
			}
		}
		return parsed;
	}

	function stopLoading() {
		$input.removeClass(options.loadingClass);
	}

}

jQuery.Autocompleter.defaults = {
	inputClass: "ac_input",
	resultsClass: "ac_results",
	loadingClass: "ac_loading",
	minChars: 1,
	delay: 400,
	matchCase: false,
	matchSubset: true,
	matchContains: false,
	cacheLength: 10,
	mustMatch: false,
	extraParams: {},
	selectFirst: true,
	max: 10,
	moreItems: "&#x25be;&#x25be;&#x25be; more &#x25be;&#x25be;&#x25be;",
	//size: 10,
	autoFill: false,
	width: 0,
	multiple: false,
	multipleSeparator: ", ",
	highlight: function(value, term) {
		return value.replace(new RegExp("(?!<[^<>]*)(" + term + ")(?![^<>]*>)", "gi"), "<strong>$1</strong>");
	}
};

jQuery.Autocompleter.Cache = function(options) {

	var data = {};
	var length = 0;
	
	function matchSubset(s, sub) {
		if (!options.matchCase) 
			s = s.toLowerCase();
		var i = s.indexOf(sub);
		if (i == -1) return false;
		return i == 0 || options.matchContains;
	};
	
	function add(q, value) {
		if (length > options.cacheLength){
			flush();
		}
		if (!data[q]){ 
			length++;
		}
		data[q] = value;
	}
	
	function populate(){
		if( !options.data ) return false;
		// track the matches
		var stMatchSets = {},
			nullData = 0;

		// no url was specified, we need to adjust the cache length to make sure it fits the local data store
		if( !options.url ) options.cacheLength = 1;
		
		// track all options for minChars = 0
		stMatchSets[""] = [];
		
		// loop through the array and create a lookup structure
		jQuery.each(options.data, function(i, rawValue) {
			// if row is a string, make an array otherwise just reference the array
			
			var value = options.formatItem
				? options.formatItem(rawValue, i+1, options.data.length)
				: rawValue;
			if ( value === false )
				return;
				
			var firstChar = value.charAt(0).toLowerCase();
			// if no lookup array for this character exists, look it up now
			if( !stMatchSets[firstChar] ) 
				stMatchSets[firstChar] = [];

			// if the match is a string
			var row = {
				value: value,
				data: rawValue,
				result: options.formatResult && options.formatResult(rawValue) || value
			}
			
			// push the current match into the set list
			stMatchSets[firstChar].push(row);

			// keep track of minChars zero items
			if ( nullData++ < options.max ) {
				stMatchSets[""].push(row);
			}
		});

		// add the data items to the cache
		jQuery.each(stMatchSets, function(i, value) {
			// increase the cache size
			options.cacheLength++;
			// add to the cache
			add(i, value);
		});
	}
	
	// populate any existing data
	populate();
	
	function flush(){
		data = {};
		length = 0;
	}
	
	return {
		flush: flush,
		add: add,
		populate: populate,
		load: function(q) {
			if (!options.cacheLength || !length)
				return null;
			/* 
			 * if dealing w/local data and matchContains than we must make sure
			 * to loop through all the data collections looking for matches
			 */
			if( !options.url && options.matchContains ){
				// track all matches
				var csub = [];
				// loop through all the data grids for matches
				for( var k in data ){
					// don't search through the stMatchSets[""] (minChars: 0) cache
					// this prevents duplicates
					if( k.length > 0 ){
						var c = data[k];
						jQuery.each(c, function(i, x) {
							// if we've got a match, add it to the array
							if (matchSubset(x.value, q)) {
								csub.push(x);
							}
						});
					}
				}				
				return csub;
			} else 
			// if the exact item exists, use it
			if (data[q]){
				return data[q];
			} else
			if (options.matchSubset) {
				for (var i = q.length - 1; i >= options.minChars; i--) {
					var c = data[q.substr(0, i)];
					if (c) {
						var csub = [];
						jQuery.each(c, function(i, x) {
							if (matchSubset(x.value, q)) {
								csub[csub.length] = x;
							}
						});
						return csub;
					}
				}
			}
			return null;
		}
	};
};

jQuery.Autocompleter.Select = function (options, input, select) {
	var CLASSES = {
		ACTIVE: "ac_over"
	};
	
	// Create results
	var element = jQuery("<div>")
		.hide()
		.addClass(options.resultsClass)
		.css("position", "absolute")
		.appendTo("body");
	
	var list = jQuery("<ul>").appendTo(element).mouseover( function(event) {
		active = jQuery("li", list).removeClass().index(target(event));
		jQuery(target(event)).addClass(CLASSES.ACTIVE);
	}).mouseout( function(event) {
		jQuery(target(event)).removeClass();
	}).click(function(event) {
		jQuery(target(event)).addClass(CLASSES.ACTIVE);
		select();
		input.focus();
		return false;
	});
	var listItems,
		active = -1,
		data,
		term = "";
		
	if( options.moreItems.length > 0 ) 
		var moreItems = jQuery("<div>")
			.addClass("ac_moreItems")
			.css("display", "none")
			.html(options.moreItems)
			.appendTo(element);
		
	if( options.width > 0 )
		element.css("width", options.width);
		
	function target(event) {
		var element = event.target;
		while(element.tagName != "LI")
			element = element.parentNode;
		return element;
	}

	function moveSelect(step) {
		active += step;
		wrapSelection();
		listItems.removeClass().eq(active).addClass(CLASSES.ACTIVE);
	};
	
	function wrapSelection() {
		if (active < 0) {
			active = listItems.size() - 1;
		} else if (active >= listItems.size()) {
			active = 0;
		}
	}
	
	function limitNumberOfItems(available) {
		return (options.max > 0) && (options.max < available)
			? options.max
			: available;
	}
	
	function fillList() {
		list.empty();
		var num = limitNumberOfItems(data.length);
		for (var i=0; i < num; i++) {
			if (!data[i])
				continue;
			
			var formatted = options.formatItem ? options.formatItem(data[i].data, i+1, num, data[i].value) : data[i].value;
			if ( formatted === false )
				continue;
			
			jQuery("<li>").html( options.highlight(formatted, term) ).appendTo(list)[0].index = i;
		}
		listItems = list.find("li");
		if ( options.selectFirst ) {
			listItems.eq(0).addClass(CLASSES.ACTIVE);
			active = 0;
		}
		if( options.moreItems.length > 0 ) moreItems.css("display", (data.length > num)? "block" : "none");
		list.bgiframe();
	}
	
	return {
		el: element,		
		display: function(d, q) {
			data = d;
			term = q;
			fillList();
		},
		next: function() {
			moveSelect(1);
		},
		prev: function() {
			moveSelect(-1);
		},
		hide: function() {
			element.hide();
			active = -1;
		},
		visible : function() {
			return element.is(":visible");
		},
		current: function() {
			return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]);
		},
		show: function() {
			element.css({
				width: typeof options.width == "string" || options.width > 0 ? options.width : jQuery(input).width()
				//height: jQuery(listItems[0]).height() * options.size,
			}).below(input).show();
		},
		selected: function() {
			return data && data[ listItems.filter("." + CLASSES.ACTIVE)[0].index ];
		}
	};
}

jQuery.Autocompleter.Selection = function(field, start, end) {
	if( field.createTextRange ){
		var selRange = field.createTextRange();
		selRange.collapse(true);
		selRange.moveStart("character", start);
		selRange.moveEnd("character", end);
		selRange.select();
	} else if( field.setSelectionRange ){
		field.setSelectionRange(start, end);
	} else {
		if( field.selectionStart ){
			field.selectionStart = start;
			field.selectionEnd = end;
		}
	}
	field.focus();
};;

/*--------------------------------------------------------------------------
 /ext/jquery/jquery.below.js
--------------------------------------------------------------------------*/
/**
 *
 * Copyright (c) 2007 Sam Collett (http://www.texotela.co.uk)
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 * 
 */

 
/**
 * Places selected element under another one
 *
 * @name     below
 * @name     element Which element to place the current one under
 * @param    options Hash with the following options:
 *                   adjustRight   How many pixels to adjust right by
 *                   adjustDown    How many pixels to adjust down by
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @example  $("#mytip").below("#myinput");
 * @example  $("#mytip").below("#myinput", {adjustRight: 10});
 */
jQuery.fn.below = function(element, options)
{
	element = element || null;
	options = jQuery.extend({adjustRight: 0, adjustDown: 0}, options);
	return this.each(
		function()
		{
			if(element == null) return false;
			var what = jQuery(element);
			var left = what[0].offsetWidth - options.adjustRight, top = what[0].offsetHeight + options.adjustDown;
			if(jQuery.browser.opera)
			{
				var version = navigator.userAgent.match(/\d+\.\d+/);
				if(version < 9)
				{
					left += (parseInt(jQuery.css(what[0], 'borderLeftWidth'))  || 0) +
						(parseInt(jQuery.css(what.parent()[0], 'paddingLeft'))  || 0);
				}
			}
			what.after(this);
			jQuery(this).css(
				{
					position: "absolute",
					display: "inline",
					marginLeft: "-" + left  + "px",
					marginTop: top + "px"
				}
			);
		}
	);
};

/*--------------------------------------------------------------------------
 /ext/jquery/jquery.bgiframe.js
--------------------------------------------------------------------------*/
/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-06-19 20:23:36 -0500 (Tue, 19 Jun 2007) $
 * $Rev: 2110 $
 *
 * Version 2.1
 */

(function($){

/**
 * The bgiframe is chainable and applies the iframe hack to get
 * around zIndex issues in IE6. It will only apply itself in IE
 * and adds a class to the iframe called 'bgiframe'. The iframe
 * is appeneded as the first child of the matched element(s)
 * with a tabIndex and zIndex of -1.
 *
 * By default the plugin will take borders, sized with pixel units,
 * into account. If a different unit is used for the border's width,
 * then you will need to use the top and left settings as explained below.
 *
 * NOTICE: This plugin has been reported to cause perfromance problems
 * when used on elements that change properties (like width, height and
 * opacity) a lot in IE6. Most of these problems have been caused by
 * the expressions used to calculate the elements width, height and
 * borders. Some have reported it is due to the opacity filter. All
 * these settings can be changed if needed as explained below.
 *
 * @example $('div').bgiframe();
 * @before <div><p>Paragraph</p></div>
 * @result <div><iframe class="bgiframe".../><p>Paragraph</p></div>
 *
 * @param Map settings Optional settings to configure the iframe.
 * @option String|Number top The iframe must be offset to the top
 * 		by the width of the top border. This should be a negative
 *      number representing the border-top-width. If a number is
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used.
 * 		By default the value is "auto" which will use an expression
 * 		to get the border-top-width if it is in pixels.
 * @option String|Number left The iframe must be offset to the left
 * 		by the width of the left border. This should be a negative
 *      number representing the border-left-width. If a number is
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used.
 * 		By default the value is "auto" which will use an expression
 * 		to get the border-left-width if it is in pixels.
 * @option String|Number width This is the width of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetWidth.
 * @option String|Number height This is the height of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetHeight.
 * @option Boolean opacity This is a boolean representing whether or not
 * 		to use opacity. If set to true, the opacity of 0 is applied. If
 *		set to false, the opacity filter is not applied. Default: true.
 * @option String src This setting is provided so that one could change
 *		the src of the iframe to whatever they need.
 *		Default: "javascript:false;"
 *
 * @name bgiframe
 * @type jQuery
 * @cat Plugins/bgiframe
 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 */
$.fn.bgIframe = $.fn.bgiframe = function(s) {
  // This is only for IE6
  if ( $.browser.msie && parseInt($.browser.version) <= 6 ) {
    s = $.extend({
      top     : 'auto', // auto == .currentStyle.borderTopWidth
      left    : 'auto', // auto == .currentStyle.borderLeftWidth
      width   : 'auto', // auto == offsetWidth
      height  : 'auto', // auto == offsetHeight
      opacity : true,
      src     : 'javascript:false;'
    }, s || {});
    var prop = function(n){return n&&n.constructor==Number?n+'px':n;},
        html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
                   'style="display:block;position:absolute;z-index:-1;'+
                     (s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
                 'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
                 'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
                 'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
                 'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
          '"/>';
    return this.each(function() {
      if ( $('> iframe.bgiframe', this).length == 0 )
        this.insertBefore( document.createElement(html), this.firstChild );
    });
  }
  return this;
};

// Add browser.version if it doesn't exist
// Additional hack for use with Adressen-Online and Mozilla Firefox with user specific user agent (e.g. 'googlebot')
//if (!$.browser.version)
//  $.browser.version = navigator.userAgent.toLowerCase().match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)[1];
if (!$.browser.version)
  $.browser.version = 7;

})(jQuery);;

/*--------------------------------------------------------------------------
 /ext/jquery/jquery.blockUI.js
--------------------------------------------------------------------------*/
/*
 * jQuery blockUI plugin
 * Version 1.33  (09/14/2007)
 * @requires jQuery v1.1.1
 *
 * $Id$
 *
 * Examples at: http://malsup.com/jquery/block/
 * Copyright (c) 2007 M. Alsup
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */
 (function($) {
/**
 * blockUI provides a mechanism for blocking user interaction with a page (or parts of a page).
 * This can be an effective way to simulate synchronous behavior during ajax operations without
 * locking the browser.  It will prevent user operations for the current page while it is
 * active ane will return the page to normal when it is deactivate.  blockUI accepts the following
 * two optional arguments:
 *
 *   message (String|Element|jQuery): The message to be displayed while the UI is blocked. The message
 *              argument can be a plain text string like "Processing...", an HTML string like
 *              "<h1><img src="busy.gif" /> Please wait...</h1>", a DOM element, or a jQuery object.
 *              The default message is "<h1>Please wait...</h1>"
 *
 *   css (Object):  Object which contains css property/values to override the default styles of
 *              the message.  Use this argument if you wish to override the default
 *              styles.  The css Object should be in a format suitable for the jQuery.css
 *              function.  For example:
 *              $.blockUI({
 *                    backgroundColor: '#ff8',
 *                    border: '5px solid #f00,
 *                    fontWeight: 'bold'
 *              });
 *
 * The default blocking message used when blocking the entire page is "<h1>Please wait...</h1>"
 * but this can be overridden by assigning a value to $.blockUI.defaults.pageMessage in your
 * own code.  For example:
 *
 *      $.blockUI.defaults.pageMessage = "<h1>Bitte Wartezeit</h1>";
 *
 * The default message styling can also be overridden.  For example:
 *
 *      $.extend($.blockUI.defaults.pageMessageCSS, { color: '#00a', backgroundColor: '#0f0' });
 *
 * The default styles work well for simple messages like "Please wait", but for longer messages
 * style overrides may be necessary.
 *
 * @example  $.blockUI();
 * @desc prevent user interaction with the page (and show the default message of 'Please wait...')
 *
 * @example  $.blockUI( { backgroundColor: '#f00', color: '#fff'} );
 * @desc prevent user interaction and override the default styles of the message to use a white on red color scheme
 *
 * @example  $.blockUI('Processing...');
 * @desc prevent user interaction and display the message "Processing..." instead of the default message
 *
 * @name blockUI
 * @param String|jQuery|Element message Message to display while the UI is blocked
 * @param Object css Style object to control look of the message
 * @cat Plugins/blockUI
 */
$.blockUI = function(msg, css, opts) {
    $.blockUI.impl.install(window, msg, css, opts);
};

// expose version number so other plugins can interogate
$.blockUI.version = 1.33;

/**
 * unblockUI removes the UI block that was put in place by blockUI
 *
 * @example  $.unblockUI();
 * @desc unblocks the page
 *
 * @name unblockUI
 * @cat Plugins/blockUI
 */
$.unblockUI = function(opts) {
    $.blockUI.impl.remove(window, opts);
};

/**
 * Blocks user interaction with the selected elements.  (Hat tip: Much of
 * this logic comes from Brandon Aaron's bgiframe plugin.  Thanks, Brandon!)
 * By default, no message is displayed when blocking elements.
 *
 * @example  $('div.special').block();
 * @desc prevent user interaction with all div elements with the 'special' class.
 *
 * @example  $('div.special').block('Please wait');
 * @desc prevent user interaction with all div elements with the 'special' class
 * and show a message over the blocked content.
 *
 * @name block
 * @type jQuery
 * @param String|jQuery|Element message Message to display while the element is blocked
 * @param Object css Style object to control look of the message
 * @cat Plugins/blockUI
 */
$.fn.block = function(msg, css, opts) {
    return this.each(function() {
    if (!this.$pos_checked) {
            if ($.css(this,"position") == 'static')
                this.style.position = 'relative';
            if ($.browser.msie) this.style.zoom = 1; // force 'hasLayout' in IE
            this.$pos_checked = 1;
        }
        $.blockUI.impl.install(this, msg, css, opts);
    });
};

/**
 * Unblocks content that was blocked by "block()"
 *
 * @example  $('div.special').unblock();
 * @desc unblocks all div elements with the 'special' class.
 *
 * @name unblock
 * @type jQuery
 * @cat Plugins/blockUI
 */
$.fn.unblock = function(opts) {
    return this.each(function() {
        $.blockUI.impl.remove(this, opts);
    });
};

/**
 * displays the first matched element in a "display box" above a page overlay.
 *
 * @example  $('#myImage').displayBox();
 * @desc displays "myImage" element in a box
 *
 * @name displayBox
 * @type jQuery
 * @cat Plugins/blockUI
 */
$.fn.displayBox = function(css, fn, isFlash) {
    var msg = this[0];
    if (!msg) return;
    var $msg = $(msg);
    css = css || {};

    var w = $msg.width()  || $msg.attr('width')  || css.width  || $.blockUI.defaults.displayBoxCSS.width;
    var h = $msg.height() || $msg.attr('height') || css.height || $.blockUI.defaults.displayBoxCSS.height ;
    if (w[w.length-1] == '%') {
        var ww = document.documentElement.clientWidth || document.body.clientWidth;
        w = parseInt(w) || 100;
        w = (w * ww) / 100;
    }
    if (h[h.length-1] == '%') {
        var hh = document.documentElement.clientHeight || document.body.clientHeight;
        h = parseInt(h) || 100;
        h = (h * hh) / 100;
    }

    var ml = '-' + parseInt(w)/2 + 'px';
    var mt = '-' + parseInt(h)/2 + 'px';

    // supress opacity on overlay if displaying flash content on mac/ff platform
    var ua = navigator.userAgent.toLowerCase();
    var opts = {
        displayMode: fn || 1,
        noalpha: isFlash && /mac/.test(ua) && /firefox/.test(ua)
    };

    $.blockUI.impl.install(window, msg, { width: w, height: h, marginTop: mt, marginLeft: ml }, opts);
};


// override these in your code to change the default messages and styles
$.blockUI.defaults = {
    // the message displayed when blocking the entire page
    pageMessage:    '<h1>Please wait...</h1>',
    // the message displayed when blocking an element
    elementMessage: '', // none
    // styles for the overlay iframe
    overlayCSS:  { backgroundColor: '#fff', opacity: '0.5' },
    // styles for the message when blocking the entire page
    pageMessageCSS:    { width:'250px', margin:'-50px 0 0 -125px', top:'50%', left:'50%', textAlign:'center', color:'#000', backgroundColor:'#fff', border:'3px solid #aaa' },
    // styles for the message when blocking an element
    elementMessageCSS: { width:'250px', padding:'10px', textAlign:'center', backgroundColor:'#fff'},
    // styles for the displayBox
    displayBoxCSS: { width: '400px', height: '400px', top:'50%', left:'50%' },
    // allow body element to be stetched in ie6
    ie6Stretch: 1,
    // supress tab nav from leaving blocking content?
    allowTabToLeave: 0,
    // Title attribute for overlay when using displayBox
    closeMessage: 'Click to close',
    // use fadeOut effect when unblocking (can be overridden on unblock call)
    fadeOut:  1,
    // fadeOut transition time in millis
    fadeTime: 400
};

// the gory details
$.blockUI.impl = {
    box: null,
    boxCallback: null,
    pageBlock: null,
    pageBlockEls: [],
    op8: window.opera && window.opera.version() < 9,
    ie6: $.browser.msie && /MSIE 6.0/.test(navigator.userAgent),
    install: function(el, msg, css, opts) {
        opts = opts || {};
        this.boxCallback = typeof opts.displayMode == 'function' ? opts.displayMode : null;
        this.box = opts.displayMode ? msg : null;
        var full = (el == window);

        // use logical settings for opacity support based on browser but allow overrides via opts arg
        var noalpha = this.op8 || $.browser.mozilla && /Linux/.test(navigator.platform);
        if (typeof opts.alphaOverride != 'undefined')
            noalpha = opts.alphaOverride == 0 ? 1 : 0;

        if (full && this.pageBlock) this.remove(window, {fadeOut:0});
        // check to see if we were only passed the css object (a literal)
        if (msg && typeof msg == 'object' && !msg.jquery && !msg.nodeType) {
            css = msg;
            msg = null;
        }
        msg = msg ? (msg.nodeType ? $(msg) : msg) : full ? $.blockUI.defaults.pageMessage : $.blockUI.defaults.elementMessage;
        if (opts.displayMode)
            var basecss = jQuery.extend({}, $.blockUI.defaults.displayBoxCSS);
        else
            var basecss = jQuery.extend({}, full ? $.blockUI.defaults.pageMessageCSS : $.blockUI.defaults.elementMessageCSS);
        css = jQuery.extend(basecss, css || {});
        var f = ($.browser.msie) ? $('<iframe class="blockUI" style="z-index:1000;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="javascript:false;"></iframe>')
                                 : $('<div class="blockUI" style="display:none"></div>');
        var w = $('<div class="blockUI" style="z-index:1001;cursor:wait;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
        var m = full ? $('<div class="blockUI blockMsg" style="z-index:1002;cursor:wait;padding:0;position:fixed"></div>')
                     : $('<div class="blockUI" style="display:none;z-index:1002;cursor:wait;position:absolute"></div>');
        w.css('position', full ? 'fixed' : 'absolute');
        if (msg) m.css(css);
        if (!noalpha) w.css($.blockUI.defaults.overlayCSS);
        if (this.op8) w.css({ width:''+el.clientWidth,height:''+el.clientHeight }); // lame
        if ($.browser.msie) f.css('opacity','0.0');

        $([f[0],w[0],m[0]]).appendTo(full ? 'body' : el);

        // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
        var expr = $.browser.msie && (!$.boxModel || $('object,embed', full ? null : el).length > 0);
        if (this.ie6 || expr) {
            // stretch content area if it's short
            if (full && $.blockUI.defaults.ie6Stretch && $.boxModel)
                $('html,body').css('height','100%');

            // fix ie6 problem when blocked element has a border width
            if ((this.ie6 || !$.boxModel) && !full) {
                var t = this.sz(el,'borderTopWidth'), l = this.sz(el,'borderLeftWidth');
                var fixT = t ? '(0 - '+t+')' : 0;
                var fixL = l ? '(0 - '+l+')' : 0;
            }

            // simulate fixed position
            $.each([f,w,m], function(i,o) {
                var s = o[0].style;
                s.position = 'absolute';
                if (i < 2) {
                    full ? s.setExpression('height','document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + "px"')
                         : s.setExpression('height','this.parentNode.offsetHeight + "px"');
                    full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"')
                         : s.setExpression('width','this.parentNode.offsetWidth + "px"');
                    if (fixL) s.setExpression('left', fixL);
                    if (fixT) s.setExpression('top', fixT);
                }
                else {
                    if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
                    s.marginTop = 0;
                }
            });
        }
        if (opts.displayMode) {
            w.css('cursor','default').attr('title', $.blockUI.defaults.closeMessage);
            m.css('cursor','default');
            $([f[0],w[0],m[0]]).removeClass('blockUI').addClass('displayBox');
            $().click($.blockUI.impl.boxHandler).bind('keypress', $.blockUI.impl.boxHandler);
        }
        else
            this.bind(1, el);
        m.append(msg).show();
        if (msg.jquery) msg.show();
        if (opts.displayMode) return;
        if (full) {
            this.pageBlock = m[0];
            this.pageBlockEls = $(':input:enabled:visible',this.pageBlock);
            setTimeout(this.focus, 20);
        }
        else this.center(m[0]);
    },
    remove: function(el, opts) {
        var o = $.extend({}, $.blockUI.defaults, opts);
        this.bind(0, el);
        var full = el == window;
        var els = full ? $('body').children().filter('.blockUI') : $('.blockUI', el);
        if (full) this.pageBlock = this.pageBlockEls = null;

        if (o.fadeOut) {
            els.fadeOut(o.fadeTime, function() {
                if (this.parentNode) this.parentNode.removeChild(this);
            });
        }
        else els.remove();
    },
    boxRemove: function(el) {
        $().unbind('click',$.blockUI.impl.boxHandler).unbind('keypress', $.blockUI.impl.boxHandler);
        if (this.boxCallback)
            this.boxCallback(this.box);
        $('body .displayBox').hide().remove();
    },
    // event handler to suppress keyboard/mouse events when blocking
    handler: function(e) {
        if (e.keyCode && e.keyCode == 9) {
            if ($.blockUI.impl.pageBlock && !$.blockUI.defaults.allowTabToLeave) {
                var els = $.blockUI.impl.pageBlockEls;
                var fwd = !e.shiftKey && e.target == els[els.length-1];
                var back = e.shiftKey && e.target == els[0];
                if (fwd || back) {
                    setTimeout(function(){$.blockUI.impl.focus(back)},10);
                    return false;
                }
            }
        }
        if ($(e.target).parents('div.blockMsg').length > 0)
            return true;
        return $(e.target).parents().children().filter('div.blockUI').length == 0;
    },
    boxHandler: function(e) {
        if ((e.keyCode && e.keyCode == 27) || (e.type == 'click' && $(e.target).parents('div.blockMsg').length == 0))
            $.blockUI.impl.boxRemove();
        return true;
    },
    // bind/unbind the handler
    bind: function(b, el) {
        var full = el == window;
        // don't bother unbinding if there is nothing to unbind
        if (!b && (full && !this.pageBlock || !full && !el.$blocked)) return;
        if (!full) el.$blocked = b;
        var $e = $(el).find('a,:input');
        $.each(['mousedown','mouseup','keydown','keypress','click'], function(i,o) {
            $e[b?'bind':'unbind'](o, $.blockUI.impl.handler);
        });
    },
    focus: function(back) {
        if (!$.blockUI.impl.pageBlockEls) return;
        var e = $.blockUI.impl.pageBlockEls[back===true ? $.blockUI.impl.pageBlockEls.length-1 : 0];
        if (e) e.focus();
    },
    center: function(el) {
    var p = el.parentNode, s = el.style;
        var l = ((p.offsetWidth - el.offsetWidth)/2) - this.sz(p,'borderLeftWidth');
        var t = ((p.offsetHeight - el.offsetHeight)/2) - this.sz(p,'borderTopWidth');
        s.left = l > 0 ? (l+'px') : '0';
        s.top  = t > 0 ? (t+'px') : '0';
    },
    sz: function(el, p) { return parseInt($.css(el,p))||0; }
};

})(jQuery);;

/*--------------------------------------------------------------------------
 /ext/jquery/jquery.dimensions.js
--------------------------------------------------------------------------*/
/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-08-17 13:14:11 -0500 (Fri, 17 Aug 2007) $
 * $Rev: 2759 $
 *
 * Version: 1.1.2
 *
 * Requires: jQuery 1.1.3+
 */
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}('(9($){l e=$.1q.C,r=$.1q.r;$.1q.M({C:9(){3(!1[0])f();3(1[0]==p)3($.7.O||($.7.E&&U($.7.13)>11))6 n.19-(($(5).C()>n.19)?i():0);k 3($.7.E)6 n.19;k 6 $.I&&5.P.1E||5.o.1E;3(1[0]==5)6 1C.1y(($.I&&5.P.1w||5.o.1w),5.o.1u);6 e.1T(1,1P)},r:9(){3(!1[0])f();3(1[0]==p)3($.7.O||($.7.E&&U($.7.13)>11))6 n.1b-(($(5).r()>n.1b)?i():0);k 3($.7.E)6 n.1b;k 6 $.I&&5.P.1N||5.o.1N;3(1[0]==5)3($.7.1M){l a=n.1p;n.1a(27,n.1o);l b=n.1p;n.1a(a,n.1o);6 5.o.1c+b}k 6 1C.1y((($.I&&!$.7.E)&&5.P.1L||5.o.1L),5.o.1c);6 r.1T(1,1P)},19:9(){3(!1[0])f();6 1[0]==p||1[0]==5?1.C():1.14(\':N\')?1[0].1u-h(1,\'q\')-h(1,\'1I\'):1.C()+h(1,\'1h\')+h(1,\'1H\')},1b:9(){3(!1[0])f();6 1[0]==p||1[0]==5?1.r():1.14(\':N\')?1[0].1c-h(1,\'s\')-h(1,\'1F\'):1.r()+h(1,\'1v\')+h(1,\'1D\')},21:9(a){3(!1[0])f();a=$.M({A:w},a||{});6 1[0]==p||1[0]==5?1.C():1.14(\':N\')?1[0].1u+(a.A?(h(1,\'L\')+h(1,\'1x\')):0):1.C()+h(1,\'q\')+h(1,\'1I\')+h(1,\'1h\')+h(1,\'1H\')+(a.A?(h(1,\'L\')+h(1,\'1x\')):0)},1Y:9(a){3(!1[0])f();a=$.M({A:w},a||{});6 1[0]==p||1[0]==5?1.r():1.14(\':N\')?1[0].1c+(a.A?(h(1,\'K\')+h(1,\'1U\')):0):1.r()+h(1,\'s\')+h(1,\'1F\')+h(1,\'1v\')+h(1,\'1D\')+(a.A?(h(1,\'K\')+h(1,\'1U\')):0)},m:9(a){3(!1[0])f();3(a!=1S)6 1.1Q(9(){3(1==p||1==5)p.1a(a,$(p).u());k 1.m=a});3(1[0]==p||1[0]==5)6 n.1p||$.I&&5.P.m||5.o.m;6 1[0].m},u:9(a){3(!1[0])f();3(a!=1S)6 1.1Q(9(){3(1==p||1==5)p.1a($(p).m(),a);k 1.u=a});3(1[0]==p||1[0]==5)6 n.1o||$.I&&5.P.u||5.o.u;6 1[0].u},12:9(a){6 1.1O({A:w,J:w,v:1.z()},a)},1O:9(b,c){3(!1[0])f();l x=0,y=0,H=0,G=0,8=1[0],4=1[0],T,10,Z=$.D(8,\'12\'),F=$.7.1M,S=$.7.26,18=$.7.O,1n=$.7.E,R=$.7.E&&U($.7.13)>11,1m=w,1l=w,b=$.M({A:Q,15:w,1k:w,J:Q,1K:w,v:5.o},b||{});3(b.1K)6 1.1J(b,c);3(b.v.1j)b.v=b.v[0];3(8.B==\'Y\'){x=8.V;y=8.X;3(F){x+=h(8,\'K\')+(h(8,\'s\')*2);y+=h(8,\'L\')+(h(8,\'q\')*2)}k 3(18){x+=h(8,\'K\');y+=h(8,\'L\')}k 3((S&&1g.I)){x+=h(8,\'s\');y+=h(8,\'q\')}k 3(R){x+=h(8,\'K\')+h(8,\'s\');y+=h(8,\'L\')+h(8,\'q\')}}k{17{10=$.D(4,\'12\');x+=4.V;y+=4.X;3((F&&!4.B.1G(/^t[d|h]$/i))||S||R){x+=h(4,\'s\');y+=h(4,\'q\');3(F&&10==\'1i\')1m=Q;3(S&&10==\'25\')1l=Q}T=4.z||5.o;3(b.J||F){17{3(b.J){H+=4.m;G+=4.u}3(18&&($.D(4,\'24\')||\'\').1G(/23-22|20/)){H=H-((4.m==4.V)?4.m:0);G=G-((4.u==4.X)?4.u:0)}3(F&&4!=8&&$.D(4,\'1e\')!=\'N\'){x+=h(4,\'s\');y+=h(4,\'q\')}4=4.1B}W(4!=T)}4=T;3(4==b.v&&!(4.B==\'Y\'||4.B==\'1d\')){3(F&&4!=8&&$.D(4,\'1e\')!=\'N\'){x+=h(4,\'s\');y+=h(4,\'q\')}3(((1n&&!R)||18)&&10!=\'1r\'){x-=h(T,\'s\');y-=h(T,\'q\')}1A}3(4.B==\'Y\'||4.B==\'1d\'){3(((1n&&!R)||(S&&$.I))&&Z!=\'1i\'&&Z!=\'1z\'){x+=h(4,\'K\');y+=h(4,\'L\')}3(R||(F&&!1m&&Z!=\'1z\')||(S&&Z==\'1r\'&&!1l)){x+=h(4,\'s\');y+=h(4,\'q\')}1A}}W(4)}l a=j(8,b,x,y,H,G);3(c){$.M(c,a);6 1}k{6 a}},1J:9(b,c){3(!1[0])f();l x=0,y=0,H=0,G=0,4=1[0],z,b=$.M({A:Q,15:w,1k:w,J:Q,v:5.o},b||{});3(b.v.1j)b.v=b.v[0];17{x+=4.V;y+=4.X;z=4.z||5.o;3(b.J){17{H+=4.m;G+=4.u;4=4.1B}W(4!=z)}4=z}W(4&&4.B!=\'Y\'&&4.B!=\'1d\'&&4!=b.v);l a=j(1[0],b,x,y,H,G);3(c){$.M(c,a);6 1}k{6 a}},z:9(){3(!1[0])f();l a=1[0].z;W(a&&(a.B!=\'Y\'&&$.D(a,\'12\')==\'1r\'))a=a.z;6 $(a)}});l f=9(){1Z"1X: 1g 1W 14 1V";};l h=9(a,b){6 U($.D(a.1j?a[0]:a,b))||0};l j=9(a,b,x,y,d,c){3(!b.A){x-=h(a,\'K\');y-=h(a,\'L\')}3(b.15&&(($.7.E&&U($.7.13)<11)||$.7.O)){x+=h(a,\'s\');y+=h(a,\'q\')}k 3(!b.15&&!(($.7.E&&U($.7.13)<11)||$.7.O)){x-=h(a,\'s\');y-=h(a,\'q\')}3(b.1k){x+=h(a,\'1v\');y+=h(a,\'1h\')}3(b.J&&(!$.7.O||a.V!=a.m&&a.X!=a.m)){d-=a.m;c-=a.u}6 b.J?{1f:y-c,1t:x-d,u:c,m:d}:{1f:y,1t:x}};l g=0;l i=9(){3(!g){l a=$(\'<1s>\').D({r:16,C:16,1e:\'2d\',12:\'1i\',1f:-1R,1t:-1R}).2c(\'o\');g=16-a.2b(\'<1s>\').2a(\'1s\').D({r:\'16%\',C:29}).r();a.28()}6 g}})(1g);',62,138,'|this||if|parent|document|return|browser|elem|function|||||||||||else|var|scrollLeft|self|body|window|borderTopWidth|width|borderLeftWidth||scrollTop|relativeTo|false|||offsetParent|margin|tagName|height|css|safari|mo|st|sl|boxModel|scroll|marginLeft|marginTop|extend|visible|opera|documentElement|true|sf3|ie|op|parseInt|offsetLeft|while|offsetTop|BODY|elemPos|parPos|520|position|version|is|border|100|do|oa|innerHeight|scrollTo|innerWidth|offsetWidth|HTML|overflow|top|jQuery|paddingTop|absolute|jquery|padding|relparent|absparent|sf|pageYOffset|pageXOffset|fn|static|div|left|offsetHeight|paddingLeft|scrollHeight|marginBottom|max|fixed|break|parentNode|Math|paddingRight|clientHeight|borderRightWidth|match|paddingBottom|borderBottomWidth|offsetLite|lite|scrollWidth|mozilla|clientWidth|offset|arguments|each|1000|undefined|apply|marginRight|empty|collection|Dimensions|outerWidth|throw|inline|outerHeight|row|table|display|relative|msie|99999999|remove|200|find|append|appendTo|auto'.split('|'),0,{}));

/*--------------------------------------------------------------------------
 /ext/jquery/jquery.form.js
--------------------------------------------------------------------------*/
/*
 * jQuery Form Plugin
 * @requires jQuery v1.1 or later
 *
 * Examples at: http://malsup.com/jquery/form/
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id$
 */
 (function($) {
/**
 * ajaxSubmit() provides a mechanism for submitting an HTML form using AJAX.
 *
 * ajaxSubmit accepts a single argument which can be either a success callback function
 * or an options Object.  If a function is provided it will be invoked upon successful
 * completion of the submit and will be passed the response from the server.
 * If an options Object is provided, the following attributes are supported:
 *
 *  target:   Identifies the element(s) in the page to be updated with the server response.
 *            This value may be specified as a jQuery selection string, a jQuery object,
 *            or a DOM element.
 *            default value: null
 *
 *  url:      URL to which the form data will be submitted.
 *            default value: value of form's 'action' attribute
 *
 *  type:     The method in which the form data should be submitted, 'GET' or 'POST'.
 *            default value: value of form's 'method' attribute (or 'GET' if none found)
 *
 *  data:     Additional data to add to the request, specified as key/value pairs (see $.ajax).
 *
 *  beforeSubmit:  Callback method to be invoked before the form is submitted.
 *            default value: null
 *
 *  success:  Callback method to be invoked after the form has been successfully submitted
 *            and the response has been returned from the server
 *            default value: null
 *
 *  dataType: Expected dataType of the response.  One of: null, 'xml', 'script', or 'json'
 *            default value: null
 *
 *  semantic: Boolean flag indicating whether data must be submitted in semantic order (slower).
 *            default value: false
 *
 *  resetForm: Boolean flag indicating whether the form should be reset if the submit is successful
 *
 *  clearForm: Boolean flag indicating whether the form should be cleared if the submit is successful
 *
 *
 * The 'beforeSubmit' callback can be provided as a hook for running pre-submit logic or for
 * validating the form data.  If the 'beforeSubmit' callback returns false then the form will
 * not be submitted. The 'beforeSubmit' callback is invoked with three arguments: the form data
 * in array format, the jQuery object, and the options object passed into ajaxSubmit.
 * The form data array takes the following form:
 *
 *     [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
 *
 * If a 'success' callback method is provided it is invoked after the response has been returned
 * from the server.  It is passed the responseText or responseXML value (depending on dataType).
 * See jQuery.ajax for further details.
 *
 *
 * The dataType option provides a means for specifying how the server response should be handled.
 * This maps directly to the jQuery.httpData method.  The following values are supported:
 *
 *      'xml':    if dataType == 'xml' the server response is treated as XML and the 'success'
 *                   callback method, if specified, will be passed the responseXML value
 *      'json':   if dataType == 'json' the server response will be evaluted and passed to
 *                   the 'success' callback, if specified
 *      'script': if dataType == 'script' the server response is evaluated in the global context
 *
 *
 * Note that it does not make sense to use both the 'target' and 'dataType' options.  If both
 * are provided the target will be ignored.
 *
 * The semantic argument can be used to force form serialization in semantic order.
 * This is normally true anyway, unless the form contains input elements of type='image'.
 * If your form must be submitted with name/value pairs in semantic order and your form
 * contains an input of type='image" then pass true for this arg, otherwise pass false
 * (or nothing) to avoid the overhead for this logic.
 *
 *
 * When used on its own, ajaxSubmit() is typically bound to a form's submit event like this:
 *
 * $("#form-id").submit(function() {
 *     $(this).ajaxSubmit(options);
 *     return false; // cancel conventional submit
 * });
 *
 * When using ajaxForm(), however, this is done for you.
 *
 * @example
 * $('#myForm').ajaxSubmit(function(data) {
 *     alert('Form submit succeeded! Server returned: ' + data);
 * });
 * @desc Submit form and alert server response
 *
 *
 * @example
 * var options = {
 *     target: '#myTargetDiv'
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc Submit form and update page element with server response
 *
 *
 * @example
 * var options = {
 *     success: function(responseText) {
 *         alert(responseText);
 *     }
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc Submit form and alert the server response
 *
 *
 * @example
 * var options = {
 *     beforeSubmit: function(formArray, jqForm) {
 *         if (formArray.length == 0) {
 *             alert('Please enter data.');
 *             return false;
 *         }
 *     }
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc Pre-submit validation which aborts the submit operation if form data is empty
 *
 *
 * @example
 * var options = {
 *     url: myJsonUrl.php,
 *     dataType: 'json',
 *     success: function(data) {
 *        // 'data' is an object representing the the evaluated json data
 *     }
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc json data returned and evaluated
 *
 *
 * @example
 * var options = {
 *     url: myXmlUrl.php,
 *     dataType: 'xml',
 *     success: function(responseXML) {
 *        // responseXML is XML document object
 *        var data = $('myElement', responseXML).text();
 *     }
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc XML data returned from server
 *
 *
 * @example
 * var options = {
 *     resetForm: true
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc submit form and reset it if successful
 *
 * @example
 * $('#myForm).submit(function() {
 *    $(this).ajaxSubmit();
 *    return false;
 * });
 * @desc Bind form's submit event to use ajaxSubmit
 *
 *
 * @name ajaxSubmit
 * @type jQuery
 * @param options  object literal containing options which control the form submission process
 * @cat Plugins/Form
 * @return jQuery
 */
$.fn.ajaxSubmit = function(options) {
    if (typeof options == 'function')
        options = { success: options };

    options = $.extend({
        url:  this.attr('action') || window.location,
        type: this.attr('method') || 'GET'
    }, options || {});

    // hook for manipulating the form data before it is extracted;
    // convenient for use with rich editors like tinyMCE or FCKEditor
    var veto = {};
    $.event.trigger('form.pre.serialize', [this, options, veto]);
    if (veto.veto) return this;

    var a = this.formToArray(options.semantic);
  if (options.data) {
      for (var n in options.data)
          a.push( { name: n, value: options.data[n] } );
  }

    // give pre-submit callback an opportunity to abort the submit
    if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) return this;

    // fire vetoable 'validate' event
    $.event.trigger('form.submit.validate', [a, this, options, veto]);
    if (veto.veto) return this;

    var q = $.param(a);//.replace(/%20/g,'+');

    if (options.type.toUpperCase() == 'GET') {
        options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
        options.data = null;  // data is null for 'get'
    }
    else
        options.data = q; // data is the query string for 'post'

    var $form = this, callbacks = [];
    if (options.resetForm) callbacks.push(function() { $form.resetForm(); });
    if (options.clearForm) callbacks.push(function() { $form.clearForm(); });

    // perform a load on the target only if dataType is not provided
    if (!options.dataType && options.target) {
        var oldSuccess = options.success || function(){};
        callbacks.push(function(data) {
            if (this.evalScripts)
                $(options.target).attr("innerHTML", data).evalScripts().each(oldSuccess, arguments);
            else // jQuery v1.1.4
                $(options.target).html(data).each(oldSuccess, arguments);
        });
    }
    else if (options.success)
        callbacks.push(options.success);

    options.success = function(data, status) {
        for (var i=0, max=callbacks.length; i < max; i++)
            callbacks[i](data, status, $form);
    };

    // are there files to upload?
    var files = $('input:file', this).fieldValue();
    var found = false;
    for (var j=0; j < files.length; j++)
        if (files[j])
            found = true;

    if (options.iframe || found) // options.iframe allows user to force iframe mode
        fileUpload();
    else
        $.ajax(options);

    // fire 'notify' event
    $.event.trigger('form.submit.notify', [this, options]);
    return this;


    // private function for handling file uploads (hat tip to YAHOO!)
    function fileUpload() {
        var form = $form[0];
        var opts = $.extend({}, $.ajaxSettings, options);

        var id = 'jqFormIO' + $.fn.ajaxSubmit.counter++;
        var $io = $('<iframe id="' + id + '" name="' + id + '" />');
        var io = $io[0];
        var op8 = $.browser.opera && window.opera.version() < 9;
        if ($.browser.msie || op8) io.src = 'javascript:false;document.write("");';
        $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });

        var xhr = { // mock object
            responseText: null,
            responseXML: null,
            status: 0,
            statusText: 'n/a',
            getAllResponseHeaders: function() {},
            getResponseHeader: function() {},
            setRequestHeader: function() {}
        };

        var g = opts.global;
        // trigger ajax global events so that activity/block indicators work like normal
        if (g && ! $.active++) $.event.trigger("ajaxStart");
        if (g) $.event.trigger("ajaxSend", [xhr, opts]);

        var cbInvoked = 0;
        var timedOut = 0;

        // take a breath so that pending repaints get some cpu time before the upload starts
        setTimeout(function() {
            $io.appendTo('body');
            // jQuery's event binding doesn't work for iframe events in IE
            io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);

            // make sure form attrs are set
            var encAttr = form.encoding ? 'encoding' : 'enctype';
            var t = $form.attr('target');
            $form.attr({
                target:   id,
                method:  'POST',
                action:   opts.url
            });
            form[encAttr] = 'multipart/form-data';

            // support timout
            if (opts.timeout)
                setTimeout(function() { timedOut = true; cb(); }, opts.timeout);

            form.submit();
            $form.attr('target', t); // reset target
        }, 10);

        function cb() {
            if (cbInvoked++) return;

            io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);

            var ok = true;
            try {
                if (timedOut) throw 'timeout';
                // extract the server response from the iframe
                var data, doc;
                doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
                xhr.responseText = doc.body ? doc.body.innerHTML : null;
                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;

                if (opts.dataType == 'json' || opts.dataType == 'script') {
                    var ta = doc.getElementsByTagName('textarea')[0];
                    data = ta ? ta.value : xhr.responseText;
                    if (opts.dataType == 'json')
                        eval("data = " + data);
                    else
                        $.globalEval(data);
                }
                else if (opts.dataType == 'xml') {
                    data = xhr.responseXML;
                    if (!data && xhr.responseText != null)
                        data = toXml(xhr.responseText);
                }
                else {
                    data = xhr.responseText;
                }
            }
            catch(e){
                ok = false;
                $.handleError(opts, xhr, 'error', e);
            }

            // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
            if (ok) {
                opts.success(data, 'success');
                if (g) $.event.trigger("ajaxSuccess", [xhr, opts]);
            }
            if (g) $.event.trigger("ajaxComplete", [xhr, opts]);
            if (g && ! --$.active) $.event.trigger("ajaxStop");
            if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error');

            // clean up
            setTimeout(function() {
                $io.remove();
                xhr.responseXML = null;
            }, 100);
        };

        function toXml(s, doc) {
            if (window.ActiveXObject) {
                doc = new ActiveXObject('Microsoft.XMLDOM');
                doc.async = 'false';
                doc.loadXML(s);
            }
            else
                doc = (new DOMParser()).parseFromString(s, 'text/xml');
            return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
        };
    };
};
$.fn.ajaxSubmit.counter = 0; // used to create unique iframe ids

/**
 * ajaxForm() provides a mechanism for fully automating form submission.
 *
 * The advantages of using this method instead of ajaxSubmit() are:
 *
 * 1: This method will include coordinates for <input type="image" /> elements (if the element
 *    is used to submit the form).
 * 2. This method will include the submit element's name/value data (for the element that was
 *    used to submit the form).
 * 3. This method binds the submit() method to the form for you.
 *
 * Note that for accurate x/y coordinates of image submit elements in all browsers
 * you need to also use the "dimensions" plugin (this method will auto-detect its presence).
 *
 * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
 * passes the options argument along after properly binding events for submit elements and
 * the form itself.  See ajaxSubmit for a full description of the options argument.
 *
 *
 * @example
 * var options = {
 *     target: '#myTargetDiv'
 * };
 * $('#myForm').ajaxSForm(options);
 * @desc Bind form's submit event so that 'myTargetDiv' is updated with the server response
 *       when the form is submitted.
 *
 *
 * @example
 * var options = {
 *     success: function(responseText) {
 *         alert(responseText);
 *     }
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc Bind form's submit event so that server response is alerted after the form is submitted.
 *
 *
 * @example
 * var options = {
 *     beforeSubmit: function(formArray, jqForm) {
 *         if (formArray.length == 0) {
 *             alert('Please enter data.');
 *             return false;
 *         }
 *     }
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc Bind form's submit event so that pre-submit callback is invoked before the form
 *       is submitted.
 *
 *
 * @name   ajaxForm
 * @param  options  object literal containing options which control the form submission process
 * @return jQuery
 * @cat    Plugins/Form
 * @type   jQuery
 */
$.fn.ajaxForm = function(options) {
    return this.ajaxFormUnbind().submit(submitHandler).each(function() {
        // store options in hash
        this.formPluginId = $.fn.ajaxForm.counter++;
        $.fn.ajaxForm.optionHash[this.formPluginId] = options;
        $(":submit,input:image", this).click(clickHandler);
    });
};

$.fn.ajaxForm.counter = 1;
$.fn.ajaxForm.optionHash = {};

function clickHandler(e) {
    var $form = this.form;
    $form.clk = this;
    if (this.type == 'image') {
        if (e.offsetX != undefined) {
            $form.clk_x = e.offsetX;
            $form.clk_y = e.offsetY;
        } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
            var offset = $(this).offset();
            $form.clk_x = e.pageX - offset.left;
            $form.clk_y = e.pageY - offset.top;
        } else {
            $form.clk_x = e.pageX - this.offsetLeft;
            $form.clk_y = e.pageY - this.offsetTop;
        }
    }
    // clear form vars
    setTimeout(function() { $form.clk = $form.clk_x = $form.clk_y = null; }, 10);
};

function submitHandler() {
    // retrieve options from hash
    var id = this.formPluginId;
    var options = $.fn.ajaxForm.optionHash[id];
    $(this).ajaxSubmit(options);
    return false;
};

/**
 * ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
 *
 * @name   ajaxFormUnbind
 * @return jQuery
 * @cat    Plugins/Form
 * @type   jQuery
 */
$.fn.ajaxFormUnbind = function() {
    this.unbind('submit', submitHandler);
    return this.each(function() {
        $(":submit,input:image", this).unbind('click', clickHandler);
    });

};

/**
 * formToArray() gathers form element data into an array of objects that can
 * be passed to any of the following ajax functions: $.get, $.post, or load.
 * Each object in the array has both a 'name' and 'value' property.  An example of
 * an array for a simple login form might be:
 *
 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
 *
 * It is this array that is passed to pre-submit callback functions provided to the
 * ajaxSubmit() and ajaxForm() methods.
 *
 * The semantic argument can be used to force form serialization in semantic order.
 * This is normally true anyway, unless the form contains input elements of type='image'.
 * If your form must be submitted with name/value pairs in semantic order and your form
 * contains an input of type='image" then pass true for this arg, otherwise pass false
 * (or nothing) to avoid the overhead for this logic.
 *
 * @example var data = $("#myForm").formToArray();
 * $.post( "myscript.cgi", data );
 * @desc Collect all the data from a form and submit it to the server.
 *
 * @name formToArray
 * @param semantic true if serialization must maintain strict semantic ordering of elements (slower)
 * @type Array<Object>
 * @cat Plugins/Form
 */
$.fn.formToArray = function(semantic) {
    var a = [];
    if (this.length == 0) return a;

    var form = this[0];
    var els = semantic ? form.getElementsByTagName('*') : form.elements;
    if (!els) return a;
    for(var i=0, max=els.length; i < max; i++) {
        var el = els[i];
        var n = el.name;
        if (!n) continue;

        if (semantic && form.clk && el.type == "image") {
            // handle image inputs on the fly when semantic == true
            if(!el.disabled && form.clk == el)
                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
            continue;
        }

        var v = $.fieldValue(el, true);
        if (v && v.constructor == Array) {
            for(var j=0, jmax=v.length; j < jmax; j++)
                a.push({name: n, value: v[j]});
        }
        else if (v !== null && typeof v != 'undefined')
            a.push({name: n, value: v});
    }

    if (!semantic && form.clk) {
        // input type=='image' are not found in elements array! handle them here
        var inputs = form.getElementsByTagName("input");
        for(var i=0, max=inputs.length; i < max; i++) {
            var input = inputs[i];
            var n = input.name;
            if(n && !input.disabled && input.type == "image" && form.clk == input)
                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
        }
    }
    return a;
};


/**
 * Serializes form data into a 'submittable' string. This method will return a string
 * in the format: name1=value1&amp;name2=value2
 *
 * The semantic argument can be used to force form serialization in semantic order.
 * If your form must be submitted with name/value pairs in semantic order then pass
 * true for this arg, otherwise pass false (or nothing) to avoid the overhead for
 * this logic (which can be significant for very large forms).
 *
 * @example var data = $("#myForm").formSerialize();
 * $.ajax('POST', "myscript.cgi", data);
 * @desc Collect all the data from a form into a single string
 *
 * @name formSerialize
 * @param semantic true if serialization must maintain strict semantic ordering of elements (slower)
 * @type String
 * @cat Plugins/Form
 */
$.fn.formSerialize = function(semantic) {
    //hand off to jQuery.param for proper encoding
    return $.param(this.formToArray(semantic));
};


/**
 * Serializes all field elements in the jQuery object into a query string.
 * This method will return a string in the format: name1=value1&amp;name2=value2
 *
 * The successful argument controls whether or not serialization is limited to
 * 'successful' controls (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
 * The default value of the successful argument is true.
 *
 * @example var data = $("input").formSerialize();
 * @desc Collect the data from all successful input elements into a query string
 *
 * @example var data = $(":radio").formSerialize();
 * @desc Collect the data from all successful radio input elements into a query string
 *
 * @example var data = $("#myForm :checkbox").formSerialize();
 * @desc Collect the data from all successful checkbox input elements in myForm into a query string
 *
 * @example var data = $("#myForm :checkbox").formSerialize(false);
 * @desc Collect the data from all checkbox elements in myForm (even the unchecked ones) into a query string
 *
 * @example var data = $(":input").formSerialize();
 * @desc Collect the data from all successful input, select, textarea and button elements into a query string
 *
 * @name fieldSerialize
 * @param successful true if only successful controls should be serialized (default is true)
 * @type String
 * @cat Plugins/Form
 */
$.fn.fieldSerialize = function(successful) {
    var a = [];
    this.each(function() {
        var n = this.name;
        if (!n) return;
        var v = $.fieldValue(this, successful);
        if (v && v.constructor == Array) {
            for (var i=0,max=v.length; i < max; i++)
                a.push({name: n, value: v[i]});
        }
        else if (v !== null && typeof v != 'undefined')
            a.push({name: this.name, value: v});
    });
    //hand off to jQuery.param for proper encoding
    return $.param(a);
};


/**
 * Returns the value(s) of the element in the matched set.  For example, consider the following form:
 *
 *  <form><fieldset>
 *      <input name="A" type="text" />
 *      <input name="A" type="text" />
 *      <input name="B" type="checkbox" value="B1" />
 *      <input name="B" type="checkbox" value="B2"/>
 *      <input name="C" type="radio" value="C1" />
 *      <input name="C" type="radio" value="C2" />
 *  </fieldset></form>
 *
 *  var v = $(':text').fieldValue();
 *  // if no values are entered into the text inputs
 *  v == ['','']
 *  // if values entered into the text inputs are 'foo' and 'bar'
 *  v == ['foo','bar']
 *
 *  var v = $(':checkbox').fieldValue();
 *  // if neither checkbox is checked
 *  v === undefined
 *  // if both checkboxes are checked
 *  v == ['B1', 'B2']
 *
 *  var v = $(':radio').fieldValue();
 *  // if neither radio is checked
 *  v === undefined
 *  // if first radio is checked
 *  v == ['C1']
 *
 * The successful argument controls whether or not the field element must be 'successful'
 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
 * The default value of the successful argument is true.  If this value is false the value(s)
 * for each element is returned.
 *
 * Note: This method *always* returns an array.  If no valid value can be determined the
 *       array will be empty, otherwise it will contain one or more values.
 *
 * @example var data = $("#myPasswordElement").fieldValue();
 * alert(data[0]);
 * @desc Alerts the current value of the myPasswordElement element
 *
 * @example var data = $("#myForm :input").fieldValue();
 * @desc Get the value(s) of the form elements in myForm
 *
 * @example var data = $("#myForm :checkbox").fieldValue();
 * @desc Get the value(s) for the successful checkbox element(s) in the jQuery object.
 *
 * @example var data = $("#mySingleSelect").fieldValue();
 * @desc Get the value(s) of the select control
 *
 * @example var data = $(':text').fieldValue();
 * @desc Get the value(s) of the text input or textarea elements
 *
 * @example var data = $("#myMultiSelect").fieldValue();
 * @desc Get the values for the select-multiple control
 *
 * @name fieldValue
 * @param Boolean successful true if only the values for successful controls should be returned (default is true)
 * @type Array<String>
 * @cat Plugins/Form
 */
$.fn.fieldValue = function(successful) {
    for (var val=[], i=0, max=this.length; i < max; i++) {
        var el = this[i];
        var v = $.fieldValue(el, successful);
        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length))
            continue;
        v.constructor == Array ? $.merge(val, v) : val.push(v);
    }
    return val;
};

/**
 * Returns the value of the field element.
 *
 * The successful argument controls whether or not the field element must be 'successful'
 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
 * The default value of the successful argument is true.  If the given element is not
 * successful and the successful arg is not false then the returned value will be null.
 *
 * Note: If the successful flag is true (default) but the element is not successful, the return will be null
 * Note: The value returned for a successful select-multiple element will always be an array.
 * Note: If the element has no value the return value will be undefined.
 *
 * @example var data = jQuery.fieldValue($("#myPasswordElement")[0]);
 * @desc Gets the current value of the myPasswordElement element
 *
 * @name fieldValue
 * @param Element el The DOM element for which the value will be returned
 * @param Boolean successful true if value returned must be for a successful controls (default is true)
 * @type String or Array<String> or null or undefined
 * @cat Plugins/Form
 */
$.fieldValue = function(el, successful) {
    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
    if (typeof successful == 'undefined') successful = true;

    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
        (t == 'checkbox' || t == 'radio') && !el.checked ||
        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
        tag == 'select' && el.selectedIndex == -1))
            return null;

    if (tag == 'select') {
        var index = el.selectedIndex;
        if (index < 0) return null;
        var a = [], ops = el.options;
        var one = (t == 'select-one');
        var max = (one ? index+1 : ops.length);
        for(var i=(one ? index : 0); i < max; i++) {
            var op = ops[i];
            if (op.selected) {
                // extra pain for IE...
                var v = $.browser.msie && !(op.attributes['value'].specified) ? op.text : op.value;
                if (one) return v;
                a.push(v);
            }
        }
        return a;
    }
    return el.value;
};


/**
 * Clears the form data.  Takes the following actions on the form's input fields:
 *  - input text fields will have their 'value' property set to the empty string
 *  - select elements will have their 'selectedIndex' property set to -1
 *  - checkbox and radio inputs will have their 'checked' property set to false
 *  - inputs of type submit, button, reset, and hidden will *not* be effected
 *  - button elements will *not* be effected
 *
 * @example $('form').clearForm();
 * @desc Clears all forms on the page.
 *
 * @name clearForm
 * @type jQuery
 * @cat Plugins/Form
 */
$.fn.clearForm = function() {
    return this.each(function() {
        $('input,select,textarea', this).clearFields();
    });
};

/**
 * Clears the selected form elements.  Takes the following actions on the matched elements:
 *  - input text fields will have their 'value' property set to the empty string
 *  - select elements will have their 'selectedIndex' property set to -1
 *  - checkbox and radio inputs will have their 'checked' property set to false
 *  - inputs of type submit, button, reset, and hidden will *not* be effected
 *  - button elements will *not* be effected
 *
 * @example $('.myInputs').clearFields();
 * @desc Clears all inputs with class myInputs
 *
 * @name clearFields
 * @type jQuery
 * @cat Plugins/Form
 */
$.fn.clearFields = $.fn.clearInputs = function() {
    return this.each(function() {
        var t = this.type, tag = this.tagName.toLowerCase();
        if (t == 'text' || t == 'password' || tag == 'textarea')
            this.value = '';
        else if (t == 'checkbox' || t == 'radio')
            this.checked = false;
        else if (tag == 'select')
            this.selectedIndex = -1;
    });
};


/**
 * Resets the form data.  Causes all form elements to be reset to their original value.
 *
 * @example $('form').resetForm();
 * @desc Resets all forms on the page.
 *
 * @name resetForm
 * @type jQuery
 * @cat Plugins/Form
 */
$.fn.resetForm = function() {
    return this.each(function() {
        // guard against an input with the name of 'reset'
        // note that IE reports the reset function as an 'object'
        if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType))
            this.reset();
    });
};

})(jQuery);;

/*--------------------------------------------------------------------------
 /ext/jquery/jquery.history_remote.pack.js
--------------------------------------------------------------------------*/
/**
 * History/Remote - jQuery plugin for enabling history support and bookmarking
 * @requires jQuery v1.0.3
 *
 * http://stilbuero.de/jquery/history/
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Version: 0.2.3
 */
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}('(2($){$.D=16 2(){4 c=\'15\';4 k=7.6;4 d=z;4 g;5.o=2(){};4 h=2(){$(\'.x-R\').1i()};$(8).K(c,h);3($.v.19){4 e,p=q;$(2(){e=$(\'<H 13="12: Z;"></H>\').E(8.U).1o(0);4 a=e.C.8;a.P();a.M();3(k&&k!=\'#\'){a.7.6=k.B(\'#\',\'\')}});5.o=2(a){k=a;4 b=e.C.8;b.P();b.M();b.7.6=a.B(\'#\',\'\')};g=2(){4 a=e.C.8;4 b=a.7.6;3(b!=k){k=b;3(b&&b!=\'#\'){$(\'a[@l$="\'+b+\'"]\').m();7.6=b}n 3(p){7.6=\'\';$(8).u(c)}}p=A}}n 3($.v.18||$.v.17){5.o=2(a){k=a};g=2(){3(7.6){3(k!=7.6){k=7.6;$(\'a[@l$="\'+k+\'"]\').m()}}n 3(k){k=\'\';$(8).u(c)}}}n 3($.v.14){4 f,r,t;$(2(){f=[];f.9=y.9;r=[]});4 j=q,p=q;t=2(a){f.G(a);r.9=0;j=q};5.o=2(a){k=a;t(k)};g=2(){4 b=y.9-f.9;3(b){j=q;3(b<0){F(4 i=0;i<11.10(b);i++)r.Y(f.X())}n{F(4 i=0;i<b;i++)f.G(r.W())}4 a=f[f.9-1];$(\'a[@l$="\'+a+\'"]\').m();k=7.6}n 3(f[f.9-1]==T&&!j){3(8.S.1n(\'#\')>=0){$(\'a[@l$="\'+\'#\'+8.S.1m(\'#\')[1]+\'"]\').m()}n 3(p){$(8).u(c)}j=A}p=A}}5.1l=2(a){3(w a==\'2\'){$(8).1k(c,h).K(c,a)}3(7.6&&w t==\'T\'){$(\'a[@l$="\'+7.6+\'"]\').u(\'m\')}3(g&&d==z){d=1j(g,1h)}}};$.Q.x=2(g,f,c){c=c||2(){};3(w f==\'2\'){c=f}f=$.1g({O:\'x-\'},f||{});4 d=$(g).1f()&&$(g)||$(\'<I></I>\').E(\'U\');d.1e(\'x-R\');L 5.1d(2(i){4 a=5.l;4 b=\'#\'+(5.N&&5.N.B(/\\s/g,\'1c\')||f.O+(i+1));5.l=b;$(5).m(2(e){3(!d[\'J\']){3(e.V){$.D.o(b)}d.1b(a,2(){d[\'J\']=z;c()})}})})};$.Q.y=2(a){L 5.m(2(e){3(e.V){$.D.o(5.6)}w a==\'2\'&&a()})}})(1a);',62,87,'||function|if|var|this|hash|location|document|length||||||||||||href|click|else|update|initialized|false|_forwardStack||_addHistory|trigger|browser|typeof|remote|history|null|true|replace|contentWindow|ajaxHistory|appendTo|for|push|iframe|div|locked|bind|return|close|title|hashPrefix|open|fn|output|URL|undefined|body|clientX|shift|pop|unshift|none|abs|Math|display|style|safari|historyReset|new|opera|mozilla|msie|jQuery|load|_|each|addClass|size|extend|200|empty|setInterval|unbind|initialize|split|indexOf|get'.split('|'),0,{}));

/*--------------------------------------------------------------------------
 /ext/jquery/jquery.metadata.js
--------------------------------------------------------------------------*/
/*
 * Metadata - jQuery plugin for parsing metadata from elements
 *
 * Copyright (c) 2006 John Resig, Yehuda Katz, Jörn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: metadata.js 1631 2007-04-05 16:02:19Z joern $
 *
 */

/**
 * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
 * in the JSON will become a property of the element itself.
 *
 * There are three supported types of metadata storage:
 *
 *   attr:  Inside an attribute. The name parameter indicates *which* attribute.
 *          
 *   class: Inside the class attribute, wrapped in curly braces: { }
 *   
 *   elem:  Inside a child element (e.g. a script tag). The
 *          name parameter indicates *which* element.
 *          
 * The metadata for an element is loaded the first time the element is accessed via jQuery.
 *
 * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
 * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
 * 
 * @name $.meta.setType
 *
 * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.meta.setType("class")
 * @after $("#one").data().item_id == 1; $("#one")[0].item_label == "Label"
 * @desc Reads metadata from the class attribute
 * 
 * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.meta.setType("attr", "data")
 * @after $("#one").data().item_id == 1; $("#one")[0].item_label == "Label"
 * @desc Reads metadata from a "data" attribute
 * 
 * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
 * @before $.meta.setType("elem", "script")
 * @after $("#one").data().item_id == 1; $("#one")[0].item_label == "Label"
 * @desc Reads metadata from a nested script element
 * 
 * @param String type The encoding type
 * @param String name The name of the attribute to be used to get metadata (optional)
 * @cat Plugins/Metadata
 * @descr Sets the type of encoding to be used when loading metadata for the first time
 * @type undefined
 * @see data()
 */

(function($) {
	// settings
	$.meta = {
	  type: "class",
	  name: "metadata",
	  setType: function(type,name){
	    this.type = type;
	    this.name = name;
	  },
	  cre: /({.*})/,
	  single: 'metadata'
	};
	
	// reference to original setArray()
	var setArray = $.fn.setArray;
	
	// define new setArray()
	$.fn.setArray = function(arr){
	    return setArray.apply( this, arguments ).each(function(){
	      if ( this.nodeType == 9 || $.isXMLDoc(this) || this.metaDone ) return;
	      
	      var data = "{}";
	      
	      if ( $.meta.type == "class" ) {
	        var m = $.meta.cre.exec( this.className );
	        if ( m )
	          data = m[1];
	      } else if ( $.meta.type == "elem" ) {
	      	if( !this.getElementsByTagName ) return;
	        var e = this.getElementsByTagName($.meta.name);
	        if ( e.length )
	          data = $.trim(e[0].innerHTML);
	      } else if ( this.getAttribute != undefined ) {
	        var attr = this.getAttribute( $.meta.name );
	        if ( attr )
	          data = attr;
	      }
	      
	      if ( !/^{/.test( data ) )
	        data = "{" + data + "}";
	
	      eval("data = " + data);
	
	      if ( $.meta.single )
	        this[ $.meta.single ] = data;
	      else
	        $.extend( this, data );
	      
	      this.metaDone = true;
	    });
	};
	
	/**
	 * Returns the metadata object for the first member of the jQuery object.
	 *
	 * @name data
	 * @descr Returns element's metadata object
	 * @type jQuery
	 * @cat Plugins/Metadata
	 */
	$.fn.data = function() {
	  return this[0][$.meta.single];
	};
})(jQuery);;

/*--------------------------------------------------------------------------
 /ext/jquery/jquery.tabs.pack.js
--------------------------------------------------------------------------*/
/**
 * Tabs - jQuery plugin for accessible, unobtrusive tabs
 * @requires jQuery v1.1.1
 *
 * http://stilbuero.de/tabs/
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Version: 2.7.4
 */
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}('(4($){$.2l({z:{2k:0}});$.1P.z=4(x,w){3(O x==\'2Y\')w=x;w=$.2l({K:(x&&O x==\'1Z\'&&x>0)?--x:0,12:C,J:$.1f?2h:T,18:T,1r:\'2X&#2Q;\',21:\'18-2F-\',1m:C,1u:C,1l:C,1F:C,1x:\'2u\',2r:C,2p:C,2m:T,2i:C,1d:C,1c:C,1j:\'z-1M\',H:\'z-2b\',14:\'z-12\',16:\'z-26\',1q:\'z-1H\',1L:\'z-2L\',2j:\'10\'},w||{});$.8.1D=$.8.U&&($.8.1Y&&$.8.1Y<7||/2A 6.0/.2y(2x.2w));4 1w(){1V(0,0)}F 5.Y(4(){2 p=5;2 r=$(\'13.\'+w.1j,p);r=r.V()&&r||$(\'>13:9(0)\',p);2 j=$(\'a\',r);3(w.18){j.Y(4(){2 c=w.21+(++$.z.2k),B=\'#\'+c,2f=5.1O;5.1O=B;$(\'<10 S="\'+c+\'" 34="\'+w.16+\'"></10>\').2c(p);$(5).19(\'1B\',4(e,a){2 b=$(5).I(w.1L),X=$(\'X\',5)[0],27=X.1J;3(w.1r){X.1J=\'<24>\'+w.1r+\'</24>\'}1p(4(){$(B).2T(2f,4(){3(w.1r){X.1J=27}b.17(w.1L);a&&a()})},0)})})}2 n=$(\'10.\'+w.16,p);n=n.V()&&n||$(\'>\'+w.2j,p);r.P(\'.\'+w.1j)||r.I(w.1j);n.Y(4(){2 a=$(5);a.P(\'.\'+w.16)||a.I(w.16)});2 s=$(\'A\',r).20($(\'A.\'+w.H,r)[0]);3(s>=0){w.K=s}3(1e.B){j.Y(4(i){3(5.B==1e.B){w.K=i;3(($.8.U||$.8.2E)&&!w.18){2 a=$(1e.B);2 b=a.15(\'S\');a.15(\'S\',\'\');1p(4(){a.15(\'S\',b)},2D)}1w();F T}})}3($.8.U){1w()}n.1a(\':9(\'+w.K+\')\').1C().1n().2C(\':9(\'+w.K+\')\').I(w.1q);$(\'A\',r).17(w.H).9(w.K).I(w.H);j.9(w.K).N(\'1B\').1n();3(w.2m){2 l=4(d){2 c=$.2B(n.1t(),4(a){2 h,1A=$(a);3(d){3($.8.1D){a.Z.2z(\'1X\');a.Z.G=\'\';a.1k=C}h=1A.L({\'1h-G\':\'\'}).G()}E{h=1A.G()}F h}).2v(4(a,b){F b-a});3($.8.1D){n.Y(4(){5.1k=c[0]+\'1W\';5.Z.2t(\'1X\',\'5.Z.G = 5.1k ? 5.1k : "2s"\')})}E{n.L({\'1h-G\':c[0]+\'1W\'})}};l();2 q=p.1U;2 m=p.1v;2 v=$(\'#z-2q-2o-V\').1t(0)||$(\'<X S="z-2q-2o-V">M</X>\').L({1T:\'2n\',3a:\'39\',38:\'37\'}).2c(Q.1S).1t(0);2 o=v.1v;36(4(){2 b=p.1U;2 a=p.1v;2 c=v.1v;3(a>m||b!=q||c!=o){l((b>q||c<o));q=b;m=a;o=c}},35)}2 u={},11={},1R=w.2r||w.1x,1Q=w.2p||w.1x;3(w.1u||w.1m){3(w.1u){u[\'G\']=\'1C\';11[\'G\']=\'1H\'}3(w.1m){u[\'W\']=\'1C\';11[\'W\']=\'1H\'}}E{3(w.1l){u=w.1l}E{u[\'1h-2g\']=0;1R=1}3(w.1F){11=w.1F}E{11[\'1h-2g\']=0;1Q=1}}2 t=w.2i,1d=w.1d,1c=w.1c;j.19(\'2e\',4(){2 c=$(5).1g(\'A:9(0)\');3(p.1i||c.P(\'.\'+w.H)||c.P(\'.\'+w.14)){F T}2 a=5.B;3($.8.U){$(5).N(\'1b\');3(w.J){$.1f.1N(a);1e.B=a.1z(\'#\',\'\')}}E 3($.8.1y){2 b=$(\'<2d 33="\'+a+\'"><10><32 31="2a" 30="h" /></10></2d>\').1t(0);b.2a();$(5).N(\'1b\');3(w.J){$.1f.1N(a)}}E{3(w.J){1e.B=a.1z(\'#\',\'\')}E{$(5).N(\'1b\')}}});j.19(\'1E\',4(){2 a=$(5).1g(\'A:9(0)\');3($.8.1y){a.1o({W:0},1,4(){a.L({W:\'\'})})}a.I(w.14)});3(w.12&&w.12.1K){29(2 i=0,k=w.12.1K;i<k;i++){j.9(--w.12[i]).N(\'1E\').1n()}};j.19(\'28\',4(){2 a=$(5).1g(\'A:9(0)\');a.17(w.14);3($.8.1y){a.1o({W:1},1,4(){a.L({W:\'\'})})}});j.19(\'1b\',4(e){2 g=e.2Z;2 d=5,A=$(5).1g(\'A:9(0)\'),D=$(5.B),R=n.1a(\':2W\');3(p[\'1i\']||A.P(\'.\'+w.H)||A.P(\'.\'+w.14)||O t==\'4\'&&t(5,D[0],R[0])===T){5.25();F T}p[\'1i\']=2h;3(D.V()){3($.8.U&&w.J){2 c=5.B.1z(\'#\',\'\');D.15(\'S\',\'\');1p(4(){D.15(\'S\',c)},0)}2 f={1T:\'\',2V:\'\',G:\'\'};3(!$.8.U){f[\'W\']=\'\'}4 1I(){3(w.J&&g){$.1f.1N(d.B)}R.1o(11,1Q,4(){$(d).1g(\'A:9(0)\').I(w.H).2U().17(w.H);R.I(w.1q).L(f);3(O 1d==\'4\'){1d(d,D[0],R[0])}3(!(w.1u||w.1m||w.1l)){D.L(\'1T\',\'2n\')}D.1o(u,1R,4(){D.17(w.1q).L(f);3($.8.U){R[0].Z.1a=\'\';D[0].Z.1a=\'\'}3(O 1c==\'4\'){1c(d,D[0],R[0])}p[\'1i\']=C})})}3(!w.18){1I()}E{$(d).N(\'1B\',[1I])}}E{2S(\'2R P 2P 2O 26.\')}2 a=1G.2N||Q.1s&&Q.1s.23||Q.1S.23||0;2 b=1G.2M||Q.1s&&Q.1s.22||Q.1S.22||0;1p(4(){1G.1V(a,b)},0);5.25();F w.J&&!!g});3(w.J){$.1f.2K(4(){j.9(w.K).N(\'1b\').1n()})}})};2 y=[\'2e\',\'1E\',\'28\'];29(2 i=0;i<y.1K;i++){$.1P[y[i]]=(4(d){F 4(c){F 5.Y(4(){2 b=$(\'13.z-1M\',5);b=b.V()&&b||$(\'>13:9(0)\',5);2 a;3(!c||O c==\'1Z\'){a=$(\'A a\',b).9((c&&c>0&&c-1||0))}E 3(O c==\'2J\'){a=$(\'A a[@1O$="#\'+c+\'"]\',b)}a.N(d)})}})(y[i])}$.1P.2I=4(){2 c=[];5.Y(4(){2 a=$(\'13.z-1M\',5);a=a.V()&&a||$(\'>13:9(0)\',5);2 b=$(\'A\',a);c.2H(b.20(b.1a(\'.z-2b\')[0])+1)});F c[0]}})(2G);',62,197,'||var|if|function|this|||browser|eq||||||||||||||||||||||||||tabs|li|hash|null|toShow|else|return|height|selectedClass|addClass|bookmarkable|initial|css||trigger|typeof|is|document|toHide|id|false|msie|size|opacity|span|each|style|div|hideAnim|disabled|ul|disabledClass|attr|containerClass|removeClass|remote|bind|filter|click|onShow|onHide|location|ajaxHistory|parents|min|locked|navClass|minHeight|fxShow|fxFade|end|animate|setTimeout|hideClass|spinner|documentElement|get|fxSlide|offsetHeight|unFocus|fxSpeed|safari|replace|jq|loadRemoteTab|show|msie6|disableTab|fxHide|window|hide|switchTab|innerHTML|length|loadingClass|nav|update|href|fn|hideSpeed|showSpeed|body|display|offsetWidth|scrollTo|px|behaviour|version|number|index|hashPrefix|scrollTop|scrollLeft|em|blur|container|tabTitle|enableTab|for|submit|selected|appendTo|form|triggerTab|url|width|true|onClick|tabStruct|remoteCount|extend|fxAutoHeight|block|font|fxHideSpeed|watch|fxShowSpeed|1px|setExpression|normal|sort|userAgent|navigator|test|removeExpression|MSIE|map|not|500|opera|tab|jQuery|push|activeTab|string|initialize|loading|pageYOffset|pageXOffset|such|no|8230|There|alert|load|siblings|overflow|visible|Loading|object|clientX|value|type|input|action|class|50|setInterval|hidden|visibility|absolute|position'.split('|'),0,{}));

/*--------------------------------------------------------------------------
 /ext/jquery/jquery.template.js
--------------------------------------------------------------------------*/
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}('(4($){$.T=4(){5 d=4(o){P(5 m 1j o){3[m]=o[m]}};6 4(a,b,c){7(N b==\'1o\'){c=b;b=a;a=4(){b.j(3,h)}}5 F=4(){},J,D=b.8;F.8=D;J=a.8=G F();J.y=a;a.K=D;7(D.y==17.8.y){D.y=b}a.S=4(o){$.Q(a.8,o)};J.S=d;$.Q(a.8,c);6 a}}();5 g=4(c,d,e,f){6 4(){5 a=e||h;7(f===1p){a=x.8.10.p(h,0);a=a.X(e)}L 7(N f=="1g"){a=x.8.10.p(h,0);5 b=[f,0].X(e);x.8.1d.j(a,b)}6 c.j(d||1c,a)}};$.u=4(a){7(a 19 x){a=a.B("")}L 7(h.A>1){a=x.8.B.p(h,"")}3.9=a};$.u.8={j:4(d){7(3.z){6 3.z(d)}5 e=3;5 f=4(m,a,b,c){6 d[a]!==U?d[a]:""};6 $(3.9.k(3.l,f))},18:4(a,b){3.9=a;3.z=16;7(b){3.E()}6 3},l:/\\{([\\w-]+)(?:\\:([\\w\\.]*)(?:\\((.*?)?\\))?)?\\}/g,E:4(){5 d=$.R.V?"+":",";5 e=4(m,a,b,c){c=\'\',b="(I[\'"+a+"\'] == U ? \'\' : ";6"\'"+d+b+"I[\'"+a+"\']"+c+")"+d+"\'"};5 f;7($.R.V){f="3.z = 4(I){ 6 \'"+3.9.k(/(\\r\\n|\\n)/g,\'\\\\n\').k("\'","\\\\\'").k(3.l,e)+"\';};"}L{f=["3.z = 4(I){ 6 [\'"];f.O(3.9.k(/(\\r\\n|\\n)/g,\'\\\\n\').k("\'","\\\\\'").k(3.l,e));f.O("\'].B(\'\');};");f=f.B(\'\')}15(f);6 3},p:4(a,b){6 3[a](b)}};$.u.13=4(a){6 G $.u($(a).12()||$(a).9())};$.t=4(){$.t.K.y.j(3,h);3.11=3.9;5 a={};5 m,l=3.M;l.1n=0;5 b=0;1m(m=l.1l(3.9)){5 c=m[1],Z=m[2];a[b]={1i:c,1h:b,C:[],q:G $.u(Z)};7(c){a[c]=a[b]}a[b].q.E();a[b].q.p=g(3.p,3);b++}3.W=b;3.H=a};$.T($.t,$.u,{M:/<q(?:\\1f="([\\w-]+)")?>((?:.|\\n)*?)<\\/q>/1e,14:4(a,b){7(h.A==1){b=h[0];a=0}5 s=3.H[a];s.C[s.C.A]=s.q.j(b);6 3},1b:4(b,c,d){5 a=h;7(a.A==1||(a.A==2&&N a[1]=="1k")){c=a[0];b=0;d=a[1]}7(d){3.Y()}5 e=3;$.1a(c,4(i,v){e.14(b,v)});6 3},Y:4(){5 s=3.H;P(5 i=0;i<3.W;i++){s[i].C=[]}6 3},j:4(b){5 s=3.H;5 c=-1;3.9=3.11.k(3.M,4(m,a){6 s[++c].C.B("")});6 $.t.K.j.p(3,b)},E:4(){6 3}});$.t.13=4(a){6 G $.t($(a).12()||$(a).9())}})(1q);',62,89,'|||this|function|var|return|if|prototype|html||||||||arguments||apply|replace|re||||call|tpl|||MasterTemplate|Template|||Array|constructor|compiled|length|join|buffer|spp|compile||new|subs|values|sbp|superclass|else|subTemplateRe|typeof|push|for|extend|browser|override|extendClass|undefined|mozilla|subCount|concat|reset|content|slice|originalHtml|val|from|add|eval|null|Object|set|instanceof|each|fill|window|splice|gi|sname|number|index|name|in|boolean|exec|while|lastIndex|object|true|jQuery'.split('|'),0,{}));

/*--------------------------------------------------------------------------
 /ext/jquery/jquery.validate.js
--------------------------------------------------------------------------*/
/*
 * Form Validation: jQuery form validation plug-in v1.1
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
 *
 * Copyright (c) 2006 JÃ¶rn Zaefferer
 *
 * $Id$
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

/**
 * Validates a single form.
 *
 * The normal behaviour is to validate a form when a submit button is clicked or
 * the user presses enter when an input of that form is focused.
 *
 * It is also possible to validate each individual element of that form, eg. on blur or keyup.
 *
 * @example $("#myform").validate();
 * @before <form id="myform">
 *   <input name="firstname" class="{required:true}" />
 * </form>
 * @desc Validates a form on submit. Rules are read from metadata.
 *
 * @example $("input").validate({
 *     event: "blur",
 *    success: "valid"
 * });
 * @desc Validates all input elements on blur event (when the element looses focus).
 * Adds a class "valid" to all error labels when the elements are valid and keeps showing
 * them.
 *
 * @example $("#myform").validate({
 *   submitHandler: function(form) {
 *     $(form).ajaxSubmit();
 *   }
 * });
 * @desc Uses form plugin's ajaxSubmit method to handle the form submit, while preventing
 * the default submit.
 *
 * @example $("#myform").validate({
 *  event: "keyup"
 *   rules: {
 *     "first-name": "required",
 *     age: {
 *      required: "#firstname:blank",
 *       number: true,
 *       minValue: 3
 *     },
 *     password: {
 *       required: function() {
 *         return $("#age").val() < 18;
 *       },
 *       minLength: 5,
 *       maxLength: 32
 *     }
 *   },
 *  messages: {
 *     password: {
 *       required: function(element, validator) {
 *         return "Your password is required because with " + $("#age").val() + ", you are not old enough yet."
 *       },
 *       minLength: "Please enter a password at least 5 characters long.",
 *       maxLength: "Please enter a password no longer than 32 characters long."
 *     },
 *    age: "Please specify your age as a number (at least 3)."
 *   }
 * });
 * @desc Validate a form on submit and each element on keyup. Rules are specified
 * for three elements, and a message is customized for the "password" and the
 * "age" elements. Inline rules are ignored. The password is only required when the age is lower
 * than 18. The age is only required when the firstname is blank. Note that "first-name" is quoted, because
 * it isn't a valid javascript identifier. "first-name": "required" also uses a shortcut replacement for
 * { required: true }. That works for all trivial validations that expect no more than a boolean-true argument.
 * The required-message for password is specified as a function to use runtime customization.
 *
 * @example $("#myform").validate({
 *   errorClass: "invalid",
 *   errorLabelContainer: $("#messageBox"),
 *   wrapper: "li"
 * });
 * @before <ul id="messageBox"></ul>
 * <form id="myform" action="/login" method="post">
 *   <label>Firstname</label>
 *   <input name="fname" class="{required:true}" />
 *   <label>Lastname</label>
 *   <input name="lname" title="Your lastname, please!" class="{required:true}" />
 * </form>
 * @result <ul id="messageBox">
 *   <li><label for="fname" class="invalid">Please specify your firstname!</label></li>
 *   <li><label for="lname" class="invalid">Your lastname, please!</label></li>
 * </ul>
 * <form id="myform" action="/login" method="post">
 *   <label>Firstname</label>
 *   <input name="fname" class="{required:true} invalid" />
 *   <label>Lastname</label>
 *   <input name="lname" title="Your lastname, please!" class="{required:true} invalid" />
 * </form>
 * @desc Validates a form on submit. The class used to search, create and display
 * error labels is changed to "invalid". This is also added to invalid elements.
 *
 * All error labels are displayed inside an unordered list with the ID "messageBox", as
 * specified by the jQuery object passed as errorContainer option. All error elements
 * are wrapped inside an li element, to create a list of messages.
 *
 * To ease the setup of the form, debug option is set to true, preventing a submit
 * of the form no matter of being valid or not.
 *
 *
 * @example $("#myform").validate({
 *   errorPlacement: function(error, element) {
 *     error.appendTo( element.parent("td").next("td") );
 *   },
 *   success: function(label) {
 *     label.text("ok!").addClass("success");
 *   }
 * });
 * @before <form id="myform" action="/login" method="post">
 *   <table>
 *     <tr>
 *       <td><label>Firstname</label>
 *       <td><input name="fname" class="{required:true}" value="Pete" /></td>
 *       <td></td>
 *     </tr>
 *     <tr>
 *       <td><label>Lastname</label></td>
 *       <td><input name="lname" title="Your lastname, please!" class="{required:true}" /></td>
 *       <td></td>
 *     </tr>
 *   </table>
 * </form>
 * @result <form id="myform" action="/login" method="post">
 *   <table>
 *     <tr>
 *       <td><label>Firstname</label>
 *       <td><input name="fname" class="{required:true}" value="Pete" /></td>
 *       <td><label for="fname" class="invalid success">ok!</label></td>
 *     </tr>
 *     <tr>
 *       <td><label>Lastname</label></td>
 *       <td><input name="lname" title="Your lastname, please!" class="{required:true}" /></td>
 *       <td><label for="lname" class="invalid">Your lastname, please!</label></td>
 *     </tr>
 *   </table>
 * </form>
 * @desc Validates a form on submit. Customizes the placement of the generated labels
 * by appending them to the next table cell. Displays "ok!" for valid elements and adds a class
 * "success" to the message (the class "invalid" is kept to identify the error label).
 *
 * @example $("#myform").validate({
 *   errorContainer: $("#messageBox1, #messageBox2"),
 *   errorLabelContainer: $("#messageBox1 ul"),
 *   wrapper: "li",
 * });
 * @before <div id="messageBox1">
 *   <h3>The are errors in your form!</h3>
 *   <ul></ul>
 * </div>
 * <form id="myform" action="/login" method="post">
 *   <label>Firstname</label>
 *   <input name="fname" class="{required:true}" />
 *   <label>Lastname</label>
 *   <input name="lname" title="Your lastname, please!" class="{required:true}" />
 * </form>
 * <div id="messageBox2">
 *   <h3>The are errors in your form, see details above!</h3>
 * </div>
 * @result <ul id="messageBox">
 *   <li><label for="fname" class="error">Please specify your firstname!</label></li>
 *   <li><label for="lname" class="error">Your lastname, please!</label></li>
 * </ul>
 * <form id="myform" action="/login" method="post">
 *   <label>Firstname</label>
 *   <input name="fname" class="{required:true} error" />
 *   <label>Lastname</label>
 *   <input name="lname" title="Your lastname, please!" class="{required:true} error" />
 * </form>
 * @desc Validates a form on submit. Similar to the above example, but with an additional
 * container for error messages. The elements given as the errorContainer are all shown
 * and hidden when errors occur. But the error labels themselve are added to the element(s)
 * given as errorLabelContainer, here an unordered list. Therefore the error labels are
 * also wrapped into li elements (wrapper option).
 *
 * @param Map options Optional settings to configure validation
 * @option String errorClass Use this class to look for existing error labels and add it to
 *    invalid elements. Default: "error"
 * @option String wrapper Wrap error labels with the specified element, eg "li". Default: none
 * @option Boolean debug If true, the form is not submitted and certain errors are display on the console (requires Firebug or Firebug lite). Default: none
 * @option Boolean focusInvalid Focus the last active or first invalid element on submit or via validator.focusInvalid(). Default: true
 * @option Function submitHandler Callback for handling the actual
 *    submit when the form is valid. Gets the form as the only argmument. Default: normal form submit
 * @option Map<String, Object> messages Key/value pairs defining custom messages.
 *    Key is the name of an element, value the message to display for that element. Instead of
 *    a plain message  another map with specific messages for each rule can be used.
 *    Can be specified for one or more elements. Overrides the title attribute of an element.
 *    Each message can be a String or a Function. The Function is called with the element
 *     as the first and the validator as the second argument and must return a String to display as the message
 *     for that element.
 *      Default: none, the default message for the method is used.
 * @option Map<String, Object> rules Key/value pairs defining custom rules.
 *    Key is the ID or name (for radio/checkbox inputs) of an element,
 *    value is an object consisting of rule/parameter pairs, eg. {required: true, min: 3}.
 *     Once specified, metadata rules are completely ignored.
 *    Default: none, rules are read from metadata via metadata plugin
 * @option Boolean onsubmit Validate the form on submit. Set to false to use only other
 *    events for validation (option event). Default: true
 * @option String meta In case you use metadata for other plugins, too, you
 *    want to wrap your validation rules
 *    into their own object that can be specified via this option. Default: none
 * @option jQuery errorContainer Hide and show this container when validating. Default: none
 * @option jQuery errorLabelContainer Search and append error labels to this container, and show and hide it accordingly. Default: none
 * @option Function showErrors A custom message display handler. Gets the map of errors as the
 *    first argument and a refernce to the validator object as the second.
 *     You can trigger (in addition to your own messages) the default behaviour by calling
 *     the defaultShowErrors() method of the validator.
 *     Default: none, uses built-in message disply.
 * @option Function errorPlacement Used to customize placement of created error labels.
 *    First argument: jQuery object containing the created error label
 *    Second argument: jQuery object containing the invalid element
 *    Default: Places the error label after the invalid element
 * @option String errorElement The element to use for generated error messages. Default: "label"
 * @option String|Function If specified, the error label is displayed to show a valid element. If
 *     a String is given, its added as a class to the label. If a Function is given, its called with
 *    the label (as a jQuery object) as its only argument. That can be used to add a text like "ok!".
 *    Default: none
 * @option Boolean focusCleanup If enabled, removes the errorClass from the invalid elements and hides
 *     all errors messages whenever the element is focused. Avoid combination with focusInvalid. Default: false
 * @option String|Element ignore Elements to ignore when validating, simply filtering them out. jQuery's not-method
 *     is used, there everything that is accepted by not() can be passed as this option. Default: None, though inputs of type
 *    submit and reset are always ignored.
 * @opton Boolean onblur Validate elements on blur. If nothing is entered, all rules are skipped,
 *     except when the field was already marked as invalid. Default: true
 *
 * @name validate
 * @type $.validator
 * @cat Plugins/Validate
 */

jQuery.extend(jQuery.fn, {
  validate: function( options ) {
    var validator = new jQuery.validator( options, this[0] );

    if ( validator.settings.onsubmit ) {

      // allow suppresing validation by adding a cancel class to the submit button
      this.find("input.cancel:submit").click(function() {
        validator.cancelSubmit = true;
      });

      // validate the form on submit
      this.submit( function( event ) {
        if ( validator.settings.debug )
          // prevent form submit to be able to see console output
          event.preventDefault();

        function handle() {
          if ( validator.settings.submitHandler ) {
            validator.settings.submitHandler.call( validator, validator.currentForm );
            return false;
          }
          return true;
        }

        // prevent submit for invalid forms or custom submit handlers
        if ( validator.cancelSubmit ) {
          validator.cancelSubmit = false;
          return handle();
        }
        if ( validator.form() ) {
          if ( this.pendingRequest ) {
            this.submitted = true;
            return false;
          }
          return handle();
        } else {
          validator.focusInvalid();
          return false;
        }
      });
    }

    validator.settings.onblur && validator.elements.blur( function() {
      validator.settings.onblur.call( validator, this );
    });
    validator.settings.onkeyup && validator.elements.keyup(function() {
      validator.settings.onkeyup.call( validator, this );
    });
    var checkables = jQuery([]);
    validator.elements.each(function() {
      if ( validator.checkable( this ) )
        checkables.push( validator.checkableGroup( this ) );
    });
    validator.settings.onchange && checkables.click(function() {
      validator.settings.onchange.call( validator, this );
    });

    return validator;
  },
  // destructive add
  push: function( t ) {
    return this.setArray( jQuery.merge( this.get(), t ) );
  }
});

/**
 * Expression to filter for blank fields.
 *
 * @example jQuery("input:blank").length
 * @before <input value="" /><input value="  " /><input value="abc" />
 * @result 2
 *
 * @property
 * @type String
 * @name :blank
 * @cat Plugins/Validate
 */

/**
 * Expression to filter for filled fields.
 *
 * @example jQuery("input:filled").length
 * @before <input value="" /><input value="  " /><input value="abc" />
 * @result 1
 *
 * @property
 * @type String
 * @name :filled
 * @cat Plugins/Validate
 */

/**
 * Expression to filter unchecked checkboxes or radio buttons.
 *
 * @example jQuery("input:unchecked").length
 * @before <input type="checkbox" /><input type="checkbox" checked="checked" />
 * @result 1
 *
 * @property
 * @type String
 * @name :unchecked
 * @cat Plugins/Validate
 */
jQuery.extend(jQuery.expr[":"], {
  blank: "!jQuery.trim(a.value)",
  filled: "!!jQuery.trim(a.value)",
  unchecked: "!a.checked"
});

/**
 * Simple string-templating, similar to Java's MessageFormat.
 *
 * Accepts a string template as the first argument. The second is optional:
 * If specified, it is used to replace placeholders in the first argument.
 *
 * It can be an Array of values or any other type, in which case only one value
 * is replaced.
 *
 * If the second argument is ommited, a function is returned that expects the value-argument
 * to return the formatted value (see example).
 *
 * @example String.format("Please enter a value no longer than {0} characters.", 0)
 * @result "Please enter a value no longer than 0 characters."
 * @desc Formats a string with a single argument.
 *
 * @example String.format("Please enter a value between {0} and {1}.", 0, 1)
 * @result "Please enter a value between 0 and 1."
 * @desc Formats a string with two arguments. Same as String.format("...", [0, 1]);
 *
 * @example String.format("Please enter a value no longer than {0} characters.")(0);
 * @result "Please enter a value no longer than 0 characters."
 * @desc String.format is called at first without the second argument, returning a function that is called immediately
 *      with the value argument. Useful to defer the actual formatting to a later point without explicitly
 *     writing the function.
 *
 * @type String
 * @name String.format
 * @cat Plugins/Validate
 */
String.format = function(source, params) {
  if ( arguments.length == 1 )
    return function() {
      var args = jQuery.makeArray(arguments);
      args.unshift(source)
      return String.format.apply( this, args );
    };
  if ( arguments.length > 2 && params.constructor != Array  ) {
    params = jQuery.makeArray(arguments).slice(1);
  }
  if ( params.constructor != Array ) {
    params = [ params ];
  }
  jQuery.each(params, function(i, n) {
    source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
  });
  return source;
};

// constructor for validator
jQuery.validator = function( options, form ) {
  this.settings = jQuery.extend( {}, jQuery.validator.defaults, options );

  this.currentForm = form;
  this.labelContainer = this.settings.errorLabelContainer;
  this.errorContext = this.labelContainer.length && this.labelContainer || jQuery(form);
  this.containers = this.settings.errorContainer.add( this.settings.errorLabelContainer );
  this.submitted = {};
  this.valueCache = {};
  this.pendingRequest = 0;
  this.invalid = {};
  this.reset();
  this.refresh();
};

jQuery.extend(jQuery.validator, {

  defaults: {
    messages: {},
    errorClass: "error",
    errorElement: "label",
    focusInvalid: true,
    errorContainer: jQuery( [] ),
    errorLabelContainer: jQuery( [] ),
    onsubmit: true,
    ignore: [],
    onblur: function(element) {
      if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
        this.element(element);
      }
    },
    onkeyup: function(element) {
      if ( element.name in this.submitted || element == this.lastElement ) {
        this.element(element);
      }
    },
    onchange: function(element) {
      if ( element.name in this.submitted )
        this.element(element);
    }
  },

  /**
  * Modify default settings for validation.
  *
  * @example jQuery.validator.setDefaults({
  *   debug: true
  * );
  * @desc Sets the debug setting for all validation calls following.
  *
  * @param Object<String, Object> settings
  * @name jQuery.validator.setDefaults
  * @type undefined
  * @cat Plugins/Validate
  */
  setDefaults: function(settings) {
    jQuery.extend( jQuery.validator.defaults, settings );
  },

  /**
  * Default messages for all default methods.
  *
  * Use addMethod() to add methods with messages.
  *
  * Replace these messages for localization.
  *
  * @property
  * @type String
  * @name jQuery.validator.messages
  * @cat Plugins/Validate
  */
  messages: {
    required: "Das Feld darf nicht leer sein.",
    remote: "Please fix this field.",
    email: "Bitte valide E-Mail Adresse eingeben.",
    url: "Bitte valide URL eingeben.",
    date: "Bitte valides Datum eingeben.",
    dateISO: "Bitte Datum eingeben (ISO).",
    dateDE: "Bitte geben Sie ein gültiges Datum ein.",
    number: "Bitte eine Zahl eingeben.",
    numberDE: "Bitte geben Sie eine gültige Zahl ein. ",
    digits: "Nur Ziffern eingeben",
    creditcard: "Bitte gültige Kreditkartennummer eingeben.",
    equalTo: "Bitte wiederholen Sie Eingabe des Feldes.",
    accept: "Bitte nur erlaubte Dateiart auswählen.",
    maxLength: String.format("Bitte geben Sie ein wort nich länger als {0} Zeichen."),
    minLength: String.format("Bitte min {0} Zeichen eingeben."),
    rangeLength: String.format("Bitte geben Sie zwischen {0} und {1} Zeichen ein."),
    rangeValue: String.format("Bitte geben Sie eine Zahl zwischen {0} und {1} ein."),
    maxValue: String.format("Bitte geben Sie ieine Zahl <= {0} ein."),
    minValue: String.format("Bitte geben Sie eine Zahl >= {0} ein.")
  },

  prototype: {

    /**
    * Validate on instant the entire form.
    *
    * @example $("#myform").validate().form();
    * @desc Triggers form validation programmatcitally.
    *
    * @name jQuery.validator.protoype.form
    * @type Boolean True when the form is valid, otherwise false
    * @cat Plugins/Validate
    */
    form: function() {
      this.prepareForm();
      for ( var i = 0; this.elements[i]; i++ ) {
        this.check( this.elements[i] );
      }
      jQuery.extend(this.submitted, this.errorMap);
      this.invalid = jQuery.extend({}, this.errorMap);
      this.settings.invalidHandler && this.settings.invalidHandler.call(this);
      this.showErrors();
      return this.valid();
    },

    /**
    * Validate on instant a single element.
    *
    * @example $("#myform").validate().element( "#myselect" );
    * @desc Triggers validation on a single element programmatically.
    *
    * @param String|Element element A selector or an element to validate
    *
    * @name jQuery.validator.protoype.element
    * @type Boolean True when the element is valid, otherwise false
    * @cat Plugins/Validate
    */
    element: function( element ) {
      element = this.clean( element );
      this.lastElement = element;
      this.prepareElement( element );
      var result = this.check( element );
      if ( result ) {
        delete this.invalid[element.name];
      } else {
        this.invalid[element.name] = true;
      }
      this.showErrors();
      return result;
    },

    /**
    * Show the specified messages.
    *
    * @example var validator = $("#myform").validate();
    * validator.showErrors({"firstname": "I know that your firstname is Pete, Pete!"});
    * @desc Adds and shows error message programmatically.
    *
    * @param Map errors One or more key/value pairs of input names and messages
    *
    * @name jQuery.validator.protoype.showErrors
    * @cat Plugins/Validate
    */
    showErrors: function(errors) {
      if(errors) {
        // add items to error list and map
        jQuery.extend( this.errorMap, errors );
        for ( name in errors ) {
          this.errorList.push({
            message: errors[name],
            element: jQuery("[@name='" + name + "']:first", this.currentForm)[0]
          });
        }
        // remove items from success list
        this.successList = jQuery.grep( this.successList, function(element) {
          return !(element.name in errors);
        });
      }
      this.settings.showErrors
        ? this.settings.showErrors.call( this, this.errorMap, this.errorList )
        : this.defaultShowErrors();
    },

    /**
    * Resets the controlled form, including resetting input fields
    * to their original value (requires form plugin), removing classes
    * indicating invalid elements and hiding error messages.
    *
    * @example var validator = $("#myform").validate();
    * validator.resetForm();
    * @desc Reset the form controlled by this validator.
    *
    * @name jQuery.validator.protoype.resetForm
    * @cat Plugins/Validate
    */
    resetForm: function() {
      if ( jQuery.fn.resetForm )
        jQuery( this.currentForm ).resetForm();
      this.prepareForm();
      this.hideErrors();
      this.elements.removeClass( this.settings.errorClass );
    },

    /**
    * Returns the number of invalid elements in the form.
    *
    * @example $("#myform").validate({
    *   showErrors: function() {
    *     $("#summary").html("Your form contains " + this.numberOfInvalids() + " errors, see details below.");
    *     this.defaultShowErrors();
    *   }
    * });
    * @desc Specifies a custom showErrors callback that updates the number of invalid elements each
    * time the form or a single element is validated.
    *
    * @name jQuery.validator.prototype.numberOfInvalids
    * @type Number
    */
    numberOfInvalids: function() {
      var count = 0;
      for ( i in this.invalid )
        count++;
      return count;
    },

    /**
    * Hides all error messages in this form.
    *
    * @example var validator = $("#myform").validate();
    * $(".cancel").click(function() {
    *   validator.hideErrors();
    * });
    * @desc Specifies a custom showErrors callback that updates the number of invalid elements each
    * time the form or a single element is validated.
    *
    * @name jQuery.validator.prototype.hideErrors
    */
    hideErrors: function() {
      this.addWrapper( this.toHide ).hide();
    },

    valid: function() {
      return this.size() == 0;
    },

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

    focusInvalid: function() {
      if( this.settings.focusInvalid ) {
        try {
          jQuery(this.findLastActive() || this.errorList.length && this.errorList[0].element || []).filter(":visible").focus();
        } catch(e) { /* ignore IE throwing errors when focusing hidden elements */ }
      }
    },

    findLastActive: function() {
      var lastActive = this.lastActive;
      return lastActive && jQuery.grep(this.errorList, function(n) {
        return n.element.name == lastActive.name;
      }).length == 1 && lastActive;
    },

    refresh: function() {
      var validator = this;
      validator.rulesCache = {};

      // select all valid inputs inside the form (no submit or reset buttons)
      this.elements = jQuery(this.currentForm)
      .find("input, select, textarea, button")
      .not(":submit, :reset, :button")
      .not( this.settings.ignore )
      .filter(function() {
        !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);

        // select only the first element for each name, and only those with rules specified
        if ( this.name in validator.rulesCache || !validator.rules(this).length )
          return false;

        validator.rulesCache[this.name] = validator.rules(this);
        return true;
      });


      // and listen for focus events to save reference to last focused element
      this.elements.focus(function() {
        validator.lastActive = this;

        // hide error label and remove error class on focus if enabled
        if ( validator.settings.focusCleanup ) {
          jQuery(this).removeClass( validator.settings.errorClass );
          validator.errorsFor(this).hide();
        }
      });
    },

    clean: function( selector ) {
      return jQuery( selector )[0];
    },

    errors: function() {
      return jQuery( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
    },

    reset: function( element ) {
      this.successList = [];
      this.errorList = [];
      this.errorMap = {};
      this.toShow = jQuery( [] );
      this.toHide = jQuery( [] );
    },

    prepareForm: function() {
      this.reset();
      this.toHide = this.errors().push( this.containers );
    },

    prepareElement: function( element ) {
      this.reset();
      this.toHide = this.errorsFor( this.clean(element) );
    },

    check: function( element ) {
      element = this.clean( element );
      jQuery( element ).removeClass( this.settings.errorClass );
      //var rules = this.rules( element );
      var rules = this.rulesCache[ element.name ];
      for( var i = 0; rules[i]; i++) {
        var rule = rules[i];
        try {
          var result = jQuery.validator.methods[rule.method].call( this, jQuery.trim(element.value), element, rule.parameters );
          if( result === -1 )
            break;
          if( !result ) {
            jQuery( element ).addClass( this.settings.errorClass );
            this.formatAndAdd( rule, element);
            return false;
          }
        } catch(e) {
          this.settings.debug && window.console && console.error("exception occured when checking element " + element.id
            + ", check the '" + rule.method + "' method");
          throw e;
        }
      }
      // show the label for valid elements if success callback is configured
      if ( rules.length && this.settings.success )
        this.successList.push(element);
      return true;
    },

    configuredMessage: function( id, method ) {
      var m = this.settings.messages[id];
      return m && (m.constructor == String
        ? m
        : m[method]);
    },

    defaultMessage: function( element, method) {
      return this.configuredMessage( element.name, method )
        || element.title
        || jQuery.validator.messages[method]
        || "<strong>Warning: No message defined for " + element.name + "</strong>";
    },

    formatAndAdd: function( rule, element) {
      var message = this.defaultMessage( element, rule.method );
      if ( typeof message == "function" )
        message = message.call(this, rule.parameters, element);
      this.errorList.push({
        message: message,
        element: element
      });
      this.errorMap[element.name] = message;
      this.submitted[element.name] = message;
    },

    addWrapper: function(toToggle) {
      if ( this.settings.wrapper )
        toToggle.push( toToggle.parents( this.settings.wrapper ) );
      return toToggle;
    },

    defaultShowErrors: function() {
      for ( var i = 0; this.errorList[i]; i++ ) {
        var error = this.errorList[i];
        this.showLabel( error.element, error.message );
      }
      if( this.errorList.length ) {
        this.toShow.push( this.containers );
      }
      for ( var i = 0; this.successList[i]; i++ ) {
        this.showLabel( this.successList[i] );
      }
      this.toHide = this.toHide.not( this.toShow );
      this.hideErrors();
      this.addWrapper( this.toShow ).show();
    },

    showLabel: function(element, message) {
      var label = this.errorsFor( element );
      if ( label.length ) {
        // refresh error/success class
        label.removeClass().addClass( this.settings.errorClass );

        // check if we have a generated label, replace the message then
        if( this.settings.overrideErrors || label.attr("generated") ) {
          label.html(message);
        }
      } else {
        // create label
        label = jQuery("<" + this.settings.errorElement + "></" + this.settings.errorElement + ">")
          .attr({"for":  this.idOrName(element), generated: true})
          .addClass(this.settings.errorClass)
          .html(message || "");
        if ( this.settings.wrapper ) {
          // make sure the element is visible, even in IE
          // actually showing the wrapped element is handled elsewhere
          label = label.hide().show().wrap("<" + this.settings.wrapper + ">").parent();
        }
        if ( !this.labelContainer.append(label).length )
          this.settings.errorPlacement
            ? this.settings.errorPlacement(label, jQuery(element) )
            : label.insertAfter(element);
      }
      if ( !message && this.settings.success ) {
        label.text("");
        typeof this.settings.success == "string"
          ? label.addClass( this.settings.success )
          : this.settings.success( label );
      }
      this.toShow.push(label);
    },

    errorsFor: function(element) {
      return this.errors().filter("[@for='" + this.idOrName(element) + "']");
    },

    idOrName: function(element) {
      return this.checkable(element) ? element.name : element.id || element.name;
    },

    rules: function( element ) {
      var data = this.data( element );
      if( !data )
        return [];
      var rules = [];
      // convert a simple string to a {string: true} rule, eg. "required" to {required:true}
      if( typeof data == "string" ) {
        var transformed = {};
        transformed[data] = true;
        data = transformed;
      }
      jQuery.each( data, function(key, value) {
        rules[rules.length] = {
          method: key,
          parameters: value
        };
      } );
      return rules;
    },

    data: function( element ) {
      return this.settings.rules
        ? this.settings.rules[ element.name ]
        : this.settings.meta
          ? jQuery(element).data()[ this.settings.meta ]
          : jQuery(element).data();
    },

    checkable: function( element ) {
      return /radio|checkbox/i.test(element.type);
    },

    checkableGroup: function( element ) {
      return jQuery(element.form || document).find('[@name="' + element.name + '"]');
    },

    getLength: function(value, element) {
      switch( element.nodeName.toLowerCase() ) {
      case 'select':
        return jQuery("option:selected", element).length;
      case 'input':
        if( this.checkable( element) )
          return this.checkableGroup( element).filter(':checked').length;
      }
      return value.length;
    },

    depend: function(param, element) {
      return this.dependTypes[typeof param]
        ? this.dependTypes[typeof param](param, element)
        : true;
    },

    dependTypes: {
      "boolean": function(param, element) {
        return param;
      },
      "string": function(param, element) {
        return !!jQuery(param, element.form).length;
      },
      "function": function(param, element) {
        return param(element);
      }
    },

    optional: function(element) {
      return !jQuery.validator.methods.required.call(this, jQuery.trim(element.value), element);
    },

    startRequest: function() {
      this.pendingRequest++;
    },

    stopRequest: function(valid) {
      this.pendingRequest--;
      if ( valid && this.pendingRequest == 0 && this.submitted && this.form() ) {
        jQuery(this.currentForm).submit();
      }
    }

  },

  /**
  * Defines a standard set of useful validation methods.
  *
  * Use jQuery.validator.addMethod() to add your own methods.
  *
  * If "all kind of text inputs" is mentioned for any if the methods defined here,
  * it refers to input elements of type text, password and file and textareas.
  *
  * @param String value The trimmed value of the element, eg. the text of a text input (trimmed: whitespace removed at start and end)
  * @param Element element the input element itself, to check for content of attributes other than value
  * @param Object paramater Some parameter, like a number for min/max rules
  *
  * @property
  * @name jQuery.validator.methods
  * @type Object<String, Function(String,Element,Object):Boolean>
  * @cat Plugins/Validate/Methods
  */
  methods: {

    /**
    * Return false if the element is empty.
    *
    * Works with all kind of text inputs, selects, checkboxes and radio buttons.
    *
    * To force a user to select an option from a select box, provide
    * an empty options like <option value="">Choose...</option>
    *
    * @example <input name="firstname" class="{required:true}" />
    * @desc Declares an input element that is required.
    *
    * @example <input id="other" type="radio" />
    * <input name="details" class="{required:'input[@name=other]:checked'}" />
    * @desc Declares an input element required, but only if a checkbox with name 'other' is checked.
    * In other words: As long 'other' isn't checked, the details field is valid.
    * Note: The expression is evaluated in the context of the current form.
    *
    * @example jQuery("#myform").validate({
    *   rules: {
    *     details: {
    *       required: function(element) {
    *        return jQuery("#other").is(":checked") && jQuery("#other2").is(":checked");
    *      }
    *    }
    *   }
    * });
    * @before <form id="myform">
    *   <input id="other" type="checkbox" />
    *   <input id="other2" type="checkbox" />
    *   <input name="details" />
    * </form>
    * @desc Declares an input element "details" required, but only if two other fields
    * are checked.
    *
    * @example <fieldset>
    *   <legend>Family</legend>
    *   <label for="family_single">
    *     <input  type="radio" id="family_single" value="s" name="family" validate="required:true" />
    *     Single
    *   </label>
    *   <label for="family_married">
    *     <input  type="radio" id="family_married" value="m" name="family" />
    *     Married
    *   </label>
    *   <label for="family_divorced">
    *     <input  type="radio" id="family_divorced" value="d" name="family" />
    *     Divorced
    *   </label>
    *   <label for="family" class="error">Please select your family status.</label>
    * </fieldset>
    * @desc Specifies a group of radio elements. The validation rule is specified only for the first
    * element of the group.
    *
    * @param String value The value of the element to check
    * @param Element element The element to check
    * @param Boolean|String|Function param A boolean "true" makes a field always required; An expression (String)
    * is evaluated in the context of the element's form, making the field required only if the expression returns
    * more than one element. The function is executed with the element as it's only argument: If it returns true,
    * the element is required.
    *
    * @name jQuery.validator.methods.required
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    required: function(value, element, param) {
      // check if dependency is met
      if ( !this.depend(param, element) )
        return -1;
      switch( element.nodeName.toLowerCase() ) {
      case 'select':
        var options = jQuery("option:selected", element);
        return options.length > 0 && ( element.type == "select-multiple" || (jQuery.browser.msie && !(options[0].attributes['value'].specified) ? options[0].text : options[0].value).length > 0);
      case 'input':
        if ( this.checkable(element) )
          return this.getLength(value, element) > 0;
      default:
        return value.length > 0;
      }
    },

    remote: function(value, element, param) {
      if ( this.optional(element) )
        return true;

      var cached = this.valueCache[element.name];
      if(!cached) {
        this.valueCache[element.name] = cached = {
          old: null,
          valid: true,
          message: this.defaultMessage( element, "remote" )
        };
      }
      this.settings.messages[element.name].remote = typeof cached.message == "function" ? cached.message(value) : cached.message;
      if ( cached.old !== value ) {
        cached.old = value;
        var validator = this;
        this.startRequest();
        jQuery.ajax({
          url: param,
          mode: "abort",
          port: "validate",
          dataType: "json",
          data: {value: value},
          success: function(response) {
            if ( !response ) {
              var errors = {};
              errors[element.name] =  validator.defaultMessage( element, "remote" );
              validator.showErrors(errors);
            }
            cached.valid = response;
            validator.stopRequest(response);
          }
        });
        return true;
      }
      return cached.valid;
    },

    /**
    * Return false, if the element is
    *
    * - some kind of text input and its value is too short
    *
    * - a set of checkboxes has not enough boxes checked
    *
    * - a select and has not enough options selected
    *
    * Works with all kind of text inputs, checkboxes and select.
    *
    * @example <input name="firstname" class="{minLength:5}" />
    * @desc Declares an optional input element with at least 5 characters (or none at all).
    *
    * @example <input name="firstname" class="{required:true,minLength:5}" />
    * @desc Declares an input element that must have at least 5 characters.
    *
    * @example <fieldset>
    *   <legend>Spam</legend>
    *   <label for="spam_email">
    *     <input type="checkbox" id="spam_email" value="email" name="spam" validate="required:true,minLength:2" />
    *     Spam via E-Mail
    *   </label>
    *   <label for="spam_phone">
    *     <input type="checkbox" id="spam_phone" value="phone" name="spam" />
    *     Spam via Phone
    *   </label>
    *   <label for="spam_mail">
    *     <input type="checkbox" id="spam_mail" value="mail" name="spam" />
    *     Spam via Mail
    *   </label>
    *   <label for="spam" class="error">Please select at least two types of spam.</label>
    * </fieldset>
    * @desc Specifies a group of checkboxes. To validate, at least two checkboxes must be selected.
    *
    * @param Number min
    * @name jQuery.validator.methods.minLength
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    minLength: function(value, element, param) {
      return this.optional(element) || this.getLength(value, element) >= param;
    },

    /**
    * Return false, if the element is
    *
    * - some kind of text input and its value is too big
    *
    * - a set of checkboxes has too many boxes checked
    *
    * - a select and has too many options selected
    *
    * Works with all kind of text inputs, checkboxes and selects.
    *
    * @example <input name="firstname" class="{maxLength:5}" />
    * @desc Declares an input element with at most 5 characters.
    *
    * @example <input name="firstname" class="{required:true,maxLength:5}" />
    * @desc Declares an input element that must have at least one and at most 5 characters.
    *
    * @param Number max
    * @name jQuery.validator.methods.maxLength
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    maxLength: function(value, element, param) {
      return this.optional(element) || this.getLength(value, element) <= param;
    },

    /**
    * Return false, if the element is
    *
      * - some kind of text input and its value is too short or too long
      *
      * - a set of checkboxes has not enough or too many boxes checked
      *
      * - a select and has not enough or too many options selected
      *
      * Works with all kind of text inputs, checkboxes and selects.
      *
    * @example <input name="firstname" class="{rangeLength:[3,5]}" />
    * @desc Declares an optional input element with at least 3 and at most 5 characters (or none at all).
    *
    * @example <input name="firstname" class="{required:true,rangeLength:[3,5]}" />
    * @desc Declares an input element that must have at least 3 and at most 5 characters.
    *
    * @example <select id="cars" class="{required:true,rangeLength:[2,3]}" multiple="multiple">
    *   <option value="m_sl">Mercedes SL</option>
    *   <option value="o_c">Opel Corsa</option>
    *   <option value="vw_p">VW Polo</option>
    *   <option value="t_s">Titanic Skoda</option>
    * </select>
    * @desc Specifies a select that must have at least two but no more than three options selected.
    *
      * @param Array<Number> min/max
      * @name jQuery.validator.methods.rangeLength
      * @type Boolean
      * @cat Plugins/Validate/Methods
      */
    rangeLength: function(value, element, param) {
      var length = this.getLength(value, element);
      return this.optional(element) || ( length >= param[0] && length <= param[1] );
    },

    /**
    * Return true, if the value is greater than or equal to the specified minimum.
    *
    * Works with all kind of text inputs.
    *
    * @example <input name="age" class="{minValue:16}" />
    * @desc Declares an optional input element whose value must be at least 16 (or none at all).
    *
    * @example <input name="age" class="{required:true,minValue:16}" />
    * @desc Declares an input element whose value must be at least 16.
    *
    * @param Number min
    * @name jQuery.validator.methods.minValue
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    minValue: function( value, element, param ) {
      return this.optional(element) || value >= param;
    },

    /**
    * Return true, if the value is less than or equal to the specified maximum.
    *
    * Works with all kind of text inputs.
    *
    * @example <input name="age" class="{maxValue:16}" />
    * @desc Declares an optional input element whose value must be at most 16 (or none at all).
    *
    * @example <input name="age" class="{required:true,maxValue:16}" />
    * @desc Declares an input element whose required value must be at most 16.
    *
    * @param Number max
    * @name jQuery.validator.methods.maxValue
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    maxValue: function( value, element, param ) {
      return this.optional(element) || value <= param;
    },

    /**
    * Return true, if the value is in the specified range.
    *
    * Works with all kind of text inputs.
    *
    * @example <input name="age" class="{rangeValue:[4,12]}" />
    * @desc Declares an optional input element whose value must be at least 4 and at most 12 (or none at all).
    *
    * @example <input name="age" class="{required:true,rangeValue:[4,12]}" />
    * @desc Declares an input element whose required value must be at least 4 and at most 12.
    *
    * @param Array<Number> min/max
    * @name jQuery.validator.methods.rangeValue
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    rangeValue: function( value, element, param ) {
      return this.optional(element) || ( value >= param[0] && value <= param[1] );
    },

    /**
    * Return true, if the value is not a valid email address.
    *
    * Works with all kind of text inputs.
    *
    * @example <input name="email1" class="{email:true}" />
    * @desc Declares an optional input element whose value must be a valid email address (or none at all).
    *
    * @example <input name="email1" class="{required:true,email:true}" />
    * @desc Declares an input element whose value must be a valid email address.
    *
    * @name jQuery.validator.methods.email
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    email: function(value, element) {
      return this.optional(element) || /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/i.test(value);
    },

    /**
    * Return true, if the value is a valid url.
    *
    * Works with all kind of text inputs.
    *
    * See http://www.w3.org/Addressing/rfc1738.txt for URL specification.
    *
    * @example <input name="homepage" class="{url:true}" />
    * @desc Declares an optional input element whose value must be a valid URL (or none at all).
    *
    * @example <input name="homepage" class="{required:true,url:true}" />
    * @desc Declares an input element whose value must be a valid URL.
    *
    * @name jQuery.validator.methods.url
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    url: function(value, element) {
      return this.optional(element) || /^(https?|ftp):\/\/[A-Z0-9](\.?[A-Z0-9Ã„ÃœÃ–][A-Z0-9_\-Ã„ÃœÃ–]*)*(\/([A-Z0-9Ã„ÃœÃ–][A-Z0-9_\-\.Ã„ÃœÃ–]*)?)*(\?([A-Z0-9Ã„ÃœÃ–][A-Z0-9_\-\.%\+=&Ã„ÃœÃ–]*)?)?$/i.test(value);
    },

    /**
    * Return true, if the value is a valid date. Uses JavaScripts built-in
    * Date to test if the date is valid, and is therefore very limited.
    *
    * Works with all kind of text inputs.
    *
    * @example <input name="birthdate" class="{date:true}" />
    * @desc Declares an optional input element whose value must be a valid date (or none at all).
    *
    * @example <input name="birthdate" class="{required:true,date:true}" />
    * @desc Declares an input element whose value must be a valid date.
    *
    * @name jQuery.validator.methods.date
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    date: function(value, element) {
      return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
    },

    /**
    * Return true, if the value is a valid date, according to ISO date standard.
    *
    * Works with all kind of text inputs.
    *
    * @example jQuery.validator.methods.dateISO("1990/01/01")
    * @result true
    *
    * @example jQuery.validator.methods.dateISO("1990-01-01")
    * @result true
    *
    * @example jQuery.validator.methods.dateISO("01.01.1990")
    * @result false
    *
    * @example <input name="birthdate" class="{dateISO:true}" />
    * @desc Declares an optional input element whose value must be a valid ISO date (or none at all).
    *
    * @name jQuery.validator.methods.date
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    dateISO: function(value, element) {
      return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
    },

    /**
    * Return true, if the value is a valid date. Supports german
    * dates (29.04.1994 or 1.1.2006). Doesn't make any sanity checks.
    *
    * Works with all kind of text inputs.
    *
    * @example jQuery.validator.methods.dateDE("1990/01/01")
    * @result false
    *
    * @example jQuery.validator.methods.dateDE("01.01.1990")
    * @result true
    *
    * @example jQuery.validator.methods.dateDE("0.1.2345")
    * @result true
    *
    * @example <input name="geburtstag" class="{dateDE:true}" />
    * @desc Declares an optional input element whose value must be a valid german date (or none at all).
    *
    * @name jQuery.validator.methods.dateDE
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    dateDE: function(value, element) {
      return this.optional(element) || /^\d\d\.\d\d\.\d\d\d\d$/.test(value);
    },

    /**
    * Return true, if the value is a valid number. Checks for
    * international number format, eg. 100,000.59
    *
    * Works with all kind of text inputs.
    *
    * @example <input name="amount" class="{number:true}" />
    * @desc Declares an optional input element whose value must be a valid number (or none at all).
    *
    * @name jQuery.validator.methods.number
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    number: function(value, element) {
      return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
    },

    /**
    * Return true, if the value is a valid number.
    *
    * Works with all kind of text inputs.
    *
    * Checks for german numbers (100.000,59)
    *
    * @example <input name="menge" class="{numberDE:true}" />
    * @desc Declares an optional input element whose value must be a valid german number (or none at all).
    *
    * @name jQuery.validator.methods.numberDE
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    numberDE: function(value, element) {
      return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(value);
    },

    /**
    * Returns true if the value contains only digits.
    *
    * Works with all kind of text inputs.
    *
    * @example <input name="serialnumber" class="{digits:true}" />
    * @desc Declares an optional input element whose value must contain only digits (or none at all).
    *
    * @name jQuery.validator.methods.digits
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    digits: function(value, element) {
      return this.optional(element) || /^\d+$/.test(value);
    },

    /**
         * Return true, if the value is a valid credit card number.
         *
         * Works with all kind of text inputs.
         *
         * @example <input name="cc1" class="{required:true,creditcard:true}" />
         * @desc Declares a required input element whose value must be a valid credit card number (ignoring any non-digts).
         *
         * @example <input name="cc2" class="{required:true,digits:true,creditcard:true}" />
         * @desc Declares a required input element whose value must be a valid credit card number.  No spaces or dashes allowed.
         *
         * @name jQuery.validator.methods.creditcard
         * @type Boolean
         * @cat Plugins/Validate/Methods
         */
    creditcard: function(value, element) {
      if ( this.optional(element) )
        return true;
      var nCheck = 0,
        nDigit = 0,
        bEven = false;

      value = value.replace(/\D/g, "");

      for (n = value.length - 1; n >= 0; n--) {
        var cDigit = value.charAt(n);
        var nDigit = parseInt(cDigit, 10);
        if (bEven) {
          if ((nDigit *= 2) > 9)
            nDigit -= 9;
        }
        nCheck += nDigit;
        bEven = !bEven;
      }

      return (nCheck % 10) == 0;
    },

    /**
    * Returns true if the value ends with one of the specified file extensions.
    * If nothing is specified, only images are allowed (default-param: "png|jpe?g|gif").
    *
    * Works with all kind of text inputs.
    *
    * @example <input type="file" name="avatar" class="{accept:true}" />
    * @desc Declares an optional file input element whose value must ends with '.png', '.jpg', '.jpeg' or '.gif'.
    *
    * @example <input type="file" name="avatar" class="{accept:'txt|docx?'}" />
    * @desc Declares an optional file input element whose value must ends with '.txt' or '.doc' or '.docx'.
    *
    * @name jQuery.validator.methods.accept
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    accept: function(value, element, param) {
      param = typeof param == "string" ? param : "png|jpe?g|gif";
      return this.optional(element) || value.match(new RegExp(".(" + param + ")$"));
    },

    /**
    * Returns true if the value has the same value
    * as the element specified by the first parameter.
    *
    * Keep the expression simple to avoid spaces when using metadata.
    *
    * Works with all kind of text inputs.
    *
    * @example <input name="email" id="email" class="{required:true,email:true'}" />
    * <input name="emailAgain" class="{equalTo:'#email'}" />
    * @desc Declares two input elements: The first must contain a valid email address,
    * the second must contain the same adress, enter once more. The paramter is a
    * expression used via jQuery to select the element.
    *
    * @param String selection A jQuery expression
    * @name jQuery.validator.methods.equalTo
    * @type Boolean
    * @cat Plugins/Validate/Methods
    */
    equalTo: function(value, element, param) {
      return value == jQuery(param).val();
    }

  },

  /**
  * Add a new validation method. It must consist of a name (must be a legal
  * javascript identifier), a function and a default message.
  *
  * Please note: While the temptation is great to
  * add a regex method that checks it's paramter against the value,
  * it is much cleaner to encapsulate those regular expressions
  * inside their own method. If you need lots of slightly different
  * expressions, try to extract a common parameter.
  *
  * A library of regular expressions: http://regexlib.com/DisplayPatterns.aspx
  *
  * @example jQuery.validator.addMethod("domain", function(value) {
  *   return /^http://mycorporatedomain.com/.test(value);
  * }, "Please specify the correct domain for your documents");
  * @desc Adds a method that checks if the value starts with http://mycorporatedomain.com
  *
  * @example jQuery.validator.addMethod("math", function(value, element, params) {
  *  return this.optional(value, element) || value == params[0] + params[1];
  * }, "Please enter the correct value for this simple question.");
  * @desc Adds a not-required method...
  *
  * @see jQuery.validator.methods
  *
  * @param String name The name of the method, used to identify and referencing it, must be a valid javascript identifier
  * @param Function rule The actual method implementation, returning true if an element is valid
  * @param String message The default message to display for this method
  *
  * @name jQuery.validator.addMethod
  * @type undefined
  * @cat Plugins/Validate
  */
  addMethod: function(name, method, message) {
    jQuery.validator.methods[name] = method;
    jQuery.validator.messages[name] = message;
  }
});;