//MooTools, My Object Oriented Javascript Tools. Copyright (c) 2006 Valerio Proietti, <http://mad4milk.net>, MIT Style License.
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('o bF={\'bG\':1.1};k $8a(O){m(O!=b9)};k $F(O){B(!$8a(O))m N;B(O.4Y)m\'G\';o F=7g O;B(F==\'2C\'&&O.c4){23(O.7s){12 1:m\'G\';12 3:m/\\S/.2t(O.8Z)?\'bk\':\'bu\'}}B(F==\'2C\'||F==\'k\'){23(O.aR){12 2I:m\'1B\';12 7V:m\'5n\';12 18:m\'4O\'}B(7g O.V==\'4S\'){B(O.3h)m\'cT\';B(O.8r)m\'1c\'}}m F};k $2c(){o 4R={};M(o i=0;i<1c.V;i++){M(o K 1b 1c[i]){o ap=1c[i][K];o 6R=4R[K];B(6R&&$F(ap)==\'2C\'&&$F(6R)==\'2C\')4R[K]=$2c(6R,ap);17 4R[K]=ap}}m 4R};o $R=7c.R=k(){o 1q=1c;B(!1q[1])1q=[c,1q[0]];M(o K 1b 1q[1])1q[0][K]=1q[1][K];m 1q[0]};o $4Q=7c.cW=k(){M(o i=0,l=1c.V;i<l;i++){1c[i].R=k(1W){M(o 1V 1b 1W){B(!c.1L[1V])c.1L[1V]=1W[1V];B(!c[1V])c[1V]=$4Q.6P(1V)}}}};$4Q.6P=k(1V){m k(Y){m c.1L[1V].3U(Y,2I.1L.aI.1S(1c,1))}};$4Q(7S,2I,6W,ao);o 3y=k(O){O=O||{};O.R=$R;m O};o cX=L 3y(U);o cM=L 3y(P);P.6s=P.35(\'6s\')[0];k $2B(O){m!!(O||O===0)};k $5F(O,a8){m $8a(O)?O:a8};k $7X(3p,1z){m 1d.an(1d.7X()*(1z-3p+1)+3p)};k $3A(){m L 97().bf()};k $4Z(1H){ci(1H);cn(1H);m 1F};U.43=!!(P.5M);B(U.aO)U.31=U[U.7d?\'cl\':\'aY\']=1e;17 B(P.9A&&!P.bz&&!bl.bM)U.cS=U.4M=U[U.43?\'cg\':\'65\']=1e;17 B(P.cb!=1F)U.7W=1e;B(7g 5O==\'b9\'){o 5O=k(){};B(U.4M)P.aq("cJ");5O.1L=(U.4M)?U["[[bA.1L]]"]:{}}5O.1L.4Y=1e;B(U.aY)5f{P.bK("cc",N,1e)}4X(e){};o 18=k(1K){o 63=k(){m(1c[0]!==1F&&c.1j&&$F(c.1j)==\'k\')?c.1j.3U(c,1c):c};$R(63,c);63.1L=1K;63.aR=18;m 63};18.1m=k(){};18.1L={R:k(1K){o 7k=L c(1F);M(o K 1b 1K){o aP=7k[K];7k[K]=18.aL(aP,1K[K])}m L 18(7k)},3q:k(){M(o i=0,l=1c.V;i<l;i++)$R(c.1L,1c[i])}};18.aL=k(2o,2a){B(2o&&2o!=2a){o F=$F(2a);B(F!=$F(2o))m 2a;23(F){12\'k\':o 7E=k(){c.1r=1c.8r.1r;m 2a.3U(c,1c)};7E.1r=2o;m 7E;12\'2C\':m $2c(2o,2a)}}m 2a};o 8b=L 18({bD:k(W){c.4j=c.4j||[];c.4j.1k(W);m c},7t:k(){B(c.4j&&c.4j.V)c.4j.9W().2k(10,c)},bC:k(){c.4j=[]}});o 2q=L 18({1I:k(F,W){B(W!=18.1m){c.$19=c.$19||{};c.$19[F]=c.$19[F]||[];c.$19[F].5w(W)}m c},1i:k(F,1q,2k){B(c.$19&&c.$19[F]){c.$19[F].1o(k(W){W.3a({\'Y\':c,\'2k\':2k,\'1c\':1q})()},c)}m c},3Z:k(F,W){B(c.$19&&c.$19[F])c.$19[F].2H(W);m c}});o 4i=L 18({2U:k(){c.C=$2c.3U(1F,[c.C].R(1c));B(!c.1I)m c;M(o 3B 1b c.C){B($F(c.C[3B]==\'k\')&&3B.2t(/^5C[A-Z]/))c.1I(3B,c.C[3B])}m c}});2I.R({7l:k(W,Y){M(o i=0,j=c.V;i<j;i++)W.1S(Y,c[i],i,c)},3f:k(W,Y){o 54=[];M(o i=0,j=c.V;i<j;i++){B(W.1S(Y,c[i],i,c))54.1k(c[i])}m 54},2K:k(W,Y){o 54=[];M(o i=0,j=c.V;i<j;i++)54[i]=W.1S(Y,c[i],i,c);m 54},4v:k(W,Y){M(o i=0,j=c.V;i<j;i++){B(!W.1S(Y,c[i],i,c))m N}m 1e},bo:k(W,Y){M(o i=0,j=c.V;i<j;i++){B(W.1S(Y,c[i],i,c))m 1e}m N},3S:k(3h,15){o 3N=c.V;M(o i=(15<0)?1d.1z(0,3N+15):15||0;i<3N;i++){B(c[i]===3h)m i}m-1},8m:k(1h,V){1h=1h||0;B(1h<0)1h=c.V+1h;V=V||(c.V-1h);o 89=[];M(o i=0;i<V;i++)89[i]=c[1h++];m 89},2H:k(3h){o i=0;o 3N=c.V;6Y(i<3N){B(c[i]===3h){c.6y(i,1);3N--}17{i++}}m c},1l:k(3h,15){m c.3S(3h,15)!=-1},bm:k(1P){o O={},V=1d.3p(c.V,1P.V);M(o i=0;i<V;i++)O[1P[i]]=c[i];m O},R:k(1B){M(o i=0,j=1B.V;i<j;i++)c.1k(1B[i]);m c},2c:k(1B){M(o i=0,l=1B.V;i<l;i++)c.5w(1B[i]);m c},5w:k(3h){B(!c.1l(3h))c.1k(3h);m c},bp:k(){m c[$7X(0,c.V-1)]||N},7Y:k(){m c[c.V-1]||N}});2I.1L.1o=2I.1L.7l;2I.1L.2t=2I.1L.1l;k $A(1B){m 2I.8m(1B)};k $1o(3W,W,Y){B(3W&&7g 3W.V==\'4S\'&&$F(3W)!=\'2C\')2I.7l(3W,W,Y);17 M(o 1w 1b 3W)W.1S(Y||3W,3W[1w],1w)};6W.R({2t:k(6o,2S){m(($F(6o)==\'2E\')?L 7V(6o,2S):6o).2t(c)},3c:k(){m 5X(c,10)},b4:k(){m 69(c)},7N:k(){m c.3l(/-\\D/g,k(2T){m 2T.7T(1).aJ()})},9o:k(){m c.3l(/\\w[A-Z]/g,k(2T){m(2T.7T(0)+\'-\'+2T.7T(1).5B())})},8I:k(){m c.3l(/\\b[a-z]/g,k(2T){m 2T.aJ()})},5Y:k(){m c.3l(/^\\s+|\\s+$/g,\'\')},7w:k(){m c.3l(/\\s{2,}/g,\' \').5Y()},5I:k(1B){o 1v=c.2T(/\\d{1,3}/g);m(1v)?1v.5I(1B):N},5H:k(1B){o 3C=c.2T(/^#?(\\w{1,2})(\\w{1,2})(\\w{1,2})$/);m(3C)?3C.aI(1).5H(1B):N},1l:k(2E,s){m(s)?(s+c+s).3S(s+2E+s)>-1:c.3S(2E)>-1},aK:k(){m c.3l(/([.*+?^${}()|[\\]\\/\\\\])/g,\'\\\\$1\')}});2I.R({5I:k(1B){B(c.V<3)m N;B(c.V==4&&c[3]==0&&!1B)m\'c5\';o 3C=[];M(o i=0;i<3;i++){o 52=(c[i]-0).4u(16);3C.1k((52.V==1)?\'0\'+52:52)}m 1B?3C:\'#\'+3C.2h(\'\')},5H:k(1B){B(c.V!=3)m N;o 1v=[];M(o i=0;i<3;i++){1v.1k(5X((c[i].V==1)?c[i]+c[i]:c[i],16))}m 1B?1v:\'1v(\'+1v.2h(\',\')+\')\'}});7S.R({3a:k(C){o W=c;C=$2c({\'Y\':W,\'I\':N,\'1c\':1F,\'2k\':N,\'4f\':N,\'6J\':N},C);B($2B(C.1c)&&$F(C.1c)!=\'1B\')C.1c=[C.1c];m k(I){o 1q;B(C.I){I=I||U.I;1q=[(C.I===1e)?I:L C.I(I)];B(C.1c)1q.R(C.1c)}17 1q=C.1c||1c;o 3P=k(){m W.3U($5F(C.Y,W),1q)};B(C.2k)m 9H(3P,C.2k);B(C.4f)m cI(3P,C.4f);B(C.6J)5f{m 3P()}4X(cE){m N};m 3P()}},cL:k(1q,Y){m c.3a({\'1c\':1q,\'Y\':Y})},6J:k(1q,Y){m c.3a({\'1c\':1q,\'Y\':Y,\'6J\':1e})()},Y:k(Y,1q){m c.3a({\'Y\':Y,\'1c\':1q})},cU:k(Y,1q){m c.3a({\'Y\':Y,\'I\':1e,\'1c\':1q})},2k:k(2k,Y,1q){m c.3a({\'2k\':2k,\'Y\':Y,\'1c\':1q})()},4f:k(at,Y,1q){m c.3a({\'4f\':at,\'Y\':Y,\'1c\':1q})()}});ao.R({3c:k(){m 5X(c)},b4:k(){m 69(c)},1E:k(3p,1z){m 1d.3p(1z,1d.1z(3p,c))},2r:k(5L){5L=1d.3J(10,5L||0);m 1d.2r(c*5L)/5L},cN:k(W){M(o i=0;i<c;i++)W(i)}});o Q=L 18({1j:k(el,1W){B($F(el)==\'2E\'){B(U.31&&1W&&(1W.1w||1W.F)){o 1w=(1W.1w)?\' 1w="\'+1W.1w+\'"\':\'\';o F=(1W.F)?\' F="\'+1W.F+\'"\':\'\';5j 1W.1w;5j 1W.F;el=\'<\'+el+1w+F+\'>\'}el=P.aq(el)}el=$(el);m(!1W||!el)?el:el.2i(1W)}});o 29=L 18({1j:k(T){m(T)?$R(T,c):c}});29.R=k(1W){M(o 1V 1b 1W){c.1L[1V]=1W[1V];c[1V]=$4Q.6P(1V)}};k $(el){B(!el)m N;B(el.4Y)m 33.4V(el);B([U,P].1l(el))m el;o F=$F(el);B(F==\'2E\'){el=P.7f(el);F=(el)?\'G\':N}B(F!=\'G\')m N;B(el.4Y)m 33.4V(el);B([\'2C\',\'cx\'].1l(el.6k.5B()))m el;$R(el,Q.1L);el.4Y=1e;m 33.4V(el)};P.77=P.35;k $$(){o T=[];M(o i=0,j=1c.V;i<j;i++){o 1Q=1c[i];23($F(1Q)){12\'G\':T.1k(1Q);12\'ce\':1D;12 N:1D;12\'2E\':1Q=P.77(1Q,1e);5D:T.R(1Q)}}m $$.5R(T)};$$.5R=k(1B){o T=[];M(o i=0,l=1B.V;i<l;i++){B(1B[i].$6T)6C;o G=$(1B[i]);B(G&&!G.$6T){G.$6T=1e;T.1k(G)}}M(o i=0,l=T.V;i<l;i++)T[i].$6T=1F;m L 29(T)};29.6D=k(K){m k(){o 1q=1c;o 1y=[];o T=1e;M(o i=0,j=c.V,3P;i<j;i++){3P=c[i][K].3U(c[i],1q);B($F(3P)!=\'G\')T=N;1y.1k(3P)};m(T)?$$.5R(1y):1y}};Q.R=k(1K){M(o K 1b 1K){5O.1L[K]=1K[K];Q.1L[K]=1K[K];Q[K]=$4Q.6P(K);o aF=(2I.1L[K])?K+\'29\':K;29.1L[aF]=29.6D(K)}};Q.R({2i:k(1W){M(o 1V 1b 1W){o 4x=1W[1V];23(1V){12\'8A\':c.4z(4x);1D;12\'19\':B(c.6B)c.6B(4x);1D;12\'1K\':c.6j(4x);1D;5D:c.7b(1V,4x)}}m c},25:k(el,aH){el=$(el);23(aH){12\'aA\':el.3r.7G(c,el);1D;12\'aB\':o 3v=el.8x();B(!3v)el.3r.81(c);17 el.3r.7G(c,3v);1D;12\'1n\':o 84=el.9i;B(84){el.7G(c,84);1D}5D:el.81(c)}m c},8o:k(el){m c.25(el,\'aA\')},6O:k(el){m c.25(el,\'aB\')},ca:k(el){m c.25(el,\'3O\')},ct:k(el){m c.25(el,\'1n\')},b8:k(){o T=[];$1o(1c,k(4n){T=T.7y(4n)});$$(T).25(c);m c},2H:k(){m c.3r.cv(c)},9M:k(b3){o el=$(c.cp(b3!==N));B(!el.$19)m el;el.$19={};M(o F 1b c.$19)el.$19[F]={\'1P\':$A(c.$19[F].1P),\'1J\':$A(c.$19[F].1J)};m el.6G()},ck:k(el){el=$(el);c.3r.cm(el,c);m el},co:k(21){B(U.31){23(c.57()){12\'1Z\':c.c6.b7=21;m c;12\'2W\':m c.7b(\'21\',21)}}c.81(P.c7(21));m c},7F:k(1A){m c.1A.1l(1A,\' \')},bh:k(1A){B(!c.7F(1A))c.1A=(c.1A+\' \'+1A).7w();m c},b5:k(1A){c.1A=c.1A.3l(L 7V(\'(^|\\\\s)\'+1A+\'(?:\\\\s|$)\'),\'$1\').7w();m c},ch:k(1A){m c.7F(1A)?c.b5(1A):c.bh(1A)},1O:k(K,J){23(K){12\'22\':m c.bi(69(J));12\'by\':K=(U.31)?\'bn\':\'bW\'}K=K.7N();23($F(J)){12\'4S\':B(![\'bH\',\'am\'].1l(K))J+=\'5a\';1D;12\'1B\':J=\'1v(\'+J.2h(\',\')+\')\'}c.1Z[K]=J;m c},4z:k(1Y){23($F(1Y)){12\'2C\':Q.6w(c,\'1O\',1Y);1D;12\'2E\':c.1Z.b7=1Y}m c},bi:k(22){B(22==0){B(c.1Z.4G!="4y")c.1Z.4G="4y"}17{B(c.1Z.4G!="8D")c.1Z.4G="8D"}B(!c.71||!c.71.cR)c.1Z.am=1;B(U.31)c.1Z.3f=(22==1)?\'\':"6Z(22="+22*3b+")";c.1Z.22=c.$1X.22=22;m c},2j:k(K){K=K.7N();o 1N=c.1Z[K];B(!$2B(1N)){B(K==\'22\')m c.$1X.22;o 1N=[];M(o 1Z 1b Q.4e){B(K==1Z){Q.4e[1Z].1o(k(s){o 1Z=c.2j(s);1N.1k(5X(1Z)?1Z:\'8W\')},c);B(K==\'2Y\'){o 4v=1N.4v(k(52){m(52==1N[0])});m(4v)?1N[0]:N}m 1N.2h(\' \')}}B(K.1l(\'2Y\')){B(Q.4e.2Y.1l(K)){m[\'8X\',\'82\',\'2M\'].2K(k(p){m c.2j(K+p)},c).2h(\' \')}17 B(Q.92.1l(K)){m[\'8S\',\'8T\',\'8U\',\'8V\'].2K(k(p){m c.2j(\'2Y\'+p+K.3l(\'2Y\',\'\'))},c).2h(\' \')}}B(P.9n)1N=P.9n.bL(c,1F).bN(K.9o());17 B(c.71)1N=c.71[K]}B(U.31)1N=Q.91(K,1N,c);B(1N&&K.2t(/2G/i)&&1N.1l(\'1v\')){m 1N.66(\'1v\').6y(1,4).2K(k(2G){m 2G.5I()}).2h(\' \')}m 1N},ba:k(){m Q.7D(c,\'2j\',1c)},5U:k(6U,1h){6U+=\'bZ\';o el=(1h)?c[1h]:c[6U];6Y(el&&$F(el)!=\'G\')el=el[6U];m $(el)},9F:k(){m c.5U(\'2o\')},8x:k(){m c.5U(\'3v\')},bq:k(){m c.5U(\'3v\',\'9i\')},7Y:k(){m c.5U(\'2o\',\'bx\')},cD:k(){m $(c.3r)},8F:k(){m $$(c.9A)},7Z:k(el){m!!$A(c.35(\'*\')).1l(el)},6n:k(K){o 26=Q.6z[K];B(26)m c[26];B(!U.31)m c.cK(K);o 7z=c.cO[K];m(7z)?7z.8Z:1F},c8:k(K){o 26=Q.6z[K];B(26)c[26]=\'\';17 c.94(K);m c},c9:k(){m Q.7D(c,\'6n\',1c)},7b:k(K,J){o 26=Q.6z[K];B(26)c[26]=J;17 c.cq(K,J);m c},6j:k(1Y){m Q.6w(c,\'7b\',1Y)},5Q:k(){c.cH=$A(1c).2h(\'\');m c},57:k(){m c.6k.5B()},1m:k(){33.44(c.35(\'*\'));m c.5Q(\'\')}});Q.91=k(K,1N,G){B($2B(5X(1N)))m 1N;B([\'2N\',\'2z\'].1l(K)){o 1J=(K==\'2z\')?[\'1t\',\'4k\']:[\'1n\',\'3O\'];o 3n=0;1J.1o(k(J){3n+=G.2j(\'2Y-\'+J+\'-2z\').3c()+G.2j(\'4F-\'+J).3c()});m G[\'1C\'+K.8I()]-3n+\'5a\'}17 B(K.2t(/2Y(.+)8X|34|4F/)){m\'8W\'}m 1N};Q.4e={\'2Y\':[],\'4F\':[],\'34\':[]};[\'8S\',\'8T\',\'8U\',\'8V\'].1o(k(5Z){M(o 1Z 1b Q.4e)Q.4e[1Z].1k(1Z+5Z)});Q.92=[\'cr\',\'cs\',\'cj\'];Q.7D=k(el,28,1P){o 1N={};$1o(1P,k(1s){1N[1s]=el[28](1s)});m 1N};Q.6w=k(el,28,80){M(o 1s 1b 80)el[28](1s,80[1s]);m el};Q.6z=L 3y({\'4O\':\'1A\',\'M\':\'cf\',\'cw\':\'cQ\',\'cP\':\'cC\',\'cB\':\'cA\',\'cy\':\'cz\',\'cF\':\'cG\',\'cY\':\'bV\',\'J\':\'J\',\'7M\':\'7M\',\'7P\':\'7P\',\'7O\':\'7O\'});Q.2F={7a:{2A:k(F,W){B(c.7v)c.7v(F,W,N);17 c.bw(\'5C\'+F,W);m c},3j:k(F,W){B(c.ad)c.ad(F,W,N);17 c.bv(\'5C\'+F,W);m c}}};U.R(Q.2F.7a);P.R(Q.2F.7a);Q.R(Q.2F.7a);o 33={T:[],4V:k(el){B(!el.$1X){33.T.1k(el);el.$1X={\'22\':1}}m el},44:k(T){M(o i=0,j=T.V,el;i<j;i++){B(!(el=T[i])||!el.$1X)6C;B(el.$19)el.1i(\'44\').6G();M(o p 1b el.$1X)el.$1X[p]=1F;M(o p 1b Q.1L)el[p]=1F;el.4Y=el.$1X=el=1F;33.T.2H(el)}},1m:k(){33.4V(U);33.4V(P);33.44(33.T)}};U.2A(\'bt\',k(){U.2A(\'af\',33.1m);B(U.31)U.2A(\'af\',bB)});o 2R=L 18({1j:k(I){B(I&&I.$9J)m I;c.$9J=1e;I=I||U.I;c.I=I;c.F=I.F;c.3u=I.3u||I.bs;B(c.3u.7s==3)c.3u=c.3u.3r;c.9W=I.bU;c.bS=I.bT;c.bX=I.bY;c.c3=I.c2;B([\'9L\',\'5r\'].1l(c.F)){c.c1=(I.9X)?I.9X/c0:-(I.bR||0)/3}17 B(c.F.1l(\'1s\')){c.6Q=I.9P||I.bQ;M(o 1w 1b 2R.1P){B(2R.1P[1w]==c.6Q){c.1s=1w;1D}}B(c.F==\'bI\'){o 7i=c.6Q-bE;B(7i>0&&7i<13)c.1s=\'f\'+7i}c.1s=c.1s||6W.bP(c.6Q).5B()}17 B(c.F.2t(/(8p|3i|bO)/)){c.1M={\'x\':I.7p||I.9h+P.2X.67,\'y\':I.7q||I.9R+P.2X.6a};c.9d={\'x\':I.7p?I.7p-U.9v:I.9h,\'y\':I.7q?I.7q-U.9t:I.9R};c.dw=(I.9P==3)||(I.eJ==2);23(c.F){12\'9E\':c.2p=I.2p||I.eK;1D;12\'9D\':c.2p=I.2p||I.8z}c.9U()}m c},1R:k(){m c.6V().76()},6V:k(){B(c.I.6V)c.I.6V();17 c.I.eI=1e;m c},76:k(){B(c.I.76)c.I.76();17 c.I.eH=N;m c}});2R.6d={2p:k(){B(c.2p&&c.2p.7s==3)c.2p=c.2p.3r},9Y:k(){5f{2R.6d.2p.1S(c)}4X(e){c.2p=c.3u}}};2R.1L.9U=(U.7W)?2R.6d.9Y:2R.6d.2p;2R.1P=L 3y({\'eG\':13,\'8B\':38,\'8C\':40,\'1t\':37,\'4k\':39,\'eL\':27,\'eM\':32,\'eR\':8,\'eS\':9,\'5j\':46});Q.2F.2q={1I:k(F,W){c.$19=c.$19||{};c.$19[F]=c.$19[F]||{\'1P\':[],\'1J\':[]};B(c.$19[F].1P.1l(W))m c;c.$19[F].1P.1k(W);o 7u=F;o 2w=Q.2q[F];B(2w){B(2w.7I)2w.7I.1S(c,W);B(2w.2K)W=2w.2K;B(2w.F)7u=2w.F}B(!c.7v)W=W.3a({\'Y\':c,\'I\':1e});c.$19[F].1J.1k(W);m c.2A(7u,W)},3Z:k(F,W){B(!c.$19||!c.$19[F])m c;o 1p=c.$19[F].1P.3S(W);B(1p==-1)m c;o 1s=c.$19[F].1P.6y(1p,1)[0];o J=c.$19[F].1J.6y(1p,1)[0];o 2w=Q.2q[F];B(2w){B(2w.2H)2w.2H.1S(c,W);B(2w.F)F=2w.F}m c.3j(F,J)},6B:k(1Y){m Q.6w(c,\'1I\',1Y)},6G:k(F){B(!c.$19)m c;B(!F){M(o 6t 1b c.$19)c.6G(6t);c.$19=1F}17 B(c.$19[F]){c.$19[F].1P.1o(k(W){c.3Z(F,W)},c);c.$19[F]=1F}m c},1i:k(F,1q,2k){B(!c.$19||!c.$19[F])m c;c.$19[F].1P.1o(k(W){W.3a({\'Y\':c,\'2k\':2k,\'1c\':1q})()},c);m c},9G:k(15,F){B(!15.$19)m c;B(!F){M(o 6t 1b 15.$19)c.9G(15,6t)}17 B(15.$19[F]){15.$19[F].1P.1o(k(W){c.1I(F,W)},c)}m c}};U.R(Q.2F.2q);P.R(Q.2F.2q);Q.R(Q.2F.2q);Q.2q=L 3y({\'8k\':{F:\'9E\',2K:k(I){I=L 2R(I);B(I.2p==c||c.7Z(I.2p))m;c.1i(\'8k\',I)}},\'8h\':{F:\'9D\',2K:k(I){I=L 2R(I);B(I.2p==c||c.7Z(I.2p))m;c.1i(\'8h\',I)}},\'5r\':{F:(U.7W)?\'9L\':\'5r\'}});7S.R({3g:k(Y,1q){m c.3a({\'Y\':Y,\'1c\':1q,\'I\':2R})}});29.R({eQ:k(a0){m L 29(c.3f(k(el){m(Q.57(el)==a0)}))},ai:k(1A,2D){o T=c.3f(k(el){m(el.1A&&el.1A.1l(1A,\' \'))});m(2D)?T:L 29(T)},ah:k(4w,2D){o T=c.3f(k(el){m(el.4w==4w)});m(2D)?T:L 29(T)},al:k(1w,7x,J,2D){o T=c.3f(k(el){o 2a=Q.6n(el,1w);B(!2a)m N;B(!7x)m 1e;23(7x){12\'=\':m(2a==J);12\'*=\':m(2a.1l(J));12\'^=\':m(2a.6p(0,J.V)==J);12\'$=\':m(2a.6p(2a.V-J.V)==J);12\'!=\':m(2a!=J);12\'~=\':m 2a.1l(J,\' \')}m N});m(2D)?T:L 29(T)}});k $E(1Q,3f){m($(3f)||P).a5(1Q)};k $eP(1Q,3f){m($(3f)||P).77(1Q)};$$.3M={\'5n\':/^(\\w*|\\*)(?:#([\\w-]+)|\\.([\\w-]+))?(?:\\[(\\w+)(?:([!*^$]?=)["\']?([^"\'\\]]*)["\']?)?])?$/,\'43\':{7C:k(1y,36,1f,i){o 2s=[36.eN?\'87:\':\'\',1f[1]];B(1f[2])2s.1k(\'[@4w="\',1f[2],\'"]\');B(1f[3])2s.1k(\'[1l(7y(" ", @4O, " "), " \',1f[3],\' ")]\');B(1f[4]){B(1f[5]&&1f[6]){23(1f[5]){12\'*=\':2s.1k(\'[1l(@\',1f[4],\', "\',1f[6],\'")]\');1D;12\'^=\':2s.1k(\'[cZ-eO(@\',1f[4],\', "\',1f[6],\'")]\');1D;12\'$=\':2s.1k(\'[eE(@\',1f[4],\', 2E-V(@\',1f[4],\') - \',1f[6].V,\' + 1) = "\',1f[6],\'"]\');1D;12\'=\':2s.1k(\'[@\',1f[4],\'="\',1f[6],\'"]\');1D;12\'!=\':2s.1k(\'[@\',1f[4],\'!="\',1f[6],\'"]\')}}17{2s.1k(\'[@\',1f[4],\']\')}}1y.1k(2s.2h(\'\'));m 1y},7B:k(1y,36,2D){o T=[];o 43=P.5M(\'.//\'+1y.2h(\'//\'),36,$$.3M.ak,eD.et,1F);M(o i=0,j=43.eu;i<j;i++)T.1k(43.es(i));m(2D)?T:L 29(T.2K($))}},\'a3\':{7C:k(1y,36,1f,i){B(i==0){B(1f[2]){o el=36.7f(1f[2]);B(!el||((1f[1]!=\'*\')&&(Q.57(el)!=1f[1])))m N;1y=[el]}17{1y=$A(36.35(1f[1]))}}17{1y=$$.3M.35(1y,1f[1]);B(1f[2])1y=29.ah(1y,1f[2],1e)}B(1f[3])1y=29.ai(1y,1f[3],1e);B(1f[4])1y=29.al(1y,1f[4],1f[5],1f[6],1e);m 1y},7B:k(1y,36,2D){m(2D)?1y:$$.5R(1y)}},ak:k(aj){m(aj==\'87\')?\'96://aQ.er.eo/ep/87\':N},35:k(36,6k){o 7Q=[];M(o i=0,j=36.V;i<j;i++)7Q.R(36[i].35(6k));m 7Q}};$$.3M.28=(U.43)?\'43\':\'a3\';Q.2F.7H={7e:k(1Q,2D){o 1y=[];1Q=1Q.5Y().66(\' \');M(o i=0,j=1Q.V;i<j;i++){o a2=1Q[i];o 1f=a2.2T($$.3M.5n);B(!1f)1D;1f[1]=1f[1]||\'*\';o 2s=$$.3M[$$.3M.28].7C(1y,c,1f,i);B(!2s)1D;1y=2s}m $$.3M[$$.3M.28].7B(1y,c,2D)},a5:k(1Q){m $(c.7e(1Q,1e)[0]||N)},77:k(1Q,2D){o T=[];1Q=1Q.66(\',\');M(o i=0,j=1Q.V;i<j;i++)T=T.7y(c.7e(1Q[i],1e));m(2D)?T:$$.5R(T)},ew:k(1A){m c.7e(\'.\'+1A)}};Q.R({7f:k(4w){o el=P.7f(4w);B(!el)m N;M(o 1r=el.3r;1r!=c;1r=1r.3r){B(!1r)m N}m el}});P.R(Q.2F.7H);Q.R(Q.2F.7H);Q.R({4b:k(){23(c.57()){12\'4o\':o 1J=[];$1o(c.C,k(3B){B(3B.eB)1J.1k($5F(3B.J,3B.21))});m(c.7O)?1J:1J[0];12\'99\':B(!(c.7P&&[\'eC\',\'eA\'].1l(c.F))&&![\'4y\',\'21\',\'ez\'].1l(c.F))1D;12\'9c\':m c.J}m N},9b:k(){m $$(c.35(\'99\'),c.35(\'4o\'),c.35(\'9c\'))},5l:k(){o 51=[];c.9b().1o(k(el){o 1w=el.1w;o J=el.4b();B(J===N||!1w||el.7M)m;o 7L=k(4x){51.1k(1w+\'=\'+6e(4x))};B($F(J)==\'1B\')J.1o(7L);17 7L(J)});m 51.2h(\'&\')}});Q.R({3x:k(x,y){c.67=x;c.6a=y},6N:k(){m{\'2J\':{\'x\':c.67,\'y\':c.6a},\'3n\':{\'x\':c.42,\'y\':c.3T},\'6M\':{\'x\':c.6H,\'y\':c.5N}}},3o:k(2m){2m=2m||[];o el=c,1t=0,1n=0;do{1t+=el.ex||0;1n+=el.ey||0;el=el.eT}6Y(el);2m.1o(k(G){1t-=G.67||0;1n-=G.6a||0});m{\'x\':1t,\'y\':1n}},aX:k(2m){m c.3o(2m).y},aW:k(2m){m c.3o(2m).x},4A:k(2m){o 1u=c.3o(2m);o O={\'2z\':c.42,\'2N\':c.3T,\'1t\':1u.x,\'1n\':1u.y};O.4k=O.1t+O.2z;O.3O=O.1n+O.2N;m O}});Q.2q.7K={7I:k(W){B(U.70){W.1S(c);m}o 5V=k(){B(U.70)m;U.70=1e;U.1H=$4Z(U.1H);c.1i(\'7K\')}.Y(c);B(P.5c&&U.4M){U.1H=k(){B([\'70\',\'8q\'].1l(P.5c))5V()}.4f(50)}17 B(P.5c&&U.31){B(!$(\'7J\')){o 59=(U.5b.f5==\'f7:\')?\'://0\':\'8n:f9(0)\';P.f3(\'<2W 4w="7J" eX 59="\'+59+\'"><\\/2W>\');$(\'7J\').6c=k(){B(c.5c==\'8q\')5V()}}}17{U.2A("4r",5V);P.2A("eV",5V)}}};U.f2=k(W){m c.1I(\'7K\',W)};U.R({8f:k(){B(c.65)m c.f0;B(c.8Y)m P.4H.90;m P.2X.90},8l:k(){B(c.65)m c.eZ;B(c.8Y)m P.4H.9e;m P.2X.9e},9w:k(){B(c.31)m 1d.1z(P.2X.42,P.2X.6H);B(c.4M)m P.4H.6H;m P.2X.6H},9x:k(){B(c.31)m 1d.1z(P.2X.3T,P.2X.5N);B(c.4M)m P.4H.5N;m P.2X.5N},8s:k(){m c.9v||P.2X.67},8u:k(){m c.9t||P.2X.6a},6N:k(){m{\'3n\':{\'x\':c.8f(),\'y\':c.8l()},\'6M\':{\'x\':c.9w(),\'y\':c.9x()},\'2J\':{\'x\':c.8s(),\'y\':c.8u()}}},3o:k(){m{\'x\':0,\'y\':0}}});o 1g={f8:{}};1g.2O=L 18({C:{45:18.1m,1T:18.1m,7m:18.1m,2b:k(p){m-(1d.as(1d.85*p)-1)/2},49:eY,2u:\'5a\',3Q:1e,9z:50},1j:k(C){c.G=c.G||1F;c.2U(C);B(c.C.1j)c.C.1j.1S(c)},2l:k(){o 3A=$3A();B(3A<c.3A+c.C.49){c.4l=c.C.2b((3A-c.3A)/c.C.49);c.4s();c.4p()}17{c.1R(1e);c.2i(c.14);c.1i(\'1T\',c.G,10);c.7t()}},2i:k(14){c.1a=14;c.4p();m c},4s:k(){c.1a=c.4t(c.15,c.14)},4t:k(15,14){m(14-15)*c.4l+15},1h:k(15,14){B(!c.C.3Q)c.1R();17 B(c.1H)m c;c.15=15;c.14=14;c.4h=c.14-c.15;c.3A=$3A();c.1H=c.2l.4f(1d.2r(ax/c.C.9z),c);c.1i(\'45\',c.G);m c},1R:k(2f){B(!c.1H)m c;c.1H=$4Z(c.1H);B(!2f)c.1i(\'7m\',c.G);m c},2w:k(15,14){m c.1h(15,14)},eW:k(2f){m c.1R(2f)}});1g.2O.3q(L 8b,L 2q,L 4i);1g.3s={4o:k(K,14){B(K.2t(/2G/i))m c.2M;B(14.1l&&14.1l(\' \'))m c.6D;m c.9q},2P:k(el,K,5d){B(!5d.1k)5d=[5d];o 15=5d[0],14=5d[1];B(!14&&14!=0){14=15;15=el.2j(K)}o 1x=c.4o(K,14);m{15:1x.2P(15),14:1x.2P(14),1x:1x}}};1g.3s.9q={2P:k(J){m 69(J)},55:k(15,14,2x){m 2x.4t(15,14)},4b:k(J,2u,K){B(2u==\'5a\'&&K!=\'22\')J=1d.2r(J);m J+2u}};1g.3s.6D={2P:k(J){m J.1k?J:J.66(\' \').2K(k(v){m 69(v)})},55:k(15,14,2x){o 1a=[];M(o i=0;i<15.V;i++)1a[i]=2x.4t(15[i],14[i]);m 1a},4b:k(J,2u,K){B(2u==\'5a\'&&K!=\'22\')J=J.2K(1d.2r);m J.2h(2u+\' \')+2u}};1g.3s.2M={2P:k(J){m J.1k?J:J.5H(1e)},55:k(15,14,2x){o 1a=[];M(o i=0;i<15.V;i++)1a[i]=1d.2r(2x.4t(15[i],14[i]));m 1a},4b:k(J){m\'1v(\'+J.2h(\',\')+\')\'}};1g.82=1g.2O.R({1j:k(el,K,C){c.G=$(el);c.K=K;c.1r(C)},5k:k(){m c.2i(0)},4s:k(){c.1a=c.1x.55(c.15,c.14,c)},2i:k(14){c.1x=1g.3s.4o(c.K,14);m c.1r(c.1x.2P(14))},1h:k(15,14){B(c.1H&&c.C.3Q)m c;o 2e=1g.3s.2P(c.G,c.K,[15,14]);c.1x=2e.1x;m c.1r(2e.15,2e.14)},4p:k(){c.G.1O(c.K,c.1x.4b(c.1a,c.C.2u,c.K))}});Q.R({f1:k(K,C){m L 1g.82(c,K,C)}});1g.4e=1g.2O.R({1j:k(el,C){c.G=$(el);c.1r(C)},4s:k(){M(o p 1b c.15)c.1a[p]=c.1x[p].55(c.15[p],c.14[p],c)},2i:k(14){o 2e={};c.1x={};M(o p 1b 14){c.1x[p]=1g.3s.4o(p,14[p]);2e[p]=c.1x[p].2P(14[p])}m c.1r(2e)},1h:k(O){B(c.1H&&c.C.3Q)m c;c.1a={};c.1x={};o 15={},14={};M(o p 1b O){o 2e=1g.3s.2P(c.G,p,O[p]);15[p]=2e.15;14[p]=2e.14;c.1x[p]=2e.1x}m c.1r(15,14)},4p:k(){M(o p 1b c.1a)c.G.1O(p,c.1x[p].4b(c.1a[p],c.C.2u,p))}});Q.R({3t:k(C){m L 1g.4e(c,C)}});1g.29=1g.2O.R({1j:k(T,C){c.T=$$(T);c.1r(C)},4s:k(){M(o i 1b c.15){o 5o=c.15[i],4a=c.14[i],3z=c.1x[i],5s=c.1a[i]={};M(o p 1b 5o)5s[p]=3z[p].55(5o[p],4a[p],c)}},2i:k(14){o 2e={};c.1x={};M(o i 1b 14){o 4a=14[i],3z=c.1x[i]={},9l=2e[i]={};M(o p 1b 4a){3z[p]=1g.3s.4o(p,4a[p]);9l[p]=3z[p].2P(4a[p])}}m c.1r(2e)},1h:k(O){B(c.1H&&c.C.3Q)m c;c.1a={};c.1x={};o 15={},14={};M(o i 1b O){o 7A=O[i],5o=15[i]={},4a=14[i]={},3z=c.1x[i]={};M(o p 1b 7A){o 2e=1g.3s.2P(c.T[i],p,7A[p]);5o[p]=2e.15;4a[p]=2e.14;3z[p]=2e.1x}}m c.1r(15,14)},4p:k(){M(o i 1b c.1a){o 5s=c.1a[i],3z=c.1x[i];M(o p 1b 5s)c.T[i].1O(p,3z[p].4b(5s[p],c.C.2u,p))}}});1g.ac=1g.2O.R({C:{2m:[],1C:{\'x\':0,\'y\':0}},1j:k(G,C){c.1a=[];c.G=$(G);c.1G={\'1R\':c.1R.Y(c,N)};c.1I(\'45\',k(){P.1I(\'5r\',c.1G.1R)}.Y(c));c.3Z(\'1T\',k(){P.3Z(\'5r\',c.1G.1R)}.Y(c));c.1r(C)},4s:k(){M(o i=0;i<2;i++)c.1a[i]=c.4t(c.15[i],c.14[i])},3x:k(x,y){B(c.1H&&c.C.3Q)m c;o el=c.G.6N();o 1J={\'x\':x,\'y\':y};M(o z 1b el.3n){o 1z=el.6M[z]-el.3n[z];B($2B(1J[z]))1J[z]=($F(1J[z])==\'4S\')?1J[z].1E(0,1z):1z;17 1J[z]=el.2J[z];1J[z]+=c.C.1C[z]}m c.1h([el.2J.x,el.2J.y],[1J.x,1J.y])},dr:k(){m c.3x(N,0)},dq:k(){m c.3x(N,\'bg\')},dl:k(){m c.3x(0,N)},dm:k(){m c.3x(\'bg\',N)},8z:k(el){o 1r=c.G.3o(c.C.2m);o 3u=$(el).3o(c.C.2m);m c.3x(3u.x-1r.x,3u.y-1r.y)},4p:k(){c.G.3x(c.1a[0],c.1a[1])}});1g.dn=1g.2O.R({C:{2d:\'8J\'},1j:k(el,C){c.G=$(el);c.3d=L Q(\'4K\',{\'8A\':$R(c.G.ba(\'34\'),{\'aT\':\'4y\'})}).6O(c.G).b8(c.G);c.G.1O(\'34\',0);c.2U(C);c.1a=[];c.1r(c.C);B(U.65)c.1I(\'1T\',k(){c.G.2H().25(c.3d)})},4s:k(){M(o i=0;i<2;i++)c.1a[i]=c.4t(c.15[i],c.14[i])},8J:k(){c.34=\'34-1n\';c.5z=\'2N\';c.1C=c.G.3T},8K:k(){c.34=\'34-1t\';c.5z=\'2z\';c.1C=c.G.42},bc:k(2d){c[2d||c.C.2d]();m c.1h([c.G.2j(c.34).3c(),c.3d.2j(c.5z).3c()],[0,c.1C])},be:k(2d){c[2d||c.C.2d]();m c.1h([c.G.2j(c.34).3c(),c.3d.2j(c.5z).3c()],[-c.1C,0])},5k:k(2d){c[2d||c.C.2d]();m c.2i([-c.1C,0])},41:k(2d){c[2d||c.C.2d]();m c.2i([0,c.1C])},en:k(2d){B(c.3d.3T==0||c.3d.42==0)m c.bc(2d);m c.be(2d)},4p:k(){c.G.1O(c.34,c.1a[0]+c.C.2u);c.3d.1O(c.5z,c.1a[1]+c.C.2u)}});1g.86=k(2b,2S){2S=2S||[];B($F(2S)!=\'1B\')2S=[2S];m $R(2b,{dC:k(1p){m 2b(1p,2S)},dD:k(1p){m 1-2b(1-1p,2S)},dE:k(1p){m(1p<=0.5)?2b(2*1p,2S)/2:(2-2b(2*(1-1p),2S))/2}})};1g.3m=L 3y({dB:k(p){m p}});1g.3m.R=k(7R){M(o 2b 1b 7R){1g.3m[2b]=L 1g.86(7R[2b]);1g.3m.88(2b)}};1g.3m.88=k(2b){[\'dA\',\'dx\',\'dy\'].1o(k(83){1g.3m[2b.5B()+83]=1g.3m[2b][\'dk\'+83]})};1g.3m.R({dj:k(p,x){m 1d.3J(p,x[0]||6)},d6:k(p){m 1d.3J(2,8*(p-1))},d7:k(p){m 1-1d.aD(1d.d8(p))},d5:k(p){m 1-1d.aD((1-p)*1d.85/2)},d4:k(p,x){x=x[0]||1.d0;m 1d.3J(p,2)*((x+1)*p-x)},d1:k(p){o J;M(o a=0,b=1;1;a+=b,b/=2){B(p>=(7-4*a)/11){J=-1d.3J((11-6*a-11*p)/4,2)+b*b;1D}}m J},d2:k(p,x){m 1d.3J(2,10*--p)*1d.as(20*p*1d.85*(x[0]||1)/3)}});[\'d9\',\'da\',\'dg\',\'dh\'].1o(k(2b,i){1g.3m[2b]=L 1g.86(k(p){m 1d.3J(p,[i+2])});1g.3m.88(2b)});o 3Y={};3Y.2O=L 18({C:{3K:N,2u:\'5a\',45:18.1m,au:18.1m,1T:18.1m,av:18.1m,8M:18.1m,1E:N,3F:{x:\'1t\',y:\'1n\'},4E:N,6u:6},1j:k(el,C){c.2U(C);c.G=$(el);c.3K=$(c.C.3K)||c.G;c.3i={\'1a\':{},\'1p\':{}};c.J={\'1h\':{},\'1a\':{}};c.1G={\'1h\':c.1h.3g(c),\'3V\':c.3V.3g(c),\'3L\':c.3L.3g(c),\'1R\':c.1R.Y(c)};c.6K();B(c.C.1j)c.C.1j.1S(c)},6K:k(){c.3K.1I(\'64\',c.1G.1h);m c},9K:k(){c.3K.3Z(\'64\',c.1G.1h);m c},1h:k(I){c.1i(\'au\',c.G);c.3i.1h=I.1M;o 1E=c.C.1E;c.1E={\'x\':[],\'y\':[]};M(o z 1b c.C.3F){B(!c.C.3F[z])6C;c.J.1a[z]=c.G.2j(c.C.3F[z]).3c();c.3i.1p[z]=I.1M[z]-c.J.1a[z];B(1E&&1E[z]){M(o i=0;i<2;i++){B($2B(1E[z][i]))c.1E[z][i]=($F(1E[z][i])==\'k\')?1E[z][i]():1E[z][i]}}}B($F(c.C.4E)==\'4S\')c.C.4E={\'x\':c.C.4E,\'y\':c.C.4E};P.2A(\'2V\',c.1G.3V);P.2A(\'6S\',c.1G.1R);c.1i(\'45\',c.G);I.1R()},3V:k(I){o aw=1d.2r(1d.dd(1d.3J(I.1M.x-c.3i.1h.x,2)+1d.3J(I.1M.y-c.3i.1h.y,2)));B(aw>c.C.6u){P.3j(\'2V\',c.1G.3V);P.2A(\'2V\',c.1G.3L);c.3L(I);c.1i(\'av\',c.G)}I.1R()},3L:k(I){c.5K=N;c.3i.1a=I.1M;M(o z 1b c.C.3F){B(!c.C.3F[z])6C;c.J.1a[z]=c.3i.1a[z]-c.3i.1p[z];B(c.1E[z]){B($2B(c.1E[z][1])&&(c.J.1a[z]>c.1E[z][1])){c.J.1a[z]=c.1E[z][1];c.5K=1e}17 B($2B(c.1E[z][0])&&(c.J.1a[z]<c.1E[z][0])){c.J.1a[z]=c.1E[z][0];c.5K=1e}}B(c.C.4E[z])c.J.1a[z]-=(c.J.1a[z]%c.C.4E[z]);c.G.1O(c.C.3F[z],c.J.1a[z]+c.C.2u)}c.1i(\'8M\',c.G);I.1R()},1R:k(){P.3j(\'2V\',c.1G.3V);P.3j(\'2V\',c.1G.3L);P.3j(\'6S\',c.1G.1R);c.1i(\'1T\',c.G)}});3Y.2O.3q(L 2q,L 4i);Q.R({e8:k(C){m L 3Y.2O(c,$2c({3F:{x:\'2z\',y:\'2N\'}},C))}});3Y.aM=3Y.2O.R({C:{6q:[],2g:N,2m:[]},1j:k(el,C){c.2U(C);c.G=$(el);c.6q=$$(c.C.6q);c.2g=$(c.C.2g);c.1u={\'G\':c.G.2j(\'1u\'),\'2g\':N};B(c.2g)c.1u.2g=c.2g.2j(\'1u\');B(![\'3X\',\'7h\'].1l(c.1u.G))c.1u.G=\'3X\';o 1n=c.G.2j(\'1n\').3c();o 1t=c.G.2j(\'1t\').3c();B(c.1u.G==\'3X\'&&![\'7h\',\'3X\',\'5S\'].1l(c.1u.2g)){1n=$2B(1n)?1n:c.G.aX(c.C.2m);1t=$2B(1t)?1t:c.G.aW(c.C.2m)}17{1n=$2B(1n)?1n:0;1t=$2B(1t)?1t:0}c.G.4z({\'1n\':1n,\'1t\':1t,\'1u\':c.1u.G});c.1r(c.G)},1h:k(I){c.3e=1F;B(c.2g){o 4J=c.2g.4A();o el=c.G.4A();B(c.1u.G==\'3X\'&&![\'7h\',\'3X\',\'5S\'].1l(c.1u.2g)){c.C.1E={\'x\':[4J.1t,4J.4k-el.2z],\'y\':[4J.1n,4J.3O-el.2N]}}17{c.C.1E={\'y\':[0,4J.2N-el.2N],\'x\':[0,4J.2z-el.2z]}}}c.1r(I)},3L:k(I){c.1r(I);o 3e=c.5K?N:c.6q.3f(c.b1,c).7Y();B(c.3e!=3e){B(c.3e)c.3e.1i(\'e2\',[c.G,c]);c.3e=3e?3e.1i(\'e3\',[c.G,c]):1F}m c},b1:k(el){el=el.4A(c.C.2m);o 1a=c.3i.1a;m(1a.x>el.1t&&1a.x<el.4k&&1a.y<el.3O&&1a.y>el.1n)},1R:k(){B(c.3e&&!c.5K)c.3e.1i(\'eb\',[c.G,c]);17 c.G.1i(\'ec\',c);c.1r();m c}});Q.R({ei:k(C){m L 3Y.aM(c,C)}});o 6h=L 18({C:{28:\'4T\',9p:1e,93:18.1m,4L:18.1m,6E:18.1m,aS:1e,5J:\'ej-8\',9m:N,4B:{}},7r:k(){c.2y=(U.7d)?L 7d():(U.31?L aO(\'ek.eh\'):N);m c},1j:k(C){c.7r().2U(C);c.C.5G=c.C.5G||c.5G;c.4B={};B(c.C.aS&&c.C.28==\'4T\'){o 5J=(c.C.5J)?\'; eg=\'+c.C.5J:\'\';c.5i(\'9Q-F\',\'ab/x-aQ-ed-ee\'+5J)}B(c.C.1j)c.C.1j.1S(c)},9g:k(){B(c.2y.5c!=4||!c.4W)m;c.4W=N;o 4C=0;5f{4C=c.2y.4C}4X(e){};B(c.C.5G.1S(c,4C))c.4L();17 c.6E();c.2y.6c=18.1m},5G:k(4C){m((4C>=e0)&&(4C<dN))},4L:k(){c.3w={\'21\':c.2y.dO,\'5q\':c.2y.dP};c.1i(\'4L\',[c.3w.21,c.3w.5q]);c.7t()},6E:k(){c.1i(\'6E\',c.2y)},5i:k(1w,J){c.4B[1w]=J;m c},5y:k(2L,1U){B(c.C.9m)c.98();17 B(c.4W)m c;c.4W=1e;B(1U&&c.C.28==\'4N\')2L=2L+(2L.1l(\'?\')?\'&\':\'?\')+1U,1U=1F;c.2y.dM(c.C.28,2L,c.C.9p);c.2y.6c=c.9g.Y(c);B((c.C.28==\'4T\')&&c.2y.dL)c.5i(\'dH\',\'dI\');$R(c.4B,c.C.4B);M(o F 1b c.4B)5f{c.2y.dJ(F,c.4B[F])}4X(e){};c.1i(\'93\');c.2y.5y($5F(1U,1F));m c},98:k(){B(!c.4W)m c;c.4W=N;c.2y.aC();c.2y.6c=18.1m;c.7r();c.1i(\'7m\');m c}});6h.3q(L 8b,L 2q,L 4i);o a9=6h.R({C:{1U:1F,7o:1F,1T:18.1m,72:N,7U:N},1j:k(2L,C){c.1I(\'4L\',c.1T);c.2U(C);c.C.1U=c.C.1U||c.C.a7;B(![\'4T\',\'4N\'].1l(c.C.28)){c.5p=\'5p=\'+c.C.28;c.C.28=\'4T\'}c.1r();c.5i(\'X-dR-dX\',\'7d\');c.5i(\'dY\',\'21/8n, 21/dZ, ab/5q, 21/5q, */*\');c.2L=2L},1T:k(){B(c.C.7o)$(c.C.7o).1m().5Q(c.3w.21);B(c.C.72||c.C.7U)c.72();c.1i(\'1T\',[c.3w.21,c.3w.5q],20)},9C:k(1U){1U=1U||c.C.1U;23($F(1U)){12\'G\':1U=$(1U).5l();1D;12\'2C\':1U=7c.5l(1U)}B(c.5p)1U=(1U)?[c.5p,1U].2h(\'&\'):c.5p;m c.5y(c.2L,1U)},72:k(){B(c.C.7U||/(dT|dU)2W/.2t(c.9Z(\'9Q-F\')))o 4d=c.3w.21;17{o 2W,4d=[],5n=/<2W[^>]*>([\\s\\S]*?)<\\/2W>/dS;6Y((2W=5n.dV(c.3w.21)))4d.1k(2W[1]);4d=4d.2h(\'\\n\')}B(4d)(U.9N)?U.9N(4d):U.9H(4d,0)},9Z:k(1w){5f{m c.2y.dW(1w)}4X(e){};m 1F}});7c.5l=k(1Y){o 51=[];M(o K 1b 1Y)51.1k(6e(K)+\'=\'+6e(1Y[K]));m 51.2h(\'&\')};Q.R({5y:k(C){m L a9(c.6n(\'dQ\'),$2c({a7:c.5l()},C,{28:\'4T\'})).9C()}});o 3I=L 3y({C:{6f:N,6i:N,49:N,56:N},2i:k(1s,J,C){C=$2c(c.C,C);J=6e(J);B(C.6f)J+=\'; 6f=\'+C.6f;B(C.6i)J+=\'; 6i=\'+C.6i;B(C.49){o 6x=L 97();6x.dK(6x.bf()+C.49*24*60*60*ax);J+=\'; e1=\'+6x.ef()}B(C.56)J+=\'; 56\';P.4D=1s+\'=\'+J;m $R(C,{\'1s\':1s,\'J\':J})},4N:k(1s){o J=P.4D.2T(\'(?:^|;)\\\\s*\'+1s.aK()+\'=([^;]*)\');m J?e5(J[1]):N},2H:k(4D,C){B($F(4D)==\'2C\')c.2i(4D.1s,\'\',$2c(4D,{49:-1}));17 c.2i(4D,\'\',$2c(C,{49:-1}))}});o 3G={4u:k(O){23($F(O)){12\'2E\':m\'"\'+O.3l(/(["\\\\])/g,\'\\\\$1\')+\'"\';12\'1B\':m\'[\'+O.2K(3G.4u).2h(\',\')+\']\';12\'2C\':o 2E=[];M(o K 1b O)2E.1k(3G.4u(K)+\':\'+3G.4u(O[K]));m\'{\'+2E.2h(\',\')+\'}\'}m 6W(O)},5M:k(4q,56){m(($F(4q)!=\'2E\')||(56&&!4q.2t(/^("(\\\\.|[^"\\\\\\n\\r])*?"|[,:{}\\[\\]0-9.\\-+e4-u \\n\\r\\t])+?$/)))?N:e6(\'(\'+4q+\')\')}};3G.e7=6h.R({1j:k(2L,C){c.2L=2L;c.1I(\'4L\',c.1T);c.1r(C);c.5i(\'X-ea\',\'e9\')},5y:k(O){m c.1r(c.2L,\'dG=\'+3G.4u(O))},1T:k(){c.1i(\'1T\',3G.5M(c.3w.21,c.C.56))}});o bb=L 3y({8n:k(1Y,1K){1K=$2c({\'5A\':18.1m},1K);o 2W=L Q(\'2W\',{\'59\':1Y}).6B({\'4r\':1K.5A,\'dF\':k(){B(c.5c==\'8q\')c.1i(\'4r\')}});5j 1K.5A;m 2W.6j(1K).25(P.6s)},1x:k(1Y,1K){m L Q(\'4m\',$2c({\'95\':\'dc\',\'db\':\'de\',\'F\':\'21/1x\',\'5h\':1Y},1K)).25(P.6s)},58:k(1Y,1K){1K=$2c({\'5A\':18.1m,\'df\':18.1m,\'di\':18.1m},1K);o 58=L d3();58.59=1Y;o G=L Q(\'8t\',{\'59\':1Y});[\'4r\',\'aC\',\'dz\'].1o(k(F){o I=1K[\'5C\'+F];5j 1K[\'5C\'+F];G.1I(F,k(){c.3Z(F,1c.8r);I.1S(c)})});B(58.2z&&58.2N)G.1i(\'4r\',G,1);m G.6j(1K)},6F:k(5e,C){C=$2c({1T:18.1m,b6:18.1m},C);B(!5e.1k)5e=[5e];o 6F=[];o 6m=0;5e.1o(k(1Y){o 8t=L bb.58(1Y,{\'5A\':k(){C.b6.1S(c,6m);6m++;B(6m==5e.V)C.1T()}});6F.1k(8t)});m L 29(6F)}});o 3H=L 18({V:0,1j:k(2C){c.O=2C||{};c.5u()},4N:k(1s){m(c.6L(1s))?c.O[1s]:1F},6L:k(1s){m(1s 1b c.O)},2i:k(1s,J){B(!c.6L(1s))c.V++;c.O[1s]=J;m c},5u:k(){c.V=0;M(o p 1b c.O)c.V++;m c},2H:k(1s){B(!c.6L(1s))m c;5j c.O[1s];c.V--;m c},1o:k(W,Y){$1o(c.O,W,Y)},R:k(O){$R(c.O,O);m c.5u()},2c:k(){c.O=$2c.3U(1F,[c.O].R(1c));m c.5u()},1m:k(){c.O={};c.V=0;m c},1P:k(){o 1P=[];M(o K 1b c.O)1P.1k(K);m 1P},1J:k(){o 1J=[];M(o K 1b c.O)1J.1k(c.O[K]);m 1J}});k $H(O){m L 3H(O)};3H.3I=3H.R({1j:k(1w,C){c.1w=1w;c.C=$R({\'bj\':1e},C||{});c.4r()},bd:k(){B(c.V==0){3I.2H(c.1w,c.C);m 1e}o 4q=3G.4u(c.O);B(4q.V>dv)m N;3I.2i(c.1w,4q,c.C);m 1e},4r:k(){c.O=3G.5M(3I.4N(c.1w),1e)||{};c.5u()}});3H.3I.2F={};[\'R\',\'2i\',\'2c\',\'1m\',\'2H\'].1o(k(28){3H.3I.2F[28]=k(){3H.1L[28].3U(c,1c);B(c.C.bj)c.bd();m c}});3H.3I.3q(3H.3I.2F);o 2M=L 18({1j:k(2G,F){F=F||(2G.1k?\'1v\':\'3C\');o 1v,2n;23(F){12\'1v\':1v=2G;2n=1v.8d();1D;12\'2n\':1v=2G.9r();2n=2G;1D;5D:1v=2G.5H(1e);2n=1v.8d()}1v.2n=2n;1v.3C=1v.5I();m $R(1v,2M.1L)},4R:k(){o 5m=$A(1c);o 6Z=($F(5m[5m.V-1])==\'4S\')?5m.dp():50;o 1v=c.8m();5m.1o(k(2G){2G=L 2M(2G);M(o i=0;i<3;i++)1v[i]=1d.2r((1v[i]/ 3b * (3b - 6Z)) + (2G[i] /3b*6Z))});m L 2M(1v,\'1v\')},du:k(){m L 2M(c.2K(k(J){m 53-J}))},dt:k(J){m L 2M([J,c.2n[1],c.2n[2]],\'2n\')},ds:k(6X){m L 2M([c.2n[0],6X,c.2n[2]],\'2n\')},em:k(6X){m L 2M([c.2n[0],c.2n[1],6X],\'2n\')}});k $eq(r,g,b){m L 2M([r,g,b],\'1v\')};k $f6(h,s,b){m L 2M([h,s,b],\'2n\')};2I.R({8d:k(){o 5t=c[0],5v=c[1],73=c[2];o 2Z,6l,8g;o 1z=1d.1z(5t,5v,73),3p=1d.3p(5t,5v,73);o 4l=1z-3p;8g=1z/53;6l=(1z!=0)?4l/1z:0;B(6l==0){2Z=0}17{o 8c=(1z-5t)/4l;o 8R=(1z-5v)/4l;o br=(1z-73)/4l;B(5t==1z)2Z=br-8R;17 B(5v==1z)2Z=2+8c-br;17 2Z=4+8R-8c;2Z/=6;B(2Z<0)2Z++}m[1d.2r(2Z*9y),1d.2r(6l*3b),1d.2r(8g*3b)]},9r:k(){o br=1d.2r(c[2]/3b*53);B(c[1]==0){m[br,br,br]}17{o 2Z=c[0]%9y;o f=2Z%60;o p=1d.2r((c[2]*(3b-c[1]))/f4*53);o q=1d.2r((c[2]*(9s-c[1]*f))/9u*53);o t=1d.2r((c[2]*(9s-c[1]*(60-f)))/9u*53);23(1d.an(2Z/60)){12 0:m[br,t,p];12 1:m[q,br,p];12 2:m[p,br,t];12 3:m[p,q,br];12 4:m[t,p,br];12 5:m[br,p,q]}}m N}});o 9B=L 18({C:{5W:20,8w:1,79:k(x,y){c.G.3x(x,y)}},1j:k(G,C){c.2U(C);c.G=$(G);c.8j=([U,P].1l(G))?$(P.4H):c.G},1h:k(){c.8i=c.9a.3g(c);c.8j.2A(\'2V\',c.8i)},1R:k(){c.8j.3j(\'2V\',c.8i);c.1H=$4Z(c.1H)},9a:k(I){c.1M=(c.G==U)?I.9d:I.1M;B(!c.1H)c.1H=c.2J.4f(50,c)},2J:k(){o el=c.G.6N();o 1p=c.G.3o();o 4h={\'x\':0,\'y\':0};M(o z 1b c.1M){B(c.1M[z]<(c.C.5W+1p[z])&&el.2J[z]!=0)4h[z]=(c.1M[z]-c.C.5W-1p[z])*c.C.8w;17 B(c.1M[z]+c.C.5W>(el.3n[z]+1p[z])&&el.2J[z]+el.3n[z]!=el.6M[z])4h[z]=(c.1M[z]-el.3n[z]+c.C.5W-1p[z])*c.C.8w}B(4h.y||4h.x)c.1i(\'79\',[el.2J.x+4h.x,el.2J.y+4h.y])}});9B.3q(L 2q,L 4i);o 8G=L 18({C:{79:18.1m,1T:18.1m,8P:k(1p){c.48.1O(c.p,1p)},2d:\'8K\',6r:3b,1C:0},1j:k(el,48,C){c.G=$(el);c.48=$(48);c.2U(C);c.8O=-1;c.8N=-1;c.2l=-1;c.G.1I(\'64\',c.aa.3g(c));o 7j,1C;23(c.C.2d){12\'8K\':c.z=\'x\';c.p=\'1t\';7j={\'x\':\'1t\',\'y\':N};1C=\'42\';1D;12\'8J\':c.z=\'y\';c.p=\'1n\';7j={\'x\':N,\'y\':\'1n\'};1C=\'3T\'}c.1z=c.G[1C]-c.48[1C]+(c.C.1C*2);c.a1=c.48[1C]/2;c.a6=c.G[\'4N\'+c.p.8I()].Y(c.G);c.48.1O(\'1u\',\'7h\').1O(c.p,-c.C.1C);o 8L={};8L[c.z]=[-c.C.1C,c.1z-c.C.1C];c.3L=L 3Y.2O(c.48,{1E:8L,3F:7j,6u:0,45:k(){c.75()}.Y(c),8M:k(){c.75()}.Y(c),1T:k(){c.75();c.2f()}.Y(c)});B(c.C.1j)c.C.1j.1S(c)},2i:k(2l){c.2l=2l.1E(0,c.C.6r);c.78();c.2f();c.1i(\'8P\',c.a4(c.2l));m c},aa:k(I){o 1u=I.1M[c.z]-c.a6()-c.a1;1u=1u.1E(-c.C.1C,c.1z-c.C.1C);c.2l=c.8H(1u);c.78();c.2f();c.1i(\'8P\',1u)},75:k(){c.2l=c.8H(c.3L.J.1a[c.z]);c.78()},78:k(){B(c.8O!=c.2l){c.8O=c.2l;c.1i(\'79\',c.2l)}},2f:k(){B(c.8N!==c.2l){c.8N=c.2l;c.1i(\'1T\',c.2l+\'\')}},8H:k(1u){m 1d.2r((1u+c.C.1C)/c.1z*c.C.6r)},a4:k(2l){m c.1z*2l/c.C.6r}});8G.3q(L 2q);8G.3q(L 4i);o ev=1g.ac.R({1j:k(C){c.1r(U,C);c.68=(c.C.68)?$$(c.C.68):$$(P.68);o 5b=U.5b.5h.2T(/^[^#]*/)[0]+\'#\';c.68.1o(k(4m){B(4m.5h.3S(5b)!=0)m;o 3E=4m.5h.6p(5b.V);B(3E&&$(3E))c.ag(4m,3E)},c);B(!U.65)c.1I(\'1T\',k(){U.5b.eU=c.3E})},ag:k(4m,3E){4m.1I(\'8p\',k(I){c.3E=3E;c.8z(3E);I.1R()}.3g(c))}});o 9S=L 18({C:{4I:N,45:18.1m,1T:18.1m,2Q:1e,6u:3,9I:k(G,2Q){2Q.1O(\'22\',0.7);G.1O(\'22\',0.7)},9T:k(G,2Q){G.1O(\'22\',1);2Q.2H();c.44.2H()}},1j:k(4U,C){c.2U(C);c.4U=$(4U);c.T=c.4U.8F();c.4I=(c.C.4I)?$$(c.C.4I):c.T;c.1G={\'1h\':[],\'62\':c.62.3g(c)};M(o i=0,l=c.4I.V;i<l;i++){c.1G.1h[i]=c.1h.3g(c,c.T[i])}c.6K();B(c.C.1j)c.C.1j.1S(c);c.1G.61=c.61.3g(c);c.1G.2f=c.2f.Y(c)},6K:k(){c.4I.1o(k(3K,i){3K.1I(\'64\',c.1G.1h[i])},c)},9K:k(){c.4I.1o(k(3K,i){3K.3Z(\'64\',c.1G.1h[i])},c)},1h:k(I,el){c.3R=el;c.8y=c.4U.4A();B(c.C.2Q){o 1u=el.3o();c.1C=I.1M.y-1u.y;c.44=L Q(\'4K\').25(P.4H);c.2Q=el.9M().25(c.44).4z({\'1u\':\'3X\',\'1t\':1u.x,\'1n\':I.1M.y-c.1C});P.2A(\'2V\',c.1G.62);c.1i(\'9I\',[el,c.2Q])}P.2A(\'2V\',c.1G.61);P.2A(\'6S\',c.1G.2f);c.1i(\'45\',el);I.1R()},62:k(I){o J=I.1M.y-c.1C;J=J.1E(c.8y.1n,c.8y.3O-c.2Q.3T);c.2Q.1O(\'1n\',J);I.1R()},61:k(I){c.3R.3R=1e;c.2o=c.2o||I.1M.y;c.1a=I.1M.y;o 5Z=((c.2o-c.1a)<=0)?\'8C\':\'8B\';o 6v=c.3R.9F();o 3v=c.3R.8x();B(6v&&5Z==\'8B\'){o 9O=6v.4A();B(I.1M.y<9O.3O)c.3R.8o(6v)}B(3v&&5Z==\'8C\'){o 9V=3v.4A();B(I.1M.y>9V.1n)c.3R.6O(3v)}c.2o=I.1M.y},eF:k(){o 8E=[];c.4U.8F().1o(k(el,i){8E[i]=c.T.3S(el)},c);m 8E},2f:k(){c.2o=1F;P.3j(\'2V\',c.1G.61);P.3j(\'6S\',c.1G.2f);B(c.C.2Q){P.3j(\'2V\',c.1G.62);c.1i(\'9T\',[c.3R,c.2Q])}c.1i(\'1T\',c.3R)}});9S.3q(L 2q,L 4i);o ar=L 18({C:{az:k(4c){4c.1O(\'4G\',\'8D\')},ay:k(4c){4c.1O(\'4G\',\'4y\')},8v:30,9j:3b,9k:3b,1A:\'bJ\',5P:{\'x\':16,\'y\':16},5S:N},1j:k(T,C){c.2U(C);c.4g=L Q(\'4K\',{\'4O\':c.C.1A+\'-4c\',\'8A\':{\'1u\':\'3X\',\'1n\':\'0\',\'1t\':\'0\',\'4G\':\'4y\'}}).25(P.4H);c.3d=L Q(\'4K\').25(c.4g);$$(T).1o(c.ae,c);B(c.C.1j)c.C.1j.1S(c)},ae:k(el){el.$1X.47=(el.5h&&el.57()==\'a\')?el.5h.3l(\'96://\',\'\'):(el.95||N);B(el.5g){o 6b=el.5g.66(\'::\');B(6b.V>1){el.$1X.47=6b[0].5Y();el.$1X.5T=6b[1].5Y()}17{el.$1X.5T=el.5g}el.94(\'5g\')}17{el.$1X.5T=N}B(el.$1X.47&&el.$1X.47.V>c.C.8v)el.$1X.47=el.$1X.47.6p(0,c.C.8v-1)+"&cu;";el.1I(\'8k\',k(I){c.1h(el);B(!c.C.5S)c.8e(I);17 c.1u(el)}.Y(c));B(!c.C.5S)el.1I(\'2V\',c.8e.3g(c));o 2f=c.2f.Y(c);el.1I(\'8h\',2f);el.1I(\'44\',2f)},1h:k(el){c.3d.1m();B(el.$1X.47){c.5g=L Q(\'9f\').25(L Q(\'4K\',{\'4O\':c.C.1A+\'-5g\'}).25(c.3d)).5Q(el.$1X.47)}B(el.$1X.5T){c.21=L Q(\'9f\').25(L Q(\'4K\',{\'4O\':c.C.1A+\'-21\'}).25(c.3d)).5Q(el.$1X.5T)}$4Z(c.1H);c.1H=c.41.2k(c.C.9j,c)},2f:k(I){$4Z(c.1H);c.1H=c.5k.2k(c.C.9k,c)},1u:k(G){o 1p=G.3o();c.4g.4z({\'1t\':1p.x+c.C.5P.x,\'1n\':1p.y+c.C.5P.y})},8e:k(I){o aE={\'x\':U.8f(),\'y\':U.8l()};o 2J={\'x\':U.8s(),\'y\':U.8u()};o 4c={\'x\':c.4g.42,\'y\':c.4g.3T};o 1V={\'x\':\'1t\',\'y\':\'1n\'};M(o z 1b 1V){o 1p=I.1M[z]+c.C.5P[z];B((1p+4c[z]-2J[z])>aE[z])1p=I.1M[z]-c.C.5P[z]-4c[z];c.4g.1O(1V[z],1p)}},41:k(){B(c.C.aG)c.1H=c.5k.2k(c.C.aG,c);c.1i(\'az\',[c.4g])},5k:k(){c.1i(\'ay\',[c.4g])}});ar.3q(L 2q,L 4i);o cd=L 18({1j:k(){c.5E=$A(1c);c.19={};c.4P={}},1I:k(F,W){c.4P[F]=c.4P[F]||{};c.19[F]=c.19[F]||[];B(c.19[F].1l(W))m N;17 c.19[F].1k(W);c.5E.1o(k(5x,i){5x.1I(F,c.3V.Y(c,[F,5x,i]))},c);m c},3V:k(F,5x,i){c.4P[F][i]=1e;o 4v=c.5E.4v(k(2a,j){m c.4P[F][j]||N},c);B(!4v)m;c.5E.1o(k(2a,j){c.4P[F][j]=N},c);c.19[F].1o(k(I){I.1S(c,c.5E,5x)},c)}});o 7n=1g.29.R({C:{8Q:18.1m,aN:18.1m,3D:0,41:N,2N:1e,2z:N,22:1e,6g:N,6A:N,3Q:N,74:N},1j:k(){o C,2v,T,2g;$1o(1c,k(4n,i){23($F(4n)){12\'2C\':C=4n;1D;12\'G\':2g=$(4n);1D;5D:o 2s=$$(4n);B(!2v)2v=2s;17 T=2s}});c.2v=2v||[];c.T=T||[];c.2g=$(2g);c.2U(C);c.2o=-1;B(c.C.74)c.C.3Q=1e;B($2B(c.C.41)){c.C.3D=N;c.2o=c.C.41}B(c.C.1h){c.C.3D=N;c.C.41=N}c.3t={};B(c.C.22)c.3t.22=\'b2\';B(c.C.2z)c.3t.2z=c.C.6A?\'b0\':\'42\';B(c.C.2N)c.3t.2N=c.C.6g?\'aU\':\'5N\';M(o i=0,l=c.2v.V;i<l;i++)c.aV(c.2v[i],c.T[i]);c.T.1o(k(el,i){B(c.C.41===i)c.1i(\'8Q\',[c.2v[i],el]);17 M(o 2x 1b c.3t)el.1O(2x,0)},c);c.1r(c.T);B($2B(c.C.3D))c.3D(c.C.3D)},aV:k(3k,G,1p){3k=$(3k);G=$(G);o 2t=c.2v.1l(3k);o 3N=c.2v.V;c.2v.5w(3k);c.T.5w(G);B(3N&&(!2t||1p)){1p=$5F(1p,3N-1);3k.8o(c.2v[1p]);G.6O(3k)}17 B(c.2g&&!2t){3k.25(c.2g);G.25(c.2g)}o aZ=c.2v.3S(3k);3k.1I(\'8p\',c.3D.Y(c,aZ));B(c.C.2N)G.4z({\'4F-1n\':0,\'2Y-1n\':\'6I\',\'4F-3O\':0,\'2Y-3O\':\'6I\'});B(c.C.2z)G.4z({\'4F-1t\':0,\'2Y-1t\':\'6I\',\'4F-4k\':0,\'2Y-4k\':\'6I\'});G.b2=1;B(c.C.6A)G.b0=c.C.6A;B(c.C.6g)G.aU=c.C.6g;G.1O(\'aT\',\'4y\');B(!2t)M(o 2x 1b c.3t)G.1O(2x,0);m c},3D:k(26){26=($F(26)==\'G\')?c.T.3S(26):26;B((c.1H&&c.C.3Q)||(26===c.2o&&!c.C.74))m c;c.2o=26;o O={};c.T.1o(k(el,i){O[i]={};B((i!=26)||(c.C.74&&(el.3T>0))){c.1i(\'aN\',[c.2v[i],el]);M(o 2x 1b c.3t)O[i][2x]=0}17{c.1i(\'8Q\',[c.2v[i],el]);M(o 2x 1b c.3t)O[i][2x]=el[c.3t[2x]]}},c);m c.1h(O)},cV:k(26){m c.3D(26)}});1g.7n=7n;',62,940,'||||||||||||this||||||||function||return||var|||||||||||||if|options|||type|element||event|value|property|new|for|false|obj|document|Element|extend||elements|window|length|fn||bind||||case||to|from||else|Class|events|now|in|arguments|Math|true|param|Fx|start|fireEvent|initialize|push|contains|empty|top|each|pos|args|parent|key|left|position|rgb|name|css|items|max|className|array|offset|break|limit|null|bound|timer|addEvent|values|properties|prototype|page|result|setStyle|keys|selector|stop|call|onComplete|data|prop|props|tmp|source|style||text|opacity|switch||inject|index||method|Elements|current|transition|merge|mode|parsed|end|container|join|set|getStyle|delay|step|overflown|hsb|previous|relatedTarget|Events|round|temp|test|unit|togglers|custom|fx|transport|width|addListener|chk|object|nocash|string|Methods|color|remove|Array|scroll|map|url|Color|height|Base|parse|ghost|Event|params|match|setOptions|mousemove|script|documentElement|border|hue||ie||Garbage|margin|getElementsByTagName|context||||create|100|toInt|wrapper|overed|filter|bindWithEvent|item|mouse|removeListener|toggler|replace|Transitions|size|getPosition|min|implement|parentNode|CSS|effects|target|next|response|scrollTo|Abstract|iCss|time|option|hex|display|anchor|modifiers|Json|Hash|Cookie|pow|handle|drag|shared|len|bottom|returns|wait|active|indexOf|offsetHeight|apply|check|iterable|absolute|Drag|removeEvent||show|offsetWidth|xpath|trash|onStart||myTitle|knob|duration|iTo|getValue|tip|scripts|Styles|periodical|toolTip|change|Options|chains|right|delta|link|argument|select|increase|str|load|setNow|compute|toString|every|id|val|hidden|setStyles|getCoordinates|headers|status|cookie|grid|padding|visibility|body|handles|cont|div|onSuccess|webkit|get|class|checker|native|mix|number|post|list|collect|running|catch|htmlElement|clear||queryString|bit|255|results|getNow|secure|getTag|image|src|px|location|readyState|fromTo|sources|try|title|href|setHeader|delete|hide|toQueryString|colors|regexp|iFrom|_method|xml|mousewheel|iNow|red|setLength|green|include|instance|send|layout|onload|toLowerCase|on|default|instances|pick|isSuccess|hexToRgb|rgbToHex|encoding|out|precision|evaluate|scrollHeight|HTMLElement|offsets|setHTML|unique|fixed|myText|walk|domReady|area|parseInt|trim|direction||move|moveGhost|klass|mousedown|webkit419|split|scrollLeft|links|parseFloat|scrollTop|dual|onreadystatechange|fix|encodeURIComponent|domain|fixedHeight|XHR|path|setProperties|tagName|saturation|counter|getProperty|regex|substr|droppables|steps|head|evType|snap|prev|setMany|date|splice|Properties|fixedWidth|addEvents|continue|Multi|onFailure|images|removeEvents|scrollWidth|none|attempt|attach|hasKey|scrollSize|getSize|injectAfter|generic|code|mp|mouseup|included|brother|stopPropagation|String|percent|while|alpha|loaded|currentStyle|evalScripts|blue|alwaysHide|draggedKnob|preventDefault|getElementsBySelector|checkStep|onChange|Listeners|setProperty|Object|XMLHttpRequest|getElements|getElementById|typeof|relative|fKey|mod|proto|forEach|onCancel|Accordion|update|pageX|pageY|setTransport|nodeType|callChain|realType|addEventListener|clean|operator|concat|node|iProps|getItems|getParam|getMany|merged|hasClass|insertBefore|Dom|add|ie_ready|domready|qs|disabled|camelCase|multiple|checked|found|transitions|Function|charAt|evalResponse|RegExp|gecko|random|getLast|hasChild|pairs|appendChild|Style|easeType|first|PI|Transition|xhtml|compat|newArray|defined|Chain|rr|rgbToHsb|locate|getWidth|brightness|mouseleave|coord|mousemover|mouseenter|getHeight|copy|javascript|injectBefore|click|complete|callee|getScrollLeft|img|getScrollTop|maxTitleChars|velocity|getNext|coordinates|toElement|styles|up|down|visible|serial|getChildren|Slider|toStep|capitalize|vertical|horizontal|lim|onDrag|previousEnd|previousChange|onTick|onActive|gr|Top|Right|Bottom|Left|0px|Width|opera|nodeValue|clientWidth|fixStyle|borderShort|onRequest|removeAttribute|rel|http|Date|cancel|input|getCoords|getFormElements|textarea|client|clientHeight|span|onStateChange|clientX|firstChild|showDelay|hideDelay|iParsed|autoCancel|defaultView|hyphenate|async|Single|hsbToRgb|6000|pageYOffset|600000|pageXOffset|getScrollWidth|getScrollHeight|360|fps|childNodes|Scroller|request|mouseout|mouseover|getPrevious|cloneEvents|setTimeout|onDragStart|extended|detach|DOMMouseScroll|clone|execScript|prevPos|which|Content|clientY|Sortables|onDragComplete|fixRelatedTarget|nextPos|shift|wheelDelta|relatedTargetGecko|getHeader|tag|half|sel|normal|toPosition|getElement|getPos|postBody|picked|Ajax|clickedElement|application|Scroll|removeEventListener|build|unload|useLink|filterById|filterByClass|prefix|resolver|filterByAttribute|zoom|floor|Number||createElement|Tips|cos|interval|onBeforeStart|onSnap|distance|1000|onHide|onShow|before|after|abort|sin|win|elementsProperty|timeout|where|slice|toUpperCase|escapeRegExp|Merge|Move|onBackground|ActiveXObject|pp|www|constructor|urlEncoded|overflow|fullHeight|addSection|getLeft|getTop|ie6|idx|fullWidth|checkAgainst|fullOpacity|contents|toFloat|removeClass|onProgress|cssText|adopt|undefined|getStyles|Asset|slideIn|save|slideOut|getTime|full|addClass|setOpacity|autoSave|textnode|navigator|associate|styleFloat|some|getRandom|getFirst||srcElement|beforeunload|whitespace|detachEvent|attachEvent|lastChild|float|all|DOMElement|CollectGarbage|clearChain|chain|111|MooTools|version|zIndex|keydown|tool|execCommand|getComputedStyle|taintEnabled|getPropertyValue|menu|fromCharCode|keyCode|detail|control|ctrlKey|shiftKey|readOnly|cssFloat|alt|altKey|Sibling|120|wheel|metaKey|meta|nodeName|transparent|styleSheet|createTextNode|removeProperty|getProperties|injectInside|getBoxObjectFor|BackgroundImageCache|Group|boolean|htmlFor|webkit420|toggleClass|clearTimeout|borderColor|replaceWith|ie7|replaceChild|clearInterval|appendText|cloneNode|setAttribute|borderWidth|borderStyle|injectTop|hellip|removeChild|colspan|embed|tabindex|tabIndex|accessKey|accesskey|rowSpan|getParent|err|maxlength|maxLength|innerHTML|setInterval|iframe|getAttribute|pass|Document|times|attributes|rowspan|colSpan|hasLayout|khtml|collection|bindAsEventListener|showThisHideOpen|Native|Window|readonly|starts|618|Bounce|Elastic|Image|Back|Sine|Expo|Circ|acos|Quad|Cubic|media|stylesheet|sqrt|screen|onabort|Quart|Quint|onerror|Pow|ease|toLeft|toRight|Slide||pop|toBottom|toTop|setSaturation|setHue|invert|4096|rightClick|Out|InOut|error|In|linear|easeIn|easeOut|easeInOut|readystatechange|json|Connection|close|setRequestHeader|setTime|overrideMimeType|open|300|responseText|responseXML|action|Requested|gi|ecma|java|exec|getResponseHeader|With|Accept|html|200|expires|leave|over|Eaeflnr|decodeURIComponent|eval|Remote|makeResizable|JSON|Request|drop|emptydrop|form|urlencoded|toGMTString|charset|XMLHTTP|makeDraggable|utf|Microsoft||setBrightness|toggle|org|1999|RGB|w3|snapshotItem|UNORDERED_NODE_SNAPSHOT_TYPE|snapshotLength|SmoothScroll|getElementsByClassName|offsetLeft|offsetTop|password|radio|selected|checkbox|XPathResult|substring|serialize|enter|returnValue|cancelBubble|button|fromElement|esc|space|namespaceURI|with|ES|filterByTag|backspace|tab|offsetParent|hash|DOMContentLoaded|clearTimer|defer|500|innerHeight|innerWidth|effect|onDomReady|write|10000|protocol|HSB|https|Shared|void'.split('|'),0,{}))
/**
* This is a small fix to correct the png transparency problem under IE under version 7
*/
window.addEvent('load', function(e) {
var arVersion = navigator.appVersion.split("MSIE");
var version = parseFloat(arVersion[1]);
if ((version >= 5.5) && (version < 7) && (document.body.filters)) {
for(var i=0; i<document.images.length; i++) {
var img = document.images[i];
var imgName = img.src.toUpperCase();
if ((imgName.substring(imgName.length-3, imgName.length) == "PNG" || imgName.indexOf('FILETYPE=PNG') != -1) && (img.height && img.width)) {
var imgID = (img.id) ? "id='" + img.id + "' " : "";
var imgClass = (img.className) ? "class='" + img.className + "' " : "";
var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' ";
var imgStyle = "display:inline-block;" + img.style.cssText;
if (img.align == "left") imgStyle = "float:left;" + imgStyle;
if (img.align == "right") imgStyle = "float:right;" + imgStyle;
if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle;
var strNewHTML = "<span " + imgID + imgClass + imgTitle
+ " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
+ "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
+ "(src=\'" + img.src + "\', sizingMethod='scale');\"></span>";
img.outerHTML = strNewHTML;
i = i-1;
}
}
}
});
var PrintingWindow = new Class({
options: {
container: document.getElement('body'),
containerClass : 'Synergee-Web-Page-Component-PrintingWindow',
outputId: 'printingWindowFrame',
width : 750,
height : 370,
button : null
},
initialize: function(options) {
this.setOptions(options);
this.output =  new Element('iframe').injectInside(document.getElement('body'));
this.output.setStyle('display','none');
this.output.setAttribute('id', this.options.outputId);
if(this.options.button)this.options.button.addEvent('click', this.displayPrintWindow.bind(this));
},
displayPrintWindow : function(){
Lightbox.show('{hiddenId|' + this.output.id + '}', '', 'width=' + this.options.width + ', height=' + this.options.height);
if (/msie/i.test(navigator.userAgent)) {
// IE
// seems to be a bug in IE that makes contentWindow raise an error in some cases
try {
var w = this.output.contentWindow;
} catch(ex) {
}
var d = w ? w.document : null;
} else {
try {
var d = this.output.contentDocument;
}
catch (ex) {
}	// in case of cross domain scripting
var w = d ? d.defaultView : null;
}
if (d) {
try {
var tempContainer = new Element('div');
var child = this.options.container.clone();
child.injectInside(tempContainer);
child.getElements('script').each(function(item, index){
item.innerHTML = '';
}.bind(this));
d.open();
d.write('<html><head/><body >'+ tempContainer.innerHTML +'</body></html>');
d.close();
var body = d.getElementsByTagName("body")[0];
body.style.textAlign = 'left';
body.setAttribute('class', this.options.containerClass);
//                    if (this.options.button && this.options.button.id && d.getElementById(this.options.button.id)) {
//                        d.getElementById(this.options.button.id).removeChild(d.getElementById(this.options.button.id).childNodes[0]);
//                    }
var styleSheets = document.getElementsByTagName("LINK");
var head = d.getElementsByTagName("HEAD")[0];
if (!head) {
head = d.createElement("HEAD");
d.getElementsByTagName("HTML")[0].insertBefore(head, d.getElementsByTagName("BODY")[0]);
}
for (var i = 0; i < styleSheets.length; i++) {
if (styleSheets[i].getAttribute("rel") == 'stylesheet') {
var linkElement = d.createElement('LINK');
linkElement.setAttribute('href', styleSheets[i].getAttribute("href"));
linkElement.setAttribute('rel', 'stylesheet');
linkElement.setAttribute('type', 'text/css');
head.appendChild(linkElement);
}
}
w.focus();
w.print();
} catch (ex) {
}
}
}
});
PrintingWindow.implement(new Events);
PrintingWindow.implement(new Options);
var ResultHelper = Events.extend( {
initialize: function (resultsPerPage, countResults) {
this.resultsPerPage = resultsPerPage;
this.countResults = countResults;
if (this.resultsPerPage == 0)
this.resultsPerPage = 1;
this.countPages = Math.ceil(this.countResults / this.resultsPerPage);
this.currentPage = 0;
},
getCountPages : function () {
return this.countPages;
},
getCurrentPage : function () {
return this.currentPage;
},
injectNavBar : function(toInjectNavBarClass, tagName, navClassBaseName, separator) {
var s = "";
for (var i=0; i<this.countPages; i++) {
var className = navClassBaseName + i;
s += "<" + (tagName == 'button' ? tagName + ' type="button"' : tagName) + " class='" + className + "'>" + (i+1) + "</" + tagName + ">";
if (i != this.countPages - 1) {
s += separator;
}
}
$$('.'+toInjectNavBarClass).setHTML(s);
},
nextPage : function () {
if (this.currentPage < this.countPages - 1) {
this.fireEvent('onPageChangeBefore');
this.currentPage++;
this.fireEvent('onPageChangeAfter');
if (this.currentPage == this.countPages - 1) {
this.fireEvent('onPageChangeUpperLimit');
}
}
},
previousPage : function () {
if (this.currentPage > 0) {
this.fireEvent('onPageChangeBefore');
this.currentPage--;
this.fireEvent('onPageChangeAfter');
if (this.currentPage == 0) {
this.fireEvent('onPageChangeLowerLimit');
}
}
},
selectPage : function (page) {
if (page >=0 && page < this.countPages) {
this.fireEvent('onPageChangeBefore');
this.currentPage = page;
this.fireEvent('onPageChangeAfter');
if (this.currentPage == 0) {
this.fireEvent('onPageChangeLowerLimit');
}
if (this.currentPage == this.countPages - 1) {
this.fireEvent('onPageChangeUpperLimit');
}
}
},
firstPage : function () {
this.selectPage(0);
},
lastPage : function () {
this.selectPage(this.countPages - 1);
}
});
/****************************************************************
*                                                              *
*  curvyCorners                                                *
*  ------------                                                *
*                                                              *
*  This script generates rounded corners for your divs.        *
*                                                              *
*  Version 1.2.9                                               *
*  Copyright (c) 2006 Cameron Cooke                            *
*  By: Cameron Cooke and Tim Hutchison.                        *
*                                                              *
*                                                              *
*  Website: http://www.curvycorners.net                        *
*  Email:   info@totalinfinity.com                             *
*  Forum:   http://www.curvycorners.net/forum/                 *
*                                                              *
*                                                              *
*  This library is free software; you can redistribute         *
*  it and/or modify it under the terms of the GNU              *
*  Lesser General Public License as published by the           *
*  Free Software Foundation; either version 2.1 of the         *
*  License, or (at your option) any later version.             *
*                                                              *
*  This library is distributed in the hope that it will        *
*  be useful, but WITHOUT ANY WARRANTY; without even the       *
*  implied warranty of MERCHANTABILITY or FITNESS FOR A        *
*  PARTICULAR PURPOSE. See the GNU Lesser General Public       *
*  License for more details.                                   *
*                                                              *
*  You should have received a copy of the GNU Lesser           *
*  General Public License along with this library;             *
*  Inc., 59 Temple Place, Suite 330, Boston,                   *
*  MA 02111-1307 USA                                           *
*                                                              *
****************************************************************/
var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1; var isMoz = document.implementation && document.implementation.createDocument; var isSafari = ((navigator.userAgent.toLowerCase().indexOf('safari')!=-1)&&(navigator.userAgent.toLowerCase().indexOf('mac')!=-1))?true:false; function curvyCorners()
{ if(typeof(arguments[0]) != "object") throw newCurvyError("First parameter of curvyCorners() must be an object."); if(typeof(arguments[1]) != "object" && typeof(arguments[1]) != "string") throw newCurvyError("Second parameter of curvyCorners() must be an object or a class name."); if(typeof(arguments[1]) == "string")
{ var startIndex = 0; var boxCol = getElementsByClass(arguments[1]);}
else
{ var startIndex = 1; var boxCol = arguments;}
var curvyCornersCol = new Array(); if(arguments[0].validTags)
var validElements = arguments[0].validTags; else
var validElements = ["div"]; for(var i = startIndex, j = boxCol.length; i < j; i++)
{ var currentTag = boxCol[i].tagName.toLowerCase(); if(inArray(validElements, currentTag) !== false)
{ curvyCornersCol[curvyCornersCol.length] = new curvyObject(arguments[0], boxCol[i]);}
}
this.objects = curvyCornersCol; this.applyCornersToAll = function()
{ for(var x = 0, k = this.objects.length; x < k; x++)
{ this.objects[x].applyCorners();}
}
}
function curvyObject()
{ this.box = arguments[1]; this.settings = arguments[0]; this.topContainer = null; this.bottomContainer = null; this.masterCorners = new Array(); this.contentDIV = null; var boxHeight = get_style(this.box, "height", "height"); var boxWidth = get_style(this.box, "width", "width"); var borderWidth = get_style(this.box, "borderBottomWidth", "border-bottom-width"); var borderColour = get_style(this.box, "borderBottomColor", "border-bottom-color"); var boxColour = get_style(this.box, "backgroundColor", "background-color"); var backgroundImage = get_style(this.box, "backgroundImage", "background-image"); var boxPosition = get_style(this.box, "position", "position"); var boxPadding = get_style(this.box, "paddingBottom", "padding-bottom"); this.boxHeight = parseInt(((boxHeight != "" && boxHeight != "auto" && boxHeight.indexOf("%") == -1)? boxHeight.substring(0, boxHeight.indexOf("px")) : this.box.scrollHeight)); this.boxWidth = parseInt(((boxWidth != "" && boxWidth != "auto" && boxWidth.indexOf("%") == -1)? boxWidth.substring(0, boxWidth.indexOf("px")) : this.box.scrollWidth)); this.borderWidth = parseInt(((borderWidth != "" && borderWidth.indexOf("px") !== -1)? borderWidth.slice(0, borderWidth.indexOf("px")) : 0)); this.boxColour = format_colour(boxColour); this.boxPadding = parseInt(((boxPadding != "" && boxPadding.indexOf("px") !== -1)? boxPadding.slice(0, boxPadding.indexOf("px")) : 0)); this.borderColour = format_colour(borderColour); this.borderString = this.borderWidth + "px" + " solid " + this.borderColour; this.backgroundImage = ((backgroundImage != "none")? backgroundImage : ""); this.boxContent = this.box.innerHTML; if(boxPosition != "absolute") this.box.style.position = "relative"; this.box.style.padding = "0px"; if(isIE && boxWidth == "auto" && boxHeight == "auto") this.box.style.width = "100%"; if(this.settings.autoPad == true && this.boxPadding > 0)
this.box.innerHTML = ""; this.applyCorners = function()
{ for(var t = 0; t < 2; t++)
{ switch(t)
{ case 0:
if(this.settings.tl || this.settings.tr)
{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var topMaxRadius = Math.max(this.settings.tl ? this.settings.tl.radius : 0, this.settings.tr ? this.settings.tr.radius : 0); newMainContainer.style.height = topMaxRadius + "px"; newMainContainer.style.top = 0 - topMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.topContainer = this.box.appendChild(newMainContainer);}
break; case 1:
if(this.settings.bl || this.settings.br)
{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var botMaxRadius = Math.max(this.settings.bl ? this.settings.bl.radius : 0, this.settings.br ? this.settings.br.radius : 0); newMainContainer.style.height = botMaxRadius + "px"; newMainContainer.style.bottom = 0 - botMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.bottomContainer = this.box.appendChild(newMainContainer);}
break;}
}
if(this.topContainer) this.box.style.borderTopWidth = "0px"; if(this.bottomContainer) this.box.style.borderBottomWidth = "0px"; var corners = ["tr", "tl", "br", "bl"]; for(var i in corners)
{ if(i > -1 < 4)
{ var cc = corners[i]; if(!this.settings[cc])
{ if(((cc == "tr" || cc == "tl") && this.topContainer != null) || ((cc == "br" || cc == "bl") && this.bottomContainer != null))
{ var newCorner = document.createElement("DIV"); newCorner.style.position = "relative"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; if(this.backgroundImage == "")
newCorner.style.backgroundColor = this.boxColour; else
newCorner.style.backgroundImage = this.backgroundImage; switch(cc)
{ case "tl":
newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.tr.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.left = -this.borderWidth + "px"; break; case "tr":
newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.tl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; newCorner.style.left = this.borderWidth + "px"; break; case "bl":
newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.br.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = -this.borderWidth + "px"; newCorner.style.backgroundPosition = "-" + (this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break; case "br":
newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.bl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = this.borderWidth + "px"
newCorner.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break;}
}
}
else
{ if(this.masterCorners[this.settings[cc].radius])
{ var newCorner = this.masterCorners[this.settings[cc].radius].cloneNode(true);}
else
{ var newCorner = document.createElement("DIV"); newCorner.style.height = this.settings[cc].radius + "px"; newCorner.style.width = this.settings[cc].radius + "px"; newCorner.style.position = "absolute"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; var borderRadius = parseInt(this.settings[cc].radius - this.borderWidth); for(var intx = 0, j = this.settings[cc].radius; intx < j; intx++)
{ if((intx +1) >= borderRadius)
var y1 = -1; else
var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1); if(borderRadius != j)
{ if((intx) >= borderRadius)
var y2 = -1; else
var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2))); if((intx+1) >= j)
var y3 = -1; else
var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);}
if((intx) >= j)
var y4 = -1; else
var y4 = Math.ceil(Math.sqrt(Math.pow(j ,2) - Math.pow(intx, 2))); if(y1 > -1) this.drawPixel(intx, 0, this.boxColour, 100, (y1+1), newCorner, -1, this.settings[cc].radius); if(borderRadius != j)
{ for(var inty = (y1 + 1); inty < y2; inty++)
{ if(this.settings.antiAlias)
{ if(this.backgroundImage != "")
{ var borderFract = (pixelFraction(intx, inty, borderRadius) * 100); if(borderFract < 30)
{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, 0, this.settings[cc].radius);}
else
{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, -1, this.settings[cc].radius);}
}
else
{ var pixelcolour = BlendColour(this.boxColour, this.borderColour, pixelFraction(intx, inty, borderRadius)); this.drawPixel(intx, inty, pixelcolour, 100, 1, newCorner, 0, this.settings[cc].radius, cc);}
}
}
if(this.settings.antiAlias)
{ if(y3 >= y2)
{ if (y2 == -1) y2 = 0; this.drawPixel(intx, y2, this.borderColour, 100, (y3 - y2 + 1), newCorner, 0, 0);}
}
else
{ if(y3 >= y1)
{ this.drawPixel(intx, (y1 + 1), this.borderColour, 100, (y3 - y1), newCorner, 0, 0);}
}
var outsideColour = this.borderColour;}
else
{ var outsideColour = this.boxColour; var y3 = y1;}
if(this.settings.antiAlias)
{ for(var inty = (y3 + 1); inty < y4; inty++)
{ this.drawPixel(intx, inty, outsideColour, (pixelFraction(intx, inty , j) * 100), 1, newCorner, ((this.borderWidth > 0)? 0 : -1), this.settings[cc].radius);}
}
}
this.masterCorners[this.settings[cc].radius] = newCorner.cloneNode(true);}
if(cc != "br")
{ for(var t = 0, k = newCorner.childNodes.length; t < k; t++)
{ var pixelBar = newCorner.childNodes[t]; var pixelBarTop = parseInt(pixelBar.style.top.substring(0, pixelBar.style.top.indexOf("px"))); var pixelBarLeft = parseInt(pixelBar.style.left.substring(0, pixelBar.style.left.indexOf("px"))); var pixelBarHeight = parseInt(pixelBar.style.height.substring(0, pixelBar.style.height.indexOf("px"))); if(cc == "tl" || cc == "bl"){ pixelBar.style.left = this.settings[cc].radius -pixelBarLeft -1 + "px";}
if(cc == "tr" || cc == "tl"){ pixelBar.style.top = this.settings[cc].radius -pixelBarHeight -pixelBarTop + "px";}
switch(cc)
{ case "tr":
pixelBar.style.backgroundPosition = "-" + Math.abs((this.boxWidth - this.settings[cc].radius + this.borderWidth) + pixelBarLeft) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "tl":
pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "bl":
pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs((this.boxHeight + this.settings[cc].radius + pixelBarTop) -this.borderWidth) + "px"; break;}
}
}
}
if(newCorner)
{ switch(cc)
{ case "tl":
if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "tr":
if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "bl":
if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break; case "br":
if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break;}
}
}
}
var radiusDiff = new Array(); radiusDiff["t"] = Math.abs(this.settings.tl.radius - this.settings.tr.radius)
radiusDiff["b"] = Math.abs(this.settings.bl.radius - this.settings.br.radius); for(z in radiusDiff)
{ if(z == "t" || z == "b")
{ if(radiusDiff[z])
{ var smallerCornerType = ((this.settings[z + "l"].radius < this.settings[z + "r"].radius)? z +"l" : z +"r"); var newFiller = document.createElement("DIV"); newFiller.style.height = radiusDiff[z] + "px"; newFiller.style.width = this.settings[smallerCornerType].radius+ "px"
newFiller.style.position = "absolute"; newFiller.style.fontSize = "1px"; newFiller.style.overflow = "hidden"; newFiller.style.backgroundColor = this.boxColour; switch(smallerCornerType)
{ case "tl":
newFiller.style.bottom = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.topContainer.appendChild(newFiller); break; case "tr":
newFiller.style.bottom = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.topContainer.appendChild(newFiller); break; case "bl":
newFiller.style.top = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.bottomContainer.appendChild(newFiller); break; case "br":
newFiller.style.top = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.bottomContainer.appendChild(newFiller); break;}
}
var newFillerBar = document.createElement("DIV"); newFillerBar.style.position = "relative"; newFillerBar.style.fontSize = "1px"; newFillerBar.style.overflow = "hidden"; newFillerBar.style.backgroundColor = this.boxColour; newFillerBar.style.backgroundImage = this.backgroundImage; switch(z)
{ case "t":
if(this.topContainer)
{ if(this.settings.tl.radius && this.settings.tr.radius)
{ newFillerBar.style.height = topMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.tl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.tr.radius - this.borderWidth + "px"; newFillerBar.style.borderTop = this.borderString; if(this.backgroundImage != "")
newFillerBar.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; this.topContainer.appendChild(newFillerBar);}
this.box.style.backgroundPosition = "0px -" + (topMaxRadius - this.borderWidth) + "px";}
break; case "b":
if(this.bottomContainer)
{ if(this.settings.bl.radius && this.settings.br.radius)
{ newFillerBar.style.height = botMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.bl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.br.radius - this.borderWidth + "px"; newFillerBar.style.borderBottom = this.borderString; if(this.backgroundImage != "")
newFillerBar.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (topMaxRadius + this.borderWidth)) + "px"; this.bottomContainer.appendChild(newFillerBar);}
}
break;}
}
}
if(this.settings.autoPad == true && this.boxPadding > 0)
{ var contentContainer = document.createElement("DIV"); contentContainer.style.position = "relative"; contentContainer.innerHTML = this.boxContent; contentContainer.className = "autoPadDiv"; var topPadding = Math.abs(topMaxRadius - this.boxPadding); var botPadding = Math.abs(botMaxRadius - this.boxPadding); if(topMaxRadius < this.boxPadding)
contentContainer.style.paddingTop = topPadding + "px"; if(botMaxRadius < this.boxPadding)
contentContainer.style.paddingBottom = botMaxRadius + "px"; contentContainer.style.paddingLeft = this.boxPadding + "px"; contentContainer.style.paddingRight = this.boxPadding + "px"; this.contentDIV = this.box.appendChild(contentContainer);}
}
this.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius)
{ var pixel = document.createElement("DIV"); pixel.style.height = height + "px"; pixel.style.width = "1px"; pixel.style.position = "absolute"; pixel.style.fontSize = "1px"; pixel.style.overflow = "hidden"; var topMaxRadius = Math.max(this.settings["tr"].radius, this.settings["tl"].radius); if(image == -1 && this.backgroundImage != "")
{ pixel.style.backgroundImage = this.backgroundImage; pixel.style.backgroundPosition = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + topMaxRadius + inty) -this.borderWidth) + "px";}
else
{ pixel.style.backgroundColor = colour;}
if (transAmount != 100)
setOpacity(pixel, transAmount); pixel.style.top = inty + "px"; pixel.style.left = intx + "px"; newCorner.appendChild(pixel);}
}
function insertAfter(parent, node, referenceNode)
{ parent.insertBefore(node, referenceNode.nextSibling);}
function BlendColour(Col1, Col2, Col1Fraction)
{ var red1 = parseInt(Col1.substr(1,2),16); var green1 = parseInt(Col1.substr(3,2),16); var blue1 = parseInt(Col1.substr(5,2),16); var red2 = parseInt(Col2.substr(1,2),16); var green2 = parseInt(Col2.substr(3,2),16); var blue2 = parseInt(Col2.substr(5,2),16); if(Col1Fraction > 1 || Col1Fraction < 0) Col1Fraction = 1; var endRed = Math.round((red1 * Col1Fraction) + (red2 * (1 - Col1Fraction))); if(endRed > 255) endRed = 255; if(endRed < 0) endRed = 0; var endGreen = Math.round((green1 * Col1Fraction) + (green2 * (1 - Col1Fraction))); if(endGreen > 255) endGreen = 255; if(endGreen < 0) endGreen = 0; var endBlue = Math.round((blue1 * Col1Fraction) + (blue2 * (1 - Col1Fraction))); if(endBlue > 255) endBlue = 255; if(endBlue < 0) endBlue = 0; return "#" + IntToHex(endRed)+ IntToHex(endGreen)+ IntToHex(endBlue);}
function IntToHex(strNum)
{ base = strNum / 16; rem = strNum % 16; base = base - (rem / 16); baseS = MakeHex(base); remS = MakeHex(rem); return baseS + '' + remS;}
function MakeHex(x)
{ if((x >= 0) && (x <= 9))
{ return x;}
else
{ switch(x)
{ case 10: return "A"; case 11: return "B"; case 12: return "C"; case 13: return "D"; case 14: return "E"; case 15: return "F";}
}
}
function pixelFraction(x, y, r)
{ var pixelfraction = 0; var xvalues = new Array(1); var yvalues = new Array(1); var point = 0; var whatsides = ""; var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x,2))); if ((intersect >= y) && (intersect < (y+1)))
{ whatsides = "Left"; xvalues[point] = 0; yvalues[point] = intersect - y; point = point + 1;}
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2))); if ((intersect >= x) && (intersect < (x+1)))
{ whatsides = whatsides + "Top"; xvalues[point] = intersect - x; yvalues[point] = 1; point = point + 1;}
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2))); if ((intersect >= y) && (intersect < (y+1)))
{ whatsides = whatsides + "Right"; xvalues[point] = 1; yvalues[point] = intersect - y; point = point + 1;}
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2))); if ((intersect >= x) && (intersect < (x+1)))
{ whatsides = whatsides + "Bottom"; xvalues[point] = intersect - x; yvalues[point] = 0;}
switch (whatsides)
{ case "LeftRight":
pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2); break; case "TopRight":
pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2); break; case "TopBottom":
pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2); break; case "LeftBottom":
pixelfraction = (yvalues[0]*xvalues[1])/2; break; default:
pixelfraction = 1;}
return pixelfraction;}
function rgb2Hex(rgbColour)
{ try{ var rgbArray = rgb2Array(rgbColour); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); var hexColour = "#" + IntToHex(red) + IntToHex(green) + IntToHex(blue);}
catch(e){ alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");}
return hexColour;}
function rgb2Array(rgbColour)
{ var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")")); var rgbArray = rgbValues.split(", "); return rgbArray;}
function setOpacity(obj, opacity)
{ opacity = (opacity == 100)?99.999:opacity; if(isSafari && obj.tagName != "IFRAME")
{ var rgbArray = rgb2Array(obj.style.backgroundColor); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); obj.style.backgroundColor = "rgba(" + red + ", " + green + ", " + blue + ", " + opacity/100 + ")";}
else if(typeof(obj.style.opacity) != "undefined")
{ obj.style.opacity = opacity/100;}
else if(typeof(obj.style.MozOpacity) != "undefined")
{ obj.style.MozOpacity = opacity/100;}
else if(typeof(obj.style.filter) != "undefined")
{ obj.style.filter = "alpha(opacity:" + opacity + ")";}
else if(typeof(obj.style.KHTMLOpacity) != "undefined")
{ obj.style.KHTMLOpacity = opacity/100;}
}
function inArray(array, value)
{ for(var i = 0; i < array.length; i++){ if (array[i] === value) return i;}
return false;}
function inArrayKey(array, value)
{ for(key in array){ if(key === value) return true;}
return false;}
function addEvent(elm, evType, fn, useCapture) { if (elm.addEventListener) { elm.addEventListener(evType, fn, useCapture); return true;}
else if (elm.attachEvent) { var r = elm.attachEvent('on' + evType, fn); return r;}
else { elm['on' + evType] = fn;}
}
function removeEvent(obj, evType, fn, useCapture){ if (obj.removeEventListener){ obj.removeEventListener(evType, fn, useCapture); return true;} else if (obj.detachEvent){ var r = obj.detachEvent("on"+evType, fn); return r;} else { alert("Handler could not be removed");}
}
function format_colour(colour)
{ var returnColour = "#ffffff"; if(colour != "" && colour != "transparent")
{ if(colour.substr(0, 3) == "rgb")
{ returnColour = rgb2Hex(colour);}
else if(colour.length == 4)
{ returnColour = "#" + colour.substring(1, 2) + colour.substring(1, 2) + colour.substring(2, 3) + colour.substring(2, 3) + colour.substring(3, 4) + colour.substring(3, 4);}
else
{ returnColour = colour;}
}
return returnColour;}
function get_style(obj, property, propertyNS)
{ try
{ if(obj.currentStyle)
{ var returnVal = eval("obj.currentStyle." + property);}
else
{ if(isSafari && obj.style.display == "none")
{ obj.style.display = ""; var wasHidden = true;}
var returnVal = document.defaultView.getComputedStyle(obj, '').getPropertyValue(propertyNS); if(isSafari && wasHidden)
{ obj.style.display = "none";}
}
}
catch(e)
{ }
return returnVal;}
function getElementsByClass(searchClass, node, tag)
{ var classElements = new Array(); if(node == null)
node = document; if(tag == null)
tag = '*'; var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp("(^|\s)"+searchClass+"(\s|$)"); for (i = 0, j = 0; i < elsLen; i++)
{ if(pattern.test(els[i].className))
{ classElements[j] = els[i]; j++;}
}
return classElements;}
function newCurvyError(errorMessage)
{ return new Error("curvyCorners Error:\n" + errorMessage)
}
/**
* This class is used for the price estimation functionnalities
*
* @event Event heightModified this event is fired when the price estimation is displayed
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param Element input the input div
* @param Element output the output div
**/
var School = Events.extend({
/**
* This is the initialization function
*/
initialize : function(schoolPriceDTO, translationsDTO, schoolContainer, listContainer, parent) {
this._parent = parent;
this._schoolContainer = schoolContainer;
this._listContainer = listContainer;
this._classNameBase = this._parent.getClassNameBase();
this._schoolPriceCalculatorDTO = schoolPriceDTO;
this._translateDTO = translationsDTO;
this.courses = new SchoolCourses(this._schoolPriceCalculatorDTO.schoolFixedDatesCourses, this._schoolPriceCalculatorDTO.schoolVariableDatesCourses, this._schoolPriceCalculatorDTO.schoolOptionalCourses,  this._translateDTO.courses, this._listContainer, this);
this.courses.getHtml().injectInside(this._schoolContainer);
this.accommodations = new SchoolAccommodations(this._schoolPriceCalculatorDTO.schoolAccommodations, this._translateDTO.accommodations, this._listContainer, this);
this.accommodations.getHtml().injectInside(this._schoolContainer);
this.transfers = new SchoolTransfers(this._schoolPriceCalculatorDTO.schoolTransfers, this._translateDTO.transfers, this);
this.transfers.getHtml().injectInside(this._schoolContainer);
this.courses.addEvent('refreshPrice', function() {
this.transfers.refreshTransfers();
this.fireEvent('refreshPrice');
}.bind(this));
this.accommodations.addEvent('refreshAccommodations', function() {
this.transfers.refreshTransfers();
this.fireEvent('refreshPrice');
}.bind(this));
this.accommodations.addEvent('refreshPrice', function() {
this.transfers.refreshTransfers();
this.fireEvent('refreshPrice');
}.bind(this));
this.transfers.addEvent('refreshPrice', function() {
this.fireEvent('refreshPrice');
}.bind(this));
this.addEvent('heightModified', function() {
this.getParent().fireEvent('heightModified');
}.bind(this));
this.addEvent('refreshAccommodations', function() {
this.accommodations.refreshAccommodations('lists');
this.transfers.refreshTransfers();
this.checkMandatoryCourseAccommodations();
});
},
getSchoolContainer : function(){
return this._schoolContainer;
},
/**
*  Return the classNameBase
*/
getClassNameBase : function() {
return this._classNameBase;
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Object The informations needed to calculate the price
*/
getDTO : function() {
var priceEstimationDTO = new Object();
priceEstimationDTO.variableDatesCourses = this.courses.getVariableCoursesDTO();
priceEstimationDTO.fixedDatesCourses = this.courses.getFixedCoursesDTO();
priceEstimationDTO.optionalCourses = this.courses.getOptionalCoursesDTO();
priceEstimationDTO.accommodations = this.accommodations.getDTO();
priceEstimationDTO.transfers = this.transfers.getDTO();
return priceEstimationDTO;
},
/**
* populate the price calculator with the DTO given in parameter
*
* @param DTO toPopulateDTO the DTO to populate from
*/
populateFromDTO : function(toPopulateDTO) {
this.courses.populateCoursesFromDTO(toPopulateDTO.fixedDatesCourses, toPopulateDTO.variableDatesCourses, toPopulateDTO.optionalCourses);
this.accommodations.populateFromDTO(toPopulateDTO.accommodations);
this.transfers.populateFromDTO(toPopulateDTO.transfers);
this.courses.fireEvent("refreshCourses");
},
checkMandatoryCourseAccommodations : function(){
var validCourses = this.courses.getValidAddedCourses();
if(validCourses.length){
var mandatoryAccommodations = this.courses.getMandatoryAccommodations();
if(mandatoryAccommodations.length){
var courseToCheck = new Array();
// find which course have a problem
var accommodations = this.accommodations.getCompletedAccommodations();
for (var i = 0; i < validCourses.length; i++) {
if (validCourses[i].getCourseDetails().type != 'optional' && validCourses[i].getCourseDetails().accommodationMandatory == true) {
var courseDetails = validCourses[i].getCourseDetails();
var isOk = false;
for(var j = 0; j < accommodations.length; j++){
if(accommodations[j].getIsAttachedToCourse() && accommodations[j].getAttachedToCourse().courseId == courseDetails.id){
isOk = true;
}
}
if(!isOk){
courseToCheck.push(validCourses[i]);
}
}
}
if(courseToCheck.length){
if(courseToCheck[0].getCourseDetails().type == "variableDate"){
var durations = courseToCheck[0]._schoolDurationList.getValidListItems();
for(var i = 0; i < durations.length; i++){
if(parseInt(durations[i].getValue()) > courseToCheck[0].getCourseDuration()){
durations[i].getHtml().fireEvent('click');
break;
}
}
if(i == durations.length){
courseToCheck[0]._deleteButton.fireEvent('click');
}
}else{
courseToCheck[0]._deleteButton.fireEvent('click');
}
}
}
}
},
/**
* Return the school accommodations object
*
* @return SchoolAccommodations the school accommodations object
*/
getAccommodations : function() {
return this.accommodations;
},
/**
* Return the school course object
*
* @return SchoolCourses the school courses object
*/
getCourses : function() {
return this.courses;
},
/**
* Returns the accommodation base start date
*
* @return Date The accommodations start date
*/
getAccommodationStartDate : function() {
return this.courses.getAccommodationStartDate();
},
/**
* Returns the end date of the accommodation
*
* @return Date The end date of the accommodation
*/
getAccommodationEndDate : function() {
return this.courses.getAccommodationEndDate();
},
/**
* Return the max accommodation end date for a course
*
* @param integer courseId The Course ID
* @param Date startDate the course start date
* @param SchoolAccommodationObject accommodation The accommodation
*
* @return Date The course accommodation end date
*/
getCourseAccommodationEndDate : function(courseId, startDate, accommodation) {
var course = this.courses.getAddedCourses().filter(function(item) {
return item.getCourseDetails().id == courseId && item.getCourseStartDate().getTime() == startDate.getTime();
});
if (course.length) {
var endDate = (new Date()).fromIso(course[0].getDTO().endDate);
var endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
while (endDateDay != accommodation.getAccommodationOptionDetails().accommodationEndDay) {
endDate.setDate(endDate.getDate() + 1);
endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
}
return endDate;
}
return false;
},
/**
* return true if the course is a fixed one type
*
* @param String coursePosition The position of the course -1 for the last one
*/
getIsFixedDateCourse : function(coursePosition) {
var courses = this.courses.getCompletedCourses();
if (courses.length) {
switch (coursePosition) {
case -1 :
return courses.getLast().getIsFixedCourse();
break;
default :
if (courses[coursePosition]) {
return courses[coursePosition].getIsFixedCourse();
} else {
return null;
}
break;
}
}
},
/**
*  Return the courses end date
*
* @return Date the courses end date
*
*/
getCoursesEndDate : function() {
var completedCourses = this.courses.getCompletedCourses();
if (completedCourses.length) {
var endDate = completedCourses[0].getDTO().endDate;
for (var i = 0; i < completedCourses.length; i++) {
if (completedCourses[i].getDTO().endDate > endDate) {
endDate = completedCourses[0].getDTO().endDate;
}
}
return endDate;
}
return null;
},
/**
* This method returns the number of completed courses
*
* @return Number The number of courses completed
*
*/
getCompletedCourses : function() {
return this.courses.getCompletedCourses();
},
/**
*  Returns the available accommodations
*
* @return Array of integer The Accommodation IDs
*/
getAvailableAccommodations : function() {
return this.courses.getAvailableAccommodations();
},
/**
* This method returns the completed accommodations
*
* @return SchoolAccommodationObject[] The completed accommodations
*
*/
getCompletedAccommodations : function() {
return this.accommodations.getCompletedAccommodations();
},
/**
* This method returns the number of completed transfers
*
* @return Number The number of transfers completed
*
*/
getCompletedTransfers : function() {
return this.transfers.getCompletedTransfers();
},
/**
* Returns the number of participant
*
* @return Number The number of participants
*
*/
getParticipants : function() {
return this.getParent().getParticipants();
},
/**
* Return an array containing the mandatory accommodations with their start and end date
*
* @return Array of MandatoryAccommodationsDTO
*/
getMandatoryAccommodations : function() {
return this.courses.getMandatoryAccommodations();
},
/**
* Return true if the transfer is mandatory
*
* @return boolean true if the transfers are mandatory
*/
getIsTransferMandatory : function() {
return this.courses.getIsTransferMandatory();
},
/**
* Return an array containing the available transfers
*
* @return Array of transfers ID
*/
getAvailableTransfers : function() {
return this.accommodations.getAvailableTransfers();
},
/**
* This method return the list container
*
* @return Element The element containing the lists
*/
getListContainer : function() {
return this.getParent()._listContainer;
},
/**
* This function set the same height for the column
*
* @param Element column1 The first column
* @param Element column2 The second column
*/
setSameColumnSize : function(column1, column2) {
this.getParent().setSameColumnSize(column1, column2);
},
/**
* Returns the  parent
*
* @return Object the parent
*
*/
getParent : function() {
return this._parent;
},
/**
*  This method return the localized dateFormat
*
*  @return String The localized date format
*/
getDateFormat : function() {
return this.getParent().getDateFormat();
},
/**
*  This method return the localized month translations
*
*  @return String[] The localized month translations
*/
getMonthTranslations : function() {
return this._translateDTO.months;
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @event Event deleteAccommodation This event is fired when a course is deleted
*
* @param AccommodationListItemDTO accommodationDetails The object containing the accommodation informations
* @param AccommodationListItemDTO accommodationOptionDetails The object containing the accommodation options informations
* @param Object translateDTO The object containing all the translations for this class
* @param SchoolCourses parent The parent
*
**/
var SchoolAccommodationObject = Events.extend({
/**
* This is the initialization function
*/
initialize : function(accommodationDetails, accommodationOptionDetails, translateDTO, classNamePrefix, oSchoolAccommodationsContainer) {
this._translateDTO = translateDTO;
this._accommodationDetails = accommodationDetails;
this._accommodationOptionDetails = accommodationOptionDetails;
this._schoolAccommodationsContainer = oSchoolAccommodationsContainer;
this._classNameBase = classNamePrefix;
this._listContainer = this._schoolAccommodationsContainer.getSchool().getListContainer();
this._dateFormat = this._schoolAccommodationsContainer.getSchool().getDateFormat();
this._monthsTranslations = this._schoolAccommodationsContainer.getSchool().getMonthTranslations();
this._accommodationStartDate = null;
this._accommodationEndDate = null;
this._accommodationDuration = null;
this._accommodationAttachedToCourse = null;
this._validStartDates = new Array();
this._manager = this._schoolAccommodationsContainer.getSchool().getParent();
this._manager.addEvent('descriptionsUpdated', function() {
this.updateDescriptions();
}.bind(this));
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Object The informations needed to calculate the price
*/
getDTO : function() {
var accommodationDTO = new Object();
accommodationDTO.id = this._accommodationOptionDetails.id;
accommodationDTO.startDate = this._accommodationStartDate.toIso();
accommodationDTO.endDate = this._accommodationEndDate.toIso();
return accommodationDTO;
},
/**
* Return the accommodation details DTO
*
* @return AccommodationDetailsDTO The Accommodation details
*/
getAccommodationDetails : function() {
return this._accommodationDetails;
},
/**
* Populate the accommodation from the given DTO
*
*
* @param AccommodationDTO toPopulateDTO The DTO to populate from
*/
populateFromDTO : function(toPopulateDTO) {
this._accommodationEndDate = (new Date()).fromIso(toPopulateDTO.endDate);
this._accommodationStartDate = (new Date()).fromIso(toPopulateDTO.startDate);
this._startDateValue.setHTML(this._accommodationStartDate.format(this._dateFormat, this._monthsTranslations));
this._accommodationDuration = Math.round((this._accommodationEndDate - this._accommodationStartDate) / (1000 * 60 * 60 * 24 * 7));
if (this._accommodationDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace('%0', this._accommodationDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._accommodationDuration));
}
this._accommodationEndDate = this.getCalculatedEndDate();
this._endDateValue.setHTML(this._accommodationEndDate.format(this._dateFormat, this._monthsTranslations));
},
/**
* set The accommodations start date for the given accommodation
*
* @param Date startDate The Start date
*/
setAttachedAccommodationStartDate : function(startDate) {
this._accommodationStartDate = startDate;
this._startDateValue.setHTML(this._accommodationStartDate.format(this._dateFormat, this._monthsTranslations));
},
/**
* set The accommodations duration for the given accommodation
*
* @param integer duration The duration
*/
setAttachedAccommodationDuration : function(duration) {
this._accommodationDuration = duration;
if (this._accommodationDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace('%0', this._accommodationDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._accommodationDuration));
}
this._accommodationEndDate = this.getCalculatedEndDate();
this._endDateValue.setHTML(this._accommodationEndDate.format(this._dateFormat, this._monthsTranslations));
},
/**
* Generate the html structure of the accommodation
*/
createVisualAccommodation : function(attachedAccommodation) {
this._container = new Element('div', {'class': this._classNameBase + 'ItemAdded'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Item-Title'});
this._subTitle = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle'});
this._moreInfo = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle MoreInfos'});
this._moreInfo.setStyle('display','none');
this._startDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-StartDate-Container'});
this._endDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-EndDate-Container'});
this._startDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._startDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._endDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._endDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._durationContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-Duration-Container'});
this._duration = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._durationValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._deleteButton = new Element('div', {'class': this._classNameBase + 'Section-Item-DeleteButton'});
this._duration.injectInside(this._durationContainer);
this._durationValue.injectInside(this._durationContainer);
this._startDate.injectInside(this._startDateContainer);
this._startDateValue.injectInside(this._startDateContainer);
this._endDate.injectInside(this._endDateContainer);
this._endDateValue.injectInside(this._endDateContainer);
this._title.injectInside(this._container);
this._subTitle.injectInside(this._container);
this._moreInfo.injectInside(this._container);
var element = new Element('div').injectInside(this._container);
element.setStyle('clear','both');
this._startDateContainer.injectInside(this._container);
this._endDateContainer.injectInside(this._container);
this._durationContainer.injectInside(this._container);
this._deleteButton.injectInside(this._container);
var element = new Element('div',{'style':'clear:both'}).injectInside(this._container);
element.setStyle('clear','both');
this._title.setHTML(this._accommodationDetails.name);
if(this._accommodationOptionDetails.noAccommodation){
this._subTitle.setStyle('display','none');
}else{
this._subTitle.removeAttribute('style');
}
this._subTitle.setHTML(this._accommodationOptionDetails.name);
this._moreInfo.setHTML(this._translateDTO.moreInfos);
this._startDate.setHTML(this._translateDTO.startDate);
this._startDateValue.setHTML(this._translateDTO.dateSelect);
this._endDate.setHTML(this._translateDTO.endDate);
this._endDateValue.setHTML(this._translateDTO.endDateValue);
this._duration.setHTML(this._translateDTO.duration);
this._durationValue.setHTML(this._translateDTO.durationSelect);
this._deleteButton.setHTML(this._translateDTO.deleteButton);
// add event listener
this._deleteButton.addEvent('click', function(e) {
this.removeAccommodation();
this.fireEvent('deleteAccommodation');
}.bind(this));
this.updateDescriptions();
this._accommodationOptionsList = new SchoolList(this._title, this._classNameBase);
this.getVisualAccommodation(this._accommodationOptionsList);
this._accommodationOptionsList.getHtml().injectInside(this._listContainer);
this._accommodationOptionsList.initializeEvents();
this._accommodationStartDatesList = new SchoolList(this._startDateValue, this._classNameBase);
this.getVisualStartDates(this._accommodationStartDatesList);
this._accommodationStartDatesList.getHtml().injectInside(this._listContainer);
this._accommodationStartDatesList.initializeEvents();
this._accommodationDurationsList = new SchoolList(this._durationValue, this._classNameBase);
this.getVisualDurations(this._accommodationDurationsList);
this._accommodationDurationsList.getHtml().injectInside(this._listContainer);
this._accommodationDurationsList.initializeEvents();
// if it is the first to be added, set the right date
if (this._schoolAccommodationsContainer.getAccommodations().length == 1 && !attachedAccommodation) {
// find the earliest start date
var startDate;
for(var i = 0 ; i <  this._accommodationStartDatesList.getListItems().length; i++){
if(this._accommodationStartDatesList.getListItems()[i].getIsSelectionnable()){
startDate = this._accommodationStartDatesList.getListItems()[i].getValue();
break;
}
}
if (startDate) {
this._accommodationStartDate = startDate;
this.refreshVisualDurations(this._accommodationDurationsList);
// find the longest duration
var duration;
for (var i = this._accommodationDurationsList.getListItems().length - 1; i >= 0; i--) {
var listItem = this._accommodationDurationsList.getListItems()[i];
if (listItem.getIsSelectionnable()) {
duration = parseInt(listItem.getValue());
break;
}
}
if (duration) {
this._accommodationStartDate = null;
this.refreshAccommodationData(startDate, duration, null);
}
}
}
},
updateDescriptions : function(){
if (this._manager.getDescription && this._manager.getDescription('accommodation', this._accommodationDetails.accommodationType) && this._manager.getDescription('accommodation', this._accommodationDetails.accommodationType) != '') {
this._moreInfo.setAttribute('title', this._accommodationDetails.name + ' :: ' + this._manager.getDescription('accommodation', this._accommodationDetails.accommodationType));
this._moreInfo.setStyle('display','');
if(!this._descriptionToolTip ){
this._descriptionToolTip = new SynergeeTips(this._moreInfo, {'className':'PriceEstimationToolTip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}else {
this._descriptionToolTip.build(this._moreInfo);
}
}else {
this._moreInfo.setStyle('display','none');
}
},
/**
* Returns the html view of this accommodation
*
* @return Element the html view of this accommodation
*/
getHtml : function() {
return this._container;
},
/**
* Generate the list for the possible durations of this accommodation
*
* @param SchoolList The duration list
*/
getVisualDurations : function(list) {
list.clear();
var index = 0;
var durations = this.getDurations();
durations.each(function(item, index) {
list.addItem(item, this._translateDTO.weeks.replace('%0', item));
index = list.getListItems().indexOf(list.getListItems().getLast());
list.getListItems().getLast().getHtml().addEvent('click', function(e) {
if (list.getListItems()[index].getIsSelectionnable())this.refreshAccommodationData(this._accommodationStartDate, item, this._accommodationEndDate);
}.bind(this));
}.bind(this));
this.refreshVisualDurations(list);
},
/**
* Refresh the list for the possible durations of this accommodation
*
* @param SchoolList The duration list
*/
refreshVisualDurations : function(list) {
var firstValid = true;
var validDurations = this._schoolAccommodationsContainer.getAccommodationValidDuration(this, list);
list.getListItems().each(function(item, index) {
if (validDurations.contains(parseInt(item.getValue()))) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (firstValid)list.setSelectedItem(item);
if (this._accommodationDuration == item.getValue()) {
list.setSelectedItem(item);
}
firstValid = false;
} else {
if (item.getValue == 'error')item.setIsValid(false);
item.setIsSelectionnable(false);
}
}.bind(this));
},
/**
* Generate the list of possible startdates
*
* @param Array list The list of possible startdates
*/
getVisualStartDates : function(list) {
// clearing the list
list.clear();
var startDates = this.getStartDates();
var index = 0;
startDates.each(function(item, index) {
list.addItem(item, item.format(this._dateFormat, this._monthsTranslations));
// Adding the events on the buttons
index = list.getListItems().indexOf(list.getListItems().getLast());
list.getListItems().getLast().getHtml().addEvent('click', function() {
if (list.getListItems()[index].getIsSelectionnable())this.refreshAccommodationData(item, this._accommodationDuration, this._accommodationEndDate);
}.bind(this));
}.bind(this));
this.refreshVisualStartDates(list);
},
/**
* Refresh the list of possible startdates
*
* @param Array list The list of possible startdates
*/
refreshVisualStartDates : function(list) {
var firstValid = true;
this._validStartDates = this._schoolAccommodationsContainer.getAccommodationValidStartDates(this, list);
list.getListItems().each(function(item, index) {
if (this._validStartDates.contains(item.getValue())) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (firstValid)list.setSelectedItem(item);
if (this._accommodationStartDate == item.getValue()) {
list.setSelectedItem(item);
}
firstValid = false;
} else {
if (item.getValue == 'error')item.setIsValid(false);
item.setIsSelectionnable(false);
}
}.bind(this));
},
/**
* Generate the accommodations list
*
* @param SchoolList list The list we want to refresh
*
*/
getVisualAccommodation : function(list) {
list.clear();
// Get the school accommodations informations to create the list
this._schoolAccommodationsContainer.getSchoolAccommodationsDTO().each(function(SectionItem, index) {
var section = SectionItem;
var sectionId = parseInt(SectionItem.id);
var value = new Object();
value.type = 'category';
value.sectionId = sectionId;
list.addItem(value, SectionItem.name);
list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item-Category');
// for each accommodation options in the accommodation section
SectionItem.option.each(function(item, index) {
item.parentId = sectionId;
list.addItem(item, item.name);
list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item-Accommodation');
// add the event on the option button
list.getListItems().getLast().getHtml().addEvent('click', function(e) {
this.setAccommodation(section, item);
}.bind(this));
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.notAvailable);
if (this._schoolAccommodationsContainer.getSchool().getCompletedCourses().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
this.refreshVisualAccommodation(list);
},
/**
* Refresh the accommodations list
*
* @param SchoolList list The list we want to refresh
*
*/
refreshVisualAccommodation : function(list) {
var availableAccommodations = this._schoolAccommodationsContainer.getAvailableAccommodations();
var accommodationStartDates = this.createStartDatesList();
var accommodationEndDate = this._schoolAccommodationsContainer.getAccommodationEndDate();
list.getListItems().each(function(item, index) {
if (availableAccommodations.contains(item.getValue().parentId) && this._schoolAccommodationsContainer.getDurationInWeeks(accommodationEndDate, accommodationStartDates[0]) >= item.getValue().minimumDurationInWeeks
&& this._schoolAccommodationsContainer.getSchool().getParticipants() >= item.getValue().minimumNumberOfPeople) {
item.setIsValid(true);
item.setIsSelectionnable(true);
} else {
if (!availableAccommodations.contains(item.getValue().sectionId) || item.getValue().type != 'category' || this._schoolAccommodationsContainer.getSchool().getCompletedCourses().length == 0) {
item.setIsValid(false);
} else {
item.setIsValid(true);
}
}
}.bind(this));
if (this._schoolAccommodationsContainer.getSchool().getCompletedCourses().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Replace an accommodation with another one
*
* @param Object accommodation The new accommodation DTO
* @param Object accommodationOption The new accommodation options DTO
*/
setAccommodation : function(accommodationSection, accommodationOption) {
// set the new accommodation informations
this._accommodationDetails = accommodationSection;
this._accommodationOptionDetails = accommodationOption;
// set the new title and subtitle
this._title.setHTML(this._accommodationDetails.name);
this._subTitle.setHTML(this._accommodationOptionDetails.name);
if(this._accommodationOptionDetails.noAccommodation){
this._subTitle.setStyle('display','none');
}else{
this._subTitle.removeAttribute('style');
}
this._title.removeEvents('click');
this._startDateValue.removeEvents('click');
this._durationValue.removeEvents('click');
this._accommodationOptionsList.deleteList();
this._accommodationStartDatesList.deleteList();
this._accommodationDurationsList.deleteList();
this.updateDescriptions();
this._accommodationOptionsList = new SchoolList(this._title, this._classNameBase);
this.getVisualAccommodation(this._accommodationOptionsList);
this._accommodationOptionsList.getHtml().injectInside(this._listContainer);
this._accommodationOptionsList.initializeEvents();
this._accommodationStartDatesList = new SchoolList(this._startDateValue, this._classNameBase);
this.getVisualStartDates(this._accommodationStartDatesList);
this._accommodationStartDatesList.getHtml().injectInside(this._listContainer);
this._accommodationStartDatesList.initializeEvents();
this._accommodationDurationsList = new SchoolList(this._durationValue, this._classNameBase);
this.getVisualDurations(this._accommodationDurationsList);
this._accommodationDurationsList.getHtml().injectInside(this._listContainer);
this._accommodationDurationsList.initializeEvents();
this.refreshAccommodationLists();
// we ask the parent to check if the other accommodations are ok
this._schoolAccommodationsContainer.checkAccommodations(this);
// and the fireAnEvent to the parent to refresh the accommodations
this._schoolAccommodationsContainer.fireEvent('refreshAccommodations');
},
/**
* Refresh the accommodation data and the visual of the accommodation
*
* @param Date startDate The new StartDate
* @param Number duration The new Duration
* @param Date endDate The new endDate
*
*/
refreshAccommodationData : function(startDate, duration, endDate) {
// if the endDate is modified and the startDate has to be calculated
if (startDate == this._accommodationStartDate && endDate != this._accommodationEndDate) {
this._accommodationDuration = duration;
this._accommodationEndDate = endDate;
// calculation of the new startDate
var startDateIndex = 0;
var startDates = this.getStartDates();
startDates.filter(function(item, index) {
if (item.toString() == this._accommodationEndDate.toString()) {
startDateIndex = index;
return index;
}
}.bind(this));
startDateIndex = startDateIndex - this._accommodationDuration;
if (startDateIndex < 0) startDateIndex = 0;
this._accommodationStartDate = startDates[startDateIndex];
} else {
// If the startDate and the duration are modified, the endDate has to be calculated
if (startDate != this._accommodationStartDate && duration != this._accommodationDuration) {
this._accommodationStartDate = startDate;
this._accommodationDuration = duration;
this._accommodationEndDate = this.getCalculatedEndDate();
// else if there is only the startDate modified
} else {
if (startDate != this._accommodationStartDate) {
this._accommodationStartDate = startDate;
// if it is a new accommodation with no data, these are set based on the previous accommodation
if (this._accommodationDuration == null) {
var startDate = new Date(this._accommodationStartDate).setDate(this._accommodationStartDate.getDate() + this._accommodationOptionDetails.minimumDurationInWeeks * 7);
// if the accommodationstart + minimum weeks date is before the previous end date
if (startDate < this._schoolAccommodationsContainer.getPreviousEndDate(this)) {
this._accommodationEndDate = this._schoolAccommodationsContainer.getPreviousEndDate(this);
} else {
this._accommodationEndDate = this.getEndDate();
}
// the duration is calculated
this._accommodationDuration = this._schoolAccommodationsContainer.getDurationInWeeks(this._accommodationEndDate, this._accommodationStartDate);
} else {
// else (the course is already complete) the end date is calculated normally
this._accommodationEndDate = this.getCalculatedEndDate();
}
} else {
// or only the duration
if (duration != this._accommodationDuration) {
this._accommodationDuration = duration;
this._accommodationEndDate = this.getCalculatedEndDate();
}
}
}
}
if(this._accommodationStartDate)this._startDateValue.setHTML(this._accommodationStartDate.format(this._dateFormat, this._monthsTranslations));
if (this._accommodationDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace('%0', this._accommodationDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._accommodationDuration));
}
if(this._accommodationEndDate)this._endDateValue.setHTML(this._accommodationEndDate.format(this._dateFormat, this._monthsTranslations));
// the parent is asked to check if the other accommodations are ok
this._schoolAccommodationsContainer.checkAccommodations(this);
if(this._startDate)  this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
if(this._duration)  this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
// and the fireAnEvent to the parent to refresh the accommodations
this._schoolAccommodationsContainer.fireEvent('refreshAccommodations');
},
/**
* Refresh the lists for this accommodation
*/
refreshAccommodationLists : function() {
this.refreshVisualAccommodation(this._accommodationOptionsList);
this.refreshVisualStartDates(this._accommodationStartDatesList);
this.refreshVisualDurations(this._accommodationDurationsList);
if (!this._accommodationAttached) {
// check if the buttons must be activated or not
if (this._accommodationStartDatesList.getValidListItems().length == 1 && this.getIsAttachedToCourse()) {
this._startDateValue.addClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
this._accommodationStartDatesList.removeButtonEvent();
if (this._accommodationStartDate != this._accommodationStartDatesList.getValidListItems()[0].getValue())this._accommodationStartDatesList.getValidListItems()[0].getHtml().fireEvent('click');
} else {
this._startDateValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._accommodationStartDatesList.addButtonEvent();
}
if (this._accommodationDurationsList.getValidListItems().length == 1) {
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
this._accommodationDurationsList.removeButtonEvent();
if (parseInt(this._accommodationDuration) != parseInt(this._accommodationDurationsList.getValidListItems()[0].getValue()))this._accommodationDurationsList.getValidListItems()[0].getHtml().fireEvent('click');
} else {
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._accommodationDurationsList.addButtonEvent();
}
}
},
/**
* Delete and generate the lists for this accommodation
*
*/
reGenerateAccommodationLists : function() {
if (this._accommodationStartDatesList._listItems.length) {
this._accommodationStartDatesList.getHtml().remove();
this._accommodationStartDatesList.clear();
}
if (this._accommodationDurationsList._listItems.length) {
this._accommodationDurationsList.getHtml().remove();
this._accommodationDurationsList.clear();
}
if (this._accommodationOptionsList._listItems.length) {
this._accommodationOptionsList.getHtml().remove();
this._accommodationOptionsList.clear();
}
this.getVisualAccommodation(this._accommodationOptionsList);
this._accommodationOptionsList.getHtml().injectInside(this._listContainer);
this._accommodationOptionsList.initializeEvents();
this.getVisualStartDates(this._accommodationStartDatesList);
this._accommodationStartDatesList.getHtml().injectInside(this._listContainer);
this.getVisualDurations(this._accommodationDurationsList);
this._accommodationDurationsList.getHtml().injectInside(this._listContainer);
if (!this.getIsAttachedToCourse()) {
this._accommodationStartDatesList.initializeEvents();
this._accommodationDurationsList.initializeEvents();
}
},
/**
* Returns an array of startDates
*
* @return Array An array of Dates
*/
getStartDates : function() {
var startDates = this.createStartDatesList();
return startDates;
},
/**
* Generate the start dates list
*/
createStartDatesList : function() {
var startDatesList = new Array();
var startDate = this._schoolAccommodationsContainer.getSchool().getAccommodationStartDate();
var endDate = this._schoolAccommodationsContainer.getSchool().getAccommodationEndDate();
// if the first course is not a fixed one
if (!this._schoolAccommodationsContainer.getSchool().getIsFixedDateCourse(0)) {
var day = startDate.getDay();
if (day == 0)day = 7;
if (this.getAccommodationOptionDetails().accommodationStartDay > 0) {
while (this.getAccommodationOptionDetails().accommodationStartDay != day) {
startDate.setDate(startDate.getDate() - 1);
day = startDate.getDay();
if (day == 0)day = 7;
}
}
}
// if the last course is not a fixed one
if (!this._schoolAccommodationsContainer.getSchool().getIsFixedDateCourse(-1)) {
var endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
if (this.getAccommodationOptionDetails().accommodationEndDay > 0) {
while (endDateDay != this.getAccommodationOptionDetails().accommodationEndDay) {
endDate.setDate(endDate.getDate() + 1);
endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
}
}
endDate.setDate(endDate.getDate() - 7* this.getAccommodationOptionDetails().minimumDurationInWeeks + 3);
}
while (startDate < endDate) {
startDatesList.push(new Date(startDate));
startDate.setDate(startDate.getDate() + 7);
}
return startDatesList;
},
/**
* Returns the endDate
*
* @return Date The end date
*/
getEndDate : function() {
var endDate = this._schoolAccommodationsContainer.getAccommodationEndDate(this);
var endDay = parseInt(this.getAccommodationOptionDetails().accommodationEndDay);
if(endDay == 7)endDay = 0;
while(endDay != endDate.getDay()){
endDate.setDate(endDate.getDate() + 1);
}
return endDate;
},
/**
* Returns the possible durations
*
* @return Array An array of possible durations
*/
getDurations : function() {
var durations = new Array();
var minDuration = parseInt(this.getAccommodationOptionDetails().minimumDurationInWeeks);
var maxDuration = this._schoolAccommodationsContainer.getDurationInWeeks(this.getEndDate(), this._accommodationStartDatesList.getListItems()[0].getValue());
for (var i = minDuration; i <= maxDuration; i++) {
durations.push(i);
}
return durations;
},
/**
* Return the endDate for an accommodation with its startDate and duration
*
* @return Date The accommodation end date.
*/
getCalculatedEndDate : function() {
var endDate = new Date(this._accommodationStartDate);
endDate.setDate(endDate.getDate() - 3 + this._accommodationDuration * 7);
var endDay = parseInt(this.getAccommodationOptionDetails().accommodationEndDay);
if(endDay == 7)endDay = 0;
while(endDay != endDate.getDay()){
endDate.setDate(endDate.getDate() + 1);
}
if (endDate > this.getEndDate()) {
endDate = this.getEndDate();
this._accommodationEndDate = endDate;
this._accommodationDuration = this._schoolAccommodationsContainer.getDurationInWeeks(this._accommodationEndDate, this._accommodationStartDate);
if (this._accommodationDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace('%0', this._accommodationDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._accommodationDuration));
}
}
return endDate;
},
/**
* Returns true if all the accommodation informations are complete
*
* @return Boolean Return true if all the accommodation informations are completed
*/
isComplete : function() {
if (this._accommodationDuration && this._accommodationStartDate && this._accommodationEndDate) {
return true;
} else {
return false;
}
},
/**
* Returns the accommodation Start date
*
* @return Date The accommodation start date
*/
getAccommodationStartDate : function() {
return this._accommodationStartDate;
},
/**
* Returns the accommodation end date
*
* @return Date The accommodation end date
*/
getAccommodationEndDate : function() {
return this._accommodationEndDate;
},
/**
* Returns the accommodation duration
*
* @return Number The accommodation duration
*/
getAccommodationDuration : function() {
return this._accommodationDuration;
},
/**
* Returns an object containing the accommodation option details
*
* @return object The accommodation option details
*/
getAccommodationOptionDetails : function() {
return this._accommodationOptionDetails;
},
/**
* set the accommodations attached to a course
*
* @param isAttached CourseDetailDTO The course to attach to
*/
setIsAttachedToCourse : function(isAttached) {
this._accommodationAttached = isAttached;
if (this._accommodationAttached) {
this._deleteButton.setStyle('display', 'none');
if (this._accommodationStartDatesList.getButtonEventInitialized()) {
this._accommodationStartDatesList.removeButtonEvent();
}
if (this._accommodationDurationsList.getButtonEventInitialized()) {
this._accommodationDurationsList.removeButtonEvent();
}
this._startDateValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._durationValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-ValueNotEditable');
} else {
this._deleteButton.setStyle('display', 'block');
if (!this._accommodationStartDatesList.getButtonEventInitialized()) {
this._accommodationStartDatesList.addButtonEvent();
}
if (!this._accommodationDurationsList.getButtonEventInitialized()) {
this._accommodationDurationsList.addButtonEvent();
}
this._startDateValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-Value');
this._durationValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-Value');
}
},
/**
* set the accommodations attached to a course
*
* @param course CourseDetailDTO The course to attach to
*/
setAttachedToCourse : function(course) {
this._accommodationAttachedToCourse = course;
},
/**
* set the accommodations attached to a course
*
* @return CourseDetailDTO The course details attached to this accommodation
*/
getAttachedToCourse : function() {
return this._accommodationAttachedToCourse;
},
/**
* set the accommodations attached to a course
*
* @return CourseDetailDTO The course details attached to this accommodation
*/
getIsAttachedToCourse : function() {
return this._accommodationAttached;
},
/**
* return the valid start dates for this accommodation
*
* @return Array of valid start dates
*/
getValidStartDates : function() {
return this._validStartDates;
},
/**
* Returns the parent
*
* @return SchoolAccommodations The parent
*/
getParent : function() {
return this._schoolAccommodationsContainer;
},
/**
* Remove the accommodation from the list
*/
removeAccommodation : function() {
this._accommodationDurationsList.deleteList();
this._accommodationStartDatesList.deleteList();
if(this._container.getParent())this._container.remove();
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
*
* @param AccommodationListItemDTO schoolAccommodationsDTO The DTO containing all the accommodations informations
* @param Object translateDTO The DTO containing all the translations for this class
* @param Element eListContainer The list container
* @param School oSchool The school
**/
var SchoolAccommodations = Events.extend({
/**
* This is the initialization function
*/
initialize : function(schoolAccommodationsDTO, translateDTO, eListContainer, oSchool) {
this._schoolAccommodationsDTO = schoolAccommodationsDTO;
this._translateDTO = translateDTO;
this._accommodations = new Array();
this._school = oSchool;
this._listContainer = eListContainer;
this._classNameBase = this._school.getClassNameBase();
this.addEvent('refreshAccommodations', function(item, index) {
this.refreshAccommodations();
}.bind(this));
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Array The informations needed to calculate the price
*/
getDTO : function() {
var accommodationsDTO = new Array();
this._accommodations.each(function(item, index) {
if (item.isComplete()) {
accommodationsDTO.push(item.getDTO());
}
});
return accommodationsDTO;
},
/**
* Populate the accommodation from a dto
*
* @param Array toPopulateDTO The accommodations to add
*/
populateFromDTO : function(toPopulateDTO) {
var accommodations = new Array();
if (toPopulateDTO) {
toPopulateDTO.each(function(item, index) {
// check
this._schoolAccommodationsDTO.each(function(accommodationItem, accommodationIndex) {
var accommodationToAdd = accommodationItem.option.filter(function(optionItem, optionIndex) {
return optionItem.id == item.id;
});
if (accommodationToAdd[0]) {
accommodationToAdd[0].parentId = accommodationItem.id;
accommodationToAdd[0].dto = item;
accommodations.push(accommodationToAdd[0]);
}
}.bind(this));
}.bind(this));
}
if (accommodations.length) {
for (var i = 0; i < accommodations.length; i++) {
this.addAccommodation(accommodations[i].parentId, accommodations[i].id);
if (this._accommodations.length)this._accommodations.getLast().populateFromDTO(accommodations[i].dto);
}
}
},
/**
*  Return the classNameBase
*/
getClassNameBase : function() {
return this._classNameBase;
},
/**
* Returns the visual accommodation container
*/
getHtml : function() {
this._accommodationContainer = new Element('div', {'class': this._classNameBase + 'Section' + ' ' + this._classNameBase2 + 'Section'});
this._accommodationTitle = new Element('div', {'class': this._classNameBase + 'Section-Title' + ' ' + this._classNameBase2 + 'Section-Title'});
this._accommodationListContainer = new Element('div', {'class': this._classNameBase + 'Courses-CoursesList-Container' + ' ' + this._classNameBase2 + 'Courses-CoursesList-Container'});
this._accommodationUserAccommodationList = new Element('div', {'class': this._classNameBase + 'Courses-UserCoursesList' + ' ' + this._classNameBase2 + 'Courses-UserCoursesList'});
this._accommodationAddButton = new Element('div', {'class': this._classNameBase + 'AddButton' + ' ' + this._classNameBase2 + 'AddButton'});
this._accommodationTitle.injectInside(this._accommodationContainer);
this._accommodationListContainer.injectInside(this._accommodationContainer);
this._accommodationUserAccommodationList.injectInside(this._accommodationListContainer);
this._accommodationAddButton.injectInside(this._accommodationContainer);
this._accommodationTitle.setHTML(this._translateDTO.title);
this._accommodationAddButton.setHTML(this._translateDTO.add);
this.accommodationsList = new SchoolList(this._accommodationAddButton, this._classNameBase);
this.getVisualAccommodationList(this.accommodationsList, this.addAccommodationEventFunction);
this.refreshVisualAccommodationList(this.accommodationsList);
this.accommodationsList.getHtml().injectInside(this._listContainer);
this.accommodationsList.initializeEvents();
var displayAccommodations = false;
for(var i = 0; i < this._schoolAccommodationsDTO.length; i++){
if(this._schoolAccommodationsDTO[i].option.length){
displayAccommodations = true;
}
}
if(!displayAccommodations){
this._accommodationContainer.setStyle('display', 'none');
}
return this._accommodationContainer;
},
/**
* Generate the accommodation list
*
* @param SchoolList list The list to refresh
*
*/
getVisualAccommodationList : function(list, eventFunction, context) {
if(!context) context = this;
// clearing the list
list.clear();
this._schoolAccommodationsDTO.each(function(item, index) {
var sectionId = parseInt(item.id);
var value = new Object();
value.type = 'category';
value.sectionId = sectionId;
list.addItem(value, item.name);
list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item-Category');
list.getListItems().getLast().getHtml().addClass(this._classNameBase2 + 'List-Item-Category');
item.option.each(function(item, index) {
item.parentId = sectionId;
var listItem = new SchoolListItem(item, item.name, this._classNameBase);
list.addListItem(listItem);
listItem.getHtml().addClass(this._classNameBase + 'List-Item-Accommodation');
listItem.getHtml().addClass(this._classNameBase2 + 'List-Item-Accommodation');
listItem.getHtml().addEvent('click', eventFunction.bind(context));
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.notAvailable);
if (this.getCompletedCourses().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
addAccommodationEventFunction : function(e){
e = new Event(e);
var listItem = e.target.listItemContainer;
if (listItem.getIsSelectionnable()) {
this.addAccommodation(listItem.getValue().parentId, listItem.getValue().id);
this._school.fireEvent('heightModified');
// refresh the accommodation, but not the shopping cart result price
this.refreshAccommodations(null, true);
}
},
/**
* Refresh the accommodation list
*
* @param SchoolList list The list to refresh
*
*/
refreshVisualAccommodationList : function(list) {
var availableAccommodations = this.getAvailableAccommodations();
var accommodationStartDate = this.getSchoolAccommodationStartDate();
var accommodationEndDate = this.getAccommodationEndDate();
list.getListItems().each(function(item, index) {
if (availableAccommodations.contains(item.getValue().parentId)) {
var startDate = new Date(accommodationStartDate);
var day = startDate.getDay();
if (day == 0)day = 7;
while (parseInt(item.getValue().accommodationStartDay) != day) {
startDate.setDate(startDate.getDate() - 1);
day = startDate.getDay();
if (day == 0)day = 7;
}
var endDate = new Date(accommodationEndDate);
var day = endDate.getDay();
if (day == 0)day = 7;
while (parseInt(item.getValue().accommodationEndDay) != day) {
endDate.setDate(endDate.getDate() + 1);
day = endDate.getDay();
if (day == 0)day = 7;
}
}
// if the accommodation is available, the duration is longer than the minimum duration of the accommodation and the number of participant is big enough
if (availableAccommodations.contains(item.getValue().parentId)
&& this.getDurationInWeeks(endDate, startDate) >= item.getValue().minimumDurationInWeeks
&& this.getSchoolParticipants() >= item.getValue().minimumNumberOfPeople) {
item.setIsSelectionnable(true);
} else {
// if the item is not a category,
if (item.getValue().type != 'category') {
item.setIsSelectionnable(false);
}
}
}.bind(this));
if (this.getCompletedCourses().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Add an accommodation
*
* @param Number id The accommodation ID
* @param Number optionID The accommodation Option ID
* @param Boolean attachedAccommodation True if the accommodation is attached (false by default)
*
* @return True if the accommodation is added
*/
addAccommodation : function(id, optionId, attachedAccommodation) {
var accommodationDetailsDTO = this._schoolAccommodationsDTO.copy();
// retrieve the course informations
accommodationDetailsDTO = accommodationDetailsDTO.filter(function(item, index) {
return item.id == id;
}.bind(this));
var accommodationOptionDetails = accommodationDetailsDTO[0].option.filter(function(item, index) {
return item.id == optionId;
}.bind(this));
var newAccommodation = new SchoolAccommodationObject(accommodationDetailsDTO[0], accommodationOptionDetails[0], this._translateDTO.accommodationObject, this._classNameBase ,this);
// if the accommodation has valid start dates it is added
if (newAccommodation.getStartDates().length) {
if(!attachedAccommodation)this._accommodations.push(newAccommodation);
newAccommodation.createVisualAccommodation(attachedAccommodation);
if(attachedAccommodation)this._accommodations.push(newAccommodation);
if(!newAccommodation.getHtml()){
return false;
}
newAccommodation.getHtml().injectInside(this._accommodationUserAccommodationList);
newAccommodation.addEvent('deleteAccommodation', function(e) {
this.deleteAccommodation(newAccommodation);
}.bind(this));
return true;
} else {
return false;
}
},
/**
* Refresh all the accommodations
*
* it is called when an accommodation or a course is modified
*
* @optionalparam String option The options - lists if the list have to be regenerated
* @optionalparam boolean noPriceRefresh True if the price should not be refreshed
*/
refreshAccommodations : function(option, noPriceRefresh) {
this.refreshVisualAccommodationList(this.accommodationsList);
// if an accomodation need more than the number of people selected, it's deleted
var accommodationModified = false;
for (var i = 0; i < this._accommodations.length; i++) {
if (this._accommodations[i].getAccommodationOptionDetails().minimumNumberOfPeople > this.getSchoolParticipants()) {
this._accommodations[i].removeAccommodation();
this._accommodations.remove(this._accommodations[i]);
accommodationModified = true;
i--;
}
}
if (accommodationModified) this._school.fireEvent('refreshPrice');
// if there are no more courses, all the accommodations are deleted
if (this.getCompletedCourses().length == 0) {
var accommodations = this._accommodations.length;
for (var i = 0; i < this._accommodations.length; i++) {
if (this._accommodations.length) {
this._accommodations[i].removeAccommodation();
this._accommodations.remove(this._accommodations[i]);
i--;
}
}
this.displayAddButton(false);
// and if there was any accommodations and there is no transfers, we send a refresh price (else the refresh price will be made by the school transfers)
if (accommodations && !this._school.getCompletedTransfers()) {
this._school.fireEvent('refreshPrice');
}
} else {
// getting the mandatory accommodations
var mandatoryAccommodations = this._school.getMandatoryAccommodations();
// checking if the there are no unavailable accommodation on the basket
var availableAccommodations = this.getAvailableAccommodations();
// remove the not authorized accommodations
for (var i = 0; i < this._accommodations.length; i++) {
if (!availableAccommodations.contains(parseInt(this._accommodations[i]._accommodationDetails.id))) {
this._accommodations[i].removeAccommodation();
this._accommodations.remove(this._accommodations[i]);
i--;
}
}
for (var i = 0; i < this._accommodations.length; i++) {
this._accommodations[i].setIsAttachedToCourse(false);
}
// if there are mandatory accommodations
if (mandatoryAccommodations.length) {
this.checkMandatoryAccomodations(mandatoryAccommodations);
}
// retrieve the max start and end date value (based on the courses and acommodation start day and end day)
var startDate = this.getAccommodationStartDate();
var endDate = this.getAccommodationEndDate();
if (this._accommodations.length && endDate < this._accommodations.getLast().getAccommodationEndDate()) {
var endDay = parseInt(this._accommodations.getLast().getAccommodationOptionDetails().accommodationEndDay);
if (endDay == 7)endDay = 0;
while (endDay != endDate.getDay()) {
endDate.setDate(endDate.getDate() + 1);
}
if (endDate < this._accommodations.getLast().getAccommodationEndDate()) {
// delete the accommodations that are beyond the end date
for (var i = this._accommodations.length - 1; i > 0; i--) {
if (this._accommodations[i].getAccommodationEndDate() > endDate) {
this._accommodations[i].removeAccommodation();
this.deleteAccommodation(this._accommodations[i]);
}
}
// if there are still accommodations the last one is adapted to fit the new dates
if (this._accommodations.length) {
var duration = this.getDurationInWeeks(endDate, this._accommodations.getLast().getAccommodationStartDate());
// if the new duration is smaller than the minimum
if (duration < this._accommodations.getLast().getAccommodationOptionDetails().minimumDurationInWeeks) {
duration = this._accommodations.getLast().getAccommodationOptionDetails().minimumDurationInWeeks;
// if it can't be adapted, it is deleted
if (this.getDurationInWeeks(endDate, startDate) < duration) {
this._accommodations.getLast().removeAccommodation();
this.deleteAccommodation(this._accommodations.getLast());
} else {
this._accommodations.getLast().refreshAccommodationData(this._accommodations.getLast().getAccommodationStartDate(), duration, endDate);
}
} else {
this._accommodations.getLast().refreshAccommodationData(this._accommodations.getLast().getAccommodationStartDate(), duration, endDate);
}
}
}
}
// if the new acomodation startDate is smaller than the old one
if (this._accommodations.length && startDate > this._accommodations[0].getAccommodationStartDate()
&& !this._accommodations[0].getIsAttachedToCourse()) {
for (var i = 0; i < this._accommodations.length; i++) {
if (this._accommodations[i].getAccommodationStartDate() < startDate) {
this._accommodations[i].removeAccommodation();
this.deleteAccommodation(this._accommodations[i]);
i--;
}
}
if (this._accommodations.length) {
var duration = this.getDurationInWeeks(this._accommodations[0].getAccommodationEndDate(), startDate);
if (duration < this._accommodations[0].getAccommodationOptionDetails().minimumDurationInWeeks) duration = this._accommodations[0].getAccommodationOptionDetails().minimumDurationInWeeks;
this._accommodations[0].refreshAccommodationData(startDate, duration, this._accommodations[0].getAccommodationEndDate());
}
}
// if the lists have to be generated again
if (option == 'lists') {
this._accommodations.each(function(item, index) {
if (!this._accommodations[0].getIsAttachedToCourse()) {
item.reGenerateAccommodationLists();
this.checkAccommodations(item);
}
}.bind(this));
} else {
this._accommodations.each(function(item, index) {
if (!this._accommodations[0].getIsAttachedToCourse()) {
item.refreshAccommodationLists();
this.checkAccommodations(item);
}
}.bind(this));
}
var refreshPrice = false;
if (this._accommodations.length == 1) {
noPriceRefresh = false;
}
for (var i = 0; i < this._accommodations.length; i++) {
if (this._accommodations[i].isComplete()) {
refreshPrice = true;
break;
}
}
if (!noPriceRefresh && refreshPrice) {
this._school.fireEvent('refreshPrice');
}
// check if the add button must be displayed or not
if((this.getCompletedCourses().length == mandatoryAccommodations.length
&& mandatoryAccommodations.length <= this._accommodations.length)
|| (this._accommodations.length && this._accommodations.getLast().getIsAttachedToCourse() == true
&& this._accommodations.getLast().getAttachedToCourse().courseId == this._school.getCourses().getValidAddedCourses().getLast().getCourseDetails().id)){
this.displayAddButton(false);
}else{
this.displayAddButton(true);
}
}
},
/**
* check if the mandatory accommodations are correctly added and displayed
*
* @param Array mandatoryAccommodations The mandatory accommodations list
* @optionalparam Integer notToAdd The accommodationOption id to not add
*
*/
checkMandatoryAccomodations : function(mandatoryAccommodations) {
// check each mandatory accommodations
for (var i = 0; i < mandatoryAccommodations.length; i++) {
// getting the accommodations informations to add
var accommodationsToAdd = this._schoolAccommodationsDTO.filter(function(item, index) {
return mandatoryAccommodations[i].ids.contains(parseInt(item.id));
});
// if there is a valid accommodation to add
if (accommodationsToAdd.length) {
var accommodationsAlreadyAdded = new Array();
// checking if the accommodation is already present
if (this._accommodations.length) {
this._accommodations.each(function(item, index) {
for (var j = 0; j < accommodationsToAdd.length; j++) {
if (item._accommodationDetails.id == accommodationsToAdd[j].id && !(item.getIsAttachedToCourse())) {
accommodationsAlreadyAdded.push(item);
}
}
}.bind(this));
}
// if there are no accommodation added
if (!accommodationsAlreadyAdded.length) {
var added = false;
var j = 0;
var k = 0;
while (!added) {
// find a valid accommodation to add in the list
if (j < accommodationsToAdd.length) {
// find the first valid accommodation option
if (k < accommodationsToAdd[j].option.length) {
this.addAccommodation(accommodationsToAdd[j].id, accommodationsToAdd[j].option[k].id, true);
if (this._accommodations.length) {
this._accommodations[this._accommodations.length - 1].setIsAttachedToCourse(true);
this._accommodations[this._accommodations.length - 1].setAttachedToCourse(mandatoryAccommodations[i]);
// set the values
var startDate = this.getAccommodationValidStartDates(this._accommodations[this._accommodations.length - 1], this._accommodations[this._accommodations.length - 1]._accommodationStartDatesList);
if (startDate.length) {
this._accommodations[this._accommodations.length - 1].setAttachedAccommodationStartDate(startDate[0]);
var duration = this.getAccommodationValidDuration(this._accommodations[this._accommodations.length - 1], this._accommodations[this._accommodations.length - 1]._accommodationDurationsList);
if (duration.length) {
this._accommodations[this._accommodations.length - 1].setAttachedAccommodationDuration(duration[0]);
}
}
if (startDate.length && duration.length) {
added = true;
} else {
// remove the accommodation and try to add the next one
this._accommodations[this._accommodations.length - 1].removeAccommodation();
this._accommodations.remove(this._accommodations[this._accommodations.length - 1]);
k++;
}
}else{
j++;
}
} else {
j++;
}
} else {
added = true;
}
}
} else {
accommodationsAlreadyAdded[0].setIsAttachedToCourse(true);
accommodationsAlreadyAdded[0].setAttachedToCourse(mandatoryAccommodations[i]);
var startDate = this.getAccommodationValidStartDates(accommodationsAlreadyAdded[0], accommodationsAlreadyAdded[0]._accommodationStartDatesList);
if (startDate.length) {
accommodationsAlreadyAdded[0].setAttachedAccommodationStartDate(startDate[0]);
var duration = this.getAccommodationValidDuration(accommodationsAlreadyAdded[0], accommodationsAlreadyAdded[0]._accommodationDurationsList);
if (duration.length) {
accommodationsAlreadyAdded[0].setAttachedAccommodationDuration(duration[0]);
accommodationsAlreadyAdded[0].refreshAccommodationLists();
this._accommodations[this._accommodations.length - 1].reGenerateAccommodationLists();
}
}
// if something was not valid, remove the accommodation and add another one
if (!startDate.length || !duration.length) {
this._accommodations.remove(accommodationsAlreadyAdded[0]);
accommodationsAlreadyAdded[0].removeAccommodation();
i--;
}
}
}
}
},
/**
* Check all the accommodations and modify them to fit the accommodation passed in parameter
*
* @param SchoolAccommodationsObject accommodation The accommodation to check
*
*/
checkAccommodations : function(accommodation) {
var index = this._accommodations.indexOf(accommodation);
// if it's the first accommodation and there are more than one accommodation
if (index == 0 && this._accommodations.length > 1) {
if (accommodation.getAccommodationEndDate() > this._accommodations[index + 1].getAccommodationStartDate() && this._accommodations[index + 1].isComplete() && accommodation.isComplete()) {
var duration = this.getDurationInWeeks(this._accommodations[index + 1].getAccommodationEndDate(), accommodation.getAccommodationEndDate());
if (duration < this._accommodations[index + 1].getAccommodationOptionDetails().minimumDurationInWeeks) duration = this._accommodations[index + 1].getAccommodationOptionDetails().minimumDurationInWeeks;
// set the new data for the next accommodation
if(this._accommodations[index+1].getIsAttachedToCourse() == false)this._accommodations[index + 1].refreshAccommodationData(accommodation.getAccommodationEndDate(), duration, this._accommodations[index + 1].getAccommodationEndDate());
}
}
// if it's not the first accommodation
if (index > 0) {
// set the previous valid accommodation with valid data (endDate is set with the actual accommodation startDate and duration is calculated)
// if the startDate is higher than the previous end Date
if (accommodation.getAccommodationStartDate() < this._accommodations[index - 1].getAccommodationEndDate() && this._accommodations[index - 1].isComplete() && accommodation.isComplete()) {
var duration = this.getDurationInWeeks(accommodation.getAccommodationStartDate(), this._accommodations[index - 1].getAccommodationStartDate());
if (duration < this._accommodations[index - 1].getAccommodationOptionDetails().minimumDurationInWeeks) {
duration = this._accommodations[index - 1].getAccommodationOptionDetails().minimumDurationInWeeks;
}
// set the new data for this accommodation
if(this._accommodations[index-1].getIsAttachedToCourse() == false)this._accommodations[index - 1].refreshAccommodationData(this._accommodations[index - 1].getAccommodationStartDate(), duration, accommodation.getAccommodationStartDate());
}
}
// if it's not the first and not the last one
if (index > 0 && this._accommodations.getLast() != accommodation) {
if (accommodation.getAccommodationEndDate() > this._accommodations[index + 1].getAccommodationStartDate() && this._accommodations[index + 1].isComplete() && accommodation.isComplete()) {
var duration = this.getDurationInWeeks(this._accommodations[index + 1].getAccommodationEndDate(), accommodation.getAccommodationEndDate());
if (duration < this._accommodations[index + 1].getAccommodationOptionDetails().minimumDurationInWeeks) {
duration = this._accommodations[index + 1].getAccommodationOptionDetails().minimumDurationInWeeks;
}
// set the new data for this accommodation
if(this._accommodations[index+1].getIsAttachedToCourse() == false)this._accommodations[index + 1].refreshAccommodationData(accommodation.getAccommodationEndDate(), duration, this._accommodations[index + 1].getAccommodationEndDate());
}
}
}
,
/**
* Return the school accommodation start date
*
* @return Date the school accommodations start date
*/
getSchoolAccommodationStartDate : function() {
return this._school.getAccommodationStartDate();
},
getSchoolParticipants : function() {
return this._school.getParticipants();
},
/**
* Returns the possible startDate for the accommodation given in parameter
*
* @param SchoolAccommodationObject accommodation The accommodation
*
* @return Date The possible startdates
*/
getAccommodationStartDate : function() {
var startDate = this.getSchoolAccommodationStartDate();
if(this._accommodations.length){
var day = startDate.getDay();
if (day == 0)day = 7;
if(this._accommodations[0] && this._accommodations[0].getAccommodationOptionDetails().accommodationStartDay > 0){
while (this._accommodations[0].getAccommodationOptionDetails().accommodationStartDay != day) {
startDate.setDate(startDate.getDate() - 1);
day = startDate.getDay();
if (day == 0)day = 7;
}
}
}
return startDate;
},
/**
* Returns the valid startDates for an accommodation given in parameter
*
* @param SchoolAccommodationObject accommodation The accommodation
* @param Array accommodationStartDates Array of number containing all the possible start dates
*
* @return Array An array of possible start dates
*/
getAccommodationValidStartDates : function(accommodation, accommodationStartDates) {
var validStartDates = new Array();
var startDates = new Array();
for(var i = 0; i < accommodationStartDates.getListItems().length; i++ ){
startDates.push(accommodationStartDates.getListItems()[i].getValue());
}
var minimumDuration = accommodation.getAccommodationOptionDetails().minimumDurationInWeeks;
var availabilities = accommodation.getAccommodationOptionDetails().availabilities;
// if this accommodation is not the first, we remove the minimum durations of the previous one
if (this._accommodations.indexOf(accommodation) > 0) {
for (var i = 0; i < this._accommodations.indexOf(accommodation); i++) {
if (this._accommodations[i].isComplete()) {
if(this._accommodations[i].getIsAttachedToCourse() == true){
startDates.splice(0, this._accommodations[i]._accommodationDuration);
}else{
startDates.splice(0, this._accommodations[i].getAccommodationOptionDetails().minimumDurationInWeeks);
}
}
}
}
// if this accommodation is not the last, we remove the minimum durations of the next one
if (this._accommodations.getLast() != accommodation) {
for (var i = this._accommodations.length - 1; i > this._accommodations.indexOf(accommodation); i--) {
if (this._accommodations[i].isComplete()) {
if(this._accommodations[i].getIsAttachedToCourse() == true){
startDates.splice(startDates.length - this._accommodations[i]._accommodationDuration, this._accommodations[i]._accommodationDuration);
}else{
startDates.splice(startDates.length - this._accommodations[i].getAccommodationOptionDetails().minimumDurationInWeeks, this._accommodations[i].getAccommodationOptionDetails().minimumDurationInWeeks);
}
}
}
}
startDates.each(function(item, index) {
var date = item;
var year = date.getFullYear();
var week = date.getWeek();
if (accommodation.getAccommodationOptionDetails().accommodationStartDay == 7) {
if (week > 1)week = week + 1;
}
// check the availabilities for this start date
var toAdd = true;
if (availabilities) {
for (var i = 0; i < parseInt(minimumDuration); i++) {
if (week > 52) {
var lastWeek = (new Date(date.getFullYear(), 12, 31)).getWeek();
if (week < lastWeek) {
week = week - lastWeek;
year = year + 1;
}
}
if (availabilities[year + '' + week] == 0) {
toAdd = false;
}
week++;
}
}
if (toAdd) {
validStartDates.push(date);
}
}.bind(this));
// if the accommodation is attached to a course, we must find the only course start date available
if (accommodation.getIsAttachedToCourse()) {
var courseStartDate = (new Date()).fromIso(accommodation.getAttachedToCourse().startDate);
var courseStartTime = courseStartDate.getTime();
for (var i = 0; i < validStartDates.length; i++) {
var n = (i == 0? i : i + 1);
if(validStartDates.length > n) {
var validStartTime = validStartDates[n].getTime();
// if the start date is smaller that the course start time (minus 3 days) we remove it
if (validStartTime < (courseStartTime - (86400 * 3 * 1000))) {
validStartDates.splice(0, i + 1);
i--;
}
// if the start date is bigger that the course start time (+3 days) we remove it
if (validStartTime > (courseStartTime + (86400 * 3 * 1000))) {
validStartDates.splice(n, validStartDates.length - 1);
}
}
}
return validStartDates;
}
return validStartDates;
},
/**
* Return the added accommodations
*/
getAccommodations : function(){
return this._accommodations;
},
/**
* Returns the final endDate for a given accommodation
*
* @param SchoolAccommodationObject accommodation The accommodation
*
* @return Date the endDate
*/
getAccommodationEndDate : function(accommodation) {
return this._school.getAccommodationEndDate(accommodation);
},
/**
* Returns an array of valid durations calculated from the startdates of the accommodation and
* the endDate returned by the parent
*
* @return Array An Array of number containing the valid durations
*/
getAccommodationValidDuration : function(accommodation, durationList) {
// check if this accommodation is attached to a course
if (accommodation.getIsAttachedToCourse()) {
var accommodationEndDate = this._school.getCourseAccommodationEndDate(accommodation.getAttachedToCourse().courseId, (new Date()).fromIso(accommodation.getAttachedToCourse().startDate), accommodation);
// if there is an accommodation end date returned
if (accommodationEndDate) {
var duration = this.getDurationInWeeks(accommodationEndDate, accommodation._accommodationStartDate);
}else{
return [];
}
}
// if the accommodations is not attached
var validDurations = new Array();
var durations = durationList;
var durationsToRemove = 0;
// if the accommodation has a start date
if (accommodation.getAccommodationStartDate()) {
var difference = this.getDurationInWeeks(this.getAccommodationEndDate(accommodation), accommodation.getAccommodationStartDate());
durationsToRemove = durations.getListItems().length - 1 + parseInt(accommodation.getAccommodationOptionDetails().minimumDurationInWeeks) - Math.round(difference);
if(this._accommodations.indexOf(accommodation) >= 0){
for (var i = this._accommodations.indexOf(accommodation); i < this._accommodations.length; i++) {
if (accommodation != this._accommodations[i] && this._accommodations[i].isComplete()) {
if (this._accommodations[i].getIsAttachedToCourse() == true) {
durationsToRemove = parseInt(durationsToRemove + parseInt(this._accommodations[i]._accommodationDuration));
} else {
durationsToRemove = parseInt(durationsToRemove + parseInt(this._accommodations[i].getAccommodationOptionDetails().minimumDurationInWeeks));
}
}
}
}
} else {
for (var i = 0; i < this._accommodations.length; i++) {
if (accommodation != this._accommodations[i] && this._accommodations[i].isComplete()) {
durationsToRemove = parseInt(durationsToRemove + parseInt(this._accommodations[i].getAccommodationOptionDetails().minimumDurationInWeeks));
}
}
}
var week = -1;
var year = -1;
if (accommodation.getAccommodationStartDate()) {
week  = accommodation.getAccommodationStartDate().getWeek();
year  = accommodation.getAccommodationStartDate().getFullYear();
if(accommodation.getAccommodationOptionDetails().accommodationStartDay == 7){
if(week > 1)week = week+1;
}
}
// add the duration items
if(durationsToRemove < 0)durationsToRemove = 0;
for(var i = 0; i < (durations.getListItems().length - durationsToRemove); i++){
var value = durations.getListItems()[i].getValue();
if(week == -1 || !accommodation.getAccommodationOptionDetails().availabilities ||
accommodation.getAccommodationOptionDetails().availabilities[accommodation.getAccommodationStartDate().getFullYear() + '' + (week + parseInt(value)-1)] != 0){
validDurations.push(parseInt(value));
}else{
break;
}
}
if (accommodation.getIsAttachedToCourse()) {
if (duration && validDurations.contains(duration)) {
return [parseInt(duration)];
} else {
return [];
}
}
return validDurations;
}
,
/**
* Returns the end date of the previous accommodation
*
* @param SchoolAccommodationObject accommodation The accommodation
*/
getPreviousEndDate : function(accommodation) {
var previousEndDate = this.getAccommodationEndDate();
for (var i = 0; i < this._accommodations.indexOf(accommodation); i++) {
if (this._accommodations[i].isComplete()) previousEndDate = this._accommodations[i].getAccommodationEndDate();
}
return previousEndDate;
}
,
/**
* Returns the duration in weeks between a startDate and an end date
*
* @param Date endDate The end date
* @param Date starDate The startdate
* @return Number The duration in week
*/
getDurationInWeeks : function(endDate, startDate) {
var duration = endDate - startDate;
duration = Math.round(duration / (1000 * 60 * 60 * 24 * 7));
return duration;
},
/**
* Returns the completed accommodations
*
* @return SchoolAccommodationObject[] The completed accommodations
*/
getCompletedAccommodations : function() {
var accommodations = new Array();
this._accommodations.each(function(item, index) {
if (item.isComplete) {
accommodations.push(item);
}
});
return accommodations;
},
/**
* Return the completed courses for this school (if any)
*
*/
getCompletedCourses : function() {
return this._school.getCompletedCourses();
},
/**
* Delete the accommodation given in parameter
*
* @param Element accommodation The accommodation to delete
*/
deleteAccommodation : function(accommodation) {
this._accommodations.remove(accommodation);
this.refreshAccommodations();
this._school.fireEvent('heightModified');
this.fireEvent('refreshPrice');
}
,
/**
*  Returns the available accommodations
*
* @return Array of integer The Accommodation IDs
*/
getAvailableAccommodations : function() {
return this._school.getAvailableAccommodations();
},
/**
* Return an array containing the available transfers
*
* @return Array of transfers ID
*/
getAvailableTransfers : function() {
var availableTransfers = new Array();
for (var i = 0; i < this._accommodations.length; i++) {
availableTransfers = availableTransfers.merge(this._accommodations[i].getAccommodationDetails().availableTransfers);
}
return availableTransfers;
},
/**
* Return the max accommodation end date for a course
*
* @param integer courseId The Course ID
* @param Date startDate the course start date
*
* @return Date The course accommodation end date
*/
getCourseAccommodationEndDate : function(courseId, startDate, accommodation) {
return this._school.getCourseAccommodationEndDate(courseId, startDate, accommodation);
},
/**
* Display or hide the add button
*
* @param boolean isDisplayed True to display the hide button
*/
displayAddButton : function(isDisplayed){
if(isDisplayed){
this._accommodationAddButton.setStyle('display', 'block');
}else{
this._accommodationAddButton.setStyle('display', 'none');
}
},
/**
* Returns the parent of this object
*
* @return Object The parent object
*/
getSchool : function() {
return this._school;
}
,
/**
* Returns the school accommodations DTO
*
* @return Object The school accommodations DTO
*/
getSchoolAccommodationsDTO : function() {
return this._schoolAccommodationsDTO;
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @event Event refreshPrice This is fired when the price have to be recalculated
* @event Event refreshAccommodations This is fired when a course is modified and the accommodations have to be refreshed
* @event Event heightModified This is fired when a course is added or deleted
*
* @param FixedDatesCourseListItemDTO schoolFixedCoursesDTO The DTO containing all the fixed courses informations
* @param VariableDatesCourseListItemDTO schoolVariableCoursesDTO The DTO containing all the variable courses informations
* @param Object translateDTO The DTO containing all the translations for this class
* @param School parent The parent
**/
var SchoolCourses = Events.extend({
/**
* This is the initialization function
*
*/
initialize : function(schoolFixedCoursesDTO, schoolVariableCoursesDTO, schoolOptionalCoursesDTO, translateDTO, listContainer, parent) {
this._schoolFixedCoursesDTO = schoolFixedCoursesDTO;
this._schoolVariableCoursesDTO = schoolVariableCoursesDTO;
this._schoolOptionalCoursesDTO = schoolOptionalCoursesDTO;
this._listContainer = listContainer;
this._translateDTO = translateDTO;
this._courses = new Array();
this._parent = parent;
this._classNameBase = this.getParent().getClassNameBase();
this.addEvent('refreshCourses', function() {
this.refreshCourses();
}.bind(this));
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Object The fixed course informations needed to calculate the price
*/
getFixedCoursesDTO : function() {
var schoolDTO = new Array();
this._courses.each(function(item, index) {
if (item.getCourseDetails().type == 'fixedDate' && item.isComplete()) {
schoolDTO.push(item.getDTO());
}
});
return schoolDTO;
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Object the variable course informations needed to calculate the price
*/
getVariableCoursesDTO : function() {
var schoolDTO = new Array();
this._courses.each(function(item, index) {
if (item.getCourseDetails().type == 'variableDate' && item.isComplete()) {
schoolDTO.push(item.getDTO());
}
});
return schoolDTO;
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Object the variable course informations needed to calculate the price
*/
getOptionalCoursesDTO : function() {
var schoolDTO = new Array();
this._courses.each(function(item, index) {
if (item.getCourseDetails().type == 'optional' && item.isComplete()) {
schoolDTO.push(item.getDTO());
}
});
return schoolDTO;
},
/**
*
* Populate the fixed courses from a dto
*
* @param Array The fixed course informations needed to populate
*/
populateCoursesFromDTO : function(fixedCoursesToPopulateDTO, variableCoursesToPopulateDTO, optionalCoursesToPopulateDTO) {
// push every courses into one array
var coursesDTO = new Array();
if (fixedCoursesToPopulateDTO) {
fixedCoursesToPopulateDTO.each(function(item, index) {
item.courseType = "fixed";
coursesDTO.push(item);
});
}
if (variableCoursesToPopulateDTO) {
variableCoursesToPopulateDTO.each(function(item, index) {
item.courseType = "variable";
coursesDTO.push(item);
});
}
if (optionalCoursesToPopulateDTO) {
optionalCoursesToPopulateDTO.each(function(item, index) {
item.courseType = "optional";
coursesDTO.push(item);
});
}
// sort the courses by startdates
coursesDTO.sort(function(x1, x2) {
return ((new Date()).fromIso(x1.startDate) - (new Date()).fromIso(x2.startDate));
});
coursesDTO.each(function(item, index) {
var course;
switch(item.courseType){
case 'variable':
course = this._schoolVariableCoursesDTO.filter(function(itemDTO, indexDTO) {
return itemDTO.id == item.id;
}.bind(this));
break;
case 'fixed':
course = this._schoolFixedCoursesDTO.filter(function(itemDTO, indexDTO) {
return itemDTO.id == item.id;
}.bind(this));
break;
case 'optional':
course = this._schoolOptionalCoursesDTO.filter(function(itemDTO, indexDTO) {
return itemDTO.id == item.id;
}.bind(this));
break;
}
// if a course has been found
if (course[0]) {
this.addCourse(course[0]);
this._courses[this._courses.length - 1].populateFromDTO(item);
}
}.bind(this));
},
/**
*  Return the classNameBase
*/
getClassNameBase : function() {
return this._classNameBase;
},
/**
* Refresh all the courses
*
*/
refreshCourses : function() {
var availableOptionalCourses = this.getAvailableOptionalCourses();
// remove the optionals course not allowed to be there
this._courses.each(function(item, index) {
if (item.getCourseDetails().type == 'optional' && !availableOptionalCourses.contains(parseInt(item.getCourseDetails().id))) {
this._courses.remove(item);
item.removeCourse();
}
}.bind(this));
// check the dates
this._courses.each(function(item, index) {
if (item.getCourseDetails().type == 'optional') {
var modified = false;
var validStartDates = this.getValidOptionalCourseStartDate(item);
if (validStartDates.length && !validStartDates.contains(item.getCourseStartDate())) {
item.setCourseStartDate(validStartDates[0]);
modified = true;
}
var validDurations = this.getValidOptionalCourseDuration(item);
if (!validDurations.contains(item.getCourseDuration()) && !item.getCourseDetails().oneDayCourse ) {
item.setCourseDuration(validDurations.getLast());
modified = true;
}
if(!validStartDates.length &&  !validDurations.length){
this._courses.remove(item);
item.removeCourse();
}
if (modified) item.refreshOptionalCourseData();
}
}.bind(this));
this.refreshVisualCoursesList(this.coursesList);
if(this.optionalCoursesList){
this.refreshVisualOptionalCoursesList(this.optionalCoursesList);
}
this._courses.each(function(item, index) {
item.refreshLists();
});
this.displayAddButton(this.getValidAddedCourses().length);
this._parent.fireEvent('refreshAccommodations');
},
/**
* Returns the visual course container
*
*/
getHtml : function() {
this._courseContainer = new Element('div', {'class': this._classNameBase + 'Section'});
this._mainCourseContainer = new Element('div', {'class': this._classNameBase + 'Section-Courses'});
this._courseTitle = new Element('div', {'class': this._classNameBase + 'Section-Title'});
this._courseListContainer = new Element('div', {'class': this._classNameBase + 'Courses-CoursesList-Container'});
this._courseUserCoursesList = new Element('div', {'class': this._classNameBase + 'Courses-UserCoursesList'});
this._courseAddButton = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._courseTitle.injectInside(this._mainCourseContainer);
this._courseListContainer.injectInside(this._mainCourseContainer);
this._courseUserCoursesList.injectInside(this._mainCourseContainer);
this._courseAddButton.injectInside(this._mainCourseContainer);
this._mainCourseContainer.injectInside(this._courseContainer);
this._courseTitle.setHTML(this._translateDTO.title);
this._courseAddButton.setHTML(this._translateDTO.add);
// initialize the courses list
this.coursesList = new SchoolList(this._courseAddButton, this._classNameBase);
this.getVisualCoursesList(this.coursesList);
this.coursesList.getHtml().injectInside(this._listContainer);
this.coursesList.initializeEvents();
if(this._schoolOptionalCoursesDTO.length){
this._optionalCourseContainer = new Element('div', {'class': this._classNameBase + 'Section-Courses'});
this._optionalCourseTitle = new Element('div', {'class': this._classNameBase + 'Section-Title'});
this._optionalCourseListContainer = new Element('div', {'class': this._classNameBase + 'Courses-CoursesList-Container'});
this._optionalCourseUserCoursesList = new Element('div', {'class': this._classNameBase + 'Courses-UserCoursesList'});
this._optionalCourseAddButton = new Element('div', {'class': this._classNameBase + 'AddButton '});
this._optionalCourseTitle.injectInside(this._optionalCourseContainer);
this._optionalCourseListContainer.injectInside(this._optionalCourseContainer);
this._optionalCourseUserCoursesList.injectInside(this._optionalCourseContainer);
this._optionalCourseAddButton.injectInside(this._optionalCourseContainer);
this._optionalCourseTitle.setHTML(this._translateDTO.optionalCourseTitle);
this._optionalCourseAddButton.setHTML(this._translateDTO.optionalCourseAdd);
this._optionalCourseContainer.injectInside(this._courseContainer);
// initialize the optional courses list
this.optionalCoursesList = new SchoolList(this._optionalCourseAddButton, this._classNameBase);
this.getVisualOptionalCoursesList(this.optionalCoursesList);
this.optionalCoursesList.getHtml().injectInside(this._listContainer);
this.optionalCoursesList.initializeEvents();
}
return this._courseContainer;
},
/**
* Generate the courses list for the "add a course" button
*
* @param SchoolList list The list we want to populate
*
*/
getVisualCoursesList : function(list) {
var validCourses = this.getValidCourses();
// clearing the list
list.clear();
var section = '';
//        list.addItem('category', this._translateDTO.coursesCategory);
//        list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item-Category');
validCourses.each(function(item, index) {
// Add each courses
var listItem = new SchoolListItem(item, item.name, this._classNameBase);
list.addListItem(listItem);
listItem.getHtml().addClass(this._classNameBase + 'List-Item');
listItem.getHtml().addEvent('click', function() {
if(listItem.getIsSelectionnable()){
this.addCourse(item);
this._parent.fireEvent('heightModified');
}
}.bind(this));
}, this);
list.addItem('error', this._translateDTO.notAvailable);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Generate the optional courses list for the "add an optional course" button
*
* @param SchoolList list The list we want to populate
*
*/
getVisualOptionalCoursesList : function(list) {
var validCourses = this.getValidCourses(null, true);
// clearing the list
list.clear();
var section = '';
validCourses.each(function(item, index) {
// Add each courses
var listItem = new SchoolListItem(item, item.name, this._classNameBase);
list.addListItem(listItem);
listItem.getHtml().addClass(this._classNameBase + 'List-Item');
listItem.getHtml().addEvent('click', function() {
if(listItem.getIsSelectionnable()){
this.addCourse(item);
this._parent.fireEvent('heightModified');
}
}.bind(this));
}, this);
list.addItem('error', this._translateDTO.notAvailable);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Refresh the courses list
*
* @param SchoolList list the list we want to populate
*
*/
refreshVisualCoursesList : function(list) {
var validCourses = this.getValidCourses();
// retrieving the id of the available optional course
var availableOptionalCourses = this.getAvailableOptionalCourses();
list.getListItems().each(function(item, index) {
if ((validCourses.indexOf(item.getValue()) != -1)) {
item.setIsValid(true);
item.setIsSelectionnable(true);
// if the course is optional, checking that it's allowed to be selectionned
if (item.getValue().type == 'optional') {
if (!availableOptionalCourses.contains(parseInt(item.getValue().id))) {
item.setIsSelectionnable(false);
}
}
} else {
if(item.getValue() != 'category') item.setIsSelectionnable(false);
}
}.bind(this));
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Refresh the optional courses list
*
* @param SchoolList list the list we want to populate
*
*/
refreshVisualOptionalCoursesList : function(list) {
var validCourses = this.getValidCourses(null, true);
// retrieving the id of the available optional course
var availableOptionalCourses = this.getAvailableOptionalCourses();
list.getListItems().each(function(item, index) {
if ((validCourses.indexOf(item.getValue()) != -1)) {
item.setIsValid(true);
item.setIsSelectionnable(availableOptionalCourses.contains(parseInt(item.getValue().id)));
} else {
if(item.getValue() != 'category') item.setIsSelectionnable(false);
}
}.bind(this));
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* return the list of available optional course
*
* @return integer[] Array of optional course IDs
*/
getAvailableOptionalCourses : function() {
var completedCourses = this.getCompletedCourses();
var availableOptionalCourses = new Array();
for (var i = 0; i < completedCourses.length; i++) {
if (completedCourses[i].getCourseDetails().type != 'optional') {
for (var j = 0; j < completedCourses[i].getCourseDetails().availableOptionalCourses.length; j++) {
availableOptionalCourses.include(completedCourses[i].getCourseDetails().availableOptionalCourses[j]);
}
}
}
return availableOptionalCourses;
},
/**
* Add a selected course
*
* @param Object course The course DTO
*/
addCourse : function(course) {
var newCourse;
switch (course.type) {
case 'fixedDate' :
newCourse = new SchoolFixedCourseObject(course, this._translateDTO.courseObject, this._listContainer, this._classNameBase, this);
break;
case 'variableDate' :
newCourse = new SchoolVariableCourseObject(course, this._translateDTO.courseObject, this._listContainer, this._classNameBase, this);
break;
case 'optional' :
newCourse = new SchoolOptionalCourseObject(course, this._translateDTO.courseObject, this._listContainer, this._classNameBase, this);
break;
}
newCourse.addEvent('refreshPrice', this.refreshPrice.bind(this));
this._courses.push(newCourse);
newCourse.createVisualCourse();
newCourse.addEvent('deleteCourse', function(e) {
this.deleteCourse(newCourse);
}.bind(this));
// add the html course
switch (course.type) {
case 'optional' :
this._courses.getLast().getHtml().injectInside(this._optionalCourseListContainer);
break;
default:
this._courses.getLast().getHtml().injectInside(this._courseUserCoursesList);
break;
}
},
/**
* Delete the course given in parameter
*
* @param SchoolCourseObject course The course to delete
*/
deleteCourse : function(course) {
this._courses.remove(course);
if (this._parent.getCompletedAccommodations().length == 0 && this._parent.getCompletedTransfers() == 0) {
this.refreshCourses();
this._parent.fireEvent('heightModified');
this.fireEvent('refreshPrice');
} else {
this.refreshCourses();
this._parent.fireEvent('heightModified');
}
},
/**
* Replace a course with another one
*
* @param SchoolCourseObject oldCourse The course we want to replace
* @param Object newCourse The new Course DTO
* @param Object oldCourseValues The old course values
*/
replaceCourse : function(oldCourse, newCourse, oldCourseValues) {
var i = this._courses.indexOf(oldCourse);
switch (newCourse.type) {
case 'fixedDate' :
var replaceCourse = new SchoolFixedCourseObject(newCourse, this._translateDTO.courseObject, this._listContainer, this._classNameBase,  this);
this._courses[i] = replaceCourse;
replaceCourse.createVisualCourse();
oldCourse.getHtml().replaceWith(replaceCourse.getHtml());
replaceCourse.addEvent('deleteCourse', function(e) {
this.deleteCourse(replaceCourse);
}.bind(this));
if (oldCourseValues) {
this._courses[i].refreshFixedCourseData(this._courses[i].getNewFixedCourseDates(oldCourseValues));
} else {
this._courses[i].refreshLists();
}
break;
case 'variableDate' :
var replaceCourse = new SchoolVariableCourseObject(newCourse, this._translateDTO.courseObject, this._listContainer, this._classNameBase,  this);
this._courses[i] = replaceCourse;
replaceCourse.createVisualCourse();
oldCourse.getHtml().replaceWith(replaceCourse.getHtml());
replaceCourse.addEvent('deleteCourse', function(e) {
this.deleteCourse(replaceCourse);
}.bind(this));
if (oldCourseValues) {
this._courses[i].replaceVariableCourseDates(oldCourseValues.startDate, oldCourseValues.duration);
} else {
this._courses[i].refreshLists();
}
break;
}
this._courses[i].addEvent('refreshPrice', this.refreshPrice.bind(this));
this._parent.fireEvent('heightModified');
},
refreshPrice : function(){
this.fireEvent('refreshPrice');
},
/**
* Returns True if the course given in parameter is a fixed course
*
* @param Object course The course DTO
*
* @return Boolean Returns true if the course given in parameter is a fixed course
*/
getIsFixedCourse : function(course) {
return course.type == 'fixedDate';
},
/**
* Returns all the courses stocked in the DTO
*
* @return Array An array containing all the courses
*/
getCourses : function() {
var validCourses = new Array();
// retrieving the valid fixed courses
this._schoolFixedCoursesDTO.each(function(item, index) {
validCourses.include(item);
});
// retrieving the variable courses
this._schoolVariableCoursesDTO.each(function(item, index) {
validCourses.include(item);
});
return validCourses;
},
/**
* Returns all the optional courses stocked in the DTO
*
* @return Array An array containing all the courses
*/
getOptionalCourses : function() {
var validCourses = new Array();
// retrieving the valid optional courses
this._schoolOptionalCoursesDTO.each(function(item, index) {
validCourses.include(item);
});
return validCourses;
},
/**
* This method returns the number of completed courses
*
* @return SchoolCourseObject The courses completed
*
*/
getCompletedCourses : function() {
var completedCourses = new Array();
if (this._courses.length) {
this._courses.each(function(item, index) {
if (item.isComplete()) {
completedCourses.push(item);
}
});
}
return completedCourses;
},
/**
* Returns all the courses added in the cart
*
* @return Array An array containing all the courses
*/
getAddedCourses : function() {
return this._courses;
},
/**
* Return all the valid courses added in the cart
*
* @param Array An array containing all the courses
*/
getValidAddedCourses : function() {
var validCourses = new Array();
for (var i = 0; i < this._courses.length; i++) {
if (this._courses[i].isComplete()) {
validCourses.push(this._courses[i]);
}
}
return validCourses;
},
/**
* Returns the valid courses for a given period based on a courseObject
*
* @param SchoolCoursesObject course The course object, if empty we consider that we want to add a new course
*
* @return Array An array of course ID (by default the one that is given in parameter)
*/
getValidCourses : function(course, optionalCourse) {
var startDate = new Date();
var endDate = new Date(startDate.getFullYear() + 10, startDate.getMonth(), startDate.getDate());
var validCourses = new Array();
// initializing the start and end dates
// if we want to add a new course
if (!course) {
if (this._courses.length > 0 && this._courses.getLast()._courseEndDate) {
startDate = this._courses.getLast()._courseEndDate;
}
// if we want to replace a course
} else {
// if the course is not the last one and there are more than one course
if (course != this._courses.getLast() && this._courses.length > 1) {
if (this._courses[this._courses.indexOf(course) + 1]._courseStartDate)endDate = this._courses[this._courses.indexOf(course) + 1]._courseStartDate;
}
// if this courses is not the first
if (this._courses.indexOf(course) > 0) {
if (this._courses[this._courses.indexOf(course) - 1]._courseEndDate)startDate = this._courses[this._courses.indexOf(course) - 1]._courseEndDate;
}
}
if (!optionalCourse) {
// retrieving the valid fixed courses
this._schoolFixedCoursesDTO.each(function(item, index) {
var courseItem = item;
item.sessions.each(function(item, index) {
//alert(item.courseStartDate);
if (item.courseStartDate >= startDate && item.courseEndDate <= endDate) {
validCourses.include(courseItem);
}
});
});
// retrieving the valid variable courses
this._schoolVariableCoursesDTO.each(function(item, index) {
var itemDuration = item.duration[0];
var courseItem = item;
item.startDates.each(function(item, index) {
var itemEndDate = new Date(item.getFullYear(), item.getMonth(), item.getDate() + itemDuration * 7);
if (item >= startDate && itemEndDate <= endDate) {
validCourses.include(courseItem);
}
}.bind(this));
}, this);
} else {
// retrieving the valid optional courses
this._schoolOptionalCoursesDTO.each(function(item, index) {
// need to recalulcate the start date for the optional courses
var completedCourses = this.getCompletedCourses();
if (completedCourses.length) {
var startDate = completedCourses[0].getCourseStartDate();
} else {
var startDate = new Date();
}
for (var i = 0; i < completedCourses.length; i++) {
if (completedCourses[i].getCourseDetails().availableOptionalCourses && completedCourses[i].getCourseDetails().availableOptionalCourses.contains(parseInt(item.id))) {
startDate = completedCourses[i].getCourseStartDate();
break;
}
}
var itemDuration = parseInt(item.duration[0]);
var courseItem = item;
item.startDates.each(function(itemStartDate, index) {
var itemEndDate = new Date(itemStartDate.getFullYear(), itemStartDate.getMonth(), (itemStartDate.getDate() + itemDuration * 7));
if (itemStartDate >= startDate && itemEndDate <= endDate) {
validCourses.include(courseItem);
}
}.bind(this));
}, this);
}
// if there is no course available and we are not on the add course list,
//  we just add the one that is already there
if (!validCourses.length && course) {
var courseItem = this._schoolVariableCoursesDTO.filter(function(item, index) {
return item.id == course._courseDetails.id;
}.bind(this));
if (!courseItem.length) {
courseItem = this._schoolFixedCoursesDTO.filter(function(item, index) {
return  item.id == course._courseDetails.id;
}.bind(this));
}
validCourses.include(courseItem[0]);
}
// sort the list
validCourses = validCourses.sort(this.sortFunction);
return validCourses;
},
/**
* function called to sort an array of valid courses
*
* @param courseDTO a The first course to compare
* @param courseDTO b The second course to compare
*/
sortFunction : function(a, b) {
return a.position - b.position;
},
/**
* Returns the valid courses date session for a given period based on a courseObject
*
* @param SchoolCoursesObject course The course object, if empty we consider that we want to add a new course
*
* @return Array An array of validSessions
*/
getValidFixedCourseSession : function(course) {
var validSessions = new Array();
var startDate = new Date();
var endDate = new Date(startDate.getFullYear() + 10, startDate.getMonth(), startDate.getDate());
// if the course is not the last one and there are more than one course
if (course != this._courses.getLast() && this._courses.length > 1) {
for (var i = this._courses.indexOf(course) + 1; i < this._courses.length; i++) {
if (this._courses[i]._courseStartDate)endDate = this._courses[i]._courseStartDate;
}
}
// if this courses is not the first
if (this._courses.indexOf(course) > 0) {
for (var i = this._courses.indexOf(course) - 1; i >= 0; i--) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i]._courseEndDate)startDate = this._courses[i]._courseEndDate;
}
}
// retrieve the valid sessions
course._courseDetails.sessions.each(function(item, index) {
if (item.courseStartDate >= startDate && item.courseEndDate <= endDate) {
validSessions.include(item);
}
}.bind(this));
return validSessions;
},
/**
* Returns the valid courses date session for a given period based on a courseObject
*
* @param SchoolCoursesObject course The course object, if empty we consider that we want to add a new course
*
* @return Array An Array of valid start date
*/
getValidVariableCourseStartDate : function(course) {
var validStartDates = new Array();
var startDate = new Date();
var endDate = new Date(startDate.getFullYear() + 10, startDate.getMonth(), startDate.getDate());
var minimalEndDate = '';
var duration = course._courseDuration;
var availabilities = course.getCourseDetails().availabilities;
if (!duration) {
duration = course._courseDetails.duration[0];
}
// if the course is not the last one and there are more than one course
if (course != this._courses.getLast() && this._courses.length > 1) {
for (var i = this._courses.indexOf(course) + 1; i < this._courses.length; i++) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i]._courseStartDate)endDate = this._courses[i]._courseStartDate;
}
}
// if this courses is not the first
if (this._courses.indexOf(course) > 0) {
for (var i = 0; i < this._courses.indexOf(course); i++) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i]._courseEndDate)startDate = this._courses[i]._courseEndDate;
}
}
course._courseDetails.startDates.each(function(item, index) {
// the minimal end date is the date minus the minimal course duration
minimalEndDate = new Date(item.getFullYear(), item.getMonth(), item.getDate() + 7 * duration);
if (item >= startDate && minimalEndDate <= endDate) {
var year = item.getFullYear();
var week = item.getWeek();
if (course.getCourseDetails().courseStartDay == 7) {
if (week > 1)week = week + 1;
}
// check the availabilities for this start date
var toAdd = true;
if (availabilities) {
for (var i = 0; i < duration; i++) {
if (week > 52) {
var lastWeek = (new Date(item.getFullYear(), 12, 31)).getWeek();
if (week < lastWeek) {
week = week - lastWeek;
year = year + 1;
}
}
if (availabilities[year + '' + week] == 0) {
toAdd = false;
}
week++;
}
}
if (toAdd) {
validStartDates.push(item);
}
}
}.bind(this));
return validStartDates;
},
/**
* Returns the valid courses date session for a given period based on a courseObject
*
* @param SchoolCoursesObject course The course object, if empty we consider that we want to add a new course
*
* @return Array An Array of valid start date
*/
getValidOptionalCourseStartDate : function(course) {
var validStartDates = new Array();
var periods = new Array();
var sameCoursesPeriods = new Array();
var addedCourses = this.getValidAddedCourses();
var sameCourses = new Array();
var availabilities =  course.getCourseDetails().availabilities;
var additionalDays = course.getCourseDetails().additionalDays;
// check every course to calculate the start date and end date validity
for (var i = 0; i < addedCourses.length; i++) {
if (addedCourses[i].getCourseDetails().type != 'optional' && addedCourses[i].getCourseDetails().availableOptionalCourses.contains(parseInt(course.getCourseDetails().id))) {
var period = new Object();
period.startDate = (new Date()).fromIso(addedCourses[i].getDTO().startDate);
period.endDate = (new Date()).fromIso(addedCourses[i].getDTO().endDate);
if(additionalDays){
period.endDate.setDate(period.endDate.getDate() + additionalDays);
}
periods.push(period);
}
if (addedCourses[i].getCourseDetails().type == 'optional' && addedCourses[i].getCourseDetails().id == course.getCourseDetails().id && addedCourses[i] != course) {
sameCourses.push(addedCourses[i]);
}
}
if (sameCourses.length) {
for (var i = 0; i < sameCourses.length; i++) {
var period = new Object();
period.startDate = sameCourses[i]._courseStartDate;
period.endDate = sameCourses[i]._courseEndDate;
sameCoursesPeriods.push(period);
}
}
var minimalEndDate = '';
var duration = course._courseDuration;
if (!duration) {
duration = course._courseDetails.duration[0];
}
course._courseDetails.startDates.each(function(item, index) {
// check if the same courses is already added
var toAdd = true;
if (sameCoursesPeriods.length) {
for (var j = 0; j < sameCoursesPeriods.length; j++) {
if ((item >= sameCoursesPeriods[j].startDate && item <= sameCoursesPeriods[j].endDate)) {
toAdd = false;
}
}
}
if (toAdd) {
// the minimal end date is the date minus the minimal course duration
if(course.getCourseDetails().oneDayCourse){
minimalEndDate = new Date(item.getFullYear(), item.getMonth(), item.getDate());
} else {
minimalEndDate = new Date(item.getFullYear(), item.getMonth(), item.getDate() + 7 * duration);
}
minimalEndDate = course.getOptionalCourseEndDate(minimalEndDate);
for (var i = 0; i < periods.length; i++) {
if (item >= periods[i].startDate && minimalEndDate <= periods[i].endDate) {
var year = item.getFullYear();
var week = item.getWeek();
if (course.getCourseDetails().courseStartDay == 7) {
if (week > 1)week = week + 1;
}
// check the availabilities for this start date
var toAdd = true;
if (availabilities) {
for (var i = 0; i < duration; i++) {
if (week > 52) {
var lastWeek = (new Date(item.getFullYear(), 12, 31)).getWeek();
if (week < lastWeek) {
week = week - lastWeek;
year = year + 1;
}
}
if (availabilities[year + '' + week] == 0) {
toAdd = false;
}
week++;
}
}
// if the item can be added
if (toAdd) {
validStartDates.include(item);
break;
}
}
}
}
}.bind(this));
return validStartDates;
},
/**
* Returns the valid courses date session for a given period based on a courseObject
*
* @param SchoolCoursesObject course The course object, if empty we consider that we want to add a new course
*
* @return Array An array of valid durations
*/
getValidOptionalCourseDuration : function(course) {
var validDurations = new Array();
var sameCoursesPeriods = new Array();
var addedCourses = this.getValidAddedCourses();
var sameCourses = new Array();
var periods = new Array();
var availabilities = course.getCourseDetails().availabilities;
var additionalDays = course.getCourseDetails().additionalDays;
if(addedCourses.length){
for (var i = 0; i < addedCourses.length; i++) {
if (addedCourses[i].getCourseDetails().type != 'optional' && addedCourses[i].getCourseDetails().availableOptionalCourses.contains(parseInt(course.getCourseDetails().id))) {
var period = new Object();
period.startDate = (new Date()).fromIso(addedCourses[i].getDTO().startDate);
period.endDate = (new Date()).fromIso(addedCourses[i].getDTO().endDate);
if(additionalDays){
period.endDate.setDate(period.endDate.getDate() + additionalDays);
}
periods.push(period);
}
if (addedCourses[i].getCourseDetails().type == 'optional' && addedCourses[i].getCourseDetails().id == course.getCourseDetails().id && addedCourses[i] != course) {
sameCourses.push(addedCourses[i]);
}
}
if (sameCourses.length) {
for (var i = 0; i < sameCourses.length; i++) {
var period = new Object();
period.startDate = sameCourses[i]._courseStartDate;
period.endDate = sameCourses[i]._courseEndDate;
sameCoursesPeriods.push(period);
}
}
var optionEndDate = '';
var week = -1;
var year = -1;
if (course.getCourseStartDate()) {
week = course.getCourseStartDate().getWeek();
year = course.getCourseStartDate().getFullYear();
if(course.getCourseDetails().courseStartDay== 7){
if(week > 1)week = week+1;
}
}
// for each duration
for (var i = 0; i < (course.getCourseDetails().duration.length); i++) {
var value = course.getCourseDetails().duration[i];
// check if there is an availability
if (week == -1 || !availabilities ||
availabilities[year + '' + (week + parseInt(value) - 1)] != 0) {
var toAdd = true;
// the minimal end date is the date minus the minimal course duration
if (course._courseStartDate) {
optionEndDate = new Date(course._courseStartDate.getFullYear(), course._courseStartDate.getMonth(), course._courseStartDate.getDate() + 7 * value);
optionEndDate = course.getOptionalCourseEndDate(optionEndDate);
} else {
optionEndDate = new Date(periods[0].startDate.getFullYear(), periods[0].startDate.getMonth(), periods[0].startDate.getDate() + 7 * value);
}
// check each periods of courses it can be attached
for (var j = 0; j < periods.length; j++) {
if (course._courseStartDate >= periods[j].startDate && optionEndDate <= periods[j].endDate || !course._courseStartDate) {
// and check the end date meets the right range.
for (var k = 0; k < sameCoursesPeriods.length; k++) {
if (optionEndDate >= sameCoursesPeriods[k].startDate && optionEndDate < sameCoursesPeriods[k].endDate) {
toAdd = false;
}
}
if (toAdd) {
validDurations.include(value);
break;
}
}
}
// if there is no more availability, the valid durations stops here
}else{
break;
}
}
}
return validDurations;
},
/**
* Returns the valid courses date session for a given period based on a courseObject
*
* @param SchoolCoursesObject course The course object, if empty we consider that we want to add a new course
*
* @return Array An array of valid durations
*/
getValidVariableCourseDuration : function(course) {
var validDurations = new Array();
var startDate = new Date();
var endDate = new Date(startDate.getFullYear() + 10, startDate.getMonth(), startDate.getDate());
var calculatedEndDate;
var availabilities = course.getCourseDetails().availabilities;
// if the course is not the last one and there are more than one course
if (course != this._courses.getLast() && this._courses.length > 1) {
for (var i = this._courses.indexOf(course) + 1; i < this._courses.length; i++) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i]._courseStartDate)endDate = this._courses[i]._courseStartDate;
}
}
// if this courses is not the first
if (this._courses.indexOf(course) > 0) {
for (var i = this._courses.indexOf(course) - 1; i >= 0; i--) {
if (this._courses[i]._courseEndDate)startDate = this._courses[i]._courseEndDate;
}
}
var week = -1;
var year = -1;
if (course.getCourseStartDate()) {
week = course.getCourseStartDate().getWeek();
year = course.getCourseStartDate().getFullYear();
if(course.getCourseDetails().courseStartDay == 7){
if(week > 1)week = week+1;
}
}
// find the default start date, usefull when the start date is not the same as the course information one
if(course.getCourseStartDate()){
var defaultCourseStartDate = new Date(course.getCourseStartDate());
// if the course start day is not the same as the given in the course informations
if (defaultCourseStartDate && course.getCourseDetails().courseStartDay && course.getCourseDetails().courseStartDay !=  defaultCourseStartDate.getDay()) {
var courseStartDayUp = (defaultCourseStartDate.getDay() == 0 ? 7 : defaultCourseStartDate.getDay());
var courseStartDayDown = courseStartDayUp;
var iter = 0;
while (course.getCourseDetails().courseStartDay != courseStartDayDown && course.getCourseDetails().courseStartDay != courseStartDayUp) {
if (courseStartDayDown == 0)courseStartDayDown = 7;
if (courseStartDayUp == 8)courseStartDayUp = 1;
courseStartDayDown--;
courseStartDayUp++;
iter++;
}
if (courseStartDayDown == course.getCourseDetails().courseStartDay) {
defaultCourseStartDate.setDate(defaultCourseStartDate.getDate() - iter);
} else {
defaultCourseStartDate.setDate(defaultCourseStartDate.getDate() + iter);
}
}
}
for (var i = 0; i < (course.getCourseDetails().duration.length); i++) {
var value = course.getCourseDetails().duration[i];
// the minimal end date is the date minus the minimal course duration
if (defaultCourseStartDate) {
calculatedEndDate = new Date(defaultCourseStartDate.getFullYear(), defaultCourseStartDate.getMonth(), defaultCourseStartDate.getDate() + 7 * value);
} else {
calculatedEndDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + 7 * value);
}
if (defaultCourseStartDate >= startDate && calculatedEndDate <= endDate || !defaultCourseStartDate) {
var currentYear = year;
var currentWeek = week;
if(currentWeek > 52){
currentWeek = currentWeek - 52;
currentYear = currentYear + 1;
}
if (currentWeek == -1 || !availabilities ||
availabilities[currentYear + '' + (currentWeek + parseInt(value) - 1)] != 0) {
validDurations.push(value);
} else {
break;
}
}
}
return validDurations;
},
/**
* Returns the accommodation start date
*
* @optionalparam AccommodationDTO accommodation The Accommodation DTO
*
* @return Date The  possible start date
*/
getAccommodationStartDate : function() {
var newDate = null;
this._courses.each(function(item, index) {
// check if the course is complete
if (item.isComplete()) {
// if it is a fixed Course
if (item.getIsFixedCourse()) {
// if this accommodation is available with this course
if (newDate > item._courseDetails.sessions[item._session].accommodationStartDate || newDate == null) {
newDate = new Date(item._courseDetails.sessions[item._session].accommodationStartDate);
}
// if it's a variable course
} else {
// if this accommodation is available with this course
// the new date is set
if (newDate > item._courseStartDate || newDate == null) {
newDate = new Date(item._courseStartDate);
}
}
}
}.bind(this));
return newDate;
},
/**
* Returns the maximal final date
*
* @return Date The end date for the accommodations
*/
getAccommodationEndDate : function() {
var endDate = new Date();
if (this._courses.length) {
for (var i = 0; i < this._courses.length; i++) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i].isComplete()) {
if (this._courses[i].getIsFixedCourse()) {
endDate = new Date(this._courses[i]._courseDetails.sessions[this._courses[i]._session].accommodationEndDate);
} else {
endDate = new Date(this._courses[i]._courseEndDate);
}
}
}
}
return endDate;
},
/**
*  Returns the available accommodations
*
* @return Array of integer The Accommodation IDs
*/
getAvailableAccommodations : function() {
var availableAccommodations = new Array();
for (var i = 0; i < this._courses.length; i++) {
if (this._courses[i].getCourseDetails().type != 'optional') {
availableAccommodations = availableAccommodations.merge(this._courses[i].getAvailableAccommodations());
}
}
return availableAccommodations;
},
/**
* Return an array containing the mandatory accommodations with their start and end date
*
* @return Array of MandatoryAccommodationsDTO
*/
getMandatoryAccommodations : function() {
var mandatoryAccommodations = new Array();
for (var i = 0; i < this._courses.length; i++) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i].getCourseDetails().accommodationMandatory == true) {
var mandatoryAccommodation = new Object();
mandatoryAccommodation.courseId = this._courses[i].getCourseDetails().id;
mandatoryAccommodation.ids = this._courses[i].getCourseDetails().availableAccommodations;
mandatoryAccommodation.startDate = this._courses[i].getDTO().startDate;
mandatoryAccommodation.endDate = this._courses[i].getDTO().endDate;
mandatoryAccommodations.push(mandatoryAccommodation);
}
}
return mandatoryAccommodations;
},
/**
* Return true if the transfer is mandatory
*
* @return boolean true if the transfers are mandatory
*/
getIsTransferMandatory : function() {
var mandatory = false;
for (var i = 0; i < this._courses.length; i++) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i].getCourseDetails().transferMandatory == true) {
mandatory = true;
}
}
return mandatory;
},
/**
* Display or hide the optional course add button
*
* @param boolean isDisplayed True to display the hide button
*/
displayAddButton : function(isDisplayed){
if (this._optionalCourseAddButton) {
if (isDisplayed) {
this._optionalCourseAddButton.setStyle('display', 'block');
} else {
this._optionalCourseAddButton.setStyle('display', 'none');
}
}
},
/**
* Returns the parent of this object
*
* @return SchoolPriceEstimation The parent object
*/
getParent : function() {
return this._parent;
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param TransferListItemDTO schoolTransfersDTO the transfers informations
* @param SchoolPriceEstimation parent the parent
**/
var SchoolCurrencySelector = Events.extend({
/**
* This is the initialization function
* @param TranslateDTO translateDTO The DTO containing the translations
* @param String defaultCurrency The default currency
* @param Array currenciesList An array containing all the currencies
* @param Object parent The parent
*/
initialize : function(translateDTO, defaultCurrency, currenciesList,parent) {
this._translateDTO = translateDTO;
this._parent = parent;
this._classNameBase = this._parent.getClassNameBase();
this._currencyAvailableList = currenciesList;
this._currency = defaultCurrency;
},
/**
* return the visual transfer container
*/
getHtml : function() {
this._currencyContainer = new Element('div', {'class': this._classNameBase + 'Currency-Section'});
this._currencyTitle = new Element('div', {'class': this._classNameBase + 'Currency-Section-Title'});
this._currencyTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text'});
this._currencyTitleText.injectInside(this._currencyTitle);
this._currencyButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._currencyButtons.addClass( this._classNameBase + 'CurrencyButton');
this._currencyTitle.injectInside(this._currencyContainer);
//        this._currencyButtons.injectInside(this._currencyContainer);
this._currencyTitleText.setHTML(this._translateDTO.title);
this._currencyButtons.setHTML(this._currency);
this._currencyButtons.injectInside(this._currencyTitle);
this._currencyList = new SchoolList(this._currencyButtons, this._classNameBase);
this.createVisualList(this._currencyList);
this._currencyList.getHtml().injectInside(this._parent.getListContainer());
this._currencyList.initializeEvents();
return this._currencyContainer;
},
/**
* Generate the list of currency
*
* @param SchoolList list The list to update
*/
createVisualList : function(list) {
for (var i = 0; i < this._currencyAvailableList.length; i++) {
list.addItem(this._currencyAvailableList[i].currencyCode, this._currencyAvailableList[i].currencyName + " (" + this._currencyAvailableList[i].currencyCode  + ")");
}
list.getListItems().each(function(item, index) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (item.getValue() == this._currency) {
this._currencyButtons.setHTML(item.getHtmlValue());
list.setSelectedItem(item);
}
item.getHtml().addEvent('click', function(event) {
this._currencyButtons.setHTML(item.getHtmlValue());
this._currency = item.getValue();
this._parent.fireEvent('refreshPrice');
list.setSelectedItem(item);
}.bind(this));
}.bind(this));
},
/**
* Returns the number of currency
*
* @return number The number of currency
*/
getCurrency : function() {
return this._currency;
},
/**
* Set the currency
*
* @param String currency the currency code to use
*/
setCurrency : function(currency){
this._currency  = currency;
this._currencyButtons.setHTML(currency);
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @event Event deleteCourse This event is fired when a course is deleted
*
* @param FixedDatesCourseListItemDTO courseDetails The object containing the course informations
* @param Object translateDTO The object containing all the translations for this class
* @param SchoolCourses parent The parent
*
**/
var SchoolFixedCourseObject = Events.extend({
/**
* This is the initialization function
*/
initialize : function(courseDetails, translateDTO, listContainer, classNamePrefix ,parent) {
this._translateDTO = translateDTO;
this._courseDetails = courseDetails;
this._parent = parent;
this._listContainer = listContainer;
this._classNameBase = classNamePrefix;
this._dateFormat = this._parent.getParent().getDateFormat();
this._monthsTranslations = this._parent.getParent().getMonthTranslations();
this._courseStartDate = null;
this._courseEndDate = null;
this._courseDuration = null;
this._manager = this._parent.getParent().getParent();
this._manager.addEvent('descriptionsUpdated', function(){
this.updateDescriptions();
}.bind(this));
},
/**
* Return the course details DTO
*
* @return CourseDetailsDTO The course Details DTO
*/
getCourseDetails : function() {
return this._courseDetails;
},
/**
* Returns true if the course is complete
*
* @return boolean true if the course is complete
*/
isComplete : function() {
if (this._courseStartDate && this._courseEndDate && this._courseDuration) {
return true;
} else {
return false;
}
},
/**
* Generate the html structure of the course
* and add an event on the delete button
*
*/
createVisualCourse : function() {
this._container = new Element('div', {'class': this._classNameBase + 'ItemAdded'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Item-Title'});
this._subTitle = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle'});
this._moreInfo = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle MoreInfos'});
this._moreInfo.setStyle('display','none');
this._startDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-StartDate-Container'});
this._endDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-EndDate-Container'});
this._startDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._startDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._endDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._endDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._durationDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-Duration-Container'});
this._duration = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._durationValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._deleteButton = new Element('div', {'class': this._classNameBase + 'Section-Item-DeleteButton'});
this._duration.injectInside(this._durationDateContainer);
this._durationValue.injectInside(this._durationDateContainer);
this._startDate.injectInside(this._startDateContainer);
this._startDateValue.injectInside(this._startDateContainer);
this._endDate.injectInside(this._endDateContainer);
this._endDateValue.injectInside(this._endDateContainer);
this._title.injectInside(this._container);
this._subTitle.injectInside(this._container);
this._moreInfo.injectInside(this._container);
new Element('div',{'style':'clear:both'}).injectInside(this._container);
this._startDateContainer.injectInside(this._container);
this._endDateContainer.injectInside(this._container);
this._durationDateContainer.injectInside(this._container);
this._deleteButton.injectInside(this._container);
new Element('div',{'style':'clear:both'}).injectInside(this._container);
this._title.setHTML(this._courseDetails.name);
this._subTitle.setHTML(this._courseDetails.subtitle);
this._moreInfo.setHTML(this._translateDTO.moreInfos);
this._startDate.setHTML(this._translateDTO.startDate);
this._startDateValue.setHTML(this._translateDTO.dateSelect);
this._endDate.setHTML(this._translateDTO.endDate);
this._endDateValue.setHTML(this._translateDTO.endDateValue);
this._duration.setHTML(this._translateDTO.duration);
this._durationValue.setHTML(this._translateDTO.durationSelect);
this._deleteButton.setHTML(this._translateDTO.deleteButton);
// add event listener
this._deleteButton.addEvent('click', function(e) {
this.removeCourse();
this.fireEvent('deleteCourse');
}.bind(this));
this.updateDescriptions();
this._coursesValidList = new SchoolList(this._title, this._classNameBase);
this.getVisualValidCoursesList(this._coursesValidList);
this._coursesValidList.getHtml().injectInside(this._listContainer);
this._coursesValidList.initializeEvents();
this._schoolSessionsList = new SchoolList(this._startDateValue, this._classNameBase);
this.getVisualFixedCourseStartDates(this._courseDetails.sessions, this._schoolSessionsList);
this._schoolSessionsList.getHtml().injectInside(this._listContainer);
this._schoolSessionsList.initializeEvents();
this.refreshLists();
},
/**
* Returns the html Element of this course
*
* @return Element The Html view of this course
*/
getHtml : function() {
return this._container;
},
updateDescriptions : function(){
if (this._manager.getDescription && this._manager.getDescription('course', this._courseDetails.courseTypeId) && this._manager.getDescription('course', this._courseDetails.courseTypeId) != '') {
this._moreInfo.setAttribute('title', this._courseDetails.name + ' :: ' + this._manager.getDescription('course', this._courseDetails.courseTypeId));
this._moreInfo.setStyle('display','');
if(!this._descriptionToolTip ){
this._descriptionToolTip = new SynergeeTips(this._moreInfo, {'className':'PriceEstimationToolTip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}else {
this._descriptionToolTip.build(this._moreInfo);
}
}else {
this._moreInfo.setStyle('display','none');
}
},
/**
* return the course start date
*
* @return Date The course start date
*/
getCourseStartDate : function() {
return this._courseStartDate;
},
/**
* return the course start date
*
* @return Date The course start date
*/
getCourseEndDate : function() {
return this._courseEndDate;
},
/**
* return the accommodation end date for this course
*
* @return Date The accommodation end date date
*/
getAccommodationEndDate : function() {
return this._courseDetails.sessions[this._session].accommodationEndDate;
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Object The informations needed to calculate the price
*/
getDTO : function() {
var courseDTO = new Object();
courseDTO.id = this._courseDetails.id;
courseDTO.startDate = this._courseStartDate.toIso();
courseDTO.endDate = this._courseEndDate.toIso();
return courseDTO;
},
/**
* Populate the fixed course from a dto
*
* @param Object The fixed course informations needed to populate
*/
populateFromDTO : function(toPopulateDTO) {
var courseInfos = new Object();
courseInfos.courseStartDate = (new Date()).fromIso(toPopulateDTO.startDate);
courseInfos.courseEndDate = (new Date()).fromIso(toPopulateDTO.endDate);
// Set the variables for this course
this._courseStartDate = courseInfos.courseStartDate;
this._courseEndDate = courseInfos.courseEndDate;
this._courseDuration = this.getCalculatedDuration(courseInfos.courseStartDate, courseInfos.courseEndDate);
// set the visual data of this course
this._startDateValue.setHTML(courseInfos.courseStartDate.format(this._dateFormat, this._monthsTranslations));
this._endDateValue.setHTML(courseInfos.courseEndDate.format(this._dateFormat, this._monthsTranslations));
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
// if the session hasn't been found (when the course is populated)
this._courseDetails.sessions.each(function(item, index) {
if (item.courseStartDate.format(this._dateFormat, this._monthsTranslations) == courseInfos.courseStartDate.format(this._dateFormat, this._monthsTranslations)) {
this._session = index;
}
}.bind(this));
},
/**
* Refresh all the lists of this course
*
*/
refreshLists : function() {
this.refreshVisualValidCoursesList(this._coursesValidList);
this.refreshVisualFixedCourseStartDates(this._parent.getValidFixedCourseSession(this), this._schoolSessionsList);
if(this._schoolSessionsList.getValidListItems().length == 1 ){
this._startDateValue.addClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
this._schoolSessionsList.removeButtonEvent();
if(this._courseStartDate != this._schoolSessionsList.getValidListItems()[0].getValue().courseStartDate
|| this._courseEndDate != this._schoolSessionsList.getValidListItems()[0].getValue().courseEndDate)this._schoolSessionsList.getValidListItems()[0].getHtml().fireEvent('click');
}else{
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._startDateValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this._schoolSessionsList.addButtonEvent();
}
},
/**
* Regenerate all the lists of this course
*
*/
reGenerateLists : function() {
// remove old list if exists
if (this._coursesValidList.getListItems().length) {
this._coursesValidList.getHtml().remove();
this._coursesValidList.clear();
}
if (this._schoolSessionsList.getListItems().length) {
this._schoolSessionsList.getHtml().remove();
this._schoolSessionsList.clear();
}
// add the list of courses that fit the start and end Date
this.getVisualValidCoursesList(this._coursesValidList);
this._coursesValidList.getHtml().injectInside(this._listContainer);
this._coursesValidList.initializeEvents();
this.getVisualFixedCourseStartDates(this._courseDetails.sessions, this._schoolSessionsList);
this.refreshVisualFixedCourseStartDates(this._parent.getValidFixedCourseSession(this), this._schoolSessionsList);
this._schoolSessionsList.getHtml().injectInside(this._listContainer);
this._schoolSessionsList.initializeEvents();
},
/**
* Refresh the values when the user change a course information
*
* @param Object values The new values
*/
refreshFixedCourseData : function(values) {
// Set the variables for this course
this._courseStartDate = values.courseStartDate;
this._courseEndDate = values.courseEndDate;
this._courseDuration = this.getCalculatedDuration(values.courseStartDate, values.courseEndDate);
// set the visual data of this course
this._startDateValue.setHTML(values.courseStartDate.format(this._dateFormat, this._monthsTranslations));
this._endDateValue.setHTML(values.courseEndDate.format(this._dateFormat, this._monthsTranslations));
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
// set the session number
this._session = this._courseDetails.sessions.indexOf(values);
// if the session hasn't been found (when the course is populated)
if (this._session == -1) {
this._courseDetails.sessions.each(function(item, index) {
if (item.courseStartDate.format(this._dateFormat, this._monthsTranslations) == values.courseStartDate.format(this._dateFormat, this._monthsTranslations)) {
this._session = index;
}
}.bind(this));
}
// refresh the valid course list for this period
if (this.isComplete()) {
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._parent.fireEvent('refreshCourses');
this._parent.fireEvent('refreshPrice');
}
},
/**
* Replace the courses and find the best possible dates
*
* @param Number newCourseId  The new course ID
*/
replaceCourse : function(newCourse) {
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
if (this._parent.getIsFixedCourse(newCourse)) {
if (this.isComplete()) {
this._courseDetails = newCourse;
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this.refreshFixedCourseData(this.getNewFixedCourseDates(this._courseStartDate));
this._title.setHTML(this._courseDetails.name);
this._subTitle.setHTML(this._courseDetails.subtitle);
this.reGenerateLists();
this._parent.fireEvent('refreshCourses');
} else {
this._schoolSessionsList.getHtml().remove();
this._coursesValidList.getHtml().remove();
this._parent.replaceCourse(this, newCourse);
}
} else {
this._schoolSessionsList.getHtml().remove();
this._coursesValidList.getHtml().remove();
if (this.isComplete()) {
var values = new Object();
values.startDate = this._courseStartDate;
values.duration = this._courseDuration;
this._parent.replaceCourse(this, newCourse, values);
} else {
this._parent.replaceCourse(this, newCourse);
}
}
},
/**
* Returns the best dates for the new fixed courses based on the old one
*
* @param Date oldStartDate The date of the replaced course
*
* @return Object The new dates session.
*/
getNewFixedCourseDates : function(oldStartDate) {
if (oldStartDate) {
var dateDifference;
var newDates;
this._courseDetails.sessions.each(function(item, index) {
if (dateDifference > Math.abs(oldStartDate - item.courseStartDate) || !dateDifference) {
dateDifference = Math.abs(oldStartDate - item.courseStartDate);
newDates = item;
}
}.bind(this));
return newDates;
}
},
/**
* Set a list of valid courses
*
* @param SchoolList list The valid courses list
*
*/
getVisualValidCoursesList : function(list) {
var validCourses = this._parent.getCourses();
// clearing the list
list.clear();
validCourses.each(function(item, index) {
list.addItem(item, item.name);
list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item');
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.replaceCourse(item);
}.bind(this));
}, this);
this.refreshVisualValidCoursesList(list);
},
/**
* Refresh a list of course that have possible dates between this courseStartDate and courseEndDate
*
* @param SchoolList list The valid courses list
*
*/
refreshVisualValidCoursesList : function(list) {
var validCourses = this._parent.getValidCourses(this);
list.getListItems().each(function(item, index) {
if (validCourses.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
} else {
item.setIsValid(false);
}
}.bind(this));
},
/**
* Generate a formated list from an array of a fixed course start dates
*
* @param Array startDates An array of Date containing all the possible startDates
* @param SchoolList list The valid courses list
*/
getVisualFixedCourseStartDates : function(startDates, list) {
var firstValid = true;
var index = 0;
// clearing the list
list.clear();
startDates.each(function(item, index) {
list.addItem(item, item.courseStartDate.format(this._dateFormat, this._monthsTranslations));
index = list.getListItems().indexOf(list.getListItems().getLast());
list.getListItems().getLast().getHtml().addEvent('click', function() {
if (list.getListItems()[index].getIsSelectionnable())this.refreshFixedCourseData(item);
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.noValidStartDates);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Refresh a list from an array of a fixed course start dates
*
* @param Array validStartDates An array of Date containing the validated startDates
* @param SchoolList list The valid courses list
*/
refreshVisualFixedCourseStartDates : function(validStartDate, list) {
var firstValid = true;
list.getListItems().each(function(item, index) {
if (validStartDate.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (firstValid)list.setSelectedItem(item);
if (this._courseStartDate == item.getValue().courseStartDate) list.setSelectedItem(item);
firstValid = false;
} else {
if (item.getValue == 'error')item.setIsValid(false);
item.setIsSelectionnable(false);
}
}.bind(this));
},
/**
* Return the duration in weeks.
* To perform the calculation we count the number of time the week day of the start date
* can be repeated between the start date and the end date.
*
* @param date startDate The start date
* @param date endDate The end date
* @return integer the number of weeks
*/
getCalculatedDuration : function(startDate, endDate) {
startDate = startDate.getTime();
endDate = endDate.getTime() - (86400 * 3 *1000) ;
var numberOfWeeks = 0;
while (startDate <= endDate) {
numberOfWeeks++;
startDate += (86400 * 7 * 1000);
}
return numberOfWeeks;
},
/**
*  Returns the available accommodations for this course
*
* @return Array of integer The Accommodation IDs
*/
getAvailableAccommodations : function() {
return this._courseDetails.availableAccommodations;
},
/**
*  return the course duration
*
* @return integer The course duration
*/
getCourseDuration : function() {
return this._courseDuration;
},
/**
* Returns true if it's a fixed course
*
* @return Boolean Return true because it's a fixed course
*/
getIsFixedCourse : function() {
return true;
},
/**
* This function remove the course from the list
*
*/
removeCourse : function() {
this._schoolSessionsList.getHtml().remove();
this._coursesValidList.getHtml().remove();
this._container.remove();
}
});
/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param number id the insurance ID
* @param char name the insurance name
* @param SchoolInsurances parent
**/
var SchoolInsuranceObject = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, insuranceDTO, translateDTO, parent) {
this._translateDTO = translateDTO;
this._insuranceDTO = insuranceDTO;
this._insuranceName = this._insuranceDTO.name;
this._type = this._insuranceDTO.type;
this._insuranceId = id;
this._parent = parent;
this._classNameBase = this._parent.getClassNameBase();
this._isMandatory = false;
this._insuranceStartDate = null;
this._insuranceEndDate = null;
this._insuranceDuration = null;
this._manager = this._parent.getParent();
this._manager.addEvent('descriptionsUpdated', function() {
this.updateDescriptions();
}.bind(this));
},
/**
* Generate the Html structure of this insurance
*/
createVisualInsurance : function() {
this._container = new Element('div', {'class': this._classNameBase + 'ItemAdded'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Item-Title'});
this._moreInfo = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle MoreInfos'});
this._moreInfo.setStyle('display', 'none');
this._startDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-StartDate-Container'});
this._endDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-EndDate-Container'});
this._startDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._startDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._endDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._endDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._durationContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-Duration-Container'});
this._duration = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._durationValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._deleteButton = new Element('div', {'class': this._classNameBase + 'Section-Item-DeleteButton'});
this._duration.injectInside(this._durationContainer);
this._durationValue.injectInside(this._durationContainer);
this._startDate.injectInside(this._startDateContainer);
this._startDateValue.injectInside(this._startDateContainer);
this._endDate.injectInside(this._endDateContainer);
this._endDateValue.injectInside(this._endDateContainer);
this._title.injectInside(this._container);
this._moreInfo.injectInside(this._container);
new Element('div', {'style':'clear:both'}).injectInside(this._container);
this._startDateContainer.injectInside(this._container);
this._endDateContainer.injectInside(this._container);
this._durationContainer.injectInside(this._container);
this._deleteButton.injectInside(this._container);
new Element('div', {'style':'clear:both'}).injectInside(this._container);
this._title.setHTML(this._insuranceName);
this._startDate.setHTML(this._translateDTO.startDate);
this._moreInfo.setHTML(this._translateDTO.moreInfos);
this._startDateValue.setHTML(this._translateDTO.dateSelect);
this._endDate.setHTML(this._translateDTO.endDate);
this._endDateValue.setHTML(this._translateDTO.endDateValue);
this._duration.setHTML(this._translateDTO.duration);
this._durationValue.setHTML(this._translateDTO.durationSelect);
this._deleteButton.setHTML(this._translateDTO.deleteButton);
// add event listener
this._deleteButton.addEvent('click', function(e) {
this.removeInsurance();
this.fireEvent('deleteInsurance');
}.bind(this));
this.updateDescriptions();
this._insuranceList = new SchoolList(this._title, this._classNameBase);
this.getVisualInsuranceList(this._insuranceList);
this._insuranceList.getHtml().injectInside(this._parent.getParent().getListContainer());
this._insuranceList.initializeEvents();
},
getInsuranceInformations : function() {
return this._insuranceDTO;
},
updateDescriptions : function() {
if (this._manager.getDescription && this._manager.getDescription('insurance', this._insuranceId) && this._manager.getDescription('insurance', this._insuranceId) != '') {
this._moreInfo.setAttribute('title', this._insuranceName + ' :: ' + this._manager.getDescription('insurance', this._insuranceId));
this._moreInfo.setStyle('display', '');
if (!this._descriptionToolTip) {
this._descriptionToolTip = new SynergeeTips(this._moreInfo, {'className':'PriceEstimationToolTip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
} else {
this._descriptionToolTip.build(this._moreInfo);
}
} else {
this._moreInfo.setStyle('display', 'none');
}
},
/**
* Returns an object containing the informations for the calculation price
*
* @return object The informations needed to calculate the price
*/
getDTO : function() {
var insuranceDTO = new Object();
insuranceDTO.id = this._insuranceId;
return insuranceDTO;
},
/**
* Return the insurance ID
*
* @return integer The Insurance ID
*/
getInsuranceId : function() {
return parseInt(this._insuranceId);
},
/**
* Populate the insurance from a dto
*/
populateFromDTO : function(toPopulateDTO) {
// there is nothing to populate in fact
},
setMandatory : function(mandatory) {
this._isMandatory = mandatory;
if (this._isMandatory) {
this._deleteButton.setStyle('display', 'none');
} else {
this._deleteButton.setStyle('display', '');
}
},
/**
* Set the dates of the insurance
* @param Date startDate The Start Date
* @param Date endDate The End Date
*/
setDates : function(startDate, endDate, duration) {
this._insuranceStartDate = startDate;
if (endDate)endDate.setDate(endDate.getDate() + this._insuranceDTO.additionalMandatoryDays);
this._insuranceEndDate = endDate;
this._insuranceDuration = duration + this._insuranceDTO.additionalMandatoryDays;
this.refreshInsuranceInterface();
},
/**
* Return true if the insurance is complete
*
* @return Boolean Return true if complete
*/
isComplete : function() {
if (this._insuranceStartDate && this._insuranceEndDate && this._insuranceDuration)return true;
return false;
},
/**
* Returns the HTML structure of this course
*
* @return Element the insurance element
*/
getHtml : function() {
return this._container;
},
/**
* Generate the list of insurances for this school
*
* @param schoolList list The list to update
*/
getVisualInsuranceList : function(list) {
list.clear();
this._parent._schoolInsurancesDTO.each(function(item, index) {
list.addItem(item.id, item.name);
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.setInsurance(item);
}.bind(this));
}.bind(this));
if (!this._parent._schoolInsurancesDTO || this._parent.getParent().getCompletedCourses().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
this.refreshVisualInsuranceList();
},
/**
* refresh the list of insurances for this school
*
*/
refreshVisualInsuranceList : function() {
this._parent.refreshVisualInsuranceList(this._insuranceList);
},
/**
* Refresh the visual interface of this insurance
*
*/
refreshInsuranceInterface : function() {
if (this._insuranceStartDate && this._insuranceEndDate) {
this._startDateValue.setHTML(this._insuranceStartDate.format(this._parent.getParent().getDateFormat(), this._parent.getParent().getMonthTranslations()));
this._endDateValue.setHTML(this._insuranceEndDate.format(this._parent.getParent().getDateFormat(), this._parent.getParent().getMonthTranslations()));
if (this._insuranceDuration > 1) {
this._durationValue.setHTML(this._translateDTO.days.replace("%0", this._insuranceDuration));
} else {
this._durationValue.setHTML(this._translateDTO.day.replace("%0", this._insuranceDuration));
}
}
},
/**
* Replace the insurance with the one given in parameter
*
* @param Object insurance The insurance DTO
*/
setInsurance : function(insurance) {
this._insuranceName = insurance.name;
this._insuranceId = insurance.id;
this._type = insurance.type;
this._insuranceDTO = insurance;
this._title.setHTML(this._insuranceName);
this.updateDescriptions();
// the check will be done again by the insurances container
this.setMandatory(false);
this.fireEvent('refreshPrice');
},
/**
* Generate the options list for a insurance
* and set an event on each option
*
* @param SchoolList The list to update
*/
getVisualInsuranceOptionsList : function(list) {
list.clear();
list.getListItems().each(function(item, index) {
item.getHtml().addClass(this._classNameBase + 'List-Item');
item.getHtml().addEvent('click', function() {
this._parent.getParent().fireEvent('refreshPrice');
}.bind(this));
}.bind(this));
},
/**
* Remove the insurance from the list
*
*/
removeInsurance : function() {
this._container.remove();
}
});
/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param InsuranceListItemDTO schoolInsurancesDTO the insurances informations
* @param Object translateDTO The DTO containing the translations for this class
* @param SchoolPriceEstimation parent the parent
**/
var SchoolInsurances = Events.extend({
/**
* This is the initialization function
*/
initialize : function(schoolInsurancesDTO, translateDTO, parent) {
this._schoolInsurancesDTO = schoolInsurancesDTO;
this._schoolInsurancesDTO = new Hash();
if (schoolInsurancesDTO) {
for (var i = 0; i < schoolInsurancesDTO.length; i++) {
this._schoolInsurancesDTO.set(schoolInsurancesDTO[i].id, schoolInsurancesDTO[i]);
}
}
this._translateDTO = translateDTO;
this._parent = parent;
this._classNameBase = this.getParent().getClassNameBase();
this._insurances = new Array();
this._mandatoryInsurances = new Array();
this._defaultCheckedInsurances = new Array();
this._schoolInsurancesDTO.each(function(item, index) {
if (item.mandatory) {
this._mandatoryInsurances.push(item);
}
if (item.defaultChecked) {
this._defaultCheckedInsurances.push(item);
}
}.bind(this));
},
/**
* Returns the visual insurance container
*/
getHtml : function() {
this._insuranceContainer = new Element('div', {'class': this._classNameBase + 'Section'});
this._insuranceTitle = new Element('div', {'class': this._classNameBase + 'Section-Title'});
this._insuranceListContainer = new Element('div', {'class': this._classNameBase + 'Courses-CoursesList-Container'});
this._insuranceUserAccommodationList = new Element('div', {'class': this._classNameBase + 'Courses-UserCoursesList'});
this._insuranceAddButton = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._insuranceTitle.injectInside(this._insuranceContainer);
this._insuranceListContainer.injectInside(this._insuranceContainer);
this._insuranceUserAccommodationList.injectInside(this._insuranceListContainer);
this._insuranceAddButton.injectInside(this._insuranceContainer);
if (this._translateDTO) {
this._insuranceTitle.setHTML(this._translateDTO.title);
this._insuranceAddButton.setHTML(this._translateDTO.add);
}
this._insurancesList = new SchoolList(this._insuranceAddButton, this._classNameBase);
this.getVisualInsuranceList(this._insurancesList);
this._insurancesList.getHtml().injectInside(this._parent.getListContainer());
this._insurancesList.initializeEvents();
return this._insuranceContainer;
},
/**
*  Return the classNameBase
*/
getClassNameBase : function() {
return this._classNameBase;
},
/**
* Returns an array containing the informations for the calculation price
*
* @return Array The informations needed to calculate the price
*/
getDTO : function() {
var insurancesDTO = new Array();
this._insurances.each(function(item, index) {
if (item.isComplete()) {
insurancesDTO.push(item.getDTO());
}
}.bind(this));
return insurancesDTO;
},
/**
* Populate the insurances from a dto
*/
populateFromDTO : function(toPopulateDTO) {
if (toPopulateDTO) {
toPopulateDTO.each(function(item, index) {
this.addInsurance(item.id, true);
}.bind(this));
}
},
/**
* Retrieve the list of insurances for this school
*
* @param schoolList list The list to update
*/
getVisualInsuranceList : function(list) {
list.clear();
this._schoolInsurancesDTO.each(function(item, index) {
list.addItem(item.id, item.name);
list.getListItems().getLast().setIsValid(true);
list.getListItems().getLast().setIsSelectionnable(true)
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.addInsurance(item.id);
}.bind(this));
}.bind(this));
this.refreshVisualInsuranceList(list);
},
/**
* Refresh the list of insurances for this school
*
* @param schoolList list The list to update
* @param availabilityItem boolean True if there is a last item to be used
*/
refreshVisualInsuranceList : function(list) {
var validListItem = 0;
list.getListItems().each(function(item, index) {
if (this._duration && (this._schoolInsurancesDTO.get(item.getValue()).availableFrom <= this._duration) &&  !this.isAdded(parseInt(item.getValue()))) {
item.setIsValid(true);
item.setIsSelectionnable(true);
validListItem++;
} else {
item.setIsValid(false);
}
}.bind(this));
if(validListItem){
this._insuranceAddButton.setStyle('display','');
}else {
this._insuranceAddButton.setStyle('display','none');
}
},
/**
* Refresh the value of the insurances (all insurances have the same duration)
*/
refreshValues : function() {
this._startDate = this.getInsuranceStartDate();
this._endDate = this.getInsuranceEndDate();
this._courseStartDate = this.getInsuranceStartDate(true);
this._courseEndDate = this.getInsuranceEndDate(true);
this._duration = this.getCalculatedDuration(this._startDate, this._endDate);
this._courseDuration = this.getCalculatedDuration(this._courseStartDate, this._courseEndDate);
if (this._insurances) {
for (var i = 0; i < this._insurances.length; i++) {
// Check if the insurance is calculated from the duration of the course
if(this._insurances[i].getInsuranceInformations().durationCalculationMethod == 1){
this._insurances[i].setDates(new Date(this._courseStartDate), new Date(this._courseEndDate), this._courseDuration);
} else {
this._insurances[i].setDates(new Date(this._startDate), new Date(this._endDate), this._duration);
}
}
}
},
/**
* Return the insurance start date calculated from the course and accommodation
*/
getInsuranceStartDate : function(courseOnly) {
if(!courseOnly)courseOnly = false;
return this._parent.getStartDate(courseOnly);
},
/**
* Return the insurance start date calculated from the course and accommodation
*/
getInsuranceCourseStartDate : function(courseOnly) {
if(!courseOnly)courseOnly = false;
return this._parent.getCourseStartDate(courseOnly);
},
/**
* Return the insurance end date calculated from the course and accommodation
*/
getInsuranceEndDate : function() {
return this._parent.getEndDate();
},
/**
* Return the durationof the insurance
*/
getInsuranceDuration : function() {
return this._duration;
},
/**
* Return the duration in days.
* To perform the calculation we count the number of time the week day of the start date
* can be repeated between the start date and the end date.
*
* @param date startDate The start date
* @param date endDate The end date
* @return integer the number of Days
*/
getCalculatedDuration : function(startDate, endDate) {
var numberOfDays = 0;
// The number of milliseconds in one day
var oneDay = 1000 * 60 * 60 * 24;
if (startDate && endDate && startDate.getTime && endDate.getTime) {
startDate = startDate.getTime();
endDate = endDate.getTime() + 1000;
var differenceMs = Math.abs(startDate - endDate)
numberOfDays = (Math.round(differenceMs/oneDay)) + 1;
}
return numberOfDays;
},
/**
* Refresh the insurances lists
*
*/
refreshInsurances : function() {
this.refreshValues();
var transfNb = this._insurances.length;
this.refreshVisualInsuranceList(this._insurancesList);
// refresh every insurance list for the added insurances
this._mandatoryInsurances.each(function(item, index) {
if (!this.isAdded(item.id)) {
var minDuration = (parseInt(item.mandatoryFrom) ? parseInt(item.mandatoryFrom) : 0);
var addedInsurance = null;
if (this._duration > 0 && minDuration <= this._duration) {
this.addInsurance(item.id);
if (addedInsurance = this.getAddedInsurance(item.id)) {
addedInsurance.setMandatory(true);
}
}
} else {
var minDuration = (parseInt(item.mandatoryFrom) ? parseInt(item.mandatoryFrom) : 0);
if (minDuration > this._duration) {
if (addedInsurance = this.getAddedInsurance(item.id)) {
addedInsurance.setMandatory(false);
}
}
}
}.bind(this));
// removing the insurances that are not meeting the min weeks
this._insurances.each(function(item, index){
if(this._schoolInsurancesDTO.get(item.getInsuranceId()).availableFrom > this._duration){
item.removeInsurance();
this._insurances.remove(item);
}
}.bind(this));
// remove all the insurance if there are no more course on the quote
if (this._parent.getCompletedCourses().length == 0) {
for (var i = this._insurances.length - 1; i >= 0; i--) {
this._insurances[i].removeInsurance();
this._insurances.remove(this._insurances[i]);
}
this._parent.fireEvent('heightModified');
if (transfNb > 0)this._parent.fireEvent('refreshPrice');
}else {
this._defaultCheckedInsurances.each(function(item, index) {
if (!this.isAdded(item.id)) {
this.addInsurance(item.id);
}
this._defaultCheckedInsurances.remove(item);
}.bind(this))
}
// refresh every insurance list for the added insurances
if (this._insurances) {
for (var i = 0; i < this._insurances.length; i++) {
this._insurances[i].refreshVisualInsuranceList();
}
}
},
/**
* Add a insurance from its ID
*
* @param Number id The insurance id
*/
addInsurance : function(id, noTest) {
if (this._schoolInsurancesDTO.hasKey(id) && (this._schoolInsurancesDTO.get(id).availableFrom <= this._duration  || noTest)  && !this.isAdded(id)) {
var schoolInsurance = this._schoolInsurancesDTO.get(id);
var newInsurance = new SchoolInsuranceObject(schoolInsurance.id, schoolInsurance, this._translateDTO.insuranceObject, this);
newInsurance.addEvent('refreshPrice', this.refreshPrice.bind(this));
this._insurances.push(newInsurance);
newInsurance.createVisualInsurance();
this._insurances.getLast().getHtml().injectInside(this._insuranceUserAccommodationList);
newInsurance.addEvent('deleteInsurance', function(e) {
this.deleteInsurance(newInsurance);
}.bind(this));
this.refreshPrice();
}
},
refreshPrice: function() {
this.fireEvent('refreshPrice');
},
/**
* Returns the parent of this object
*
* @return SchoolPriceEstimation The parent
*/
getParent : function() {
return this._parent;
},
/**
* Display or hide the add button
*
* @param boolean isDisplayed True to display the hide button
*/
displayAddButton : function(isDisplayed) {
if (isDisplayed) {
this._insuranceAddButton.setStyle('display', 'block');
} else {
this._insuranceAddButton.setStyle('display', 'none');
}
},
/**
* Returns the number of completed insurances
*
* @return Number The number of completed insurances
*/
getCompletedInsurances : function() {
return this._insurances;
},
/**
* Test if the insurance is added
*
* @param insuranceId The insurance id
*
* @return Boolean True if the insurance is added
*/
isAdded : function (insuranceId) {
insuranceId  = parseInt(insuranceId);
if (this._insurances) {
for (var i = 0; i < this._insurances.length; i++) {
if (this._insurances[i].getInsuranceId() == insuranceId)return true;
}
}
return false;
},
/**
* Return the added insurance from its id
* @param insuranceId integer The insurance ID
*
* @return SchoolInsuranceObject The insurance object
*
*/
getAddedInsurance : function (insuranceId) {
if (this._insurances) {
for (var i = 0; i < this._insurances.length; i++) {
if (this._insurances[i].getInsuranceId() == parseInt(insuranceId))return this._insurances[i];
}
}
return false;
},
/**
* Delete the given insurance
*
* @param SchoolInsuranceObject insurance The insurance to delete
*/
deleteInsurance : function(insurance) {
this._insurances.remove(insurance);
this._parent.fireEvent('heightModified');
this._parent.fireEvent('refreshPrice');
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param Element button the button attached to the list
*
**/
var SchoolList = Events.extend({
/**
* This is the initialization function
*/
initialize : function(button, classNameBase) {
this._classNameBase = classNameBase;
this._listItems = new Array();
this._button = button;
this._list = this.setHtml();
this._list.setStyle('display', 'none');
this._selectedItem = -1;
this._buttonEventInitialized = false;
},
/**
* return true if the event on the list button is initialized
*
* @return boolean True if initialized
*/
getButtonEventInitialized : function() {
return this._buttonEventInitialized;
},
/**
*  Create the HTML structure
*
* @return Element The div container
*/
setHtml : function() {
return new Element('div', {'class': this._classNameBase + 'List', 'style':'display:none'});
},
/**
* This method add an element to the list
*
* @param Object value The value of the item
* @param String html The html value of the item
*/
addItem : function(value, html) {
var newItem = new SchoolListItem(value, html, this._classNameBase);
this._listItems.push(newItem);
newItem._listItem.injectInside(this._list);
},
/**
* This method add an element to the list
*
* @param SchoolListItem listItem The school list item
*/
addListItem : function(schooListItem) {
this._listItems.push(schooListItem);
schooListItem._listItem.injectInside(this._list);
},
/**
* this method clear the list
*/
clear : function() {
this._listItems = new Array();
this._list = this.setHtml();
},
/**
* This method return the list html formatted
*
* @return Element The list element
*/
getHtml : function() {
return this._list;
},
/**
* This method return the listItem Array
*
* @return Array The array containing all the list items
*/
getListItems : function() {
return this._listItems;
},
/**
* Returns the valid list items
*
* @return SchoolListItem[] The valid list items
*/
getValidListItems : function() {
var listItems = new Array();
this._listItems.each(function(item, index) {
if (item.getIsValid()) {
listItems.push(item);
}
;
});
return listItems;
},
/**
* Returns the height of a valid Item
*
* @return Number The height of a valid Item
*/
getItemHeight : function() {
var test = false;
var height = 0;
var i = 0;
while (!test) {
height = this._listItems[i].getHtml().getCoordinates().height;
test = this._listItems[i].getIsValid();
i++;
}
;
return height;
},
/**
* Returns the height of a list
*
* @return Number The height of this school list
*/
getListHeight : function() {
var height = 0;
this._listItems.each(function(item, index) {
if (item.getIsValid()) {
height = height + item.getHtml().getCoordinates().height;
}
});
return height;
},
/**
* This method set the item the list has to scroll to
*
* @param SchoolListItem item The item the list has to scroll to
*/
setSelectedItem : function(item) {
if (this._selectedItem != -1){
if(this._listItems[this._selectedItem])this._listItems[this._selectedItem].getHtml().removeProperty('id');
}
this._selectedItem = this._listItems.indexOf(item);
if(this._listItems[this._selectedItem])this._listItems[this._selectedItem].getHtml().setProperty('id', 'firstValid');
},
/**
*  Initialize the main events for this list
*/
initializeEvents : function() {
//        if (this.getValidListItems().length) {
var myTimer = -1;
// add the mouseleave event on the list
this.getHtml().addEvent('mouseleave', function() {
myTimer = this.getHtml().setStyles.delay(500, this.getHtml(), {'visibility':'hidden','display':'none', 'z-index':0});
}.bind(this));
this.getHtml().addEvent('mouseover', function() {
$clear(myTimer);
});
this._listItems.each(function(item, index) {
item.getHtml().addEvent('click', function() {
if (item.getIsSelectionnable() && !(item.getValue() == 'category' || item.getValue() == 'error' )) {
this.getHtml().setStyle('visibility', 'hidden');
this.getHtml().setStyle('display', 'none');
this.getHtml().setStyle('height', '0px');
}
}.bind(this));
}.bind(this));
// add an event on the button to appear the list
this.addButtonEvent();
//        }
},
/**
* Return the list button
*/
getButton : function(){
return this._button;
},
/**
* add the event on the list button
*/
addButtonEvent : function(){
if(!this._buttonEventInitialized)this._button.addEvent('click', this.buttonClickEvent.bind(this));
this._buttonEventInitialized = true;
},
/**
*  remove the button event for this button
*/
removeButtonEvent : function() {
if(this._buttonEventInitialized)this._button.removeEvent('click', this.buttonClickEvent.bind(this));
if(this._buttonEventInitialized)this._button.removeEvents();
this._buttonEventInitialized = false;
},
/**
* method to call when the button is clicked
*/
buttonClickEvent : function() {
// add an event on the button to appear the list
var scroll = new Fx.Scroll(this._list);
var listHeight = parseInt(this.getHtml().getStyle('max-height'));
if (!listHeight) listHeight = 165;
this.getHtml().setStyle('height', '0px');
if(window.ie6){
this.getHtml().setStyle('width', this._button.getCoordinates().width + 'px');
}else{
this.getHtml().setStyle('min-width', this._button.getCoordinates().width + 'px');
}
this.setPosition();
this.getHtml().setStyle('display', 'block');
// the list is scrolled to the first valid element
if (this.getHtml().getElements('div[id=firstValid]')[0]) {
scroll.toElement(this.getHtml().getElements('div[id=firstValid]')[0]);
}
// set the overflow-y auto if the list is taller than the list
if (this.getListHeight() > listHeight) {
this.getHtml().setStyle('overflow-y', 'auto');
if(window.ie6){
this.getHtml().setStyle('width', (parseInt(this.getHtml().getStyle('width')) + 15) + 'px');
}else{
this.getHtml().setStyle('min-width', (parseInt(this.getHtml().getStyle('width')) + 15) + 'px');
}
new Fx.Style(this.getHtml(), 'height', {transition : Fx.Transitions.Quart.easeOut}).start('0', (listHeight) + 'px');
} else {
new Fx.Style(this.getHtml(), 'height', {transition : Fx.Transitions.Quart.easeOut}).start('0', this.getListHeight() + 'px');
}
this.getHtml().setStyle('visibility', 'visible');
this.getHtml().setStyle('z-index', 1000);
},
deleteList : function(){
this.removeButtonEvent();
if(this.getHtml().getParent())this.getHtml().remove();
},
/**
* This function Set the list position relative to its button
*
*/
setPosition : function() {
//        if(window.ie7){
//            this._list.setStyle('left', this._button.getBoundingClientRect().left);
//            this._list.setStyle('top', this._button.getBoundingClientRect().top);
//
//        }else{
this._list.setStyle('left', this._button.getCoordinates().left);
this._list.setStyle('top', this._button.getCoordinates().top);
//        }
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param Object value The value of the item
* @param String html The visual value of the item
*
**/
var SchoolListItem = Events.extend({
/**
* This is the initialization function
*/
initialize : function(value, html, classNameBase) {
this._classNameBase = classNameBase;
this._value = value;
this._html = html;
this.setVisualHtml();
this._isValid = true;
this._isSelectionnable = true;
},
/**
* Create the HTHML part of the item
*/
setVisualHtml : function() {
this._listItem = new Element('div');
this._listItem.setHTML(this._html);
this._listItem.listItemContainer = this;
},
/**
* set the new html value
*
* @param html String the new html value
*/
setHtml : function(html){
this._html = html;
this._listItem.setHTML(this._html);
},
/**
* Returns the element
*
* @return Element The list item
*/
getHtml : function() {
return this._listItem;
},
/**
* Returns the html value of the item
*
* @return Element The Html view of the item
*/
getHtmlValue : function() {
return this._html;
},
/**
* Returns the element value
*
* @return Object The item value
*/
getValue : function() {
return this._value;
},
/**
*  Set the validity of a list item
*
* @param Boolean validity The new validity of the list item
*/
setIsValid : function(validity) {
if (validity) {
this.getHtml().setStyle('display', 'block');
} else {
this.getHtml().setStyle('display', 'none');
}
this._isValid = validity;
},
/**
* Returns true if the item is valid
*
* @return Boolean Return true if the item is valid
*/
getIsValid : function() {
return this._isValid;
},
/**
* This method set if an item is selectionnable or not
*
* @param Boolean value Set true if the item is selectionnable
*/
setIsSelectionnable : function(value) {
if (value) {
this.getHtml().addClass(this._classNameBase + 'List-Item');
this.getHtml().removeClass(this._classNameBase + 'NotSelectionable');
} else {
this.getHtml().addClass(this._classNameBase + 'NotSelectionable');
this.getHtml().removeClass(this._classNameBase + 'List-Item');
}
this._isSelectionnable = value;
},
/**
* Returns true if the item is selectionnable
*
* @return Boolean Returns true if the item is selectionnable
*/
getIsSelectionnable : function() {
return this._isSelectionnable;
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @event Event deleteCourse This event is fired when a course is deleted
*
* @param FixedDatesCourseListItemDTO courseDetails courseDetails The object containing the course informations
* @param Object translateDTO The object containing all the translations for this class
* @param SchoolCourses parent The parent
*
**/
var SchoolOptionalCourseObject = Events.extend({
/**
* This is the initialization function
*
*/
initialize : function(courseDetails, translateDTO, listContainer, classNamePrefix, parent) {
this._translateDTO = translateDTO;
this._courseDetails = courseDetails;
this._parent = parent;
this._listContainer = listContainer;
this._classNameBase = classNamePrefix;
this._dateFormat = this._parent.getParent().getDateFormat();
this._monthsTranslations = this._parent.getParent().getMonthTranslations();
this._courseStartDate = null;
this._courseEndDate = null;
this._courseDuration = null;
this._manager = this.getParent().getParent().getParent();
this._manager.addEvent('descriptionsUpdated', function(){
this.updateDescriptions();
}.bind(this));
},
/**
* Return the course details DTO
*
* @return CourseDetailsDTO The course Details DTO
*/
getCourseDetails : function() {
return this._courseDetails;
},
/**
* Return true if the course is complete
*
* @return Boolean Return true if the course is complete
*/
isComplete : function() {
if (this._courseStartDate && this._courseEndDate && this._courseDuration) {
return true;
} else {
return false;
}
},
/**
* Generate the html structure of the course
* and add an event on the delete button
*
*/
createVisualCourse : function() {
this._container = new Element('div', {'class': this._classNameBase + 'ItemAdded'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Item-Title'});
this._subTitle = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle'});
this._moreInfo = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle MoreInfos'});
this._moreInfo.setStyle('display','none');
this._startDateContainer = new Element('div',{'class': this._classNameBase + 'Section-Item-StartDate-Container'});
this._endDateContainer = new Element('div',{'class': this._classNameBase + 'Section-Item-EndDate-Container'});
this._startDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._startDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._endDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._endDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._durationContainer = new Element('div',{'class': this._classNameBase + 'Section-Item-Duration-Container'});
this._duration = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._durationValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._deleteButton = new Element('div', {'class': this._classNameBase + 'Section-Item-DeleteButton'});
this._duration.injectInside(this._durationContainer);
this._durationValue.injectInside(this._durationContainer);
this._startDate.injectInside(this._startDateContainer);
this._startDateValue.injectInside(this._startDateContainer);
this._endDate.injectInside(this._endDateContainer);
this._endDateValue.injectInside(this._endDateContainer);
this._title.injectInside(this._container);
this._subTitle.injectInside(this._container);
this._moreInfo.injectInside(this._container);
new Element('div',{'style':'clear:both'}).injectInside(this._container);
this._startDateContainer.injectInside(this._container);
this._endDateContainer.injectInside(this._container);
this._durationContainer.injectInside(this._container);
this._deleteButton.injectInside(this._container);
new Element('div',{'style':'clear:both'}).injectInside(this._container);
this._title.setHTML(this._courseDetails.name);
this._subTitle.setHTML(this._courseDetails.subtitle);
this._moreInfo.setHTML(this._translateDTO.moreInfos);
this._startDate.setHTML(this._translateDTO.startDateOptional);
this._startDateValue.setHTML(this._translateDTO.dateSelectOptional);
this._endDate.setHTML(this._translateDTO.endDateOptional);
this._endDateValue.setHTML(this._translateDTO.endDateValueOptional);
this._duration.setHTML(this._translateDTO.durationOptional);
this._durationValue.setHTML(this._translateDTO.durationSelectOptional);
this._deleteButton.setHTML(this._translateDTO.deleteButtonOptional);
// add event listener
this._deleteButton.addEvent('click', function(e) {
this.removeCourse();
this.fireEvent('deleteCourse');
}.bind(this));
this.updateDescriptions();
this._coursesValidList = new SchoolList(this._title, this._classNameBase);
this.getVisualValidCoursesList(this._coursesValidList);
this._coursesValidList.getHtml().injectInside(this._listContainer);
this._coursesValidList.initializeEvents();
this._schoolStartList = new SchoolList(this._startDateValue, this._classNameBase);
this.getVisualOptionalCourseStartDates(this._courseDetails.startDates, this._schoolStartList);
this.refreshVisualOptionalCourseStartDates(this._parent.getValidOptionalCourseStartDate(this), this._schoolStartList);
this._schoolStartList.getHtml().injectInside(this._listContainer);
this._schoolStartList.initializeEvents();
this._schoolDurationList = new SchoolList(this._durationValue, this._classNameBase);
this.getVisualOptionalCourseDurationList(this._courseDetails.duration, this._schoolDurationList);
this.refreshVisualOptionalCourseDurationList(this._parent.getValidOptionalCourseDuration(this), this._schoolDurationList);
this._schoolDurationList.getHtml().injectInside(this._listContainer);
this._schoolDurationList.initializeEvents();
if(this._courseDetails.oneDayCourse){
this._duration.setStyle('display','none');
this._durationValue.setStyle('display','none');
}
},
/**
* Returns the html Element of this course
*
* @return Element The HTML view of this course
*/
getHtml : function() {
return this._container;
},
updateDescriptions : function(){
if (this._manager.getDescription && this._manager.getDescription('course', this._courseDetails.courseTypeId) && this._manager.getDescription('course', this._courseDetails.courseTypeId) != '') {
this._moreInfo.setAttribute('title', this._courseDetails.name + ' :: ' + this._manager.getDescription('course', this._courseDetails.courseTypeId));
this._moreInfo.setStyle('display','');
if(!this._descriptionToolTip ){
this._descriptionToolTip = new SynergeeTips(this._moreInfo, {'className':'PriceEstimationToolTip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}else {
this._descriptionToolTip.build(this._moreInfo);
}
}else {
this._moreInfo.setStyle('display','none');
}
},
/**
* Return an object containing the informations for the calculation price
*
* @return Object The informations needed to calculate the price
*/
getDTO : function() {
var courseDTO = new Object();
courseDTO.id = this._courseDetails.id;
courseDTO.startDate = this._courseStartDate.toIso();
courseDTO.endDate = this._courseEndDate.toIso();
return courseDTO;
},
/**
* Populate the variable course from a dto
*
* @param Object The fixed course informations needed to populate
*/
populateFromDTO : function(toPopulateDTO) {
this._courseStartDate = (new Date()).fromIso(toPopulateDTO.startDate);
this._startDateValue.setHTML(this._courseStartDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
this._courseEndDate = (new Date()).fromIso(toPopulateDTO.endDate);
this._courseDuration = this.getCalculatedDuration(this._courseStartDate, this._courseEndDate );
if(this._courseDetails.duration.length && this._courseDuration < parseInt(this._courseDetails.duration[0])) this._courseDuration = parseInt(this._courseDetails.duration[0]);
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
// If the start and the duration are set,  the end date is calculated
if (this._courseStartDate && this._courseDuration) {
this._courseEndDate = this.getOptionalCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
}
// when the user selects only the start date, the duration is set with the minimal value
if (this._courseStartDate && !this._courseDuration) {
this._courseDuration = this._courseDetails.duration[0];
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this._courseEndDate = this.getOptionalCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
}
},
/**
* Refresh all the lists of this course
*
*/
refreshLists : function() {
// add the list of courses that fit the start and end Date
this.refreshVisualValidCoursesList(this._coursesValidList);
// initialize the start date list and its event
this.refreshVisualOptionalCourseStartDates(this._parent.getValidOptionalCourseStartDate(this), this._schoolStartList);
// initialize the duration list and its event
this.refreshVisualOptionalCourseDurationList(this._parent.getValidOptionalCourseDuration(this), this._schoolDurationList);
},
/**
* Generate all the lists of this course
*
*/
reGenerateLists : function() {
// remove old list if exists
if (this._coursesValidList._listItems.length) {
this._coursesValidList.getHtml().remove();
this._coursesValidList.clear();
}
if (this._schoolStartList._listItems.length) {
this._schoolStartList.getHtml().remove();
this._schoolStartList.clear();
}
if (this._schoolDurationList._listItems.length) {
this._schoolDurationList.getHtml().remove();
this._schoolDurationList.clear();
}
this.getVisualValidCoursesList(this._coursesValidList);
this._coursesValidList.getHtml().injectInside(this._listContainer);
this._coursesValidList.initializeEvents();
this.getVisualOptionalCourseStartDates(this._courseDetails.startDates, this._schoolStartList);
this.refreshVisualOptionalCourseStartDates(this._parent.getValidOptionalCourseStartDate(this), this._schoolStartList);
this._schoolStartList.getHtml().injectInside(this._listContainer);
this._schoolStartList.initializeEvents();
this.getVisualOptionalCourseDurationList(this._courseDetails.duration, this._schoolDurationList);
this.refreshVisualOptionalCourseDurationList(this._parent.getValidOptionalCourseDuration(this), this._schoolDurationList);
this._schoolDurationList.getHtml().injectInside(this._listContainer);
this._schoolDurationList.initializeEvents();
},
/**
* Refresh the course data
*
*/
refreshOptionalCourseData : function() {
// If the start and the duration are set,  the end date is calculated
if (this._courseStartDate && this._courseDuration) {
this._courseEndDate = this.getOptionalCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
}
// when the user selects only the start date, the duration is set with the minimal value
if (this._courseStartDate && !this._courseDuration) {
this._courseDuration = this._courseDetails.duration[0];
this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this._courseEndDate = this.getOptionalCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
}
if (this.isComplete()) {
this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
// refresh the course list
this._parent.fireEvent('refreshCourses');
this._parent.fireEvent('refreshPrice');
}
},
/**
*  Returns the endDate of a variable course
*
* @param Date endDate The enddate to calculate
* @return Date The variable course end date
*/
getOptionalCourseEndDate : function(endDate) {
if ((this._courseDetails.courseStartDay == this._courseDetails.courseEndDay && this._courseDetails.oneDayCourse)) {
if (!endDate)endDate = new Date(this._courseStartDate);
} else {
if (!endDate)endDate = new Date(this._courseStartDate.getFullYear(), this._courseStartDate.getMonth(), this._courseStartDate.getDate() + this._courseDuration * 7);
var endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
while (endDateDay != this._courseDetails.courseEndDay) {
endDate.setDate(endDate.getDate() - 1);
endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
}
}
return endDate;
},
/**
* Replace the courses and find the best possible dates
*
* @param Object The new course DTO
*/
replaceCourse : function(newCourse) {
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
if (!this._parent.getIsFixedCourse(newCourse)) {
if (this.isComplete()) {
this._courseDetails = newCourse;
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this.replaceOptionalCourseDates(this._courseStartDate, this._courseDuration);
this._title.setHTML(this._courseDetails.name);
this._subTitle.setHTML(this._courseDetails.subtitle);
this.reGenerateLists();
this._parent.fireEvent('refreshCourses');
} else {
this._schoolStartList.getHtml().remove();
this._schoolDurationList.getHtml().remove();
this._coursesValidList.getHtml().remove();
this._parent.replaceCourse(this, newCourse);
}
} else {
this._schoolStartList.getHtml().remove();
this._schoolDurationList.getHtml().remove();
this._coursesValidList.getHtml().remove();
if (this.isComplete()) {
this._parent.replaceCourse(this, newCourse, this._courseStartDate);
} else {
this._parent.replaceCourse(this, newCourse);
}
}
this.updateDescriptions();
},
/**
* this method find the best dates and duration for the new variable course based on the old one
*
* @param Date oldStartDate the date of the replaced course
* @param number oldDuration the duration of the replaced course
*/
replaceOptionalCourseDates : function(oldStartDate, oldDuration) {
// if the start date is already set
if (oldStartDate) {
var dateDifference = null;
var newDate;
this._courseDetails.startDates.each(function(item, index) {
if (dateDifference > Math.abs(oldStartDate.getTime() - item.getTime()) || dateDifference == null) {
dateDifference = Math.abs(oldStartDate.getTime() - item.getTime());
newDate = item;
}
});
// if there is already a duration set
if (oldDuration) {
var durationDifference = null;
var newDuration;
this._courseDetails.duration.each(function(item, index) {
if (durationDifference > Math.abs(oldDuration - item) || durationDifference == null) {
durationDifference = Math.abs(oldDuration - item);
newDuration = item;
}
});
this._courseDuration = newDuration;
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
}
this._courseStartDate = newDate;
this._startDateValue.setHTML(newDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
this.refreshOptionalCourseData();
}
},
/**
* Generate a list of valid course
*
* @param SchoolList list The valid courses list
*
*/
getVisualValidCoursesList : function(list) {
var validCourses = this._parent.getOptionalCourses();
// clearing the list
list.clear();
validCourses.each(function(item, index) {
list.addItem(item, item.name);
list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item');
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.replaceCourse(item);
}.bind(this));
}, this);
this.refreshVisualValidCoursesList(list);
},
/**
* Refresh a list of course that have possible dates between this courseStartDate and courseEndDate
*
* @param SchoolList list The courses list
*
*/
refreshVisualValidCoursesList : function(list) {
var validCourses = this._parent.getValidCourses(this, true);
list.getListItems().each(function(item, index) {
if (validCourses.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
} else {
item.setIsValid(false);
}
}.bind(this));
},
/**
* This function set a formated list from an array of a course start dates
*
* @param Array startDates An array of Date containing all the possible startDates
* @param SchoolList list The valid courses list
*/
getVisualOptionalCourseStartDates : function(startDates, list) {
// clearing the list
list.clear();
startDates.each(function(item, index) {
list.addItem(item, item.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
index = list.getListItems().indexOf(list.getListItems().getLast());
list.getListItems().getLast().getHtml().addEvent('click', function() {
if (list.getListItems()[index].getIsSelectionnable()) {
// Set the variables for this course
this._courseStartDate = item;
// set the visual data of this course
this._startDateValue.setHTML(item.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
this.refreshOptionalCourseData();
}
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.noValidStartDates);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* this function refresh a list from an array of a course start dates
*
* @param Array validStartDates an array of Date containing the validated startDates
* @param SchoolList list the valid courses list
*/
refreshVisualOptionalCourseStartDates : function(validStartDate, list) {
var firstValid = true;
list.getListItems().each(function(item, index) {
if (validStartDate.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (firstValid) {
list.setSelectedItem(item);
}
if (this._courseStartDate == item.getValue()) {
list.setSelectedItem(item);
}
firstValid = false;
} else {
if (item.getValue == 'error') {
item.setIsValid(false);
}
item.setIsSelectionnable(false);
}
}.bind(this));
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* This function return a formated list from an array of duration
*
* @param Array durations An array of Date containing the startDates
* @param Array validDurations An array of number containing the validated durations
*/
getVisualOptionalCourseDurationList : function(durations, list) {
// clearing the list
list.clear();
durations.each(function(item, index) {
if (item > 1) {
list.addItem(item, this._translateDTO.weeks.replace('%0', item));
} else {
list.addItem(item, this._translateDTO.week.replace('%0', item));
}
index = list.getListItems().indexOf(list.getListItems().getLast());
// adding the event on the valid courses
list.getListItems().getLast().getHtml().addEvent('click', function() {
if (list.getListItems()[index].getIsSelectionnable()) {
this._courseDuration = item;
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this.refreshOptionalCourseData();
}
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.noValidDuration);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* This function return a formated list from an array of duration
*
* @param Array validDurations An array of number containing the validated durations
* @param SchoolList list The list to refresh
*/
refreshVisualOptionalCourseDurationList : function(validDurations, list) {
var firstValid = true;
list.getListItems().each(function(item, index) {
if (validDurations.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (firstValid)list.setSelectedItem(item);
if (this._courseDuration == item.getValue()) list.setSelectedItem(item);
firstValid = false;
} else {
if (item.getValue == 'error')item.setIsValid(false);
item.setIsSelectionnable(false);
}
}.bind(this));
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Return the duration in weeks.
* To perform the calculation we count the number of time the week day of the start date
* can be repeated between the start date and the end date.
*
* @param date startDate The start date
* @param date endDate The end date
* @return integer the number of weeks
*/
getCalculatedDuration : function(startDate, endDate) {
startDate = startDate.getTime();
endDate = endDate.getTime() - (86400 * 3 *1000) ;
var numberOfWeeks = 0;
while(startDate <= endDate) {
numberOfWeeks++;
startDate += (86400 * 7 * 1000);
}
return numberOfWeeks;
},
/**
*  Returns the available accommodations for this course
*
* @return Array of integer The Accommodation IDs
*/
getAvailableAccommodations : function() {
return this._courseDetails.availableAccommodations;
},
/**
*  return the course duration
*
* @return integer The course duration
*/
getCourseDuration : function() {
return this._courseDuration;
},
/**
*  set the course duration
*
* @param integer duration The course duration
*/
setCourseDuration : function(duration) {
this._courseDuration = duration;
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
},
/**
* return the course start date
*
* @return Date The course start date
*/
getCourseStartDate : function() {
return this._courseStartDate;
},
/**
* return the course start date
*
* @return Date The course start date
*/
getCourseEndDate : function() {
return this._courseEndDate;
},
/**
*  set the course duration
*
* @param integer duration The course duration
*/
setCourseStartDate : function(startDate) {
this._courseStartDate = startDate;
this._startDateValue.setHTML(this._courseStartDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
},
/**
* Returns false is it's not a fixed course
*
* @return Boolean Return false because it's a variable course
*/
getIsFixedCourse : function() {
return false;
},
/**
* return the parent
*
* @return SchoolCourses The parent
*/
getParent : function() {
return this._parent;
},
/**
* Remove the course from the list
*
*/
removeCourse : function() {
this._schoolStartList.getHtml().remove();
this._schoolDurationList.getHtml().remove();
this._coursesValidList.getHtml().remove();
this._container.remove();
}
});
/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param TransferListItemDTO schoolTransfersDTO the transfers informations
* @param SchoolPriceEstimation parent the parent
**/
var SchoolParticipants = Events.extend({
/**
* This is the initialization function
*/
initialize : function(translateDTO, enabled, parent) {
this._translateDTO = translateDTO;
this._enabled = enabled;
this._parent = parent;
this._classNameBase = this._parent.getClassNameBase();
this._participant = 1;
},
/**
* return the visual transfer container
*/
getHtml : function() {
this._participantContainer = new Element('div', {'class': this._classNameBase + 'Participants-Section'});
this._participantTitle = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title'});
this._participantTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text'});
this._participantTitleText.injectInside(this._participantTitle);
this._participantButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._participantButtons.addClass( this._classNameBase + 'ParticipantsButton');
this._participantTitle.injectInside(this._participantContainer);
this._participantTitleText.setHTML(this._translateDTO.title);
this._participantButtons.setHTML('1');
this._participantButtons.injectInside(this._participantTitle);
this._participantsList = new SchoolList(this._participantButtons, this._classNameBase);
this.createVisualList(this._participantsList);
this._participantsList.getHtml().injectInside(this._parent.getListContainer());
this._participantsList.initializeEvents();
if(!this._enabled){
this._participantContainer.setStyle('display', 'none');
}
return this._participantContainer;
},
/**
* Generate the list of participants
*
* @param SchoolList list The list to update
*/
createVisualList : function(list) {
for (var i = 1; i < 50; i++) {
if(i > 1){
list.addItem(i, i);
} else{
list.addItem(i, i);
}
}
list.getListItems().each(function(item, index) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (item.getValue() == this._participant) {
list.setSelectedItem(item);
}
item.getHtml().addEvent('click', function(event) {
this._participantButtons.setHTML(item.getHtmlValue());
this._participant = item.getValue();
this._parent.refreshAccommodations();
this._parent.fireEvent('refreshPrice');
list.setSelectedItem(item);
}.bind(this));
}.bind(this));
},
/**
* Returns the number of participant
*
* @return number The number of participants
*/
getParticipant : function() {
if(!this._participant)this._participant = 1;
return this._participant;
},
setParticipant : function(participants){
this._participant  = participants;
this._participantButtons.setHTML(participants);
//        this._participantButtons.setHTML(participants + (participants > 1? " "+this._translateDTO.participants : " "+this._translateDTO.participant));
}
});/**
* This class is used for the price calculation functionnalities DTO
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
**/
var SchoolPriceCalculatorDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function() {
this.dateFormat = '';
this.schoolInformations = '';
this.schoolFixedDatesCourses = new Array();
this.schoolVariableDatesCourses = new Array();
this.schoolOptionalCourses = new Array();
this.schoolAccommodations = new Array();
this.schoolTransfers = new Array();
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var SchoolInformationDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(schoolGroupID, vacationAndHolidays) {
this.schoolGroupID = schoolGroupID;
this.vacationAndHolidays = vacationAndHolidays;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var FixedDatesCourseListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, sessions, subtitle, accommodationMandatory, transferMandatory, availableAccommodations, position, availableOptionalCourses, courseTypeId) {
this.id = id;
this.type = 'fixedDate';
this.name = name;
this.sessions = sessions;
this.subtitle = subtitle;
this.accommodationMandatory = accommodationMandatory;
this.transferMandatory = transferMandatory;
this.availableAccommodations = availableAccommodations;
this.position = position;
this.availableOptionalCourses = availableOptionalCourses;
this.courseTypeId = courseTypeId;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var FixedDatesCourseSessionListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(courseStartDate, courseEndDate, accommodationStartDate, accommodationEndDate) {
this.courseStartDate = courseStartDate;
this.courseEndDate = courseEndDate;
this.accommodationStartDate = accommodationStartDate;
this.accommodationEndDate = accommodationEndDate;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var VariableDatesCourseListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, startDates, duration, courseStartDay, courseEndDay, subtitle,  accommodationMandatory, transferMandatory, availableAccommodations, position, availableOptionalCourses, availabilities, courseTypeId) {
this.id = id;
this.type = 'variableDate';
this.name = name;
this.startDates = startDates;
this.duration = duration;
this.courseStartDay = courseStartDay;
this.courseEndDay = courseEndDay;
this.subtitle = subtitle;
this.accommodationMandatory = accommodationMandatory;
this.transferMandatory = transferMandatory;
this.availableAccommodations = availableAccommodations;
this.position = position;
this.availableOptionalCourses = availableOptionalCourses;
this.availabilities = availabilities;
this.courseTypeId = courseTypeId;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var OptionalCourseListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, startDates, duration, courseStartDay, courseEndDay, subtitle, position, availabilities, oneDayCourse, courseTypeId, additionalDays) {
this.id = id;
this.type = 'optional';
this.name = name;
this.startDates = startDates;
this.duration = duration;
this.courseStartDay = courseStartDay;
this.courseEndDay = courseEndDay;
this.subtitle = subtitle;
this.position = position;
this.availabilities = availabilities;
this.oneDayCourse = oneDayCourse;
this.courseTypeId = courseTypeId;
this.additionalDays = (additionalDays ? parseInt(additionalDays) : 0);
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var AccommodationOptionListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, minimumDurationInWeeks, minimumNumberOfPeople, accommodationStartDay, accommodationEndDay, availabilities, noAccommodation) {
this.id = id;
this.name = name;
this.minimumDurationInWeeks = minimumDurationInWeeks;
this.minimumNumberOfPeople = minimumNumberOfPeople;
this.accommodationStartDay = accommodationStartDay;
this.accommodationEndDay = accommodationEndDay;
this.availabilities = availabilities;
this.noAccommodation = noAccommodation;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var AccommodationListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, option, availableTransfers, accommodationType ) {
this.id = id;
this.name = name;
this.option = option;
this.availableTransfers = availableTransfers;
this.accommodationType = accommodationType ? parseInt(accommodationType): 0;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var TransferListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, type) {
this.id = id;
this.name = name;
this.type = type;
}
});
/**
* This class is used for the price calculation functionalities
*
**/
var InsuranceListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name,defaultChecked, mandatory, availableFrom, mandatoryFrom, additionalMandatoryDays, durationCalculationMethod) {
this.id = parseInt(id);
this.name = name;
this.defaultChecked = (defaultChecked ? parseInt(defaultChecked) : 0);
this.mandatory =  (mandatory ? parseInt(mandatory) : 0);
this.availableFrom = (availableFrom ? parseInt(availableFrom) : 0);
this.mandatoryFrom = (mandatoryFrom ? parseInt(mandatoryFrom) : 0);
this.additionalMandatoryDays = (additionalMandatoryDays ? parseInt(additionalMandatoryDays) : 0);
this.durationCalculationMethod = (durationCalculationMethod ? parseInt(durationCalculationMethod) : 0);
}
});
/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param TransferListItemDTO schoolTransfersDTO the transfers informations
* @param SchoolPriceEstimation parent the parent
**/
var SchoolSelector = Events.extend({
/**
* This is the initialization function
*
* @param Object translateDTO the object containing the translations for this class
* @param SchoolsListDTO schoolsList The Schools list
* @param Objec parent The class that calls this class
*/
initialize : function(translateDTO, schoolsList, parent, advancedSchoolSelector) {
this._translateDTO = translateDTO;
this._parent = parent;
this._schoolsList = schoolsList;
this._schoolsHash = new Hash();
this._cityCountryHash = new Hash();
if (advancedSchoolSelector) {
this._advancedSchoolSelector = true;
} else {
this._advancedSchoolSelector = false;
}
this._classNameBase = this._parent.getClassNameBase();
if (this._schoolsList.length == 1 && (!this._parent.getType || this._parent.getType() == 'PriceEstimation')) {
this._selectedSchoolId = this._schoolsList[0].schoolId;
} else {
this._selectedSchoolId = null;
}
},
/**
* return the visual transfer container
*/
getHtml : function() {
this._schoolSelectorContainer = new Element('div', {'class': this._classNameBase + 'Participants-Section ' + this._classNameBase + 'SchoolsSelector-Section'});
this._schoolSelectorTitle = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title ' + this._classNameBase + 'SchoolsSelector-Section-Title'});
this._schoolSelectorTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text ' + this._classNameBase + 'SchoolsSelector-Section-Title-Text'});
this._schoolSelectorTitleText.injectInside(this._schoolSelectorTitle);
this._schoolSelectorButtonsContainer = new Element('ul', {'class': this._classNameBase + 'AddSchoolMenu'});
this._schoolSelectorTitle.injectInside(this._schoolSelectorContainer);
this._schoolSelectorTitleText.setHTML(this._translateDTO.school);
if (this._schoolsList.length > 0) {
if (this._advancedSchoolSelector) {
this.programs = new Hash();
for (var i = 0; i < this._schoolsList.length; i++) {
var programId = this._schoolsList[i].schoolProgramId;
var countryCode = this._schoolsList[i].schoolCountryCode;
var cityId = this._schoolsList[i].schoolCityId;
if (!this.programs.hasKey(programId)) {
var program = new Object();
program.name = this._schoolsList[i].schoolProgramName;
program.id = this._schoolsList[i].schoolProgramId;
program.countries = new Hash();
this.programs.set(this._schoolsList[i].schoolProgramId, program);
}
if (!this.programs.get(programId).countries.hasKey(countryCode)) {
var country = new Object();
country.name = this._schoolsList[i].schoolCountryName;
country.id = countryCode;
country.cities = new Hash();
this.programs.get(programId).countries.set(countryCode, country);
}
if (!this.programs.get(programId).countries.get(countryCode).cities.hasKey(cityId)) {
var city = new Object();
city.name = this._schoolsList[i].schoolCityName;
city.id = cityId;
city.schools = new Hash();
this.programs.get(programId).countries.get(countryCode).cities.set(cityId, city);
}
if (!this._cityCountryHash.hasKey(cityId)) {
this._cityCountryHash.set(cityId, countryCode)
}
if (!this.programs.get(programId).countries.get(countryCode).cities.get(cityId).schools.hasKey(this._schoolsList[i].schoolId)) {
var school = new Object();
school.name = this._schoolsList[i].schoolName;
school.id = this._schoolsList[i].schoolId;
if (!this._schoolsHash.hasKey(school.id)) {
this._schoolsHash.set(school.id, this._schoolsList[i]);
}
this.programs.get(programId).countries.get(countryCode).cities.get(cityId).schools.set(this._schoolsList[i].schoolId, school);
}
}
this._advancedSchoolSelectorContainer = new Element('div', {'class': this._classNameBase + 'SchoolsSelector-Section-Container AdvancedSchoolSelector'});
this._programSelectorContainer = new Element('div', {'class': this._classNameBase + 'Participants-Section ' + this._classNameBase + 'SchoolsSelector-Section AdvancedSchoolSelector SchoolSelectorProgram'});
this._programSelectorTitle = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title ' + this._classNameBase + 'SchoolsSelector-Section-Title AdvancedSchoolSelector SchoolSelectorProgram'});
this._programSelectorTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text ' + this._classNameBase + 'SchoolsSelector-Section-Title-Text SchoolSelectorProgram'});
this._programSelectorTitleText.injectInside(this._programSelectorTitle);
this._programSelectorTitle.injectInside(this._programSelectorContainer);
this._programSelectorTitleText.setHTML(this._translateDTO.program);
this._programSelectorContainer.injectInside(this._advancedSchoolSelectorContainer);
this._programSelectorButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._programSelectorButtons.addClass(this._classNameBase + 'SchoolSelectorButton ' + this._classNameBase + 'Section-Item-ToUpdate');
this._programSelectorButtons.setHTML(this._translateDTO.addProgram);
this._programSelectorButtons.defaultText = this._translateDTO.addProgram;
this._programSelectorButtons.injectInside(this._programSelectorTitle);
this._programSelectorsList = new SchoolList(this._programSelectorButtons, this._classNameBase);
this.createAdvancedList(this._programSelectorsList, this.programs, 'program');
this._programSelectorsList.getHtml().injectInside(this._parent.getListContainer());
this._programSelectorsList.initializeEvents();
this._countrySelectorContainer = new Element('div', {'class': this._classNameBase + 'Participants-Section ' + this._classNameBase + 'SchoolsSelector-Section AdvancedSchoolSelector SchoolSelectorCountry'});
this._countrySelectorTitle = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title ' + this._classNameBase + 'SchoolsSelector-Section-Title AdvancedSchoolSelector SchoolSelectorCountry'});
this._countrySelectorTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text ' + this._classNameBase + 'SchoolsSelector-Section-Title-Text SchoolSelectorCountry'});
this._countrySelectorTitleText.injectInside(this._countrySelectorTitle);
this._countrySelectorTitle.injectInside(this._countrySelectorContainer);
this._countrySelectorTitleText.setHTML(this._translateDTO.country);
this._countrySelectorContainer.injectInside(this._advancedSchoolSelectorContainer);
this._countrySelectorButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._countrySelectorButtons.addClass(this._classNameBase + 'SchoolSelectorButton ' + this._classNameBase + 'Section-Item-ToUpdate');
this._countrySelectorButtons.setHTML(this._translateDTO.addCountry);
this._countrySelectorButtons.defaultText = this._translateDTO.addCountry;
this._countrySelectorButtons.injectInside(this._countrySelectorTitle);
this._countrySelectorsList = new SchoolList(this._countrySelectorButtons, this._classNameBase);
this._citySelectorContainer = new Element('div', {'class': this._classNameBase + 'Participants-Section ' + this._classNameBase + 'SchoolsSelector-Section AdvancedSchoolSelector SchoolSelectorCity'});
this._citySelectorTitle = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title ' + this._classNameBase + 'SchoolsSelector-Section-Title AdvancedSchoolSelector SchoolSelectorCity'});
this._citySelectorTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text ' + this._classNameBase + 'SchoolsSelector-Section-Title-Text SchoolSelectorCity'});
this._citySelectorTitleText.injectInside(this._citySelectorTitle);
this._citySelectorTitle.injectInside(this._citySelectorContainer);
this._citySelectorTitleText.setHTML(this._translateDTO.city);
this._citySelectorContainer.injectInside(this._advancedSchoolSelectorContainer);
this._citySelectorButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._citySelectorButtons.addClass(this._classNameBase + 'SchoolSelectorButton ' + this._classNameBase + 'Section-Item-ToUpdate');
this._citySelectorButtons.setHTML(this._translateDTO.addCity);
this._citySelectorButtons.defaultText = this._translateDTO.addCity;
this._citySelectorButtons.injectInside(this._citySelectorTitle);
this._citySelectorsList = new SchoolList(this._citySelectorButtons, this._classNameBase);
this._schoolSelectorContainer = new Element('div', {'class': this._classNameBase + 'Participants-Section ' + this._classNameBase + 'SchoolsSelector-Section AdvancedSchoolSelector SchoolSelectorSchool'});
this._schoolSelectorTitle = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title ' + this._classNameBase + 'SchoolsSelector-Section-Title AdvancedSchoolSelector SchoolSelectorSchool'});
this._schoolSelectorTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text ' + this._classNameBase + 'SchoolsSelector-Section-Title-Text SchoolSelectorSchool'});
this._schoolSelectorTitleText.injectInside(this._schoolSelectorTitle);
this._schoolSelectorTitle.injectInside(this._schoolSelectorContainer);
this._schoolSelectorTitleText.setHTML(this._translateDTO.school);
this._schoolSelectorContainer.injectInside(this._advancedSchoolSelectorContainer);
this._schoolSelectorButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._schoolSelectorButtons.addClass(this._classNameBase + 'SchoolSelectorButton ' + this._classNameBase + 'Section-Item-ToUpdate');
this._schoolSelectorButtons.setHTML(this._translateDTO.addSchool);
this._schoolSelectorButtons.defaultText = this._translateDTO.addSchool;
this._schoolSelectorButtons.injectInside(this._schoolSelectorTitle);
new Element('div', {'style': 'clear:both'}).injectInside(this._advancedSchoolSelectorContainer);
this._schoolSelectorsList = new SchoolList(this._schoolSelectorButtons, this._classNameBase);
// set to inactive the inactive menu
this.setActive(this._countrySelectorButtons, false);
this.setActive(this._citySelectorButtons, false);
this.setActive(this._schoolSelectorButtons, false);
if(this._programSelectorsList.getListItems().length == 1){
this._programSelectorsList.getListItems()[0].getHtml().fireEvent('click');
this._programSelectorContainer.addClass('Component-Booking-OneOption');
}
return this._advancedSchoolSelectorContainer;
} else {
this._schoolSelectorButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._schoolSelectorButtons.addClass(this._classNameBase + 'SchoolSelectorButton ' + this._classNameBase + 'Section-Item-ToUpdate');
this._schoolSelectorButtons.setHTML(this._translateDTO.add);
this._schoolSelectorButtons.injectInside(this._schoolSelectorTitle);
this._schoolSelectorsList = new SchoolList(this._schoolSelectorButtons, this._classNameBase);
this.createVisualList(this._schoolSelectorsList);
if (this._schoolsList.length == 1) {
this._schoolSelectorContainer.setStyle('display', 'none');
}
this._schoolSelectorsList.getHtml().injectInside(this._parent.getListContainer());
this._schoolSelectorsList.initializeEvents();
}
} else {
this._schoolSelectorButtons.setHTML(this._translateDTO.noSchools);
this._schoolSelectorButtons.injectInside(this._schoolSelectorTitle);
}
return this._schoolSelectorContainer;
},
/**
* Generate the list of schoolSelectors
*
* @param SchoolList list The list to update
*/
createVisualList : function(list) {
for (var i = 0; i < this._schoolsList.length; i++) {
list.addItem(this._schoolsList[i].schoolId, this._schoolsList[i].schoolName + ' - ' + this._schoolsList[i].schoolCityName + ' - ' + this._schoolsList[i].schoolCountryName);
}
list.getListItems().each(function(item, index) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (item.getValue() == this._selectedSchoolId) {
list.setSelectedItem(item);
this._schoolSelectorButtons.setHTML(item.getHtmlValue());
}
item.getHtml().addEvent('click', function(event) {
this._schoolSelectorButtons.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
if (this._selectedSchoolId != item.getValue()) {
this._schoolSelectorButtons.setHTML(item.getHtmlValue());
this._selectedSchoolId = item.getValue();
this.fireEvent('changeSchool');
list.setSelectedItem(item);
}
}.bind(this));
}.bind(this));
},
sortFunction : function(a,b){
var a = a.name.toLowerCase();
var b = b.name.toLowerCase();
if (a < b) {
return -1;
} else if (a > b) {
return  1;
} else {
return 0;
}
},
/**
* Create the list for the advanced school selector
* @param list
* @param listItems
* @param eventFunction
*/
createAdvancedList : function(list, listItems, eventFunction) {
list.clear();
var orderedListItems = new Array();
listItems.each(function(item, index) {
orderedListItems.push(item);
}.bind(this));
orderedListItems.sort(this.sortFunction);
orderedListItems.each(function(item, index) {
list.addItem(item.id, item.name);
}.bind(this));
list.getListItems().each(function(item, index) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (item.getValue() == this._selectedSchoolId) {
list.setSelectedItem(item);
this._schoolSelectorButtons.setHTML(item.getHtmlValue());
}
item.getHtml().addEvent('click', function(e) {
if (eventFunction == 'program') {
this.programEventFunction(item);
}
if (eventFunction == 'country') {
this.countryEventFunction(item);
}
if (eventFunction == 'city') {
this.cityEventFunction(item);
}
if (eventFunction == 'school') {
this.schoolEventFunction(item);
}
}.bind(this));
}.bind(this));
},
/**
* Function called when program is changed
*
* @param SchoolListItem item The new item
*/
programEventFunction : function(item) {
if (this._selectedProgramId != item.getValue()) {
this._programSelectorButtons.setHTML(item.getHtmlValue());
this._selectedProgramId = item.getValue();
this._selectedCityId = null;
this._selectedCountryId = null;
this._selectedSchoolId = null;
this.setActive(this._countrySelectorButtons, false);
this.setActive(this._citySelectorButtons, false);
this.setActive(this._schoolSelectorButtons, false);
this.updateCountryList(this._selectedProgramId);
this.fireEvent('changeSchool');
}
},
/**
* Function called when the country change
* @param SchoolListItem item The new item
*/
countryEventFunction : function(item) {
if(this._selectedCountryId != item.getValue()){
this._countrySelectorButtons.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._countrySelectorButtons.setHTML(item.getHtmlValue());
this._selectedCountryId = item.getValue();
this._selectedCityId = null;
this._selectedSchoolId = null;
this.setActive(this._citySelectorButtons, false);
this.setActive(this._schoolSelectorButtons, false);
this.updateCityList(this._selectedProgramId, this._selectedCountryId);
this.fireEvent('changeSchool');
}
},
/**
* Function called when the city change
* @param SchoolListItem item The new item
*/
cityEventFunction : function(item) {
if(this._selectedCityId != item.getValue()){
this._citySelectorButtons.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._citySelectorButtons.setHTML(item.getHtmlValue());
this._selectedCityId = item.getValue();
this._selectedSchoolId = null;
this.setActive(this._schoolSelectorButtons, false);
this.updateSchoolList(this._selectedProgramId, this._selectedCountryId, this._selectedCityId);
this.fireEvent('changeSchool');
}
},
/**
* Function called when the school change
* @param SchoolListItem item The new item
*/
schoolEventFunction : function(item) {
if(this._selectedSchoolId != item.getValue()){
this._schoolSelectorButtons.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._schoolSelectorButtons.setHTML(item.getHtmlValue());
this._selectedSchoolId = item.getValue();
this.fireEvent('changeSchool');
}
},
/**
* Update the country list
*
* @param programId
*/
updateCountryList : function(programId) {
this.createAdvancedList(this._countrySelectorsList, this.programs.get(programId).countries, 'country');
this._countrySelectorsList.getHtml().injectInside(this._parent.getListContainer());
this._countrySelectorsList.initializeEvents();
this.setActive(this._countrySelectorButtons, true);
if(this._countrySelectorsList.getListItems().length == 1){
this._countrySelectorsList.getListItems()[0].getHtml().fireEvent('click');
this._countrySelectorContainer.addClass('Component-Booking-OneOption');
}
},
/**
* Update the city list
* @param programId
* @param country
*/
updateCityList : function(programId, country) {
this.createAdvancedList(this._citySelectorsList, this.programs.get(programId).countries.get(country).cities, 'city');
this._citySelectorsList.getHtml().injectInside(this._parent.getListContainer());
this._citySelectorsList.initializeEvents();
this.setActive(this._citySelectorButtons, true);
if(this._citySelectorsList.getListItems().length == 1){
this._citySelectorsList.getListItems()[0].getHtml().fireEvent('click');
this._citySelectorContainer.addClass('Component-Booking-OneOption');
}
},
/**
* Update the school list
*
* @param programId
* @param country
* @param city
*/
updateSchoolList : function(programId, country, city) {
this.createAdvancedList(this._schoolSelectorsList, this.programs.get(programId).countries.get(country).cities.get(city).schools, 'school');
this._schoolSelectorsList.getHtml().injectInside(this._parent.getListContainer());
this._schoolSelectorsList.initializeEvents();
this.setActive(this._schoolSelectorButtons, true);
if(this._schoolSelectorsList.getListItems().length == 1){
this._schoolSelectorsList.getListItems()[0].getHtml().fireEvent('click');
this._schoolSelectorContainer.addClass('Component-Booking-OneOption');
}
},
/**
* Update the selector with the given parameter
*
*
* @param integer school The School Id
* @param integer program The program Id
* @param string country The country code
* @param integer city The city Id
*/
updateSelector : function(school, program, country, city) {
if (school.toInt()) {
if (this._schoolsHash.hasKey(school)) {
var schoolObject = this._schoolsHash.get(school);
this.updateProgramSelector(schoolObject.schoolProgramId);
this.updateCountrySelector(schoolObject.schoolCountryCode);
this.updateCitySelector(schoolObject.schoolCityId);
this.updateSchoolSelector(school);
}
} else {
if (program.toInt()) {
this.updateProgramSelector(program);
if (country) {
this.updateCountrySelector(country);
}
if (city) {
if (!country) {
this.updateCountrySelector(this._cityCountryHash.get(city));
}
this.updateCitySelector(city);
}
}
}
},
/**
* Update the program selector
*
* @param integer program The program Id
*/
updateProgramSelector : function(program) {
this._programSelectorsList.getListItems().each(function(item, index) {
if (item.getValue().toInt() == program.toInt()) {
item.getHtml().fireEvent('click');
}
}.bind(this));
},
/**
* Update the Country selector
*
* @param string country The Country code
*/
updateCountrySelector : function(country) {
this._countrySelectorsList.getListItems().each(function(item, index) {
if (item.getValue() == country) {
item.getHtml().fireEvent('click');
}
}.bind(this));
},
/**
* Update the city selector
*
* @param integer city The city Id
*/
updateCitySelector : function(city) {
this._citySelectorsList.getListItems().each(function(item, index) {
if (item.getValue().toInt() == city.toInt()) {
item.getHtml().fireEvent('click');
}
}.bind(this));
},
/**
* Update the school selector
*
* @param integer school The school Id
*/
updateSchoolSelector : function(school) {
this._schoolSelectorsList.getListItems().each(function(item, index) {
if (item.getValue() == school) {
item.getHtml().fireEvent('click');
}
}.bind(this));
},
/**
* Set active the button given
* @param button
* @param boolean
*/
setActive : function(button, active) {
if (active) {
button.removeClass(this._classNameBase + 'SchoolSelectorButtonInactive');
button.getParent().getParent().setStyle('display','');
} else {
button.addClass(this._classNameBase + 'SchoolSelectorButtonInactive');
button.getParent().getParent().setStyle('display','none');
if(button.defaultText){
button.setHTML(button.defaultText);
}
}
},
/**
* Returns the number of schoolSelector
*
* @return number The number of schoolSelectors
*/
getSelectedSchoolId : function() {
return this._selectedSchoolId;
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param number id the transfer ID
* @param char name the transfer name
* @param SchoolTransfers parent
**/
var SchoolTransferObject = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, type,  translateDTO, parent) {
this._translateDTO = translateDTO;
this._transferName = name;
this._type = type;
this._transferId = id;
this._parent = parent;
this._classNameBase = this._parent.getClassNameBase();
this._isMandatory = false;
// true if roundtrip
this._roundTrip = 1;
},
/**
* Generate the Html structure of this transfer
*/
createVisualTransfer : function() {
this._container = new Element('div', {'class': this._classNameBase + 'ItemAdded'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Item-Title'});
this._transferTypeValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value'});
this._transferType = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name TransferType'});
this._deleteButton = new Element('div', {'class': this._classNameBase + 'Section-Item-DeleteButton'});
this._title.injectInside(this._container);
this._transferType.injectInside(this._container);
this._transferTypeValue.injectInside(this._container);
this._deleteButton.injectInside(this._container);
this._clearElement = new Element('div');
this._clearElement.setStyle('clear', 'both');
this._clearElement.injectInside(this._container);
this._title.setHTML(this._transferName);
this._transferType.setHTML(this._translateDTO.transferType);
this._transferTypeValue.setHTML(this._translateDTO.roundTrip);
this._deleteButton.setHTML(this._translateDTO.deleteButton);
// add event listener
this._deleteButton.addEvent('click', function(e) {
this.removeTransfer();
this.fireEvent('deleteTransfer');
}.bind(this));
this._transferList = new SchoolList(this._title, this._classNameBase);
this.getVisualTransferList(this._transferList);
this._transferList.getHtml().injectInside(this._parent.getParent().getListContainer());
this._transferList.initializeEvents();
this._transfersList = new SchoolList(this._transferTypeValue, this._classNameBase);
this.getVisualTransferOptionsList(this._transfersList);
this._transfersList.getHtml().injectInside(this._parent.getParent().getListContainer());
this._transfersList.initializeEvents();
if(this._transfersList.getValidListItems().length == 1){
this._transferTypeValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._transfersList.removeButtonEvent();
this._transfersList.getValidListItems()[0].getHtml().fireEvent('click');
}else{
this._transferTypeValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-Value');
this._transfersList.addButtonEvent();
}
},
/**
* Returns an object containing the informations for the calculation price
*
* @return object The informations needed to calculate the price
*/
getDTO : function() {
var transferDTO = new Object();
transferDTO.id = this._transferId;
transferDTO.roundTrip = this._roundTrip;
return transferDTO;
},
/**
* Set this transfer mandatory
*
* @param Boolean isMandatory True if the transfer is mandatory
*/
setIsMandatoryTransfer : function(isMandatory) {
this._isMandatory = isMandatory;
if (this._isMandatory) {
this._deleteButton.setStyle('display', 'none');
} else {
this._deleteButton.setStyle('display', 'block');
}
},
/**
* Get this transfer mandatory
*
* @return Boolean True if mandatory
*/
getIsMandatoryTransfer : function() {
return this._isMandatory;
},
/**
* Return the transfer ID
*
* @return integer The Transfer ID
*/
getTransferId : function() {
return parseInt(this._transferId);
},
/**
* Populate the transfer from a dto
*/
populateFromDTO : function(toPopulateDTO) {
this._roundTrip = parseInt(toPopulateDTO.roundTrip);
if (!this._roundTrip) {
this._transferTypeValue.setHTML(this._translateDTO.oneWay);
} else {
this._transferTypeValue.setHTML(this._translateDTO.roundTrip);
}
},
/**
* Return true if the transfer is complete
*
* @return Boolean Return true if complete
*/
isComplete : function() {
if (this._roundTrip != -1) {
return true;
}
},
/**
* Returns the HTML structure of this course
*
* @return Element the transfer element
*/
getHtml : function() {
return this._container;
},
/**
* Generate the list of transfers for this school
*
* @param schoolList list The list to update
*/
getVisualTransferList : function(list) {
list.clear();
this._parent._schoolTransfersDTO.each(function(item, index) {
list.addItem(item.id, item.name);
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.setTransfer(item);
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.notAvailable);
if (!this._parent._schoolTransfersDTO || this._parent.getParent().getCompletedCourses().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
this.refreshVisualTransferList();
},
/**
* refresh the list of transfers for this school
*
*/
refreshVisualTransferList : function() {
this._parent.refreshVisualTransferList(this._transferList);
},
/**
* Replace the transfer with the one given in parameter
*
* @param Object transfer The transfer DTO
*/
setTransfer : function(transfer) {
this._transferName = transfer.name;
this._transferId = transfer.id;
this._type = transfer.type;
this._title.setHTML(this._transferName);
if (this._transfersList._listItems.length) {
this._transfersList.getHtml().remove();
this._transfersList.clear();
}
this.getVisualTransferOptionsList(this._transfersList);
this._transfersList.getHtml().injectInside(this._parent.getParent().getListContainer());
this._transfersList.initializeEvents();
if(this._transfersList.getValidListItems().length == 1){
this._transferTypeValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._transfersList.removeButtonEvent();
this._transfersList.getValidListItems()[0].getHtml().fireEvent('click');
}else{
this._transferTypeValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-Value');
this._transfersList.addButtonEvent();
}
this._parent.getParent().fireEvent('refreshPrice');
},
/**
* Generate the options list for a transfer
* and set an event on each option
*
* @param SchoolList The list to update
*/
getVisualTransferOptionsList : function(list) {
list.clear();
if(this._type != 2){
list.addItem(0, this._translateDTO.oneWay);
}
if(this._type != 1){
list.addItem(1, this._translateDTO.roundTrip);
}
list.getListItems().each(function(item, index) {
item.getHtml().addClass(this._classNameBase + 'List-Item');
item.getHtml().addEvent('click', function() {
this._transferTypeValue.setHTML(item.getHtmlValue());
this._roundTrip = item.getValue();
this._parent.getParent().fireEvent('refreshPrice');
}.bind(this));
if((this._roundTrip == 1 && this._type == 1) || (this._roundTrip == 0 && this._type == 2)){
item.getHtml().fireEvent('click');
}
}.bind(this));
},
/**
* Remove the transfer from the list
*
*/
removeTransfer : function() {
this._transfersList.getHtml().remove();
this._container.remove();
}
});
/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param TransferListItemDTO schoolTransfersDTO the transfers informations
* @param Object translateDTO The DTO containing the translations for this class
* @param SchoolPriceEstimation parent the parent
**/
var SchoolTransfers = Events.extend({
/**
* This is the initialization function
*/
initialize : function(schoolTransfersDTO, translateDTO, parent) {
this._schoolTransfersDTO = schoolTransfersDTO;
this._translateDTO = translateDTO;
this._parent = parent;
this._classNameBase = this.getParent().getClassNameBase();
this._transfers = new Array();
},
/**
* Returns the visual transfer container
*/
getHtml : function() {
this._transferContainer = new Element('div', {'class': this._classNameBase + 'Section'});
this._transferTitle = new Element('div', {'class': this._classNameBase + 'Section-Title'});
this._transferListContainer = new Element('div', {'class': this._classNameBase + 'Courses-CoursesList-Container'});
this._transferUserAccommodationList = new Element('div', {'class': this._classNameBase + 'Courses-UserCoursesList'});
this._transferAddButton = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._transferTitle.injectInside(this._transferContainer);
this._transferListContainer.injectInside(this._transferContainer);
this._transferUserAccommodationList.injectInside(this._transferListContainer);
this._transferAddButton.injectInside(this._transferContainer);
this._transferTitle.setHTML(this._translateDTO.title);
this._transferAddButton.setHTML(this._translateDTO.add);
this._transfersList = new SchoolList(this._transferAddButton, this._classNameBase);
this.getVisualTransferList(this._transfersList);
this._transfersList.getHtml().injectInside(this._parent.getListContainer());
this._transfersList.initializeEvents();
if(!this._schoolTransfersDTO.length){
this._transferContainer.setStyle('display','none');
}
return this._transferContainer;
},
/**
*  Return the classNameBase
*/
getClassNameBase : function() {
return this._classNameBase;
},
/**
* Returns an array containing the informations for the calculation price
*
* @return Array The informations needed to calculate the price
*/
getDTO : function() {
var transfersDTO = new Array();
this._transfers.each(function(item, index) {
if (item.isComplete()) {
transfersDTO.push(item.getDTO());
}
});
return transfersDTO;
},
/**
* Populate the transfers from a dto
*/
populateFromDTO : function(toPopulateDTO) {
if (toPopulateDTO) {
toPopulateDTO.each(function(item, index) {
var transfer;
transfer = this._schoolTransfersDTO.filter(function(itemDTO, indexDTO) {
return itemDTO.id == item.id;
}.bind(this));
if (transfer[0]) {
for(var i = 0; i < this._transfers.length; i++){
if(parseInt(this._transfers[i]._transferId) == parseInt(transfer[0].id)){
this._transfers[i].removeTransfer();
this._transfers.remove(this._transfers[i]);
i--;
}
}
this.addTransfer(item.id);
this._transfers[this._transfers.length - 1].populateFromDTO(item);
}
}.bind(this));
}
},
/**
* Retrieve the list of transfers for this school
*
* @param schoolList list The list to update
*/
getVisualTransferList : function(list) {
list.clear();
this._schoolTransfersDTO.each(function(item, index) {
list.addItem(item.id, item.name);
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.addTransfer(item.id);
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.notAvailable);
if (this._parent.getCompletedCourses().length > 0) {
if (this._schoolTransfersDTO.length) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setHtml(this._translateDTO.noTransfers);
list.getListItems().getLast().setIsValid(true);
}
} else {
list.getListItems().getLast().setHtml(this._translateDTO.notAvailable);
list.getListItems().getLast().setIsValid(true);
}
this.refreshVisualTransferList(list);
},
/**
* Refresh the list of transfers for this school
*
* @param schoolList list The list to update
*/
refreshVisualTransferList : function(list) {
var availableTransfers = this._parent.getAvailableTransfers();
list.getListItems().each(function(item, index) {
if ((!this._schoolTransfersDTO || this._parent.getCompletedCourses().length > 0) && availableTransfers.contains(parseInt(item.getValue()))) {
item.setIsValid(true);
item.setIsSelectionnable(true);
} else {
item.setIsValid(false);
}
}.bind(this));
if (this._parent.getCompletedCourses().length > 0) {
if (this._schoolTransfersDTO.length) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setHtml(this._translateDTO.noTransfers);
list.getListItems().getLast().setIsValid(true);
}
} else {
list.getListItems().getLast().setHtml(this._translateDTO.notAvailable);
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Refresh the transfers lists
*
*/
refreshTransfers : function() {
var transfNb = this._transfers.length;
this.refreshVisualTransferList(this._transfersList);
// refresh every transfer list for the added transfers
for (var i = 0; i < this._transfers.length; i++) {
this._transfers[i].refreshVisualTransferList();
}
if (this._parent.getCompletedCourses().length == 0) {
for (var i = this._transfers.length - 1; i >= 0; i--) {
this._transfers[i].removeTransfer();
this._transfers.remove(this._transfers[i]);
}
this._parent.fireEvent('heightModified');
if (transfNb > 0)this._parent.fireEvent('refreshPrice');
} else {
// get the available transfers List
var availableTransfers = this._parent.getAvailableTransfers();
// remove the unavailable transfers
this._transfers.each(function(item) {
if (!availableTransfers.contains(item.getTransferId())) {
item.removeTransfer();
this._transfers.remove(item);
}
}.bind(this));
// add transfers if they are mandatory
if (!this._transfers.length && availableTransfers.length && this._parent.getIsTransferMandatory()) {
var transfersToAdd = this._schoolTransfersDTO.filter(function(item) {
return  availableTransfers.contains(parseInt(item.id));
});
if (transfersToAdd.length) {
this.addTransfer(transfersToAdd[0].id);
} else {
this.addTransfer(availableTransfers[0]);
}
this._transfers[0].setIsMandatoryTransfer(true);
} else {
if (this._parent.getIsTransferMandatory() && this._transfers.length) {
this._transfers[0].setIsMandatoryTransfer(true);
}
}
}
if (!this._parent.getIsTransferMandatory()) {
for (var i = 0; i < this._transfers.length; i++) {
this._transfers[i].setIsMandatoryTransfer(false);
}
}
if ((this._parent.getIsTransferMandatory() == true && this._transfers.length) || this._parent.getCompletedAccommodations().length == 0) {
this.displayAddButton(false);
} else {
this.displayAddButton(true);
}
},
/**
* Add a transfer from its ID
*
* @param Number id The transfer id
*/
addTransfer : function(id) {
var schoolTransfersDTO = this._schoolTransfersDTO.copy();
var schoolTransfer = schoolTransfersDTO.filter(function(item, index) {
return item.id == id;
}.bind(this));
var newTransfer = new SchoolTransferObject(schoolTransfer[0].id, schoolTransfer[0].name, schoolTransfer[0].type, this._translateDTO.transferObject, this);
this._transfers.push(newTransfer);
newTransfer.createVisualTransfer();
this._transfers.getLast().getHtml().injectInside(this._transferUserAccommodationList);
newTransfer.addEvent('deleteTransfer', function(e) {
this.deleteTransfer(newTransfer);
}.bind(this));
this._parent.fireEvent('heightModified');
this._parent.fireEvent('refreshPrice');
},
/**
* Returns the parent of this object
*
* @return SchoolPriceEstimation The parent
*/
getParent : function() {
return this._parent;
},
/**
* Display or hide the add button
*
* @param boolean isDisplayed True to display the hide button
*/
displayAddButton : function(isDisplayed) {
if (isDisplayed) {
this._transferAddButton.setStyle('display', 'block');
} else {
this._transferAddButton.setStyle('display', 'none');
}
},
/**
* Returns the number of completed transfers
*
* @return Number The number of completed transfers
*/
getCompletedTransfers : function() {
return this._transfers.length;
},
/**
* Delete the given transfer
*
* @param SchoolTransferObject transfer The transfer to delete
*/
deleteTransfer : function(transfer) {
this._transfers.remove(transfer);
this._parent.fireEvent('heightModified');
this._parent.fireEvent('refreshPrice');
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @event Event deleteCourse This event is fired when a course is deleted
*
* @param FixedDatesCourseListItemDTO courseDetails courseDetails The object containing the course informations
* @param Object translateDTO The object containing all the translations for this class
* @param SchoolCourses parent The parent
*
**/
var SchoolVariableCourseObject = Events.extend({
/**
* This is the initialization function
*
*/
initialize : function(courseDetails, translateDTO, listContainer, classNamePrefix, parent) {
this._translateDTO = translateDTO;
this._courseDetails = courseDetails;
this._parent = parent;
this._listContainer = listContainer;
this._classNameBase = classNamePrefix;
this._dateFormat = this._parent.getParent().getDateFormat();
this._monthsTranslations = this._parent.getParent().getMonthTranslations();
this._manager = this.getParent().getParent().getParent();
this._manager.addEvent('descriptionsUpdated', function(){
this.updateDescriptions();
}.bind(this));
this._courseStartDate = null;
this._courseEndDate = null;
this._courseDuration = null;
},
/**
* Return the course details DTO
*
* @return CourseDetailsDTO The course Details DTO
*/
getCourseDetails : function() {
return this._courseDetails;
},
/**
* Return true if the course is complete
*
* @return Boolean Return true if the course is complete
*/
isComplete : function() {
if (this._courseStartDate && this._courseEndDate && this._courseDuration) {
return true;
} else {
return false;
}
},
/**
* Generate the html structure of the course
* and add an event on the delete button
*
*/
createVisualCourse : function() {
this._container = new Element('div', {'class': this._classNameBase + 'ItemAdded'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Item-Title'});
this._subTitle = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle'});
this._moreInfo = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle MoreInfos'});
this._moreInfo.setStyle('display','none');
this._startDateContainer = new Element('div',{'class': this._classNameBase + 'Section-Item-StartDate-Container'});
this._endDateContainer = new Element('div',{'class': this._classNameBase + 'Section-Item-EndDate-Container'});
this._startDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._startDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._endDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._endDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._durationContainer = new Element('div',{'class': this._classNameBase + 'Section-Item-Duration-Container'});
this._duration = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._durationValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._deleteButton = new Element('div', {'class': this._classNameBase + 'Section-Item-DeleteButton'});
this._duration.injectInside(this._durationContainer);
this._durationValue.injectInside(this._durationContainer);
this._startDate.injectInside(this._startDateContainer);
this._startDateValue.injectInside(this._startDateContainer);
this._endDate.injectInside(this._endDateContainer);
this._endDateValue.injectInside(this._endDateContainer);
this._title.injectInside(this._container);
this._subTitle.injectInside(this._container);
this._moreInfo.injectInside(this._container);
new Element('div',{'style':'clear:both'}).injectInside(this._container);
this._startDateContainer.injectInside(this._container);
this._endDateContainer.injectInside(this._container);
this._durationContainer.injectInside(this._container);
this._deleteButton.injectInside(this._container);
new Element('div',{'style':'clear:both'}).injectInside(this._container);
this._title.setHTML(this._courseDetails.name);
this._subTitle.setHTML(this._courseDetails.subtitle);
this._moreInfo.setHTML(this._translateDTO.moreInfos);
this._startDate.setHTML(this._translateDTO.startDate);
this._startDateValue.setHTML(this._translateDTO.dateSelect);
this._endDate.setHTML(this._translateDTO.endDate);
this._endDateValue.setHTML(this._translateDTO.endDateValue);
this._duration.setHTML(this._translateDTO.duration);
this._durationValue.setHTML(this._translateDTO.durationSelect);
this._deleteButton.setHTML(this._translateDTO.deleteButton);
this.updateDescriptions();
// add event listener
this._deleteButton.addEvent('click', function(e) {
this.removeCourse();
this.fireEvent('deleteCourse');
}.bind(this));
this._coursesValidList = new SchoolList(this._title, this._classNameBase);
this.getVisualValidCoursesList(this._coursesValidList);
this._coursesValidList.getHtml().injectInside(this._listContainer);
this._coursesValidList.initializeEvents();
this._schoolStartList = new SchoolList(this._startDateValue, this._classNameBase);
this.getVisualVariableCourseStartDates(this._courseDetails.startDates, this._schoolStartList);
this._schoolStartList.getHtml().injectInside(this._listContainer);
this._schoolStartList.initializeEvents();
this._schoolDurationList = new SchoolList(this._durationValue, this._classNameBase);
this.getVisualVariableCourseDurationList(this._courseDetails.duration, this._schoolDurationList);
this._schoolDurationList.getHtml().injectInside(this._listContainer);
this._schoolDurationList.initializeEvents();
this.refreshLists();
},
updateDescriptions : function(){
if (this._manager.getDescription && this._manager.getDescription('course', this._courseDetails.courseTypeId) && this._manager.getDescription('course', this._courseDetails.courseTypeId) != '') {
this._moreInfo.setAttribute('title', this._courseDetails.name + ' :: ' + this._manager.getDescription('course', this._courseDetails.courseTypeId));
this._moreInfo.setStyle('display','');
if(!this._descriptionToolTip ){
this._descriptionToolTip = new SynergeeTips(this._moreInfo, {'className':'PriceEstimationToolTip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}else {
this._descriptionToolTip.build(this._moreInfo);
}
}else {
this._moreInfo.setStyle('display','none');
}
},
/**
* Returns the html Element of this course
*
* @return Element The HTML view of this course
*/
getHtml : function() {
return this._container;
},
/**
* return the course start date
*
* @return Date The course start date
*/
getCourseStartDate : function() {
return this._courseStartDate;
},
/**
* return the course start date
*
* @return Date The course start date
*/
getCourseEndDate : function() {
return this._courseEndDate;
},
/**
* return the accommodation end date for this course
*
* @return Date The accommodation end date date
*/
getAccommodationEndDate : function() {
var endDate = new Date(this._courseEndDate);
var endDateDay = endDate.getDay();
return endDate;
},
/**
* Return an object containing the informations for the calculation price
*
* @return Object The informations needed to calculate the price
*/
getDTO : function() {
var courseDTO = new Object();
courseDTO.id = this._courseDetails.id;
courseDTO.startDate = this._courseStartDate.toIso();
courseDTO.endDate = this._courseEndDate.toIso();
return courseDTO;
},
/**
* Populate the variable course from a dto
*
* @param Object The fixed course informations needed to populate
*/
populateFromDTO : function(toPopulateDTO) {
this._courseStartDate = (new Date()).fromIso(toPopulateDTO.startDate);
this._startDateValue.setHTML(this._courseStartDate.format(this._dateFormat , this._monthsTranslations));
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._courseEndDate = (new Date()).fromIso(toPopulateDTO.endDate);
this._courseDuration = this.getCalculatedDuration(this._courseStartDate, this._courseEndDate );
if(this._courseDetails.duration.length && this._courseDuration < parseInt(this._courseDetails.duration[0])) this._courseDuration = parseInt(this._courseDetails.duration[0]);
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
// If the start and the duration are set,  the end date is calculated
if (this._courseStartDate && this._courseDuration) {
this._courseEndDate = this.getVariableCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat , this._monthsTranslations));
}
// when the user selects only the start date, the duration is set with the minimal value
if (this._courseStartDate && !this._courseDuration) {
this._courseDuration = this._courseDetails.duration[0];
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this._courseEndDate = this.getVariableCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat , this._monthsTranslations));
}
},
/**
* Refresh all the lists of this course
*
*/
refreshLists : function() {
// add the list of courses that fit the start and end Date
this.refreshVisualValidCoursesList(this._coursesValidList);
// initialize the start date list and its event
this.refreshVisualVariableCourseStartDates(this._parent.getValidVariableCourseStartDate(this), this._schoolStartList);
// initialize the duration list and its event
this.refreshVisualVariableCourseDurationList(this._parent.getValidVariableCourseDuration(this), this._schoolDurationList);
// check if the buttons must be activated or not
if(this._schoolStartList.getValidListItems().length == 1 ){
this._startDateValue.addClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
this._schoolStartList.removeButtonEvent();
if(this._courseStartDate != this._schoolStartList.getValidListItems()[0].getValue())this._schoolStartList.getValidListItems()[0].getHtml().fireEvent('click');
}else{
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._startDateValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this._schoolStartList.addButtonEvent();
}
if(this._schoolDurationList.getValidListItems().length == 1 ){
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
this._schoolDurationList.removeButtonEvent();
if(parseInt(this._courseDuration) != parseInt(this._schoolDurationList.getValidListItems()[0].getValue()))this._schoolDurationList.getValidListItems()[0].getHtml().fireEvent('click');
}else{
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._schoolDurationList.addButtonEvent();
}
},
/**
* Generate all the lists of this course
*
*/
reGenerateLists : function() {
// remove old list if exists
if (this._coursesValidList._listItems.length) {
this._coursesValidList.getHtml().remove();
this._coursesValidList.clear();
}
if (this._schoolStartList._listItems.length) {
this._schoolStartList.getHtml().remove();
this._schoolStartList.clear();
}
if (this._schoolDurationList._listItems.length) {
this._schoolDurationList.getHtml().remove();
this._schoolDurationList.clear();
}
this.getVisualValidCoursesList(this._coursesValidList);
this._coursesValidList.getHtml().injectInside(this._listContainer);
this._coursesValidList.initializeEvents();
this.getVisualVariableCourseStartDates(this._courseDetails.startDates, this._schoolStartList);
this.refreshVisualVariableCourseStartDates(this._parent.getValidVariableCourseStartDate(this), this._schoolStartList);
this._schoolStartList.getHtml().injectInside(this._listContainer);
this._schoolStartList.initializeEvents();
this.getVisualVariableCourseDurationList(this._courseDetails.duration, this._schoolDurationList);
this.refreshVisualVariableCourseDurationList(this._parent.getValidVariableCourseDuration(this), this._schoolDurationList);
this._schoolDurationList.getHtml().injectInside(this._listContainer);
this._schoolDurationList.initializeEvents();
},
/**
* Refresh the course data
*
*/
refreshVariableCourseData : function() {
// If the start and the duration are set,  the end date is calculated
if (this._courseStartDate && this._courseDuration) {
this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._courseEndDate = this.getVariableCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat , this._monthsTranslations));
}
// when the user selects only the start date
if (this._courseStartDate && !this._courseDuration) {
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
if(this._courseDuration){
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this._courseEndDate = this.getVariableCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat , this._monthsTranslations));
}else {
this.refreshVisualVariableCourseDurationList(this._parent.getValidVariableCourseDuration(this), this._schoolDurationList);
}
}
if (this.isComplete()) {
this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
// refresh the course list
this._parent.fireEvent('refreshCourses');
this._parent.fireEvent('refreshPrice');
}
},
/**
*  Returns the endDate of a variable course
*
*  @return Date The variable course end date
*/
getVariableCourseEndDate : function() {
var endDate = new Date(this._courseStartDate.getFullYear(), this._courseStartDate.getMonth(), this._courseStartDate.getDate() + this._courseDuration * 7 + 2);
var endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
while (endDateDay != this._courseDetails.courseEndDay) {
endDate.setDate(endDate.getDate() - 1);
endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
}
return endDate;
},
/**
* Replace the courses and find the best possible dates
*
* @param Object The new course DTO
*/
replaceCourse : function(newCourse) {
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
if (!this._parent.getIsFixedCourse(newCourse)) {
if (this.isComplete()) {
this._courseDetails = newCourse;
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this.replaceVariableCourseDates(this._courseStartDate, this._courseDuration);
this._title.setHTML(this._courseDetails.name);
this._subTitle.setHTML(this._courseDetails.subtitle);
this.reGenerateLists();
this._parent.fireEvent('refreshCourses');
} else {
this._schoolStartList.getHtml().remove();
this._schoolDurationList.getHtml().remove();
this._coursesValidList.getHtml().remove();
this._parent.replaceCourse(this, newCourse);
}
} else {
this._schoolStartList.getHtml().remove();
this._schoolDurationList.getHtml().remove();
this._coursesValidList.getHtml().remove();
if (this.isComplete()) {
this._parent.replaceCourse(this, newCourse, this._courseStartDate);
} else {
this._parent.replaceCourse(this, newCourse);
}
}
this.updateDescriptions();
},
/**
* this method find the best dates and duration for the new variable course based on the old one
*
* @param Date oldStartDate the date of the replaced course
* @param number oldDuration the duration of the replaced course
*/
replaceVariableCourseDates : function(oldStartDate, oldDuration) {
// if the start date is already set
if (oldStartDate) {
var dateDifference = null;
var newDate;
this._courseDetails.startDates.each(function(item, index) {
if (dateDifference > Math.abs(oldStartDate.getTime() - item.getTime()) || dateDifference == null) {
dateDifference = Math.abs(oldStartDate.getTime() - item.getTime());
newDate = item;
}
});
// if there is already a duration set
if (oldDuration) {
var durationDifference = null;
var newDuration;
this._courseDetails.duration.each(function(item, index) {
if (durationDifference > Math.abs(oldDuration - item) || durationDifference == null) {
durationDifference = Math.abs(oldDuration - item);
newDuration = item;
}
});
this._courseDuration = newDuration;
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
}
this._courseStartDate = newDate;
this._startDateValue.setHTML(newDate.format(this._dateFormat , this._monthsTranslations));
this.refreshVariableCourseData();
}
},
/**
* Generate a list of valid course
*
* @param SchoolList list The valid courses list
*
*/
getVisualValidCoursesList : function(list) {
var validCourses = this._parent.getCourses();
// clearing the list
list.clear();
validCourses.each(function(item, index) {
list.addItem(item, item.name);
list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item');
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.replaceCourse(item);
}.bind(this));
}, this);
this.refreshVisualValidCoursesList(list);
},
/**
* Refresh a list of course that have possible dates between this courseStartDate and courseEndDate
*
* @param SchoolList list The courses list
*
*/
refreshVisualValidCoursesList : function(list) {
var validCourses = this._parent.getValidCourses(this);
list.getListItems().each(function(item, index) {
if (validCourses.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
} else {
item.setIsValid(false);
}
}.bind(this));
},
/**
* This function set a formated list from an array of a course start dates
*
* @param Array startDates An array of Date containing all the possible startDates
* @param SchoolList list The valid courses list
*/
getVisualVariableCourseStartDates : function(startDates, list) {
// clearing the list
list.clear();
startDates.each(function(item, index) {
list.addItem(item, item.format(this._dateFormat , this._monthsTranslations));
index = list.getListItems().indexOf(list.getListItems().getLast());
list.getListItems().getLast().getHtml().addEvent('click', function() {
if (list.getListItems()[index].getIsSelectionnable()) {
// Set the variables for this course
this._courseStartDate = item;
// set the visual data of this course
this._startDateValue.setHTML(item.format(this._dateFormat , this._monthsTranslations));
this.refreshVariableCourseData();
}
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.noValidStartDates);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* this function refresh a list from an array of a course start dates
*
* @param Array validStartDates an array of Date containing the validated startDates
* @param SchoolList list the valid courses list
*/
refreshVisualVariableCourseStartDates : function(validStartDate, list) {
var firstValid = true;
list.getListItems().each(function(item, index) {
if (validStartDate.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (firstValid) {
list.setSelectedItem(item);
}
if (this._courseStartDate == item.getValue()) {
list.setSelectedItem(item);
}
firstValid = false;
} else {
if (item.getValue == 'error') {
item.setIsValid(false);
}
item.setIsSelectionnable(false);
}
}.bind(this));
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* This function return a formated list from an array of duration
*
* @param Array durations An array of Date containing the startDates
* @param Array validDurations An array of number containing the validated durations
*/
getVisualVariableCourseDurationList : function(durations, list) {
// clearing the list
list.clear();
durations.each(function(item, index) {
if (item > 1) {
list.addItem(item, this._translateDTO.weeks.replace('%0', item));
} else {
list.addItem(item, this._translateDTO.week.replace('%0', item));
}
index = list.getListItems().indexOf(list.getListItems().getLast());
// adding the event on the valid courses
list.getListItems().getLast().getHtml().addEvent('click', function() {
if (list.getListItems()[index].getIsSelectionnable()) {
this._courseDuration = item;
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this.refreshVariableCourseData();
}
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.noValidDuration);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* This function return a formated list from an array of duration
*
* @param Array validDurations An array of number containing the validated durations
* @param SchoolList list The list to refresh
*/
refreshVisualVariableCourseDurationList : function(validDurations, list) {
var firstValid = true;
var lastValid = null;
list.getListItems().each(function(item, index) {
if (validDurations.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (firstValid)list.setSelectedItem(item);
if (this._courseDuration == item.getValue()) list.setSelectedItem(item);
firstValid = false;
lastValid = item;
} else {
if (item.getValue == 'error')item.setIsValid(false);
item.setIsSelectionnable(false);
if(this._courseDuration == item.getValue()){
if(lastValid)lastValid.getHtml().fireEvent('click');
}
}
}.bind(this));
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Return the duration in weeks.
* To perform the calculation we count the number of time the week day of the start date
* can be repeated between the start date and the end date.
*
* @param date startDate The start date
* @param date endDate The end date
* @return integer the number of weeks
*/
getCalculatedDuration : function(startDate, endDate) {
startDate = startDate.getTime();
endDate = endDate.getTime() - (86400 * 3 * 1000);
var numberOfWeeks = 0;
while(startDate <= endDate) {
numberOfWeeks++;
startDate += (86400 * 7 * 1000);
}
return numberOfWeeks;
},
/**
*  Returns the available accommodations for this course
*
* @return Array of integer The Accommodation IDs
*/
getAvailableAccommodations : function() {
return this._courseDetails.availableAccommodations;
},
/**
*  return the course duration
*
* @return integer The course duration
*/
getCourseDuration : function() {
return this._courseDuration;
},
/**
* Returns false is it's not a fixed course
*
* @return Boolean Return false because it's a variable course
*/
getIsFixedCourse : function() {
return false;
},
/**
* return the parent
*
* @return SchoolCourses The parent
*/
getParent : function() {
return this._parent;
},
/**
* Remove the course from the list
*
*/
removeCourse : function() {
this._schoolStartList.getHtml().remove();
this._schoolDurationList.getHtml().remove();
this._coursesValidList.getHtml().remove();
this._container.remove();
}
});
var Lightbox={init:function(options){this.options=Object.extend({resizeDuration:400,resizeTransition:Fx.Transitions.sineInOut,initialWidth:250,initialHeight:250,animateCaption:true,defaultIframeWidth:500,defaultIframeHeight:300},options||{});if(window.ie6&&document.compatMode=="BackCompat"){this.options.animateCaption=false}this.anchors=[];$each(document.links,function(el){if(el.rel&&el.rel.test(/^lightbox/i)){el.onclick=this.click.pass(el,this);this.anchors.push(el)}},this);this.eventKeyDown=this.keyboardListener.bindAsEventListener(this);this.eventPosition=this.position.bind(this);this.overlay=new Element("div").setProperty("id","lbOverlay").injectInside(document.body);this.center=new Element("div").setProperty("id","lbCenter").setStyles({width:this.options.initialWidth+"px",height:this.options.initialHeight+"px",marginLeft:"-"+(this.options.initialWidth/2)+"px",display:"none"}).injectInside(document.body);this.canvas=new Element("div").setProperty("id","lbCanvas").injectInside(this.center);new Element("a").setProperties({id:"lbCloseLinkTop",href:"#"}).injectInside(this.canvas).onclick=this.overlay.onclick=this.close.bind(this);this.prevLink=new Element("a").setProperties({id:"lbPrevLink",href:"#"}).setStyle("display","none").injectInside(this.canvas);this.nextLink=this.prevLink.clone().setProperty("id","lbNextLink").injectInside(this.canvas);this.prevLink.onclick=this.previous.bind(this);this.nextLink.onclick=this.next.bind(this);this.bottomContainer=new Element("div").setProperty("id","lbBottomContainer").setStyle("display","none").injectInside(document.body);this.bottom=new Element("div").setProperty("id","lbBottom").injectInside(this.bottomContainer);new Element("a").setProperties({id:"lbCloseLink",href:"#"}).injectInside(this.bottom).onclick=this.overlay.onclick=this.close.bind(this);this.caption=new Element("div").setProperty("id","lbCaption").injectInside(this.bottom);this.number=new Element("div").setProperty("id","lbNumber").injectInside(this.bottom);new Element("div").setStyle("clear","both").injectInside(this.bottom);var nextEffect=this.nextEffect.bind(this);this.fx={overlay:this.overlay.effect("opacity",{duration:500}).hide(),resizeCenter:this.center.effects({duration:this.options.resizeDuration,transition:this.options.resizeTransition,onComplete:nextEffect}),image:this.canvas.effect("opacity",{duration:500,onComplete:nextEffect}),bottom:this.bottomContainer.effect("height",{duration:400,onComplete:nextEffect})};this.preloadPrev=new Image();this.preloadNext=new Image()},click:function(link){if(link.rel.length==8){return this.show(link.href,link.title,link.rev)}var j,itemNumber,items=[];this.anchors.each(function(el){if(el.rel==link.rel){for(j=0;j<items.length;j++){if(items[j][0]==el.href&&items[j][2]==el.rev){break}}if(j==items.length){items.push([el.href,el.title,el.rev]);if(el.href==link.href&&el.rev==link.rev){itemNumber=j}}}},this);return this.open(items,itemNumber)},show:function(url,title,rev){return this.open([[url,title,rev]],0)},open:function(items,itemNumber){this.items=items;this.position();this.setup(true);var wh=(window.getHeight()==0)?window.getScrollHeight():window.getHeight();var st=document.body.scrollTop||document.documentElement.scrollTop;var rev=this.items[0][2];var height=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),600);this.top=st+((wh-(height))/2)-30;this.center.setStyles({top:this.top+"px",display:""});this.fx.overlay.start(0.8);return this.changeItem(itemNumber)},position:function(){var ww=(window.getWidth()==0)?window.getScrollWidth()-22:window.getWidth();var wh=(window.getHeight()==0)?window.getScrollHeight():window.getHeight();var st=document.body.scrollTop||document.documentElement.scrollTop;this.overlay.setStyles({top:st+"px",height:wh+"px",width:ww+"px"})},setup:function(open){var elements=$A(document.getElementsByTagName("object"));if(window.ie){elements.extend(document.getElementsByTagName("select"))}elements.each(function(el){el.style.visibility=open?"hidden":""});var fn=open?"addEvent":"removeEvent";window[fn]("scroll",this.eventPosition)[fn]("resize",this.eventPosition);document[fn]("keydown",this.eventKeyDown);this.step=0},keyboardListener:function(event){switch(event.keyCode){case 27:case 88:case 67:this.close();break;case 37:case 80:this.previous();break;case 39:case 78:this.next()}},previous:function(){return this.changeItem(this.activeItem-1)},next:function(){return this.changeItem(this.activeItem+1)},changeItem:function(itemNumber){if(this.step||(itemNumber<0)||(itemNumber>=this.items.length)){return false}this.step=1;this.activeItem=itemNumber;this.bottomContainer.style.display=this.prevLink.style.display=this.nextLink.style.display="none";this.fx.image.hide();this.center.className="lbLoading";this.removeCurrentItem();var url=this.items[this.activeItem][0];var rev=this.items[this.activeItem][2];var re_imageURL=/\.(jpe?g|png|gif|bmp)/i;var re_flashURL=/\.(swf)/i;var re_youtubeURL=/http\:\/\/(?:www\.){0,1}youtube\.com\/watch\?v=(.*)?/i;var re_dailymotionURL=/^http\:\/\/(?:www\.){0,1}dailymotion\.com\/video\/(.*?)\_/i;var re_streamURL=/stream\.(php)/i;var re_externalStreamURL=/^http\:\/\/(.*).(mp4|flv)/i;var re_downloadURL=/download\.php\?ressource=(.*)\&filename=(.*)/i;var re_hiddenDivURL=/\{hiddenId\|(\w+)\}/i;var matches=null;if(url.match(re_imageURL)){this.preload=new Image();this.preload.datatype="image";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+%?)","i"),-1);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+%?)","i"),-1);this.preload.onload=this.nextEffect.bind(this);this.preload.src=url}else{if(url.match(re_flashURL)){this.preload=new Object();this.preload.datatype="flash";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),425);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),355);this.preload.src=url;this.nextEffect()}else{if(url.match(re_streamURL)){this.preload=new Object();this.preload.datatype="stream";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),425);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),355);this.preload.src=url;this.nextEffect()}else{if(matches=url.match(re_downloadURL)){this.preload=new Object();if(matches[2].match(/\.flv/)||matches[2].match(/\.mp4/)){this.preload.src="stream.php?media="+matches[2];this.preload.datatype="stream"}else{this.preload.src="ressource.php?media="+matches[2];this.preload.datatype="iframe"}this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),425);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),355);this.nextEffect()}else{if(matches=url.match(re_youtubeURL)){this.preload=new Object();this.preload.datatype="youtube";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),this.options.defaultIframeWidth);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),this.options.defaultIframeHeight);this.preload.src=matches[1];this.nextEffect()}else{if(matches=url.match(re_dailymotionURL)){this.preload=new Object();this.preload.datatype="dailymotion";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),this.options.defaultIframeWidth);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),this.options.defaultIframeHeight);this.preload.src=matches[1];this.nextEffect()}else{if(matches=url.match(re_hiddenDivURL)){this.preload=new Object();this.preload.datatype="hidden";this.preload.src=matches[1];this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),this.options.defaultIframeWidth);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),this.options.defaultIframeHeight);this.nextEffect()}else{if(matches=url.match(re_externalStreamURL)){this.preload=new Object();this.preload.src=url;this.preload.datatype="stream";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),425);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),355);this.nextEffect()}else{this.preload=new Object();this.preload.datatype="iframe";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),this.options.defaultIframeWidth);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),this.options.defaultIframeHeight);this.preload.src=url;this.nextEffect()}}}}}}}}return false},nextEffect:function(){switch(this.step++){case 1:this.center.className="";if(this.preload.datatype=="image"){var ws=(this.preload.w==-1)?this.preload.width.toString():this.preload.w.toString();var hs=(this.preload.h==-1)?this.preload.height.toString():this.preload.h.toString();this.p_width=(q=ws.match(/(\d+)%/))?q[1]*this.preload.width*0.01:ws;this.p_height=(q=hs.match(/(\d+)%/))?q[1]*this.preload.height*0.01:hs;new Element("img").setProperties({id:"lbImage",src:this.preload.src,width:this.p_width,height:this.p_height}).injectInside(this.canvas);this.nextLink.style.right=""}else{if(this.preload.datatype=="youtube"){this.p_width=this.preload.w;this.p_height=this.preload.h;var so=new SWFObject("http://www.youtube.com/v/"+this.preload.src+"&rel=0&autoplay=1&enablejsapi=1&playerapiid=lbYoutube","lbYoutubePlayer",this.p_width,this.p_height,"8","#FFFFFF");new Element("div").setProperties({id:"lbYoutube"}).injectInside(this.canvas);so.write("lbYoutube")}else{if(this.preload.datatype=="dailymotion"){this.p_width=this.preload.w;this.p_height=this.preload.h;var so=new SWFObject("http://www.dailymotion.com/swf/"+this.preload.src+"&v3=1&related=0&autoplay=1","lbDailymotionPlayer",this.p_width,this.p_height,"8","#FFFFFF");new Element("div").setProperties({id:"lbDailymotion"}).injectInside(this.canvas);so.write("lbDailymotion")}else{if(this.preload.datatype=="stream"){this.p_width=this.preload.w;this.p_height=this.preload.h;var so=new SWFObject(window.getCurrentPageLocation()+"Themes/Default/Components/Video/Flash/mediaplayer.swf","lbStreamPlayer",this.p_width,this.p_height,"8","#FFFFFF");so.addParam("allowfullscreen","true");so.addVariable("type","flv");so.addVariable("displayheight",this.p_height);so.addVariable("file",this.preload.src);so.addVariable("enablejs","true");so.addVariable("overstretch","true");new Element("div").setProperties({id:"lbStream"}).injectInside(this.canvas);so.write("lbStream")}else{if(this.preload.datatype=="flash"){this.p_width=this.preload.w;this.p_height=this.preload.h;var so=new SWFObject(this.preload.src,"lbFlashPlayer",this.p_width,this.p_height,"8","#FFFFFF");new Element("div").setProperties({id:"lbFlash"}).injectInside(this.canvas);so.write("lbFlash")}else{if(this.preload.datatype=="googleMap"){this.p_width=this.preload.w;this.p_height=this.preload.h;this.iframeId="mapContainer";new Element("iframe").setProperties({id:this.iframeId,width:this.p_width,height:this.p_height,frameBorder:0,scrolling:"auto",src:this.preload.src+"&output=embed&s=AARTsJrrJfAezwFwvFA6u8OWSecjpwNIVw"}).injectInside(this.canvas);this.nextLinkscr.style.right="25px"}else{if(this.preload.datatype=="hidden"){this.p_width=this.preload.w;this.p_height=this.preload.h;this.iframeId=this.preload.src;$(this.iframeId).setStyles({left:"0px",top:"0px",height:this.p_height,width:this.p_width,display:"block"});$(this.preload.src).setProperties({width:this.p_width,height:this.p_height,frameBorder:0,scrolling:"auto"}).injectInside(this.canvas);this.nextLink.style.right="25px"}else{this.p_width=this.preload.w;this.p_height=this.preload.h;this.iframeId="lbFrame_"+new Date().getTime();try{new Element("iframe").setProperties({id:this.iframeId,width:this.p_width,height:this.p_height,frameBorder:0,scrolling:"auto",src:this.preload.src}).injectInside(this.canvas)}catch(ex){}this.nextLink.style.right="25px"}}}}}}}this.canvas.style.width=this.bottom.style.width=this.p_width+"px";this.canvas.style.height=this.prevLink.style.height=this.nextLink.style.height=this.p_height+"px";this.caption.setHTML(this.items[this.activeItem][1]||"");this.number.setHTML((this.items.length==1)?"":"Page "+(this.activeItem+1)+" of "+this.items.length);if(this.activeItem){this.preloadPrev.src=this.items[this.activeItem-1][0]}if(this.activeItem!=(this.items.length-1)){this.preloadNext.src=this.items[this.activeItem+1][0]}if(this.center.clientHeight!=this.canvas.offsetHeight){var oh=(this.p_height==this.canvas.clientHeight)?this.canvas.offsetHeight:eval(this.p_height)+18;this.fx.resizeCenter.start({height:oh});break}this.step++;case 2:if(this.center.clientWidth!=this.canvas.offsetWidth){var ow=(this.p_width==this.canvas.clientWidth)?this.canvas.offsetWidth:eval(this.p_width)+18;this.fx.resizeCenter.start({width:ow,marginLeft:-ow/2});break}this.step++;case 3:this.bottomContainer.setStyles({top:(this.top+this.center.clientHeight)+"px",height:"0px",marginLeft:this.center.style.marginLeft,width:this.center.style.width,display:""});this.fx.image.start(1);break;case 4:if(this.options.animateCaption){this.fx.bottom.start(0,this.bottom.offsetHeight+10);break}this.bottomContainer.style.height=(this.bottom.offsetHeight+10)+"px";case 5:if(this.activeItem){this.prevLink.style.display=""}if(this.activeItem!=(this.items.length-1)){this.nextLink.style.display=""}if(this.preload.datatype=="stream"){try{$("lbStreamPlayer").sendEvent("playpause")}catch(ex){}}else{if(this.preload.datatype=="youtube"){try{$("lbYoutube").playVideo()}catch(ex){}}}window.fireEvent("slimboxready");this.step=0}},close:function(){if(this.step<0){return}this.step=-1;this.removeCurrentItem();for(var f in this.fx){this.fx[f].stop()}this.center.style.display=this.bottomContainer.style.display="none";this.center.style.width=this.options.initialWidth+"px";this.center.style.height=this.options.initialHeight+"px";this.center.style.marginLeft="-"+(this.options.initialWidth/2)+"px";this.fx.overlay.chain(this.setup.pass(false,this)).start(0);return false},removeCurrentItem:function(){if(this.preload){if(this.preload.datatype=="image"){$("lbImage").remove();this.preload.onload=Class.empty}else{if(this.preload.datatype=="youtube"){$("lbYoutubePlayer").parentNode.removeChild($("lbYoutubePlayer"))}else{if(this.preload.datatype=="dailymotion"){$("lbDailymotionPlayer").parentNode.removeChild($("lbDailymotionPlayer"))}else{if(this.preload.datatype=="flash"){$("lbFlashPlayer").parentNode.removeChild($("lbFlashPlayer"))}else{if(this.preload.datatype=="stream"){$("lbStreamPlayer").parentNode.removeChild($("lbStreamPlayer"))}else{if(this.preload.datatype=="googleMap"){$(this.iframeId).remove()}else{if(this.preload.datatype=="hidden"){$(this.iframeId).setStyle("display","none")}else{$(this.iframeId).remove()}}}}}}}this.preload=null}},matchOrDefault:function(str,re,val){if(!str){return val}var hasQuery=str.match(re);return hasQuery?hasQuery[1]:val}};window.addEvent("domready",Lightbox.init.bind(Lightbox));/**
* SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
*
* SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
*/
if(typeof deconcept == "undefined") var deconcept = new Object();
if(typeof deconcept.util == "undefined") deconcept.util = new Object();
if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
deconcept.SWFObject = function(swf, id, w, h, ver, c, quality, xiRedirectUrl, redirectUrl, detectKey) {
if (!document.getElementById) { return; }
this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
this.params = new Object();
this.variables = new Object();
this.attributes = new Array();
if(swf) { this.setAttribute('swf', swf); }
if(id) { this.setAttribute('id', id); }
if(w) { this.setAttribute('width', w); }
if(h) { this.setAttribute('height', h); }
if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion();
if (!window.opera && document.all && this.installedVer.major > 7) {
// only add the onunload cleanup if the Flash Player version supports External Interface and we are in IE
deconcept.SWFObject.doPrepUnload = true;
}
if(c) { this.addParam('bgcolor', c); }
var q = quality ? quality : 'high';
this.addParam('quality', q);
this.setAttribute('useExpressInstall', false);
this.setAttribute('doExpressInstall', false);
var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
this.setAttribute('xiRedirectUrl', xir);
this.setAttribute('redirectUrl', '');
if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
};
deconcept.SWFObject.prototype = {
useExpressInstall: function(path) {
this.xiSWFPath = !path ? "expressinstall.swf" : path;
this.setAttribute('useExpressInstall', true);
},
setAttribute: function(name, value){
this.attributes[name] = value;
},
getAttribute: function(name){
return this.attributes[name];
},
addParam: function(name, value){
this.params[name] = value;
},
getParams: function(){
return this.params;
},
addVariable: function(name, value){
this.variables[name] = value;
},
getVariable: function(name){
return this.variables[name];
},
getVariables: function(){
return this.variables;
},
getVariablePairs: function(){
var variablePairs = new Array();
var key;
var variables = this.getVariables();
for(key in variables){
variablePairs[variablePairs.length] = key +"="+ variables[key];
}
return variablePairs;
},
getSWFHTML: function() {
var swfNode = "";
if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
if (this.getAttribute("doExpressInstall")) {
this.addVariable("MMplayerType", "PlugIn");
this.setAttribute('swf', this.xiSWFPath);
}
swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'" style="'+ this.getAttribute('style') +'"';
swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
var params = this.getParams();
for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
var pairs = this.getVariablePairs().join("&");
if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
swfNode += '/>';
} else { // PC IE
if (this.getAttribute("doExpressInstall")) {
this.addVariable("MMplayerType", "ActiveX");
this.setAttribute('swf', this.xiSWFPath);
}
swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'" style="'+ this.getAttribute('style') +'">';
swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
var params = this.getParams();
for(var key in params) {
swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
}
var pairs = this.getVariablePairs().join("&");
if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
swfNode += "</object>";
}
return swfNode;
},
write: function(elementId){
if(this.getAttribute('useExpressInstall')) {
// check to see if we need to do an express install
var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
this.setAttribute('doExpressInstall', true);
this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
document.title = document.title.slice(0, 47) + " - Flash Player Installation";
this.addVariable("MMdoctitle", document.title);
}
}
if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
n.innerHTML = this.getSWFHTML();
return true;
}else{
if(this.getAttribute('redirectUrl') != "") {
document.location.replace(this.getAttribute('redirectUrl'));
}
}
return false;
}
};
/* ---- detection functions ---- */
deconcept.SWFObjectUtil.getPlayerVersion = function(){
var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
if(navigator.plugins && navigator.mimeTypes.length){
var x = navigator.plugins["Shockwave Flash"];
if(x && x.description) {
PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
}
}else if (navigator.userAgent && navigator.userAgent.indexOf("Windows CE") >= 0){ // if Windows CE
var axo = 1;
var counter = 3;
while(axo) {
try {
counter++;
axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+ counter);
//				document.write("player v: "+ counter);
PlayerVersion = new deconcept.PlayerVersion([counter,0,0]);
} catch (e) {
axo = null;
}
}
} else { // Win IE (non mobile)
// do minor version lookup in IE, but avoid fp6 crashing issues
// see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
try{
var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
}catch(e){
try {
var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
PlayerVersion = new deconcept.PlayerVersion([6,0,21]);
axo.AllowScriptAccess = "always"; // error if player version < 6.0.47 (thanks to Michael Williams @ Adobe for this code)
} catch(e) {
if (PlayerVersion.major == 6) {
return PlayerVersion;
}
}
try {
axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
} catch(e) {}
}
if (axo != null) {
PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
}
}
return PlayerVersion;
};
deconcept.PlayerVersion = function(arrVersion){
this.major = arrVersion[0] != null ? parseInt(arrVersion[0]) : 0;
this.minor = arrVersion[1] != null ? parseInt(arrVersion[1]) : 0;
this.rev = arrVersion[2] != null ? parseInt(arrVersion[2]) : 0;
};
deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
if(this.major < fv.major) return false;
if(this.major > fv.major) return true;
if(this.minor < fv.minor) return false;
if(this.minor > fv.minor) return true;
if(this.rev < fv.rev) return false;
return true;
};
/* ---- get value of query string param ---- */
deconcept.util = {
getRequestParameter: function(param) {
var q = document.location.search || document.location.hash;
if (param == null) { return q; }
if(q) {
var pairs = q.substring(1).split("&");
for (var i=0; i < pairs.length; i++) {
if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
return pairs[i].substring((pairs[i].indexOf("=")+1));
}
}
}
return "";
}
};
/* fix for video streaming bug */
deconcept.SWFObjectUtil.cleanupSWFs = function() {
var objects = document.getElementsByTagName("OBJECT");
for (var i = objects.length - 1; i >= 0; i--) {
objects[i].style.display = 'none';
for (var x in objects[i]) {
if (typeof objects[i][x] == 'function') {
objects[i][x] = function(){};
}
}
}
};
// fixes bug in some fp9 versions see http://blog.deconcept.com/2006/07/28/swfobject-143-released/
if (deconcept.SWFObject.doPrepUnload) {
if (!deconcept.unloadSet) {
deconcept.SWFObjectUtil.prepUnload = function() {
__flash_unloadHandler = function(){};
__flash_savedUnloadHandler = function(){};
window.attachEvent("onunload", deconcept.SWFObjectUtil.cleanupSWFs);
};
window.attachEvent("onbeforeunload", deconcept.SWFObjectUtil.prepUnload);
deconcept.unloadSet = true;
}
};
/* add document.getElementById if needed (mobile IE < 5) */
if (!document.getElementById && document.all) { document.getElementById = function(id) { return document.all[id]; }}
/* add some aliases for ease of use/backwards compatibility */
var getQueryParamValue = deconcept.util.getRequestParameter;
var FlashObject = deconcept.SWFObject; // for legacy support
var SWFObject = deconcept.SWFObject;
// Calendar: a Javascript class for Mootools that adds accessible and unobtrusive date pickers to your form elements <http://electricprism.com/aeron/calendar>
// Calendar RC4, Copyright (c) 2007 Aeron Glemann <http://electricprism.com/aeron>, MIT Style License.
var Calendar = new Class({
options: {
blocked: [], // blocked dates
classes: [], // ['calendar', 'prev', 'next', 'month', 'year', 'today', 'invalid', 'valid', 'inactive', 'active', 'hover', 'hilite']
days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // days of the week starting at sunday
direction: 0, // -1 past, 0 past + future, 1 future
draggable: true,
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
navigation: 1, // 0 = no nav; 1 = single nav for month; 2 = dual nav for month and year
offset: 0, // first day of the week: 0 = sunday, 1 = monday, etc..
onHideStart: Class.empty,
onHideComplete: Class.empty,
onShowStart: Class.empty,
onShowComplete: Class.empty,
pad: 1, // padding between multiple calendars
tweak: {x: 0, y: 0} // tweak calendar positioning
},
// initialize: calendar constructor
// @param obj (obj) a js object containing the form elements and format strings { id: 'format', id: 'format' etc }
// @param props (obj) optional properties
initialize: function(obj, options) {
// basic error checking
if (!obj) { return false; }
this.setOptions(options);
// create our classes array
var keys = ['calendar', 'prev', 'next', 'month', 'year', 'today', 'invalid', 'valid', 'inactive', 'active', 'hover', 'hilite'];
var values = keys.map(function(key, i) {
if (this.options.classes[i]) {
if (this.options.classes[i].length) { key = this.options.classes[i]; }
}
return key;
}, this);
this.classes = values.associate(keys);
// create cal element with css styles required for proper cal functioning
this.calendar = new Element('div', {
'styles': { left: '-1000px', opacity: 0, position: 'absolute', top: '-1000px', zIndex: 1000 }
}).addClass(this.classes.calendar).injectInside(document.body);
// iex 6 needs a transparent iframe underneath the calendar in order to not allow select elements to render through
if (window.ie6) {
this.iframe = new Element('iframe', {
'styles': { left: '-1000px', position: 'absolute', top: '-1000px', zIndex: 999 }
}).injectInside(document.body);
this.iframe.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';
}
// initialize fade method
this.fx = this.calendar.effect('opacity', {
onStart: function() {
if (this.calendar.getStyle('opacity') == 0) { // show
if (window.ie6) { this.iframe.setStyle('display', 'block'); }
this.calendar.setStyle('display', 'block');
this.fireEvent('onShowStart', this.element);
}
else { // hide
this.fireEvent('onHideStart', this.element);
}
}.bind(this),
onComplete: function() {
if (this.calendar.getStyle('opacity') == 0) { // hidden
this.calendar.setStyle('display', 'none');
if (window.ie6) { this.iframe.setStyle('display', 'none'); }
this.fireEvent('onHideComplete', this.element);
}
else { // shown
this.fireEvent('onShowComplete', this.element);
}
}.bind(this)
});
// initialize drag method
if (window.Drag && this.options.draggable) {
this.drag = new Drag.Move(this.calendar, {
onDrag: function() {
if (window.ie6) { this.iframe.setStyles({ left: this.calendar.style.left, top: this.calendar.style.top }); }
}.bind(this)
});
}
// create calendars array
this.calendars = [];
this._id = 0;
var d = new Date(); // today
d.setDate(d.getDate() + this.options.direction.toInt()); // correct today for directional offset
for (var i in obj) {
var cal = {
button: new Element('button', { 'type': 'button' }),
el: $(i),
els: [],
id: this._id++,
month: d.getMonth(),
visible: false,
year: d.getFullYear()
};
// fix for bad element (naughty, naughty element!)
if (!this.element(i, obj[i], cal)) { continue; }
//cal.el.addClass(this.classes.calendar);
// create cal button
cal.button.addClass(this.classes.calendar).addEvent('click', function(cal) { this.toggle(cal); }.pass(cal, this)).injectAfter(cal.el);
// read in default value
cal.val = this.read(cal);
$extend(cal, this.bounds(cal)); // abs bounds of calendar
$extend(cal, this.values(cal)); // valid days, months, years
this.rebuild(cal);
this.calendars.push(cal); // add to cals array
}
},
addElement: function(obj){
var d = new Date(); // today
d.setDate(d.getDate() + this.options.direction.toInt()); // correct today for directional offset
for (var i in obj) {
var cal = {
button: new Element('button', { 'type': 'button' }),
el: $(i),
els: [],
id: this._id++,
month: d.getMonth(),
visible: false,
year: d.getFullYear()
};
// fix for bad element (naughty, naughty element!)
if (!this.element(i, obj[i], cal)) { continue; }
//cal.el.addClass(this.classes.calendar);
// create cal button
cal.button.addClass(this.classes.calendar).addEvent('click', function(cal) { this.toggle(cal); }.pass(cal, this)).injectAfter(cal.el);
// read in default value
//	cal.val = this.read(cal);
$extend(cal, this.bounds(cal)); // abs bounds of calendar
$extend(cal, this.values(cal)); // valid days, months, years
//this.rebuild(cal);
this.calendars.push(cal); // add to cals array
}
},
// blocked: returns an array of blocked days for the month / year
// @param cal (obj)
// @returns blocked days (array)
blocked: function(cal) {
var blocked = [];
var offset = new Date(cal.year, cal.month, 1).getDay(); // day of the week (offset)
var last = new Date(cal.year, cal.month + 1, 0).getDate(); // last day of this month
this.options.blocked.each(function(date){
var values = date.split(' ');
// preparation
for (var i = 0; i <= 3; i++){
if (!values[i]){ values[i] = (i == 3) ? '' : '*'; } // make sure blocked date contains values for at least d, m and y
values[i] = values[i].contains(',') ? values[i].split(',') : new Array(values[i]); // split multiple values
var count = values[i].length - 1;
for (var j = count; j >= 0; j--){
if (values[i][j].contains('-')){ // a range
var val = values[i][j].split('-');
for (var k = val[0]; k <= val[1]; k++){
if (!values[i].contains(k)){ values[i].push(k + ''); }
}
values[i].splice(j, 1);
}
}
}
// execution
if (values[2].contains(cal.year + '') || values[2].contains('*')){
if (values[1].contains(cal.month + 1 + '') || values[1].contains('*')){
values[0].each(function(val){ // if blocked value indicates this month / year
if (val > 0){ blocked.push(val.toInt()); } // add date to blocked array
});
if (values[3]){ // optional value for day of week
for (var i = 0; i < last; i++){
var day = (i + offset) % 7;
if (values[3].contains(day + '')){
blocked.push(i + 1); // add every date that corresponds to the blocked day of the week to the blocked array
}
}
}
}
}
}, this);
return blocked;
},
// bounds: returns the start / end bounds of the calendar
// @param cal (obj)
// @returns obj
bounds: function(cal) {
// 1. first we assume the calendar has no bounds (or a thousand years in either direction)
// by default the calendar will accept a millennium in either direction
var start = new Date(1000, 0, 1); // jan 1, 1000
var end = new Date(2999, 11, 31); // dec 31, 2999
// 2. but if the cal is one directional we adjust accordingly
var date = new Date().getDate() + this.options.direction.toInt();
if (this.options.direction > 0) {
start = new Date();
start.setDate(date + this.options.pad * cal.id);
}
if (this.options.direction < 0) {
end = new Date();
end.setDate(date - this.options.pad * (this.calendars.length - cal.id - 1));
}
// 3. then we can further filter the limits by using the pre-existing values in the selects
cal.els.each(function(el) {
if (el.getTag() == 'select') {
if (el.format.test('(y|Y)')) { // search for a year select
var years = [];
el.getChildren().each(function(option) { // get options
var values = this.unformat(option.value, el.format);
if (!years.contains(values[0])) { years.push(values[0]); } // add to years array
}, this);
years.sort(this.sort);
if (years[0] > start.getFullYear()) {
d = new Date(years[0], start.getMonth() + 1, 0); // last day of new month
if (start.getDate() > d.getDate()) { start.setDate(d.getDate()); }
start.setYear(years[0]);
}
if (years.getLast() < end.getFullYear()) {
d = new Date(years.getLast(), end.getMonth() + 1, 0); // last day of new month
if (end.getDate() > d.getDate()) { end.setDate(d.getDate()); }
end.setYear(years.getLast());
}
}
if (el.format.test('(F|m|M|n)')) { // search for a month select
var months_start = [];
var months_end = [];
el.getChildren().each(function(option) { // get options
var values = this.unformat(option.value, el.format);
if ($type(values[0]) != 'number' || values[0] == years[0]) { // if it's a year / month combo for curr year, or simply a month select
if (!months_start.contains(values[1])) { months_start.push(values[1]); } // add to months array
}
if ($type(values[0]) != 'number' || values[0] == years.getLast()) { // if it's a year / month combo for curr year, or simply a month select
if (!months_end.contains(values[1])) { months_end.push(values[1]); } // add to months array
}
}, this);
months_start.sort(this.sort);
months_end.sort(this.sort);
if (months_start[0] > start.getMonth()) {
d = new Date(start.getFullYear(), months_start[0] + 1, 0); // last day of new month
if (start.getDate() > d.getDate()) { start.setDate(d.getDate()); }
start.setMonth(months_start[0]);
}
if (months_end.getLast() < end.getMonth()) {
d = new Date(start.getFullYear(), months_end.getLast() + 1, 0); // last day of new month
if (end.getDate() > d.getDate()) { end.setDate(d.getDate()); }
end.setMonth(months_end.getLast());
}
}
}
}, this);
return { 'start': start, 'end': end };
},
// caption: returns the caption element with header and navigation
// @param cal (obj)
// @returns caption (element)
caption: function(cal) {
// start by assuming navigation is allowed
var navigation = {
prev: { 'month': true, 'year': true },
next: { 'month': true, 'year': true }
};
// if we're in an out of bounds year
if (cal.year == cal.start.getFullYear()) {
navigation.prev.year = false;
if (cal.month == cal.start.getMonth() && this.options.navigation == 1) {
navigation.prev.month = false;
}
}
if (cal.year == cal.end.getFullYear()) {
navigation.next.year = false;
if (cal.month == cal.end.getMonth() && this.options.navigation == 1) {
navigation.next.month = false;
}
}
// special case of improved navigation but months array with only 1 month we can disable all month navigation
if ($type(cal.months) == 'array') {
if (cal.months.length == 1 && this.options.navigation == 2) {
navigation.prev.month = navigation.next.month = false;
}
}
var caption = new Element('caption');
//		var prev = new Element('a').addClass(this.classes.prev).appendText('\x3c'); // <
//		var next = new Element('a').addClass(this.classes.next).appendText('\x3e'); // >
var prev = new Element('a').addClass(this.classes.prev).setHTML('&nbsp;&nbsp;&nbsp;&nbsp;'); // <
var next = new Element('a').addClass(this.classes.next).setHTML('&nbsp;&nbsp;&nbsp;&nbsp;'); // >
if (this.options.navigation == 2) {
var month = new Element('span').addClass(this.classes.month).injectInside(caption);
if (navigation.prev.month) { prev.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', -1); }.pass(cal, this)).injectInside(month); }
var monthSpan = new Element('span').setHTML(this.options.months[cal.month]);
monthSpan.setStyle('cursor','pointer');
monthSpan.addEvent('mouseenter', function(e){
monthSpan.setStyle('text-decoration', 'underline');
});
monthSpan.addEvent('mouseleave', function(e){
monthSpan.setStyle('text-decoration', 'none');
});
// create a list of month select menu
var monthsList = new Element('select', {'style': 'width:60px; font-size:11px;'});
for (var i = 0; i < this.options.months.length; i++) {
var option = new Element('option', {'style': 'font-size:11px;','value':i}).setHTML(this.options.months[i]);
if(cal.month == i){
option.setAttribute('selected', 'selected');
}
option.injectInside(monthsList);
}
monthsList.addEvent('change', function(e){
this.navigate(cal, 'm', monthsList.value-cal.month);
}.bind(this));
monthSpan.addEvent('click', function(e){
monthSpan.removeEvents('click');
monthSpan.empty();
monthsList.injectInside(monthSpan);
}.bind(this));
month.adopt(monthSpan);
if (navigation.next.month) { next.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', 1); }.pass(cal, this)).injectInside(month); }
var year = new Element('span').addClass(this.classes.year).injectInside(caption);
if (navigation.prev.year) { prev.clone().addEvent('click', function(cal) { this.navigate(cal, 'y', -1); }.pass(cal, this)).injectInside(year); }
var yearSpan = new Element('span').appendText(cal.year);
yearSpan.setStyle('cursor','pointer');
yearSpan.addEvent('mouseenter', function(e){
yearSpan.setStyle('text-decoration', 'underline');
});
yearSpan.addEvent('mouseleave', function(e){
yearSpan.setStyle('text-decoration', 'none');
});
// create a list of years select menu
var yearsList = new Element('select', {'style': 'font-size:11px;'});
for (var i = new Date().getFullYear() - 100; i < new Date().getFullYear() + 5; i++) {
var option = new Element('option', {'style': 'font-size:11px;','value':i}).appendText(i);
if(cal.year == i){
option.setAttribute('selected', 'selected');
}
option.injectInside(yearsList);
}
yearsList.addEvent('change', function(e){
this.navigate(cal, 'y', yearsList.value-cal.year);
}.bind(this));
yearSpan.addEvent('click', function(e){
yearSpan.removeEvents('click');
yearSpan.empty();
yearsList.injectInside(yearSpan);
}.bind(this));
year.adopt(yearSpan);
if (navigation.next.year) { next.clone().addEvent('click', function(cal) { this.navigate(cal, 'y', 1); }.pass(cal, this)).injectInside(year); }
}
else { // 1 or 0
if (navigation.prev.month && this.options.navigation) { prev.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', -1); }.pass(cal, this)).injectInside(caption); }
caption.adopt(new Element('span').addClass(this.classes.month).appendText(this.options.months[cal.month]));
caption.adopt(new Element('span').addClass(this.classes.year).appendText(cal.year));
if (navigation.next.month && this.options.navigation) { next.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', 1); }.pass(cal, this)).injectInside(caption); }
}
return caption;
},
// changed: run when a select value is changed
// @param cal (obj)
changed: function(cal) {
cal.val = this.read(cal); // update calendar val from inputs
$extend(cal, this.values(cal)); // update bounds - based on curr month
this.rebuild(cal); // rebuild days select
if (!cal.val) { return; } // in case the same date was clicked the cal has no set date we should exit
if (cal.val.getDate() < cal.days[0]) { cal.val.setDate(cal.days[0]); }
if (cal.val.getDate() > cal.days.getLast()) { cal.val.setDate(cal.days.getLast()); }
cal.els.each(function(el) {	// then we can set the value to the field
el.value = this.format(cal.val, el.format);
}, this);
this.check(cal); // checks other cals
this.calendars.each(function(kal) { // update cal graphic if visible
if (kal.visible) { this.display(kal); }
}, this);
},
// check: checks other calendars to make sure no overlapping values
// @param cal (obj)
check: function(cal) {
/** this.calendars.each(function(kal, i) {
if (kal.val) { // if calendar has value set
var change = false;
if (i < cal.id) { // preceding calendar
var bound = new Date(Date.parse(cal.val));
bound.setDate(bound.getDate() - (this.options.pad * (cal.id - i)));
if (bound < kal.val) { change = true; }
}
if (i > cal.id) { // following calendar
var bound = new Date(Date.parse(cal.val));
bound.setDate(bound.getDate() + (this.options.pad * (i - cal.id)));
if (bound > kal.val) { change = true; }
}
if (change) {
if (kal.start > bound) { bound = kal.start; }
if (kal.end < bound) { bound = kal.end; }
kal.month = bound.getMonth();
kal.year = bound.getFullYear();
$extend(kal, this.values(kal));
// TODO - IN THE CASE OF SELECT MOVE TO NEAREST VALID VALUE
// IN THE CASE OF INPUT DISABLE
// if new date is not valid better unset cal value
// otherwise it would mean incrementally checking to find the nearest valid date which could be months / years away
kal.val = kal.days.contains(bound.getDate()) ? bound : null;
this.write(kal);
if (kal.visible) { this.display(kal); } // update cal graphic if visible
}
}
else {
kal.month = cal.month;
kal.year = cal.year;
}
}, this); **/
},
// clicked: run when a valid day is clicked in the calendar
// @param cal (obj)
clicked: function(td, day, cal) {
cal.val = (this.value(cal) == day) ? null : new Date(cal.year, cal.month, day); // set new value - if same then disable
this.write(cal);
// ok - in the special case that it's all selects and there's always a date no matter what (at least as far as the form is concerned)
// we can't let the calendar undo a date selection - it's just not possible!!
if (!cal.val) { cal.val = this.read(cal); }
if (cal.val) {
this.check(cal); // checks other cals
this.toggle(cal); // hide cal
}
else { // remove active class and replace with valid
td.addClass(this.classes.valid);
td.removeClass(this.classes.active);
}
},
// display: create calendar element
// @param cal (obj)
display: function(cal) {
// 1. header and navigation
this.calendar.empty(); // init div
this.calendar.className = this.classes.calendar + ' ' + this.options.months[cal.month].toLowerCase();
var div = new Element('div').injectInside(this.calendar); // a wrapper div to help correct browser css problems with the caption element
var table = new Element('table').injectInside(div).adopt(this.caption(cal));
// 2. day names
var thead = new Element('thead').injectInside(table);
var tr = new Element('tr').injectInside(thead);
for (var i = 0; i <= 6; i++) {
var th = this.options.days[(i + this.options.offset) % 7];
tr.adopt(new Element('th', { 'title': th }).appendText(th.substr(0, 1)));
}
// 3. day numbers
var tbody = new Element('tbody').injectInside(table);
var tr = new Element('tr').injectInside(tbody);
var d = new Date(cal.year, cal.month, 1);
var offset = ((d.getDay() - this.options.offset) + 7) % 7; // day of the week (offset)
var last = new Date(cal.year, cal.month + 1, 0).getDate(); // last day of this month
var prev = new Date(cal.year, cal.month, 0).getDate(); // last day of previous month
var active = this.value(cal); // active date (if set and within curr month)
var valid = cal.days; // valid days for curr month
var inactive = []; // active dates set by other calendars
var hilited = [];
/**	this.calendars.each(function(kal, i) {
if (kal != cal && kal.val) {
if (cal.year == kal.val.getFullYear() && cal.month == kal.val.getMonth()) { inactive.push(kal.val.getDate()); }
if (cal.val) {
for (var day = 1; day <= last; day++) {
d.setDate(day);
if ((i < cal.id && d > kal.val && d < cal.val) || (i > cal.id && d > cal.val && d < kal.val)) {
if (!hilited.contains(day)) { hilited.push(day); }
}
}
}
}
}, this);**/
var d = new Date();
var today = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime(); // today obv
for (var i = 1; i < 43; i++) { // 1 to 42 (6 x 7 or 6 weeks)
if ((i - 1) % 7 == 0) { tr = new Element('tr').injectInside(tbody); } // each week is it's own table row
var td = new Element('td').injectInside(tr);
var day = i - offset;
var date = new Date(cal.year, cal.month, day);
var cls = '';
if (day === active) { cls = this.classes.active; } // active
else if (inactive.contains(day)) { cls = this.classes.inactive; } // inactive
else if (valid.contains(day)) { cls = this.classes.valid; } // valid
else if (day >= 1 && day <= last) { cls = this.classes.invalid; } // invalid
if (date.getTime() == today) { cls = cls + ' ' + this.classes.today; } // adds class for today
if (hilited.contains(day)) { cls = cls + ' ' + this.classes.hilite; } // adds class if hilited
td.addClass(cls);
if (valid.contains(day)) { // if it's a valid - clickable - day we add interaction
td.setProperty('title', this.format(date, 'D M jS Y'));
td.addEvents({
'click': function(td, day, cal) {
this.clicked(td, day, cal);
}.pass([td, day, cal], this),
'mouseover': function(td, cls) {
td.addClass(cls);
}.pass([td, this.classes.hover]),
'mouseout': function(td, cls) {
td.removeClass(cls);
}.pass([td, this.classes.hover])
});
}
// pad calendar with last days of prev month and first days of next month
if (day < 1) { day = prev + day; }
else if (day > last) { day = day - last; }
td.appendText(day);
}
},
// element: helper function
// @param el (string) element id
// @param f (string) format string
// @param cal (obj)
element: function(el, f, cal) {
if ($type(f) == 'object') { // in the case of multiple inputs per calendar
for (var i in f) {
if (!this.element(i, f[i], cal)) { return false; }
}
return true;
}
el = $(el);
if (!el) { return false; }
el.format = f;
if (el.getTag() == 'select') { // select elements allow the user to manually set the date via select option
el.addEvent('change', function(cal) { this.changed(cal); }.pass(cal, this));
}
else { // input (type text) elements restrict the user to only setting the date via the calendar
el.readOnly = true;
el.addEvent('focus', function(cal) { this.toggle(cal); }.pass(cal, this));
}
cal.els.push(el);
return true;
},
// format: formats a date object according to passed in instructions
// @param date (obj)
// @param f (string) any combination of punctuation / separators and d, j, D, l, S, m, n, F, M, y, Y
// @returns string
format: function(date, format) {
var str = '';
if (date) {
var j = date.getDate(); // 1 - 31
var w = date.getDay(); // 0 - 6
var l = this.options.days[w]; // Sunday - Saturday
var n = date.getMonth() + 1; // 1 - 12
var f = this.options.months[n - 1]; // January - December
var y = date.getFullYear() + ''; // 19xx - 20xx
for (var i = 0, len = format.length; i < len; i++) {
var cha = format.charAt(i); // format char
switch(cha) {
// year cases
case 'y': // xx - xx
y = y.substr(2);
case 'Y': // 19xx - 20xx
str += y;
break;
// month cases
case 'm': // 01 - 12
if (n < 10) { n = '0' + n; }
case 'n': // 1 - 12
str += n;
break;
case 'M': // Jan - Dec
f = f.substr(0, 3);
case 'F': // January - December
str += f;
break;
// day cases
case 'd': // 01 - 31
if (j < 10) { j = '0' + j; }
case 'j': // 1 - 31
str += j;
break;
case 'D': // Sun - Sat
l = l.substr(0, 3);
case 'l': // Sunday - Saturday
str += l;
break;
case 'N': // 1 - 7
w += 1;
case 'w': // 0 - 6
str += w;
break;
case 'S': // st, nd, rd or th (works well with j)
if (j % 10 == 1 && j != '11') { str += 'st'; }
else if (j % 10 == 2 && j != '12') { str += 'nd'; }
else if (j % 10 == 3 && j != '13') { str += 'rd'; }
else { str += 'th'; }
break;
default:
str += cha;
}
}
}
return str; //  return format with values replaced
},
// navigate: calendar navigation
// @param cal (obj)
// @param type (str) m or y for month or year
// @param n (int) + or - for next or prev
navigate: function(cal, type, n) {
switch (type) {
case 'm': // month
if ($type(cal.months) == 'array') {
var i = cal.months.indexOf(cal.month) + n; // index of current month
if (i < 0 || i == cal.months.length) { // out of range
if (this.options.navigation == 1) { // if type 1 nav we'll need to increment the year
this.navigate(cal, 'y', n);
}
i = (i < 0) ? cal.months.length - 1 : 0;
}
cal.month = cal.months[i];
}
else {
var i = cal.month + n;
if (i < 0 || i == 12) {
if (this.options.navigation == 1) {
this.navigate(cal, 'y', n);
}
i = (i < 0) ? 11 : 0;
}
cal.month = i;
}
break;
case 'y': // year
if ($type(cal.years) == 'array') {
var i = cal.years.indexOf(cal.year) + n;
cal.year = cal.years[i];
}
else {
cal.year += n;
}
break;
}
$extend(cal, this.values(cal));
if ($type(cal.months) == 'array') { // if the calendar has a months select
var i = cal.months.indexOf(cal.month); // and make sure the curr months exists for the new year
if (i < 0) { cal.month = cal.months[0]; } // otherwise we'll reset the month
}
this.display(cal);
},
// read: compiles cal value based on array of inputs passed in
// @param cal (obj)
// @returns date (obj) or (null)
read: function(cal) {
var arr = [null, null, null];
cal.els.each(function(el) {
// returns an array which may contain empty values
var values = this.unformat(el.value, el.format);
values.each(function(val, i) {
if ($type(val) == 'number') { arr[i] = val; }
});
}, this);
// we can update the cals month and year values
if ($type(arr[0]) == 'number') { cal.year = arr[0]; }
if ($type(arr[1]) == 'number') { cal.month = arr[1]; }
var val = null;
if (arr.every(function(i) { return $type(i) == 'number'; })) { // if valid date
var last = new Date(arr[0], arr[1] + 1, 0).getDate(); // last day of month
if (arr[2] > last) { arr[2] = last; } // make sure we stay within the month (ex in case default day of select is 31 and month is feb)
val = new Date(arr[0], arr[1], arr[2]);
}
return (cal.val == val) ? null : val; // if new date matches old return null (same date clicked twice = disable)
},
// rebuild: rebuilds days + months selects
// @param cal (obj)
rebuild: function(cal) {
cal.els.each(function(el) {
/*
if (el.getTag() == 'select' && el.format.test('^(F|m|M|n)$')) { // special case for months-only select
if (!cal.options) { cal.options = el.clone(); } // clone a copy of months select
var val = (cal.val) ? cal.val.getMonth() : el.value.toInt();
el.empty(); // initialize select
cal.months.each(function(month) {
// create an option element
var option = new Element('option', {
'selected': (val == month),
'value': this.format(new Date(1, month, 1), el.format);
}).appendText(day).injectInside(el);
}, this);
}
*/
if (el.getTag() == 'select' && el.format.test('^(d|j)$')) { // special case for days-only select
var d = this.value(cal);
if (!d) { d = el.value.toInt(); } // if the calendar doesn't have a set value, try to use value from select
el.empty(); // initialize select
cal.days.each(function(day) {
// create an option element
var option = new Element('option', {
'selected': (d == day),
'value': ((el.format == 'd' && day < 10) ? '0' + day : day)
}).appendText(day).injectInside(el);
}, this);
}
}, this);
},
// sort: helper function for numerical sorting
sort: function(a, b) {
return a - b;
},
// toggle: show / hide calendar
// @param cal (obj)
toggle: function(cal) {
document.removeEvent('mousedown', this.fn); // always remove the current mousedown script first
if (cal.visible) { // simply hide curr cal
cal.visible = false;
cal.button.removeClass(this.classes.active); // active
this.fx.start(1, 0);
}
else { // otherwise show (may have to hide others)
// hide cal on out-of-bounds click
this.fn = function(e, cal) {
var e = new Event(e);
var el = e.target;
var stop = false;
while (el != document.body && el.nodeType == 1) {
if (el == this.calendar) { stop = true; }
this.calendars.each(function(kal) {
if (kal.button == el || kal.els.contains(el)) { stop = true; }
});
if (stop) {
e.stop();
return false;
}
else { el = el.parentNode; }
}
this.toggle(cal);
}.create({ 'arguments': cal, 'bind': this, 'event': true });
document.addEvent('mousedown', this.fn);
this.calendars.each(function(kal) {
if (kal == cal) {
kal.visible = true;
kal.button.addClass(this.classes.active); // css c-icon-active
}
else {
kal.visible = false;
kal.button.removeClass(this.classes.active); // css c-icon-active
}
}, this);
var size = window.getSize().scrollSize;
var coord = cal.button.getCoordinates();
var x = coord.right + this.options.tweak.x;
var y = coord.top + this.options.tweak.y;
// make sure the calendar doesn't open off screen
if (!this.calendar.coord) { this.calendar.coord = this.calendar.getCoordinates(); }
if (x + this.calendar.coord.width > size.x) { x -= (x + this.calendar.coord.width - size.x); }
if (y + this.calendar.coord.height > size.y) { y -= (y + this.calendar.coord.height - size.y); }
this.calendar.setStyles({ left: x + 'px', top: y + 'px' });
if (window.ie6) {
this.iframe.setStyles({ height: this.calendar.coord.height + 'px', left: x + 'px', top: y + 'px', width: this.calendar.coord.width + 'px' });
}
this.display(cal);
this.fx.start(0, 1);
}
},
// unformat: takes a value from an input and parses the d, m and y elements
// @param val (string)
// @param f (string) any combination of punctuation / separators and d, j, D, l, S, m, n, F, M, y, Y
// @returns array
unformat: function(val, f) {
f = f.escapeRegExp();
var re = {
d: '([0-9]{2})',
j: '([0-9]{1,2})',
D: '(' + this.options.days.map(function(day) { return day.substr(0, 3); }).join('|') + ')',
l: '(' + this.options.days.join('|') + ')',
S: '(st|nd|rd|th)',
F: '(' + this.options.months.join('|') + ')',
m: '([0-9]{2})',
M: '(' + this.options.months.map(function(month) { return month.substr(0, 3); }).join('|') + ')',
n: '([0-9]{1,2})',
Y: '([0-9]{4})',
y: '([0-9]{2})'
};
var arr = []; // array of indexes
var g = '';
// convert our format string to regexp
for (var i = 0; i < f.length; i++) {
var c = f.charAt(i);
if (re[c]) {
arr.push(c);
g += re[c];
}
else {
g += c;
}
}
// match against date
var matches = val.match('^' + g + '$');
var dates = new Array(3);
if (matches) {
matches = matches.slice(1); // remove first match which is the date
arr.each(function(c, i) {
i = matches[i];
switch(c) {
// year cases
case 'y':
i = '19' + i; // 2 digit year assumes 19th century (same as JS)
case 'Y':
dates[0] = i.toInt();
break;
// month cases
case 'F':
i = i.substr(0, 3);
case 'M':
i = this.options.months.map(function(month) { return month.substr(0, 3); }).indexOf(i) + 1;
case 'm':
case 'n':
dates[1] = i.toInt() - 1;
break;
// day cases
case 'd':
case 'j':
dates[2] = i.toInt();
break;
}
}, this);
}
return dates;
},
// value: returns day value of calendar if set
// @param cal (obj)
// @returns day (int) or null
value: function(cal) {
var day = null;
if (cal.val) {
if (cal.year == cal.val.getFullYear() && cal.month == cal.val.getMonth()) { day = cal.val.getDate(); }
}
return day;
},
// values: returns the years, months (for curr year) and days (for curr month and year) for the calendar
// @param cal (obj)
// @returns obj
values: function(cal) {
var years, months, days;
cal.els.each(function(el) {
if (el.getTag() == 'select') {
if (el.format.test('(y|Y)')) { // search for a year select
years = [];
el.getChildren().each(function(option) { // get options
var values = this.unformat(option.value, el.format);
if (!years.contains(values[0])) { years.push(values[0]); } // add to years array
}, this);
years.sort(this.sort);
}
if (el.format.test('(F|m|M|n)')) { // search for a month select
months = []; // 0 - 11 should be
el.getChildren().each(function(option) { // get options
var values = this.unformat(option.value, el.format);
if ($type(values[0]) != 'number' || values[0] == cal.year) { // if it's a year / month combo for curr year, or simply a month select
if (!months.contains(values[1])) { months.push(values[1]); } // add to months array
}
}, this);
months.sort(this.sort);
}
if (el.format.test('(d|j)') && !el.format.test('^(d|j)$')) { // search for a day select, but NOT a days only select
days = []; // 1 - 31
el.getChildren().each(function(option) { // get options
var values = this.unformat(option.value, el.format);
// in the special case of days we dont want the value if its a days only select
// otherwise that will screw up the options rebuilding
// we will take the values if they are exact dates though
if (values[0] == cal.year && values[1] == cal.month) {
if (!days.contains(values[2])) { days.push(values[2]); } // add to days array
}
}, this);
}
}
}, this);
// we start with what would be the first and last days were there no restrictions
var first = 1;
var last = new Date(cal.year, cal.month + 1, 0).getDate(); // last day of the month
// if we're in an out of bounds year
if (cal.year == cal.start.getFullYear()) {
// in the special case of improved navigation but no months array, we'll need to construct one
if (months == null && this.options.navigation == 2) {
months = [];
for (var i = 0; i < 12; i ++) {
if (i >= cal.start.getMonth()) { months.push(i); }
}
}
// if we're in an out of bounds month
if (cal.month == cal.start.getMonth()) {
first = cal.start.getDate(); // first day equals day of bound
}
}
if (cal.year == cal.end.getFullYear()) {
// in the special case of improved navigation but no months array, we'll need to construct one
if (months == null && this.options.navigation == 2) {
months = [];
for (var i = 0; i < 12; i ++) {
if (i <= cal.end.getMonth()) { months.push(i); }
}
}
if (cal.month == cal.end.getMonth()) {
last = cal.end.getDate(); // last day equals day of bound
}
}
// let's get our invalid days
var blocked = this.blocked(cal);
// finally we can prepare all the valid days in a neat little array
if ($type(days) == 'array') { // somewhere there was a days select
days = days.filter(function(day) {
if (day >= first && day <= last && !blocked.contains(day)) { return day; }
});
}
else { // no days select we'll need to construct a valid days array
days = [];
for (var i = first; i <= last; i++) {
if (!blocked.contains(i)) { days.push(i); }
}
}
days.sort(this.sort); // sorting our days will give us first and last of month
return { 'days': days, 'months': months, 'years': years };
},
// write: sets calendars value to form elements
// @param cal (obj)
write: function(cal) {
this.rebuild(cal);	 // in the case of options, we'll need to make sure we have the correct number of days available
cal.els.each(function(el) {	// then we can set the value to the field
el.value = this.format(cal.val, el.format);
}, this);
}
});
Calendar.implement(new Events, new Options);/**
*  Create a drop-down menu for navigation
*
*/
var DropDownMenu = Options.extend({
options: {
onComplete: Class.empty,
onStart: Class.empty,
delay:500
},
initialize: function(el, options) {
this.el = $(el);
this.setOptions(options);
var elementToHide;
this.el.getElements('li').each(function(li, index) {
if(li.getElements('a')[0])li.getElements('a')[0].removeAttribute('title');
if(li.getElements('ul').length){
li.addClass('HasChild');
}
li.menu = this;
li.addEvent('mouseenter', function() {
this.addClass('iehover');
$clear(this._myTimer);
if(elementToHide && !this.getElements('ul').contains(elementToHide)){
elementToHide.removeClass('ulhover');
}
elementToHide = null;
if(this.getElements('ul')[0]) {
this.getElements('ul')[0].addClass('ulhover');
}
});
li.addEvent('mouseleave', function() {
this.removeClass('iehover');
if(this.getElements('ul')[0]) {
elementToHide = this.getElements('ul')[0];
this._myTimer = this.getElements('ul')[0].removeClass.delay(this.menu.options.delay ,this.getElements('ul')[0], 'ulhover');
}
});
}.bind(this));
},
hide : function(){
this.el.getElements('ul').each(function(item,index){
item.removeClass('ulhover');
});
}
});
var SynergeeNews = new Class({
initialize: function(el, elementClass, timer, className) {
this.el = el;
this.elementClass = elementClass;
this._timer = timer;
this._className = ' ';
if(className){
this._className += className;
}
this.items = this.el.getElements(this.elementClass);
// create the nav div
var nav = new Element('ul', {'class': 'Synergee-Web-Page-TextTicker-Nav-Container' + this._className});
this.navButtons = new Array();
for (var i = 0; i < this.items.length; i++) {
this.navButtons[i] = new Element('li', {'class': 'Synergee-Web-Page-TextTicker-NavButton' + this._className});
this.navButtons[i].position = i;
nav.appendChild(this.navButtons[i]);
this.navButtons[i].addEvent('click', function(event) {
event = new Event(event);
this.goto(event.target.position);
}.bind(this));
}
this.el.getParent().appendChild(nav);
if (this.items.length) {
var w = 0;
this.items.each(function(item, index) {
w += item.getSize().size.x;
item.addEvent('mouseenter', function() {
$clear(this.delayedFunction);
}.bind(this));
item.addEvent('mouseleave', function() {
$clear(this.delayedFunction);
this.delayedFunction = this.next.bind(this).delay(this._timer);
}.bind(this));
}.bind(this));
this.el.setStyles({
position: 'absolute',
top: 0,
left: 0,
width: w
});
this.fx = new Fx.Styles(this.el, {duration:800, transition: Fx.Transitions.Quint.easeInOut,
onStart: function(){
var i = (this.current == 0) ? this.items.length : this.current;
this.navButtons[this.current].addClass('Active');
for (var j = 0; j < this.navButtons.length; j ++) {
if (j != this.current)this.navButtons[j].removeClass('Active');
}
this.el.fireEvent('onstart', this.items[this.current]);
}.bind(this),
onCancel :function() {
this.el.fireEvent('oncancel', this.items[this.current]);
},
onComplete:function() {
this.el.fireEvent('itemchanged', this.items[this.current]);
}.bind(this)});
this.current = this.items.length;
this.next();
}
},
next : function() {
this.current++;
if (this.current >= this.items.length) this.current = 0;
this.fx.stop();
this.fx.start({
top: this.items[this.current].offsetTop,
left: -this.items[this.current].offsetLeft
});
this.delayedFunction = this.next.bind(this).delay(this._timer );
},
goto : function(to) {
$clear(this.delayedFunction);
this.current = to;
this.fx.start({
top: this.items[to].offsetTop,
left: -this.items[to].offsetLeft
});
this.delayedFunction = this.next.bind(this).delay(this._timer);
}
});var TextSplitter = new Class({
initialize: function(component, splitterElements, titleElement) {
if (component.getElement) {
this.el = component.getElement('div');
var elements = new Array();
if(!(splitterElements instanceof Array)){
splitterElements = new Array(splitterElements);
}
for(var i = 0; i < splitterElements.length; i++){
elements = this.el.getElement(splitterElements[i]);
if(elements.length)break;
}
// retrieve the blocks
if (elements) {
var children = this.el.childNodes;
this.blocks = new Array();
this.titles = new Array();
this.blocks.push(new Element('div', {"class": "Synergee-Web-Page-TextSplitter-Content"}));
for (var i = 0; i < children.length; i++) {
if ($type(children[i]) == 'element' && splitterElements.contains(children[i].tagName.toLowerCase())) {
this.blocks.push(new Element('div', {"class": "Synergee-Web-Page-TextSplitter-Content"}));
} else if (this.blocks.length) {
if ($type(children[i]) == 'element') {
this.blocks[this.blocks.length - 1].appendChild(children[i]);
} else {
this.blocks[this.blocks.length - 1].appendChild(children[i]);
}
i--;
}
}
this.el.empty();
if (titleElement) {
for (var i = 0; i < this.blocks.length; i++) {
if (this.blocks[i].getElement(titleElement)) {
this.titles[i] = this.blocks[i].getElement(titleElement);
this.titles[i].addClass('Synergee-Web-Page-TextSplitter-Title');
} else {
this.titles[i] = new Element(titleElement, {'class': 'Synergee-Web-Page-TextSplitter-Title'});
this.titles[i].setHTML('"' + titleElement + '" title missing');
}
}
if (this.titles.length) {
this.titles[this.titles.length - 1].addClass('Synergee-Web-Page-TextSplitter-Title-Last');
}
this.titlesContainer = new Element('div', {"class": "Synergee-Web-Page-TextSplitter-Title-Container"});
this.el.appendChild(this.titlesContainer);
}
this.contentsContainer = new Element('div', {"class": "Synergee-Web-Page-TextSplitter-Content-Container"});
this.el.appendChild(this.contentsContainer);
for (var i = 0; i < this.titles.length; i ++) {
this.titlesContainer.appendChild(this.titles[i]);
}
for (var i = 0; i < this.blocks.length; i ++) {
this.contentsContainer.appendChild(this.blocks[i]);
}
}
}
},
getContentContainer : function() {
return this.contentsContainer;
},
getTitleContainer :  function() {
if(this.titlesContainer)return this.titlesContainer;
return null;
},
getTitles : function() {
return this.titles;
},
getContents : function(){
return this.blocks;
}
});var SynergeeTips = Tips.extend({
options: {
onShow: function(tip){
tip.setStyle('visibility', 'visible');
},
onHide: function(tip){
tip.setStyle('visibility', 'hidden');
},
maxTitleChars: 30,
showDelay: 100,
hideDelay: 100,
className: 'tool',
offsets: {'x': 16, 'y': 16},
fixed: false,
maxHeight : 0,
closeButton : false,
eventType : 'click'
},
build: function(el){
el.$tmp.myTitle = (el.href && el.getTag() == 'a') ? el.href.replace('http://', '') : (el.rel || false);
if (el.title){
var dual = el.title.split('::');
if (dual.length > 1) {
el.$tmp.myTitle = dual[0].trim();
el.$tmp.myText = dual[1].trim();
} else {
el.$tmp.myText = el.title;
}
el.removeAttribute('title');
} else {
el.$tmp.myText = false;
}
if (el.$tmp.myTitle && el.$tmp.myTitle.length > this.options.maxTitleChars) el.$tmp.myTitle = el.$tmp.myTitle.substr(0, this.options.maxTitleChars - 1) + "&hellip;";
el.addEvent(this.options.eventType, function(event){
this.start(el);
if (this.options.maxHeight) {
if(this.text && this.options.maxHeight < this.text.getParent().getCoordinates().height){
this.text.getParent().setStyle('max-height', this.options.maxHeight);
this.text.getParent().setStyle('overflowY', 'scroll');
}
}
if (!this.options.fixed) this.locate(event);
else this.position(el);
}.bind(this));
if (!this.options.fixed) el.addEvent('mousemove', this.locate.bindWithEvent(this));
var end = this.end.bind(this);
el.addEvent('mouseleave', end);
el.addEvent('trash', end);
this.toolTip.addEvent('mouseleave', end);
this.toolTip.addEvent('mouseenter', function(event){
$clear(this.timer);
}.bind(this));
},
start: function(el){
this.wrapper.empty();
if (el.$tmp.myTitle){
this.title = new Element('span').inject(
new Element('div', {'class': this.options.className + '-title'}).inject(this.wrapper)
).setHTML(el.$tmp.myTitle);
if(this.options.closeButton){
this.closeButton = new Element('div',{'class':this.options.className + '-Close'});
var end = this.hide.bind(this);
this.closeButton.injectInside(this.title.getParent());
this.closeButton.addEvent('click',end);
}
}
if (el.$tmp.myText){
this.text = new Element('span').inject(
new Element('div', {'class': this.options.className + '-text'}).inject(this.wrapper)
).setHTML(el.$tmp.myText);
}
$clear(this.timer);
this.timer = this.show.delay(this.options.showDelay, this);
}
});
/**
* The synergee form javascript code.
* This file contains all the necessary code used by the form widget.
*
* Copyright (c) 2007 Pyrameed all right reserved (http://www.pyrameed.com)
*/
/**
* The field validator.
* This class is used to validate a form field
*/
var SynergeeFieldValidator = new Class({
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return true;
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
throw Error('The method "getValidatorName" has to be defined for the field validator classes.');
}
});
/**
* The not empty field validator
*/
var SynergeeFieldValidatorNotEmpty = SynergeeFieldValidator.extend({
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return (field.tagName.toLowerCase() == 'div' || field.getValue() != '');
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorNotEmpty';
}
});
/**
* The email field validator
*/
var SynergeeFieldValidatorEmail = SynergeeFieldValidator.extend({
_emailRegex : new RegExp("^([_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3}))?$"),
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return this._emailRegex.test(field.getValue());
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorEmail';
}
});
/**
* The list field validator
*/
var SynergeeFieldValidatorList = SynergeeFieldValidator.extend({
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
var inputElements = field.getElementsByTagName('input');
for (var i = 0; i < inputElements.length; i++) {
if (inputElements[i].checked) {
return true;
}
}
return false;
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorList';
}
});
/**
* The alpha field validator
*/
var SynergeeFieldValidatorAlpha = SynergeeFieldValidator.extend({
_alphaRegex : new RegExp("^([a-zA-Z])*?$"),
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return this._alphaRegex.test(field.getValue());
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorAlpha';
}
});
/**
* The numeric field validator
*/
var SynergeeFieldValidatorNum = SynergeeFieldValidator.extend({
_numRegex : new RegExp("^([0-9])*?$"),
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return this._numRegex.test(field.getValue());
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorNum';
}
});
/**
* The alphanumeric field validator
*/
var SynergeeFieldValidatorAlnum = SynergeeFieldValidator.extend({
_alnumRegex : new RegExp("^([a-zA-Z0-9])*?$"),
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return this._alnumRegex.test(field.getValue());
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorAlnum';
}
});
/**
* The date field validator
*/
var SynergeeFieldValidatorDate = SynergeeFieldValidator.extend({
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return (field.tagName.toLowerCase() == 'div' || field.getValue() != '');
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorDate';
}
});
/**
* The Birthdate field validator
*/
var SynergeeFieldValidatorBirthdate = SynergeeFieldValidator.extend({
initialize : function(minDate, maxDate, format) {
if(minDate){
this._minDate = (new Date()).fromIso(minDate);
}   else{
this._minDate = null;
}
if(maxDate){
this._maxDate = (new Date()).fromIso(maxDate);
}   else{
this._maxDate = null;
}
if(format) this._format = format;
},
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
// always return true, the backend check the right dates
////
//        var fieldValue = field.getValue();
//        if(fieldValue != '' && (new Date()).fromIso(fieldValue)){
//            fieldValue = (new Date()).fromIso(fieldValue);
//            if(this._maxDate && this._maxDate.getTime() < fieldValue){
//                return false;
//
//            }
//            if(this._minDate && this._minDate.getTime() > fieldValue){
//                return false;
//            }
//        }
return true;
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorBirthdate';
}
});
/**
* The Birthdate field validator
*/
var SynergeeFieldValidatorLevel = SynergeeFieldValidator.extend({
initialize : function(minimumLevel, maximumLevel) {
if(minimumLevel){
this._minimumLevel = minimumLevel;
}   else{
this._minimumLevel = 1;
}
if(maximumLevel){
this._maximumLevel = maximumLevel;
}   else{
this._maximumLevel = 7;
}
},
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
var selIndex = field.selectedIndex;
var comboValue = field.options[selIndex].value;
if(comboValue){
if(comboValue >= this._minimumLevel && comboValue <= this._maximumLevel){
return true;
}
return false;
}
return true;
},
/**
* Return the validator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorLevel';
}
});
/**
* The form validator.
* This class is used to validate the fields of a specific form
*/
var SynergeeFormValidator = new Class({
_formElement : null,
_onComplete : null,
_fields : [],
_submitButton : null,
/**
* The constructor
*
* @param Element formElement The form element
* @param function onComplete The function called once the form has been submitted (this function is called by the ajax component)
*/
initialize: function(formElement, onComplete) {
this._fields = [];
this._formElement = formElement;
this._scroller = new Fx.Scroll(window, {offset: {'x': 0, 'y': -50}});
if (typeof(onComplete) == 'function') {
this._onComplete = onComplete;
} else {
this._onComplete = eval(onComplete);
}
this._formElement.addEvent('submit', function(e) {
new Event(e).stop();
});
// The error message functions are added to the form
this._formElement._errorMessage = new Fx.Slide(this._formElement.getElementsByTagName('div')[0]);
this._formElement.getElementsByTagName('div')[0].setStyle('clear', 'both');
this._formElement._errorMessage.hide();
this._formElement.displayErrorMessage = function() {
if (this._errorMessage) {
this._errorMessage.stop();
this._errorMessage.slideIn();
}
};
this._formElement.hideErrorMessage = function() {
if (this._errorMessage) {
this._errorMessage.stop();
this._errorMessage.slideOut();
}
};
},
/**
* This method is called when the response of the form has been received.
* The goal of this method is to analyse the response and if some fields were
* invalid the error message is displayed again.
* If no invalidate fields are returned, the user defined function (set on the onComplete
* attribute of the form tag) is called with the response as parameter.
*
* @param string response The response returned by the server
*/
onComplete : function(response) {
// The submit button is ungrayed
if (this._submitButton) {
this._submitButton.removeProperty('disabled');
}
// We check if the invalidateFields is empty or not
try {
var response = Json.evaluate(response);
if (response.invalidFields && response.invalidFields.length) {
try {
if ($(response.invalidFields[0])) {
$(response.invalidFields[0]).focus();
} else {
$('id_' + response.invalidFields[0]).focus();
}
}catch(ex){
// if the element is not focusable (it's hidden or something)
}
response.invalidFields.each(function(fieldName) {
if ($(fieldName)) {
$(fieldName).displayErrorMessage();
} else {
$('id_' + fieldName).displayErrorMessage();
}
});
try {
if(response.invalidFields[0]){
if ($(response.invalidFields[0])) {
if($(response.invalidFields[0]).getStyle('display') == 'none'){
var element = $(response.invalidFields[0]).getParent();
}else {
var element = $(response.invalidFields[0]);
}
this._scroller.toElement(element);
} else {
if($('id_' + response.invalidFields[0]).getStyle('display') == 'none'){
var element = $('id_' + response.invalidFields[0]).getParent();
}else {
var element = $('id_' + response.invalidFields[0]);
}
this._scroller.toElement(element);
}
}
}catch (ex){}
this._formElement.fireEvent('invalidfield');
} else if (response.isValid) {
// The user defined on complete method is called with the response as parameter
this._onComplete(response.response);
} else {
// The request wasn't valid, then a global message has to be send
this._formElement.displayErrorMessage();
}
} catch(ex) {
// The response is not a valid JSON encoded one
this._formElement.displayErrorMessage();
this._formElement.fireEvent('invalidfield');
}
},
/**
* Validate the fields of the form
*
* @param boolean ajaxCall True if an ajax call has to be done
*/
validate : function(ajaxCall) {
// The submit button is grayed
if (this._submitButton) {
this._submitButton.setProperty('disabled', true);
}
// The error message of the form is hidden
this._formElement.hideErrorMessage();
var valid = true;
var invalidFields = new Array();
for (var i = 0; i < this._fields.length; i++) {
for (var j = 0; j < this._fields[i].getValidators().length; j++) {
if (!this._fields[i].getValidators()[j].isValid(this._fields[i])) {
invalidFields.push(this._fields[i]);
}
}
}
// The valid fields error message are hidden
for (var i = 0; i < this._fields.length; i++) {
if (!invalidFields.contains(this._fields[i])) {
this._fields[i].hideErrorMessage();
}
}
// The invalidate fields error message are displayed
if (invalidFields.length) {
invalidFields[0].focus();
// The page is scrolled to the first error message
this._scroller.toElement(invalidFields[0]);
for (var i = 0; i < invalidFields.length; i++) {
invalidFields[i].displayErrorMessage();
}
// The submit button is ungrayed
if (this._submitButton) {
this._submitButton.removeProperty('disabled');
}
return false;
} else {
if (ajaxCall) {
// The right page location is set to the action attribute of the form
this._formElement.setProperty('action', window.getCurrentPageUrl());
// The componentName and componentId fields are populated
if (!this._formElement.getChildren().contains($('id_componentName'))) {
if ($('id_componentName')) {
$('id_componentName').remove();
}
(new Element('input', {name:'componentName',id:'id_componentName',type:'hidden'})).injectBefore(this._formElement.getChildren()[0]);
}
$('id_componentName').setProperty('value', this._formElement.getComponentName());
if (!this._formElement.getChildren().contains($('id_componentId'))) {
if ($('id_componentId')) {
$('id_componentId').remove();
}
(new Element('input', {name:'componentId',id:'id_componentId',type:'hidden'})).injectBefore(this._formElement.getChildren()[1]);
}
$('id_componentId').setProperty('value', this._formElement.getComponentId());
// The validationInformation field is populated with all the validation information
if (!this._formElement.getChildren().contains($('id_validationInformation'))) {
if ($('id_validationInformation')) {
$('id_validationInformation').remove();
}
(new Element('input', {name:'validationInformation',id:'id_validationInformation',type:'hidden'})).injectBefore(this._formElement.getChildren()[2]);
}
$('id_validationInformation').setProperty('value', this.getValidationInformation());
// All the fields are ok, then the form is sent
this._formElement.fireEvent('ajaxcall');
this._formElement.send({onComplete:this.onComplete.bind(this)});
return false;
} else {
return true;
}
}
},
createTips : function(field) {
},
/**
* Add a field to the validator
*
* @param Element field The field to validate
* @optionalParam string[] validators The list of validators to apply to the field
*/
addField : function(field, validators) {
var validatorObjects = [];
if (validators && validators.length) {
for (var i = 0; i < validators.length; i++) {
validatorObjects.push(validators[i]);
}
if (field.getStyle('position') == "absolute") {
if (field.parentNode.getElementsByTagName('div').length) {
field._errorImage = field.getParent().getElementsByTagName('div')[0];
field._errorMessage = new Tips(field._errorImage);
}
} else {
if (field.parentNode.getElementsByTagName('div').length) {
if (field.parentNode.getElementsByTagName('div').length) {
// The error fx object is created
field._errorMessage = new Fx.Slide(field.parentNode.getElementsByTagName('div')[0]);
field._errorMessage.hide();
}
}
}
}
field._validators = validatorObjects;
field.getValidators = function() {
return this._validators;
};
field.displayErrorMessage = function() {
if (this._errorMessage) {
if (this.getStyle('position') == "absolute") {
this._errorImage.setStyle('display', 'block');
} else {
this._errorMessage.stop();
this.setStyle('margin-top', '2px');
this._errorMessage.slideIn();
}
}
};
field.hideErrorMessage = function() {
if (this._errorMessage) {
if (this.getStyle('position') == "absolute") {
this._errorImage.setStyle('display', 'none');
} else {
this._errorMessage.stop();
this.setStyle('margin-top', '0px');
this._errorMessage.slideOut();
}
}
};
this._fields.push(field);
// A check to determine if this is the submit button
if (field && field.getProperty('type') && field.getProperty('type').toLowerCase() == 'submit') {
this._submitButton = field;
}
},
/**
* Return the validation information encoded in JSON.
* This is a hash table that have the field name as key and a coma separated validator name as values.
*
* @return string
*/
getValidationInformation : function() {
var validationInformation = {};
this._fields.each(function(field) {
var validators = new Array();
field.getValidators().each(function(validator) {
validators.push(validator.getValidatorName());
});
validationInformation[field.getProperty('name')] = validators.join(',');
});
return Json.toString(validationInformation);
}
});
/**
* The synergee general javascript code.
* This file contains all the necessary code used by the form widget.
*
* Copyright (c) 2007 Pyrameed all right reserved (http://www.pyrameed.com)
*/
/**
* Add two usefull method to the Element objects in order to determine
* its synergee web page parent component name and id.
* Those informations are usefull when dealing with AJAX requests.
*/
Element.extend({
/**
* Return the first synergee web page component name
*
* @return string The first synergee web page component name
*/
getComponentName : function() {
var currentElement = this;
while(!(currentElement.className && currentElement.className.test('Synergee-Web-Page-Component-(.*)-Container', 'i'))) {
currentElement = currentElement.getParent();
}
var regex = new RegExp('Synergee-Web-Page-Component-(.*)-Container', 'i');
var values = regex.exec(currentElement.className);
if (values && values.length == 2) {
return values[1];
} else {
return null;
}
},
/**
* Return the first synergee web page component id
*
* @return string The first synergee web page component id
*/
getComponentId : function() {
var currentElement = this;
while(!(currentElement.className && currentElement.className.test('Synergee-Web-Page-Component-(.*)-Container', 'i'))) {
currentElement = currentElement.getParent();
}
var regex = new RegExp('Synergee-Web-Page-Component-(.*)-Container', 'i');
var values = regex.exec(currentElement.className);
if (values && values.length == 2) {
return currentElement.getParent().id;
} else {
return null;
}
}
});
/**
* The getUrl method is added to the window object in order to be able to get the current page url easily
*/
window.extend({
/**
* Bookmark the current web page
*
* @param string title The page title
* @param string url The web page url
*/
bookmark : function(title, url) {
if (document.all) {
window.external.AddFavorite(url, title);
} else if (window.sidebar) {
window.sidebar.addPanel(title, url, "");
}
},
/**
* Return the current web page url
*
* @return string The current web page url
*/
getCurrentPageUrl : function() {
if (window.location.href.indexOf('?') != -1) {
return window.location.href.substr(0, window.location.href.indexOf('?'));
}
return window.location.href;
},
/**
* Return the current JSON url.
* This url is used by all the JSON invokations
*
* @param Element element The component element
* @return string The current JSON url
*/
getCurrentJsonUrl : function(element) {
var htmlElement = $E('html');
var windowUrl = window.getCurrentPageUrl();
//        if(windowUrl.indexOf('#')){
//            windowUrl = windowUrl.slice(0, windowUrl.indexOf('#'));
//        }
if (htmlElement.getAttribute('designmode') == 'on') {
var webPageId = /webPageId=([0-9]*)/.exec(window.location.href);
return windowUrl + '?webPageId=' + webPageId[1] + '&componentName=' + element.getComponentName() + '&componentId=' + element.getComponentId();
} else {
return windowUrl + '?componentName=' + element.getComponentName() + '&componentId=' + element.getComponentId();
}
},
/**
* Return the currrent page location (the url without the page name)
*
* @return string The current page location
*/
getCurrentPageLocation : function() {
return window.getCurrentPageUrl().substr(0, window.getCurrentPageUrl().lastIndexOf('/')) + '/';
}
});
/**
* Docucment is extended to add the isInDesignMode method.
*/
document.extend({
/**
* This method return true when the page is displayed in the designer
* @return boolean True if the page is displayed in the designer
*/
isInDesignMode : function() {
var htmlElement = $E('html');
return (htmlElement.getAttribute('designmode') == 'on');
}
});
/**
* Decode the html entities
*
* @param String sa
* @return String
*/
function decodeHtmlEntities(sa) {
var ta=document.createElement("textarea");
ta.innerHTML=sa.replace(/</g,"&lt;").replace(/>/g,"&gt;");
return ta.value;
};
/**
* Pad a number regarding the number passed to the pad. By default 2
* @param number valueToPad The value to pad
* @param number pad The pad value
* @return string the padded number
*/
Number.padTo = function(valueToPad, pad) {
pad = pad ? pad : 2;
pad = Math.pow(10, pad-1);
return (valueToPad < pad) ? ("0" + valueToPad) : valueToPad;
};
/**
* Populate the date from an iso formatted string that represent a date
*
* @param string The iso formatted date
*/
Date.prototype.fromIso = function(isoFormattedDate) {
var dateTimeRegex = new RegExp('^([0-9]{4})-([0-9]{2})-([0-9]{2})[T ]([0-9]{2}):([0-9]{2}):([0-9]{2})(([+-])([0-9]{2})(:([0-9]{2}))?)?$');
var dateRegex = new RegExp('^([0-9]{4})-([0-9]{2})-([0-9]{2})$');
var timeRegex = new RegExp('^([0-9]{2}):([0-9]{2}):([0-9]{2})$');
if (dateTimeRegex.test(isoFormattedDate)) {
var values = dateTimeRegex.exec(isoFormattedDate);
var tmpDate = new Date(values[1], values[2] - 1, values[3], values[4], values[5], values[6]);
this.setTime(tmpDate.getTime());
//this.setTime(Date.parse(values[1] + ' ' + values[2] + ' ' + values[3] + ' ' + values[4] + ':' + values[5] + ':' + values[6]));
// The time zone is calculated
if(values[9]){
var timeZoneOffset = -1 * (values[9]*60 + (values[11]?values[11]*1:0)) * (values[8]=='-'?-1:1);
var currentTimeZoneOffset = this.getTimezoneOffset();
this.setTime(this.getTime() + (timeZoneOffset - currentTimeZoneOffset) * 60000);
}
} else if (dateRegex.test(isoFormattedDate)) {
var values = dateRegex.exec(isoFormattedDate);
var tmpDate = new Date(values[1], values[2] - 1, values[3]);
this.setTime(tmpDate.getTime());
//this.setTime(Date.parse(values[1] + ' ' + values[2] + ' ' + values[3]));
} else if (timeRegex.test(isoFormattedDate)) {
var values = timeRegex.exec(isoFormattedDate);
this.setHours(values[1]);
this.setMinutes(values[2]);
this.setSeconds(values[3]);
}
return this;
};
/**
* Return the iso formatted representation of the date
*
* @return string The iso formatted date
*/
Date.prototype.toIso = function() {
var formattedDate = this.getFullYear() + '-' + Number.padTo(this.getMonth()+1) + '-' + Number.padTo(this.getDate());
formattedDate = formattedDate + 'T' + Number.padTo(this.getHours()) + ':' + Number.padTo(this.getMinutes()) + ':' + Number.padTo(this.getSeconds());
return formattedDate;
};
/**
* Return formatted date
*
* @param string format The date output format
* @optionalparam string[] months The translated months
* @return string The formatted date
*/
Date.prototype.format = function(format, months) {
// The date is formatted
format = format.replace('dddd','dd');
format = format.replace('ddd', 'dd');
format = format.replace('dd', Number.padTo(this.getDate()));
format = format.replace('d', this.getDate());
format = format.replace('yyyy', this.getFullYear());
format = format.replace('yy', (new String(this.getFullYear())).substr(2,2));
// The time is formatted
format = format.replace('HH', Number.padTo(this.getHours()));
format = format.replace('H', this.getHours());
format = format.replace('mm', Number.padTo(this.getMinutes()));
format = format.replace('m', this.getMinutes());
format = format.replace('ss', Number.padTo(this.getSeconds()));
format = format.replace('s', this.getSeconds());
if(format.indexOf('MMMM') != -1 && months && months.length && months[this.getMonth()]){
format = format.replace('MMMM', months[this.getMonth()]);
}else{
format = format.replace('MMMM','MM');
format = format.replace('MMM', 'MM');
format = format.replace('MM', Number.padTo(this.getMonth()+1));
format = format.replace('M', this.getMonth()+1);
}
format = format.replace(/['"]/g,'');
return format;
};
/**
* Returns the week number for this date.
* @return int
*/
Date.prototype.getWeek = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((((this - onejan) / 86400000) + onejan.getDay())/7);
};
var Ticker = new Class({
setOptions: function(options) {
this.options = Object.extend({
speed: 1000,
delay: 5000,
onComplete: Class.empty,
onStart: Class.empty
}, options || {});
},
initialize: function(el,options){
this.setOptions(options);
this.el = $(el).getElement('div');
if (this.el.getElement('hr')) {
var children = this.el.childNodes;
var news = new Array();
news.push(new Element('div'));
for (var i = 0; i < children.length; i++) {
if ($type(children[i]) == 'element' && children[i].tagName.toLowerCase() == 'hr') {
news.push(new Element('div'));
} else if (news.length) {
if ($type(children[i]) == 'element') {
news[news.length - 1].appendChild(children[i]);
} else {
news[news.length - 1].appendChild(children[i]);
}
i--;
}
}
this.el.empty();
for(var i = 0; i < news.length; i ++){
this.el.appendChild(news[i]);
}
this.items = this.el.getElements('div');
if (this.items.length) {
var w = 0;
this.items.each(function(item, index) {
w += item.getSize().size.x;
item.addEvent('mouseenter', function(){
$clear(this.delayedFunction);
}.bind(this));
item.addEvent('mouseleave', function(){
this.next();
}.bind(this));
}.bind(this));
this.el.setStyles({
position: 'absolute',
top: 0,
left: 0,
width: w
});
this.periodical =
this.fx = new Fx.Styles(this.el, {duration:this.options.speed,onComplete:function() {
var i = (this.current == 0) ? this.items.length : this.current;
this.items[i - 1].injectInside(this.el);
this.el.setStyle('left', 0);
}.bind(this)});
this.current = this.items.length;
this.next();
}
}
},
next: function() {
this.current++;
if (this.current >= this.items.length) this.current = 0;
this.fx.start({
top: this.items[this.current].offsetTop,
left: -this.items[this.current].offsetLeft
});
this.delayedFunction = this.next.bind(this).delay(this.options.delay);
}
});/**
*  Create a waiting panel object
*
*/
var WaitingPanel = Events.extend({
initialize: function(el) {
if($(el).waitingPanel){
return $(el).waitingPanel;
}
this.el = $(el);
this.el.waitingPanel = this;
},
buildObjects : function() {
// the waiting panel layer and fx style are created
this._waitingPanelLayer = new Element('div', {'class': 'WaitingPanel-AjaxLoading','id':'waitingPanel'});
this._waitingFxStyle = new Fx.Style(this._waitingPanelLayer, 'opacity', {duration:100});
this._waitingPanelLayer.injectAfter(document.getElementsByTagName('div')[0]);
this._waitingPanelLayer.setStyle('position', 'absolute');
this._waitingPanelLayer.setStyles({
opacity : 0
});
this._waitingImageLayer = new Element('div', {'class': 'WaitingPanel-AjaxLoadingImage','id':'waitingPanel'});
this._waitingImageFxStyle = new Fx.Style(this._waitingImageLayer, 'opacity', {duration:100});
this._waitingImageLayer.injectAfter(this._waitingPanelLayer);
this._waitingImageLayer.setStyle('position', 'absolute');
this._waitingImageLayer.setStyles({
opacity : 0
});
},
/**
*  Display a waiting panel layer over the element
*/
display : function() {
if (!this._waitingPanelLayer) {
this.buildObjects();
}
// refresh the height of the waiting panel layer
var coordinates = this.el.getCoordinates();
this._waitingPanelLayer.elementTo = this.el;
this._waitingPanelLayer.setStyles({
height : (coordinates.height + 2),
width : (coordinates.width + 2),
left : (coordinates.left - 2),
top : (coordinates.top - 2)
});
this._waitingImageLayer.setStyles({
height : (coordinates.height + 2),
width : (coordinates.width + 2),
left : (coordinates.left - 2),
top : (coordinates.top - 2)
});
this._waitingFxStyle.start(0, 0.5);
this._waitingImageFxStyle.start(0, 1);
},
/**
* Hide the waiting panel
*/
hide : function() {
if (this._waitingPanelLayer.getStyle('opacity') != 0) {
this._waitingFxStyle.start(0.5, 0);
this._waitingImageFxStyle.start(1, 0);
}
}
});/**
*  Create a message panel object
*
*/
var WindowMessagePanel = Events.extend({
initialize: function(el) {
if ($(el).messagePanel) {
return $(el).messagePanel;
}
this.el = $(el);
this.el.messagePanel = this;
},
/**
* Display a given message
* @param string message The message
* @param integer autoClose The autoclose timer in milliseconds
*/
displayMessage : function(message, title ,autoClose) {
$clear(this.autoClose);
if (!this._messageContainer) {
this._container = new Element('div');
this._messageContainer = new Element('div', {'class': 'Synergee-Web-Page-Component-MessagePanel'});
this._messageTitle = new Element('div', {'class': 'Synergee-Web-Page-Component-MessagePanel-Title'});
this._messageContainerClose = new Element('div', {'class': 'Synergee-Web-Page-Component-MessagePanel-Close'});
this._messageContainerClose.addEvent('click', this.hideMessage.bind(this));
this._messageContainerClose.setHTML('x');
this._messageTitle.setHTML(title);
this._messageContainerFx = new Fx.Style(this._container, 'opacity', {duration:300});
this._container.injectInside(this.el);
this._messageTitle.injectInside(this._container);
this._messageContainer.injectInside(this._container);
this._messageContainerClose.injectInside(this._container);
this._container.setStyle('position', 'absolute');
this._container.setOpacity(0);
}
this._messageContainer.setHTML(message);
// the waiting panel layer and fx style are created
var containerCoord = this.el.getCoordinates();
this._messageContainerFx.stop();
this._container.setStyles({
'top': (this.el.getCoordinates().height - this._container.getCoordinates().height ) / 2,
'left': (containerCoord.width - 300) / 2,
'width':300,
'min-height':20,
'z-index':10000
});
this._messageContainerFx.start(0, 1);
if (autoClose) {
this.autoClose =  this.hideMessage.delay(autoClose, this);
}
},
getContent : function(){
return this._messageContainer;
},
hideMessage : function() {
$clear(this.autoClose);
this._messageContainerFx.stop();
this._messageContainerFx.start(1, 0);
}
});
var QuickSearch = Events.extend({
initialize : function(resultContainer, containerType) {
if (containerType) {
this._resultContainer =  $(resultContainer);
}
else {
if($$('.'+resultContainer) && $$('.'+resultContainer).length){
this._resultContainer = $$('.'+resultContainer)[0];
}
}
if (this._resultContainer) {
var defaultValue = $('idQuickSearchTextField').getProperty('value');
function onQuickSearchTextFieldClick() {
if($('idQuickSearchTextField').getProperty('value') == defaultValue)
$('idQuickSearchTextField').setProperty('value', '');
};
function onQuickSearchTextFieldClickOut() {
if($('idQuickSearchTextField').getProperty('value') == '')
$('idQuickSearchTextField').setProperty('value', defaultValue);
};
$('idQuickSearchTextField').addEvent('focus', onQuickSearchTextFieldClick);
$('idQuickSearchTextField').addEvent('blur', onQuickSearchTextFieldClickOut);
$('idQuickSearchTextField').addClass('QuickSearchText');
this._waitingPanel = new WaitingPanel(this._resultContainer);
$('id_QuickSearchForm').addEvent('submit', function(){
this._waitingPanel.display();
}.bind(this));
}
},
highlight : function (oElements, sSearch) {
if (sSearch) {
var searchParts = sSearch.split(' ');
if (oElements && oElements.length) {
for (var i = 0; i < oElements.length; i++) {
for (var j = 0; j < searchParts.length; j++) {
oElements[i].setHTML(oElements[i].innerHTML.replace(new RegExp('(' + searchParts[j] + ')', 'ig'), '<span class="highlighted">$1</span>'));
}
}
}
}
},
handleResponse : function (response) {
if(this._resultContainer){
var recherche = $("idQuickSearchTextField").value;
this._resultContainer.setHTML(response);
this.highlight(this._resultContainer.getElements(".Synergee-Web-Page-Component-QuickSearch-Results-Page-Title a"), recherche);
this.highlight(this._resultContainer.getElements(".Synergee-Web-Page-Component-QuickSearch-Results-Page-Description"), recherche);
this.highlight(this._resultContainer.getElements(".Synergee-Web-Page-Component-QuickSearch-Results-Page-Url a"), recherche);
this._waitingPanel.hide();
var nbResults = $$('.Synergee-Web-Page-Component-QuickSearch-Item').length;
if (nbResults > 10 && nbResults <= 100) {
var resultsHelper = new ResultHelper(10, nbResults);
resultsHelper.injectNavBar('Synergee-Web-Page-Component-QuickSearch-NavigationBars', 'button', 'QuickSearchNav', '');
$$('.QuickSearchNavNext').addEvent('click', function (e) {
resultsHelper.nextPage();
if (e.target) e.target.blur();
else e.srcElement.blur();
});
$$('.QuickSearchNavPrevious').addEvent('click', function (e) {
resultsHelper.previousPage();
if (e.target) e.target.blur();
else e.srcElement.blur();
});
resultsHelper.addEvent('onPageChangeBefore', function () {
$$('.Synergee-Web-Page-Component-QuickSearch-Page' + resultsHelper.getCurrentPage()).setStyle('display','none');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).removeClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Selected');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).addClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Default');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).removeClass('QuickSearchNavButtonSelectedColor');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).addClass('QuickSearchNavButtonDefaultColor');
$$('.QuickSearchNavNext').removeClass('QuickSearchNavButtonSelectedColor');
});
resultsHelper.addEvent('onPageChangeAfter', function () {
$$('.Synergee-Web-Page-Component-QuickSearch-Page' + resultsHelper.getCurrentPage()).setStyle('display','block');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).removeClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Default');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).addClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Selected');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).removeClass('QuickSearchNavButtonDefaultColor');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).addClass('QuickSearchNavButtonSelectedColor');
$$('.QuickSearchNavPrevious').removeClass('QuickSearchNavButtonSelectedColor');
});
resultsHelper.addEvent('onPageChangeLowerLimit', function () {
$$('.QuickSearchNavPrevious').addClass('QuickSearchNavButtonSelectedColor');
});
resultsHelper.addEvent('onPageChangeUpperLimit', function () {
$$('.QuickSearchNavNext').addClass('QuickSearchNavButtonSelectedColor');
});
for (var i=0; i < resultsHelper.getCountPages(); i++) {
$$('.QuickSearchNav'+i).each(function (e) { e.pageNumber = i; });
$$('.QuickSearchNav'+i).addClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Default');
$$('.QuickSearchNav'+i).addClass('QuickSearchNavButtonDefaultColor');
$$('.QuickSearchNav'+i).addEvent('click', function (e) {
if (e.target) {
resultsHelper.selectPage(e.target.pageNumber);
e.target.blur();
}
else {
resultsHelper.selectPage(e.srcElement.pageNumber);
e.srcElement.blur();
}
});
}
$$('.QuickSearchNav0').removeClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Default');
$$('.QuickSearchNav0').removeClass('QuickSearchNavButtonDefaultColor');
$$('.QuickSearchNav0').addClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Selected');
$$('.QuickSearchNav0').addClass('QuickSearchNavButtonSelectedColor');
// comment/uncomment the following 2 lines to put/remove a results nav bar on top (also comment/uncomment relevant part in QuickSearch.xsl)
//            $('idQuickSearchNavPreviousTop').setStyle('display','inline');
//            $('idQuickSearchNavNextTop').setStyle('display','inline');
// comment/uncomment the following 2 lines to put/remove a results nav bar on bottom (also comment/uncomment relevant part in QuickSearch.xsl)
//            $('idQuickSearchNavPreviousBottom').setStyle('display','inline');
//            $('idQuickSearchNavNextBottom').setStyle('display','inline');
$$('.QuickSearchNavPrevious').addClass('QuickSearchNavButtonSelectedColor');
}
}
}
});
var WebsiteSelector = Options.extend({
initialize: function(componentId) {
this._componentId = componentId;
this._websiteList = $(this._componentId + '_siteSelectorLanguageListId');
this._textLink = $(this._componentId + '_siteSelectorLanguageText');
this._websiteList.setStyle('margin-top', '-540000px');
window.addEvent('load', function(){
this._height = this._websiteList.getCoordinates().height;
$(this._componentId + '_siteSelectorCurrentSelectionId').addEvent('mouseover', this.displaySiteSelector.bind(this));
$(this._componentId + '_siteSelectorCurrentSelectionId').getParent().addEvent('mouseleave', this.hideSiteSelector.bind(this));
this._websiteList.setStyle('margin-top', '');
if(this.listFx)this.listFx.set(0);
this._websiteList.addClass('HideClass');
}.bind(this));
try {
this._websiteList.addClass('SiteSelectorLanguageListFx');
} catch(ex) {
}
if (!document.isInDesignMode()) {
this._fxTime = 300;
this.listFx = new Fx.Style($(this._componentId + '_siteSelectorLanguageListId'), 'height', {wait:false, duration:this._fxTime});
this._textFx = new Fx.Style($(this._componentId + '_siteSelectorLanguageText'), 'opacity', {wait:false, duration:this._fxTime / 2});
}
},
hideSiteSelector : function(e) {
var target = e.relatedTarget;
while (target && target.getAttribute && (target.getAttribute('id') != this._componentId + '_siteSelectorCurrentSelectionId' && target.getAttribute('id') != this._componentId + '_siteSelectorLanguageListId')) {
if (target.getParent && target.getParent()) {
target = target.getParent();
} else {
target = false;
}
}
if (target != this._websiteList) {
this.listFx.stop();
this.listFx.start(this._websiteList.getCoordinates().height, 0);
this._textFx.stop();
this._textFx.start(this._textLink.getStyle('opacity'), 1);
this._websiteList.addClass('HideClass');
}
},
displaySiteSelector : function(e) {
this._websiteList.removeClass('HideClass');
this._textFx.stop();
this.listFx.stop();
var height = this._websiteList.getCoordinates().height;
if(height < this._websiteList.getCoordinates().height)height =  this._websiteList.getCoordinates().height;
this.listFx.start(height, this._height);
this._textFx.start(this._textLink.getStyle('opacity'), 0);
}
});
