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;}('G 1i={8h:\'1.6.0.2\',1J:{3a:!!(1s.9R&&!1s.4K),6e:!!1s.4K,3L:4L.5D.2r(\'kA/\')>-1,8i:4L.5D.2r(\'8i\')>-1&&4L.5D.2r(\'fw\')==-1,fx:!!4L.5D.1C(/kB.*kC.*fy/)},4M:{9S:!!19.3b,8j:!!1s.8k,9T:19.2b(\'2H\').6f&&19.2b(\'2H\').6f!==19.2b(\'8l\').6f},9U:\'<4s[^>]*>([\\\\S\\\\s]*?)<\\/4s>\',fz:/^\\/\\*-kD-([\\s\\S]*)\\*\\/\\s*$/,2I:C(){},K:C(x){E x}};if(1i.1J.fx)1i.4M.9T=14;G 1D={1E:C(){G a=1e,8m=$A(1f);if(O.2c(8m[0]))a=8m.6g();C 3y(){q.1K.4c(q,1f)}O.Y(3y,1D.1m);3y.cj=a;3y.fA=[];if(a){G b=C(){};b.1p=a.1p;3y.1p=1b b;a.fA.1j(3y)}1h(G i=0;i<8m.V;i++)3y.7a(8m[i]);if(!3y.1p.1K)3y.1p.1K=1i.2I;3y.1p.kE=3y;E 3y}};1D.1m={7a:C(a){G b=q.cj&&q.cj.1p;G c=O.6h(a);if(!O.6h({2S:1c}).V)c.1j("2S","fB");1h(G i=0,V=c.V;i<V;i++){G d=c[i],1k=a[d];if(b&&O.2c(1k)&&1k.fC().3M()=="$4t"){G e=1k,1k=O.Y((C(m){E C(){E b[m].4c(q,1f)}})(d).6i(e),{fB:C(){E e},2S:C(){E e.2S()}})}q.1p[d]=1k}E q}};G 6j={};O.Y=C(a,b){1h(G c in b)a[c]=b[c];E a};O.Y(O,{2m:C(a){2s{if(O.2z(a))E\'3j\';if(a===1e)E\'1e\';E a.2m?a.2m():1T(a)}2A(e){if(e ck kF)E\'...\';2T e;}},4d:C(a){G b=2i a;4N(b){1H\'3j\':1H\'C\':1H\'kG\':E;1H\'kH\':E a.2S()}if(a===1e)E\'1e\';if(a.4d)E a.4d();if(O.5e(a))E;G c=[];1h(G d in a){G e=O.4d(a[d]);if(!O.2z(e))c.1j(d.4d()+\': \'+e)}E\'{\'+c.2d(\', \')+\'}\'},5E:C(a){E $H(a).5E()},5f:C(a){E a&&a.5f?a.5f():1T.7b(a)},6h:C(a){G b=[];1h(G c in a)b.1j(c);E b},1O:C(a){G b=[];1h(G c in a)b.1j(a[c]);E b},2B:C(a){E O.Y({},a)},5e:C(a){E a&&a.3k==1},4e:C(a){E a!=1e&&2i a=="2U"&&\'kI\'in a&&\'2d\'in a},cl:C(a){E a ck 4O},2c:C(a){E 2i a=="C"},2t:C(a){E 2i a=="7c"},5F:C(a){E 2i a=="fD"},2z:C(a){E 2i a=="3j"}});O.Y(co.1p,{fC:C(){G a=q.2S().1C(/^[\\s\\(]*C[^(]*\\((.*?)\\)/)[1].3N(",").7d("3l");E a.V==1&&!a[0]?[]:a},1o:C(){if(1f.V<2&&O.2z(1f[0]))E q;G a=q,3m=$A(1f),2U=3m.6g();E C(){E a.4c(2U,3m.22($A(1f)))}},3O:C(){G b=q,3m=$A(1f),2U=3m.6g();E C(a){E b.4c(2U,[a||1s.4u].22(3m))}},9V:C(){if(!1f.V)E q;G a=q,3m=$A(1f);E C(){E a.4c(q,3m.22($A(1f)))}},3c:C(){G a=q,3m=$A(1f),fE=3m.6g()*3P;E 1s.6k(C(){E a.4c(a,3m)},fE)},6i:C(a){G b=q;E C(){E a.4c(q,[b.1o(q)].22($A(1f)))}},5G:C(){if(q.cp)E q.cp;G a=q;E q.cp=C(){E a.4c(1e,[q].22($A(1f)))}}});co.1p.5H=co.1p.3c.9V(0.fF);8n.1p.4d=C(){E\'"\'+q.kJ()+\'-\'+(q.kK()+1).5I(2)+\'-\'+q.kL().5I(2)+\'T\'+q.kM().5I(2)+\':\'+q.kN().5I(2)+\':\'+q.kO().5I(2)+\'Z"\'};G fG={fH:C(){G a;1h(G i=0,V=1f.V;i<V;i++){G b=1f[i];2s{a=b();1I}2A(e){}}E a}};5g.1p.1C=5g.1p.2C;5g.fI=C(a){E 1T(a).1S(/([.*+?^=!:${}()|[\\]\\/\\\\])/g,\'\\\\$1\')};G fJ=1D.1E({1K:C(a,b){q.4v=a;q.5J=b;q.9W=14;q.8o()},8o:C(){q.4w=9X(q.6l.1o(q),q.5J*3P)},cq:C(){q.4v(q)},2M:C(){if(!q.4w)E;9Y(q.4w);q.4w=1e},6l:C(){if(!q.9W){2s{q.9W=1c;q.cq()}kP{q.9W=14}}}});O.Y(1T,{7b:C(a){E a==1e?\'\':1T(a)},fK:{\'\\b\':\'\\\\b\',\'\\t\':\'\\\\t\',\'\\n\':\'\\\\n\',\'\\f\':\'\\\\f\',\'\\r\':\'\\\\r\',\'\\\\\':\'\\\\\\\\\'}});O.Y(1T.1p,{3z:C(a,b){G c=\'\',5K=q,1C;b=1f.5h.cr(b);1Q(5K.V>0){if(1C=5K.1C(a)){c+=5K.3n(0,1C.2u);c+=1T.7b(b(1C));5K=5K.3n(1C.2u+1C[0].V)}1d{c+=5K,5K=\'\'}}E c},fL:C(b,c,d){c=q.3z.cr(c);d=O.2z(d)?1:d;E q.3z(b,C(a){if(--d<0)E a[0];E c(a)})},fM:C(a,b){q.3z(a,b);E 1T(q)},kQ:C(a,b){a=a||30;b=O.2z(b)?\'...\':b;E q.V>a?q.3n(0,a-b.V)+b:1T(q)},3l:C(){E q.1S(/^\\s+/,\'\').1S(/\\s+$/,\'\')},8p:C(){E q.1S(/<\\/?[^>]+>/gi,\'\')},4P:C(){E q.1S(1b 5g(1i.9U,\'fN\'),\'\')},fO:C(){G b=1b 5g(1i.9U,\'fN\');G c=1b 5g(1i.9U,\'im\');E(q.1C(b)||[]).1R(C(a){E(a.1C(c)||[\'\',\'\'])[1]})},5L:C(){E q.fO().1R(C(a){E 7e(a)})},8q:C(){G a=1f.5h;a.3Q.fP=q;E a.2H.2V},fQ:C(){G c=1b M(\'2H\');c.2V=q.8p();E c.2o[0]?(c.2o.V>1?$A(c.2o).3A(\'\',C(a,b){E a+b.7f}):c.2o[0].7f):\'\'},8r:C(e){G f=q.3l().1C(/([^?#]*)(#.*)?$/);if(!f)E{};E f[1].3N(e||\'&\').3A({},C(a,b){if((b=b.3N(\'=\'))[0]){G c=cs(b.6g());G d=b.V>1?b.2d(\'=\'):b[0];if(d!=3j)d=cs(d);if(c in a){if(!O.4e(a[c]))a[c]=[a[c]];a[c].1j(d)}1d a[c]=d}E a})},3R:C(){E q.3N(\'\')},ct:C(){E q.3n(0,q.V-1)+1T.fR(q.fS(q.V-1)+1)},9Z:C(a){E a<1?\'\':1b 2v(a+1).2d(q)},8s:C(){G a=q.3N(\'-\'),8t=a.V;if(8t==1)E a[0];G b=q.5M(0)==\'-\'?a[0].5M(0).2e()+a[0].5i(1):a[0];1h(G i=1;i<8t;i++)b+=a[i].5M(0).2e()+a[i].5i(1);E b},8u:C(){E q.5M(0).2e()+q.5i(1).1U()},kR:C(){E q.3z(/::/,\'/\').3z(/([A-Z]+)([A-Z][a-z])/,\'#{1}3S#{2}\').3z(/([a-z\\d])([A-Z])/,\'#{1}3S#{2}\').3z(/-/,\'3S\').1U()},fT:C(){E q.3z(/3S/,\'-\')},2m:C(c){G d=q.3z(/[\\kS-\\kT\\\\]/,C(a){G b=1T.fK[a[0]];E b?b:\'\\\\kU\'+a[0].fS().5I(2,16)});if(c)E\'"\'+d.1S(/"/g,\'\\\\"\')+\'"\';E"\'"+d.1S(/\'/g,\'\\\\\\\'\')+"\'"},4d:C(){E q.2m(1c)},cu:C(a){E q.fL(a||1i.fz,\'#{1}\')},fU:C(){G a=q;if(a.6m())E 14;a=q.1S(/\\\\./g,\'@\').1S(/"[^"\\\\\\n\\r]*"/g,\'\');E(/^[,:{}\\[\\]0-9.\\-+kV-u \\n\\r\\t]*$/).2C(a)},7g:C(a){G b=q.cu();2s{if(!a||b.fU())E 7e(\'(\'+b+\')\')}2A(e){}2T 1b kW(\'kX kY fV 7c: \'+q.2m());},1L:C(a){E q.2r(a)>-1},cv:C(a){E q.2r(a)===0},fW:C(a){G d=q.V-a.V;E d>=0&&q.a0(a)===d},6n:C(){E q==\'\'},6m:C(){E/^\\s*$/.2C(q)},fX:C(a,b){E 1b 3d(q,b).3b(a)}});if(1i.1J.3L||1i.1J.3a)O.Y(1T.1p,{8q:C(){E q.1S(/&/g,\'&fY;\').1S(/</g,\'&lt;\').1S(/>/g,\'&gt;\')},fQ:C(){E q.1S(/&fY;/g,\'&\').1S(/&lt;/g,\'<\').1S(/&gt;/g,\'>\')}});1T.1p.3z.cr=C(b){if(O.2c(b))E b;G c=1b 3d(b);E C(a){E c.3b(a)}};1T.1p.kZ=1T.1p.8r;O.Y(1T.1p.8q,{2H:19.2b(\'2H\'),3Q:19.6o(\'\')});6p(1T.1p.8q)2H.2j(3Q);G 3d=1D.1E({1K:C(a,b){q.8v=a.2S();q.fZ=b||3d.g0},3b:C(f){if(O.2c(f.cw))f=f.cw();E q.8v.3z(q.fZ,C(a){if(f==1e)E\'\';G b=a[1]||\'\';if(b==\'\\\\\')E a[2];G c=f,8w=a[3];G d=/^([^.[]+|\\[((?:.*?[^\\\\])?)\\])(\\.|\\[|$)/;a=d.g1(8w);if(a==1e)E b;1Q(a!=1e){G e=a[1].cv(\'[\')?a[2].3z(\'\\\\\\\\]\',\']\'):a[1];c=c[e];if(1e==c||\'\'==a[3])1I;8w=8w.5i(\'[\'==a[3]?a[1].V:a[0].V);a=d.g1(8w)}E b+1T.7b(c)})}});3d.g0=/(^|.|\\r|\\n)(#\\{(.*?)\\})/;G $1I={};G 2W={1n:C(b,c){G d=0;b=b.1o(c);2s{q.4x(C(a){b(a,d++)})}2A(e){if(e!=$1I)2T e;}E q},g2:C(a,b,c){b=b?b.1o(c):1i.K;G d=-a,cx=[],7h=q.3R();1Q((d+=a)<7h.V)cx.1j(7h.3n(d,d+a));E cx.7i(b,c)},cy:C(c,d){c=c?c.1o(d):1i.K;G e=1c;q.1n(C(a,b){e=e&&!!c(a,b);if(!e)2T $1I;});E e},cz:C(c,d){c=c?c.1o(d):1i.K;G e=14;q.1n(C(a,b){if(e=!!c(a,b))2T $1I;});E e},7i:C(c,d){c=c?c.1o(d):1i.K;G e=[];q.1n(C(a,b){e.1j(c(a,b))});E e},5N:C(c,d){c=c.1o(d);G e;q.1n(C(a,b){if(c(a,b)){e=a;2T $1I;}});E e},5O:C(c,d){c=c.1o(d);G e=[];q.1n(C(a,b){if(c(a,b))e.1j(a)});E e},l0:C(c,d,e){d=d?d.1o(e):1i.K;G f=[];if(O.2t(c))c=1b 5g(c);q.1n(C(a,b){if(c.1C(a))f.1j(d(a,b))});E f},1L:C(b){if(O.2c(q.2r))if(q.2r(b)!=-1)E 1c;G c=14;q.1n(C(a){if(a==b){c=1c;2T $1I;}});E c},l1:C(b,c){c=O.2z(c)?1e:c;E q.g2(b,C(a){1Q(a.V<b)a.1j(c);E a})},3A:C(c,d,e){d=d.1o(e);q.1n(C(a,b){c=d(c,a,b)});E c},7d:C(b){G c=$A(1f).3n(1);E q.1R(C(a){E a[b].4c(a,c)})},4Q:C(c,d){c=c?c.1o(d):1i.K;G e;q.1n(C(a,b){a=c(a,b);if(e==1e||a>=e)e=a});E e},7j:C(c,d){c=c?c.1o(d):1i.K;G e;q.1n(C(a,b){a=c(a,b);if(e==1e||a<e)e=a});E e},l2:C(c,d){c=c?c.1o(d):1i.K;G e=[],cA=[];q.1n(C(a,b){(c(a,b)?e:cA).1j(a)});E[e,cA]},5P:C(b){G c=[];q.1n(C(a){c.1j(a[b])});E c},6q:C(c,d){c=c.1o(d);G e=[];q.1n(C(a,b){if(!c(a,b))e.1j(a)});E e},a1:C(e,f){e=e.1o(f);E q.1R(C(a,b){E{1k:a,8x:e(a,b)}}).l3(C(c,d){G a=c.8x,b=d.8x;E a<b?-1:a>b?1:0}).5P(\'1k\')},3R:C(){E q.1R()},l4:C(){G c=1i.K,3m=$A(1f);if(O.2c(3m.2D()))c=3m.l5();G d=[q].22(3m).1R($A);E q.1R(C(a,b){E c(d.5P(b))})},6r:C(){E q.3R().V},2m:C(){E\'#<2W:\'+q.3R().2m()+\'>\'}};O.Y(2W,{1R:2W.7i,cB:2W.5N,24:2W.5O,6s:2W.5O,l6:2W.1L,l7:2W.3R,l8:2W.cy,l9:2W.cz});C $A(a){if(!a)E[];if(a.3R)E a.3R();G b=a.V||0,1q=1b 2v(b);1Q(b--)1q[b]=a[b];E 1q}if(1i.1J.3L){$A=C(a){if(!a)E[];if(!(O.2c(a)&&a==\'[2U la]\')&&a.3R)E a.3R();G b=a.V||0,1q=1b 2v(b);1Q(b--)1q[b]=a[b];E 1q}}2v.3e=$A;O.Y(2v.1p,2W);if(!2v.1p.cC)2v.1p.cC=2v.1p.7k;O.Y(2v.1p,{4x:C(a){1h(G i=0,V=q.V;i<V;i++)a(q[i])},g3:C(){q.V=0;E q},3M:C(){E q[0]},2D:C(){E q[q.V-1]},g4:C(){E q.24(C(a){E a!=1e})},3T:C(){E q.3A([],C(a,b){E a.22(O.4e(b)?b.3T():[b])})},7l:C(){G b=$A(1f);E q.24(C(a){E!b.1L(a)})},7k:C(a){E(a!==14?q:q.3R()).cC()},lb:C(){E q.V>1?q:q[0]},g5:C(d){E q.3A([],C(a,b,c){if(0==c||(d?a.2D()!=b:!a.1L(b)))a.1j(b);E a})},lc:C(c){E q.g5().5O(C(b){E c.5N(C(a){E b===a})})},2B:C(){E[].22(q)},6r:C(){E q.V},2m:C(){E\'[\'+q.1R(O.2m).2d(\', \')+\']\'},4d:C(){G c=[];q.1n(C(a){G b=O.4d(a);if(!O.2z(b))c.1j(b)});E\'[\'+c.2d(\', \')+\']\'}});if(O.2c(2v.1p.g6))2v.1p.4x=2v.1p.g6;if(!2v.1p.2r)2v.1p.2r=C(a,i){i||(i=0);G b=q.V;if(i<0)i=b+i;1h(;i<b;i++)if(q[i]===a)E i;E-1};if(!2v.1p.a0)2v.1p.a0=C(a,i){i=cD(i)?q.V:(i<0?q.V+i:i)+1;G n=q.3n(0,i).7k().2r(a);E(n<0)?n:i-n-1};2v.1p.3R=2v.1p.2B;C $w(a){if(!O.2t(a))E[];a=a.3l();E a?a.3N(/\\s+/):[]}if(1i.1J.6e){2v.1p.22=C(){G a=[];1h(G i=0,V=q.V;i<V;i++)a.1j(q[i]);1h(G i=0,V=1f.V;i<V;i++){if(O.4e(1f[i])){1h(G j=0,g7=1f[i].V;j<g7;j++)a.1j(1f[i][j])}1d{a.1j(1f[i])}}E a}}O.Y(6t.1p,{7m:C(){E q.5I(2,16)},ct:C(){E q+1},9Z:C(a){$R(0,q,1c).1n(a);E q},5I:C(a,b){G c=q.2S(b||10);E\'0\'.9Z(a-c.V)+c},4d:C(){E ld(q)?q.2S():\'1e\'}});$w(\'8y 3o lf cE\').1n(C(a){6t.1p[a]=2w[a].5G()});C $H(a){E 1b 4O(a)};G 4O=1D.1E(2W,(C(){C cF(a,b){if(O.2z(b))E a;E a+\'=\'+4y(1T.7b(b))}E{1K:C(a){q.5Q=O.cl(a)?a.8z():O.2B(a)},4x:C(a){1h(G b in q.5Q){G c=q.5Q[b],a2=[b,c];a2.4f=b;a2.1k=c;a(a2)}},5j:C(a,b){E q.5Q[a]=b},3p:C(a){E q.5Q[a]},lg:C(a){G b=q.5Q[a];7n q.5Q[a];E b},8z:C(){E O.2B(q.5Q)},6h:C(){E q.5P(\'4f\')},1O:C(){E q.5P(\'1k\')},2u:C(b){G c=q.5N(C(a){E a.1k===b});E c&&c.4f},lh:C(a){E q.2B().1A(a)},1A:C(c){E 1b 4O(c).3A(q,C(a,b){a.5j(b.4f,b.1k);E a})},5E:C(){E q.1R(C(a){G b=4y(a.4f),1O=a.1k;if(1O&&2i 1O==\'2U\'){if(O.4e(1O))E 1O.1R(cF.9V(b)).2d(\'&\')}E cF(b,1O)}).2d(\'&\')},2m:C(){E\'#<4O:{\'+q.1R(C(a){E a.1R(O.2m).2d(\': \')}).2d(\', \')+\'}>\'},4d:C(){E O.4d(q.8z())},2B:C(){E 1b 4O(q)}}})());4O.1p.cw=4O.1p.8z;4O.3e=$H;G g8=1D.1E(2W,{1K:C(a,b,c){q.1V=a;q.3B=b;q.g9=c},4x:C(a){G b=q.1V;1Q(q.1L(b)){a(b);b=b.ct()}},1L:C(a){if(a<q.1V)E 14;if(q.g9)E a<q.3B;E a<=q.3B}});G $R=C(a,b,c){E 1b g8(a,b,c)};G 1x={ga:C(){E fG.fH(C(){E 1b gb()},C(){E 1b gc(\'lj.gd\')},C(){E 1b gc(\'ge.gd\')})||14},cG:0};1x.7o={8A:[],4x:C(a){q.8A.4x(a)},a3:C(a){if(!q.1L(a))q.8A.1j(a)},cH:C(a){q.8A=q.8A.7l(a)},a4:C(b,c,d,f){q.1n(C(a){if(O.2c(a[b])){2s{a[b].4c(a,[c,d,f])}2A(e){}}})}};O.Y(1x.7o,2W);1x.7o.a3({a5:C(){1x.cG++},2N:C(){1x.cG--}});1x.3f=1D.1E({1K:C(a){q.J={1W:\'8B\',8C:1c,gf:\'a6/x-lk-8l-ll\',cI:\'lm-8\',2E:\'\',7g:1c,cJ:1c};O.Y(q.J,a||{});q.J.1W=q.J.1W.1U();if(O.2t(q.J.2E))q.J.2E=q.J.2E.8r();1d if(O.cl(q.J.2E))q.J.2E=q.J.2E.8z()}});1x.4g=1D.1E(1x.3f,{cK:14,1K:C($4t,b,c){$4t(c);q.2O=1x.ga();q.4R(b)},4R:C(a){q.3g=a;q.1W=q.J.1W;G b=O.2B(q.J.2E);if(![\'3p\',\'8B\'].1L(q.1W)){b[\'ln\']=q.1W;q.1W=\'8B\'}q.2E=b;if(b=O.5E(b)){if(q.1W==\'3p\')q.3g+=(q.3g.1L(\'?\')?\'&\':\'?\')+b;1d if(/lo|fy|fw/.2C(4L.5D))b+=\'&3S=\'}2s{G c=1b 1x.cL(q);if(q.J.a5)q.J.a5(c);1x.7o.a4(\'a5\',q,c);q.2O.lp(q.1W.2e(),q.3g,q.J.8C);if(q.J.8C)q.cM.1o(q).5H(1);q.2O.a7=q.cN.1o(q);q.gg();q.28=q.1W==\'8B\'?(q.J.lq||b):1e;q.2O.lr(q.28);if(!q.J.8C&&q.2O.gh)q.cN()}2A(e){q.6u(e)}},cN:C(){G a=q.2O.4S;if(a>1&&!((a==4)&&q.cK))q.cM(q.2O.4S)},gg:C(){G b={\'X-ls-lu\':\'gb\',\'X-1i-8h\':1i.8h,\'lv\':\'3Q/cO, 3Q/lw, a6/gj, 3Q/gj, */*\'};if(q.1W==\'8B\'){b[\'cP-1M\']=q.J.gf+(q.J.cI?\'; lx=\'+q.J.cI:\'\');if(q.2O.gh&&(4L.5D.1C(/8i\\/(\\d{4})/)||[0,gk])[1]<gk)b[\'ly\']=\'lz\'}if(2i q.J.gl==\'2U\'){G c=q.J.gl;if(O.2c(c.1j))1h(G i=0,V=c.V;i<V;i+=2)b[c[i]]=c[i+1];1d $H(c).1n(C(a){b[a.4f]=a.1k})}1h(G d in b)q.2O.lA(d,b[d])},5R:C(){G a=q.8D();E!a||(a>=gm&&a<lB)},8D:C(){2s{E q.2O.a8||0}2A(e){E 0}},cM:C(a){G b=1x.4g.gn[a],5k=1b 1x.cL(q);if(b==\'cQ\'){2s{q.cK=1c;(q.J[\'on\'+5k.a8]||q.J[\'on\'+(q.5R()?\'lC\':\'lD\')]||1i.2I)(5k,5k.a9)}2A(e){q.6u(e)}G c=5k.7p(\'cP-1M\');if(q.J.cJ==\'go\'||(q.J.cJ&&q.aa()&&c&&c.1C(/^\\s*(3Q|a6)\\/(x-)?(lE|lF)4s(;.*)?\\s*$/i)))q.gp()}2s{(q.J[\'on\'+b]||1i.2I)(5k,5k.a9);1x.7o.a4(\'on\'+b,q,5k,5k.a9)}2A(e){q.6u(e)}if(b==\'cQ\'){q.2O.a7=1i.2I}},aa:C(){G m=q.3g.1C(/^\\s*lG?:\\/\\/[^\\/]*/);E!m||(m[0]==\'#{cR}//#{cS}#{ab}\'.fX({cR:ac.cR,cS:19.cS,ab:ac.ab?\':\'+ac.ab:\'\'}))},7p:C(a){2s{E q.2O.cT(a)||1e}2A(e){E 1e}},gp:C(){2s{E 7e((q.2O.3U||\'\').cu())}2A(e){q.6u(e)}},6u:C(a){(q.J.gq||1i.2I)(q,a);1x.7o.a4(\'gq\',q,a)}});1x.4g.gn=[\'lH\',\'cU\',\'lI\',\'lJ\',\'cQ\'];1x.cL=1D.1E({1K:C(a){q.4R=a;G b=q.2O=a.2O,4S=q.4S=b.4S;if((4S>2&&!1i.1J.3a)||4S==4){q.a8=q.8D();q.cV=q.gr();q.3U=1T.7b(b.3U);q.a9=q.gs()}if(4S==4){G c=b.gu;q.gu=O.2z(c)?1e:c;q.lK=q.gv()}},a8:0,cV:\'\',8D:1x.4g.1p.8D,gr:C(){2s{E q.2O.cV||\'\'}2A(e){E\'\'}},7p:1x.4g.1p.7p,lL:C(){2s{E q.cW()}2A(e){E 1e}},cT:C(a){E q.2O.cT(a)},cW:C(){E q.2O.cW()},gs:C(){G a=q.7p(\'X-fV\');if(!a)E 1e;a=cs(fI(a));2s{E a.7g(q.4R.J.gw||!q.4R.aa())}2A(e){q.4R.6u(e)}},gv:C(){G a=q.4R.J;if(!a.7g||(a.7g!=\'go\'&&!(q.7p(\'cP-1M\')||\'\').1L(\'a6/lM\'))||q.3U.6m())E 1e;2s{E q.3U.7g(a.gw||!q.4R.aa())}2A(e){q.4R.6u(e)}}});1x.cX=1D.1E(1x.4g,{1K:C($4t,d,e,f){q.5S={5R:(d.5R||d),ad:(d.ad||(d.5R?1e:d))};f=O.2B(f);G g=f.2N;f.2N=(C(a,b){q.gx(a.3U);if(O.2c(g))g(a,b)}).1o(q);$4t(e,f)},gx:C(a){G b=q.5S[q.5R()?\'5R\':\'ad\'],J=q.J;if(!J.5L)a=a.4P();if(b=$(b)){if(J.ae){if(O.2t(J.ae)){G c={};c[J.ae]=a;b.3V(c)}1d J.ae(b,a)}1d b.1A(a)}}});1x.lN=1D.1E(1x.3f,{1K:C($4t,b,c,d){$4t(d);q.2N=q.J.2N;q.5J=(q.J.5J||2);q.6v=(q.J.6v||1);q.cY={};q.5S=b;q.3g=c;q.1V()},1V:C(){q.J.2N=q.gy.1o(q);q.6l()},2M:C(){q.cY.J.2N=3j;af(q.4w);(q.2N||1i.2I).4c(q,1f)},gy:C(a){if(q.J.6v){q.6v=(a.3U==q.gz?q.6v*q.J.6v:1);q.gz=a.3U}q.4w=q.6l.1o(q).3c(q.6v*q.5J)},6l:C(){q.cY=1b 1x.cX(q.5S,q.3g,q.J)}});C $(a){if(1f.V>1){1h(G i=0,8E=[],V=1f.V;i<V;i++)8E.1j($(1f[i]));E 8E}if(O.2t(a))a=19.lO(a);E M.Y(a)}if(1i.4M.9S){19.cZ=C(a,b){G c=[];G d=19.3b(a,$(b)||19,1e,lP.lQ,1e);1h(G i=0,V=d.lR;i<V;i++)c.1j(M.Y(d.lS(i)));E c}}if(!1s.8F)G 8F={};if(!8F.gA){O.Y(8F,{gA:1,lT:2,gB:3,lU:4,lV:5,lW:6,lX:7,lY:8,lZ:9,m0:10,m1:11,m2:12})}(C(){G d=q.M;q.M=C(a,b){b=b||{};a=a.1U();G c=M.8G;if(1i.1J.3a&&b.29){a=\'<\'+a+\' 29="\'+b.29+\'">\';7n b.29;E M.8H(19.2b(a),b)}if(!c[a])c[a]=M.Y(19.2b(a));E M.8H(c[a].gC(14),b)};O.Y(q.M,d||{})}).d0(1s);M.8G={};M.1m={ag:C(a){E $(a).17.3C!=\'4h\'},d1:C(a){a=$(a);M[M.ag(a)?\'25\':\'2J\'](a);E a},25:C(a){$(a).17.3C=\'4h\';E a},2J:C(a){$(a).17.3C=\'\';E a},4T:C(a){a=$(a);a.1z.6w(a);E a},1A:C(a,b){a=$(a);if(b&&b.4i)b=b.4i();if(O.5e(b))E a.1A().3V(b);b=O.5f(b);a.2V=b.4P();b.5L.1o(b).5H();E a},1S:C(a,b){a=$(a);if(b&&b.4i)b=b.4i();1d if(!O.5e(b)){b=O.5f(b);G c=a.m3.m4();c.m5(a);b.5L.1o(b).5H();b=c.m6(b.4P())}a.1z.d2(b,a);E a},3V:C(a,b){a=$(a);if(O.2t(b)||O.5F(b)||O.5e(b)||(b&&(b.4i||b.5f)))b={2P:b};G c,3V,1B,2o;1h(G d in b){c=b[d];d=d.1U();3V=M.7q[d];if(c&&c.4i)c=c.4i();if(O.5e(c)){3V(a,c);4j}c=O.5f(c);1B=((d==\'ah\'||d==\'7r\')?a.1z:a).1B.2e();2o=M.ai(1B,c.4P());if(d==\'1r\'||d==\'7r\')2o.7k();2o.1n(3V.9V(a));c.5L.1o(c).5H()}E a},6i:C(a,b,c){a=$(a);if(O.5e(b))$(b).8H(c||{});1d if(O.2t(b))b=1b M(b,c);1d b=1b M(\'2H\',b);if(a.1z)a.1z.d2(b,a);b.2j(a);E b},2m:C(d){d=$(d);G e=\'<\'+d.1B.1U();$H({\'id\':\'id\',\'2a\':\'6x\'}).1n(C(a){G b=a.3M(),6y=a.2D();G c=(d[b]||\'\').2S();if(c)e+=\' \'+6y+\'=\'+c.2m(1c)});E e+\'>\'},aj:C(a,b){a=$(a);G c=[];1Q(a=a[b])if(a.3k==1)c.1j(M.Y(a));E c},d3:C(a){E $(a).aj(\'1z\')},gD:C(a){E $(a).24("*")},gE:C(a){a=$(a).4z;1Q(a&&a.3k!=1)a=a.5l;E $(a)},gF:C(a){if(!(a=$(a).4z))E[];1Q(a&&a.3k!=1)a=a.5l;if(a)E[a].22($(a).8I());E[]},d4:C(a){E $(a).aj(\'d5\')},8I:C(a){E $(a).aj(\'5l\')},m7:C(a){a=$(a);E a.d4().7k().22(a.8I())},1C:C(a,b){if(O.2t(b))b=1b 1l(b);E b.1C($(a))},m8:C(a,b,c){a=$(a);if(1f.V==1)E $(a.1z);G d=a.d3();E O.5F(b)?d[b]:1l.5T(d,b,c)},3q:C(a,b,c){a=$(a);if(1f.V==1)E a.gE();E O.5F(b)?a.gD()[b]:a.24(b)[c||0]},m9:C(a,b,c){a=$(a);if(1f.V==1)E $(1l.2p.8J(a));G d=a.d4();E O.5F(b)?d[b]:1l.5T(d,b,c)},gG:C(a,b,c){a=$(a);if(1f.V==1)E $(1l.2p.8K(a));G d=a.8I();E O.5F(b)?d[b]:1l.5T(d,b,c)},24:C(){G a=$A(1f),N=$(a.6g());E 1l.ak(N,a)},6z:C(){G a=$A(1f),N=$(a.6g());E 1l.ak(N.1z,a).7l(N)},gH:C(a){a=$(a);G b=a.6A(\'id\'),d6=1f.5h;if(b)E b;do{b=\'ma\'+d6.gI++}1Q($(b));a.8H(\'id\',b);E b},6A:C(a,b){a=$(a);if(1i.1J.3a){G t=M.4A.al;if(t.1O[b])E t.1O[b](a,b);if(t.5U[b])b=t.5U[b];if(b.1L(\':\')){E(!a.d7||!a.d7[b])?1e:a.d7[b].1k}}E a.d8(b)},8H:C(a,b,c){a=$(a);G d={},t=M.4A.7s;if(2i b==\'2U\')d=b;1d d[b]=O.2z(c)?1c:c;1h(G e in d){b=t.5U[e]||e;c=d[e];if(t.1O[e])b=t.1O[e](a,c);if(c===14||c===1e)a.d9(b);1d if(c===1c)a.da(b,b);1d a.da(b,c)}E a},db:C(a){E $(a).4B().1t},gJ:C(a){E $(a).4B().1u},6B:C(a){E 1b M.am(a)},8L:C(a,b){if(!(a=$(a)))E;G c=a.2a;E(c.V>0&&(c==b||1b 5g("(^|\\\\s)"+b+"(\\\\s|$)").2C(c)))},3W:C(a,b){if(!(a=$(a)))E;if(!a.8L(b))a.2a+=(a.2a?\' \':\'\')+b;E a},4U:C(a,b){if(!(a=$(a)))E;a.2a=a.2a.1S(1b 5g("(^|\\\\s+)"+b+"(\\\\s+|$)"),\' \').3l();E a},mb:C(a,b){if(!(a=$(a)))E;E a[a.8L(b)?\'4U\':\'3W\'](b)},7t:C(a){a=$(a);G b=a.4z;1Q(b){G c=b.5l;if(b.3k==3&&!/\\S/.2C(b.7f))a.6w(b);b=c}E a},6n:C(a){E $(a).2V.6m()},ao:C(b,c){b=$(b),c=$(c);G d=c;if(b.gK)E(b.gK(c)&8)===8;if(b.8M&&!1i.1J.6e){G e=b.8M,a=c.8M,7u=c.5l;if(!7u){do{c=c.1z}1Q(!(7u=c.5l)&&c.1z)}if(7u&&7u.8M)E(e>a&&e<7u.8M)}1Q(b=b.1z)if(b==d)E 1c;E 14},8N:C(a){a=$(a);G b=a.3r();1s.8N(b[0],b[1]);E a},1v:C(a,b){a=$(a);b=b==\'dc\'?\'ap\':b.8s();G c=a.17[b];if(!c){G d=19.aq.dd(a,1e);c=d?d[b]:1e}if(b==\'1Y\')E c?3s(c):1.0;E c==\'ar\'?1e:c},7v:C(a){E $(a).1v(\'1Y\')},1F:C(a,b){a=$(a);G c=a.17,1C;if(O.2t(b)){a.17.de+=\';\'+b;E b.1L(\'1Y\')?a.5V(b.1C(/1Y:\\s*(\\d?\\.?\\d*)/)[1]):a}1h(G d in b)if(d==\'1Y\')a.5V(b[d]);1d c[(d==\'dc\'||d==\'ap\')?(O.2z(c.df)?\'ap\':\'df\'):d]=b[d];E a},5V:C(a,b){a=$(a);a.17.1Y=(b==1||b===\'\')?\'\':(b<0.at)?0:b;E a},4B:C(a){a=$(a);G b=$(a).1v(\'3C\');if(b!=\'4h\'&&b!=1e)E{1u:a.3X,1t:a.3D};G c=a.17;G d=c.6C;G e=c.1y;G f=c.3C;c.6C=\'5W\';c.1y=\'3E\';c.3C=\'mc\';G g=a.8O;G h=a.7w;c.3C=f;c.1y=e;c.6C=d;E{1u:g,1t:h}},3Y:C(a){a=$(a);G b=M.1v(a,\'1y\');if(b==\'7x\'||!b){a.dg=1c;a.17.1y=\'6D\';if(1s.4K){a.17.1r=0;a.17.1w=0}}E a},4V:C(a){a=$(a);if(a.dg){a.dg=3j;a.17.1y=a.17.1r=a.17.1w=a.17.2P=a.17.5m=\'\'}E a},4W:C(a){a=$(a);if(a.6E)E a;a.6E=M.1v(a,\'dh\')||\'ar\';if(a.6E!==\'5W\')a.17.dh=\'5W\';E a},4X:C(a){a=$(a);if(!a.6E)E a;a.17.dh=a.6E==\'ar\'?\'\':a.6E;a.6E=1e;E a},3r:C(a){G b=0,3h=0;do{b+=a.5n||0;3h+=a.5X||0;a=a.5o}1Q(a);E M.6F(3h,b)},8P:C(a){G b=0,3h=0;do{b+=a.5n||0;3h+=a.5X||0;a=a.5o;if(a){if(a.1B==\'au\')1I;G p=M.1v(a,\'1y\');if(p!==\'7x\')1I}}1Q(a);E M.6F(3h,b)},8Q:C(a){a=$(a);if(a.1v(\'1y\')==\'3E\')E;G b=a.8P();G c=b[1];G d=b[0];G e=a.8O;G f=a.7w;a.gL=d-3s(a.17.1w||0);a.gM=c-3s(a.17.1r||0);a.gN=a.17.1u;a.gO=a.17.1t;a.17.1y=\'3E\';a.17.1r=c+\'px\';a.17.1w=d+\'px\';a.17.1u=e+\'px\';a.17.1t=f+\'px\';E a},av:C(a){a=$(a);if(a.1v(\'1y\')==\'6D\')E;a.17.1y=\'6D\';G b=3s(a.17.1r||0)-(a.gM||0);G c=3s(a.17.1w||0)-(a.gL||0);a.17.1r=b+\'px\';a.17.1w=c+\'px\';a.17.1t=a.gO;a.17.1u=a.gN;E a},di:C(a){G b=0,3h=0;do{b+=a.3t||0;3h+=a.3F||0;a=a.1z}1Q(a);E M.6F(3h,b)},7y:C(a){if(a.5o)E $(a.5o);if(a==19.28)E $(a);1Q((a=a.1z)&&a!=19.28)if(M.1v(a,\'1y\')!=\'7x\')E $(a);E $(19.28)},8R:C(a){G b=0,3h=0;G c=a;do{b+=c.5n||0;3h+=c.5X||0;if(c.5o==19.28&&M.1v(c,\'1y\')==\'3E\')1I}1Q(c=c.5o);c=a;do{if(!1i.1J.6e||c.1B==\'au\'){b-=c.3t||0;3h-=c.3F||0}}1Q(c=c.1z);E M.6F(3h,b)},gP:C(a,b){G c=O.Y({gQ:1c,dj:1c,gR:1c,dk:1c,5n:0,5X:0},1f[2]||{});b=$(b);G p=b.8R();a=$(a);G d=[0,0];G e=1e;if(M.1v(a,\'1y\')==\'3E\'){e=a.7y();d=e.8R()}if(e==19.28){d[0]-=19.28.5X;d[1]-=19.28.5n}if(c.gQ)a.17.1w=(p[0]-d[0]+c.5X)+\'px\';if(c.dj)a.17.1r=(p[1]-d[1]+c.5n)+\'px\';if(c.gR)a.17.1u=b.3X+\'px\';if(c.dk)a.17.1t=b.3D+\'px\';E a}};M.1m.gH.gI=1;O.Y(M.1m,{md:M.1m.24,me:M.1m.gF});M.4A={7s:{5U:{2a:\'6x\',dl:\'1h\'},1O:{}}};if(1i.1J.6e){M.1m.1v=M.1m.1v.6i(C(d,e,f){4N(f){1H\'1w\':1H\'1r\':1H\'5m\':1H\'2P\':if(d(e,\'1y\')===\'7x\')E 1e;1H\'1t\':1H\'1u\':if(!M.ag(e))E 1e;G g=3u(d(e,f),10);if(g!==e[\'2K\'+f.8u()])E g+\'px\';G h;if(f===\'1t\'){h=[\'aw-1r-1u\',\'ax-1r\',\'ax-2P\',\'aw-2P-1u\']}1d{h=[\'aw-1w-1u\',\'ax-1w\',\'ax-5m\',\'aw-5m-1u\']}E h.3A(g,C(a,b){G c=d(e,b);E c===1e?a:a-3u(c,10)})+\'px\';8S:E d(e,f)}});M.1m.6A=M.1m.6A.6i(C(a,b,c){if(c===\'8T\')E b.8T;E a(b,c)})}1d if(1i.1J.3a){M.1m.7y=M.1m.7y.6i(C(a,b){b=$(b);G c=b.1v(\'1y\');if(c!==\'7x\')E a(b);b.1F({1y:\'6D\'});G d=a(b);b.1F({1y:c});E d});$w(\'8P 8R\').1n(C(f){M.1m[f]=M.1m[f].6i(C(a,b){b=$(b);G c=b.1v(\'1y\');if(c!==\'7x\')E a(b);G d=b.7y();if(d&&d.1v(\'1y\')===\'mf\')d.1F({7z:1});b.1F({1y:\'6D\'});G e=a(b);b.1F({1y:c});E e})});M.1m.1v=C(a,b){a=$(a);b=(b==\'dc\'||b==\'ap\')?\'df\':b.8s();G c=a.17[b];if(!c&&a.7A)c=a.7A[b];if(b==\'1Y\'){if(c=(a.1v(\'6s\')||\'\').1C(/dm\\(1Y=(.*)\\)/))if(c[1])E 3s(c[1])/3Z;E 1.0}if(c==\'ar\'){if((b==\'1u\'||b==\'1t\')&&(a.1v(\'3C\')!=\'4h\'))E a[\'2K\'+b.8u()]+\'px\';E 1e}E c};M.1m.5V=C(b,c){C dn(a){E a.1S(/dm\\([^\\)]*\\)/gi,\'\')}b=$(b);G d=b.7A;if((d&&!d.dp)||(!d&&b.17.7z==\'mg\'))b.17.7z=1;G e=b.1v(\'6s\'),17=b.17;if(c==1||c===\'\'){(e=dn(e))?17.6s=e:17.d9(\'6s\');E b}1d if(c<0.at)c=0;17.6s=dn(e)+\'dm(1Y=\'+(c*3Z)+\')\';E b};M.4A={al:{5U:{\'6x\':\'2a\',\'1h\':\'dl\'},1O:{ay:C(a,b){E a.d8(b,2)},gS:C(a,b){G c=a.gT(b);E c?c.1k:""},2L:C(a,b){b=a.d8(b);E b?b.2S().3n(23,-2):1e},8U:C(a,b){E $(a).4C(b)?b:1e},17:C(a){E a.17.de.1U()},8T:C(a){E a.8T}}}};M.4A.7s={5U:O.Y({mh:\'mi\',mj:\'mk\'},M.4A.al.5U),1O:{4D:C(a,b){a.4D=!!b},17:C(a,b){a.17.de=b?b:\'\'}}};M.4A.dq={};$w(\'ml mn mo mp mq az \'+\'mr ms mt mu\').1n(C(a){M.4A.7s.5U[a.1U()]=a;M.4A.dq[a.1U()]=a});(C(v){O.Y(v,{dr:v.ay,4Y:v.ay,1M:v.ay,7B:v.gS,2x:v.8U,4D:v.8U,mv:v.8U,gU:v.8U,mw:v.2L,gV:v.2L,ds:v.2L,mx:v.2L,my:v.2L,mz:v.2L,mA:v.2L,mB:v.2L,mC:v.2L,mD:v.2L,gW:v.2L,mE:v.2L,mF:v.2L,mG:v.2L,gX:v.2L,mH:v.2L,mI:v.2L,mJ:v.2L})})(M.4A.al.1O)}1d if(1i.1J.8i&&/mK:1\\.8\\.0/.2C(4L.5D)){M.1m.5V=C(a,b){a=$(a);a.17.1Y=(b==1)?0.mL:(b===\'\')?\'\':(b<0.at)?0:b;E a}}1d if(1i.1J.3L){M.1m.5V=C(a,b){a=$(a);a.17.1Y=(b==1||b===\'\')?\'\':(b<0.at)?0:b;if(b==1)if(a.1B==\'dt\'&&a.1u){a.1u++;a.1u--}1d 2s{G n=19.6o(\' \');a.2j(n);a.6w(n)}2A(e){}E a};M.1m.3r=C(a){G b=0,3h=0;do{b+=a.5n||0;3h+=a.5X||0;if(a.5o==19.28)if(M.1v(a,\'1y\')==\'3E\')1I;a=a.5o}1Q(a);E M.6F(3h,b)}}if(1i.1J.3a||1i.1J.6e){M.1m.1A=C(b,c){b=$(b);if(c&&c.4i)c=c.4i();if(O.5e(c))E b.1A().3V(c);c=O.5f(c);G d=b.1B.2e();if(d in M.7q.5Y){$A(b.2o).1n(C(a){b.6w(a)});M.ai(d,c.4P()).1n(C(a){b.2j(a)})}1d b.2V=c.4P();c.5L.1o(c).5H();E b}}if(\'du\'in 19.2b(\'2H\')){M.1m.1S=C(b,c){b=$(b);if(c&&c.4i)c=c.4i();if(O.5e(c)){b.1z.d2(c,b);E b}c=O.5f(c);G d=b.1z,1B=d.1B.2e();if(M.7q.5Y[1B]){G e=b.gG();G f=M.ai(1B,c.4P());d.6w(b);if(e)f.1n(C(a){d.4Z(a,e)});1d f.1n(C(a){d.2j(a)})}1d b.du=c.4P();c.5L.1o(c).5H();E b}}M.6F=C(l,t){G a=[l,t];a.1w=l;a.1r=t;E a};M.ai=C(a,b){G c=1b M(\'2H\'),t=M.7q.5Y[a];if(t){c.2V=t[0]+b+t[1];t[2].9Z(C(){c=c.4z})}1d c.2V=b;E $A(c.2o)};M.7q={ah:C(a,b){a.1z.4Z(b,a)},1r:C(a,b){a.4Z(b,a.4z)},2P:C(a,b){a.2j(b)},7r:C(a,b){a.1z.4Z(b,a.5l)},5Y:{gY:[\'<2X>\',\'</2X>\',1],7C:[\'<2X><7D>\',\'</7D></2X>\',2],aA:[\'<2X><7D><aB>\',\'</aB></7D></2X>\',3],8V:[\'<2X><7D><aB><gZ>\',\'</gZ></aB></7D></2X>\',4],aC:[\'<24>\',\'</24>\',1]}};(C(){O.Y(q.5Y,{aD:q.5Y.7C,aE:q.5Y.7C,aF:q.5Y.8V})}).d0(M.7q);M.1m.aG={4C:C(a,b){b=M.4A.dq[b]||b;G c=$(a).gT(b);E c&&c.h0}};M.1m.4k={};O.Y(M,M.1m);if(!1i.4M.8j&&19.2b(\'2H\').6f){1s.8k={};1s.8k.1p=19.2b(\'2H\').6f;1i.4M.8j=1c}M.Y=(C(){if(1i.4M.9T)E 1i.K;G c={},4k=M.1m.4k;G d=O.Y(C(a){if(!a||a.aH||a.3k!=1||a==1s)E a;G b=O.2B(c),1B=a.1B,5p,1k;if(4k[1B])O.Y(b,4k[1B]);1h(5p in b){1k=b[5p];if(O.2c(1k)&&!(5p in a))a[5p]=1k.5G()}a.aH=1i.2I;E a},{aI:C(){if(!1i.4M.8j){O.Y(c,M.1m);O.Y(c,M.1m.aG)}}});d.aI();E d})();M.4C=C(a,b){if(a.4C)E a.4C(b);E M.1m.aG.4C(a,b)};M.7a=C(f){G F=1i.4M,T=M.1m.4k;if(!f){O.Y(1N,1N.1m);O.Y(1N.M,1N.M.1m);O.Y(M.1m.4k,{"h1":O.2B(1N.1m),"dv":O.2B(1N.M.1m),"aC":O.2B(1N.M.1m),"aJ":O.2B(1N.M.1m)})}if(1f.V==2){G g=f;f=1f[1]}if(!g)O.Y(M.1m,f||{});1d{if(O.4e(g))g.1n(Y);1d Y(g)}C Y(a){a=a.2e();if(!M.1m.4k[a])M.1m.4k[a]={};O.Y(M.1m.4k[a],f)}C aK(a,b,c){c=c||14;1h(G d in a){G e=a[d];if(!O.2c(e))4j;if(!c||!(d in b))b[d]=e.5G()}}C h2(a){G b;G c={"dw":"mM","aJ":"mN","P":"mO","h3":"mP","h4":"mQ","h5":"mR","h6":"mS","h7":"mT","h8":"7E","h9":"7E","ha":"7E","hb":"7E","hc":"7E","hd":"7E","Q":"mU","he":"hf","hg":"hf","A":"mV","dt":"mW","dx":"mX","dy":"hh","dz":"hh","aD":"dA","aE":"dA","7C":"dA","aA":"mY","aF":"hi","8V":"hi","hj":"mZ","hk":"n0"};if(c[a])b=\'aL\'+c[a]+\'M\';if(1s[b])E 1s[b];b=\'aL\'+a+\'M\';if(1s[b])E 1s[b];b=\'aL\'+a.8u()+\'M\';if(1s[b])E 1s[b];1s[b]={};1s[b].1p=19.2b(a).6f;E 1s[b]}if(F.8j){aK(M.1m,8k.1p);aK(M.1m.aG,8k.1p,1c)}if(F.9T){1h(G h in M.1m.4k){G i=h2(h);if(O.2z(i))4j;aK(T[h],i.1p)}}O.Y(M,M.1m);7n M.4k;if(M.Y.aI)M.Y.aI();M.8G={}};19.aM={4B:C(){G a={};G B=1i.1J;$w(\'1u 1t\').1n(C(d){G D=d.8u();a[d]=(B.3L&&!19.3b)?d6[\'n1\'+D]:(B.6e)?19.28[\'hl\'+D]:19.3i[\'hl\'+D]});E a},gJ:C(){E q.4B().1u},db:C(){E q.4B().1t},dB:C(){E M.6F(1s.hm||19.3i.3F||19.28.3F,1s.hn||19.3i.3t||19.28.3t)}};G 1l=1D.1E({1K:C(a){q.51=a.3l();q.ho()},hp:C(){if(!1i.4M.9S)E 14;G e=q.51;if(1i.1J.3L&&(e.1L("-of-1M")||e.1L(":6n")))E 14;if((/(\\[[\\w-]*?:|:4D)/).2C(q.51))E 14;E 1c},ho:C(){if(q.hp())E q.hq();G e=q.51,ps=1l.8W,h=1l.2p,c=1l.8x,le,p,m;if(1l.6G[e]){q.4E=1l.6G[e];E}q.4E=["q.4E = C(hr) {","G r = hr, h = 1l.2p, c = 14, n;"];1Q(e&&le!=e&&(/\\S/).2C(e)){le=e;1h(G i in ps){p=ps[i];if(m=e.1C(p)){q.4E.1j(O.2c(c[i])?c[i](m):1b 3d(c[i]).3b(m));e=e.1S(m[0],\'\');1I}}}q.4E.1j("E h.dC(n);\\n}");7e(q.4E.2d(\'\\n\'));1l.6G[q.51]=q.4E},hq:C(){G e=q.51,ps=1l.8W,x=1l.2Q,le,m;if(1l.6G[e]){q.2Q=1l.6G[e];E}q.4E=[\'.//*\'];1Q(e&&le!=e&&(/\\S/).2C(e)){le=e;1h(G i in ps){if(m=e.1C(ps[i])){q.4E.1j(O.2c(x[i])?x[i](m):1b 3d(x[i]).3b(m));e=e.1S(m[0],\'\');1I}}}q.2Q=q.4E.2d(\'\');1l.6G[q.51]=q.2Q},52:C(a){a=a||19;if(q.2Q)E 19.cZ(q.2Q,a);E q.4E(a)},1C:C(a){q.41=[];G e=q.51,ps=1l.8W,as=1l.dD;G b,p,m;1Q(e&&b!==e&&(/\\S/).2C(e)){b=e;1h(G i in ps){p=ps[i];if(m=e.1C(p)){if(as[i]){q.41.1j([i,O.2B(m)]);e=e.1S(m[0],\'\')}1d{E q.52(19).1L(a)}}}}G c=1c,29,dE;1h(G i=0,aN;aN=q.41[i];i++){29=aN[0],dE=aN[1];if(!1l.dD[29](a,dE)){c=14;1I}}E c},2S:C(){E q.51},2m:C(){E"#<1l:"+q.51.2m()+">"}});O.Y(1l,{6G:{},2Q:{5Z:"//*",1Z:"/*",6z:"/8X-60::*[1]",8Y:\'/8X-60::*\',1B:C(m){if(m[1]==\'*\')E\'\';E"[hs-29()=\'"+m[1].1U()+"\' or hs-29()=\'"+m[1].2e()+"\']"},2a:"[8Z(22(\' \', @6x, \' \'), \' #{1} \')]",id:"[@id=\'#{1}\']",7F:C(m){m[1]=m[1].1U();E 1b 3d("[@#{1}]").3b(m)},53:C(m){m[1]=m[1].1U();m[3]=m[5]||m[6];E 1b 3d(1l.2Q.90[m[2]]).3b(m)},91:C(m){G h=1l.2Q.2F[m[1]];if(!h)E\'\';if(O.2c(h))E h(m);E 1b 3d(1l.2Q.2F[m[1]]).3b(m)},90:{\'=\':"[@#{1}=\'#{3}\']",\'!=\':"[@#{1}!=\'#{3}\']",\'^=\':"[n2-6p(@#{1}, \'#{3}\')]",\'$=\':"[5i(@#{1}, (7c-V(@#{1}) - 7c-V(\'#{3}\') + 1))=\'#{3}\']",\'*=\':"[8Z(@#{1}, \'#{3}\')]",\'~=\':"[8Z(22(\' \', @#{1}, \' \'), \' #{3} \')]",\'|=\':"[8Z(22(\'-\', @#{1}, \'-\'), \'-#{3}-\')]"},2F:{\'3M-1Z\':\'[5q(dF-60::*)]\',\'2D-1Z\':\'[5q(8X-60::*)]\',\'4l-1Z\':\'[5q(dF-60::* or 8X-60::*)]\',\'6n\':"[aO(*) = 0 dG (aO(3Q()) = 0 or n3(3Q(), \' \\t\\r\\n\', \'\') = \'\')]",\'4D\':"[@4D]",\'2x\':"[@2x]",\'ht\':"[5q(@2x)]",\'5q\':C(m){G e=m[6],p=1l.8W,x=1l.2Q,le,v;G a=[];1Q(e&&le!=e&&(/\\S/).2C(e)){le=e;1h(G i in p){if(m=e.1C(p[i])){v=O.2c(x[i])?x[i](m):1b 3d(x[i]).3b(m);a.1j("("+v.5i(1,v.V-1)+")");e=e.1S(m[0],\'\');1I}}}E"[5q("+a.2d(" dG ")+")]"},\'2f-1Z\':C(m){E 1l.2Q.2F.2f("(aO(./dF-60::*) + 1) ",m)},\'2f-2D-1Z\':C(m){E 1l.2Q.2F.2f("(aO(./8X-60::*) + 1) ",m)},\'2f-of-1M\':C(m){E 1l.2Q.2F.2f("1y() ",m)},\'2f-2D-of-1M\':C(m){E 1l.2Q.2F.2f("(2D() + 1 - 1y()) ",m)},\'3M-of-1M\':C(m){m[6]="1";E 1l.2Q.2F[\'2f-of-1M\'](m)},\'2D-of-1M\':C(m){m[6]="1";E 1l.2Q.2F[\'2f-2D-of-1M\'](m)},\'4l-of-1M\':C(m){G p=1l.2Q.2F;E p[\'3M-of-1M\'](m)+p[\'2D-of-1M\'](m)},2f:C(c,m){G d,6H=m[6],dH;if(6H==\'hu\')6H=\'2n+0\';if(6H==\'hv\')6H=\'2n+1\';if(d=6H.1C(/^(\\d+)$/))E\'[\'+c+"= "+d[1]+\']\';if(d=6H.1C(/^(-?\\d*)?n(([+-])(\\d+))?/)){if(d[1]=="-")d[1]=-1;G a=d[1]?6t(d[1]):1;G b=d[2]?6t(d[2]):0;dH="[((#{dI} - #{b}) n4 #{a} = 0) dG "+"((#{dI} - #{b}) 2H #{a} >= 0)]";E 1b 3d(dH).3b({dI:c,a:a,b:b})}}}},8x:{1B:\'n = h.1B(n, r, "#{1}", c);      c = 14;\',2a:\'n = h.2a(n, r, "#{1}", c);    c = 14;\',id:\'n = h.id(n, r, "#{1}", c);           c = 14;\',7F:\'n = h.7F(n, r, "#{1}", c); c = 14;\',53:C(m){m[3]=(m[5]||m[6]);E 1b 3d(\'n = h.53(n, r, "#{1}", "#{3}", "#{2}", c); c = 14;\').3b(m)},91:C(m){if(m[6])m[6]=m[6].1S(/"/g,\'\\\\"\');E 1b 3d(\'n = h.91(n, "#{1}", "#{6}", r, c); c = 14;\').3b(m)},5Z:\'c = "5Z";\',1Z:\'c = "1Z";\',6z:\'c = "6z";\',8Y:\'c = "8Y";\'},8W:{8Y:/^\\s*~\\s*/,1Z:/^\\s*>\\s*/,6z:/^\\s*\\+\\s*/,5Z:/^\\s/,1B:/^\\s*(\\*|[\\w\\-]+)(\\b|$)?/,id:/^#([\\w\\-\\*]+)(\\b|$)/,2a:/^\\.([\\w\\-\\*]+)(\\b|$)/,91:/^:((3M|2D|2f|2f-2D|4l)(-1Z|-of-1M)|6n|4D|(en|n5)n6|5q)(\\((.*?)\\))?(\\b|$|(?=\\s|[:+~>]))/,7F:/^\\[([\\w]+)\\]/,53:/\\[((?:[\\w-]*:)?[\\w-]+)\\s*(?:([!^$*~|]?=)\\s*(([\'"])([^\\4]*?)\\4|([^\'"][^\\]]*?)))?\\]/},dD:{1B:C(a,b){E b[1].2e()==a.1B.2e()},2a:C(a,b){E M.8L(a,b[1])},id:C(a,b){E a.id===b[1]},7F:C(a,b){E M.4C(a,b[1])},53:C(a,b){G c=M.6A(a,b[1]);E c&&1l.90[b[2]](c,b[5]||b[6])}},2p:{22:C(a,b){1h(G i=0,1a;1a=b[i];i++)a.1j(1a);E a},6I:C(a){G b=1i.2I;1h(G i=0,1a;1a=a[i];i++)1a.4F=b;E a},5r:C(a){1h(G i=0,1a;1a=a[i];i++)1a.4F=3j;E a},2u:C(a,b,c){a.4F=1i.2I;if(b){1h(G d=a.2o,i=d.V-1,j=1;i>=0;i--){G e=d[i];if(e.3k==1&&(!c||e.4F))e.aP=j++}}1d{1h(G i=0,j=1,d=a.2o;e=d[i];i++)if(e.3k==1&&(!c||e.4F))e.aP=j++}},dC:C(a){if(a.V==0)E a;G b=[],n;1h(G i=0,l=a.V;i<l;i++)if(!(n=a[i]).4F){n.4F=1i.2I;b.1j(M.Y(n))}E 1l.2p.5r(b)},5Z:C(a){G h=1l.2p;1h(G i=0,1q=[],1a;1a=a[i];i++)h.22(1q,1a.42(\'*\'));E 1q},1Z:C(a){G h=1l.2p;1h(G i=0,1q=[],1a;1a=a[i];i++){1h(G j=0,1Z;1Z=1a.2o[j];j++)if(1Z.3k==1&&1Z.1B!=\'!\')1q.1j(1Z)}E 1q},6z:C(a){1h(G i=0,1q=[],1a;1a=a[i];i++){G b=q.8K(1a);if(b)1q.1j(b)}E 1q},8Y:C(a){G h=1l.2p;1h(G i=0,1q=[],1a;1a=a[i];i++)h.22(1q,M.8I(1a));E 1q},8K:C(a){1Q(a=a.5l)if(a.3k==1)E a;E 1e},8J:C(a){1Q(a=a.d5)if(a.3k==1)E a;E 1e},1B:C(a,b,c,d){G e=c.2e();G f=[],h=1l.2p;if(a){if(d){if(d=="5Z"){1h(G i=0,1a;1a=a[i];i++)h.22(f,1a.42(c));E f}1d a=q[d](a);if(c=="*")E a}1h(G i=0,1a;1a=a[i];i++)if(1a.1B.2e()===e)f.1j(1a);E f}1d E b.42(c)},id:C(a,b,c,d){G e=$(c),h=1l.2p;if(!e)E[];if(!a&&b==19)E[e];if(a){if(d){if(d==\'1Z\'){1h(G i=0,1a;1a=a[i];i++)if(e.1z==1a)E[e]}1d if(d==\'5Z\'){1h(G i=0,1a;1a=a[i];i++)if(M.ao(e,1a))E[e]}1d if(d==\'6z\'){1h(G i=0,1a;1a=a[i];i++)if(1l.2p.8J(e)==1a)E[e]}1d a=h[d](a)}1h(G i=0,1a;1a=a[i];i++)if(1a==e)E[e];E[]}E(e&&M.ao(e,b))?[e]:[]},2a:C(a,b,c,d){if(a&&d)a=q[d](a);E 1l.2p.hw(a,b,c)},hw:C(a,b,c){if(!a)a=1l.2p.5Z([b]);G d=\' \'+c+\' \';1h(G i=0,1q=[],1a,92;1a=a[i];i++){92=1a.2a;if(92.V==0)4j;if(92==c||(\' \'+92+\' \').1L(d))1q.1j(1a)}E 1q},7F:C(a,b,c,d){if(!a)a=b.42("*");if(a&&d)a=q[d](a);G e=[];1h(G i=0,1a;1a=a[i];i++)if(M.4C(1a,c))e.1j(1a);E e},53:C(a,b,c,d,e,f){if(!a)a=b.42("*");if(a&&f)a=q[f](a);G g=1l.90[e],1q=[];1h(G i=0,1a;1a=a[i];i++){G h=M.6A(1a,c);if(h===1e)4j;if(g(h,d))1q.1j(1a)}E 1q},91:C(a,b,c,d,e){if(a&&e)a=q[e](a);if(!a)a=d.42("*");E 1l.2F[b](a,c,d)}},2F:{\'3M-1Z\':C(a,b,c){1h(G i=0,1q=[],1a;1a=a[i];i++){if(1l.2p.8J(1a))4j;1q.1j(1a)}E 1q},\'2D-1Z\':C(a,b,c){1h(G i=0,1q=[],1a;1a=a[i];i++){if(1l.2p.8K(1a))4j;1q.1j(1a)}E 1q},\'4l-1Z\':C(a,b,c){G h=1l.2p;1h(G i=0,1q=[],1a;1a=a[i];i++)if(!h.8J(1a)&&!h.8K(1a))1q.1j(1a);E 1q},\'2f-1Z\':C(a,b,c){E 1l.2F.2f(a,b,c)},\'2f-2D-1Z\':C(a,b,c){E 1l.2F.2f(a,b,c,1c)},\'2f-of-1M\':C(a,b,c){E 1l.2F.2f(a,b,c,14,1c)},\'2f-2D-of-1M\':C(a,b,c){E 1l.2F.2f(a,b,c,1c,1c)},\'3M-of-1M\':C(a,b,c){E 1l.2F.2f(a,"1",c,14,1c)},\'2D-of-1M\':C(a,b,c){E 1l.2F.2f(a,"1",c,1c,1c)},\'4l-of-1M\':C(a,b,c){G p=1l.2F;E p[\'2D-of-1M\'](p[\'3M-of-1M\'](a,b,c),b,c)},hx:C(a,b,d){if(a==0)E b>0?[b]:[];E $R(1,d).3A([],C(c,i){if(0==(i-b)%a&&(i-b)/a>=0)c.1j(i);E c})},2f:C(c,d,e,f,g){if(c.V==0)E[];if(d==\'hu\')d=\'2n+0\';if(d==\'hv\')d=\'2n+1\';G h=1l.2p,1q=[],dJ=[],m;h.6I(c);1h(G i=0,1a;1a=c[i];i++){if(!1a.1z.4F){h.2u(1a.1z,f,g);dJ.1j(1a.1z)}}if(d.1C(/^\\d+$/)){d=6t(d);1h(G i=0,1a;1a=c[i];i++)if(1a.aP==d)1q.1j(1a)}1d if(m=d.1C(/^(-?\\d*)?n(([+-])(\\d+))?/)){if(m[1]=="-")m[1]=-1;G a=m[1]?6t(m[1]):1;G b=m[2]?6t(m[2]):0;G k=1l.2F.hx(a,b,c.V);1h(G i=0,1a,l=k.V;1a=c[i];i++){1h(G j=0;j<l;j++)if(1a.aP==k[j])1q.1j(1a)}}h.5r(c);h.5r(dJ);E 1q},\'6n\':C(a,b,c){1h(G i=0,1q=[],1a;1a=a[i];i++){if(1a.1B==\'!\'||(1a.4z&&!1a.2V.1C(/^\\s*$/)))4j;1q.1j(1a)}E 1q},\'5q\':C(a,b,c){G h=1l.2p,n7,m;G d=1b 1l(b).52(c);h.6I(d);1h(G i=0,1q=[],1a;1a=a[i];i++)if(!1a.4F)1q.1j(1a);h.5r(d);E 1q},\'ht\':C(a,b,c){1h(G i=0,1q=[],1a;1a=a[i];i++)if(!1a.2x)1q.1j(1a);E 1q},\'2x\':C(a,b,c){1h(G i=0,1q=[],1a;1a=a[i];i++)if(1a.2x)1q.1j(1a);E 1q},\'4D\':C(a,b,c){1h(G i=0,1q=[],1a;1a=a[i];i++)if(1a.4D)1q.1j(1a);E 1q}},90:{\'=\':C(a,v){E a==v},\'!=\':C(a,v){E a!=v},\'^=\':C(a,v){E a.cv(v)},\'$=\':C(a,v){E a.fW(v)},\'*=\':C(a,v){E a.1L(v)},\'~=\':C(a,v){E(\' \'+a+\' \').1L(\' \'+v+\' \')},\'|=\':C(a,v){E(\'-\'+a.2e()+\'-\').1L(\'-\'+v.2e()+\'-\')}},3N:C(a){G b=[];a.fM(/(([\\w#:.~>+()\\s-]+|\\*|\\[.*?\\])+)\\s*(,|$)/,C(m){b.1j(m[1].3l())});E b},hy:C(a,b){G c=$$(b),h=1l.2p;h.6I(c);1h(G i=0,1q=[],N;N=a[i];i++)if(N.4F)1q.1j(N);h.5r(c);E 1q},5T:C(a,b,c){if(O.5F(b)){c=b;b=14}E 1l.hy(a,b||\'*\')[c||0]},ak:C(a,b){b=1l.3N(b.2d(\',\'));G c=[],h=1l.2p;1h(G i=0,l=b.V,93;i<l;i++){93=1b 1l(b[i].3l());h.22(c,93.52(a))}E(l>1)?h.dC(c):c}});if(1i.1J.3a){O.Y(1l.2p,{22:C(a,b){1h(G i=0,1a;1a=b[i];i++)if(1a.1B!=="!")a.1j(1a);E a},5r:C(a){1h(G i=0,1a;1a=a[i];i++)1a.d9(\'4F\');E a}})}C $$(){E 1l.ak(19,$A(1f))}G 1N={94:C(a){$(a).94();E a},hz:C(c,d){if(2i d!=\'2U\')d={aQ:!!d};1d if(O.2z(d.aQ))d.aQ=1c;G e,1k,dK=14,61=d.61;G f=c.3A({},C(a,b){if(!b.2x&&b.29){e=b.29;1k=$(b).3G();if(1k!=1e&&(b.1M!=\'61\'||(!dK&&61!==14&&(!61||e==61)&&(dK=1c)))){if(e in a){if(!O.4e(a[e]))a[e]=[a[e]];a[e].1j(1k)}1d a[e]=1k}}E a});E d.aQ?f:O.5E(f)}};1N.1m={54:C(a,b){E 1N.hz(1N.7G(a),b)},7G:C(c){E $A($(c).42(\'*\')).3A([],C(a,b){if(1N.M.7H[b.1B.1U()])a.1j(M.Y(b));E a})},n8:C(a,b,c){a=$(a);G d=a.42(\'7I\');if(!b&&!c)E $A(d).1R(M.Y);1h(G i=0,dL=[],V=d.V;i<V;i++){G e=d[i];if((b&&e.1M!=b)||(c&&e.29!=c))4j;dL.1j(M.Y(e))}E dL},aR:C(a){a=$(a);1N.7G(a).7d(\'aR\');E a},aS:C(a){a=$(a);1N.7G(a).7d(\'aS\');E a},hA:C(b){G c=$(b).7G().5O(C(a){E\'5W\'!=a.1M&&!a.2x});G d=c.5O(C(a){E a.4C(\'az\')&&a.az>=0}).a1(C(a){E a.az}).3M();E d?d:c.cB(C(a){E[\'7I\',\'24\',\'95\'].1L(a.1B.1U())})},n9:C(a){a=$(a);a.hA().55();E a},4R:C(a,b){a=$(a),b=O.2B(b||{});G c=b.2E,7B=a.6A(\'7B\')||\'\';if(7B.6m())7B=1s.ac.dr;b.2E=a.54(1c);if(c){if(O.2t(c))c=c.8r();O.Y(b.2E,c)}if(a.4C(\'1W\')&&!b.1W)b.1W=a.1W;E 1b 1x.4g(7B,b)}};1N.M={62:C(a){$(a).62();E a},24:C(a){$(a).24();E a}};1N.M.1m={54:C(a){a=$(a);if(!a.2x&&a.29){G b=a.3G();if(b!=3j){G c={};c[a.29]=b;E O.5E(c)}}E\'\'},3G:C(a){a=$(a);G b=a.1B.1U();E 1N.M.7H[b](a)},7J:C(a,b){a=$(a);G c=a.1B.1U();1N.M.7H[c](a,b);E a},g3:C(a){$(a).1k=\'\';E a},na:C(a){E $(a).1k!=\'\'},55:C(a){a=$(a);2s{a.62();if(a.24&&(a.1B.1U()!=\'7I\'||![\'6J\',\'94\',\'61\'].1L(a.1M)))a.24()}2A(e){}E a},aR:C(a){a=$(a);a.hB();a.2x=1c;E a},aS:C(a){a=$(a);a.2x=14;E a}};G aT=1N.M;G $F=1N.M.1m.3G;1N.M.7H={7I:C(a,b){4N(a.1M.1U()){1H\'hC\':1H\'hD\':E 1N.M.7H.hE(a,b);8S:E 1N.M.7H.95(a,b)}},hE:C(a,b){if(O.2z(b))E a.4D?a.1k:1e;1d a.4D=!!b},95:C(a,b){if(O.2z(b))E a.1k;1d a.1k=b},24:C(a,b){if(O.2z(b))E q[a.1M==\'24-nb\'?\'hF\':\'hG\'](a);1d{G c,1k,hH=!O.4e(b);1h(G i=0,V=a.V;i<V;i++){c=a.J[i];1k=q.aU(c);if(hH){if(1k==b){c.5s=1c;E}}1d c.5s=b.1L(1k)}}},hF:C(a){G b=a.nc;E b>=0?q.aU(a.J[b]):1e},hG:C(a){G b,V=a.V;if(!V)E 1e;1h(G i=0,b=[];i<V;i++){G c=a.J[i];if(c.5s)b.1j(q.aU(c))}E b},aU:C(a){E M.Y(a).4C(\'1k\')?a.1k:a.3Q}};6j.dM=1D.1E(fJ,{1K:C($4t,b,c,d){$4t(d,c);q.N=$(b);q.3H=q.3G()},cq:C(){G a=q.3G();if(O.2t(q.3H)&&O.2t(a)?q.3H!=a:1T(q.3H)!=1T(a)){q.4v(q.N,a);q.3H=a}}});1N.M.hI=1D.1E(6j.dM,{3G:C(){E 1N.M.3G(q.N)}});1N.hI=1D.1E(6j.dM,{3G:C(){E 1N.54(q.N)}});6j.96=1D.1E({1K:C(a,b){q.N=$(a);q.4v=b;q.3H=q.3G();if(q.N.1B.1U()==\'8l\')q.hJ();1d q.8o(q.N)},dN:C(){G a=q.3G();if(q.3H!=a){q.4v(q.N,a);q.3H=a}},hJ:C(){1N.7G(q.N).1n(q.8o,q)},8o:C(a){if(a.1M){4N(a.1M.1U()){1H\'hC\':1H\'hD\':1g.2k(a,\'dO\',q.dN.1o(q));1I;8S:1g.2k(a,\'97\',q.dN.1o(q));1I}}}});1N.M.96=1D.1E(6j.96,{3G:C(){E 1N.M.3G(q.N)}});1N.96=1D.1E(6j.96,{3G:C(){E 1N.54(q.N)}});if(!1s.1g)G 1g={};O.Y(1g,{nd:8,dP:9,aV:13,aW:27,hK:37,hL:38,hM:39,hN:40,ne:46,nf:36,ng:35,nh:33,ni:34,nj:45,8G:{},dQ:C(a){G b;4N(a.1M){1H\'dR\':b=a.nk;1I;1H\'hO\':b=a.4i;1I;8S:E 1e}E M.Y(b)}});1g.1m=(C(){G e;if(1i.1J.3a){G f={0:1,1:4,2:2};e=C(a,b){E a.6J==f[b]}}1d if(1i.1J.3L){e=C(a,b){4N(b){1H 0:E a.aX==1&&!a.hP;1H 1:E a.aX==1&&a.hP;8S:E 14}}}1d{e=C(a,b){E a.aX?(a.aX===b+1):(a.6J===b)}}E{dS:C(a){E e(a,0)},nl:C(a){E e(a,1)},nm:C(a){E e(a,2)},N:C(a){G b=1g.Y(a).hQ;E M.Y(b.3k==8F.gB?b.1z:b)},5T:C(a,b){G c=1g.N(a);if(!b)E c;G d=[c].22(c.d3());E 1l.5T(d,b,0)},aY:C(a){E{x:a.hR||(a.nn+(19.3i.3F||19.28.3F)),y:a.hS||(a.np+(19.3i.3t||19.28.3t))}},6K:C(a){E 1g.aY(a).x},6L:C(a){E 1g.aY(a).y},2M:C(a){1g.Y(a);a.hT();a.hU();a.nq=1c}}})();1g.Y=(C(){G c=O.6h(1g.1m).3A({},C(m,a){m[a]=1g.1m[a].5G();E m});if(1i.1J.3a){O.Y(c,{hU:C(){q.nr=1c},hT:C(){q.ns=14},2m:C(){E"[2U 1g]"}});E C(a){if(!a)E 14;if(a.aH)E a;a.aH=1i.2I;G b=1g.aY(a);O.Y(a,{hQ:a.nt,dQ:1g.dQ(a),hR:b.x,hS:b.y});E O.Y(a,c)}}1d{1g.1p=1g.1p||19.98("hV").6f;O.Y(1g.1p,c);E 1i.K}})();O.Y(1g,(C(){G h=1g.8G;C dT(a){if(a.dU)E a.dU[0];1f.5h.id=1f.5h.id||1;E a.dU=[++1f.5h.id]}C dV(a){if(a&&a.1L(\':\'))E"hW";E a}C aZ(a){E h[a]=h[a]||{}}C b0(a,b){G c=aZ(a);E c[b]=c[b]||[]}C hX(b,d,e){G f=dT(b);G c=b0(f,d);if(c.5P("b1").1L(e))E 14;G g=C(a){if(!1g||!1g.Y||(a.dW&&a.dW!=d))E 14;1g.Y(a);e.d0(b,a)};g.b1=e;c.1j(g);E g}C dX(b,d,e){G c=b0(b,d);E c.cB(C(a){E a.b1==e})}C hY(a,b,d){G c=aZ(a);if(!c[b])E 14;c[b]=c[b].7l(dX(a,b,d))}C hZ(){1h(G a in h)1h(G b in h[a])h[a][b]=1e}if(1s.9R){1s.9R("gV",hZ)}E{2k:C(a,b,c){a=$(a);G d=dV(b);G e=hX(a,b,c);if(!e)E a;if(a.b2){a.b2(d,e,14)}1d{a.9R("on"+d,e)}E a},2Y:C(b,c,d){b=$(b);G e=dT(b),29=dV(c);if(!d&&c){b0(e,c).1n(C(a){b.2Y(c,a.b1)});E b}1d if(!c){O.6h(aZ(e)).1n(C(a){b.2Y(a)});E b}G f=dX(e,c,d);if(!f)E b;if(b.i0){b.i0(29,f,14)}1d{b.nu("on"+29,f)}hY(e,c,d);E b},63:C(a,b,c){a=$(a);if(a==19&&19.98&&!a.i1)a=19.3i;G d;if(19.98){d=19.98("hV");d.nv("hW",1c,1c)}1d{d=19.nw();d.i2="nx"}d.dW=b;d.ny=c||{};if(19.98){a.i1(d)}1d{a.nz(d.i2,d)}E 1g.Y(d)}}})());O.Y(1g,1g.1m);M.7a({63:1g.63,2k:1g.2k,2Y:1g.2Y});O.Y(19,{63:M.1m.63.5G(),2k:M.1m.2k.5G(),2Y:M.1m.2Y.5G(),99:14});(C(){G a;C 9a(){if(19.99)E;if(a)1s.9Y(a);19.63("nA:99");19.99=1c}if(19.b2){if(1i.1J.3L){a=1s.9X(C(){if(/99|i3/.2C(19.4S))9a()},0);1g.2k(1s,"b3",9a)}1d{19.b2("nB",9a,14)}}1d{19.7s("<4s id=i4 5H 4Y=//:><\\/4s>");$("i4").a7=C(){if(q.4S=="i3"){q.a7=1e;9a()}}}})();4O.5E=O.5E;G nC={3C:M.d1};M.1m.i5=M.1m.ao;G i6={i7:C(a,b){E M.3V(a,{ah:b})},nD:C(a,b){E M.3V(a,{1r:b})},nE:C(a,b){E M.3V(a,{2P:b})},dY:C(a,b){E M.3V(a,{7r:b})}};G $4j=1b i8(\'"2T $4j" is nF, nG "E" nH\');G 1X={i9:14,6M:C(){q.b4=1s.hm||19.3i.3F||19.28.3F||0;q.b5=1s.hn||19.3i.3t||19.28.3t||0},dZ:C(a,x,y){if(q.i9)E q.ia(a,x,y);q.9b=x;q.9c=y;q.2K=M.3r(a);E(y>=q.2K[1]&&y<q.2K[1]+a.3D&&x>=q.2K[0]&&x<q.2K[0]+a.3X)},ia:C(a,x,y){G b=M.di(a);q.9b=x+b[0]-q.b4;q.9c=y+b[1]-q.b5;q.2K=M.3r(a);E(q.9c>=q.2K[1]&&q.9c<q.2K[1]+a.3D&&q.9b>=q.2K[0]&&q.9b<q.2K[0]+a.3X)},43:C(a,b){if(!a)E 0;if(a==\'7K\')E((q.2K[1]+b.3D)-q.9c)/b.3D;if(a==\'b6\')E((q.2K[0]+b.3X)-q.9b)/b.3X},3r:M.1m.3r,8P:M.1m.8P,8Q:C(a){1X.6M();E M.8Q(a)},av:C(a){1X.6M();E M.av(a)},ib:M.1m.di,5o:M.1m.7y,ic:M.1m.8R,2B:C(a,b,c){c=c||{};E M.gP(b,a,c)}};if(!19.b7)19.b7=C(f){C e0(a){E a.6m()?1e:"[8Z(22(\' \', @6x, \' \'), \' "+a+" \')]"}f.b7=1i.4M.9S?C(a,b){b=b.2S().3l();G c=/\\s/.2C(b)?$w(b).1R(e0).2d(\'\'):e0(b);E c?19.cZ(\'.//*\'+c,a):[]}:C(b,c){c=c.2S().3l();G d=[],6B=(/\\s/.2C(c)?$w(c):1e);if(!6B&&!c)E d;G e=$(b).42(\'*\');c=\' \'+c+\' \';1h(G i=0,1Z,cn;1Z=e[i];i++){if(1Z.2a&&(cn=\' \'+1Z.2a+\' \')&&(cn.1L(c)||(6B&&6B.cy(C(a){E!a.2S().6m()&&cn.1L(\' \'+a+\' \')}))))d.1j(M.Y(1Z))}E d};E C(a,b){E $(b||19.28).b7(a)}}(M.1m);M.am=1D.1E();M.am.1p={1K:C(a){q.N=$(a)},4x:C(b){q.N.2a.3N(/\\s+/).24(C(a){E a.V>0}).4x(b)},5j:C(a){q.N.2a=a},6N:C(a){if(q.1L(a))E;q.5j($A(q).22(a).2d(\' \'))},4T:C(a){if(!q.1L(a))E;q.5j($A(q).7l(a).2d(\' \'))},2S:C(){E $A(q).2d(\' \')}};O.Y(M.am.1p,2W);M.7a();G 9d={8h:\'1.8.1\',ie:C(a){19.7s(\'<4s 1M="3Q/cO" 4Y="\'+a+\'"><\\/4s>\')},e1:\'1.6.0\',b3:C(){C e2(a){G r=a.3N(\'.\');E 3u(r[0])*nI+3u(r[1])*3P+3u(r[2])}if((2i 1i==\'3j\')||(2i M==\'3j\')||(2i M.1m==\'3j\')||(e2(1i.8h)<e2(9d.e1)))2T("4s.e3.e4 e5 ig 1i nJ nK >= "+9d.e1);G d=/(nL|nM)nN[a-ih-9.3S-]*\\.js(\\?.*)?$/;$A(19.42("4s")).5O(C(s){E(s.4Y&&s.4Y.1C(d))}).1n(C(s){G b=s.4Y.1S(d,\'\');G c=(s.4Y.1C(/\\?.*b3=([a-z,]*)/)||[,\'\'])[1];c.3N(\',\').7l(\'\').1n(C(a){9d.ie(b+a+\'.js\')})})}};G 6O={ii:{ij:\'1R\',dx:\'2X\',dy:\'2X\',dz:\'2X\',ik:\'nO\',dw:\'24\',e6:\'24\',il:\'2U\',7C:\'2X\',8V:\'2X\',aE:\'2X\',aF:\'2X\',aD:\'2X\',aA:\'2X\'},1a:C(a){a=a.2e();G b=q.ii[a]||\'2H\';G c=19.2b(b);2s{c.2V="<"+a+"></"+a+">"}2A(e){}G d=c.4z||1e;if(d&&(d.1B.2e()!=a))d=d.42(a)[0];if(!d)d=19.2b(a);if(!d)E;if(1f[1])if(q.b8(1f[1])||(1f[1]ck 2v)||1f[1].1B){q.e7(d,1f[1])}1d{G f=q.io(1f[1]);if(f.V){2s{c.2V="<"+a+" "+f+"></"+a+">"}2A(e){}d=c.4z||1e;if(!d){d=19.2b(a);1h(53 in 1f[1])d[53==\'6x\'?\'2a\':53]=1f[1][53]}if(d.1B.2e()!=a)d=c.42(a)[0]}}if(1f[2])q.e7(d,1f[2]);E d},7L:C(a){E 19.6o(a)},e8:{\'2a\':\'6x\',\'dl\':\'1h\'},io:C(a){G b=[];1h(6y in a)b.1j((6y in q.e8?q.e8[6y]:6y)+\'="\'+a[6y].2S().8q().3z(/"/,\'&nP;\')+\'"\');E b.2d(" ")},e7:C(a,b){if(b.1B){a.2j(b);E}if(2i b==\'2U\'){b.3T().1n(C(e){if(2i e==\'2U\')a.2j(e);1d if(6O.b8(e))a.2j(6O.7L(e))})}1d if(6O.b8(b))a.2j(6O.7L(b))},b8:C(a){E(2i a==\'7c\'||2i a==\'fD\')},nQ:C(a){G b=q.1a(\'2H\');$(b).1A(a.3l());E b.3q()},nR:C(b){if(2i b!=\'2U\'&&2i b!=\'C\')b=1s;G c=("A nS nT nU nV ij B nW nX nY nZ o0 au "+"o1 ip dx o2 o3 o4 dy dz o5 hg o6 h7 iq h6 o7 o8 h3 "+"o9 h1 oa hj h8 h9 ha hb hc hd ob oc aL I hk dt dv he od "+"oe og ik e9 oh oi oj ol om oo op h5 dw e6 P "+"il oq Q S os ot aC ou ov ow ox oy oz oA gY 7C 8V "+"aJ aE aF aD oB aA oC U h4 oD").3N(/\\s+/);c.1n(C(a){b[a]=C(){E 6O.1a.4c(6O,[a].22($A(1f)))}})}};1T.1p.64=C(){G a=\'#\';if(q.3n(0,4)==\'oE(\'){G b=q.3n(4,q.V-1).3N(\',\');G i=0;do{a+=3u(b[i]).7m()}1Q(++i<3)}1d{if(q.3n(0,1)==\'#\'){if(q.V==4)1h(G i=1;i<4;i++)a+=(q.5M(i)+q.5M(i)).1U();if(q.V==7)a=q.1U()}}E(a.V==7?a:(1f[0]||q))};M.b9=C(b){E $A($(b).2o).7i(C(a){E(a.3k==3?a.7f:(a.ea()?M.b9(a):\'\'))}).3T().2d(\'\')};M.ba=C(b,c){E $A($(b).2o).7i(C(a){E(a.3k==3?a.7f:((a.ea()&&!M.8L(a,c))?M.ba(a,c):\'\'))}).3T().2d(\'\')};M.ir=C(a,b){a=$(a);a.1F({6P:(b/3Z)+\'em\'});if(1i.1J.3L)1s.eb(0,0);E a};M.5t=C(a){E $(a).17.1Y||\'\'};M.ec=C(a){2s{a=$(a);G n=19.6o(\' \');a.2j(n);a.6w(n)}2A(e){}};G 18={7M:{29:\'oF\',oG:\'oH h0 oI N oJ 5q oK, oL is oM 1h q 9e 3v oN\'},4m:{it:1i.K,6Q:C(a){E(-2w.bb(a*2w.bc)/2)+0.5},7k:C(a){E 1-a},iu:C(a){G a=((-2w.bb(a*2w.bc)/4)+0.75)+2w.oO()/4;E a>1?1:a},oP:C(a){E(-2w.bb(a*2w.bc*(9*a))/2)+0.5},iv:C(a,b){b=b||5;E(((a%(1/b))*b).3o()==0?((a*b*2)-(a*b*2).cE()):1-((a*b*2)-(a*b*2).cE()))},oQ:C(a){E 1-(2w.bb(a*4.5*2w.bc)*2w.oR(-a*6))},4h:C(a){E 0},iw:C(a){E 1}},6R:{2l:1.0,ix:3Z,3I:14,3e:0.0,3v:1.0,3c:0.0,44:\'oS\'},oT:C(c){G d=\'1y:6D\';if(1i.1J.3a)d+=\';7z:1\';c=$(c);$A(c.2o).1n(C(b){if(b.3k==3){b.7f.3R().1n(C(a){c.4Z(1b M(\'oU\',{17:d}).1A(a==\' \'?1T.fR(oV):a),b)});M.4T(b)}})},gU:C(c,d){G e;if(((2i c==\'2U\')||O.2c(c))&&(c.V))e=c;1d e=$(c).2o;G f=O.Y({iy:0.1,3c:0.0},1f[2]||{});G g=f.3c;$A(e).1n(C(a,b){1b d(a,O.Y(f,{3c:b*f.iy+g}))})},ed:{\'oW\':[\'iz\',\'iA\'],\'oX\':[\'iB\',\'iC\'],\'ee\':[\'bd\',\'ef\']},d1:C(a,b){a=$(a);b=(b||\'ee\').1U();G c=O.Y({44:{1y:\'3B\',9f:(a.id||\'9g\'),eg:1}},1f[2]||{});18[a.ag()?18.ed[b][1]:18.ed[b][0]](a,c)}};18.6R.47=18.4m.6Q;18.iD=1D.1E(2W,{1K:C(){q.26=[];q.9h=1e},4x:C(a){q.26.4x(a)},6N:C(a){G b=1b 8n().iE();G c=O.2t(a.J.44)?a.J.44:a.J.44.1y;4N(c){1H\'oY\':q.26.5O(C(e){E e.7N==\'eh\'}).1n(C(e){e.65+=a.67;e.67+=a.67});1I;1H\'6p-2D\':b=q.26.5P(\'65\').4Q()||b;1I;1H\'3B\':b=q.26.5P(\'67\').4Q()||b;1I}a.65+=b;a.67+=b;if(!a.J.44.eg||(q.26.V<a.J.44.eg))q.26.1j(a);if(!q.9h)q.9h=9X(q.7O.1o(q),15)},4T:C(a){q.26=q.26.6q(C(e){E e==a});if(q.26.V==0){9Y(q.9h);q.9h=1e}},7O:C(){G a=1b 8n().iE();1h(G i=0,8t=q.26.V;i<8t;i++)q.26[i]&&q.26[i].7O(a)}});18.be={ei:$H(),3p:C(a){if(!O.2t(a))E a;E q.ei.3p(a)||q.ei.5j(a,1b 18.iD())}};18.oZ=18.be.3p(\'9g\');18.3f=1D.1E({1y:1e,1V:C(c){C 9i(a,b){E((a[b+\'bf\']?\'q.J.\'+b+\'bf(q);\':\'\')+(a[b]?\'q.J.\'+b+\'(q);\':\'\'))}if(c&&c.47===14)c.47=18.4m.it;q.J=O.Y(O.Y({},18.6R),c||{});q.ej=0;q.7N=\'eh\';q.65=q.J.3c*3P;q.67=q.65+(q.J.2l*3P);q.iF=q.J.3v-q.J.3e;q.iG=q.67-q.65;q.iH=q.J.ix*q.J.2l;7e(\'q.56 = C(9j){ \'+\'if (q.7N=="eh"){q.7N="iI";\'+9i(q.J,\'6S\')+(q.7P?\'q.7P();\':\'\')+9i(q.J,\'bg\')+\'};if (q.7N=="iI"){\'+\'9j=q.J.47(9j)*\'+q.iF+\'+\'+q.J.3e+\';\'+\'q.1y=9j;\'+9i(q.J,\'p0\')+(q.1A?\'q.1A(9j);\':\'\')+9i(q.J,\'p1\')+\'}}\');q.4u(\'p2\');if(!q.J.3I)18.be.3p(O.2t(q.J.44)?\'9g\':q.J.44.9f).6N(q)},7O:C(a){if(a>=q.65){if(a>=q.67){q.56(1.0);q.5u();q.4u(\'iJ\');if(q.6T)q.6T();q.4u(\'ek\');E}G b=(a-q.65)/q.iG,el=(b*q.iH).3o();if(el>q.ej){q.56(b);q.ej=el}}},5u:C(){if(!q.J.3I)18.be.3p(O.2t(q.J.44)?\'9g\':q.J.44.9f).4T(q);q.7N=\'p3\'},4u:C(a){if(q.J[a+\'bf\'])q.J[a+\'bf\'](q);if(q.J[a])q.J[a](q)},2m:C(){G a=$H();1h(5p in q)if(!O.2c(q[5p]))a.5j(5p,q[5p]);E\'#<18:\'+a.2m()+\',J:\'+$H(q.J).2m()+\'>\'}});18.7Q=1D.1E(18.3f,{1K:C(a){q.26=a||[];q.1V(1f[1])},1A:C(a){q.26.7d(\'56\',a)},6T:C(b){q.26.1n(C(a){a.56(1.0);a.5u();a.4u(\'iJ\');if(a.6T)a.6T(b);a.4u(\'ek\')})}});18.iK=1D.1E(18.3f,{1K:C(b,c,d){b=O.2t(b)?$(b):b;G e=$A(1f),1W=e.2D(),J=e.V==5?e[3]:1e;q.1W=O.2c(1W)?1W.1o(b):O.2c(b[1W])?b[1W].1o(b):C(a){b[1W]=a};q.1V(O.Y({3e:c,3v:d},J||{}))},1A:C(a){q.1W(a)}});18.1g=1D.1E(18.3f,{1K:C(){q.1V(O.Y({2l:0},1f[0]||{}))},1A:1i.2I});18.57=1D.1E(18.3f,{1K:C(a){q.N=$(a);if(!q.N)2T(18.7M);if(1i.1J.3a&&(!q.N.7A.dp))q.N.1F({7z:1});G b=O.Y({3e:q.N.7v()||0.0,3v:1.0},1f[1]||{});q.1V(b)},1A:C(a){q.N.5V(a)}});18.48=1D.1E(18.3f,{1K:C(a){q.N=$(a);if(!q.N)2T(18.7M);G b=O.Y({x:0,y:0,iL:\'6D\'},1f[1]||{});q.1V(b)},7P:C(){q.N.3Y();q.9k=3s(q.N.1v(\'1w\')||\'0\');q.9l=3s(q.N.1v(\'1r\')||\'0\');if(q.J.iL==\'3E\'){q.J.x=q.J.x-q.9k;q.J.y=q.J.y-q.9l}},1A:C(a){q.N.1F({1w:(q.J.x*a+q.9k).3o()+\'px\',1r:(q.J.y*a+q.9l).3o()+\'px\'})}});18.p4=C(a,b,c){E 1b 18.48(a,O.Y({x:c,y:b},1f[3]||{}))};18.4n=1D.1E(18.3f,{1K:C(a,b){q.N=$(a);if(!q.N)2T(18.7M);G c=O.Y({58:1c,9m:1c,59:1c,bh:14,5a:\'eo\',6U:3Z.0,iM:b},1f[2]||{});q.1V(c)},7P:C(){q.4o=q.J.4o||14;q.iN=q.N.1v(\'1y\');q.ep={};[\'1r\',\'1w\',\'1u\',\'1t\',\'6P\'].1n(C(k){q.ep[k]=q.N.17[k]}.1o(q));q.9l=q.N.5n;q.9k=q.N.5X;G b=q.N.1v(\'p5-6r\')||\'3Z%\';[\'em\',\'px\',\'%\',\'pt\'].1n(C(a){if(b.2r(a)>0){q.6P=3s(b);q.iO=a}}.1o(q));q.iP=(q.J.iM-q.J.6U)/3Z;q.4G=1e;if(q.J.5a==\'eo\')q.4G=[q.N.3D,q.N.3X];if(/^p6/.2C(q.J.5a))q.4G=[q.N.p7,q.N.p8];if(!q.4G)q.4G=[q.J.5a.9n,q.J.5a.9o]},1A:C(a){G b=(q.J.6U/3Z.0)+(q.iP*a);if(q.J.59&&q.6P)q.N.1F({6P:q.6P*b+q.iO});q.iQ(q.4G[0]*b,q.4G[1]*b)},6T:C(a){if(q.4o)q.N.1F(q.ep)},iQ:C(a,b){G d={};if(q.J.58)d.1u=b.3o()+\'px\';if(q.J.9m)d.1t=a.3o()+\'px\';if(q.J.bh){G c=(a-q.4G[0])/2;G e=(b-q.4G[1])/2;if(q.iN==\'3E\'){if(q.J.9m)d.1r=q.9l-c+\'px\';if(q.J.58)d.1w=q.9k-e+\'px\'}1d{if(q.J.9m)d.1r=-c+\'px\';if(q.J.58)d.1w=-e+\'px\'}}q.N.1F(d)}});18.bi=1D.1E(18.3f,{1K:C(a){q.N=$(a);if(!q.N)2T(18.7M);G b=O.Y({bj:\'#iR\'},1f[1]||{});q.1V(b)},7P:C(){if(q.N.1v(\'3C\')==\'4h\'){q.5u();E}q.eq={};if(!q.J.er){q.eq.iS=q.N.1v(\'bk-p9\');q.N.1F({iS:\'4h\'})}if(!q.J.bl)q.J.bl=q.N.1v(\'bk-5v\').64(\'#es\');if(!q.J.bm)q.J.bm=q.N.1v(\'bk-5v\');q.et=$R(0,2).1R(C(i){E 3u(q.J.bj.3n(i*2+1,i*2+3),16)}.1o(q));q.iT=$R(0,2).1R(C(i){E 3u(q.J.bl.3n(i*2+1,i*2+3),16)-q.et[i]}.1o(q))},1A:C(a){q.N.1F({7R:$R(0,2).3A(\'#\',C(m,v,i){E m+((q.et[i]+(q.iT[i]*a)).3o().7m())}.1o(q))})},6T:C(){q.N.1F(O.Y(q.eq,{7R:q.J.bm}))}});18.pa=C(a){G b=1f[1]||{},eu=19.aM.dB(),bn=$(a).3r(),4Q=19.aM.dB[0]-19.aM.db();if(b.2K)bn[1]+=b.2K;E 1b 18.iK(1e,eu.1r,bn[1]>4Q?4Q:bn[1],b,C(p){8N(eu.1w,p.3o())})};18.ef=C(b){b=$(b);G c=b.5t();G d=O.Y({3e:b.7v()||1.0,3v:0.0,2g:C(a){if(a.J.3v!=0)E;a.N.25().1F({1Y:c})}},1f[1]||{});E 1b 18.57(b,d)};18.bd=C(b){b=$(b);G c=O.Y({3e:(b.1v(\'3C\')==\'4h\'?0.0:b.7v()||0.0),3v:1.0,2g:C(a){a.N.ec()},6S:C(a){a.N.5V(a.J.3e).2J()}},1f[1]||{});E 1b 18.57(b,c)};18.pb=C(b){b=$(b);G c={1Y:b.5t(),1y:b.1v(\'1y\'),1r:b.17.1r,1w:b.17.1w,1u:b.17.1u,1t:b.17.1t};E 1b 18.7Q([1b 18.4n(b,gm,{3I:1c,bh:1c,59:1c,4o:1c}),1b 18.57(b,{3I:1c,3v:0.0})],O.Y({2l:1.0,pd:C(a){1X.8Q(a.26[0].N)},2g:C(a){a.26[0].N.25().1F(c)}},1f[1]||{}))};18.iC=C(b){b=$(b);b.4W();E 1b 18.4n(b,0,O.Y({59:14,58:14,4o:1c,2g:C(a){a.N.25().4X()}},1f[1]||{}))};18.iB=C(b){b=$(b);G c=b.4B();E 1b 18.4n(b,3Z,O.Y({59:14,58:14,6U:0,5a:{9n:c.1t,9o:c.1u},4o:1c,bg:C(a){a.N.4W().1F({1t:\'ev\'}).2J()},2g:C(a){a.N.4X()}},1f[1]||{}))};18.pe=C(c){c=$(c);G d=c.5t();E 1b 18.bd(c,O.Y({2l:0.4,3e:0,47:18.4m.iu,2g:C(b){1b 18.4n(b.N,1,{2l:0.3,bh:1c,58:14,59:14,4o:1c,6S:C(a){a.N.3Y().4W()},2g:C(a){a.N.25().4X().4V().1F({1Y:d})}})}},1f[1]||{}))};18.pf=C(b){b=$(b);G c={1r:b.1v(\'1r\'),1w:b.1v(\'1w\'),1Y:b.5t()};E 1b 18.7Q([1b 18.48(b,{x:0,y:3Z,3I:1c}),1b 18.57(b,{3I:1c,3v:0.0})],O.Y({2l:0.5,6S:C(a){a.26[0].N.3Y()},2g:C(a){a.26[0].N.25().4V().1F(c)}},1f[1]||{}))};18.pg=C(g){g=$(g);G h=O.Y({iU:20,2l:0.5},1f[1]||{});G i=3s(h.iU);G j=3s(h.2l)/10.0;G k={1r:g.1v(\'1r\'),1w:g.1v(\'1w\')};E 1b 18.48(g,{x:i,y:0,2l:j,2g:C(f){1b 18.48(f.N,{x:-i*2,y:0,2l:j*2,2g:C(e){1b 18.48(e.N,{x:i*2,y:0,2l:j*2,2g:C(d){1b 18.48(d.N,{x:-i*2,y:0,2l:j*2,2g:C(c){1b 18.48(c.N,{x:i*2,y:0,2l:j*2,2g:C(b){1b 18.48(b.N,{x:-i,y:0,2l:j,2g:C(a){a.N.4V().1F(k)}})}})}})}})}})}})};18.iz=C(b){b=$(b).7t();G c=b.3q().1v(\'2P\');G d=b.4B();E 1b 18.4n(b,3Z,O.Y({59:14,58:14,6U:1s.4K?0:1,5a:{9n:d.1t,9o:d.1u},4o:1c,bg:C(a){a.N.3Y();a.N.3q().3Y();if(1s.4K)a.N.1F({1r:\'\'});a.N.4W().1F({1t:\'ev\'}).2J()},iV:C(a){a.N.3q().1F({2P:(a.4G[0]-a.N.7w)+\'px\'})},2g:C(a){a.N.4X().4V();a.N.3q().4V().1F({2P:c})}},1f[1]||{}))};18.iA=C(b){b=$(b).7t();G c=b.3q().1v(\'2P\');G d=b.4B();E 1b 18.4n(b,1s.4K?0:1,O.Y({59:14,58:14,5a:\'eo\',6U:3Z,5a:{9n:d.1t,9o:d.1u},4o:1c,bg:C(a){a.N.3Y();a.N.3q().3Y();if(1s.4K)a.N.1F({1r:\'\'});a.N.4W().2J()},iV:C(a){a.N.3q().1F({2P:(a.4G[0]-a.N.7w)+\'px\'})},2g:C(a){a.N.25().4X().4V();a.N.3q().4V().1F({2P:c})}},1f[1]||{}))};18.ph=C(b){E 1b 18.4n(b,1s.4K?1:0,{4o:1c,6S:C(a){a.N.4W()},2g:C(a){a.N.25().4X()}})};18.pi=C(c){c=$(c);G d=O.Y({bo:\'bp\',bq:18.4m.6Q,bs:18.4m.6Q,bt:18.4m.iw},1f[1]||{});G e={1r:c.17.1r,1w:c.17.1w,1t:c.17.1t,1u:c.17.1u,1Y:c.5t()};G f=c.4B();G g,6V;G h,3J;4N(d.bo){1H\'1r-1w\':g=6V=h=3J=0;1I;1H\'1r-5m\':g=f.1u;6V=3J=0;h=-f.1u;1I;1H\'2P-1w\':g=h=0;6V=f.1t;3J=-f.1t;1I;1H\'2P-5m\':g=f.1u;6V=f.1t;h=-f.1u;3J=-f.1t;1I;1H\'bp\':g=f.1u/2;6V=f.1t/2;h=-f.1u/2;3J=-f.1t/2;1I}E 1b 18.48(c,{x:g,y:6V,2l:0.fF,6S:C(a){a.N.25().4W().3Y()},2g:C(b){1b 18.7Q([1b 18.57(b.N,{3I:1c,3v:1.0,3e:0.0,47:d.bt}),1b 18.48(b.N,{x:h,y:3J,3I:1c,47:d.bq}),1b 18.4n(b.N,3Z,{5a:{9n:f.1t,9o:f.1u},3I:1c,6U:1s.4K?1:0,47:d.bs,4o:1c})],O.Y({6S:C(a){a.26[0].N.1F({1t:\'ev\'}).2J()},2g:C(a){a.26[0].N.4X().4V().1F(e)}},d))}})};18.pj=C(b){b=$(b);G c=O.Y({bo:\'bp\',bq:18.4m.6Q,bs:18.4m.6Q,bt:18.4m.4h},1f[1]||{});G d={1r:b.17.1r,1w:b.17.1w,1t:b.17.1t,1u:b.17.1u,1Y:b.5t()};G e=b.4B();G f,3J;4N(c.bo){1H\'1r-1w\':f=3J=0;1I;1H\'1r-5m\':f=e.1u;3J=0;1I;1H\'2P-1w\':f=0;3J=e.1t;1I;1H\'2P-5m\':f=e.1u;3J=e.1t;1I;1H\'bp\':f=e.1u/2;3J=e.1t/2;1I}E 1b 18.7Q([1b 18.57(b,{3I:1c,3v:0.0,3e:1.0,47:c.bt}),1b 18.4n(b,1s.4K?1:0,{3I:1c,47:c.bs,4o:1c}),1b 18.48(b,{x:f,y:3J,3I:1c,47:c.bq})],O.Y({pk:C(a){a.26[0].N.3Y().4W()},2g:C(a){a.26[0].N.25().4X().4V().1F(d)}},c))};18.pl=C(b){b=$(b);G c=1f[1]||{};G d=b.5t();G e=c.47||18.4m.6Q;G f=C(a){E e(1-18.4m.iv(a,c.pm))};f.1o(e);E 1b 18.57(b,O.Y(O.Y({2l:2.0,3e:0,2g:C(a){a.N.1F({1Y:d})}},c),{47:f}))};18.pn=C(c){c=$(c);G d={1r:c.17.1r,1w:c.17.1w,1u:c.17.1u,1t:c.17.1t};c.4W();E 1b 18.4n(c,5,O.Y({59:14,58:14,2g:C(b){1b 18.4n(c,1,{59:14,9m:14,2g:C(a){a.N.25().4X().1F(d)}})}},1f[1]||{}))};18.ew=1D.1E(18.3f,{1K:C(c){q.N=$(c);if(!q.N)2T(18.7M);G d=O.Y({17:{}},1f[1]||{});if(!O.2t(d.17))q.17=$H(d.17);1d{if(d.17.1L(\':\'))q.17=d.17.iW();1d{q.N.3W(d.17);q.17=$H(q.N.9p());q.N.4U(d.17);G e=q.N.9p();q.17=q.17.6q(C(a){E a.1k==e[a.4f]});d.2g=C(b){b.N.3W(b.J.17);b.bu.1n(C(a){b.N.17[a.17]=\'\'})}}}q.1V(d)},7P:C(){C 64(a){if(!a||[\'po(0, 0, 0, 0)\',\'iX\'].1L(a))a=\'#es\';a=a.64();E $R(0,2).1R(C(i){E 3u(a.3n(i*2+1,i*2+3),16)})}q.bu=q.17.1R(C(a){G b=a[0],1k=a[1],4H=1e;if(1k.64(\'#iY\')!=\'#iY\'){1k=1k.64();4H=\'5v\'}1d if(b==\'1Y\'){1k=3s(1k);if(1i.1J.3a&&(!q.N.7A.dp))q.N.1F({7z:1})}1d if(M.iZ.2C(1k)){G c=1k.1C(/^([\\+\\-]?[0-9\\.]+)(.*)$/);1k=3s(c[1]);4H=(c.V==3)?c[2]:1e}G d=q.N.1v(b);E{17:b.8s(),4I:4H==\'5v\'?64(d):3s(d||0),6W:4H==\'5v\'?64(1k):1k,4H:4H}}.1o(q)).6q(C(a){E((a.4I==a.6W)||(a.4H!=\'5v\'&&(cD(a.4I)||cD(a.6W))))})},1A:C(a){G b={},2Z,i=q.bu.V;1Q(i--)b[(2Z=q.bu[i]).17]=2Z.4H==\'5v\'?\'#\'+(2w.3o(2Z.4I[0]+(2Z.6W[0]-2Z.4I[0])*a)).7m()+(2w.3o(2Z.4I[1]+(2Z.6W[1]-2Z.4I[1])*a)).7m()+(2w.3o(2Z.4I[2]+(2Z.6W[2]-2Z.4I[2])*a)).7m():(2Z.4I+(2Z.6W-2Z.4I)*a).pp(3)+(2Z.4H===1e?\'\':2Z.4H);q.N.1F(b,1c)}});18.pq=1D.1E({1K:C(a){q.4J=[];q.J=1f[1]||{};q.j0(a)},j0:C(c){c.1n(C(a){a=$H(a);G b=a.1O().3M();q.4J.1j($H({j1:a.6h().3M(),9e:18.ew,J:{17:b}}))}.1o(q));E q},ey:C(){E 1b 18.7Q(q.4J.1R(C(a){G b=a.3p(\'j1\'),9e=a.3p(\'9e\'),J=a.3p(\'J\');G c=[$(b)||$$(b)].3T();E c.1R(C(e){E 1b 9e(e,O.Y({3I:1c},J))})}).3T(),q.J)}});M.bv=$w(\'7R pr pu pv \'+\'pw py pz pA \'+\'pB pC pD pE \'+\'pF pG pH 2P pI 5v \'+\'6P pJ 1t 1w pK pL \'+\'pM pN pO pP pQ pR \'+\'pS pT pU 1Y pV pW \'+\'pX pY pZ q0 q1 \'+\'5m q2 1r 1u q3 9q\');M.iZ=/^(([\\+\\-]?[0-9\\.]+)(em|ex|px|in|cm|mm|pt|pc|\\%))|0$/;1T.ez=19.2b(\'2H\');1T.1p.iW=C(){G b,bw=$H();if(1i.1J.3L)b=1b M(\'2H\',{17:q}).17;1d{1T.ez.2V=\'<2H 17="\'+q+\'"></2H>\';b=1T.ez.2o[0].17}M.bv.1n(C(a){if(b[a])bw.5j(a,b[a])});if(1i.1J.3a&&q.1L(\'1Y\'))bw.5j(\'1Y\',q.1C(/1Y:\\s*((?:0|1)?(?:\\.\\d*)?)/)[1]);E bw};if(19.aq&&19.aq.dd){M.9p=C(c){G d=19.aq.dd($(c),1e);E M.bv.3A({},C(a,b){a[b]=d[b];E a})}}1d{M.9p=C(c){c=$(c);G d=c.7A,9r;9r=M.bv.3A({},C(a,b){a[b]=d[b];E a});if(!9r.1Y)9r.1Y=c.7v();E 9r}}18.1m={q4:C(a,b){a=$(a);1b 18.ew(a,O.Y({17:b},1f[2]||{}));E a},q5:C(a,b,c){a=$(a);G s=b.fT().8s(),3y=s.5M(0).2e()+s.5i(1);1b 18[3y](a,c);E a},q6:C(a,b){a=$(a);1b 18.bi(a,b);E a}};$w(\'q7 ee q8 q9 qa qb qc qd qe \'+\'qf qg qh qi qj qk\').1n(C(c){18.1m[c]=C(a,b){a=$(a);18[c.5M(0).2e()+c.5i(1)](a,b);E a}});$w(\'5t ec ir b9 ba 9p\').1n(C(f){18.1m[f]=M[f]});M.7a(18.1m);if(O.2z(18))2T("ql.js e5 j2 4s.e3.e4\' 26.js j3");G 49={7S:[],4T:C(a){q.7S=q.7S.6q(C(d){E d.N==$(a)})},6N:C(a){a=$(a);G b=O.Y({qm:1c,5b:1e,3K:14},1f[1]||{});if(b.6X){b.9s=[];G d=b.6X;if(O.4e(d)){d.1n(C(c){b.9s.1j($(c))})}1d{b.9s.1j($(d))}}if(b.9t)b.9t=[b.9t].3T();M.3Y(a);b.N=a;q.7S.1j(b)},j4:C(a){bx=a[0];1h(i=1;i<a.V;++i)if(M.9u(a[i].N,bx.N))bx=a[i];E bx},j5:C(a,b){G d;if(b.3K){d=a.eA}1d{d=a.1z}E b.9s.5N(C(c){E d==c})},eB:C(a,b,c){E((c.N!=b)&&((!c.9s)||q.j5(b,c))&&((!c.9t)||(M.6B(b).5N(C(v){E c.9t.1L(v)})))&&1X.dZ(c.N,a[0],a[1]))},9v:C(a){if(a.5b)M.4U(a.N,a.5b);q.4a=1e},55:C(a){if(a.5b)M.3W(a.N,a.5b);q.4a=a},2J:C(b,c){if(!q.7S.V)E;G d,by=[];q.7S.1n(C(a){if(49.eB(b,c,a))by.1j(a)});if(by.V>0)d=49.j4(by);if(q.4a&&q.4a!=d)q.9v(q.4a);if(d){1X.dZ(d.N,b[0],b[1]);if(d.68)d.68(c,d.N,1X.43(d.43,d.N));if(d!=q.4a)49.55(d)}},63:C(a,b){if(!q.4a)E;1X.6M();if(q.eB([1g.6K(a),1g.6L(a)],b,q.4a))if(q.4a.j6){q.4a.j6(b,q.4a.N,a);E 1c}},94:C(){if(q.4a)q.9v(q.4a)}};G 21={7T:[],7U:[],a3:C(a){if(q.7T.V==0){q.7V=q.7W.3O(q);q.7X=q.bz.3O(q);q.eC=q.bA.3O(q);1g.2k(19,"bB",q.7V);1g.2k(19,"bC",q.7X);1g.2k(19,"j7",q.eC)}q.7T.1j(a)},cH:C(a){q.7T=q.7T.6q(C(d){E d==a});if(q.7T.V==0){1g.2Y(19,"bB",q.7V);1g.2Y(19,"bC",q.7X);1g.2Y(19,"j7",q.eC)}},55:C(a){if(a.J.3c){q.9w=6k(C(){21.9w=1e;1s.62();21.5c=a}.1o(q),a.J.3c)}1d{1s.62();q.5c=a}},9v:C(){q.5c=1e},bz:C(a){if(!q.5c)E;G b=[1g.6K(a),1g.6L(a)];if(q.7Y&&(q.7Y.2m()==b.2m()))E;q.7Y=b;q.5c.bz(a,b)},7W:C(a){if(q.9w){af(q.9w);q.9w=1e}if(!q.5c)E;q.7Y=1e;q.5c.7W(a);q.5c=1e},bA:C(a){if(q.5c)q.5c.bA(a)},j8:C(a){q.7U.1j(a);q.eD()},j9:C(a){q.7U=q.7U.6q(C(o){E o.N==a});q.eD()},9x:C(a,b,c){if(q[a+\'ja\']>0)q.7U.1n(C(o){if(o[a])o[a](a,b,c)});if(b.J[a])b.J[a](b,c)},eD:C(){[\'eE\',\'eF\',\'eG\'].1n(C(a){21[a+\'ja\']=21.7U.24(C(o){E o[a]}).V})}};G 6Y=1D.1E({1K:C(e){G f={2R:14,6Z:C(a,b,c){G d=2w.qn(2w.8y(b^2)+2w.8y(c^2))*0.qo;1b 18.48(a,{x:-c,y:-b,2l:d,44:{9f:\'jb\',1y:\'3B\'}})},70:C(a){G b=O.5F(a.bD)?a.bD:1.0;1b 18.57(a,{2l:0.2,3e:0.7,3v:b,44:{9f:\'jb\',1y:\'3B\'},ek:C(){6Y.9y[a]=14}})},71:3P,eH:14,7Z:14,1P:14,4p:20,3w:15,5w:14,3c:0};if(!1f[1]||O.2z(1f[1].70))O.Y(f,{80:C(a){a.bD=M.7v(a);6Y.9y[a]=1c;1b 18.57(a,{2l:0.2,3e:a.bD,3v:0.7})}});G g=O.Y(f,1f[1]||{});q.N=$(e);if(g.2R&&O.2t(g.2R))q.2R=q.N.3q(\'.\'+g.2R,0);if(!q.2R)q.2R=$(g.2R);if(!q.2R)q.2R=q.N;if(g.1P&&!g.1P.8N&&!g.1P.du){g.1P=$(g.1P);q.eI=M.i5(q.N,g.1P)}M.3Y(q.N);q.J=g;q.4q=14;q.69=q.jc.3O(q);1g.2k(q.2R,"81",q.69);21.a3(q)},82:C(){1g.2Y(q.2R,"81",q.69);21.cH(q)},bE:C(){E([3u(M.1v(q.N,\'1w\')||\'0\'),3u(M.1v(q.N,\'1r\')||\'0\')])},jc:C(a){if(!O.2z(6Y.9y[q.N])&&6Y.9y[q.N])E;if(1g.dS(a)){G b=1g.N(a);if((83=b.1B.2e())&&(83==\'dv\'||83==\'aC\'||83==\'e6\'||83==\'ip\'||83==\'aJ\'))E;G c=[1g.6K(a),1g.6L(a)];G d=1X.3r(q.N);q.2K=[0,1].1R(C(i){E(c[i]-d[i])});21.55(q);1g.2M(a)}},bF:C(a){q.4q=1c;if(!q.9z)q.9z=q.bE();if(q.J.71){q.jd=3u(M.1v(q.N,\'z-2u\')||0);q.N.17.9q=q.J.71}if(q.J.6a){q.bG=q.N.gC(1c);q.bH=(q.N.1v(\'1y\')==\'3E\');if(!q.bH)1X.8Q(q.N);q.N.1z.4Z(q.bG,q.N)}if(q.J.1P){if(q.J.1P==1s){G b=q.bI(q.J.1P);q.eJ=b.1w;q.eK=b.1r}1d{q.eJ=q.J.1P.3F;q.eK=q.J.1P.3t}}21.9x(\'eE\',q,a);if(q.J.80)q.J.80(q.N)},bz:C(a,b){if(!q.4q)q.bF(a);if(!q.J.7Z){1X.6M();49.2J(b,q.N)}21.9x(\'eG\',q,a);q.9A(b);if(q.J.97)q.J.97(q);if(q.J.1P){q.eL();G p;if(q.J.1P==1s){6p(q.bI(q.J.1P)){p=[1w,1r,1w+1u,1r+1t]}}1d{p=1X.ic(q.J.1P);p[0]+=q.J.1P.3F+1X.b4;p[1]+=q.J.1P.3t+1X.b5;p.1j(p[0]+q.J.1P.3X);p.1j(p[1]+q.J.1P.3D)}G c=[0,0];if(b[0]<(p[0]+q.J.4p))c[0]=b[0]-(p[0]+q.J.4p);if(b[1]<(p[1]+q.J.4p))c[1]=b[1]-(p[1]+q.J.4p);if(b[0]>(p[2]-q.J.4p))c[0]=b[0]-(p[2]-q.J.4p);if(b[1]>(p[3]-q.J.4p))c[1]=b[1]-(p[3]-q.J.4p);q.je(c)}if(1i.1J.3L)1s.eb(0,0);1g.2M(a)},9B:C(a,b){q.4q=14;if(q.J.7Z){1X.6M();G c=[1g.6K(a),1g.6L(a)];49.2J(c,q.N)}if(q.J.6a){if(!q.bH)1X.av(q.N);7n q.bH;M.4T(q.bG);q.bG=1e}G e=14;if(b){e=49.63(a,q.N);if(!e)e=14}if(e&&q.J.jf)q.J.jf(q.N);21.9x(\'eF\',q,a);G f=q.J.eH;if(f&&O.2c(f))f=f(q.N);G d=q.bE();if(f&&q.J.6Z){if(e==0||f!=\'ad\')q.J.6Z(q.N,d[1]-q.9z[1],d[0]-q.9z[0])}1d{q.9z=d}if(q.J.71)q.N.17.9q=q.jd;if(q.J.70)q.J.70(q.N);21.9v(q);49.94()},bA:C(a){if(a.72!=1g.aW)E;q.9B(a,14);1g.2M(a)},7W:C(a){if(!q.4q)E;q.eL();q.9B(a,1c);1g.2M(a)},9A:C(a){G b=1X.3r(q.N);if(q.J.6a){G r=1X.ib(q.N);b[0]+=r[0]-1X.b4;b[1]+=r[1]-1X.b5}G d=q.bE();b[0]-=d[0];b[1]-=d[1];if(q.J.1P&&(q.J.1P!=1s&&q.eI)){b[0]-=q.J.1P.3F-q.eJ;b[1]-=q.J.1P.3t-q.eK}G p=[0,1].1R(C(i){E(a[i]-b[i]-q.2K[i])}.1o(q));if(q.J.5w){if(O.2c(q.J.5w)){p=q.J.5w(p[0],p[1],q)}1d{if(O.4e(q.J.5w)){p=p.1R(C(v,i){E(v/q.J.5w[i]).3o()*q.J.5w[i]}.1o(q))}1d{p=p.1R(C(v){E(v/q.J.5w).3o()*q.J.5w}.1o(q))}}}G c=q.N.17;if((!q.J.73)||(q.J.73==\'b6\'))c.1w=p[0]+"px";if((!q.J.73)||(q.J.73==\'7K\'))c.1r=p[1]+"px";if(c.6C=="5W")c.6C=""},eL:C(){if(q.bJ){9Y(q.bJ);q.bJ=1e;21.5d=1e}},je:C(a){if(!(a[0]||a[1]))E;q.3w=[a[0]*q.J.3w,a[1]*q.J.3w];q.eM=1b 8n();q.bJ=9X(q.1P.1o(q),10)},1P:C(){G a=1b 8n();G b=a-q.eM;q.eM=a;if(q.J.1P==1s){6p(q.bI(q.J.1P)){if(q.3w[0]||q.3w[1]){G d=b/3P;q.J.1P.8N(1w+d*q.3w[0],1r+d*q.3w[1])}}}1d{q.J.1P.3F+=q.3w[0]*b/3P;q.J.1P.3t+=q.3w[1]*b/3P}1X.6M();49.2J(21.7Y,q.N);21.9x(\'eG\',q);if(q.eI){21.5d=21.5d||$A(21.7Y);21.5d[0]+=q.3w[0]*b/3P;21.5d[1]+=q.3w[1]*b/3P;if(21.5d[0]<0)21.5d[0]=0;if(21.5d[1]<0)21.5d[1]=0;q.9A(21.5d)}if(q.J.97)q.J.97(q)},bI:C(w){G T,L,W,H;6p(w.19){if(w.19.3i&&3i.3t){T=3i.3t;L=3i.3F}1d if(w.19.28){T=28.3t;L=28.3F}if(w.jg){W=w.jg;H=w.qp}1d if(w.19.3i&&3i.8O){W=3i.8O;H=3i.7w}1d{W=28.3X;H=28.3D}}E{1r:T,1w:L,1u:W,1t:H}}});6Y.9y={};G jh=1D.1E({1K:C(a,b){q.N=$(a);q.84=b;q.3H=1G.54(q.N)},eE:C(){q.3H=1G.54(q.N)},eF:C(){1G.5r();if(q.3H!=1G.54(q.N))q.84(q.N)}});G 1G={ji:/^[^3S\\-](?:[A-qq-ih-9\\-\\3S]*)[3S](.*)$/,9C:{},jj:C(a){1Q(a.1B.2e()!="au"){if(a.id&&1G.9C[a.id])E a;a=a.1z}},J:C(a){a=1G.jj($(a));if(!a)E;E 1G.9C[a.id]},82:C(a){G s=1G.J(a);if(s){21.j9(s.N);s.9D.1n(C(d){49.4T(d)});s.eN.7d(\'82\');7n 1G.9C[s.N.id]}},1E:C(b){b=$(b);G c=O.Y({N:b,85:\'li\',jk:14,3K:14,9E:\'eO\',43:\'7K\',73:\'7K\',6X:b,2R:14,4l:14,3c:0,5b:1e,6a:14,7Z:14,1P:14,4p:20,3w:15,6b:q.ji,8E:14,2q:14,5x:1i.2I,jl:1i.2I},1f[1]||{});q.82(b);G d={eH:1c,7Z:c.7Z,1P:c.1P,3w:c.3w,4p:c.4p,3c:c.3c,6a:c.6a,73:c.73,2R:c.2R};if(c.80)d.80=c.80;if(c.6Z)d.6Z=c.6Z;1d if(c.6a)d.6Z=C(a){a.17.1r=0;a.17.1w=0};if(c.70)d.70=c.70;if(c.71)d.71=c.71;G f={43:c.43,6X:c.6X,3K:c.3K,5b:c.5b,68:1G.68};G g={68:1G.jm,43:c.43,6X:c.6X,5b:c.5b};M.7t(b);c.eN=[];c.9D=[];if(c.jk||c.3K){49.6N(b,g);c.9D.1j(b)}(c.8E||q.52(b,c)||[]).1n(C(e,i){G a=c.2q?$(c.2q[i]):(c.2R?$(e).24(\'.\'+c.2R)[0]:e);c.eN.1j(1b 6Y(e,O.Y(d,{2R:a})));49.6N(e,f);if(c.3K)e.eA=b;c.9D.1j(e)});if(c.3K){(1G.jn(b,c)||[]).1n(C(e){49.6N(e,g);e.eA=b;c.9D.1j(e)})}q.9C[b.id]=c;21.j8(1b jh(b,c.jl))},52:C(a,b){E M.bK(a,b.4l,b.3K?1c:14,b.85)},jn:C(a,b){E M.bK(a,b.4l,b.3K?1c:14,b.9E)},68:C(a,b,c){if(M.9u(b,a))E;if(c>.33&&c<.66&&1G.J(b).3K){E}1d if(c>0.5){1G.6I(b,\'ah\');if(b.d5!=a){G d=a.1z;a.17.6C="5W";b.1z.4Z(a,b);if(b.1z!=d)1G.J(d).5x(a);1G.J(b.1z).5x(a)}}1d{1G.6I(b,\'7r\');G e=b.5l||1e;if(e!=a){G d=a.1z;a.17.6C="5W";b.1z.4Z(a,e);if(b.1z!=d)1G.J(d).5x(a);1G.J(b.1z).5x(a)}}},jm:C(a,b,c){G d=a.1z;G e=1G.J(b);if(!M.9u(b,a)){G f;G g=1G.52(b,{85:e.85,4l:e.4l});G h=1e;if(g){G i=M.9F(b,e.43)*(1.0-c);1h(f=0;f<g.V;f+=1){if(i-M.9F(g[f],e.43)>=0){i-=M.9F(g[f],e.43)}1d if(i-(M.9F(g[f],e.43)/2)>=0){h=f+1<g.V?g[f+1]:1e;1I}1d{h=g[f];1I}}}b.4Z(a,h);1G.J(d).5x(a);e.5x(a)}},5r:C(){if(1G.5y)1G.5y.25()},6I:C(a,b){G c=1G.J(a.1z);if(c&&!c.6a)E;if(!1G.5y){1G.5y=($(\'jo\')||M.Y(19.2b(\'iq\'))).25().3W(\'jo\').1F({1y:\'3E\'});19.42("28").qr(0).2j(1G.5y)}G d=1X.3r(a);1G.5y.1F({1w:d[0]+\'px\',1r:d[1]+\'px\'});if(b==\'7r\')if(c.43==\'b6\')1G.5y.1F({1w:(d[0]+a.8O)+\'px\'});1d 1G.5y.1F({1r:(d[1]+a.7w)+\'px\'});1G.5y.2J()},eP:C(a,b,c){G d=1G.52(a,b)||[];1h(G i=0;i<d.V;++i){G e=d[i].id.1C(b.6b);if(!e)4j;G f={id:4y(e?e[1]:1e),N:a,eQ:c,86:[],1y:c.86.V,5S:$(d[i]).3q(b.9E)};if(f.5S)q.eP(f.5S,b,f);c.86.1j(f)}E c},3K:C(a){a=$(a);G b=q.J(a);G c=O.Y({85:b.85,9E:b.9E,4l:b.4l,29:a.id,6b:b.6b},1f[1]||{});G d={id:1e,eQ:1e,86:[],5S:a,1y:0};E 1G.eP(a,c,d)},jp:C(a){G b=\'\';do{if(a.id)b=\'[\'+a.1y+\']\'+b}1Q((a=a.eQ)!=1e);E b},jq:C(b){b=$(b);G c=O.Y(q.J(b),1f[1]||{});E $(q.52(b,c)||[]).1R(C(a){E a.id.1C(c.6b)?a.id.1C(c.6b)[1]:\'\'})},qs:C(b,c){b=$(b);G d=O.Y(q.J(b),1f[2]||{});G e={};q.52(b,d).1n(C(n){if(n.id.1C(d.6b))e[n.id.1C(d.6b)[1]]=[n,n.1z];n.1z.6w(n)});c.1n(C(a){G n=e[a];if(n){n[1].2j(n[0]);7n e[a]}})},54:C(b){b=$(b);G c=O.Y(1G.J(b),1f[1]||{});G d=4y((1f[1]&&1f[1].29)?1f[1].29:b.id);if(c.3K){E 1G.3K(b,1f[1]).86.1R(C(a){E[d+1G.jp(a)+"[id]="+4y(a.id)].22(a.86.1R(1f.5h))}).3T().2d(\'&\')}1d{E 1G.jq(b,1f[1]).1R(C(a){E d+"[]="+4y(a)}).2d(\'&\')}}};M.9u=C(a,b){if(!a.1z||a==b)E 14;if(a.1z==b)E 1c;E M.9u(a.1z,b)};M.bK=C(b,c,d,f){if(!b.ea())E 1e;f=f.2e();if(c)c=[c].3T();G g=[];$A(b.2o).1n(C(e){if(e.1B&&e.1B.2e()==f&&(!c||(M.6B(e).5N(C(v){E c.1L(v)}))))g.1j(e);if(d){G a=M.bK(e,c,d,f);if(a)g.1j(a)}});E(g.V>0?g.3T():[])};M.9F=C(a,b){E a[\'2K\'+((b==\'7K\'||b==\'1t\')?\'qt\':\'qu\')]};if(2i 18==\'3j\')2T("qv.js e5 j2 4s.e3.e4\' 26.js j3");G 74={};74.3f=1D.1E({eR:C(c,d,e){c=$(c);q.N=c;q.1A=$(d);q.87=14;q.9G=14;q.3x=14;q.2u=0;q.5z=0;q.9H=q.N.1k;if(q.eS)q.eS(e);1d q.J=e||{};q.J.88=q.J.88||q.N.29;q.J.41=q.J.41||[];q.J.5J=q.J.5J||0.4;q.J.eT=q.J.eT||1;q.J.eU=q.J.eU||C(a,b){if(!b.17.1y||b.17.1y==\'3E\'){b.17.1y=\'3E\';1X.2B(a,b,{dk:14,5n:a.3D})}18.bd(b,{2l:0.15})};q.J.eV=q.J.eV||C(a,b){1b 18.ef(b,{2l:0.15})};if(2i(q.J.41)==\'7c\')q.J.41=1b 2v(q.J.41);if(!q.J.41.1L(\'\\n\'))q.J.41.1j(\'\\n\');q.84=1e;q.N.da(\'qw\',\'qx\');M.25(q.1A);1g.2k(q.N,\'hB\',q.jr.3O(q));1g.2k(q.N,\'jt\',q.ju.3O(q))},2J:C(){if(M.1v(q.1A,\'3C\')==\'4h\')q.J.eU(q.N,q.1A);if(!q.6c&&(1i.1J.3a)&&(M.1v(q.1A,\'1y\')==\'3E\')){1b i6.dY(q.1A,\'<jv id="\'+q.1A.id+\'jw" \'+\'17="3C:4h;1y:3E;6s:qy:qz.ge.qA(1Y=0);" \'+\'4Y="cO:14;" qB="0" qC="no"></jv>\');q.6c=$(q.1A.id+\'jw\')}if(q.6c)6k(q.jx.1o(q),50)},jx:C(){1X.2B(q.1A,q.6c,{dj:(!q.1A.17.1t)});q.6c.17.9q=1;q.1A.17.9q=2;M.2J(q.6c)},25:C(){q.eW();if(M.1v(q.1A,\'3C\')!=\'4h\')q.J.eV(q.N,q.1A);if(q.6c)M.25(q.6c)},jy:C(){if(q.J.bL)M.2J(q.J.bL)},eW:C(){if(q.J.bL)M.25(q.J.bL)},ju:C(a){if(q.3x)4N(a.72){1H 1g.dP:1H 1g.aV:q.bM();1g.2M(a);1H 1g.aW:q.25();q.3x=14;1g.2M(a);E;1H 1g.hK:1H 1g.hM:E;1H 1g.hL:q.jz();q.56();1g.2M(a);E;1H 1g.hN:q.jA();q.56();1g.2M(a);E}1d if(a.72==1g.dP||a.72==1g.aV||(1i.1J.3L>0&&a.72==0))E;q.9G=1c;q.87=1c;if(q.84)af(q.84);q.84=6k(q.jB.1o(q),q.J.5J*3P)},55:C(){q.9G=14;q.87=1c;q.bN()},68:C(a){G b=1g.5T(a,\'e9\');if(q.2u!=b.bO){q.2u=b.bO;q.56()}1g.2M(a)},jC:C(a){G b=1g.5T(a,\'e9\');q.2u=b.bO;q.bM();q.25()},jr:C(a){6k(q.25.1o(q),qD);q.87=14;q.3x=14},56:C(){if(q.5z>0){1h(G i=0;i<q.5z;i++)q.2u==i?M.3W(q.76(i),"5s"):M.4U(q.76(i),"5s");if(q.87){q.2J();q.3x=1c}}1d{q.3x=14;q.25()}},jz:C(){if(q.2u>0)q.2u--;1d q.2u=q.5z-1;q.76(q.2u).jD(1c)},jA:C(){if(q.2u<q.5z-1)q.2u++;1d q.2u=0;q.76(q.2u).jD(14)},76:C(a){E q.1A.4z.2o[a]},jE:C(){E q.76(q.2u)},bM:C(){q.3x=14;q.bP(q.jE())},bP:C(a){if(q.J.bP){q.J.bP(a);E}G b=\'\';if(q.J.24){G c=$(a).24(\'.\'+q.J.24)||[];if(c.V>0)b=M.b9(c[0],q.J.24)}1d b=M.ba(a,\'qE\');G d=q.bQ();if(d[0]!=-1){G e=q.N.1k.5A(0,d[0]);G f=q.N.1k.5A(d[0]).1C(/^\\s+/);if(f)e+=f[0];q.N.1k=e+b+q.N.1k.5A(d[1])}1d{q.N.1k=b}q.9H=q.N.1k;q.N.62();if(q.J.jF)q.J.jF(q.N,a)},eX:C(a){if(!q.9G&&q.87){q.1A.2V=a;M.7t(q.1A);M.7t(q.1A.3q());if(q.1A.4z&&q.1A.3q().2o){q.5z=q.1A.3q().2o.V;1h(G i=0;i<q.5z;i++){G b=q.76(i);b.bO=i;q.jG(b)}}1d{q.5z=0}q.eW();q.2u=0;if(q.5z==1&&q.J.qF){q.bM();q.25()}1d{q.56()}}},jG:C(a){1g.2k(a,"dR",q.68.3O(q));1g.2k(a,"dO",q.jC.3O(q))},jB:C(){q.9G=14;q.bR=1e;if(q.bS().V>=q.J.eT){q.bN()}1d{q.3x=14;q.25()}q.9H=q.N.1k},bS:C(){G a=q.bQ();E q.N.1k.5i(a[0],a[1]).3l()},bQ:C(){if(1e!=q.bR)E q.bR;G a=q.N.1k;if(a.3l().6n())E[-1,0];G b=1f.5h.jH(a,q.9H);G c=(b==q.9H.V?1:0);G d=-1,bT=a.V;G e;1h(G f=0,l=q.J.41.V;f<l;++f){e=a.a0(q.J.41[f],b+c-1);if(e>d)d=e;e=a.2r(q.J.41[f],b+c);if(-1!=e&&e<bT)bT=e}E(q.bR=[d+1,bT])}});74.3f.1p.bQ.jH=C(a,b){G c=2w.7j(a.V,b.V);1h(G d=0;d<c;++d)if(a[d]!=b[d])E d;E c};1x.74=1D.1E(74.3f,{1K:C(a,b,c,d){q.eR(a,b,d);q.J.8C=1c;q.J.2N=q.2N.1o(q);q.J.eY=q.J.2E||1e;q.3g=c},bN:C(){q.jy();G a=4y(q.J.88)+\'=\'+4y(q.bS());q.J.2E=q.J.4v?q.J.4v(q.N,a):a;if(q.J.eY)q.J.2E+=\'&\'+q.J.eY;1b 1x.4g(q.3g,q.J)},2N:C(a){q.eX(a.3U)}});74.qG=1D.1E(74.3f,{1K:C(a,b,c,d){q.eR(a,b,d);q.J.7h=c},bN:C(){q.eX(q.J.93(q))},eS:C(h){q.J=O.Y({eZ:10,jI:1c,jJ:2,f0:1c,jK:14,93:C(a){G b=[];G c=[];G d=a.bS();G e=0;1h(G i=0;i<a.J.7h.V&&b.V<a.J.eZ;i++){G f=a.J.7h[i];G g=a.J.f0?f.1U().2r(d.1U()):f.2r(d);1Q(g!=-1){if(g==0&&f.V!=d.V){b.1j("<li><bU>"+f.5A(0,d.V)+"</bU>"+f.5A(d.V)+"</li>");1I}1d if(d.V>=a.J.jJ&&a.J.jI&&g!=-1){if(a.J.jK||/\\s/.2C(f.5A(g-1,1))){c.1j("<li>"+f.5A(0,g)+"<bU>"+f.5A(g,d.V)+"</bU>"+f.5A(g+d.V)+"</li>");1I}}g=a.J.f0?f.1U().2r(d.1U(),g+1):f.2r(d,g+1)}}if(c.V)b=b.22(c.3n(0,a.J.eZ-b.V));E"<eO>"+b.2d(\'\')+"</eO>"}},h||{})}});aT.jL=C(a){6k(C(){aT.55(a)},1)};1x.5B=1D.1E({1K:C(a,b,c){q.3g=b;q.N=a=$(a);q.jM();q.2y={};1f.5h.jN(c);O.Y(q.J,c||{});if(!q.J.89&&q.N.id){q.J.89=q.N.id+\'-bV\';if($(q.J.89))q.J.89=\'\'}if(q.J.4b)q.J.4b=$(q.J.4b);if(!q.J.4b)q.J.bW=14;q.bX=q.N.1v(\'bk-5v\')||\'iX\';q.N.8T=q.J.jO;q.bY=q.f1.1o(q);q.jP=(q.J.2N||1i.2I).1o(q);q.bZ=q.jQ.1o(q);q.9I=q.f2.1o(q);q.f3=q.f4.1o(q);q.jR()},jS:C(e){if(!q.c0||e.qH||e.qI||e.qJ)E;if(1g.aW==e.72)q.f1(e);1d if(1g.aV==e.72)q.f2(e)},f5:C(a,b,c){G d=q.J[a+\'c1\'];G e=q.J[a+\'qK\'];if(\'6J\'==d){G f=19.2b(\'7I\');f.1M=\'61\';f.1k=e;f.2a=\'jT\'+a+\'qL\';if(\'5u\'==a)f.ds=q.bY;q.2G.2j(f);q.2y[a]=f}1d if(\'c2\'==d){G g=19.2b(\'a\');g.dr=\'#\';g.2j(19.6o(e));g.ds=\'5u\'==a?q.bY:q.9I;g.2a=\'jT\'+a+\'qM\';if(c)g.2a+=\' \'+c;q.2G.2j(g);q.2y[a]=g}},f6:C(){G a=(q.J.8a?q.J.f7:q.c3());G b;if(1>=q.J.9J&&!/\\r|\\n/.2C(q.c3())){b=19.2b(\'7I\');b.1M=\'3Q\';G c=q.J.6r||q.J.f8||0;if(0<c)b.6r=c}1d{b=19.2b(\'95\');b.9J=(1>=q.J.9J?q.J.jU:q.J.9J);b.f8=q.J.f8||40}b.29=q.J.88;b.1k=a;b.2a=\'qN\';if(q.J.jV)b.gW=q.9I;q.2y.31=b;if(q.J.8a)q.c4();q.2G.2j(q.2y.31)},jW:C(){G d=q;C c5(a,b){G c=d.J[\'3Q\'+a+\'qO\'];if(!c||b===14)E;d.2G.2j(19.6o(c))};q.2G=$(19.2b(\'8l\'));q.2G.id=q.J.89;q.2G.3W(q.J.jX);q.2G.gX=q.9I;q.f6();if(\'95\'==q.2y.31.1B.1U())q.2G.2j(19.2b(\'br\'));if(q.J.f9)q.J.f9(q,q.2G);c5(\'i7\',q.J.9K||q.J.9L);q.f5(\'ok\',q.9I);c5(\'qP\',q.J.9K&&q.J.9L);q.f5(\'5u\',q.bY,\'qQ\');c5(\'dY\',q.J.9K||q.J.9L)},82:C(){if(q.77)q.N.2V=q.77;q.fa();q.jY()},jZ:C(e){if(q.9M||q.c0)E;q.c0=1c;q.8b(\'k0\');if(q.J.4b)q.J.4b.25();q.N.25();q.jW();q.N.1z.4Z(q.2G,q.N);if(!q.J.8a)q.fb();if(e)1g.2M(e)},k1:C(e){if(q.J.9N)q.N.3W(q.J.9N);if(q.9M)E;q.8b(\'k2\')},c3:C(){E q.N.2V},jQ:C(a){q.8b(\'5C\',a);if(q.77){q.N.2V=q.77;q.77=1e}},f1:C(e){q.f4();if(e)1g.2M(e)},f2:C(e){G a=q.2G;G b=$F(q.2y.31);q.k3();G c=q.J.4v(a,b)||\'\';if(O.2t(c))c=c.8r();c.c6=q.N.id;if(q.J.k4){G d=O.Y({5L:1c},q.J.8c);O.Y(d,{2E:c,2N:q.f3,5C:q.bZ});1b 1x.cX({5R:q.N},q.3g,d)}1d{G d=O.Y({1W:\'3p\'},q.J.8c);O.Y(d,{2E:c,2N:q.f3,5C:q.bZ});1b 1x.4g(q.3g,d)}if(e)1g.2M(e)},fa:C(){q.N.4U(q.J.fc);q.fd();q.c7();q.N.17.7R=q.bX;q.N.2J();if(q.J.4b)q.J.4b.2J();q.9M=14;q.c0=14;q.77=1e;q.8b(\'k5\')},c7:C(e){if(q.J.9N)q.N.4U(q.J.9N);if(q.9M)E;q.8b(\'k6\')},c4:C(){q.2G.3W(q.J.9O);q.2y.31.2x=1c;G c=O.Y({1W:\'3p\'},q.J.8c);O.Y(c,{2E:\'c6=\'+4y(q.N.id),2N:1i.2I,fe:C(a){q.2G.4U(q.J.9O);G b=a.3U;if(q.J.k7)b=b.8p();q.2y.31.1k=b;q.2y.31.2x=14;q.fb()}.1o(q),5C:q.bZ});1b 1x.4g(q.J.8a,c)},fb:C(){G a=q.J.k8;if(a)$(q.2y.31)[\'62\'==a?\'62\':\'55\']()},jM:C(){q.J=O.2B(1x.5B.6R);O.Y(q.J,1x.5B.k9);[q.ka].3T().g4().1n(C(a){O.Y(q.J,a)}.1o(q))},k3:C(){q.9M=1c;q.fd();q.c7();q.kb()},jR:C(){q.ff={};G b;$H(1x.5B.kc).1n(C(a){b=q[a.1k].1o(q);q.ff[a.4f]=b;if(!q.J.bW)q.N.2k(a.4f,b);if(q.J.4b)q.J.4b.2k(a.4f,b)}.1o(q))},fd:C(){if(!q.2G)E;q.2G.4T();q.2G=1e;q.2y={}},kb:C(){q.77=q.N.2V;q.N.2V=q.J.kd;q.N.3W(q.J.fc);q.N.17.7R=q.bX;q.N.2J()},8b:C(a,b){if(\'C\'==2i q.J[a]){q.J[a](q,b)}},jY:C(){$H(q.ff).1n(C(a){if(!q.J.bW)q.N.2Y(a.4f,a.1k);if(q.J.4b)q.J.4b.2Y(a.4f,a.1k)}.1o(q))},f4:C(a){q.fa();q.jP(a,q.N)}});O.Y(1x.5B.1p,{ke:1x.5B.1p.82});1x.fg=1D.1E(1x.5B,{1K:C($4t,b,c,d){q.ka=1x.fg.6R;$4t(b,c,d)},f6:C(){G a=19.2b(\'24\');a.29=q.J.88;a.6r=1;q.2y.31=a;q.8d=q.J.kf||[];if(q.J.kg)q.kh();1d q.fh();q.2G.2j(q.2y.31)},kh:C(){q.2G.3W(q.J.9O);q.fi(q.J.ki);G c=O.Y({1W:\'3p\'},q.J.8c);O.Y(c,{2E:\'c6=\'+4y(q.N.id),2N:1i.2I,fe:C(a){G b=a.3U.3l();if(!/^\\[.*\\]$/.2C(b))2T(\'qR qS an qT kf qU.\');q.8d=7e(b);q.fh()}.1o(q),5C:q.5C});1b 1x.4g(q.J.kg,c)},fi:C(a){q.2y.31.2x=1c;G b=q.2y.31.4z;if(!b){b=19.2b(\'kj\');b.1k=\'\';q.2y.31.2j(b);b.5s=1c}b.1A((a||\'\').4P().8p())},fh:C(){q.7L=q.c3();if(q.J.8a)q.c4();1d q.fj()},c4:C(){q.fi(q.J.f7);G b=O.Y({1W:\'3p\'},q.J.8c);O.Y(b,{2E:\'c6=\'+4y(q.N.id),2N:1i.2I,fe:C(a){q.7L=a.3U.3l();q.fj()}.1o(q),5C:q.5C});1b 1x.4g(q.J.8a,b)},fj:C(){q.2G.4U(q.J.9O);q.8d=q.8d.1R(C(a){E 2===a.V?a:[a,a].3T()});G c=(\'1k\'in q.J)?q.J.1k:q.7L;G d=q.8d.cz(C(a){E a[0]==c}.1o(q));q.2y.31.1A(\'\');G e;q.8d.1n(C(a,b){e=19.2b(\'kj\');e.1k=a[0];e.5s=d?a[0]==c:0==b;e.2j(19.6o(a[1]));q.2y.31.2j(e)}.1o(q));q.2y.31.2x=14;aT.jL(q.2y.31)}});1x.5B.1p.1K.jN=C(c){if(!c)E;C 9P(a,b){if(a in c||b===3j)E;c[a]=b};9P(\'9L\',(c.kk?\'c2\':(c.kl?\'6J\':c.kk==c.kl==14?14:3j)));9P(\'9K\',(c.km?\'c2\':(c.kn?\'6J\':c.km==c.kn==14?14:3j)));9P(\'9Q\',c.qV);9P(\'fk\',c.qW)};O.Y(1x.5B,{6R:{8c:{},jU:3,9L:\'c2\',qX:\'5u\',jO:\'qY 3v qZ\',4b:1e,bW:14,k8:\'55\',jX:\'bV-8l\',89:1e,9Q:\'#iR\',fk:\'#es\',9N:\'\',k4:1c,9O:\'bV-r0\',f7:\'cU...\',9K:\'6J\',r1:\'ok\',88:\'1k\',9J:1,fc:\'bV-r2\',kd:\'r3...\',6r:0,k7:14,jV:14,r4:\'\',r5:\'\',r6:\'\'},k9:{4v:C(a){E 1N.54(a)},2N:C(a,b){1b 18.bi(b,{bj:q.J.9Q,er:1c})},k0:1e,k2:C(a){a.N.17.7R=a.J.9Q;if(a.fl)a.fl.5u()},5C:C(a,b){r7(\'i8 r8 6p ig r9: \'+a.3U.8p())},f9:1e,k5:1e,k6:C(a){a.fl=1b 18.bi(a.N,{bj:a.J.9Q,bl:a.J.fk,bm:a.bX,er:1c})}},kc:{dO:\'jZ\',jt:\'jS\',dR:\'k1\',hO:\'c7\'}});1x.fg.6R={ki:\'cU J...\'};1N.M.ra=1D.1E({1K:C(a,b,c){q.3c=b||0.5;q.N=$(a);q.4v=c;q.4w=1e;q.3H=$F(q.N);1g.2k(q.N,\'rb\',q.ko.3O(q))},ko:C(a){if(q.3H==$F(q.N))E;if(q.4w)af(q.4w);q.4w=6k(q.6l.1o(q),q.3c*3P);q.3H=$F(q.N)},6l:C(){q.4w=1e;q.4v(q.N,$F(q.N))}});if(!c1)G c1={};c1.rc=1D.1E({1K:C(a,b,c){G d=q;if(O.4e(a)){q.2q=a.7i(C(e){E $(e)})}1d{q.2q=[$(a)]}q.2h=$(b);q.J=c||{};q.fm=q.J.fm||\'b6\';q.kp=q.J.kp||1;q.kq=3u(q.J.kq||\'1\');q.32=q.J.32||$R(0,1);q.1k=0;q.1O=q.2q.1R(C(){E 0});q.78=q.J.78?q.J.78.1R(C(s){E $(s)}):14;q.J.c8=$(q.J.c8||1e);q.J.c9=$(q.J.c9||1e);q.fn=q.J.fn||14;q.ca=q.J.ca||q.32.3B;q.fo=q.J.fo||q.32.1V;q.cb=3u(q.J.cb||\'0\');q.cc=3u(q.J.cc||\'0\');q.fp=q.kr()-q.ks();q.cd=q.6d()?(q.2q[0].3D!=0?q.2q[0].3D:q.2q[0].17.1t.1S(/px$/,"")):(q.2q[0].3X!=0?q.2q[0].3X:q.2q[0].17.1u.1S(/px$/,""));q.3x=14;q.4q=14;q.2x=14;if(q.J.2x)q.kt();q.4r=q.J.1O?q.J.1O.a1(1i.K):14;if(q.4r){q.fo=q.4r.7j();q.ca=q.4r.4Q()}q.69=q.bF.3O(q);q.7V=q.7W.3O(q);q.7X=q.1A.3O(q);q.2q.1n(C(h,i){i=d.2q.V-1-i;d.7J(3s((O.4e(d.J.fq)?d.J.fq[i]:d.J.fq)||d.32.1V),i);h.3Y().2k("81",d.69)});q.2h.2k("81",q.69);19.2k("bB",q.7V);19.2k("bC",q.7X);q.ce=1c},ke:C(){G a=q;1g.2Y(q.2h,"81",q.69);1g.2Y(19,"bB",q.7V);1g.2Y(19,"bC",q.7X);q.2q.1n(C(h){1g.2Y(h,"81",a.69)})},kt:C(){q.2x=1c},rd:C(){q.2x=14},ku:C(b){if(q.4r){if(b>=q.4r.4Q())E(q.4r.4Q());if(b<=q.4r.7j())E(q.4r.7j());G c=2w.8y(q.4r[0]-b);G d=q.4r[0];q.4r.1n(C(v){G a=2w.8y(v-b);if(a<=c){d=v;c=a}});E d}if(b>q.32.3B)E q.32.3B;if(b<q.32.1V)E q.32.1V;E b},7J:C(a,b){if(!q.3x){q.8e=b||0;q.8f=q.2q[q.8e];q.fr()}b=b||q.8e||0;if(q.ce&&q.fn){if((b>0)&&(a<q.1O[b-1]))a=q.1O[b-1];if((b<(q.2q.V-1))&&(a>q.1O[b+1]))a=q.1O[b+1]}a=q.ku(a);q.1O[b]=a;q.1k=q.1O[0];q.2q[b].17[q.6d()?\'1r\':\'1w\']=q.8g(a);q.kv();if(!q.4q||!q.4u)q.fs()},re:C(a,b){q.7J(q.1O[b||q.8e||0]+a,b||q.8e||0)},8g:C(a){E 2w.3o(((q.fp-q.cd)/(q.32.3B-q.32.1V))*(a-q.32.1V))+"px"},ft:C(a){E((a/(q.fp-q.cd)*(q.32.3B-q.32.1V))+q.32.1V)},cf:C(a){G v=q.1O.a1(1i.K);a=a||0;E $R(v[a],v[a+1])},ks:C(){E(q.6d()?q.cc:q.cb)},kr:C(){E(q.6d()?(q.2h.3D!=0?q.2h.3D:q.2h.17.1t.1S(/px$/,""))-q.cc:(q.2h.3X!=0?q.2h.3X:q.2h.17.1u.1S(/px$/,""))-q.cb)},6d:C(){E(q.fm==\'7K\')},kv:C(){G a=q;if(q.78)$R(0,q.78.V-1).1n(C(r){a.cg(a.78[r],a.cf(r))});if(q.J.c8)q.cg(q.J.c8,$R(0,q.1O.V>1?q.cf(0).7j():q.1k));if(q.J.c9)q.cg(q.J.c9,$R(q.1O.V>1?q.cf(q.78.V-1).4Q():q.1k,q.ca))},cg:C(a,b){if(q.6d()){a.17.1r=q.8g(b.1V);a.17.1t=q.8g(b.3B-b.1V+q.32.1V)}1d{a.17.1w=q.8g(b.1V);a.17.1u=q.8g(b.3B-b.1V+q.32.1V)}},fr:C(){q.2q.1n(C(h){M.4U(h,\'5s\')});M.3W(q.8f,\'5s\')},bF:C(a){if(1g.dS(a)){if(!q.2x){q.3x=1c;G b=1g.N(a);G c=[1g.6K(a),1g.6L(a)];G d=b;if(d==q.2h){G e=1X.3r(q.2h);q.4u=a;q.7J(q.ft((q.6d()?c[1]-e[1]:c[0]-e[0])-(q.cd/2)));G e=1X.3r(q.8f);q.fu=(c[0]-e[0]);q.fv=(c[1]-e[1])}1d{1Q((q.2q.2r(b)==-1)&&b.1z)b=b.1z;if(q.2q.2r(b)!=-1){q.8f=b;q.8e=q.2q.2r(q.8f);q.fr();G e=1X.3r(q.8f);q.fu=(c[0]-e[0]);q.fv=(c[1]-e[1])}}}1g.2M(a)}},1A:C(a){if(q.3x){if(!q.4q)q.4q=1c;q.9A(a);if(1i.1J.3L)1s.eb(0,0);1g.2M(a)}},9A:C(a){G b=[1g.6K(a),1g.6L(a)];G c=1X.3r(q.2h);b[0]-=q.fu+c[0];b[1]-=q.fv+c[1];q.4u=a;q.7J(q.ft(q.6d()?b[1]:b[0]));if(q.ce&&q.J.kw)q.J.kw(q.1O.V>1?q.1O:q.1k,q)},7W:C(a){if(q.3x&&q.4q){q.9B(a,1c);1g.2M(a)}q.3x=14;q.4q=14},9B:C(a,b){q.3x=14;q.4q=14;q.fs()},fs:C(){if(q.ce&&q.J.5x)q.J.5x(q.1O.V>1?q.1O:q.1k,q);q.4u=1e}});79={4J:{},ch:1c,8v:1b 3d(\'<rf 17="1t:0" id="ci#{2h}3S#{id}" 4Y="#{3g}" 7O="14" kx="1c" 5W="1c"/>\'),aS:C(){79.ch=1c},aR:C(){79.ch=14},ey:C(c){if(!79.ch)E;G d=O.Y({2h:\'9g\',3g:c,1S:14},1f[1]||{});if(d.1S&&q.4J[d.2h]){$R(0,q.4J[d.2h].id).1n(C(a){G b=$(\'ci\'+d.2h+\'3S\'+a);b.ky&&b.ky();b.4T()});q.4J[d.2h]=1e}if(!q.4J[d.2h])q.4J[d.2h]={id:0};1d q.4J[d.2h].id++;d.id=q.4J[d.2h].id;$$(\'28\')[0].3V(1i.1J.3a?1b M(\'rg\',{id:\'ci\'+d.2h+\'3S\'+d.id,4Y:d.3g,7O:1,kx:1c}):79.8v.3b(d))}};if(1i.1J.8i&&4L.5D.2r("rh")>0){if(4L.kz&&$A(4L.kz).5N(C(p){E p.29.2r(\'ri\')!=-1}))79.8v=1b 3d(\'<2U id="ci#{2h}3S#{id}" 1u="0" 1t="0" 1M="rj/rk" fP="#{3g}"/>\');1d 79.ey=C(){}}9d.b3();',62,1695,'||||||||||||||||||||||||||this||||||||||||function||return||var|||options|||Element|element|Object|||||||length|||extend||||||false|||style|Effect|document|node|new|true|else|null|arguments|Event|for|Prototype|push|value|Selector|Methods|each|bind|prototype|results|top|window|height|width|getStyle|left|Ajax|position|parentNode|update|tagName|match|Class|create|setStyle|Sortable|case|break|Browser|initialize|include|type|Form|values|scroll|while|map|replace|String|toLowerCase|start|method|Position|opacity|child||Draggables|concat||select|hide|effects||body|name|className|createElement|isFunction|join|toUpperCase|nth|afterFinishInternal|track|typeof|appendChild|observe|duration|inspect||childNodes|handlers|handles|indexOf|try|isString|index|Array|Math|disabled|_controls|isUndefined|catch|clone|test|last|parameters|pseudos|_form|div|emptyFunction|show|offset|_getEv|stop|onComplete|transport|bottom|xpath|handle|toString|throw|object|innerHTML|Enumerable|table|stopObserving|transform||editor|range||||||||IE|evaluate|delay|Template|from|Base|url|valueL|documentElement|undefined|nodeType|strip|args|slice|round|get|down|cumulativeOffset|parseFloat|scrollTop|parseInt|to|scrollSpeed|active|klass|gsub|inject|end|display|offsetHeight|absolute|scrollLeft|getValue|lastValue|sync|moveY|tree|WebKit|first|split|bindAsEventListener|1000|text|toArray|_|flatten|responseText|insert|addClassName|offsetWidth|makePositioned|100||tokens|getElementsByTagName|overlap|queue|||transition|Move|Droppables|last_active|externalControl|apply|toJSON|isArray|key|Request|none|toElement|continue|ByTag|only|Transitions|Scale|restoreAfterFinish|scrollSensitivity|dragging|allowedValues|script|super|event|callback|timer|_each|encodeURIComponent|firstChild|_attributeTranslations|getDimensions|hasAttribute|checked|matcher|_countedByPrototype|dims|unit|originalValue|tracks|opera|navigator|BrowserFeatures|switch|Hash|stripScripts|max|request|readyState|remove|removeClassName|undoPositioned|makeClipping|undoClipping|src|insertBefore||expression|findElements|attr|serialize|activate|render|Opacity|scaleX|scaleContent|scaleMode|hoverclass|activeDraggable|_lastScrollPointer|isElement|toHTML|RegExp|callee|substring|set|response|nextSibling|right|offsetTop|offsetParent|property|not|unmark|selected|getInlineOpacity|cancel|color|snap|onChange|_marker|entryCount|substr|InPlaceEditor|onFailure|userAgent|toQueryString|isNumber|methodize|defer|toPaddedString|frequency|source|evalScripts|charAt|detect|findAll|pluck|_object|success|container|findElement|names|setOpacity|hidden|offsetLeft|tags|descendant|sibling|submit|focus|fire|parseColor|startOn||finishOn|onHover|eventMouseDown|ghosting|format|iefix|isVertical|Opera|__proto__|shift|keys|wrap|Abstract|setTimeout|onTimerEvent|blank|empty|createTextNode|with|reject|size|filter|Number|dispatchException|decay|removeChild|class|attribute|adjacent|readAttribute|classNames|visibility|relative|_overflow|_returnOffset|_cache|formula|mark|button|pointerX|pointerY|prepare|add|Builder|fontSize|sinoidal|DefaultOptions|beforeSetup|finish|scaleFrom|initialMoveY|targetValue|containment|Draggable|reverteffect|endeffect|zindex|keyCode|constraint|Autocompleter||getEntry|_oldInnerHTML|spans|Sound|addMethods|interpret|string|invoke|eval|nodeValue|evalJSON|array|collect|min|reverse|without|toColorPart|delete|Responders|getHeader|_insertionTranslations|after|write|cleanWhitespace|nextAncestor|getOpacity|clientHeight|static|getOffsetParent|zoom|currentStyle|action|TBODY|tbody|Heading|attrPresence|getElements|Serializers|input|setValue|vertical|_text|_elementDoesNotExistError|state|loop|setup|Parallel|backgroundColor|drops|drags|observers|eventMouseUp|endDrag|eventMouseMove|_lastPointer|quiet|starteffect|mousedown|destroy|tag_name|observer|tag|children|hasFocus|paramName|formId|loadTextURL|triggerCallback|ajaxOptions|_collection|activeHandleIdx|activeHandle|translateToPx|Version|Gecko|ElementExtensions|HTMLElement|form|properties|Date|registerCallback|stripTags|escapeHTML|toQueryParams|camelize|len|capitalize|template|expr|criteria|abs|toObject|responders|post|asynchronous|getStatus|elements|Node|cache|writeAttribute|nextSiblings|previousElementSibling|nextElementSibling|hasClassName|sourceIndex|scrollTo|clientWidth|positionedOffset|absolutize|viewportOffset|default|title|_flag|TD|patterns|following|laterSibling|contains|operators|pseudo|nodeClassName|selector|reset|textarea|EventObserver|change|createEvent|loaded|fireContentLoadedEvent|xcomp|ycomp|Scriptaculous|effect|scope|global|interval|codeForEvent|pos|originalLeft|originalTop|scaleY|originalHeight|originalWidth|getStyles|zIndex|styles|_containers|accept|isParent|deactivate|_timeout|notify|_dragging|delta|draw|finishDrag|sortables|droppables|treeTag|offsetSize|changed|oldElementValue|_boundSubmitHandler|rows|okControl|cancelControl|_saving|hoverClassName|loadingClassName|fallback|highlightColor|attachEvent|XPath|SpecificElementExtensions|ScriptFragment|curry|currentlyExecuting|setInterval|clearInterval|times|lastIndexOf|sortBy|pair|register|dispatch|onCreate|application|onreadystatechange|status|headerJSON|isSameOrigin|port|location|failure|insertion|clearTimeout|visible|before|_getContentFromAnonymousElement|recursivelyCollect|findChildElements|read|ClassNames||descendantOf|cssFloat|defaultView|auto||00001|BODY|relativize|border|padding|_getAttr|tabIndex|TR|tr|SELECT|THEAD|TFOOT|TH|Simulated|_extendedByPrototype|refresh|TEXTAREA|copy|HTML|viewport|token|count|nodeIndex|hash|disable|enable|Field|optionValue|KEY_RETURN|KEY_ESC|which|pointer|getCacheForID|getWrappersForEventName|handler|addEventListener|load|deltaX|deltaY|horizontal|getElementsByClassName|_isStringOrNumber|collectTextNodes|collectTextNodesIgnoreClass|cos|PI|Appear|Queues|Internal|afterSetup|scaleFromCenter|Highlight|startcolor|background|endcolor|restorecolor|elementOffsets|direction|center|moveTransition||scaleTransition|opacityTransition|transforms|CSS_PROPERTIES|styleRules|deepest|affected|updateDrag|keyPress|mouseup|mousemove|_opacity|currentDelta|startDrag|_clone|_originallyAbsolute|_getWindowScroll|scrollInterval|findChildren|indicator|selectEntry|getUpdatedChoices|autocompleteIndex|updateElement|getTokenBounds|tokenBounds|getToken|nextTokenPos|strong|inplaceeditor|externalControlOnly|_originalBackground|_boundCancelHandler|_boundFailureHandler|_editing|Control|link|getText|loadExternalText|addText|editorId|leaveHover|startSpan|endSpan|maximum|alignX|alignY|handleLength|initialized|getRange|setSpan|_enabled|sound_|superclass|instanceof|isHash|||Function|_methodized|execute|prepareReplacement|decodeURIComponent|succ|unfilterJSON|startsWith|toTemplateReplacements|slices|all|any|falses|find|_reverse|isNaN|floor|toQueryPair|activeRequestCount|unregister|encoding|evalJS|_complete|Response|respondToReadyState|onStateChange|javascript|Content|Complete|protocol|domain|getResponseHeader|Loading|statusText|getAllResponseHeaders|Updater|updater|_getElementsByXPath|call|toggle|replaceChild|ancestors|previousSiblings|previousSibling|self|attributes|getAttribute|removeAttribute|setAttribute|getHeight|float|getComputedStyle|cssText|styleFloat|_madePositioned|overflow|cumulativeScrollOffset|setTop|setHeight|htmlFor|alpha|stripAlpha||hasLayout|has|href|onclick|IMG|outerHTML|INPUT|OPTGROUP|CAPTION|COL|COLGROUP|TableSection|getScrollOffsets|unique|assertions|matches|preceding|and|predicate|fragment|indexed|submitted|matchingInputs|TimedObserver|onElementEvent|click|KEY_TAB|relatedTarget|mouseover|isLeftClick|getEventID|_prototypeEventID|getDOMEventName|eventName|findWrapper|After|within|iter|REQUIRED_PROTOTYPE|convertVersionString|aculo|us|requires|OPTION|_children|ATTR_MAP|LI|hasChildNodes|scrollBy|forceRerendering|PAIRS|appear|Fade|limit|idle|instances|currentFrame|afterFinish|frame|||box|originalStyle|oldStyle|keepBackgroundImage|ffffff|_base|scrollOffsets|0px|Morph||play|__parseStyleElement|treeNode|isAffected|eventKeypress|_cacheObserverCallbacks|onStart|onEnd|onDrag|revert|_isScrollChild|originalScrollLeft|originalScrollTop|stopScrolling|lastScrolled|draggables|ul|_tree|parent|baseInitialize|setOptions|minChars|onShow|onHide|stopIndicator|updateChoices|defaultParams|choices|ignoreCase|handleFormCancellation|handleFormSubmission|_boundWrapperHandler|wrapUp|createControl|createEditField|loadingText|cols|onFormCustomization|leaveEditMode|postProcessEditField|savingClassName|removeForm|onSuccess|_listeners|InPlaceCollectionEditor|checkForExternalText|showLoadingText|buildOptionList|highlightEndColor|_effect|axis|restricted|minimum|trackLength|sliderValue|updateStyles|updateFinished|translateToValue|offsetX|offsetY|KHTML|MobileSafari|Safari|JSONFilter|subclasses|valueOf|argumentNames|number|timeout|01|Try|these|escape|PeriodicalExecuter|specialChar|sub|scan|img|extractScripts|data|unescapeHTML|fromCharCode|charCodeAt|dasherize|isJSON|JSON|endsWith|interpolate|amp|pattern|Pattern|exec|eachSlice|clear|compact|uniq|forEach|arrayLength|ObjectRange|exclusive|getTransport|XMLHttpRequest|ActiveXObject|XMLHTTP|Microsoft|contentType|setRequestHeaders|overrideMimeType||xml|2005|requestHeaders|200|Events|force|evalResponse|onException|getStatusText|_getHeaderJSON||responseXML|_getResponseJSON|sanitizeJSON|updateContent|updateComplete|lastText|ELEMENT_NODE|TEXT_NODE|cloneNode|descendants|firstDescendant|immediateDescendants|next|identify|counter|getWidth|compareDocumentPosition|_originalLeft|_originalTop|_originalWidth|_originalHeight|clonePosition|setLeft|setWidth|_getAttrNode|getAttributeNode|multiple|onunload|onblur|onsubmit|TABLE|td|specified|FORM|findDOMClass|FIELDSET|UL|OL|DL|DIR|H1|H2|H3|H4|H5|H6|INS|Mod|DEL|TableCol|TableCell|FRAMESET|IFRAME|client|pageXOffset|pageYOffset|compileMatcher|shouldUseXPath|compileXPathMatcher|root|local|enabled|even|odd|byClassName|getIndices|matchElements|serializeElements|findFirstElement|blur|checkbox|radio|inputSelector|selectOne|selectMany|single|Observer|registerFormCallbacks|KEY_LEFT|KEY_UP|KEY_RIGHT|KEY_DOWN|mouseout|metaKey|target|pageX|pageY|preventDefault|stopPropagation|HTMLEvents|dataavailable|createWrapper|destroyWrapper|destroyCache|removeEventListener|dispatchEvent|eventType|complete|__onDOMContentLoaded|childOf|Insertion|Before|Error|includeScrollOffsets|withinIncludingScrolloffsets|realOffset|page||require||the|z0|NODEMAP|AREA|LEGEND|PARAM|||_attributes|BUTTON|DIV|setContentZoom||linear|flicker|pulse|full|fps|speed|SlideDown|SlideUp|BlindDown|BlindUp|ScopedQueue|getTime|fromToDelta|totalTime|totalFrames|running|beforeFinish|Tween|mode|scaleTo|elementPositioning|fontSizeType|factor|setDimensions|ffff99|backgroundImage|_delta|distance|afterUpdateInternal|parseStyle|transparent|zzzzzz|CSS_LENGTH|addTracks|ids|including|library|findDeepestChild|isContained|onDrop|keypress|addObserver|removeObserver|Count|_draggable|initDrag|originalZ|startScrolling|onDropped|innerWidth|SortableObserver|SERIALIZE_RULE|_findRootElement|dropOnEmpty|onUpdate|onEmptyHover|findTreeElements|dropmarker|_constructIndex|sequence|onBlur||keydown|onKeyPress|iframe|_iefix|fixIEOverlapping|startIndicator|markPrevious|markNext|onObserverEvent|onClick|scrollIntoView|getCurrentEntry|afterUpdateElement|addObservers|getFirstDifferencePos|partialSearch|partialChars|fullSearch|scrollFreeActivate|prepareOptions|dealWithDeprecatedOptions|clickToEditText|_boundComplete|handleAJAXFailure|registerListeners|checkForEscapeOrReturn|editor_|autoRows|submitOnBlur|createForm|formClassName|unregisterListeners|enterEditMode|onEnterEditMode|enterHover|onEnterHover|prepareSubmission|htmlResponse|onLeaveEditMode|onLeaveHover|stripLoadedTextTags|fieldPostCreation|DefaultCallbacks|_extraDefaultOptions|showSaving|Listeners|savingText|dispose|collection|loadCollectionURL|loadCollection|loadingCollectionText|option|cancelLink|cancelButton|okLink|okButton|delayedListener|increment|step|maximumOffset|minimumOffset|setDisabled|getNearestValue|drawSpans|onSlide|autostart|Stop|plugins|AppleWebKit|Apple|Mobile|secure|constructor|RangeError|unknown|boolean|splice|getUTCFullYear|getUTCMonth|getUTCDate|getUTCHours|getUTCMinutes|getUTCSeconds|finally|truncate|underscore|x00|x1f|u00|Eaeflnr|SyntaxError|Badly|formed|parseQuery|grep|inGroupsOf|partition|sort|zip|pop|member|entries|every|some|NodeList|reduce|intersect|isFinite||ceil|unset|merge||Msxml2|www|urlencoded|UTF|_method|Konqueror|open|postBody|send|Requested||With|Accept|html|charset|Connection|close|setRequestHeader|300|Success|Failure|java|ecma|https|Uninitialized|Loaded|Interactive|responseJSON|getAllHeaders|json|PeriodicalUpdater|getElementById|XPathResult|ORDERED_NODE_SNAPSHOT_TYPE|snapshotLength|snapshotItem|ATTRIBUTE_NODE|CDATA_SECTION_NODE|ENTITY_REFERENCE_NODE|ENTITY_NODE|PROCESSING_INSTRUCTION_NODE|COMMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE|DOCUMENT_FRAGMENT_NODE|NOTATION_NODE|ownerDocument|createRange|selectNode|createContextualFragment|siblings|up|previous|anonymous_element_|toggleClassName|block|getElementsBySelector|childElements|fixed|normal|cellpadding|cellPadding|cellspacing|cellSpacing|colSpan||rowSpan|vAlign|dateTime|accessKey|encType|maxLength|readOnly|longDesc|readonly|onload|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onfocus|onkeypress|onkeydown|onkeyup|onreset|onselect|onchange|rv|999999|OptGroup|TextArea|Paragraph|FieldSet|UList|OList|DList|Directory|Quote|Anchor|Image|TableCaption|TableRow|FrameSet|IFrame|inner|starts|translate|mod|dis|abled|selectorType|getInputs|focusFirstElement|present|one|selectedIndex|KEY_BACKSPACE|KEY_DELETE|KEY_HOME|KEY_END|KEY_PAGEUP|KEY_PAGEDOWN|KEY_INSERT|fromElement|isMiddleClick|isRightClick|clientX||clientY|stopped|cancelBubble|returnValue|srcElement|detachEvent|initEvent|createEventObject|ondataavailable|memo|fireEvent|dom|DOMContentLoaded|Toggle|Top|Bottom|deprecated|use|instead|100000|JavaScript|framework|proto|scripta|culous|fieldset|quot|build|dump|ABBR|ACRONYM|ADDRESS|APPLET|BASE|BASEFONT|BDO|BIG|BLOCKQUOTE|BR|CENTER|CITE|CODE|DD|DFN|DT|EM|FONT|FRAME|HEAD|HR|ISINDEX|KBD||LABEL|LINK|MAP|MENU||META|NOFRAMES||NOSCRIPT|OBJECT|PRE||SAMP|SCRIPT|SMALL|SPAN|STRIKE|STRONG|STYLE|SUB|SUP|TITLE|TT|VAR|rgb|ElementDoesNotExistError|message|The|DOM|does|exist|but|required|operate|random|wobble|spring|exp|parallel|tagifyText|span|160|slide|blind|front|Queue|beforeUpdate|afterUpdate|beforeStart|finished|MoveBy|font|content|scrollHeight|scrollWidth|image|ScrollTo|Puff||beforeSetupInternal|SwitchOff|DropOut|Shake|Squish|Grow|Shrink|beforeStartInternal|Pulsate|pulses|Fold|rgba|toFixed|Transform|backgroundPosition|||borderBottomColor|borderBottomStyle|borderBottomWidth||borderLeftColor|borderLeftStyle|borderLeftWidth|borderRightColor|borderRightStyle|borderRightWidth|borderSpacing|borderTopColor|borderTopStyle|borderTopWidth|clip|fontWeight|letterSpacing|lineHeight|marginBottom|marginLeft|marginRight|marginTop|markerOffset|maxHeight|maxWidth|minHeight|minWidth|outlineColor|outlineOffset|outlineWidth|paddingBottom|paddingLeft|paddingRight|paddingTop|textIndent|wordSpacing|morph|visualEffect|highlight|fade|grow|shrink|fold|blindUp|blindDown|slideUp|slideDown|pulsate|shake|puff|squish|switchOff|dropOut|dragdrop|greedy|sqrt|02|innerHeight|Za|item|setSequence|Height|Width|controls|autocomplete|off|progid|DXImageTransform|Alpha|frameborder|scrolling|250|informal|autoSelect|Local|ctrlKey|altKey|shiftKey|Text|_button|_link|editor_field|Controls|Between|editor_cancel|Server|returned|invalid|representation|highlightcolor|highlightendcolor|cancelText|Click|edit|loading|okText|saving|Saving|textAfterControls|textBeforeControls|textBetweenControls|alert|communication|server|DelayedObserver|keyup|Slider|setEnabled|setValueBy|embed|bgsound|Win|QuickTime|audio|mpeg'.split('|'),0,{}));

// see http://prototype.lighthouseapp.com/projects/8887/tickets/51

Droppables.isAffected = function(point, element, drop) {
  return (
    (drop.element!=element) &&
    ((!drop._containers) ||
      this.isContained(element, drop)) &&
    ((!drop.accept) ||
      (Element.classNames(element).detect( 
        function(v) { return drop.accept.include(v); } ) )) &&
    Position.withinIncludingScrolloffsets(drop.element, point[0], point[1]) );
};

Droppables.show = function(point, element) {
  if(!this.drops.length) return;
  var drop, affected = [];
  
  this.drops.each( function(drop) {
    if(Droppables.isAffected(point, element, drop))
      affected.push(drop);
  });
      
  if(affected.length>0)
    drop = Droppables.findDeepestChild(affected);

  if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
  if (drop) {
    Position.withinIncludingScrolloffsets(drop.element, point[0], point[1]);
    if(drop.onHover)
      drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
    
    if (drop != this.last_active) Droppables.activate(drop);
  }
};


// see http://dev.rubyonrails.org/ticket/6411

Element.Methods.cumulativeOffset = function(element) {
  var valueT = 0, valueL = 0;
  do {
    if(Element.getStyle(element, 'position') == 'fixed') {
      var deltaX =  window.pageXOffset
                  || document.documentElement.scrollLeft
                  || document.body.scrollLeft
                  || 0;
      var deltaY =  window.pageYOffset
                  || document.documentElement.scrollTop
                  || document.body.scrollTop
                  || 0;
      valueT += deltaY + element.offsetTop;
      valueL += deltaX + element.offsetLeft;
      element = null;
    } else {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
    }
  } while (element);
  return Element._returnOffset(valueL, valueT);
};

/*  Prototype-UI, version trunk
 *
 *  Prototype-UI is freely distributable under the terms of an MIT-style license.
 *  For details, see the PrototypeUI web site: http://www.prototype-ui.com/
 *
 *--------------------------------------------------------------------------*/

if(typeof Prototype == 'undefined' || !Prototype.Version.match("1.6"))
  throw("Prototype-UI library require Prototype library >= 1.6.0");

if (Prototype.Browser.WebKit) {
  Prototype.Browser.WebKitVersion = parseFloat(navigator.userAgent.match(/AppleWebKit\/([\d\.\+]*)/)[1]);
  Prototype.Browser.Safari2 = (Prototype.Browser.WebKitVersion < 420);
}

if (Prototype.Browser.IE) {
  Prototype.Browser.IEVersion = parseFloat(navigator.appVersion.split(';')[1].strip().split(' ')[1]);
  Prototype.Browser.IE6 =  Prototype.Browser.IEVersion == 6;
  Prototype.Browser.IE7 =  Prototype.Browser.IEVersion == 7;
}

Prototype.falseFunction = function() { return false; };
Prototype.trueFunction  = function() { return true;  };

/*
Namespace: UI

  Introduction:
    Prototype-UI is a library of user interface components based on the Prototype framework.
    Its aim is to easilly improve user experience in web applications.

    It also provides utilities to help developers.

  Guideline:
    - Prototype conventions are followed
    - Everything should be unobstrusive
    - All components are themable with CSS stylesheets, various themes are provided

  Warning:
    Prototype-UI is still under deep development, this release is targeted to developers only.
    All interfaces are subjects to changes, suggestions are welcome.

    DO NOT use it in production for now.

  Authors:
    - SÃ©bastien Gruhier, <http://www.xilinus.com>
    - Samuel Lebeau, <http://gotfresh.info>
*/

var UI = {
  Abstract: { },
  Ajax: { }
};
Object.extend(Class.Methods, {
  extend: Object.extend.methodize(),

  addMethods: Class.Methods.addMethods.wrap(function(proceed, source) {
    // ensure we are not trying to add null or undefined
    if (!source) return this;

    // no callback, vanilla way
    if (!source.hasOwnProperty('methodsAdded'))
      return proceed(source);

    var callback = source.methodsAdded;
    delete source.methodsAdded;
    proceed(source);
    callback.call(source, this);
    source.methodsAdded = callback;

    return this;
  }),

  addMethod: function(name, lambda) {
    var methods = {};
    methods[name] = lambda;
    return this.addMethods(methods);
  },

  method: function(name) {
    return this.prototype[name].valueOf();
  },

  classMethod: function() {
    $A(arguments).flatten().each(function(method) {
      this[method] = (function() {
        return this[method].apply(this, arguments);
      }).bind(this.prototype);
    }, this);
    return this;
  },

  // prevent any call to this method
  undefMethod: function(name) {
    this.prototype[name] = undefined;
    return this;
  },

  // remove the class' own implementation of this method
  removeMethod: function(name) {
    delete this.prototype[name];
    return this;
  },

  aliasMethod: function(newName, name) {
    this.prototype[newName] = this.prototype[name];
    return this;
  },

  aliasMethodChain: function(target, feature) {
    feature = feature.camelcase();

    this.aliasMethod(target+"Without"+feature, target);
    this.aliasMethod(target, target+"With"+feature);

    return this;
  }
});
Object.extend(Number.prototype, {
  // Snap a number to a grid
  snap: function(round) {
    return parseInt(round == 1 ? this : (this / round).floor() * round);
  }
});
/*
Interface: String

*/

Object.extend(String.prototype, {
  camelcase: function() {
    var string = this.dasherize().camelize();
    return string.charAt(0).toUpperCase() + string.slice(1);
  },

  /*
    Method: makeElement
      toElement is unfortunately already taken :/

      Transforms html string into an extended element or null (when failed)

      > '<li><a href="#">some text</a></li>'.makeElement(); // => LI href#
      > '<img src="foo" id="bar" /><img src="bar" id="bar" />'.makeElement(); // => IMG#foo (first one)

    Returns:
      Extended element

  */
  makeElement: function() {
    var wrapper = new Element('div'); wrapper.innerHTML = this;
    return wrapper.down();
  }
});
Object.extend(Array.prototype, {
  empty: function() {
    return !this.length;
  },

  extractOptions: function() {
    return this.last().constructor === Object ? this.pop() : { };
  },

  removeAt: function(index) {
    var object = this[index];
    this.splice(index, 1);
    return object;
  },

  remove: function(object) {
    var index;
    while ((index = this.indexOf(object)) != -1)
      this.removeAt(index);
    return object;
  },

  insert: function(index) {
    var args = $A(arguments);
    args.shift();
    this.splice.apply(this, [ index, 0 ].concat(args));
    return this;
  }
});
Element.addMethods({
  getScrollDimensions: function(element) {
    return {
      width:  element.scrollWidth,
      height: element.scrollHeight
    };
  },

  getScrollOffset: function(element) {
    return Element._returnOffset(element.scrollLeft, element.scrollTop);
  },

  setScrollOffset: function(element, offset) {
    element = $(element);
    if (arguments.length == 3)
      offset = { left: offset, top: arguments[2] };
    element.scrollLeft = offset.left;
    element.scrollTop  = offset.top;
    return element;
  },

  // returns "clean" numerical style (without "px") or null if style can not be resolved
  // or is not numeric
  getNumStyle: function(element, style) {
    var value = parseFloat($(element).getStyle(style));
    return isNaN(value) ? null : value;
  },

  // by Tobie Langel (http://tobielangel.com/2007/5/22/prototype-quick-tip)
  appendText: function(element, text) {
    element = $(element);
    text = String.interpret(text);
    element.appendChild(document.createTextNode(text));
    return element;
  }
});

document.whenReady = function(callback) {
  if (document.loaded)
    callback.call(document);
  else
    document.observe('dom:loaded', callback);
};

Object.extend(document.viewport, {
  // Alias this method for consistency
  getScrollOffset: document.viewport.getScrollOffsets,

  setScrollOffset: function(offset) {
    Element.setScrollOffset(Prototype.Browser.WebKit ? document.body : document.documentElement, offset);
  },

  getScrollDimensions: function() {
    return Element.getScrollDimensions(Prototype.Browser.WebKit ? document.body : document.documentElement);
  }
});
/*
Interface: UI.Options
  Mixin to handle *options* argument in initializer pattern.

  TODO: find a better example than Circle that use an imaginary Point function,
        this example should be used in tests too.

  It assumes class defines a property called *options*, containing
  default options values.

  Instances hold their own *options* property after a first call to <setOptions>.

  Example:
    > var Circle = Class.create(UI.Options, {
    >
    >   // default options
    >   options: {
    >     radius: 1,
    >     origin: Point(0, 0)
    >   },
    >
    >   // common usage is to call setOptions in initializer
    >   initialize: function(options) {
    >     this.setOptions(options);
    >   }
    > });
    >
    > var circle = new Circle({ origin: Point(1, 4) });
    >
    > circle.options
    > // => { radius: 1, origin: Point(1,4) }

  Accessors:
    There are builtin methods to automatically write options accessors. All those
    methods can take either an array of option names nor option names as arguments.
    Notice that those methods won't override an accessor method if already present.

     * <optionsGetter> creates getters
     * <optionsSetter> creates setters
     * <optionsAccessor> creates both getters and setters

    Common usage is to invoke them on a class to create accessors for all instances
    of this class.
    Invoking those methods on a class has the same effect as invoking them on the class prototype.
    See <classMethod> for more details.

    Example:
    > // Creates getter and setter for the "radius" options of circles
    > Circle.optionsAccessor('radius');
    >
    > circle.setRadius(4);
    > // 4
    >
    > circle.getRadius();
    > // => 4 (circle.options.radius)

  Inheritance support:
    Subclasses can refine default *options* values, after a first instance call on setOptions,
    *options* attribute will hold all default options values coming from the inheritance hierarchy.
*/

(function() {
  UI.Options = {
    methodsAdded: function(klass) {
      klass.classMethod($w(' setOptions allOptions optionsGetter optionsSetter optionsAccessor '));
    },

    // Group: Methods

    /*
      Method: setOptions
        Extends object's *options* property with the given object
    */
    setOptions: function(options) {
      if (!this.hasOwnProperty('options'))
        this.options = this.allOptions();

      this.options = Object.extend(this.options, options || {});
    },

    /*
      Method: allOptions
        Computes the complete default options hash made by reverse extending all superclasses
        default options.

        > Widget.prototype.allOptions();
    */
    allOptions: function() {
      var superclass = this.constructor.superclass, ancestor = superclass && superclass.prototype;
      return (ancestor && ancestor.allOptions) ?
          Object.extend(ancestor.allOptions(), this.options) :
          Object.clone(this.options);
    },

    /*
      Method: optionsGetter
        Creates default getters for option names given as arguments.
        With no argument, creates getters for all option names.
    */
    optionsGetter: function() {
      addOptionsAccessors(this, arguments, false);
    },

    /*
      Method: optionsSetter
        Creates default setters for option names given as arguments.
        With no argument, creates setters for all option names.
    */
    optionsSetter: function() {
      addOptionsAccessors(this, arguments, true);
    },

    /*
      Method: optionsAccessor
        Creates default getters/setters for option names given as arguments.
        With no argument, creates accessors for all option names.
    */
    optionsAccessor: function() {
      this.optionsGetter.apply(this, arguments);
      this.optionsSetter.apply(this, arguments);
    }
  };

  // Internal
  function addOptionsAccessors(receiver, names, areSetters) {
    names = $A(names).flatten();

    if (names.empty())
      names = Object.keys(receiver.allOptions());

    names.each(function(name) {
      var accessorName = (areSetters ? 'set' : 'get') + name.camelcase();

      receiver[accessorName] = receiver[accessorName] || (areSetters ?
        // Setter
        function(value) { return this.options[name] = value; } :
        // Getter
        function()      { return this.options[name];         });
    });
  }
})();
/*
  Class: UI.Carousel

  Main class to handle a carousel of elements in a page. A carousel :
    * could be vertical or horizontal
    * works with liquid layout
    * is designed by CSS

  Assumptions:
    * Elements should be from the same size

  Example:
    > ...
    > <div id="horizontal_carousel">
    >   <div class="previous_button"></div>
    >   <div class="container">
    >     <ul>
    >       <li> What ever you like</li>
    >     </ul>
    >   </div>
    >   <div class="next_button"></div>
    > </div>
    > <script>
    > new UI.Carousel("horizontal_carousel");
    > </script>
    > ...
*/
UI.Carousel = Class.create(UI.Options, {
  // Group: Options
  options: {
	// Property: direction
	//   Can be horizontal or vertical, horizontal by default
    direction               : "horizontal",

    // Property: previousButton
    //   Selector of previous button inside carousel element, ".previous_button" by default,
    //   set it to false to ignore previous button
    previousButton          : ".previous_button",

    // Property: nextButton
    //   Selector of next button inside carousel element, ".next_button" by default,
    //   set it to false to ignore next button
    nextButton              : ".next_button",

    // Property: container
    //   Selector of carousel container inside carousel element, ".container" by default,
    container               : ".container",

    // Property: scrollInc
    //   Define the maximum number of elements that gonna scroll each time, auto by default
    scrollInc               : "auto",

    // Property: disabledButtonSuffix
    //   Define the suffix classanme used when a button get disabled, to '_disabled' by default
    //   Previous button classname will be previous_button_disabled
    disabledButtonSuffix : '_disabled',

    // Property: overButtonSuffix
    //   Define the suffix classanme used when a button has a rollover status, '_over' by default
    //   Previous button classname will be previous_button_over
    overButtonSuffix : '_over'
  },

  /*
    Group: Attributes

      Property: element
        DOM element containing the carousel

      Property: id
        DOM id of the carousel's element

      Property: container
        DOM element containing the carousel's elements

      Property: elements
        Array containing the carousel's elements as DOM elements

      Property: previousButton
        DOM id of the previous button

      Property: nextButton
        DOM id of the next button

      Property: posAttribute
        Define if the positions are from left or top

      Property: dimAttribute
        Define if the dimensions are horizontal or vertical

      Property: elementSize
        Size of each element, it's an integer

      Property: nbVisible
        Number of visible elements, it's a float

      Property: animating
        Define whether the carousel is in animation or not
  */

  /*
    Group: Events
      List of events fired by a carousel

      Notice: Carousel custom events are automatically namespaced in "carousel:" (see Prototype custom events).

      Examples:
        This example will observe all carousels
        > document.observe('carousel:scroll:ended', function(event) {
        >   alert("Carousel with id " + event.memo.carousel.id + " has just been scrolled");
        > });

        This example will observe only this carousel
        > new UI.Carousel('horizontal_carousel').observe('scroll:ended', function(event) {
        >   alert("Carousel with id " + event.memo.carousel.id + " has just been scrolled");
        > });

      Property: previousButton:enabled
        Fired when the previous button has just been enabled

      Property: previousButton:disabled
        Fired when the previous button has just been disabled

      Property: nextButton:enabled
        Fired when the next button has just been enabled

      Property: nextButton:disabled
        Fired when the next button has just been disabled

      Property: scroll:started
        Fired when a scroll has just started

      Property: scroll:ended
        Fired when a scroll has been done,
        memo.shift = number of elements scrolled, it's a float

      Property: sizeUpdated
        Fired when the carousel size has just been updated.
        Tips: memo.carousel.currentSize() = the new carousel size
  */

  // Group: Constructor

  /*
    Method: initialize
      Constructor function, should not be called directly

    Parameters:
      element - DOM element
      options - (Hash) list of optional parameters

    Returns:
      this
  */
  initialize: function(element, options) {
    this.setOptions(options);
    this.element = $(element);
    this.id = this.element.id;
    this.container   = this.element.down(this.options.container).firstDescendant();
    this.elements    = this.container.childElements();
    this.previousButton = this.options.previousButton == false ? null : this.element.down(this.options.previousButton);
    this.nextButton = this.options.nextButton == false ? null : this.element.down(this.options.nextButton);

    this.posAttribute = (this.options.direction == "horizontal" ? "left" : "top");
    this.dimAttribute = (this.options.direction == "horizontal" ? "width" : "height");

    this.elementSize = this.computeElementSize();
    this.nbVisible = this.currentSize() / this.elementSize;

    var scrollInc = this.options.scrollInc;
    if (scrollInc == "auto")
      scrollInc = Math.floor(this.nbVisible);
    [ this.previousButton, this.nextButton ].each(function(button) {
      if (!button) return;
      var className = (button == this.nextButton ? "next_button" : "previous_button") + this.options.overButtonSuffix;
      button.clickHandler = this.scroll.bind(this, (button == this.nextButton ? -1 : 1) * scrollInc * this.elementSize);
      button.observe("click", button.clickHandler)
            .observe("mouseover", function() {button.addClassName(className);}.bind(this))
            .observe("mouseout",  function() {button.removeClassName(className);}.bind(this));
    }, this);
    this.updateButtons();
  },

  // Group: Destructor

  /*
    Method: destroy
      Cleans up DOM and memory
  */
  destroy: function($super) {
    [ this.previousButton, this.nextButton ].each(function(button) {
      if (!button) return;
        button.stopObserving("click", button.clickHandler);
    }, this);
	  this.element.remove();
	  this.fire('destroyed');
  },

  // Group: Event handling

  /*
    Method: fire
      Fires a carousel custom event automatically namespaced in "carousel:" (see Prototype custom events).
      The memo object contains a "carousel" property referring to the carousel.

    Example:
      > document.observe('carousel:scroll:ended', function(event) {
      >   alert("Carousel with id " + event.memo.carousel.id + " has just been scrolled");
      > });

    Parameters:
      eventName - an event name
      memo      - a memo object

    Returns:
      fired event
  */
  fire: function(eventName, memo) {
    memo = memo || { };
    memo.carousel = this;
    return this.element.fire('carousel:' + eventName, memo);
  },

  /*
    Method: observe
      Observe a carousel event with a handler function automatically bound to the carousel

    Parameters:
      eventName - an event name
      handler   - a handler function

    Returns:
      this
  */
  observe: function(eventName, handler) {
    this.element.observe('carousel:' + eventName, handler.bind(this));
    return this;
  },

  /*
    Method: stopObserving
      Unregisters a carousel event, it must take the same parameters as this.observe (see Prototype stopObserving).

    Parameters:
      eventName - an event name
      handler   - a handler function

    Returns:
      this
  */
  stopObserving: function(eventName, handler) {
	  this.element.stopObserving('carousel:' + eventName, handler);
	  return this;
  },

  // Group: Actions

  /*
    Method: checkScroll
      Check scroll position to avoid unused space at right or bottom

    Parameters:
      position       - position to check
      updatePosition - should the container position be updated ? true/false

    Returns:
      position
  */
  checkScroll: function(position, updatePosition) {
    if (position > 0)
      position = 0;
    else {
      var limit = this.elements.last().positionedOffset()[this.posAttribute] + this.elementSize;
      var carouselSize = this.currentSize();

      if (position + limit < carouselSize)
        position += carouselSize - (position + limit);
      position = Math.min(position, 0);
    }
    if (updatePosition)
      this.container.style[this.posAttribute] = position + "px";

    return position;
  },

  /*
    Method: scroll
      Scrolls carousel from maximum deltaPixel

    Parameters:
      deltaPixel - a float

    Returns:
      this
  */
  scroll: function(deltaPixel) {
    if (this.animating)
      return this;

    // Compute new position
    var position =  this.currentPosition() + deltaPixel;

    // Check bounds
    position = this.checkScroll(position, false);

    // Compute shift to apply
    deltaPixel = position - this.currentPosition();
    if (deltaPixel != 0) {
      this.animating = true;
      this.fire("scroll:started");

      var that = this;
      // Move effects, our version:
      that.container.morph(that.posAttribute + ": " + position + "px", {
        duration: 0.6,
        afterFinish: function() {
          that.animating = false;
          that.updateButtons()
            .fire("scroll:ended", { shift: deltaPixel / that.currentSize() });
        }
      });
    }
      
    //   this.container.morph("opacity:0.5", {duration: 0.2, afterFinish: function() {
    //     that.container.morph(that.posAttribute + ": " + position + "px", {
    //       duration: 0.4,
    //       delay: 0.2,
    //       afterFinish: function() {
    //         that.container.morph("opacity:1", {
    //           duration: 0.2,
    //           afterFinish: function() {
    //             that.animating = false;
    //             that.updateButtons()
    //               .fire("scroll:ended", { shift: deltaPixel / that.currentSize() });
    //           }
    //         });
    //       }
    //     });
    //   }});
    // }
    return this;
  },

  /*
    Method: scrollTo
      Scrolls carousel, so that element with specified index is the left-most.
      This method is convenient when using carousel in a tabbed navigation.
      Clicking on first tab should scroll first container into view, clicking on a fifth - fifth one, etc.
      Indexing starts with 0.

    Parameters:
      Index of an element which will be a left-most visible in the carousel

    Returns:
      this
  */
  scrollTo: function(index) {
    if (this.animating || index < 0 || index > this.elements.length || index == this.currentIndex() || isNaN(parseInt(index)))
      return this;
    return this.scroll((this.currentIndex() - index) * this.elementSize);
  },

  /*
    Method: updateButtons
      Update buttons status to enabled or disabled
      Them status is defined by classNames and fired as carousel's custom events

    Returns:
      this
  */
  updateButtons: function() {
	  this.updatePreviousButton();
    this.updateNextButton();
    return this;
  },

  updatePreviousButton: function() {
    var position = this.currentPosition();
    var previousClassName = "previous_button" + this.options.disabledButtonSuffix;

    if (this.previousButton.hasClassName(previousClassName) && position != 0) {
      this.previousButton.removeClassName(previousClassName);
      this.fire('previousButton:enabled');
    }
    if (!this.previousButton.hasClassName(previousClassName) && position == 0) {
	    this.previousButton.addClassName(previousClassName);
      this.fire('previousButton:disabled');
    }
  },

  updateNextButton: function() {
    var lastPosition = this.currentLastPosition();
    var size = this.currentSize();
    var nextClassName = "next_button" + this.options.disabledButtonSuffix;

    if (this.nextButton.hasClassName(nextClassName) && lastPosition != size) {
      this.nextButton.removeClassName(nextClassName);
      this.fire('nextButton:enabled');
    }
    if (!this.nextButton.hasClassName(nextClassName) && lastPosition == size) {
	    this.nextButton.addClassName(nextClassName);
      this.fire('nextButton:disabled');
    }
  },

  // Group: Size and Position

  /*
    Method: computeElementSize
      Return elements size in pixel, height or width depends on carousel orientation.

    Returns:
      an integer value
  */
  computeElementSize: function() {
    return this.elements.first().getDimensions()[this.dimAttribute];
  },

  /*
    Method: currentIndex
      Returns current visible index of a carousel.
      For example, a horizontal carousel with image #3 on left will return 3 and with half of image #3 will return 3.5
      Don't forget that the first image have an index 0

    Returns:
      a float value
  */
  currentIndex: function() {
    return - this.currentPosition() / this.elementSize;
  },

  /*
    Method: currentLastPosition
      Returns the current position from the end of the last element. This value is in pixel.

    Returns:
      an integer value, if no images a present it will return 0
  */
  currentLastPosition: function() {
    if (this.container.childElements().empty())
      return 0;
    return this.currentPosition() +
           this.elements.last().positionedOffset()[this.posAttribute] +
           this.elementSize;
  },

  /*
    Method: currentPosition
      Returns the current position in pixel.
      Tips: To get the position in elements use currentIndex()

    Returns:
      an integer value
  */
  currentPosition: function() {
    return this.container.getNumStyle(this.posAttribute);
  },

  /*
    Method: currentSize
      Returns the current size of the carousel in pixel

    Returns:
      Carousel's size in pixel
  */
  currentSize: function() {
    return this.container.parentNode.getDimensions()[this.dimAttribute];
  },

  /*
    Method: updateSize
      Should be called if carousel size has been changed (usually called with a liquid layout)

    Returns:
      this
  */
  updateSize: function() {
    this.nbVisible = this.currentSize() / this.elementSize;
    var scrollInc = this.options.scrollInc;
    if (scrollInc == "auto")
      scrollInc = Math.floor(this.nbVisible);

    [ this.previousButton, this.nextButton ].each(function(button) {
      if (!button) return;
      button.stopObserving("click", button.clickHandler);
      button.clickHandler = this.scroll.bind(this, (button == this.nextButton ? -1 : 1) * scrollInc * this.elementSize);
      button.observe("click", button.clickHandler);
    }, this);

    this.checkScroll(this.currentPosition(), true);
    this.updateButtons().fire('sizeUpdated');
    return this;
  }
});
/*
  Class: UI.Ajax.Carousel

  Gives the AJAX power to carousels. An AJAX carousel :
    * Use AJAX to add new elements on the fly

  Example:
    > new UI.Ajax.Carousel("horizontal_carousel",
    >   {url: "get-more-elements", elementSize: 250});
*/
UI.Ajax.Carousel = Class.create(UI.Carousel, {
  // Group: Options
  //
  //   Notice:
  //     It also include of all carousel's options
  options: {
	// Property: elementSize
	//   Required, it define the size of all elements
    elementSize : -1,

	// Property: url
	//   Required, it define the URL used by AJAX carousel to request new elements details
    url         : null
  },

  /*
    Group: Attributes

      Notice:
        It also include of all carousel's attributes

      Property: elementSize
        Size of each elements, it's an integer

      Property: endIndex
        Index of the last loaded element

      Property: hasMore
        Flag to define if there's still more elements to load

      Property: requestRunning
        Define whether a request is processing or not

      Property: updateHandler
        Callback to update carousel, usually used after request success

      Property: url
        URL used to request additional elements
  */

  /*
    Group: Events
      List of events fired by an AJAX carousel, it also include of all carousel's custom events

      Property: request:started
        Fired when the request has just started

      Property: request:ended
        Fired when the request has succeed
  */

  // Group: Constructor

  /*
    Method: initialize
      Constructor function, should not be called directly

    Parameters:
      element - DOM element
      options - (Hash) list of optional parameters

    Returns:
      this
  */
  initialize: function($super, element, options) {
    if (!options.url)
      throw("url option is required for UI.Ajax.Carousel");
    if (!options.elementSize)
      throw("elementSize option is required for UI.Ajax.Carousel");

    $super(element, options);

    this.endIndex = 0;
    this.hasMore  = true;

    // Cache handlers
    this.updateHandler = this.update.bind(this);
    this.updateAndScrollHandler = function(nbElements, transport, json) {
	    this.update(transport, json);
	    this.scroll(nbElements);
	  }.bind(this);

    // Run first ajax request to fill the carousel
    this.runRequest.bind(this).defer({parameters: {from: 0, to: Math.ceil(this.nbVisible) - 1}, onSuccess: this.updateHandler});
  },

  // Group: Actions

  /*
    Method: runRequest
      Request the new elements details

    Parameters:
      options - (Hash) list of optional parameters

    Returns:
      this
  */
  runRequest: function(options) {
    this.requestRunning = true;
    new Ajax.Request(this.options.url, Object.extend({method: "GET"}, options));
    this.fire("request:started");
    return this;
  },

  /*
    Method: scroll
      Scrolls carousel from maximum deltaPixel

    Parameters:
      deltaPixel - a float

    Returns:
      this
  */
  scroll: function($super, deltaPixel) {
    if (this.animating || this.requestRunning)
      return this;

    var nbElements = (-deltaPixel) / this.elementSize;
    // Check if there is not enough
    if (this.hasMore && nbElements > 0 && this.currentIndex() + this.nbVisible + nbElements - 1 > this.endIndex) {
      var from = this.endIndex + 1;
      var to   = Math.ceil(from + this.nbVisible - 1);
      this.runRequest({parameters: {from: from, to: to}, onSuccess: this.updateAndScrollHandler.curry(deltaPixel).bind(this)});
      return this;
    }
    else
      $super(deltaPixel);
  },

  /*
    Method: update
      Update the carousel

    Parameters:
      transport - XMLHttpRequest object
      json      - JSON object

    Returns:
      this
  */
  update: function(transport, json) {
    this.requestRunning = false;
    this.fire("request:ended");
    if (!json)
      json = transport.responseJSON;
    this.hasMore = json.more;

    this.endIndex = Math.max(this.endIndex, json.to);
    this.elements = this.container.insert({bottom: json.html}).childElements();
    return this.updateButtons();
  },

  // Group: Size and Position

  /*
    Method: computeElementSize
      Return elements size in pixel

    Returns:
      an integer value
  */
  computeElementSize: function() {
    return this.options.elementSize;
  },

  /*
    Method: updateSize
      Should be called if carousel size has been changed (usually called with a liquid layout)

    Returns:
      this
  */
  updateSize: function($super) {
    var nbVisible = this.nbVisible;
    $super();
    // If we have enough space for at least a new element
    if (Math.floor(this.nbVisible) - Math.floor(nbVisible) >= 1 && this.hasMore) {
      if (this.currentIndex() + Math.floor(this.nbVisible) >= this.endIndex) {
        var nbNew = Math.floor(this.currentIndex() + Math.floor(this.nbVisible) - this.endIndex);
        this.runRequest({parameters: {from: this.endIndex + 1, to: this.endIndex + nbNew}, onSuccess: this.updateHandler});
      }
    }
    return this;
  },

  updateNextButton: function($super) {
    var lastPosition = this.currentLastPosition();
    var size = this.currentSize();
    var nextClassName = "next_button" + this.options.disabledButtonSuffix;

    if (this.nextButton.hasClassName(nextClassName) && lastPosition != size) {
      this.nextButton.removeClassName(nextClassName);
      this.fire('nextButton:enabled');
    }
    if (!this.nextButton.hasClassName(nextClassName) && lastPosition == size && !this.hasMore) {
	    this.nextButton.addClassName(nextClassName);
      this.fire('nextButton:disabled');
    }
  }
});


// Google Analytics Fix (doh!)
// see: http://www.startupcto.com/marketing-tech/google-analytics/setvar-and-the-zero-bounce-rate-bug
/*
 * getCookie(): given a cookie name, get its value. Returns null if the cookie can't be found.
 * From http://www.webreference.com/js/column8/functions.html
 *
 */
function getCookie(name) {
  var dc = document.cookie;
  var prefix = name + "=";
  var begin = dc.indexOf("; " + prefix);
  if (begin == -1) {
    begin = dc.indexOf(prefix);
    if (begin != 0) return null;
  } else
    begin += 2;
  var end = document.cookie.indexOf(";", begin);
  if (end == -1)
    end = dc.length;
  return unescape(dc.substring(begin + prefix.length, end));
}
 
/*
 * utmvCookieCheck(): given a value, read the __utmv cookie and see if
 * that value is already set. Return true if so, false otherwise.
 *
 */
function utmvCookieCheck(value) {
	var utmvCookie = getCookie("__utmv"); 
 
	if (utmvCookie == null)
		return false;
 
	// get rid of the Google's domain prefix ID, which appear on all
	// GA cookies
	utmvCookie = utmvCookie.replace(/^\d*\./, '');
 
	return (utmvCookie == value) ? true : false;
}


function addLoadEvent(func) {
  if(window.loaded) {
    func();
    return;
  }
  
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    var oldonload = window.onload;
    window.onload = function() { if (oldonload) { oldonload(); } func(); };
  }
}

addLoadEvent(function() { window.loaded = true; });


// Adds the possibility to fire native events
function fireNativeEvent(element, eventName, memo) {
  if(document.createEventObject) {
    // dispatch for IE
    var evt = document.createEventObject();
    return element.fireEvent('on'+eventName, evt);
  }
  else{
    // dispatch for firefox + others
    var evt = document.createEvent("HTMLEvents");
    evt.initEvent(eventName, true, true);
    return !element.dispatchEvent(evt);
  }
}

Element.addMethods({
  fireNative: fireNativeEvent
});




// holds all uploads:
var fileUploads = {};

// Initialize a new file upload form using SWFUpload.
// +post_url+ is an absolute URL to post to.
// +options+ allows to override these setting:
// - file_size_limit
// - file_types
// - file_types_description
//
function initFileUpload(upload_id, post_url, done_url, form_authenticity_token, options) {
  placeholder_id = upload_id + "_placeholder";
  if( $(placeholder_id) == null ){ return; };
  
  var button_text = options["button_text"] || "Datei auswÃ¤hlenâ€¦";
  
  var swf_upload = new SWFUpload({
    upload_url              : post_url,
    flash_url               : '/flash/swfupload_f10.swf',
    
    button_placeholder_id   : placeholder_id,
    button_width            : '176',
    button_height           : '31',
    button_text_top_padding : '9',
    button_text_left_padding : '30',
    button_text_style       : '.swf_upload_button { font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: bold; color: #999999; }',
    button_text             : '<span class="swf_upload_button">'+button_text+'</span>',
    button_image_url        : '/images/buttons/tools/swf_upload_button.png',
    
    file_queue_limit        : 1,
    post_params             : { "authenticity_token"  : form_authenticity_token },
    custom_settings         : { browse_link_innerhtml : button_text },
    file_size_limit         : options["file_size_limit"]        || "100MB", // most probably get overridden by values defined in appl_upl_helper
    file_types              : options["file_types"]             || "*",
    file_types_description  : options["file_types_description"] || "Alle Dateien ...",
    
    swfupload_loaded_handler      : function(){ $('noflash').hide(); },
    file_dialog_complete_handler  : function(){ swf_upload.startUpload(); },
    upload_start_handler          : function(file){ eval("fileUploads['" + upload_id + "'].uploadFileStart(file)"); },
    upload_complete_handler       : function(file){ eval("fileUploads['" + upload_id + "'].uploadFileComplete(file)"); },
    file_queue_error_handler      : function(){ alert('Datei zu gross! Das Limit ist ' + swf_upload.settings.file_size_limit + '.'); },
    upload_error_handler          : function(file, errorCode, message){ alert('Fehler beim Hochladen. :( '+errorCode+' '+message); },
    
    debug                         : false  
  });
  
  fileUploads[upload_id] = new FileUpload(done_url, upload_id, swf_upload);
  fileUploads[upload_id].init(swf_upload);
};

// Assign all the attributes of this FileUpload object:
//
function FileUpload(done_url, upload_id, swf_upload) {
  this.done_url   = done_url;
  this.upload_id  = upload_id;
  this.swf_upload = swf_upload;
  this.progress   = $(this.upload_id + "_progress");
  this.link       = $(this.upload_id + "_link");
};

// Put the upload-link into link div:
//
FileUpload.prototype.init = function(swf_upload) {
  this.form = $("hidden_field_for_" + this.upload_id).form;
  swf_upload.refreshCookies;
};

// FileUpload.prototype.swfUploadLoaded = function(swf_upload){
//   var browselink = document.createElement("a");
//   browselink.href = "javascript:void(0);";
//   browselink.className = "icon edit";
//   browselink.onclick = function() { swf_upload.selectFile(); return false; };
//   browselink.innerHTML = swf_upload.customSettings["browse_link_innerhtml"];
//   
//   this.link.innerHTML = "";
//   this.link.appendChild(browselink);
// };

// We hide the upload link,
// disable the form, with the first occurence of a hidden field with the upload_id value
// and display a loadingâ€¦ indicator
// while uploading:
//
FileUpload.prototype.uploadFileStart = function(file, position, queuelength) {
  try { this.form.disable(); } catch(e) {}
  
  var progress_indicator = document.createElement("img");
  progress_indicator.src = "/images/layout/working_bar.gif";
  progress_indicator.className = "progress_indicator";
  
  this.link.childElements().each(function(e){ e.setStyle({'width':'0px', 'height':'0px'}); });
  this.link.appendChild(progress_indicator);
  
  //
  return true;
};

// This somehow doesn't work as expectedâ€¦ at least in FF/Mac and Safari.
//
FileUpload.prototype.uploadProgress = function(file, bytesLoaded, bytesTotal) {
  // alert(this.swf_upload.upload_id + "_progress");
  // $(this.swf_upload.upload_id + "_progress").show();
  // progress_indicator.show();
  // var percent = Math.ceil((bytesLoaded / bytesTotal) * 100);
  // this.progress.innerHTML = "" + percent + "%";
};

// When the upload is completed, we send a AJAX request to the done action
// and re-enable the form again.
//
FileUpload.prototype.uploadFileComplete = function(file) {
  new Ajax.Request(
    this.done_url, { method: 'get', asynchronous: true, evalScripts: true, parameters: {upload_id: this.upload_id} }
  );
  
  try { this.form.enable(); } catch(e) {}
};

// We monkey-patch the Ajax.Request.request method to remove eventual domains:
Ajax.Request.prototype.old_request = Ajax.Request.prototype.request;
Ajax.Request.prototype.request = function(url){
  this.old_request(url.gsub(/http:\/\/[^\/]*/,''));
};

// toggle blindUp and blindDown
//
var effect_locked = false;
function toggleBlinds(id){
  if( !effect_locked ) {
    effect_locked = true;
    Effect.toggle( id, 'blind', { afterFinish: function(effect) { effect_locked = false; }, duration:0.5 } );
  }
}

// sorts given 'elements' within a given 'div' by a given 'function'
//
function sort_elements_by_function(div, elements, fn){
  elements = elements.sortBy( fn );                                                               // sort 'em
  elements.each( function(elm){ elm.remove(); });                                                 // zap 'em
  elements.each( function(elm){                                                                   // re-insert 'em
    div.appendChild(elm);
    div.appendChild(document.createTextNode(' '));
  });
  div.className = div.className.replace(/sorted_by_.*/g , '');                                    // remove the sorted_by classname
}

// Wellâ€¦ guess what this is doing :)
//
function sort_elements_by_abc(div, elements){
  fn = function(elm){ return elm.innerHTML; };                                                    // define the sort function
  sort_elements_by_function(div, elements, fn);                                                   // sort
  div.addClassName('sorted_by_abc');                                                              // add the corresponding classname
}

function sort_elements_by_count(div, elements){
  fn = function(elm){ return ( (10000-elm.readAttribute('count')) + elm.innerHTML ); };           // define the sort function
  sort_elements_by_function(div, elements, fn);                                                   // sort
  div.addClassName('sorted_by_count');                                                            // add the corresponding classname
}

INFO_BANNERS = [
  'info_banner_tags.jpg',
  'info_banner_all.jpg',
  'info_banner_band.jpg',
  'info_banner_member.jpg',
  'info_banner_venue.jpg'
];
INFO_BANNER_INDEX = 0;

function rotateInfoBanner() {
  INFO_BANNER_INDEX++;

  $('info_banner').setStyle('opacity:0; background-image:url("/images/main/'+INFO_BANNERS[INFO_BANNER_INDEX%INFO_BANNERS.length]+'")');
  new Effect.Opacity('info_banner', { from: 0.0, to: 1.0, duration: 2.0 });
}

PROMO_BANNER_INDEX = 0;
function rotatePromoBanner() {
  var active  = $$('.promo_banner.shown.active').first();
  var banners = $$('.promo_banner.shown');
  if(active && banners) {
    active.removeClassName('active');
    banners[PROMO_BANNER_INDEX%3].addClassName('active');
    PROMO_BANNER_INDEX++;
  }
}
function initPromoBanners(){
  $A(['front_page_top', 'front_page_middle', 'front_page_bottom']).each(function(position){
    var this_banner = $$('.promo_banner.'+position).sort( randomOrder ).first();
    if (this_banner){
      this_banner.show();
      this_banner.addClassName('shown');
    };
  });
  var top_banner = $$('.promo_banner.front_page_top.shown').first();
  if (top_banner){
    top_banner.addClassName('active');
  }
  if($$('.promo_banner').select(function(el){return el.visible();}).size() == 3){
    $('promo_banners').show();
  }
}

function randomOrder(){
  return(Math.round(Math.random())-0.5);
};

function show_and_hide_or_link(show, hide, link){
  resetSkyscraper();
  if( $(show).style.display == 'none' ){
    new Effect.BlindUp(hide,{duration:0.25});
    new Effect.BlindDown(show,{duration:0.25});
    return false;
  }else{
    location.href = link;
  }
}


/*
 * Cookie handling
 *
 */ 
function writeCookie(name, value) {
  var cookie = name+'='+escape(value);
  if(SESSION_DOMAIN) cookie += '; domain='+SESSION_DOMAIN;
  cookie += '; path=/;';
  
  document.cookie = cookie;
}

function readCookie(name) {
  var result = null;
  
  var cookieArray = document.cookie.split(';');
  cookieArray.each(function(item) {
    if(item.strip().indexOf(name+'=') == 0) {
      result = item.split('=').last();
      result = unescape(result);
    }
  });
  
  return result;
}

function deleteCookie(name) {
  document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain='+SESSION_DOMAIN;
}

// wraps Prototype's toJSON to work in more circumstances
function serialize(obj) {
  return '('+Object.toJSON(obj)+')';
}

function closeAllModals() {
  Control.Modal.close();
  $$('.modal_menu').each(function(menu) { menu.hide(); });
}

if(Prototype.Browser.IE) {
  var console = {
    log: function(str) {
      $('body_wrapper').insert({after:str});
    }
  };
}

function printError(exception) {
  if(typeof(DEVELOPMENT) != 'undefined' && DEVELOPMENT) console.log('ERROR: ' + exception.message);
}

function scrollSkyscraper(){
  // If scrolling happend during the time threshold, start counting again:
  if(typeof(pendingSkyscraperscrolling) != "undefined"){
    window.clearTimeout(pendingSkyscraperscrolling);
  }
  pendingSkyscraperscrolling = window.setTimeout(function(){doTheSkyscraperScrolling();}, 1000);
}

function resetSkyscraper(){
  if($('skyscraper_placeholder')){
    $('skyscraper_placeholder').remove();
  }
  $('skyscraper').relativize();
  if(typeof(initialSkyscraperOffsetLeft) != "undefined"){
    $('skyscraper').setStyle({'left':initialSkyscraperOffsetLeft+'px'});
  };
  initialSkyscraperOffsetTop = false;
}

function doTheSkyscraperScrolling(){
  var skyscraper = $('skyscraper');
  
  if(skyscraper.getStyle('position') != 'absolute'){
    var skyscraperPlaceholder = new Element('div', { 'id': 'skyscraper_placeholder'});
    skyscraper.parentNode.appendChild(skyscraperPlaceholder);
    skyscraperPlaceholder.clonePosition(skyscraper);
    skyscraper.absolutize();
  }
  
  // Set the vars:
  if(typeof(initialSkyscraperOffsetTop) == "undefined" || initialSkyscraperOffsetTop == false){
    initialSkyscraperOffsetTop = skyscraper.positionedOffset()['top'];
  };
  if(typeof(initialSkyscraperOffsetLeft) == "undefined"){
    initialSkyscraperOffsetLeft = skyscraper.positionedOffset()['left'];
  };
  if(typeof(skyscraperHeight) == "undefined"){
    skyscraperHeight = skyscraper.getHeight() + 100;
  };
  if(typeof(bodyHeight) == "undefined"){
    bodyHeight = $('body_wrapper').getHeight();
  };
  var toolsScrollOffset = -$('tools').viewportOffset()['top'];
  
  skyscraperScrollTo = Math.min(bodyHeight-skyscraperHeight, (initialSkyscraperOffsetTop + Math.max(0, (toolsScrollOffset - initialSkyscraperOffsetTop))));
  
  // Do the movin':
  if((typeof(oldskyscraperScrollTo) == "undefined") || (skyscraperScrollTo != oldskyscraperScrollTo)){
    oldskyscraperScrollTo = skyscraperScrollTo;
    new Effect.Move('skyscraper', { x:initialSkyscraperOffsetLeft , y:skyscraperScrollTo , mode:'absolute' });
  }
}

function syncGenresToTags(genreElement, tagsElement) {
  var genres  = genreElement.value.split('/').map(function(item) {return item.toLowerCase().strip();});
  var tags    = tagsElement.value.split(/[,;\/\|]/).map(function(item) { return item ? item.toLowerCase().strip() : null; }).compact();
  var newTags = new Array();
  
  if(genreElement.checked) {
    newTags = genres.concat(tags).compact();
  } else {
    newTags = tags.clone();
    genres.each(function(item) { newTags = newTags.without(item); });
  }
  tagsElement.value = newTags.join(', ');
}

function validateGenreCanBeChecked(el, count) {
  var valid = el.form.select('[name="'+el.name+'"]').select(function(item) {return item.checked;}).size() <= count;
  if(!valid) {
    el.checked = false;
    alert('Du kannst maximal '+count+' Musikstile auswÃ¤hlen');
  }
  return valid;
}

function getFuncName(fn) {
  return fn.arguments.callee;
}
function getStackTrace(func){
    
    if(!func )return "";
    var trace = getFuncName(func);

    var args = "(";
    for(var arg in func.arguments) {
        if(args && args.length && args.length > 1 ) args += ",";
        args += func.arguments.toString();
    }
    trace += args + ")\n";

    return trace + "\n---\n" + getStackTrace(func.caller);

}

function addHiddenFieldTo(form, name, value) {
  var field   = document.createElement('input');
  field.type  = 'hidden';
  field.name  = name;
  field.value = value;
  $(form).appendChild(field);
}

function toS(val) {
  return ''+val;
}

function show_video_url_image_for(type) {
  $$('.video_url').each(function(u){u.hide();});
  $(type+'_url').show();
}

function openVideo(id) {
  $('video_'+id+'_thumb').hide();
  $('video_'+id+'_player').show();
}
function closeVideo(id) {
  $('video_'+id+'_player').hide();
  $('video_'+id+'_thumb').show();
}

function addToReceivers(el, string) {
  if(el.value.blank())
    el.value = string;
  else
    el.value += ', ' + string;
}

function setInvitationField(check) {
  if(check.checked) {
    $(check).up('.contact').down('input[name="emails[]"]').enable();
  } else {
    $(check).up('.contact').down('input[name="emails[]"]').disable();
  }
}

function setInvitationFields(check) {
  if(check.checked) {
    $(check).up('.contacts').select('.contact input[name="emails[]"]').each( function(i) {i.enable();} );
    $(check).up('.contacts').select('.contact input[type="checkbox"]').each( function(i) {i.checked = true;} );
  } else {
    $(check).up('.contacts').select('.contact input[name="emails[]"]').each( function(i) {i.disable();} );
    $(check).up('.contacts').select('.contact input[type="checkbox"]').each( function(i) {i.checked = false;} );
  }
}

function setReceiversFieldMulti(add, content) {
  var el = $('receivers');
  if(add) {
    content.each(function(i) { addToReceiversField(i); });
    el.up('form').select('.contacts input[type="checkbox"]').each( function(i) {i.checked = true;} );
  } else {
    content.each(function(i) { removeFromReceiversField(i); });
    el.up('form').select('.contacts input[type="checkbox"]').each( function(i) {i.checked = false;} );
  }
}

function setReceiversField(add, content) {
  if(add) {
    addToReceiversField(content);
  } else {
    removeFromReceiversField(content);
  }
}

function addToReceiversField(content) {
  var el = $('receivers');
  if(el.value.blank()) {
    el.value = content;
  } else {
    if(!el.value.include(content)) el.value += ', ' + content;
  }
}

function removeFromReceiversField(content) {
  var el = $('receivers');
  el.value = el.value.gsub(content, '').split(',').
    map(function(item){
      return item.strip();
    }).
    reject(function(item){
      return item.blank();
    }).
    join(', ');
}

function infoLoginRequired() {
  alert("Um diese Aktion durchzufÃ¼hren, musst du dich einloggen.");
}

function displayFlash(text, type) {
  var content = new Element('div', {className: type}).update(text);
  $('flash').update(content);
  Effect.Appear('flash');
  Effect.ScrollTo('flash');
}

function trackAccess(accesseeType, accesseeId, kind) {
  Ajax.supressBusyAjax = true;
  
  accessor = readCookie('uid');
  new Ajax.Request('/track', {
    parameters: {
      accessee_type: accesseeType,
      accessee_id:   accesseeId,
      kind:          kind,
      accessor_id:   accessor
    },
    method: 'POST'
  });
  
  Ajax.supressBusyAjax = false;
}


(function(){
var add_message = function(css_class, message, replace) {
    if (!$('flash').visible()) {
        $('flash').show();
    };
    
    var msg_list = $('flash').down('ul.#{cls}, ol.#{cls}'.interpolate({cls: css_class}));
    if (!msg_list) {
        msg_list = new Element('ul', {"class": css_class});
        $('flash').insert(msg_list);
    };
    
    var message_element = new Element('li').update(message);
    if (replace) {
        msg_list.update(message_element);
    } else {
        msg_list.insert(message_element);
    }
    
    msg_list.scrollTo();
};

FlashMessenger = {
    error:    add_message.curry('error'),
    notice:   add_message.curry('notice'),
    warning:  add_message.curry('warning'),
    success:  add_message.curry('success')
};

})();

/**
 * SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com
 *
 * mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/,  http://www.vinterwebb.se/
 *
 * SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilzén and Mammon Media and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */


/* ******************* */
/* Constructor & Init  */
/* ******************* */
var SWFUpload;

if (SWFUpload == undefined) {
  SWFUpload = function (settings) {
    this.initSWFUpload(settings);
  };
}

SWFUpload.prototype.initSWFUpload = function (settings) {
  try {
    this.customSettings = {}; // A container where developers can place their own settings associated with this instance.
    this.settings = settings;
    this.eventQueue = [];
    this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
    this.movieElement = null;


    // Setup global control tracking
    SWFUpload.instances[this.movieName] = this;

    // Load the settings.  Load the Flash movie.
    this.initSettings();
    this.loadFlash();
    this.displayDebugInfo();
  } catch (ex) {
    delete SWFUpload.instances[this.movieName];
    throw ex;
  }
};

/* *************** */
/* Static Members  */
/* *************** */
SWFUpload.instances = {};
SWFUpload.movieCount = 0;
SWFUpload.version = "2.2.0 2009-03-25";
SWFUpload.QUEUE_ERROR = {
  QUEUE_LIMIT_EXCEEDED        : -100,
  FILE_EXCEEDS_SIZE_LIMIT     : -110,
  ZERO_BYTE_FILE              : -120,
  INVALID_FILETYPE            : -130
};
SWFUpload.UPLOAD_ERROR = {
  HTTP_ERROR                  : -200,
  MISSING_UPLOAD_URL          : -210,
  IO_ERROR                    : -220,
  SECURITY_ERROR              : -230,
  UPLOAD_LIMIT_EXCEEDED       : -240,
  UPLOAD_FAILED               : -250,
  SPECIFIED_FILE_ID_NOT_FOUND : -260,
  FILE_VALIDATION_FAILED      : -270,
  FILE_CANCELLED              : -280,
  UPLOAD_STOPPED              : -290
};
SWFUpload.FILE_STATUS = {
  QUEUED        : -1,
  IN_PROGRESS   : -2,
  ERROR         : -3,
  COMPLETE      : -4,
  CANCELLED     : -5
};
SWFUpload.BUTTON_ACTION = {
  SELECT_FILE  : -100,
  SELECT_FILES : -110,
  START_UPLOAD : -120
};
SWFUpload.CURSOR = {
  ARROW : -1,
  HAND  : -2
};
SWFUpload.WINDOW_MODE = {
  WINDOW      : "window",
  TRANSPARENT : "transparent",
  OPAQUE      : "opaque"
};

// Private: takes a URL, determines if it is relative and converts to an absolute URL
// using the current site. Only processes the URL if it can, otherwise returns the URL untouched
SWFUpload.completeURL = function(url) {
  if (typeof(url) !== "string" || url.match(/^https?:\/\//i) || url.match(/^\//)) {
    return url;
  }
  
  var currentURL = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port : "");
  
  var indexSlash = window.location.pathname.lastIndexOf("/");
  if (indexSlash <= 0) {
    path = "/";
  } else {
    path = window.location.pathname.substr(0, indexSlash) + "/";
  }
  
  return /*currentURL +*/ path + url;
  
};


/* ******************** */
/* Instance Members  */
/* ******************** */

// Private: initSettings ensures that all the
// settings are set, getting a default value if one was not assigned.
SWFUpload.prototype.initSettings = function () {
  this.ensureDefault = function (settingName, defaultValue) {
    this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
  };
  
  // Upload backend settings
  this.ensureDefault("upload_url", "");
  this.ensureDefault("preserve_relative_urls", false);
  this.ensureDefault("file_post_name", "Filedata");
  this.ensureDefault("post_params", {});
  this.ensureDefault("use_query_string", false);
  this.ensureDefault("requeue_on_error", false);
  this.ensureDefault("http_success", []);
  this.ensureDefault("assume_success_timeout", 0);
  
  // File Settings
  this.ensureDefault("file_types", "*.*");
  this.ensureDefault("file_types_description", "All Files");
  this.ensureDefault("file_size_limit", 0); // Default zero means "unlimited"
  this.ensureDefault("file_upload_limit", 0);
  this.ensureDefault("file_queue_limit", 0);

  // Flash Settings
  this.ensureDefault("flash_url", "swfupload.swf");
  this.ensureDefault("prevent_swf_caching", true);
  
  // Button Settings
  this.ensureDefault("button_image_url", "");
  this.ensureDefault("button_width", 1);
  this.ensureDefault("button_height", 1);
  this.ensureDefault("button_text", "");
  this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;");
  this.ensureDefault("button_text_top_padding", 0);
  this.ensureDefault("button_text_left_padding", 0);
  this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES);
  this.ensureDefault("button_disabled", false);
  this.ensureDefault("button_placeholder_id", "");
  this.ensureDefault("button_placeholder", null);
  this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW);
  this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW);
  
  // Debug Settings
  this.ensureDefault("debug", true);
  this.settings.debug_enabled = this.settings.debug;  // Here to maintain v2 API
  
  // Event Handlers
  this.settings.return_upload_start_handler = this.returnUploadStart;
  this.ensureDefault("swfupload_loaded_handler", null);
  this.ensureDefault("file_dialog_start_handler", null);
  this.ensureDefault("file_queued_handler", null);
  this.ensureDefault("file_queue_error_handler", null);
  this.ensureDefault("file_dialog_complete_handler", null);
  
  this.ensureDefault("upload_start_handler", null);
  this.ensureDefault("upload_progress_handler", null);
  this.ensureDefault("upload_error_handler", null);
  this.ensureDefault("upload_success_handler", null);
  this.ensureDefault("upload_complete_handler", null);
  
  this.ensureDefault("debug_handler", this.debugMessage);

  this.ensureDefault("custom_settings", {});

  // Other settings
  this.customSettings = this.settings.custom_settings;
  
  // Update the flash url if needed
  if (!!this.settings.prevent_swf_caching) {
    this.settings.flash_url = this.settings.flash_url + (this.settings.flash_url.indexOf("?") < 0 ? "?" : "&") + "preventswfcaching=" + new Date().getTime();
  }
  
  if (!this.settings.preserve_relative_urls) {
    //this.settings.flash_url = SWFUpload.completeURL(this.settings.flash_url); // Don't need to do this one since flash doesn't look at it
    this.settings.upload_url = SWFUpload.completeURL(this.settings.upload_url);
    this.settings.button_image_url = SWFUpload.completeURL(this.settings.button_image_url);
  }
  
  delete this.ensureDefault;
};

// Private: loadFlash replaces the button_placeholder element with the flash movie.
SWFUpload.prototype.loadFlash = function () {
  var targetElement, tempParent;
  // Make sure an element with the ID we are going to use doesn't already exist
  if (document.getElementById(this.movieName) !== null) {
    throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
  }

  // Get the element where we will be placing the flash movie
  targetElement = document.getElementById(this.settings.button_placeholder_id) || this.settings.button_placeholder;

  if (targetElement == undefined) {
    throw "Could not find the placeholder element: " + this.settings.button_placeholder_id;
  }

  // Append the container and load the flash
  tempParent = document.createElement("div");
  tempParent.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
  targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement);

  // Fix IE Flash/Form bug
  if (window[this.movieName] == undefined) {
    window[this.movieName] = this.getMovieElement();
  }
  
};

// Private: getFlashHTML generates the object tag needed to embed the flash in to the document
SWFUpload.prototype.getFlashHTML = function () {
  // Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay
  return ['<object id="', this.movieName, '" type="application/x-shockwave-flash" data="', this.settings.flash_url, '" width="', this.settings.button_width, '" height="', this.settings.button_height, '" class="swfupload">',
        '<param name="wmode" value="', this.settings.button_window_mode, '" />',
        '<param name="movie" value="', this.settings.flash_url, '" />',
        '<param name="quality" value="high" />',
        '<param name="menu" value="false" />',
        '<param name="allowScriptAccess" value="always" />',
        '<param name="flashvars" value="' + this.getFlashVars() + '" />',
        '</object>'].join("");
};

// Private: getFlashVars builds the parameter string that will be passed
// to flash in the flashvars param.
SWFUpload.prototype.getFlashVars = function () {
  // Build a string from the post param object
  var paramString = this.buildParamString();
  var httpSuccessString = this.settings.http_success.join(",");
  
  // Build the parameter string
  return ["movieName=", encodeURIComponent(this.movieName),
      "&amp;uploadURL=", encodeURIComponent(this.settings.upload_url),
      "&amp;useQueryString=", encodeURIComponent(this.settings.use_query_string),
      "&amp;requeueOnError=", encodeURIComponent(this.settings.requeue_on_error),
      "&amp;httpSuccess=", encodeURIComponent(httpSuccessString),
      "&amp;assumeSuccessTimeout=", encodeURIComponent(this.settings.assume_success_timeout),
      "&amp;params=", encodeURIComponent(paramString),
      "&amp;filePostName=", encodeURIComponent(this.settings.file_post_name),
      "&amp;fileTypes=", encodeURIComponent(this.settings.file_types),
      "&amp;fileTypesDescription=", encodeURIComponent(this.settings.file_types_description),
      "&amp;fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit),
      "&amp;fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit),
      "&amp;fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit),
      "&amp;debugEnabled=", encodeURIComponent(this.settings.debug_enabled),
      "&amp;buttonImageURL=", encodeURIComponent(this.settings.button_image_url),
      "&amp;buttonWidth=", encodeURIComponent(this.settings.button_width),
      "&amp;buttonHeight=", encodeURIComponent(this.settings.button_height),
      "&amp;buttonText=", encodeURIComponent(this.settings.button_text),
      "&amp;buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding),
      "&amp;buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding),
      "&amp;buttonTextStyle=", encodeURIComponent(this.settings.button_text_style),
      "&amp;buttonAction=", encodeURIComponent(this.settings.button_action),
      "&amp;buttonDisabled=", encodeURIComponent(this.settings.button_disabled),
      "&amp;buttonCursor=", encodeURIComponent(this.settings.button_cursor)
    ].join("");
};

// Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload
// The element is cached after the first lookup
SWFUpload.prototype.getMovieElement = function () {
  if (this.movieElement == undefined) {
    this.movieElement = document.getElementById(this.movieName);
  }

  if (this.movieElement === null) {
    throw "Could not find Flash element";
  }
  
  return this.movieElement;
};

// Private: buildParamString takes the name/value pairs in the post_params setting object
// and joins them up in to a string formatted "name=value&amp;name=value"
SWFUpload.prototype.buildParamString = function () {
  var postParams = this.settings.post_params; 
  var paramStringPairs = [];

  if (typeof(postParams) === "object") {
    for (var name in postParams) {
      if (postParams.hasOwnProperty(name)) {
        paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString()));
      }
    }
  }

  return paramStringPairs.join("&amp;");
};

// Public: Used to remove a SWFUpload instance from the page. This method strives to remove
// all references to the SWF, and other objects so memory is properly freed.
// Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state.
// Credits: Major improvements provided by steffen
SWFUpload.prototype.destroy = function () {
  try {
    // Make sure Flash is done before we try to remove it
    this.cancelUpload(null, false);
    

    // Remove the SWFUpload DOM nodes
    var movieElement = null;
    movieElement = this.getMovieElement();
    
    if (movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
      // Loop through all the movie's properties and remove all function references (DOM/JS IE 6/7 memory leak workaround)
      for (var i in movieElement) {
        try {
          if (typeof(movieElement[i]) === "function") {
            movieElement[i] = null;
          }
        } catch (ex1) {}
      }

      // Remove the Movie Element from the page
      try {
        movieElement.parentNode.removeChild(movieElement);
      } catch (ex) {}
    }
    
    // Remove IE form fix reference
    window[this.movieName] = null;

    // Destroy other references
    SWFUpload.instances[this.movieName] = null;
    delete SWFUpload.instances[this.movieName];

    this.movieElement = null;
    this.settings = null;
    this.customSettings = null;
    this.eventQueue = null;
    this.movieName = null;
    
    
    return true;
  } catch (ex2) {
    return false;
  }
};


// Public: displayDebugInfo prints out settings and configuration
// information about this SWFUpload instance.
// This function (and any references to it) can be deleted when placing
// SWFUpload in production.
SWFUpload.prototype.displayDebugInfo = function () {
  this.debug(
    [
      "---SWFUpload Instance Info---\n",
      "Version: ", SWFUpload.version, "\n",
      "Movie Name: ", this.movieName, "\n",
      "Settings:\n",
      "\t", "upload_url:               ", this.settings.upload_url, "\n",
      "\t", "flash_url:                ", this.settings.flash_url, "\n",
      "\t", "use_query_string:         ", this.settings.use_query_string.toString(), "\n",
      "\t", "requeue_on_error:         ", this.settings.requeue_on_error.toString(), "\n",
      "\t", "http_success:             ", this.settings.http_success.join(", "), "\n",
      "\t", "assume_success_timeout:   ", this.settings.assume_success_timeout, "\n",
      "\t", "file_post_name:           ", this.settings.file_post_name, "\n",
      "\t", "post_params:              ", this.settings.post_params.toString(), "\n",
      "\t", "file_types:               ", this.settings.file_types, "\n",
      "\t", "file_types_description:   ", this.settings.file_types_description, "\n",
      "\t", "file_size_limit:          ", this.settings.file_size_limit, "\n",
      "\t", "file_upload_limit:        ", this.settings.file_upload_limit, "\n",
      "\t", "file_queue_limit:         ", this.settings.file_queue_limit, "\n",
      "\t", "debug:                    ", this.settings.debug.toString(), "\n",

      "\t", "prevent_swf_caching:      ", this.settings.prevent_swf_caching.toString(), "\n",

      "\t", "button_placeholder_id:    ", this.settings.button_placeholder_id.toString(), "\n",
      "\t", "button_placeholder:       ", (this.settings.button_placeholder ? "Set" : "Not Set"), "\n",
      "\t", "button_image_url:         ", this.settings.button_image_url.toString(), "\n",
      "\t", "button_width:             ", this.settings.button_width.toString(), "\n",
      "\t", "button_height:            ", this.settings.button_height.toString(), "\n",
      "\t", "button_text:              ", this.settings.button_text.toString(), "\n",
      "\t", "button_text_style:        ", this.settings.button_text_style.toString(), "\n",
      "\t", "button_text_top_padding:  ", this.settings.button_text_top_padding.toString(), "\n",
      "\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n",
      "\t", "button_action:            ", this.settings.button_action.toString(), "\n",
      "\t", "button_disabled:          ", this.settings.button_disabled.toString(), "\n",

      "\t", "custom_settings:          ", this.settings.custom_settings.toString(), "\n",
      "Event Handlers:\n",
      "\t", "swfupload_loaded_handler assigned:  ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n",
      "\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n",
      "\t", "file_queued_handler assigned:       ", (typeof this.settings.file_queued_handler === "function").toString(), "\n",
      "\t", "file_queue_error_handler assigned:  ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n",
      "\t", "upload_start_handler assigned:      ", (typeof this.settings.upload_start_handler === "function").toString(), "\n",
      "\t", "upload_progress_handler assigned:   ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n",
      "\t", "upload_error_handler assigned:      ", (typeof this.settings.upload_error_handler === "function").toString(), "\n",
      "\t", "upload_success_handler assigned:    ", (typeof this.settings.upload_success_handler === "function").toString(), "\n",
      "\t", "upload_complete_handler assigned:   ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n",
      "\t", "debug_handler assigned:             ", (typeof this.settings.debug_handler === "function").toString(), "\n"
    ].join("")
  );
};

/* Note: addSetting and getSetting are no longer used by SWFUpload but are included
  the maintain v2 API compatibility
*/
// Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used.
SWFUpload.prototype.addSetting = function (name, value, default_value) {
    if (value == undefined) {
        return (this.settings[name] = default_value);
    } else {
        return (this.settings[name] = value);
  }
};

// Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found.
SWFUpload.prototype.getSetting = function (name) {
    if (this.settings[name] != undefined) {
        return this.settings[name];
  }

    return "";
};


// Private: callFlash handles function calls made to the Flash element.
// Calls are made with a setTimeout for some functions to work around
// bugs in the ExternalInterface library.
SWFUpload.prototype.callFlash = function (functionName, argumentArray) {
  argumentArray = argumentArray || [];
  
  var movieElement = this.getMovieElement();
  var returnValue, returnString;

  // Flash's method if calling ExternalInterface methods (code adapted from MooTools).
  try {
    returnString = movieElement.CallFunction('<invoke name="' + functionName + '" returntype="javascript">' + __flash__argumentsToXML(argumentArray, 0) + '</invoke>');
    returnValue = eval(returnString);
  } catch (ex) {
    throw "Call to " + functionName + " failed";
  }
  
  // Unescape file post param values
  if (returnValue != undefined && typeof returnValue.post === "object") {
    returnValue = this.unescapeFilePostParams(returnValue);
  }

  return returnValue;
};

/* *****************************
  -- Flash control methods --
  Your UI should use these
  to operate SWFUpload
   ***************************** */

// WARNING: this function does not work in Flash Player 10
// Public: selectFile causes a File Selection Dialog window to appear.  This
// dialog only allows 1 file to be selected.
SWFUpload.prototype.selectFile = function () {
  this.callFlash("SelectFile");
};

// WARNING: this function does not work in Flash Player 10
// Public: selectFiles causes a File Selection Dialog window to appear/ This
// dialog allows the user to select any number of files
// Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names.
// If the selection name length is too long the dialog will fail in an unpredictable manner.  There is no work-around
// for this bug.
SWFUpload.prototype.selectFiles = function () {
  this.callFlash("SelectFiles");
};


// Public: startUpload starts uploading the first file in the queue unless
// the optional parameter 'fileID' specifies the ID 
SWFUpload.prototype.startUpload = function (fileID) {
  this.callFlash("StartUpload", [fileID]);
};

// Public: cancelUpload cancels any queued file.  The fileID parameter may be the file ID or index.
// If you do not specify a fileID the current uploading file or first file in the queue is cancelled.
// If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter.
SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) {
  if (triggerErrorEvent !== false) {
    triggerErrorEvent = true;
  }
  this.callFlash("CancelUpload", [fileID, triggerErrorEvent]);
};

// Public: stopUpload stops the current upload and requeues the file at the beginning of the queue.
// If nothing is currently uploading then nothing happens.
SWFUpload.prototype.stopUpload = function () {
  this.callFlash("StopUpload");
};

/* ************************
 * Settings methods
 *   These methods change the SWFUpload settings.
 *   SWFUpload settings should not be changed directly on the settings object
 *   since many of the settings need to be passed to Flash in order to take
 *   effect.
 * *********************** */

// Public: getStats gets the file statistics object.
SWFUpload.prototype.getStats = function () {
  return this.callFlash("GetStats");
};

// Public: setStats changes the SWFUpload statistics.  You shouldn't need to 
// change the statistics but you can.  Changing the statistics does not
// affect SWFUpload accept for the successful_uploads count which is used
// by the upload_limit setting to determine how many files the user may upload.
SWFUpload.prototype.setStats = function (statsObject) {
  this.callFlash("SetStats", [statsObject]);
};

// Public: getFile retrieves a File object by ID or Index.  If the file is
// not found then 'null' is returned.
SWFUpload.prototype.getFile = function (fileID) {
  if (typeof(fileID) === "number") {
    return this.callFlash("GetFileByIndex", [fileID]);
  } else {
    return this.callFlash("GetFile", [fileID]);
  }
};

// Public: addFileParam sets a name/value pair that will be posted with the
// file specified by the Files ID.  If the name already exists then the
// exiting value will be overwritten.
SWFUpload.prototype.addFileParam = function (fileID, name, value) {
  return this.callFlash("AddFileParam", [fileID, name, value]);
};

// Public: removeFileParam removes a previously set (by addFileParam) name/value
// pair from the specified file.
SWFUpload.prototype.removeFileParam = function (fileID, name) {
  this.callFlash("RemoveFileParam", [fileID, name]);
};

// Public: setUploadUrl changes the upload_url setting.
SWFUpload.prototype.setUploadURL = function (url) {
  this.settings.upload_url = url.toString();
  this.callFlash("SetUploadURL", [url]);
};

// Public: setPostParams changes the post_params setting
SWFUpload.prototype.setPostParams = function (paramsObject) {
  this.settings.post_params = paramsObject;
  this.callFlash("SetPostParams", [paramsObject]);
};

// Public: addPostParam adds post name/value pair.  Each name can have only one value.
SWFUpload.prototype.addPostParam = function (name, value) {
  this.settings.post_params[name] = value;
  this.callFlash("SetPostParams", [this.settings.post_params]);
};

// Public: removePostParam deletes post name/value pair.
SWFUpload.prototype.removePostParam = function (name) {
  delete this.settings.post_params[name];
  this.callFlash("SetPostParams", [this.settings.post_params]);
};

// Public: setFileTypes changes the file_types setting and the file_types_description setting
SWFUpload.prototype.setFileTypes = function (types, description) {
  this.settings.file_types = types;
  this.settings.file_types_description = description;
  this.callFlash("SetFileTypes", [types, description]);
};

// Public: setFileSizeLimit changes the file_size_limit setting
SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) {
  this.settings.file_size_limit = fileSizeLimit;
  this.callFlash("SetFileSizeLimit", [fileSizeLimit]);
};

// Public: setFileUploadLimit changes the file_upload_limit setting
SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) {
  this.settings.file_upload_limit = fileUploadLimit;
  this.callFlash("SetFileUploadLimit", [fileUploadLimit]);
};

// Public: setFileQueueLimit changes the file_queue_limit setting
SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) {
  this.settings.file_queue_limit = fileQueueLimit;
  this.callFlash("SetFileQueueLimit", [fileQueueLimit]);
};

// Public: setFilePostName changes the file_post_name setting
SWFUpload.prototype.setFilePostName = function (filePostName) {
  this.settings.file_post_name = filePostName;
  this.callFlash("SetFilePostName", [filePostName]);
};

// Public: setUseQueryString changes the use_query_string setting
SWFUpload.prototype.setUseQueryString = function (useQueryString) {
  this.settings.use_query_string = useQueryString;
  this.callFlash("SetUseQueryString", [useQueryString]);
};

// Public: setRequeueOnError changes the requeue_on_error setting
SWFUpload.prototype.setRequeueOnError = function (requeueOnError) {
  this.settings.requeue_on_error = requeueOnError;
  this.callFlash("SetRequeueOnError", [requeueOnError]);
};

// Public: setHTTPSuccess changes the http_success setting
SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) {
  if (typeof http_status_codes === "string") {
    http_status_codes = http_status_codes.replace(" ", "").split(",");
  }
  
  this.settings.http_success = http_status_codes;
  this.callFlash("SetHTTPSuccess", [http_status_codes]);
};

// Public: setHTTPSuccess changes the http_success setting
SWFUpload.prototype.setAssumeSuccessTimeout = function (timeout_seconds) {
  this.settings.assume_success_timeout = timeout_seconds;
  this.callFlash("SetAssumeSuccessTimeout", [timeout_seconds]);
};

// Public: setDebugEnabled changes the debug_enabled setting
SWFUpload.prototype.setDebugEnabled = function (debugEnabled) {
  this.settings.debug_enabled = debugEnabled;
  this.callFlash("SetDebugEnabled", [debugEnabled]);
};

// Public: setButtonImageURL loads a button image sprite
SWFUpload.prototype.setButtonImageURL = function (buttonImageURL) {
  if (buttonImageURL == undefined) {
    buttonImageURL = "";
  }
  
  this.settings.button_image_url = buttonImageURL;
  this.callFlash("SetButtonImageURL", [buttonImageURL]);
};

// Public: setButtonDimensions resizes the Flash Movie and button
SWFUpload.prototype.setButtonDimensions = function (width, height) {
  this.settings.button_width = width;
  this.settings.button_height = height;
  
  var movie = this.getMovieElement();
  if (movie != undefined) {
    movie.style.width = width + "px";
    movie.style.height = height + "px";
  }
  
  this.callFlash("SetButtonDimensions", [width, height]);
};
// Public: setButtonText Changes the text overlaid on the button
SWFUpload.prototype.setButtonText = function (html) {
  this.settings.button_text = html;
  this.callFlash("SetButtonText", [html]);
};
// Public: setButtonTextPadding changes the top and left padding of the text overlay
SWFUpload.prototype.setButtonTextPadding = function (left, top) {
  this.settings.button_text_top_padding = top;
  this.settings.button_text_left_padding = left;
  this.callFlash("SetButtonTextPadding", [left, top]);
};

// Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button
SWFUpload.prototype.setButtonTextStyle = function (css) {
  this.settings.button_text_style = css;
  this.callFlash("SetButtonTextStyle", [css]);
};
// Public: setButtonDisabled disables/enables the button
SWFUpload.prototype.setButtonDisabled = function (isDisabled) {
  this.settings.button_disabled = isDisabled;
  this.callFlash("SetButtonDisabled", [isDisabled]);
};
// Public: setButtonAction sets the action that occurs when the button is clicked
SWFUpload.prototype.setButtonAction = function (buttonAction) {
  this.settings.button_action = buttonAction;
  this.callFlash("SetButtonAction", [buttonAction]);
};

// Public: setButtonCursor changes the mouse cursor displayed when hovering over the button
SWFUpload.prototype.setButtonCursor = function (cursor) {
  this.settings.button_cursor = cursor;
  this.callFlash("SetButtonCursor", [cursor]);
};

/* *******************************
  Flash Event Interfaces
  These functions are used by Flash to trigger the various
  events.
  
  All these functions a Private.
  
  Because the ExternalInterface library is buggy the event calls
  are added to a queue and the queue then executed by a setTimeout.
  This ensures that events are executed in a determinate order and that
  the ExternalInterface bugs are avoided.
******************************* */

SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) {
  // Warning: Don't call this.debug inside here or you'll create an infinite loop
  
  if (argumentArray == undefined) {
    argumentArray = [];
  } else if (!(argumentArray instanceof Array)) {
    argumentArray = [argumentArray];
  }
  
  var self = this;
  if (typeof this.settings[handlerName] === "function") {
    // Queue the event
    this.eventQueue.push(function () {
      this.settings[handlerName].apply(this, argumentArray);
    });
    
    // Execute the next queued event
    setTimeout(function () {
      self.executeNextEvent();
    }, 0);
    
  } else if (this.settings[handlerName] !== null) {
    throw "Event handler " + handlerName + " is unknown or is not a function";
  }
};

// Private: Causes the next event in the queue to be executed.  Since events are queued using a setTimeout
// we must queue them in order to garentee that they are executed in order.
SWFUpload.prototype.executeNextEvent = function () {
  // Warning: Don't call this.debug inside here or you'll create an infinite loop

  var  f = this.eventQueue ? this.eventQueue.shift() : null;
  if (typeof(f) === "function") {
    f.apply(this);
  }
};

// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have
// properties that contain characters that are not valid for JavaScript identifiers. To work around this
// the Flash Component escapes the parameter names and we must unescape again before passing them along.
SWFUpload.prototype.unescapeFilePostParams = function (file) {
  var reg = /[$]([0-9a-f]{4})/i;
  var unescapedPost = {};
  var uk;

  if (file != undefined) {
    for (var k in file.post) {
      if (file.post.hasOwnProperty(k)) {
        uk = k;
        var match;
        while ((match = reg.exec(uk)) !== null) {
          uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16)));
        }
        unescapedPost[uk] = file.post[k];
      }
    }

    file.post = unescapedPost;
  }

  return file;
};

// Private: Called by Flash to see if JS can call in to Flash (test if External Interface is working)
SWFUpload.prototype.testExternalInterface = function () {
  try {
    return this.callFlash("TestExternalInterface");
  } catch (ex) {
    return false;
  }
};

// Private: This event is called by Flash when it has finished loading. Don't modify this.
// Use the swfupload_loaded_handler event setting to execute custom code when SWFUpload has loaded.
SWFUpload.prototype.flashReady = function () {
  // Check that the movie element is loaded correctly with its ExternalInterface methods defined
  var movieElement = this.getMovieElement();

  if (!movieElement) {
    this.debug("Flash called back ready but the flash movie can't be found.");
    return;
  }

  this.cleanUp(movieElement);
  this.queueEvent("swfupload_loaded_handler");
};

// Private: removes Flash added fuctions to the DOM node to prevent memory leaks in IE.
// This function is called by Flash each time the ExternalInterface functions are created.
SWFUpload.prototype.cleanUp = function (movieElement) {
  // Pro-actively unhook all the Flash functions
  try {
    if (this.movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
      this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)");
      for (var key in movieElement) {
        try {
          if (typeof(movieElement[key]) === "function") {
            movieElement[key] = null;
          }
        } catch (ex) {
        }
      }
    }
  } catch (ex1) {
  
  }

  // Fix Flashes own cleanup code so if the SWFMovie was removed from the page
  // it doesn't display errors.
  window["__flash__removeCallback"] = function (instance, name) {
    try {
      if (instance) {
        instance[name] = null;
      }
    } catch (flashEx) {
    
    }
  };

};


/* This is a chance to do something before the browse window opens */
SWFUpload.prototype.fileDialogStart = function () {
  this.queueEvent("file_dialog_start_handler");
};


/* Called when a file is successfully added to the queue. */
SWFUpload.prototype.fileQueued = function (file) {
  file = this.unescapeFilePostParams(file);
  this.queueEvent("file_queued_handler", file);
};


/* Handle errors that occur when an attempt to queue a file fails. */
SWFUpload.prototype.fileQueueError = function (file, errorCode, message) {
  file = this.unescapeFilePostParams(file);
  this.queueEvent("file_queue_error_handler", [file, errorCode, message]);
};

/* Called after the file dialog has closed and the selected files have been queued.
  You could call startUpload here if you want the queued files to begin uploading immediately. */
SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued, numFilesInQueue) {
  this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued, numFilesInQueue]);
};

SWFUpload.prototype.uploadStart = function (file) {
  file = this.unescapeFilePostParams(file);
  this.queueEvent("return_upload_start_handler", file);
};

SWFUpload.prototype.returnUploadStart = function (file) {
  var returnValue;
  if (typeof this.settings.upload_start_handler === "function") {
    file = this.unescapeFilePostParams(file);
    returnValue = this.settings.upload_start_handler.call(this, file);
  } else if (this.settings.upload_start_handler != undefined) {
    throw "upload_start_handler must be a function";
  }

  // Convert undefined to true so if nothing is returned from the upload_start_handler it is
  // interpretted as 'true'.
  if (returnValue === undefined) {
    returnValue = true;
  }
  
  returnValue = !!returnValue;
  
  this.callFlash("ReturnUploadStart", [returnValue]);
};



SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) {
  file = this.unescapeFilePostParams(file);
  this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]);
};

SWFUpload.prototype.uploadError = function (file, errorCode, message) {
  file = this.unescapeFilePostParams(file);
  this.queueEvent("upload_error_handler", [file, errorCode, message]);
};

SWFUpload.prototype.uploadSuccess = function (file, serverData, responseReceived) {
  file = this.unescapeFilePostParams(file);
  this.queueEvent("upload_success_handler", [file, serverData, responseReceived]);
};

SWFUpload.prototype.uploadComplete = function (file) {
  file = this.unescapeFilePostParams(file);
  this.queueEvent("upload_complete_handler", file);
};

/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the
   internal debug console.  You can override this event and have messages written where you want. */
SWFUpload.prototype.debug = function (message) {
  this.queueEvent("debug_handler", message);
};


/* **********************************
  Debug Console
  The debug console is a self contained, in page location
  for debug message to be sent.  The Debug Console adds
  itself to the body if necessary.

  The console is automatically scrolled as messages appear.
  
  If you are using your own debug handler or when you deploy to production and
  have debug disabled you can remove these functions to reduce the file size
  and complexity.
********************************** */
   
// Private: debugMessage is the default debug_handler.  If you want to print debug messages
// call the debug() function.  When overriding the function your own function should
// check to see if the debug setting is true before outputting debug information.
SWFUpload.prototype.debugMessage = function (message) {
  if (this.settings.debug) {
    var exceptionMessage, exceptionValues = [];

    // Check for an exception object and print it nicely
    if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") {
      for (var key in message) {
        if (message.hasOwnProperty(key)) {
          exceptionValues.push(key + ": " + message[key]);
        }
      }
      exceptionMessage = exceptionValues.join("\n") || "";
      exceptionValues = exceptionMessage.split("\n");
      exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: ");
      SWFUpload.Console.writeLine(exceptionMessage);
    } else {
      SWFUpload.Console.writeLine(message);
    }
  }
};

SWFUpload.Console = {};
SWFUpload.Console.writeLine = function (message) {
  var console, documentForm;

  try {
    console = document.getElementById("SWFUpload_Console");

    if (!console) {
      documentForm = document.createElement("form");
      document.getElementsByTagName("body")[0].appendChild(documentForm);

      console = document.createElement("textarea");
      console.id = "SWFUpload_Console";
      console.style.fontFamily = "monospace";
      console.setAttribute("wrap", "off");
      console.wrap = "off";
      console.style.overflow = "auto";
      console.style.width = "700px";
      console.style.height = "350px";
      console.style.margin = "5px";
      documentForm.appendChild(console);
    }

    console.value += message + "\n";

    console.scrollTop = console.scrollHeight - console.clientHeight;
  } catch (ex) {
    alert("Exception: " + ex.name + " Message: " + ex.message);
  }
};


/**
 * @author Ryan Johnson <http://saucytiger.com/>
 * @copyright 2008 PersonalGrid Corporation <http://personalgrid.com/>
 * @package LivePipe UI
 * @license MIT
 * @url http://livepipe.net/core
 * @require prototype.js
 */

if(typeof(Control) == 'undefined')
	Control = {};
	
var $proc = function(proc){
	return typeof(proc) == 'function' ? proc : function(){ return proc; };
};

var $value = function(value){
	return typeof(value) == 'function' ? value() : value;
};

Object.Event = {
	extend: function(object){
		object._objectEventSetup = function(event_name){
			this._observers = this._observers || {};
			this._observers[event_name] = this._observers[event_name] || [];
		};
		object.observe = function(event_name,observer){
			if(typeof(event_name) == 'string' && typeof(observer) != 'undefined'){
				this._objectEventSetup(event_name);
				if(!this._observers[event_name].include(observer))
					this._observers[event_name].push(observer);
			}else
				for(var e in event_name)
					this.observe(e,event_name[e]);
		};
		object.stopObserving = function(event_name,observer){
			this._objectEventSetup(event_name);
			if(event_name && observer)
				this._observers[event_name] = this._observers[event_name].without(observer);
			else if(event_name)
				this._observers[event_name] = [];
			else
				this._observers = {};
		};
		object.observeOnce = function(event_name,outer_observer){
			var inner_observer = function(){
				outer_observer.apply(this,arguments);
				this.stopObserving(event_name,inner_observer);
			}.bind(this);
			this._objectEventSetup(event_name);
			this._observers[event_name].push(inner_observer);
		};
		object.notify = function(event_name){
			this._objectEventSetup(event_name);
			var collected_return_values = [];
			var args = $A(arguments).slice(1);
			try{
				for(var i = 0; i < this._observers[event_name].length; ++i)
					collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null);
			}catch(e){
				if(e == $break)
					return false;
				else
					throw e;
			}
			return collected_return_values;
		};
		if(object.prototype){
			object.prototype._objectEventSetup = object._objectEventSetup;
			object.prototype.observe = object.observe;
			object.prototype.stopObserving = object.stopObserving;
			object.prototype.observeOnce = object.observeOnce;
			object.prototype.notify = function(event_name){
				if(object.notify){
					var args = $A(arguments).slice(1);
					args.unshift(this);
					args.unshift(event_name);
					object.notify.apply(object,args);
				}
				this._objectEventSetup(event_name);
				var args = $A(arguments).slice(1);
				var collected_return_values = [];
				try{
					if(this.options && this.options[event_name] && typeof(this.options[event_name]) == 'function')
						collected_return_values.push(this.options[event_name].apply(this,args) || null);
					for(var i = 0; i < this._observers[event_name].length; ++i)
						collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null);
				}catch(e){
					if(e == $break)
						return false;
					else
						throw e;
				}
				return collected_return_values;
			};
		}
	}
};

/* Begin Core Extensions */

//Element.observeOnce
Element.addMethods({
	observeOnce: function(element,event_name,outer_callback){
		var inner_callback = function(){
			outer_callback.apply(this,arguments);
			Element.stopObserving(element,event_name,inner_callback);
		};
		Element.observe(element,event_name,inner_callback);
	}
});

//mouseenter, mouseleave
//from http://dev.rubyonrails.org/attachment/ticket/8354/event_mouseenter_106rc1.patch
Object.extend(Event, (function() {
	var cache = Event.cache;

	function getEventID(element) {
		if (element._prototypeEventID) return element._prototypeEventID[0];
		arguments.callee.id = arguments.callee.id || 1;
		return element._prototypeEventID = [++arguments.callee.id];
	}

	function getDOMEventName(eventName) {
		if (eventName && eventName.include(':')) return "dataavailable";
		//begin extension
		if(!Prototype.Browser.IE){
			eventName = {
				mouseenter: 'mouseover',
				mouseleave: 'mouseout'
			}[eventName] || eventName;
		}
		//end extension
		return eventName;
	}

	function getCacheForID(id) {
		return cache[id] = cache[id] || { };
	}

	function getWrappersForEventName(id, eventName) {
		var c = getCacheForID(id);
		return c[eventName] = c[eventName] || [];
	}

	function createWrapper(element, eventName, handler) {
		var id = getEventID(element);
		var c = getWrappersForEventName(id, eventName);
		if (c.pluck("handler").include(handler)) return false;

		var wrapper = function(event) {
			if (!Event || !Event.extend ||
				(event.eventName && event.eventName != eventName))
					return false;

			Event.extend(event);
			handler.call(element, event);
		};
		
		//begin extension
		if(!(Prototype.Browser.IE) && ['mouseenter','mouseleave'].include(eventName)){
			wrapper = wrapper.wrap(function(proceed,event) {	
				var rel = event.relatedTarget;
				var cur = event.currentTarget;			 
				if(rel && rel.nodeType == Node.TEXT_NODE)
					rel = rel.parentNode;	  
				if(rel && rel != cur && !rel.descendantOf(cur))	  
					return proceed(event);   
			});	 
		}
		//end extension

		wrapper.handler = handler;
		c.push(wrapper);
		return wrapper;
	}

	function findWrapper(id, eventName, handler) {
		var c = getWrappersForEventName(id, eventName);
		return c.find(function(wrapper) { return wrapper.handler == handler; });
	}

	function destroyWrapper(id, eventName, handler) {
		var c = getCacheForID(id);
		if (!c[eventName]) return false;
		c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
	}

	function destroyCache() {
		for (var id in cache)
			for (var eventName in cache[id])
				cache[id][eventName] = null;
	}

	if (window.attachEvent) {
		window.attachEvent("onunload", destroyCache);
	}

	return {
		observe: function(element, eventName, handler) {
			element = $(element);
			var name = getDOMEventName(eventName);

			var wrapper = createWrapper(element, eventName, handler);
			if (!wrapper) return element;

			if (element.addEventListener) {
				element.addEventListener(name, wrapper, false);
			} else {
				element.attachEvent("on" + name, wrapper);
			}

			return element;
		},

		stopObserving: function(element, eventName, handler) {
			element = $(element);
			var id = getEventID(element), name = getDOMEventName(eventName);

			if (!handler && eventName) {
				getWrappersForEventName(id, eventName).each(function(wrapper) {
					element.stopObserving(eventName, wrapper.handler);
				});
				return element;

			} else if (!eventName) {
				Object.keys(getCacheForID(id)).each(function(eventName) {
					element.stopObserving(eventName);
				});
				return element;
			}

			var wrapper = findWrapper(id, eventName, handler);
			if (!wrapper) return element;

			if (element.removeEventListener) {
				element.removeEventListener(name, wrapper, false);
			} else {
				element.detachEvent("on" + name, wrapper);
			}

			destroyWrapper(id, eventName, handler);

			return element;
		},

		fire: function(element, eventName, memo) {
			element = $(element);
			if (element == document && document.createEvent && !element.dispatchEvent)
				element = document.documentElement;

			var event;
			if (document.createEvent) {
				event = document.createEvent("HTMLEvents");
				event.initEvent("dataavailable", true, true);
			} else {
				event = document.createEventObject();
				event.eventType = "ondataavailable";
			}

			event.eventName = eventName;
			event.memo = memo || { };

			if (document.createEvent) {
				element.dispatchEvent(event);
			} else {
				element.fireEvent(event.eventType, event);
			}

			return Event.extend(event);
		}
	};
})());

Object.extend(Event, Event.Methods);

Element.addMethods({
	fire:			Event.fire,
	observe:		Event.observe,
	stopObserving:	Event.stopObserving
});

Object.extend(document, {
	fire:			Element.Methods.fire.methodize(),
	observe:		Element.Methods.observe.methodize(),
	stopObserving:	Element.Methods.stopObserving.methodize()
});

//mouse:wheel
(function(){
	function wheel(event){
		var delta;
		// normalize the delta
		if(event.wheelDelta) // IE & Opera
			delta = event.wheelDelta / 120;
		else if (event.detail) // W3C
			delta =- event.detail / 3;
		if(!delta)
			return;
		var custom_event = event.element().fire('mouse:wheel',{
			delta: delta
		});
		if(custom_event.stopped){
			event.stop();
			return false;
		}
	}
	document.observe('mousewheel',wheel);
	document.observe('DOMMouseScroll',wheel);
})();

/* End Core Extensions */

//from PrototypeUI
var IframeShim = Class.create({
	initialize: function() {
		this.element = new Element('iframe',{
			style: 'position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);display:none',
			src: 'javascript:void(0);',
			frameborder: 0 
		});
		$(document.body).insert(this.element);
	},
	hide: function() {
		this.element.hide();
		return this;
	},
	show: function() {
		this.element.show();
		return this;
	},
	positionUnder: function(element) {
		var element = $(element);
		var offset = element.cumulativeOffset();
		var dimensions = element.getDimensions();
		this.element.setStyle({
			left: offset[0] + 'px',
			top: offset[1] + 'px',
			width: dimensions.width + 'px',
			height: dimensions.height + 'px',
			zIndex: element.getStyle('zIndex') - 1
		}).show();
		return this;
	},
	setBounds: function(bounds) {
		for(prop in bounds)
			bounds[prop] += 'px';
		this.element.setStyle(bounds);
		return this;
	},
	destroy: function() {
		if(this.element)
			this.element.remove();
		return this;
	}
});

/**
 * @author Ryan Johnson <http://saucytiger.com/>
 * @copyright 2008 PersonalGrid Corporation <http://personalgrid.com/>
 * @package LivePipe UI
 * @license MIT
 * @url http://livepipe.net/control/window
 * @require prototype.js, effects.js, draggable.js, resizable.js, livepipe.js
 */

//adds onDraw and constrainToViewport option to draggable
if(typeof(Draggable) != 'undefined'){
	//allows the point to be modified with an onDraw callback
	Draggable.prototype.draw = function(point) {
		var pos = Position.cumulativeOffset(this.element);
		if(this.options.ghosting) {
			var r = Position.realOffset(this.element);
			pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
		}
		
		var d = this.currentDelta();
		pos[0] -= d[0]; pos[1] -= d[1];
		
		if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
			pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
			pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
		}
		
		var p = [0,1].map(function(i){ 
			return (point[i]-pos[i]-this.offset[i]);
		}.bind(this));
		
		if(this.options.snap) {
			if(typeof this.options.snap == 'function') {
				p = this.options.snap(p[0],p[1],this);
			} else {
				if(this.options.snap instanceof Array) {
					p = p.map( function(v, i) { return Math.round(v/this.options.snap[i])*this.options.snap[i]; }.bind(this));
				} else {
					p = p.map( function(v) { return Math.round(v/this.options.snap)*this.options.snap; }.bind(this));
	  		}
			}
		}
		
		if(this.options.onDraw)
			this.options.onDraw.bind(this)(p);
		else{
			var style = this.element.style;
			if(this.options.constrainToViewport){
				var viewport_dimensions = document.viewport.getDimensions();
				var container_dimensions = this.element.getDimensions();
				var margin_top = parseInt(this.element.getStyle('margin-top'));
				var margin_left = parseInt(this.element.getStyle('margin-left'));
				var boundary = [[
					0 - margin_left,
					0 - margin_top
				],[
					(viewport_dimensions.width - container_dimensions.width) - margin_left,
					(viewport_dimensions.height - container_dimensions.height) - margin_top
				]];
				if((!this.options.constraint) || (this.options.constraint=='horizontal')){ 
					if((p[0] >= boundary[0][0]) && (p[0] <= boundary[1][0]))
						this.element.style.left = p[0] + "px";
					else
						this.element.style.left = ((p[0] < boundary[0][0]) ? boundary[0][0] : boundary[1][0]) + "px";
				} 
				if((!this.options.constraint) || (this.options.constraint=='vertical')){ 
					if((p[1] >= boundary[0][1] ) && (p[1] <= boundary[1][1]))
						this.element.style.top = p[1] + "px";
				  else
						this.element.style.top = ((p[1] <= boundary[0][1]) ? boundary[0][1] : boundary[1][1]) + "px";			   
				}
			}else{
				if((!this.options.constraint) || (this.options.constraint=='horizontal'))
				  style.left = p[0] + "px";
				if((!this.options.constraint) || (this.options.constraint=='vertical'))
				  style.top	 = p[1] + "px";
			}
			if(style.visibility=="hidden")
				style.visibility = ""; // fix gecko rendering
		}
	};
}

if(typeof(Prototype) == "undefined")
	throw "Control.Window requires Prototype to be loaded.";
if(typeof(IframeShim) == "undefined")
	throw "Control.Window requires IframeShim to be loaded.";
if(typeof(Object.Event) == "undefined")
	throw "Control.Window requires Object.Event to be loaded.";
/*
	known issues:
		- when iframe is clicked is does not gain focus
		- safari can't open multiple iframes properly
		- constrainToViewport: body must have no margin or padding for this to work properly
		- iframe will be mis positioned during fade in
		- document.viewport does not account for scrollbars (this will eventually be fixed in the prototype core)
	notes
		- setting constrainToViewport only works when the page is not scrollable
		- setting draggable: true will negate the effects of position: center
*/
Control.Window = Class.create({
	initialize: function(container,options){
		Control.Window.windows.push(this);
		
		//attribute initialization
		this.container = false;
		this.isOpen = false;
		this.href = false;
		this.sourceContainer = false; //this is optionally the container that will open the window
		this.ajaxRequest = false;
		this.remoteContentLoaded = false; //this is set when the code to load the remote content is run, onRemoteContentLoaded is fired when the connection is closed
		this.numberInSequence = Control.Window.windows.length + 1; //only useful for the effect scoping
		this.indicator = false;
		this.effects = {
			fade: false,
			appear: false
		};
		this.indicatorEffects = {
			fade: false,
			appear: false
		};
		
		//options
		this.options = Object.extend({
			//lifecycle
			beforeOpen: Prototype.emptyFunction,
			afterOpen: Prototype.emptyFunction,
			beforeClose: Prototype.emptyFunction,
			afterClose: Prototype.emptyFunction,
			//dimensions and modes
			height: null,
			width: null,
			className: false,
			position: 'center', //'center', 'relative', [x,y], [function(){return x;},function(){return y;}]
			offsetLeft: 0, //available only for anchors opening the window, or windows set to position: hover
			offsetTop: 0, //""
			iframe: false, //if the window has an href, this will display the href as an iframe instead of requesting the url as an an Ajax.Request
			hover: false, //element object to hover over, or if "true" only available for windows with sourceContainer (an anchor or any element already on the page with an href attribute)
			indicator: false, //element to show or hide when ajax requests, images and iframes are loading
			closeOnClick: false, //does not work with hover,can be: true (click anywhere), 'container' (will refer to this.container), or element (a specific element)
			iframeshim: true, //wether or not to position an iFrameShim underneath the window 
			//effects
			fade: false,
			fadeDuration: 0.75,
			//draggable
			draggable: false,
			onDrag: Prototype.emptyFunction,
			//resizable
			resizable: false,
			minHeight: false,
			minWidth: false,
			maxHeight: false,
			maxWidth: false,
			onResize: Prototype.emptyFunction,
			//draggable and resizable
			constrainToViewport: false,
			//ajax
			parameters: {},
			onComplete: Prototype.emptyFunction,
			onSuccess: Prototype.emptyFunction,
			onFailure: Prototype.emptyFunction,
			onException: Prototype.emptyFunction,
			//any element with an href (image,iframe,ajax) will call this after it is done loading
			onRemoteContentLoaded: Prototype.emptyFunction,
			insertRemoteContentAt: false //false will set this to this.container, can be string selector (first returned will be selected), or an Element that must be a child of this.container
		},options || {});
		
		//container setup
		this.indicator = this.options.indicator ? $(this.options.indicator) : false;
		if(container){
			if(typeof(container) == "string" && container.match(Control.Window.uriRegex))
				this.href = container;
			else{
				this.container = $(container);
				//need to create the container now for tooltips (or hover: element with no container already on the page)
				//second call made below will not create the container since the check is done inside createDefaultContainer()
				this.createDefaultContainer(container);
				//if an element with an href was passed in we use it to activate the window
				if(this.container && ((this.container.readAttribute('href') && this.container.readAttribute('href') != '') || (this.options.hover && this.options.hover !== true))){						
					if(this.options.hover && this.options.hover !== true)
						this.sourceContainer = $(this.options.hover);
					else{
						this.sourceContainer = this.container;
						this.href = this.container.readAttribute('href');
						var rel = this.href.match(/#(.+)$/);
						if(rel && rel[1]){
							this.container = $(rel[1]);
							this.href = false;
						}else
							this.container = false;
					}
					//hover or click handling
					this.sourceContainerOpenHandler = function(event){
						this.open(event);
						event.stop();
						return false;
					}.bindAsEventListener(this);
					this.sourceContainerCloseHandler = function(event){
						this.close(event);
					}.bindAsEventListener(this);
					this.sourceContainerMouseMoveHandler = function(event){
						this.position(event);
					}.bindAsEventListener(this);
					if(this.options.hover){
						this.sourceContainer.observe('mouseenter',this.sourceContainerOpenHandler);
						this.sourceContainer.observe('mouseleave',this.sourceContainerCloseHandler);
						if(this.options.position == 'mouse')
							this.sourceContainer.observe('mousemove',this.sourceContainerMouseMoveHandler);
					}else
						this.sourceContainer.observe('click',this.sourceContainerOpenHandler);
				}
			}
		}
		this.createDefaultContainer(container);
		if(this.options.insertRemoteContentAt === false)
			this.options.insertRemoteContentAt = this.container;
		var styles = {
			margin: 0,
			position: 'absolute',
			zIndex: Control.Window.initialZIndexForWindow()
		};
		if(this.options.width)
			styles.width = $value(this.options.width) + 'px';
		if(this.options.height)
			styles.height = $value(this.options.height) + 'px';
		this.container.setStyle(styles);
		if(this.options.className)
			this.container.addClassName(this.options.className);
		this.positionHandler = this.position.bindAsEventListener(this);
		this.outOfBoundsPositionHandler = this.ensureInBounds.bindAsEventListener(this);
		this.bringToFrontHandler = this.bringToFront.bindAsEventListener(this);
		this.container.observe('mousedown',this.bringToFrontHandler);
		this.container.hide();
		this.closeHandler = this.close.bindAsEventListener(this);
		//iframeshim setup
		if(this.options.iframeshim){
			this.iFrameShim = new IframeShim();
			this.iFrameShim.hide();
		}
		//resizable support
		this.applyResizable();
		//draggable support
		this.applyDraggable();
		
		//makes sure the window can't go out of bounds
		Event.observe(window,'resize',this.outOfBoundsPositionHandler);
		
		this.notify('afterInitialize');
	},
	open: function(event){
		if(this.isOpen){
			this.bringToFront();
			return false;
		}
		if(this.notify('beforeOpen') === false)
			return false;
		//closeOnClick
		if(this.options.closeOnClick){
			if(this.options.closeOnClick === true)
				this.closeOnClickContainer = $(document.body);
			else if(this.options.closeOnClick == 'container')
				this.closeOnClickContainer = this.container;
			else if (this.options.closeOnClick == 'overlay'){
				Control.Overlay.load();
				this.closeOnClickContainer = Control.Overlay.container;
			}else
				this.closeOnClickContainer = $(this.options.closeOnClick);
			this.closeOnClickContainer.observe('click',this.closeHandler);
		}
		if(this.href && !this.options.iframe && !this.remoteContentLoaded){
			//link to image
			this.remoteContentLoaded = true;
			if(this.href.match(/\.(jpe?g|gif|png|tiff?)$/i)){
				var img = new Element('img');
				img.observe('load',function(img){
					this.getRemoteContentInsertionTarget().insert(img);
					this.position();
					if(this.notify('onRemoteContentLoaded') !== false){
						if(this.options.indicator)
							this.hideIndicator();
						this.finishOpen();
					}
				}.bind(this,img));
				img.writeAttribute('src',this.href);
			}else{
				//if this is an ajax window it will only open if the request is successful
				if(!this.ajaxRequest){
					if(this.options.indicator)
						this.showIndicator();
					this.ajaxRequest = new Ajax.Request(this.href,{
						method: 'post',
						parameters: this.options.parameters,
						onComplete: function(request){
							this.notify('onComplete',request);
							this.ajaxRequest = false;
						}.bind(this),
						onSuccess: function(request){
							this.getRemoteContentInsertionTarget().insert(request.responseText);
							this.notify('onSuccess',request);
							if(this.notify('onRemoteContentLoaded') !== false){
								if(this.options.indicator)
									this.hideIndicator();
								this.finishOpen();
							}
						}.bind(this),
						onFailure: function(request){
							this.notify('onFailure',request);
							if(this.options.indicator)
								this.hideIndicator();
						}.bind(this),
						onException: function(request,e){
							this.notify('onException',request,e);
							if(this.options.indicator)
								this.hideIndicator();
						}.bind(this)
					});
				}
			}
			return true;
		}else if(this.options.iframe && !this.remoteContentLoaded){
			//iframe
			this.remoteContentLoaded = true;
			if(this.options.indicator)
				this.showIndicator();
			this.getRemoteContentInsertionTarget().insert(Control.Window.iframeTemplate.evaluate({
				href: this.href
			}));
			var iframe = this.container.down('iframe');
			iframe.onload = function(){
				this.notify('onRemoteContentLoaded');
				if(this.options.indicator)
					this.hideIndicator();
				iframe.onload = null;
			}.bind(this);
		}
		this.finishOpen(event);
		return true;
	},
	close: function(event){ //event may or may not be present
		if(!this.isOpen || this.notify('beforeClose',event) === false)
			return false;
		if(this.options.closeOnClick)
			this.closeOnClickContainer.stopObserving('click',this.closeHandler);
		if(this.options.fade){
			this.effects.fade = new Effect.Fade(this.container,{
				queue: {
					position: 'front',
					scope: 'Control.Window' + this.numberInSequence
				},
				from: 1,
				to: 0,
				duration: this.options.fadeDuration / 2,
				afterFinish: function(){
					if(this.iFrameShim)
						this.iFrameShim.hide();
					this.isOpen = false;
					this.notify('afterClose');
				}.bind(this)
			});
		}else{
			this.container.hide();
			if(this.iFrameShim)
				this.iFrameShim.hide();
		}
		if(this.ajaxRequest)
			this.ajaxRequest.transport.abort();
		if(!(this.options.draggable || this.options.resizable) && this.options.position == 'center')
			Event.stopObserving(window,'resize',this.positionHandler);
		if(!this.options.draggable && this.options.position == 'center')
			Event.stopObserving(window,'scroll',this.positionHandler);
		if(this.options.indicator)
			this.hideIndicator();
		if(!this.options.fade){
			this.isOpen = false;
			this.notify('afterClose');
        }
		return true;
	},
	position: function(event){
		//this is up top for performance reasons
		if(this.options.position == 'mouse'){
			var xy = [Event.pointerX(event),Event.pointerY(event)];
			this.container.setStyle({
				top: xy[1] + $value(this.options.offsetTop) + 'px',
				left: xy[0] + $value(this.options.offsetLeft) + 'px'
			});
			return;
		}
		var container_dimensions = this.container.getDimensions();
		var viewport_dimensions = document.viewport.getDimensions();
		Position.prepare();
		var offset_left = (Position.deltaX + Math.floor((viewport_dimensions.width - container_dimensions.width) / 2));
		var offset_top = (Position.deltaY + ((viewport_dimensions.height > container_dimensions.height) ? Math.floor((viewport_dimensions.height - container_dimensions.height) / 2) : 0));
		if(this.options.position == 'center'){
			this.container.setStyle({
				top: (container_dimensions.height <= viewport_dimensions.height) ? ((offset_top != null && offset_top > 0) ? offset_top : 0) + 'px' : 0,
				left: (container_dimensions.width <= viewport_dimensions.width) ? ((offset_left != null && offset_left > 0) ? offset_left : 0) + 'px' : 0
			});
		}else if(this.options.position == 'relative'){
			var xy = this.sourceContainer.cumulativeOffset();
			var top = xy[1] + $value(this.options.offsetTop);
			var left = xy[0] + $value(this.options.offsetLeft);
			this.container.setStyle({
				top: (container_dimensions.height <= viewport_dimensions.height) ? (this.options.constrainToViewport ? Math.max(0,Math.min(viewport_dimensions.height - (container_dimensions.height),top)) : top) + 'px' : 0,
				left: (container_dimensions.width <= viewport_dimensions.width) ? (this.options.constrainToViewport ? Math.max(0,Math.min(viewport_dimensions.width - (container_dimensions.width),left)) : left) + 'px' : 0
			});
		}else if(this.options.position.length){
			var top = $value(this.options.position[1]) + $value(this.options.offsetTop);
			var left = $value(this.options.position[0]) + $value(this.options.offsetLeft);
			this.container.setStyle({
				top: (container_dimensions.height <= viewport_dimensions.height) ? (this.options.constrainToViewport ? Math.max(0,Math.min(viewport_dimensions.height - (container_dimensions.height),top)) : top) + 'px' : 0,
				left: (container_dimensions.width <= viewport_dimensions.width) ? (this.options.constrainToViewport ? Math.max(0,Math.min(viewport_dimensions.width - (container_dimensions.width),left)) : left) + 'px' : 0
			});
		}
		if(this.iFrameShim)
			this.updateIFrameShimZIndex();
	},
	ensureInBounds: function(){
		if(!this.isOpen)
			return;
		var viewport_dimensions = document.viewport.getDimensions();
		var container_offset = this.container.cumulativeOffset();
		var container_dimensions = this.container.getDimensions();
		if(container_offset.left + container_dimensions.width > viewport_dimensions.width){
			this.container.setStyle({
				left: (Math.max(0,viewport_dimensions.width - container_dimensions.width)) + 'px'
			});
		}
		if(container_offset.top + container_dimensions.height > viewport_dimensions.height){
			this.container.setStyle({
				top: (Math.max(0,viewport_dimensions.height - container_dimensions.height)) + 'px'
			});
		}
	},
	bringToFront: function(){
		Control.Window.bringToFront(this);
		this.notify('bringToFront');
	},
	destroy: function(){
		this.container.stopObserving('mousedown',this.bringToFrontHandler);
		if(this.draggable){
			Resizables.removeObserver(this.container);
			this.draggable.handle.stopObserving('mousedown',this.bringToFrontHandler);
			this.draggable.destroy();
		}
		if(this.resizable){
			Resizables.removeObserver(this.container);
			this.resizable.handle.stopObserving('mousedown',this.bringToFrontHandler);
			this.resizable.destroy();
		}
		if(this.container && !this.sourceContainer)
			this.container.remove();
		if(this.sourceContainer){
			if(this.options.hover){
				this.sourceContainer.stopObserving('mouseenter',this.sourceContainerOpenHandler);
				this.sourceContainer.stopObserving('mouseleave',this.sourceContainerCloseHandler);
				if(this.options.position == 'mouse')
					this.sourceContainer.stopObserving('mousemove',this.sourceContainerMouseMoveHandler);
			}else
				this.sourceContainer.stopObserving('click',this.sourceContainerOpenHandler);
		}
		if(this.iFrameShim)
			this.iFrameShim.destroy();
		Event.stopObserving(window,'resize',this.outOfBoundsPositionHandler);
		Control.Window.windows = Control.Window.windows.without(this);
		this.notify('afterDestroy');
	},
	//private
	applyResizable: function(){
		if(this.options.resizable){
			if(typeof(Resizable) == "undefined")
				throw "Control.Window requires resizable.js to be loaded.";
			var resizable_handle = null;
			if(this.options.resizable === true){
				resizable_handle = new Element('div',{
					className: 'resizable_handle'
				});
				this.container.insert(resizable_handle);
			}else
				resizable_handle = $(this.options.resziable);
			this.resizable = new Resizable(this.container,{
				handle: resizable_handle,
				minHeight: this.options.minHeight,
				minWidth: this.options.minWidth,
				maxHeight: this.options.constrainToViewport ? function(element){
					//viewport height - top - total border height
					return (document.viewport.getDimensions().height - parseInt(element.style.top || 0)) - (element.getHeight() - parseInt(element.style.height || 0));
				} : this.options.maxHeight,
				maxWidth: this.options.constrainToViewport ? function(element){
					//viewport width - left - total border width
					return (document.viewport.getDimensions().width - parseInt(element.style.left || 0)) - (element.getWidth() - parseInt(element.style.width || 0));
				} : this.options.maxWidth
			});
			this.resizable.handle.observe('mousedown',this.bringToFrontHandler);
			Resizables.addObserver(new Control.Window.LayoutUpdateObserver(this,function(){
				if(this.iFrameShim)
					this.updateIFrameShimZIndex();
				this.notify('onResize');
			}.bind(this)));
		}
	},
	applyDraggable: function(){
		if(this.options.draggable){
			if(typeof(Draggables) == "undefined")
				throw "Control.Window requires dragdrop.js to be loaded.";
			var draggable_handle = null;
			if(this.options.draggable === true){
				draggable_handle = new Element('div',{
					className: 'draggable_handle'
				});
				this.container.insert(draggable_handle);
			}else
				draggable_handle = $(this.options.draggable);
			this.draggable = new Draggable(this.container,{
				handle: draggable_handle,
				constrainToViewport: this.options.constrainToViewport,
				zindex: this.container.getStyle('z-index'),
				starteffect: function(){
					if(Prototype.Browser.IE){
						this.old_onselectstart = document.onselectstart;
						document.onselectstart = function(){
							return false;
						};
					}
				}.bind(this),
				endeffect: function(){
					document.onselectstart = this.old_onselectstart;
				}.bind(this)
			});
			this.draggable.handle.observe('mousedown',this.bringToFrontHandler);
			Draggables.addObserver(new Control.Window.LayoutUpdateObserver(this,function(){
				if(this.iFrameShim)
					this.updateIFrameShimZIndex();
				this.notify('onDrag');
			}.bind(this)));
		}
	},
	createDefaultContainer: function(container){
		if(!this.container){
			//no container passed or found, create it
			this.container = new Element('div',{
				id: 'control_window_' + this.numberInSequence
			});
			$(document.body).insert(this.container);
			if(typeof(container) == "string" && $(container) == null && !container.match(/^#(.+)$/) && !container.match(Control.Window.uriRegex))
				this.container.update(container);
		}
	},
	finishOpen: function(event){
		this.bringToFront();
		if(this.options.fade){
			if(typeof(Effect) == "undefined")
				throw "Control.Window requires effects.js to be loaded.";
			if(this.effects.fade)
				this.effects.fade.cancel();
			this.effects.appear = new Effect.Appear(this.container,{
				queue: {
					position: 'end',
					scope: 'Control.Window.' + this.numberInSequence
				},
				from: 0,
				to: 1,
				duration: this.options.fadeDuration / 2,
				afterFinish: function(){
					if(this.iFrameShim)
						this.updateIFrameShimZIndex();
					this.isOpen = true;
					this.notify('afterOpen');
				}.bind(this)
			});
		}else
			this.container.show();
		this.position(event);
		if(!(this.options.draggable || this.options.resizable) && this.options.position == 'center')
			Event.observe(window,'resize',this.positionHandler,false);
		if(!this.options.draggable && this.options.position == 'center')
			Event.observe(window,'scroll',this.positionHandler,false);
		if(!this.options.fade){
			this.isOpen = true;
			this.notify('afterOpen');
		}
		return true;
	},
	showIndicator: function(){
		this.showIndicatorTimeout = window.setTimeout(function(){
			if(this.options.fade){
				this.indicatorEffects.appear = new Effect.Appear(this.indicator,{
					queue: {
						position: 'front',
						scope: 'Control.Window.indicator.' + this.numberInSequence
					},
					from: 0,
					to: 1,
					duration: this.options.fadeDuration / 2
				});
			}else
				this.indicator.show();
		}.bind(this),Control.Window.indicatorTimeout);
	},
	hideIndicator: function(){
		if(this.showIndicatorTimeout)
			window.clearTimeout(this.showIndicatorTimeout);
		this.indicator.hide();
	},
	getRemoteContentInsertionTarget: function(){
		return typeof(this.options.insertRemoteContentAt) == "string" ? this.container.down(this.options.insertRemoteContentAt) : $(this.options.insertRemoteContentAt);
	},
	updateIFrameShimZIndex: function(){
		if(this.iFrameShim)
			this.iFrameShim.positionUnder(this.container);
	}
});
//class methods
Object.extend(Control.Window,{
	windows: [],
	baseZIndex: 9999,
	indicatorTimeout: 250,
	iframeTemplate: new Template('<iframe src="#{href}" width="100%" height="100%" frameborder="0"></iframe>'),
	uriRegex: /^(\/|\#|https?\:\/\/|[\w]+\/)/,
	bringToFront: function(w){
		Control.Window.windows = Control.Window.windows.without(w);
		Control.Window.windows.push(w);
		Control.Window.windows.each(function(w,i){
			var z_index = Control.Window.baseZIndex + i;
			w.container.setStyle({
				zIndex: z_index
			});
			if(w.isOpen){
				if(w.iFrameShim)
				w.updateIFrameShimZIndex();
			}
			if(w.options.draggable)
				w.draggable.options.zindex = z_index;
		});
	},
	open: function(container,options){
		var w = new Control.Window(container,options);
		w.open();
		return w;
	},
	//protected
	initialZIndexForWindow: function(w){
		return Control.Window.baseZIndex + (Control.Window.windows.length - 1);
	}
});
Object.Event.extend(Control.Window);

//this is the observer for both Resizables and Draggables
Control.Window.LayoutUpdateObserver = Class.create({
	initialize: function(w,observer){
		this.w = w;
		this.element = $(w.container);
		this.observer = observer;
	},
	onStart: Prototype.emptyFunction,
	onEnd: function(event_name,instance){
		if(instance.element == this.element && this.iFrameShim)
			this.w.updateIFrameShimZIndex();
	},
	onResize: function(event_name,instance){
		if(instance.element == this.element)
			this.observer(this.element);
	},
	onDrag: function(event_name,instance){
		if(instance.element == this.element)
			this.observer(this.element);
	}
});

//overlay for Control.Modal
Control.Overlay = {
	id: 'control_overlay',
	loaded: false,
	container: false,
	lastOpacity: 0,
	styles: {
		position: 'fixed',
		top: 0,
		left: 0,
		width: '100%',
		height: '100%',
		zIndex: 9998
	},
	ieStyles: {
		position: 'absolute',
		top: 0,
		left: 0,
		zIndex: 9998
	},
	effects: {
		fade: false,
		appear: false
	},
	load: function(){
		if(Control.Overlay.loaded)
			return false;
		Control.Overlay.loaded = true;
		Control.Overlay.container = new Element('div',{
			id: Control.Overlay.id
		});
		$(document.body).insert(Control.Overlay.container);
		if(Prototype.Browser.IE){
			Control.Overlay.container.setStyle(Control.Overlay.ieStyles);
			Event.observe(window,'scroll',Control.Overlay.positionOverlay);
			Event.observe(window,'resize',Control.Overlay.positionOverlay);
			Control.Overlay.observe('beforeShow',Control.Overlay.positionOverlay);
		}else
			Control.Overlay.container.setStyle(Control.Overlay.styles);
		Control.Overlay.iFrameShim = new IframeShim();
		Control.Overlay.iFrameShim.hide();
		Event.observe(window,'resize',Control.Overlay.positionIFrameShim);
		Control.Overlay.container.hide();
		return true;
	},
	unload: function(){
		if(!Control.Overlay.loaded)
			return false;
		Event.stopObserving(window,'resize',Control.Overlay.positionOverlay);
		Control.Overlay.stopObserving('beforeShow',Control.Overlay.positionOverlay);
		Event.stopObserving(window,'resize',Control.Overlay.positionIFrameShim);
		Control.Overlay.iFrameShim.destroy();
		Control.Overlay.container.remove();
		Control.Overlay.loaded = false;
		return true;
	},
	show: function(opacity,fade){
		if(Control.Overlay.notify('beforeShow') === false)
			return false;
		Control.Overlay.lastOpacity = opacity;
		Control.Overlay.positionIFrameShim();
		Control.Overlay.iFrameShim.show();
		if(fade){
			if(typeof(Effect) == "undefined")
				throw "Control.Window requires effects.js to be loaded.";
			if(Control.Overlay.effects.fade)
				Control.Overlay.effects.fade.cancel();
			Control.Overlay.effects.appear = new Effect.Appear(Control.Overlay.container,{
				queue: {
					position: 'end',
					scope: 'Control.Overlay'
				},
				afterFinish: function(){
					Control.Overlay.notify('afterShow');
				},
				from: 0,
				to: Control.Overlay.lastOpacity,
				duration: (fade === true ? 0.75 : fade) / 2
			});
		}else{
			Control.Overlay.container.setStyle({
				opacity: opacity || 1
			});
			Control.Overlay.container.show();
			Control.Overlay.notify('afterShow');
		}
		return true;
	},
	hide: function(fade){
		if(Control.Overlay.notify('beforeHide') === false)
			return false;
		if(Control.Overlay.effects.appear)
			Control.Overlay.effects.appear.cancel();
		Control.Overlay.iFrameShim.hide();
		if(fade){
			Control.Overlay.effects.fade = new Effect.Fade(Control.Overlay.container,{
				queue: {
					position: 'front',
					scope: 'Control.Overlay'
				},
				afterFinish: function(){
					Control.Overlay.notify('afterHide');
				},
				from: Control.Overlay.lastOpacity,
				to: 0,
				duration: (fade === true ? 0.75 : fade) / 2
			});
		}else{
			Control.Overlay.container.hide();
			Control.Overlay.notify('afterHide');
		}
		return true;
	},
	positionIFrameShim: function(){
		if(Control.Overlay.container.visible())
			Control.Overlay.iFrameShim.positionUnder(Control.Overlay.container);
	},
	//IE only
	positionOverlay: function(){
		var dimensions = document.viewport.getDimensions();
		// modified as of
		// http://livepipe.lighthouseapp.com/projects/11811-livepipe-ui/tickets/18-ie-overlay-height
		Control.Overlay.container.setStyle({
			width: dimensions.width + 'px',
			height: document.body.clientHeight + 'px'
		});
	}
};
Object.Event.extend(Control.Overlay);

Control.ToolTip = Class.create(Control.Window,{
	initialize: function($super,container,tooltip,options){
		$super(tooltip,Object.extend(Object.extend(Control.ToolTip.defaultOptions,options || {}),{
			position: 'mouse',
			hover: container
		}));
	}
});
Object.extend(Control.ToolTip,{
	defaultOptions: {
		offsetLeft: 10
	}
});

Control.Modal = Class.create(Control.Window,{
	initialize: function($super,container,options){
		Control.Modal.InstanceMethods.beforeInitialize.bind(this)();
		$super(container,Object.extend(Control.Modal.defaultOptions,options || {}));
	}
});
Object.extend(Control.Modal,{
	defaultOptions: {
		overlayOpacity: 0.5,
		closeOnClick: 'overlay'
	},
	current: false,
	open: function(container,options){
		var modal = new Control.Modal(container,options);
		modal.open();
		return modal;
	},
	close: function(){
		if(Control.Modal.current)
			Control.Modal.current.close();
	},
	InstanceMethods: {
		beforeInitialize: function(){
			Control.Overlay.load();
			this.overlayFinishedOpening = false;
			this.observe('beforeOpen',Control.Modal.Observers.beforeOpen.bind(this));
			this.observe('afterOpen',Control.Modal.Observers.afterOpen.bind(this));
			this.observe('afterClose',Control.Modal.Observers.afterClose.bind(this));
		}
	},
	Observers: {
		beforeOpen: function(){
			if(!this.overlayFinishedOpening){
				Control.Overlay.observeOnce('afterShow',function(){
					this.overlayFinishedOpening = true;
					this.open();
				}.bind(this));
				Control.Overlay.show(this.options.overlayOpacity,this.options.fade ? this.options.fadeDuration : false);
				throw $break;
			}else
			Control.Window.windows.without(this).invoke('close');
		},
		afterOpen: function(){
			Control.Modal.current = this;
		},
		afterClose: function(){
			Control.Overlay.hide(this.options.fade ? this.options.fadeDuration : false);
			Control.Modal.current = false;
			this.overlayFinishedOpening = false;
		}
	}
});

Control.LightBox = Class.create(Control.Window,{
	initialize: function($super,container,options){
		this.allImagesLoaded = false;
		if(options.modal){
			var options = Object.extend(Control.LightBox.defaultOptions,options || {});
			options = Object.extend(Control.Modal.defaultOptions,options);
			options = Control.Modal.InstanceMethods.beforeInitialize.bind(this)(options);
			$super(container,options);
		}else
			$super(container,Object.extend(Control.LightBox.defaultOptions,options || {}));
		this.hasRemoteContent = this.href && !this.options.iframe;
		if(this.hasRemoteContent)
			this.observe('onRemoteContentLoaded',Control.LightBox.Observers.onRemoteContentLoaded.bind(this));
		else
			this.applyImageObservers();
		this.observe('beforeOpen',Control.LightBox.Observers.beforeOpen.bind(this));
	},
	applyImageObservers:function(){
		var images = this.getImages();
		this.numberImagesToLoad = images.length;
		this.numberofImagesLoaded = 0;
		images.each(function(image){
			image.observe('load',function(image){
				++this.numberofImagesLoaded;
				if(this.numberImagesToLoad == this.numberofImagesLoaded){
					this.allImagesLoaded = true;
					this.onAllImagesLoaded();
				}
			}.bind(this,image));
			image.hide();
		}.bind(this));
	},
	onAllImagesLoaded: function(){
		this.getImages().each(function(image){
			this.showImage(image);
		}.bind(this));
		if(this.hasRemoteContent){
			if(this.options.indicator)
				this.hideIndicator();
			this.finishOpen();
		}else
			this.open();
	},
	getImages: function(){
		return this.container.select(Control.LightBox.imageSelector);
	},
	showImage: function(image){
		image.show();
	}
});
Object.extend(Control.LightBox,{
	imageSelector: 'img',
	defaultOptions: {},
	Observers: {
		beforeOpen: function(){
			if(!this.hasRemoteContent && !this.allImagesLoaded)
				throw $break;
		},
		onRemoteContentLoaded: function(){
			this.applyImageObservers();
			if(!this.allImagesLoaded)
				throw $break;
		}
	}
});

/**
 * @author Ryan Johnson <http://saucytiger.com/>
 * @copyright 2008 PersonalGrid Corporation <http://personalgrid.com/>
 * @package LivePipe UI
 * @license MIT
 * @url http://livepipe.net/control/textarea
 * @require prototype.js, livepipe.js
 */

if(typeof(Prototype) == "undefined")
	throw "Control.TextArea requires Prototype to be loaded.";
if(typeof(Object.Event) == "undefined")
	throw "Control.TextArea requires Object.Event to be loaded.";

Control.TextArea = Class.create({
	initialize: function(textarea){
		this.onChangeTimeout = false;
		this.element = $(textarea);
		$(this.element).observe('keyup',this.doOnChange.bindAsEventListener(this));
		$(this.element).observe('paste',this.doOnChange.bindAsEventListener(this));
		$(this.element).observe('input',this.doOnChange.bindAsEventListener(this));
		if(!!document.selection){
			$(this.element).observe('mouseup',this.saveRange.bindAsEventListener(this));  
			$(this.element).observe('keyup',this.saveRange.bindAsEventListener(this));
		}
	},
	doOnChange: function(event){
		if(this.onChangeTimeout)
			window.clearTimeout(this.onChangeTimeout);
		this.onChangeTimeout = window.setTimeout(function(){
			this.notify('change',this.getValue());
		}.bind(this),Control.TextArea.onChangeTimeoutLength);
	},
	saveRange: function(){
		this.range = document.selection.createRange();  
	},
	getValue: function(){
		return this.element.value;
	},
	getSelection: function(){
		if(!!document.selection)
      // return document.selection.createRange().text; // we use this instead:
      // (see http://groups.google.com/group/livepipe/browse_thread/thread/50858ca39f984603)
			return this.range ? this.range.text : document.selection.createRange().text;
		else if(!!this.element.setSelectionRange)
			return this.element.value.substring(this.element.selectionStart,this.element.selectionEnd);
		else
			return false;
	},
	replaceSelection: function(text){
		var scroll_top = this.element.scrollTop;
		if(!!document.selection){
			this.element.focus();
			var range = (this.range) ? this.range : document.selection.createRange();
			range.text = text;
			range.select();
		}else if(!!this.element.setSelectionRange){
			var selection_start = this.element.selectionStart;
			this.element.value = this.element.value.substring(0,selection_start) + text + this.element.value.substring(this.element.selectionEnd);
			this.element.setSelectionRange(selection_start + text.length,selection_start + text.length);
		}
		this.doOnChange();
		this.element.focus();
		this.element.scrollTop = scroll_top;
	},
	wrapSelection: function(before,after){
		this.replaceSelection(before + this.getSelection() + after);
	},
	insertBeforeSelection: function(text){
		this.replaceSelection(text + this.getSelection());
	},
	insertAfterSelection: function(text){
		this.replaceSelection(this.getSelection() + text);
	},
	collectFromEachSelectedLine: function(callback,before,after){
		this.replaceSelection((before || '') + $A(this.getSelection().split("\n")).collect(callback).join("\n") + (after || ''));
	},
	insertBeforeEachSelectedLine: function(text,before,after){
		this.collectFromEachSelectedLine(function(line){
		},before,after);
	}
});
Object.extend(Control.TextArea,{
	onChangeTimeoutLength: 500
});
Object.Event.extend(Control.TextArea);

Control.TextArea.ToolBar = Class.create(	{
	initialize: function(textarea,toolbar){
		this.textarea = textarea;
		if(toolbar)
			this.container = $(toolbar);
		else{
			this.container = $(document.createElement('ul'));
			this.textarea.element.parentNode.insertBefore(this.container,this.textarea.element);
		}
	},
	attachButton: function(node,callback){
		node.onclick = function(){ return false; };
		$(node).observe('click',callback.bindAsEventListener(this.textarea));
	},
	addButton: function(link_text,callback,attrs){
		var li = document.createElement('li');
		var a = document.createElement('a');
		a.href = '#';
		this.attachButton(a,callback);
		li.appendChild(a);
		Object.extend(a,attrs || {});
		if(link_text){
			var span = document.createElement('span');
			span.innerHTML = link_text;
			a.appendChild(span);
		}
		this.container.appendChild(li);
	}
});


Control.TextArea.ToolBar.prototype.addModalButton = function(link_text, result_parser, a_attrs, modal_content, selection_input_index){
  
  // make an array with modal_content, if it's a string:
  if( Object.isString(modal_content)){ modal_content = [modal_content]; };
  
  var li = new Element('li');
  var a = new Element('a', { href: '#' + link_text, title: link_text } );
  
  if(link_text){
    var span = new Element('span');
    span.update(link_text);
    a.insert(span);
  }
  
  // insert the link into the toolbar:
  Object.extend(a, a_attrs || {});
  this.container.insert(li);
  li.insert(a);
  
  // create the modal:
  var modal = new Control.Modal(a, {
    position: 'relative',
    offsetTop: 18,
    offsetLeft: this.container.positionedOffset()[0] - li.positionedOffset()[0],
    width: 448,
    fade: false,
    overlayOpacity: 0.2
  } );
  modal.container.className = 'textile_modal';
  modal.container.modal = modal; // to be able to access the modal from the links
  modal.textarea = this.textarea; // to be able to access the textarea from the modal
  
  // for each modal_content create the content and one input element:
  modal.result_inputs = [];
  modal_content.each(function(mc, index){
    wrapped_mc = new Element('div', {'class': 'modal_content'} );
    wrapped_mc.update(mc);
    modal.container.insert(wrapped_mc);
    
    modal.result_inputs[index] = new Element('input', { type: 'text', size:50 });
    modal.container.insert(modal.result_inputs[index]);
  });
  
  modal.observe('beforeOpen', function(){
    // var the_modal = modal;
    modal.container.select('a.ajax_link').each(function(ajax_link){
      new Ajax.Request(ajax_link.href,{
        method: 'get',
        onSuccess: function(request){
          var r = new Element('div');
          r.insert(request.responseText);
          ajax_link.replace(r);
          r.select('input, select, textarea').each(function(i){ modal.result_inputs.push(i); });
        }.bind(this)
      });
    });
  });
  
  // focus the first input, that isn't already prefilled by the selection:
  if(selection_input_index==0){ var focus = 1; } else { var focus = 0; };
  modal.observe('afterOpen', function(){ modal.result_inputs[focus].focus(); });
  
  // fill the selection into the input indicated by the selection_input_index parameter:
  if(selection_input_index != undefined){
    modal.observe('afterOpen', function(){ modal.result_inputs[selection_input_index].value = modal.textarea.getSelection(); });
  };
  
  // a container for the buttons:
  var modal_buttons = new Element('div', { 'class': 'modal_buttons' });
  modal.container.insert(modal_buttons);
  
  // create the CANCEL button:
  var close_link = new Element('a', { 'class': 'textile_modal_close_link', href: '#cancel' });
  close_link.update('abbrechen').observe('click', function(){ this.up('.textile_modal').modal.close(); });
  modal_buttons.insert(close_link);
  
  // create the INSERT button:
  var ok_link = new Element('a', { 'class': 'textile_modal_ok_link', href: '#insert' });
  ok_link.update('einfÃ¼gen').observe('click', function(){ this.up('.textile_modal').modal.close(); });
  this.attachButton(ok_link, function(){
    var result = modal.result_inputs.map( function(ri){ return ri.value; } );
    
    if(!result.include('')){
      result = result_parser( result.reduce() );
      this.replaceSelection(result);
    };
  });
  modal_buttons.insert(ok_link);
  
};


// Changed it to use protoypes getElementsBySelector function instead of it's own. -nd-
// Also we're using our own addLoadEvent (application.js).  behaviour.js isn't selfcontained any more anyway. -nd-

/*
   Behaviour v1.1 by Ben Nolan, June 2005. Based largely on the work
   of Simon Willison (see comments by Simon below).

   Description:
   	
   	Uses css selectors to apply javascript behaviours to enable
   	unobtrusive javascript in html documents.
   	
   Usage:   
   
	var myrules = {
		'b.someclass' : function(element){
			element.onclick = function(){
				alert(this.innerHTML);
			}
		},
		'#someid u' : function(element){
			element.onmouseover = function(){
				this.innerHTML = "BLAH!";
			}
		}
	};
	
	Behaviour.register(myrules);
	
	// Call Behaviour.apply() to re-apply the rules (if you
	// update the dom, etc).

   License:
   
   	This file is entirely BSD licensed.
   	
   More information:
   	
   	http://ripcord.co.nz/behaviour/
   
*/   

var Behaviour = {
	list : new Array,
	
	clear : function() {
	  Behaviour.list = new Array;
	},
	
	register : function(sheet){
		Behaviour.list.push(sheet);
	},
	
	start : function(){
		addLoadEvent(function(){
			Behaviour.apply();
		});
	},
	
	apply : function(node){
		for (h=0;sheet=Behaviour.list[h];h++){
			for (selector in sheet){
				list = $$(selector); // has been getElementsBySelector before, but we have prototype. -nd- 2008-09-08
				
				if (!list){
					continue;
				}

				for (i=0;element=list[i];i++){
				  if (!node || this.isParentOrEqual(node, element)) {
					  sheet[selector](element);
				  }
				}
			}
		}
	},
	
	isParentOrEqual : function(parent, node) {
	  do {
	    if (parent == node) {
	      return true;
	    }
	    node = node.parentNode;
	  } while (node);
	  return false;
	}
};

Behaviour.start();


// Deactivates onclick callback for elements with this class after a click.
//
var single_click_rules = {

  '.single_click': function(el) {
    var old_onclick = el.onclick;
    if (old_onclick) {
      el.onclick = function() {
        old_onclick();
        el.onclick = function() {return false;};
        return false;
      };
    }
  }
};

Behaviour.register(single_click_rules);

var form_rules = {
  '.value_label' : function(element) {
    element.onfocus = function() {
      dv = (element.readAttribute('defaultValue') || element.defaultValue);
      if (element.value == dv) {
        element.value = '';
        if (element.hasClassName('password')) { element.type = 'password'; }
      }
    };
    element.onblur  = function() {
      dv = (element.readAttribute('defaultValue') || element.defaultValue);
      if (element.value == '') {
        element.value = dv;
        if (element.hasClassName('password')) { element.type = 'text'; }
      }
    };
  },
  
  '.vignette_as_label' : function(el) {
    var name = el.id.match(/label_for_(.*)/)[1];
    var radio_button_id = 'radio_button_for_' + name;
    
    var elements = Array.from(el.descendants);
    elements.push(el);
    
    elements.each( function(item) {
      item.onclick = function() {
        $(radio_button_id).checked = true;
        return false;
      }; 
    });
  }
};

var autocompleter_rules = {
  '.id_agnostic_autocompleter'          : function(element){ Restorm.id_agnostic_autocompleter(element);          },
  '.id_agnostic_band_autocompleter'     : function(element){ Restorm.id_agnostic_band_autocompleter(element);     },
  '.id_agnostic_profile_autocompleter'  : function(element){ Restorm.id_agnostic_profile_autocompleter(element);  },
  '.id_agnostic_venue_autocompleter'    : function(element){ Restorm.id_agnostic_venue_autocompleter(element);    },
  '.id_agnostic_member_autocompleter'   : function(element){ Restorm.id_agnostic_member_autocompleter(element);   },
  '.id_agnostic_band_name_autocompleter': function(element){ Restorm.id_agnostic_band_name_autocompleter(element);}
};

var textile_textarea_rules = {
  '.textile.add_toolbar' : function(element){
    element.removeClassName('add_toolbar');
    var textarea = new Control.TextArea(element);
    var toolbar = new Control.TextArea.ToolBar(textarea);
    toolbar.container.className = 'textile_toolbar';
    
    var description = new Element('li');
    description.addClassName('toolbar-description');
    description.update('Format: ');
    toolbar.container.appendChild(description);
    
    toolbar.addButton('Ãœberschrift', function(){ this.insertBeforeSelection('h1. '); },{ className: 'textile_header_button', title: 'Ãœberschrift' });
    toolbar.addButton('Fett', function(){ this.wrapSelection('*','*'); },{ className: 'textile_bold_button', title: 'Fett' });
    toolbar.addButton('AufzÃ¤hlung', function(event){
        this.collectFromEachSelectedLine(function(line){
          return event.shiftKey ? (line.match(/^\*{2,}/) ? line.replace(/^\*/,'') : line.replace(/^\*\s/,'')) : (line.match(/\*+\s/) ? '*' : '* ') + line;
        }); 
    },{ className: 'textile_ul_button', title: 'AufzÃ¤hlung' });
    
    toolbar.addModalButton('Link', parse_link, { className: 'textile_link_button' }, ['Linktext:','Link-Ziel (URL mit "http://"):'], 0);
    toolbar.addModalButton('Bild', parse_image, { className: 'textile_image_button' }, 'Bild-URL (mit "http://"):');
    toolbar.addModalButton('Verlinktes Bild', parse_linked_image, { className: 'textile_linked_image_button' }, ['Bild-URL (mit "http://"):','Link-Ziel (URL mit "http://")):'], 0);
    
    var br = new Element('br');
    toolbar.container.appendChild(br);
    
    var description = new Element('li');
    description.addClassName('toolbar-description');
    description.update('Widgets: ');
    toolbar.container.appendChild(description);
    
    var song_list_link = '<a class="ajax_link" href="/videos/song_list"></a><br/>';
    
    var descr = 'URL der YouTube-Seite kopieren und einfÃ¼gen: <br/><img src="/images/textile_textarea/youtube_url.png" />';
    toolbar.addModalButton('YouTube Video', parse_youtube,  { className: 'textile_youtube_button' }, song_list_link+descr);
    
    var descr = 'URL der Vimeo-Seite kopieren und einfÃ¼gen: <br/><img src="/images/textile_textarea/vimeo_url.png"/>';
    toolbar.addModalButton('Vimeo Video', parse_vimeo,  { className: 'textile_vimeo_button' }, song_list_link+descr);
    
    var descr = 'URL der MySpace-Video-Seite kopieren und einfÃ¼gen: <br/><br/><img src="/images/textile_textarea/myspace_url.png" />';
    toolbar.addModalButton('MySpace Video', parse_myspace_video,  { className: 'textile_myspace_video_button' }, song_list_link+descr);
    
    var descr = 'URL deiner Kyte-Kanal-Seite kopieren und einfÃ¼gen: <br/><img src="/images/textile_textarea/kyte_url.png"/>';
    toolbar.addModalButton('Kyte Video', parse_kyte,  { className: 'textile_kyte_button' }, descr);
    
    var descr = 'URL deiner Flickr-Seite kopieren und hier einfÃ¼gen: <br/><img src="/images/textile_textarea/flickr_url.png" />';
    toolbar.addModalButton('Flickr', parse_flickr,  { className: 'textile_flickr_button' }, descr);
    
    var descr = 'Auf Picasa beliebigen Feed abonnieren (<img src="/images/textile_textarea/feed.png" style="margin-bottom:-5px;" />), Feed-URL kopieren und hier einfÃ¼gen: <br/><img src="/images/textile_textarea/picasa_url.png" />';
    toolbar.addModalButton('Picasa', parse_picasa,  { className: 'textile_picasa_button' }, descr);
    
    var descr = 'URL deiner Tumblr-Seite kopieren und einfÃ¼gen: <br/><img src="/images/textile_textarea/tumblr_url.png" />';
    toolbar.addModalButton('Tumblr', parse_tumblr,  { className: 'textile_tumblr_button' }, descr);
    
    var descr = 'URL deiner FriendFeed-Seite kopieren und einfÃ¼gen: <br/><img src="/images/textile_textarea/friendfeed_url.png" />';
    toolbar.addModalButton('FriendFeed', parse_friendfeed,  { className: 'textile_friendfeed_button' }, descr);
    
    var descr = 'URL deiner Twitter-Seite kopieren und einfÃ¼gen: <br/><img src="/images/textile_textarea/twitter_url.png" />';
    toolbar.addModalButton('Twitter', parse_twitter,  { className: 'textile_twitter_button' }, descr);
    
    
    
    // var descr = '<a class="ajax_link" href="/videos/song_list"></a>';
    // toolbar.addModalButton('YouTube', parse_youtube_songlist,  { className: 'textile_youtube_button' }, descr);
    
  }
};

Behaviour.register(form_rules);
Behaviour.register(autocompleter_rules);
Behaviour.register(textile_textarea_rules);

// Reloads the behaviour for the autocompleter
function reloadAutocompleterRules(){
  Behaviour.clear();
  Behaviour.register(autocompleter_rules);
  Behaviour.apply();
}

var Restorm = {

  // Traverses the DOM-tree upwards starting at the given 'element',
  // checks each descendant for the given 'classname' and returns this
  // descendant.
  //
  // p.e. (in HAML notation)
  //
  //  .class_a
  //    .class_z
  //    .class_b
  //      .class_z
  //        Hello World!
  //      #the_element
  //
  // find_closest_element_with_classname($('the_element'),'class_z')
  // will return the "Hello World"-node as it doesn't even traverse the
  // .class_a node.
  //
  // Be careful to avoid ambiguity.
  //
  find_closest_element_with_classname: function(element, classname){
    var element_with_classname;
    element.ancestors().each(
      function(e){
        element_with_classname = e.down('.'+classname);
        if( element_with_classname != undefined ){ throw $break; };
      }
    );
    return element_with_classname;
  },

  // First fades the element and then removes it from the DOM.
  fade_and_remove: function(element) {
    new Effect.Fade(element, {duration: 0.5});
    setTimeout(function() {
      $(element).remove(); 
    }, 500);
  },

  // This autocompleter works without a specified element or element.id
  // of the result-div. It's added (with class'auto_complete' as that's the
  // Rails convention) automagically.
  // The input_field on which it's applied should have the attribute 'autocomplete_url'
  // containing the url of the controller and action for the autocompletion.
  //
  // p.e.
  //
  //  = f.text_field :url, :class => 'auto_complete', :autocomplete_url => '/acts/auto_complete_for_band_name'
  //
  //
  // The autocompleter also prevents any links inside the result list to be clicked.
  //
  id_agnostic_autocompleter: function(element, options){
    
    // We need to remove the autocompleter class-name to prevent the same behaviour being applied twice
    // to the same input field and the results div being added twice.
    element.className = element.className.replace(/id_agnostic_.*autocompleter/g , '');
    
    // Append the results div to the element:
    results = document.createElement('div');
    results.className = 'auto_complete';
    element.parentNode.appendChild(results);
    
    if(name = element.getAttribute('param_name')) {
      options = Object.extend({ paramName: name }, options);
    }
    
    // Get the autocomplete-url and delete the protocol and domain
    url = element.getAttribute('autocomplete_url');
    
    // We use 'get' to make the forgery protection not kick in:
    options = Object.extend({ method: 'get' }, options);
    
    autocompleter = new Ajax.Autocompleter(element, results, url, options);
    
    oldOnClick = autocompleter.onClick;
    autocompleter.onClick = function(event) {
      // do not issue a click event on the link
      // remark: the prototype method Event.stop does not work in IE6/7.
      // Therefore we made the code inline.
      if (event.preventDefault) {
        event.preventDefault();
        event.stopPropagation();
      } else {
        event.returnValue = false;
        event.cancelBubble = true;
      }
      
      // apply the old onClick code in the context of the autocompleter
      oldOnClick.call(this, event);
      
    };
  },

  // This autocompleter is made for the needs of member-autocompletion
  //
  id_agnostic_member_autocompleter: function(element){
    Restorm.id_agnostic_autocompleter(element, {minChars:3, select:'choice', tokens:',', paramName:'member_name'});
    element.onblur = function(){ element.value = element.value.gsub(/[, ]*$/,''); };
  },
  
  // This autocompleter is made for the needs of member-autocompletion
  //
  id_agnostic_band_name_autocompleter: function(element){
    Restorm.id_agnostic_autocompleter(element, {minChars:2, select:'choice', tokens:',', paramName:'band_name'});
    element.onblur = function(){ element.value = element.value.gsub(/[, ]*$/,''); };
  },

  // This autocompleter is made for the special needs of the band autocompletion
  // including band_id, restorm_page_link, band homepage link and soundsample link.
  //
  // TODO: merge options hash.
  //
  id_agnostic_band_autocompleter: function(element){
    Restorm.id_agnostic_autocompleter(element,
      {minChars:2, select:'choice',
        afterUpdateElement:function(element, selected){

          band_id                   = selected.readAttribute('band_id');
          band_vignette             = selected.down('.vignette');

          band_id_field             = Restorm.find_closest_element_with_classname(element, 'band_id_field');
          band_name_field           = Restorm.find_closest_element_with_classname(element, 'band_name_field');
          band_link_field           = Restorm.find_closest_element_with_classname(element, 'band_link_field');
          restorm_band_vignette     = Restorm.find_closest_element_with_classname(element, 'restorm_band_vignette');

          band_id_field.value = band_id;
          band_name_field.value = '';
          band_name_field.up('li').hide();
          band_link_field.value = '';
          band_link_field.up('li').hide();

          restorm_band_vignette.show();
          restorm_band_vignette.appendChild(band_vignette);
        }
      }
    );
  },

  // This autocompleter is made for selecting receivers on message compose view.
  //
  id_agnostic_profile_autocompleter: function(element){
    Restorm.id_agnostic_autocompleter(element,
      {minChars:2, select:'choice',
        afterUpdateElement:function(element, selected){
          profile_id = selected.readAttribute('profile_id');
          profile_token = selected.down('.profile_token');
          profile_token.show();

          token_id = document.createElement('input');
          token_id.type = 'hidden';
          token_id.name = 'message[receiver_ids][]';
          token_id.value = profile_id;
          token = document.createElement('div');
          token.className = 'receiver_token';
          token.appendChild(token_id);
          token.appendChild(profile_token);
          
          $('receiver_list').appendChild(token);
        }
      }
    );
  },
  
  id_agnostic_venue_autocompleter: function(element){
    Restorm.id_agnostic_autocompleter(element,
      {minChars:2, select:'choice',
        afterUpdateElement:function(element, selected){

          venue_id                   = selected.readAttribute('venue_id');
          venue_vignette             = selected.down('.vignette');

          $$('#venue_id_field').each(function(el){ el.value = venue_id; });
          $('venue_name_field').up('li').remove();
          $('venue_link_field').up('li').remove();

          $('restorm_venue_vignette').show();
          $('restorm_venue_vignette').appendChild(venue_vignette);
        }
      }
    );
  }, 
  
  replace_descendant_ids: function(element, field, newIndex) {
    var newElement = $(element);
    var descendants = newElement.descendants();
    
    descendants.select(
      function(el) { return el.id.startsWith(field + '_'); }
    ).each(
      function(el){ 
        el.id = el.id.sub(field +"_(\\-\\\d+)?_", field+'_'+newIndex+'_'); 
      }
    );
    
    descendants.select(
      function(el) { return el.hasAttribute('name') && el.readAttribute('name').startsWith(field + '['); }
    ).each(
      function(el){ 
        el.setAttribute('name', el.readAttribute('name').sub(field +"\\[(\\-\\\d+)?\\]", field+'['+newIndex+']')); 
      }
    );
    
    descendants.select(
      function(el) { return el.tagName == 'LABEL'; }
    ).each(
      function(el){ 
        el.setAttribute('for', el.readAttribute('for').sub(field+"_(\\-\\\d+)?_", field+'_'+newIndex+'_'));
      }
    );
  }
  
};


// this is an extra file so we can conviniently test the functions here: textile_toolbar_test.html

var parse_link = function(results){
  if (results[0] == '' || results[1] == ''){ return(''); };
  return '"' + results[0].strip() + '":' + results[1].strip() + ' ';
};

var parse_image = function(string){ return "!" + string.strip() + "!"; };

var parse_linked_image = function(results){
  if (results[0] == '' || results[1] == ''){ return(''); };
  return '!' + results[0].strip() + '!:' + results[1].strip() + ' ';
};


parse_youtube = function(results){
  return video_with_songlist(results, youtube_tag_from);
};
parse_vimeo = function(results){
  return video_with_songlist(results, vimeo_tag_from);
};
parse_myspace_video = function(results){
  return video_with_songlist(results, myspace_video_tag_from);
};

youtube_tag_from = function(string){
  return string.gsub(/.*[&\?]v=([^&"]+).*/, "\nyoutube:#{1}").gsub(/.*#play\/all\/uploads-all\/[0-9]+\/([^&"]+).*/, "\nyoutube:#{1}");
};
vimeo_tag_from = function(string){
  return string.gsub(/.*vimeo\.com\/([0-9]+)/, "\nvimeo:#{1}");
};
myspace_video_tag_from = function(string){
  return string.gsub(/.*[&\?]videoid=([^&"]+).*/i, "\nmyspace_video:#{1}");
};

video_with_songlist = function(results, tag_parser){
  if(typeof results == 'string'){ results = [results]; }
  tag = tag_parser(results[0]);
  if (typeof results[1] == 'string' && results[1] != '-'){ tag = tag + '/' + results[1]; }
  return tag + "\n\n";
};


parse_kyte = function(string){
  return string.gsub(/.*www\.kyte\.tv\/.*ch(annels)?\/([0-9]+).*/, "\n\kyte:#{2}\n\n");
};


parse_flickr = function(string){
  return string.gsub(/.*flickr\.com\/photos\/([^\/]+)(\/.*)?/, "\nflickr:#{1}\n\n");
};

parse_picasa = function(string){
  return "\n\npicasa:" + string.strip() + "\n\n";
};

parse_tumblr = function(string){
  return string.gsub(/http:\/\/([^\.]+).tumblr.com.*/, "\ntumblr:#{1}\n\n");
};

parse_friendfeed = function(string){
  return string.gsub(/http:\/\/friendfeed.com\/([^\/]+).*/, "\nfriendfeed:#{1}\n\n");
};

parse_twitter = function(string){
  return string.gsub(/http:\/\/twitter.com\/([^\/]+).*/, "\ntwitter:#{1}\n\n");
};



/*
   SoundManager 2: Javascript Sound for the Web
   --------------------------------------------
   http://schillmania.com/projects/soundmanager2/

   Copyright (c) 2008, Scott Schiller. All rights reserved.
   Code licensed under the BSD License:
   http://schillmania.com/projects/soundmanager2/license.txt

   V2.94a.20090206
*/
var soundManager=null;function SoundManager(b,a){this.flashVersion=8;this.debugMode=true;this.useConsole=true;this.consoleOnly=false;this.waitForWindowLoad=false;this.nullURL="null.mp3";this.allowPolling=true;this.useMovieStar=false;this.bgColor="#ffffff";this.useHighPerformance=false;this.flashLoadTimeout=750;this.defaultOptions={autoLoad:false,stream:true,autoPlay:false,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onstop:null,onfinish:null,onbeforefinish:null,onbeforefinishtime:5000,onbeforefinishcomplete:null,onjustbeforefinish:null,onjustbeforefinishtime:200,multiShot:true,position:null,pan:0,volume:100};this.flash9Options={onbufferchange:null,isMovieStar:null,usePeakData:false,useWaveformData:false,useEQData:false};this.movieStarOptions={onmetadata:null,useVideo:false};var f=null;var e=this;this.version=null;this.versionNumber="V2.94a.20090206";this.movieURL=null;this.url=null;this.altURL=null;this.swfLoaded=false;this.enabled=false;this.o=null;this.id=(a||"sm2movie");this.oMC=null;this.sounds={};this.soundIDs=[];this.muted=false;this.wmode=null;this.isIE=(navigator.userAgent.match(/MSIE/i));this.isSafari=(navigator.userAgent.match(/safari/i));this.isGecko=(navigator.userAgent.match(/gecko/i));this.debugID="soundmanager-debug";this._debugOpen=true;this._didAppend=false;this._appendSuccess=false;this._didInit=false;this._disabled=false;this._windowLoaded=false;this._hasConsole=(typeof console!="undefined"&&typeof console.log!="undefined");this._debugLevels=["log","info","warn","error"];this._defaultFlashVersion=8;this._oRemoved=null;this._oRemovedHTML=null;var g=function(h){return document.getElementById(h)};this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.netStreamTypes=["aac","flv","mov","mp4","m4v","f4v","m4a","mp4v","3gp","3g2"];this.netStreamPattern=new RegExp("\\.("+this.netStreamTypes.join("|")+")(\\?.*)?$","i");this.filePattern=null;this.features={buffering:false,peakData:false,waveformData:false,eqData:false,movieStar:false};this.sandbox={type:null,types:{remote:"remote (domain-based) rules",localWithFile:"local with file access (no internet access)",localWithNetwork:"local with network (internet access only, no local access)",localTrusted:"local, trusted (local + internet access)"},description:null,noRemote:null,noLocal:null};this._setVersionInfo=function(){if(e.flashVersion!=8&&e.flashVersion!=9){alert('soundManager.flashVersion must be 8 or 9. "'+e.flashVersion+'" is invalid. Reverting to '+e._defaultFlashVersion+".");e.flashVersion=e._defaultFlashVersion}e.version=e.versionNumber+(e.flashVersion==9?" (AS3/Flash 9)":" (AS2/Flash 8)");if(e.flashVersion>8){e.defaultOptions=e._mergeObjects(e.defaultOptions,e.flash9Options);e.features.buffering=true}if(e.flashVersion>8&&e.useMovieStar){e.defaultOptions=e._mergeObjects(e.defaultOptions,e.movieStarOptions);e.filePatterns.flash9=new RegExp("\\.(mp3|"+e.netStreamTypes.join("|")+")(\\?.*)?$","i");e.features.movieStar=true}else{e.useMovieStar=false;e.features.movieStar=false}e.filePattern=e.filePatterns[(e.flashVersion!=8?"flash9":"flash8")];e.movieURL=(e.flashVersion==8?"soundmanager2.swf":"soundmanager2_flash9.swf");e.features.peakData=e.features.waveformData=e.features.eqData=(e.flashVersion==9)};this._overHTTP=(document.location?document.location.protocol.match(/http/i):null);this._waitingforEI=false;this._initPending=false;this._tryInitOnFocus=(this.isSafari&&typeof document.hasFocus=="undefined");this._isFocused=(typeof document.hasFocus!="undefined"?document.hasFocus():null);this._okToDisable=!this._tryInitOnFocus;this.useAltURL=!this._overHTTP;var d="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html";this.supported=function(){return(e._didInit&&!e._disabled)};this.getMovie=function(h){return e.isIE?window[h]:(e.isSafari?g(h)||document[h]:g(h))};this.loadFromXML=function(h){try{e.o._loadFromXML(h)}catch(i){e._failSafely();return true}};this.createSound=function(i){if(!e._didInit){throw new Error("soundManager.createSound(): Not loaded yet - wait for soundManager.onload() before calling sound-related methods")}if(arguments.length==2){i={id:arguments[0],url:arguments[1]}}var j=e._mergeObjects(i);var h=j;if(e._idCheck(h.id,true)){return e.sounds[h.id]}if(e.flashVersion>8&&e.useMovieStar){if(h.isMovieStar===null){h.isMovieStar=(h.url.match(e.netStreamPattern)?true:false)}if(h.isMovieStar&&(h.usePeakData||h.useWaveformData||h.useEQData)){h.usePeakData=false;h.useWaveformData=false;h.useEQData=false}}e.sounds[h.id]=new f(h);e.soundIDs[e.soundIDs.length]=h.id;if(e.flashVersion==8){e.o._createSound(h.id,h.onjustbeforefinishtime)}else{e.o._createSound(h.id,h.url,h.onjustbeforefinishtime,h.usePeakData,h.useWaveformData,h.useEQData,h.isMovieStar,(h.isMovieStar?h.useVideo:false))}if(h.autoLoad||h.autoPlay){if(e.sounds[h.id]){e.sounds[h.id].load(h)}}if(h.autoPlay){e.sounds[h.id].play()}return e.sounds[h.id]};this.createVideo=function(h){if(arguments.length==2){h={id:arguments[0],url:arguments[1]}}if(e.flashVersion>=9){h.isMovieStar=true;h.useVideo=true}else{return false}return e.createSound(h)};this.destroySound=function(j,h){if(!e._idCheck(j)){return false}for(var k=0;k<e.soundIDs.length;k++){if(e.soundIDs[k]==j){e.soundIDs.splice(k,1);continue}}e.sounds[j].unload();if(!h){e.sounds[j].destruct()}delete e.sounds[j]};this.destroyVideo=this.destroySound;this.load=function(h,i){if(!e._idCheck(h)){return false}e.sounds[h].load(i)};this.unload=function(h){if(!e._idCheck(h)){return false}e.sounds[h].unload()};this.play=function(h,i){if(!e._idCheck(h)){if(typeof i!="Object"){i={url:i}}if(i&&i.url){i.id=h;e.createSound(i)}else{return false}}e.sounds[h].play(i)};this.start=this.play;this.setPosition=function(h,i){if(!e._idCheck(h)){return false}e.sounds[h].setPosition(i)};this.stop=function(h){if(!e._idCheck(h)){return false}e.sounds[h].stop()};this.stopAll=function(){for(var h in e.sounds){if(e.sounds[h] instanceof f){e.sounds[h].stop()}}};this.pause=function(h){if(!e._idCheck(h)){return false}e.sounds[h].pause()};this.pauseAll=function(){for(var h=e.soundIDs.length;h--;){e.sounds[e.soundIDs[h]].pause()}};this.resume=function(h){if(!e._idCheck(h)){return false}e.sounds[h].resume()};this.resumeAll=function(){for(var h=e.soundIDs.length;h--;){e.sounds[e.soundIDs[h]].resume()}};this.togglePause=function(h){if(!e._idCheck(h)){return false}e.sounds[h].togglePause()};this.setPan=function(h,i){if(!e._idCheck(h)){return false}e.sounds[h].setPan(i)};this.setVolume=function(i,h){if(!e._idCheck(i)){return false}e.sounds[i].setVolume(h)};this.mute=function(h){if(typeof h!="string"){h=null}if(!h){for(var j=e.soundIDs.length;j--;){e.sounds[e.soundIDs[j]].mute()}e.muted=true}else{if(!e._idCheck(h)){return false}e.sounds[h].mute()}};this.muteAll=function(){e.mute()};this.unmute=function(h){if(typeof h!="string"){h=null}if(!h){for(var j=e.soundIDs.length;j--;){e.sounds[e.soundIDs[j]].unmute()}e.muted=false}else{if(!e._idCheck(h)){return false}e.sounds[h].unmute()}};this.unmuteAll=function(){e.unmute()};this.getMemoryUse=function(){if(e.flashVersion==8){return 0}if(e.o){return parseInt(e.o._getMemoryUse(),10)}};this.setPolling=function(h){if(!e.o||!e.allowPolling){return false}e.o._setPolling(h)};this.disable=function(j){if(typeof j=="undefined"){j=false}if(e._disabled){return false}e._disabled=true;for(var h=e.soundIDs.length;h--;){e._disableObject(e.sounds[e.soundIDs[h]])}e.initComplete(j)};this.canPlayURL=function(h){return(h?(h.match(e.filePattern)?true:false):null)};this.getSoundById=function(i,j){if(!i){throw new Error("SoundManager.getSoundById(): sID is null/undefined")}var h=e.sounds[i];return h};this.onload=function(){soundManager._wD("<em>Warning</em>: soundManager.onload() is undefined.",2)};this.onerror=function(){};this._idCheck=this.getSoundById;var c=function(){return false};c._protected=true;this._disableObject=function(i){for(var h in i){if(typeof i[h]=="function"&&typeof i[h]._protected=="undefined"){i[h]=c}}h=null};this._failSafely=function(h){if(typeof h=="undefined"){h=false}if(!e._disabled||h){e.disable(h)}};this._normalizeMovieURL=function(h){var i=null;if(h){if(h.match(/\.swf(\?.*)?$/i)){i=h.substr(h.toLowerCase().lastIndexOf(".swf?")+4);if(i){return h}}else{if(h.lastIndexOf("/")!=h.length-1){h=h+"/"}}}return(h&&h.lastIndexOf("/")!=-1?h.substr(0,h.lastIndexOf("/")+1):"./")+e.movieURL};this._getDocument=function(){return(document.body?document.body:(document.documentElement?document.documentElement:document.getElementsByTagName("div")[0]))};this._getDocument._protected=true;this._createMovie=function(n,l){if(e._didAppend&&e._appendSuccess){return false}if(window.location.href.indexOf("debug=1")+1){e.debugMode=true}e._didAppend=true;e._setVersionInfo();var u=(l?l:e.url);var k=(e.altURL?e.altURL:u);e.url=e._normalizeMovieURL(e._overHTTP?u:k);l=e.url;var m=null;if(e.useHighPerformance&&e.useMovieStar){m="Note: disabling highPerformance, not applicable with movieStar mode on";e.useHighPerformance=false}e.wmode=(e.useHighPerformance&&!e.useMovieStar?"transparent":"");var t={name:n,id:n,src:l,width:"100%",height:"100%",quality:"high",allowScriptAccess:"always",bgcolor:e.bgColor,pluginspage:"http://www.macromedia.com/go/getflashplayer",type:"application/x-shockwave-flash",wmode:e.wmode};var w={id:n,data:l,type:"application/x-shockwave-flash",width:"100%",height:"100%",wmode:e.wmode};var o={movie:l,AllowScriptAccess:"always",quality:"high",bgcolor:e.bgColor,wmode:e.wmode};var j=null;var r=null;if(e.isIE){j=document.createElement("div");var h='<object id="'+n+'" data="'+l+'" type="application/x-shockwave-flash" width="100%" height="100%"><param name="movie" value="'+l+'" /><param name="AllowScriptAccess" value="always" /><param name="quality" value="high" />'+(e.useHighPerformance&&!e.useMovieStar?'<param name="wmode" value="'+e.wmode+'" /> ':"")+'<param name="bgcolor" value="'+e.bgColor+'" /><!-- --></object>'}else{j=document.createElement("embed");for(r in t){if(t.hasOwnProperty(r)){j.setAttribute(r,t[r])}}}var q="soundManager._createMovie(): appendChild/innerHTML set failed. May be app/xhtml+xml DOM-related.";var i=e._getDocument();if(i){e.oMC=g("sm2-container")?g("sm2-container"):document.createElement("div");if(!e.oMC.id){e.oMC.id="sm2-container";e.oMC.className="movieContainer";var z=null;var p=null;if(e.useHighPerformance){z={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px"}}else{z={position:"absolute",width:"1px",height:"1px",top:"-999px",left:"-999px"}}var y=null;for(y in z){if(z.hasOwnProperty(y)){e.oMC.style[y]=z[y]}}try{if(!e.isIE){e.oMC.appendChild(j)}i.appendChild(e.oMC);if(e.isIE){p=e.oMC.appendChild(document.createElement("div"));p.className="sm2-object-box";p.innerHTML=h}e._appendSuccess=true}catch(v){throw new Error(q)}}else{e.oMC.appendChild(j);if(e.isIE){p=e.oMC.appendChild(document.createElement("div"));p.className="sm2-object-box";p.innerHTML=h}e._appendSuccess=true}}};this._writeDebug=function(h,j,i){};this._writeDebug._protected=true;this._wdCount=0;this._wdCount._protected=true;this._wD=this._writeDebug;this._toggleDebug=function(){};this._toggleDebug._protected=true;this._debug=function(){};this._debugTS=function(j,h,i){};this._debugTS._protected=true;this._mergeObjects=function(j,h){var m={};for(var k in j){if(j.hasOwnProperty(k)){m[k]=j[k]}}var l=(typeof h=="undefined"?e.defaultOptions:h);for(var n in l){if(l.hasOwnProperty(n)&&typeof m[n]=="undefined"){m[n]=l[n]}}return m};this.createMovie=function(h){if(h){e.url=h}e._initMovie()};this.go=this.createMovie;this._initMovie=function(){if(e.o){return false}e.o=e.getMovie(e.id);if(!e.o){if(!e.oRemoved){e._createMovie(e.id,e.url)}else{if(!e.isIE){e.oMC.appendChild(e.oRemoved)}else{e.oMC.innerHTML=e.oRemovedHTML}e.oRemoved=null;e._didAppend=true}e.o=e.getMovie(e.id)}};this.waitForExternalInterface=function(){if(e._waitingForEI){return false}e._waitingForEI=true;if(e._tryInitOnFocus&&!e._isFocused){return false}if(e.flashLoadTimeout>0){setTimeout(function(){if(!e._didInit&&e._okToDisable){e._failSafely(true)}},e.flashLoadTimeout)}};this.handleFocus=function(){if(e._isFocused||!e._tryInitOnFocus){return true}e._okToDisable=true;e._isFocused=true;if(e._tryInitOnFocus){window.removeEventListener("mousemove",e.handleFocus,false)}e._waitingForEI=false;setTimeout(e.waitForExternalInterface,500);if(window.removeEventListener){window.removeEventListener("focus",e.handleFocus,false)}else{if(window.detachEvent){window.detachEvent("onfocus",e.handleFocus)}}};this.initComplete=function(h){if(e._didInit){return false}e._didInit=true;if(e._disabled||h){e.onerror.apply(window);return false}else{}if(e.waitForWindowLoad&&!e._windowLoaded){if(window.addEventListener){window.addEventListener("load",e.initUserOnload,false)}else{if(window.attachEvent){window.attachEvent("onload",e.initUserOnload)}}return false}else{e.initUserOnload()}};this.initUserOnload=function(){e.onload.apply(window)};this.init=function(){e._initMovie();if(e._didInit){return false}if(window.removeEventListener){window.removeEventListener("load",e.beginDelayedInit,false)}else{if(window.detachEvent){window.detachEvent("onload",e.beginDelayedInit)}}try{e.o._externalInterfaceTest(false);e.setPolling(true);if(!e.debugMode){e.o._disableDebug()}e.enabled=true}catch(h){e._failSafely(true);e.initComplete();return false}e.initComplete()};this.beginDelayedInit=function(){e._windowLoaded=true;setTimeout(e.waitForExternalInterface,500);setTimeout(e.beginInit,20)};this.beginInit=function(){if(e._initPending){return false}e.createMovie();e._initMovie();e._initPending=true;return true};this.domContentLoaded=function(){if(document.removeEventListener){document.removeEventListener("DOMContentLoaded",e.domContentLoaded,false)}e.go()};this._externalInterfaceOK=function(){if(e.swfLoaded){return false}e.swfLoaded=true;e._tryInitOnFocus=false;if(e.isIE){setTimeout(e.init,100)}else{e.init()}};this._setSandboxType=function(h){var i=e.sandbox;i.type=h;i.description=i.types[(typeof i.types[h]!="undefined"?h:"unknown")];if(i.type=="localWithFile"){i.noRemote=true;i.noLocal=false}else{if(i.type=="localWithNetwork"){i.noRemote=false;i.noLocal=true}else{if(i.type=="localTrusted"){i.noRemote=false;i.noLocal=false}}}};this.reboot=function(){if(e.soundIDs.length){}for(var h=e.soundIDs.length;h--;){e.sounds[e.soundIDs[h]].destruct()}try{if(e.isIE){e.oRemovedHTML=e.o.innerHTML}e.oRemoved=e.o.parentNode.removeChild(e.o)}catch(j){}e.enabled=false;e._didInit=false;e._waitingForEI=false;e._initPending=false;e._didInit=false;e._didAppend=false;e._appendSuccess=false;e._didInit=false;e._disabled=false;e._waitingforEI=true;e.swfLoaded=false;e.soundIDs={};e.sounds=[];e.o=null;window.setTimeout(function(){soundManager.beginDelayedInit()},20)};this.destruct=function(){e.disable(true)};f=function(h){var i=this;this.sID=h.id;this.url=h.url;this.options=e._mergeObjects(h);this.instanceOptions=this.options;this._iO=this.instanceOptions;this.pan=this.options.pan;this.volume=this.options.volume;this._debug=function(){if(e.debugMode){var l=null;var n=[];var k=null;var m=null;var j=64;for(l in i.options){if(i.options[l]!==null){if(i.options[l] instanceof Function){k=i.options[l].toString();k=k.replace(/\s\s+/g," ");m=k.indexOf("{");n[n.length]=" "+l+": {"+k.substr(m+1,(Math.min(Math.max(k.indexOf("\n")-1,j),j))).replace(/\n/g,"")+"... }"}else{n[n.length]=" "+l+": "+i.options[l]}}}}};this._debug();this.id3={};this.resetProperties=function(j){i.bytesLoaded=null;i.bytesTotal=null;i.position=null;i.duration=null;i.durationEstimate=null;i.loaded=false;i.playState=0;i.paused=false;i.readyState=0;i.muted=false;i.didBeforeFinish=false;i.didJustBeforeFinish=false;i.isBuffering=false;i.instanceOptions={};i.instanceCount=0;i.peakData={left:0,right:0};i.waveformData=[];i.eqData=[]};i.resetProperties();this.load=function(j){if(typeof j!="undefined"){i._iO=e._mergeObjects(j);i.instanceOptions=i._iO}else{j=i.options;i._iO=j;i.instanceOptions=i._iO}if(typeof i._iO.url=="undefined"){i._iO.url=i.url}if(i._iO.url==i.url&&i.readyState!==0&&i.readyState!=2){return false}i.loaded=false;i.readyState=1;i.playState=0;try{if(e.flashVersion==8){e.o._load(i.sID,i._iO.url,i._iO.stream,i._iO.autoPlay,(i._iO.whileloading?1:0))}else{e.o._load(i.sID,i._iO.url,i._iO.stream?true:false,i._iO.autoPlay?true:false);if(i._iO.isMovieStar&&i._iO.autoLoad&&!i._iO.autoPlay){i.pause()}}}catch(k){e.onerror();e.disable()}};this.unload=function(){if(i.readyState!==0){if(i.readyState!=2){i.setPosition(0,true)}e.o._unload(i.sID,e.nullURL);i.resetProperties()}};this.destruct=function(){e.o._destroySound(i.sID);e.destroySound(i.sID,true)};this.play=function(k){if(!k){k={}}i._iO=e._mergeObjects(k,i._iO);i._iO=e._mergeObjects(i._iO,i.options);i.instanceOptions=i._iO;if(i.playState==1){var j=i._iO.multiShot;if(!j){return false}}if(!i.loaded){if(i.readyState===0){i._iO.stream=true;i._iO.autoPlay=true;i.load(i._iO)}else{if(i.readyState==2){return false}}}if(i.paused){i.resume()}else{i.playState=1;if(!i.instanceCount||e.flashVersion==9){i.instanceCount++}i.position=(typeof i._iO.position!="undefined"&&!isNaN(i._iO.position)?i._iO.position:0);if(i._iO.onplay){i._iO.onplay.apply(i)}i.setVolume(i._iO.volume,true);i.setPan(i._iO.pan,true);e.o._start(i.sID,i._iO.loop||1,(e.flashVersion==9?i.position:i.position/1000))}};this.start=this.play;this.stop=function(j){if(i.playState==1){i.playState=0;i.paused=false;if(i._iO.onstop){i._iO.onstop.apply(i)}e.o._stop(i.sID,j);i.instanceCount=0;i._iO={}}};this.setPosition=function(k,j){if(typeof k=="undefined"){k=0}var l=Math.min(i.duration,Math.max(k,0));i._iO.position=l;e.o._setPosition(i.sID,(e.flashVersion==9?i._iO.position:i._iO.position/1000),(i.paused||!i.playState))};this.pause=function(){if(i.paused||i.playState===0){return false}i.paused=true;e.o._pause(i.sID);if(i._iO.onpause){i._iO.onpause.apply(i)}};this.resume=function(){if(!i.paused||i.playState===0){return false}i.paused=false;e.o._pause(i.sID);if(i._iO.onresume){i._iO.onresume.apply(i)}};this.togglePause=function(){if(!i.playState){i.play({position:(e.flashVersion==9?i.position:i.position/1000)});return false}if(i.paused){i.resume()}else{i.pause()}};this.setPan=function(k,j){if(typeof k=="undefined"){k=0}if(typeof j=="undefined"){j=false}e.o._setPan(i.sID,k);i._iO.pan=k;if(!j){i.pan=k}};this.setVolume=function(j,k){if(typeof j=="undefined"){j=100}if(typeof k=="undefined"){k=false}e.o._setVolume(i.sID,(e.muted&&!i.muted)||i.muted?0:j);i._iO.volume=j;if(!k){i.volume=j}};this.mute=function(){i.muted=true;e.o._setVolume(i.sID,0)};this.unmute=function(){i.muted=false;var j=typeof i._iO.volume!="undefined";e.o._setVolume(i.sID,j?i._iO.volume:i.options.volume)};this._whileloading=function(j,k,l){if(!i._iO.isMovieStar){i.bytesLoaded=j;i.bytesTotal=k;i.duration=Math.floor(l);i.durationEstimate=parseInt((i.bytesTotal/i.bytesLoaded)*i.duration,10);if(i.readyState!=3&&i._iO.whileloading){i._iO.whileloading.apply(i)}}else{i.bytesLoaded=j;i.bytesTotal=k;i.duration=Math.floor(l);i.durationEstimate=i.duration;if(i.readyState!=3&&i._iO.whileloading){i._iO.whileloading.apply(i)}}};this._onid3=function(n,k){var o=[];for(var m=0,l=n.length;m<l;m++){o[n[m]]=k[m]}i.id3=e._mergeObjects(i.id3,o);if(i._iO.onid3){i._iO.onid3.apply(i)}};this._whileplaying=function(k,l,j,m){if(isNaN(k)||k===null){return false}i.position=k;if(i._iO.usePeakData&&typeof l!="undefined"&&l){i.peakData={left:l.leftPeak,right:l.rightPeak}}if(i._iO.useWaveformData&&typeof j!="undefined"&&j){i.waveformData=j}if(i._iO.useEQData&&typeof m!="undefined"&&m){i.eqData=m}if(i.playState==1){if(i._iO.whileplaying){i._iO.whileplaying.apply(i)}if(i.loaded&&i._iO.onbeforefinish&&i._iO.onbeforefinishtime&&!i.didBeforeFinish&&i.duration-i.position<=i._iO.onbeforefinishtime){i._onbeforefinish()}}};this._onload=function(j){j=(j==1?true:false);i.loaded=j;i.readyState=j?3:2;if(i._iO.onload){i._iO.onload.apply(i)}};this._onbeforefinish=function(){if(!i.didBeforeFinish){i.didBeforeFinish=true;if(i._iO.onbeforefinish){i._iO.onbeforefinish.apply(i)}}};this._onjustbeforefinish=function(j){if(!i.didJustBeforeFinish){i.didJustBeforeFinish=true;if(i._iO.onjustbeforefinish){i._iO.onjustbeforefinish.apply(i)}}};this._onfinish=function(){if(i._iO.onbeforefinishcomplete){i._iO.onbeforefinishcomplete.apply(i)}i.didBeforeFinish=false;i.didJustBeforeFinish=false;if(i.instanceCount){i.instanceCount--;if(!i.instanceCount){i.playState=0;i.paused=false;i.instanceCount=0;i.instanceOptions={};if(i._iO.onfinish){i._iO.onfinish.apply(i)}}}else{}};this._onmetadata=function(j){if(!j.width&&!j.height){j.width=320;j.height=240}i.metadata=j;i.width=j.width;i.height=j.height;if(i._iO.onmetadata){i._iO.onmetadata.apply(i)}};this._onbufferchange=function(j){if(j==i.isBuffering){return false}i.isBuffering=(j==1?true:false);if(i._iO.onbufferchange){i._iO.onbufferchange.apply(i)}}};if(window.addEventListener){window.addEventListener("focus",e.handleFocus,false);window.addEventListener("load",e.beginDelayedInit,false);window.addEventListener("unload",e.destruct,false);if(e._tryInitOnFocus){window.addEventListener("mousemove",e.handleFocus,false)}}else{if(window.attachEvent){window.attachEvent("onfocus",e.handleFocus);window.attachEvent("onload",e.beginDelayedInit);window.attachEvent("unload",e.destruct)}else{soundManager.onerror();soundManager.disable()}}if(document.addEventListener){document.addEventListener("DOMContentLoaded",e.domContentLoaded,false)}}soundManager=new SoundManager();

var Playlist = Class.create({
  
  initialize: function() {
    this.list     = new Array();
    this.position = 0;
    
    this.title    = '';
    this.url      = '';
    this.id       = null;
  },
  
  current: function() {
    return this.list[this.position];
  },
  
  add: function(song) {
    this.list.push(song);
  },
  
  next: function() {
    this.position = (this.position + 1) % this.list.length;
  },

  previous: function() {
    if(this.position > 0) this.position = (this.position - 1);
  },
  
  setPosition: function(pos) {
    if(pos == undefined || pos == null) return;
    this.position = pos;
    
    if(this.position < 0)               this.position = 0;
    if(this.position > this.size() - 1) this.position = this.size() - 1;
  },
  
  reorder: function(newIndices) {
    
    var newList = new Array();
    var oldList = this.list;
    $A(newIndices).each(function(i) {
      newList.push(oldList[i]);
    });

    this.list = newList;
    this.setPosition(newIndices.indexOf(this.position.toString()));
  },
  
  remove: function(index) {
    this.list[index] = null;
    this.list = this.list.compact();
  },
  
  clear: function() {
    this.list.clear();
    this.position = 0;
    this.title    = '';
  },
  
  size: function() {
    return this.list.length;
  },
  
  toHTML: function() {
    var result = '';
    
    result += '<ul id="playlist_container">';
    result += '<li class="row title"><div class="cell title">Titel</div><div class="cell artist">Interpret</div><div class="cell download"></div><div class="cell duration">Dauer</div><div class="cell edit"></div></li>';
    
    for(var i = 0; i < this.list.length; i++) {
      var song = this.list[i];
      
      var className = '';
      if(i == this.position) className = 'current';
      
      result += song.playlist_row_html.gsub('_CLASSNAME_', className).gsub('_INDEX_', i);
    }
    result += '</ul>';
    
    return result;
  }
});

// requires playlist.js

STOPPED = 0;
PAUSED  = 1;
PLAYING = 2;

function defaultAfterTrackFunction(player) {
  if(player.getPlaylistSize() > 1)      player.next();
  if(player.getPlaylistPosition() == 0) player.stop();
}

var Player = Class.create({
  
  initialize: function() {
    this.playlist = new Playlist();
    this.state    = STOPPED;
    
    this.allowEditing = true;
    this.expanded     = false;
    
    this.channelURL  = '';
    this.channelName = '';
    
    this.afterTrackFunction = defaultAfterTrackFunction;
  },

  currentSong: function() {
    return this.playlist.current();
  },
  
  playState: function() {
    return this.state;
  },

  clearPlaylist: function() {
    this.stop();
    this.playlist.clear();
    this.triggerUpdate();
  },

  addSong: function(song) {
    this.playlist.add(song);
    this.triggerUpdate();
  },
  
  addSongs: function(songs) {
    var self = this;
    $A(songs).each(function(song) {self.playlist.add(song);});
    this.triggerUpdate();
  },
  
  removeFromPlaylist: function(index) {
    this.playlist.remove(index);
    if(this.getPlaylistSize() == 0) this.stop();
    this.triggerUpdate();
  },

  next: function() {
    if(this.getPlaylistPosition() == this.getPlaylistSize()-1)
      this.setPlaylistPosition(0);
    else
      this.setPlaylistPosition(this.getPlaylistPosition() + 1);
  },

  previous: function() {
    this.setPlaylistPosition(this.getPlaylistPosition() - 1);
  },
  
  getPlaylist: function() {
    return this.playlist;
  },
  
  setPlaylistPosition: function(pos) {
    this.playlist.setPosition(pos);
    if(this.getChannelMode()) this.refreshChannel();
    this.afterPlaylistUpdate();
  },
  
  setPlaylistTitle: function(title) {
    this.playlist.title = title;
  },
  
  getPlaylistTitle: function(title) {
    return this.playlist.title;
  },

  setPlaylistId: function(id) {
    this.playlist.id = id;
  },
  
  afterPlaylistUpdate: function() {
    if(this.state == PAUSED) {
      this.stop();
    }
    if(this.state == PLAYING) {
      this.stop();
      this.play();
    }

    this.triggerUpdate();
  },

  getPlaylistPosition: function() {
    return this.playlist.position;
  },
  
  getPlaylistSize: function() {
    return this.playlist.size();
  },

  play: function() {
    if(this.state == PLAYING) return;

    var song = this.currentSong();
    if(!song) return;
    
    if(this.state == PAUSED) {
      soundManager.resume(song.id);
    } else {
      soundManager.stopAll();
      soundManager.play(song.id, song.filename);
      
      var player = this;
      soundManager.sounds[song.id]._onfinish = function() { player.afterTrackFunction(player); };
      
      // track a listening if the same song is still playing in 15 secs
      setTimeout(function(){ if(player.currentSong().id == song.id && player.state == PLAYING) trackAccess('Audio::Song', song.id, 'listen'); }, 15000);
    }
    
    this.state = PLAYING;
    
    this.triggerUpdate();
  },

  pause: function() {
    var song = this.currentSong();
    if(!song) return;
    
    soundManager.pause(song.id);
    
    this.state = PAUSED;
    
    this.triggerUpdate();
  },
  
  stop: function() {
    soundManager.stopAll();
    this.state = STOPPED;
    
    this.triggerUpdate();
  },
  
  togglePause: function() {
    if(this.state == PLAYING) this.pause();
    else                      this.play();
  },
  
  setPosition: function(percent) {
    song = this.currentSong();
    if(!song) return;
    
    sound = soundManager.sounds[song.id];
    if(sound) sound.setPosition(percent*sound.durationEstimate);
    
    this.triggerUpdate();
  },

  getPosition: function() {
    var song = this.currentSong();
    if(!song || this.state == STOPPED) return;

    var sound = soundManager.sounds[song.id];
    return sound ? (sound.position/sound.durationEstimate) : 0;
  },

  triggerUpdate: function() {
    try {
      if(window.opener) window.opener.document.fire('player:updated');
    } catch(e) {printError(e);}
  },
  
  getAllowEditing: function() {
    return this.allowEditing;
  },
  
  setAllowEditing: function(val) {
    this.allowEditing = (val ? true : false);
    this.triggerUpdate();
  },

  getExpanded: function() {
    return this.expanded;
  },

  setExpanded: function(val) {
    this.expanded = (val ? true : false);
    this.triggerUpdate();
  },
  
  getChannelMode: function() {
    return !!this.channelURL;
  },
  
  getChannelName: function() {
    return this.channelName;
  },

  setChannelMode: function(val) {
    if(val) {
      this.storePlaylist();
      this.clearPlaylist();
      this.channelURL  = val.url;
      this.channelName = val.name;
      this.playlist.url = '';
    } else {
      this.channelURL  = '';
      this.channelName = '';
      this.loadPlaylist();
    }
    this.triggerUpdate();
  },
  
  refreshChannel: function() {
    if(this.getChannelMode()) {
      // ensure to have a 5 track reserve after skipping to the next track
      var toLoad = 5 - (this.getPlaylistSize()-1 - this.getPlaylistPosition());
      if(toLoad > 0) this.loadChannelSongs(toLoad);
    }
  },
  
  loadChannelSongs: function(count) {
    if(this.getChannelMode() && count > 0)
      new Ajax.Request(this.channelURL.gsub('_COUNT_', count), {method:'get'});
  },
  
  getPlaylistMode: function() {
    return !!this.playlist.url;
  },
  
  setPlaylistMode: function(val) {
    if(val) {
      this.storePlaylist();
      this.clearPlaylist();
      this.playlist.url   = val.url;
      this.playlist.title = val.title;
      this.channelURL = this.channelName = '';
    } else {
      this.playlist.url   = '';
      this.playlist.title = '';
      this.loadPlaylist();
    }
    this.triggerUpdate();
  },
  
  loadPlaylistSongs: function() {
    if(this.getPlaylistMode())
      new Ajax.Request(this.playlist.url, {method:'get'});
  },
  
  storePlaylist: function() {
    var cookieData = {title: this.playlist.title, position: this.playlist.position, songs: this.playlist.list.map(function(song){return song.id;})};
    writeCookie('playlist', serialize(cookieData));
  },
  
  loadPlaylist: function() {
    var s = readCookie('playlist');
    if(s) {
      this.clearPlaylist();
      
      var cookieData = eval(s);
      this.playlist.title    = cookieData.title;
      this.playlist.position = cookieData.position;
      
      var params = '?ids[]='+cookieData.songs.join('&ids[]=');
      new Ajax.Request('/music/load_songs'+params, {method: 'get'});
      
      deleteCookie('playlist');
    }
  }
});


// requires player.js

// (singleton, as good as it gets)
var PlayerController = Class.create({
  
  initialize: function() {
    if(PlayerController._instance) throw "I'm a sigleton, back off!";
    
    this.windowName   = 'replayer';
    this.windowHandle = null;
    
    this.player = null;
    this.scheduledForPlayer = new Array();
    
    this.clearPlaylist        = this.playerFunction('clearPlaylist');
    this.removeFromPlaylist   = this.playerFunction('removeFromPlaylist');
    this.addSong              = this.playerFunction('addSong');
    this.addSongs             = this.playerFunction('addSongs');
    this.next                 = this.playerFunction('next');
    this.previous             = this.playerFunction('previous');
    this.getPlaylist          = this.playerFunction('getPlaylist');
    this.getPlaylistPosition  = this.playerFunction('getPlaylistPosition');
    this.setPlaylistPosition  = this.playerFunction('setPlaylistPosition');
    this.getPlaylistTitle     = this.playerFunction('getPlaylistTitle');
    this.setPlaylistTitle     = this.playerFunction('setPlaylistTitle');
    this.setPlaylistId        = this.playerFunction('setPlaylistId');
    this.getPlaylistSize      = this.playerFunction('getPlaylistSize');
    this.currentSong          = this.playerFunction('currentSong');
    this.play                 = this.playerFunction('play');
    this.pause                = this.playerFunction('pause');
    this.stop                 = this.playerFunction('stop');
    this.togglePause          = this.playerFunction('togglePause');
    this.setPosition          = this.playerFunction('setPosition');
    this.getPosition          = this.playerFunction('getPosition');
    this.playState            = this.playerFunction('playState');
    this.setAllowEditing      = this.playerFunction('setAllowEditing');
    this.getAllowEditing      = this.playerFunction('getAllowEditing');
    this.setExpanded          = this.playerFunction('setExpanded');
    this.getExpanded          = this.playerFunction('getExpanded');
    this.setChannelMode       = this.playerFunction('setChannelMode');
    this.getChannelMode       = this.playerFunction('getChannelMode');
    this.getChannelName       = this.playerFunction('getChannelName');
    this.loadChannelSongs     = this.playerFunction('loadChannelSongs');
    this.setPlaylistMode      = this.playerFunction('setPlaylistMode');
    this.getPlaylistMode      = this.playerFunction('getPlaylistMode');
    this.loadPlaylistSongs    = this.playerFunction('loadPlaylistSongs');
  },

  isControllingPlayer: function() {
    return readCookie('player') && WINDOW_ID == readCookie('window_controlling_player');
  },

  openWindow: function() {
    if (this.windowHandle = this.openCall()){
      if(typeof(this.windowHandle.rePlayer) == "undefined"){
        this.windowHandle.location.href = '/music/player';
      }
      
      // focus the main window stealthly
      var func = window.onfocus;
      window.onfocus = null;
      window.focus();
      window.onfocus = func;
      
      this.player = this.windowHandle.rePlayer;
    }
  },

  openCall: function() {
    var win = window.open('', this.windowName, 'width=300, height=188, top=0, left=0');
    if(win)
      win.opener = window;
    else {
      if(Prototype.Browser.WebKit) console.log(getStackTrace(this.openCall));
      else                         alert('Player konnte nicht geÃ¶ffnet werden... Ist ein Popup-Blocker aktiviert?');
    }
    writeCookie('window_controlling_player', WINDOW_ID);
      
    return win;
  },
  
  grabPlayer: function() {
    if(!readCookie('player') || this.isControllingPlayer()) return;
    
    this.player = null;
    this.openWindow();
    
    if(!this.windowHandle) deleteCookie('player');
    
    if(Prototype.Browser.WebKit) this.windowHandle.blur(); // Safari Hack
  },
  
  editMode: function() {
    if(this.isControllingPlayer()) {
      $('save_playlist_form').down('input[name="title"]').value = rePlayer.getPlaylist().title;
      rePlayer.stop();
      window.openPlayer();
    } else {
      setTimeout('PlayerController.instance().editMode();', 200);
    }
  },

  playerFunction: function(name) {
    return function(args) {
      
      var toCall;
      if(args == undefined) toCall = name+'();';
      else                  toCall = name+'('+serialize(args)+');';
      
      if(this.isControllingPlayer() && !this.executionLock) {
        // execute every queued command
        this.execute();
        // execute the current command
        return eval('PlayerController.instance().player.'+toCall);
      } else {
        // schedule the command for later execution
        this.scheduledForPlayer.push(toCall);
        this.execute();
      }
    };
  },
  
  execute: function() {
    clearTimeout(this.executioner);
    
    if(!this.isControllingPlayer() || this.executionLock) {
      this.executioner = setTimeout('PlayerController.instance().execute()', 100);
      return;
    }
    
    this.executionLock = true;
    while(this.scheduledForPlayer.length > 0) {
      var item = this.scheduledForPlayer.shift();
      eval('PlayerController.instance().player.'+item);
    }
    this.executionLock = false;
  },
  
  triggerUpdate: function() {
    window.document.fire('player:updated');
  }
});

PlayerController._instance = null;
PlayerController.instance = function() {
  if(!this._instance) this._instance = new PlayerController();
  return this._instance;
};


// requires player_controller.js

if(Prototype.Browser.IE) {
  Effect.Opacity = Class.create(Effect.Base, {
    initialize: function(element) {
      this.element = $(element);
      if (!this.element) throw(Effect._elementDoesNotExistError);
      // make this work on IE on elements without 'layout'
      // this line crash-proofed by checking for currentStyle before invoking hasLayout on it...
      if (Prototype.Browser.IE && !(this.element.currentStyle && this.element.currentStyle.hasLayout)) this.element.setStyle({zoom: 1});
      var options = Object.extend({
        from: this.element.getOpacity() || 0.0,
        to:   1.0
      }, arguments[1] || { });
      this.start(options);
    },
    update: function(position) {
      this.element.setOpacity(position);
    }
  });
}

function generateWindowId() {
  var timeString = (new Date()).getTime().toString();
  var randString = (Math.floor(Math.random()*9000) + 1000).toString();
  WINDOW_ID = timeString + '_' + randString;
}

function isReplayerPopup() {
  //return !!opener; // does not work on IE (IE regards every window in a new tab as a popup...)
  return window.name == 'replayer';
}

// Display updating
function updateDisplay() {
  
  if(isReplayerPopup()) return;
  
  var player_div = $('player');
  
  // if no player is avilable...
  if(!readCookie('player') || !rePlayer || rePlayer.getPlaylistSize() == 0) {
    
    // reset everything
    try {
      player_div.down('.current_track').update('');
      player_div.down('.playlist_view').update('');
      
      $('toggle_pause').className = 'icon play';
      seekSlider.setValue(0);
      
      player_div.down('.channels .current_channel').update('Channel');
      player_div.down('.channels .channel_menu').removeClassName('playing');
      $$('#channel_selector .playing').each(function(e){e.removeClassName('playing');});
      player_div.down('.playlists .current_playlist').update('Meine Playlists');
      player_div.down('.playlists .playlist_menu').removeClassName('playing');
      $$('#playlist_selector .playing').each(function(e){e.removeClassName('playing');});
      player_div.down('.song_controls').hide();
    
    } catch(e) {printError(e);}
    
    return;
  }
  
  if(!rePlayer.isControllingPlayer()) return;
  
  try {
    // update the currently playing song
    var song = rePlayer.currentSong();
    player_div.down('.current_track').update(song.playing_html);
      
    var recommendation_modal = $$('.modal_window.player_recommendation').first();
    if(recommendation_modal) recommendation_modal.down('#recommendable_id').value = toS(song.id);
    
    $('toggle_pause').className = (rePlayer.playState() == PLAYING) ? 'icon pause' : 'icon play';
    
    // update_the playlist div
    if(playerExpanded) {
      var playlist_div = player_div.down('.playlist_view');
      playlist_div.update(rePlayer.getPlaylist().toHTML());
      makePlaylistSortable();
      try {
        var playlistTop = playlist_div.cumulativeOffset().top;
        var currentTop  = playlist_div.down('.current').cumulativeOffset().top;
        playlist_div.scrollTop = currentTop - playlistTop - 50;
      } catch(e) {printError(e);}

      if(rePlayer.getAllowEditing()) {
        player_div.down('.playlist_wrapper').removeClassName('non_editable');
      } else {
        player_div.down('.playlist_wrapper').addClassName('non_editable');
        player_div.down('.edit_controls').down('.hint').update('Die Playlist kann nicht gespeichert werden, da sie geschÃ¼tzte Songs enthÃ¤lt.');
      }
    }
    
    // update the menus
    if(rePlayer.getChannelMode()) {
      player_div.down('.channels .current_channel').update(rePlayer.getChannelName());
      player_div.down('.channels .channel_menu').addClassName('playing');
      $$('#channel_selector li').each(function(e){if(e.down('a').innerHTML == rePlayer.getChannelName()) e.addClassName('playing');});
    } else {
      player_div.down('.channels .current_channel').update('Channel');
      player_div.down('.channels .channel_menu').removeClassName('playing');
      $$('#channel_selector .playing').each(function(e){e.removeClassName('playing');});
    }
    
    var playlistTitle = rePlayer.getPlaylistTitle();
    if(playlistTitle) {
      player_div.down('.playlists .current_playlist').update(playlistTitle);
      player_div.down('.playlists .playlist_menu').addClassName('playing');
      $$('#playlist_selector li').each(function(e){if(e.down('a').innerHTML == rePlayer.getChannelName()) e.addClassName('playing');});
    } else {
      player_div.down('.playlists .current_playlist').update('Meine Playlists');
      player_div.down('.playlists .playlist_menu').removeClassName('playing');
      $$('#playlist_selector .playing').each(function(e){e.removeClassName('playing');});
    }  
    player_div.down('.song_controls').show();
    
    updateSharingLinks(song);
    
    updateSlider(seekSlider);
  
  } catch(e) {printError(e);}
}

// Sets the current window as the one controlling the player and
// updates the display if the window was not in control before...
function takeOverPlayer() {
  if(WINDOW_ID != readCookie('window_controlling_player')) {
    if(readCookie('player')) rePlayer.grabPlayer();
    else                     writeCookie('window_controlling_player', WINDOW_ID);
    updateDisplay();
  }
}

function updateSharingLinks(song) {
  var title = encodeURI(encodeURI(encodeURI(encodeURIComponent('Â«'+song.title+'Â» von '+song.artist)))); // the fb sharer needs this many escapes...
  var url   = encodeURIComponent(song.url).gsub(/\./,'%2E');
  
  var twitter_link  = $('player').down('.twitter_link');
  twitter_link.href = 'http://twitter.com/home?status='+title+'%3A%20'+url;
  
  var myspace_link  = $('player').down('.myspace_link');
  myspace_link.href = 'http://www.myspace.com/Modules/PostTo/Pages/?u='+url+'&t='+title;
  
  var facebook_link  = $('player').down('.facebook_link');
  facebook_link.href = 'http://www.facebook.com/sharer.php?u=http://restorm.com/fb_share?url='+url+'%26cachebuster='+(Math.floor(Math.random()*1000))+'%26description='+title+'%26title='+title+'%26song_id='+song.id;
}

function updateSlider(slider) {
  try {
    if(!rePlayer.isControllingPlayer()) return;
  
    var func = slider.options.onChange;
    slider.options.onChange = null;

    var position = rePlayer.getPosition() || 0;
    slider.setValue(position*100);

    slider.options.onChange = func;
  } catch(e) {printError(e);}
}

window.playerExpanded = false;
function togglePlayer(duration) {
  try {
    playerExpanded ? closePlayer() : openPlayer();
  } catch(e) {printError(e);}
}
function openPlayer(duration) {
  duration = typeof(duration) == 'number' ? duration : 1.0;
  if(!playerExpanded) {
    playerExpanded = true;
    $('player').addClassName('expanded');
    updateDisplay();
    
    new Effect.Morph('player', {style:'bottom:0px; opacity:0.95;', duration: duration});
    $('player').down('a.open').className = 'icon close';
    
    $('player_overlay').show();
    Event.observe('player_overlay', 'click', closePlayer);
    
    $$('.ad').each(function(ad){ad.setStyle({visibility:'hidden'});});
  }
}
function closePlayer(duration) {
  duration = typeof(duration) == 'number' ? duration : 1.0;
  if(playerExpanded) {
    new Effect.Morph('player', {style:'bottom:-439px; opacity:1.0;', duration: duration});
    $('player').down('a.close').className = 'icon open';
    
    setTimeout(
      "$('player_overlay').hide(); \
      $$('.ad').each(function(ad){ad.setStyle({visibility:'visible'});}); \
      playerExpanded = false; \
      $('player').removeClassName('expanded'); \
      updateDisplay();",
    duration*1000);
  }
}

function teasePlayer() {
  openPlayer(1);
  setTimeout('closePlayer(1.5);', 2000);
}


function makePlaylistSortable() {
  try {
    Sortable.create('playlist_container', {
      tag:'li',
      only:'song',
      onUpdate: function(container) {
        var newOrder = Sortable.serialize(container).split('&').map(function(item){ return item.split('=').last(); });
        try {
          rePlayer.getPlaylist().reorder(newOrder);
          rePlayer.triggerUpdate();
        } catch(e) {printError(e);}
      }
    });
  } catch(e) {printError(e);}
}

function fillPlaylistForm() {
  // clear old data
  try {
    $('save_playlist_form').select('input[name="songs[]"]').each(function(item) {item.remove();});
  } catch(e) {printError(e);}
  
  // fill in new form elements
  if(rePlayer.getPlaylistSize() > 0) {
    rePlayer.getPlaylist().list.each(function(song){
      addHiddenFieldTo('save_playlist_form', 'songs[]', song.id);
    });
  }
}

function preparePlaylistFormForSubmission() {
  
  fillPlaylistForm();
  
  if(!$('save_playlist_form').down('[name="title"]').value) {
    alert('Eine Playlist muss einen Titel haben');
    return false;
  }
  
  return confirm("Eine eventuell bestehende Playlist mit demselben Namen wird geÃ¤ndert, bist du sicher?");
}

// Initialization /////////////////////////////////////////////////////////////
//

function initializeSoundManager() {
  if(!soundManager) throw "SoundManager not initialized!";
  
  soundManager.log = "";
  soundManager._wD = function(sText,sType,bTimestamp) {
    soundManager.log += sText + "\n";
    soundManager._writeDebug(sText,sType,bTimestamp);
  };
  
  soundManager.url          = '/flash/';
  soundManager.debugMode    = false;
  soundManager.consoleOnly  = true;
}

/*
 * Initializes a Player instance or a PlayerController,
 * depending on wether the function is called in the popup
 * or the main window.
 *
 */
function initializeReplayer() {
  
  if(isReplayerPopup()) {

    rePlayer = new Player();

    // as soon as everything is loaded, set the player instance
    // as delegation target in the main window and trigger a 
    // display update
    soundManager.onload = function() {
      window.opener.rePlayer.player = rePlayer;
      window.opener.teasePlayer();
      writeCookie('player', 1);
      rePlayer.triggerUpdate();
    };
    
    soundManager.onerror = function() {
      try {
        $('player').down('.overlay .text').update(
          'Bei der Initialisierung des Soundsystems ist etwas schief gelaufen...<br/> \
          Also gibts im Moment keinen Sound, sorry :( \
          <br/><br/> \
          <a href=# onclick="alert(soundManager.log); return false;">Fehlermeldung</a>'
        );
        $('player').down('.overlay').addClassName('error');
      } catch(e) {printError(e);}
    };

    // on unload, delete the cookie and unset the delegation target
    // in the main window
    Event.observe(window, 'unload', function() {
      try {
        deleteCookie('player');
        if(window.opener) {
          window.opener.closePlayer();
          if(window.opener.rePlayer) window.opener.rePlayer.player = null;
        }
        rePlayer.triggerUpdate();
      } catch(e) {printError(e);}
    });

  } else {

    rePlayer = PlayerController.instance();
    
    // on focus, connect the main window and the popup (after a short delay)
    if(!Prototype.Browser.WebKit) {
      Event.observe(window, 'focus', function() {
        setTimeout(takeOverPlayer, 200);
      });
    } else { // Safari doesn't know about onfocus :( So we use onmouseover as cheap fix...    
      Event.observe(window, 'load', function(){
        setTimeout(takeOverPlayer, 200);
      });
      Event.observe(window, 'mousemove', takeOverPlayer);
    }
    Event.observe(window, 'load', updateDisplay);

    // update the display on player:updated
    Event.observe(document, 'player:updated', updateDisplay);
  }
}

generateWindowId();
initializeSoundManager();
initializeReplayer();

// Homepage::  http://restorm.com
// Author::    Niko Dittmann (http://niko-at-restorm.members.restorm.com)
// Copyright:: (cc) 2008 restorm AG
// License::   BSD

// A javscript-badge that handles these post types (all available as of 2008/11/20):
// audio, conversation, link, photo, quote, regular, video
//
// Requirements: Prototype.
//
// It produces basically the same html structure as the standard tumblr javascript produces
// but adds additional date and the tag divs.  It also links photos to the post itself.
// Click-through links aren't supported by the API (yet?).
//
// The used css classes are (for your reference):
//
// tumblr_posts, tumblr_post, tumblr_[type]_post,
// tumblr_date*, tumblr_tags*,
// tumblr_title,
// tumblr_photo, tumblr_photo_link*,
// tumblr_link, tumblr_video, tumblr_audio,
// tumblr_caption, tumblr_body, tumblr_label,
// tumblr_open_quote, tumblr_close_quote, tumblr_quote, tumblr_source,
//
//    *(new classes)
//
// to use it, you just call the javascript like that:
//
// tumblrPosts({})
//
// or with some options:
//
// tumblrPosts( {"username" : "restorm-news", "num" : 1} )

// At the moment, there are just 3 functions:
//
// * tumblrPosts()          to add a whole feed
// * tumblrLastPostDate()   to output the date of the latest post
// * tumblrPostsAppend()    only used internally for a budget pagination: it only adds posts to the bottom
//
// All three have their callback counterparts, which actually insert the content after the data is loaded:
//
// * tumblrInsertPosts()
// * tumblrInsertLastPostDate()
// * tumblrInsertPostsAppend()
//
//
// The actual content is inserted into divs with css-classes and ids deriving from the callback:
//
// * class = "tumblrInsertLastPostDate_container" p.e. for all tumblrLastPostDate inserts and
// * id = sanitized tumblr username + classname
//
// You can style the containers to prevent shifts in the layout while the tumblr content loads.
//

// Don't laugh. Function name property for Safari and IE.
//
function defineName(fn,name){
  if(!fn.name){fn.name = name;};
}

// Outputs the date of the last post in the feed.
//
function tumblrLastPostDate(tumblrUsername){
  username = tumblrUsername != undefined ? tumblrUsername : 'tumblr-api-test';
  tumblrContainerWrite(username, tumblrInsertLastPostDate, 1, 0);
}

// Outputs *num* posts of the feed.
//
function tumblrPosts(options){
  var num          = options['num']        != undefined ? options['num']         : 10;
  
  tumblrUsername   = options['username']   != undefined ? options['username']    : 'tumblr-api-test';
  tumblrOpenQuote  = options['oquote']     != undefined ? options['oquote']      : '<span class="tumblr_open_quote">&#8220;</span>';
  tumblrCloseQuote = options['cquote']     != undefined ? options['cquote']      : '<span class="tumblr_close_quote">&#8221;</span>';
  tumblrPhotoSize  = options['psize']      != undefined ? options['psize']       : 400; // available are 75, 100, 250, 400, 500
  tumblrMoreLinkText = options['moreLink'] != undefined ? options['moreLink']    : '...';
  
  tumblrContainerWrite(tumblrUsername, tumblrInsertPosts, num, 0);
}

// Loads more posts.
//
function tumblrPostsAppend(div_id){
  container = $(div_id);
  container.tumblr_start = container.tumblr_start + container.tumblr_num;
  tumblrContainerWrite(tumblrUsername, tumblrInsertPostsAppend, container.tumblr_num, container.tumblr_start);
}


// This is a generic function to generate a container for the tumblr data and
// add the tumblr call to the HTMl header.
// The containers id is generated from the (sanitized) username and the name of the callback.
// This means, you can not use the same tumlbr feed twice in one HTML document.
//
function tumblrContainerWrite(tumblrUsername, callback, num, start){
  var div_class = callback.name.replace('Append','') + '_container';
  var div_id = tumblrUsername.replace(/[^A-Za-z0-9]/g,'_') + '_' + div_class;
  if ($(div_id) == null){ document.write('<div id="' + div_id + '" class="' + div_class + '"></div>'); }
  
  var callback_name = "update_" + div_id;
  window[callback_name] = function(json){ callback(json, div_id, num, start); };
  var json_url = 'http://' + tumblrUsername + '.tumblr.com/api/read/json?num=' + num + '&start=' + start + '&callback=' + callback_name;
  var e = document.createElement("script");
  e.src = json_url;
  e.type="text/javascript";
  document.getElementsByTagName("head")[0].appendChild(e);
}


// The callback for tumblrPosts.
//
function tumblrInsertPosts(json, div_id, num, start){
  var container = $(div_id);
  container.tumblr_num = parseInt(num);
  container.tumblr_start = parseInt(start);
  
  var ol = new Element("ol", {'class':'tumblr_posts'});
  var tumblr = new TumblrPosts(json);
  
  insertListOfPosts(tumblr, ol);
  container.appendChild(ol);
  tumblrMoreLink(container, tumblr, div_id);
}
defineName(tumblrInsertPosts, 'tumblrInsertPosts');

// The callback for tumblrLastPostDate.
//
function tumblrInsertLastPostDate(json, div_id, num, start){
  var tumblr = new TumblrPosts(json);
  var post = tumblr.posts[0];
  Object.extend(post, tumblr.methods);
  $(div_id).appendChild(post.dateInfo());
}
defineName(tumblrInsertLastPostDate, 'tumblrInsertLastPostDate');

// The callback for tumblrPostsAppend.
//
function tumblrInsertPostsAppend(json, div_id, num, start){
  var container = $(div_id);
  container.tumblr_num = parseInt(num);
  container.tumblr_start = parseInt(start);
  
  var ol = container.down('ol');
  var tumblr = new TumblrPosts(json);
  
  insertListOfPosts(tumblr, ol);
  
  tumblrMoreLink(container, tumblr, div_id);
}
defineName(tumblrInsertPostsAppend, 'tumblrInsertPostsAppend');

function insertListOfPosts(tumblr, ol){
  tumblr.posts.each(function(post){
    Object.extend(post, tumblr.methods);
    
    var li = new Element("li", {'class':'tumblr_post tumblr-'+ post['type'] +'-post'})
      .insert(post.dateInfo())
      .insert(post.tagList());
    
    var methodName = post['type'] + 'Body';
    post[methodName]().each(function(el){
      li.insert(el);
    });
    
    ol.appendChild(li);
  });
}

function tumblrMoreLink(container, tumblr, div_id){
  if(tumblr.postsTotal > container.tumblr_num + container.tumblr_start){
    var link = new Element("a").update(tumblrMoreLinkText);
    link.observe('click', function(){ this.remove(); tumblrPostsAppend(div_id); });
    container.appendChild(link);
  }
}

TumblrPosts = Class.create({
  initialize: function(json){
    this.posts      = json['posts'];
    this.postsTotal = json['posts-total'];
  },
  
  methods: {
    div_el: function(content, klass){
      return new Element("div", {'class':klass}).insert(content);
    },
    
    dateInfo: function(){
      var c = this['date-gmt'].split(' ')[0].replace(/-/g,'/');
      return(this.div_el(c, 'tumblr_date'));
    },
    tagList: function(){
      if(this['tags'] != undefined){
        var ul = new Element("ul", {'class':'tumblr_tags'});
        
        this['tags'].each(function(tag){
          var url = 'http://'+ tumblrUsername +'.tumblr.com/tagged/'+ tag.replace(' ','_');
          ul.insert(
            new Element("li", {}).insert(
              new Element("a", {'href':url}).update(tag)
            )
          );
        });
        
      }
      return ul;
    },
    
    photoBody: function(){
      var photo = new Element("a", {'class':'tumblr_photo_link', 'href':this['url']})
        .insert(new Element("img", {'class':'tumblr_photo', 'src':this['photo-url-' + tumblrPhotoSize]}));
      var caption = this.div_el(this['photo-caption'], "tumblr_caption");
      return [photo, caption];
    },
    linkBody: function(){
      var linkText = this['link-text'] == '' ? this['link-url'] : this['link-text'];
      var link = new Element("a", {'class':'tumblr_link', 'href':this['link-url']}).update(linkText);
      if(this['link-description'] != ''){
        var desc = this.div_el(this['link-description'], 'tumblr_description');
      }
      return[link, desc].compact();
    },
    videoBody: function(){
      var body = this.div_el(this['video-player'], 'tumblr_video');
      if(this['video-caption'] != ''){
        var caption = this.div_el(this['video-caption'], 'tumblr_caption');
      }
      return [body, caption].compact();
    },
    audioBody: function(){
      var body = this.div_el(this['audio-player'], 'tumblr_audio');
      if(this['audio-caption'] != ''){
        var caption = this.div_el(this['audio-caption'], 'tumblr_caption');
      }
      return [body, caption].compact();
    },
    conversationBody: function(){
      if(this['conversation-title'] != ''){
        var title = this.div_el(this['conversation-title'], 'tumblr_title');
      };
      var conversation = new Element("ul");
      this['conversation-lines'].each(function(line){
        conversation.insert(
          new Element("li").insert(
            new Element("span", {'class':'tumblr_label'}).update(line['label'])
          ).update(line['phrase'])
        );
      });
      return [title, conversation].compact();
    },
    quoteBody: function(){
      quoteText = this['quote-text'].replace(/^&#8220;/,'').replace(/&#8221;$/,''); // we strip those hard-coded quotes, use our own:
      var quote = this.div_el(tumblrOpenQuote + quoteText + tumblrCloseQuote, "tumblr_quote");
      if(this['quote-source'] != ''){
        var source = this.div_el(this['quote-source'], "tumblr_source");
      }
      return [quote, source].compact();
    },
    regularBody: function(){
      if(this['regular-title'] != ''){
        var title = this.div_el(this['regular-title'], "tumblr_title");
      }
      if(this['regular-body'] != ''){
        var body = this.div_el(this['regular-body'], "tumblr_body");
      }
      return [title, body].compact();
    }
  }
});

(function(){
/**
 * Wrapper for use of SWFUpload with selection of multiple files. It initializes
 * SWFUpload, creates DOM for upload Queue and handles SWFUpload events.
 */
MultiUpload = function(upload_id, post_url, post_params, options, swfup_options) {
    var default_swfup_options = {
	    upload_url: post_url,
	    flash_url: '/flash/swfupload.swf',
        button_width: '150',
        button_height: '31',
        button_text_top_padding: '9',
        button_text_left_padding: '0',
        button_text_style: '.swf_upload_button { font-family: Helvetica, Arial, sans-serif; font-size: 12px; font-weight: bold; color: #999999; }',
        button_text: '<span class="swf_upload_button">Dateien auswÃ¤hlenâ€¦</span>',
    	button_cursor : SWFUpload.CURSOR.HAND,
    	button_window_mode : SWFUpload.WINDOW_MODE.TRANSPARENT,
        post_params: post_params,
        swfupload_loaded_handler: this.swfupload_loaded.bind(this),
        file_queued_handler: this.file_queued.bind(this),
        upload_start_handler: this.upload_start.bind(this),
        upload_progress_handler: this.upload_progress.bind(this),
        upload_complete_handler: this.upload_success.bind(this),
        upload_error_handler: this.upload_error.bind(this)
	}
	
	var default_options = {
	    all_uploads_completed_handler: function() { alert('Uploads done!') },
	    start_upload_caption: 'Upload starten',
	    upload_progress_caption: '#{percentage}% hochgeladen'
	}
    
    this.options = default_options;
    
    this.swfupload_ready = false;
    this.swfupload_tasks_after_ready = [];
    
    // Attempt to find container for the upload
    var container_id = upload_id + "_container";
	var container = $(container_id);
	if (!container) {return};
    
    // empty container (it might contain text that explains that you need 
    // JavaScript (or some other stuff))
    container.update('');
    
    // add CSS class to container
    container.addClassName('multiupload_container');
    
    // add container for upload queue
    var queue_id = upload_id + "_upload_queue";
    var queue_container = new Element('ul', {id: queue_id, "class": "multiupload_queue"});
    container.insert(queue_container);
	
	// button container
	var button_container = new Element('div', {"class": "multiupload_button_container"});
	container.insert(button_container);
	
	// add file selection button
	var button_id = upload_id + "_button";
	var button_placeholder = new Element('div', {id: button_id, "class": "multiupload_button"});
	button_container.insert(button_placeholder);
	
	// add clear list button
	var start_button = new Element('a', {href: '#', "class": 'multiupload_start_button'})
	    .update(this.options.start_upload_caption);
	button_container.insert(start_button);    
    start_button.observe('click', this.start_upload.bindAsEventListener(this));
    this.start_button = start_button;
	
	default_swfup_options.button_placeholder_id = button_id;
	
	swfup_options = Object.extend(default_swfup_options, swfup_options);
	this.swfup = new SWFUpload(swfup_options);
	
	this.container = container;
	this.queue_container = queue_container;
	this.upload_id = upload_id;
    this.list_items = $H();
    
	MultiUpload.add_instance(upload_id, this);
};

// local alias for MultiUpload and its prototype (yes, I'm too lazy to type that every time ;-)
var mu = MultiUpload;
var mup = MultiUpload.prototype;

/**
 * Add an instance to Multiupload.instances (useful for debugging)
 */
mu.add_instance = function(id, instance) {
    if (!MultiUpload.instances) {
        MultiUpload.instances = {};
    };
    MultiUpload.instances[id] = instance;
};

/**
 * Format a file size in bytes to a human readable format. It converts to the
 * biggest prefix without a leading zero and for each bigger unit, there's
 * one more decimal place (e.g. 200 B => 200 B, 2000 B => 1.9 kB, 2000000 B => 1.91 MB)
 */
mu.human_readable_size = function(size_in_bytes) {
    var prefixes = ['', 'k', 'M', 'G'];
    var exp = 0;
    var human_size = size_in_bytes;
    while((human_size > 1024) && (exp < 3)) {
        human_size = human_size / 1024;
        exp++;
    }
    
    var digits = (exp > 0) ? exp - 1 : 0;
    human_size = human_size.toFixed(digits);

    return human_size+' '+prefixes[exp]+'B';
};

/**
 * Generate ID for delete button
 */
mu.delete_button_id = function(file_id) {
    return 'multiupload_file_delete_'+file_id;
};

/**
 * Extract the file ID from the DOM ID of the delete button
 */
mu.file_id_from_delete_id = function(button_id) {
    // drop 'multiupload_file_delete_' from element id to get the file id
    return button_id.substr(24);
};


mup.swfupload_loaded = function() {
    this.swfupload_ready = true;
    this.swfupload_tasks_after_ready.each(function(task){ task(); });
};

/**
 * Event handler for SWFUpload file queued event. Adds a <li> entry to the upload queue,
 * fills it with file informations, add a delete link and attach event handler
 * to the delete link
 */
mup.file_queued = function(file) {
    var list_item = new Element('li', {id: this.upload_id+'_file_'+file.id})
        .addClassName('multiupload_file')
        .addClassName('upload_pending')
        .update(
            '<span class="multiupload_file_name">'+file.name + '</span> '+
            '<span class="multiupload_file_size">('+mu.human_readable_size(file.size)+')</span> '
        );
        
    var delete_link = new Element('a', {href: '#', "class": 'multiupload_file_delete', id: mu.delete_button_id(file.id)}).update('x');
    list_item.insert(delete_link);
    
    // attach file hover handlers
    list_item.observe('mouseover', function(ev){this.addClassName('multiupload_file_hover')})
        .observe('mouseout', function(ev){this.removeClassName('multiupload_file_hover')});
    
    delete_link.observe('click', this.remove_from_queue.bindAsEventListener(this));
    
    this.queue_container.insert(list_item);
    this.list_items.set(file.id, list_item);
};

/**
 * Remove file from swfupload upload queue
 */
mup.remove_queued_file = function(file_id) {
   this.swfup.cancelUpload(file_id);
};

/**
 * Remove file from HTML upload queue
 */
mup.remove_queue_item = function(file_id) {
    var list_item = this.list_items.unset(file_id);

    var delete_button = list_item.down('.multiupload_file_delete');
    if (delete_button) {
        delete_button.stopObserving();
    };
    list_item.stopObserving();
    list_item.remove();
};

/**
 * Clears the queue. Click handler for the clear list button. Extracts file id
 * from the element's ID and remove the file.
 */
mup.start_upload = function(ev) {
    this.swfup.startUpload();
    
    ev.stop();
};

/**
 * Removes one file from the upload queue. Click handler for delete 
 */
mup.remove_from_queue = function(ev) {
    var element = ev.element();
    var file_id = mu.file_id_from_delete_id(element.id);
    
    this.remove_queued_file(file_id);
    this.remove_queue_item(file_id);
    
    ev.stop();
};

/**
 * Event handler for upload start event.
 */
mup.upload_start = function(file) {
    var list_item = this.list_items.get(file.id);
    list_item.removeClassName('upload_pending').addClassName('upload_running');
    list_item.insert(new Element('span', {'class': 'multiupload_file_progress'}));
};

/**
 * Event handler for upload progress event. Updates the progress display
 */
mup.upload_progress = function(file, completed_bytes, file_size) {
    var percentage = ((completed_bytes / file_size) * 100).toFixed(0);
    // we cheat a little and diplay one precent less to bridge the time between
    // upload completed and upload success (otherwise the progress would be at
    // 100% while it's not really done)
    if (percentage > 1) {
        percentage--;
    };
    var list_item = this.list_items.get(file.id)
    list_item.down('.multiupload_file_progress').update(
        this.options.upload_progress_caption.interpolate({percentage: percentage})
    );
};

/**
 * Event handler for upload success event. Marks file as completed with CSS class
 * and removes delete button.
 */
mup.upload_success = function(file) {
    var list_item = this.list_items.get(file.id);
    if (list_item) {
        // remove 'upload_pending' class, add 'upload_completed'
        if (!list_item.hasClassName('upload_failed')){
            list_item.removeClassName('upload_running').addClassName('upload_completed');
        }
        // remove delete link and progress
        list_item.down('.multiupload_file_delete').stopObserving().remove();
        list_item.down('.multiupload_file_progress').update('Done');
    }    
    
    if (this.swfup.getStats().files_queued == 0) {
        // uploads done; call all_uploads_completed_handler
        this.options.all_uploads_completed_handler();
    } else {
        // still has pending uploads. starting the next
        this.swfup.startUpload();
    };
};

/**
 * Event handler for upload error.
 */
mup.upload_error = function(file, status, message) {
    var list_item = this.list_items.get(file.id);
    if (list_item) {
        list_item.removeClassName('upload_running')
            .removeClassName('upload_completed')
            .addClassName('upload_failed');  
    };
};

/**
 * Sets POST parameters for SWFUpload. It accepts either an object, a hash or a string.
 *
 * Given a string, the string will be used as index for the parameter to set and the second
 * Parameter sets the value.
 *
 * Given an object or a hash, the passed object will be merged with the current POST parameters.
 */
mup.set_post_params = function(obj_or_index, value) {
    var post_params = this.swfup.settings.post_params;
    
    if (Object.isString(obj_or_index)) {
        post_params[obj_or_index] = value;
    } else {
        if (Object.isHash(obj_or_index)) {
            obj_or_index = obj_or_index.toObject();
        }
        
        post_params = Object.extend(post_params, obj_or_index);
    };
    
    if (this.swfupload_ready) {
        this.swfup.setPostParams(post_params);
    } else {
        var that = this;
        this.swfupload_tasks_after_ready.push(function(){
            that.swfup.setPostParams(post_params);
        });
    };
};

})();


(function() {
    /**
     * Handles gallery upload
     */
    GalleryUpload = function(multiupload, galleries, options) {
        var default_options = {
            gallery_url_pattern: '',
            gallery_create_url: '',
            form_authenticity_token: '',
            initial_gallery_id: null
        };
        
        this.multiupload = multiupload;
        
        this.options = options ? Object.extend(default_options, options) : default_options;
        
        var initial_gallery_id = this.options.initial_gallery_id;
        // get gallery id from fragment if no id is given
        if (!initial_gallery_id) {
            initial_gallery_id = document.location.hash ? document.location.hash.substr(1) : null;
        };
        this.set_gallery_id(initial_gallery_id);
        
        this.multiupload.options.all_uploads_completed_handler = this.redirect_to_gallery.bind(this);
        this.multiupload.swfup.settings.upload_success_handler = this.show_completed_thumbnail.bind(this);
        
        // title for file selection
        this.multiupload.container.insert({top:
            new Element('h2').update('Dateien auswÃ¤hlen')
        });

        // uploaded picture previews
        this.uploaded_pictures_container = new Element('div', {"class": "gallery_uploaded_pictures"}).hide();
        this.uploaded_pictures_list = new Element('div');
        this.multiupload.container.insert({top: this.uploaded_pictures_container});
        this.uploaded_pictures_container
            .insert(new Element('h2').update('Hochgeladene Bilder'))
            .insert(this.uploaded_pictures_list);
        
        // gallery selection
        var gallery_select_container = new Element('div', {"class": "gallery_select_container"});
        this.multiupload.container.insert({top: gallery_select_container});
        
        this.multiupload.container.insert({top:
            new Element('h2').update('Gallerie AuswÃ¤hlen')
        });
        
        // create selector for which gallery the pictures goes into
        var gallery_selector = new Element('select', {"class": "gallery_selector"});
        gallery_select_container.insert(gallery_selector);
        
        // populate gallery list
        $A(galleries).each(function(g) {
            var option = new Element('option', {value: g.gallery_id}).update(g.title);
            if (g.gallery_id == this.selected_gallery_id) {
                option.writeAttribute('selected', true)
            };
            gallery_selector.insert(option);
        }.bind(this));
        
        if ($A(galleries).length < 1) {
            this.multiupload.start_button.hide();
        };
        
        gallery_selector.insert(new Element('option', {value: -1, "class": "separator"}).update('----'));
        gallery_selector.insert(new Element('option', {value: -2, "class": "create"}).update('Neue Galerie erstellen'));
        
        gallery_selector.observe('change', this.set_gallery.bindAsEventListener(this));
        
        if (!this.selected_gallery_id) {
            this.set_gallery_id(gallery_selector.value);
        };
        
        this.gallery_selector = gallery_selector;
        
        // create new gallery form
        this.gallery_creator = {};
        
        this.gallery_creator.container = new Element('form', {"class": "gallery_creator"})
            .setStyle({display: 'none'});
        gallery_select_container.insert(this.gallery_creator.container);
        this.gallery_creator.container.observe('submit', this.create_gallery.bindAsEventListener(this));

        // event handler for handling input clearing on click (and do it only once)
        var input_clearer = function(ev){
            var el = ev.element();
            
            // only do something if entry hasn't been changed yet
            if (el.hasClassName('noentry')) {
                el.value = '';
                el.removeClassName('noentry');
                
                // unregister itself from event handlers. no need to do this anymore.
                el.stopObserving('click', arguments.callee);
            };
        };
        
        this.gallery_creator.title = new Element('input', {
            type: "text", value: "Titel", "class": "gallery_creator_title noentry"}
        );
        
        this.gallery_creator.container.insert(this.gallery_creator.title);
        this.gallery_creator.title.observe('focus', input_clearer);
        
        this.gallery_creator.description = new Element('textarea', {"class": "gallery_creator_description noentry"})
            .update('Beschreibung');
        this.gallery_creator.container.insert(this.gallery_creator.description);
        this.gallery_creator.description.observe('focus', input_clearer);
        
        this.gallery_creator.button = new Element('input', {
            type: 'submit', "class": "gallery_creator_button", value: 'Gallerie erstellen'
        });
        this.gallery_creator.container.insert(this.gallery_creator.button);
        
        this.gallery_creator.error_list = new Element('ul', {"class": "gallery_creator_errors"}).hide();
        this.gallery_creator.container.insert(this.gallery_creator.error_list);
        
        if (document.location.hash == '#new') {
            gallery_selector.value = -2;
            this.show_gallery_creator();
        };
    };
    
    var gu = GalleryUpload;
    var gup = GalleryUpload.prototype;
    
    /**
     * Event handler for onChange of the gallery selector. Sets the gallery ID to transmit over POST.
     */
    gup.set_gallery = function(ev) {
        var el = ev.element();
        var selected_item = $(el.options.item(el.selectedIndex));
        
        if (selected_item.hasClassName('create')) {
            this.show_gallery_creator();
        } else if (selected_item.hasClassName('separator')) {
            this.multiupload.start_button.hide();
        } else {
            this.set_gallery_id(el.value);
            this.hide_gallery_creator();
            this.multiupload.start_button.show();
        };
        
    };
    
    /**
     * Set gallery ID to transmit over POST
     */
    gup.set_gallery_id = function(gallery_id) {
        this.selected_gallery_id = gallery_id;
        
        gallery_id = (gallery_id ? gallery_id : -1);
        
        this.multiupload.set_post_params('gallery_id', gallery_id);
    };
    
    gup.show_gallery_creator = function() {
        this.gallery_creator.container.show();
        this.multiupload.start_button.hide();
    };
    
    gup.hide_gallery_creator = function() {
        this.gallery_creator.container.hide();
        this.multiupload.start_button.show();
    };
    
    gup.gallery_url_for_id = function(gallery_id) {
        return this.options.gallery_url_pattern.interpolate({gallery_id: gallery_id}, /(^|.|\r|\n)(\::\s*(\w+)\s*::)/)
    };
    
    gup.redirect_to_gallery = function() {
        window.location.href = this.gallery_url_for_id(this.selected_gallery_id);
    };
    
    gup.show_errors = function(messages) {
        var error_list = this.gallery_creator.error_list;
        
        error_list.update('');
        $A(messages).each(function(msg) {
            error_list.insert(new Element('li').update(msg));
        });
        error_list.show();
    };
    
    gup.create_gallery = function(ev) {
        var title_input = this.gallery_creator.title;
        var description_input = this.gallery_creator.description;
        
        // leave title and description empty if nothing has been entered, that is wenn it has never
        // got focus and the default text is still inside
        var title = title_input.hasClassName('noentry') ? '' : title_input.value;
        var description = description_input.hasClassName('noentry') ? '' : description_input.value;
        
        // alias this on uploader for access to this object inside the AJAX handlers
        var uploader = this;
        new Ajax.Request(this.options.gallery_create_url, {
            method: 'post',
            parameters: {
                title: title,
                description: description,
                authenticity_token: this.options.form_authenticity_token
            },
            
            onSuccess: function(transport){
                var created_gallery = transport.responseJSON.gallery;
                var gallery_selector = uploader.gallery_selector;
                
                var new_option = new Element('option', {value: created_gallery.id})
                    .update(created_gallery.title);
                
                gallery_selector.down('.separator').insert({before: new_option});
                
                gallery_selector.value = created_gallery.id;
                uploader.set_gallery_id(created_gallery.id);
                uploader.hide_gallery_creator();
                uploader.gallery_creator.error_list.hide();
            },
            
            onFailure: function(transport) {
                var error_messages = transport.responseJSON.messages;
                uploader.show_errors(error_messages);
            }
        });
        
        // abort form submission
        ev.stop();
        return false;
    };
    
    gup.show_completed_thumbnail = function(file, server_response) {
        var response = server_response.evalJSON();
        var mu = this.multiupload;
        
        if (!this.uploaded_pictures_container.visible()) {
            this.uploaded_pictures_container.show();
        };
        
        this.uploaded_pictures_list.insert(
            new Element('img', {src: response.thumbnail_url}).setStyle({
                width: '75px', height: '75px', 
                marginRight: '1em', marginBottom: '1em'
            })
        );
        
        mu.remove_queue_item(file.id);
    };
})();

(function(){
    EventSelector = Class.create({
        initialize: function(container, options){
            // alias this to avoid scoping issues in closures
            var self = this;
            
            this.options = Object.extend({
                autocomplete_url: '',
                autocomplete_select: Prototype.emptyFunction
            }, options||{});
            
            this.container = container = $(container);
            var search_form = container.down('.search_form');
            
            this.date_input         = search_form.down('.date_input');
            this.date_display       = search_form.down('.date_display');
            this.calendar_trigger   = search_form.down('.calendar_trigger');
            this.search_field       = search_form.down('.search_field');
            this.ac_results         = search_form.down('.event_autocomplete');
            
            this.search_form        = search_form;
            this.selected_entry     = container.down('.selected_entry');
            
            this.autocomplete = new Ajax.Autocompleter(this.search_field, this.ac_results, this.options.autocomplete_url, {
              paramName: 'q',
              method: 'get',
              callback: this.ac_callback.bind(this),
              updateElement: this.ac_update_element.bind(this)
            });
            
            this.calendar = Calendar.setup({
              inputField     :    this.date_input.identify(),
              ifFormat       :    "%Y-%m-%d",     // format of the input field (even if hidden, this format will be honored
              displayArea    :    this.date_display.identify(),// ID of the span where the date is to be shown
              daFormat       :    "%A, %d. %B %Y",// format of the displayed date
              button         :    this.calendar_trigger.identify(),  // trigger button (well, IMG in our case)
              align          :    "Tl",           // alignment (defaults to "Bl")
              singleClick    :    true
            });
        },
        
        ac_callback: function(input, query_string){
            var params = $H(query_string.toQueryParams());
            if (!$F(this.date_input).empty()) {
                params.set('d', $F(this.date_input));
            };
            
            return params.toQueryString();
        },
        
        ac_update_element: function(selected_element){
            var selected_id = selected_element.readAttribute('event_id');
            
            this.show_selected();
            this.selected_entry.innerHTML = selected_element.innerHTML;
            this.selected_entry.writeAttribute('event_id', selected_id);
            try {
              $('event_id_field').value = selected_id;
            } catch(e) {printError(e);}
            
            this.options.autocomplete_select(this, selected_id);
        },
        
        show_search: function() {
            this.selected_entry.hide();
            this.search_form.show();
        },
        
        show_selected: function() {
            this.search_form.hide();
            this.selected_entry.show();
        },
        
        clear_date: function() {
            this.date_input.value = '';
        }
    });
})();

//http://www.featureblend.com/license.txt
var FlashDetect=new function(){var self=this;self.installed=false;self.raw="";self.major=-1;self.minor=-1;self.revision=-1;self.revisionStr="";var activeXDetectRules=[{"name":"ShockwaveFlash.ShockwaveFlash.7","version":function(obj){return getActiveXVersion(obj);}},{"name":"ShockwaveFlash.ShockwaveFlash.6","version":function(obj){var version="6,0,21";try{obj.AllowScriptAccess="always";version=getActiveXVersion(obj);}catch(err){}
return version;}},{"name":"ShockwaveFlash.ShockwaveFlash","version":function(obj){return getActiveXVersion(obj);}}];var getActiveXVersion=function(activeXObj){var version=-1;try{version=activeXObj.GetVariable("$version");}catch(err){}
return version;};var getActiveXObject=function(name){var obj=-1;try{obj=new ActiveXObject(name);}catch(err){}
return obj;};var parseActiveXVersion=function(str){var versionArray=str.split(",");return{"raw":str,"major":parseInt(versionArray[0].split(" ")[1],10),"minor":parseInt(versionArray[1],10),"revision":parseInt(versionArray[2],10),"revisionStr":versionArray[2]};};var parseStandardVersion=function(str){var descParts=str.split(/ +/);var majorMinor=descParts[2].split(/\./);var revisionStr=descParts[3];return{"raw":str,"major":parseInt(majorMinor[0],10),"minor":parseInt(majorMinor[1],10),"revisionStr":revisionStr,"revision":parseRevisionStrToInt(revisionStr)};};var parseRevisionStrToInt=function(str){return parseInt(str.replace(/[a-zA-Z]/g,""),10)||self.revision;};self.majorAtLeast=function(version){return self.major>=version;};self.FlashDetect=function(){if(navigator.plugins&&navigator.plugins.length>0){var type='application/x-shockwave-flash';var mimeTypes=navigator.mimeTypes;if(mimeTypes&&mimeTypes[type]&&mimeTypes[type].enabledPlugin&&mimeTypes[type].enabledPlugin.description){var version=mimeTypes[type].enabledPlugin.description;var versionObj=parseStandardVersion(version);self.raw=versionObj.raw;self.major=versionObj.major;self.minor=versionObj.minor;self.revisionStr=versionObj.revisionStr;self.revision=versionObj.revision;self.installed=true;}}else if(navigator.appVersion.indexOf("Mac")==-1&&window.execScript){var version=-1;for(var i=0;i<activeXDetectRules.length&&version==-1;i++){var obj=getActiveXObject(activeXDetectRules[i].name);if(typeof obj=="object"){self.installed=true;version=activeXDetectRules[i].version(obj);if(version!=-1){var versionObj=parseActiveXVersion(version);self.raw=versionObj.raw;self.major=versionObj.major;self.minor=versionObj.minor;self.revision=versionObj.revision;self.revisionStr=versionObj.revisionStr;}}}}}();};FlashDetect.release="1.0.3";

Calendar=function(a,b,c,d){this.activeDiv=null;this.currentDateEl=null;this.getDateStatus=null;this.getDateToolTip=null;this.getDateText=null;this.timeout=null;this.onSelected=c||null;this.onClose=d||null;this.dragging=false;this.hidden=false;this.minYear=1970;this.maxYear=2050;this.dateFormat=Calendar._TT["DEF_DATE_FORMAT"];this.ttDateFormat=Calendar._TT["TT_DATE_FORMAT"];this.isPopup=true;this.weekNumbers=true;this.firstDayOfWeek=typeof a=="number"?a:Calendar._FD;this.showsOtherMonths=false;this.dateStr=b;this.ar_days=null;this.showsTime=false;this.time24=true;this.yearStep=2;this.hiliteToday=true;this.multiple=null;this.table=null;this.element=null;this.tbody=null;this.firstdayname=null;this.monthsCombo=null;this.yearsCombo=null;this.hilitedMonth=null;this.activeMonth=null;this.hilitedYear=null;this.activeYear=null;this.dateClicked=false;if(typeof Calendar._SDN=="undefined"){if(typeof Calendar._SDN_len=="undefined")Calendar._SDN_len=3;var e=new Array();for(var i=8;i>0;){e[--i]=Calendar._DN[i].substr(0,Calendar._SDN_len)}Calendar._SDN=e;if(typeof Calendar._SMN_len=="undefined")Calendar._SMN_len=3;e=new Array();for(var i=12;i>0;){e[--i]=Calendar._MN[i].substr(0,Calendar._SMN_len)}Calendar._SMN=e}};Calendar._C=null;Calendar.is_ie=(/msie/i.test(navigator.userAgent)&&!/opera/i.test(navigator.userAgent));Calendar.is_ie5=(Calendar.is_ie&&/msie 5\.0/i.test(navigator.userAgent));Calendar.is_opera=/opera/i.test(navigator.userAgent);Calendar.is_khtml=/Konqueror|Safari|KHTML/i.test(navigator.userAgent);Calendar.getAbsolutePos=function(a){var b=0,ST=0;var c=/^div$/i.test(a.tagName);if(c&&a.scrollLeft)b=a.scrollLeft;if(c&&a.scrollTop)ST=a.scrollTop;var r={x:a.offsetLeft-b,y:a.offsetTop-ST};if(a.offsetParent){var d=this.getAbsolutePos(a.offsetParent);r.x+=d.x;r.y+=d.y}return r};Calendar.isRelated=function(a,b){var c=b.relatedTarget;if(!c){var d=b.type;if(d=="mouseover"){c=b.fromElement}else if(d=="mouseout"){c=b.toElement}}while(c){if(c==a){return true}c=c.parentNode}return false};Calendar.removeClass=function(a,b){if(!(a&&a.className)){return}var c=a.className.split(" ");var d=new Array();for(var i=c.length;i>0;){if(c[--i]!=b){d[d.length]=c[i]}}a.className=d.join(" ")};Calendar.addClass=function(a,b){Calendar.removeClass(a,b);a.className+=" "+b};Calendar.getElement=function(a){var f=Calendar.is_ie?window.event.srcElement:a.currentTarget;while(f.nodeType!=1||/^div$/i.test(f.tagName))f=f.parentNode;return f};Calendar.getTargetElement=function(a){var f=Calendar.is_ie?window.event.srcElement:a.target;while(f.nodeType!=1)f=f.parentNode;return f};Calendar.stopEvent=function(a){a||(a=window.event);if(Calendar.is_ie){a.cancelBubble=true;a.returnValue=false}else{a.preventDefault();a.stopPropagation()}return false};Calendar.addEvent=function(a,b,c){if(a.attachEvent){a.attachEvent("on"+b,c)}else if(a.addEventListener){a.addEventListener(b,c,true)}else{a["on"+b]=c}};Calendar.removeEvent=function(a,b,c){if(a.detachEvent){a.detachEvent("on"+b,c)}else if(a.removeEventListener){a.removeEventListener(b,c,true)}else{a["on"+b]=null}};Calendar.createElement=function(a,b){var c=null;if(document.createElementNS){c=document.createElementNS("http://www.w3.org/1999/xhtml",a)}else{c=document.createElement(a)}if(typeof b!="undefined"){b.appendChild(c)}return c};Calendar._add_evs=function(a){with(Calendar){addEvent(a,"mouseover",dayMouseOver);addEvent(a,"mousedown",dayMouseDown);addEvent(a,"mouseout",dayMouseOut);if(is_ie){addEvent(a,"dblclick",dayMouseDblClick);a.setAttribute("unselectable",true)}}};Calendar.findMonth=function(a){if(typeof a.month!="undefined"){return a}else if(typeof a.parentNode.month!="undefined"){return a.parentNode}return null};Calendar.findYear=function(a){if(typeof a.year!="undefined"){return a}else if(typeof a.parentNode.year!="undefined"){return a.parentNode}return null};Calendar.showMonthsCombo=function(){var a=Calendar._C;if(!a){return false}var a=a;var b=a.activeDiv;var c=a.monthsCombo;if(a.hilitedMonth){Calendar.removeClass(a.hilitedMonth,"hilite")}if(a.activeMonth){Calendar.removeClass(a.activeMonth,"active")}var d=a.monthsCombo.getElementsByTagName("div")[a.date.getMonth()];Calendar.addClass(d,"active");a.activeMonth=d;var s=c.style;s.display="block";if(b.navtype<0)s.left=b.offsetLeft+"px";else{var e=c.offsetWidth;if(typeof e=="undefined")e=50;s.left=(b.offsetLeft+b.offsetWidth-e)+"px"}s.top=(b.offsetTop+b.offsetHeight)+"px"};Calendar.showYearsCombo=function(a){var b=Calendar._C;if(!b){return false}var b=b;var c=b.activeDiv;var d=b.yearsCombo;if(b.hilitedYear){Calendar.removeClass(b.hilitedYear,"hilite")}if(b.activeYear){Calendar.removeClass(b.activeYear,"active")}b.activeYear=null;var Y=b.date.getFullYear()+(a?1:-1);var e=d.firstChild;var f=false;for(var i=12;i>0;--i){if(Y>=b.minYear&&Y<=b.maxYear){e.innerHTML=Y;e.year=Y;e.style.display="block";f=true}else{e.style.display="none"}e=e.nextSibling;Y+=a?b.yearStep:-b.yearStep}if(f){var s=d.style;s.display="block";if(c.navtype<0)s.left=c.offsetLeft+"px";else{var g=d.offsetWidth;if(typeof g=="undefined")g=50;s.left=(c.offsetLeft+c.offsetWidth-g)+"px"}s.top=(c.offsetTop+c.offsetHeight)+"px"}};Calendar.tableMouseUp=function(a){var b=Calendar._C;if(!b){return false}if(b.timeout){clearTimeout(b.timeout)}var c=b.activeDiv;if(!c){return false}var d=Calendar.getTargetElement(a);a||(a=window.event);Calendar.removeClass(c,"active");if(d==c||d.parentNode==c){Calendar.cellClick(c,a)}var e=Calendar.findMonth(d);var f=null;if(e){f=new Date(b.date);if(e.month!=f.getMonth()){f.setMonth(e.month);b.setDate(f);b.dateClicked=false;b.callHandler()}}else{var g=Calendar.findYear(d);if(g){f=new Date(b.date);if(g.year!=f.getFullYear()){f.setFullYear(g.year);b.setDate(f);b.dateClicked=false;b.callHandler()}}}with(Calendar){removeEvent(document,"mouseup",tableMouseUp);removeEvent(document,"mouseover",tableMouseOver);removeEvent(document,"mousemove",tableMouseOver);b._hideCombos();_C=null;return stopEvent(a)}};Calendar.tableMouseOver=function(a){var b=Calendar._C;if(!b){return}var c=b.activeDiv;var d=Calendar.getTargetElement(a);if(d==c||d.parentNode==c){Calendar.addClass(c,"hilite active");Calendar.addClass(c.parentNode,"rowhilite")}else{if(typeof c.navtype=="undefined"||(c.navtype!=50&&(c.navtype==0||Math.abs(c.navtype)>2)))Calendar.removeClass(c,"active");Calendar.removeClass(c,"hilite");Calendar.removeClass(c.parentNode,"rowhilite")}a||(a=window.event);if(c.navtype==50&&d!=c){var e=Calendar.getAbsolutePos(c);var w=c.offsetWidth;var x=a.clientX;var f;var g=true;if(x>e.x+w){f=x-e.x-w;g=false}else f=e.x-x;if(f<0)f=0;var h=c._range;var j=c._current;var k=Math.floor(f/10)%h.length;for(var i=h.length;--i>=0;)if(h[i]==j)break;while(k-->0)if(g){if(--i<0)i=h.length-1}else if(++i>=h.length)i=0;var l=h[i];c.innerHTML=l;b.onUpdateTime()}var m=Calendar.findMonth(d);if(m){if(m.month!=b.date.getMonth()){if(b.hilitedMonth){Calendar.removeClass(b.hilitedMonth,"hilite")}Calendar.addClass(m,"hilite");b.hilitedMonth=m}else if(b.hilitedMonth){Calendar.removeClass(b.hilitedMonth,"hilite")}}else{if(b.hilitedMonth){Calendar.removeClass(b.hilitedMonth,"hilite")}var n=Calendar.findYear(d);if(n){if(n.year!=b.date.getFullYear()){if(b.hilitedYear){Calendar.removeClass(b.hilitedYear,"hilite")}Calendar.addClass(n,"hilite");b.hilitedYear=n}else if(b.hilitedYear){Calendar.removeClass(b.hilitedYear,"hilite")}}else if(b.hilitedYear){Calendar.removeClass(b.hilitedYear,"hilite")}}return Calendar.stopEvent(a)};Calendar.tableMouseDown=function(a){if(Calendar.getTargetElement(a)==Calendar.getElement(a)){return Calendar.stopEvent(a)}};Calendar.calDragIt=function(a){var b=Calendar._C;if(!(b&&b.dragging)){return false}var c;var d;if(Calendar.is_ie){d=window.event.clientY+document.body.scrollTop;c=window.event.clientX+document.body.scrollLeft}else{c=a.pageX;d=a.pageY}b.hideShowCovered();var e=b.element.style;e.left=(c-b.xOffs)+"px";e.top=(d-b.yOffs)+"px";return Calendar.stopEvent(a)};Calendar.calDragEnd=function(a){var b=Calendar._C;if(!b){return false}b.dragging=false;with(Calendar){removeEvent(document,"mousemove",calDragIt);removeEvent(document,"mouseup",calDragEnd);tableMouseUp(a)}b.hideShowCovered()};Calendar.dayMouseDown=function(a){var b=Calendar.getElement(a);if(b.disabled){return false}var c=b.calendar;c.activeDiv=b;Calendar._C=c;if(b.navtype!=300)with(Calendar){if(b.navtype==50){b._current=b.innerHTML;addEvent(document,"mousemove",tableMouseOver)}else addEvent(document,Calendar.is_ie5?"mousemove":"mouseover",tableMouseOver);addClass(b,"hilite active");addEvent(document,"mouseup",tableMouseUp)}else if(c.isPopup){c._dragStart(a)}if(b.navtype==-1||b.navtype==1){if(c.timeout)clearTimeout(c.timeout);c.timeout=setTimeout("Calendar.showMonthsCombo()",250)}else if(b.navtype==-2||b.navtype==2){if(c.timeout)clearTimeout(c.timeout);c.timeout=setTimeout((b.navtype>0)?"Calendar.showYearsCombo(true)":"Calendar.showYearsCombo(false)",250)}else{c.timeout=null}return Calendar.stopEvent(a)};Calendar.dayMouseDblClick=function(a){Calendar.cellClick(Calendar.getElement(a),a||window.event);if(Calendar.is_ie){document.selection.empty()}};Calendar.dayMouseOver=function(a){var b=Calendar.getElement(a);if(Calendar.isRelated(b,a)||Calendar._C||b.disabled){return false}if(b.ttip){if(b.ttip.substr(0,1)=="_"){b.ttip=b.caldate.print(b.calendar.ttDateFormat)+b.ttip.substr(1)}b.calendar.tooltips.innerHTML=b.ttip}if(b.navtype!=300){Calendar.addClass(b,"hilite");if(b.caldate){Calendar.addClass(b.parentNode,"rowhilite")}}return Calendar.stopEvent(a)};Calendar.dayMouseOut=function(a){with(Calendar){var b=getElement(a);if(isRelated(b,a)||_C||b.disabled)return false;removeClass(b,"hilite");if(b.caldate)removeClass(b.parentNode,"rowhilite");if(b.calendar)b.calendar.tooltips.innerHTML=_TT["SEL_DATE"];return stopEvent(a)}};Calendar.cellClick=function(c,d){var e=c.calendar;var f=false;var g=false;var h=null;if(typeof c.navtype=="undefined"){if(e.currentDateEl){Calendar.removeClass(e.currentDateEl,"selected");Calendar.addClass(c,"selected");f=(e.currentDateEl==c);if(!f){e.currentDateEl=c}}e.date.setDateOnly(c.caldate);h=e.date;var j=!(e.dateClicked=!c.otherMonth);if(!j&&!e.currentDateEl)e._toggleMultipleDate(new Date(h));else g=!c.disabled;if(j)e._init(e.firstDayOfWeek,h)}else{if(c.navtype==200){Calendar.removeClass(c,"hilite");e.callCloseHandler();return}h=new Date(e.date);if(c.navtype==0)h.setDateOnly(new Date());e.dateClicked=false;var k=h.getFullYear();var l=h.getMonth();function setMonth(m){var a=h.getDate();var b=h.getMonthDays(m);if(a>b){h.setDate(b)}h.setMonth(m)};switch(c.navtype){case 400:Calendar.removeClass(c,"hilite");var n=Calendar._TT["ABOUT"];if(typeof n!="undefined"){n+=e.showsTime?Calendar._TT["ABOUT_TIME"]:""}else{n="Help and about box text is not translated into this language.\n"+"If you know this language and you feel generous please update\n"+"the corresponding file in \"lang\" subdir to match calendar-en.js\n"+"and send it back to <mihai_bazon@yahoo.com> to get it into the distribution  ;-)\n\n"+"Thank you!\n"+"http://dynarch.com/mishoo/calendar.epl\n"}alert(n);return;case-2:if(k>e.minYear){h.setFullYear(k-1)}break;case-1:if(l>0){setMonth(l-1)}else if(k-->e.minYear){h.setFullYear(k);setMonth(11)}break;case 1:if(l<11){setMonth(l+1)}else if(k<e.maxYear){h.setFullYear(k+1);setMonth(0)}break;case 2:if(k<e.maxYear){h.setFullYear(k+1)}break;case 100:e.setFirstDayOfWeek(c.fdow);return;case 50:var o=c._range;var p=c.innerHTML;for(var i=o.length;--i>=0;)if(o[i]==p)break;if(d&&d.shiftKey){if(--i<0)i=o.length-1}else if(++i>=o.length)i=0;var q=o[i];c.innerHTML=q;e.onUpdateTime();return;case 0:if((typeof e.getDateStatus=="function")&&e.getDateStatus(h,h.getFullYear(),h.getMonth(),h.getDate())){return false}break}if(!h.equalsTo(e.date)){e.setDate(h);g=true}else if(c.navtype==0)g=f=true}if(g){d&&e.callHandler()}if(f){Calendar.removeClass(c,"hilite");d&&e.callCloseHandler()}};Calendar.prototype.create=function(p){var q=null;if(!p){q=document.getElementsByTagName("body")[0];this.isPopup=true}else{q=p;this.isPopup=false}this.date=this.dateStr?new Date(this.dateStr):new Date();var r=Calendar.createElement("table");this.table=r;r.cellSpacing=0;r.cellPadding=0;r.calendar=this;Calendar.addEvent(r,"mousedown",Calendar.tableMouseDown);var s=Calendar.createElement("div");this.element=s;s.className="calendar";if(this.isPopup){s.style.position="absolute";s.style.display="none"}s.appendChild(r);var t=Calendar.createElement("thead",r);var u=null;var v=null;var w=this;var x=function(a,b,c){u=Calendar.createElement("td",v);u.colSpan=b;u.className="button";if(c!=0&&Math.abs(c)<=2)u.className+=" nav";Calendar._add_evs(u);u.calendar=w;u.navtype=c;u.innerHTML="<div unselectable='on'>"+a+"</div>";return u};v=Calendar.createElement("tr",t);var z=6;(this.isPopup)&&--z;(this.weekNumbers)&&++z;x("?",1,400).ttip=Calendar._TT["INFO"];this.title=x("",z,300);this.title.className="title";if(this.isPopup){this.title.ttip=Calendar._TT["DRAG_TO_MOVE"];this.title.style.cursor="move";x("&#x00d7;",1,200).ttip=Calendar._TT["CLOSE"]}v=Calendar.createElement("tr",t);v.className="headrow";this._nav_py=x("&#x00ab;",1,-2);this._nav_py.ttip=Calendar._TT["PREV_YEAR"];this._nav_pm=x("&#x2039;",1,-1);this._nav_pm.ttip=Calendar._TT["PREV_MONTH"];this._nav_now=x(Calendar._TT["TODAY"],this.weekNumbers?4:3,1);this._nav_now.ttip=Calendar._TT["GO_TODAY"];this._nav_nm=x("&#x203a;",1,1);this._nav_nm.ttip=Calendar._TT["NEXT_MONTH"];this._nav_ny=x("&#x00bb;",1,2);this._nav_ny.ttip=Calendar._TT["NEXT_YEAR"];v=Calendar.createElement("tr",t);v.className="daynames";if(this.weekNumbers){u=Calendar.createElement("td",v);u.className="name wn";u.innerHTML=Calendar._TT["WK"]}for(var i=7;i>0;--i){u=Calendar.createElement("td",v);if(!i){u.navtype=100;u.calendar=this;Calendar._add_evs(u)}}this.firstdayname=(this.weekNumbers)?v.firstChild.nextSibling:v.firstChild;this._displayWeekdays();var A=Calendar.createElement("tbody",r);this.tbody=A;for(i=6;i>0;--i){v=Calendar.createElement("tr",A);if(this.weekNumbers){u=Calendar.createElement("td",v)}for(var j=7;j>0;--j){u=Calendar.createElement("td",v);u.calendar=this;Calendar._add_evs(u)}}if(this.showsTime){v=Calendar.createElement("tr",A);v.className="time";u=Calendar.createElement("td",v);u.className="time";u.colSpan=2;u.innerHTML=Calendar._TT["TIME"]||"&nbsp;";u=Calendar.createElement("td",v);u.className="time";u.colSpan=this.weekNumbers?4:3;(function(){function makeTimePart(a,b,c,d){var e=Calendar.createElement("span",u);e.className=a;e.innerHTML=b;e.calendar=w;e.ttip=Calendar._TT["TIME_PART"];e.navtype=50;e._range=[];if(typeof c!="number")e._range=c;else{for(var i=c;i<=d;++i){var f;if(i<10&&d>=10)f='0'+i;else f=''+i;e._range[e._range.length]=f}}Calendar._add_evs(e);return e};var g=w.date.getHours();var j=w.date.getMinutes();var k=!w.time24;var l=(g>12);if(k&&l)g-=12;var H=makeTimePart("hour",g,k?1:0,k?12:23);var n=Calendar.createElement("span",u);n.innerHTML=":";n.className="colon";var M=makeTimePart("minute",j,0,59);var o=null;u=Calendar.createElement("td",v);u.className="time";u.colSpan=2;if(k)o=makeTimePart("ampm",l?"pm":"am",["am","pm"]);else u.innerHTML="&nbsp;";w.onSetTime=function(){var a,g=this.date.getHours(),j=this.date.getMinutes();if(k){a=(g>=12);if(a)g-=12;if(g==0)g=12;o.innerHTML=a?"pm":"am"}H.innerHTML=(g<10)?("0"+g):g;M.innerHTML=(j<10)?("0"+j):j};w.onUpdateTime=function(){var a=this.date;var h=parseInt(H.innerHTML,10);if(k){if(/pm/i.test(o.innerHTML)&&h<12)h+=12;else if(/am/i.test(o.innerHTML)&&h==12)h=0}var d=a.getDate();var m=a.getMonth();var y=a.getFullYear();a.setHours(h);a.setMinutes(parseInt(M.innerHTML,10));a.setFullYear(y);a.setMonth(m);a.setDate(d);this.dateClicked=false;this.callHandler()}})()}else{this.onSetTime=this.onUpdateTime=function(){}}var B=Calendar.createElement("tfoot",r);v=Calendar.createElement("tr",B);v.className="footrow";u=x(Calendar._TT["SEL_DATE"],this.weekNumbers?8:7,300);u.className="ttip";if(this.isPopup){u.ttip=Calendar._TT["DRAG_TO_MOVE"];u.style.cursor="move"}this.tooltips=u;s=Calendar.createElement("div",this.element);this.monthsCombo=s;s.className="combo";for(i=0;i<Calendar._MN.length;++i){var C=Calendar.createElement("div");C.className=Calendar.is_ie?"label-IEfix":"label";C.month=i;C.innerHTML=Calendar._SMN[i];s.appendChild(C)}s=Calendar.createElement("div",this.element);this.yearsCombo=s;s.className="combo";for(i=12;i>0;--i){var D=Calendar.createElement("div");D.className=Calendar.is_ie?"label-IEfix":"label";s.appendChild(D)}this._init(this.firstDayOfWeek,this.date);q.appendChild(this.element)};Calendar._keyEvent=function(b){var c=window._dynarch_popupCalendar;if(!c||c.multiple)return false;(Calendar.is_ie)&&(b=window.event);var d=(Calendar.is_ie||b.type=="keypress"),K=b.keyCode;if(b.ctrlKey){switch(K){case 37:d&&Calendar.cellClick(c._nav_pm);break;case 38:d&&Calendar.cellClick(c._nav_py);break;case 39:d&&Calendar.cellClick(c._nav_nm);break;case 40:d&&Calendar.cellClick(c._nav_ny);break;default:return false}}else switch(K){case 32:Calendar.cellClick(c._nav_now);break;case 27:d&&c.callCloseHandler();break;case 37:case 38:case 39:case 40:if(d){var e,x,y,ne,el,step;e=K==37||K==38;step=(K==37||K==39)?1:7;function setVars(){el=c.currentDateEl;var p=el.pos;x=p&15;y=p>>4;ne=c.ar_days[y][x]};setVars();function prevMonth(){var a=new Date(c.date);a.setDate(a.getDate()-step);c.setDate(a)};function nextMonth(){var a=new Date(c.date);a.setDate(a.getDate()+step);c.setDate(a)};while(1){switch(K){case 37:if(--x>=0)ne=c.ar_days[y][x];else{x=6;K=38;continue}break;case 38:if(--y>=0)ne=c.ar_days[y][x];else{prevMonth();setVars()}break;case 39:if(++x<7)ne=c.ar_days[y][x];else{x=0;K=40;continue}break;case 40:if(++y<c.ar_days.length)ne=c.ar_days[y][x];else{nextMonth();setVars()}break}break}if(ne){if(!ne.disabled)Calendar.cellClick(ne);else if(e)prevMonth();else nextMonth()}}break;case 13:if(d)Calendar.cellClick(c.currentDateEl,b);break;default:return false}return Calendar.stopEvent(b)};Calendar.prototype._init=function(a,b){var c=new Date(),TY=c.getFullYear(),TM=c.getMonth(),TD=c.getDate();this.table.style.visibility="hidden";var d=b.getFullYear();if(d<this.minYear){d=this.minYear;b.setFullYear(d)}else if(d>this.maxYear){d=this.maxYear;b.setFullYear(d)}this.firstDayOfWeek=a;this.date=new Date(b);var e=b.getMonth();var f=b.getDate();var g=b.getMonthDays();b.setDate(1);var h=(b.getDay()-this.firstDayOfWeek)%7;if(h<0)h+=7;b.setDate(-h);b.setDate(b.getDate()+1);var k=this.tbody.firstChild;var l=Calendar._SMN[e];var m=this.ar_days=new Array();var n=Calendar._TT["WEEKEND"];var o=this.multiple?(this.datesCells={}):null;for(var i=0;i<6;++i,k=k.nextSibling){var p=k.firstChild;if(this.weekNumbers){p.className="day wn";p.innerHTML=b.getWeekNumber();p=p.nextSibling}k.className="daysrow";var q=false,iday,dpos=m[i]=[];for(var j=0;j<7;++j,p=p.nextSibling,b.setDate(iday+1)){iday=b.getDate();var r=b.getDay();p.className="day";p.pos=i<<4|j;dpos[j]=p;var s=(b.getMonth()==e);if(!s){if(this.showsOtherMonths){p.className+=" othermonth";p.otherMonth=true}else{p.className="emptycell";p.innerHTML="&nbsp;";p.disabled=true;continue}}else{p.otherMonth=false;q=true}p.disabled=false;p.innerHTML=this.getDateText?this.getDateText(b,iday):iday;if(o)o[b.print("%Y%m%d")]=p;if(this.getDateStatus){var t=this.getDateStatus(b,d,e,iday);if(this.getDateToolTip){var u=this.getDateToolTip(b,d,e,iday);if(u)p.title=u}if(t===true){p.className+=" disabled";p.disabled=true}else{if(/disabled/i.test(t))p.disabled=true;p.className+=" "+t}}if(!p.disabled){p.caldate=new Date(b);p.ttip="_";if(!this.multiple&&s&&iday==f&&this.hiliteToday){p.className+=" selected";this.currentDateEl=p}if(b.getFullYear()==TY&&b.getMonth()==TM&&iday==TD){p.className+=" today";p.ttip+=Calendar._TT["PART_TODAY"]}if(n.indexOf(r.toString())!=-1)p.className+=p.otherMonth?" oweekend":" weekend"}}if(!(q||this.showsOtherMonths))k.className="emptyrow"}this.title.innerHTML=Calendar._MN[e]+", "+d;this.onSetTime();this.table.style.visibility="visible";this._initMultipleDates()};Calendar.prototype._initMultipleDates=function(){if(this.multiple){for(var i in this.multiple){var a=this.datesCells[i];var d=this.multiple[i];if(!d)continue;if(a)a.className+=" selected"}}};Calendar.prototype._toggleMultipleDate=function(a){if(this.multiple){var b=a.print("%Y%m%d");var c=this.datesCells[b];if(c){var d=this.multiple[b];if(!d){Calendar.addClass(c,"selected");this.multiple[b]=a}else{Calendar.removeClass(c,"selected");delete this.multiple[b]}}}};Calendar.prototype.setDateToolTipHandler=function(a){this.getDateToolTip=a};Calendar.prototype.setDate=function(a){if(!a.equalsTo(this.date)){this._init(this.firstDayOfWeek,a)}};Calendar.prototype.refresh=function(){this._init(this.firstDayOfWeek,this.date)};Calendar.prototype.setFirstDayOfWeek=function(a){this._init(a,this.date);this._displayWeekdays()};Calendar.prototype.setDateStatusHandler=Calendar.prototype.setDisabledHandler=function(a){this.getDateStatus=a};Calendar.prototype.setRange=function(a,z){this.minYear=a;this.maxYear=z};Calendar.prototype.callHandler=function(){if(this.onSelected){this.onSelected(this,this.date.print(this.dateFormat))}};Calendar.prototype.callCloseHandler=function(){if(this.onClose){this.onClose(this)}this.hideShowCovered()};Calendar.prototype.destroy=function(){var a=this.element.parentNode;a.removeChild(this.element);Calendar._C=null;window._dynarch_popupCalendar=null};Calendar.prototype.reparent=function(a){var b=this.element;b.parentNode.removeChild(b);a.appendChild(b)};Calendar._checkCalendar=function(a){var b=window._dynarch_popupCalendar;if(!b){return false}var c=Calendar.is_ie?Calendar.getElement(a):Calendar.getTargetElement(a);for(;c!=null&&c!=b.element;c=c.parentNode);if(c==null){window._dynarch_popupCalendar.callCloseHandler();return Calendar.stopEvent(a)}};Calendar.prototype.show=function(){var a=this.table.getElementsByTagName("tr");for(var i=a.length;i>0;){var b=a[--i];Calendar.removeClass(b,"rowhilite");var c=b.getElementsByTagName("td");for(var j=c.length;j>0;){var d=c[--j];Calendar.removeClass(d,"hilite");Calendar.removeClass(d,"active")}}this.element.style.display="block";this.hidden=false;if(this.isPopup){window._dynarch_popupCalendar=this;Calendar.addEvent(document,"keydown",Calendar._keyEvent);Calendar.addEvent(document,"keypress",Calendar._keyEvent);Calendar.addEvent(document,"mousedown",Calendar._checkCalendar)}this.hideShowCovered()};Calendar.prototype.hide=function(){if(this.isPopup){Calendar.removeEvent(document,"keydown",Calendar._keyEvent);Calendar.removeEvent(document,"keypress",Calendar._keyEvent);Calendar.removeEvent(document,"mousedown",Calendar._checkCalendar)}this.element.style.display="none";this.hidden=true;this.hideShowCovered()};Calendar.prototype.showAt=function(x,y){var s=this.element.style;s.left=x+"px";s.top=y+"px";this.show()};Calendar.prototype.showAtElement=function(e,f){var g=this;var p=Calendar.getAbsolutePos(e);if(!f||typeof f!="string"){this.showAt(p.x,p.y+e.offsetHeight);return true}function fixPosition(a){if(a.x<0)a.x=0;if(a.y<0)a.y=0;var b=document.createElement("div");var s=b.style;s.position="absolute";s.right=s.bottom=s.width=s.height="0px";document.body.appendChild(b);var c=Calendar.getAbsolutePos(b);document.body.removeChild(b);if(Calendar.is_ie){c.y+=document.body.scrollTop;c.x+=document.body.scrollLeft}else{c.y+=window.scrollY;c.x+=window.scrollX}var d=a.x+a.width-c.x;if(d>0)a.x-=d;d=a.y+a.height-c.y;if(d>0)a.y-=d};this.element.style.display="block";Calendar.continuation_for_the_fucking_khtml_browser=function(){var w=g.element.offsetWidth;var h=g.element.offsetHeight;g.element.style.display="none";var a=f.substr(0,1);var b="l";if(f.length>1){b=f.substr(1,1)}switch(a){case"T":p.y-=h;break;case"B":p.y+=e.offsetHeight;break;case"C":p.y+=(e.offsetHeight-h)/2;break;case"t":p.y+=e.offsetHeight-h;break;case"b":break}switch(b){case"L":p.x-=w;break;case"R":p.x+=e.offsetWidth;break;case"C":p.x+=(e.offsetWidth-w)/2;break;case"l":p.x+=e.offsetWidth-w;break;case"r":break}p.width=w;p.height=h+40;g.monthsCombo.style.display="none";fixPosition(p);g.showAt(p.x,p.y)};if(Calendar.is_khtml)setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()",10);else Calendar.continuation_for_the_fucking_khtml_browser()};Calendar.prototype.setDateFormat=function(a){this.dateFormat=a};Calendar.prototype.setTtDateFormat=function(a){this.ttDateFormat=a};Calendar.prototype.parseDate=function(a,b){if(!b)b=this.dateFormat;this.setDate(Date.parseDate(a,b))};Calendar.prototype.hideShowCovered=function(){if(!Calendar.is_ie&&!Calendar.is_opera)return;function getVisib(a){var b=a.style.visibility;if(!b){if(document.defaultView&&typeof(document.defaultView.getComputedStyle)=="function"){if(!Calendar.is_khtml)b=document.defaultView.getComputedStyle(a,"").getPropertyValue("visibility");else b=''}else if(a.currentStyle){b=a.currentStyle.visibility}else b=''}return b};var c=new Array("applet","iframe","select");var d=this.element;var p=Calendar.getAbsolutePos(d);var e=p.x;var f=d.offsetWidth+e;var g=p.y;var h=d.offsetHeight+g;for(var k=c.length;k>0;){var j=document.getElementsByTagName(c[--k]);var l=null;for(var i=j.length;i>0;){l=j[--i];p=Calendar.getAbsolutePos(l);var m=p.x;var n=l.offsetWidth+m;var o=p.y;var q=l.offsetHeight+o;if(this.hidden||(m>f)||(n<e)||(o>h)||(q<g)){if(!l.__msh_save_visibility){l.__msh_save_visibility=getVisib(l)}l.style.visibility=l.__msh_save_visibility}else{if(!l.__msh_save_visibility){l.__msh_save_visibility=getVisib(l)}l.style.visibility="hidden"}}}};Calendar.prototype._displayWeekdays=function(){var a=this.firstDayOfWeek;var b=this.firstdayname;var c=Calendar._TT["WEEKEND"];for(var i=0;i<7;++i){b.className="day name";var d=(i+a)%7;if(i){b.ttip=Calendar._TT["DAY_FIRST"].replace("%s",Calendar._DN[d]);b.navtype=100;b.calendar=this;b.fdow=d;Calendar._add_evs(b)}if(c.indexOf(d.toString())!=-1){Calendar.addClass(b,"weekend")}b.innerHTML=Calendar._SDN[(i+a)%7];b=b.nextSibling}};Calendar.prototype._hideCombos=function(){this.monthsCombo.style.display="none";this.yearsCombo.style.display="none"};Calendar.prototype._dragStart=function(a){if(this.dragging){return}this.dragging=true;var b;var c;if(Calendar.is_ie){c=window.event.clientY+document.body.scrollTop;b=window.event.clientX+document.body.scrollLeft}else{c=a.clientY+window.scrollY;b=a.clientX+window.scrollX}var d=this.element.style;this.xOffs=b-parseInt(d.left);this.yOffs=c-parseInt(d.top);with(Calendar){addEvent(document,"mousemove",calDragIt);addEvent(document,"mouseup",calDragEnd)}};Date._MD=new Array(31,28,31,30,31,30,31,31,30,31,30,31);Date.SECOND=1000;Date.MINUTE=60*Date.SECOND;Date.HOUR=60*Date.MINUTE;Date.DAY=24*Date.HOUR;Date.WEEK=7*Date.DAY;Date.parseDate=function(c,e){var f=new Date();var y=0;var m=-1;var d=0;var a=c.split(/\W+/);var b=e.match(/%./g);var i=0,j=0;var g=0;var h=0;for(i=0;i<a.length;++i){if(!a[i])continue;switch(b[i]){case"%d":case"%e":d=parseInt(a[i],10);break;case"%m":m=parseInt(a[i],10)-1;break;case"%Y":case"%y":y=parseInt(a[i],10);(y<100)&&(y+=(y>29)?1900:2000);break;case"%b":case"%B":for(j=0;j<12;++j){if(Calendar._MN[j].substr(0,a[i].length).toLowerCase()==a[i].toLowerCase()){m=j;break}}break;case"%H":case"%I":case"%k":case"%l":g=parseInt(a[i],10);break;case"%P":case"%p":if(/pm/i.test(a[i])&&g<12)g+=12;else if(/am/i.test(a[i])&&g>=12)g-=12;break;case"%M":h=parseInt(a[i],10);break}}if(isNaN(y))y=f.getFullYear();if(isNaN(m))m=f.getMonth();if(isNaN(d))d=f.getDate();if(isNaN(g))g=f.getHours();if(isNaN(h))h=f.getMinutes();if(y!=0&&m!=-1&&d!=0)return new Date(y,m,d,g,h,0);y=0;m=-1;d=0;for(i=0;i<a.length;++i){if(a[i].search(/[a-zA-Z]+/)!=-1){var t=-1;for(j=0;j<12;++j){if(Calendar._MN[j].substr(0,a[i].length).toLowerCase()==a[i].toLowerCase()){t=j;break}}if(t!=-1){if(m!=-1){d=m+1}m=t}}else if(parseInt(a[i],10)<=12&&m==-1){m=a[i]-1}else if(parseInt(a[i],10)>31&&y==0){y=parseInt(a[i],10);(y<100)&&(y+=(y>29)?1900:2000)}else if(d==0){d=a[i]}}if(y==0)y=f.getFullYear();if(m!=-1&&d!=0)return new Date(y,m,d,g,h,0);return f};Date.prototype.getMonthDays=function(a){var b=this.getFullYear();if(typeof a=="undefined"){a=this.getMonth()}if(((0==(b%4))&&((0!=(b%100))||(0==(b%400))))&&a==1){return 29}else{return Date._MD[a]}};Date.prototype.getDayOfYear=function(){var a=new Date(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0);var b=new Date(this.getFullYear(),0,0,0,0,0);var c=a-b;return Math.floor(c/Date.DAY)};Date.prototype.getWeekNumber=function(){var d=new Date(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0);var a=d.getDay();d.setDate(d.getDate()-(a+6)%7+3);var b=d.valueOf();d.setMonth(0);d.setDate(4);return Math.round((b-d.valueOf())/(7*864e5))+1};Date.prototype.equalsTo=function(a){return((this.getFullYear()==a.getFullYear())&&(this.getMonth()==a.getMonth())&&(this.getDate()==a.getDate())&&(this.getHours()==a.getHours())&&(this.getMinutes()==a.getMinutes()))};Date.prototype.setDateOnly=function(a){var b=new Date(a);this.setDate(1);this.setFullYear(b.getFullYear());this.setMonth(b.getMonth());this.setDate(b.getDate())};Date.prototype.print=function(b){var m=this.getMonth();var d=this.getDate();var y=this.getFullYear();var c=this.getWeekNumber();var w=this.getDay();var s={};var e=this.getHours();var f=(e>=12);var g=(f)?(e-12):e;var h=this.getDayOfYear();if(g==0)g=12;var j=this.getMinutes();var k=this.getSeconds();s["%a"]=Calendar._SDN[w];s["%A"]=Calendar._DN[w];s["%b"]=Calendar._SMN[m];s["%B"]=Calendar._MN[m];s["%C"]=1+Math.floor(y/100);s["%d"]=(d<10)?("0"+d):d;s["%e"]=d;s["%H"]=(e<10)?("0"+e):e;s["%I"]=(g<10)?("0"+g):g;s["%j"]=(h<100)?((h<10)?("00"+h):("0"+h)):h;s["%k"]=e;s["%l"]=g;s["%m"]=(m<9)?("0"+(1+m)):(1+m);s["%M"]=(j<10)?("0"+j):j;s["%n"]="\n";s["%p"]=f?"PM":"AM";s["%P"]=f?"pm":"am";s["%s"]=Math.floor(this.getTime()/1000);s["%S"]=(k<10)?("0"+k):k;s["%t"]="\t";s["%U"]=s["%W"]=s["%V"]=(c<10)?("0"+c):c;s["%u"]=w+1;s["%w"]=w;s["%y"]=(''+y).substr(2,2);s["%Y"]=y;s["%%"]="%";var l=/%./g;if(!Calendar.is_ie5&&!Calendar.is_khtml)return b.replace(l,function(a){return s[a]||a});var a=b.match(l);for(var i=0;i<a.length;i++){var n=s[a[i]];if(n){l=new RegExp(a[i],'g');b=b.replace(l,n)}}return b};Date.prototype.__msh_oldSetFullYear=Date.prototype.setFullYear;Date.prototype.setFullYear=function(y){var d=new Date(this);d.__msh_oldSetFullYear(y);if(d.getMonth()!=this.getMonth())this.setDate(28);this.__msh_oldSetFullYear(y)};window._dynarch_popupCalendar=null;



// full day names
Calendar._DN = new Array
("Sonntag",
 "Montag",
 "Dienstag",
 "Mittwoch",
 "Donnerstag",
 "Freitag",
 "Samstag",
 "Sonntag");

// First day of the week. "0" means display Sunday first, "1" means display
// Monday first, etc.
Calendar._FD = 1;


// Please note that the following array of short day names (and the same goes
// for short month names, _SMN) isn't absolutely necessary.  We give it here
// for exemplification on how one can customize the short day names, but if
// they are simply the first N letters of the full name you can simply say:
//
//   Calendar._SDN_len = N; // short day name length
//   Calendar._SMN_len = N; // short month name length
//
// If N = 3 then this is not needed either since we assume a value of 3 if not
// present, to be compatible with translation files that were written before
// this feature.

// short day names
Calendar._SDN = new Array
("So",
 "Mo",
 "Di",
 "Mi",
 "Do",
 "Fr",
 "Sa",
 "So");

// full month names
Calendar._MN = new Array
("Januar",
 "Februar",
 "M\u00e4rz",
 "April",
 "Mai",
 "Juni",
 "Juli",
 "August",
 "September",
 "Oktober",
 "November",
 "Dezember");

// short month names
Calendar._SMN = new Array
("Jan",
 "Feb",
 "M\u00e4r",
 "Apr",
 "May",
 "Jun",
 "Jul",
 "Aug",
 "Sep",
 "Okt",
 "Nov",
 "Dez");

// tooltips
Calendar._TT = {};
Calendar._TT["INFO"] = "\u00DCber dieses Kalendarmodul";

Calendar._TT["ABOUT"] =
"DHTML Date/Time Selector\n" +
"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this ;-)
"For latest version visit: http://www.dynarch.com/projects/calendar/\n" +
"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details." +
"\n\n" +
"Datum ausw\u00e4hlen:\n" +
"- Benutzen Sie die \xab, \xbb Buttons um das Jahr zu w\u00e4hlen\n" +
"- Benutzen Sie die " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " Buttons um den Monat zu w\u00e4hlen\n" +
"- F\u00fcr eine Schnellauswahl halten Sie die Maustaste \u00fcber diesen Buttons fest.";
Calendar._TT["ABOUT_TIME"] = "\n\n" +
"Zeit ausw\u00e4hlen:\n" +
"- Klicken Sie auf die Teile der Uhrzeit, um diese zu erh\u00F6hen\n" +
"- oder klicken Sie mit festgehaltener Shift-Taste um diese zu verringern\n" +
"- oder klicken und festhalten f\u00fcr Schnellauswahl.";

hold = "<br>(Festhalten f\u00fcr Schnellauswahl)"
Calendar._TT["TOGGLE"] = "Ersten Tag der Woche w\u00e4hlen";
Calendar._TT["PREV_YEAR"] = "Voriges Jahr" + hold;
Calendar._TT["PREV_MONTH"] = "Voriger Monat" + hold;
Calendar._TT["GO_TODAY"] = "Heute ausw\u00e4hlen";
Calendar._TT["NEXT_MONTH"] = "N\u00e4chst. Monat" + hold;
Calendar._TT["NEXT_YEAR"] = "N\u00e4chst. Jahr" + hold;
Calendar._TT["SEL_DATE"] = "Datum ausw\u00e4hlen";
Calendar._TT["DRAG_TO_MOVE"] = "Zum Bewegen festhalten";
Calendar._TT["PART_TODAY"] = " (Heute)";

// the following is to inform that "%s" is to be the first day of week
// %s will be replaced with the day name.
Calendar._TT["DAY_FIRST"] = "Woche beginnt mit %s ";

// This may be locale-dependent.  It specifies the week-end days, as an array
// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1
// means Monday, etc.
Calendar._TT["WEEKEND"] = "0,6";

Calendar._TT["CLOSE"] = "Schlie\u00dfen";
Calendar._TT["TODAY"] = "Heute";
Calendar._TT["TIME_PART"] = "(Shift-)Klick oder Festhalten und Ziehen um den Wert zu \u00e4ndern";

// date formats
Calendar._TT["DEF_DATE_FORMAT"] = "%d.%m.%Y";
Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e";

Calendar._TT["WK"] = "wk";
Calendar._TT["TIME"] = "Zeit:";


Calendar.setup=function(h){function param_default(a,b){if(typeof h[a]=="undefined"){h[a]=b;}};param_default("inputField",null);param_default("displayArea",null);param_default("button",null);param_default("eventName","click");param_default("ifFormat","%Y/%m/%d");param_default("daFormat","%Y/%m/%d");param_default("singleClick",true);param_default("disableFunc",null);param_default("dateStatusFunc",h["disableFunc"]);param_default("dateText",null);param_default("firstDay",null);param_default("align","Br");param_default("range",[1900,2999]);param_default("weekNumbers",true);param_default("flat",null);param_default("flatCallback",null);param_default("onSelect",null);param_default("onClose",null);param_default("onUpdate",null);param_default("date",null);param_default("showsTime",false);param_default("timeFormat","24");param_default("electric",true);param_default("step",2);param_default("position",null);param_default("cache",false);param_default("showOthers",false);param_default("multiple",null);var j=["inputField","displayArea","button"];for(var i in j){if(typeof h[j[i]]=="string"){h[j[i]]=document.getElementById(h[j[i]]);}}if(!(h.flat||h.multiple||h.inputField||h.displayArea||h.button)){alert("Calendar.setup:\n  Nothing to setup (no fields found).  Please check your code");return false;}function onSelect(a){var p=a.params;var b=(a.dateClicked||p.electric);if(b&&p.inputField){p.inputField.value=a.date.print(p.ifFormat);if(typeof p.inputField.onchange=="function")p.inputField.onchange();}if(b&&p.displayArea)p.displayArea.innerHTML=a.date.print(p.daFormat);if(b&&typeof p.onUpdate=="function")p.onUpdate(a);if(b&&p.flat){if(typeof p.flatCallback=="function")p.flatCallback(a);}if(b&&p.singleClick&&a.dateClicked)a.callCloseHandler();};if(h.flat!=null){if(typeof h.flat=="string")h.flat=document.getElementById(h.flat);if(!h.flat){alert("Calendar.setup:\n  Flat specified but can't find parent.");return false;}var k=new Calendar(h.firstDay,h.date,h.onSelect||onSelect);k.showsOtherMonths=h.showOthers;k.showsTime=h.showsTime;k.time24=(h.timeFormat=="24");k.params=h;k.weekNumbers=h.weekNumbers;k.setRange(h.range[0],h.range[1]);k.setDateStatusHandler(h.dateStatusFunc);k.getDateText=h.dateText;if(h.ifFormat){k.setDateFormat(h.ifFormat);}if(h.inputField&&typeof h.inputField.value=="string"){k.parseDate(h.inputField.value);}k.create(h.flat);k.show();return false;}var l=h.button||h.displayArea||h.inputField;l["on"+h.eventName]=function(){var b=h.inputField||h.displayArea;var c=h.inputField?h.ifFormat:h.daFormat;var e=false;var f=window.calendar;if(b)h.date=Date.parseDate(b.value||b.innerHTML,c);if(!(f&&h.cache)){window.calendar=f=new Calendar(h.firstDay,h.date,h.onSelect||onSelect,h.onClose||function(a){a.hide();});f.showsTime=h.showsTime;f.time24=(h.timeFormat=="24");f.weekNumbers=h.weekNumbers;e=true;}else{if(h.date)f.setDate(h.date);f.hide();}if(h.multiple){f.multiple={};for(var i=h.multiple.length;--i>=0;){var d=h.multiple[i];var g=d.print("%Y%m%d");f.multiple[g]=d;}}f.showsOtherMonths=h.showOthers;f.yearStep=h.step;f.setRange(h.range[0],h.range[1]);f.params=h;f.setDateStatusHandler(h.dateStatusFunc);f.getDateText=h.dateText;f.setDateFormat(c);if(e)f.create();f.refresh();if(!h.position)f.showAtElement(h.button||h.displayArea||h.inputField,h.align);else f.showAt(h.position[0],h.position[1]);return false;};return k;};

Ajax.Responders.register({
  onCreate: function() {
    if($('busy_ajax') && Ajax.activeRequestCount>0 && !Ajax.supressBusyAjax) {
      Effect.Appear('busy_ajax',{duration:0.5});
    }
  },
  onComplete: function() {
    if($('busy_ajax') && Ajax.activeRequestCount==0 && !Ajax.supressBusyAjax)
      Effect.Fade('busy_ajax',{duration:0.5});
  }
});

var BusyAjax = {
  offX: 12, 
  offY: 10, 
  divName: 'busy_ajax',
  mouseX: function(evt) {
    if (!evt) evt = window.event;
    if (evt.pageX) return evt.pageX;
    else if (evt.clientX) return evt.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
    else return 0;
  },
  mouseY: function(evt) {
    if (!evt) evt = window.event;
    if (evt.pageY) return evt.pageY;
    else if (evt.clientY) return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
    else return 0;
  },
  follow: function(evt) {
    var element = $(this.divName);
    if (element) {
      var style = element.style; 
      style.visibility = 'visible';
      style.left = (parseInt(this.mouseX(evt), 10) + this.offX) + 'px';
      style.top = (parseInt(this.mouseY(evt), 10) + this.offY) + 'px';
    }
  }, 
  start: function() {
    Event.observe(document, "mousemove", this.follow.bindAsEventListener(this));
  }
};

BusyAjax.start();