From fc289f2258bd6130b5d6cd7250670f0005d44e7c Mon Sep 17 00:00:00 2001 From: dsainty Date: Mon, 17 Jun 2024 22:44:21 +1000 Subject: [PATCH] Sixth pass at adding key files --- site/.vscode/settings.json | 3 + site/articles/include_form.js | 112 + site/coaches/javascript.js | 123 + site/coaches/rating/scripts/prototype.js | 3271 +++++++++++++++++ site/coaches/rating/scripts/rating.js | 54 + .../fitters/class/rating/scripts/prototype.js | 3271 +++++++++++++++++ site/fitters/class/rating/scripts/rating.js | 54 + site/fitters/gmaps_allfitter.js | 21 + site/fitters/javascript.js | 123 + site/fitters/rating/scripts/prototype.js | 3271 +++++++++++++++++ site/fitters/rating/scripts/rating.js | 54 + site/glist/.htaccess | 7 + site/googlemaps/gmaps_all.js | 21 + site/googlemaps/json/coach.json | 1 + site/googlemaps/json/fitter.json | 1 + site/googlemaps/json/json.zip | Bin 0 -> 373184 bytes site/googlemaps/json/race.json | 1 + site/googlemaps/json/retailer.json | 1 + site/googlemaps/json/roadshow.json | 1 + site/googlemaps/json/runshop.json | 1 + site/googlemaps/json/triclub.json | 1 + site/googlemaps/util.js | 84 + site/racecalendar/javascript.js | 123 + site/racecalendar/old.htaccess | 5 + site/racecalendar/rating/scripts/prototype.js | 3271 +++++++++++++++++ site/racecalendar/rating/scripts/rating.js | 54 + site/retailers/javascript.js | 123 + site/retailers/rating/scripts/prototype.js | 3271 +++++++++++++++++ site/retailers/rating/scripts/rating.js | 54 + .../class/rating/scripts/prototype.js | 3271 +++++++++++++++++ site/roadshow/class/rating/scripts/rating.js | 54 + site/roadshow/gmaps_allroadshow.js | 22 + site/roadshow/javascript.js | 123 + site/roadshow/rating/scripts/prototype.js | 3271 +++++++++++++++++ site/roadshow/rating/scripts/rating.js | 54 + site/runshops/javascript.js | 123 + site/runshops/rating/scripts/prototype.js | 3271 +++++++++++++++++ site/runshops/rating/scripts/rating.js | 54 + .../class/rating/scripts/prototype.js | 3271 +++++++++++++++++ site/triclubs/class/rating/scripts/rating.js | 54 + site/triclubs/javascript.js | 123 + slowtwitch.com/.htpasswd | 0 42 files changed, 31068 insertions(+) create mode 100644 site/.vscode/settings.json create mode 100644 site/articles/include_form.js create mode 100644 site/coaches/javascript.js create mode 100644 site/coaches/rating/scripts/prototype.js create mode 100644 site/coaches/rating/scripts/rating.js create mode 100644 site/fitters/class/rating/scripts/prototype.js create mode 100644 site/fitters/class/rating/scripts/rating.js create mode 100644 site/fitters/gmaps_allfitter.js create mode 100644 site/fitters/javascript.js create mode 100644 site/fitters/rating/scripts/prototype.js create mode 100644 site/fitters/rating/scripts/rating.js create mode 100644 site/glist/.htaccess create mode 100644 site/googlemaps/gmaps_all.js create mode 100644 site/googlemaps/json/coach.json create mode 100644 site/googlemaps/json/fitter.json create mode 100644 site/googlemaps/json/json.zip create mode 100644 site/googlemaps/json/race.json create mode 100644 site/googlemaps/json/retailer.json create mode 100644 site/googlemaps/json/roadshow.json create mode 100644 site/googlemaps/json/runshop.json create mode 100644 site/googlemaps/json/triclub.json create mode 100644 site/googlemaps/util.js create mode 100755 site/racecalendar/javascript.js create mode 100644 site/racecalendar/old.htaccess create mode 100644 site/racecalendar/rating/scripts/prototype.js create mode 100644 site/racecalendar/rating/scripts/rating.js create mode 100644 site/retailers/javascript.js create mode 100644 site/retailers/rating/scripts/prototype.js create mode 100644 site/retailers/rating/scripts/rating.js create mode 100644 site/roadshow/class/rating/scripts/prototype.js create mode 100644 site/roadshow/class/rating/scripts/rating.js create mode 100644 site/roadshow/gmaps_allroadshow.js create mode 100644 site/roadshow/javascript.js create mode 100644 site/roadshow/rating/scripts/prototype.js create mode 100644 site/roadshow/rating/scripts/rating.js create mode 100644 site/runshops/javascript.js create mode 100644 site/runshops/rating/scripts/prototype.js create mode 100644 site/runshops/rating/scripts/rating.js create mode 100644 site/triclubs/class/rating/scripts/prototype.js create mode 100644 site/triclubs/class/rating/scripts/rating.js create mode 100644 site/triclubs/javascript.js create mode 100644 slowtwitch.com/.htpasswd diff --git a/site/.vscode/settings.json b/site/.vscode/settings.json new file mode 100644 index 0000000..3b66410 --- /dev/null +++ b/site/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "git.ignoreLimitWarning": true +} \ No newline at end of file diff --git a/site/articles/include_form.js b/site/articles/include_form.js new file mode 100644 index 0000000..9aa47b9 --- /dev/null +++ b/site/articles/include_form.js @@ -0,0 +1,112 @@ + diff --git a/site/coaches/javascript.js b/site/coaches/javascript.js new file mode 100644 index 0000000..9ca0ce3 --- /dev/null +++ b/site/coaches/javascript.js @@ -0,0 +1,123 @@ +function validateEmail(emailAddress) { + var match = /^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*$/.test(emailAddress); + return match; +} + + + +function CheckRegisterForm(RegisterForm) + { + if (RegisterForm.username.value == "" ) { alert( "Please choose a username!" ); + RegisterForm.username.focus(); + return false; } + + if (RegisterForm.password.value == "" ) { alert( "Please choose a password!" ); + RegisterForm.password.focus(); + return false; } + + if (RegisterForm.email.value == "" ) { alert( "Please enter your email address." ); + RegisterForm.email.focus(); + return false; } + + checkEmail = RegisterForm.email.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("Your emails address is invalid!."); + RegisterForm.email.focus(); + return false; } + + + // return true; +} + + +function CheckTellForm(tellform) + { + if (tellform.name.value == "" ) { alert( "الرجاء أدخل الإسم بالكامل" ); + tellform.name.focus(); + return false; } + + if (tellform.email.value == "" ) { alert( "أدخل البريد الإلكتروني" ); + tellform.email.focus(); + return false; } + + checkEmail = tellform.email.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("البريد الإلكتروني خطأ!."); + tellform.email.focus(); + return false; } + + + if (tellform.fname.value == "" ) { alert( "أدخل إسم صديقك" ); + tellform.fname.focus(); + return false; } + + + + if (tellform.femail.value == "" ) { alert( "أدخل البريد الالكتروني الخاص بصديقك" ); + tellform.femail.focus(); + return false; } + + checkEmail = tellform.femail.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("البريد الإلكتروني خطأ!."); + tellform.femail.focus(); + return false; } + + + + // return true; +} + + +var newwindow; +function pop(url) +{ + newwindow=window.open(url,'poppage', 'toolbars=0, scrollbars=1, location=0, statusbars=1, menubars=0, resizable=0, width=500, height=400'); + if (window.focus) {newwindow.focus()} +} + + function popimg(url) + { + newwindow=window.open(url,'name','height=500,width=650,left=100,top=100,resizable=yes,scrollbars=yes,toolbar=yes,status=yes'); + if (window.focus) {newwindow.focus()} + } + + + +}u{=lrpA~M2dT*CnG!FG2wx*F>&y6<*Mep8#>cra9WuzPKW0? z$IHv6%4>E8{RJhD8Jn6(uU>4XNJYDs#a~FT7eE~0z1T_dNRJ3_?px8?FWNcY+jnoK zMZL0~!HF*BT}AfkYxgd>f&5a&ZyxX(9A=l92{ zo@$89$nQ`&828T7^*N#|MB((xNJyjM)#_8&-UqZZ8oCHntYjHs0|J5h4~+k>Vogz+ z8&bce03W228ac>|rj9ihyA)EC-i8R7jCv^@Y0o2%-PzGfnefTGTIY4z>Cl~X_@Z<& zm5B<;Fi%%)wF&4nA6Z=+byYES7XwrhXhel5_)MbCo9a-SNO-Y#6%{7|Si40f;0|^T z!F=Xeqr$`rm=U0_(Iw~cp;Ev1=oL{YC<#TU;qe^XKd~aFd6gAau}K^A8F6q??J5;A z2Asg1$SYutW$#{BYr}HeK#^#_}e}a4G7miFYat5qP!s zYA^OVJk+)t9Wk;3)6KdK3NR5IOE}!wJ@XnDL5v#q)rk8fHak*0G${GPkWnrrBvfD= zWm5Iwq19hxe>e6bh>@PEGA1CS0KAT_Y>`o6l|HK_py``DzRLTI(VUCv;wLpKw$dlH zh@k1Kh(Ty=7PX@;a`CmrL|6I+7D+NxZHqh;u?}baMbV-fTvP|btan1k?aO;ancSZs zaAUJ-%%3A+3vArw_eC|`&}@}v3!{RB=?9>cVuc6=;n1Kn>^!=!V`;0Fas8Yalap8} zC+VxId|G6WC8(3Tl@uimn?xb+yf>ih78>>y-jm7B;c3itVoQv^x*9Czthj9!X?=&; zvlOKVoA8iOz#N$QGWf6aRR*RA{g#E^=7 zN50&DuechSu~UxWrcS|VAR{_pu(b}z%k&Gf?oUxNuO}iUe!miOIiQ$W!2l&Ej)QAK%GXqhyuZh4yMHbrM^BlH>-NSOl#vciK-7%l$NUw z|2T!s=M|_mU_s^H;BS1aDC#f`Bg%(Zm5%^pFDrjJtSI&i3F9Pzuy#550T~pZn(O#r z5dl&(K$&iJjSId^pW4JvYrhZ5yZU`YunaDxJL7|Cpl<^0UGF{r27V zBU-YSq9kh#(nt(-E)!28Zxiu9}jSc(#?RY}Mq3HGwYp-D-dzB=Bi z7Hl2g=+G$%I8%1dZn0YDMu@AvBK~ z*E#B@%#oT46s1gSB4Ns)R*t7?)^p&oH?n;Yj~NQ1G-;DKjQYxt`+)ZO@Am0*DV&&i zDPdvKrylO>Vb~WAwS_|5BIuYfQOzmi;4FrfGoSIw3C=oWLPgD4MWGNwv&nYzp31Pa z*Yxe8E}F?t`7EzDlRv+k7#4I|&nMsKwf@6`E>#@JSl>vABIXT` zS1gPG3wEEQ!ydU5cddyL>`fB$+b)tepVRtw_0Zhyrp>Hw^d*E_ZB&bjhD62$zzW;l z9Y5H4z0t6F2MgkA#3Yb2%|4(Q)gS5?lXw8=|DM#=LUUVM~*tsOXg?7NRT`?^Pr zmvSOhJo)(M?cXM^Bq8**1>OulPwRYMud=%gHPEgj=5I9#&{Sx&y+)_3`Y>mSEB z3j}wBpJub^I$s9c1|@Dqaaz4`$SB}=;CqE#COP#T)4$|ZwVS-#R_Q~!n;56$fHDnQ zI64M*^X?m_W%^L)#m2!#^}A@;Z_<7pH$3E8?_5s(As537SEQD3kSMVtnuAVzXKQ<w^@~|^3n%)mR z{b`{ZC^D2(LQe}W*bM>^-_H2P&np?>c_GJ-ea}lm&#M>4_!>^%_Gu;22u}+uoJV`| z8IM69SoiOVqWF9_zVXwFM|fI@h$0$nD&A)Ghpha(8Q(X4Ok{+|gfu>stY-+(JuRaH zb}dhfjqtRPriqjR(-{2GDC7VO%iAH380Uhy{g`is6B(@~LXp9)5T0=SWp;%a;c4N* zK^6)?-(IxW{*e6b4+s0vAmvG@H;2=v(=q&_bsPL#r#NaJN^IE=lF+LJiK?r3LDJ|d zL897LDwGl=%z8v_giC7o<}W0UCW_GsBaX=BPeob2U2UsPz5CRTE4*o%>Kw&OiV|5) z^w~}5u*Bf21l#$i-K?{#gM_nyBr4#Y1?Tfv=v}#O^e4KTW<|Kkm+LYQH(xNhHcDX` zGBEhse?6yoG@6S6MX4*F2h?q-J5}EiaiW4W7V4;D*thXD)b}*yoUTojOavzr5p(-} z{cMW)yW70Vo1!tbqI89PO;I7%KCD1a*q?>8&tTUq#sk;HBHs=&Ze|_k_6v_wrk7*t zZel^qwPox9gq_0v^V9D?{Am7x>921-y$e5l{PA>@D1tN#6#>|#{EL1{`&O_7&#%%B`fTiNuW6u?sR8Tj@kvqP6ld(kEoN@dyb4;8?@ z>~u^Ib1(P#p3*4M-%UfI9O~um`lih1d2Pbt23O}sDewxTn+@jm(HT{cS4ybY6RB9h zV#he=bK0z`X`L3;Z1sR;IH4qXO=B^Uy&@uQ3;L~#%+Mj|XfjvC7-zj+Vx!~Ws%{%M<{Kj|!*?ZP}py~U3Q?I_SS9kg-{^P7Z4N8;N zTscWRJe!^bvxlP_JvoIvobXX^9+WEWsc6Y{Kt;8b49B#`$1{~U*@nZ=_=fA9=rxJd z(Qv@q>r2UR4;9r75~1Q?*wo49?JvH>{@Yc?GDwm*NMe_{v`FXSU9Evlzl!?nysk*I z29?{PWLgdCB!j%fZ49~xTiQ&#N5hPsLX~0dL zR(I3&w#pW>?d|PuU9aZbw(o`OUZK=#HE5lKK~rY1*GlZ{WTzSM0*Fz0tsao$WaZ!m=sMcD`AC>B<(ZZz$%fMM>9!5oAj;?1Z=u)!kx0+)#^ZT@#?=t<)W;ZA!4vJE%H3+HKa1f9n_8duSh%o&22vMPue$N>5he`*; z7VKrDj&(7K35Wn zqz{wMizX}9Wl`b0UMWtgl^eeeNOB9V4C8MXP)wx2 zLM9V{=j)RfPld-l@jA|3)KyADB49VR6OW_Ittmr^k{YjX5`j`w z1WH~h3E9P|TbFBsJ6L3Xm4)ET^v(De^i^I3J$9oqN@_ zB1PS&#Q0APPo!hy@m>liQYs>r5jgP&-={f@@K#IYCY z9yO*5LPdoQKqwfquc|gf&c_ujDoUBugbjd9fS00m0`qxPtf+DW4LJu?FTAo$(VnC& zyj0r8P|Bp9WX9`L>o9`p%j{od;J_43Ae`sSmyHV)6*uruL}a*mxo1JI<48g}bR_`Q z!Mk<81=3gviXVbwD0Ra)PC^2VPIW6fBr3UE*Xa^lD3u{ibA2aEX``GKWjW1D4XHCg zxkuHr8A|of2UK|Gi;n~PN+W$e84)TbWAj1vX$M~kRNTxI3{`m;z*hnlH#G%9eY|9@ z7Ame$nuM@|E&(TN99t%bqjO25xQ3}-R0=js!N~V0!{O19;>x`+($14LM<|HI)$k=eZ~8-w@F|1o#1y^R}L_OA$8VBrRq4C`GrgTX431d}W} z!Js?9?f?N6G+nmXrbsPG*{y%SRix~$BCBNSs^#{FbkZ+J$Mw38bINukNW}$+zx6C$+{Y!Y?{twR9_)tBWRX1FsB$X7WbR@xeLE&A~w7298Bd<%A5>Fa8 zW<_;~aAoeI#QeMl$$LPot@i|giv2q?tK=W>BlW6D9PyNKo(d`4J#0VH_^P&feY48#vcjfS zDM%pjRJ@abFqYT60$Nb@_f)iR1S_Zj9LE|qYw}k%^}W?5LLZlh3=;dbY{G2L_~o%6 z(e;+Vt^|?GgGDCB&Jto@+fhTrdw+_&>#F=7`1}9`_lXRI6ESZ3G(_}>%?{2hl~I$$ zQIT-wE$j7d-u11%v%)QTdycLY1*yNq0FPnC+Xf6$f{OtjkM0`>3{!<;DGFFeKMf}1 z!-L5&;nh*@S*474a%r8;>-16AH~n&#uNsiv2L%bkjW~mBXB86JKk~J`C{9pY!{8)1 zRO^q7&-g$|l=^W|q|kI7p;t&y}ciQT**T8Xd3e$oMz_jZ?1{URfGU^S$1dc}$Bx3aSQ+KZC zkUdm3O!mq%SE=ULAzd%m+N7{&PNhE?F#d9l1HO=`CT z&0bTGKAcoRzc@C$Jo82Xj-mC8;t)%ekS2t}ZWX3&A2v%X+}M^TA_hT(3BsW?qd`mM z@CeFeygZAn>E(vYDM$%!oc#+fr3wd4$Mz$U^^KMZQ`7}Iys5voP5qCug;gLx(rAZa zhV1W-yN)i062`$3CgzDTD+8CV`^Ln?_b&$#RQ9GR4#fC8(x|d6$iYF-*|RZw?8^ZK zN|qDGV^*_sq(>V1T@EBjOx5P%bGp8b5`r7nQ=fMkANW-u!q{hn*25HHeDdPBnjj@C z;ljFEG8g3PvAbJ#x-L!NV?GotBmhZ&nOr5qDwwPAP)u+%O`m6pd506CJY8Jdf!d{A zudho3xNq&h3zMAn?U<#378oS|bu#d1Lz(%o7Y6ns0=xaXxS`y3isoz(F-S$tpVUKE z@7R}$x)Paqw_w=DS|r$kd?;&e9V9?#!Sr@MFOKs4O@$_{WjZ;=o_4vr(4E$cr_b-l zgY7!ED{3h)<|kEo3u{7xbif7y=z!7rXrKF1^c$nN3#1Ygza>g~V&0ooSuOjO?l-Vz zGFSo(1tfS#f=xt-&X{zxq%CaTACt$pd$-$e+S|4uN`b|Z1}>;$IWLz4 z3bm?Ncz#CZ5dNN0F5{lM2O(L)r3s>ya?Nah|M9nH{of91ctT;4U_6y1pp^BbP4hz5 z<_R#mkB%@vxrv^zM}+v4mutOj9(CPaH*Et|U!)4g#*?WG2o60Jl4gu8e@ZuMDP}f? z`Lc-^{TZI1=H05&yQMX=H%TQ(Q1)&SlX-IYBwI7LRB$)5x0n6q)N4RyAmuQIQz<8u7hA2s zHm^g6m1C(F7Q1(qN$J!(LCm)fd5(Zx|EXEkgJm3;3eG^XVS=QX2HK7)qI!48<7VRV zNXEXS^h~NZc~|6>9@4q}ngXsW22&0*`6mkay~GN`l*>p49qHc_)1U#>LHblKg+fHRbs(8pw0-u&m?w(Cos42L%_Qhl>M9VtjmEHD)5 zHm!g)RclQpDNZgh70EziVzxX!jxA1usZn|UFrz8T6XxbFHM~(0g>dz1P;$u@a>!w~b?c(D~msP&_BX8PuS?ALw)?E(|mKjV~ z%s^KGf=>)PJ%rtlsRXf3+%h${=WM9qJftvTu@jM^NuT+^Dqj#Os1XuCY7NKaKCzv* zn!PaU2*`lJH@7H8r@PL#7 zQI@4yP~#j0g^Z4FY+YeHNGGuMk5}#~{_va0WS8q6mb!yv0WA-asgT!}t+~znlu>T< zcWwe85`|viZUiZM+6^21Jax7&k(0vv|CObd9 zlihqEbI&-zRA6r>+u_JtZAWyhuO+mR$3OysLZxD&kunMkhacOiW9tDcHA1*aWKlwh zcR63{`ct|5Wd2My;x$k=dA)-{1{G#hilvxe%}>q*z~tTBP6;DsU;9-z`+;uCRu_HK z4m9F*4$f{tVu6+_orM{T!Pl4gOY9EmxHt1Zw%y`=ZVOEdiP)dtn-6E+VlTS7tA^iS z*0ut-Y0A3SE1g$8h!xL3@`0zW^|3+LkE?RC_(xmb-s<{Niw&b%Sk~s`Jd?fIbSUib zjO9EHD^EOzn!hd>TTnmJT5YQB`g*x*w*6|=tbwT?NJLPGRH=z7?`W${f~}w3+NUlK%`JUw=-E+x36mZabY1gtxy9f8c*dl>eTuH-8;|;n$!3 zhJ@$aeD}DkYrUL&(UZShAYDG|Y(@hO;F#O(^g&Bw22ocW@pp`7iOR%mIPuY>kL$8n zm3MiaeDSJo!T!w*q}0c8DmV`I(1Q9{Z)1j)cGo}mu5K&6Ue}zf(ivpSQ3(d17!Q+G|FDM0dPF{mYK;ph%|X6@q+I$ zy=t|-Y1X%9Yp?Rhyo6ou1ZXs`I0{9jcK($Ah0Ww=j!ZZH(AIMOx8i-iy<1gfy~z8; zl{wVryCBeTrTv@4nf$BGv;SkEKlkR_>%9ZuFL2^_4aT#SX+S{XiN5th-8Yt)3KJ#U zVKKx!Ch4zsi~Q5vZ?|RfacI`OfBz$Fhk(pqRLVIGhC9JW(Lep3&w@KMW>#{6i3#qI zCyH@h?EA=Pbk3oIhm;4}QX?1oRFe=F=@ql}2Evq0Tik`U&zP?4(`}oLU=a`o(mj+o zm3Zzz5Iy*zp(EdJ)~o+wVg3)9iKvu&vp?(PEwA%kk+&KYwS&|E?Tl46G3^|qSR65d z_8x3U_K|-1-DeILv0sKKWRw+ug8SnyKY#ew`^AsH{P6qF|2iEe&^Hb#8obZLjhcyq z8pj?=aRkc3+FWxCt}%c#04;}UI=bMh60wAxnUCAxt+evOArB^f%N}u z?*a!x5+0da5C?K?znGGdL@|?LBQopJnCz=9a+8nj*#V$q3Y*bjDViQrJ62{{5P<+} z%5eF1XhCsAWNnq5heY(HVz2kO`qM@ihYNI{HE&@oW1I^L@MDEL>4I^x7}TqsBfDGo zJCiY;)rNzK|DA~Q1VPrzA%&^_MUaX}A^#1mC`jy2pmZn{Oe;e&67f$+OR?FM$W(7% zuCH~w&TFdbDZv37E*W8>QSZf3e#Orx2s4^sW$;qu);9Y4YTKF5 zb-ygiwAbrRrPKa%y6sNK3yCF^Oc|LvA!bk2>=#*;zQ~q)3IE*$4fW#VYF*y+i)10~ z$dwI@si(+vecctqA0gt5BmkrYs8p)5;J9meuwgO)>a#1^w?Yo$l?K-QknYx$SL)#Q zlu%H%pbAqd-FvHQT3zRsByC`oBaIdY6{rnpBIO`d5_*lEH87`RIxZ8>mhQO82e?9R zn7qmRez*M8bSrD4Qr35{dNc#6Gs%>*iDx!qPZ@1U$zMe4l%9~9KnZ3j;hFas4WX3& zjPsj^!3PM~sDSApl9Vz$XTOM;%V+G-b(hpUS`gomN0@HQA>vdh1U0&auGl>I|j8j>PP{52g);gZdGpBCxH1o*8JVQ#D zd&%z?=T%u)4YjK3@=XV#^K;n9AWrF=?qP$*u$29gU1Ew7Dy-BBnv^FjrRA)K35R8{ zG?iJ9hsPEu0CS?6{N)aw@_DST0*Y|iYSoz<`OwKhnbTk~HU z3K=AocK~ukZ`TvNiON;I5@aC3UyK8)v+i9`n$=(Bs58)OK?XAYW01uW4sGfiuQG^{ z7lAA-1UlgkZ z@&0Lw*nD8pmK^CZD;sCcT^1|MA4sMFD>D^o#Am5;kYe|=`kg%`%!Mwf*&W2ak&9JZ zc9uuB%)3I@p0+>aMuy2oO0$=r#_82~9mli3=KMc7i>j$Wvvjnx-q-a8Y`QL>bvz%<8rYG2kRh;HO7k#Y0-D4qzEd7>hDo3Gl{w(Cr41Sdy);_c_s89(-iDta0{S^hT+i;Uy z5Mrx8^XjUJBhDaigY^?nfjQ}U`A;l;9h^YNAgbm#_cPA$<+KyA!^S1Pl$2J{Kbu&$%{NtU;$0Y0SZFjyx@RkfN7H@%?C4u+p$djf_At-g&PNK0ju=nr zL>Xmdp^nZ+ZxbmM$*LA!t7-3zN~BAZI<>27($@rhb@$*mwfnlGo)qwIyVJJW%jsEAX{G4iHlhn>7?`tEru z4RjrY`I7K1SnG2_%#I!v z&AeXKqpqrMSu|DCTH%B1GsLtxNG#D@%4)ikzl?prOT%^#V`0((=8fLn>xZ%)N^Cdz zZeIq6T*olE#E2cW+H3fLb>Wq{i!m1om@P-aaG#nczE29{AsC z^SUEjb=UwL|H0EWE$ZEQF%(Q7kz1Fjko{M9q<^9g?+GfohtveveCSCsw>ti-1^V$m zuRlPAv^hu<(VS9&@O-RN?S~7Y_SAMxNhq8!rQExyy8EKhaK?Nv2MHnylkKp%=kLCq ze$I1qX!j0L#Kx8@D&TbliX~X8LM`=}$Bf(FVX;M(R3x05XDZ{fB1O^W<=s+$-q^>~ z#K!$O#w#48fp{S6;WmLkEUV((zu&z^#siW+wC*y~64d^{24`YVFu%3-K}w>8`_oy& zE^hS$0l%lf@By)G-pAsRVEBX@s+1|Q(&WB*=-Dtq`iuu)vT)4raR?4D2rh*ZB&#e; z)DR}(os*{jR^IEy-|f}fIS|+8SJRFOi&Fh3U(T{yp zJ?9v!Q`+l%y>7Y=s64?5wB~~4oZ~)Tv-3h)mU=_KEcFvr`JG>PG0~dI5WG^v^~$pO zm+MtufUOUF&{j&gPBP4=!L&3P@g3 zn&g87XHrm*nHEx+ixv7M%Mv2ZyMmP4a?PvjjJM0%4%WN@=|K+C0}~Fvy=uu`Tn_F= z&DFxB+zZ9M691$5=-sxxU3O*Ho2aO(OkjUspAHr@h+^eoCT^%!NsmQDLu4GQdq4-{ z4Q^6z<}oTa`L@ctdynh7A-IjkDv_?Wt!v(&_DCN-jAK}eI5mUY?Z)_VfhvVmy_BI{c`j|5394L?q-o|t45 zqYJrjbC_&kB#1x;xNI)I9?pYd(`Fh zDsVyZ6HnRyQ+IXEjoVoEujn!TAQbTp%#$*c*?rmUR?W;Gpe4p;S`uB9+#ToFFF@ID z0KA~2E0bcXl9{A4WMS&t!>F-5NeQTrIh9Kj&0c{IL3|_WN6{O%zHO(NhDU?arJR zbGp1cbQ_PPQV{3;JE15AM8gOd=>U~=sS^BkUO@(+3(4(*>&SGjZC>i_ zwrn>_tab-n0}Z8tNLfLcO0L~b1M#G7b52k?J-Lw%A}^LwC@(!0X8XrxvspdVj}P0I z>f`FgA;x4*mb&cRKwa*fDdvUyx-Pxe%)5+6YxbM+Tjgnn`(}?L7%EKma4pD`bQjy5 z(kWn~dif5fO;7I$CWGYA(ENGi+KlHDon9&}y?IQme&fIUI``TqR zLv`i&p?ZC++wG5<6`wdLEaAZv{dXqEV2Q8asH;!ou=0fzY{3K#Ul~89S$#b=-?0ik z3MFl+y`Q!MPH*P!4KLpCjfoQmPj`@lFO}%Oq@O`aLg^qH(UWvV)xKitib!v7wk@?TN(8A@GI4zMM&HF>fL zNL-raGGErCO7cy8Sl7?ndXFqlaT<@3C?Wc{uUIkz1vR_Nnl3#0Y;YWyNHJw4Mc+)t zFJ(e4hf86O7)|7ioNLyA?Eer*DYi#2cj_VE_@nQH5yKAR{*&`N_>S zO$;+;(M7&T7#`=yLm7bf4*lH!?#kZ+q>A))zXca}o6cbWoUo&W9S!r!AdrO)EQc5K zW5aU56q6lrl&s?b(hHtnmR-dd7bz;Ax)Q0(zrT}ZR0gN1;J4%Y@2|eOJuJKulF@|5 zMbGZ|LjX}guD?3shE@ztxUwsGAUnz1wjRd~D>ALR3hDi;JCtChODzO9{pt>}45udp zip-(30(wp-ufe&VTofCm)5hrEyu6c(=#wL2q=VZ;g;~f>4&LY#>&?;_SnW!a>VUj0 zoxsG1_>~Eu#v7}aiq5r*#zg40{`1dQ~K!Fu3BvuDaj3shEF*dfz&IJpVZit# zVhY5#v`G+=O1!+A7Xu1D7xFEqfQwt&xDM{DPBc!~Qh4GpkXXPI?r#b zRqL+{(J?U8QtM~};>ULn?w_v?Pvv*AF0Y4+72vumzO(v(u@YQxfPI2&(Hcz?1Q?rD zG1KcmcFMHA%u8QjHJ=w4HOjjZZa9wS;X=o>m$NQV{ilu>+8@&DP8b}|0%CqfYo+`7 zJjx=ylETWbNG^BfV~x_a(HK3?A`Ry$Pd-Z;iDb9fQ~*(3C*>Un`&>Pdk$7hjP7{%1 zCIgC1pCAea&$y0XdSop#OV1ltv9n?)JXN>V`q;Fq-8o*6pfPi8~_e(P+q~PX2o&} z*eIb-?_XvO#Jzw;dc$CwFsF)Gj7E5ygMt(~B3A#tTR%46s&>D6`nD!5YFSBB)bft2 z3ygx45igl>4Q#WI2^5oTxQb6(U@o8ge)D6?sL48FLs{drOoeAZL+jnJYIq_z7G6_R z4MQ|e$CMMnQtOf8hl6uk^dvwdZ(lMMokrv2OMSbd|BdE$*yk_}(Kzi=mnWN|f9aac z`tLlDA{U*ll>Pk4bTfjvB1O`Ks4n^!Z_dbz&HyJWPm)AxU~$KI>g`-3%1|pxnpo3k zJ-O07lQZy0yD4f=#FkGdfng;hf#I*mdROlcUtez%7uG02)@}nCNE_anjJ?*{ETW3) z#(1S&Ks&@{XYLp4T8@epl_YT@z2O;v75-L>fh>tkmM5XKS*@?%fQ78AJ;SBLEN`l! znBQ72!t(7ih4VB@p*6#1>p-7n1KowSr*Z16E-f^Dmi32{KT;2IT%f34Q^5)25Y3i> z3h!~MpB+E{^0Hr-`^Eol_tk3vbkqGZY5Xs*T3@eXwv;qZmsPru+J0JSJ8|K2qV9v_ z+UyF?;pMq%Ps;AExR@f-r5w@=65xR)$}zWs=-@b6j zfT{KsX+#$5ZCgtkr(jBnmKIck1nqH>@l^mcTAq|_$*pjyGz-VBg3{HY+3nn`iWXVZ zCf81;e&U7vvd~odNoFXPx2=!sYPGA&U43lp8;}ZAu8=vk z>aAKk!yOK9TRzdTMQQF@MW_N6)pH_wiPdLLHBM8e8Iwka5nVU?W4S)A4t4Y5oh6Vu z=NcuqI~Y(v=luTH5K3p)Yk(CdH%IJqqLXtgNa%GhV%;L{`wVocOeE+2L*Zs!A77i_ z9?E0+tu8S%e~l8`%|-S!QJm+eipqoebwEHj4Zo zAkO$Iiim?#!TiL0$k%G1a^)4CVxwaH#GELPH9)GOFEq7Y9S!Cu=0tgzcW-f`q;x;? zhn`q~}k-?%=(i~Ws zy8L*srYqvko?&^PxT0jz98^KmR{kljAl+(6HF-j)sERf7=Gcsi@JyiMc2>OxQ<4+Q z?sB9c&FxF64p&U5LbrAo^CLv{+O7 zWx=^;NOHaS>3`}&`6Yy0?&{9;9B=-uQEF+!h|hWZh$Loy8CJN0mktqhY-&? zz^JM=16Owjb8`k{0vQo0s$(MwH-MR<%FIPl>!*m+m738NM0sfu zD|;S6&rkJsi#542C{eKiq~b;w&=HZMx-|u%J%h}X0}0re;<1cP&e)Z?)Wm3!l4;BD z<>Be!rQKJn^~>&|YPaQnbJBFdT6-Ck)|i9Mn1<9Me9hbU8%*VUvNmQ8xAuF>GSV7* zu8vi^a(}b0*5!U(wK$|m(;!g*Y7y@Y;w!cSlTX(DW*M%QwlLweE7E3Km(TUF*?z05 z?>A}om;yEZx)M5Ii5kW^`Hm-rk4ZV)8CMGMY<@SJ>|fU(GKz2awaf>f(55rSluq>lX?{8KGSwI9K5!w~ zl9|YZyF>ZZxJ;_qR+|Q!PoZ?h+?!MMbJJpAL|OGqGnL)VlJ$bft}?7G`_uXG%u-iSybWPRw2^3uAArQs$I8L^%Wghlx_xh z^*fj-QxIxM@rwjPVnxp(sK2>?3!fk#s(ivfV-c=4w3TMxj9ojd`SoLVSypy$s&HU|g^$tuabHyQELx)ZV4~COL_b z!J>LIoOI&^;A=Hd&p5fC@})a-d6(!e;%G6p+HYRkstzpb4tS3`gHj#KK{gp3>6t-B zDdmC^W#F6B_6D%yQ^wGwwfMN1nt8V^UGEt0Z2G|x|~$EMk|_4)}17n4V6 zMUy6L~1cY$>?%BGO^=ZCme`yR!YddjAU?SmYR_P&6smX$Q7D&a9VV zm;kIONElqx{lj;#`(| zVw;UD0Jd6tk^9Z3fJKgdpwPOP*S$nwf)Or>up&yO#B_m04t_LE*CuFJ=7EY;ahXT+ zV;@(yFNJcKyJfv$$ojFyn;00BGS{^@dky0NXxv8}5hyCNaCLx!j6*%n{*#m3!6GRG z!dFMQpJSz7TE)V`=ecp%ny;0sdGMoX!%-=PBuWC-6z`_o{VFdW^+dZ8lYOTs2{J#n z6jTA{7v74V2~<=XAqkbx=GsXDvX6A2ae4;o`miRu_4 z!kZ|-7v8s$7oCt3Eoe{3>7jmn*uGTd#y1mPQj9~2$dU>G;%Oak$W(*ptO<<&zZ0s#3UebhWn@t@U0M^>@4j?0dhobPWIMw)0QU{-)_l0J> z=mMNenZY@JP*DpJtm6PdZz(w0NT_=3ZYLPqEfs*&yY6_Hbe^v&N;hT@DOk*eNBC|p z4oW)4AK`*S{CEx$21GU+j08Bw2a8+9v&0I>6$f?}NrtX>`(9BhG9D~Yyycu3SlDEV znrD+D#pV0%8t&VucuJy~@6CjHaI7MV^M1#>YXP4(w3Sg;lt*S=|2~%Mdhz$R*;Fas z=WU6m)}qu^983#!y5AcQXLR24eeRJ!DwO$;%k>rDFK04a{5)Bw7Ih?`uC34b%GV$i~9x=yS@&%Af9r0hzt<5 z8M4$JtBa*lcBy#8XL+t3A75A7=3C`?O55^lb!_~9;_zaZ*8#lxZBZj_?k1B7o}I!> z0vP8ktqG%jH5}XZ8_q>IPtH=*E+ymMeK&PUUwMk*{z2j$Dzg9N_&POWV;I! zWG^Hb?&D^I|3ZK0N8|gv3Z>X8h_n)FAW^UhnsC?idvcy?XIw-%RUsqmYrP{6ZMl2c zR>$KFU^R*!n*nRyD0je4LioMroo~hli(0*rgmMjW(A?$ZGJ2W5s^L`}-AvI^AmgGa zl(C_--Uq4hu&(y?+DoASptRr+qc(2xh{3a*G(*Gi$~!>Dm2I3TU?W2=IcP>kqt7?5 z#O8%@81sM1$T7Ql+IJ#AZ=B%rdX%^xAtxNLKR?aepjYSKC~-3ycc}oYyr=D&Iikc- zV>!{_?&E1MYbF8F?nVAUunQMz*O!e#xoXKwZszNNWcu!-(kl(d|G zUNq=@&Op7jn7%HvYhhDiMrBMxn1M~@D2a#;ad8L4IFVlW)&Of6rei1JSE$^VyO5SG z6pMD!yE^@_-W^dNElR4^5=m3pKo?TlnH}{zy^%*(fG#TEx^-l}wAO~#QnzqYzOLT> z`?M&Abj&s=@i7Os6EE)HQ7&_!XX(xI$KOJbg>b1QQ*<=QC>7TX63Cv^fGYq70C6i`KaviDh;i7UaMwA>_ z?>)Dtku8wMhl|RyTy!}DUtrh`c3@p2x~ay8i^{R`a6vB2z>Idv*jkhV+qGbm*yi*h z#|Mkbs|rG;g}SRSQ=~V3C;81IUP!{E^ztiVVfZE)QvI>6w&Vqg6-U*huDb7I)o(s6 z=RVr3?a+VM`*QJXz1>!Afb*B?uzq?uR)=58!_(@&+UoH1bKU+M%_g=u5jIXVB*oP| zx#x9$;`kO`tQe$f4aqV{)R21+9^Nt236$iRp`>%L>}O828+W7{O-U6O z9^OcP%ZrUMZ;cSWHa?h-Wgs_(1Bz-wDB_MmpLQTJYb-q9Ka7SP$^oVB{3{;nEj%>! zwrWon6}J+rElPaLy01$ZXsqMuw`a@qn1LI&B8)B;OsIuYCKMjtY~ManyvB`1DQ^ux z1qFSQp3A+UqPFT7Q9M-$lQ2?+EBrI8n=l8JsqAbi+?n#yS35 z%0I=)MQs#biImL(DXOWT`9`xNsyx!EjxMUDKNL`i;S|6u2*skjA(*Jl=!OrJsYrn} zkvSYOoXCzo`un^aP*hfw2MRJjk^%C7tow*SQKJh+v;e#b)SJIX+E$5+7!^xL1UQ9D zg1In6(ju&4zE_9iZ*{fZd@sLMH(*6ci}^;V0yOM-C-ld~3jIn--OEb&8(KVD??PabQke+FHiu^miCl|GVYZvX%o8VSv$Ze;aE{9fOr`zYY=-cUr?x&U{#8|* z0O;EPV(WfwRr(#P<8#|=Ue?FD*&lG%E^5owTM=uBfd$K;BrMUq)(bD(gC!+#Z)s2D z`n7p!*X7Hhdh2>(=4&{?zbnylLg#^2qSQz|+YgY|>V$lNZNZC`+DAu=;!QH5n96mu z)!!s?Q$aKBes;0c+J-sAk52YO`MNIK3WpRm|JPnv0kksZ=PkJ+k&qavl1oipHYjyZ zAkLMfhx)yRkGhaiihtfg4|sQS-jA2Y^ylruP|y2kOZS0<{$oFHSO03(Uw>=b%}p+? z7AO1X-XG0+m7BMc03#cer94Qu(s$Nsm*5M^c&J|V+0PG3{ja-_Q>{+kWy1O*QaSYY3IKIob}RYk8V}yOEQ3wCGhw7%a#i$F#T#K_El_OA^*vcDP>9u>^zMgr zx5mPW(sR^`6omy~`fSOb@fT*fVfct3QH=*hWZFZboy-f!P@h9AvCbzpO&WOjl+G3> z()L89!*BYwm3#qA8ufXn0*W*}$pqBPT=(^fIt|I-?KELTMZBvzB2<)ly}NHkYVbn4 zx*X)<&){7_$vJw<9-A)X(vG(csy@eK{xmn3Dxx?kM@HBW#@E|erVG=P^hjcukDC#Hm9?Cf} zZ@j4PPh7Guiu=Sv_c{)nc6|eTPNRAa9w#W%S%AZs)LScGw~UDtMTq3Y6^{K;h0HLQ zFRj4G#EIfVy1UeZ+OnR?3rTy#5zXxxjENJ~P@zO{z)0+UpW@ufE$)C5t7`$pQ)k_Y z?jKLo#z-cfrw!_P#uKS#k%{L?+k1{UQJW$zo zrf?c5UYRLOgcF$&LFd;0pD{@I>5NppMUw%p*prBUwtrON$$6ONd? zEymNz{YTXvntj<;dMT6-KvuIpbB_Cv4(m|WJA#RNtadlTD$V+8gl`LaMjN$eK4C9y+N z)7$>_sUkJqtl}+7yb>v8VeIbA4%#}Z*L|FOPQr+pJft_ph>}Rv7~=>~n&&AYgWZOhc z^hxIYlzHOk*{3_7sD6?PMFct&QcytAzJms|ZKs2Y>Lr=07N7u150#Z(N_d zDL}>W)rAHI*_}|2ng(MONL!cSkNNsVf4HB@{P(-#YMBUUkLv(nK(Mgwr%NGN1i8fl#w)i9}Ny z6Tt({Sipd!vr(EbpA82St!C=B?ms$$@`AdMU;0K!5-<%{n2Dp?LPeE@JS+OGEOfS5 zGLT?T2o+TqG7js2w)D4B!a1nED)odgQDq@`ML)#vN5PzHJyE5hkwCo!h1pOd%RwN@ z_*9F3$mK*8g+>Cs|8k;QWge71rI3eMPE@aKB+$DrCr+Ie9&m2TV7DG{4uW7jD3tn1 z9L5|ddbJNFzJW5u;5Ls?YNSerk^mxjEkwX~@Y0z&s^fJ^<3Li;ozSVbMY&w<@|XO8 z8QRb&u{xv@&>`g~%KwmfgttR9(JG?KA}oxde!N!?u7i*I!nuj?p{TVyjJWd2v!7W% zKJWUWY9M<3IO|W!wVJ?>wSK7L2Mc8c`cT1=3659z%=aj&?qN<~1Q`Xwg7el6^))M} z!H3dHZEjG|6wotUZ!KWA3czduyJ;YzdOt%D`|W0OSAa;hb(4Al709c|OcNnQb$eih ziRYPj5&CRACPIjcWX2&RcZ7!wWD-bfJMkC-IQNW?S2z(uR46kNA-N+yL?{yhz*?{8 zhmp9_z>o!trrzpixTKN%glgfkgOGL+x}D_7ivB1KR}GZX{zG^IdX@jkWHk$vh^tbe z{@THq4HUwR!q}4H=my@lUbtS%#LS-1WbrGBxQn$+_xj@*(X#PmI*k?O#2)d`$?~a@ zXEV<8(V2GDkfyXzYLJ`;aYA|;@GVAT!dE_*#*7cQv?ysW5H2<8Fa$UH=u@KZu56^%Vr#LbWt2fO;V;zqZE9@oR$|G$CW-j5O*{#T#*A*-6 z)x$d|?d1*J=RL6~HPEqWA82(^>Y$BIkm_^S6VKS9jo16m&VUxB584Q~*~Q9}zBYqY zk!-YHwZ-YdqT&h~g#xIoGoR7og+v%0sUW6G{}gUHxYd>UP@BBW)^$;$WqdVSR9G<* z?Z8H!87+!ez{8mFe$}0woa)?3DVv2zedPV`CE;HdLWw{p!rj<-eXQz6%pxnl=Id;^ zeR@5G$tcK33pYw#`WkHt@d`4Uq29CG&3pdx^AGT3C)y9S?0rZPyW&HZ&WiAG5v**0!jtPaQ%` zu7}b|jd@6tz73Yy#GsaD6f&!d<|iE(-$lwvz=h~lDt@Uxt*}rli&9A)z$zaZE2=@k z!zc!3Hd>z7d92i#PEoU=MRqF)=TJ}7XnLGQn+%NNObZs-xEKJdpIZ0bv31Wr3sY_Z zby}!MS|$~=pA57_cyL|2o7i4eF&k7=H-m?ac&$7jsQz};j8L%*jR=U0Tcw0P)BzsR zsVg@RRuo$UesfM-x5s^RP|OXDl~8D|Eb=tux?K-jkI}Zp8pf)_ruFW)LIq7IRag@u z#z6aDHWVtL>+w;)Vb-spygf-wf7Y6~+J~>{>ziK6?J|4K*JZX#-*NLRC~a6mjLT4e zS=GsVr-xQ`y%IiuH9uNZqep~H^@Z)c(>j-Rd883W7J(F&YJ$miR>dKw8r?drYE**~ zr4j2vX=Wqgk={!s^oM~iuL6qVta^a@M(G{`C@NH9A!V}P$C4-2-x1}enX`11P^^l> zBmyoad14R%;MK-%~-pEKHZ3Q`)_np3C&G*{6r)zF6hEY?Z#hWZ7$0qFx@9 zZfs&i;6UpO;+a#jqC}rME~UmjOXweO;r$FEp7I(w>8pXFicTz)+%?W>w=+1r{Xp9p zMHop!CHl+yZLaxD&1ql~HX;k5Z#tet)-|lHm@72e2C14T`^i~~v@0ceb3#;}mZ zuAo-4f#I?I%Y;P_4`mE0r_8D}7QA_5O;cRi)ooBMZVRxkdxEp}=7o5f%C$5{M$YFKqJ zZ_3m>s^!K2FJ9KD=M|-yt5HhJnFrwHb3OU1PgKJ`xc9+{ikJrT9qju$?Sq4=HIX>HTw~19 zyYXE~lF9{RB#4OY`M>Fti8kZp5lT82#^@Vp>lTBpgQ@00h+;K?2rsko8!+UV4kW6m zM2*9nKRN9?@^n!8xJ=5}nMf6ggmqt%7oCviWpQ}UOI%QoQ^}3PSh*uL#IHZ)uw1&) zpT%;~AipdOO5XNtt(CkECXNx^XQj0i2v{J_Nk?O=lJC@3CWMOfJ5EC3>H)V-bB zvA+kcmA=TRPes2b%q+r2Ko=C7y+6D5(WGnXiGn-(oyscA6wo)TBH$X-;d zd}Iy)(@QEWf9I+=zLx)6FZcOoU6|kiwW>(UQbb+d?uHUg;Q69QNxo6Cxr&5}i+*g& zJPn#bg?;C=O7=xCu3s1{EB$3uCjEkK|RV)J* z$AM(BI}G~Q^!<=6%c9D*>27z8i?;@hi8D;?OvkdlJ?z!%y7<(JfJQWkBi7x(b!m#g zt{{0`S{td;reO+&rioHOV@Q?9DdvUf&Xby{zJNd{io(P{`BK- z2~WD`{rTV7^tbfE}6s=d|fCGHuQCUkR8vB z6cb;i;I^AfOtHC8EN-aKKtBB>dKJ;jvXz^DTX94t__mN92K|eRd?QB#udkExbdRF- z{NDKc;`^81D z8-HOFT=ggw=7BE^d>Jp~q22h~QWJbzh*&xTz9u6o(m#b47iw<%Me!-VC{!38hcR)J z4$_cnU`?$1d|zaO7y_p;?feN&&zn>Qa{PUkW>?kL9))P zY`4=3e2ugz!6{#Bq%;A2EDKvRqU=0m$lCqYgGn#xPI`b+q5`Q*JHhHb>%IGI zEVP&V!#Z8shP(kFjgmy&fziA8>z6ev;*TM=OLs2xr}uV^j?NNv+@ zU!`RFk;j!bY=UMXE`t7??hirXE20w~~XE-32I0gbNBE+Oirr#qdDk z12$SBE(^7ZmKf-muKcf!nhz>UF+64=OWfny()QregI!+k?qG+5$^vN`fvT^0S!Zdr z-xpQ2Pf_F$f|3l6qcDLOY(C{y_hKR;^KN3HS2f{05QOzOY}N7b$=JIhmu0B9iHAvh zi@@RGaQDD(TEJ+)sTs&;mZR_HSeH3nzLv!%e||^ZPbi7>vAfvO;Od4=m+#^0wlIpL zCqu$rEyRz(m0>?ZODfPdyhSg5_^x6P{aZfJv60n4)iw_=Q7TSr7-6HCU<}HljLREgDlklrCS|NHzr6r zmf7+tt?G|o;i4v#417#<_}?eBna~{!6{XeZrPPiTzw2gpEQp1Eib&%|^g&jvzP>IG z>paCRHO_ei@G%fgXBK3#UEa!`ILkq4gX`E|N#-j`oK4j2XQ+eq_uDeB7Jtn2)l@HH zMfA>50Z*)%{I&Tr%~pOY%D1#M!yPE)5Q35mCsZ$wD+TkRxCVq%AGvy)^;jy9(kd#F zKqtNd<9fZhw8E;>1=jNakrx>15spGBfdPO4bi`%C_5sSF7{1(Q0;S=iWYhD&F%c|Ac z(+iD*iK5Yy$VjGpuIzr$HL#bvwN*hQ9d2{1Fx}-_vbT;Bez44SR^83buCkVD$(>);+T( zRicUUD`eAbWt1YOXO$C=e3d<1>79_6b(L|hZ%GK4`?kg9zQd@qx&4)8rhkM`v5sG& zZtnk*?RM|qM*Y{t<{gI=6JsT@k)Q6pKYm3khkVyP$cYtCI*a^sJ?%2z%i zFA4igJp*Wz!~+W@1L$J%bedgHo&f=8+xLPSWglS~B>a-^m)S1cXNPOLyEyrAYFKfg zs}wBNXT!9s@K$IUM+?g3LQ2(52RFMD#4Da%l>GQupbjD9K0r~yl^YAf8?m1i2spMOYbq;p^E>G_lX)8oNm1E_J} zm{qlL_4~+$=$5PF=6FR?k5V5uW@t&&?}rIb%IEZZyNy8Z-M=?IrHDu=>cP8A?29R@ zb#DcR|5facIxNV_s)O$HHHigNGC59to6$(hKzT-)2CH zYHXRY(tfSj%jE?7@dM1b3E`ql-$ueE4}cR@UeN)b1j;Mwq@W3$)C*lyCj^R$9&|<> zg9bDazvN1~3sBVj_eh}R?kJJU+;I#{L+Cipw{Hhtn3;g02)ZMIl6#{>X>glOD*&PO zmI?EirxPW z(hOI}Rp78JT@XHI2-==Wi%l7|k9Ae;b;h>bq~$I@JlDmcT5pSDhcUwaDK0o`CDYTh-5*-n`j$Sdqiuy^>PfW4&ETX_~q|N^jiM^?jBIUAbLoTLK80$b88US8dd!6@TCuUMC7`%7AGvcp?e)$6VPTUIts0r*#Ww?Q;`h*rPw2L-93VzvPC%N6T!VnW-lXT#8a6Z`7RKK!Z2!N3c=l z6#Bc7qp;vI8JUPQj3bN2_UE$L>y2EjFpn)osgMss95;DMLpeD_Y;URu@q>&A)JH>U zZCd*ho&hAPw8TPXymW!v7kp}*lj)n#n*LnkNIZH)WpB@_reJtZq`_8Mr(*KuL@JIe z0*{n}HGQj|WJ@zxAwQ8p!y=8XkUv}R@>d-KfAlW!?+QgphI@`^%gQ3;%n`ME7&Dwt zRBWU_1W3RFhg9sg8}*U>JdM$~JJ*F~M~+U5+Na7Iyb(Z-%Jq9D5;G>N)Ab(;Y&s`8@3L~zgt46MB9)7M>I zoB7aP;GeQGU;HuM@3Y-vK}j5P%G^_{L*9J3$@C{amg}!89BNbr#*aE0D+;9U0UE^* zCi)3-4LLvd_Bi7fizXn6zOxJk+`{?G-q@Pd%XM{JVZ6^MN;z4HP;s~R!uOKG=%QqhRT2u?x43J)YR=k8 zF^gR3RAQvQ@D-EBiKsh^WfSny*Ss!vU-RtknrjTz#~OK{2lSCF*s~pIWVwQHw?5NY z(i5;;;qVW;Nsv=^GX{>*C99Z=lBuLvoFGTaEPKe^*%-HL_% zys(Jr*II;)ex9>&-wXYSrpGEf`9EXQd9(toA8x;3F<=zbn~t0oEmi>5kG7xHlgGe{ zQh+594H*S>QNfMu45!$G4DBZWcv=}#(^ni~3QTnfDm{|dmG0JoQ zKF)zfNumzJ?Qh|W1Bl7dqN0eAXx&YGKeRaUHu!pK8nFb>>3fjt>6Q;qBPar3eVB&_ zrK~x6Wgq5}LMdxDstdiR=hOx1%e6V`)b~5JD0NMf=_uBJX!*&>lZeX;jM0T)jZ_LY zEJjIZ4uh1v$@@{dlGDJ%Wvwh^K=)aky3asgz{=*jiz(&+iDj;h0qM*|ve`E*suN2{ zNctCUYp)9p+~0X2QMu|6MyRu4VPx^_3yBI8hCrSj;+=o9qQV2uiS+fT?!8-4+MdH8 zA8#d5DxRKq(vYA*X|21jY|UfM(to#`ez8G0?w@g^L<*r zWOaUcURH1U-stTbO?>?i+}a|7gOP9@c_mvG!j>JH1u=@YB|;^memjPFtR0*}3LB6$ zG22-sEFg(x?Qp0v(?4Fm=4E==rokyKLm@`BiA5Mk(kUI0Z%P;Ow?Vz|g4 zDyFV~DEZ7_&xI8JG02I*BIBnhaZRI0qX&M`6uw{GaAL5i2x=r)CndNSR-9_3KQM-G zD7zKq4C3?oz#?5$K(NXu-Sa45QQ=b(CW+_|Tg3r`SN2lQ-NaZ?@zY4G&Lonr&NeYp zRP;0wDSZH(Sl!CRB`kfoPo8~nl#REN_vsaLf++dQVXT09`y&8F zNmsIv2|!x_m8siU55=PS*Tvyzrgnd`c-{SdajddMi@akzxyycCZu9kv{?yN9@in`S z_l?qh1jZ)Yk%fymYSzrccin38CVxTc%HW9UQ9^2NfxW=!5D}3$bpk?j)g=5EwB3me;ojiK9iRu%~47A&JtbxH#+C zEz5L6C`D8p#Y*+P2M_77&e!Qa-Q}wzw(Wz{K;-|&+_m<$ZEV}WBAid{2TnLI&al7* z)b{iM#YKytJs$&H&=hSkmMDXi;<&&5?xEy(hBHG+TM;dwY0$)QwLGu=SbHtwCgQKB zjP$k!P@RGG3AZk4dW;i*7III$XzN}VC{oWy(m|D?x9~PHYayR!XJE`Vh#3g2v6TNf z%NR>CDeYYhTesb;=a2Qm%%rq+SK}CIC_O|fCDQtp63@lTZUHDNe~0ThXf7F6q;+u8k>K&VNKwiA+dboi$$joK^cnQ#x8DgU zDszV?GYz;-MB9}o%Z;fd*Am{I%rQ$@%%30c>$bv%5hyXlV<7!E$5qG9NIVF>8c~*w4ktM z3Xg$xh%#xKz~@PH>YEp@>xGfZ+ZSUl&=)`nAp+XeXbJ`biBm{W@h#lD;Bam1ntdVO z?}Zp8B@OE<^y!v3&V!Rj`#Y21MF}Bl!dO5-B8zA(pU&&2$pqV)qvR0HA}bnXq6Xbw zqZQSOmzblJ5dp2D{*?t85T{|IYB#os2T_wiMhYFJSsF6OOoJ?3``16* z=R4xSesbH#INWA=nrP{`3x2NG_p7?u&bud*=C&1%$jEV$iE*&OvE~uGc{w3e>^LY5 zK;2W2kD2*KLo3CMA~$3NDR(OtFN>mSo;Ry|e7Tt8R1>KpddRET50}x9%le3|tIM?( zNv_PsV78H0e_)>=ZoIF{{efMrN*q{JMTF({v&dYCfDizBH}FLOaWgw6itvJnZ*PoW6L+hM7DBhC zc=c_Il!(-XhE>rcbfCD!%A{a%Q#=~-aj!Dovt+{4gR#Q+v{+HG5+#`q1jG6u)Z|~j zH?xnwn|=oC;ht0*ABi8}A~8NBwkp-{2CNzOF!p;@xofLrQ8iz18q*vl4cSkA_$DO# z;81(Zd!mpnr!o=36nPxHW%19OE@JcY)@Vm`0XRw$@d#Y>XxbEbQN1leJkym|sf9qD z(WzHB^{C0J#vG^mcplEvJ)y1(6;+dACa^d|rgv=iaM**E8Rvp~^_Xo@Zt%hx93}l| z`p+t;LvTW^%@KZdA>41ER2WGEbEJC(quh^!&sof?Aw>leXCh_##4^M+fuceP z#tcU!0`%y-ox|pGfc~I4{c$F!aaM91;(Ms~byIiCRozri?Pjqn&4@56j6exMYGqc} z&s#-=!Zy5s?TpUh0LipB3DU|DqunE3ZQA0lSfi*S93}qm-)x4P1_E;&x)n{cY zks6*Wo!eEHZxO@%u6QYnw!&>=@pOF8DH%@t9S4wjf5*y90xwULm*&gnj`s-mlc z6zcvuE{msa^%YxWL#bUFq%`Om8kY9wj+%<&kYoY&8`Jbez3XBLYN{BD{0adx%mmE)Qk z83}mC^N4ckPzcDWtJybGmd@ZBPE_g?B9`0j(@&p1eERVG{7fEKRo#@UqJ4au;raC8 zeAuY=Mo$^>_p^uyuetl#3Y87;eevxTx->0o2p4mzyn^C|Cl}S>2qC2gDGR!{4YGjP zEv%JMXx7PJKmYohg|e;7$9a2qS;Z8kT?%Qs8aiRoIKgXBKuldCo4u2{>Evo6Q(^PO zt1rd8da6tF$#6|{lw>JfPF#x6pb`!8{@F?Ws_WC(I8w7z6Ds}E3r|=Y3=*9)YTv`o z3FYuTG^2^qxpzVzss=*g@&a-MQn)lH(hvM!d+2Cx1gw9eGLdlO{Ak-2RP)Vldsmc? zuSkpYfuby+LL0bmY=lWoC$a_p{Pf}H>+M}s7?BdneR9u%Er7Qx)>Ol*s*=z=QU`0g zysL_GiG5;FBBnYcI+LLZ9Tu!Kom3%JsV1Cp!ZPQOJ{8;fy4tSl`wBifdOVV&luVDU z>9~oC>&G|UlA;Kv@S3vRA4bysa~d)$bHfJ5i+QqhiX%u+l8cZ7khyyO^!&v5=-b$D zxoNgVX-`Nxwrty7*=?E&KqEy?1<8jAYabMb`&0vw)A;2CQ6c2~u#>e{CjGjt+O~LF z6~?#=h4g(xh{*y7l-Oym0A@fzL_}4VZ(&7Iqs$rPpu;J3`kJ5LDpI5%nHb(o^lk8U z%m(PaU?Pn%Q$5sOlW$zv@n(ke)C`&#@Lf!f3Mri3rdqu;&HTC8Jr!k9wB~6ouzuqS2z|dJfs$_N9B;JR(cOD3wzKmIqondn?<337w79 zj-e*Ph>DyzQJjY!oAA84GprsX_g@nvvi71ypcwqBnsI9jiR#v5MEl<8GLn?LEmj?! zUuN(f;J_y`cY4Wvk7mBDigmIs9%@`u3MFDnQ%C7yFGVx^r6?BF zrw@X&L`#)u<;+ukzB7M4?{=$p({-d;?9PXb36XL^qzXEc#H?jbmN7Dfhy#Mz{ib~_ zt`9F>?etBatM_eDk96YH$ul5eb`)3UPGyy=8~j)p)fC!NW)o<(_Us# zZFmi*mvfP1JhM+PWa+S+n`YOps(V~52BmH~f|EwZ1s&}WIKDEveIr=gT_a3CXTC0w zS2M~gUXn})#uxGfVPI6R_I+TYh%RTsyp09LmYDK@1z#RvfDGt{P9KuEfxb>Mn!%6K zA6Q-+o@KqbNUD{iq*~8~OXHKSQ^UnpUe1DhDnsJ>a8d0XO}GvV`~*V?H$slOLNRK1 zX%H`JWz#{7Yu$1UK)JerZHW@5Rorj~LPaK1E0ul(aWeA-U}iZ@*#1ZJ#(Y^e^T$nl ze-8mf)jqX#hs=9W61Cb8DE+p&?04~5WIUTdpx_&5E)&iiL$_kFt{Y41vMicnftymn ziPQ$b@;KO&M93z9iYmU0K&8}&dfIU{U{$UXkxP0dut*wAd|mZVVw@Y|C>QBz(W1&R z=b_a%0u?oXltZ+a`{`VkgbmyVu^TY)OeAeGx7BWylhad zh!TM&#)?$1^|AJ6m+jkj1FXsw`*HR%bvYx~2aJ+PIdd~JH_Uiv#3+%Joba4_fYo8P zW2k|1aw;?dT-0RuINagkrBSdGpI&5S6~P+R`?;Nm$b6FT1Gl%bFpNH5W8+jw$m@ee zMpfs4l`*K3uPid88auS;GTa1kQ4KC>hEQVTO1B(Q36yTFSzem^QHDNnj^#*1^}d@K z8B>j*^($1jb59`yDjzLIT^tw{%xwhIhPF<=~yTR3%XQwn`J43E!h$y;`l_ z=;1}F+Xlh1H?TvN$qn7iC~;ezLKMjc&FemDX6cOjamFoOR;aitzP@=V(zux@5~t;R z1ntdcyC@}J*vly$jt{VYd_W(oxxVk(BAb7sXm59IQLOASv=Cw3@V$(a_8rB`Z~0!v zsr*u-2(Fx6AqF~KU19+=ALRdfl=TZ5pFY zjzfzoQz=3@9Yh%7z%atgohh0TnQD?Mr{dZJ?#fMDCEI0f8 zUC$&lqY{p2&~N>W<^1C>$;Y<`6bBbI&m|?1fe{#W7`YsizhZ*eVvFw7+V$aLbqMuv zCjOhWK|qoEX5gZPj7Q-HN)ZEtJ4WIT5Z4Ec8emHW;QQqRymL(ujQ}Qc(Mn zTCIz=TNbO;{QmA9cSoUgjI|;n^H(*CbnV9MH;FSQ4cEDVTqe($J*C%`%V${C$Euyb ztjmH_Uy7#tQmoUu?)QTnv+_IHif1CosMv{*~JV zHdTi_x>$Q_mTM2P?2E%0I_}RP;pdEG+PRI5EJxLpbyIJP&U`u?P+T0P2oETfsD$@E z-eWJVy?6BhCB&|TOKm4{3pkvMm-2D`RKhKcI-jVnl_Ht9l>GrUu|xpjiLxBO{`~Q; z-)H-WbQlqr#Zz13WjO>&yx9O1VW2t~G@Tas8#|ibAVYa0;g`Zh$u;XYc8jCeCPR`O zgRoyak&^3amnQWj| zJN2v@O#_xe_@Gi-RQ~g33GsqKT6J5zBbY!*H>->Y7NE-K5mkc`muEXTG_J>)Hft+A zJId~{XwV)l0wvqLmy+}rR37G*{CCvGXhBS!PL1Sd4jG^O?+ zuO+I^dnUr@bu$4zlvr0rU|0FI1lG%l_!ZvF!uM9XA6Dxbg?K7eL`tUz+_jsof|#d( z9ISb`tM690hXbc^YFz2U-UcT~BnmqX^MnIAgnEiQ0!I+ zRkf;KE+cE8luV5+9UC^*_Qtj+#XoVf21~O~AB>(U&m9l>-wohjcK_b}g|q)t74_5+aY} zGkjGy-*u#D*DqvUug=Gc3XBxVSs(-yk)<7|bG=>3-k~*$+JYxCm+4p6VewGDoj=#B zH7x9Q)0necZR@gJ?e1{vj1neeB-b?9kx|FZb*LV&%N$dAYJ4RXB!Nz4_pt|BHRbaK zjFdva9h=!UIy?0d>y(7`>` z3&krFRoJbjKZ^Eo{@=F#+i+fg-4x{#dncnbPT>iXSwL(ckMz}U#oSk*q%eEhYZ_~u zhKQiTeuXG|BZeMMtZhibQx54=YLxN4c%>o2>>Afvj9aDW;0A&c0Yw!Oqopy3|h|AAW}k$Yw9Z{4LJ zsCzV*+wId&pFVv0U?@3tyJ^-%)4jk)f@s0u`}D#30i5*3XZ|=)196OKL1QWXQALF@ z`lx+^;j_=nRkiLm4aPx9poA|CKZ!yDO;ql|!DMtZ{rDfT$2D4AA^@f;q?3ONgVZpNH@rmr$Z4EQ87Tz8hD`r!9i)PVQ&-3lFt-9rAwb++d z>IUV8Byqx(ili(!ZeVC-p$ehfxyguQCFvGda!zMF&1WjlY_@Axz~V0IZockNJt~Qk ztn6>1U@K$actp$mX=%j9j25J{7q?Ge9ykA7=pQ3dik0S85<`DBOXUICrTX*JhoAp- zrRt!>iB=LFc%hH*EEJ$*fz+SKz~l#j0DRZybbY!!ivEadW<25H;Qj75xQD2?Hs;z>rO zy;l!oZ3ToB0AROgK_EjWlo+MX&8`jd@q>ah4p<%m%Z>4*i4R$3$A-(zQ?)4Id96x( zr(B{`C;=uUTYeb)TJJql5gSDN7SunA?RNGD{I9CULb`@OCF}lA=gazGX(E42iA-Wd zC{q`u?8~6Rx}SSIod(4r<9UVozYrGHv;P*=L)F?3iuvPh|EKtpuS982=A5KrcuIQ- zy28Ii&o5NBhXS;4CXmq?OJZ3`g4 z_WfM1*F_6(FF3e3DaMrKSsqO2@(@yf6G)LdjB+nqH9WE5fj&B5eJkfi9w;$h6)lQK zn!yeZuR^=E{+f1 z+S`^*0T5M#fXgx$e&id=#0>*0PMyr0o7W73amfu>yDGZZ(xmiZwYe*BP&ulB5r-NM z^4(h~vR$tT67!Dc8Ob2E@<8ShRUKCVz>e5y=;b9@gyO)WK-~cUx=>M;5CD}*>0#BUDfPvblCFIt zAtMMy1B$--PzCiVq0Wm#T!n{hLbRyP1te|h@VL@Ai*R@^#Yd-fnlOkX;Jevz1O)cw zuA7%dyIIvuVWyK;7qlKx(u6_G)?GZRK*Qe`FCvCYy~T~SEk+)l!Eh&K3D0x$%LaQW z1$TFCx7qRM6{Sw5ALl>5>CYk_c7BQyGx#S`hd4E8Vh~0EWQeDo z>i(+gDFBC}KDz3HlIf$S84)BI?v?XBZyFnG=7dZG767M7mYOHaIlPB^7|@o*%4oVZ zHOjn1qSX41p*?bVwZpv2T^U@!%N4&KUKIP`2;O6Dn*kYrO1L;CX%sG>r9Lru5L7q= zoKs>&(IG~$9@qbfO1xbgELOKKr+)D}?*|)03p=)thu73q;i4)rM&fwbrRu4q`)NOX z3-YRLQiEh3=YdYkn?Jn9MvXuX*HT>ilwRw2I!&lG$EV||H|EW8>9@lN{ z4F46QS9_z7Dt?F`y>glaIp?(LMG~|q&>LCS*otMzmF$@~zrLh2Gn=GHTV5V}oFE4~ znAr#LYf9u=i|=|?_CLS1B}^=|yC$Wf=lBXkw6>E{xm%T>7)+z3Uw$ zmO)}E$<>zZwi(g>vV)(USZTR^453^_jD+ZlPGXfO>eoh%D^`?&re~3ux#iQr7%{;Y zZN?MGCdMKWafTwAFw+6PDW1!Ez9;z`-vr_S0ij0KVkX=zoxYF27@s)S7HsvF|C5>S zD3wyFM_{8wFs@QQeZ9j;`qX4BlTgb&eZDt7RfhlPJ~I4niDH#C~10 z#h)LsC&AF8A{M$SU|dP`H`d#ZmmrRaBc{TXBw{=<%N0dlmAkI^HlFetxgbubS}^Vz zl_2}Dc-%B+gL*8>OKeUNU}|kS!4V_G)SIufW!@aiqMh%uS}%2eR9^uwfCBM4r5bvim92z4``RqUQ+26|5`XxKgQZoDTcFKXyz0^0$gv)B34z;wZQufR(&j0scFxEr2*l6bCzAZK{YMG5Px?1oO*vkSV zT`SFB<_?OyXof2Oy$M0`^Na3(c1sr3Kvs}Jj zX}ecO4=EgSz0i+T8Q*cgmfZg$D-LVDWHBEjo%(+s*F&|99J*!E7-BqCgGZZhHS+P-f^ z&skL!$EUKWmT{h4t`{^A>O#GfSxNU03`!a=6dc^0aD4X#23`D$7$eWb;!vkJvY%&5 zv2}kWaq?Ad^eRiC$W^>8mwLw<@YC?gSSg4%*w3c%j0p`T$0rmg>RCzeE*dyuiF=!= z^^tUu=1*8 zN4F_hAp8|mqH-*TW=%W$LJ3aE;0Q@_^g_5Y*Tj(&XkR{}~H zRRrc8#vZUgOtu5i1b<}`so<85E-RXCw$83XL@*H6P=}kodnlo zWd_0-a+OMW+IC;lU@`W}nr7M143L{C1Wmz6c`UGZilf(`#KU+5V%<0ql&I%bVjDS{ zt@i8UrD?0>{0O}!W*~;4&|pe8?7)2~hfNqgDlDN^MMH;{LT~lf_MES?wko>Sx+t!2 z05A~5P=m8ZJ%H~mD87xEITsM7!_H>6Q1x{&%4U*ab7lXL{n736IcZfo*mlbWDBouw zl%Z5fk3i$#N(R(A`F{9<_?@r5C$ZXI*V)Ua8@TGZI##lLuRpo*9ZdcE7k($e@QZNi z15o(~pt#c`g5SxPl#{PB?Xbki@`3zRR@DzG9_hN~piW!>eTspwhPnkbby@r;syz;v zDb&L(uuyNcjF=R*-LQPMrKx>vQDoh|c~bvX0P)ETL^wPl**k|Tu}O{=$ng^-gD?w9 zvUE*c{Xwkq36J&A5*&h|+)FT!wcr!{9$Sq@X@mrS#zPIH7cnY)p_bnPPpkyW9&VbL zp|fCmFt19V2(ntRe$Vnv*VOZ>+^P&p{ax6e1so18uv6nodml((@|Z(bv#(dIM>=H@ zmMlsIHr=$psL%96*%tY}Y3Kh|w)y&{X_o(?Ql##;tMUdA9Z?VdA!wX8@@Zq3gGthN z^{Omp|DM&$tjeDDhWW8u~x)XuyK0PS2;X~F|x56 z!Fy8HlfP2!C^C!YqItQ||nn2)d1 zhCJ}>XfB)4dq1f#XM>D=jc0zav|WFvpCS`P5=2PtzMk;~6VcM4_mnYRTjmj^R#9@7 z9jZm!=zVv-1>N&A5K1tlGL+SSzDl5*fv2t^{KQ&1y$v}0e%^B62m`?brFuIP&zLzG z7!qi6$qboRpMJ`?&=+>2uxO`Zg+iM4ClS#%5i~WU-fh+%=iU04)%8Z{sEZCXRhoeyf)d9p^>{SYX&L}S zPHnpSt!Ufh?E5NfH-^}Ku77~$-C?;b>Z+_a;0qHNM-XY$@^}{UKuz)46>N~8sn_fw z)CD)mh;A_(*^YK)t3IRtaJ%ckwG0Fk)Lo*ZF*%0A*S)-*ZdeeMsGti+R9Kj&s;O6t z>iMMObXA~4Jp%@7dIOJ`-^ymuLdStOxMlxjf%#fK1#3E{6X|>(+ zZeHhQ20BwAbi}?z5c{K~q0?gAtZqKAVNfl{JmQ>0Dqu1n*Tv#+?79N%IRFt7b#PC- z!9DVNrJM^}6j(=r^!!g5^`y~n691OfoqA-mt?rEjM)x3Ypl;Ll*Hf?;1nJ1M*i=@L z{|nJQu7cu-W6Kb=D>p@cMFTzq;Q|GT>1Z0d5iFdl8(Ho5w#F1Ijp~V&*vh^8vvZ~X zQd=&er9c=rPaOxIkVppF{p{70aro6#X;DNHJ&Dhbc(dwt^v@Lw3S;IaEFQtAPV~7s zb3{TW`=7E!TdMRkoBb4aCzZbxw)CLn%7j==iX1yUat3kF`ZUC`XZ9# z>x`(^9pThLzO+rg(Q~wS#lGCDG_7q8AmlIu!SaM!A;HE6>YEYw-2)K|!u z+MGWE|QlAm6a|JFr9#k14>nN8}nDgu0!yq!A#JVLSR8l$J>0=cb zEP!;Xw?dP5KLDK4wswMJMHrFvEYlA{p#NySq2vTL4nqeFMBo>iI(sSko6d3_i0 z*sS$hZt#Ts;S<(EjPZ1!WizYMwA-sC-Bjvyg|ki6Nd_!&r{gyGU_-4FINA3z*z!^9 zI=4>YQf_%V^ln`58y)qRou1$g}(QaNymVZ{ig7LOj~_d4jQc{wgE+uE6Ls1xR7(W~l1S?G?u z@v2%``iW}q4P}DROG(U`9ACfR9bfyY+l`XuCtX*9Xs` zExNLX83I83L!IpiFDcu9{7emt8DZ=>tlU>u}jGK!p6O_YHk(hLMa)N6{zmpFP&y%0pFGu)KutZ0nY=8tq6F1mPAUoI6^srd$6eXlX9b=7s6GYv_JmEt;enuzI( zoniKco#OVFt_K}y>G~qDDg|OZsso6){iHfF2$ajskctG9>a!;$G9o-RD>a+v?66vA zwaUEYH4iVSa3NzkB0A#!Uee1mm>Nm_Gn#$D3H>_bDx^YGn)zNkTubg@{jwm8p+qqw z?zpRA(%_VlNa27{on9QP-JKKjC0%CEg$@|&rUngEVIXATr6S#sDSYE`GnpXXgpw)U z-kP_mkscJdRV{YxqcKkJAroGbaCTd)j}?@9S;CXeN>rEEq@KoN)lc)RD~?y@uOR-Q z-f5{zoKQ+hfFm>Q)l{49Ol`I^XR}qONLf``yJU2}?O=hf08y`0oJ(D(JL*;XsaF%X zpj+w$RU=3&BynC(($`4?+$Ssiv))cCo>!p;PWA9qY#ElyKmTkH9ul|17Ivh7CPs#J zdVO}&-_L;3U;eI?&VOrEtgy|%h#vvD%;9?Gv}@5CDokE9DzShANSF^V#g?(>hpeuT zv!C_Y6KXR8<)p7pP6BDIR10%$^_c#sQx;k61nWiDjRT*SP zDA@@DpQj)?=n0X5A?ZO7h{MHD5_Djlr<*lBdB=u2czvacM-e zOC3Y6E|>HEyO2QuGdaUt%y43vob@E1Axb!O*%epFFx=^dQYY>_H&zOCxm=`l@-BO0 ztuQmNr&8aiY5FxCSL$u8A`ZW&5{nsE|M|hidJck`YR~hieZ0@p67NJR*SKV;G|v>y zk{Q7?;)!*&xN3{ld{Y(b+|=!0aN8&c;Y?46W&V;8x2~H)O{%w73%YCa84delXOjB- z02lOssmxC>5v9`V!&o$jYFV@@1Sa#cZEE%I!qkEaNC}OZXKi^u*WsM4(t41GU)`-> z&q3hQ{@RIn`;h&G2UD$;u^Cz!W>jEG(TG6%$G&LWtgD-sfuRl)3bVCbDAexUJf$^K zVx!xs1;tG`M$)w!_FL4@9yT)ZO!M98HxfPQWEy@+{)I%LGaQ`b=oJab>`ejB`jR>t4#Zjzth*kR$wUZq7eily;S1^ zJh349Xh%6(PBkr!O!) z`n;b3XRYoBO9ob#E|Wa@?Y)m?P{^bQ&hl}{&jOv;D5O{#a;eG~Qj|tmFf(cGcjZHu znTQrh42*z?mJ?<=4-(mi(wL94RnfnxnT~@Pu|mWtbuW-l1Wyj{Eo5-kW6udCoMFqe zf7t0_%RE2q_bNdzmaDg(F~~s#BgF>vve!fo{@&K=kMTJ050(tNpi1L}yCu{9Y4(?3 zoU@mnASf`dIXrrdx@F;iZ&X&B)S@~R-3FGbgCMzHxk*^AGjGI}o7_<>DA3?>nt0uI z{yX#J-8nmCv6dg!hMiy}hn_&eEPQ*>7*k@Q{2C4e}g(f{S zbGK@9?GRO`ZM-d)c>{Z4VWkNgOSfzJ{e?X%GgO-RB9NXS!bC(l9o0;AWq4J#z|{mb z7U5VXd>lfh0UA*fll~v`ZMCKY-A5}39xIbLVPt$omj*!~;Z|j5F3b&;LPwS}Z;J8D+tAqix&3@mr|KOlt<}wb9Qvxqb>D1@wkz7_ zGB4)qr(Fx4%gsUbSQQ=#Mn|*fH0SxsEIn}7+6yeMzG?-rV}<&J(xorq{*3WA)Z1cH zt8h9>Zf?K8pb>N;PJDj$G%%6NDHbCOuw}Wngj(B_M=Z6b?REPsKhC>NQFI`nAqOF2 zrHoaOKiZmfR^xTw*()oP@Vb6U5&k+;0bG=_@qE*DxmrJ!&sTt5IG7%*rSvrQ(%uZ6=YNv)?MXZpV}q0!kT`p>>LY>GE;Zg4(HMEK_&TCGMxgc{A9@Q44IQlAby#e}yom zBX_^GTiM%{T_+7>0(!>du2L$OS7ibqj<9}hi3<|@kkeo*i5 z7wSC>ll5;zmQJHNrO(Q3uI#OJ!o0zk>3o0(7lsMGbUh#7!3DyBFBEF`Q4uqycOmAt zQ3(r(P)y{Qi6wfD-D5tsQ1s3vIv?V(g@S-D68hQcb89>JGs&3=4zqc<-U#t9&k!Jk8)_B;mx&z z;)e^hx(~8h!e;jr3uXLXB9=VFvVx+BzzZv*g!l%RKhACpI$|$W`#8HXi1>S{+=tnX zLFiwu-F7akQbfr+mv%z1J{>O?;Q zLqxxP_x+EC%C^im^L8;TVO4>6b{qu4)iW!ZJ7Q{Jj(g_>m=~oX&Rd!YoF<%F17-7d z)>dUPSAW)ZQEd;^zU=kFw1ONRC?=_=*Bte8A5O#MtueuO)(S%62G$h^*3~Qxa?2Zf zZ?!-(EKfZ}rT#Y2v$DwCc+F4=S+3t#capG&a~_+0QKW3XtP7YO3B<$Ipakae<%htN zHp>s&401!Hq;jSw(5I;d%wLpMRTWvjo_C9URW%Ex0HhTZH((qmE^d985P+|PW+lTv zhS1-Ot}FBGD%%DSfQw@0VaoHqayAw@@%+>?Xq3Xpk@@3tsb0~an?tR%)IVqSk8qD9 z2!QLA+qcjR0NgRVdLoPb4tk*%7rx~c{ZJ+LuW0lPo4uNriyNam>xCLRM)2QZ`1Lj6 z;63ERt}!l?`$&&7>^|d^Uf=8cIFB>zUW3MX94q$4HQ#aT^p%^ZExof`=_5W)C+RM zYQ1vY7x&gGcBXAA)MC@iO-MwA1Z?L#!uZtFbExYp&ED*xS!}+_s-gywR|SZu%UR6RQ2)6HsOuCM*=MdRs37Ih z+xMR&{(96jtiV0g0w*;k%pC*%-fnXqOJvA(I?)rXVhj;6VZ|8F`|eQB_sy!xOmWzL)3b5Yf;zEP7@vAj0#t3m z0UVJP6I=DvNwA1Y{kGd@SCjb#h_fq@9x)l3x^Qk{u%XpFYf>bsR9mkFO=!E#VNq1@ z0b2qD*wr;-LdFLS4Nwyt=28eP#gQh3>6{Lmi}`jf`P3HK26nE1$ht_SC(;uO%7AIj z9@K6X*^>LHgcX}EQ+dHGyc;Tom6<+H>75o7R$jVH=85Xzom9fE=sxP@ypzcPr|#Nz zBR7)luL%3FXg`q73zM1jVz9Mi12YD87K?EM`(j|huA)?IRgqeH z4L+Qp8@rtbIgBM6BB2TAL_Y(FO%$k%n)M*-@sb-{EPJd_GQftIMFCr)81aKR#4O^- zMuj7Olll@VlnC&3K1?yHzzkqfQhrb>f5`kMkbP?(s;(SF%CE}fQ4+vLS~LTW-z+w7 z^HIQ}YDSPUJJYFt!s&H>^b>={s$=2ts}M8MvcO<(p`KSxob$4Y}O0P!6; z=t)fgcDrwu_0>|13MGA<7ip0LPgC(+JPKquT{U3p)*39VpBRxp+%QHHk%7rXqW`@? zNf#=V@bRTc*$2Rh>bU8gfcbtPhujdT-pAP=_65s^p3WpFQJprO>jVPqhZ8A`rjhKn z0~+%s)i9?DCaS+ijo@*3@TzAEDk^-Kb}$PIWHwJMk$T6B`h4J{e5GrBNIQMKw9VBg zE>8GZzdDW3VTd*|J#{VGa(}n)cjfhHapO~f$LtZK1kdJMIyT93n#?Mc^07{ohS}!u zl7Zn~ukN<1{wS}@2vKs!dKDAmXM`g|ICB0vam}ONc!eSf6I{QKsQo_QmfdpSFP3H3 zZtAAob^5pQ%6$qYer%Zhg|Ab1=!-*`oq}j=BxNEoJB1QFz8qt;RpE)LzP((mLg^eI zML6820lUEh=nQ1c5kyo&4TeaGxnfQX6FJLth7jWVX<15z$HN&r`@?9tPxw7tn*8es6)e-S34B6%JWr#{xm+ZLQVB1JEm3`6eXE;A)vWe9HCm4I zn)*H|@2YLppoXOsR_0gafZxW$va( zxnPn?;f&@^f*X}XXxtK*W0f%#Yd6?VC-r@nI4X-U(ayq*cpSdDh;1g{V~OK*fU}g- z@EP#z8xa;I>>G){f1pvi!1^r9Na&RjZFIQiX>PihzRPKbk_na~<;q{*BfXHHah!=X zW+jnRk}Jsz5$Fs&tn1C@2`OEqP#VD?$|FSnqjrb0phQjJM`EcW7HayU0m_kqENO4hELN^^7jm`RKfD_J z3_pJLN4mV-{`>8|ugbwa{4c{F_}>xbzn0sFe;a<|*I)iZjhWHwC%b!mYMN@{{iPRw zEtG(-{#xN&&ynlRo7;+w<-O_G%A8S|xB6O03(g|vkVcp(hK8OV)csuXL8!M~UCs&o zR^JPiJh4_0)KA9`H1U2I)pZYB(`?o)C^fn&l)>(&-eL_f7S<*sZ&&U$>iQ zLV4YwBoh@*blIqrQBd;!O1`nd%!PR^QRPSXw(k1fWBIL0hVvK)7uN{X%Nel#j0w+u ztN^2i?1oW7P!kjO!F2Yo6W`Q7nWsmL8o1LjF5oVaJT(N8aaUW=fy_vLBW0m~v0!B2 zvFggYH*>#V$_|GW#g@|1r9L+-8|tmh4uEHCkLo1)?>v&CELXNehl6Qhds1YN%L^%wQQ0P+6pHaArz1F<6|k_Jv^2 zy@RI4ic6<14J`X0kwwv{NSZ6Zfy>PJA*_SrJoZ$Y+uC#X=~U1n$rLrR>48oBZQoa2 zUE!XzC^c~@Qw}gzc|;8+%A$AkiRmz+N@yxA2=QLCVxZ;1vTGJd9xHJeh+O7LkvYYj zH-Lz=gy+m(tYU~GSjRcfMB892xDF%B+1p}7&fH1jkB*8#_#W)x1j1BKg5;(Q(=Aw3 zM^YajO5|rF^}IOpBeePHfT9|a%82@eA=NhuNOL^fbY!~SiPC5?yVG}(5yKb+NQz;e zL)%f9lWb6wZn%aii0{lhz&z&=qH!YQbTCofQT@_l1*Cd7@{j#!dfm}H3Ug5PrzFXR zu!kT1UN7(U5BIsNf8OlBEXo$wH%DoO%OYi&ga$p}{J;-sYNPe9PczTLxv&dLcV+jq z=pXCtZQJ$RdQ;)5g(#hHoeB}|tCjL0O#nMbcEYC|76|#584g^OIJn-TD$hNPV~OFM z12>+*Pj=vCxEl+EKZ^Jlc8xqVw-MI zl{X)TU_W%z0;K_N@KUgW9qGMUV4V_vF(XiH>n#rSWa}-i&^ayG0ww)@1T1X-c|osY zO03vA5%G_uu?+>DzHVTNQ?y4mp-|^jfs%!e^<-Eqx&J^tnF1vc9Yf5&3&hyYOlZh# z*rO6^%($C3CR#NQTzBf$N`VRd>~L*LI8D-G14(4PI2F zK&mW5fTJ7;_W|$p-{!}Qb@SqYpE`e5$iY&!&Vqb3Vx08yWr)wTYn}%%PKNnA4lz=X znWhE6mKKBN9%Kr89^wJwP1|gqEWBUWcby^7cX%6v0wu?MDatb!a?{=n|9JB}_&Hr@ zky<)=U{Ghh4^E7;zcTc~DwX6}qB4<4x7+iz-Y%-mFtvY0B?G0+90NOMRv#EF%FQbR zwuq1|KMYuuHZxC&0Equ0BEX@Py?1>=fdy4bqMsOflIP0qZml-Y5EoD7x@~blG5J&s zX#UKA_q~meI1bJQ6D2gLVM+z=)X1yA;WXI|5!a$^LY$c7=?G46I>+ndxvh3F6HwHA zI!lY3g_rB7_XUs*-DjTD$#Zohb=IU8c_LKq^x3=WZgIEKKi}F&;$Lwdp;U?u+)RXU zWuy)5jUC2viRrI za8Y@LjtK{vUFzAN8a$eO$Foxmhii<(L0U@7iydV?-5WG)4jF9ErhF z=qijwrV?35n=n&0cXhQ`uFGD(Svf9}s0z%Wx*coaom{r@g2Z$#${nuR7TXSr4Uz6E+6SV*xB6yA)){#w86g&j1?7LI#$zrFZ1p!FjbeoBWo|wxIFSFyHZEg;$6H zL7!7MfA3w4>Uu$!F?rRY_7e}6?-x~qo#`IVku%at0IDLR4$wsuM~`$s^F-;LoV!x2 ztFl>C%T4{zSJ%SD(UN7FgDx1x-<*Xz*(rCt(jCX0Y;R?n>N6{4g-8`uPHE@mz*=-= zz1pp-Mk8M1AfqxZV_WFk)*m$5PSmlS08^(!B9wkH5&f4CTgdshUw&;?ZQFhB>feUJ z%qwVNC^cu}m+U=>haF5o;<^1kj9HD%wS7_DKBxphUWgZfla1RDiuN|=!i;M9Mamun zW}2N%xOeyOT!>Lstz(G4gD9hlTP!UgdS`6R+P7+rUQ9XFZ)?sH!JLEZYju0O&^WvD zw%#TC9yeuxQa3hGN3#W}2oER^1{38`wFjC^3l~?@(g6XQp3*QBXlUwrgluCU(|;?w zraF;q{3D;XS@(- zmL55ZrM|(q-uIl?v3=#(clDRezUuFvaBz`4?1BNz$2_8S7Qp521{cYn;+bz=d*~0I zgiD>PXI{8S29?Zds8BQN4V|Q-Fnja5(k%w9DD+*+982OiLyK$>5}Aj$PfYmY`n9Z4 z>KE=q+1+3B@IxsYE17Z*&{}2Wo$FH>;tTmx!N?Ccxj6zd0WM|p;$7-XXlHEl%&mm1 zTA}ofLEz*?lKiA!+>v&f#+}Ro8>w{6Qw}U{F=#bHGY7WkW#Qx-j`pu0H;kEI&a}+y zAo7dgRCzg0Y+l6`WPS#>ygvd?Tt|?nj6j+J1lE~)f0(!)AWtR0Pf8#&{?v8=1vic&4?70IMGxm#gJ<>ffc3fkj7rJ|EQPu)zi&C z|9sk3_ZHI6k9E_3*>`uVJyuM$K&c%Y;n)H|8SDKV(ao}8a?|ut`b!ms-T3*hpZ{^F zBKCNks01mF6LhKZ(%>WRvM|)Y{rveQ9YO=e2_BoLI&kL3#xVU9INr_6Ns)5>*XLPb zR}uSN^{}p*#j4tD+cC5_w3x(55`7#2?ou%)%JWU4rJ_kT2$wq24(1Op`hD|S4!@!n zgONWbKxAPCf{)eV@y?ADMNC&|A$^@8>!E(s2tv9wCmS!-7ZFkVSsXgr_sh1clHIyS z!o*rZ1Te`9nB7WMFJ&H~3+5AXD zeBS~vQdo!O-nlfqZWvr?IYMW2-mE%{5L`;@{|x? z%8m`=!(gS~eV4QN;8P)4B8noBLfW3}LqNaOcU9T#)@WHM4Hl(K5&^3s6Sf})Eb2MO zjj1dsK?(X|comnp-^qkj2|-Yzu?2s*7yJw&qLbw5&A8K<_N^ny4a@SIH`kldKrwGQ zBdnu*-rhmN8xT=F^c{nTt9$F51d7cGHBd~II~LJ#-Um?Fv|&2ZD>FqCbH5ZU%{j0` zV=PREp=X1n#8*k03@7IG7E|{cgBd0co{X7$?9L(wrGcXK+H^n(4VxCD*5XOMHgYM@ zU;gv+^+1t&ZQ%CIBaY?g>$Od`a8ZVS%)CsYv441S*yU>F4llrQ#GpE}%(7I!2^?{i zs^8t#)n;W3F|IjrQG)sxVkN0lOX87`P7M|1>lcM;MCQdu4J%UQwn&MDh)ZzM;fTns zTTPNVNhH;O4V5<7UroyU_xf)An|`Wx<>#(O7}#j6IH_BM6{5C`Si|(*d7;|OmKl+v zwCPk@udHbDviieDq&Sg22SUsc4l~l zp_R!(Fe*o`+krRR?U&VJTlc%FyW3-EcN!)tiC`(G3UY`WDWv{ftU8iJ%$5J*WM3}? zO5;kB^8rQGR}4^)o5Vo3H0FylJLHGiprXpZ#sGqbXHt~6bM^^5-AkOKYAY84CuUZ z`kMIEIgz4o)TvTHlz45Vj-;c>PJ0%*63laD3n3WX$`h3jgHaAIXWuOAN|KZ>>aK0JCGO3Q zQam-XuFUUEh@sgJzPZmtT2P}qQKTXlc0lj$7UpNFHV%w~D9`ygRBPpwT z?`=98R-_H?5v-wcj>}DVZqOMQFsf*ur9@_+IyyZks=frXnhPyT+f$j^G|=cDNpv7u z8*IE~IxSQbKV4@IH2O$`pdOK4o)0QY5J9hD0J@g~R~nlSD~g#8UpUXY z@E`SV#Rz#)eVDKe8n7@);bll?!->iv1i->)!}5hC(qjA638#?bggncfk(u(YT0QL+ z1FLu2?sw~NCBkq-BSoYT$0G{y1RVkG_qkP3>XmwzDhlXY46!S)XO|3bCC%1 zU@*gl7L&Q|tIekB`h`ZhEc;#BRJ+U3B6Em~(6TtxVD9TU)NfT+|JgPus5rsOHw`SA z4J&T+pQRa?8k+vvDeGcp=ljAb@^aJpmnxBCvEl{lrfavYUcFyX4S$?EB?OTToi&i* z%F^79X6AL)^2tHsX8u8tMlUKeBJamR&W#W?$0kzBcsR#4@-|K!K<{<@peid6P#On% z{?O^PSW#&aN%K4hEs4P?c=Iyl+X8o(8P{r>V8D7zhOnL?;J;bzc0IT-L3b1U*U)01;GhTYOv6R*D%UPGl1VB_gr*0?x!u&UvCFvorqX zmOYrH-`Hhb!{l`X zC@QE-sqadB#KP%%w5zhIzUn`5-2(unENM#J%uf&xz15Hv;8Y*%^ia&Vgi%_O-z89F zPl__ovWbG#vkw6j)sd2^P(Gn$9RELK!p%t`9H_(b&67+yiVhj2i>_X-w{5d}t#;#1 zC6ub=p6Zkkx(WooGCROte!@icfwps4!N zh1J84P$or5OX`RUsUVeGnw_Du9)FKd3l*6pT?F;Ky2GS6vEq{8CY3P-H|IRc?W1?j zO9m$`sbfmAaNxEWlu=Kfy^c;tIwx2pdFLXq&gmOv{!R=OHEyd?o&hC@@tO&JrG2Sp zr`PC|l`@$Yxl#MeZLqt?@?QUQv)I(THLCD{(v(y(&3tvQgZu8u7izrZt2cjQ-l#>+ z>?TIPTtDh}_`QCSKW&#~T74^<{#&h2DcsqFDlW;C3BOatUc5>}%<5QO^c^rGlcumW z_o9JyLJ`0#kQ$Vc0dPCSxR=s{#Pm9~S+a`DcH;U3*)G)IgpzvhF0N5$9FZURB)xM_1 zipnHd`b>%g%HELVfpaq1NfVz9C(;rv%OEor0zPcqsTy0_m!xoFYQba;6xaO1J&A8R}=l)$C}=Z^~v_Egp5M)b4kidRyb_ zXZmNxP5EU|YA9k3@Ak=SA4e8WGhv(w{Y!FN5cN(2X!=KU!K`)0VBGzl9@_4Hxo&l8 zyl+J2+z_ z1C2>0a<1P19GtcROHDRl9uvO(R1o$<#`I#5&h+1Zm;24asQXq!GxBmz8hz4WT}KN* zFG@sIYf=j`iB0rK^f(bQ`EhNieRMi01V0Hr5+b}=#xk$+6-xS+p)^F@+rt5Jgg(l%oG@((*KC6D zx{eiR7P0mbw{`ire`TCy^KFCLM`kDuQRcMuGSJ@b^c(A=)FCV47I8%xL0G&JSQR^% zT|>$Lc@5K>07lj6Hogp4E;2`V?{N};95A+2e|m6Ln>srm>DcAZF(;um)@a-HWCWHt|Z$z*}jVH_ax0!sWmy5mD!? z#QK)j@4m-Szu!07j*b*9ry9XP7*b_ma9+s><(64MuD9Lf2h3{a9xmu+++IMou;)79 zEp<>IcS(-g!C*MiP(*!vjU37C~SRpmg3J3|$ z(a$vfaIh%pP}g4px(;t^xoC-0PE%VOWrSsP@Rhc^Hs7p^eABMcUW^tlPJUd1=QuXQ z2zq8C3E(VC^^7X*Pgd*Q>%7UU)$5|jm+QCO2!|EjW&yBfk#hVZtW$zTr4EtYUdOKD zJF3M|Vxoo-t@@6Pv~!^Zoq&5{qT%GxPkR;b)aC7&>(}D$Pjueww%ek{lY$vaQuJU4 zJbY<8v_Lk|+jfk%(2TNIU6v-wa6bWF?c8=JaYX36Ub#l;0#ET_C~Z+giDAIith)*N z6zds>XQ*iR&(~bbNR#s6VSb-k>48zB9O;nW^em%tsklxA*oL@1u*ciV{ccP9R|PIb z7AOt&l<33IFpMm7b5}Oxf%s|>-|F=K0EauZ462DzL2cgDyQY}i9IC8r616B7$N>&c zKNdntodX8DW2DGY75MbLIZNH^*NT#pjU^T_TkCsDEHJ9Fbbyq1?NLZ0t=D~tt0*YV z2zL`sDF+WuU3?X7UE%)2$k|y!eFS%(ezQ5*H+WHZxA|8aV$9GE zBQ=|tln70SBt+S%$DQ23?{%MiMo7w(J<&Wd;d7g>p5GwjyG|&v*~~sElnpstI$|Y8 zNy=lV*#|0^w114Q7B5BCeJs3K&i(^u1 z>;YE6;I4fsH&1ypZ|s>xom-T^ETfE={>^l-Cz3E<>)bTaxbcoKgdQa5zGan8`T=x#41ZNE=HVVD=spt$zVXwH@7aJr}+&;S8CXZ?0b+am(^0E5+ z;U-4YLQtZ!Ak4#_)j5(yvCs9Vx>(JA`RD7lc=~vpsD;-EP93rS3&$P)_?h1dCaO0f z2xWa$M{gPORBt$XE2Z}S6@uH6hx#SJ@5RHz+-4DV{!q5bzQNTxIQdyYIJB#M<_dFs zq~qA6Tq&EVWPXy^RXg?~vOue%X>hkNYUxuDTbc}GnjPDv<3Ph5K_0Z#zF4T=k3qcx zDXLzlu2~H(S%I3fXA&&G*!T4NS!z#jMyZ_rYj*e>+ExRS*`NHc*{@Hp&&7Y%FYU5z z{nMQ{HiL3a^2P22+quB0vudJP22xEsnpfXWI9#m@J%0iQu|3I&)sV zI8oVz{Z%t?1Brnq*u7ClusjzMyfn3`ibw=YgEFVwl0}_w7n`DOuPEto+N=?<=BV>H z?vye@-J2RLNenwH8#My6R4XGoSH)i!S(ZtRIx;Iwj$b*4axE`4gVCHmY> zj1%buWT*jcm%*2|CmbS4(5Vo&1B+U4X3i;RNR$y>7B!p)BrLd_e58pVSEWUwwcF)Z zgCwe(eAurR+Z#q{w~hlHHlGr|?n(R?C*ilkiOHNCPC(I!ai@04hD4E`h=z$AU58Uj zik~5;=KOsYp zQ=}cxAf|774M6=CNbkm5g_DL9r!mYlVPe=QbQ)8q*UUzYk61P{HpR?zpnsuWGYg@7sUQH|0aomfPZuW{Sd#s?IONd+s5=1zeO>FSoxJ zUXe1Nrag$iT!*F{cHJ^;2O6oJ*w_PaSWD6ji;t zYqIa}B)U5oT*f(*|1MdYWHL>p(*CgK$>tER#KKz4pSSA=ge3#VNtjY%G|)~vu)a@x zp>gW$7aPy-XFx!mt;oam0Yz1-oxKx;G(v~CgM*979S#|Ah_kES1jyq*znf-L;KZiD z36uiQo4uQs*Sp8--cyuxtLwi=V6@63w{KJ&(a)7!4xDPIsH}arm_=PwEqNlp+kdK= z?;DcW+gGx+|J%h-aoVkvWB}_!Ml!?bDhdr=)GvmK?`I}8iOPaq*Dh1~x!zU(U9NBm zAxhfQRyG;$%c{Lkr%u_EMK53bLy|PJm$+a)$i=SQxMc8~#KINz4NBhAP{Onvo?vq|{&hN!Q z@8HZLQz0;zCc3ry>1XyMGod)l&pxxLB#0BGDAYwcFR}fcd=IC|c_Gvb^1W%|iA{r` zcQd=+cN3cgT?X@9l+%O~n*yagM!Ubqdscm93KWO=$@eTyY!pVxXhb0E%3`zp0GQZr z&?PWG;5qpSsK_)((jf!K{VVdEoX!254k*q~HzO$^IwQ_f17>NU9qZq=PD|BfA`w|I z)88+fg`>9Ct1Eh$3Z+u+gr57S_b@oq(2{LW=-J=X3mG`}Q8JmC2^N@Dy5DG3)`jzU znK%Ep&$ngcZBk>%kSHltr%rb>ExdK@O&|DPRcn?Yz8O$ z(QS77cD>E_<#jVPl&C6GhEQ--{$LM1zVJ07{}uuK+!XWYd|5t}%TDs)3bHy*UR7xl zy`E1^`+IEln*&C<=fwcCY{n?GU*bQ!{(-(VTHN9VC(yQhOj@o47qm zKd$W$r-{~?&vt0`OAt+}E3p2lt2WZ_M)@E~F?e)d)sgz>B-Yh|;qVL<@j9Xk1F%0UV>~L={S;?yP+5 zp$$~o7xms=Mz*wTi`wlWpkSg1ubeQ-L34o!l_UCf`iervzN4w)i81Lw_+Xvat*z=- z+q||}KQie@NvT?}DlY-MnoEjJ#X{2or{zxem<%X2xmU{TE`l$0vtlo(j0FcQnN zUAJahni-SY?-U=M^773lv5Ec_g*i%FG*fN>04^YC*JtYQRrkJCNrF8gaS)|{|6=V~ zHe9%($!Dw|nrrKPwR>6CMe*dm-s{9SIZB|B(QoqH!!Vz?rQ+>kLsP+}=D~u=L*BFx zMRELG(WxR%nNbmz0&MO#vfVHp9?6CSi)?A@ICm>MHI80^kC2WlQaTwf{YRQ$uu%>4iX9Dz|@9&cU9g+&{Hl|F@nm+MValiuy!R+JuZV5@Ef-I$7tMfHNt0M%6&g zx|`C~MgD{YiRz15kXbt1(>#cQ0V`2Kmc&iaEEIvuiH+*t{$Ow1L>x-R0P14zl3{d4 zh|=u46e}a?cmDIz>jB>kD{i?jBV0p!2qHowIG4^eDOA)}pM@&=ofq%+9q)E~IKz^4 zQk=Mzz7d?jB(6^!_?(EM3Y&|Op1c1wAyk1e|&kZs$$+0?fx0x6cs38w-KbEuv?Ff=Eqds3MXo~ zYEPUL7pSfGBTCXwi79Hf8poQR5z`m}ZBm@5!K#z)ppbSQyrmjuzER@nq&QI%)s&69z0Z^=nG`3gd9R670QEWRzR^?XHv0^isKz~fsnz z3-%@gJn2{*(zbMf)P@PeL@kcV7 zvh7%B`PQvqTycI;T8oS^A^=fIeWWOz_)bG^bC21aWXkEu3m@$vv0pSxq$Pqt=`0#f zG-E@QCbD^P!LIcbi>m@9vl!X5K3=(Z2oj}&pqv~vB!UXpXT6>$`}VE&4=hi!B-8dp z91`gF)xXtzwc9&u@^V|C4=uKr0x`^Dy_CT1*iRKakVdd1O`RuhKvr?jN;&WTvstdI zqFfavPyYLYPhwO64<%`G%b6C-GnhFX%VyqXuwP5Imu-)6(8u%h(o zK(z0U-GuuRa{&VQmhh9 zmH|?zag|$nX4X3uN~8$QMJV~_LPQaIBM?m|KYf3P6}kBo!+58M6~!To9#$CT=N?v^ z`pm!Et%Fmai62+6MfCY7QQ|X-sKMet??ie*lxffiV_{CvV^b+duXk+NAdUa2E>_FD z+7%6!mMn0RES$m21rFx$ikRN;H{6R6zTa!c?B6iXG*|g0_HV!ZI{!6a{^(5kUQt;* zN}I%aX0jAAdxgKxF@Kc+q)B9ED;6RAg@WJ8?d*?rQEtlW^2`n;L}JTpZh-A38R?Xa zJ(j&4TJ7M;BooXpu>;YWb-A#m*}icVC?=UjDUujNsLqCvmD65fz>>d@H@1Aqos+mw z&ScPE=h~LbbzW>po$r_Hx&1$u^)|0x*G0Z**EqaWG?5BckFhgK5F_m{&(naJBZoCDu-cC^33&z=mkL3Wwu z;Z(ebw%%30=gX(L`wROSuj*%9aMAoSHhhc@gYe5*Nf(Y0wP)_B6--i3^b4VSBf;@2%SbN9lXSfUC=a)6YST zs(&@%3~;49SgW4WS_%>o|A|sGQK_^)T?X55yL`E}6=7TC+rRwvXBZ1 zOp-v6l&M79>{2M@m-)v%^T&KsR5{sQUNqozK7{kjiV4sU53LC~5wVG+ktz|~{#y!v z%lhTn7J>8Ee7)P@LWyFrGe$Bo?AWM|EecrhoSRTN!8h&_DjpF&bHF`hKkHIR|58!qRX&h8Y>*>?Pdd$;<#cBvJ25II-hC%*0j&u1Z zKgU?|n#{n|AEvtdU=#m7);9&4VHdHZU>O^Br2N3fvWn@UV&5KMQjo<+G17zTN7dXG zDz1lYa|%E+x5IkBQAH{@YMKs}kWJJNFId|hlYLgq{t(U*L5)AZ-8_E83Ij^>BL+6E z&2#n^4l@?&G)S@aPNpFlWYH~a^mXrg#a%{xpOiq7Q`mrNCzTDU{I!l+vT>#%Rhi?^ zVk@2jTKXo@1FWW;D`_|_Sc%sDkP;e##Ja;iSRZQ-DiKb`bpZ8akYb0^0yxAvves}x zSR+_JD6D9q6CkWHl3NH?UmVsCf{HaKHQ;V5KjRt>nx^`eSWyjP#~sRsVa<+u^jHJ) z$-&}U#XwDW*h6BF5@!#r30|En?D|iQ7pVlD@(eu4pfpB*!@)!A7j~J@l4+&&Ky}o$ z#O;N=E}!wTh7u)tVieK;Puq=r}+lf2o?Lyv`e*E(-_y#?2)O6!T=KS|9-kU+Me2%k%tNUWZYsaiB3h{EJ;vF=Qa9K^3CM*-qg^`_8Gb(~gC85B0U96Y!(D6EEC2N}^ zraVa8*H5dwX&&493qH9MDAtSXA<$sa2^Pwt%#0wj%d*5?W{Khf1bTDt)mP-TRQt^8ci<-Z)myQOFsv_1mhbDMRCPr&# zyzE~)x8+0CEGMQg>%7UY%e57b(v8BwWQu4-=Z~|oKI@dIU`QmJG^YB=-Ul1zeOwsj z;*7vX?>T@h+WLNdRiO~}0*!_NhVz~cTp4ziDYw_TYupPe$KMY(bvcxu%kH6aEqs#7 z6t}dvKuQq-5Ff?1?l#@hVOq;$^%R;H~dGS zbMd__E%w=+NpRjYT~M>Ho$swoHUvXOQ<|h^{yuB(+=F;WaS)Ij$F!%EHhy-ycJ46E zvS{y{qN>{_Z&%2h2g~1u7FLgs(eHR+vGpj3;s0D_e6M0Ta?T?Ke5*D^MxZA(EUEgZ zlYck~8#i(nHwIJFC$^3Yj;lf$BIcu((dy!)T`^!mPQ2!*%>$?nHK`v;Jcoz(LwV=t(Q=UWETjY%?HV%6Tk+&p`;*pGJY{7`I1#VJAi8RVhZ`*t}}FihuQxoD?J(Rb6QsK1q0 zWjA~`d6-#_?woD+n0G5Ivr`BZfj=eoA^;!A!D+`s7n9jPFQcUm)>Yu9yDHkcT)Ka` z$sN%WXSeEJelZ8DAQ~J_-)!8SJ>J1r$->my#&RM}?7bAgNqt02UFNHG-XIyJjvj#P z^^m|uR$EpwdMt4Ap$0;S`@*g%-Wf!osE5Z&JE|`OX8EhmIWQp25LWf7NmDm(dMU6as zaaQJnZ~$8s119eX+5K(%L1yw}#ziu|aeCd(>%8l4^15Drx%z_3qEP@unr37Zc7`%d zY$nbZsYooOb=B%jh$Kw|#M-B}s}{fHP181u|GTySW%-cTZMWqY{r}ODaX>`j=x;y_ z0Y4@lY&{^TNo>rW7-@XXeg9Yuf0o^{&)3`k*g4kC6Kauha70ZE1%~5P#13T|HpN^e z)Hvv%61&>I;_)obpO)Ky-@GZ-H4300aGXR%97zh=)rVkx0@wQQ{L(dZnDZnJ1E=As zw#(}%H??ElV9#TT#8U~C&cELn_ak(=p*-j;+?UYY)%g=z9VSdNiYPb2F@H;g{fZ_P zFm@?zn7HUzZQ;tr00OTr4TZFH(f~Ux5ivpzYqKG{GbLwTIZO-`lP9;0+S3?l`ppG5 zh&rb_Q~^klbmO#gScxlyve1n9Nwy4U+A=XVp->f=7XF&w*ZK1EV1Lu+_WthIu3fjA z?njhpR9Q$7ngOC?o)P-MbnGIE6($NY&VUK%yoqL@Z}yF%(3~52VE7K=Xn6eQIOp+- zA#l1op9(eCmW|QP36RF~5-A0WziIa!k@Ir&rl5I3q2%0JvCwMmy$ z8unrd{n@U`^fVXt!_QQbN#@@%d0l?Zn^l+FZ1XyAPT`FT6npd7BlwMicZCU(j@5Rs z-SMld!$dLnt{&CII00lHQ0nOuMcW2dxs^=(@r4T#i5Rh)tv6 zK7|)wMHCv*dF{}7;t@Bb3&PWoz#A0Jo#CLA2{plldia3ZRjab@afUkrg$vZ0aK|l} z$ER>tFb$pvSaeApaF`pBa6x^!-`9CV{<|vcRoN~7_L=u!xx?sZ=a zf)TPU1!i5X^1+_ULsgK+sz-T82^<@dF(QGNu$a~D!Ja~?Aja+;E%?lH#+CQh&gm_$ znitL->b5n=6efNHQ3~)|{mV9RVxhqk3$xM1x$Yo?vTc@x3D80w9%rTpEv?WZ(JrcB zGPJ0!%Vj^5WxZ+WJ7rmMZGD2!>7Y7I#?1`wWKXP&VLlDBe^zPg{_-o;3rMbSkG~r_^-Rby5@y=C!{I3t|qrY^3sU zpz)BhJ2+|DN1R6N%eDrSbJ(pSyl8`gqf1D{_4O&jr-mF}3px7nOga}Cp_8pajfbeU z`?k2r`>MI-IGrf}CmYO5;CbcweRm!Urw6lXvy>;9Gg;X<4uw+zF!VZRfUdw zR-&=AXOoHQ;j=L?onk@KXKc|)K7=mycm7culE~}HM3o@`nd9*jk$D7B`D{8-VUZvr zowpae6=l$EGHuCBN$f&V_K!=tKQa@LUW%$O>$>dv-e#!zRo>Zu<|n195=ZrfG^=mJ zg}awI)_#0B&8SClK}oj@Cdkv7+P{ZRHp+n`}K5{2^Aqpc!nz;Osj`dFFc z;6vV2Wp{#3?98a)vzDrD4D}j1MLN^jKa|%w9#14u7*EYe#^>D}<5BuLn5{r*QI~o5 zm=7ndD9TSo5-!0|F$Jg5RH)OJ8K9%>g`EkNFsA*~ych@3`iIKK#joHsB2gSq7h))Y zw-CkoA6}2(iO4d$wm}=@b>2NK^9^jPuiN|P8Z}fYQ5;Xl6jK0XcvF;^KfF$63wV(9 zOdug#YAR?j&|cqEO>tY7PxO>kMOB%s&=i0SZ{TSM2n|RDVY=>UA=3461!6a8to_Nb zX)KE0Nog!V=3otY3bse9{JpD=R)`{XZZLQ;8%5~oJ-F_&Um|KDQG`w>Qv(aRaoW(c zyL37gJK>RDV#6ZooDPu&P5;6KkppQ2g0lrzY$15+Yb@7oS2pdkU6p;GKdlQC`A(wH zoEart1JKnd`a9krFs0b*#H7q#*4mHpi^AR}gN*_mDlNygE=d%ZbEi_kZz2@x=?puU z&Z-l|H`g|&0L5+uL%H4-40y2x@9Se)@U&o88C% zo8PQ)a#8iBjA&p$WDCLudSQc;_Zy_bDRvxuPxOaOW*^HO|(g8@lf|y^VWjzpWln=3Wv7N*o^x!VlT4sE#D^@t8Rn{UYRh z;wk%jcR#c}O_%-C`Ys=;q9sLsygt^NfcwDJy6*_ z)vd!QyApYk_XFzfj-z-_nvBqyX~|S=UqGgtHT*cEO=(CrUhiU@Rgi}5*E=8?f4;@p~sT<=<9ZZj%~5{_j430 zF&4td_~yanSkz9!4USRgTBZHBsh`@Lrg^f8?N!=UO^c`UOB68CwHuo0Ocfum8V0o+ zP9lbQU4LA-yY{i{Jhk6`5nXCR5d)n{HE(2(vP@Zg1G7tLL?xb#a5Du#%JEDBS2Db1 z!Yo@}LL};TVQyAl&9s{kE`hORvvp;fZrbquLiy1GyUeadX4l3QjVG(=;#?48KQ#r}@fvkDov7>@()kk4 z&v$J~j2|k5juMyIw5a%C&vMQ`&O_f&&n6QY8ZbJiBDjGl4rbdghYql7!*T0#=|rIe zomF%SHE|qb49BC{nQQ1)$|Q;hV1&E!`ub^Ew-2t#Y~`A;hSvQnPA@9!mTo+Co}rCZ z6kv=#DmQ$Vv0?1uQ&-ltC)WMWC0|v2QQg&5Q=;bEB#J7iIT6#ic8A;4K_VHa4^}Y=Lpq=TY*Vsmj~PM7=Tm=gCAxL#|&?K$cSsG{N4{7pZ~=;`2&HvOKr| z8du^2CWqdk=hcehcraozU|Ba4L%>BE1t@JEM=zrkMe&F$1)FrHY0DdJU{rsDASx43 zmyR=RoG+?)p&ZPv7;(8(MR5hks}$hwY|4K}9ZU2mrFYc{N>QN^BRYfXoD76yWrvaY z&by*WLkR|TfvSj2%7Jb$=M{>Ik0i+y;G7XF)W6!+JxM7lc8Huu&w#gCWz65XzRuYl zL#$A89-&wY*t8epn^2&Z8}B!v7ZZxae+g+IE;@|=I{YKuE%c;Q7irNz4JZ`0FrsOw zGm4q)ik4 zUW*Ywm)S&#mywDJ90Usa)9*t`^0uQaj(?3T2)k(B#FI@p*Cc=4dx#Hiln59Y@$?*O2OHQqY8xQlZqmw#>!@9?7oIx+TOus zgJPrF6PV9Hp?rMrH<40kaM{Fq&Cjb82_QFsF@Sp{1|h%U{#6{ef2md+Pm+`NdYS$!t!dxTycxic#|~%qnKFS_J-t z`g=PptRDMAmMc$f*;U1|AG$JMyU(_KKyPRiHk1;oK|>Ze%h^GA^Rqeb43(8k?8&L7 zD_i92yQ01C^6Rp_$2In%u$uOiN&)7~wmu5cCJ!XBh|KPpEMZEAjp^O(k~8{0E&h;F zD6Hm)K4bI1DOOC&qEppDS30MO^T|%No_(xes;261-1fB_e05*AFBYd41qO)djb?R| zP3)gf7Z;48Cyjz9J9&&O=w9ddSXu2dYH`+zj7U1qc}(Oy-ov*DLa9_GTChZB%x_d5 zI)|2T9VMXZUF%YEg6E*ZK`CiQ)YPT!g?DxeyTk}HF0}m!4nvz5_!A40-y|S68U-0)}fcthb-eCMJia>i8t!4t1snHtx@fF3J0XL zpBn|R7n`@&`Ow>hWF5>fdLn;no5km$tm{V`Lo}Yuul>ufE^n(W*n5`W?j881O=L=L5}rw4X4l?V zb)9!BC6?T7x+YMptUy7TVk-#(3uIwJFqU`Is zzzN2ID322y1@l~9E;g1*0V`v@HU8MgE)R!o1PSag?6EGhEKw%)ub!)VSYDO+L)ne3 z-f*ZMfyCvoqC<0=) zVuacID`k3CWP8l(yS%u4tei`yOI?ebysk?mGFG90jW)+gGaz76E{CP_XMxamDcj}! zw;y}4zQYBMOeLJ#{~@Yok9RglJ)tblP+(`q2>?`juDHw|DLsucs_{cc#m9x?jZ(>Gp}swW zt1nftArfK(eH4-OPz#V9tFahDVH%oXWF_E$J?Obj+RU3^d?v&We;!eoKv@K^iO z^vkjyk=~ovE(9@Hp$LeE5)O>Y##-q^aMO+r&1jY=`&X)!-+u7VbwTX%T7^SWok-&^Nny7;fExb@^VM#eX4)}c z8KBDDHW{Ipb za{)}PZJN&ab~(QJLZd*CgklGKNKM{u9kts{v&dw^9#oH{24+s zsK&8*(VgcD!Scpn%NJ0K>a}MilTokYy>Vph7P7ZPBA5fz1c|~be<EtLQ#>|d z#Cv)_sFZ(PWRfNJw)F>sy8hvA*%VcdYMw$dCEXK(R&$ZD?0r{%f`1l&D!cA!@!M10 zEbJALXg+4Oer$2;e#h95k&i=9no8!r8k|$kvGHg{ACV4?=IrD`7RIL|3 z+;{atOZ|_(FliFA`G0vSwifp9F8jQ}zK`KBlltG>z1x!O#+5DlD;0j&Aw?WO$a}*5 zLRs$9E#KN9X-B^(q60-@6}gHeszGv6yI+ueLwRcjnz+}bHmSr_oJMFFfO%6N~$JHk|(U#3X7 z)^5l6xv0zSY<0HSBo!>*29j7Y@>w=jQLsc8ATrtdkv%1&7j`Y)HE> zqXabYV19v<#`eOk*|M-iN3PuOw6zj1*6YLowJHFYRCFlSNo%+h?)`rl(E#~FDg$Dt z_FmV_yM>ibOeUP<#CvuA@jw4<5{Xr@+08bu^Le@{4B&Ec7!DYzJ}EQaWh#rK_!*uc zW-iOb{7~jr@QR!HvR>_GznOnVT=4FolnU+h%1KAn!3LOKhELGz z`&j+I=s4qQ_uQ1Q9d8<&PzWfYpgvF8^GKzEdXy50lGNlCw6p$H{_CY&tZd1?DR7xF zPO^|&H_dLnE*mA9?%X3#$IVjZz;#O<#keT}h+P>`9jq^_c|-QY;Y9NMx;WW!vkSo4 zsa-vw{&vhe)L(x3@#lwcEZ}diix?+cXb^{c(|I;`VED8!Uw~@k%z+le;%wF&H75e z3ZyzR4aHiTs~UDbCMow?=hAB?A6HDAbDm1;mz{Y#Z`U~BNQz_Ub8cTH2|^A022MT1 z;{int2t=BzP#dkuu3(oUpUdfuLwuZnwWihO_Ti_hd|*U8D4N?Yx?3PUxBtj&ao8_Q z+h0ZE#_lwB`1b}ki%>gz5{I<;#p&GqA+522qrOvqu-~4`?V>Jr_V3~FqB4(WTeX`- zbNlg{$~Rn(8nmsN3Tf(!>u;;#WE`VN&9^%y(q9bHzyI?`3{r*Caf~6g_Ny0fAdiL= zH6Dl{m3DjcZjs_O5g?>jPzo3gDXOlIAXUd3={}L7@}>w<-ONKqK>EWqkmA)JAf!az zZ%py(4-it8-R~=dRHCGW(+*M=A(H!TzOiJQM@cLuU9-jJ+Yh0@0w2-5#H-PE2=fDk2&m8+Di zP%o-Ya=}_WnD6*9ebYn|rHf@EDOre*Zv0$R4pK=L!$2Kq{zQ8F9DApqPy5e9ZFNGA-0ALUS{iMOF@7HOI8{KigJ)y zHT!NOT{fR*S77*r$dLPxu#6>=(?sQ@L;Y)Y&<@*0SwGd4`FGs;MF|{cmgfQ)l))Z! zJtZC{K#O`nNh(=rG5%3wp5y<;_eF9+Q%dtxDUVO`uHCV%wgn0#N+l}}G6S2=A*(Yk zDJ%(16;&x!j9wKcs^@H_q5-Xg1}4e6Jv7~qF_FB-O-5JmD_S&C>&5!wxCl%0ig0I(}9!_qAHW-W1z&FyDy8y zta>fCyT_`o-Zt|Bvzez*N?5sx2{5HqM`k%zqd#_Nck|_8|Jyb81{6vPYarY}-aNiw zIt5;=5|$1({S9E+q=SIkw*xm;pb3#{$^{YbD(z!kY!}tm-bl%QiL*vjDEX_Q5IxbA zm{ih;7_kc=p;85VzjaS5d=nYfThvk{xz?6->aDpq%WA&9_omnuPmM+{?(8BNnbejB z-BKpvwC27vZeWQE`mYwawWRL{`sQK2U8c)TiPp>$9SeNlUlv8apDp)Ky_8@sXZ01GNCa98%?had1 z$iA-j%U!ibQOOlb94m5%#do_-++u-%yA)Irljn)C4={?xY2{%;EhX02Gk}+Ou)OEK z!oFm`fo(qADZX12r_*X&gp>w$^trmAw4L(K#2<|hOk26v9Z4zBhz@(c(^?Z4m47BOJ<=hM?=&n3QDkp{KR{%yvK?qii?C1Pu=FnrsH0IVc6LpMsO>Gz%^Nj zKws5DnSa(4C!BLv`fqhHK18ww;%kJpLVTfp-N%3J4sT5WQxm{62;k)aQTxWqRDs>$ z?Qxp~Tq1X~Ne3hqS#U}vQ|1p+okH-JpML!Dmw)`%f2TkE*WZVu#3WN7N^#uyg1YO$ zpv21^sYiD{1=N}X?Y9-K=tU`q#lrc{$_v+^`stgGhY@F$s!|GIYzu*|L`~1eg_4;m zcaKX)j#t^ywX59DSKHMdzbCFx!eMq8Pcx{oo`G|rQ^R=o`y6o?kJ1f`9Nb2V6FRtl zRqHh+1L4MzjxI_p%tliIL--gC@eZgJD2*^;#eG%4d}<0gyB`j$3HdvUUO1;ZwJ1`M zkS0%ohM5GsihB2A8Uas|@Jw`A6}#%NUv7%S>f>(0onM^Xs9m$|$|})@Uhoi zI?%$xwLVvw+iCpy&p&P#RaO5|uYPXgiq{5KDET*2mgh8N9yDcngvLKW{te6lFHYi7 znr|vgB?oB3su8DzteXAwC|0TbV1@f0{%9ZA)${vQ?Dn6k`n9MR_!kxH^x8SY z%~&(iYw3N4Q*(yXG0!k2Te88G;dr3oePv+3Axl}W;F@PXQA8&^*L0NNqGaC;S}ilk zb-eXOIV*H`Gqk9riJ7FS3syCu?GhOKzCP6EOq3>4_$uwI`D#CVUM+U3?cCr1oj_v0 zM$YMT6g?_SgBlCCrHB&{WMr}qhNS7m8-3TD_! zf_j0M14XrxAfWsmXt!lHC|eo_CQgf1g*i=M5T#F-vy@A)kp%Aqp4ck) zV`+*SqRd&L32R3i?>G&pq0lr=rp>Cuhf~J(Edc}Azb`*V_%uqOE#?nLnw^}}+`ZU_ z_2`yb8l}({he|;MF&C=zR&*x@i<&7xXP3p#?htwIvCc0lH5iEV;>!DSm}v7m`0P^X z?8-kxE~2JsJ>l8K5qMy*mXmkUhib5n2o*(SvBx(&yw=Da)-JpG;U%c*)6Ta6jdc;z zpYFZhs)a3fwE4e4U7Gm1E*Ew6I-5VO+SM`~)@wd8P16Vxgu08fOVCeD@3VWlCY$7e zA(#io9$p?UteiN!D$ckHm}Xzku8VSWowJK7KzVwcBmAzQqDs&#Wh#Wq8=d&b*41rm zGmVl{j9o@7rcQSkmk~-=F%Ff%$-S?HaXYXmmYiL43-8{hfkKD64NY@;QNn|RLwX+p zMO85a1A6i?ohTJV$t=cV%A3~TITLT+y}|2Rj~>=*7Bak9cI~3|N^n>2ginbS>$@32 zDtg5AW>`^k;V4$Sa4{gNdP=0&{2|LhK?Trbrl;4+*jQ0wlS8qxyFiL<`9_dNx(+=R z2gU}At;b=o1YW9UUr8WosBzdJjOc850ClMMTr?nKFM4b=j|Wk*lm{kNawK zSnpTuViyiBZtWmX37{vSBOdg@7aJQJj~!Z+I%n)0>*!Wc-wDR(aIcw7=!m7x3Aj^! zwJ5dD=Bouh+n8#C%cS$@kv?N^N@GBEOlj;+zE+e@X$)+; zX>rG3k%|sl1CHFWzMB8GnxrtE{*Q_kDdfO1+TGfWrA+sN6_Ybb1}|Eu2wVNDb6rao zh-HX*Moosu6Gc2l;r(jUxU4UVdcU!Yji^f)rC54Rq?~$R>$qSsY11{q2J-deg2giQ zL)!&*oVpU;QR?q2Y?w)tpyVmZGnbTR|Is#;SeC_lzifArabQvVeI(5V4VJ(}lQ;3k zm!LaicGC&!CQkmF(;#`NUd!5n`}J?miVC&Hs8NcY#QgSUs8&f55+jd_7{>N;{t%ln zg+rd%eFUXDL9N@0wXvMQ(wK14oSBvQ>wK*2xO+jdTjk~}&{8K>G|2(`{eHPF_vO!J z{be;TcQauU6C74l?}eC5BI|-}WjfD0!FZ3W`@L>|{jLZ@`uMn;V~G(cZBDxr)e*iD zO}U!Eb1LuN%{;zK`#*kY^fQuBkte)e0quUEYa~uotHnl`0bv~Nmc^->4-KPBSUT1By?PjNisn{l5mF9<{n2iB*WiQ=hM~LRH;9|R zkdy%%iL$3<*kr*&iD3>!Hz0Ud#fD<0490e=TLmRFmb8MFmyLOnb%BJTD!J;3f?tSl^D7k1`n62 zfN8WT7wCPZDmY2Xf#_}*Jd_gUaCo=MR&WxO*7XulzmO3r+~91glnpqWZ`Glm7l++Z zg&QL+q;Ue215pNNlzF4LvuE@wFj4u-K$zmjp+u!I5sb}Pm9RTJu&8uqAj&&9uxQWS z0WfcUV6jXV$%FY5Y1;R#uSF=T9*B`Il<+Jdb6qQI_j z{h7aGqs0<`HNfe9M;nfc1JYTX*D*F&>>7~acrz8c@LTDj-k@WG8}+4 z;9^BzQ=Rd|dY*I5TowQ)WLB@{%T2XiT*`GusS;ZKe1MN-{>9A0+EpSC^!j2C>lARY zJ{LC8f@d9oJDP{qt3Wf)&SMI|D4ItUF#HCc&|{o7zBx*xap?DZLRxBSxF{*DfpFb7 z_m+26j#6yAVsNL1i{gM>@hzGfFY4`8DJP-1GCd(<DKqrH7j;E#~G(l3La+++KG=dTBTGoaJLs`fQ6aW3D?STtNa`#;@RL0JFO@9 z8$;SRBlaM3l#HhZ3poM4`@Ub)nHv=?Rx{)j+Dkffqk_fm`9{Ek-|YaiS)Pee;i3j4 zS)Q7!6Udjd9O_l6xbe6D29cy8#mgrA;V#EvU!Zo7a-2r%DU3aqK~IzgBw>;y=ChL5 zM2VAU9fD%VUKl zUf>Om;H0uBC2KU4xP-|1-*plqyQji0(Vx**7$ysY` z*omh&I_ZYe816m}^KkO%aN-i7EafWZc6~-G!ofLVI8j{|2_4)IPw#MxH8{8=c5t~l z`nlxhx5zuMhiZM;Jgy2+liV~@}1!A}MRL#ogY2`4_8-#np?cYcuzkSfc4&*)UCHoV7n5>!vX;H3sxE0qN zCA_LwnswNDt=1nXTPgjPV7#%QGnz216RExJ`Y-$4!D>xCmHTB`V}x9Coaid~N^@{g zW<83Qs95D+s^#|K`|YBvcU5Pv@RDp7r?zVM3IUyjca_R}S+mG-@~R{^32xUnHtJ>L zX1Ff0Fq1bY)RY90x#h}Jxh?BrJ=+!Aeeqb-=3j+DTkMzXYKy~+)mV*S1|uq>&kMZ; zW|Y>dQfbb4x4*z6vSHzj!b=}K?~FW8j(_D2?9J-AobAf};pKuHpQ92bol2&=PfhD4 zaTaN;lQJq!ls1})iDca;hQ}O9y?ZIY1x!?uq*E@Uh8btW8M}N(#fjvzWE{vCVq8Oh z2geqb8R?Yed5ouYwq<=ny?jihC=pqjN)9rid$p~Dift;Sm=sB8sTSd6i8sw_keU?I zMpG3zy^P6(E0QqgdH+3@+s~`nXYggv}YZ!<#&& zs76wrW|`{lzsF|%w|``C3bHiS4ER)Ih0I-CN;vu0I8sn^|HQy>vWTKuNao;@uF$ic z#K4YBBFJ}dkvQOVV`+M9en9oZi&9uLKp9GQ^?wXldUlrl_ft$&DDms)}`b?em2Ru7K?>VS1xRB{Y$GE@rAb+;ppj`z)B8RyBy5%>N%!=&GnpPG z>WywBRH9_k2NotuCq$Nl^kHDb>{>`si4sjYQ_zMUygWfKx|6P#D4|qsO<0L!pidYq zNqk{Vb49qQrV>q=43|clWC?DE-o@R7QoKEfG)y6a?=>c_G%`};5Q@QDGT^v4=x`4l zo?Z(mY6_)OP=7juHT&-(pr};IJT)BfE{x4)?&7IIY2n6h-#oU%mihOQn-!|*pdxc6 zP6;I9U=>CIJEGv~jS6s&j1|e%If*qiL%WNn5=t9asZ`6*CPg%3w;o~@1Lqdo`Thzp zQCU)!Y7VTB#Q3h44c%Ho(#1fry`($@${V^X?empJ-9@J0UZG@io6rgXFa-~A&xCLi zxJW)Tw_Kmz0q)%y-4yk6xi^@All#FBDC)P14>n3Q_XKY6`RU2`m<}{DkzyQ}w#KH) z!G@}50NCTnz0SRb(#~zZVt~Hhc4E3aejz*d78i7mN~6pNNhLTy2M2Ta5mJ<9Uu5&* zy$y3Nq(gU1t^^g!cqXCybIW)J`-nX+r%4_mY&zA!+nX^kw8M6#z@pksmhLiuF>w29 zN!kkYO3&*@bK?9S#x3q80~M7)K`HWw57>F;=q>Ig0~M7tnd&a%-77fnr;0n2J$fai zsJ*b#DuGFaN0a59`%#UoIS+ z_9xoSzU+4!EJ&ob5Of0_1>Mf~5N~k@jQ)4m@#6Pm0lVO%lhZRYA?sUB0xrKn8A$1!_nP+F%{uU<5>QNfSnx|Y- zNChE_G|T#4w^HduNS)*=cl8M8OB2@FZ|0v7mte*ARO}27==JtkXuQGVrooAAsQ{<9 z5nTjMZ!?UjU5Ew9$~%G0Y=ZCx(B!swz%H|jO6hQl6(lV z`+*_7$~%M7Fm71DfSjg|@b$xt&;vU0mx^2uBRU+n@n*2triq9?hJ}fg%hP|Y$Hm#tUEiH0lD4mqHO8u^=-So z{BA-i8b|18M~kTL9eg5*m~1SA(=>($PzETx+jvIPc&bHCgBB^;XI1VaX!Qm9<0FGb zY8vM@}| zGRjnDq5H%8LI%msTu(zk+AmjVisA%^RH~r-uxS|rFvISzp9@a}6zM4%11cb(C*-Q9 ziYIE!mZy|wU3p_3v1bWh)q!KvtH4C0gINck=+(p@nl)SnAJR2c6VeT%h|Je6ep{}A z6eXo}0%@N)|G-h=RbV1%NI4G$&pzl3XO)a^@Li&Glq_q*nhAt3WBaL>t<+@+c+mibX$`?e6!oZM88IM9a+D(VTxZsYx_G<9l*E9=uC_(Mg8jdq zWc#t9BAG`*1J}{J@XVPh;y^K>s~lgXW|AV|`UGn_*XnMI7Mx~M9H~CP0d$M}4<(q? zGUh;+88D!iky)<-6PXq<71HKde5v>jU}Bg5JC!zX)9_G7h+YW$HfKkdwAYjq} zhE>~o8ct7x7-t7REX4PP7-tSoYhSE&3ev1MmMP{Ijdhh1SKYso0`|$#b@{1n`wPzkN zE>INNil^L4Ermd123XoJ$lZueem!A{=@Gn_1a=z0D7Mu=!2LU-lR!oh)z3htL6eEz zQH)VaN>;E#ghse0oM}8hM;48+midE}{DErD9Kf&U2j3m)PqUp(qwCdfUGCE7?Qp0l zsu@oy57)&VFg(#&DP9VbOjwqOuK@nA3DgVo*&7wgjpMBrQF8hqS&s=b-MU%b$Hx8uP#WR zP+Buhk_gaNTKS6eMSJu+9m!|iz(mq}6<~HD-dhtV)o;Da*TtyJAE0uTaFM$qEf$;A zcD6aJ_p9AYRqyA;wpbJxumq*P0)eGRu!I9rzYbQB-4HC2=6f=-CmS;ChG3CQ-zZqp z-4;5*8Jrj_s@*SAMj1qc=woqwKC~?fehjpz=QWPD$7<9q(IR~)DI{a@PH;Ir;J77P z)BxZVT9S3i%>%#N@zA0vqA*$p#g_W3H2DqTA{{uv4_6(P^~1uBxM02fNlXhCRmGkG zi!R*9$BR;ExhCF;;i8hMINXT*v3pNBSa~)vT2wZ55^X-@TK1Q(C%}8ngbIOo;^PaF7=%sWmIn}4j1e@-p^4+%KtG+!Lc5wGH~KnRudONIANPC z%?Q9bZm88jf^kQO8ENR5QQ$B)^F6|W`JQ)CdD-J2xEG^Ekyj~6Ww;*NG8@|&HL4fK zGo1<|QmSS4hhUO<*cC5zwK&Z8t7^MTtNLj$Qifb>&NzXr0$YchQ|t!N-pc$NXds=EjUke_6;VRzQTGqx`&h<-4!OfoK9@>9F`Fng-Ya=R{zPk81N zVW@ErH&tDza>#n?%zCDIT`?P~WTFIh<9bCg8^TZ{AC~5tcUdIjXu5lWdXG2)_DC}Z z@YV2QURBG)l_9r{#f^OY^Xy(uu7;Yn>>y1OA{lqUK9$?DF4nVMvE3JsMQ#37T(o3J z7;Z7-ca522UfJBb+yifrUEYF3eG>OWPF&213tA|a2xWlN+*Ltr6N>e|E;hx#3|bsc zOojJ*#EE%_a%$>!4H~y9SW?a7FuKnzn+hl9KDId9pC!DH+ZX6eH-_H=C*~f`MJg$v za{g|A*eT`$)lOI4M@RwW*$bpI{j~wIv z8~md}MUHlI0t!Y`P=3Noh~0o{ud60a1;EVjOHk>`SsoVed314yF*lZO_r)mvdW0+{mtW?cbYyDeKj5CLP?C`{7_w${SaUYBo_wk>dPAP-Y)aW5+B% z-bot~DOQVY2-2Wqcq^o+?1-nTy9V3t>~zN%oyyI{IoT(QlOf}&CO~!{>+*+CMe2g3 zsdjTgn+G=2Ev-PbCYN)~Ka@x@4XJoH4Q#aB$>|~{ijp#t2yS0vnqMC# zYW2w691;*&5J&px{lP@Zkr|koqEPET(l-ivfi6-$(XmCTkXbsg;N6Q>L{t$^G*VdBCzawMKIhyWY4hrWyBi_~V#g@~`dox6O+ZJ?rZBxzn$+HD`{NXH?7daI}+ z(E>_I(8-{pG9~k@ zs_s+sJ_`>$obIE?LUAg9k%GK+HU~62@8GeaI0-Wz>hb0w2{bU#%Zdu!a=*M;ez%$Z_@@m3w*o3EwM+iFp+@dGxBlKiuq zsG4@Od=km>6PCLo!rp!4Ju=)pR9t3>_6gf|9jbht?U!}ATUP5u%Zfy~#d3$(G1 zI5XT;fKlE+0}knXPNP1rTpqZNRdwU;ns(-I5?Drr2P1)XCgL!~Q_!`lZ-a z7d*iz0YHnBMvEW3tIC)-akfAzwQ82 z*Du9-UB2PqqUhZsB@`fN$p~lvB%yLLG8#o`{|&`T?*S-^-OW=a0M<)Pc(y~PjA9*? zCrfdve*?kNdq9ek{JSu$)K@skrUQ%QdFNTUOw8jChWFC#z#?hhLILaaIwIrJTitzJs3=9Eflxbvjbw-8 zB1NhZ4MN(lo*Ne@s{NFi#|9vKw~A?W7~V7)9$Yt#60tA^xfgb z9Nwzl6x;cFwcTG((4n;bv`#Zkx>QHyHD4CxI<1St zd^t1!A6Eu;{kANN^?r$wGo&c7KYO4xpbagP4BTM|nlP~?Ic9b6I5U5UC--N6pxNKc zeO>*juAa?p^~)vFQWPuxm#dH{-K?Hxp!i=P(WByailePR+B*TKl}tl5ypPWp*xc=H z88aeKWcCE+|G7QGzzF(ON-<%kh!b=)X>q78Ma)+m(a{Q_W;cS0%%3_?X&h?wGM*AA zQcZy5Ku(b#wY2DfnEJbqV^-=Y`NrStmx`o2Nu5L6ffSU23t!e#i}sA0*Ht9u{&hRy zpI4iAZJt(%6?Fxp^cshQ%^k3mr*YA+als-PPaxQL`QW>aEOLkL_X!qB5eLEMR=$xy z_tTw#MG>FQfW6yq7CWocpwKDawQU?iK~A1zlU|-b;u5u4icy=*Iv{n!yFHs !L+aiYjSl%$~@ zjN|sx5z$Ds&nfWcSu$llGsf~oOkqrw+if!?&)Qr`v-0J|+(l1ySy;`^64hK3sKyL4 zKPSM_jO~jCA&wXEHpE)mSs-@-?_XEzXY;l0Op%8w^aQdcLvm1Pj5K=5qJxshQF=yB zjGC94BwTd+Y@c@*P6PysTy5S4fWX!!QRfLyJUGPe1#HhR&2#fR^PE%6D5c(%w=< z&W*I9Y&~x7q@0_3Nq8`y%k}y#HLxCMFPr5jgnBSVsX`M%QYpLEFpc9Upa$3zr3rd^ z{L8(F%Ee+;&NkIyYp`rL#rA@7MsLe`)c!8ZC96Q08*6j zbp&4{XAVU3rudMXW|DQ4i%52)3Wtpd+UKz5<}K0YcVuoKH!*ttQXHO^#gh3oo+cu#fe|@G*cX0L&_si zeXPNG){~({@}r?j#$Lzrek&Q23br-{b_OVnk8zeNFG2KX7n7pJBu>&4=#qDvqVHmB*mdR~%#Zl?@Kg1;nlH=Z;GX5T z?P~r^F0s9#D1B_DQz=4!))S*;zvS_>*4$I9W&Xg;U%AxoxbfBe;JZWpX|`MK_GP`= ztxGGlF&HXJBip9K8Q`tf_6oZRVrU-XKt1LdlVpfEnQWTox(hYtSQ?#Nc)ee$txB^g zkv(Iz=39MQn;&gi9kz=LnuREt?3|?;4+)6mt6Cu7Q{{n8rJGPtUz&^PgxR=~?lA7L zE?*7cU3rngFh$8_D`F|k;EpXT{W-j8dv9_1ha{dDUV8n zciX~!A06Ge@7W7V^Dw5n>absKio@!{LyXFwgf_1%IJzMaUePbA-x$2#J^+AUcIE7) zn6Eyq=FMe%$wh@qp@d2S!WxShp`Tp7njA2S%M=9+x`W51?#a|>QH*JkQb3-p8PWCW zQhZIA!xK$qW?mulS(tn6;a}Ek)nQ4jUT4oQ^KJRML(O+kO4>?T+1i*u@0m?AacZ~O z-1J(p+{>bt`~AxwfBo*)?_OVD)7`SHt9MJ@U%xw=x~9whW<4A`(zLd_m&Cu02<~w& z2_>yP6ll+x^O!KNwr6$%X0Nfwm>^M9rYj!Wsm?5_|D;k5)Uxk}=w~$2{rw!Tnl*n4 z&q$I>>Q=M6`SR5~GS6i_d)v&5wER+RcVAZPb&0!+QG+`ea!fsuL;+6^7dgFS1Q5vN z5x!6V9V{V9!URu5&PjNdn+m>RAEJ&jN?Lm`P<4BtsJw|<{RMF5(Mu~O&a)g1D8s30 z4+KhXjuO>)%2EP3=ZJ7YylQ3I3QcapO6XYTg~F$C^w2*>!It_b%FgDc9A@tf=1S zQSUgV$uF5?=G#zoI6&N998dF*wZ$6704(Y6Ju58wtk{OP5+u=DyAT3j&eWDF-au1HYHx+ z-N5{`+7|2GzApFkB@QMgDau*Oqyl}VL4T1j|MM1-Cqs%!iVRW(5h3JJSqr~|JT6vD zR%Eb>4Djtz$MvvNJVWM&RC}D@ae-pZMQGO_^2iB>j&IK<3MZo3;Uv22k5g{Htm+ES zSz;(HY`dbHhdW}<4t;k=*Q-gjSCjf&Z<@(pzsqT6eMmaAfX9Q~U1+jh6jrR8$Pla~ zm2OyhP?S!E6(xq<=wJYz%OYZN+P^OCMuk(BIH1De1yP$MB|AH~~bqasBSl?>8Q4C2EZ{p_3S0~J#N#ksMW zpPfU^BiN12e^768A7Qhk4Dbulk?zr{B%e(O6>GglfYxWL;RwB^o&*o|c6KKWD=teK zij{d)Dm}5FJSJF_`gL=Lft0YN#Gd(9PdL_&i4*6vHVkJc9lTXgaVBf#0tU8DRL|U( zrY>!gHsaTlfJHHplnE?@QY8XT{Cg)5-*A$B`=EuTcIR&U?8u&*y{@+VW%+6KwA^Fl zl^9A3+R~kKVArvgR}#Sbl!I2dRZU2C7Q%`^3OA_xdbKXL#R|XZ$WSWKElA*DC2%{` zUpbK{zSR+d;>gWlH0>frGoLx5hZZkVN5qMnLs<Z;6QdPtCS)@a^_b zrTG-g*{ZIr1P=}&$~Qxpwc56`qYfv)6dz=ajQdTin zIk=NZZ;1tK1O^DHx7XtBpr9HYLZljK&&i`*Xtx#FcWiJG6ckICq)KIAuLh*gP6P!t z%rTc3?GEQuGg_7%HJgC-;Ue+tSw)zpOlNr~V>Ay^^<2Ev)uw9K&@mS_M>$QHypaK$ zC$VjeiNc1Xu>dTO4>PWtLBS;ouw-9*$3gZ}ZlfW06C&yY$*GBJmL-8^-@iASeSbe{ z_Wixs{yTd8iQy!iS<0b}<5>H%XZ>ycu(g3KGT9mYZ>xI0oLk8C+i@dkFjka~v*syb zfM;C0sR?yJrPo-AvC4!wAXLdj5Y+*@uU@L+ef9P@Tg23AC`o6{tZy775=%j~15yF?ce`Z_H5;^hhFy?+3XCW^uTDva zbM=u#c5kIqMgo41L38!(gP`Vfm!4DHez!07)pqt;9Ol(_QM_0=4;)}rPNUOC%fF85%b#|50eyy2an4QZmWLbi&4O3kJHiT+$Y-lZURvSXX5o?Ykq=|ctJg0>1y#yO7k!YXQ9tf;X} zCQ=$Q2SwAA0J8@|gGR6C_$|CeMJwOOn;bKD7c&25wMA#ItNpS%?ANQ!3Yi(A)SQ)- zl?*8W4c>nGef}LRe6$AaSXfa_8VD;-T34b=v5p#9R2#=8wt{sctDzO$|*Ak#I#4=JO>V%kAgY?6di2cI^zxz zGH`n_x{MIs#3N(HnY$aTp(Fqh_%p>hC7~uMS7f4Y$ z&%eu#qlF7~sR z!{+6=@eaF4Sd`&(o*~G@LM9Ojn!e3MYQ6_9NTPh%hpQsSl7dCppJ)+-tMnb`Z-1~8 zEM+9xe8ECdZ>&=ntL?tB_3LV9?&(GHX|>;$JKV`e2|p`gcK~B1C|%)apIhl^_XX`I z^Gj1Se~{9%N`9`bX8CruIP90@x_Cy;cTj@QcH+!4h)5c9R)`*H_uW;DOQl7|JL-Mq z%W7_aE+j^zqkGOn!*BMr4TI7ww_fgoSz&A5d4Mj&h&0H!Addb-$3L{Ag%YK@!&Ax$ zlqFKo-zCtSJSmVhVnk7bgb-BRm)VVIVnUjX5L0B%#DPUl+JyA9-i3G9dcNh7CsdJy zQ|aEcpBKfK)o!*c_lK7Y@+F+Mu}(z}a8uuDw&#wn$8~XUBF;FMQfTIOg3HDK?Dp0C z`PJl57c_!VO2&k!6mp|CNib+4(095lN&cYCACW81yV6u|^W|)3B3gf{tEbDdB$T3Y z&QqauH?(mUQ$N5C$l*Y+qI@EUoUGx2MQFwo?`(@i5ox)LT|vH8v9T@zmwb;%7xrA! zE|0R+RTmx8mcBuw<`*V&V!mpRNBO=IwSAjonJp;g;dei7j%pWc~n@A(k+}Z_n zoAVLp@xJ=#|M>O0@7+KhtiN$t@5=hiYF^HkpI$Cl*h6U%=PZ?wpHNF$xlzoJTEpG@ zgf;g`MC9{6?h}-}p0>KmG4AeJl~10!Br@*17qBeh=C8cnZE={MN21YuwSTKVJr;YD z-V_+kY>pEiw&VqXnoT1cT><1+@)m(RuZsEdb5+jDf4x{1v zspEd5+{QEX@Be7$r$iK z!g;@Xv|YTfBCi7hB25dr`g1HUKpd!WoN5nHl3U*bb1*#1wsl!;cVBN}G+GpmH*$LO zBL_VUXMZP^k$-4TT}-ex3B1~3W3w@{KaSJs{T%{D$@JzbH8oAQFUy+> z?CcZc0`-LM3FV3k$ve)9%hl8J)9Ook!7GCjuQfnryV>aj6-Ot@b3i?{hUuUpU8yq) z7~IO(zDVX{b?;x72beQuCq;?Kh&uz_tmePcUp54Q)z(GZ}+y_CWcYqVwa|dxo z8<+PHQe@A45Y&4JDdsJ;7ZPKT%&8TOUA<^Y?YC}^)V zE2eNU6NJ=XexLC8qEzqmlyv0ag)L>^X=fm;5p#_hH9aB5&mX!Rv;Bwut#D22u288D>?PXw1qE<7^a z54Jh@|JKF!*|w3AZS{%^DXLv>v4$aKU)%K|R^N}6l2ni3=>s?vsCbCFCUVD?>B(4ZX@QTn=C62_VUuTsmIIOLfu!NR@>DMWoE!p z5~l_(Re(&diu8K#2rg1|Bo}~qVw>edO+w!R(;d`^Y2hN}M=}L&A;R5UB|gS%_EsHO`wIWaIA7dB5M=eR{aADILs`_$xG=~yItj*@vb za3$B>n>n^q8*ERgG?o~T4;R&cF%MA&3|C{Oib2*GOOD3}i{w3OyA=l9%YD4lJzo<4 z(;Xcy(vCR>7o_e66<%zhJUUpEKI~AiL2P5|Y~zDPX_FB11PPD^5)o7PH-WrHn}b$n zEK%H2yR%L+vDm&@84Dzpj-$k7?Qj{QySxwP&S|iC1Rn<{6(q@ZmI>p61K4ep}Bz znYb2@#Rk`S!b#6sI|`sjL7Qeww?`p*_9#S_D9REpa+kHWugmgM!6c5-rPVUk8K4wT zkL-``qK_|H7prKs)&{8gOM9YU&*hiZc2;h!1Hg8E)LPsW+v2I*m@gKG8%qQEy~P(R zl5f8NxQxg1D6MonrRKNA8>)#v<){w(<)%2SF5{-5RBjcw3hN!Xd1Tc#y0zwk{dr%$ zEX(b~pUd^b->dDubP(^_|82G?*P9D`2{}p#SJG5T+Kq0EyLCzu%R9za#YJ&zI4Q=! zib|eDN;J@+;W1y$o+nwUEXk=%sFlI_iuEt6&Frc8%JRV>#Yx~Aq!JLFen%QMQ)RzF zz_>tBS(8kKl{D#IP7Gce2?loY{b@!-BDF{u6TlF**rNBlI9C3aQUPwqfINvH@sIJD z#*HYl^Q0h=@yiwaBUnFQ2P<-?R^_1B7tHMMIj?RWS}qR50iu$m2teM5UUieC6Lt9%5V5qLjCCRAk*hY?Q;0G4 z$33h#ZvZ%!&3g2`9ag01h{yp`lo+YUO>sTyhes0NS;DQmIPo_2HoMoQfiwHEN8!Us z+U6Z6ck@<4ccmMV<-YRN!ycHyD}TW zb1A%qDH6Jsnc(c>y+4;1pcl+1k zOPO3S5ywfqQWIRj4Xf4BIZNA#?I;MAB|>o%V&=ZF?P|j8FkfKD;W%Yi>!}FHJjGl+ z18qp@EfIxrB?)IL(OP%(J&Mh0UNkLiv=tUdX}dN`I-y|DiG9D&BkF|b_9?uN)nUCT zYZKZ_03#QXH37VnVt16UgBh4&buwbBcbo}#K0e=6Rc-3>?d)Zr?5g#l^*cQb&y3OP zt{U(`j`3uJZF;YqYjgx$aaT=wLaAre_xZ416|=|Eihi2EwZ*N*;bdJiJClL5l-i?w zW;ZTYqRUJqT$}reO80(xTyA!=&1x~PP|`Fw4Of}wpoD7%y7Ps)wXyd#v$|d~5zMz- zwB^mqYI_CeFOE}jr6%i#lk8^es;IGY0Vo+) z`>1C5^?B?$v5I6lS02yVgmOFESNmf9SS{Wz&>-e0Jy*$6)@ng_zEIH1En3XEi+|tb z8U2=1VZL(VF2wz_IIL&$xB0r*6eP(cxMWsy*XlVNcUbgYS)hx|2H*exMK#fYCBB5@Y{lJuw z^u%l+C*vbVnF*QeDi8Gvt?*s5W8aOlZ~o=JK*ZY$Y@83&wx|=3(MRzv1PG;s`mTh6*sOzY2Mm0mIFH{tT7V; zX6AmXnC1RXk((~kOq*9cOHESexjHNlPfMFYtv;3e)uy~8xj;$Z+N((m=rX3@gw9)` z@`R`=(bWwm+P*+QT$%k9pp zaO3bI$5hU(_AmDUK#`EoTco~*^QDF*7o7IxRjsRT}qRhpz3=peT#2>nwGb%D z){}sN_D$l}K#BVVCv^a|LN=GDKM)6@n~!rWK>+E4G>o%H`6S*LGnber2kf ztm6wV%|a=g4h0;|oF_+%+KRX^yzZ5iO$!%Q7FkUVK)$L~B0k5VciT3em7{fsX7&wd zo%Iic*d)t1H9>*WHjQDF$At(ItTa>a8S-R)yh+e_C{ccDDrF|K>!8e&3{*!6Q2Jf; ziEv`N$+=7!1872R&*H4lQ>^IARsKLJf8ff^7A>RX>1kEk#0gI-5hw{)LUby-2Bda? z3F}k!rfudtPjh7@4Ll#@|2>quhVnJ5%We5oEXvDhegdWDDmhsHh-RthoHk07IYfz; zS`vRb;`#NZ+U<(fY_pvgkLwacj}j;yS3>es$}S~WA1U;w#_=rn#OTcG4p6H>?9KH| zFzaGH+ZEe=@mSR6U&Te@C<3SHD(z?*^bZ8L215F#1KQ){W;Bt4B|P^;s>;n~wcpR4 z%KhhJQ_T0+M-`>#YH|odRsR8y3sigWjixcY+lq2!9f*{v$o3^6xKv^U1Jcawl^! zDI#d+47c{}7ksXgu$<96^J<%>#kQ);`M#=W^Qzvynv(spmj@-{YETOeXr;vVgunKk z+IhS;&hvNr69=wsjPL7m^JtRA{cKfN+f9K)i4-3LQOa0K(fgZ?f>c?`E(3}heTY<9 zQZHNp;O)&LnMCu!UYA5Oi5W4TNWFVg#X+>xJHCBUDy{K=f<{625KvThL`+={1T^N? z5Uy&a?kCE<1bFOw7nLSO-qbvz=zl+NDr#6|PNfExUEcMq&b%@_jW3ao4Hw51$0F-RDk+XySoEXsQvuc<8*nSs!Qeait@T#ELZFGSO0X2 z_Tm4m_y2bOANxN~`+xhl;lCLyolyYGm^vaN6yDkHZ^oPX(5z{gXN}#xWo4{$h%9LwhZy@G+7K}b(Tf|$Jh+AwIbvavBl|A4`4L;2EjM8$=RhltiL>XIY z`f!nA?tke_)-#eYmYF{$bJYw=gR~Xq!1u&)g02}!vn+UXdDDm?(14P;DA_GgqVgzf z6$H@O-nISDjC0~?)HgI^-#$*~pMYWs^)*O(@eCJf332S^?>mBMCNKsO+R;w41$rLf4I`=Me(_-!IXh|x~cS=lR zA#(uc1s#8s$g4%EfL+-b%D~Yp#+DcnB}&{CMtP)4;M3s|Vd7S0hrtYj$vko5iNc9W zgmg+EqbC+|7UA(k$h~c)c|N)ME6+U6@Z1{Rey++{X-n5tY3kO?hEzC>*9c}F>8srv zW*ozbrli}Qh)OgBkB!@S@*f**%DP+&?#Uo+EQ@PZ{#LHH)>Iy!FQIf_wYhV0U)9 z{Kv1~eea&%!){+$DaEq>vYMNM=F>}?2IB&XT!uaV!aIFac&hB-jHytJiW8^xO4FQz zJE9c4jPC&_QVu^C0I&3Yejc)fdun)%3lv3UlBv{y;KsY||2fqs=@m5oY=dVsG3mHD zG}_~++2>}qUpW8k=-K&scp1uJm6)Gi-G!dJe63R13|pz(fV^SuO4T%b97u7 zMP0opNn6F!?swW&Zav&FPv~R*usqD4AAT;^YjbklxUP2X- zvCMOb?%wWmhqSGebDZg*qVz;8Re*OUbjLL55;h*o1QlFMKR0}-cIDgbu&WPST+)w{ zv$bvxG};_IEB|?$`xm)DCKz;ZX+$X{zF;J#JGiKETqaV;-!*1Z)|+mqXlpM+l((kd z)T@hf`=ycVy`Y*w>DOwWLVL{c={+TQ>V2X=7n_Hl?FM97J4koC_HWI0#pd`Q>#|ty zQTk*8rSRJH&%kB`+{_OUdyCr+-ftA)-#+BZq|t(QB*kCMxB6){Zxz(BTiYm!S3>Rm z1iY>!LL2a;CSteK6ligh@q^Iz9xq$Ta;4Mpz@pw)lFD2{l^ndLe&Qrg9b054Vh~(E zxSq~-AONI5TfYu7K3>#&YZ*U)`=E?GxNf6ACb%GpN|=&~q_i{4*gVeXsGJ`qbE>oh5x?#IOI2fBd(vDhfQ2=7kY0^}v^Xd0EYyg=HL26rrW*8A1*ncIO`W zOtbjZ#=Uv}QkCn6|EO1+O}XE@$JhM*M!Bf|khVdh#Uu{7xqL;~IBb1{K-pU5gOw-9 zq&mwIMu^EfJ+UV9iPqKpd1fHKl>61*JT!H6c)>wNN_^_C;^$vQ#7RG!?btT@6mU_= zM3yqbyB{u(2os+YzVwPZO_)gyrA(CeIJEX>YChii`tZ0Z7sb3-lpCbpfW&EFp23Xu zc$*3{ifS6c{N95KXC3zzXVeQk5c9po8TAmun5{@=M04T3;*26voWYFNKAi|Ns)M0Z zF1k`NA9hP8CAwTvkUPt>j})i5`Gt1Z9yY7RYq{IE)jYm9k~rO0lS@m$t6v+0U0IzIuvpcWg0IMCxMJgz6@l^!S0oY z>BjNRjvGKm(JxF%0k}k~NQ!-D=NhFZGYs*a9cv_kRb}0Y{jtR^|HwP}wWmzZT*%Wu zQ3T0fJpp;xj@AvLjLo_fgDQ&imIBo6aZMgzWY)zw@EP~XF}?Yxi#DejV_GZT8RK6K zD^8xzfXyKh*bHay{MDU~y{wBjWanL?1bt)8Xddx6@rm^(yjcxCt`q93@okFvllfsk&kmc_ ze3_Pu!*G;HdlRM!G_lVv+JO0M`DL|z_@SH8D~i&PMuC`l5YNp*FcC@NZ|S^PuRc}vc2(fe;@ov<+OAhYMcuiNHg=H52aD75)oEh|*-i8_ zaMh=$+0r+hWVWMhG7;L<2>qpA{ZOqBo5vMuc}t@7d>eud$idcNj_>74c?4(9^M_p7 z{jX8w#wAMDSE-ar3Q>w;dQiP+tW;3*i~KM?{TSdE+r|8`+HT8wHg9gIxAkiKjCzAm z%D$SXlmnB3_brigYo^{C6xalOa5F@wa=nO~AyHbl4L=z$rV+>eyp9NWTzHVR5Aj#Z z4K*iOGvfHI%a8RHZgq~;IE5+;fJvTlmnnkhM0 z_c*L5%~x|B2`WJgUGVmm{zod}SVxR1O7GPm&DsRLlOBSKZT{05b3YgvDC&hV$5(OI zIlj8##GL~g%OOTTy{I;Sopwc)M!yd@=T^I0|k&^ zVIY6EKRQ^oE_RY8y8TYRcFs2CF8x%l_rJ~7#eBO-54+(waiZcpC83LTW12)j0qVY4 zJ~vgaHXm(HeVMXizyF_IS+328yL+CaM#wlp%y>NW2f|M8$qtO>&ZG@#o9CAo#1kcn zsdXw;Xo7V@O*&|S=APk!r=pl?YwDQhoV%2OCQtfm@S9xloub4shvE%XIG6zyJHitn zMk+q#1ehr6<0$SVRmpSva^F~UiYYgDF{AEDt`9q_uaYjxb@4KrA6{`EEQ%jszE=V$ zv%T+>p0b(b(UOL!giD_Aw%q%;m8@R)&U~rcd9mAs46CyDF@d(D?*l8U z9}&T-EluE#v7(6mI;B*1DG@P+SJz}RZs|oe4x2}5SqG37nSWwq~_CI7WKj)eSEy+mO>^JnzC*~v0*X+ zT+9A8Z4ZVY<&i^cXJ=;BTaL?l9@MmAmyypWT<2*>=7vP&cwh z<`Y?Xlp6&Sc$F*=yZUPE+zo3^OwA)@l2hV$W9sMGa<%{JeRTmr4W+XfhYXei1NH^E zFa>SXgX%bLUJWsd;Xe%V0K4um0iU#gRI&+JJ~pEuwjtz z?Pw!?=_vu_7YVa|5aH-OXt&1NagqDF#rtJH$Gu6&{3@p*;fY@5QJN&E$n+|P8P?Ri zt8W*jJvkKeoqf9~8A?0)VqqhlH(EN^d6rb7s8{b_7c)-R8o=D>2f@A9J3HDqU$J43 z@9k)#GA?3%(5~*N{h~q4cXn%|U5EK!p{skLM3T35oYBiGFwxf*a5tO>Y0X+CJ}6+j=jH z+8kx%rkd4(#p#VO)t&ji`*9)tV7{T0+Z9u59?~T()WxQ5?O+gXXob@s9f&i~H23!3 zv#Efhcql3r3iwug_BdkRrK93RvQMssbFz4%IJ*OJ`qX64Mq(x~Ac3!r*5)Lb>OC{|whIZ9p*B3wY_hx{^PaaqzxTVGsH^84? z4*P0Hvf1u!^HS_r^D3Pe!;#|nx|vCo0v<-g*JT9KloT|WcgBUSa;h5+pb(im#$MFr zYx-nP@2A!F0zD*!QVnhFZFrY<(#PH=OJm$POUJOq4a>MIo-?m@s}0`bMxjJP&1afr z8N~jBKi#rAY!`T5f2#Y)N=3 zvqqoB^TRe(_rIl#bfS6~3jUwp09Wn3sz`AKRQ<}>#IZ_4#*w=4F)728V= zFsjcIWz-WqqyDFsI{)zJ@^8h9n;c$)Qm+UuchITq-bo);yJsXZV*#B=0ZE~xBTrzC zG$8tRg(riJdVWln$bh+YY<HLU{T77TBJnNSZN1{t@O_sRo3uyO?~Wh}T9pCLtF7wwCi_M!| ze&4Sa<=1^vToQp28Pw+O&@vX){NxHIiK(DUB88Q7_nb?;j_KmCEq99p4kzw?C8>s8 zTEWxX_fq0SB-%2Hcn(}jyR!UTY|Hw9TD?>#^}SX$vP&2sjnz`Oq&q1a8K_1YsOGQh z>qc4=3Y2;oVd07dZxUcoL5FGSA|+l=n5LflF4qr?iwDV>J5Zii+kG+L+sB4-6i}SV zAW6H@GN!zt8CbgZXMiw46J||@ndbq}{7L5j#%xz@Hf4RmorF^wJOQ_x3A?qNjCT3Q zM~bUl^Hcze6>X|?R+l-Z3HpuB#J3Mp^F;7WJe2?1rw^RDTUs3C-E*8~C^S?dQ7u?M#xkcNP$ut<@ND&a- zUZZ{|m1t8o=|t+hGx9Lk@_t!1ng=+fs1_^RZ-DMsAzLN+5#nFu91nPc(h>uIjna~xo- zt#mlQGleLPFr4}(k0epbJWJHpv@}HAoak#fvMQ|LMku+1;4K`E%=6UWelH2|9 zb-A0ZAFTw$Ky+;{4KFBq6NynV=dMB78chqre zmA_lKIMK?JaPxD+p*)R|Yeq+l+Q*Ee1u0YaGSfxrRyJz7;Us~b(3cGwckWRR8+Yc} zmCBTc#M9LM(cV-qWw9%^`%QssI%5PYGasXgCOKjZOTqqME91gk$d+K{ZKr)c?5yVM zY*W_rL;cn&YvF*Rb_VRemhNcjHoS}T^FFuq^+ubvtxk24OOJH%QdduPvDwY4*K#|r z4%_`3R<=?}l(D6>LMB}$lh)nllHLX<<|2?h4UFTQ5B37QFEDNU^d9dH|~2ig@j4EPE0Jw3rmlH1MqHggVV_Kz0)cE2oN z%iRT56AGtHdJ6PKMeS6maWu~;YA{*uzn(Y|XslYPQr-JY96eORg1&#Ke|}l7_76Xo z2Ik`7r)ItO55WXTc!R_i#^w7|8%V8DV^_KM7>ie9S;r zV37n{j|@ntEoRPC%1CZ8|G7FmT^}=QKz0%{aIgo3d34CAuFe(19Dd5914a$Yt{3CU z@gjRW8Ie#?Ve_wxzGEd++j?dm-MP_SE_Z}yIFz`2i=;9n#M+;%5rkKNWMNdJ50d)= z^Gv6Lh?Hs>QYUAJUGY*^i^IIBD^P_KO0u*?+I@-|qyVF?mu%M9Kymw=xk)FxJIT7? z;dDE&Lk_NLY&pzbKsy>A<-cCa#mZvEjuB82rP`zcIt#8Pn>a@V;60*btWQUUOgK>q zWuAlEvMkrdb}_Gu?ehifNTe)jo@T%pj7FRr{4p3IKL6F%4#=z}wYExkE-B-2wO-Fk zQyd)mpkHw8Iiw&djF#O!T3k;DM$04i+xLSOwWMn@JRT+zywNX=P$P2(t=Fv!_Eu$P zt^+IXcTjD#ne!geo%D6Aj%?X)Vldes*U0k>_ zu2J%Y4cIOP$}SDSQ=O60F5#`CgBb@Q!q6DKoRp`%i6<#z+%pcsSFsh7ns4Q2ZL~E3k zsA6fZfZkzicqjiTPWKLjvGLT1k?XO%BZu3{27!_kUTMQljLD@W2{V6j=~)_<^LImx zkNxdq#u=d{c0m*~z*r5}XUNv^sgXTO<$MBtYiG)g|zK+Q<#|8Zi#5iacn zQk!%ttSE^Q^VJg7y_Q=gnJ!ituXFfRI8j3@kxCx=fwx2mdQO#)#n&}hqD5}L)l7#d zca@dcEDq~EW-y0SP8BH!Hbm7?IyHQA0w+UL$hl^Q<{OnBRB8TvI|owkmYt__-1y3_ zcNL0TsB!A4Je3hmFK}QLW>6kt2d=h}HRqQr&y=W%?5eJ|PpcY<5|d5jEM<~*=gO^~ zGt$o`0`YNORU7k+?yK#ENU`4LIfXt`+l>I+;QWys^&VAm9_^R%sj$}17eYl%Yz$Hv z8U%}XGU1sTCwe1gd8)bjEAQS&=G)v<7tCr<(x?U{m!tzyA2l`Z4JmA$)BFhxKeh-q(krZD$TIh!wwow;=x4kv1b zmDv4{u1NrkiJtc515i#`&YABp+8o-a;uFqpUZYf9Z6rmAu&K{ra{zz%bUKhZ*NMs% zxo#j)O0JOuYfWv56(}BbU`d*(X`rH}G6t#)TcGTH7!KS(!8p;Y%v#_RAVmweitdCM zqr&XTm@1m&S|q&vFy3MQwXF$wiML5iBrz(`}(&i?J|fXuzcpb95J-0!PP*ZJ-L=6qQudJ zMaqCdvrIAq^%Qe&%%Ngcy`(bXnkJlkL*_+U?3eYsFn%kYfWwM%a?er%b^hD^dLV`N zGp-ocZ%jzPeHbaGNYA0)8%~spYwQcvJ8T#LQ|^jx1YH!@t^ zGze^8GmcS#qWV!;n&kka=Y6hodP)~vycZegf=eM?jJw0G*v?+cO|nK=jcAYoi3D^ zgdrA6exy@&S-@^2-9QF&j!{C1-M2pVUE-ViBZm`}G*FY#ha4>@|2wUs<*&p!NI7AG zQpu?o&c{u)EzD&*GqIc(JCxv?#!0AB%i!orsKyAfeeYVqvVSRCS&TA|b%BqK!5G&jlTm`PVfW9p$;dn}x=md!>gshie_CCzCx_D*jX+gLN1!u%a#VP^VIVU) zDq1W(I1|vG9070TU}r(!D6mM9@F1vRVB;bY<6=c^715NLG^c|##x3pl2IZVQ2$nxE zabd`i+UmXY_r43{h`!H2S>EOdGDwZMGa^MMzlZH@uHe%$Pvv+q}XcJ;50DD zK#66rNRY`zL8;2jrdck|JoTQ{<9{6=ENVs*0jnYuz2RU-JHc2g3j{ZA0eUxZQG^y# z*|F|svfUX2lfytCIo5MAFwJi=Hwky{!hHTx9G*;RM<~tlW2rnt4r~S?rFVc6Ijezi z#&^x#oY0fRaNkt(Cs0$xn%c%KZax>ARXMXt!R5Z(y)LVHQJ0vuM2?aS9t!mo&wpC9 zC_2l);?;j!gWAUTksH5s%~1lv1~ScoMGh5pJ@o?|Uk)4}FiJyM>y#_nZM3Q5j?Nk7 zw435ZWl}m-T6G7@>cYYDB!E%bRBkoYKu$2&p}3=#TaJiaw$5T28F%#wqo!CY z6}bph6+|m|S7$b0>f4t0jaTl^QIf*v5aaclCIF0@ZgF!< z1D=R6s_-S#tskrv;(oO)FPL!UC`I9%q&x#q%Hvgae<(3om7P>7Kw2%2jJ9sc_{mW+ z!nsJ9(BPEkK2Ix3L)bp78a%9b3KEkp<UZkrLgD>$$yAM0ZF&%<`U{L|s->CN?< zMMV}V^rs;wqgZ+{ga9MVFHR&%YP-6G7m}mIgH>kj4!c!(+Y|0;p>!mn zQytfzIwU^;VGt_W#Khx{I+;0 z>o2SIx=b&)ofzspHHkd1pv#XAh+(M~=r^)xOmij^$+)SEJhh@lW%oE=iu!p+DB~AI z7N@H_@EFtHXZRa)h`)Up=@g>`b#11UbstwAF`GTXd2tW1xsM-Yt{$4iCOF0~>*5W$ znVX{&bO%E83m3l|Onr=r!I)efBZ}gZr;Oy?gjdH5q5JA=nR9B@G7_E(PcdV$S#4)u zjhW^qr&u5_Boxmjj<;3M4O=Nuv|?JYNXN&MU{CXxyqVm@p+z+sWGY!G(nOngl|dr9 z)c;=HgFMC8it02#5Kp8IC(JFG=O;WCN|aJ?lkICrZ3|}2p742`;@(9`0}sV`l5aN! zNK~I;AjnXvJf0+sgAthraRJD&%Qz#}!KkJ_tH?Y^XIb1FV}Q%-6cAC|mCR({;J_gR zhiKG`Vr*~7Iz!N$nMy@>bh_(e^SEAZ>uOix)#h`YAh1p)2T0s4GZX;p72Emkz#?;? z49bC2M9A6)d&9^g1z9LG?bi`M=(_=nRAtcs6SiGbJ@?7p?i8cMg6%2(|EN2=-pGwB z?|&6#uRIr|S#K;dSM4}P;;fxKn3?Qi0RsWmO{qERCKZw`MgH_p6)9<|$Wv_cv`BFl zFcy)WiGHr)sq^|jfLJgI9DO>gfkh1<2R@VC&UHQ{Lu0KHb5EGafccUO6%_H_lT)S- z4EyAu)Pf`Rdr$`Ew4?LEnLSeOFB^=aG=p_83RYuU;qu;)lzF695qN1>WY;g}eXo#^ zM%-KW)=f>w-OqK0vDqW|Oq;j0o8BGBFD!hfD7Pu}W!UYNF$~{A(^1+IaM~C%ie0KUAe{Y#E4Ns!4dI80ne3#5-nX! zxi}_D0N8b!Z5#6%PZKBX>o`s6oF#ep(?p8aIZhMaqcEt>w+tq#ahLd<5hz$=qdJw} z;nJd9AsAEdwqsDc?)YbOMo?4^=?rLp+q1j#d@)c|W6DI(u`>lTVxrn}LqC>)>Z@{u zz#-IkE^(t2d^Kat`#~sc%D-n74qWqHvoT_eW`u$A9ALMjojcLnzXp1XW=dkC+$8Mv4R9)4i%Z*mdDH|!pY9fG|bv$M2mMXB@- zBAzesn#X7_u$v1K+n77${b1Hw3d^_i7dc6kzr%bcfwn%;*qnY_->3op|4#G#>FU4B z^l<0`vRzhfv-?Aq<93|IC}rL#_LTz$&RoS1ipu^7UogOfZDmw|=05vK4bIT+7Mhb3rOvBAQ4Rn)KU~en zit>_}-tGjp6R{DIi*&Kh=?Tm2?f$c@f)JCCC zV(>&MJnCWV`cw8UM;fD^Q|?O!c=+wSXdgAQU59t^@KFl2%JlMpfK5aW(>u1fGA}DK z4Cl1F8q#Q(8a`C3yuz3B9B>M?T)i^fJ=DEQ)8)L zOwQGA-8s>B@_ZF6vR_rm2(n2Ob_mx3i*z6Y0#5Y=;K_~_z6=77alHj8?5STFdA z;RVHsipQBRICz8MROrwOFJWcy=RQ?rK+ajv_m$tmds@B6vl*rEz0MRHlLH%(VrQOZv<%?Put-gRFjeT%wOq-^ic_TxecFCcT~-QK z7}vszb(%2##I-HN8&D+F;%4 zA8&4ws=g`8$E4ipUlPZQn(`YV!Kyc;MJ+=jzKns2 zdFXh0I*mF`rC}mHp@l1?wTHQ?)BFAA{!~_{tkx5Gr!uXw93#A|cu~_nXL!%;2r`r3 zcI{>nWYo-$8`)7;9{c1jf{fH+lOd2hb))3YJ3HpD7jh}=S#M&-;HmL zvAOHaGjgJarJbB`1iyy!L_M}=IPn_jGlHVEP6^oH1Im8BZ%d_u#LiX#EzU3c?!&D; zc7ixqh7!4g4-n&c88JOK59G?g{J1}D@2)5{O> zjl}`5f!n2+cqRk0;3tb*SUd%mu7ec0uUJUHIJxG)dgp4eip5A#@%Tj2(F(ouq9XmJ zNvLC2mCebCa+lulNEahTNx3RgSI9O(uEKY_OY^=oC`nhv8VBHLYOCjP&fh0a*m=(t z=`8WM`_k~H6ba78kB`P@K3Jr`M09&5T#1x_q!X$dVmVZ#xAbPH%f+lX$yerwQ49{p zIjqw_ms&^9i*YaFLa(i2Qcjug&RsG9VuL%J>UI@!JnEXsXieh|YJ zYUYX~wr+!yd?kJaOrR5wfV&PRY$g6%b~s#pF4NTXoW7_ZZuVJSeQml_9u%^<2_^nI z5qNwEumCSo_RPTx%1HG#b`03#1&C3O)HLF*IM~2zy8tlCnIe810xK7pODb$lA2Cij zbt3VazGAF~stXv*k+17B#_6d}L|)Z*jFMI*l=>8qrQ#0DwXW|N^B7MhUe$Mud5s5v zzlHA@^Bhk_Ue|Ywd5;H)35CYf3}Q>LU|Cp{PHE&*8TZXJe;%4$wb8-}mQEyIlhMMd zm%4#LY0q^TEtHsP6!_4{C3WudvDz7(sSc(h8WMVhklwoMW0o8<#d|>t3#Vy1@o-mV zo^cYVL&PgK&nT%=5=6cr{nD6l$nvhsJfmE!iNvci&nO4W4LnM-_npl%%ENLZe+xzn z<7T;t*KV{>x~P)*Tq{!c3k|Re^{R{(N*{G9@tTYlN+#6}?AXq`Dx-x`OPz|mDx-zc zO&ug&v(Z9zF$aDebQJ0g2v)z&Vq{GmTN@B(4=N z`i-z*GfsWBZ-ol$E$XNu$jB2h_ZYQQFLqg(ZtJ4da!c2TQ(E0U;dqhhoKUwQc6qr& z|Crghk>g+)3q3B0I$UdP^E%DHWScMQpQ+UEmgTpK^FGOuyr@bN;XaVQ;v+S4T^E_F z3nJ8Irh=Kgx7i`BHhEHK59w1mPpD{;>GE{H zC25zGcPv0}c2lglV%a3t-Z%Shuqf9;`hj53n#nPFD`9@Iod}RAr!16#CrR8(!rrGz zmE`pi`RL$Oa|1u(z*tS}5N+)226HXW(k<5^iy~rvslTMz?fzd$o^Q5Aaky4K^zZ5R zX?sXZlyM>`l}e&KA7C9UcZolDjFY{p+4357eqIQV1VOK5a(_~XdMqBAHc|hWPDe$V zr)jA6(Z)l4zciQ;6{}Jy`cIB%^wFSDpfj*K5dKi*uU1_XDqs#RiJ?PQC7WY$Qnpw*5=BxcyBDD$94}JX zThP8SCPDM`^npVI*o@*sn^)n^O^XV6q|a#AS$r)ZoKtMKdb%S6SXpA_ensk18mMf0xB0y& zj;&*SsuC0@POfs06Wq*Xy|ktf9A63)8Ql$l_Vo3H^PC3z;VNuGHdU+4&?s?%aE8@fdCn?s075e%XDw-=qgcl`7cep(v5C$aSPK2lnBKW(urtnmVwqO)qn!qMRg! zN`Y=Sx0KWQ2mez6FAx3zf|XL^^b70sOoy?%LvE^yH?wberDr1_MZPThsq!7YEz~4>HZQs zjFbptF);Qd92zx&Z)RIwMZX)wJv%EEH$VNK8YsOsCFqdm$ytf1=7&1f-vpt2j<8z-5PLj(1QBt3(U+5tsYa zhZO@^7~h`pVd~#xqznSHN*hU8ZEn(}JfxLw3&9>NN}Qc4+XQSI6OI_b%I~`q6f)5J zpOl{%S#`O?vkcGXDcKhVjuJJA=%xf;ohWjiC{wQWGNdSdN<|vAPd!wjI(v6*tGg5^ zYVwfkHF-Tw*HQtK(mc+EZY@faGS-n-1O=@G_V?eJ5jA5-eMW(OovyCgQ3dlkAyG!w zaggoyYp6BY^#7O{xGiO7Q96ZFIjQC6+Bt`%Y!4<_8{hceFAi zRT7C`6?_wE$pp>hxT$qW^IxWkr zRhRq^juBZvb;Z~mToy2{+jr&&TVPiqPeJXZ6U=njg2@Dw9-S0^9CDZD0MOE5_2^jh z7M;wWZUW%yW9L?HzW$XqyHmYS56K-elYr8pi-pf=pHntT&ak&Epz9M^L%Zq`wYKFF z7Eu-jvH6i+mrqH)smmg}OYY0!Sk#%`(~jarCjKaQ>Qn>82@}_ZjVu>1eYZg`Sb`h#SHg;_vMHBbbWD?IlJzn4y>jawo36bz z`NoJxMeK1w%=ff0M)$>IT5gg8S6D*{uSx2MG3!L#{3V^+ZyfAYVFp&y%*Tn`zXL5W zX_E`#AH`rD+zh+v`$TS96qX_g{*1 zlm6#kmtAt@7GBg|hf-RbO5Hi;RdA!4lpt>YwYy_@v#J^41m}^zPMB}A`l-0NPU_?# zOE8-21Sh$sPDXYWs(Dj-qR_`|)rnoR$Xx0tmUvQHQ&QLENx6#2;n2=WDIaQg+BQxU za!)zIX|5?`(cM$dU$%0d9r`0KGd)Os%qkV+-JWo>jVQUb0ZwphfR!5!tQLUh27%?z z7Ztke_le0KccedHBF;3UnO2Lw3o~-X;lxfYHd63qfmSW7Xj2^0el*0MYgNNx?!ZnA z2k;NS{PedU{{H8WKYaY@hrj&r_sw7b@%h&ue*VS(@gKiV2S!RZO#%+Bz7Hzj6&R`5 z1Of}!J`nSKU6r~eU{L`t1WUidUU0hN8CaUr+3Nd!v(Fb5^a?-ZfG+imP~`Cb9uhfu zf6cag6~|wFOm}7RXb>OE<|mu&ZT1r2V_;F%SsiY~p=<^$`C|9In>CQ&{8fHa%Z!YH z!?4?j*NQX+Bht$5C7zMcadhN8uik#+gGH^ORR;@ZAi*&e^NS7N?@(i;4CcTU1`_B7 zt80zDgS83sbvUGgBOD-d_iRYxzCm)8*oP$Z7H)ON$xujE_}3No*+Rs317 zB!ZHla(EJiJhzElA))rZ)2nr^$ioFe5r4kSa*NmcJpvxOlO>$sreOKi7Fy|&V=6?(D|HQ zD}M@GDN?@}3Q+yZtnVPVa}E9E@_;0weWKsVF!*p4vd9ay?%P+&f1lE-$-Zs$+{*q9 z1ehsGS1!^69bweKL^s%3;NMdpg`~i=?XkqP(3BiJJPA zek5o==|~y@hT%~T;sBJ&;bx&OKv=hTyU(_X`pweYtg6dIAMxgp-K2GPOmDI}Pb=i% zqC`_7Usu7q*z|d{8-uOOLo8OeBU}a>rJ)k}0o1cfT}|a9xFcnn1(9A;qg;R+sj5PN z9j?^1-*e<~>mkZGZqf&{V+1NvE$l(7VDe_`LN!7ZLS1S%w?i=fD6NA?N5~{-c|-x3>@3krQ2!82~)l(^m4Z5G8X#neU@R=tFAe?(lPR>^gm82%`Z z7nKT%eaQgfD5}ebB$V7e*9YEKVYi7#UHjef@n`*6hq<(I}*yzy4Fs4P(IN0LCaqfS-~h&;^Bi`p$m zxE}%gPWW?O>C7U`!KFp{Z{H`~@Amq-+9FF36s7T|6}o9Zu5e9KPvP_45)P&5Mgrl} zZdXpbRSbM)yL8fb3v`%tKVM9T%5-QAE3gy@@8QLs-Q{!`SHW>HW2cfdn!)lHaS)4^M(#gCJLp<=Aw+6Wl8;~@ck)~Gl@-?uPajN zwY<60sit$I{7R2S`o>#r72E3~&(kNpo#Q?&w`G#umPx+dLF)$Hxm#@O7t)ErmhZ zOp}xcDU-*jE)acbu7!)M^Kl>Q4xnRDY0_@ox_G z^T(fm{`~iU{4b_eNPBy4N9k%Qw`ba1st&J=lJyvsCC=)+c*LC~QrHz_d{Lezow;~w zc@dTpiIoGJj}p}_;-HkzTSI#%X?JVdJHFbtX3Ukn2o$BS2ZHjKeOJ(jDI8bUahz{X ziPUcGQ#QkRziMJQ3Okc09?xOIJ$xLvQx z1p+-F0?t>DNI+95mJy3Y>~7=LD8bzmG4@ zi)wgLo*x00201$c>hVCD{U3k(iweN&&HrSI>~nIwPyUpk=7lLr zOfd?4_3J=Nt^w%P52_Gb^TM&fBJUtUCw5-3yb%kRKH;42<(Fs83{H?o7I*3oO^d?KUoei}fwyZmypX$Z)R)7p1W2 zw92{+dq(N^{k~k3#-`II>$J>zQBege7`3fwtQQsMLlK_leB~jEOTsT+y0at z4u8CgiTV!IpTumTvupJ?H+4}bhwEbZbV=85h;yVAG1%m-E6vb678%7nKP}Fa8lvsr z_(4IhYX_=Sxk)UCCFAQc%^bfom_=xk+#P ztzDEA>qbprW$Pftx==7Ftd6uAQ;hW~oUl_$wq#LMtUm#w!qb22IajPh;e=i7xkgxT z0!9Vh#Bu#2^P^&Yi3zB56`)uzf&)ubLr2iQnvWHw@B4;!}M?pUK6#l2d&{m#JNywq`5*hAz{OX=F|aT-V9dp(riqxHD)s!pmg9nT?OGeUG!Vq88!_KkW65 z4<$_pw!_IKVNrwJTr2qYty5d4JKIb^L}!fB9N7ACf7;$%ebO@?Wn}S! z--{g6JI+wTy;E`NN?4IQ0^aawgXLgRbKRk`#!cRD^Dw+TiAh@n(@36Vab(1u|O1^``I4Og02hJnY4@ED_}kjQnJ zC3$iv^4ra^LXF-roCvSFe&P5PQoUt7U;X3OOEkk+s!;VxfM)dbE9yh`xVgLE=IJA9 znuVdnXJewrNI_LRc*JmIa&7L{2BkQwMe+g$Rj%5*JG}Fay1r8$gkca+X~lBQbW&EP z+giDZ*TwJZ=XqUbb&;b4yBJDqb{O~)-JfNcQ5gzlpnBWEU)Olx)5ReTm2o0o(5_YJ z&VS=qN->nw>{Lv9$*fbWYeq^`UIM1nQ4T2L^!}7MVcBVvomqZ!R5Y^O!WlWSz5~Q5 zT%rZmT*Dp4IY`qut)Z*f zN}?^~EZ{_ViCzcQ_wrq<76z3y%;RJMi)a)DtS6XvlP2XMtt$Q7AxW`r5kUH?R@J+> zb{*rLNKvj)pk<@`IZ>B5ZD+SxFrXSON$iJ=`;xKV*x-Gd++CROMrrXz)QzdUlqB5+KAEC&p+SXmT8(-kLdxWhsbbRyvi^EJFH#JcpU>w zeBwYBgnC?3PlUX8ldHQltx_B###3_X4Y!go=T-olPmC=|JG;CxV<<%!eSEzvGmBxZ*+Jg;8u~TK@d=$De-u{Ev^DPe1td;R`y%{t<6`y^sE(blph0-WvU`MNnNTPr8ZcXD#FV6B{}{EYA^2Ui3TaCb-4t!|k;ww=D1h(|FO(kc_|l0&+w z>NGvH4KWvZ4k*dusl34}VB;=@7Ox!(%+8DPlp^AXG0+>|4pD~vQmu85txByG%zh^c z|8Nyc_3uqkQ<1u@j3nFaCfl~jio*dVr^t}P#momj+ctJT(^lbxRjl5;sJMop$R}|> z0~I?8wjC2?+9G4_fPurrd zul_eFcLr@;7TI0$YMt==&KOFvST9fSF6?VfGPse^uJ5_@w;2n)Fyfx%VXttz&+2-g zUYFT_{)3`KDHX@+0{36_s90?Zt`vYfCEMC zj}pF!UT1mFZ|QTXsoPy7>PzQg=*fVH?s480$)QS0T<1SZpI9MA97qv|4$M{9;piw z$Lh}t%$McIKb6H}9&QfVO{y2)UNFkdP-?_d`b5P2aU|NDHPr1NaURN)n4VJahuwFT z@<9D7kR1-`ap&I_57XIEEkc2w*@xD3!$bQ6&GFqV zY3xN*5AR6xZT(zk$Kv?B#QLTz@;bw56fmSZF?G#k5wJw*GR~a>r7~MI(o1lAE>o2z zH%W#=L`f1yD%6gpYeVDtnMrpMCsIa$Hu-bQ4hP8^lDo8bOaQYJ%1CU#d%z;Mb(QQ<3VSPRp(}`gF>FeeH(%>4IyET^H3R z`FeR53B5JK{nnTsmEgpSiSPs=R%%$iEy=dtTx+jN?`M2Wn`sC%GQzd!oNZHmgauAJ zXDgiA8cQ55c3V^ctm}xM7Xx21CK~VI1k@nr^bPsvnbw^dc*a^(DUD>x>jA zb|S;0F2eoN+N0hJL8H<#%0=d)UkPY)ihzr3TWK@>WPZq0y+V=XI^Z(rpTC?AS-MgG zAy2csy3fjVcL^{mNu!LB)?kO7WXN_gi`ZqlG_jP-qrw^qsmsh7`fk{_x|^az#rsI% z;-QcEBAvE{t~M%08~q<<&m@+Yi4Y zc`;d?koqAN;2?qHl*e_bMqzvvhWv^~+`QS>%B#%Nhpf7wFo4o9j+na4&>A>c*SFK2 zYGPWQZH#z=>%kh@8%SiktlDPxddoTTJW&H(+?Ny>A9hVR(f7y1_*Rkn?l^^J`{50S zt2j?oK`Zhj*-b1rrJew;LXVmakR#~ucH zfE=LhP*uR`5!#-SG_8@e%FZzfJP|3^ND7nn@yla&xKmF5 zsY*6a$-XFXM~iY8Cc<{AKJu%&ZJRchayedfA2HZmDf+v>o(Lr|T7eEFQY?k9esyq#U3^9QU+nm(CKB4miq!vtRq{BfaJ4KRH``ks(_z!7 zD3RhwePrSIrC6PQOslEOH=|Zv1>k{-;XPPYDpfg?eg~ z^mT&xI1e%6LV0De7llF3ciKPHTO1%xGl%=EFHJ#6v$o@`@W@b?frg|is)?e$@W?)^ zzfN7@J1aO!r`XLLIAk(M8{;LAaa}aikiVX5Ym}{vY&(pLFyk6%)GrF!E4UD{wyTY6 zGIlb9q2Aig8P{q&jd^9CGs?xHTFk)VZk+2kHe)|)y+<5-&wrU&s4u%jCr+!hKHcNf z;+&wCKt#S2fJ8+b=mJOENw`^O8!X3)a<82dQ=J4Jw5 zSy7cc_YDU7_NaBNrcI)YaUyGWTy*u-2TIPgqi1Y_`Xe6I^pO3YT&MN^a$HCepsZ-#8_9MfHw*S5v0o989@sNBr>BwZ;;|1i(|9$oc#Ng)Y-P$D%7;3o9c8_ z|KF=nLIoV9<1DEkK=QtAk1f=B=^p*Ck;A|X1@)pR>}hlFld`@k%H1(3lX{O+Q{gBD zXRTBqz|=PAr_syt*m7ml<4`MF z^!ElR;B9d@9j`Ogls`vlQR{aW=&OCvYB;l@(WQnt`!kDDqJ~%-A?k6PmdvZmd?pv= z#rjb2*@B;HSNF)bwTl<^8F8Z219utF<3GA6ZqZhQRM;8OeDN~bJuZ8FlxAI5R zqMvY4T9mHhL|UgoUKSO%IBXhfrvPASQY;FKN<%4^A_}0~IIP@jM?cbDA7+`UNT{G8 zREA7)(_7pY$#$Pst#bZ-h9gDQ>KvrPq20RjjL3XvI zs8KT~DGk<3ikdcakV>78SuH8DWgH~cN3%+t>B|AAkG)x9=Yx zAN~E!{nz1@-@bpI)c5x_0vY8f>8+UoIPMEJ$FB?-S-2z6XrXH`zte^2syZ))jGWP@ z3>;X3lWg{^v!!q4zXvnQiJHjVnS8eLr|*D_@}}I#pp_n1dS8kdHp>0ten1Dd4X@o~qa3g^%jMphIrjxHcIIG9P-*tHcIweK~ot+tH^?H!DM4Jz|S(T++?FX zFgNlyV6u^Fl>@|UH`z$C4H(J+8zesWF26HzjPkzD5TEg~UDG;CAtP0*29ek9WupYu z!PT6+Q7oX~^1_kRXELB#5>)R%F$G^Mg_M?Wv6hpgbk!SN*6ZXWLDO4I&W!=MJdydg zkaCo|dZbq)19B=ZjfRdsnRCsM3_PvqOM+&i;;WkPG1;ANlN_(S%~7)IdbW@QO5^U? zLTl#EoXWB#8XUug2lcBb7f%b?6527$ylIms5Oi0q*;y-ih+JtZ-%nOvx_%L!mnSn$8>s-jl0-76HMFc%lysDg)K*@}sW5(yK zk|mIlGUIXF^@u5TbUDNvH*nmLe=m?m9+YEs~o$MrD-Yi8T!qmv3~?{Uh=269Q^ zHCteGw5DvVz-f^W60f`GL7*hb36Z`8cFZzeWFUY>l<8L**^b738O$G_lKkpdy@$wL z{9Zog#j*Ke7~{9h3Y;YQnX_GWcZa}9lb=CedEQx|WXjJ$vo7@L2zV*#w;bGi*`m-3 zgE5wCF83OzU4DjG;1cc&A>%a62a$o@tt>hQPzvYgh`W!~y547;(D@nU-cx0N&&;{GX(?!=A4VzAa@uTpJumGjY|WGR`Jxfd zn69`80_CaUZp4w-I~1`9B57uCTbbEyQIxwZPwJxF92HQbwTtq$QJUaV9SotaQwAh5 z%zJHChdX6c5%`i*pM};U-|F;xlIN*^NVfYV-=-S{krs8SMWd7Hz!-N#hCYpgeulnP zXN8s*4@hL2Hal$o2<5%Tp;;2&l}~AYNbb^`w5qd*pQZdWU?<{ zea~~n^{fb=!De{Ws^a&fMG0g>9XhYw-z&byICX4wwu-n*tGg$~h)rJaceXfnY&R{q zaHDg!u05a&&?3u7u7FQMB?dc{Va2%rZWFX<4P^L#6@%E83gRi7XzuIKkqi2pzu)~|fbre7TQjnfuu$HnSB4rOW1?2Dh0rFmmoR39+) z1t)9mbSD|e7W}4}?>!d87>Ql8%@?!Ilmf7z`?&oPe9Twv~#d;ZC z)X%iFAL~Ue&Y^OkR6M~0s~z^3-KCq|>2Rv|mo>y-E@KR2kgJZ4V-tPK14V=S4*gPfbImYv9EAN|zm}6{-h|fg;=_ z5->jo)?#wU7SORJEFP-Ii_KZWLg^&O#1|BrUxgDec0q@kv7A+#4O!spG8X5=^a!uh zs@^3>y-5*Y$U%uC%cj8s+@da^%GK+B({BH=xvNY2y`jfA*Vzbjfz^Fd*H4=-MYX@q z4hQv?;@l*ZA~GSNANTVv&+5R?21RbNs{gj>JTTv^=QO_G_4R|E-8`JGpP?+zu=jT- zB4eIbhpcV z0VDTz#RLWhw`5Wa*pe5pOV1xql{UOre@=f%?oF?${kgwO56S&zdwTTK-Dx^2F8i-O z-Kf7MGaQ!@=T?wz&Fsp+6H%Z)7;`#V-QIr{`M>IY`mg&#lI0bC99!V@aj756sQ&@K ztU!I+uBfj&ieGB%m$#1KByxwafo+)juEocc-hA zKjJeM`9y0ZcB6?+k*j|Sy@Fk!lyYV0OB#Y(&oFzP%~wkj^~{H{$GI>=C*A6Jo!#DK z)m}ZST{&L$z9v*yjM7ODJ@#QkDLn-X!<;hqU`8zTnz_ z^Mb%1rGqP_AA}6riqvk7Iium^w!?oZ)7z_0$<1A1us*-2o5w6y0mMyqyRR|gMgk{) zOMDgwUj&hhtU8za_rwC?k-(BHx=#+psY)+Pwc;dQ zm3tHcPJX*M0Z2}D-J{4s8mgB{2<{0jZeS#Al(D_5{0m7@nVMLgr|74qBB$fan*VdT zNEWO*Qc0TBqbca4D7luQQvXB21&Jw?jH}iO6#dCeLL4i}Y!@PQx)4zqUxgvRQof*7 zfY0ty70YDR1;>gKZ*_6DwXU;mK?Ak-D2P?mMrG7%T~z0Kf6~4~k|#J)RF5W6fvSXN z^YlyF&qQ<`-hoI)(7>ZAl8Hqq0N9(Nyi**Fj2gy4LaDXN*bgO`exUGv-;q8r(;0|B zm(48w(ihf;>~y@K*$buAIu*4&yw^81wh|C_Og=L$YW9N?KN!DwYwWqkI{Oe%MH`qE z0-aCV)J2^fu8ZB%C1QXmxz<70Ga9DmsggxWQ9~|@lmNOdE(Io?bu;agYbE6Tw5UQC ze6BC<;jr8Eeg}(6v`j-Ks{lo1U4}rRt{G?33}28n#Hq4QW2NgLMY&DiBq>soRoNNH z0>h04otTvmO3%trdSM{U2BF4@*e3VsA<1`jd8$z9vk)iD`v0lB)*i==?D|)P{Sway zR#@+)nbQ|rZfKasUrKqdP&q(lhOkA!0^~cAKzlt zeVlua!Ac`zxuoaJ0fO;#NMWn8!j$M?a@Y+ZL!_=ExO0Tv)KKNjD&`}dJL8&%Vz-;G z_7BD8q5f7rl$#xTC{Kq9>$ylIRBXdAZ)dH6aOLn?j`Pe^t(l-AsOIi!Q{Oxl%@Upn z3y@ByW{B~4WTR?^E|;L6FS)}Sp@nWu6r4`P{bGK9=2h`TPZa{N<<9 z0fY7cawLeaHQP#^=g}0{q4K4!Bw_x43Bog?MgKG17R#zc`{t(D%%7_5qTXz)4Z5qp zoemW^MrKOJ_LCA`oX&^pyfo6~$D98OXLjD`$n}4H-0$k`eE(Df^iu>(t56{(qLQ+4 zJqG6YTikI}{}6BLS^Jl>b+z4<%O1|B5`Fyf=kxlb0;E!?Il?3&b*>Zr(G!+fY-g04 z%hy!}+EtrkUKym%6bJxmT!54b4N~)y#Efy`EkiG`sVr$sm_UOGp(4-A3xDUx2!kh2 zuSt?-OtKjvr2od;FY5i>YF%yS&F$R^gcGDeXtM?t*>=FK7*4FQ&xeJR&9tiLM8ciTq<8%ZhR5HTvVSH(s)Jqimb#UW zxjH#+N0VZOcF<12O0EJakg0@~NHx4eYN7MN%ESRSuRIs#3Q_$LhW%ldRa08d|9rVO zFqeA}PLLv*vSwY;3_t$T#Ac4^jR%oqO_f%%-`T(0HvAqwY!nbZvOE&Vcz=6nGhb1R zsH7+tvVZwLQ|s)`O0l+MsZ9kMzzK*HSrlb^>9Ug;qGU>(pbZ^qGr?5HAuPk)K_f}? z2sO(yb6zt-op1E(P5o3h50+^6w1@1f2#^MuDNl34VzU_%ZI^lT)I1SVO=ZR<$#{8-vR>)8$y|!Cz|l)(WJrqN|j?Or%^vkQdY=~YNQB>aA4oz0K*>A zLwIAZO$Qm>Q^JMKqLOfTlrq?a-0Y!ic~OF&yiN zo@ZH`=cY93{_NMP<#Jh-^M~4!TdIw@k>T430;Ia8ILfhzroeI1$IxvXCFLxenJe7< zim484*GznO^=-AOwji3ffT^yT$~7{?FlRX~<2o2EVYyO@Xx_*9)h>mar{{gV5d}z* z%pxW@WRG^!I1y}-4L#2S>x>hc5$5WLSibv1ZHE|(?~8Q_-q#l(K{A=6oYH6mJW3+% z-&H9a8qvMBqs^nV z&f3i`e|NpQD~o2gI%8@BQsz1p?lDn4G9g}|ZaUK>b|rTu-U;oseiQKrlG6_}Vdrw% zowe>BZ|C+Gs|i``s(J&OwSwfiOugPtX(P{VT-(Sk2~r;7c7(&sH_NdzY5n?-Rq=Gc zeX1Vji0_b5k~Vpwb;8`_odPnGWUUaF$2q<-$8SX;kt9C;5k&mO4{H z_QQK`e!@k)F7+ABH4YkA5oC%U96Q8O(ZIpZ=maaf%YzhkDDJyeac9y96I(9M$R#*v zYr&K|IS*anMZ)0G(+^2!5{g^HSCzHqN4>PEDVI(CG+*3RXS}N*F((662wxVaGrW(w z&Uj(P7lI1Xb23$(@(u9Vv)*#7>valD>;J5gt$?u*pMYf5qtW_Tjl`haX;`n3E}P zxbk7z%rL4A;vU}AtNP!oV)rlGSbt-3x!gjV z5kP4!f&8+Sy*REM(^x)4@6imKq8MkbAW3f!S+CcdYH`1-m&06-=lfhl)HmZ4!K>giBvc*n9})b0w7b&#*~+>!w)N$Z4o>g9f6`w*bzM*&jXIt(;&A1C|5 zd_ts9f=`(5vxF&Mj%fcFJE5-KQXNLY^2cr zPU6d9us1oa!%Jhhe}LUrb!@Oug4!Xl(AC|su|gL-Ps2JiUm6=NbjMS%u*W14OGe%? zrk6U#AeE^DU=vOr9S~vnld$PPQ%KMCKOMcP0v2VssHBK@>NNdnE*!2qM`^6Hd?k7MpQ<@{~bNahv zDay_B+AbHIDTBnOPDFb}BV`56BV=Sx?))Qc1y$eo@Pf>{B;v{+Be(I46Y|n;Y3@=# z7&RB1qJ4@B!+73Qi`7HDS-wdJ!&-+RU9A?Z8s6M@8^P{6iZgZ`A1-J@br5dk?7EaK z2QT*bu`_F!IU-_^!j_Uq<-Qdidy$9>6?6x))F?Jr6Q(ACP<_6@#=u)W*41Wb$IFXm zzg@lIhQS7APGO+=OQ28Em*o>j86+MdkP;+S@0`QDoB%LLLE<3blhz}rjxQvk654J% zgabR?F5^e8X>y>#^R_`VN>#?VGqn3&-`-m9%%@_#tQVG1{QdjGq5xGsFy$>Qk@VFE z3}DiZw0M|QxlJfH$LJ@JUkdY+&wefT>+*XK@c-_uT)!#q=GL|Dt}w-c`60JuQvn%I zAQdjf5exJ@TLYFjTTi%|WU6y4u=!f7+j-6dYL~gCw`^4w>m7_b4btB-IL!yi2jd*x zo)MParOhdk&ff33HjmNSP(i|_r$QZiGmnZCCcs6J@FnEhJ1XU)=`?0o3Mer}Jh2j& z#5uihs~s<2>B-6x5+=Tt3*=icy!M}B<&Wdz#xDUAHpHTciZF5PcGY9y>6}rd7bHkQ&VH!O*CgotGx6~ZIHim- zI#j4ysnQ`-{cKWwmZ-+KaAC=lc|-i^ByacDTe$w_>oCRW(V>FYUMb=cqm7q=fPaQv z$tIBqs<5O)t~185@R2@R{SYYmQo{5P4Myc_r1U;i|Ma>wxk72;&l{q5h6yr~kB5>a zc2wL$+i!tCf4!rF1dZ!V0EFKfYJBhh+SanNDFFLR`N`{`@M_0SggL*<-GjAN1N(z7J-Z6iI_n?a|z5ev8i)ym;nhz z9y!u+W1N9D8{=(qNQm&`aD2YRa6gHd3Lt1&qft(AIE&-9m3D-hmo$bUrc_YG+)PCF z_gud;l~sJ{GT_^$-t4Lp)_x$MX$?hEN5;w>)U#xirTILG^#^q{?7vnI^Sk2AnX)9X zc@05ChGA6+tX>z*RB&lavT@0@5+vu@Rp-&WH~zWu^yli%&^bkfaij?gz*_&crY!DZ zafQfvwm1XbqOP@+kS%p`MMsO)!TAHn`G-s~nK9`c;y>1N^WFZ3#fd&bV8Z4$k!H*A zgoz{7kElz#95JHM(aj;Kp&}x4K2=)=CO_2?u|nrIhp--TxW80bp<|nO3@Zd{4Z#W> z*_`sVdM1gN3M+J6^NwN7r$GwaJ9^J6cp{*%REZ(X!?aME-x-!FUEul!Nq8PZdL*QW zb{R%Q3QLntL+af~7eWfllu}3seWq#Ci4k$a(xlVA(i577;{k=`NT&gHkM4zl!ZM_H zi|9n>7MdFo%mb7!qBh6Ycl~kHL;;27MyEi1Mssnj(Cp~l!aC9M1^1Co!s+xIM9@c? zCZ-_aRUGyPtwd+^GV=OI)X|=r>e}VN4pIyyjuDgG4LOXQopWz)JR(e(;vYvMa&Wt5 zZ@6Qk9i*~9jB$whL|DDFj4_An(4u^(zZT!hWm&XqyCn=Oh}Ci4f*46Eu8zMkW!L3F z3xJFYuiMLCG%+HpG-)l;X&1yKNI%%X4dh69D-K)3KAqStIW?Wb*SS=?D|kd(7dnHnS5-d z;O3xOSySq`b3Ik_+j6_B>ow4sOM>KO?N_NuxMa@SjkjaBZgO4oea|T9@zltip)h!? zrRId$g6AQZ+OB?IV4!DGBXfRY`VVpGc~|6lqKH97OQeX=cH=yIn%q%Gld5x02l=a9rXisPL{U>YKI9wv?=VI6phCk>=TdLU$R&%BFVAHaH42Msjd zj-uL?A%6HPOZ8XY6&OfQ)c_+p4_|7Ts7Lt)3T>EpszSN1U(vS2^61vI7qFC!_50!i zJ<+G(y2vL6(nf7tKEB^uhb)>8yH#hZWBb0iKrS={2}NTAviPOwtN1$hEH2X|(ekOz zZTWz7P*25qc4zB+m>`j^6Jh#fupUf01xC=yM;c>vp5Sy7oXs7lnJ^kg;I4-zzFYNG zH)27Or>DX^%;=jSm>`)`y9Lbse#3#q9cv?X0H%M*W(H{X?m$6XlXhn9Z+EnhWPH2h zgvTVIDA(dVQ&CRBR82X;IN~RnHZOK#dMKjf99>Y_b0W&iKbs&4Q)O3_z2r``a&kku z6sa;pnlD^xnKA7+UbPV4=9Y_MQ!HVFA&`2h`A8|DQMN^NUH^2j<6s5$G6?ex+uFbq z9uo|453l1rh^LJ#XwIUMrZlD&7#D{hT78X=7Sztsh)PC+*vf<{$Mv8E&SP*O{NG8n zo~2dwbG@6btL?5_{^9*fQ3cX2JpeKK)(mWljD!%xUBns*e_ANo{3u?8_VCf92CXs& zRw!bQJ?;B&w6?azdT!lvikqS_e-vjaEGU?SX$J+8}Q zTh3aLv;B5f?EGhEv8oouU5(Ci<5nO!(}Son4#edKPJ<@H49TOkKoa{3Z0yaSBbe=_ z#TXohx%qEUMKhd}e#Nu6sW+SQ`+QN?k7cuHit5h#;DSn71=2N5;g!!?Y(a1Pits{m zsefX;Af3|`Uj3XqUh#PbNu4T;81*OE2TZaC(sLh*=Dyrn*RPQM^2&`Vn(yb5V-!sE zR3Jq{^S&f4(tnQ3Cn5(@Yn0Yes#knn(PdRSBsOxH zfP>O7^Ko+#bsI7P$HxlcD>&w$MwUV}=Hqy_ht_nkL8HDLDMn*{y0#?{idK7HcglKo zI?$lmA3=i2SRZ5v0n5~3&dTaVV1qhb3JDo;66mtB@WVa``y$bXX{&0)@@O(jqC~=h z49V$0gEBON6pb8lb+!fie>Uaa>`(jK+kcxWqB54}8CRk|GQ2bY#Qbh;e%4jJ-z?98 z4)T&tLyr^deMjEZO>U7-2OYF_br5>Y&vj58GTl)JrD+=Fc|x*Ls zlC7|oVYZ?YqZzMhL{LhYbvoFfUYW^Ogm0(E(yi{`1xwKcr-Ka|J1X=%EA!h6iLv9= zRh}?8-W&g(F>aF9B$VhB?j^Qn&CXY|!!u;Vp3 zL;~Vik^exL`Y@x6XQC@~-q7xLmf1uY3@0cp`zOQ+>Xk8bWBH=tG|eC#u2J@JwO`!N zek<4Ovf1`fE~;(!_vYWqrux0!piQ|u9W1m%#v`M-0~|}*L+dO|yG*seHg>GOF>s5U zdflJkJpa!8r=qFr&99$fp#`N|%KE$x7fJWgrYRqwEsh8hxtKFvD0+R=r z1YHWOy??J4EKs8N5ZJ?K*d0ma(}IOb(Z#_MYuXTz0lJ#V!i0KLU^~s6s|5>F>y3l$ zUYuj@Ko^Az)9gJ2H|F5xj1v3#u#IOQzNaES#VBb4$e?Bv zM>&>Z>ru9SnWJBDo(%F2!W`-u(XHiIUxe@LI=BCUm*Nb8ck_%N}P2W5m3S-<> zK4<9-Qk*fYO%bK~P}?H!w%SzN)w_gk+ncAR9)dK>4u4|!V_oB3T?G*9JrcT?TN&NN8wS5ZWz z-+6nL+lq|F`oT>R)(ABzH8Zt6A=-~DT~^yg^=Ly2dy6<|0;mz?ByHe)cmjAKprD09 zZh*4T#F=M=T`f@1sLveSZspGh8uwqk3ZOt`1uY{H?Wjm60i~`X%cxL6tSg0RFyuKv zK=Nihsma#3K!I5k!#v8gk})@|6HHk~#R`&IAV_NeLw#Le39$~;gB=wpOv9KXDM%jwLF<;@g%lQXu3 z7o<&XPA(&Pz#_nTqW^ytcM&isS!t9MwI`R z?Sfw`P*7^bkmfv0cT-f5s{jhhi>${}L?^!^?Oi8Okm|Kfc14Vn85d9X9+&=xwzDlX zE>KWjWPTVH6`@Sg1+E~Xz`Q5~`f9uqX$rbLrsSgIxJW^Xkw8>n9E7yvT3%^LL79<4 zTIOMIJCzxEKvOyj;{pXz#G~z$j)Hfk5e212CfD@`GcC@}nD0tk3=*W9z!6ryvRKdO zYQer>P$1me5|)c(^T6tD8V2xar2rIp+oj}s_*Fy+^{o`alu-tL&=%B z3zY1Ey=%(F-275*zE$gW`A~tlh9G_M!+}+S2#81v2uv7PnBq7?k!78(Z6AKEo?U2C zKUY}(oxR(%6Vmr#1;Yf$bA(BRKKin>5h8VYvgUtN538@$DKmw2#;6Exred+HzLiuXS`e{;%O+6n%-8I!YrxzwXW%o0pT<`dpxQ|jeMvKas zn2v}Osy1~BPOq4u$z9o*6fn#P2Fcow2e?hEUu8D5)2607~LJM4n<1%uJUslwEx^1Yq%(zfN%W!W*IA=eb z#hI{fR3%DRGUGx8ZNf1-HI3P1baJ}n2--9!bX=?;H#T#E35lNIgzbrom0buch|g{A zCh2qNx~^|DRr0Zl3tW__+o84l*g-7?+hokkjBLd(la+$ab!>T<#sy3>&&BY zt33ZOqZpgyi}%I(O~TaFi~G4rmmbSqwX2)Errtk-(kGCpxt1oS2-8FxmT3AUUC6@e zLHO43c{VO&or9)u#MC*F20u>7{~XXypcBJ|`q3stirZHl(31_@!m<094MA1}}$_Psvd$?<}?FA8Z9!JBg27Zg zg>~UA^WiY*^f}Wf=}wUBg8+j70Y#N1Zc(H{Qg(a)`l%vi?<%rNqDzYuJ4s({IDS>P zb$ymvZ+In2Bl@O7%q?#c$!vu$+b^e>!Z&LN87`vqK+2l`B;>7rO7=;y;`$x_0XTDf z0+w?~hMxd2e*(SA0}~Uu{}HU_`V1`VjXRpn;6BGATH5_9Cg;OG2CHghx+b2s>lZUZ~EHop&1e=<0^QsXWg z2UqN&xini^fkVw*UBA`}`~VGOKH*lDpwAz_eplf5DL-gUdYKS47UQjbpZ`nZ$&OvJ zJzb`e-4S%MLTX3;+Se7xM3+{wekO#NZ~0ysF`{i5apWm@z(2B0mBfEN7wLX;-tAt$ z@jvWbSu3FSbdSD2&^@l*X zCR0vm4I;Ac1t_-d>Ym_M*K+LK716`tF6!#aCcHaVal4=Y0HW9`-^E{P+@JMvg&{F= zn4*U~N>Sto12Sz|p4u5~j2$fJsYh18Y*GK^_9s2Oj|0_s=|-K3n;v>%f~xDFj;ncU;a^+-x!LHPoa)Jj09!8B?U#pGs$)0Il<%gQ={wt8j~x zJa@`-V_)wU*?_a%fkJ95{!%<{`6`yLr^%6dkqt6?yi7HC`ateuWCP0{>NJgPxI!9` zv(UY9y@%JF@ki!(I%Ea65bv5w9N9p!wF31Mm`7X1f8wH6e>hhK%k#;!S{O^?H|;{m ztdR{Qd#JLzV}}icW4-(tbXpikAUbE3X<-p*Wun^%kVkG?8!q;Eol7~KHbCs5$}S*3 zH09lOB=GYi-}7XhU+RWmzc0y-74ae4)>)BOS)J83Es>E84qGc#8*fof zc=>cH@n)^eLzZR@fIuJ{s0*q01>;EGY^Osv`|^0IMMy<7x7IIw zW$m^s$a~@&*gOh3L1|TF zSsxS|Ebe%jWFaC!Zdy|Thw_vtb3o@63F2xR@7cxJ?KV7I5S=s21aUTfLy6>4_AHQX zppVloXwQQ9nie`|mI-79>7jk9uPM7G^ZH;m_}lR+@iH_*`I%Zw{&Ehc4fqyB=gcxe z3?LJ#c`?SU4fS@s%!L@UHpJWU9@s(*0~_3}N#vsM9}ok`Lg&mfLF}JyhU${<9}xS; zBy%D6j}7Hk7cp=Ry-Z^>euVfA4aBV2w!`FIC@a2X@fZF*b=S8gnrxHe)lMr=5XjZ{ zsr7hfidc7Usepl?q12J6_*sMk*+N*Gl2=DgDzmQU)(K(^nZV-6ymjf^LLm&I3%g>N z`Rmv8J#yy)g@p9%Hf&l?wTIND{AnQ$6;toO>7)q7RhI6LWwAY;^Cs(R?(JlP*hF2; zOz=B8Fc##op+rSO`Ra)731K9W4c@k=QoJjogdPo1ud3x2sKCLsTD<2vo==@HPzu^o zQFhDfxM9ihc(SWew1L_VC3+(2rRfG%OQ|0u(FSH~iUkds480~``PGzPlZXV47ht|u zkz8AQ%+f>rwJeX_&2z33JBdJ{Abq%tzaxr9xet=grx7R&Bs31oDzK`NC_LBsGy)~T z7OfG;=5e)^?hDZf68{M=jPQk?M-WS=)40@Y6~xNvnkknm5h&_ofJO9nYWSF)3Ka4Y z8gJh?vROXgjbp>59oljJ#UQ`l0Qev~&IU)TeH_tZO;sBP?Qj*l;f_mPMWE0QS@0@C zMRmw>CEjn~cuSWEV&C94Q7{Zy$pH?vCRTnkrq2}Euw`{Bk#_Wy+^wgiL-4$%kTnn*MXwb zG#q0FoghYmcQNg5Kxyz5C{2KT?t}1s5h%Q4@y&6amKAfFeP*coDbhSE8tY#7(6yo8nrcFZFpgf&u-}__r#zk^!C{C)s(^1d z)oW73O;u)x$I3Lky6$N7JBROyP?=!1gU2(+AG(xqSj$p(okEd+b z@^y4@`!r$se6nWGcWqjgb?pe5wPOuw2wfZ6tu8~UpOQPWoM{%JAm)&%R^m#Ka(1CW z29X|U<}XMnkVzy$B=kmAh>7$xi%y_!DE-K8waQ0vJ|&$rh#U_iCkTAS?yJrz6R4Q3 zMnXa!WkqTyc3KEWuS`uXn2-feX#UyoXva(J75T^;cQymp1~sdzmLM&I&AX~F>REmA zE#z^D1QCZDe}j1k&skb-n4LV3FbTO7FAZHzqL_Q;$x)%_@&&|%^aiqU3#ejW-vKdq z*zY#DSe+R}46_PVrRIUv*h7>Ms?H(bRY|esPD*?%x&O&F$?JhJ?z&hI3_{n23u{U# zSYy_FDYO#kzEc$f2EY+s&>?HxwC4WD%Qe$e*)@CG^+ znVx*DV%2Q@j{4E36%|n+g5*lycbam#=jJ*qb}Zf}F9-I@UTi3|p=(3!)SXXPdp_ND zB%20;-(rxFShK6slCF=Ab>E$h@;p?Zl;^@sAQm7kb-RRYyn=sEwRIY%=H1u+@k za!36byhRaky;|w)5A*fXa4Ji>-=}uUnCFC=%hOa2qMJjlu)) zJ3Z$zOHjjdA8i9h{3GKoD8JM20D%3uJn!}$kJU~i5KjebU2GVQ&Al3dx@U-%b-j#r zgn@RN-c2BlfBB#P`oBN@{%32AP{9Lj^(?H$&$b$&sO4IXJ>S~wu<$p8J1pE@^di}& z{ZU91zfkjwojMSU=YGbuVFiB#If+2g5fQW;I@Jr&2o)Wf=GB1Fc)z9dUT3gajUX0I z(4w9fs}UqL61LrXi`58{D4EPs1k%%fJbxmfb~8L<#>fk-Pc@DRqda zeNxn{h|{uZ%HpLgw|kcD_Lea{C~mG{ZtSzo ziY!gD=Jgw@z)tJ^hJj}ew=2;tQ}%1OQ!Z^@x-u2?eU2(8uhSBorcZB3Lks-?|_XkS?P2F{0Xf z-p&&krmTrerNk#qGZNZ77!5=nmn&)Hsy5|u6K`0a*X6m{TX0}P7ltO=E+lfVLVb+- zFbW)kDgTI+Jm2Qu$8EeX8|!xjhB|sbDNe*)sn4%z!7`EJuKOyhBegsJ&olPOs^Qe6_dey(?(zIzcg47hy3pVxxg9UrkM(&7k zH_M@2QR#aD9;>S4lob&5cQCNg$PkR|Cwq`lYMvF&F{uu#uGU3T`}URi?QiUK0=8S+ zPHLID_P8(7&-ue(Ke!`ACdI2`RSADgc>%ZE#B%ko%%|N8tp4x6OVs~ z;9^PpR`l;}v#NRBWYs<8TL6Sn&#crln?CB4<#2@~;jwv2=~h=f&<=shS@P5oaO`A4 z4V=-p?%|#RbbUejdQP^SP<^NPu4+8$N6s9zcu<&8aqIpXj2I!-DKozuHOIR`5}6Brh)bv&A{5Df z*`LMT6Tf85zC1U1cFZj8Apn}3XU-1wAvtSvTxeRAK!wg@$_!PJ?rai4fO4Jz>eR#I zm`5#p+P^?_-Ag}P+T}syTy%`7qkk{#4@PUK~QW|g8Wk>|EZz54Ey4Y0&%FybGTYbWz z;rS=x2XLK!NMr-xbCn&-<0atyRFy@O*|lyV03M!ap84J5_?R<6KeWPR;&IU=Y16e( z?AfNuwmT~;4na}y^a4i$Lnf35H2)fFBRQk%2trYh6^4ADDuKuLEIza9$o1A|t5hX| zA>RewyJCy`Yj3_~gsNT+R%n<>Rxg}yl4n;5$~d`E zi0-K)Wz?&6TA3iPrD+Vna%6(MlD^|25epbh&NcS zYO6uj_d}jxiRTgshI(uJmagM`A7kWz(cQG0bab?8T8&VHf$3uJ8W^72xNhIa+%+&P zH~+#?SmIp+V&8Pdj>G7<>QF^j#{YarQ1EFbS_wlO4dCIYJSn)6tq7E#tJYVxQwtOn z=$7-w&1xFzH0^o&v)VflQoEBN{}oWR5RUV|4R59smqCS)?`LWKxkZ5I5fd zqd;80(Acwp>lKFJ_9k$NrW_2vty8$v3kQbc_NK9a;Vk7W0_6qtUB2JyH@m_Wr3SE< z`ygn&T45SEI8tb*2mUvQGLMh7UFHJ-;`ZMAaJ#$rT3K$(fG6P^QKen`t@EsGs_c%6 z2LO{Y2h;zQJI7x? zMj}uvx_%0kOu{l>s=kjL-=mK2hJ$Ggo8-W6o>r+P;0!@Q++0H!dha-@&WD_hj3{zK zz8xZ>9LIO+*K<~|*Q63-8N{GYE3q&%H#5Iq5$pcObn{@BIN0-?FpT7UYPUMQx|Ml;4+58_6xll9zv~owaL$pFM z;U*pq+)0)cs{BKX?O#Hn00^(nd^(Lc?YvhI6s=#|yR(R81TlibwmZpsqk4hoP!u}c z36x{6?*>r1&vLd;s%LK8+FE-sw7PaF5gMkLmyi$fp`tyJZoJqM@*zIpw4#M3wP4VL zrUsrxEFy@x6I>!a3yit~Uz8bOu0O63YF?q1wcJmOn5rVC774`bcb99p!a(>siOV!xVYqu?OJiB2 z;R-_9dl$GwQw|2M7aD*%%P{2t7<=y_ooG0mXbE>s2-NDTXX-5Bu7M#3ni@f`D4cH% zfm&S+<1rq8o5Ii$-vlo4Hie-hb_y4Jn*y0NoyLV0LIO|`-$&JaXeN&`D8r2$-@}eC z5~AOfei0&Hcic&?v%0CW-zTM=mmGpvH?2qw`myI|$Ptdqmp-U7w$=&7Dlq?+u=?rE`)pqjDUA&kR{LA9hM>U9myD;21)MPD2_ zdd>pBC)^+meSgJ%X;wroR%!!uMRIO3?k*>JwmI7->LQ@x7G#JAD9b9B*VFl>0(EMO zW_vWW)UR~gt9b%3A|wn$2S=V{d zyJ+pVauC=1w8BB)xFVD>1cA5XjM6gU3vFpA!N6Sk9&RtkA@ zec!gj_jT-}Gn-nV6cN@&hI-GAT$)dnu*pnv#ZH5vy&9&ik6T=ixQ;lllq%)G-FZ#+ zB|EX?@IIBnPACZT)hu+Z|0bk*A>j+F)axJ0BFPymz~oMv9qZwkc>xk{zFtwnk6<#ZD-Qu|(Q?SQFZnWV(t+ zr?h|}ZZ^5@8sR`r)wkm;w|SW!?&z$+FhJPQ#1BzVC{m0;B?`e$xaU#F^N?%^(q zf1fyQ2-;FAgjK;;Pgv+f;_YKr4+!F`Up>5_wS%xVx(0;BoID_Auj%B;T~1hagz3C% z2UHw$dy`&~`9DRT)eYNDBoU}IMjtiiM^6U6AXC_FVvYBkD5OnMw&^U(a=ZWsPKfyj zk#415bRFe{cWImZtfL^UkybzI4a|uS_X|S;-bz+qu`KhJ5 zmLODKqe?Uuf?l^`~cu}!6?55>DFKZ`I7;!dDur>YeLk1=du zAjEGH2gNOlL}j1OCJ<=8Lf2e+efpVNYBrlfAj1Z`qHnvekQkRx!3**qK?2u_-1d%r z=VLZpR(#5nS4(~(hT#u)LyB+L1{fcU>GT1`Zn`YMkUcyO(lzb=gtBO~OW3PoF&W;| zEg%pqMl9fP64+8+dJx{QcbRR{e_dY1A`-{-753w0s6Ai7G|984vMRE~ zN+tkq_+6&Pff~J*lj{UZSLquDMze;eRtYsQGhY zS<%iz7iFJZjGaiJ;^bwE1hH_40XC*uI10E^u0i^o70K!!d;VMVJt@b<8~%kj;}Y$s zfMFPZFm;etp=yRJjRLa?1Z>2*InvF0$Pxl|VIgf%j=F@hm4jvzIB5sgB9;&;YNMT3 z)3a3Ndq!yw@B)na_fnZPx_Qp3@(|Zau{|bMgU$&I4w#Jdq|C2ArkF&OP{j-v-x=?c zr>7S?X(0B@GNpkSF~lLR-anM{!AhHhD=Q25Pw+{=e^4;c_W5r={`mRlzx-qU{a=3i zxI8F~9@5F9qu#xDaRC{KDfP!oP#K zlOj)vj;i9gHr=+oPa04c74nyw(Izke-%jEpGui|O<7?^?dwhC=!0>$E1mfkT3JDC} z_f6p-xVD5;Apzt4YF$6~TE~L&3gW<_*mbDy%ZBHc)!DB2S6Ay5A8R|?69xcmruvNR z%HSHg#Ay@)88Y2m-Qh%5(}N+Y6Z6SJ5A*$wWqmBqz9wFJ0JxS<~tv^v^m_3*I zv(*$00s|9nv!VACL5T^Fo~Xl(Lb={D&BVYp{&d98tjfNYg-x7-K+%Oer?9_W`)86E z_v^GGC!OQ%t^=b;WlA7H4h?*VM#}i2OCaVOv!PDwJh34*5C8~qmvqviqK&t!Iw+*Q zbDY3M@^S1!7iE&yNoA=Gh~}psi-(n0Q5J{YS=0d~m^x-kU!9C4RuV5Lm_;1Kv1v^GvugfRjykD<84n3B+zTUF+<`r3Mck105r#HbCkTqzNWEKtKA>b0(hntn zygtDGZq2-uYwx@Ax`$$FpW`7_3f*jwEX3Im!lAUc|coO;jvuB$}{)Q`Av z#?LW9vi zDU`s#dOe3|^Pc0fFcA@nPtQei0m(5-5AoNsJa+N5b8S^WLSV?fp+TSfUavN2{gLk) zF-1~P>=FNIl0@;FyiZr;;*RGcYhLf`I3zG6Uo$vN)@!ofsOPTu73H`=FdY2)<~Kcy z1N!=uv3$EulaK2J?UvQVheuqn-$ls(gk8+NX=Oa1I^rh@*yJtRe))G0rp?>pE|D~MlgN=@}f_{u}Z z7`iS;?pv{AvB!PoKuLxFlpWZn@&sehZm18f5UToN6t3D#ai-W?lL)U#sMta60nO?<`S&^5 zTeiUw7*MP~u5|jEoj?#FE_EZ9ND{fK=j?omBG^xcCorVg&TiK<`}Mj}v1zY{+{bBS zUmlfT&f{~lZmZw#Q3zxMb*W{|)gud}%FqfmwkM+N7!fy=uh(RI5WmiGcf3m@koiOO z<>I5;{HBx$G*Y=6$}x<1$GL10Zs7Ztt;}R3lW7 zM{kr%3e5t)^W5N5NQr}qVwBene<-%eOI;RmnjBBhnTS8X+UW!_Z`uM@G^`L*yECJ; z>9Qe+8~1I3M4|aTF}B?#=^?(jS9b>1Vc@WyX-#{M)}zG&jc!KT6zxc_awe%j6%)cF zxFwZa0jA!+nZyE>Puy$&%%m2?6f(ttmUd*JXe8Qd?ZH0w9xE2AUDuFaFjt7mTBpy9 z!SG|dw&YuvlW(j(m_a90RS6!EE;2Qk&ma?!OS1S22?{Ig{wl-*B4&phSnY^aLbeZ( z3e+*3b13A93}pRl}?Cs8DG?HLM9%-21Xl( z6U&6imLX)A3eidV_MYO$=>)Nlx}L=08C70WlS6}DepArM$8rgn_$})Ah5uUB=3KqL z9#gwAei;6&iL1{q9qJ)pUQBiNx%3U+D1)9u3BSPokV=BN?xc^~XhmKqJFTjK1Fz-79i)AE6L{7ugv>+B2#2)4HZZ8S*_qLT`m# zPYz*kURbhAil&Y3o>-Bw-0F^nK}Cx47ahZ*_Wu! zP73DI2sF_QkC<;tLeoACX&}ToA>Y`d3~If?M817mgP=+-1s8TF60k;bxL-rn!8FG) zy_TIt10)-;Y4Y`3%SIv9f?Ej%s!`N8qslJV)z%bIqljE2d(lm~-Nu`2x5>{e*$O}8 zT-h0~Am~Ullwo9L?WCnaFziTvXAs@x)3bISRRAR{OAwb!Lo{o|nm>-6jE;hwbvA!~QemgYqEUK9ED@mu?L zF2|VyfGH)RceE-@F7$pY=*o)Xr7R~%tS4+U&o|+e4-5BD06ygvnO8)<+t=I z$s$$~08aV-Na`GEW&DIWErLVerC0@2ROez{thps{$2$VUr+k~fcq0#cWi;VBh{zg? zFsV%a-BgJn zCI|`fa>p+BYytof+tt*Y0jd+C7EI2&nD_h5b~5K(OsFymZCNNaZP-8^H!``(`;DLX zwOp`DpehOdT3)?o=hX>h0_j(CG1n}J2^3zMW%@yoD+8ToHh}&zI764`0sni-kV-p6`%e?>5w39inN{~mhQyKjZ4Js&2BIiAqAYp^hP>i-5M-u>k z*y+?)Pb}q@1$r~}Dn|}MoL(i+i>Y@rm$PR9$cJw_`R!vp@Ns&bK(FSkcj@s(g|hQhq9J@M}&eJ7`TImCzj^fsb=@VCMXOVF)+-79(&JDFB6E4=xSj< z%aIAxZP88L9b7@`u9Y{fq|!q;2t(`!N{tBn!iqc2BMb>KXro)YnMy?I48B(6qZz7{ zW*ez*eQ+2Psl}quuz0?_e4@0S*SUKlfQvzt4EHlL?VF zxl}pdCbGMR75y$mqBn>if>0&0A6b2h#h>iN0ZqWx1NE1)hCoJ7M+#Z4Oen~qww0|n zd(gB~&ox`Mx>g&OmoJjaKU7(I=q6!{ODIihyDlgI#$h{RQJhFJh&-!+ErsF}&TFaz zFb>~c67oCJuX9%H0i_~uUI!C^ariEi{tjR56IMpn%`6k7U?eimK{XyuI;%>k$WI$$ z_xjxy%g71=01e+oYWP}X|6LZVzc(z;Uy>awB&}cS_kVjg*oOkJ{-pZ6 z51i0GrIKLkgg6>Z#(K(=dVeajLO@|ylN|*x#cE-p3>`IDgcBL@fKY*qL#~0o2 z@NEe&tiNu|(Dlr%5qzT`3c3*^L%$6LwS#PgAR&?NNcsbAL9aW}f2VPFH;~dh%r~nb z8M&@6M}NL-E@S!P=H+aI_oE?H|D`rIGWspy{w4mj!fjv|%dHoz*>iPiRo1mrmC3et z?qH^bK)$rAoqyW*rA^V1kRXQyguhIIqO{c|x=hj}&z{Pv$n2g?5MrZHsm1#!_)T@o z_I%B$WkU3{U1Z)4jPx)@J)M&Z1wc1S>v@An6|Ut8J<)p3jSB;Cj4tDe>4#Rdw{zEA z=Xx@oK<)h4a1C8SZzxmm5fO9|2Vo);a*s)sv3Nr(cC=Fm@}iiqxV;yJD2?FCi{g8q zR=yxFhbr!en{o-a2-r6;!;wp}k3)l?91%98O?p0x0(F+REVm7~A?r|&_`@xmY%5kI z?L^zw7UBj2cUg}7Yj%nu%y+K1s}{bd*j3(_o?xzb4!Ir-NX|GlUER;JT;;TWzvrIi z>TitIY!z`^o>FlE__F6Me@iOs0Lm56b0L2f9|07q4(TQ~ z{W?AZpv#{7^JqAZUUdkSV6pT8^xo<^iQ6E>FLr`}hUn^%ZjTTILTB;YbE?aLt45@3 ze)Ne#g2s#KFwwTHQu~mE2Lq?`FNCjK`b?vzCe#N4WC;xLz0m}->GXjZPwpi{an)Q5 zjOOBZUO>cn3_;XXqM!9C&zfUWH>~QSo^hT%TV;bi7!;i`>8-|MSU6jb}@;qi>EvQ ze%ZU}H=H9snE#=mP2~fLsGy5rUp|i2KB@S7!C&`({#wP{9JC+o&UFaZf4`A{1auBdN19O(SjvkCl3aU&xAq`X%A7;Wl~B>bTCV zGJ+n4ux&1r6^9#CK7z=&J-gs7_34V6TC(BBzrH*0KY)U_9srl^eZs(q>RL6!D+!Lc zc@soY6v~_R3zzrhd_0v!vuACQiJeBMB3pVNnAPXDco^^_=_zo%mn`3krklJhPv4ex zUpCf38UQ@o`>eB@wwwu-7`oIEr3o}t#tl(~;wnq`M}ADd6-n9ItN?hn&I<{&C)G3R zly~knDdKIC=SeMAjy0_ACbwJ^eY=k4Xn$wsl@~v_jF~jp+@Pz-v>O=Rx9u zz~}m!jo!L1OghNZi&_g&V?C(@ag9jA2Wba-nDyOuvT$nbDGa^P34KvL>d9fFGusS$V9?&zQ8%9|QmE5vW?U^q`i?)v zpH}?Y=I^mmJ$K;0TYgTH+CIn$fI*W~_DfcR-c_vB=JY~=Q;Gzkhqp$uCh4V&aWuJe zn4p#(jxin->z*z(kmuTJHn#@=KWk^KV{LoySb1wMZ#{{;`>h4OdbpK$y+Zdcc?CCv z_xv{!)m2uzlmfLc>tpiQLY%!yUEkqOEB`S>o}qTgjvH3xuj>QL^K!R~59zVATTiI^ zDuc_ac&sLWHQ+x(jEzN}QmxyqC^vDQvP+IE&+TF?01&(PT7%m_c=h?{Q52?D3SkUf zyw#iQY0BqLuM)J4`Nq_0tW+h>Digx$F}h}bt4AFVgJ%^A6k|bJ&_K@*3)kix=#-H& z0F>S0qk{k#ySM8{Ly=OptE5ixDSbgT5sm3er0ke+cd|MNZ%Y&+G-ctWjn#_@fOczx z1}?e<$}$3n0u*6_Y3G@Jix0et-1UYl5!3Ma|2u2$2nPaC2HMIee#N38#J5KoP?_*b zfga`-R1ie`52YcCJ0knnm>YWu_nn2_q_UF<;*A6?_H4m20Vo4k@FrL5*p&NqYMCJ3 ziCN}CRNj9BT~RqU={vPZAhx7_0N`?VEa*VT#qQXNr#UWT#{x}qbhX{t@8J-k(N~CP z3dm(xpYYt&M@u6h1SwE&n*}wt&gg#LpUY;IXLZB2pyD7lrLp?H7i~2US?4y0L-?`> z9+pEq$BJ#M@+D4p*&SIPfF9*5_0K&D#Fd8gNi~AZ7NwU=)_Bt3$rh>ADsu3TjW{lJww7{eEr(AB0=o!H<9+G z&(n$o>doU`0k_}!p&RvKR9c_b^KDiT)25TCIh5u;lKB=9D9q?;cdGh&$n_3*Hh~}} z&YM8b4);B!LLY!=@UHMCp#F-JIH^Xcz@odGJLxAAlzy z3A}OF$Vt@sHYtc<;~Q9y3%P4R>>468YJzTZLP~irWU?+1Feg`Jo0ahpO~rrP^Rd%r z&%N*gr~_S83N7}kf#MFJ<-QkCnNz&b+Y|sfAPHQe<%U44noi+TZ&L(f)|il_3kbmZ z0QiV^g_?oyOHc@6*R%?erZsH=?*#xbLQ*&g*ev0_0Dwlcc?=OJUgo0@K#h1;xX?!* z02|?5!SF2L(Fd_=-URmNcP!!22S7%6qlu~ydh`LH5na8BHfOqoy9R(7At@YGz%Svh z0YFE*7Y*Hl2^!}*Osf#Yu89o8%@=T+Vi2?DP2dt;C;;TgyTUuB=S-^+#IAYM*dI~0 zjBKJ0fcbcv!?sZK6aet?u5h8|DFDdBbKWOFF7QGHfOSX$Z(OJ*7|pZ_K@1xcv0)h( zDgb-qtx|ZgClRQw-Cb;m9{{`YUYEJdy9TPBeX;Rx0IJBl!o}V-Pqu@Aie!y=wks8YDk5ndL~WL# z5yZHmEzk5i07q%6QD#vEk>g?H1c5SLep8*fx+KrLw&+t;ZqI3xm4%qJYNr*d;6^|1 zLLFYDT5|X?f}!efMhy6nUlaTgu~5T5^u0fV-BVF`-L|OQz$v`T&>_@7qY18^}Y`4Lm)s)(1e1 zTuDU^MoCb!(rMSzgRqM(eDHf3R_0hz2=mA+b*w)&hf)wD30;6k9~cm#P~VB`@XhN) zt}9=?X_=(^FC~lFFDF)ItVq92x3m)rVkLFVz~zetv5<&^M>KpsUMx`dOJ6|PYcDsA zOzwFzhu56Nr}Oc2$ckf9+$j(!^@R-Jim{jPpSY;iAI??5@_aI_P&LciW7^{(^d?{{ zV!2`LT>fw+u|I6L8H;}^&jlA!{FD?wSTmD-53tO~*Q7KfNvrCI&n(mjw37Va;X%Y< z9C>99p->%KTGGV=!tp*-e^$8EaJ&!IpA{}Q9PdL#j9QHgt)=jRqD1-}Zl7arFbnu4 z@9<;m5Fg3V(qmFJS<%jf-6pRW?0&(TkBfwg4(Z!oC5eulh!2$zTZd>hob zNQF@0AZ^6fRV*DWhl5mv@PrBh*p^q|a&`}6#dcZEPo9Wa#>wfF-|1+~`%_&+=1JTa7ICVX%%ZgGCQvm#-K3>`^6efJJv#B*@XBJfiVs&y^f69u&WEvOC(c z1322uUDTjCq=LTtw+2E`B_E{5nhA0!iulh8e*Sk^@+cV*C=!k(yUZ_~&J8lWY zyPW@Gd%knG_G7;M5U7zEX|vH-xnz~yDsR{C^W?QDi`8eg*|4UmC8a6TasLa7qOV)%p5>WADsEmYe4WIYnpUzWq z%<|XEAUC^r69(T(FZIFKi=2#Yq($0r6NfeDlVSn9sWyE1gF>O4=rL{>Rvb-r`vziY zoiL6A&+9L3ot71Intf)e5h#4F$3>35g}A~sSGb-+At2%Go{aO95&`QfhZ1|!zOE&j zr_>1KOPeOq_)E|T#BTlYR-Nl80ujz!EuFsC!zQ~Scouzu3j{dR>s!EO8o*#%jS5G( zS5wLZ3JK`tjr2OE)CWX16W;N#mE>9;S)GRMx#ZI-!q`D#Vudtvk3Btc7rCxk-c?`O zsRW{%>Fch>zxY$jgzA^o)}{9fBLj7~`Apjts$o{EkUU-=RJ-hQR}d(SW0+I6gclJg zjH6d5r;#7=V89?-ZPst5<%1!%-dXD~r9MFV$ITjK^BCyqA{YS-t<_jjer4uWf2Q|z z5`jkSxRIEtJ2YrQc@bS@s4h|}9wxSEV4$sc*QEE`P|o6(Twuz>r(1 zp;f1MvznSErxXZ7#Plw>8hbZtQjJhIt9};b680$!GEx*fj<5h8vQI%S)$Snr!;!4Y z+bA!fB+o+u4p9^-b%0;8V_d%$tlGUE4^3U>=eFJ6P9w;DYMMW%PPI0gsSzShWvdl)$mU3JsQCyb}3XOT$|hP3siFZvq^*-@^M?@Lj-~XBd-_UM32x1HQ-}Z zA@15Ve{NEVKoM{~$zpH}O>~_}CBjjn7wbj=;uLSk;FQe%T&oBMQyg&?AL2!UkQ4}&u9KJgWTy_QDNd`dw|b@?_{qdU#W2Q*!*h#+3I?}9 zw(H`0R8L8rkGSv6|Et6<(whH&X3t3xzp!m~DA#4R`?x;1Nf%2EBEm2bN2U=U@%+KS z4?PD{;qcywT2Rvx*8Ak8$aZ`?W>qNwRK2ox)7L+!6)1jz3|i#|+)#ne%37bZv?;4B z3EVX?$i4C{A5;v8`nk2b#MqizC-os|%F?*HhOd86D^O%Z)G*%M$wn)HU#V$%erA;_1ntQ}?wGYJ{+RxM7a8GtGKkD84aL6^izvfI8fEmD_QX zf1i^kOY4;1ysW};eLnKPI<*y2IDo+)b|I_b-X&_GLnv=vij`uHG%1p8Vpvn{7e6Qz z#3UkZ<=@R7D!g`0Ayyyz4k5^KkuN`~ZA$093IG`Rp-Ew{Du)<@R}%^ZF^NoVaB|BH zA!|AO7|tROhK^^F*Nf;pV*Oy?c+@cETP`kE(s1%E!<`Wad;DJYsO)Z~)!`}o#U92H zK;hy9o?@82>3Nf;tA+oNRT!Zac0;+sXj8o=#W8+)O%LVM)9W!!tb8sQSlnCF?Vtf( z7HC>MLR`lWeQrM}v7FB@Sy6A!)$WhyI4La`5UMbI1jWEKW5^)yzrO$cmf*LS2L+4K zPWnQsJ_P}!mTXQb5$bga#r*l}4}7$i*HAu#1O=js(IJ6St$Ey(=Q?Mv@ud&^87liyM_#t&X>UyhRD3Re6Nx@BpG+U=hb;^W;nI-)1*XR1O98!2$ZT~jDClGOh$3vTiz#pMa~9 z24SGE6X)QX1_1QL(Q2=bMw>+}P_jYaz|}8Hkn4fy>{6lNNm@%^EhLq64(OkgS-vnZ z#W(XFUw=Z?a6FmKyoaGFzV#gpXo~XLG*&45ASA6$IZJ9LDHJo%%5$?x(!*Ow{=?HT z0vM2@X<)UxRxAT*biRFV^mz#Lj|s_9`MP1JeOxycOOE15-jRBMAt-i2hXqkMkXKT+ z3M7$~zm|kjhkxkui+M_#<~9CO*85GCbCo+wfk3$xea-XLoORDIApV+icP8>NR%D*V z60V?qZk^TFEwl;@6@1Y^N@h>Eg#6W zB$q1aM!3{@_Ec7d2>01&1ZpA`#eBEQg3N(UuN@=hI#H-(cVAv42KYS-2?ZX~ny+I; zVn4$CSBcPoc_J!<>{%co3`@}@@6qC*DloO-Ej9lsUp5M_1_urmB$vn=P)_*iV|B7& zNxHwQojZg9Dw-nFOA-o2A<}NwB?$$wb%qMU562MR(=$4O910_U+hT?)v!I9 zK;@RM_U$m2UZ^nv*N+Id1!N;<^TLuHzjERPD<`D}NAsSVGp_HsfvQ)2oV7Xk`!vCdV zRh7j1Gj~Z(i{{ z#me@DVK%9-S?i@eX9ctDp9(P)WK64YEVg+{fk1;c^v~wlQ7}^q1RAx0J>5~nYRDa# zJeEln0$KwfTEhO|sVOxA+5jJ0MckurPbm`Q?eFMD!#byH1OC(kAiU9FsxBi ziz9MXqg5`V^;L~r;xr0jV56-F0+jFyTv+2AWGO5NVz0haQYAJ3xUGMn3;3p)B@= z@7A1c+2*{j;#Or>U23<5p$3kQVLU%pDTqyEDiR)V#LuD?Fgjv=F>#?>=cF=$3TIp` z*tV4b?sDT zvaKEas^JiX&^op^Sr$s>7CLFl=o(+&pIa#uzf4O`7|Ar9MJSMIgtRRBUf|taHY7^> zF?Ai!3*>^6Y8&s)O}c04;lAQ17>uh)CSHa{ko*ubfV~DTsnVsP#E8Bl$o;e;G;lmW zk}IVSNm*ralIKo&ZtmH%faBP8rPA_x64~{ZUzUgjUVuFp$!GJJrHA-ySsuGI-?_G` zlMZ31uAM;bG;gCRL}yY6gLUl`MuV!TD{m&AOCZqv(r$p+5(NTP5W9K@Yzcc5#N6o= zF7ldzp|qM?P9851s5weMsAUm*6mS&HGOrmRn#{dZT6}K(g+bs@Pr>ZIWcgN<@aJWD z`c_1{FB|I`5g%}fnPzyBBv;|=BKb`2o96VpfByELzkPXmS?6rWiY@=&xk`$T*6`2Y zcK_0Osu*+XhX1bXeRIsE52pJDh`M4J;OW~$uxqFeq!jMid>)6ac}a?7!Vd%JO~TrN zKES&pO-_!OJlTF6tJUAwE~}d=5oxK_pR?ldyVXkhSxMSt&zB$3lqYtW<|71Z3hqWG z+$;vAhCPMdU`Zu91YO{rZwVGLJsMvX2|k3>gmM ze&`5na>lm&-E+DDtP|b{Ko2C=z8B*k$kDe#!v80(feAkns2Y+H1UeilNH#f@fLeng z@Q^4CcKc_bs|`NoiJ&}Lse~F>t1lu^XDk@=2osBhLD+V8nMR~6(MZ;tS|U(IsjzQ! z>*&k7RgT(qpvbvY0-;s(5%u1gj2^X=5Z0Lp!J;J}Nf7(VH1fRHaAC?u2LX0OK%GXu z%mB#qdi~6*vhAn7;{^eu(rU}t`zF+t4poc<9krAaa8fpoU-6<{RH3)OS3e%3FC;AG2m3Z<9(u_C&>Lx-UyRpa%%F z)d&;nwKAA#9tNem7gnt6tm5aij+4fUG#tX9T1{lgo;x2u!0#Ztb zObb;gQO4pR^)=-W6mf||Ln2dm|CXiuV_9rhKYc^AeOx0DyWZ9J#VZ3NNv{o}SQI2mTtgL0QmT7{bx}W%je_jf&^_WzLxXF%edyhz{aDp~1_<{b$ zkf8Nyg(?5MA_XVdI@|ost|}2K-HFpni-Gwa!+y`tOp|Te7c z_Z?r!Pb-iAoCqn2wyI1ItPvN_oiZUT12N`UJJ9h1G#Sr#Cf~78eYu7J%2=(!+)1kK z>c_8NOL<8%{?Bn!o_BkD#%bh&q*Q{t6Nb}@1S-G8ca{xJD-x&#bJ^P!3R!W2+GwwyHbgEsbfz9 zPnF7*_JscQ^ADZSKXajiOn?Wm-Ii#H(+}BDTsT7D}-z7i? zL{~|s5~`h9Bvf`qyPO}uL()(0Jn7%`yz4t~(h&^AwYzbL?4W++@|wPBc-avQxwYG+ z!`vq^E}tSUY6C!#@5#X~0VH8BW&RYu+FI%n6suJ~*`>F9ro8U-!Mq5D(kdJ1Hl$K;n2tDZ^`YEM~N?0f|x+Yu>=be3RSFoC#PcurGT9(_GHNEWdatN*yAf^&^hU( z<10Gnl?elEHOpMi`Gg_2S}2`)L7@s~TFYoSU4zO~3{kN5ugnqQUc{%B>$;As0F^h{ zZo`sF%oEGc8~b=I|0p4~-teypQgWTD*EzjZAYdEP(j9uXk=Y*;6LBdCoyd!1JFu=_ zvgRwR;yO8A{87|9ZQsd}eonN+KAXt!XO{ko`(jtjEB*CU}#d zpPtf+v4gD(4#Tp23l!Z0nkG&_1;3CEVkqf8$#YihnDdkzv;39+W@5~vowo|ZwH>#W zvH3EdO)m`P_AQ9yEq{Tbu(z(S4`{oiC#hVMT(M_jduCxUw_U@THe_$!!bFv~=JM9y z@_;NRy}S?YSff7J9Sg`f`E>{enUjbG>=yaAHn7s%-antyY+xYZ3DK6yUs=!b@?e(} zD6OW~+gna=0eUCyVOrjK1&lM@RmnP=Vi*9fsdo38EBg?&P+=#nTE&-D`UjL5CG)9; zFrO|E%KNV8c?@C@B(4#<`H|OlCcO~m)UQb|h&6>wG%h7nVIDCwpIpFciub&}KWFJ- z_4lS^`)U=rp5yu0@%=!KtQP!R)^+2R*t52+Gvb3=bHNt>&-?R<`G)iBIEVb8H zGJ{kYqHbWIV)dpcn5-%>ork*A36V1GEosvC?(jPz^7rQ9bevnLj_?XfKQHvN_bu;@6AVCcFgoukKK%perRWOCaQt|5+3 zadrYFyQAm~h(iNWkr~ND3hPszHOHiGSk+|5tk}i*g~0f6nNYoL`lOx8J~9HHeC#`f z2!fI_jIq6F`7+u==OY->u1Q}HH$v8OTGE?GAdn#>8ZEp*MXdT(UbFo|{xiG?IZ;TI zd75RK#Nto;mLd+SD&!JZl+rDk@}s0VAUdG^S3fWZfjMd0E9=;7(k%Y03X7*_P{F z`TSwEKH%tSO+`00hLyZWh=nqRv~|I~`I^eBf*+w43IS~>3|69OSH_Ba*bjrim9Hi4 zh#it0qsvgTG?_BG}f!0DJit<&V=LV-${ zU3%AiZL*4pxN^clB$gk>bCu-#Y`3@42le)kh=5SVftL3wH&6Krdg9zj7WtQQU);yL ziC|#5rnwncOdACjOpxz~6jM1`CwR|Q^Ch7;eogjeX(tb8$g)09Kf2-B55(T&pOQ}o zslLxu_WSeZTou3nvz0^;f-HXw@fehkJPoUl^1+_(iiHgN3ajjyRaJTZ#kM>Q1{>P} zDTh#|KwU*S3Mmi#!mi+Fcuo)w*RU*J%X1|dcz1;Arsc)EY`o zHq0*4ovQ-k$p$SP{pJZWtqS(26L@0mu`72JrQ75=tK*j>Ex9Xu?2Hhm>~ zFEgwZBf0a5gz{*$^X*1vzvZpiUVbN5iKyo$sk7pa>kkH6YZ5owU7t)IP)5JAN(ScT zSb3gkUI=~ulKHy9b5AU7lKb*%Ftpk?>iLb>U|`s!GsuKul;}(Gdx2hL4D`zTl`GmN zd7ji49G$&83qz-k4DM{--!leyClUwbs~e8u$l@B}VaF%@#i4=hu7CV>2Vu~@`vF6? zoSHfE4NGN^)1J6(mEMt3f#J@Em#TT-<+@v6tanIgKm zc1qw#Y1cRV2(7G_{cDFxu{K+{I6#PqMqJP4G{Oj`(FRKm=~n=ekv@Y*kwY-y&!sQ> z3?F?6xE>IbBzT+o)zjl&d$het^gtLPV$zy^ys2U^kBKEfSs+{)papUh&?sMtYNdAI z1cW$*C{Ui}{L7{)WBz-;t}7cqmCFOPNR}uM$RI)588Q!-2L*q{+STh_BPPp#LU~X@ z6fL`Vv?D&DK)_+b_PqlHab?sMg!-ZX{hXbT))Y6c5bB}RRy_7vUA`G$U07C5xQZ|X z4RC+hiinZHP;dE)d$q%Qi|s@@cGYim1!c|%{eW_Q2I2fZ3YE%ivuWE#?1rd z4lf~JZGV-ws-*7EWmRQN(pBdFzqxB!P8)`zzrqjTF|r=^j%k0OyRN!0-~k%2Q;dhw zukV%cq`F3;j&(({$R>*bSU{)0OwLHwJ@<9a_4vA9mm5v&x>I#N!S4f#Iwaz2a8KRV zvSD?H7WqQ(j2DQ-cIWnAuQLQ6m4v^uL4W7Ak@%e0iv`bBQRsn9>r*^ehr^}Z zR(0|-03(e;lksz8j+;6%caF8j4EU(l?VTbKcYE4}=blCcNcGeNstOzD8_wrEL%ySJ zr_Eqa%~k;c4iKsVpi~qwmWjSoAKCJB^ti)uqRCdmAVrsyh4soaF9U7LKvRw8-y%S+Bwn}7#`N8*}8g(kTYy&-%j0T*Bp;_c5!T)w$jD8e&9ENloE*RSb^g|0uR`Z(Sj;e#<^e;HT4Z+ z>kg1Q9n0SVGc*L+Gg2FBy0;$}_JJZTmS^E3kgt$hcie5SB+>IDZN7$IR|cG0a5>lh zs6&*m%|%Z-*EN9L^*Wi;uu?omI!|1<>NQ?55;hP86~>a0YhApdCF7eh&AP11%|w(W zAEoTq1>fh>GH3c^a@trKfq=)2)_J<+BRv*lqa-0b3$wuNAg}1Y+GmN` zt5B&C-W9mXaj6am-9}wPK6!!5dz~P;3lK^8&MlpE^r;dgRx%KZ9*F75f~8q;A3j!{ zmWrM{j--ext(kM^VZ1MVG=Mo(#nnAv?L(J71sheZ)pSM?`FH=!OCDgHMjC z#_B1{4Mb*<3N%a9Qy>!6Hc}5nG&07LkGP;DY^LZ1*&lv>{w_c~bU4V3E^2dcZdFtX00TWw+EzVJ+E#UV z3jhHG=>q@&1n&a?0Hj=PZ`(MR{VPQ0OACxt@kJyxz+#=aX`81>8pN3fi!HEVY$n!3 zmJCUbC(mO4`(8?ZAuY*PHNbSx+LT2f-dcLz5C-`u1ggsI)C^3 zyHqVSymFT%3A)Z^Iw{a)I)yh9Rl@6x_#_nA{5ySye|wVpBoGu{h|{MG!%LhqjBZu_ zg3eyGzj=ee8=JpU`0H7c=(Jk2d6B`3*YR{7KdTg8TF$f7Y=dIzQAs=;MFG657qCsU zU)bHE+T5skoIWSnqe}c#m#}25AB(uu_3dWW_bT8YKR<52WAXE2oX+Ccc(#Izmhhll}_~@CgF1?*&ZfLh)=`Nf(Zv0 z-Ne%u*in|EN%=dPtYG5^he11L6RpZJ(H3A2s+h;=bD7zYk$`&=bB{90Ey&C@qxoj* zMYZ$ge&hZ$TR7m&%X0b0&yPPp9=+t}$3Y;6r$N5Y;~L)0&T3dG@v#UZ3sxNX5#|=G zj71@u_-LG|=^TB^I}GrCH7zRGwpgC!@xQZFSwMy)@T6p(6pUIx7An!jsLbQS-d_uH z>-E|{T=wf&@zYp+(JDuuvm9NolCr+v4lyGAFvQaGSL_QynQe$Th|oAL^HqWFv$f9A zdGb1IhiwcuUSw%$0rxq{@_1$gM?>P#hrACwBFYP?G`n!YJ|x4IQHcFIUrYRL=Di#0Im|Zs?ke1^|ao19uH> zke28?u70J$&I^JtZbJvAKy2v1{y6#?gD2(j6n)ZgpH+_TX13975-<%N7*q5qhAmkL zj#Uyvh)NyjZ;1()B zVt@v_gH;1i>p}j`bz<@#dYEgSth4-OZ-hXNsTAQJGl6|9BVqfm4A6b9mO9DMU8Xt! z+uXxu#;PcQ&a4UzM9i@{ftZYdSqfpJwpyC7KU(iLc^tXMx&her;B=LljSoDR`J2GA z1x@&p2E@q~L0wM(Gx@CYg>hQ+8Cg z#I|}J!s6=OLTuR{))~ozgF7ph{>9h9bbQjwvAFcNz36WI=4C6(nWDYQ;!tNeHc*IYNSY$H9W z&14yG^2r43eQ$-p%7n1EjVVJSZp#KHpM;QwX0b_0XRkV4>2~xCsWHUc0`L1g&Mes8 z6U;xLkYETW%&vm}%I4{)fIU{Z_@wi;tQ-Jak7RuN=hfr_U2K1(jkI8!Ag6-4Cg=o7 z91ut?F%;_x$PFZ8{f5pw(hlHwzDg8&1u~>g86dD42p2pAHbpEPlUOZk1N2T&nuApX z@avJ50WbKKkS_O16_tJz*mN2)3*p2DjSvO~w@ma=bNdnNG_`^H5kuYP!XyG9eiC~m z2y7Dl*HR@=xPir)?ZNK4p*mbL0H+>O!F?X1NnFOp!*Z>5U=jG00}HE2`XObudlGmb z-8`VHEL$SX17?A>;mrYm=Z3hm6q0Rh2f0Jq2aXziU=i_{ls0fxfHUGrwO0jOJ*~4G zE**ei55?dCHc%Rkq|Qq=f?+N2Z6OSOOk8Oykmv#3D98WA-O`S z8`;c6YqUkDo9We`zDcTsfueni+_Sqc7x#B(mp7L;Uyw08mCkDVXQu^B9m-6N(Bh<4 zLC|ehloek_7pf?`a4X7<^0fRmq=cGDY~2LR1J@0<8V8Pn%ZPkCJ+$$8FDDGyt(4^w%_M;+g5! z!0*_C8v_rewirbr5FS(v1WgnaX=-YsUOQ}+>R#W=!tO?|(SK!C$9o4GmX&7AFll&f zeSN*v6BSmqa#^kX$I>zDp)>)RE6UZ=6N4LBMXEHKvF*7*=m$>!f&iZ?iZx z?TNGl!Uw4DjYS;J2te8em!8?hzQB>kC3ta2ZQI-TX?I&a(!gk0HlVNFgBFifo}jNP zZ!^EZm(uQT3*tv%U<1gZ%D;|hvnt=LQWO62PU^B*cv%=Aj~n89PVt9`0DqBT6T~U( zd45uVKUg&Yz8;jgF7y{rT;Ar{6Z}}F=1X=-_`y-+Y2ed{*kx_t2aZ2u$t2opz!25e z>g`x2z6Ky0Y^F-h2d&6RhVbhN_=B+x=XUoaz;IT?4M2zC)`PEnzPvfRLf2$;pRF>2&LIiTEsR1p2F=>lzWE6+33TjOyB#j@P(9idjjfQ zMjXP-Sb)w~P_=de>U{L?cD`*Bg&7VB5Xgwx0?NX)d37?HFB7kLIx&~E)cLNgIbh(ndoyINQ`*N;z2a31zIDuOy%Xw@|2Dds*i?`%e zxhN7GdWJVM8Z^dLru8?N)?eUM-fdYs0N5Vc7l@xK=LuA8kZ6;cU2ue4+U*_TN6ala z7!47|0y6C}vHhD)GblkV^x8zJ_k@!V5DCTMaNcf%YqP)6tFET{j#q7^bIqz4t{?Lr z)$bm{tF!aH6H{L@C!1htxQp$?A&}>@SGd|#&D|q=EW7m#dMPU@ZDI7~7T(fUk$r_kCqXcwegS z>_Oc@z**~t&enU0FBm(hdolX5N}kX?Sk{Ilw*xp%;5)6A+rwxMiPr46F)sD0l2NwZ z>T$n4Ts8o=9+JUDqRmLwp7(*daprg`ydoS09y7s^hcJtdri+W285VG-kdsH9JG!Wl zK$0QQ1q|CHStoI!N4nnJhL9YQl$#3&pw)u{em42F{?3PTyaZB0tyT{v)QD0xZjgnM z^$G2${fG^ZjeBbHB!mDbna4S|Su=#l(UWPhS2wa`_O3dkZS8=Gz(+*H|-Sik3bVL{e11WHKg1%a@~B~+3?ty%#6h2Y5m~i7=tG3jI))Ko;m6bNT^9I9t6s5$r_YM+(!BC5;|7 zWX0W%mw9$NBXnOd0Mj1v?J9#$&uUK57~3(Y2V`Wo8?k9OI-Q_^2IxDK4$sG@C>~-% zx)0^NW?p#D0`UQH5_yPl*&rp!Zo56EY1#It;=dRqtf=tn$OyXXYw+WW~NHgcqCx zXCVa>{JMTa9N^ME!n=NWLlCW-W``5;Z4(xR!=I?hiVL$zM`P~_h>eB6j+*R|FYc=H z_H2WjIjrZ~iGvHflWQ6p!X5q$LKL1T${<>1FUgxTH`~;Z1qM5#+zSaKhp6SM4`c_c z2H@302{nf=Dy+~|_GF#DAU>1Ct|QF!wsc0Iq#1U91SfkwB2BIGq%mdO)ix8x&>(XJ zQrL#3(h?TDjVd$}*yRZU;9%JR-1-%+kGk!M8Pu*Uav3r9BkUCaoG^5O>LWX7GM#6c zIWK^I!$HRwR5g}S%#@?FH_zxX8F8t#;FCKt!zcY{M zUQg$?R&`a*9Cr>PY#+WQ=B${FG{<3xzOK?T(Qk)SE%lh*H@jA=$jr(fEI62?fX=uw@tHcuayQ~$e8I)+EKB{SJM|qu|IW)pkAk{TMoyq2a~zY^)xQF zM8@f+k$_r4b3_0|3o}YEL;uR=X>s&C-<5h&Zx9Gi_0T94UIYPB)Xk_Za@S{f->xsO zt}gCIw|5ug%gN>Un`&s^uZQ;ACg8W<=%3L**@MH3S4$}1<1}kw(^U8r+x>9@08%#@ zb5fmN{+wmyJWi5hI?MJ>7L4s`y_w((L#XeZGXw=x7tL*#XE+04q8TAnJ zALd$_qmm}+wjDI(kv-#AjT|_sCy=2zrbcB=aypFCx{HlxbJ~Cg6fzF@Ga*iAw`!CF zHPGw)$dq@*a-2m2KV8B={Qz;qxEdA zY$@RwxnV5wn9HJpKdE%|1RE@>{hes=9*4Q=~NtLuMx(rT#R_LGVce2wZ$qAfvC^JTag+GJSuMyr3_6_Nvk5 zwic$B;Nxi)JEzE*fWR1elrkI8*Eof`@3sDf&2iGUV#Pq&wQ2yE{U#~V-6~B1ki91} z@LRVR4CRWQrU`Hl^aCQ!Dp$uCqFSgNzRu}Wra=fr9`nEf>>zkvWojte@_L6*te>p! z8cPS@)`MnOCnYtyv}_OiLfWOVG-q@jnJ{4JVXJj@kQ=o$B7r;K*J5X!1|9{_xDa*{ zt`6C1049%LM$hKO<9Kb?*AHm{^!~w9M|v>nZ4x%KME7&+=o5GWE zF3~fc1IICH>u;2FJgMrFPIA*DKA1pg3e=$ySp~1V`tMCE*cNW;DTKM+%rqYzL#WKJ zW$6$od+^1{5{TRzx~u-*qKVbd|8iPUKqZ;&#N5pC-drFovEk}n)$%u;F0#DWQ@=PR zP%w+=5W=F`Y;OK{>bUda!XfbWJpxiab;6E%!Wkios>f+Kef59>gSmlpF{?(%Rc@$s z*JDSnV)L{#SnNy*p5-qpEgZE!ta_geD5t}yHxIyB6{G2Hx83kH)(k?CDB95 zPL!{oZjh4DydrdJ&zw4^&JB{`WfJJi>a|8{AKu50ukGMRMIoUp#eq^(Fh@evmtvV_faCBcU1OT~E-e<>mT3Pi z(xrVqaHf4FB}PC*!wxsNF&pfZn{0PctHsZN&7n5?RdfZ6$k~q?l}0THJx)aU3R`8t zA%Wdr>_W#;>`Qu)KZ#SL&Lx|%*FOV6hv@q&{Dkbs@j!jGP1pN!bvi?Rq*E(Pem9h1 zzzLyM{P%xKNTQL(P)P{9&(cM2EP1`hh|_|ygZ}XEap%In{hK}mUYF>+F7(-bXuPVfvGa3_#oHD=k%hJV(p0TC*5n3KiApN^;?oKq!T}Y*=U!(-Wvf#Ucn<{1csc*uRlVxKY6P`v{@cK@WA6zRr9%6mKb@R=_kd+c6F!Crbw3SWd|)aUOKpv%kI0>8yo z(zko@6!4s)nX0j1x`E!xW*~DF#N57vA*Y6Wk>oY-4-e-;)81_6YgV)e8armn6o(`x zK{@kI*;!0vP^#JpYz@~W?axe}FAKRtP0}2Dx!35Via^<7g34$-+qXs%c^^|OE)g{b z3p3Zc8d7vvM9GQE{GmGPa);Qtv2bct%|*WQU0&6_TI#5wEwlxXn36=UOjMcPRk6;} zZAsHSGcs^y0r!5juA0-35Vo{as${W4FIvN&j3+WkBpEbA@^SezpWWq-jv?)ZQ?PUh zT`u>#BJbgIGeJmoD5jqX^6;_RV+AgaS~1$|<#L~I=PStZ($OPO#Vm;7ugMs*qrQqx zvfX#d3=-_@B~wK6U3#eNbbfE9TYCteRm^{SZMh(ggiz}^!6C=298w+pxZlo~vb;I&)Q#8KyM79i4rQ>jB1`X6Be>HNLJ~n3+Y%w@AHpPc!iYkYQF_Yu z0}7XqjPnY3b(*THG0-O z8C9TpNZQaLP7K&U3U1`6e)b1`Z_;g(6VV;PBwW7qG-u61f_WZqtDRQEWFw@{j-^xZ zbBO!K@k{Kcw4rQMF+w4^_c6zFewdP&uD6dn?=`HrcLOp}$^RE1T^iHak;Xcchjvsa z1Z5Br`vJI|V;0)ALCua5T+7E|zU+UWU+3F-(|(}GzTpKNi7%CIiLn}w8sk6pgt~fz zukvy2^Z?LBgY|rE+VCw;n~?$D+1n1t*qx{T#lnAq)99Q}!ix>?NRiT2(DBGO12))yW9{TDif z7ngHLK{Ri@xc6qG4s*+mg;OJH;i5DJ;q5xRNsF=`ihP|1Hh2lqx==cRIM;p#V=cY& z?cLfKGW1^|XOFkHDIp?uln&q;hI~W|=`%r`9Njm$m@uDy@h_f=U_ zn>gzsC?bKoElS-|R7M+3sgZ>-m-T?X7)H{Zg%yB zqpyR7nSl5PQ#r`r3kanbeSVo`TBNmNcYpmQi9%n*v9AW1n;k`&Iua% z!G3RXyCd&!W7!n+TvRcO6(o%4{MN0rM;gRRk=c3?C_(NKQH6k6(e4jh2)-+DO7Ak8 zj})O_Nc8`S&^S0Gw3;e2K5V=n#^#bK5W2`Et#%$aC9N*&*7%?oe+r$$gbV^iNzBlc zMMfhr;Ol&zccmX4@34$e$i`=tM&~JRo-gqR;U|`Q|Lwt_MP-j%q(abU%3K`nF(@4| zItKtCQpFmrjrS-ZIO7m8zM%ChH!tHzEDNs9D2U)aOTO}sCJRBzgP;FghXp^K}|)fb7Xdh z`*q1O8Vjf1uP(yV=ksOy@Q``u|MR$dAc}A(+a1UBbV~&FWKlYV?Dz?GvRY)cWN+v% z;@kq$t&$!}(NW~;sF?nI2-IQ|cZZdz&4 zh38gkR*A0IZAl}#LPqVF;NE56Ve30928zwUptX`D5hgKRR$UKux2(*!@Dh(ZC>_^7 z^zi@ZP6`F-u%*z=I> z^Rhfb*mI^q*yc&8J*C_85k|2O_O))uALbNm{@+vZafo^$QNO3PCNIDB&e29CHv#Y^ z8VXt&SPZwSZQZEDKr?OUt(u|1?K=HgSvP)6@A7Is$D|N_O*Qiq2SYiIlduWCw2UaA z=cs{{-J1mKw))iA+uFH$3c?OSv6-#I38&mr`Y_s#v=Wa^BD=N5V|aQDjU^hPp-s?t zRAJ=TB-bO3S&?n_)pXs?>~`4ItGR9pd=8=UtH*Lz&4-w@th5@t3~QnGkeCV-t%W9B zcxP#0^m`s~B){xNu=*hue9hr78FIX!f`m)E6p${`%`7z^hAUuRZE*PE>sdVkJr{-Z z>&I=eDl>%7J^)E*f+mHM+gGjR%sYItS1qa%9!+odYwAGVJ_gYk!=0OFc$_|y51Re?PKMRRsn1j0W|v!hKNN|A`k>D=Wz7l6t)pr=v8Q~)>tUE^=yL} zjZAdZMi6$qh7H%F>hlp&LErKzcsc}sAGRh%xO&{RnvoJN4&v&i1C1vtN!Yme4*u>K z%ni6JK}trZ8Tz_tT5DfK!jA=*HY-MSF`x>rxZ(jokNm!r7%=c-C@PnCdG9NFQE zhI^Twe;Q&n@56fto4s$|AF><7vpg%dcCOo=Y-eViP*(}!$ziz?5WT}4R<(iAW=7}Q zDag4n`b_5063N3lvgCG26f+QNxD*QSD|(w1H!HZ#4byg@U~o)v26GP?#|>$KPZ{Ja zv#t5`yxQdmp|4}<1n`tYja2-2o0cS65lPF;khB{`f}_BYvTgC$8_G96=5Ur%9%;w5 zktjI#Vg)H%(waLEKTrs77%Z}83Q8`dy?pyKZ4+=I5K+?B&QfsZksKEyKW+xiZ_^(T z;jQ}01ZEb!CIVS-bt$)@_LycU-C-9~j<%0CW~-xRD6(t{Y7Q~osn1Pr1r^hFb|eWk zAW^aOF1^>;BJH7gJKqM_$i}f2R>?My`RJ-WJ=>?td?XUS%a0#;PPJV*L~tK2-hTMv zz1l6;*$%E&+X?M@_qbRQLv%iv{1C+!y!L=1NZ74MW_2c47`KsVQ zysQ_!tHP)*4#KCH^aM{lCStq0T^M$4wPhy>lKPR86w*OEx~a}RVaK3X&VcP_Tuk_bQ+-A zA^v-x{=_`7?vm3C4zA|VPCQVMG1kPe1rm-|+jO2jr2WN%>lDsIEU(_Ag?&u+X)<~c zfO^^jGJsE$4_gSbc1WF(f9)Dp$ad!KC= z$iW%XIH`M1O(I_hr-envnM5gN7o%~TxXZ&P$El?`d;%Ly&nGs!IF+0gt8Be)tDZw{ z5{8798wE^C(kq9j=dbOmOAg8cu>JuSc36!56Rk4#_M0t`j;8&(J=)|_;aBu!bJavl z$C4?KInWEvf6TLWGd(f>uA$X}Gu1z$SH@X{fys85<>D+$5=9Y8;}N-ilb2+;KbLxG zd*Kwseqna^eO9-ykJm=bl~wdhbPy$i7Msx&_x)pbvqgHrA{cRBLXY8BSpHktZOhip z95T~5VobDXE%j^XFU?*@#@V{oPQlP2TdA8mr?xP0rDH*yH0VJhB;%Ak)FvxA2(EJubK>;+T~1cG**AY*$Qdv4Rf`MIr5FQ&4hZ6|6*y@6$3jRB^-RThl{7 zW*WWbjRni_ND$8HU*!41t{aSWz!P||Amy-QyL))19NvHjf11Ohpf*T2ixC7RI0us1F7z)V zE?(*c9hP~E6OXyHaT7bn6HN%sRnW6)3W5%q#i!Ms_n~OdLZZNS$S7e79yoG~a-|Mu zST}I*)+vVaH;<(M*q!6*m_gJgd=Zfz?hS-{``N?lZUvj{xk?eXt`!p?bFrwoNYN0- zyZ*i^%a%AAq+3c^$pcmh7zua}Zoq9Bzh-C1R@Wy>e^5 zz^RnlwR8$>PQ>Oe?qr)V$z_u-N!X?dlkh~Qn-%;M!X^B@pV6lD;m-H9BH6~TQ6#c_^^{iw5y^(C&Z|khxOnZ<|%_A_h)#6AqOJ^ zX8 zswM|!h#@6*f73Pmje0sKn9wvj>==jIkvM0{SDL|@+~&h<_PE;%2eH_mmA{T5cX4d_ zA}Z8cjG`oDRw}6DAk>u2CL-Z|^K`shb^}&Fdk^pymxGU_KqXG8kgaJyl22K&o$cC+ z&wbh7@6d+k%q5;gV>x89bTsQw7wm*u#Xlu97$v>)z)KjaTXo}hqPsS_?rj39h$AN2 z^waragKk0^eaol7=So$$MM36HjdIOwc`GCW5+Ym3SX`fnAG0Fg51xpwTtFoaozfaD?UF>t6XA zDZiB$I2<-{lb-u8b8?stvke#YSbN6 zLf%_0v9rE0!|1&eNQm3sd%s$*33`2{2N?s1F`+5cSLwXoqMN6H^?_#~=rT8B(k*i~ z9a$gt7z5XVR758cg-pqav*0JeNREC=yINdD3jkfR7qIa;_=tTG2oZMyiFRpNYu=XC%>6)X9s44G z=H;lon(=XtTD0={O@Y&@qtD_R&ItHjkU29QH5XfuciGNMaSGv~!(%h4{8UaxOG;3G zNFft^20s)}cp4a|&EArOqvetxapgy<9a7)H-tSZy$}IX@4W#2}lugKL#K}#adlpS0H~Ihz>Oxa|Qx#JNUNKyNePU z38fzhO=tBDmm_?I+}=OJ<2Bt%I3O&8b76rFoTI|TNI>9P`l52dIbgRavhVk%8+BXl zb1XYebF zoy(@+=nxg6X2!0QlO^CqwyzSDRujbV5ORi=NO3oS#;Xf|t+A&N1&Sjy7m_5eLpuA; z(irdNQdg3aWaV`5T+9J*1g;v0w&TI7xqNyIu_-ET)};t!Oy@F{j;pwE|1;gCLjp}7 zbGWoI1SM%5wnZ!Lu#?IVhZ|Y=j1hSzJmF?I^JctK;J*xAC9PFcV05uVN_XWw+DBYq z>kYe`UAZyF(%hEojL<`u&@3b3z-IwitA$AmNMv?=O4qxe7LZ+&!jXhi1l_K<{Z9YA zncwB6M6-OF2SqWGrPRORrvCkY$IIQ43gVc#EPMoj!l+{mG?GB z@q=N8Lzdo9dPAQ-N}{wc1@{##F<=99kBV2{VTYrNSJt8_V7X}3)nM5#ZkX6Edyp4v zP8{PRh}n7`ISZ<9>1tORi6;xKuUP?iik%a`&pU1)uT2KTb*e&zT z14JX7F+DbXQyhLJySq7&UCv#+0lpdQPp_j*VnZ2+nv%G5oDe>eK!0lp1~XJ792iIc z)^r-}z%kJZUQuD+7L`G1U1O=68?#N>CI*`5uVeA_2hqhU03VY|hl)0d8M2V51ag7=B{nIZRFbi3TpCVR}B!L(HG!Nk|kSnG#=|%&baDS zUYaB%A_55oAT7&ZpS>Hr^u~=n(A4ClQc0EFB3sMdz3*!U%@C^<)2fiNt*Z#R4u03$ zhvjgBxu>A}soH6I9I3A3fBu~-6^NAT#UP*Enci)&FgrZKG1Rwq3Um%>`p++mop=nP zY37o28h{_1(2nR7S?W;?_6H8Je(i_tqSA|YS*@R^SqbS2PWrEI^|m-O+q)Pa9qg=` z0+oXsva1Dk24G?pL~%O<->CH+FJ+3f>X%!HJ@H0*e~Z`v8TiMtdeG}mVQ44?uOMEK zG3g|d}+*duz!ClaAOE2jYG@XoyhCq3Kbz1lD+WXJ6Mdm8NIN{_Kb z3RiYpZA`n(NWb5QZE?R#C)lnD{`cw0_D&c}e2#OgEb5XT%#WMhbv4T-{hEt4Hr0&ULQ5FZo8V^X;lv10}HsFB2KWX+j%aBqr+3z1BYx7Q`|k-7=zf@8{l{aCNEV)G-bkcF~(bg3707fylFA>RF{=Sv7fk=vkr?$y!? zl}N}jjTJej5<=duW_Evteb{$jhUB#LBCm;Q`I>{RUDvs7l_k89oHJjfU7Fa{ey{NF z;nw~#@)J|=bg<8dEZ^^_oxL+X{UI0GP+CTVxCWT9=j z(^Lv?UlZRKj|Qr6e`EqUNkYX~rv{9DyZ_QB5?6H51Q?x|in}n{zu%$Ec(mP#t&0pu z@{qR%A>tjE(@4s`_d7-$$==R#$7P~pBN&CqB^QZjgx z27*x`a|MRvGFxHF5MDW~p0j=sKjw=C1YAzGB#EV;hDpbk97MJqdZ2sPP65#2HM}Y^ z^Un7diPAWt{V!4}JN?X*;Ak-36)!XJ97pmouH7%FS`+Yu7~`zjIgp;(KUk8=r}-SJ+}^LE3P;ub%208@26!n?bL=Eor{vP-At8o-TINOmbXMaQPl485GzBm>6$|e} zmOa+JFJT%)v1*y(gxPgoql=>W&j&5HxF5BENE0t%#P(vZ?gq619UPa= zx+!?M5VU3M?3*4+;p5nXwEM?pkSfwC#FNy!`aWOk^+UD;&U^ED6L=AS+mB%LjV(jb z7U)4G)dc4YyOaM9=I31)+UUZmFPsYl>boUGy~Y?F2s#hh=~O26(PM#@&hLWtki>JWnU|?^u`Z=FJcB{R+mPJd( zmn-|B!vNaK^Y>QGzkmP!{{%S~Nv-Wm-8<|S zaY-A}QaXyxq<6J{?nY+OGgI|#=U7G#Un~Ts!t5Ns(bIx`x+VR3R!+gr!AZHBFAEe~ z?nyl(ZwDdhRe_-Gxi}{X7x%(Q4?(;;++hFdvCzvB{YN@9xc~E?>=Kg*Sd3D9ywhY= z?{@2k;=t-DNIL3l?HG)1v+{{Pfikh@juaB$$3$r>^(u(G(90Xh7`)e&=_WsQbJH;S z=igC$fiXIUexH9gR`hJG=e;yLO$Fr1?0quB4s#*rz14Hr&V0ZxW`t=HRgOX`N|r|B z96Ntp-6%-FC*lb)7f;P5O|@Cgh2fU|sk!eY<`Q$TZ3hI;q$ zs#l*kmaU1lL6>DFcZSNfxG&%_uD|v1{v1a<8_%M>DPRN zm6V=K3-4qQW8Zg@&`Z0@3LQLZBqcIT8nD}KeL~)?XXO+Gord!(WPF%Q5ZWS=o z^R51C-D4LT)KA;ZqAcN1g6Cq#7*TBZW~4}FM@RBi6dswJhZ-}o)zgwRHuss^G>m-3 zn4hGi72Lp9?zYz_N@j?!JAXd~Cx=uXb`{>0+iFg70Fp|7B7X)aRWpe_132r~aAAzq zyBob8+o$U%&`=`vMM$K0s%i_a_1P?cuyol*hIMQ6i!96+z5+G}e;5f0ywBOXv{Brn)WO!CEj`oQ+~|4r5vOi0GDxOxW!&EHNEM? zYpN^#0M}?Y)N%wW4tOkxEsX+|(2?*1t<8trm`0N?*_S2;6nZ~qwVfgE7t}_nu}G5P zy{BfQyHS|%du&HZNu?F( z)$s zmIw$-zm~;)Lwhr#D~3JH5SMO#8n=-U%13X#G*&*R#Np;Kt7dMpb#&e28|jeyy@8{Q z0$J@&rzGGZ=}cr%z{$)HIBEczcbB8w{frzx3sytvVM zomFSMt-f=}Ts}5SU+b5-P?CNC*Ho`s;}}Np+3r%r5k0DB7e#D0TEENw_Ty)j1xG4{ zEW+_)<}*$jJD=gbJlm8H19ifkyd-S@wU^YT5x&wtFb?e*#y}Q5n?L}JWgtj>RY-6& z8vA*f)o4C12CTqU0fBx!rVo)u!WW6~Q%UFZwoj&yX^#7xV{m4@@3=+-diMUSMowMAu~dTs z&w`NB=x^DHQ`i36DVRApwFWc1WV^cOQF1M{C-ML`WSyb@T5~zC#>Tk+z}-yYRg=s{ z>BQY^jWfO;E|)fJglkVcL*BARtIC2)&>4zI#NPY7!j$-*02a7tVHh&^BlRbP6}vF2 znt%zbah*OJ7ATU_MRL`U)curd)LN1ua#ieuYmw1*sV!wBO{EmPS=*gmAq5J?L_X>p z4%GSf5{TV3Q{ZxNXzd(OTir%c77B%=s#MR*u#ka+kLAeWBX+le9qgA`*bQWX5(o!a z3|=lL?KS`2!o|nACMy+$(-EU`>%B`2YT5T-xtR*AgYz4=r^-|yC?hibK}=LOB;zR8 zhoZy7Rr?;g=^hQ;B;+iC=&Z|#yjem7;v!VlT{s0P7aE@Z%o-R#lG#N$A(c{sP!W?O zD8XB6?C7|{lDXE%VYJHhqI|Y5@IWbnL&T=MkxX>x$>!YR19*i(4(KI=t3*G22Vi6E7+g_@Meyhsz@()-_SGn3d4+50M6WLV+r z2zp&q+qLN(vZE^z%D0&Oh`F+pw^g&h=xjZMkSSQt+VvL`jy8)-?Oemp;IHu`y7d{{=Y zNr1DM+jsRB0Bt~$zdU}&z4sd1&RbaIp|4Wfu}eS#CrXbX*uQ=A$> z&cU*(@`iU2XK++MU`7M%Q>E7rT#u&QZs6;-+P`Viw|l6r;k@NUWj%yoiph2u z-{jq9`z@kq+Ue3kd+8M59E|Ga7Ch~CJw8V0sA@=@(w0@hyuF8U`f7eDtCD7rdUe%N z^}?4;iybiy3*6+c;yzMcZZDexnS(jSNZdmah`KAx$^(`Va|*Fm5|IHz6~~PeGK7}N zWWqZz&)eiqZEG4OzF@H*D@pXxs$8$nAlg_y;U=9DmIJG&Am~sFz0P#8S-yDJ5a?}= zt*d6n`nT<-GQ0#o{cN{~5GB$Od(}vj4Tcz(**Dm$hkeo`e(?qPZ`pcLR`(XTExNHc zLdI{s7*%g0-f0k7HoIS%&HsBOs4&3xE}nv`LyqYdEYxOK;UXEj1nXIhAShx&02RfC zb$d7YI{XqMiPlax&32BvG+HRPoO0#IanxaperopVbTWI_PQlM5-_$$DZhqYoPR$Wd z5yaf)O+nSPhS&Vyzl0G>QT--gWynf~KKNjg*#3sYeIJrpQaHktCVm)_;*Loh%*(Qv z!9U)QK|SWqEVfCt%=a6ZjxTd5AC|Mam1)P~D|s=o^Ds$B^H<8b$C9RvsS$nSRM5R7sqGNDouu=a+uBx+U3TO@^63_?!zZ6vb!RN1=WB^)W2?LYcxerA=fA8AJzGg?&%HGMdR^;!-qAc+tj~E2g`gxs!$Bj%q@bcb1 z4mJ}vD=kQy@BPWHY{WjQH_L>iV;VLygz9lDgY_pu=}N9oRh{8g47s3uNHU>4i85~T z^0y_#2Gyw6Ddqw5?%2stV-vi;NZezWY~fW~Y;fe~sQ0`%DH`5hI0ZkKxf8uw=@oY5 z|E}Q|d}+Jj$P18I=g)A%6A{FOi^z*4-@S`}0yjK7yMDrXXI8P^@AX6vd+)j___^>8 zqR`I_Y(dWiKp04ArvsBDU^KgcGKF{ZWp1(yyEN*UW%*dna&ij0cI6Ed(OVDYibHyR zS77o&MEuzCuV4&M0PV_uQ6Bo8=|34$PoMP#Nu5vN(DFSb?D>1yv~l{So* z%!i=4JMh%(?ZliDSu_PD2jB3b+$>RD3eYlfig^Hy`PYZDZm~kyO`Ujm8SxI2kcCK% zy#LTaN~oJ`y(%mF(YZ)mG8@{X}3UqXOzsgkc$Gi zxYQYB5n<CVCl__wI3^V>bUP=x|H3)XwB5A`rAiFGg}? zgs>@q4Ibd?)PX8Y2r00K2qI)dBf-DdEvto69;&sVtC`BP?d zf_~KNd{fTos2%sgA%gcV>?8^_?h}3umqK~(+9~+C5XdZd)!zRrt%(4EQxmqGh>-|| z2!?Pjyc=Zs#XRC|{y213*JWo|r!O)~q`(>rgcYR4tVU%-V#t050p@+Bw}%Ej>5Yvw-1G`M;sFOrXZA9;i;WAE%dh1XLH=j3Bo^{M$)?~;I)Ex498e>VL{l;SX^01 zo^NzL*Ndz=*_51sq2*HgOp*y>)Ku2<&DjIGZTZIK_SS`wBdE6PS0U*_dY-{Q8fu** zZ;kC6D<0D(7nP7vG0DLHsCK4c*v=l;*y#1j;J!&D1ZPqyUxnRKyLq!w!>@Cq(YCvC z0(jiP^8T9Rbk0jJorfT^ipa1}8RKJ>c-Ka1`#^^}NOfK>v-bNpXmJykFvVNGUX?Gh zv!dCpLsw+a$|(rCXg}t~f;NzLQuH{6K{zRrB-~qC?_i6&0~mTnoVy{y&sa!5rTpgR zygkFtX3eLJgVkL)1uF+P@(#_bn2$brLm3V# zrVJiA!WJ_#KRqn&)1sF>EPe%CE?!CX(gQK*WPXOVq zB~FVXqh>5YbxaeUMv0j?8}eElifa2>+D@8@ym520<&i$-o&{6TbMR4c0@P?6cA^Ri zftcMRpTZwB9e&4-moV}o@#WemvEB`uR>G>d8+mDm|L}PFvBd6W5`rx-?^|OdWV6ei zTQWcluxo|vSvmzh2fyTfzWMQxff--)v5m#(<=MhN5zZYDb_MW~zk1htU5|7{?#Re( zEAdjUnpU{ua5gHzabG5hJpp8F#QkxTZn^g1AD956a7f`HE$aE)5)|?D#`}V{s(pn8 z_{l0IMIh8`u@lLEi+u*KqxZf**BN~9LG`m6y(-G`$xcpig7Iz-d0Sa5Hn2&m1UGOhd)H1u&mpxph8|O*1z$rcc!+$%F!g@(KF-na z{bnRt`yu?I=MBx>N%+tvr#)%q{|bB#5yu#OA-B`=2wzIM+~DxN(@*)PG&P_hv+}8U zSv}<^(Tin>WHUZIyPcM+{|b5z(Z&w6%W}RctAE^`AN?03h$f0?GLTJK?O25rk%uys z-UnSR*4e=Ay?}SG8}N23K@j6WP$+y63j6Sp9iHjUrk6ah{d>FuH5Yx0Vw*iwx~@Bi z4!r3&PVF#Pz?CI@sWObfo38faq&RhzAE0Tw(N$Mw^ag_Y?flUuT@)eCE*rw$zBJ2h zzg?%}H?VpNlnx$s1ooJeZ^3a^G38BB0c|&pxKfe#@#Vg(7HDxjLsfn;@bb0k8v2Fh zk=ueZKTKJt;S^SE4x1bREjq540+dSuyn=nyeKSNnh?ubZ&Z0m?ksZLv$guOA>=}5! zmtJboqz+{YWTN0*AY%!u8SeAU{BLc`C664qzO_?Obet(N5Ki{MfcmiJU(aqZ+OB%gk;7hQsU8Hc_~W1mw>yj_tD&(ecK_Ju5;e)wD@ zK#ts6eblpHalxS4?jF)?2}-k-qSCD?l)QMq=4;H50+vHrm_2Dh?R`dpX8RHB<=hGw z(v&2fgP8oqlv}ZMoH=SUm5Cryv7L4agM^b7NFM)(yK8N38_BMJ1vRNk%~Tc$`h`d3 zizG^xwU#BVsIfDtRHYyil4yg379=HWetqt3fMj1h+fa5t%W-f299AS@Bcak}vB--e(_#p;WmJNcX_6n$VWOl) z>f+dj-?(PTK&-v#ue9N8rD85q%)D#w?_o-Cwr+lQv3;7n!)!J_G92D;oOfs-@z@J| zv(YV%JmoXettBJ`X_pZGJ1p=exj3eGXO8nPjO``(O4gs1bBrp&i#{e6&U7KqV*x4d zep@V;Z})Hm>sedWHd;oGv7}AD9&eDFbe<&#br1nxfP`rfXhe)O^YYk^PXvN8TiRp6 z<5u(!8sS+_aCr5RabqlI5ot_HL6stTFo09o?P9`Mq$d=C*T&ARW^9upZhr;1n6C^Of$@fLNnkN;}@eHRpP=&0I8)GvIPx<)n*qQt>xrB@I`f750 zdwQ@O_oOnjq#^SJ0RY9qxqHfsG}(3^bf}7*7X(PqK~4~dkt+gJprHiYn=;)#RNH`Y z@54&jsLp6lL}x;s|H@YccM(ehEn^;6B$CD4-B-9PS2KvH9#S2OO*@QsnXl%=C2qE$ zDi%Yyj3n-XnfBa8u?L!Q_s@KYTB?2U7!%sC4VLL-4H%%>$-XjqlE6C&LfXU<1kUZo zksZjg)AV`sK$lwU28~qUBHR%}$}cf1XFXK!Xg>BHM2n5cioSL~EH=(< z`T_wc?e6u#k|fE@;7p|SR51&k^CEdeP+AJVxK+mm{4u>pa(S9N_%=m~;7kg+xJXB)aNp_xpgy?^g^ldi=d#BL+(|=F(-Nss1~wW^3W_wGAC(LrWm! z{|7es{~H2$VWT^6z18(`*s@oLlndo8=aCmGlK=?q zA`DAv;)Bmrh@fdm>4#YPby=*;hK)%M4$uUG=3%#{;xpIi`S(U0HfjVF_4}^s+j6-C zOqku|!V{d9&as*Ny1+K=dC7F!O>i*POlf+Q=^?fN>171osPq^k{kzyTiNFmjiG0fHb(r*sIuv1Rc*p=cZK&7%Og(Z}$B` zAk1q(U9Q|4RI$~Gmd_~2H9+W1Ay}}vD-863_r>>kj0$0d672gthk-|U<~>_!0hc^i zt)oYn(uU*vYm#Mc!h3MFaG#rO88d&QICt9b^Xxdw(q5wPSOveuA#>r^ zLU@C5W=Hz}mL-tp*s+VyhD-SN4V@@T1i?eEbSeyZE(HN17w&1EJwNql@25$TtV_IA z_azcbFq&enl4RB0B-`vr&+cT{i)oA-V=XJxyc<;{MEHc0xz_nE%46UK%^_{%kSHv7v0PpxLV zxC{w7P6$SnMCXxnj#=fU4jWf!$h526JIKzj71P%wr*;+7tpJ;XPY*4-r$M)o$}Gp`W|Vw~KWRn8D%F5mLG;;6#WzUmh8x ztvyUFbkN9?P1-qP<^V2)}aZAu4?F`UIAcbdYFxAjW_u^5DkAd=uLkT`=YzM~XD zUBY?lT&8{9FVzPbRy$Ag;&DMk4C&$x5rxdm5zNa+OBGQI=hz(o4(nNfSTt&OzhQCT zeOPR;?qDuGPDs-s$l#$QRSqfqi1g`p3MgqTqV@@x%HYfo^mcmpv zK!c(0u3H=O5C zO|mg^jPY#P=x;Cn(>XsozC9R@L#%4{)+1_7Os z8(e+ZIueI|Oe7C>_v;UL7)nqdHpXf;91hrQ(BOtta1Z!otJd3dS;U;__Fk{1Zl?q> z1DD{uIoJ1i8Vnf?ZdVK{cz~{5DRuKBm@cCib*&q3~s92__RmtNW z2DAwJFV-0?vh7%u_Vxp7@sLtBqja}vKo!K!r{p<#+Gg9{R{Irvr)+DOv5ljZd_|_HHobFS65J!Y`V@T|`fy!r|4h5D zit6>fUU3Mo2_$!<-=Zp4lrON%)3pvBV>t`oc=}c(Gt{1K^k)dqSHc8ipwJ7YO;XZ# z&Wc4^>WTJ%S$3b&AB{n13_fMx1rZAxCR|squmZ`q4<2JeD_&fDt1h55DX+OFVrdrA zga=V9A#hcGC`$Q_s;j>9%Du_n8XDfs&;pzPB=_q=kQ+TsS69-Ezc&oo{Mi`0*?_%0 z=fW$YK))C{J0Xa^3*yg6NEDkS>=DOM>raR(B{6k^!?41ban%7no^JBh8_M(L1EN(W z=W0V&R68Q&3{PyfWZTd&cC(c`NT^ySlIL+rX&a+Z(Txb6Txm72huGG0OUd)IhKQ{D zjfUcJG7xSkn^1uJa(crE#>1d7hO$H)w-`zgkTw`9BupSd%quf>80mBJls_l4VG9ME zxjbqvtACP(Y>LyF#)nk#e9fcf5jNqOrD^15hzZeo1n!4(T+)9)IJ$Oj3Y2(!N&7j^ z?_js|*JvUp;27{dpZli2k(U!L0gUiB6jko(k^k?1H%GsdcuU$4TprlE>$zX$i72Li zTFfG1N)|Hb_o*Y8bJcM@rki~IJv9LmZH0ZogbV{lnz!+fJuUZ8nWi~zr-e3q7->8k zcFRcyE2hk9BR%iyVs*fYiNI5W;>4s^;!3q9Qu z;51l_Z67?wkTwc_`i{9nDBH7ik?n5G{u&i|M?Cl{a2oUhlnpQdDuMTCTq#aIwC z3?~&fNqy0&y&j(5YJg$4PU1lwQ%KU!4HkYZaW-1ttD}lI(n2=G0p(TYoS$8t-5%dv zTwfi0y}%R9l=0Sx*npg6LIzHX5}8PyzrN3l+_}$QI%4^Gnida>G@Cp3X+oMmTktpv zBYKU>CQ?@LVOjcSU2(0lA&=<_w&(j&nl`kd9~K*arwPUOt4uJ$UoMcXmgLeo#1?l? z`SKZQxKF?gkKHVT=Lo}TI413xIVHGLb4(s!dYfXgT_+v3tN4$qLGQ4YMGk4#XmO0; zSWC%Jay;}+|2Xs_Nm?u-Yy(ZUnt!;{W~aMVXS#CD-t9<+;L9l&ejN?k_o^=J&%kqsI+jFPtzZp3Pq<=>C?J7g)k31T#6C7R0Ru#bCP`Tl@TsKr9a*%({X{T z;%1;b*U#ey#y0R_Lw1fIV?~<`ly*ssCJ7xtOw$B`0pHY(OXlG{pc)KZ`m90g$ilpH#u)3G z7;Nb&MTnyyMs@BkF7M!J-5=Rvs;leUyN@3(&Mr?4YqhqY1%B)X8qrDI;boD(fPZ_0 z*H2l~U$pR=*QhX?L&w<8#=YAyTHKoAD+2eeNwymM$gV=b!#v^|-mmLvJxx7LE)jOjO^dfmmhb8@F=gcY-ew58!^UW7Vh1?Wd9}2a_91La@e1~N4F2Q`6)zJ;s-VF1kFF7@)D4!~ei@kf8enyWU4WA(c z*^-k-eYkJQk0Bt6IcSU>EmEX-grBV*v$FnQqM#=EYK^}}LoEXli)2%W+zSFpnLz^Q zCW9CuK}y$pW}s{`4FX5H+aMaU(zP-_~v7 z=D5)ow#ffYpHWAtDmIb5j;RJk`|CNA=G`MyxD&7%pzpd&bAs8sNmr}2Zi=ii?uBj$ zOEjj^5Ji4}w65ma;ko&vcfaR{Zb?!2of+ zapyfj3i{F zOPthVKfQs{Mt$5Eb6I2oPtV(n=XhPn$aG+s=PN>O7DNux2Y*cGbG)~^cITOfWLVq@ zcqL#qMup8QVgA@Gg3}|dZNwOxS&@lqR=`6OL8D&*4pG_zpO57+)X%Q*H zfXTRYK45>@99`~h(Q$)*&QU5EjtB%RpW^JIBnET}GIdn3GNB@AN1XIq|m zvvRT+OU(6D2XcQM!^fD?%5$zT-SD-DZ^Fu+h+Qg6cp@aJEI2D-WOn?xU1D!-7ythB z8KZ!DR=-8h1#i_zXA>lq*4TFdFJXp9Z^_e;gb;b)9oDmvtb%p0XlcvBvy-jIAML4`B8K6WqN{x?HG+=V?zlWUP8(T zoNQnTJw8F$c040ldr?w}?kyO2r9}MBg0U~13AmsoqjFbgi%xkJi`3k~7jsxdznB?& z4GeMvC2LK}OFT!5<*KuX57*n1o_;cW$Mq3d_$shdk0H=Q(YwP+<49&EO_U!)NhY$= zz!8g`sotj9qPzO0d89tSQS@ljzvBYphzQQQFf{!XEI}5VQe!09O|w1g+#E2*ViukX zCVwetO8B1eVjlB{iXy& zeZXjY+E8ZV;rBas%4n@a-4%{qV61SzBXH>-ycd)Qc zQ&@Knrn7RY1NUzG=rM-0a9qw-bL`{0*f>b3kiXtn%>oC>O+^?;Lob$OL2};-huWCw zs|PXzf(ti@$Q7cud8%h>Cso=yc8moroR<&VESo;3so4gucX~a=2f;}w%m!Vgj1vTb z1zWr9jC8I#s^=dUv+p_KhwBsFL|CE67$K*AfcdU*zK5!jO?9s2v3JzTx)GlDDKoU&(gwaThLe5}E1QbQ`Nf zp=GqyEIeiGdVv58PVjRG*XM+$j0;Y)DY9f5+$RFK^S5o9_Io2cU3$Y>tsRdpgkWw+ ztBy%h6iDiebA;>ZQO|Io#h@{EY(N`X_;e_{49CyxJN6koEKrDoSWx&TJ6;%hf)fj} zAa-WE9)eD$w;K#~5x2V~Dbc1GLtnvJreK?r^9=mw%|;6`qo3Q|cC}MsHb#xHn^lKj zUgtemo{E`?y#SwBDbodxm@~|JDn0eoc18@Ra z*pdO&Q=RLX4kSODBgdG}rnG1v24KtO5K80^;7QCEYm?y|;@W@|7~#IzQ+tFIJl#Pvr3azPJ|U(IRXS3We$aZi?h(vHqX+>}i=~n?H5Eae#;mhph3-Ez1vn zhfOU!m8p&%zP1$8SY%41h0KHdmEa=dzz~_U*3RgwrE%nxD(mTc11^?F>(>rxW(^FW zKOAEwOBV%h3EJ39>LCo-Wwvu4i_1?F_M@z zi1d$Mk{>@7Ln;~7;IYba(uOela*NGc6@acGUMONua$(vm@B$h|F>ohz!La+7JA8y; zvW^;$iu9&5os;bFJXm8rOx|NWKskG}`}Hb)9eZWOR`S)2Gw%-kiPa`I*I`HqkYOE) zn9#q0?;^maB`IxJ)nfnJ?nNkB;7GX5Yp2{E1GOpN(W_tB7&pdp7T~-}?fWEIr^^%p zi`&)e?IkfY%b_PCK?IkX7gOR37KYBJwCG{DG~e5M-%7Y5Lcv{MG^^g_8FpXIwR<&= zG?z_pL9v~sJBYwn?3UZxNpX+3Cw>4PpP5NIM)`T^OknDGqxPT~*ASuS63&^WYe3>~43#%pOhVNTnPhNYh_hEM{=UE|$8lV7vO>UIJ7Olzj|0K;%Opcw|Cx58eljnsWkkN zDcBlZenUouRku-fZXVb{NIXcn?YB(OxZ_!FbJbX##X~uqt-i9@E%wFwC+n9R4dgDn z;0(5ucUBl-&D13=Y^V~qE4T0{GhN5tu|E#0=NRcHH?%zrY0k6bdTKVyh|mcFr65Ew z^_|(J^;?`}$%Eog_2a2O`$TfbeIG*VkkkMVpPrkt_m1P5&%Oc6AMAXwRH^4^;82?> zADi?;!UGTNuu7jBOp&4SY<%>lE38114r3o4w9H4Do#i90hsLO6dfnD8~W;ZsmI z2-?q6$d)&lfywOHoC&F0OvuqZ)FXI^LLp=)Ob$qcBI~XaH$mB^vs$Y&c&7pWHBNR& ztVBK-7Uj08ck%FL2gI-BM(&pT6PvGa&}jlYlSnN?$|^lNSy8J8z5!jMh`s{!e~>et ztx4eraw58d1-T)JoDhT6t9-vs^@E zyWC=b{mkLBDTE`C8J?gD?qLNb<;k|-GnaYqETl$2q|g=q$LSt^kkQFB@`)*sn)Kjk z-Ch`bUgfVTro%79)mU(!x==D6>FKBMDi6Ra`|QV*Joo_WKszgEXp#jHs7KbODyE%k z{Q4)_zC07tliPfi>^Hq(kwCL@o&2k0>`7$F`~WTDAs()psF(3iR@LNxJ|L=iUZ&Xo zrJ>hr_GCl!0N>WFg5Sq-bNl(~!yg|<*I@OtK7M%vcn0?estH&R#W^8MBkO@2!amBO z+QiUlum<_NOyQXQJJ;XdK4n=y`s-)UpWR+xo!_*Hd0Rs?JRImLL!Xd$R(@>rFUA3=U^A~Nm_Jk z;1tkIszBOPy<(&K*lL55w#ZMp{s|VU4b5?w z{$46JbPdN&&2jvyrElmI>!`nJo9Ej->C*d@q_g6+x;A zo>y|eeM~Z$?B<7GfIp!3xa}D*1xypOY>XdTo{HGj;4uA77Pc=amoRi4>&uJv^)XR} zOH?i%v&lZsp5jc$?nC}U+=`UUh6l@!lA~dEbNoLOE5OdUDUcZicUQ=z+Gpi`k$l;2 zw~d|N|1)@E#$C5l##z;qMT<^-vP0sEeZwc-;d|U5-n)xe3DqxVwnIcdJ)1j3)5#5m zV;$;%BX`sdpw?<7t${@JARzYp2X$FE7A@pLQ zYx|t~FF1Z6EG6tW+P`oUOBB7+!0HqRA|__O8_s-Alu5qD4-fMg=QpN@(=%WSREBZg z`}bDWbwtQqJhEA(=X&fhs;QR^T-ce3ayYVB;U!7=I?~N>C12rO=(1P4cPJvn9$Gk$ zBDW*Fv0le$7`IE)6TZ$6s;t+l%SiJxo&usl$@bkXGu`&`LtmA3VZc6-*twsmec467I z3BD??I8b(%^@Q@&-C>Fbq)ekMvb@2JxMBnZ7O{o*(F`K?6m( z)-&0jYo#C%GZFoV>OW%%$E0^PFEHlp+$M_v_90yqEI|2UB0d>nJ^5CuEATP5?1ONa z24+u^8#?YRaM_GiEIa~ce3+)ud)zmAa)4r_htOfOUdW) zK1=g$W!N_85!gJrd80dg*0aFz-dTYVkoFQ=%I3avp&oLQ(5ercf}M#T>iOOK>-)R& z51&4KdXK)IP2Vq#_u94jfNGeCz^!t<+kFX79=wG|p{(~s9A_^HZ6)c=(~v_JMOZ!H zJ>rOoi5D~(HhB>mq#PfY>&Hab>%^{QpXioAm`rHEE@bl9?4Y9H^DTrYLn^#-XZ;zk zC3SOqmLz%!9By%sTcOjHq?>Q5*$rbw2TZ`o#2V^WE|Z63X%Q|fU1lEjzVif;TJw-k zczDRzJw_=v541yMc!hbe@r9A!XPdpPzH7HQLH6j3n*yLo^|;72xwS^I>A2_|+v7U7 z5UCx6RP8ax`b8!M#HQory~7|4!t+!vBw;6T50Co@(rLdF_MwOdP8DVfFX2cnxifC+ zYieQxbrr83<)-Dw!?DALYWy*J)WWMu~QmvJ7z>%ctEj(dhVR1vV$NLI|L}kfa-|IvmDXnr)quo*2b*otbb{A9c^` z`oH_#Tx@Z&$INR;k+?N%3Unp{5Cwb<#*?k`orvtnBh57)tT=k4MqFT$wkxxJY3+tU zgD@+Vt2l*!8p!2xID;T8uzjil@d4l0X08Txyxy@>Ff<5}&(ma!G@h<$Hf(l`m@)dc zS2b8SoB_tIUvuTTJrt3AN|v1t;U0Qr=sEBFAVfh^9l5nEUX!f>GbP2}FnhBGwrAvM zblBgI!t9%^%w8#SLFP+GfFK;={Ko}1Q9|&MZcicsN`5*@-&CMb!UCp zDW2(|vhHdf>%5>LYOf2~gd4%>F1o==J#iC)bnndy(XW(vuCU z)i`w~!_t4_+3XsGhN^!7o6(xeLEGq3ctOjvf(dfb27h_gN59WuR~`J!X=`vR|SA~%q#$<=(bJ0U}n9eyBcRaTI`0a24K#RQqNR%Ka4UwDYy zV3*XD?3gX8gt=Lv4s+qOFR<}{OfBqlfqSEV_H;uY*9m6WPa5y;Y}W%{==fA1RkVB^1HsXJC4Q7eIjqDB=Xa~P(2pL<05aP01abT~ zoLmLODGlRYsSSS9*==GNP}Rv`>Fpq)$d1jP!nK*J7Zn%_ZAOUAEP!ZH)fKGI@@c2R zcII>co#i2I1q~6kUGexeqw!DY0gYpK{ebz&Iv^b|1wMnou}2>DDo$lr9o3^Q6|UnE zxiKDEUm;)Fjn=pHCpVj5zb>lnyFRiTbm+cG*v7u$UE59?$fDva{7*@vdM4&lcgm?d zYbVVRcKgI)+J%6prKK(W%42%iC%$_p*QJx51r97a!ChGELeKZG9X8MA)jtdp+AC0SLeCjDNVRhR4+dz33zh1cPhnOfbUav2~E z$=!Qn!T3ys;mmcoz9g5qTs|(~$CUGJJ^$@-`l(#>ZjGZur@(6vci&&1e3#`hHT?Jgi0h(l)EE5gZ7LmcL6)u_Qb)v;GmYbSX1amdI zLLU3b6if{w@8hANTXTSue@yK7*h zRqO{-CPF-cGL{*Hy1(3>g%v?vKce!q8>@maN9aqpGFXbwn(%gQ}N0l~o{qh5)T&7%xAsW};Wu@$^zQu;h^O zQOR=uQy9)%0m&d$p57L!LF5#E{}gP#K>&GIdt@}cB+^CVauf_`>4}OqJ;bV7Lq>hR z{)~&9q|pOHqBd8K?n1BIR>|C9BU3ZnnJC=!eC`ck{y-a;*8GY>nL$)N=yZ zVXZ&02_7)atYWC3b0O2!OOkcX(z+r+0@k0ZDl%V>b8zu}Uyk1c9!%D!OVxNLPE_~B zYyHN4P0~%1OB|b*TypUYFR|cyEQ8V?D#NRq_{YkK?mhUAscBIdlalm(6;cUkJ? zk9X(g6Z{>_A)z$!#~{Q0`Z>)3lqApK5A{h+!PtmDe8Bh)f`??Sd4_v-=;}Jb0i@uS zrC#%1(~U|_K+zc z8U%^ANX?5Cou)-7!Q@4EjYNJl^$d3c;aE3GS*n6%x&Mw@oS1B%sQZv>t^xU|$mvVdkqY=F1bk%Y z9BEdJ(3msQPn_RmHa|@L;&dT$Q4f7%DbmDj?YKF9#QLCho5pe{^}vzCnL}Ri2;e36 z|15&w2U8z-pMSDgV13fS{1#o@cJ`C)i+T%|iLue+8{v9sW zSgCn>%e3Tg26(B>X9Bh+4sEqjRmHV^iDT^^huMtlcZq?p14ioVRk}T*3vym;@=VuF z>xnia=2|=uD6~Q(sFEz7KUT9t+APlPL~B)d@YJk3FvxuXt*m_IPE(`2%x(R67lKhu zKcABZtDrIn6#j^K8U*cSvdN26YVEGD0xz;4&CnA@2*&XaVP4iVHBzbRA3Oy^gOo=r ze$@s>{gp{#7R_zphk6nTffMrh4!a|2Ne=rh{#a%5EcD%XmIyt-mx$9{$t;P}`MP=9 zQqBJ~E9m{@#a6y4Y%+0W!(*iqG;1*gu=CH=1-t^!77^_{_0__>frLfwYQx!q+^E&n zJiy5HA>f3+G4uuQmUkavrg)h-fLrxq_Y9c=oI$|e25w9?Nmr#pax;;agdGjbLRb3* z+R)z8P^mhFTn)+}S5OM!sAJt4@Bby9Cicfga^y+2u5E)LpgSaI#Cst^&pX??m+2xO zFX(O&Bo><&^w2dt1}uX;lAMjTe1&l{L3{P&-%KYrJM>$002*fcEWMy}<;xkmDC z=4{J(8E3OCP8Kk+_fI3oOK0E|_>3a-q-CIjycGSqF!B!}x>n0&)>ruENBNBCcXI6m zQ;(2*V2SA^-L}N$Srl+MLeO~D4XA2ylFp6z0B@cyybxy)jIKqX6MdNNxgn*E`rJByD)MXw2SJkU_Ng3} ze#UVcq^+xKAsomA9W+MOkKi0eX_g=-$+wEqOg=OHVlXr;iC@8)Sne0cP7i9a;&R*f zbSVu?Q+%QX;rjl;>ulUePn9;tvlWkpGgr7X77&-qRXxcn3Pi31Eb?VMaL=&L^YvS} zdM1u}6<6AYra@JC&Rw|$LH@Qz28*j59Pxiy8+q0`U zcP}_e1EN{~;3@bSxq`?HCZV)ySZJHmjLWL)l1YjXd@oBQiNE4vq3-JQ-C4BlBW^E}cGs6yq#3EIrCH(DMV zH32sh!#Abktr)|D91=KndBj>_Ohj}IQ6obtiM^4Iz~fixt8S?K-geQp$_;hNk#Dky zS4haIpL0@{9Gl*91;^#cw;|5zdW@tD0XuHdZaS9}FfnG2`{yHQd z%O}j!T1&6aJDTFFx)O*}r7bj0VG^9p0;J@)MBu;q@LZd8J?C*a2ggqV)#$1}`E8%A zHK`Wv*@5sv0wos_k=G1)go=jh>KUC8`j_Cx1dfhz_)w43$NSQ-&xY%pn%PjPfc)tc zcuczQjtMUGuLV;vy!xNxlde4pm~-7xhK&xOwg7CiLxwNC{X6-MAS zow3O6R8|%^NwbE@zM)f~Gl=loVh`4*ug4t@nc6-ve?u8-4ZmfY@8W^u;rsXR8d|+{ zcR03ZF5Y;$u3k*3KKW1CS9&JyZKxkw{r>xSvn4T_%c%x1Z2S6-#W}aC%K1m^rs$+r zhiXZrL38+yrqomu&Fo0tN=z_uBKsXei@1bv`Z>nl>?3Ru zb|YyUJ-l|dL)b?mKw|C&^4N+cGKO+yiIrFFE zMB`PDQHIj2?Hw}(ITNmBl^ZL*-|i4$v<0XmTM#R9Y@e?R?#BYV<69STiVbnfs zv22Z)f|g078^cZx8RX*#jnxVCbQPlAfD=de&|#X1P(M~kB#bGyV8BI873xG+ZR+_j z(-Q%2YuFUr3~O_pB0FFuh&C4-A|Y`T5k7?U);4|JsFUO0%w1bk<3_jrE2`vW=0S?O z)vcD^%rG!ah5-tga8i}3Q?e0Q!L}&LhLB(X?cI{?-nzLzk&`-4lZsn%d()SFS$nOb zj|Dh;$yXG~)=rH?QbI(pMA#-EoTqk~_2#%S# ztP)D+$ucPhu8X5hxz5bXqFIW7NJ_Ko2SS-4{htV3|KG)~$xh#%gQn{mInqZ7Z8X-j ztCrW+yWFf7snM<&co8Q8s&IEmQj3NC#8FTed**vxUF;j7yk>3I%UH`3NH>f_^E}J- zj3%1cH@6^RZ44Z3ISVJZzHoH8WM?u4K1%GH2{;*gK82MBt_)f1d`mX-e3A58?HhdG zCUL(}c>Y=Pnq+2!Y~)8S91O1SN9JCwvGsa(bN!6X{n~!&9h=v}L%u;;hrKR&1IeqC zA>2gzX^t8*r^LB*j*qTRoU^ZA&hCzW?>6Ph(ao)Md-UVt_VVH<(_87rpMH>j^wEhp zY-vP#8BPmMcUqK_<$=t|cHld#XOaBX=6cAGM|w&r9UJFhdHpU9k-|0>h$bX@Tk*hA}(%_LLvEB9N|>q;2GWS~c3h%w6ntJz&Y!$T8Nm2szTTb~Rqf`r za{c+_0+#Oi`Hi_OGh|55*Cce4s3eJP@WkCiWd3}z%3pQa#FbdY-SOC+$6<1?*Qr599jD^MXVTU zb>-VS?dLRE4T7UiFbmm`)WE#nuUMvjGZ&mdO=wgw7Ojd;iSr!5l(jz}V=#-b1Fw#B zomGV4yHigJKOp7`CBc9P(ucb{1!Fnq`Q`-+WS1LCSy5y1cBF?D?EbLQCe{^^Xdw#8 zp{Mlf`kz?^t*ip7ak)Bqg=>4dp1T+QWBgQiy>`o>Ydu zbKyBBNc@Jxk$t$bPp-N4zQB%sOB3^i>qwUJz>T?dxzAhaf=xZ)+1ui9yZ?UhyW0Ij z8~M4Ltc!hn5r6xgo?O@5r~ z=e0Rz)%0vGT>9X9f;$@tFl6IMSB{4Il(iZnaj8)O!c@so60s_Twpvi$>i%m4?3WZ~ zF9#BI!T&NPa*($=2wQxFEB)x?RZmx=cn%?b+9OAp&_?*HYP#M5E>>n@!S__$KwC(P zP!3R|33bm`EyS(49N+S?OxMF}QL+$BCtM){)7x97u%gmcB_z3pQ>@Yh2?qF8^^dwT zM~|_g4UJT)xf672VHZ&kGQveMjqDoDFbuOZxT9yA^*S5Kab4%Lxu!unV9iJhF1Vul zV6z;aTrBd*6lZ(@an>3$#(EYG%|YvNPbpzyR*>Y8nbC)Ups%XLz19>_{RV`iNlS`7 z)6LvrL&ZYy2phU2fBu=QN?4Eongwl~o5L22V=0LR6;Xs$C>c>B{)SWdnpf3=LjjBz z1xiE_Vb+5`&U5}+K4t%&{cJD6D2Z2A2un~|d{Z+!}d!!VYDtSr=40fC@ z(rK~H;r18XJ_H>6nK+1>7qIpRQ$0lsoNZ&^SP#ZV8|*C6ZM_Y!R3%Dp`Yi&kVuJ8d z&h@PmFh`RYcUuj+r#gX-?ZDTM;c{2VS!AAd$dFqGY}FZx=te3WFncEoDzuUR`jjpn zv(1t)PjlsQ7Ey9^9ulMh^W(@_y*dvy)L>q9oArGOu2N#%9oHG$eVN0TPT1~K1 zrL^kJZ+IYPM+`b@Z=oEvz<+m@md z^@O_(d9(({bZy=MZH8Lm3zy3l{aR&9Bu}hnZo#rh29B_!jqumaGXzkGa^E$CUv97_ zfXtac8IdhG1tts>CDa%#_69=2Uqe6mib@;(4#^jASssZm+!hv=uo}4tToDtx7tLNe zDPhuxXt!z&?;bqHoHp(CMVj1~yVz`ROXp})obp=FcT)W`gibR)A7eV3h{8zrofdfXXGQ}HLaWGD zhGtFQ z#r<=!Q{YUd5C)C)SZtKS;0Kp;?Hf5qJIdbQj`rpS-&heDPUSJ5W({I4khl!{(FV{Q z+qWB*?I~Y!5y53f;F7aN{*slGhuv(4B(eKOjWMBxuWXnQ>GU6xznt%RnPf9+#0G^M z=aCt4#9BRPT_msI;umiN>6iLDtjzfT#fmn}SbHmeN|Ea0J~8bFP8uWj^W%_&yx^Z} zh5~)>rh_Sc1@k~?_StFFv7 zRmZC=|EXcvbBOyImAUTw#zief#zHfjFwGW=gZE7>v-`d~#|91!-sm9l^*ku9JF#(hk zj2{S&?JZ_R_h+6i)*5cQPG@bjX`N)m{aN*Zk6u|edTV#{9QNdqE|R8%YroNz7AP!| zH|UOKXx_Z)80n$2XSi*!U7=t5#yMJ*>0)U`)ypM{2nFU!yGPvMr!jah+sRd5Sg~5VYNoP|!^Vc`0r=jZC%_@i6C?UGn?KFZ6nHzG| z4D4QzR}!OSO(EMs!P0ETrQ^of%hH>^YjQUzMjFrp2ti^q7?u#@I7f^0udHl_Z|3{< z6`~!<&u*_$0tdn3DB^xZHE!~GT^XV~u^;UGPwZKnroDN(P3m=(B{7$vNXb0%{01*M z#8}SP$)djj;XHA^XGKC>lg^C_=YSiFpt z>GhUP7ulnU&YHQahN0j_~kiyO#k@h9%fN71-Y}t)o7ZL#G{rIrlP09v=@R&cqFWEmceodG+>*{{&KM`Oel zU{X3Joo&-+okpz^-p4jES+0i~@z`i5#a3yqbS@tth{|(=c>s}poHlz1MU2ROUsX>b z2gZ;vRbJ$)wYk9B4IhGq9t09_UojKhS0PjKhbevy);<;*WHA8pBTtN9eKs;_=-}NF zvO+K#xotx@!AO1-8;sZ=zi@=9u|N}&_Q?pq{v$1H_sQHe7`P}9&MEl22qJ@xG|-tY zfncU#if=jS-Ze*#v6sCHTAeX9t>!Z`uZ%*5Dxg7_M2ihl;C{|G<&w1U_J|n9p%jcX zgIC$n!>nA@xOW)I!VCUhILAe@e1_w`zOLJ z*XjK-CqZmqJAD+!+$W7NbB*;`7BfBZ;pMg+^{$GyjjS0;Rl~{l1r5=5jp6DHhZzB89ay#Ef@?wOR;d%fnK(%2z1k7`PD7nc2$KY+AzC9dcn;c`-{C z|A3caqdQh{#xN3;!0O3CqSNRI!SPrNXL!v$GVF0l55MP%?C-eY2jWrjY|p zZmn)}Vb%o&?9K3Vnyz%_a@n;DTYd7zs4=#(@MM2WV0+bB5Urg2lN)hi<{-MZW{jF_c1n%KB~C zHFETBwMdwMPFE;5i?Su>`2&g2!HNw4KurC#(04v1t5rUGYPhx>@s4$fv2)q<7m=&8 zRg?J;_`ydfikQo}Y;{ZB>o+`P>jg}---2DkMi?)&2nulh-L!nRFmA~F1_YHYL!UWZ zR3w&O#gEjrWzz&jiVpc`mBO#`Ls!sf{bmM7=p6<;I>HQS>J|AF)`ouqg z>FgXg#%eaKAcm^i?##O__GcbuL8K|(gjo=pPZNUsM4k0yx~H z&RMqS9PIZ~Vg`#b7R>cyTClFq!S$>@*&q--5UDmsj$V`&(Zly+XHTc!*w29{Iq9Eg z5U&#bCKfr!^1bL?l;_E;!MajK63b`U&%_N5ebhpZP&?j?^OvY%Fj>yFEcq5>7~O-% z*w0GTE=d}A_gJu3N~$jpD6stVJ|NXP#Mg3Va`Um!XC4dK&phy9%-$#@ zQzB(+go$khw6zQUv+Oou2VMdb2Iis1ea)TZGD)`Y_c#1ge@|!gWR=ZqiZt|zcPv92 ze7C{ii@o1B>tqSnVMFN4#M;3{A_%k_;t%dr$~YCtSs!2F{?&)GPH~90M~l;ZQnlRb z>CW0$$BzG}F=B-AY~<0-vxln8+m)*mo-ce-&(V#Jrs3dfajw#&SPU~XY#vj>u1;bnGB-I@7!sKi0<8F*g`i{GP!zjbQLB{qrDjEEcgF$=F4lqG3*)^=hZhRlKz@C}&NH@{ZACENYQx z*5O7~$28ACCC#8C#2cBY^Kn0RN(fggnZNsyn*FzovhbddF;-Z$R~_6J(rkmr9x6s)V~m9mYaA_}=Lx(P790gWZ3|>3 z4g7UpzCui37_Qw&6{^UMC3E9|WR~aY8!9NlT(|3ITJ?GKt0%R`jmxH2DNqdw1H5EVp= zj6Ir3AsEhAveju@R+FTwsn1R68au{#7CzoJ1WVKWbsMV@H#s)>-!MjF$~0cAob#-l z<^!rV=jm%!QWvEoI#ZEQl3b`r`8p}8sr5D|w?7|aBO4UO<^OcTCm7~=&Ao~42&vSn z08cdM`sm{G<@wcFw~>y|z8)Waxg1_w2$>V8uE&Ui**5RF%>UYh2V2(a`gDw~Y#g`@ zt3Air`fb}#yT3`fCrH>I2cF^t1s14C!D+sMBh2~S<8$21i}WR}{}Nk^b!l4!EOJBM zVpXU>5}1@JW-v{w&ZeHxV{B-V?!5l``J~JH^@S-th~6(J4WL438?WG3*nE)BnkVA>^?;)q}1w6YY!Y_JPUufqE1SRw`K~IBQ78`m!I?my$&J; zC-|r8GCj}p=Zc-D$MwxOjgzfODxg>Zk!$4gpq(yx-pi_Gh+$=PPQ zKk5`V(uIx17c{6XeTm)LH_t`#xJidPbs!9fU(_yqcNQR}A0xe%D=N|l6J|HxOebIr z6udqN`>)5B)px(ch88*Gv&}L=RspSyzU625ltUz6LRh*=-Zm>kn$Y)r9+(v%2{$dt z3J50S3I|p8-LzNpY?0ij5QC6HP`?(nBjBi2g4TiRxlQKy1OA5jcN3^IJ{@C4i(uj` zd4=UsnhK(eef~3$a2}fAMHP8*mEql)4IB&SI!Q6PIpE%%CU2etCO)Vq;6?3pWU)>j&IihzJKV)e5@FY1#uu7|cea z5Rp^P%`$0Pi?C~<_6_lm1En}RGsvjYn|sF#2Kz~`z$-2-SDzyxP!<6RZXdw_)3O#D zNe)$So5RM~%?6{5To0J%*paLB5!E1fGA9Vyz>_|Kq6z2MWcF060ryzbma58Dn4A?Rac#PToe7@cj0=sR9wi5apVzD$K`9 zuX*GNg>876S0GK23~$8_WECpHtWvJCbTv(j$H`({ z*icS2hmEnFMM!e|`|&x%B-cl$x6Z|{WZRl8wMuw_G&gM=gUL3?&>dZwB3<1ltGWtVBt!7MeJ#=$H^yuh!N}!ijSgqF+EENTTk);E zt{0QWCa!e7D6#-4Q@npp*((Yd6U0O*}=Q`|4H;0X}oRxY@gO}?kBkeMRjO!g# zTpy$oADs>|uIK-bjH_ed=;O{t!DTbu6w_oir7%e4iHPVrphPACFULG|K4E?8b%3n< zI=$E6dCc^fM_pF}A(Xxw>tu{1T>DxZvNWf8ATQc6bd2#VVvjAXq*q-IxjqO*ist$t zTp!o)GZBQ*AG+C5et6&~dkuoZZ3*qUe#O=$){`AriP)Fz4Lvl*tQL_6($|%H zglSD#tKAwy!xU~6$q4hbfNMsOY=bZH6m)`~r zr!Za2nJw{8P_5hgGD%m5(qNcA+zo!m$*F9#C2wA{a1#p%}z)cn%UxFK`}$E9zgIke<6sjLV8sqNaD z+s3W%dw&I{eduO7R7rp!fj7s=ZYGnk!kuE9O@xSjm043q@CWLOE zJY$0tbd1ZneCPXAgoP+@i_n)GxzVx4K@ZGN`)uR-jv=_JLUBR{X?|Y86Ie{hNA@u; zzri7MOy#GJZIxKh#Dt0@YtluOa2LY?E>OhYo76uF2AiceRZ92gc|=EH5s9QvhHEBy zv7i1tW{$DEc=QTP0Awcx>2`O@MUqIG4-}dLUw9Y^b^{BGW2>8001Fs`-`FWM=4Rme z??3Gib;+_lTfwD~*KGO7ULHz}kzQ6M9P!T_E59qUT`?WcAZ{t@C@wl5$aG&jpAP#=p}FM6sQ zefpX||Cve|2&KECPG5`fSM5*BA~MZoK!(k>osaCFJ$Id!8n~uQ!q*JWGIue)sRqxP z=#a}KM&%fkfH7dh@#MtyVPLBdi_8iHe@GHqf2;DV(oVRxvz+Ln9vU~ph(4-+wvmk) ziC#m?H$~A05n@WRWY{`KX~g4L!SVTPo#FpvY)$%g&jlhxX(s{*S%RxlUhU2E`Ekw` zOnzZYPdqZmv>xswcF;6M(^r*%i#pM+hmMuLkWd{)7<(U@%`F^5(@?IgQ+*z(^d(Uk za4Eo^aW8MXwi7+Ze?3DE|9y_tJX}SanPt~mlkf7 z5I(1bd#fm+l(C)Ej_s^_>Cz4TQc)bqu;FwX22#eo#P@(9{=X*k@DE>PcZ~@~Y?8H0 z&&<=LlY30v1|}hOcz$|pGh^NneDeRmQrr@jlL?0A1ot!?h^gW|`h~H3bMbaoHf) z3tw{Tj@V=mlg5Nco|X_#eH0f_v~rk5jDv3-37W+TC20%eQOa&E6FFfj5(Dokr5?=U zz_Ac$dv>0v{mk?n&dtYcQ%z*R4PAY<%9rpTwed>#4Kq#Y1Gz4moIPJw_x&41FVZA& zGdU=_O^(DU)R^Bv0=tigB|18!!wws@SQfa4BT`f57s}DF1elB?mPC?FPrqF{GFN;&x1aRtxS1&k|cs2(kpCYfH}d zA!`~$42~zbe+-xy1w4|0j77I{V7*4NCPPE#SkjB0BENMCh2VcRnCrG@{(;1Q zp>_fAO298dO2Pn^y~!SS82^3PW~+RviPrgqk^D{)#X+nR@U2L73v7lO6t|`jxN6@r z#b7Z!bdEheyzUdL+o}8Ax+YF(7y&}{ zK4CoNXaYi>21zosLJPOgebuw616=HknPW^3=leySmACnqcB6Ny*zqD#shf3Fi#Vb9 zr!brj3E$^=nYs1AA)-{x!vI!x&|$(~*}0irYG!t+jMaPK3AXd_!rxVh)wNA8W|XL-kb44f+_1lh(9_s!Kq`=Yi0 zHG=(|X*3VN8duH=*%w|MEB3B-3dDG6=vYjrU_!F|Vj&Ds4@!*veH`%qxhTuxE?<+a z3qeb@B#=8EBIHhrKq}o+WPNC->Oox58#;U4d3e;;a-T{pq&L_BiK?n6O%8{@G3~59 zo)Y9p9EZ-M>~r?`KiJ6u>|}@>$xeprv{+lv?7;&tdw9YT=;21ctIGWv%eIe$iXL#@ z5#AnzeOmO$>DG+w$7JV^aje$Q7zz;!ncQ4|bTK!(U30ZNJwMTLdotd{ z=s9Nez#Kof1x@4c#q87BfT9&6b6WV6bc2s5)k?CP+eg#ujw-+l*wQ&0S$nVHtRng9 zQOcAQ<$%HW>v_u=!c5Vdizn7!XVB~&?1dZ2z;iWD-*0t+(q1kJoIaj;XB3G{BvG;8 zoZT3(67`qcbiZS~w|S2I67D%TP(qO@1jIVRim1B`TlmOvu9vwk2ZqkEphvjjhWobp zaaWiY+H-P&0C6z4Krtl>ZD{DE*(>m$^KR4Q%^gO?FWuPf$9f-=6g;PRA$2s+$#QDhx`HT3PH$vECD238L)^IU z^ZV>eW*lsLm#7g!<+iu}l0%41^&*miibY5)STt4)<7+;dg5i9+AM-ESmf_m7 ztPbZjmoBuH?ui#KVuJ4yu?*QqIJZ!Trc)##*YNiqw(Ct^?hmV5w@Cmw-*}4A2vsdO zst?}bL}B?^riM#x0s~{`7|je>hmVwe;qq@&1n&a?0PI}-Z`($b{#O=xfuaFQWX?-$N6X++pydk#RWL5B}!sMkvfu!>mKfZzgbcecV$wPl-~7zxB^KUd9_?VnVor_ znc4lf|9mylWi-w5=U4xHm9NrbmMvfX^eWYh2tF9<6uph%$LMaArg1t&AJd|Y%T*b{ zphTB2hEZQCBFx{@Dg50dMEW=+@IjnTG6ElQ8DQ@meU6JF&QkO~%cl{#P4p;Q527$= z{lCn9?D{hfpIzuAo@99%Yxre-No}LiO@w{KBMz^9wD8Mw;*0*i=|GV8wf+6;*d5FhTIPnmllKpqY7O` zPjP{UD|i<~F>VL%R_F6?agsz9cn0}wmB$uziUgie(o;l{UFb$;?IT$FeB_U^MK^*w z1HZgE0ZRFoLn#9nN-mfUWheuIuF*v_)_FUGpLAO2qIzOKh@1!yWBm7msCq#hTztMn zpI1p47t1U!iw3d4XOsmEVk+<@CieafF$SR1Nt8$FC_-=Z_*=)$eV=9HBr3~d*8=aO zG>wWPiY)Yg42XD*ln@>P2Vvp&6rJhOB3d-7-H%}V;A1fi`!P&Yz04BWgB$Z3)<0h( zsr*o?21ptBJhWgWlA_N#PSLPzM{hg7ZFM?-PQco<#MDy~dt9nucjxBOIEVGF!5P)7-H+(LuN)02>4o%N z5=A9?XMP*L*v$l2!Em#iu}=eOV>$G}0CQbJG&TP)dTc@YLBlS+&z{l<{RTT&Pa_N1 zhZur?mU=^-L<<{SSiuZk=p0NcwL$)ovEVh56rko(S}@O}xSX9$%v((0*VB69!c4p$ z=)K=L8fn^(v<90y&m%oYgK`G0Ego553m*rJSzrsF;gH#TJ~S4aXY(jR=gBu4YYW+n znJ!D6X4zEt`AkmPYh*YN7R-)0f9eq+3afoIi`AR8_Mq7{{%9mwFOui^a|-V7DYyK< z7Dz0RehIS2`WRqN5xQx?<4wK^By^0A=xO31;(0QAY&& z9F1dr7;XXJh6DV!;wE}=1HBTDBXqNR=_!S;Ft#?YR6gh!8#Lh96ur;mVhm2km|lm) zf$Ou0Vy8b0L9Xy1@Gx=c;wT<}&ClX$rP-=Hgz>ZwJ{rG%8S^62m{2~8%noceFY^hd zHj>g8BIGublwkBZOY?g*GgDvyZ_vCvgdnEo?xs2<^C{0AVE@Kyf8vbTZ3U>24TzykVBj zCvlXFEl3~YVw8air52_%ps)qFC&P-0Z7?-|oGqJmulH>0zU~}$G?e{Z{0JzepbnHg zkWPqZ3Zq;72!Z~c&KE}a<)fs-KyLuIY>_=>qXXas|KZWQU$1|pz%pN-0IFlCe;K;8 zpR-@+vX}z_M4wCFQjHC)#Fv~}Ngv4pXX02W4>oFNC*J&HJC3cl_pMIKKlg8W#f2{g zHczq5^XpdN%tu^7Ed(K3c!l0`?4GmNugCR45PN>Q|SS_voGZZFqZgcRxhK z!QEhZb3fRkNhOe-z*3Hi`hszr{Sd`48ls!w?cL??Xz<(RPiT05i3sNHc4|Fi1M0gZ z%VS3bg`9XQUIl9qvTSK;HAVU&(A+T}9sI4RCaXxP%kvDMlN!Th=q(T?9>Rg{%G zY_!ZDl_1|na6&yEG7pE;&0);av)rt0v$7uDZHBJB;qF(CMy;QP@3B1L6JqaRL&=>a z8W*sGZ?k2hEA8T2zzuh@H^2|s%A^POSfC^fv>)ggCYS}@ zWRk``0D1R})fA3`Wd~=zY8;N zau1j}m~E3X^&|eb(d#GPdp0gm3c`tt9&-|A3dlCP%2rWXYIN6Sal>T}PG}E!R1uGv zlq2ETF}S3j`s`WHvh2Vu`kjdN*9-RAn+OGS5DTcor~@K#U9fr3$-D!v)f7D8Rh`=2 zhZ*d5Q(&?4hs!KUo*OXErmd-l{}JT+mC1*AIz#Uxc)1KOAAB->#p@GO{l40J-R@6>#j6(5@9o=@aEx9|d1`Y0|d0*e@WBALfR;n9%VLawg7)C<+H&KJ_GivjNW%F$3B zpgj!HG;V7iHC4btI!5<-Y?A08Dqff@^*OVv`&C`g5hauebm?C)N%ba)d68o(U436W8uNaw@-hecUdQDOUgdF>Pn$>{ z`h*Ir^d-%PrFI3D3V}X>LNEo@0-a~8B>JZFj?CH4L-rJ88SwCs2429qgZM0ui-vL=I;K3?I)z9mh&}vN$#}zFpeJ3FVSQItKKKD zn`iF#76HS?kUbJQl?K~e99E$HOKkN7Wm8wJKj^%ww>nVT`}%%g`J9QQASIvB0F18cPOWFhaZjWX>|ylW^=0# z4R$*V>>?OQaEa|CT0ki>#qFvjWK!m6_|T4NGx-M1-{O24yNo~pF_jW*lLU6|=P}Wy z3&W}_RC66%g|J5-jpPB{RPc|rsL46(c61&kXb?BW9PpxoaVv!e(TZ`Wlt=?K^f$TP z4x?Pf>)2zl zhkwPj8MSdRUC`|Q%3kb zWe3K0j8B1a2<#+{BoJnA!cp(Xbv(!tKWIrk7k{x0zh9&_=iEMz0%oO=QXK*h4~s zouAbOv!5zAK(Ph-F^%Vxd!dxX;p=6#IFPOHj{5ROThBfk=@aT0=q5L>)pSo%(==dL zfPg14<@B;J(Bg(CC8b_~S2RZ;eDn_>^&Mw$nt?T;w{d;hhQYA}9Z3ONr>eH&RK*EsgJUJi8iFxuWDV5R|sbGqBZ^0jI} zXwWOR6Sj7)b&oq1JkhU(?sGi{La65rXv_zKVkh7OAAGChOBE-GsB*T(4GlYDQe35s zX4>x1Z}Fd4ROcT=z#X)~%_3d|J*s+!6bjoa;x=Om_7?T=^L6B zF`G|qvyJfbWRt;cLx`JSd;KMa(=V}NxEV{2EV^^6C`pq=4I zW7{u!KxKfRs1MTZG)yvzr30v9+-U#`xH-KUr$wDaGyJl{7*}~x=PzyD2(&VHq+_`HHNP&;f-l%XLp$|18xTtB102U zZZlx!UAdr#nX$|o=pA{uQ}GE2_X0&dT=%{;$LO}}%=6Y$Vb+`E@FF#GrvlfnXa;DQ znmN&}wz_tQGy4o3Kt=540&|);blWkc!stQgX>|ys9lLky22b>x1|DY@%Ugqp1OOET z5eUFGfN%A;$iIu8(<~VmXM=k2X6@bd{N8I0@Fj0L^}_azBe26uLTKfM6>g*gG3@-|c`AG@x}x z7}W<~*Jo~iTHhT|H=wmOaBLp_QnqY<Ao%)cfiqL_Dht# zC%-7M4{9syE8!lO115ro=wi0YN3%*VZwrYpk8b7(kY+nw(a9AhuA1#V#hkO7iwNXz zq5qB}U_rlJ8S1308eaA_Wl2n(ElvPYn}jpMDFAAEdc ziN_W9LgGl6%KQqL!}O>e*pAgT{Ae^!(KN&7T#r^oQ^_`Gmh66B8TdG`+gKPE6kXANNVGW?7<5vD@U%0CloW zbJo{|#K}r~pE4&7eb7%jb}kF4ieu6Xnd2_M>LN?e9^+|Tz0NUBE&IQ8H0lR*V&z#{ zHer6JFIf3f*xjwf2Sc^JDuXSH9{hT9oBU#vkc6N_!gd?pj<&#UPognOO}gpDRV)*; z>@`M*xYo|`M?>1LiS7q??=SD~1|P3KUcWb8gw^#n)s;84pd`#b6aj(~B)M}zhNNpX zxnGeR#kcPL+}|feG4m)`Ye1Ynp$bpX@6)KvL0|PAT5KD7G>QkbT|t~p(5HAbZ@Ca7 z#M13&!GTljp(+sQ>N!nkKnK(A^AVdCAaow-kzKKE=?#)X`n=i!PJhPNDKO0_HO-eg znZt5>n=PGTMZE~_5zoV|VQC>hp8@ioz__l0tU{Kl} ze>9W_95R7dA7_h}6DGv&^;5!^fzy{p2*v1rmMwI#j~Lx*c#vLSgtcRWFCC&103+ye zN}LmR)dpTXPwKTE;tg8{pBB{*5J2Gm0KKwqQh#xNf6prpv0U_OHFp5BU~L1 zX%J9f5GUXt2I&UL)?r8E*{_~16O#rqB(pxU*o1k;toD9$4JCE2v%-O7+lxHA8wRf; zZO(#Pu+?`ezOsuJ%nP^)^A5rM8i5ap%=$+4^7h+b%gCegI^_h)`UZhlwq}=h-9m-F zpzZ}$oMUtYj&`V5^X_w`&CDC<+O8J~Kup5!^+NdXh1_X6{Hm!A?g!kCKFxRbi=CUv z1YK|RqfOBXaSlkCk|W-^?uMXWGQH;l>M;k?VT(wyD21*F5@74rk>95)%3<{)HU zZ~RjuA@TOUroDX{jU(KacipyNPC`#93appfTwpOatA=+WoRC9KK5xc;Omt%1=m%t-+ZXYg>(v6~oW?UJb>Bvbe$si% zwP1Cvf^Y9Rt{VzAPw8Rpj8TsX=bAO0RL35-ji>cghqkFYqmM?kU;2O$)+M|^i|AoI zv=2NJh&0N%8(I={o;@e#So_}HdY1$&ea7n#+5Ao`u#RCC`XVrld=cX*MgwQX#FYnEq{)SySf*& zt^j=TsRYMxATw@%&J?f`SvI(IeMyX=$L1B^0oZ9DrVZ@-WR+(HS);->$no5aA`&eE zo3fvw&Njz)ubqP;cz~|&>sE3XU+^6;oc3$l7=pQsKe~+}99;I{>3dQ$N-Qh-m!<~> z%)r{*f6N?Am4wx)rS0Zysuz3*Os9RE0GUTn+oF#!T6oeY#GcqtLl&j-L+4X+8?UNJ za9y$S!$9@H{B8+11dj*q^A=yP*kr-UmozU*WH3qQ@M?*!`!Da}o11J?$Gv+AwUw5Xj@+*p9`~RK=bz~Bo0=9R))`K^TA$Ve zsMF`E!brg79}z|Y^nLei7rh4eb1PTWw1S4dov)s0g;^G z4CqF_dLhzSmk|gz@I%62v8qn?lk5TZ654|k>Ob|@!I96q6Q)5A53ilm$UW=F z@N~7Uk$Cad!e@dDtZ(eWNKPBfKgY}aPw`@r z?qW8-Y%q#{^_A>m9@)hb98<0~rh+-2oj{mW|G;IiKln%P0v0ewGU+f)`q`1C3K^b3KFbF{S~8zMm%Gm`Oc}!oa;2n z^B4nQVDJr;jK8|uu43ocv?!-boC6J)E7*AzlN(u%58G9dB+Z=r(@%Xv4#w}8uJ$W1 zB1^m4NqXROw7Rpo4WWiz{o1)S*U(U4diT;@7G>w8*sIV-^(*axiDU2KRwlZrUN*P< zk&HeV!fAu}Dp_Wm8|NysLGwMP?VcmW!QGXFWKO{~auvf*T--km0@uW2E#z7eeJOmG zN80rxvd{`Ms{$r9C!D_@U1nvxdS+>fo;HDh&h9pbvCmMFc7(es)`UGTCs@FQ)+~_7 zd30J-)yuV=#ac;Z3r)C}s7i##Gf==l?a$sYo;}PaLeR~XyJ{ZAin;DC9 zXz6E9sUnL!rR;tg<$HceJlue586wH)yU)KlK|hS(j%71yoWdwDIy9{`2}#8btj01= z|B4DvJ#9Bv`MF*j2I)k(&1Q;;IZicb;7pg!2hTZA|45VJ=AuiuOrF|Yg?+g=u%07M zY823{jQ8Z31AzTSNjN=iEh8`EO_F!W2+xzvH~8c0WO=uz(b=<>>Cm>Lu_=alu?p-p z)5M?05AX$(k?IALO2+zymI&HF9}M>~5ATCXO<~QKB}{c`W_q%oxIPxum(Dwt+`s== z|JCn5-XssD7Z(rzTOg9YsRzP8t3*BgBYq7mR++Q!Pq*bAY(A^ThM}?DVolJTw5$g* z(%QM&uEF+3dZeMG=o?sc&ikjT3we06GY)4a##kj`yT>eNUM2+=BM%4e zm{yN>>GD3ytwJT#G$BCVZ0ZJ!e^)QVa*@?hfX>kV7y>j>5vPD^L3!O( zh-MJ!)cgm!k)`wVkU5EG_VoEF!5~s1wCRy<%%kI|_JMg6YSWGjK@H^q(p}(vUv(G> zvLdn6(~ji`B$e`<_sdstfhXeG#jod$p7Ve`X@Abt9mFD6M#K_Y?H+&D>O2b4X-DRA z6+f-9?T(Z?NM^SZqAkutN<|L0%4g4co15-0ECC&^3j27UtTX#w=^@Jx1IdNv)#0%# z+}zFWWdE-dwXp4RhhsMF$6yF`q!SbD$A|>3!7mIIx?`cwrS^O_!8kH)PR?WBC!Uo1;V_Bvl&Cz&35Gj zEz}nPj&q$S6Z=&%uordY3a;!5n-%;mUh&V^tw#YkuQ&ZudV5!*2V=z@w8tV_dNg3% z3j{5%!LC0CLx%CtHvKi;EVC`WDbBz=ON%?aZMN$Ljdg+TBDr*tDzd%wkT4zR3DXCY zJMIUrJLquCrX3lKHheHWeVrzLAG0HNv!wQX?%RP@9dK2V=UpVXNm&k848Ps3zO<5W zra~M3_wZnMpfWJ~5IRAl`ckeC- zA<n z?M+&uP}m-{(1Y(_E4p#d_a!OB3^aGdME71rM|76NmHGu)Y$#2Zm1Kv8LDd4JiCkm6 z#sS%O|6|rgYL7e| zy=kMjIox2M+RIL;fR>pHLir##Q@-P1Ix|I`j-k8YL-s8lUu;Z(?=Pe)w4fzb-_j=i z3wv*@$YB51hvPGC;11x!v`-rtlpw92regt9oLGfF2+!$e1B}97qzhbg&)%gn(r)Mn_O03M z(!X)B%}~_tg-c+t!zQ8%y-1K?2j>-K%4wRTi9cLCb)Co93)>-0>K6w@5*j$+h+I`! zzX92q|4!`Y>({lhv*~>hxn1&fcukHJPIfe#zMzw?Hep_tuN zA|tm)^2gr4Y8b=!)>}Yi0Ks}wGy*KZ0x_qWnqvE?4YoGn$Dkc2v2vay(AIHTo-_r< zG0uFVkg8|s;b_i~wYY}?Q8fZy>=OPpM6<~EF$`39%Q{aR#C}Rb}0Qhr=|3&9z##RTygLv%}#+i?X9o5-zRKhkcwl=LzN_ zzF}eQ$89pWwvf;&iEW4KU)yAnEG@tSS1GjL6zqE=ev>vhh}N zUM%mD^yXw;KbIe_`nZZ0W(^+=;_l$APPMvkEltJ#8{tZ zuS7#NNVHMX74}%YOX8cF{LsR6n2kqpmuWz^D#Id`w%?W~w^>C}GkZ#iVK{wMz98F9NA`q~v2x)ojbc7U=70JZZGT6vgfwM{=+c_Qc8 zH*D7ToWfYq19|`V%TxF;d*8RE-C;R8kz!6%>0C4zelwG-ahntKBo7>o-v5KxI#z<7 z^hM5xtDv4AWS=3KeO1-D4<&VY9BU!b z)Q$;5EjW*4*f9|cGv|Dq!rDaKI|C1gaN6U*Qg4T0Ez_!p-;(JdqVVy6RGpwvjb$ep zeC?_UrXRIm(*j_c>@)z_Ox0}|lISSR`UDHQSpn0WbD{JPJ{-SkPh=cFMY``1ze;&) z7h3j1hRg3VUagCtI{}tS(U6Yz&xk{7u@csJQc2dB)2_>n(!-W@CdH+E=4HFQ6 zj{(Ph^v>lhfLlqpEFiUaH}U4AB0;W_U$dywhsGa{;jDZH9$e0E*%nUs^b27qP^9%1 zte7C;q*zBgXIs8} z!*QJUT>kmAN($#Jy+@f#r0m;n%E~F+K0K_fAVuIw-)@o7*z`eae*z_Z=jyXl+l48L zP;|T(3)RyN_{w(F`lsxX3Xp>P7lrN3zkowF+59PnN-+qQ_xSY|`0b7_VVNNmzTfJ$ zvc|4l-sd5`ag-lXw=amCPYIZtH;vlKPyLu3EZh+a;fjdasiu0LFIOdd_C8-)^En*Y zc}Wzk*tlG6E$c@k!>65rg2R+?do3z0{fg&&HeOU1qwW-^Y1BXw7>^t!%|>8YU|Bly8f|Vvol+&Fts3#~zN~jB+ZxBJQZ> zm>=4m7&=1INm4}>;8KIntt1ODy!A**xtkQHO`doOR3ih%elJcrb z;J2oi9HA&lSC8@bo>X`D(esJ`t89Jb{j<+Hm|!*kxk}%=2aZN`+Ce!I(a2U^Rmu}S zQMi;r=)6rfNs%POaALE0yE3K^P6qoq5|PV&(k}fS;GFhVj)9ZG-C}pI0-U}eX{#s< zeT?B;WLRV1T*RA^vZFV7yt${<%|nY+g$nFXQg!+rP@Q&Cj$5RRG22?iE1W1%2O(IC zn8ZrHZpX?7tG}PINSO%0g!0+!!K*5^1+?lN0^48`$?Y(&6(FCw+5feOI1UTpJ4 zJc8L3W=^+h;e1?R)@bV54lowtMLrk{p|+E#CLUW`F^|o3Cu`r@BM$~~hK@H%qJqN= zZeHG>Rlzh>WEWv->B*3ia=o)D**>3CUZj|v z+gCvlIImFkXN}bsLqL9tS4nznQ*?}}q`L|`95m^&yp8jx?;(2`%#is8yS(;iu9NkH zbwYAaFuRNi)h-F?BwRc7rhbn{!~nB-uycWoLs)-CgJhSxE%Nbx!JbP}(p12YP@K%n z;XgZrKSSkvhua=8*tpUsi20r-Ec!y|y0tuB-VMhXuD8okj6$%vl>)Oy5-rQw7(E}K zX%7bQF`PM#?XrhSd9q?)-pj19fY55gQG_U6$E!tFjw>^i4p!R42~q7HkXw^@%qdPU z4V0w>JWyOEsWc`h*H(Az;Q&rMELRU$&4Gbd!{^jyqQu|=qnyQB6DCT=Lg&@#6S@6(E~T|z>y~3v>(z-Wfx#G9Ay@Qvxzj3 zXjr1oc~a(CT8>o;XUqGis-D<_vdxMm;Lgw(XeEi|1^fUftm3E}2hAFE98fbvxG%Pt zR=R-iW3yhN=#)*mi-E#`RBeH`A+doxUOu&M)gJBx6ao7io)YJ)Yl79?16L9j7 z)O#B^hEWz4xV|Pu)i>rjbR@D(iH}Tr4|Lq&Xw67_{B*qmo55o9Q(mBy?Qx+RO^a1B z;M%#2izFLOs~aH+%;`Olw%%^u;|09%r6Z84K#NX$16Hiz6o=8WM;y7XW)x&SFUn$J;j3zi0};f>b&ZvsS>>(CI2>V|6&BT3YYG===9&e489i zd^SVtdXhUy2eu6tA)7%+bKy?)j&VsN_}s^IX%k@gawlOy8|%t9{=M8uGjy$uMpMxw zcRy~+RbmC@Br3vK)hx)?%mNw?iI{ZGGB7SzE9W&BV@PLH%O(t9SPixi?4@shAy^1^ zh0k30;q0J$qvL3_q2}?l^bI{6&3Rqtn8JBYRLYQe-7d3|9FAua+GK)Fs};S8b1W7E z<6=VD8cb@5w*b;#6KS3L3`<~kRn%m32U{f>_{4Jp#52UM$1V!)1&omI!9~HDU5pw= zUo>b4ux>JPt?{onPdLdS*1mp+zf%p zdan-v&VUGpb3Kov562n0*3Gf_rs6K!or#JGyJb^*oRb`y^c6DmqH@Q$kXD@E-^FVS z%5IUW2qI4ezQ-l0Q(IS$?s}@>L*_MA?*|@^*!+sB^MvRC!)ZqW(>@UZP*GJ+)o5jX z9_-qD7q3mn*C=M%51o*4N2;z2MZKbKl9A9I9dq2?ogq0rB2*9e1)*++1)xY3v_ujF zx9V~v~TTqP91%$15Nb|V^4+&)_NXx788}PfEBOGhA?GTG~u5a>PBGstcDgbQCiEGg6thyxT7CPm*ea zjqR2h4*Vg(_`b1+qc-hqTxMmqj+YIaK^HsPISAHRK-eMztPF78ri(>UueO?Lc|f@c zW1Ss$t()$Fqtu1t7FM^mPrdjC?8cLaYR>pGHB9uw%Wq)tk;`yK6G)b=lFgnS(g=9% z0aZxcWVZxsto9*`kul#f-2TpcQ=I=Q&x!(HHJER_x=UA?o#5_?vb=}__0ox$a-r$9QEXJ13FRKmJHir@fK0B)?B+S8&HG_NAb>3QllkDrC4cu`(?!pGL)#yBcqO zrBsoxT&_bDrS04=i+aXQd}>Y~$mlcwE$-TO+s1+DuMp_d0+m5ssLNZj*(3#$rbe5l zPy3+SOstJ88J4nX3hck{3>C{Wl67+n1SrxMnwAep%^Y&(oawL*GnLD{z2i}^h@PcJ z#zdJCWjlljePe{J`!9E|6AUl{w>(R79^Cbv8uqvmPm82=PLQyf+fdr()rp)f0|6V{4wZ&zu%b&gLZ}&|UwiKnvXt435ixU49 z5ISB$o zKBY^e7k>KmU@G@?XBpKb*$KxFE$K@dXO=Pi=3kJV==J8ONflcPLj00t)8scr9 z^#2e6CO-}{6osr4y%Wgc;Ch^p{eI|?Yj1>s-XYm%rD&3)uqBffJwt#I-*lXotCz|L z;QTObueKENCRq;nP8iu|;VGbiT%~N1?(=WZd>-K-eU&U8jREl9`m#pPfdJz$F?%_K z#HQiI8kslZfQ#9k-j4Bo3j)UqBF~c2ruiYf%F>tYuXmo<8wW2b{S%wRso z*(xqeEKTlix3)tXt0RBr+f08P2%Hk9W_NWR;?&@!nX0;tXhyT87^ebCOuo*sU|BH_fnGV-58M*swPQYrfId29`k@f(~Sr{qq86(AY z4(oNECt0aYJq$tZwM3!Tk*m#_@K$4rIPc zQb?%N&5FT1*I8B=T;QMP-3!*OlDn5k;w=K(`areC+IXLfZ3lrVARRLD1)66(m_Kf* z0Zpisb^Z0ua;(o^Z-o9)3VQNgl&_NzidY&4v#}I$Kl-@XGs6G77fau#)Fr}xHk)to zP~3jFFurexp*&mZqHMP(jlpszSOo-`=AUjYO!0PT4l|qn)hU@iHK55;BS@B9TYN+z2D5g08t4i!*W1av zeI~fSW3jTM0)3JLLJ$5}O zWLE4(u-VvdJmW;&8N5k9JI75&bc~c2q&JCCZ@%3oC>Twpynz1Ltak?`!?_hfarYnEIT;8xDT_vJm;bxIhvk z=Br$1$q#Nu3X9UNTv+ytQek--EeG(#pOvOh--2vRKd>Ub(2E@S$8yX#O&{@@^ZR>v z;vU~GKJaK5hbhrKUL^O)LVS5n)^#V@9z1&{J$5 z47fq@& z1n&a?0IXbVZ{xU<{VPOYVE4;}t@qiBRAnI%Xc002`<|%d0ph_ z;+dlRnpG5Cp1IvP3&wT7+VJZlVG&vJ?i&Zb`H-e8=d6UU)(OvPJDz5QrSL0lCy8P9 zSWN$XCH{aTp246EU6$}P7?xDk`tRRfe|z1HKZEgSVm!`Sz7oT~y@m^7TEW#NT=4C6 zhe!GCHOpi6%;K7)c%7{O(f#317XNBGum10saTGtN+icDLRZ|JaYg!`lqE9q04|uxR zb%O((z73zvP=d3)RfO&<60{l#)gL>YM&wj^f|9c!T2yjE6R(Q z(d>Ln63*55Y&ILrn>$y#={E+}UN9RhUkes1c)qGx494^&q3DKI36GDkLvP}Yw{TqU zadg459LG7}Xqq;5LV4wW`u6%_7`)vLCHOAVB`qp43}3`al)x&B5}uYkKR?VG=d@Bo z*&p}qbwptC9-ciL&p?akm%9&(&ky&<2=Yht!17XHcu&B4>|wM$Y#6pBIY0wDmKFBQ z(MRui`uNP~23-~GnGS<`5kHeWq7tT`cu^&2L11aJTmh|k1HLJ7#<_0s3Pc}CM3FLI^;x1`02@srK91_(<67`9KHi?L;BF}~yxL3c#hWd|&+=pmd~ z9(H^?>{+J~gsz0;?Pqk!e<05etYO@)Xj+ghx}>m#CFtI!ykM~cH!Iy z4xArN8LcPA|W?6|hPWGxGuz8sTX z!$jAlE@%qOML}97#!}Uqv`y?AwnSjU z0GpOAM~rSwx?V7h)b9QgPG9H`qF~40IanD4XI*$my1Okp&#j<70$7g^TDN`mW#6x$Rc*Dze`f|d~F^6EU}@ap^NVcy(CvG@kZ&c;kni5n9G zW>aVD1l{u*DAY&sui8pLmNJMzXi5amcW`K#vbVp*pK$}D>6qp)jDXkCf)obVK32io zV3vQv+{G;a%)d_&7UGibiZcJ+Ixs+r{=i9(p9Kg&L<`$-JrN@7_3B5>v! zCM*w`4V<3+3VMoeX;EyI>(_B$xq6;tdI8v?A>-wMc6eJr42+&iv=kH!-NnOz9Uds* zH7aT&l9QMbnQfgXywZyZ@hWTaBxyM>Q@(=VsuK~l^;{Q(7XS#3|7j!}6<9sG>*K&R z{Z~V4*;EAA%L3%lBco|7;W(auDq&`km{>RGDMIY{np1Jp^W1lJ+NjsKRA~f|1bqc- z`%YhPSqf40g`_D-fCE!G*p6z06-;L%X0rneUOXaYH7>2>t4<6Zww~R-WhuJI1WZSU zWq=*Ia-?-2^cpf}vrP1!r)5P8BG z;+n1$08GQdzAMX3(=(cdhEL;GBaXep;X zM%QOj@dA)Mj~>&$Yf^ysV%%)N^s3=~9hczje+O>^udDL@7Br`QQmy{IcGfQVEhzxA?JbA97aW^K7m<`hewZP&HEi3d-kVhFEtJ(Oz6eU9w zd!8$+^-qet?}Ekz{2N)bSY~A(_(ow&+2+TLnAna!)r|DY;OdJl`7YUQd4Pzt+8k`y zy@ZctIOrqXq(pb@S-5yk6i)t%Z2La`bE4v3ab*Jo*yyN#H|$hc^c?@gms=!6lWZY| z@AS)1ju-Y;l7T*_G5QUZc8T6^wyn^TAZgRFmhbkkDHxTpS#VI%QN^OV8iwe5ou9L6 z-EjU!E{sde7el|jhL`(OyqwTTr@*IY`puiuB1a!`!KUTPRS#7=z=mVWX69qt3kKv7 z_;$tmOTd$-y_ncNbQnH7!ao_jh)|R#C&C;(WnaJ}SVU5gC6BzwM0o?f$>X|ce!K50 zaVNxn=t+LbG=WdpmV}RMfpEMgPqa*ULDdfYH=6QIE?4(1#Z1aXc>g+EsDl}hEh$jc`vhWhsf>mO zc0J3ItxohbNN9zw;iIcMFIf(33tbhm(cQqL0U<=<7)Vozc%E)$5Zm+v-~dH4Ov3L2rea zPIz4^3ZH^LparYs#D$ttJhANil15Kc2u0P+`BYT&RQ~JbLTOncwmes^uv<2^92uW` zp*r#kea%HC?6PKQ494_}_zWxq-e?Q)pib#CDHL?$cW^ble(r^YX}+#rM!g<|X{jHQ zl^CwXq7vWXw}1W9qR51r0WUeE<7u$vv$mVIlg6?%Lpm&9c0_rXrQB=RKS&2R` z1*w*)ou+ViQ0pRW!aSwgrOE&mBWHs*v4-$lMsgW0N6yu@X!XJbaN;+qNNlj2qq{@< z)p4IkMaqc8w3q`|PB&#!=X`=mY0RuYYBoB0!O->R$@D|GtV$~8i5O}~#wGd!on9lG z!C4P?@LnwhCd99kjQqGWRS|Jj>1`shyrN28pYKUYcZ6~}W+g;*k)E)hqoZwm^Gi$%&Z0qA|ll;eeu9i!K+u&)w0R-njy@1G(;I9@e<++DHDh)gK? z$=CdJJE5zm%pfp}lvkBV9uYuLcz+d&E;fC+S2Ykx@&Pq#g4|GmxPP1k;*_R00GXUe zyNjzT8n?iKk+ZSW6J!x9Mb1MMHs$17bVOEMM^kQU@SNGrKCe`IC`2DK_>O+u084SL;Jh6|v> z%Wg=Tj)DeOMf0c^c&|Co7j*_jOu3oiIpKP-an_DK)yDKx_>esL)a1AhFgYOd?VgMc z04G^&0E(zBsR)dQ0lMLN!Jm6(rDG;A#RNh^H?O=+z18JdJQx@|8!J5lzDO(1d+E62 zG`Qy(a-KvaIej@#VjCuSud)K`!sye3g3h&%k(r57yFNZHDIiH5*PpTiNqg(R#P{nt z?;Vexw&;e}AbnUq5jPhP1x{7R4P3m~qY_#+o z_#&@Z%GbbrtDy!`*9at^)okOCA^KWU)VvsirG>zgS0t*+VVq`e=4fytyV;!`#F8>Z zDh8j#cU?W-eai}1QV-<036ihmL|kb0F$-jd>v=$t(|E%M0^==j``q^X7ut>(mRIPS z^Cwh!wGUj2! z?bY-=S0v*IKyMpBu*OzqS5pA3&3a|Nu~I{0c2P6S2qrnD^gc3rHi8q{VBmf84Fs!^ zfM8fwf7N=HA#420qK;@2L`P}H{!u;WrYUtb0IqgdYTcY-qNUVE$H32>;;&oBdmmNr8fuR}pdm`+>?9n{S7u&bu z?XF6QZc`G;F0t(axI&iaOOW=ikpO*1!B9r`c|^PUP9lMd(X(;XD~(AW@_~qi+Ad7#j&lOd6NSsL*hIPF83nHMGmdi8o5O5uCuZV>G@;dim5TV% zYpL+SP4>5H88-S%o)Rzw1>2b)XA&wJ@8Sql?2}H%iEMn)Oust0bJf$!k@viAcBkHv zNR*=$am5niP0kX8E_RIG-pWIRv~4)5y_DV4B)mrU9~~+^Nqbq*%yE424h@|Rn_i0u zobnX}Pq8IQ0Qauo_4;66F4&hV9d7^;#P>{jc|v4{i%VE<=z(*wD&NWEHX z;zGWSCPjo7<7OkJmlxE3c=^Z-(=u_`Yp!!_3%w^r_3x3& z>lMk5eU>g$CpG6hwzJHdNx~wddho_BnT?}fb==XMzi4tomvx%nz?wM5G{jEO!_)*p z?8zN`|-_EBu4~vWYFV}A*v>pi9 zSH5b4!_ZM9G(Ugl*3{1Yp`o+k(hG@8&cLKDXu+lSCR=nx%l#3ihpk=~&$VnHB|J^H zC;^)qMrkSTEg|$F2Ew3VW*Y{2>9n!Lf^D(bj8YugN)sdP=^~5v$Dsx9>i6mC2<(9VoUP#sGa82bX=pE zMlP8Rq@LWrOIRr^rK7E{B<1dTwv;yt4eXggZzGXsqHEA2O)LH{-RU2uq1;W1nnIt1 z;0-HFkcVu9SL~*DH-WIOy0HhwdXj4Q^;BPUcYu0}2jq~CJ$e5Nd>p99TcK?!c7yM3 zEx|ON=8z~w(Os)$V#5Px1EnYT-LCKZrdM3eUQM%i*oPw$=e<0K;i~HKd$9x*`henP z!RX7qLu32=8f*K$ueXn;*p7$I1uoFD{r!1S3ea3}GJ|z=c9d)M&fqefP_!c%;b^5{ z?m<$Ewo)dlW*LHM?J!aoo4W`6oUsLZ-oF6i-Si(Q@}hTI1I7xnzq`2v zlfFSU>Mk1G)u_ywja)MuH9gD!v{Z!6_G$slDfsDm{w3L#N9{((JGnx) z*BcFLJ?tkiLUdI>32oJGid61wyA>x7&W4hdq9uvv=bWz7T6X|c_d3;KYtkvWP1u3U zw_NDS18kzx?GpZjFVf(qoZD#5B6E6GX(RLm5rnu;Vm?ZE7o&uMI9TQEVe((_2N0CCMXYpSftyH;*vvb(sSRZcg#J(XYac+Z5DjFL{~-A zn`C;5!`tq&ZPDvZ(id4sJ54Q(8yq(qHoZppiWm5BOrX-rEF1*=<1AsN+A@y|MFYe; zmWp!U%S~K>XG{?YworoanxKy$@8`6`H5k@W8CUwoo1tN|5uC8Ux8QjKu}to=+!qRZ z(Za>9?e(^Vh!cEd*=2d6YyScLPU=-Meh`;9kf!T~-jkLBCaI9D?ZG{4H`l3(RdK;d z;w#W=iVyiCYr1?TC{@zJ!fqgMun8<2wkNIZi})c#7jS+>PSrh`_uycgJ%;ZoTP0Or z!$t{P5e1@+DY9;l{x^Imo>@MpTv3WleMH+sFt>W%BMq7ji(aYRkabEoqQW=SeivZRlm&5UfOzSh z*W$aj0|4bwLc2qPDb;L%+Kv7T{Aj2b zE^i8^&dFHV2<4^-acXVY%gJ=g&vsM^KXHEvv|F0zmYM-Jq(S{i%y|;_0Gq=|BIFS7zu1au1k~!D?iL?x@tu@S+xY)aNjs4sGQcOyZIL z7%2trc4PN4OZNZ$+84E_hpPKG|UO;$i`g5e&1g2C)G@n_XZm`5ni zzY&Kci~oPdgypz9@HL*NtYQqu5T7ch?N1N_YBxpF*RX2oW@w8ItA0a!Z+5<{+icQt zXudi<(+lik^;z%(7vL^O11veK6;d^wD>W<+E`|@6UMm~ekJa&<^%=I56dVwII0>_O~```e+$Ek`JX#e>pf9U)B zIb9G~BRVP0si2w0aLmBUUdcY~Wc}rPmk`&=#|`f|JHF%BUHw93ub6py&-GJHP${dC zoeUgrmEqvw4$}dJoMq1Pbjx%_hFahEdHcAYZD{{RR;c*F=wW13@6~syt~OW}>urjG zB!&i)6az|pP;N1P$aq@~2N5?Zb31O*1w=Mdnkwwjx5b_=WG5GLL^f;bI>u{%#B|qf zvX2Q(=UG0wFcGt<#??%R62YfK$6IeWh{8_L`ZQ#XtjWvdqmogJQCR}RZ6D0u8P*lbTL zD1h?$HM{xsD>E&WO^MgrwY-Ul`yEejGn%PTT*%{DR)1S#CPz0+pG$azmhSjMLEpFR zI$5SYN+=)r_cm$SG^Ir*11_x*4YJ(s6a1W+8GlwXfs!^T@~*nz!{ zOY4cJF0kM-6bPgP-LQoA0~0$scI65VXzVe1rF}|($C21kBy`~Sa-P+iM5}nYLhnFL zSb=*;e~y2hWibW3O+sJkAvixdxg1}hEn573Q%8u2tvIop3z2Jln^Eo6Of)CJ7<$Un>K)Rn|U}w2-y$ zv1v_S`qQ z)Lg@9FbjWyENK_w@1QeUr6lk#@Xv-jt{uUszVl z-LK10hGEF0n~vYX8FMI`T}9u=Cx_$j_R#YZKMLZm$lzO%34TovwP3ag8O}lgXPA!N zLRgv}f9Bb?ts&Y5Tj7g?j*2{WCVYwNs>Jyh+hRTB;<7<+YV0-@)Lk!`xX_OD#Y_-S zhI|ggbM!!z62~}OyGZb#J^mW^UHmbay%OeN%MAA1Ja+Iz6rzLEr_Q$GaEx$~km5xO zS@ld^0QNee9&~aEShi`&>H!yN1img=w%8ZoYrCyRe$2rKo-CsQUM|AkQN9sgi6pzj z++1n2zxv54gc5Qth{r@^ujvVAo8tzqc9{_PZzRjtrZO62_$mlAAxu;Aa&cy~nwiSl z;>VwDFoky8JYzlbmn4UCU^^$G8l4yNB_^ZIJ7b4Npxq%961n~R_T{%WdZRb7_*~8E z`8cU}*$zUZDmtiveFHnQ^@6iE=5VlZeLH<>4l-N!tri2m9|)DrP-AH?WT(~cIBT)I zY-sSH=ga)0Wu~{;Xt9n;a3o;u!X2fgREH0orH*1MNak{9Rn3IcqDi&gmdoZkLZog6 zfuUU#W!$&4W{Bj=wCOe?>nvT4PQ*5)j^iW;lR}aQ#v5@sdSIs*)91mWa0l(Sw#&U4J{+Tz!8mh1I>g#w5>&`m*}b5p;f+fWbUrz(eCQyV_KT4|+q4<2tc z1->5G1X-?yJ-7|$RFy0c+p=s8F3ot(dapWJ5!nYxf^tR@Y;qBzC%ki?>gA3 zj~03p(>$l|_OG;&P7<<#!;uc?F0ZM+WfNzJpyTg3FX^G6jZ2=m1W~iR%odD0 z4E0cKj${mU+68Nkxz%Pg(vV|J2Bw0ome3_VsL*ppRARDg!pf4Yw{q}%=eY4^8;%DK zQ0yxHtfUp2Rc7h7ZSnXZOAl>967Vk5vc)2fB)(b)(z{<;9)1nYUC&Tc-+8HD|7Os# zsi2a3HN9y>C>t9Yx+S#m1g`Elp^z7MOkew^J#OdE+k7uQ!)~__qYI2reZ1K;ivRnl zh@e)ogGY`}oNcG!7~nGnALx0TzEo(i9{DxjG8{4&$OfOYD?P*4qwPS zv7~Am>uM&Ti^b&S@XT`s$52L{y*$6ww-^owKIHT#O{6W$aD=%IZ#Y*s1CL*E5LcO1 z;WOQq@@mz?Do(&%N;WG&xnsELiBJj`;ZhQ`GjU1w6Uv&8;oJ*z*yF#WOE`#MQ4}_b z%MS2?!Jl8DhwQ`xWuj>r+BB#11^L*ropg7CCjqWRqRd{pq&Z3EleC^+fzwkVFqJrxZ1=HSrnwd?!mb<@OyZ^Kd%{kGG@(DW~072D}ZPts=zE z3Sos=j$uNy1Urk-I!oeSpn=D`{6(w&J+v7Dh z11w_-tbg?hjm2?9|`Gip1_M!~@F@ zbzAp*i|2DiT(JQDw?fa?kSl^Fu$QW|cFmahQTx5&OYiL1|J#Ve9(9U}ZBFw^#xpJd zP2+e1Gc~T}_OS8x9gYN8br-qiJF)+vXNhcWrjX8H&&l`Y@!g#HhG+mwFw$~4tTea8 z%J12B8TR}ywF`##kE5dPiJ@KGfagoJ^+42hH4tQwkb&$!oa-;(4ycoIR5*=y1nX760%$o+}W9oZTTTCOYN4D zdA8%T{A#&FX1q=QPNj{wYuI?>DWKZp=!MR&QISd>A)$CEXFtQiv=4tF94jKOjQ{0< zBx~^b5FW}OWxZl^Yj#*Bbh2ZUT#%w10;P3~9BnlPb=$-LXQ}s!NKu=YoewSDb_L!< z#tCtq<=eG(nY;=_B-O282iotp$!n=`%S)}k1oK7_>h%PCi3J_P9n^1s`?_-#32v&| zW|jQkH?~9aSDp_6Rc}lII=eMY) zH(Xol7(L!{!=b=6?6WBxH&j~PbR6AseX%%f`2zfw>3&Z!bzR6guRfFQ3)u>lrUAxl znCv3^N!Cgo7BG_YF3!tkD<}d#Ud%2Y@1HKT$EW+*t@bp#(WYO%UjD`fnwIa03}LQm z^Qp5ML2CN8E2H=$5Wr+Yhf}Y=`&iOfIywITLl>pzEc5ti23`5zS}VBD1U&ucy& z0AIrnc|vQ`aCNb*)ecRq(h-%fr7v04dZ2vxaajZcMU-xN))m_Xqfw zn-Bk1br_8|({M!aEl1o_pEj#y@Raj#p4pa=xUeKmn3t4*6(h``afXsZ%a})z!k^_P z;yxX33k9H0h8+CJKbkUVEIZOURBWINA{VCK!ENJtW~2OmvazBZz6s**5fRXjY?V$* zoLPLBSWOMre~8PU7;m~^2mgU=vxK&*L`W}UwDN-{0f;p|8sG45rWwK=Yhz;`Agj?dlLG@R?~tHw;UlxAnqM z!^RuT;~bt}Q&9PR zWCX#}eEX}TLTP(?=s5!a4_3wb^q6l*$Q_y&k2uS4dX+bO&=&w7L$QF%KXJC5 z6kyh5UlBNTq$aFT=c%MZaIE-4t3mD`qrkRTMagn|Vx^(v^E26_29_$DS?BQcjw}T^ z)CX1-dZ6T`2fP`$4zDw2IJ)n4k`h>sEFp35K07o}`yEqO@!sGpH!#T&#cugCXBtxp zhOJ$13m$xp4o2t-P&yxVj(G>eHf-=PKER2yW?ThwO(bw$UYZY;JH23{?-p!cgLrFk z+;}4m`(gi!FUfh1+`Iqc8*qku}V9HCey}2Xlqupz(GZcE6@8aKA~KWlK367|wh?Qv6_6i_@%aHCT5;9z-))Oedzo;JJD7I;MYLLhqyhTazm4YW<;s%q zGjimK>UZ3PLF0`#oMOc;1+5mxZ7k;Kmd!IEfyF{g)MbFXR0BsHWwMK&gY8?KtdDo( z@h(unSd%DqL))Hg(`YBhyQW$F$2~neg|8rQdQFl=oEF;SE?(o$(FEF0VWrtZMg!b6 zv0CW_zV;0!6RqNPozTb9ha}f}w&zx1YuC$svZ$usf0>Gd##?YWHh3TrV{bSXdK;tp zdfx;ciA^~P*X24bmg0U_q7{8?3~BoQ+4DwKL9Bgb28I69b;b=7*^r}*hu zJeVIG5GyoAK&N&aU1QH%+RFfR{4&mT{ebJk1DpVWO2hBzV`p||D#)gO-L$pJM1KVK zro+2$7WQ+s=`_&I^(;@4#b(?vZCz{?Lf*zL*=`OJWE>PxV!qC?<4vc)=90(YGooL` zSuYY6AGX8UVmq8w!Hb*Rzv)&Dak&(>a!ul#wV(?}n^H5}af*X?s5oxCy%h4b$aPVd zDx2+EoD?g=fG@v=HUw4z-puz*?T$X@j0NH1m1+_%j*%LZEnnyzAcXrtbGqIaaEiiI z)w(3gsM)2(TcA-2+Ns|z874}EV<2sTC^iwa6tPW9WU!P%))|2%87E&4ZgNqq<75y> zyhCjN8w3PR1&vfzutb#ZjvPwv$BpO-w*Vrfd{@|rZeVINSTeS(_VkTxHsD}jRsejR zgm*OhQBw14yPP}=(~{-ZghAs?G#m)rqygu%42saycFbcO}}!+e@*t@)Cj@R+)Pda@)S{`G&Cd5TwrA%XHv$ zztd(Y8&lK%Be+L$UX4zk;dXk)xfRu;N<@~eXU?{rLc?VhGHDD^+>`MT(CC(-dmTk# z(~uR(AL3%2jh3N|qB5G0a-b*>Rlk5?ivOAwr--^>K2u{OTQ@_iMN=$52m-hhi)?|4 zW^*kU&||+_oUvZxq8!sIj;nkVyv*RPnvl)sNv`(k1IFi#khkDSi$#nq@ z%urG&XKx>2CO&}%PmZVpNXL&i+OV^KiCWkP_Ohdtl|035hP?9{U|+PbH@l5DuGjMT z+b7S3Qqyh>pX$xn@pe-1>{<6q7X%&LtGZpS(mW)y zF5cR;clGXze`8hG-o1MDual-O+5ZBqI^Fa9)-N~~n&O3E+i6S_P*zM8ClXrN1R`i$ zGg-cre^k2hM`W_S(Rd8c1A{o?bC~k&X)O&K9)?jr2}aUQNIn3qTfVBT1er)=y??;p z0bbDp;th3KGY8brJDY}#N8F9(#veYapM9Q#G;T=ts1-)Q*sRCjA&CyqVe(>6VnKFu zkMcxatZghbf4F{=acDzEMK|Wk z!ac+owKYAHIKJ*g2@4q-3UlZW`hu#Oa4?1GWlQC4P+zJBjx8|->*Jeq4=h*;xjZVD z46%MVK8X01>;-XA;H5?!BfwDUdQ(( zYe^aLJ?8=64mrWHZHXMm8&b@MCvfQ7{qX>mk>ngH3!q9P6JD1GqF;NL*m?H2Lv*@M z>C(UK4JwMa+A*8R%afTpsPk+dKFdx&IWj=hPsTM?R`Ojuex3mr{vy0jtS~8Z#UVYh z#mX$t^>1S}t^}h;T-F z-P#_vYtro{fviJsVy?vN!Hh|G(&DYF0Z%cOY!&Fwe1Kn=#avU2%((4Nks1v8LlA6> zm%vK%=BPSw^gol1JE1`F*CLJnL`R0kC7C@4(S3UaCN@9qn&wZ$Y1Sv6Nh#-P7p0u3 z_f_DEPPYIK*OnTr;e$&$sGLW6C?dPBsJ^*Xd;DI-L+q}zjIk9!kE!10PY0v-WQ(NVaO$GAL<9LtFXFiB$a9Ca!UbdySpKgbAO z8-=Q(WVA0t;+%{s4WvfK-vOrs!;y)u_;_##Zw4J%OjI8#d4 z1+@V=ODaY*)MomFG1v}BN%Wu6$1)0B2YKN6?=op3Bs&42MC+9a$s<5U{ zcK92gu%)HeIm7T*sk}@o_*CwDvctDS3+m;k!PKiI@_(%L3%Cse9wEhH@}NNaN&z2wq=Pk{OKoTFB4qpuvTj zi@-m%ZGQU%0dj~~2-eoGW)C*f`svz`^KE;5R!}9ur_?T9Pmy_K>->YZRwde`vI&8p zGHfwb8ghFy#dRjN+?Dck*FK>!`0%_wzMenLpP>j1Q@zOua*9cXe=C6xGc|aQ^B%PQ znVv-JXDs8VBE}OKT)gD4ttD$9z2S14XgH0?OXdvz3$F~xJqCKHWwO*sx>6{zk5G~) z1$*}@o{_dw*CaZLc!Q8BNV@iN9>1^CQwn@v+_KQ&hQFi!gMDVBVQzy;kT3l9mXQ{a z98Vi}5?v?F8Gp7VzRcm;1x%Vf=S$slN$wf)O<$cCm^l!^7p!8=*S(Gts;qj?eX+)n z+~Kh@EAgwE?_CnQXxZ%|qbQF*5%e-o#Ir{ejLvLJMCkl1OTrwa^ZGr~N9%K-ATQ|w z|5L#GNVQYh5Y_#wS=l(~yk_>ElhjX+@ z37$TF=ze@#I_W}F2)hW$@-a7_j#0GFWIWf84ii*-Jz!zF<>+0iG%UBwF+_X zQuC}mi(EV{nCMCgUN_=nUbvBjXR{25yXP81ucVdwy)V|%REzq;EkOs=qU7-2=CL?_&_;|Ilb$IKi ze4?7R<2IHo9AmE^zj)hZ3n9&MooFA%0zkPAQMSy*E=$LZ0V%v z@>Az0HY`-6mGRp`Dz~<|dJZSK)oAN@ddgV7@3dvXRKQ>M(%x>XE3$LK85sbOe~XhV z^XH86ETwo~DewKpJi-LZP3cbWwHJ8{*7DQaeMic(r;Yd|&2$Pq%7#%!V_Mzk)F+uq zFS1d#h9O6G=jmH#sjYk_25d`)>HMx#p#YYxh9nB^to#Bxgi_xnh^a5l4fS9AD&)PiPYXP>RJ;7MNzAO+w9=-=c<)c)K5ep&jfWe!dq--=NaDo%DC#%Kw_gcR*gNS5ue1 zsWy>D-Qu~yr?bVA-3bf@>s!I>c+8=chJ$?eSlIj3GQ&nrH}bgZq(FcRC@nsmW5F2$ zVyH5F4_0plLhPawF2=KARatQ4F86D#7e`VlZ0;K9;e>(Z#i-OZ!9Ne))eW&Z?k?H3 zvAbnE=SSfK_creNA5k7j=4@`;SQP~#VyxpKV%Fu9GYQzI8GRPbB*h&!kVcw_Ag3dwKAA4zmK=CeT!YWrH2pSa+J_D&TYz4wP2Bt;c(*E%~u$Bm~H$(*W{oKO|=ajs> zxP{U6zV1aXs-s9aww$rQWhmJ|$;9I`*qyLeDlGWH0_Pdt8pw}+FWs*ON`ybcIRZEO zTsLbQvi(Ui$*w3jV&)F&;z$0{K?R*A$GhU$vhji7ZRgHz+ck#{3qR16e1}gRKdos6 zs>iKVtBCbwPN-)%j-6U+Rd_Wsgce>PUDz}2L8*(&k)@#;Q0r#!N0e%w&DcN@}-D3zGN_GQ{`WJm{1f9n^ zoEdJ1&IWAN zSGfHD%F6k2NT}${r*^oXj9iKV<-w)!@G zko|-DT@YVJUGc7)pK)uHF}jh%A-$I%KWIijlsWrVgnLG}#$xmL?Ksch?y`@3VmEx~ zox}hGSC5beHsKe7=x-rujqb6#y9<>0LOcuU`F563sh;UKlGchVo#QNZz$wSaK%Usc zPLPz-ZyEWDoqNHc#N7C-y_)qwM5~M%fMa-kR6vm5_DCR_!oI^O|6-+J`&S#vrH=IS z*~${VH6ww3qNG^qt{6Hx-x_KjkNY21w}TY1+vqSwf2RU}4hI=D8^$aaj|P)1l3+VD zX7U4+==W>lANm60lQiXZ2?OQ@39%tJQ`cNt3J}_N8K&*7OZ_|~oWsO2N=iA~K;be@ zcF0a?nuf4{2=$J~nQtBQEDj1|G?rdl32k|DV{Zbx zC<=5+t#fO@*rsrgR1lS~S|wt*euE}`KJI;_heHV` zLQ49goZ;GNJwAqkZF50f#0zsVh-{9y1s6E!3KN1wu>`JM|_;V z*3h$+(w9MXwBWm_Er49&z&xh{U7PZ5A(RR13*;h7hgHc5h*@8p`bu72G%EgR4pvR9 z;=vd5mB86xrNZ-slWhn(_HvM*3pGh8ZGx^>mQ@P6?wd117O@>kTn3$KtWc8pBgBRF z+x-s5+a!)L&6a@zAlOwQ=UlOT6E4(;zlJ8f5j|BZ6?MP zEa@j3xkjk;l9}fO7LMrHajP9a?&wzj>wk%z<+nEC;yTy->eb^Bcby#JE=7W--R#w7dD?2^#-m9-GuKU`U2x@?M4UxiOhi}HPn_sy>r8IiRNurTeKhYH;Adp`Cu+rb9 zURFusfdPWnft&x?aXrWx{(g3cC)<|@xQS?wv(m~Bbn|N8ot`%}TbM>ZY=T$f^^0T5Tnh3lb z&I^gF1E-PV89$)ef2`)fQ)3 zNd--77SB;(+I3{{8rh8H@^}P@^ncpTTHB(&v!byqA$=CL72w|cVq-|O-~~OJz%ZT# zEaQeMu!Hm(Q>?vZ#wkBODyurAT-D(2wms^xZut-T(l5s!NVte>uXZ6~m)dF~z}uILhm+2=HSjXfne@EL7>=R3VnhR_&xHa>(C zgD3`PW2CO7+>UMh&Bf5RDz!-Uh#HJKI}tr$S`3L*Yc=UeXbe6fL!Y2OQf;Q?NX_&}*fkuL8)KIigq?9@jWP$5_RVr4XK!*D$-1 zvmXCNv1rh@Zom+w#Bqh0*})*#6Eiy1f$-X}R&}&?V49XjJX(IZDh*yCN+XptK3*3k zi$7ZA$wzKn4>;uQ`%I2UG}ZRH6mV^k{jKr4Ii zn^!KSIG0Q76C|{M1|K%oN8+WT96;^#CchO(pfW3EcJnOKl%S}yifM1ikJDTFmOqPO zO)CD1h_XOi+(u$+RhMqjb$#i1N(WEybeq@>13xx;BcVEKN(Aj*!&t+FS@$akCMWa? z3KWuLkwB#28{3O-za3usvE+^NqKxF1a? zC2U*t0<|o*YM>l~v1y`@nuIM-{K2gN!yCP1sD1%d5kq|O%pR46Io{~5OChCrgVR72 zss7ADlSg0xdI@18z(c&@e$Fo^I=fdcj%L90W#sz{SY7giq+MdKeLp!|u$n5NHms*F zHkh4t5(UmS@+mGh?4@L}>&fB9e$CmZ%%ZGmlXoQcJAedR37AB&=FGRzZ(nn%1!}O>`u+?l{S^HTeyjVUaJ#$#MQ07{*D>ne*K3R^IGiEc3Nyk=1OG_IV+w6q zk-kbaS}VO)%D*LIwKA3~D6>3`S{9E~`vn3dr4#L3iiiowl}y)j&qjm@c+DH@FiE)bPE#qW9Qe_R$WP6CodCcQ(**-zBL62#c5OgeIJyS#H_EK5Rn1o6hlQ8#`_jS|8sUiJxx@IZM z-|2sV5G_GoHdjYbh}D!JVj0!!5rnqzY56auTides2JnvlUa4Azey{dr5y}J z;upM=6R~*dQlQBgavJ23Vk-sAyJ#XpqW!YZ66W}1I*o}{8mBOa)=*Sj-97gVlj$I- zw7`0y1@OG!HY71oCF;lygI8T0OeR?+-{sa<&zkY_;LFYa6INx(IxZ)jqjggre;<2zV?r9 z*{@+v*TLOPBC*vm-A00r(T!Geqf@L5A}6MM@*he&{1q>rZOf(@)4yxrsJ;Uo zecOIS_EqZ2E(Ysu?}b3iw#wzZQ)nv{MHi-CT`_lA^5DUq4@wKrrCr2Nxs%ywg7LT$ zhYwP{f7(BpzCrPs3F*y21xwL$Yx*m&o;X@Msj8~Ch?J66KqCS)rP$JI+_m$`NPu;i z#x@|Y-lzc=UfLh8;)$l=4sMW#)1=Iz2F~R^JC=9%Zpv^^K09ZZXr%p^xY z--G#D;q5*x!r-EpaGWdp^>*$we9lMaCNfPoT=_i_uG(YM+QzCpNp((ga+i=OQqpc< z@jF30uxqjouW2JU{i9vL3)R*5Y_#Cx(AmWVkkuAI!A0QsXY2uV*I>V*Rx*?{!0m2q zb8?*z+8mlc$Kbe-xVtgHu=%?xX-Jx`@%h;4x9j?2 z8lt7$2@&b-S+u($W}>^d?mA`*t=2Dq?_7*0sIW~bf}HIzn;tC}qFE_}r-rf4Prrcy zm=?wq*M?iVT9-D;AHzM#`pjG5gZ+OgXqp`E|41R>t6?Axg?7P>a5xB?R-Ck~e_jSJ z`NtbQR2@X9cvlG6cKr$$gTs`5$Lz2ho;fYGB3#)4GB*F!SF zOhfb_xflIw2M2cAph%XAPTb0@=~@f!`v4OwgnCKnXI8aK!Kpevf>{agn!vp$93tN{Ju%f7qtZ#0 zjE}D@ysGvgQcyV5QX)a}Diaz>E#TJz=g%T0{@=ENuZ^=A?V7)n&*~hudX;FEZ$9+&RNEa295ex__m6Gz}9akyjEk_ zd^AC5Nei)%R7OG$WPEG$j=jt@?Vw+q-{455ay~qY&@8L|LO1T66C`k6FEb)2i0qtO z)X^a<9HvF9wm$&MgJK4@2#tHb`EdIRXxP7WR=FXR=!!6%iA&?q;8WK6$}s3OG{QZ1 z$dTCX?ma58-a-i7wJ%jq%B&aIX$!f|bM7~qSUS~z!(c4kt^Hms^PD{3T`Y}K3-yvu zxEDINqS*W=_|wi0)IU#}W~4D3d6ZAopfQHquitR@*9l(A;WGYyLfBtH^ZU#U3GJRD zcr3N36P5Zkjrig2CL}Y6&#nistvInDa04Y^9oV_$9b}qM9seq+-I zxfA?_lwX>@#}!^45tQY=Dy;|1HSIM*!g;i7px{};?t|Oa?Gn2UvgOHESk4%-Q1#V( zLJ+x|fkDvhEZC9wOSg(fTckBMqGZi=_XpQ4Om$w{pkjUlsLR6gR74En14)P>tpSyM zIBjNmT=Ul@05a$D*(bW_j zxU<^elDwD{&r40r)rnUMa}c1MEqHRKnz@R|700Y{1qb+}!m6a^+aFRay!iQY=yBoh z@9p&Q%R@YP)`rF*Lo|Zeb9N_+oq^}$gWV*VYvJfzJ-$4F1axCxVnb470pqFc%(ill zECQkBqwmp+ga_%7wo%W&{ROGZp`;s2UT8i+(*ee`6v|vjKi>2PykyCN*lE`DjGFxK zS5!6Ic{iiNRk2`Nc_+vfTOZx>?KjDbgMER^XoSgo^P`hnJX>rrP04?%?&i0!)F-t6 z7x8+Ma>=>(a*JXTrA;^?Rz`YnZ{v=`+XumCgpkmhDe{!6DP=oxrT*Q5?WEkU<=)%#l#m213=T4)f!&lQI-?MZ8) z&Tmy3vWxWb)dr0PRzl#P&XmwF%J$6v1Bki$p*$tl1v{RRDs=|3EnFJo6|jzIVJ#x; zk@5zq1vFo0VnEAk)5G=fJ3%ek;xKs}tB6Ex5t3-&Q=?ly=EV*2zcS+z^ZveO%JBCD2KB`q?q$z9vef*s~ zrKBek3n`3izIZsR-c&OVg#y7Fj%Dw{tN<0UdgMn2!(UA4u+8W}Fq%gB*StXtxpxf` zRc`-XTbpqdBTdauWI-1-vXsLP&V@)bYf3Tj(4Vbm$SD_bPY0YO2^zj4)83ksxZLTdM|AKZyev)pON~@37{}KUv>(shr z9JxK#T))XG1m9nj_R);M8Ikr3D^^m@{vpqBdjRMUr0@WKR3?YQ-I;E_U?zc`2??dJ zxM;o0?4v?W>)_6{*U|h0`2a0kv|vG|yva^vh4J5=?xQ+NECFCPEZZK@3u7?o}0PWyn_S)U$h<)(4g~!Gj5mdJSSl z;k>TNNMLM9T|{p2(a{>N6$kU_r<`7Yk*}qgyS|&Ed_wa_YR!VDi4x}j?mb0_g&|&w zSB86p5PFbIqYg>6l69eQe=xIHhQN-dUoLC<8uZp$J`S$d806dz2^@o_Vj=9?`431e zhZml5UKJ+X*QjAk&_+9VC(@(Y0*PZJ+6zPMv@~Fs32P~dK2QXS10IvwJ&*6$gVy^| zBA}^ePS<`C((}Yn_v^Ht*U3&Dmx;B~?LcA{*9mp0boca}JyaO33ztgf{HlLJ`#Oor zI5m$)L{|?)S9Vy{TqC2fyxDq$Hj@hujf;Za5T_ZJY!$HGXee!ml>^016ZCVixoH*vQFOSLx?&pb`rC~^hWP=OkwB%|z&~hcBLlhp@04)`}T0?T! zumPOV(jT(%<6V6Nc`S^pQH%q>7NXiS!f7y1=HRBeayPBCN{loN=j|QaL1Q%dVSHou zRpxioD1hUreGSZ1vT7Fc=*3GNjp!DjXn*kY7pa>>v0Mu8rm+2WOr2UlEqoIv;VEgP zJOsNWHui4*yt}zH&!*i1UJ&&liW+dU?<8~D)p zn_ZES%4LkK6V}F39fvze1@Rnv;>1teGa*i)m%E9Q1ph3&g+SixJ5c#U!FgQHc=|0Q zRjq$WB@N34ltgcTY$u&g`VvEnsd{;LB>b1`DF~TT>08ENAIHW*fBjH5VJ1m$b-&hr z$!XpclRV+W`KI+R&$E9h<-$eu*bz>;IW{TP2Q_^}Q$d0sMXLR+ZLH3m@ixyTB65?c z{w6ZcH(dN*=M8%k*`+?DL<`ue)IVSD_O|!I=O_~?2&u#@e#!^s5%@IN*YkDfk21*1 zUm0V7u|%HXMBk6)lSxE&)MR39tt7RgRu5F~b8m@j$%%K|oNu_f~s6L#S-(Q zpW6eOjDY&ZMQkE5xpvfHuW==t8q~Ahg!z&%wmG*8b(WhunIP@*nN^GirR!DTO^>(t zsxgUT$)!C~mPBUr?C2h2x)Wm}0;i(IBpB!Q?3$&233cH6f3SjXG#T0jy=5OjXaLcK zZzKf+|D^PE@baO}D$35MO~UhT^E&S+a2Q-mO?Y7c1O%Q7F8G6#?jDi;{R;}U*Jf8^ zXu*rnqyX|L#uTPPa)d~wNm!MY0f)k ze8UH3ZDa5+oblJV07|R%`K1-QvD+XJb*`J2co`Ai`_Dra>@(0GJ8$Q#&IBRF zazRwM4He{y+4}QQ!#(!nazEp9T3EeCcfHAj>hR(?Z<;6z1-+J%hB?Ie8t>2ewhY4gnj57HFri^tGDD>_|0!Fp$9sXNmw`ynJ+)l# z%$LY=py|5^_(D>W1py@lLk9o=(13sGrcw$@3%^Cn0RY%_Pyj3d`#T>10QtU)g8nCE z;$UQA`F}}~5CAX%#dQrgPdESw_z4&Q0DkrT_T2fvUkM5}O6^^-fdL972>>wvAt0&q4mG5fFNq?uS|*>k>IKMM*#_zyY1-{1ge zGgl)k+yAnLz*J&SD|P??`xfvG*! ' + title + '<\/title> <\/head> <body bgcolor= \"' + colour + '\"> <center>'); +newwindow.document.writeln('<a titl="إضغط الصورة للإغلاق" href="javascript:window.close();"><img src=' + url + ' border=0></a>'); +newwindow.document.writeln('<\/center> <\/body> <\/html>'); +newwindow.document.close(); +newwindow.focus(); +} + +// Routines to tidy up popup windows when page is left +// Call with an onUnload="tidy5()" in body tag + +function tidy5() { +if (newwindow && !newwindow.closed) { newwindow.close(); } +} diff --git a/site/racecalendar/old.htaccess b/site/racecalendar/old.htaccess new file mode 100644 index 0000000..56940df --- /dev/null +++ b/site/racecalendar/old.htaccess @@ -0,0 +1,5 @@ +Header set Access-Control-Allow-Origin "https://www.slowtwitch.com" + +RewriteEngine On +RewriteCond %{HTTP_HOST} calendar.slowtwitch.com [NC] +RewriteRule ^(.*)$ https://www.slowtwitch.com/calendar$1 [R=301,L] diff --git a/site/racecalendar/rating/scripts/prototype.js b/site/racecalendar/rating/scripts/prototype.js new file mode 100644 index 0000000..5d2100f --- /dev/null +++ b/site/racecalendar/rating/scripts/prototype.js @@ -0,0 +1,3271 @@ +/* Prototype JavaScript framework, version 1.5.1 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.1', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + (document.createElement('div').__proto__ !== + document.createElement('form').__proto__) + }, + + ScriptFragment: '<script[^>]*>([\u0001-\uFFFF]*?)</script>', + JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch(type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (object.ownerDocument === document) return; + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + return '{' + results.join(', ') + '}'; + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (hash[key].constructor != Array) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) + return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#<Enumerable:' + this.toArray().inspect() + '>'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + $A = Array.from = function(iterable) { + if (!iterable) return []; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (arguments[i].constructor == Array) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (value.constructor == Array) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#<Hash:{' + this.map(function(pair) { + return pair.map(Object.inspect).join(': '); + }).join(', ') + '}>'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + if (this.options.onCreate) this.options.onCreate(this.transport); + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + var contentType = this.getHeader('Content-type'); + if (contentType && contentType.strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? json.evalJSON() : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (typeof element == 'string') + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(query.snapshotItem(i)); + return results; + }; + + document.getElementsByClassName = function(className, parentElement) { + var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; + return document._getElementsByXPath(q, parentElement); + } + +} else document.getElementsByClassName = function(className, parentElement) { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + var elements = [], child; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) var Element = {}; + +Element.extend = function(element) { + var F = Prototype.BrowserFeatures; + if (!element || !element.tagName || element.nodeType == 3 || + element._extended || F.SpecificElementExtensions || element == window) + return element; + + var methods = {}, tagName = element.tagName, cache = Element.extend.cache, + T = Element.Methods.ByTag; + + // extend methods for all tags (Safari doesn't need this) + if (!F.ElementExtensions) { + Object.extend(methods, Element.Methods), + Object.extend(methods, Element.Methods.Simulated); + } + + // extend methods for specific tags + if (T[tagName]) Object.extend(methods, T[tagName]); + + for (var property in methods) { + var value = methods[property]; + if (typeof value == 'function' && !(property in element)) + element[property] = cache.findOrStore(value); + } + + element._extended = Prototype.emptyFunction; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + hide: function(element) { + $(element).style.display = 'none'; + return element; + }, + + show: function(element) { + $(element).style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: function(element, html) { + html = typeof html == 'undefined' ? '' : html.toString(); + $(element).innerHTML = html.stripScripts(); + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + replace: function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + var range = element.ownerDocument.createRange(); + range.selectNodeContents(element); + element.parentNode.replaceChild( + range.createContextualFragment(html.stripScripts()), element); + } + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (typeof selector == 'string') + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = element.ancestors(); + return expression ? Selector.findElement(ancestors, expression, index) : + ancestors[index || 0]; + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + var descendants = element.descendants(); + return expression ? Selector.findElement(descendants, expression, index) : + descendants[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = element.previousSiblings(); + return expression ? Selector.findElement(previousSiblings, expression, index) : + previousSiblings[index || 0]; + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = element.nextSiblings(); + return expression ? Selector.findElement(nextSiblings, expression, index) : + nextSiblings[index || 0]; + }, + + getElementsBySelector: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + getElementsByClassName: function(element, className) { + return document.getElementsByClassName(className, element); + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + if (!element.attributes) return null; + var t = Element._attributeTranslations; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + var attribute = element.attributes[name]; + return attribute ? attribute.nodeValue : null; + } + return element.getAttribute(name); + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + if (elementClassName.length == 0) return false; + if (elementClassName == className || + elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) + return true; + return false; + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).add(className); + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).remove(className); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className); + return element; + }, + + observe: function() { + Event.observe.apply(Event, arguments); + return $A(arguments).first(); + }, + + stopObserving: function() { + Event.stopObserving.apply(Event, arguments); + return $A(arguments).first(); + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + while (element = element.parentNode) + if (element == ancestor) return true; + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Position.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + style = style == 'float' ? 'cssFloat' : style.camelize(); + var value = element.style[style]; + if (!value) { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, + + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, + + setStyle: function(element, styles, camelized) { + element = $(element); + var elementStyle = element.style; + + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]) + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : + (camelized ? property : property.camelize())] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = $(element).getStyle('display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + // All *Width and *Height properties give 0 on elements with display none, + // so enable the element temporarily + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (window.opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = element.style.overflow || 'auto'; + if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + } +}; + +Object.extend(Element.Methods, { + childOf: Element.Methods.descendantOf, + childElements: Element.Methods.immediateDescendants +}); + +if (Prototype.Browser.Opera) { + Element.Methods._getStyle = Element.Methods.getStyle; + Element.Methods.getStyle = function(element, style) { + switch(style) { + case 'left': + case 'top': + case 'right': + case 'bottom': + if (Element._getStyle(element, 'position') == 'static') return null; + default: return Element._getStyle(element, style); + } + }; +} +else if (Prototype.Browser.IE) { + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; + + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset'+style.capitalize()] + 'px'; + return null; + } + return value; + }; + + Element.Methods.setOpacity = function(element, value) { + element = $(element); + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + style.filter = filter.replace(/alpha\([^\)]*\)/gi,''); + return element; + } else if (value < 0.00001) value = 0; + style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + // IE is missing .innerHTML support for TABLE-related elements + Element.Methods.update = function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + var tagName = element.tagName.toUpperCase(); + if (['THEAD','TBODY','TR','TD'].include(tagName)) { + var div = document.createElement('div'); + switch (tagName) { + case 'THEAD': + case 'TBODY': + div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>'; + depth = 2; + break; + case 'TR': + div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>'; + depth = 3; + break; + case 'TD': + div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>'; + depth = 4; + } + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + depth.times(function() { div = div.firstChild }); + $A(div.childNodes).each(function(node) { element.appendChild(node) }); + } else { + element.innerHTML = html.stripScripts(); + } + setTimeout(function() { html.evalScripts() }, 10); + return element; + } +} +else if (Prototype.Browser.Gecko) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +Element._attributeTranslations = { + names: { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } + } +}; + +(function() { + Object.extend(this, { + href: this._getAttr, + src: this._getAttr, + type: this._getAttr, + disabled: this._flag, + checked: this._flag, + readonly: this._flag, + multiple: this._flag + }); +}).call(Element._attributeTranslations.values); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + var t = Element._attributeTranslations, node; + attribute = t.names[attribute] || attribute; + node = $(element).getAttributeNode(attribute); + return node && node.specified; + } +}; + +Element.Methods.ByTag = {}; + +Object.extend(Element, Element.Methods); + +if (!Prototype.BrowserFeatures.ElementExtensions && + document.createElement('div').__proto__) { + window.HTMLElement = {}; + window.HTMLElement.prototype = document.createElement('div').__proto__; + Prototype.BrowserFeatures.ElementExtensions = true; +} + +Element.hasAttribute = function(element, attribute) { + if (element.hasAttribute) return element.hasAttribute(attribute); + return Element.Methods.Simulated.hasAttribute(element, attribute); +}; + +Element.addMethods = function(methods) { + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || {}); + else { + if (tagName.constructor == Array) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = {}; + Object.extend(Element.Methods.ByTag[tagName], methods); + } + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + var cache = Element.extend.cache; + for (var property in methods) { + var value = methods[property]; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = cache.findOrStore(value); + } + } + + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + window[klass] = {}; + window[klass].prototype = document.createElement(tagName).__proto__; + return window[klass]; + } + + if (F.ElementExtensions) { + copy(Element.Methods, HTMLElement.prototype); + copy(Element.Methods.Simulated, HTMLElement.prototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (typeof klass == "undefined") continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; +}; + +var Toggle = { display: Element.toggle }; + +/*--------------------------------------------------------------------------*/ + +Abstract.Insertion = function(adjacency) { + this.adjacency = adjacency; +} + +Abstract.Insertion.prototype = { + initialize: function(element, content) { + this.element = $(element); + this.content = content.stripScripts(); + + if (this.adjacency && this.element.insertAdjacentHTML) { + try { + this.element.insertAdjacentHTML(this.adjacency, this.content); + } catch (e) { + var tagName = this.element.tagName.toUpperCase(); + if (['TBODY', 'TR'].include(tagName)) { + this.insertContent(this.contentFromAnonymousTable()); + } else { + throw e; + } + } + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.insertContent([this.range.createContextualFragment(this.content)]); + } + + setTimeout(function() {content.evalScripts()}, 10); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; + return $A(div.childNodes[0].childNodes[0].childNodes); + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, this.element); + }).bind(this)); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function(fragments) { + fragments.reverse(false).each((function(fragment) { + this.element.insertBefore(fragment, this.element.firstChild); + }).bind(this)); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.appendChild(fragment); + }).bind(this)); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, + this.element.nextSibling); + }).bind(this)); + } +}); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; return; + } + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + return this.findElements(document).include(element); + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#<Selector:" + this.expression.inspect() + ">"; + } +}; + +Object.extend(Selector, { + _cache: {}, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (typeof h === 'function') return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!nodes && root == document) return targetNode ? [targetNode] : []; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != null) { + if (key in result) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || {}); + + var params = options.parameters; + options.parameters = form.serialize(true); + + if (params) { + if (typeof params == 'string') params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(form.readAttribute('action'), options); + } +} + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type))) + element.select(); + } catch (e) {} + return element; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +} + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return $(event.target || event.srcElement); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (Prototype.Browser.IE) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (Prototype.Browser.WebKit) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); \ No newline at end of file diff --git a/site/racecalendar/rating/scripts/rating.js b/site/racecalendar/rating/scripts/rating.js new file mode 100644 index 0000000..1ac8b0a --- /dev/null +++ b/site/racecalendar/rating/scripts/rating.js @@ -0,0 +1,54 @@ +function RateItem(varParentId, varItemId, varRating) +{ + var elementId = varParentId+"_"+varItemId; + var varOrigClassName = document.getElementById(elementId).className; + + // Retrieve Ajax Feeds + new Ajax.Request('ajax.rate.item.php', + { + method: 'post', + parameters: {parent: varParentId, item: varItemId, rating: varRating, classes: varOrigClassName}, + onSuccess: ReloadRating, + onFailure: RatingError + } + ); + +} + +function ReadNameValuePairs(nameValuePair) +{ + var trimspaces = /(\s)+/; + var returnData = new Array(); + var pairs = nameValuePair.split('&'); + + for (var i = 0; i < pairs.length; i++) + { + var pair = pairs[i].split('='); + returnData[pair[0].replace(trimspaces, "")] = pair[1]; + } + + return returnData; +} + +function ReloadRating(requestObj, jsonObj) +{ + var newlines = /(\r\n|\r|\n)/; + var returnData = ReadNameValuePairs(requestObj.responseText.replace(newlines, "")); + var elementId = returnData['parent']+"_"+returnData['item']; + + document.getElementById(elementId).className = returnData['classes']; + var liObj = document.getElementById(elementId).getElementsByTagName('a'); + + for (var i = 0; i < liObj.length; i++) + { + liObj[i].onclick = function(){}; + } + document.getElementById(returnData['parent']).className = returnData['parentClass']; +} + +function RatingError() +{ + + //alert ("Error"); + +} \ No newline at end of file diff --git a/site/retailers/javascript.js b/site/retailers/javascript.js new file mode 100644 index 0000000..9ca0ce3 --- /dev/null +++ b/site/retailers/javascript.js @@ -0,0 +1,123 @@ +function validateEmail(emailAddress) { + var match = /^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*$/.test(emailAddress); + return match; +} + + + +function CheckRegisterForm(RegisterForm) + { + if (RegisterForm.username.value == "" ) { alert( "Please choose a username!" ); + RegisterForm.username.focus(); + return false; } + + if (RegisterForm.password.value == "" ) { alert( "Please choose a password!" ); + RegisterForm.password.focus(); + return false; } + + if (RegisterForm.email.value == "" ) { alert( "Please enter your email address." ); + RegisterForm.email.focus(); + return false; } + + checkEmail = RegisterForm.email.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("Your emails address is invalid!."); + RegisterForm.email.focus(); + return false; } + + + // return true; +} + + +function CheckTellForm(tellform) + { + if (tellform.name.value == "" ) { alert( "الرجاء أدخل الإسم بالكامل" ); + tellform.name.focus(); + return false; } + + if (tellform.email.value == "" ) { alert( "أدخل البريد الإلكتروني" ); + tellform.email.focus(); + return false; } + + checkEmail = tellform.email.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("البريد الإلكتروني خطأ!."); + tellform.email.focus(); + return false; } + + + if (tellform.fname.value == "" ) { alert( "أدخل إسم صديقك" ); + tellform.fname.focus(); + return false; } + + + + if (tellform.femail.value == "" ) { alert( "أدخل البريد الالكتروني الخاص بصديقك" ); + tellform.femail.focus(); + return false; } + + checkEmail = tellform.femail.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("البريد الإلكتروني خطأ!."); + tellform.femail.focus(); + return false; } + + + + // return true; +} + + +var newwindow; +function pop(url) +{ + newwindow=window.open(url,'poppage', 'toolbars=0, scrollbars=1, location=0, statusbars=1, menubars=0, resizable=0, width=500, height=400'); + if (window.focus) {newwindow.focus()} +} + + function popimg(url) + { + newwindow=window.open(url,'name','height=500,width=650,left=100,top=100,resizable=yes,scrollbars=yes,toolbar=yes,status=yes'); + if (window.focus) {newwindow.focus()} + } + + + +<!-- ; +var newwindow; +var wheight = 0, wwidth = 0; +function viewimg(url, title, iwidth, iheight, colour) { +var pwidth, pheight; + +if ( !newwindow || newwindow.closed ) { +pwidth=iwidth+30; +pheight=iheight+30; +newwindow=window.open('','htmlname','width=' + pwidth +',height=' +pheight + ',resizable=1,top=50,left=10'); +wheight=iheight; +wwidth=iwidth; +} + +if (wheight!=iheight || wwidth!=iwidth ) { +pwidth=iwidth+30; +pheight=iheight+60; +newwindow.resizeTo(pwidth, pheight); +wheight=iheight; +wwidth=iwidth; +} + +newwindow.document.clear(); +newwindow.focus(); +newwindow.document.writeln('<html> <head> <title>' + title + '<\/title> <\/head> <body bgcolor= \"' + colour + '\"> <center>'); +newwindow.document.writeln('<a titl="إضغط الصورة للإغلاق" href="javascript:window.close();"><img src=' + url + ' border=0></a>'); +newwindow.document.writeln('<\/center> <\/body> <\/html>'); +newwindow.document.close(); +newwindow.focus(); +} + +// Routines to tidy up popup windows when page is left +// Call with an onUnload="tidy5()" in body tag + +function tidy5() { +if (newwindow && !newwindow.closed) { newwindow.close(); } +} diff --git a/site/retailers/rating/scripts/prototype.js b/site/retailers/rating/scripts/prototype.js new file mode 100644 index 0000000..5d2100f --- /dev/null +++ b/site/retailers/rating/scripts/prototype.js @@ -0,0 +1,3271 @@ +/* Prototype JavaScript framework, version 1.5.1 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.1', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + (document.createElement('div').__proto__ !== + document.createElement('form').__proto__) + }, + + ScriptFragment: '<script[^>]*>([\u0001-\uFFFF]*?)</script>', + JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch(type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (object.ownerDocument === document) return; + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + return '{' + results.join(', ') + '}'; + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (hash[key].constructor != Array) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) + return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#<Enumerable:' + this.toArray().inspect() + '>'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + $A = Array.from = function(iterable) { + if (!iterable) return []; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (arguments[i].constructor == Array) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (value.constructor == Array) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#<Hash:{' + this.map(function(pair) { + return pair.map(Object.inspect).join(': '); + }).join(', ') + '}>'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + if (this.options.onCreate) this.options.onCreate(this.transport); + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + var contentType = this.getHeader('Content-type'); + if (contentType && contentType.strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? json.evalJSON() : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (typeof element == 'string') + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(query.snapshotItem(i)); + return results; + }; + + document.getElementsByClassName = function(className, parentElement) { + var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; + return document._getElementsByXPath(q, parentElement); + } + +} else document.getElementsByClassName = function(className, parentElement) { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + var elements = [], child; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) var Element = {}; + +Element.extend = function(element) { + var F = Prototype.BrowserFeatures; + if (!element || !element.tagName || element.nodeType == 3 || + element._extended || F.SpecificElementExtensions || element == window) + return element; + + var methods = {}, tagName = element.tagName, cache = Element.extend.cache, + T = Element.Methods.ByTag; + + // extend methods for all tags (Safari doesn't need this) + if (!F.ElementExtensions) { + Object.extend(methods, Element.Methods), + Object.extend(methods, Element.Methods.Simulated); + } + + // extend methods for specific tags + if (T[tagName]) Object.extend(methods, T[tagName]); + + for (var property in methods) { + var value = methods[property]; + if (typeof value == 'function' && !(property in element)) + element[property] = cache.findOrStore(value); + } + + element._extended = Prototype.emptyFunction; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + hide: function(element) { + $(element).style.display = 'none'; + return element; + }, + + show: function(element) { + $(element).style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: function(element, html) { + html = typeof html == 'undefined' ? '' : html.toString(); + $(element).innerHTML = html.stripScripts(); + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + replace: function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + var range = element.ownerDocument.createRange(); + range.selectNodeContents(element); + element.parentNode.replaceChild( + range.createContextualFragment(html.stripScripts()), element); + } + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (typeof selector == 'string') + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = element.ancestors(); + return expression ? Selector.findElement(ancestors, expression, index) : + ancestors[index || 0]; + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + var descendants = element.descendants(); + return expression ? Selector.findElement(descendants, expression, index) : + descendants[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = element.previousSiblings(); + return expression ? Selector.findElement(previousSiblings, expression, index) : + previousSiblings[index || 0]; + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = element.nextSiblings(); + return expression ? Selector.findElement(nextSiblings, expression, index) : + nextSiblings[index || 0]; + }, + + getElementsBySelector: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + getElementsByClassName: function(element, className) { + return document.getElementsByClassName(className, element); + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + if (!element.attributes) return null; + var t = Element._attributeTranslations; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + var attribute = element.attributes[name]; + return attribute ? attribute.nodeValue : null; + } + return element.getAttribute(name); + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + if (elementClassName.length == 0) return false; + if (elementClassName == className || + elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) + return true; + return false; + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).add(className); + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).remove(className); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className); + return element; + }, + + observe: function() { + Event.observe.apply(Event, arguments); + return $A(arguments).first(); + }, + + stopObserving: function() { + Event.stopObserving.apply(Event, arguments); + return $A(arguments).first(); + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + while (element = element.parentNode) + if (element == ancestor) return true; + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Position.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + style = style == 'float' ? 'cssFloat' : style.camelize(); + var value = element.style[style]; + if (!value) { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, + + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, + + setStyle: function(element, styles, camelized) { + element = $(element); + var elementStyle = element.style; + + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]) + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : + (camelized ? property : property.camelize())] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = $(element).getStyle('display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + // All *Width and *Height properties give 0 on elements with display none, + // so enable the element temporarily + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (window.opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = element.style.overflow || 'auto'; + if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + } +}; + +Object.extend(Element.Methods, { + childOf: Element.Methods.descendantOf, + childElements: Element.Methods.immediateDescendants +}); + +if (Prototype.Browser.Opera) { + Element.Methods._getStyle = Element.Methods.getStyle; + Element.Methods.getStyle = function(element, style) { + switch(style) { + case 'left': + case 'top': + case 'right': + case 'bottom': + if (Element._getStyle(element, 'position') == 'static') return null; + default: return Element._getStyle(element, style); + } + }; +} +else if (Prototype.Browser.IE) { + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; + + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset'+style.capitalize()] + 'px'; + return null; + } + return value; + }; + + Element.Methods.setOpacity = function(element, value) { + element = $(element); + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + style.filter = filter.replace(/alpha\([^\)]*\)/gi,''); + return element; + } else if (value < 0.00001) value = 0; + style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + // IE is missing .innerHTML support for TABLE-related elements + Element.Methods.update = function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + var tagName = element.tagName.toUpperCase(); + if (['THEAD','TBODY','TR','TD'].include(tagName)) { + var div = document.createElement('div'); + switch (tagName) { + case 'THEAD': + case 'TBODY': + div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>'; + depth = 2; + break; + case 'TR': + div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>'; + depth = 3; + break; + case 'TD': + div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>'; + depth = 4; + } + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + depth.times(function() { div = div.firstChild }); + $A(div.childNodes).each(function(node) { element.appendChild(node) }); + } else { + element.innerHTML = html.stripScripts(); + } + setTimeout(function() { html.evalScripts() }, 10); + return element; + } +} +else if (Prototype.Browser.Gecko) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +Element._attributeTranslations = { + names: { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } + } +}; + +(function() { + Object.extend(this, { + href: this._getAttr, + src: this._getAttr, + type: this._getAttr, + disabled: this._flag, + checked: this._flag, + readonly: this._flag, + multiple: this._flag + }); +}).call(Element._attributeTranslations.values); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + var t = Element._attributeTranslations, node; + attribute = t.names[attribute] || attribute; + node = $(element).getAttributeNode(attribute); + return node && node.specified; + } +}; + +Element.Methods.ByTag = {}; + +Object.extend(Element, Element.Methods); + +if (!Prototype.BrowserFeatures.ElementExtensions && + document.createElement('div').__proto__) { + window.HTMLElement = {}; + window.HTMLElement.prototype = document.createElement('div').__proto__; + Prototype.BrowserFeatures.ElementExtensions = true; +} + +Element.hasAttribute = function(element, attribute) { + if (element.hasAttribute) return element.hasAttribute(attribute); + return Element.Methods.Simulated.hasAttribute(element, attribute); +}; + +Element.addMethods = function(methods) { + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || {}); + else { + if (tagName.constructor == Array) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = {}; + Object.extend(Element.Methods.ByTag[tagName], methods); + } + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + var cache = Element.extend.cache; + for (var property in methods) { + var value = methods[property]; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = cache.findOrStore(value); + } + } + + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + window[klass] = {}; + window[klass].prototype = document.createElement(tagName).__proto__; + return window[klass]; + } + + if (F.ElementExtensions) { + copy(Element.Methods, HTMLElement.prototype); + copy(Element.Methods.Simulated, HTMLElement.prototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (typeof klass == "undefined") continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; +}; + +var Toggle = { display: Element.toggle }; + +/*--------------------------------------------------------------------------*/ + +Abstract.Insertion = function(adjacency) { + this.adjacency = adjacency; +} + +Abstract.Insertion.prototype = { + initialize: function(element, content) { + this.element = $(element); + this.content = content.stripScripts(); + + if (this.adjacency && this.element.insertAdjacentHTML) { + try { + this.element.insertAdjacentHTML(this.adjacency, this.content); + } catch (e) { + var tagName = this.element.tagName.toUpperCase(); + if (['TBODY', 'TR'].include(tagName)) { + this.insertContent(this.contentFromAnonymousTable()); + } else { + throw e; + } + } + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.insertContent([this.range.createContextualFragment(this.content)]); + } + + setTimeout(function() {content.evalScripts()}, 10); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; + return $A(div.childNodes[0].childNodes[0].childNodes); + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, this.element); + }).bind(this)); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function(fragments) { + fragments.reverse(false).each((function(fragment) { + this.element.insertBefore(fragment, this.element.firstChild); + }).bind(this)); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.appendChild(fragment); + }).bind(this)); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, + this.element.nextSibling); + }).bind(this)); + } +}); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; return; + } + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + return this.findElements(document).include(element); + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#<Selector:" + this.expression.inspect() + ">"; + } +}; + +Object.extend(Selector, { + _cache: {}, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (typeof h === 'function') return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!nodes && root == document) return targetNode ? [targetNode] : []; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != null) { + if (key in result) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || {}); + + var params = options.parameters; + options.parameters = form.serialize(true); + + if (params) { + if (typeof params == 'string') params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(form.readAttribute('action'), options); + } +} + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type))) + element.select(); + } catch (e) {} + return element; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +} + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return $(event.target || event.srcElement); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (Prototype.Browser.IE) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (Prototype.Browser.WebKit) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); \ No newline at end of file diff --git a/site/retailers/rating/scripts/rating.js b/site/retailers/rating/scripts/rating.js new file mode 100644 index 0000000..1ac8b0a --- /dev/null +++ b/site/retailers/rating/scripts/rating.js @@ -0,0 +1,54 @@ +function RateItem(varParentId, varItemId, varRating) +{ + var elementId = varParentId+"_"+varItemId; + var varOrigClassName = document.getElementById(elementId).className; + + // Retrieve Ajax Feeds + new Ajax.Request('ajax.rate.item.php', + { + method: 'post', + parameters: {parent: varParentId, item: varItemId, rating: varRating, classes: varOrigClassName}, + onSuccess: ReloadRating, + onFailure: RatingError + } + ); + +} + +function ReadNameValuePairs(nameValuePair) +{ + var trimspaces = /(\s)+/; + var returnData = new Array(); + var pairs = nameValuePair.split('&'); + + for (var i = 0; i < pairs.length; i++) + { + var pair = pairs[i].split('='); + returnData[pair[0].replace(trimspaces, "")] = pair[1]; + } + + return returnData; +} + +function ReloadRating(requestObj, jsonObj) +{ + var newlines = /(\r\n|\r|\n)/; + var returnData = ReadNameValuePairs(requestObj.responseText.replace(newlines, "")); + var elementId = returnData['parent']+"_"+returnData['item']; + + document.getElementById(elementId).className = returnData['classes']; + var liObj = document.getElementById(elementId).getElementsByTagName('a'); + + for (var i = 0; i < liObj.length; i++) + { + liObj[i].onclick = function(){}; + } + document.getElementById(returnData['parent']).className = returnData['parentClass']; +} + +function RatingError() +{ + + //alert ("Error"); + +} \ No newline at end of file diff --git a/site/roadshow/class/rating/scripts/prototype.js b/site/roadshow/class/rating/scripts/prototype.js new file mode 100644 index 0000000..5d2100f --- /dev/null +++ b/site/roadshow/class/rating/scripts/prototype.js @@ -0,0 +1,3271 @@ +/* Prototype JavaScript framework, version 1.5.1 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.1', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + (document.createElement('div').__proto__ !== + document.createElement('form').__proto__) + }, + + ScriptFragment: '<script[^>]*>([\u0001-\uFFFF]*?)</script>', + JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch(type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (object.ownerDocument === document) return; + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + return '{' + results.join(', ') + '}'; + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (hash[key].constructor != Array) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) + return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#<Enumerable:' + this.toArray().inspect() + '>'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + $A = Array.from = function(iterable) { + if (!iterable) return []; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (arguments[i].constructor == Array) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (value.constructor == Array) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#<Hash:{' + this.map(function(pair) { + return pair.map(Object.inspect).join(': '); + }).join(', ') + '}>'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + if (this.options.onCreate) this.options.onCreate(this.transport); + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + var contentType = this.getHeader('Content-type'); + if (contentType && contentType.strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? json.evalJSON() : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (typeof element == 'string') + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(query.snapshotItem(i)); + return results; + }; + + document.getElementsByClassName = function(className, parentElement) { + var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; + return document._getElementsByXPath(q, parentElement); + } + +} else document.getElementsByClassName = function(className, parentElement) { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + var elements = [], child; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) var Element = {}; + +Element.extend = function(element) { + var F = Prototype.BrowserFeatures; + if (!element || !element.tagName || element.nodeType == 3 || + element._extended || F.SpecificElementExtensions || element == window) + return element; + + var methods = {}, tagName = element.tagName, cache = Element.extend.cache, + T = Element.Methods.ByTag; + + // extend methods for all tags (Safari doesn't need this) + if (!F.ElementExtensions) { + Object.extend(methods, Element.Methods), + Object.extend(methods, Element.Methods.Simulated); + } + + // extend methods for specific tags + if (T[tagName]) Object.extend(methods, T[tagName]); + + for (var property in methods) { + var value = methods[property]; + if (typeof value == 'function' && !(property in element)) + element[property] = cache.findOrStore(value); + } + + element._extended = Prototype.emptyFunction; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + hide: function(element) { + $(element).style.display = 'none'; + return element; + }, + + show: function(element) { + $(element).style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: function(element, html) { + html = typeof html == 'undefined' ? '' : html.toString(); + $(element).innerHTML = html.stripScripts(); + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + replace: function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + var range = element.ownerDocument.createRange(); + range.selectNodeContents(element); + element.parentNode.replaceChild( + range.createContextualFragment(html.stripScripts()), element); + } + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (typeof selector == 'string') + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = element.ancestors(); + return expression ? Selector.findElement(ancestors, expression, index) : + ancestors[index || 0]; + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + var descendants = element.descendants(); + return expression ? Selector.findElement(descendants, expression, index) : + descendants[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = element.previousSiblings(); + return expression ? Selector.findElement(previousSiblings, expression, index) : + previousSiblings[index || 0]; + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = element.nextSiblings(); + return expression ? Selector.findElement(nextSiblings, expression, index) : + nextSiblings[index || 0]; + }, + + getElementsBySelector: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + getElementsByClassName: function(element, className) { + return document.getElementsByClassName(className, element); + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + if (!element.attributes) return null; + var t = Element._attributeTranslations; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + var attribute = element.attributes[name]; + return attribute ? attribute.nodeValue : null; + } + return element.getAttribute(name); + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + if (elementClassName.length == 0) return false; + if (elementClassName == className || + elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) + return true; + return false; + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).add(className); + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).remove(className); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className); + return element; + }, + + observe: function() { + Event.observe.apply(Event, arguments); + return $A(arguments).first(); + }, + + stopObserving: function() { + Event.stopObserving.apply(Event, arguments); + return $A(arguments).first(); + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + while (element = element.parentNode) + if (element == ancestor) return true; + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Position.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + style = style == 'float' ? 'cssFloat' : style.camelize(); + var value = element.style[style]; + if (!value) { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, + + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, + + setStyle: function(element, styles, camelized) { + element = $(element); + var elementStyle = element.style; + + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]) + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : + (camelized ? property : property.camelize())] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = $(element).getStyle('display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + // All *Width and *Height properties give 0 on elements with display none, + // so enable the element temporarily + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (window.opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = element.style.overflow || 'auto'; + if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + } +}; + +Object.extend(Element.Methods, { + childOf: Element.Methods.descendantOf, + childElements: Element.Methods.immediateDescendants +}); + +if (Prototype.Browser.Opera) { + Element.Methods._getStyle = Element.Methods.getStyle; + Element.Methods.getStyle = function(element, style) { + switch(style) { + case 'left': + case 'top': + case 'right': + case 'bottom': + if (Element._getStyle(element, 'position') == 'static') return null; + default: return Element._getStyle(element, style); + } + }; +} +else if (Prototype.Browser.IE) { + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; + + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset'+style.capitalize()] + 'px'; + return null; + } + return value; + }; + + Element.Methods.setOpacity = function(element, value) { + element = $(element); + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + style.filter = filter.replace(/alpha\([^\)]*\)/gi,''); + return element; + } else if (value < 0.00001) value = 0; + style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + // IE is missing .innerHTML support for TABLE-related elements + Element.Methods.update = function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + var tagName = element.tagName.toUpperCase(); + if (['THEAD','TBODY','TR','TD'].include(tagName)) { + var div = document.createElement('div'); + switch (tagName) { + case 'THEAD': + case 'TBODY': + div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>'; + depth = 2; + break; + case 'TR': + div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>'; + depth = 3; + break; + case 'TD': + div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>'; + depth = 4; + } + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + depth.times(function() { div = div.firstChild }); + $A(div.childNodes).each(function(node) { element.appendChild(node) }); + } else { + element.innerHTML = html.stripScripts(); + } + setTimeout(function() { html.evalScripts() }, 10); + return element; + } +} +else if (Prototype.Browser.Gecko) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +Element._attributeTranslations = { + names: { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } + } +}; + +(function() { + Object.extend(this, { + href: this._getAttr, + src: this._getAttr, + type: this._getAttr, + disabled: this._flag, + checked: this._flag, + readonly: this._flag, + multiple: this._flag + }); +}).call(Element._attributeTranslations.values); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + var t = Element._attributeTranslations, node; + attribute = t.names[attribute] || attribute; + node = $(element).getAttributeNode(attribute); + return node && node.specified; + } +}; + +Element.Methods.ByTag = {}; + +Object.extend(Element, Element.Methods); + +if (!Prototype.BrowserFeatures.ElementExtensions && + document.createElement('div').__proto__) { + window.HTMLElement = {}; + window.HTMLElement.prototype = document.createElement('div').__proto__; + Prototype.BrowserFeatures.ElementExtensions = true; +} + +Element.hasAttribute = function(element, attribute) { + if (element.hasAttribute) return element.hasAttribute(attribute); + return Element.Methods.Simulated.hasAttribute(element, attribute); +}; + +Element.addMethods = function(methods) { + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || {}); + else { + if (tagName.constructor == Array) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = {}; + Object.extend(Element.Methods.ByTag[tagName], methods); + } + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + var cache = Element.extend.cache; + for (var property in methods) { + var value = methods[property]; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = cache.findOrStore(value); + } + } + + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + window[klass] = {}; + window[klass].prototype = document.createElement(tagName).__proto__; + return window[klass]; + } + + if (F.ElementExtensions) { + copy(Element.Methods, HTMLElement.prototype); + copy(Element.Methods.Simulated, HTMLElement.prototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (typeof klass == "undefined") continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; +}; + +var Toggle = { display: Element.toggle }; + +/*--------------------------------------------------------------------------*/ + +Abstract.Insertion = function(adjacency) { + this.adjacency = adjacency; +} + +Abstract.Insertion.prototype = { + initialize: function(element, content) { + this.element = $(element); + this.content = content.stripScripts(); + + if (this.adjacency && this.element.insertAdjacentHTML) { + try { + this.element.insertAdjacentHTML(this.adjacency, this.content); + } catch (e) { + var tagName = this.element.tagName.toUpperCase(); + if (['TBODY', 'TR'].include(tagName)) { + this.insertContent(this.contentFromAnonymousTable()); + } else { + throw e; + } + } + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.insertContent([this.range.createContextualFragment(this.content)]); + } + + setTimeout(function() {content.evalScripts()}, 10); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; + return $A(div.childNodes[0].childNodes[0].childNodes); + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, this.element); + }).bind(this)); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function(fragments) { + fragments.reverse(false).each((function(fragment) { + this.element.insertBefore(fragment, this.element.firstChild); + }).bind(this)); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.appendChild(fragment); + }).bind(this)); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, + this.element.nextSibling); + }).bind(this)); + } +}); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; return; + } + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + return this.findElements(document).include(element); + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#<Selector:" + this.expression.inspect() + ">"; + } +}; + +Object.extend(Selector, { + _cache: {}, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (typeof h === 'function') return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!nodes && root == document) return targetNode ? [targetNode] : []; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != null) { + if (key in result) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || {}); + + var params = options.parameters; + options.parameters = form.serialize(true); + + if (params) { + if (typeof params == 'string') params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(form.readAttribute('action'), options); + } +} + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type))) + element.select(); + } catch (e) {} + return element; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +} + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return $(event.target || event.srcElement); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (Prototype.Browser.IE) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (Prototype.Browser.WebKit) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); \ No newline at end of file diff --git a/site/roadshow/class/rating/scripts/rating.js b/site/roadshow/class/rating/scripts/rating.js new file mode 100644 index 0000000..1ac8b0a --- /dev/null +++ b/site/roadshow/class/rating/scripts/rating.js @@ -0,0 +1,54 @@ +function RateItem(varParentId, varItemId, varRating) +{ + var elementId = varParentId+"_"+varItemId; + var varOrigClassName = document.getElementById(elementId).className; + + // Retrieve Ajax Feeds + new Ajax.Request('ajax.rate.item.php', + { + method: 'post', + parameters: {parent: varParentId, item: varItemId, rating: varRating, classes: varOrigClassName}, + onSuccess: ReloadRating, + onFailure: RatingError + } + ); + +} + +function ReadNameValuePairs(nameValuePair) +{ + var trimspaces = /(\s)+/; + var returnData = new Array(); + var pairs = nameValuePair.split('&'); + + for (var i = 0; i < pairs.length; i++) + { + var pair = pairs[i].split('='); + returnData[pair[0].replace(trimspaces, "")] = pair[1]; + } + + return returnData; +} + +function ReloadRating(requestObj, jsonObj) +{ + var newlines = /(\r\n|\r|\n)/; + var returnData = ReadNameValuePairs(requestObj.responseText.replace(newlines, "")); + var elementId = returnData['parent']+"_"+returnData['item']; + + document.getElementById(elementId).className = returnData['classes']; + var liObj = document.getElementById(elementId).getElementsByTagName('a'); + + for (var i = 0; i < liObj.length; i++) + { + liObj[i].onclick = function(){}; + } + document.getElementById(returnData['parent']).className = returnData['parentClass']; +} + +function RatingError() +{ + + //alert ("Error"); + +} \ No newline at end of file diff --git a/site/roadshow/gmaps_allroadshow.js b/site/roadshow/gmaps_allroadshow.js new file mode 100644 index 0000000..f74a0a5 --- /dev/null +++ b/site/roadshow/gmaps_allroadshow.js @@ -0,0 +1,22 @@ +<script type="text/javascript" src="http://www.slowtwitch.com/googlemaps/util.js"></script> +<script type="text/javascript"> + function initializeRoadshowMap() { + //alert("mapping!"); + var myLatlng = new google.maps.LatLng(40, -100); + var myOptions = { + zoom: 3, + center: myLatlng, + mapTypeId: google.maps.MapTypeId.ROADMAP + } + var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); + downloadUrl("http://www.slowtwitch.com/googlemaps/roadshow_xml.php", function(data) { + var markers = data.documentElement.getElementsByTagName("marker"); + for (var i = 0; i < markers.length; i++) { + var latlng = new google.maps.LatLng(parseFloat(markers[i].getAttribute("lat")), + parseFloat(markers[i].getAttribute("lng"))); + var marker = new google.maps.Marker({position: latlng, map: map, title: markers[i].getAttribute("name")}); + //alert (latlng); + } + }); + } +</script> \ No newline at end of file diff --git a/site/roadshow/javascript.js b/site/roadshow/javascript.js new file mode 100644 index 0000000..9ca0ce3 --- /dev/null +++ b/site/roadshow/javascript.js @@ -0,0 +1,123 @@ +function validateEmail(emailAddress) { + var match = /^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*$/.test(emailAddress); + return match; +} + + + +function CheckRegisterForm(RegisterForm) + { + if (RegisterForm.username.value == "" ) { alert( "Please choose a username!" ); + RegisterForm.username.focus(); + return false; } + + if (RegisterForm.password.value == "" ) { alert( "Please choose a password!" ); + RegisterForm.password.focus(); + return false; } + + if (RegisterForm.email.value == "" ) { alert( "Please enter your email address." ); + RegisterForm.email.focus(); + return false; } + + checkEmail = RegisterForm.email.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("Your emails address is invalid!."); + RegisterForm.email.focus(); + return false; } + + + // return true; +} + + +function CheckTellForm(tellform) + { + if (tellform.name.value == "" ) { alert( "الرجاء أدخل الإسم بالكامل" ); + tellform.name.focus(); + return false; } + + if (tellform.email.value == "" ) { alert( "أدخل البريد الإلكتروني" ); + tellform.email.focus(); + return false; } + + checkEmail = tellform.email.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("البريد الإلكتروني خطأ!."); + tellform.email.focus(); + return false; } + + + if (tellform.fname.value == "" ) { alert( "أدخل إسم صديقك" ); + tellform.fname.focus(); + return false; } + + + + if (tellform.femail.value == "" ) { alert( "أدخل البريد الالكتروني الخاص بصديقك" ); + tellform.femail.focus(); + return false; } + + checkEmail = tellform.femail.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("البريد الإلكتروني خطأ!."); + tellform.femail.focus(); + return false; } + + + + // return true; +} + + +var newwindow; +function pop(url) +{ + newwindow=window.open(url,'poppage', 'toolbars=0, scrollbars=1, location=0, statusbars=1, menubars=0, resizable=0, width=500, height=400'); + if (window.focus) {newwindow.focus()} +} + + function popimg(url) + { + newwindow=window.open(url,'name','height=500,width=650,left=100,top=100,resizable=yes,scrollbars=yes,toolbar=yes,status=yes'); + if (window.focus) {newwindow.focus()} + } + + + +<!-- ; +var newwindow; +var wheight = 0, wwidth = 0; +function viewimg(url, title, iwidth, iheight, colour) { +var pwidth, pheight; + +if ( !newwindow || newwindow.closed ) { +pwidth=iwidth+30; +pheight=iheight+30; +newwindow=window.open('','htmlname','width=' + pwidth +',height=' +pheight + ',resizable=1,top=50,left=10'); +wheight=iheight; +wwidth=iwidth; +} + +if (wheight!=iheight || wwidth!=iwidth ) { +pwidth=iwidth+30; +pheight=iheight+60; +newwindow.resizeTo(pwidth, pheight); +wheight=iheight; +wwidth=iwidth; +} + +newwindow.document.clear(); +newwindow.focus(); +newwindow.document.writeln('<html> <head> <title>' + title + '<\/title> <\/head> <body bgcolor= \"' + colour + '\"> <center>'); +newwindow.document.writeln('<a titl="إضغط الصورة للإغلاق" href="javascript:window.close();"><img src=' + url + ' border=0></a>'); +newwindow.document.writeln('<\/center> <\/body> <\/html>'); +newwindow.document.close(); +newwindow.focus(); +} + +// Routines to tidy up popup windows when page is left +// Call with an onUnload="tidy5()" in body tag + +function tidy5() { +if (newwindow && !newwindow.closed) { newwindow.close(); } +} diff --git a/site/roadshow/rating/scripts/prototype.js b/site/roadshow/rating/scripts/prototype.js new file mode 100644 index 0000000..5d2100f --- /dev/null +++ b/site/roadshow/rating/scripts/prototype.js @@ -0,0 +1,3271 @@ +/* Prototype JavaScript framework, version 1.5.1 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.1', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + (document.createElement('div').__proto__ !== + document.createElement('form').__proto__) + }, + + ScriptFragment: '<script[^>]*>([\u0001-\uFFFF]*?)</script>', + JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch(type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (object.ownerDocument === document) return; + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + return '{' + results.join(', ') + '}'; + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (hash[key].constructor != Array) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) + return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#<Enumerable:' + this.toArray().inspect() + '>'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + $A = Array.from = function(iterable) { + if (!iterable) return []; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (arguments[i].constructor == Array) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (value.constructor == Array) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#<Hash:{' + this.map(function(pair) { + return pair.map(Object.inspect).join(': '); + }).join(', ') + '}>'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + if (this.options.onCreate) this.options.onCreate(this.transport); + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + var contentType = this.getHeader('Content-type'); + if (contentType && contentType.strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? json.evalJSON() : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (typeof element == 'string') + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(query.snapshotItem(i)); + return results; + }; + + document.getElementsByClassName = function(className, parentElement) { + var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; + return document._getElementsByXPath(q, parentElement); + } + +} else document.getElementsByClassName = function(className, parentElement) { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + var elements = [], child; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) var Element = {}; + +Element.extend = function(element) { + var F = Prototype.BrowserFeatures; + if (!element || !element.tagName || element.nodeType == 3 || + element._extended || F.SpecificElementExtensions || element == window) + return element; + + var methods = {}, tagName = element.tagName, cache = Element.extend.cache, + T = Element.Methods.ByTag; + + // extend methods for all tags (Safari doesn't need this) + if (!F.ElementExtensions) { + Object.extend(methods, Element.Methods), + Object.extend(methods, Element.Methods.Simulated); + } + + // extend methods for specific tags + if (T[tagName]) Object.extend(methods, T[tagName]); + + for (var property in methods) { + var value = methods[property]; + if (typeof value == 'function' && !(property in element)) + element[property] = cache.findOrStore(value); + } + + element._extended = Prototype.emptyFunction; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + hide: function(element) { + $(element).style.display = 'none'; + return element; + }, + + show: function(element) { + $(element).style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: function(element, html) { + html = typeof html == 'undefined' ? '' : html.toString(); + $(element).innerHTML = html.stripScripts(); + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + replace: function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + var range = element.ownerDocument.createRange(); + range.selectNodeContents(element); + element.parentNode.replaceChild( + range.createContextualFragment(html.stripScripts()), element); + } + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (typeof selector == 'string') + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = element.ancestors(); + return expression ? Selector.findElement(ancestors, expression, index) : + ancestors[index || 0]; + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + var descendants = element.descendants(); + return expression ? Selector.findElement(descendants, expression, index) : + descendants[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = element.previousSiblings(); + return expression ? Selector.findElement(previousSiblings, expression, index) : + previousSiblings[index || 0]; + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = element.nextSiblings(); + return expression ? Selector.findElement(nextSiblings, expression, index) : + nextSiblings[index || 0]; + }, + + getElementsBySelector: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + getElementsByClassName: function(element, className) { + return document.getElementsByClassName(className, element); + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + if (!element.attributes) return null; + var t = Element._attributeTranslations; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + var attribute = element.attributes[name]; + return attribute ? attribute.nodeValue : null; + } + return element.getAttribute(name); + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + if (elementClassName.length == 0) return false; + if (elementClassName == className || + elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) + return true; + return false; + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).add(className); + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).remove(className); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className); + return element; + }, + + observe: function() { + Event.observe.apply(Event, arguments); + return $A(arguments).first(); + }, + + stopObserving: function() { + Event.stopObserving.apply(Event, arguments); + return $A(arguments).first(); + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + while (element = element.parentNode) + if (element == ancestor) return true; + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Position.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + style = style == 'float' ? 'cssFloat' : style.camelize(); + var value = element.style[style]; + if (!value) { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, + + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, + + setStyle: function(element, styles, camelized) { + element = $(element); + var elementStyle = element.style; + + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]) + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : + (camelized ? property : property.camelize())] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = $(element).getStyle('display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + // All *Width and *Height properties give 0 on elements with display none, + // so enable the element temporarily + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (window.opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = element.style.overflow || 'auto'; + if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + } +}; + +Object.extend(Element.Methods, { + childOf: Element.Methods.descendantOf, + childElements: Element.Methods.immediateDescendants +}); + +if (Prototype.Browser.Opera) { + Element.Methods._getStyle = Element.Methods.getStyle; + Element.Methods.getStyle = function(element, style) { + switch(style) { + case 'left': + case 'top': + case 'right': + case 'bottom': + if (Element._getStyle(element, 'position') == 'static') return null; + default: return Element._getStyle(element, style); + } + }; +} +else if (Prototype.Browser.IE) { + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; + + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset'+style.capitalize()] + 'px'; + return null; + } + return value; + }; + + Element.Methods.setOpacity = function(element, value) { + element = $(element); + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + style.filter = filter.replace(/alpha\([^\)]*\)/gi,''); + return element; + } else if (value < 0.00001) value = 0; + style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + // IE is missing .innerHTML support for TABLE-related elements + Element.Methods.update = function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + var tagName = element.tagName.toUpperCase(); + if (['THEAD','TBODY','TR','TD'].include(tagName)) { + var div = document.createElement('div'); + switch (tagName) { + case 'THEAD': + case 'TBODY': + div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>'; + depth = 2; + break; + case 'TR': + div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>'; + depth = 3; + break; + case 'TD': + div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>'; + depth = 4; + } + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + depth.times(function() { div = div.firstChild }); + $A(div.childNodes).each(function(node) { element.appendChild(node) }); + } else { + element.innerHTML = html.stripScripts(); + } + setTimeout(function() { html.evalScripts() }, 10); + return element; + } +} +else if (Prototype.Browser.Gecko) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +Element._attributeTranslations = { + names: { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } + } +}; + +(function() { + Object.extend(this, { + href: this._getAttr, + src: this._getAttr, + type: this._getAttr, + disabled: this._flag, + checked: this._flag, + readonly: this._flag, + multiple: this._flag + }); +}).call(Element._attributeTranslations.values); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + var t = Element._attributeTranslations, node; + attribute = t.names[attribute] || attribute; + node = $(element).getAttributeNode(attribute); + return node && node.specified; + } +}; + +Element.Methods.ByTag = {}; + +Object.extend(Element, Element.Methods); + +if (!Prototype.BrowserFeatures.ElementExtensions && + document.createElement('div').__proto__) { + window.HTMLElement = {}; + window.HTMLElement.prototype = document.createElement('div').__proto__; + Prototype.BrowserFeatures.ElementExtensions = true; +} + +Element.hasAttribute = function(element, attribute) { + if (element.hasAttribute) return element.hasAttribute(attribute); + return Element.Methods.Simulated.hasAttribute(element, attribute); +}; + +Element.addMethods = function(methods) { + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || {}); + else { + if (tagName.constructor == Array) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = {}; + Object.extend(Element.Methods.ByTag[tagName], methods); + } + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + var cache = Element.extend.cache; + for (var property in methods) { + var value = methods[property]; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = cache.findOrStore(value); + } + } + + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + window[klass] = {}; + window[klass].prototype = document.createElement(tagName).__proto__; + return window[klass]; + } + + if (F.ElementExtensions) { + copy(Element.Methods, HTMLElement.prototype); + copy(Element.Methods.Simulated, HTMLElement.prototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (typeof klass == "undefined") continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; +}; + +var Toggle = { display: Element.toggle }; + +/*--------------------------------------------------------------------------*/ + +Abstract.Insertion = function(adjacency) { + this.adjacency = adjacency; +} + +Abstract.Insertion.prototype = { + initialize: function(element, content) { + this.element = $(element); + this.content = content.stripScripts(); + + if (this.adjacency && this.element.insertAdjacentHTML) { + try { + this.element.insertAdjacentHTML(this.adjacency, this.content); + } catch (e) { + var tagName = this.element.tagName.toUpperCase(); + if (['TBODY', 'TR'].include(tagName)) { + this.insertContent(this.contentFromAnonymousTable()); + } else { + throw e; + } + } + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.insertContent([this.range.createContextualFragment(this.content)]); + } + + setTimeout(function() {content.evalScripts()}, 10); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; + return $A(div.childNodes[0].childNodes[0].childNodes); + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, this.element); + }).bind(this)); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function(fragments) { + fragments.reverse(false).each((function(fragment) { + this.element.insertBefore(fragment, this.element.firstChild); + }).bind(this)); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.appendChild(fragment); + }).bind(this)); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, + this.element.nextSibling); + }).bind(this)); + } +}); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; return; + } + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + return this.findElements(document).include(element); + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#<Selector:" + this.expression.inspect() + ">"; + } +}; + +Object.extend(Selector, { + _cache: {}, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (typeof h === 'function') return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!nodes && root == document) return targetNode ? [targetNode] : []; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != null) { + if (key in result) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || {}); + + var params = options.parameters; + options.parameters = form.serialize(true); + + if (params) { + if (typeof params == 'string') params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(form.readAttribute('action'), options); + } +} + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type))) + element.select(); + } catch (e) {} + return element; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +} + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return $(event.target || event.srcElement); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (Prototype.Browser.IE) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (Prototype.Browser.WebKit) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); \ No newline at end of file diff --git a/site/roadshow/rating/scripts/rating.js b/site/roadshow/rating/scripts/rating.js new file mode 100644 index 0000000..1ac8b0a --- /dev/null +++ b/site/roadshow/rating/scripts/rating.js @@ -0,0 +1,54 @@ +function RateItem(varParentId, varItemId, varRating) +{ + var elementId = varParentId+"_"+varItemId; + var varOrigClassName = document.getElementById(elementId).className; + + // Retrieve Ajax Feeds + new Ajax.Request('ajax.rate.item.php', + { + method: 'post', + parameters: {parent: varParentId, item: varItemId, rating: varRating, classes: varOrigClassName}, + onSuccess: ReloadRating, + onFailure: RatingError + } + ); + +} + +function ReadNameValuePairs(nameValuePair) +{ + var trimspaces = /(\s)+/; + var returnData = new Array(); + var pairs = nameValuePair.split('&'); + + for (var i = 0; i < pairs.length; i++) + { + var pair = pairs[i].split('='); + returnData[pair[0].replace(trimspaces, "")] = pair[1]; + } + + return returnData; +} + +function ReloadRating(requestObj, jsonObj) +{ + var newlines = /(\r\n|\r|\n)/; + var returnData = ReadNameValuePairs(requestObj.responseText.replace(newlines, "")); + var elementId = returnData['parent']+"_"+returnData['item']; + + document.getElementById(elementId).className = returnData['classes']; + var liObj = document.getElementById(elementId).getElementsByTagName('a'); + + for (var i = 0; i < liObj.length; i++) + { + liObj[i].onclick = function(){}; + } + document.getElementById(returnData['parent']).className = returnData['parentClass']; +} + +function RatingError() +{ + + //alert ("Error"); + +} \ No newline at end of file diff --git a/site/runshops/javascript.js b/site/runshops/javascript.js new file mode 100644 index 0000000..9ca0ce3 --- /dev/null +++ b/site/runshops/javascript.js @@ -0,0 +1,123 @@ +function validateEmail(emailAddress) { + var match = /^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*$/.test(emailAddress); + return match; +} + + + +function CheckRegisterForm(RegisterForm) + { + if (RegisterForm.username.value == "" ) { alert( "Please choose a username!" ); + RegisterForm.username.focus(); + return false; } + + if (RegisterForm.password.value == "" ) { alert( "Please choose a password!" ); + RegisterForm.password.focus(); + return false; } + + if (RegisterForm.email.value == "" ) { alert( "Please enter your email address." ); + RegisterForm.email.focus(); + return false; } + + checkEmail = RegisterForm.email.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("Your emails address is invalid!."); + RegisterForm.email.focus(); + return false; } + + + // return true; +} + + +function CheckTellForm(tellform) + { + if (tellform.name.value == "" ) { alert( "الرجاء أدخل الإسم بالكامل" ); + tellform.name.focus(); + return false; } + + if (tellform.email.value == "" ) { alert( "أدخل البريد الإلكتروني" ); + tellform.email.focus(); + return false; } + + checkEmail = tellform.email.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("البريد الإلكتروني خطأ!."); + tellform.email.focus(); + return false; } + + + if (tellform.fname.value == "" ) { alert( "أدخل إسم صديقك" ); + tellform.fname.focus(); + return false; } + + + + if (tellform.femail.value == "" ) { alert( "أدخل البريد الالكتروني الخاص بصديقك" ); + tellform.femail.focus(); + return false; } + + checkEmail = tellform.femail.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("البريد الإلكتروني خطأ!."); + tellform.femail.focus(); + return false; } + + + + // return true; +} + + +var newwindow; +function pop(url) +{ + newwindow=window.open(url,'poppage', 'toolbars=0, scrollbars=1, location=0, statusbars=1, menubars=0, resizable=0, width=500, height=400'); + if (window.focus) {newwindow.focus()} +} + + function popimg(url) + { + newwindow=window.open(url,'name','height=500,width=650,left=100,top=100,resizable=yes,scrollbars=yes,toolbar=yes,status=yes'); + if (window.focus) {newwindow.focus()} + } + + + +<!-- ; +var newwindow; +var wheight = 0, wwidth = 0; +function viewimg(url, title, iwidth, iheight, colour) { +var pwidth, pheight; + +if ( !newwindow || newwindow.closed ) { +pwidth=iwidth+30; +pheight=iheight+30; +newwindow=window.open('','htmlname','width=' + pwidth +',height=' +pheight + ',resizable=1,top=50,left=10'); +wheight=iheight; +wwidth=iwidth; +} + +if (wheight!=iheight || wwidth!=iwidth ) { +pwidth=iwidth+30; +pheight=iheight+60; +newwindow.resizeTo(pwidth, pheight); +wheight=iheight; +wwidth=iwidth; +} + +newwindow.document.clear(); +newwindow.focus(); +newwindow.document.writeln('<html> <head> <title>' + title + '<\/title> <\/head> <body bgcolor= \"' + colour + '\"> <center>'); +newwindow.document.writeln('<a titl="إضغط الصورة للإغلاق" href="javascript:window.close();"><img src=' + url + ' border=0></a>'); +newwindow.document.writeln('<\/center> <\/body> <\/html>'); +newwindow.document.close(); +newwindow.focus(); +} + +// Routines to tidy up popup windows when page is left +// Call with an onUnload="tidy5()" in body tag + +function tidy5() { +if (newwindow && !newwindow.closed) { newwindow.close(); } +} diff --git a/site/runshops/rating/scripts/prototype.js b/site/runshops/rating/scripts/prototype.js new file mode 100644 index 0000000..5d2100f --- /dev/null +++ b/site/runshops/rating/scripts/prototype.js @@ -0,0 +1,3271 @@ +/* Prototype JavaScript framework, version 1.5.1 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.1', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + (document.createElement('div').__proto__ !== + document.createElement('form').__proto__) + }, + + ScriptFragment: '<script[^>]*>([\u0001-\uFFFF]*?)</script>', + JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch(type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (object.ownerDocument === document) return; + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + return '{' + results.join(', ') + '}'; + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (hash[key].constructor != Array) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) + return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#<Enumerable:' + this.toArray().inspect() + '>'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + $A = Array.from = function(iterable) { + if (!iterable) return []; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (arguments[i].constructor == Array) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (value.constructor == Array) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#<Hash:{' + this.map(function(pair) { + return pair.map(Object.inspect).join(': '); + }).join(', ') + '}>'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + if (this.options.onCreate) this.options.onCreate(this.transport); + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + var contentType = this.getHeader('Content-type'); + if (contentType && contentType.strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? json.evalJSON() : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (typeof element == 'string') + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(query.snapshotItem(i)); + return results; + }; + + document.getElementsByClassName = function(className, parentElement) { + var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; + return document._getElementsByXPath(q, parentElement); + } + +} else document.getElementsByClassName = function(className, parentElement) { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + var elements = [], child; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) var Element = {}; + +Element.extend = function(element) { + var F = Prototype.BrowserFeatures; + if (!element || !element.tagName || element.nodeType == 3 || + element._extended || F.SpecificElementExtensions || element == window) + return element; + + var methods = {}, tagName = element.tagName, cache = Element.extend.cache, + T = Element.Methods.ByTag; + + // extend methods for all tags (Safari doesn't need this) + if (!F.ElementExtensions) { + Object.extend(methods, Element.Methods), + Object.extend(methods, Element.Methods.Simulated); + } + + // extend methods for specific tags + if (T[tagName]) Object.extend(methods, T[tagName]); + + for (var property in methods) { + var value = methods[property]; + if (typeof value == 'function' && !(property in element)) + element[property] = cache.findOrStore(value); + } + + element._extended = Prototype.emptyFunction; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + hide: function(element) { + $(element).style.display = 'none'; + return element; + }, + + show: function(element) { + $(element).style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: function(element, html) { + html = typeof html == 'undefined' ? '' : html.toString(); + $(element).innerHTML = html.stripScripts(); + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + replace: function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + var range = element.ownerDocument.createRange(); + range.selectNodeContents(element); + element.parentNode.replaceChild( + range.createContextualFragment(html.stripScripts()), element); + } + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (typeof selector == 'string') + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = element.ancestors(); + return expression ? Selector.findElement(ancestors, expression, index) : + ancestors[index || 0]; + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + var descendants = element.descendants(); + return expression ? Selector.findElement(descendants, expression, index) : + descendants[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = element.previousSiblings(); + return expression ? Selector.findElement(previousSiblings, expression, index) : + previousSiblings[index || 0]; + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = element.nextSiblings(); + return expression ? Selector.findElement(nextSiblings, expression, index) : + nextSiblings[index || 0]; + }, + + getElementsBySelector: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + getElementsByClassName: function(element, className) { + return document.getElementsByClassName(className, element); + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + if (!element.attributes) return null; + var t = Element._attributeTranslations; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + var attribute = element.attributes[name]; + return attribute ? attribute.nodeValue : null; + } + return element.getAttribute(name); + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + if (elementClassName.length == 0) return false; + if (elementClassName == className || + elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) + return true; + return false; + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).add(className); + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).remove(className); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className); + return element; + }, + + observe: function() { + Event.observe.apply(Event, arguments); + return $A(arguments).first(); + }, + + stopObserving: function() { + Event.stopObserving.apply(Event, arguments); + return $A(arguments).first(); + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + while (element = element.parentNode) + if (element == ancestor) return true; + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Position.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + style = style == 'float' ? 'cssFloat' : style.camelize(); + var value = element.style[style]; + if (!value) { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, + + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, + + setStyle: function(element, styles, camelized) { + element = $(element); + var elementStyle = element.style; + + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]) + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : + (camelized ? property : property.camelize())] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = $(element).getStyle('display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + // All *Width and *Height properties give 0 on elements with display none, + // so enable the element temporarily + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (window.opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = element.style.overflow || 'auto'; + if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + } +}; + +Object.extend(Element.Methods, { + childOf: Element.Methods.descendantOf, + childElements: Element.Methods.immediateDescendants +}); + +if (Prototype.Browser.Opera) { + Element.Methods._getStyle = Element.Methods.getStyle; + Element.Methods.getStyle = function(element, style) { + switch(style) { + case 'left': + case 'top': + case 'right': + case 'bottom': + if (Element._getStyle(element, 'position') == 'static') return null; + default: return Element._getStyle(element, style); + } + }; +} +else if (Prototype.Browser.IE) { + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; + + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset'+style.capitalize()] + 'px'; + return null; + } + return value; + }; + + Element.Methods.setOpacity = function(element, value) { + element = $(element); + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + style.filter = filter.replace(/alpha\([^\)]*\)/gi,''); + return element; + } else if (value < 0.00001) value = 0; + style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + // IE is missing .innerHTML support for TABLE-related elements + Element.Methods.update = function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + var tagName = element.tagName.toUpperCase(); + if (['THEAD','TBODY','TR','TD'].include(tagName)) { + var div = document.createElement('div'); + switch (tagName) { + case 'THEAD': + case 'TBODY': + div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>'; + depth = 2; + break; + case 'TR': + div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>'; + depth = 3; + break; + case 'TD': + div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>'; + depth = 4; + } + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + depth.times(function() { div = div.firstChild }); + $A(div.childNodes).each(function(node) { element.appendChild(node) }); + } else { + element.innerHTML = html.stripScripts(); + } + setTimeout(function() { html.evalScripts() }, 10); + return element; + } +} +else if (Prototype.Browser.Gecko) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +Element._attributeTranslations = { + names: { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } + } +}; + +(function() { + Object.extend(this, { + href: this._getAttr, + src: this._getAttr, + type: this._getAttr, + disabled: this._flag, + checked: this._flag, + readonly: this._flag, + multiple: this._flag + }); +}).call(Element._attributeTranslations.values); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + var t = Element._attributeTranslations, node; + attribute = t.names[attribute] || attribute; + node = $(element).getAttributeNode(attribute); + return node && node.specified; + } +}; + +Element.Methods.ByTag = {}; + +Object.extend(Element, Element.Methods); + +if (!Prototype.BrowserFeatures.ElementExtensions && + document.createElement('div').__proto__) { + window.HTMLElement = {}; + window.HTMLElement.prototype = document.createElement('div').__proto__; + Prototype.BrowserFeatures.ElementExtensions = true; +} + +Element.hasAttribute = function(element, attribute) { + if (element.hasAttribute) return element.hasAttribute(attribute); + return Element.Methods.Simulated.hasAttribute(element, attribute); +}; + +Element.addMethods = function(methods) { + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || {}); + else { + if (tagName.constructor == Array) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = {}; + Object.extend(Element.Methods.ByTag[tagName], methods); + } + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + var cache = Element.extend.cache; + for (var property in methods) { + var value = methods[property]; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = cache.findOrStore(value); + } + } + + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + window[klass] = {}; + window[klass].prototype = document.createElement(tagName).__proto__; + return window[klass]; + } + + if (F.ElementExtensions) { + copy(Element.Methods, HTMLElement.prototype); + copy(Element.Methods.Simulated, HTMLElement.prototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (typeof klass == "undefined") continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; +}; + +var Toggle = { display: Element.toggle }; + +/*--------------------------------------------------------------------------*/ + +Abstract.Insertion = function(adjacency) { + this.adjacency = adjacency; +} + +Abstract.Insertion.prototype = { + initialize: function(element, content) { + this.element = $(element); + this.content = content.stripScripts(); + + if (this.adjacency && this.element.insertAdjacentHTML) { + try { + this.element.insertAdjacentHTML(this.adjacency, this.content); + } catch (e) { + var tagName = this.element.tagName.toUpperCase(); + if (['TBODY', 'TR'].include(tagName)) { + this.insertContent(this.contentFromAnonymousTable()); + } else { + throw e; + } + } + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.insertContent([this.range.createContextualFragment(this.content)]); + } + + setTimeout(function() {content.evalScripts()}, 10); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; + return $A(div.childNodes[0].childNodes[0].childNodes); + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, this.element); + }).bind(this)); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function(fragments) { + fragments.reverse(false).each((function(fragment) { + this.element.insertBefore(fragment, this.element.firstChild); + }).bind(this)); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.appendChild(fragment); + }).bind(this)); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, + this.element.nextSibling); + }).bind(this)); + } +}); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; return; + } + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + return this.findElements(document).include(element); + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#<Selector:" + this.expression.inspect() + ">"; + } +}; + +Object.extend(Selector, { + _cache: {}, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (typeof h === 'function') return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!nodes && root == document) return targetNode ? [targetNode] : []; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != null) { + if (key in result) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || {}); + + var params = options.parameters; + options.parameters = form.serialize(true); + + if (params) { + if (typeof params == 'string') params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(form.readAttribute('action'), options); + } +} + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type))) + element.select(); + } catch (e) {} + return element; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +} + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return $(event.target || event.srcElement); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (Prototype.Browser.IE) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (Prototype.Browser.WebKit) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); \ No newline at end of file diff --git a/site/runshops/rating/scripts/rating.js b/site/runshops/rating/scripts/rating.js new file mode 100644 index 0000000..1ac8b0a --- /dev/null +++ b/site/runshops/rating/scripts/rating.js @@ -0,0 +1,54 @@ +function RateItem(varParentId, varItemId, varRating) +{ + var elementId = varParentId+"_"+varItemId; + var varOrigClassName = document.getElementById(elementId).className; + + // Retrieve Ajax Feeds + new Ajax.Request('ajax.rate.item.php', + { + method: 'post', + parameters: {parent: varParentId, item: varItemId, rating: varRating, classes: varOrigClassName}, + onSuccess: ReloadRating, + onFailure: RatingError + } + ); + +} + +function ReadNameValuePairs(nameValuePair) +{ + var trimspaces = /(\s)+/; + var returnData = new Array(); + var pairs = nameValuePair.split('&'); + + for (var i = 0; i < pairs.length; i++) + { + var pair = pairs[i].split('='); + returnData[pair[0].replace(trimspaces, "")] = pair[1]; + } + + return returnData; +} + +function ReloadRating(requestObj, jsonObj) +{ + var newlines = /(\r\n|\r|\n)/; + var returnData = ReadNameValuePairs(requestObj.responseText.replace(newlines, "")); + var elementId = returnData['parent']+"_"+returnData['item']; + + document.getElementById(elementId).className = returnData['classes']; + var liObj = document.getElementById(elementId).getElementsByTagName('a'); + + for (var i = 0; i < liObj.length; i++) + { + liObj[i].onclick = function(){}; + } + document.getElementById(returnData['parent']).className = returnData['parentClass']; +} + +function RatingError() +{ + + //alert ("Error"); + +} \ No newline at end of file diff --git a/site/triclubs/class/rating/scripts/prototype.js b/site/triclubs/class/rating/scripts/prototype.js new file mode 100644 index 0000000..5d2100f --- /dev/null +++ b/site/triclubs/class/rating/scripts/prototype.js @@ -0,0 +1,3271 @@ +/* Prototype JavaScript framework, version 1.5.1 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.1', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + (document.createElement('div').__proto__ !== + document.createElement('form').__proto__) + }, + + ScriptFragment: '<script[^>]*>([\u0001-\uFFFF]*?)</script>', + JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch(type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (object.ownerDocument === document) return; + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + return '{' + results.join(', ') + '}'; + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (hash[key].constructor != Array) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) + return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#<Enumerable:' + this.toArray().inspect() + '>'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + $A = Array.from = function(iterable) { + if (!iterable) return []; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (arguments[i].constructor == Array) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (value.constructor == Array) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#<Hash:{' + this.map(function(pair) { + return pair.map(Object.inspect).join(': '); + }).join(', ') + '}>'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + if (this.options.onCreate) this.options.onCreate(this.transport); + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + var contentType = this.getHeader('Content-type'); + if (contentType && contentType.strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? json.evalJSON() : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (typeof element == 'string') + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(query.snapshotItem(i)); + return results; + }; + + document.getElementsByClassName = function(className, parentElement) { + var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; + return document._getElementsByXPath(q, parentElement); + } + +} else document.getElementsByClassName = function(className, parentElement) { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + var elements = [], child; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) var Element = {}; + +Element.extend = function(element) { + var F = Prototype.BrowserFeatures; + if (!element || !element.tagName || element.nodeType == 3 || + element._extended || F.SpecificElementExtensions || element == window) + return element; + + var methods = {}, tagName = element.tagName, cache = Element.extend.cache, + T = Element.Methods.ByTag; + + // extend methods for all tags (Safari doesn't need this) + if (!F.ElementExtensions) { + Object.extend(methods, Element.Methods), + Object.extend(methods, Element.Methods.Simulated); + } + + // extend methods for specific tags + if (T[tagName]) Object.extend(methods, T[tagName]); + + for (var property in methods) { + var value = methods[property]; + if (typeof value == 'function' && !(property in element)) + element[property] = cache.findOrStore(value); + } + + element._extended = Prototype.emptyFunction; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + hide: function(element) { + $(element).style.display = 'none'; + return element; + }, + + show: function(element) { + $(element).style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: function(element, html) { + html = typeof html == 'undefined' ? '' : html.toString(); + $(element).innerHTML = html.stripScripts(); + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + replace: function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + var range = element.ownerDocument.createRange(); + range.selectNodeContents(element); + element.parentNode.replaceChild( + range.createContextualFragment(html.stripScripts()), element); + } + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (typeof selector == 'string') + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = element.ancestors(); + return expression ? Selector.findElement(ancestors, expression, index) : + ancestors[index || 0]; + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + var descendants = element.descendants(); + return expression ? Selector.findElement(descendants, expression, index) : + descendants[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = element.previousSiblings(); + return expression ? Selector.findElement(previousSiblings, expression, index) : + previousSiblings[index || 0]; + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = element.nextSiblings(); + return expression ? Selector.findElement(nextSiblings, expression, index) : + nextSiblings[index || 0]; + }, + + getElementsBySelector: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + getElementsByClassName: function(element, className) { + return document.getElementsByClassName(className, element); + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + if (!element.attributes) return null; + var t = Element._attributeTranslations; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + var attribute = element.attributes[name]; + return attribute ? attribute.nodeValue : null; + } + return element.getAttribute(name); + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + if (elementClassName.length == 0) return false; + if (elementClassName == className || + elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) + return true; + return false; + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).add(className); + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).remove(className); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className); + return element; + }, + + observe: function() { + Event.observe.apply(Event, arguments); + return $A(arguments).first(); + }, + + stopObserving: function() { + Event.stopObserving.apply(Event, arguments); + return $A(arguments).first(); + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + while (element = element.parentNode) + if (element == ancestor) return true; + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Position.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + style = style == 'float' ? 'cssFloat' : style.camelize(); + var value = element.style[style]; + if (!value) { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, + + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, + + setStyle: function(element, styles, camelized) { + element = $(element); + var elementStyle = element.style; + + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]) + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : + (camelized ? property : property.camelize())] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = $(element).getStyle('display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + // All *Width and *Height properties give 0 on elements with display none, + // so enable the element temporarily + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (window.opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = element.style.overflow || 'auto'; + if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + } +}; + +Object.extend(Element.Methods, { + childOf: Element.Methods.descendantOf, + childElements: Element.Methods.immediateDescendants +}); + +if (Prototype.Browser.Opera) { + Element.Methods._getStyle = Element.Methods.getStyle; + Element.Methods.getStyle = function(element, style) { + switch(style) { + case 'left': + case 'top': + case 'right': + case 'bottom': + if (Element._getStyle(element, 'position') == 'static') return null; + default: return Element._getStyle(element, style); + } + }; +} +else if (Prototype.Browser.IE) { + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; + + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset'+style.capitalize()] + 'px'; + return null; + } + return value; + }; + + Element.Methods.setOpacity = function(element, value) { + element = $(element); + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + style.filter = filter.replace(/alpha\([^\)]*\)/gi,''); + return element; + } else if (value < 0.00001) value = 0; + style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + // IE is missing .innerHTML support for TABLE-related elements + Element.Methods.update = function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + var tagName = element.tagName.toUpperCase(); + if (['THEAD','TBODY','TR','TD'].include(tagName)) { + var div = document.createElement('div'); + switch (tagName) { + case 'THEAD': + case 'TBODY': + div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>'; + depth = 2; + break; + case 'TR': + div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>'; + depth = 3; + break; + case 'TD': + div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>'; + depth = 4; + } + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + depth.times(function() { div = div.firstChild }); + $A(div.childNodes).each(function(node) { element.appendChild(node) }); + } else { + element.innerHTML = html.stripScripts(); + } + setTimeout(function() { html.evalScripts() }, 10); + return element; + } +} +else if (Prototype.Browser.Gecko) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +Element._attributeTranslations = { + names: { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } + } +}; + +(function() { + Object.extend(this, { + href: this._getAttr, + src: this._getAttr, + type: this._getAttr, + disabled: this._flag, + checked: this._flag, + readonly: this._flag, + multiple: this._flag + }); +}).call(Element._attributeTranslations.values); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + var t = Element._attributeTranslations, node; + attribute = t.names[attribute] || attribute; + node = $(element).getAttributeNode(attribute); + return node && node.specified; + } +}; + +Element.Methods.ByTag = {}; + +Object.extend(Element, Element.Methods); + +if (!Prototype.BrowserFeatures.ElementExtensions && + document.createElement('div').__proto__) { + window.HTMLElement = {}; + window.HTMLElement.prototype = document.createElement('div').__proto__; + Prototype.BrowserFeatures.ElementExtensions = true; +} + +Element.hasAttribute = function(element, attribute) { + if (element.hasAttribute) return element.hasAttribute(attribute); + return Element.Methods.Simulated.hasAttribute(element, attribute); +}; + +Element.addMethods = function(methods) { + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || {}); + else { + if (tagName.constructor == Array) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = {}; + Object.extend(Element.Methods.ByTag[tagName], methods); + } + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + var cache = Element.extend.cache; + for (var property in methods) { + var value = methods[property]; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = cache.findOrStore(value); + } + } + + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + window[klass] = {}; + window[klass].prototype = document.createElement(tagName).__proto__; + return window[klass]; + } + + if (F.ElementExtensions) { + copy(Element.Methods, HTMLElement.prototype); + copy(Element.Methods.Simulated, HTMLElement.prototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (typeof klass == "undefined") continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; +}; + +var Toggle = { display: Element.toggle }; + +/*--------------------------------------------------------------------------*/ + +Abstract.Insertion = function(adjacency) { + this.adjacency = adjacency; +} + +Abstract.Insertion.prototype = { + initialize: function(element, content) { + this.element = $(element); + this.content = content.stripScripts(); + + if (this.adjacency && this.element.insertAdjacentHTML) { + try { + this.element.insertAdjacentHTML(this.adjacency, this.content); + } catch (e) { + var tagName = this.element.tagName.toUpperCase(); + if (['TBODY', 'TR'].include(tagName)) { + this.insertContent(this.contentFromAnonymousTable()); + } else { + throw e; + } + } + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.insertContent([this.range.createContextualFragment(this.content)]); + } + + setTimeout(function() {content.evalScripts()}, 10); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; + return $A(div.childNodes[0].childNodes[0].childNodes); + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, this.element); + }).bind(this)); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function(fragments) { + fragments.reverse(false).each((function(fragment) { + this.element.insertBefore(fragment, this.element.firstChild); + }).bind(this)); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.appendChild(fragment); + }).bind(this)); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, + this.element.nextSibling); + }).bind(this)); + } +}); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; return; + } + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + return this.findElements(document).include(element); + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#<Selector:" + this.expression.inspect() + ">"; + } +}; + +Object.extend(Selector, { + _cache: {}, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (typeof h === 'function') return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!nodes && root == document) return targetNode ? [targetNode] : []; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != null) { + if (key in result) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || {}); + + var params = options.parameters; + options.parameters = form.serialize(true); + + if (params) { + if (typeof params == 'string') params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(form.readAttribute('action'), options); + } +} + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type))) + element.select(); + } catch (e) {} + return element; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +} + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return $(event.target || event.srcElement); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (Prototype.Browser.IE) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (Prototype.Browser.WebKit) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); \ No newline at end of file diff --git a/site/triclubs/class/rating/scripts/rating.js b/site/triclubs/class/rating/scripts/rating.js new file mode 100644 index 0000000..1ac8b0a --- /dev/null +++ b/site/triclubs/class/rating/scripts/rating.js @@ -0,0 +1,54 @@ +function RateItem(varParentId, varItemId, varRating) +{ + var elementId = varParentId+"_"+varItemId; + var varOrigClassName = document.getElementById(elementId).className; + + // Retrieve Ajax Feeds + new Ajax.Request('ajax.rate.item.php', + { + method: 'post', + parameters: {parent: varParentId, item: varItemId, rating: varRating, classes: varOrigClassName}, + onSuccess: ReloadRating, + onFailure: RatingError + } + ); + +} + +function ReadNameValuePairs(nameValuePair) +{ + var trimspaces = /(\s)+/; + var returnData = new Array(); + var pairs = nameValuePair.split('&'); + + for (var i = 0; i < pairs.length; i++) + { + var pair = pairs[i].split('='); + returnData[pair[0].replace(trimspaces, "")] = pair[1]; + } + + return returnData; +} + +function ReloadRating(requestObj, jsonObj) +{ + var newlines = /(\r\n|\r|\n)/; + var returnData = ReadNameValuePairs(requestObj.responseText.replace(newlines, "")); + var elementId = returnData['parent']+"_"+returnData['item']; + + document.getElementById(elementId).className = returnData['classes']; + var liObj = document.getElementById(elementId).getElementsByTagName('a'); + + for (var i = 0; i < liObj.length; i++) + { + liObj[i].onclick = function(){}; + } + document.getElementById(returnData['parent']).className = returnData['parentClass']; +} + +function RatingError() +{ + + //alert ("Error"); + +} \ No newline at end of file diff --git a/site/triclubs/javascript.js b/site/triclubs/javascript.js new file mode 100644 index 0000000..9ca0ce3 --- /dev/null +++ b/site/triclubs/javascript.js @@ -0,0 +1,123 @@ +function validateEmail(emailAddress) { + var match = /^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*$/.test(emailAddress); + return match; +} + + + +function CheckRegisterForm(RegisterForm) + { + if (RegisterForm.username.value == "" ) { alert( "Please choose a username!" ); + RegisterForm.username.focus(); + return false; } + + if (RegisterForm.password.value == "" ) { alert( "Please choose a password!" ); + RegisterForm.password.focus(); + return false; } + + if (RegisterForm.email.value == "" ) { alert( "Please enter your email address." ); + RegisterForm.email.focus(); + return false; } + + checkEmail = RegisterForm.email.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("Your emails address is invalid!."); + RegisterForm.email.focus(); + return false; } + + + // return true; +} + + +function CheckTellForm(tellform) + { + if (tellform.name.value == "" ) { alert( "الرجاء أدخل الإسم بالكامل" ); + tellform.name.focus(); + return false; } + + if (tellform.email.value == "" ) { alert( "أدخل البريد الإلكتروني" ); + tellform.email.focus(); + return false; } + + checkEmail = tellform.email.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("البريد الإلكتروني خطأ!."); + tellform.email.focus(); + return false; } + + + if (tellform.fname.value == "" ) { alert( "أدخل إسم صديقك" ); + tellform.fname.focus(); + return false; } + + + + if (tellform.femail.value == "" ) { alert( "أدخل البريد الالكتروني الخاص بصديقك" ); + tellform.femail.focus(); + return false; } + + checkEmail = tellform.femail.value + if ((checkEmail.indexOf('@') < 0) || ((checkEmail.charAt(checkEmail.length-4) != '.') && (checkEmail.charAt(checkEmail.length-3) != '.'))) + {alert("البريد الإلكتروني خطأ!."); + tellform.femail.focus(); + return false; } + + + + // return true; +} + + +var newwindow; +function pop(url) +{ + newwindow=window.open(url,'poppage', 'toolbars=0, scrollbars=1, location=0, statusbars=1, menubars=0, resizable=0, width=500, height=400'); + if (window.focus) {newwindow.focus()} +} + + function popimg(url) + { + newwindow=window.open(url,'name','height=500,width=650,left=100,top=100,resizable=yes,scrollbars=yes,toolbar=yes,status=yes'); + if (window.focus) {newwindow.focus()} + } + + + +<!-- ; +var newwindow; +var wheight = 0, wwidth = 0; +function viewimg(url, title, iwidth, iheight, colour) { +var pwidth, pheight; + +if ( !newwindow || newwindow.closed ) { +pwidth=iwidth+30; +pheight=iheight+30; +newwindow=window.open('','htmlname','width=' + pwidth +',height=' +pheight + ',resizable=1,top=50,left=10'); +wheight=iheight; +wwidth=iwidth; +} + +if (wheight!=iheight || wwidth!=iwidth ) { +pwidth=iwidth+30; +pheight=iheight+60; +newwindow.resizeTo(pwidth, pheight); +wheight=iheight; +wwidth=iwidth; +} + +newwindow.document.clear(); +newwindow.focus(); +newwindow.document.writeln('<html> <head> <title>' + title + '<\/title> <\/head> <body bgcolor= \"' + colour + '\"> <center>'); +newwindow.document.writeln('<a titl="إضغط الصورة للإغلاق" href="javascript:window.close();"><img src=' + url + ' border=0></a>'); +newwindow.document.writeln('<\/center> <\/body> <\/html>'); +newwindow.document.close(); +newwindow.focus(); +} + +// Routines to tidy up popup windows when page is left +// Call with an onUnload="tidy5()" in body tag + +function tidy5() { +if (newwindow && !newwindow.closed) { newwindow.close(); } +} diff --git a/slowtwitch.com/.htpasswd b/slowtwitch.com/.htpasswd new file mode 100644 index 0000000..e69de29