From b259ce34ed45b7cbb129e579c8dd0428fa80eca1 Mon Sep 17 00:00:00 2001 From: Mike Rockwell Date: Thu, 24 Jul 2025 23:49:19 -0400 Subject: [PATCH] Add FancyZoom for QR code image viewing --- images-global/zoom/closebox.png | Bin 0 -> 1910 bytes images-global/zoom/spacer.gif | Bin 0 -> 43 bytes images-global/zoom/zoom-caption-fill.png | Bin 0 -> 134 bytes images-global/zoom/zoom-caption-l.png | Bin 0 -> 310 bytes images-global/zoom/zoom-caption-r.png | Bin 0 -> 290 bytes images-global/zoom/zoom-shadow1.png | Bin 0 -> 310 bytes images-global/zoom/zoom-shadow2.png | Bin 0 -> 164 bytes images-global/zoom/zoom-shadow3.png | Bin 0 -> 368 bytes images-global/zoom/zoom-shadow4.png | Bin 0 -> 178 bytes images-global/zoom/zoom-shadow5.png | Bin 0 -> 180 bytes images-global/zoom/zoom-shadow6.png | Bin 0 -> 428 bytes images-global/zoom/zoom-shadow7.png | Bin 0 -> 186 bytes images-global/zoom/zoom-shadow8.png | Bin 0 -> 426 bytes images-global/zoom/zoom-spin-1.png | Bin 0 -> 1882 bytes images-global/zoom/zoom-spin-10.png | Bin 0 -> 1892 bytes images-global/zoom/zoom-spin-11.png | Bin 0 -> 1901 bytes images-global/zoom/zoom-spin-12.png | Bin 0 -> 1902 bytes images-global/zoom/zoom-spin-2.png | Bin 0 -> 1893 bytes images-global/zoom/zoom-spin-3.png | Bin 0 -> 1922 bytes images-global/zoom/zoom-spin-4.png | Bin 0 -> 1890 bytes images-global/zoom/zoom-spin-5.png | Bin 0 -> 1938 bytes images-global/zoom/zoom-spin-6.png | Bin 0 -> 1927 bytes images-global/zoom/zoom-spin-7.png | Bin 0 -> 1898 bytes images-global/zoom/zoom-spin-8.png | Bin 0 -> 1910 bytes images-global/zoom/zoom-spin-9.png | Bin 0 -> 1901 bytes index.html | 6 +- js-global/FancyZoom.js | 761 +++++++++++++++++++++++ js-global/FancyZoomHTML.js | 318 ++++++++++ 28 files changed, 1083 insertions(+), 2 deletions(-) create mode 100644 images-global/zoom/closebox.png create mode 100644 images-global/zoom/spacer.gif create mode 100644 images-global/zoom/zoom-caption-fill.png create mode 100644 images-global/zoom/zoom-caption-l.png create mode 100644 images-global/zoom/zoom-caption-r.png create mode 100644 images-global/zoom/zoom-shadow1.png create mode 100644 images-global/zoom/zoom-shadow2.png create mode 100644 images-global/zoom/zoom-shadow3.png create mode 100644 images-global/zoom/zoom-shadow4.png create mode 100644 images-global/zoom/zoom-shadow5.png create mode 100644 images-global/zoom/zoom-shadow6.png create mode 100644 images-global/zoom/zoom-shadow7.png create mode 100644 images-global/zoom/zoom-shadow8.png create mode 100644 images-global/zoom/zoom-spin-1.png create mode 100644 images-global/zoom/zoom-spin-10.png create mode 100644 images-global/zoom/zoom-spin-11.png create mode 100644 images-global/zoom/zoom-spin-12.png create mode 100644 images-global/zoom/zoom-spin-2.png create mode 100644 images-global/zoom/zoom-spin-3.png create mode 100644 images-global/zoom/zoom-spin-4.png create mode 100644 images-global/zoom/zoom-spin-5.png create mode 100644 images-global/zoom/zoom-spin-6.png create mode 100644 images-global/zoom/zoom-spin-7.png create mode 100644 images-global/zoom/zoom-spin-8.png create mode 100644 images-global/zoom/zoom-spin-9.png create mode 100644 js-global/FancyZoom.js create mode 100644 js-global/FancyZoomHTML.js diff --git a/images-global/zoom/closebox.png b/images-global/zoom/closebox.png new file mode 100644 index 0000000000000000000000000000000000000000..4de4396d4a09677774f79289de2a09511baeea22 GIT binary patch literal 1910 zcmV-+2Z{KJP)z^Q>-8KIssI20AY({UO#lFGm;eBCjsO7iaR2~=Yybd* zy8r;x$N&H_>;M26yq<`~KL7v*>`6pHRCwBAWWWy?p_swJ!GY=X=g*8ke*9qk`ST}Z zdU`qw7Z(@fv}x0Rf#f+jIR5kU^8P2LK7aoF=BZPs zUOIK^)MsF*`~o`QH`D=t(JcoEAauk84FygG1qFf7&``O#bLZLs4PE;m4ZL{q;_rh8 z5B{QyfBg7y1u$e3few}u6cpqKnFTeI3E3im07CaENCB6OjEqoBOpMCLjT`;`{{8y^ zWZ_n$O7C)YSBAZ*T9f@87@wgQ~r-ckkXvV`F1EUVpg2H5Y-eYuxnRM9M39EBU%&nZ#x+Xt8W|aVwYIj#h+{D^u`kKV z$v=Qu3ogdS#`gK?)2F{dW*t0uupVfZDo|VqWEaTS009KEm>Z}`3Ydy*?%%(^5TtnW z(;G*fzk0D zSSo?}K!do)4&2r=HI`6@Kg;DK;Y5@D8S6f$jA!R2#R=y z-@kw3EZXkgz5D;mmoF#|yK?2qKWvtQ08AWYDKNn@LoH?k2q3V5?BoZ76wef+J_SucZ|q}*4Eat0ppwvn;u{u2G>@=;`K8pCnvlB0SF)lXugsH z7X0Rlii*j=;_ekFPSCRwF!6l>MgdBk`uh5!#Cc9m&JXm$1Xy;1vlOsk$^_bB1{9YD zI&JkwlS1w(;^Z^)!@LCEWfM7lr1G>gQO-(Jludi=U<2%PtU4%`gn2LZ7@5Q~G#ZGZrRXD5)S*xA{=fSSvIdGkEBd`SvUNJ#h& zEi#`0(?mH?%mZWxEIR=N5WD~ZWo}@L!d6H~C^;o1WhN}%Kn9R%DX3Tl1uIBDuwk$s zD3%Dsw#WqtKmai#w>W@Fo)wt5IG#Lt!pzOh{RtR^ngIa;EI|DX!1DGl0}&uLHkM`0 znlZR5`~$4;!Ko9NO&EZQ5}bNLd|;LO3|NQX zDk&*B3FO`b6<$F66o}sdF(~nY(#>Ch0AfUH2(Un1!w0oo5@@*$Fu}2#z zG+4x;SOQq;hynAf5U?N-FflO^1=e1m<_rU{W%&_U5xfEBgts6ML*w!V5Wj@tchKm7 z#Vt550|XEwmS!y*Qm}(kyC5{X2|-gN4>0wE+fTqMj{(U315A|Pffy8wAD|Y29Pu8S zm|(&C3%QvK5I~Grnzu|)pR++TIyW=~c%hErLTWoPKn(*K{0(XeEWv#R;_pxkeqBrOP0*Db$8yndX$XyynEc#&m wB;+m&vSk?cJ3s(2G7t}lRr{Y9MF0T?00rpcocj25u>b%707*qoM6N<$g7#h)yUAf^t80Ld^gF}W}@SOWlZ0R#L1 literal 0 HcmV?d00001 diff --git a/images-global/zoom/zoom-caption-fill.png b/images-global/zoom/zoom-caption-fill.png new file mode 100644 index 0000000000000000000000000000000000000000..1e341533e8be5fc8b9a296803342e4e51df6777f GIT binary patch literal 134 zcmeAS@N?(olHy`uVBq!ia0vp^tUxTq!3HGj-%nc&q*&4&eH|GXuHCreA7KRKOP07s zlmzFem6RtIr7}3CmUKs7M+Sy#H?H_c7y8>=y&s-w7`{yp#B)MOPepDIoe!W%rU5A11$9Ry{SM)%M!C z?V0h*%icsJ2Q4;Qy}^90?p2|clRUhX_NrWRR=TTtNjH4f0bwx%|92_-{{NP|7wO(t zuIM+Z+Uk(0_oCYlGC?kH`!-BDxTv;R-{jDil!!VO35MJKS}ZAQ`LBR}V(@hJb6Mw< G&;$UuzIp`! literal 0 HcmV?d00001 diff --git a/images-global/zoom/zoom-caption-r.png b/images-global/zoom/zoom-caption-r.png new file mode 100644 index 0000000000000000000000000000000000000000..15980d58abf90c96369ec822918b8a2da63fca33 GIT binary patch literal 290 zcmeAS@N?(olHy`uVBq!ia0vp@KrF?<1|)MVuEhf>mUKs7M+Sy#H?H_c7yM% zu~l`y?7u5h>2&4slboNTpJeRvS)~^6%*Ng8)^FakXa9R{%w*R2Exej@3g`99I=d&w jY!J{nxw=(_7iY}2>c~iBkf4)?1 z;Z;_aInj3ZmWJb>H<|{LUy}_wu6?`ubwPpjLmtlkh3Utck{BmS3TXeEB01q=4o_p+ z#p_N?sT@nryXAgb&X&TazdYgA`OR~>_I%X8O-xS>N=;0uEIgTN15{+@>EaktaVse$At50}foa2pMH4zB zTF)HON?EweDJ)5JmcZf(AMFKzX1^@s6z#LUx00004XF*Lt007q5 z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz0!c(cRCwC7 zlu-`DAP9!})!k_Cz5m0q6HQl}wV@QOtJK6`t?~f^AR^G%D7^^AV(Bzs zw_icA160Hw#6K8Ner|!K4(lZ}GexVkpc^oWFtz|iDCOVO@O&4>M+4THS*%;YWnE#< zh9`6ac`4`2q(Pa-mEr<0&EoxoXJ$ke;7z81Vh&1;X3-=LsXqd%_dm+Nti9bREGq8{ zr7V`nkH8``RwfCw^!I>SrE%yW!6A%m%L~jS-r(T{ODrpc0Fsm*o<#!&?ZVZ8e?VTI zS)c=S1jd0-CV3_Zm`7T2kf&!*!iT#OgwB-T0Sii9xx-4MfK}*MfB^tY0%omCOdy2- O00003`!3HE<<5aVO6id3JuOkD)wHsIbBaDE2$r9Iy zlHmNblJdl&R0hYC{G?O`&)mfH)S%SFl*+=BsWw1GE}kxqAr-fhQW6ppT9VWh(%6#3 zG}2g;%ru@cB$a9C{`&v_|5=_C1~sEEf6^6%d8$tTyLj2CE%Ei{|A);a+TAX(a~Lpa X@^Q2C@40miXdZ*7tDnm{r-UW|sB<^y literal 0 HcmV?d00001 diff --git a/images-global/zoom/zoom-shadow5.png b/images-global/zoom/zoom-shadow5.png new file mode 100644 index 0000000000000000000000000000000000000000..2a75b82abc5386e5516f1b185ea320f5803af3d2 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^(m>3`!3HE<<5aVO6id3JuOkD)wHsIbBaDE2$r9Iy zlHmNblJdl&R0hYC{G?O`&)mfH)S%SFl*+=BsWw1GZk{fVAr-fh{_wN#q%gR-9dl6l zD$`NV@X=r6FLzfx^GA7&f80m@H~g>{X8!p=ex;Pg#-7G`(=J|3|KGkgbunj3!XqAq a0}Nc@;#`q$Yz_fUWbkzLb6Mw<&;$T`g*uS{ literal 0 HcmV?d00001 diff --git a/images-global/zoom/zoom-shadow6.png b/images-global/zoom/zoom-shadow6.png new file mode 100644 index 0000000000000000000000000000000000000000..65801aa0f2b7bb482bd19c88a00d7fa84f128967 GIT binary patch literal 428 zcmV;d0aN~oP){qR)z);aw%GfZ-d(DwaR)buRfOTLtfJ+0;E9~|y zjFt7pQMWYM{Ro&=rte!(t(=w0Nkvf|5jB$3^NRz-eKLX#gQ1b$&V9Cca4R|DNig)WpGT%PfAtr%uP&B4N6T+sVqF1Y6Dc{bP0l+XkKj@~!= literal 0 HcmV?d00001 diff --git a/images-global/zoom/zoom-shadow8.png b/images-global/zoom/zoom-shadow8.png new file mode 100644 index 0000000000000000000000000000000000000000..f1c6acdb2eef3363f03713c077d52bd67ee5d7b6 GIT binary patch literal 426 zcmV;b0agBqP)u-O|T@Th@*TPy^ zz``!NmGg~^emL=~Ffu^oL9f7&2gPqYqYU&3XXrpp_!StaP@(~$PdkIe)!v_az1+nI za)6f_YZW!La81b?LMJ;9&L%F%qJS1`75!$wFiVz+XGtnF8n^)#F@d*%n==YRse#gE zQy>fq{U0`q7nlGw48#+SNgoqL!88z@H5^&HVkOAz>`6pHRCwCl zTHj9-SrneO(_cUf#TKZdKu}!KRlpTi-Ka4pMuVG>4Vw^2eDP%;{YQ*1uvty^ZL`D; z5($x*7>zLz+2BghXpA6AKrFwZ(BGZz_l+GhG*vs@cBS0pq&S_q_k8!9?>py?)d|Um z9@YSBg1KQ8@oQgWNU*oCY1km_pI9s=CElb<@*o}m1y(I=%rOT06=0@62jncQ6=o7P z_6WiL0+?ILfV9Dyh1?o_0Q0Ay%KPtg5CliFPN$>qf*7}UA$P~m05imhG{PJ?45XA8 z2&7)f{ZUUKRht0FE&?gs1V9`FlD7$fh*@nrEEbFY^5x6lT)lerTf5zE$mUuZ15#L6 zDAIBDwWg*fds|yuO-oBlb#rsGbKSyvy? zD=RC(#l=Ox&1N&IK~z>&S`HjIP*7Z4Y}_zF>g((6*j;^XZEbOTdwZF3JraqagNO+z zSh{F5`mtjzDk>7UY}sPOWg$~3mk}U0Zrt#^d-rb5=ktY;N|o4UQEueuX~HlV3_7>l zZ6?TYI2@aqnF((gAd{1m!JeL;Nl_Ga`T6E^g=>Vf6KWSB`D_5@UudAzbfaDIp-ya5m06rxU zJ8WE&eBTYL8G*&23S59Kl-LX)GTqyF2s zZ_nJkd2`z1@r1eSNGk(DGa6Jls@Jw{+ssT$&W}jRykXR|_{E3+(1aY$AS#B|*4DBU zCr-G`W-~WKN9Vh`y54qocYAP6&)udoOdI97_@~Snrr7rF+s$zr2~f2dQ;~dQ+9@fU zwTN(GE;KSS;(hw`=`wS=w6xTM2#I-ldHTM-zS*_4H3^Ohij&H7Oe27k)vUa{+|20E zS%M}2q}#_xXaSK{M3S{3s3Qd+xbyDayK{qsgDYQhf@CJwTrQW)hlPcO2qW@e{Llmh z1lH}`xzoxtQ5NRk+{KBBi2z1SNs})D;d6`-m5#lzVR|6`v;vMui~ww-WuVq!t(C?m=qpiPu@3$qlB1mc{8T zn?|UdoSy29KhBivnlmXsQCJdiV6$WimLU6 zG|Zg*(&t2DE+0E~%z>KXMx`&>x^=7R@#Du{wd{UsQyLl?Y-nRFY#=$$($Z2yk!-c4 zoTh0tXmDiDo;~?z&YXdQx=d^*U{N-Ksm`&yyd0qflM{>#`z&+^env=Z4N1F2Ie-4V z`}FD4E|68uHx$6g{rmUlakyI8yLWFsqlA_u1n#W!h*FD&vyf*HD3YJwBQ0f-AlVU7 zGdaWdMN2f&iU=3pw{IT_FCUgr-Ms*@I5#)P9X7BqQjQ6(zrTM0axEXa9z1xkR8>`F zL0clH6Z=d8iZLw#D8|->ZT{zYlaYwTHD5xT5ahx)OsEPC$TITzDKQ88Xa zbc(5VsNQru#MXp!@EDA)ImommKUm?ZBa9@$DZI>DL^%1qd-oQ(D9Nc*@tT?%D{|e+ zoS&MS3cP;(+Rt5vghtsYLTdGB3M1e^01>bPh!OXjabJLQP`aN#f9|6aQW>@KMDq!T z$5R@2QUSqwKwjXQ#On_qK3w8G2~DHiZoGK$!pHmgJK#pVjQ^(0 zk~49|i)O+HF%y#@3O;bb!`hIjHauh{5|`W>8XEGlcO%I+3=sB2$vRc44~fq-!e>y; z7ZM+q^p#Q8&m&r^KMS4eEUx+Zsx>0MY`l?=6IWKa|KV+Xfcd+;3I1DQkwC^b0g!P5 zd9n$BJRy+3VV)cYF-r_AyHcDdO*snWcc}S<(m(L+hZVLf$3WZyh<>GxsN0nvVJ(>| zlvy0?26|w<%1@qh^=D4M0l-vZW&cz&`CXhh{E5WZ{!zhroYVubp=3Wi`&WPg022rt UoBn=zz5oCK07*qoM6N<$f*sO;iU0rr literal 0 HcmV?d00001 diff --git a/images-global/zoom/zoom-spin-10.png b/images-global/zoom/zoom-spin-10.png new file mode 100644 index 0000000000000000000000000000000000000000..77595dbd00c94f5735e9b0cb053b8e0bbb066006 GIT binary patch literal 1892 zcmV-q2b=hbP)4(E%{l;5MGjn!%u0cOl486jw4p|-BBE^m2xIr8%5%fBs8 zV4+Zm-(&dx5r|#8c9}PB+^8QN9rZXIj^LW`h{a;jP-&aZrcJbbG#dQ}ok~kf^#s8= zMMXurHAAhLnVC=^5QqkY!DvNAg`PA^{0+P$f09n{UOoV-{C>_E6FDYR+RCcOx5T6cbaKIHX!WwVnm zX0uuIAunoWaP&xCUY;5tjp1-ON)Nt$`_|976nbjw)~$Kv<>mU-0OMxgr89vWHZ(Mt zps04kh7DRONQ&?i3dV3x2jyjeb8~Yc0^y0V!Uv!dZa}yW}W8dW-IFiy+S&XDpX=?vJy?jnu4NC*X#;th{U*HZAu56 zHl6r5ckWz6dwY8gC>2QPsSJaIgZ7grPmZQS2|>|)`}SGu>+8)hKt!2x0Z{Ym)hq9< zTen=PQY>X42w(}RR42Hu9K3-xMaSRpGS&6y5w4|NkBW0WdOfZ6Ql%Cx#@3>>wY7ws z2)C0K4Ay~xftlIa*-$#XHX4oU>gsBv!C+uUlh_G}Po{ImU#h7%Eg-^@;=9;{4In62 za{c=CITXH>dM9SOrluy#TK9UUFjICq#wMn-0i zA3y%be+4NOK6>MpufL= z{QUXz6Gx65DeCU-u0${8VauYNTU=bMJ9g|?1&b&=u!wm<++*9XW?XOIzTLtTC2LI9 z3nJs;;K76Z$DYk%#?PV%fVHR%`h|ss;Much$Gf_^%0WTRg$oxZ z_w3nY-LYeb6_hgLBjcki}r+qTV2Kx`a&P{aIiRy~5VM-0{r14QWJ#f$d7 zzP>4DD+cH3)2C}-VIyc3zIyelgV_h(sYYLAnw*^UK701eizd;+`=r(I@bD6gC=XY7 z?niM|J%9e(W4GJ=S@#G7`O>9JlT4HRF8F-lzyT}T`$Aqr8TZ4750_!(e1M7|rlRbY z2^cZ33@|o$&)Cw^V!eC!uAA$iM++iu7DQdj`oW5d(kt;Zh`b?`RD=6fJTT!|q^GCH zkt_qz$~SJ@n5W0M#^J+fRUSblaOIO2xmCqn;~D_5M#IwBMk|6%bOVBI`>2w-dGf32H0 zZ@Qq+7&_Jd6Mm%FMW$7z zT4j^TwnVfhnHc}8MMMm@}n#GLQJO^^ZI)kNAm+{wiA_$W{isJ6o$O z70)6F4i|ygRk=Ux1oCJd0C_|pzeA>T7{n|w5D4@BFF6dP4>=_)D*FS-wHyR-4Imzf zI-+b>+9BU&s!(QekVONKU&Sj=x%!&Z&j8>^tn8m^CYw|rUOeL~5?}hI0((5De}fDs ed-3cq0R{k-QcFqR9b9t&0000T2* literal 0 HcmV?d00001 diff --git a/images-global/zoom/zoom-spin-11.png b/images-global/zoom/zoom-spin-11.png new file mode 100644 index 0000000000000000000000000000000000000000..c2147d56687834b00927c9a2337c2236c45541b4 GIT binary patch literal 1901 zcmV-z2a@=SP)|AQx`Ab z#Ke`xh(i!`VN?_g@~jlFQ2K7~d|$`kPtJkf+BuEpa z1yTvA{dDYGtOR5NG7I?|GOQ>{BK0EuIyX}BE=avDKi3%KSAd!Q5|AGt9S~WU-zx(7 z17P~s1JVg;(-qeG3t)cNsd(R7fFQWq^m=`(0AhsvqAT3>Gr$-L9ROsc) zm#d@|gBmenqEb|Lad9z9Kn!?LC|q4#ZRUA+Lq9Pw5yJTxl_v0}rY3t$O^v0ZqC%dX zosDoWO@V;_(#ex2i{T9!3LDOxIa7V=)Txp;Z{GOE$HzmY7lDv!z^M3qz8C?)^8cme zj~_qACMPGu{QJOx1NQp*dMoZrx*-@0GHx=iIT-_?b?@K5?}4S2y1F_CEGiWj7h5h} zy0in-iS_sQFEIFNQF?{f69g{PQ#k@84UrV&#>PemJqBtem7bfMi@bXE3JeV-7(={Y zGa%fYvGC~8qotvtAukj%L2O9DGShH(clV^QraIV#Qand$?cKYV_ZSJ3UK<@94S;T8 zX0p_KH31@&q5=%od-v{r0Iillr})jAH{DPu$n)!2QyinUsW83t?%liK*w|QTd3iZ5 z?#sjz>Y2Se-HVwv4<9~kXPpprL0Fjp=qXxKeQw=Ui2$cp0A2@LGWd0ZUOdkGnFzkN z&zi0=?L3W#-?(w3;q2M7HLzY-ZDmw+8J?NEcJ10|I+Wlw*iSif6 z8)}UAYgvbeplA2(+vi|0Wb48jf=syPIhkaytXgQgzon(caryG)TGWtau%aTzJRVOd z-91DfECI-lKFc;TGP2C>(;HA ztoUxXJD6!f%-AE$`>n05 zrO7wRkw_d0E#A3v$HS`3hO)D>vj$_WytK3wMS+|_V_8b-^!E08I7RN-wJT|TC>uf{ z4WOuo7%P}AZ7_<&d4@e0?vH8e5mt20Nu<*4+qb9S2`_sqTC}UHs|G-2o&Wa=uWNly^(Tf~$U%Ys+%El7$5d|&7ERd}9>=@K3Srd=2iud&N%!wvY@VU9U z*}i-C?jro30MGr;pFj6=hKHhYcrMxXvSEDt_U$UJvtuqXA3S())9~=HpL_7!!-o%j znP#i32dhsbs>0D$fFN~{y(;0YbM)Dq*dW5=A?)D2C5a2R5Ypt6S&}1@tnMB%*7@H0|P#!(lJhgso4e{vq8MyQopPK;CXfgoD}m02o*!n zuB1|fuXCr0qlo@W zD-c*A2D?wI-PMX~2!d;gK-{{*Uv2^!*#JOB2xJiADPR!u#6TcSfxQI`qz5@ACMx?A zNPhu>=m&@=qK>HBl^-GPxhj+zF0$xPNT2xRsZc+2`V9c4Q!D%Dn#pF}zaO6Q6NzvA nQGxqYP!B+c*8A}69{~mcLjGE2+o}~y00000NkvXXu0mjf2C$tb literal 0 HcmV?d00001 diff --git a/images-global/zoom/zoom-spin-12.png b/images-global/zoom/zoom-spin-12.png new file mode 100644 index 0000000000000000000000000000000000000000..cf02724819f839cdabf8e98eeb0ce72a866d9c5c GIT binary patch literal 1902 zcmV-!2a))RP)|yom@)CjKj07W2TbO|aY=@` zVB#bbghb;q@oGjLjK+<{vdT``y0_=d^VEJxIWkC@Hc;N=4X3B)eCK`M_4y8!G%Jf1 zS_f@}I-%w9a~mNtbPzfQ{R{e!qA0TZB58#iY4{J&D$VAUe&~+?GqxI#X6QFiqh@nU z2-*%Xoht$P4thqDS<(S8ziJZl{$K`zpq!B;>7W3jhkmcgT=^DY^aRoXb!0G*B4Qwr zT21ClErC>S0U*@`V&4Kl90X$B0zmZobgr(`>7?!3w;T0(y)-;L91MrUO1hqvGXCUn zIP_+-dD(hdSy|emq9S8KL4m<;w=Z*=R;$$*3_U+qOc=6&z*D^9EeeU$UygUPy$JyE0 zx=jP*_U+rFkVQ!N{Q2`Wg@uKN)#}FOa+w&VP$(o%O-+Rvp-lmVh1}NG=0;SsHk-|G z_3G7{*hWJBv~2*fBY@a3iytD<_}SUn$kNhMbi*QY^ytyt%a<>g=H%qWtcymY%FUZM zNBjEv=IQ08rY2WILxaud^F`UQs077kke{D#ATZX>`1p8;=cyu6NICs_B1A*JPUZ%7 zAf!@beSLiaioDS8_Xm4=di*e2URYT0pFVxsg$`wc*Q0mu-kn4Z=$S?zKYk23olYaV zTMWp^$Vd>W7-bC+-0t1Gt^9u5wrxhFTPWF9oiq@7_t2q3_T1cDBfW^|6dyTq#Qy&M z`^9I^o-LM?l<3g8bT@9?aQF81`se58BOZ?@BGQb-4ZzW{v9S;%v}@NcYiVhziR-dA zFrti70c=IpG4mpPZ!i5X2e}1e z$Cxq@jWAN&M*%p3kq83U>j{7b?{>Qb=zL5mIk8cs4Tvy`-ew9se*Ad0zrTM0-j>n1 zhG|eD0QG%hwy*{mp@D&c0HeUhK;wDMf8C$5)MDG*vu95h(}bOh2Jtu;49XuqdF7NRmQs#>w?sUp9KgZOtWOtYt5vQ54&>ZO2x5b$BH@l#Kh*q*_j?bd^mpX+O>hT zJeb#TJvs$*#e@Q<&2&s`QF1V(S@7k{mrHAILTe5kgf*ailFz~qFow7xN-~WjzLpYq zinv#bcd^u`7Cp!|30`H#L$o5bc%J$F=+UD&cB*6|Ok+7Wn6e^Lj0V@9oSY1cx=A?@ z5t)SIjd>6=MSuA4;aqkyHh{IPM~YuvU2Pp28VbzK%|%vA!<2R{kxq$fGMTi^&CU6k zDP@RMer08)>B*BPb6@H@bP9mmLFKI&peC*}GcyxrYgRuaccJ}O9CsM=A zu7%kWot~Z!t#u7X0W3M@ZbpVY>+RdOUbgRKXUMwd2y^(-rAwtPEiENvyY!mZ>y6yI zcW(k4t0@4?MwAM`r2;s=%p#IZbiF*L;;UD$yre2@zpNEFhosTWnjsHM7EIC+p%K{G z%^jkY6b<*aTAP!#WC5GD617l*KgxTpLPzjgUiibaYJ9NFIwRzIX55 zEOqid%d87f5n>X})EK2+L@6S%WW<4NM286Uez6TFIc<{iJNE#JY zqSMfK@80=vE%}UvY@e{Xe@9iC#(BB*+*3|}cCzI45jPk0lOwwKqU zOj+#nTj1Xc9s+T10U&My>D~fBx(VcO=tKsCm?8%DcsX7tjTs8$XEehh@xO@?sD*o+ z3#5MAnl$lr8usC|{HL77J3w&8c^ABh7|Et&8$r=JjsQT4`3Eqp2VCv;fMHOv$q=DNqbpQYW07*qoM6N<$f+-}Dp8x;= literal 0 HcmV?d00001 diff --git a/images-global/zoom/zoom-spin-2.png b/images-global/zoom/zoom-spin-2.png new file mode 100644 index 0000000000000000000000000000000000000000..95eaae89556315471e33f150f20e421c7933a938 GIT binary patch literal 1893 zcmV-r2b%baP)xjcNo2QR$vAOkVS+lTfwyviWCzQO*Bm;gh&VtBz-eJ^u_oW_^yfZ#iZ6Z9~wye z(1ajHeK65zZLP&6CTKziMD}G^X1#M~ZqFI!XRZ^(xs(xxU-E^?ox6PJTh4cW!*w87m4Kfla{vg8i#$S~T$_d6f(4_)oAZX=|<_*v|knu@;bKSO?4| zZSAGNeg~NT)qr%tTBP(^eE`!f>FT~I4MA|V$ge8i4HBP6~oXTfy7!W#Y zv)MjU3WpCLcDA>-m$$UE>^XJn)JM!{wOVDD%VpV8KpGnxv%9;yzrB3<@?JfdoSYoX z($bQ$u&@xy%F43nLEN};p z?5zLh&71GG43L?bnQ(u9|D@S$mK_d<_3YWRr7=Y+$Exf@R=CceKfhC**Aj~>mZ)4UHdVCwDd9Y@{IaS(dF-UuCyMpw4iEEo0# zqHe`^QBv^k-Mj7LzRV0Vr=s5!WI1+`xHcsjVbd~dgM)*>~@r4w{c?Au#~2zrosTBfVw|`|J?QeyR=vi<>loWbVNLi&cLZC=7<7j z(gcgGNtGxwmMHIotl*Cc9 zDwzkz&(W%?sxk`-3al(u21I0wy##tz+-`R;X%aHf8!{X=X)CGFbicr8BC_(z)YA+E zN9OJLR}4&1TFh8VN{bmG#~(a+&>+9FAeV=0;24&yAeGW(xJLd{}g0xH~Onkefo6a(W6I;1jsB= z5wphi*Kz>X*Vo774V}h{;xp+tCQra%HV#-`YjlKFQI8PvPX-k@}W zY{?}ZlK=<|+A1d5c}`hbnVsbX($H{zn9-*|#4#JyGFy)V5)wzo^{Ew&aGpJ`F`5q_ zKJ;)uL8nOo$B!S+W3*XnuU@_K#wEWiu4u!QAe8cqc6N5Q8M0sDAVf(<2uREi3QWRFa*T1%R=$Kae3C6mkgP zYy6JtnL%PujP{A)9Sk2p0CZS9jO+zDpTpyfBJ|gC;(mgeFI4n!UE3t?h=)k;KJvfeeq(DX}RM^M<`4bd;{oB#?oR3`q7`PX0DnTP~nw*Gooy+i6*U0pzlN6N#tdaf2dNSfq#V_(=&p`lRU_VWuwL=XQ@Xz9^a}utB~JEFiOB|O<;64pk8iVIDsab}`cK$D ftG#&kp8x{@FRL{p^PL_A00000NkvXXu0mjffxCu3 literal 0 HcmV?d00001 diff --git a/images-global/zoom/zoom-spin-3.png b/images-global/zoom/zoom-spin-3.png new file mode 100644 index 0000000000000000000000000000000000000000..9e2b9cb3d59033bb8f9a3103590043bf6a2d9e9e GIT binary patch literal 1922 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 N002ovPDHLkV1m|;ni2p2 literal 0 HcmV?d00001 diff --git a/images-global/zoom/zoom-spin-7.png b/images-global/zoom/zoom-spin-7.png new file mode 100644 index 0000000000000000000000000000000000000000..9b6e489f9f678a52baaaa16c959a251df39fb228 GIT binary patch literal 1898 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 literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 327c2ee..0ea7ff2 100644 --- a/index.html +++ b/index.html @@ -27,7 +27,7 @@ - +
@@ -89,7 +89,9 @@
- + + + diff --git a/js-global/FancyZoom.js b/js-global/FancyZoom.js new file mode 100644 index 0000000..42d71ce --- /dev/null +++ b/js-global/FancyZoom.js @@ -0,0 +1,761 @@ +// FancyZoom.js - v1.1 - http://www.fancyzoom.com +// +// Copyright (c) 2008 Cabel Sasser / Panic Inc +// All rights reserved. +// +// Requires: FancyZoomHTML.js +// Instructions: Include JS files in page, call setupZoom() in onLoad. That's it! +// Any links to images will be updated to zoom inline. +// Add rel="nozoom" to your to disable zooming for an image. +// +// Redistribution and use of this effect in source form, with or without modification, +// are permitted provided that the following conditions are met: +// +// * USE OF SOURCE ON COMMERCIAL (FOR-PROFIT) WEBSITE REQUIRES ONE-TIME LICENSE FEE PER DOMAIN. +// Reasonably priced! Visit www.fancyzoom.com for licensing instructions. Thanks! +// +// * Non-commercial (personal) website use is permitted without license/payment! +// +// * Redistribution of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution of source code and derived works cannot be sold without specific +// written prior permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +var includeCaption = true; // Turn on the "caption" feature, and write out the caption HTML +var zoomTime = 5; // Milliseconds between frames of zoom animation +var zoomSteps = 15; // Number of zoom animation frames +var includeFade = 1; // Set to 1 to fade the image in / out as it zooms +var minBorder = 90; // Amount of padding between large, scaled down images, and the window edges +var shadowSettings = '0px 5px 25px rgba(0, 0, 0, '; // Blur, radius, color of shadow for compatible browsers + +var zoomImagesURI = '/images-global/zoom/'; // Location of the zoom and shadow images + +// Init. Do not add anything below this line, unless it's something awesome. + +var myWidth = 0, myHeight = 0, myScroll = 0; myScrollWidth = 0; myScrollHeight = 0; +var zoomOpen = false, preloadFrame = 1, preloadActive = false, preloadTime = 0, imgPreload = new Image(); +var preloadAnimTimer = 0; + +var zoomActive = new Array(); var zoomTimer = new Array(); +var zoomOrigW = new Array(); var zoomOrigH = new Array(); +var zoomOrigX = new Array(); var zoomOrigY = new Array(); + +var zoomID = "ZoomBox"; +var theID = "ZoomImage"; +var zoomCaption = "ZoomCaption"; +var zoomCaptionDiv = "ZoomCapDiv"; + +if (navigator.userAgent.indexOf("MSIE") != -1) { + var browserIsIE = true; +} + +// Zoom: Setup The Page! Called in your 's onLoad handler. + +function setupZoom() { + prepZooms(); + insertZoomHTML(); + zoomdiv = document.getElementById(zoomID); + zoomimg = document.getElementById(theID); +} + +// Zoom: Inject Javascript functions into hrefs pointing to images, one by one! +// Skip any href that contains a rel="nozoom" tag. +// This is done at page load time via an onLoad() handler. + +function prepZooms() { + if (! document.getElementsByTagName) { + return; + } + var links = document.getElementsByTagName("a"); + for (i = 0; i < links.length; i++) { + if (links[i].getAttribute("href")) { + if (links[i].getAttribute("href").search(/(.*)\.(jpg|jpeg|gif|png|bmp|tif|tiff)/gi) != -1) { + if (links[i].getAttribute("rel") != "nozoom") { + links[i].onclick = function (event) { return zoomClick(this, event); }; + links[i].onmouseover = function () { zoomPreload(this); }; + } + } + } + } +} + +// Zoom: Load an image into an image object. When done loading, function sets preloadActive to false, +// so other bits know that they can proceed with the zoom. +// Preloaded image is stored in imgPreload and swapped out in the zoom function. + +function zoomPreload(from) { + + var theimage = from.getAttribute("href"); + + // Only preload if we have to, i.e. the image isn't this image already + + if (imgPreload.src.indexOf(from.getAttribute("href").substr(from.getAttribute("href").lastIndexOf("/"))) == -1) { + preloadActive = true; + imgPreload = new Image(); + + // Set a function to fire when the preload is complete, setting flags along the way. + + imgPreload.onload = function() { + preloadActive = false; + } + + // Load it! + imgPreload.src = theimage; + } +} + +// Zoom: Start the preloading animation cycle. + +function preloadAnimStart() { + preloadTime = new Date(); + document.getElementById("ZoomSpin").style.left = (myWidth / 2) + 'px'; + document.getElementById("ZoomSpin").style.top = ((myHeight / 2) + myScroll) + 'px'; + document.getElementById("ZoomSpin").style.visibility = "visible"; + preloadFrame = 1; + document.getElementById("SpinImage").src = zoomImagesURI+'zoom-spin-'+preloadFrame+'.png'; + preloadAnimTimer = setInterval("preloadAnim()", 100); +} + +// Zoom: Display and ANIMATE the jibber-jabber widget. Once preloadActive is false, bail and zoom it up! + +function preloadAnim(from) { + if (preloadActive != false) { + document.getElementById("SpinImage").src = zoomImagesURI+'zoom-spin-'+preloadFrame+'.png'; + preloadFrame++; + if (preloadFrame > 12) preloadFrame = 1; + } else { + document.getElementById("ZoomSpin").style.visibility = "hidden"; + clearInterval(preloadAnimTimer); + preloadAnimTimer = 0; + zoomIn(preloadFrom); + } +} + +// ZOOM CLICK: We got a click! Should we do the zoom? Or wait for the preload to complete? +// todo?: Double check that imgPreload src = clicked src + +function zoomClick(from, evt) { + + var shift = getShift(evt); + + // Check for Command / Alt key. If pressed, pass them through -- don't zoom! + if (! evt && window.event && (window.event.metaKey || window.event.altKey)) { + return true; + } else if (evt && (evt.metaKey|| evt.altKey)) { + return true; + } + + // Get browser dimensions + getSize(); + + // If preloading still, wait, and display the spinner. + if (preloadActive == true) { + // But only display the spinner if it's not already being displayed! + if (preloadAnimTimer == 0) { + preloadFrom = from; + preloadAnimStart(); + } + } else { + // Otherwise, we're loaded: do the zoom! + zoomIn(from, shift); + } + + return false; + +} + +// Zoom: Move an element in to endH endW, using zoomHost as a starting point. +// "from" is an object reference to the href that spawned the zoom. + +function zoomIn(from, shift) { + + zoomimg.src = from.getAttribute("href"); + + // Determine the zoom settings from where we came from, the element in the . + // If there's no element in the , or we can't get the width, make stuff up + + if (from.childNodes[0].width) { + startW = from.childNodes[0].width; + startH = from.childNodes[0].height; + startPos = findElementPos(from.childNodes[0]); + } else { + startW = 50; + startH = 12; + startPos = findElementPos(from); + } + + hostX = startPos[0]; + hostY = startPos[1]; + + // Make up for a scrolled containing div. + // TODO: This HAS to move into findElementPos. + + if (document.getElementById('scroller')) { + hostX = hostX - document.getElementById('scroller').scrollLeft; + } + + // Determine the target zoom settings from the preloaded image object + + endW = imgPreload.width; + endH = imgPreload.height; + + // Start! But only if we're not zooming already! + + if (zoomActive[theID] != true) { + + // Clear everything out just in case something is already open + + if (document.getElementById("ShadowBox")) { + document.getElementById("ShadowBox").style.visibility = "hidden"; + } else if (! browserIsIE) { + + // Wipe timer if shadow is fading in still + if (fadeActive["ZoomImage"]) { + clearInterval(fadeTimer["ZoomImage"]); + fadeActive["ZoomImage"] = false; + fadeTimer["ZoomImage"] = false; + } + + document.getElementById("ZoomImage").style.webkitBoxShadow = shadowSettings + '0.0)'; + } + + document.getElementById("ZoomClose").style.visibility = "hidden"; + + // Setup the CAPTION, if existing. Hide it first, set the text. + + if (includeCaption) { + document.getElementById(zoomCaptionDiv).style.visibility = "hidden"; + if (from.getAttribute('title') && includeCaption) { + // Yes, there's a caption, set it up + document.getElementById(zoomCaption).innerHTML = from.getAttribute('title'); + } else { + document.getElementById(zoomCaption).innerHTML = ""; + } + } + + // Store original position in an array for future zoomOut. + + zoomOrigW[theID] = startW; + zoomOrigH[theID] = startH; + zoomOrigX[theID] = hostX; + zoomOrigY[theID] = hostY; + + // Now set the starting dimensions + + zoomimg.style.width = startW + 'px'; + zoomimg.style.height = startH + 'px'; + zoomdiv.style.left = hostX + 'px'; + zoomdiv.style.top = hostY + 'px'; + + // Show the zooming image container, make it invisible + + if (includeFade == 1) { + setOpacity(0, zoomID); + } + zoomdiv.style.visibility = "visible"; + + // If it's too big to fit in the window, shrink the width and height to fit (with ratio). + + sizeRatio = endW / endH; + if (endW > myWidth - minBorder) { + endW = myWidth - minBorder; + endH = endW / sizeRatio; + } + if (endH > myHeight - minBorder) { + endH = myHeight - minBorder; + endW = endH * sizeRatio; + } + + zoomChangeX = ((myWidth / 2) - (endW / 2) - hostX); + zoomChangeY = (((myHeight / 2) - (endH / 2) - hostY) + myScroll); + zoomChangeW = (endW - startW); + zoomChangeH = (endH - startH); + + // Shift key? + + if (shift) { + tempSteps = zoomSteps * 7; + } else { + tempSteps = zoomSteps; + } + + // Setup Zoom + + zoomCurrent = 0; + + // Setup Fade with Zoom, If Requested + + if (includeFade == 1) { + fadeCurrent = 0; + fadeAmount = (0 - 100) / tempSteps; + } else { + fadeAmount = 0; + } + + // Do It! + + zoomTimer[theID] = setInterval("zoomElement('"+zoomID+"', '"+theID+"', "+zoomCurrent+", "+startW+", "+zoomChangeW+", "+startH+", "+zoomChangeH+", "+hostX+", "+zoomChangeX+", "+hostY+", "+zoomChangeY+", "+tempSteps+", "+includeFade+", "+fadeAmount+", 'zoomDoneIn(zoomID)')", zoomTime); + zoomActive[theID] = true; + } +} + +// Zoom it back out. + +function zoomOut(from, evt) { + + // Get shift key status. + // IE events don't seem to get passed through the function, so grab it from the window. + + if (getShift(evt)) { + tempSteps = zoomSteps * 7; + } else { + tempSteps = zoomSteps; + } + + // Check to see if something is happening/open + + if (zoomActive[theID] != true) { + + // First, get rid of the shadow if necessary. + + if (document.getElementById("ShadowBox")) { + document.getElementById("ShadowBox").style.visibility = "hidden"; + } else if (! browserIsIE) { + + // Wipe timer if shadow is fading in still + if (fadeActive["ZoomImage"]) { + clearInterval(fadeTimer["ZoomImage"]); + fadeActive["ZoomImage"] = false; + fadeTimer["ZoomImage"] = false; + } + + document.getElementById("ZoomImage").style.webkitBoxShadow = shadowSettings + '0.0)'; + } + + // ..and the close box... + + document.getElementById("ZoomClose").style.visibility = "hidden"; + + // ...and the caption if necessary! + + if (includeCaption && document.getElementById(zoomCaption).innerHTML != "") { + // fadeElementSetup(zoomCaptionDiv, 100, 0, 5, 1); + document.getElementById(zoomCaptionDiv).style.visibility = "hidden"; + } + + // Now, figure out where we came from, to get back there + + startX = parseInt(zoomdiv.style.left); + startY = parseInt(zoomdiv.style.top); + startW = zoomimg.width; + startH = zoomimg.height; + zoomChangeX = zoomOrigX[theID] - startX; + zoomChangeY = zoomOrigY[theID] - startY; + zoomChangeW = zoomOrigW[theID] - startW; + zoomChangeH = zoomOrigH[theID] - startH; + + // Setup Zoom + + zoomCurrent = 0; + + // Setup Fade with Zoom, If Requested + + if (includeFade == 1) { + fadeCurrent = 0; + fadeAmount = (100 - 0) / tempSteps; + } else { + fadeAmount = 0; + } + + // Do It! + + zoomTimer[theID] = setInterval("zoomElement('"+zoomID+"', '"+theID+"', "+zoomCurrent+", "+startW+", "+zoomChangeW+", "+startH+", "+zoomChangeH+", "+startX+", "+zoomChangeX+", "+startY+", "+zoomChangeY+", "+tempSteps+", "+includeFade+", "+fadeAmount+", 'zoomDone(zoomID, theID)')", zoomTime); + zoomActive[theID] = true; + } +} + +// Finished Zooming In + +function zoomDoneIn(zoomdiv, theID) { + + // Note that it's open + + zoomOpen = true; + zoomdiv = document.getElementById(zoomdiv); + + // Position the table shadow behind the zoomed in image, and display it + + if (document.getElementById("ShadowBox")) { + + setOpacity(0, "ShadowBox"); + shadowdiv = document.getElementById("ShadowBox"); + + shadowLeft = parseInt(zoomdiv.style.left) - 13; + shadowTop = parseInt(zoomdiv.style.top) - 8; + shadowWidth = zoomdiv.offsetWidth + 26; + shadowHeight = zoomdiv.offsetHeight + 26; + + shadowdiv.style.width = shadowWidth + 'px'; + shadowdiv.style.height = shadowHeight + 'px'; + shadowdiv.style.left = shadowLeft + 'px'; + shadowdiv.style.top = shadowTop + 'px'; + + document.getElementById("ShadowBox").style.visibility = "visible"; + fadeElementSetup("ShadowBox", 0, 100, 5); + + } else if (! browserIsIE) { + // Or, do a fade of the modern shadow + fadeElementSetup("ZoomImage", 0, .8, 5, 0, "shadow"); + } + + // Position and display the CAPTION, if existing + + if (includeCaption && document.getElementById(zoomCaption).innerHTML != "") { + // setOpacity(0, zoomCaptionDiv); + zoomcapd = document.getElementById(zoomCaptionDiv); + zoomcapd.style.top = parseInt(zoomdiv.style.top) + (zoomdiv.offsetHeight + 15) + 'px'; + zoomcapd.style.left = (myWidth / 2) - (zoomcapd.offsetWidth / 2) + 'px'; + zoomcapd.style.visibility = "visible"; + // fadeElementSetup(zoomCaptionDiv, 0, 100, 5); + } + + // Display Close Box (fade it if it's not IE) + + if (!browserIsIE) setOpacity(0, "ZoomClose"); + document.getElementById("ZoomClose").style.visibility = "visible"; + if (!browserIsIE) fadeElementSetup("ZoomClose", 0, 100, 5); + + // Get keypresses + document.onkeypress = getKey; + +} + +// Finished Zooming Out + +function zoomDone(zoomdiv, theID) { + + // No longer open + + zoomOpen = false; + + // Clear stuff out, clean up + + zoomOrigH[theID] = ""; + zoomOrigW[theID] = ""; + document.getElementById(zoomdiv).style.visibility = "hidden"; + zoomActive[theID] == false; + + // Stop getting keypresses + + document.onkeypress = null; + +} + +// Actually zoom the element + +function zoomElement(zoomdiv, theID, zoomCurrent, zoomStartW, zoomChangeW, zoomStartH, zoomChangeH, zoomStartX, zoomChangeX, zoomStartY, zoomChangeY, zoomSteps, includeFade, fadeAmount, execWhenDone) { + + // console.log("Zooming Step #"+zoomCurrent+ " of "+zoomSteps+" (zoom " + zoomStartW + "/" + zoomChangeW + ") (zoom " + zoomStartH + "/" + zoomChangeH + ") (zoom " + zoomStartX + "/" + zoomChangeX + ") (zoom " + zoomStartY + "/" + zoomChangeY + ") Fade: "+fadeAmount); + + // Test if we're done, or if we continue + + if (zoomCurrent == (zoomSteps + 1)) { + zoomActive[theID] = false; + clearInterval(zoomTimer[theID]); + + if (execWhenDone != "") { + eval(execWhenDone); + } + } else { + + // Do the Fade! + + if (includeFade == 1) { + if (fadeAmount < 0) { + setOpacity(Math.abs(zoomCurrent * fadeAmount), zoomdiv); + } else { + setOpacity(100 - (zoomCurrent * fadeAmount), zoomdiv); + } + } + + // Calculate this step's difference, and move it! + + moveW = cubicInOut(zoomCurrent, zoomStartW, zoomChangeW, zoomSteps); + moveH = cubicInOut(zoomCurrent, zoomStartH, zoomChangeH, zoomSteps); + moveX = cubicInOut(zoomCurrent, zoomStartX, zoomChangeX, zoomSteps); + moveY = cubicInOut(zoomCurrent, zoomStartY, zoomChangeY, zoomSteps); + + document.getElementById(zoomdiv).style.left = moveX + 'px'; + document.getElementById(zoomdiv).style.top = moveY + 'px'; + zoomimg.style.width = moveW + 'px'; + zoomimg.style.height = moveH + 'px'; + + zoomCurrent++; + + clearInterval(zoomTimer[theID]); + zoomTimer[theID] = setInterval("zoomElement('"+zoomdiv+"', '"+theID+"', "+zoomCurrent+", "+zoomStartW+", "+zoomChangeW+", "+zoomStartH+", "+zoomChangeH+", "+zoomStartX+", "+zoomChangeX+", "+zoomStartY+", "+zoomChangeY+", "+zoomSteps+", "+includeFade+", "+fadeAmount+", '"+execWhenDone+"')", zoomTime); + } +} + +// Zoom Utility: Get Key Press when image is open, and act accordingly + +function getKey(evt) { + if (! evt) { + theKey = event.keyCode; + } else { + theKey = evt.keyCode; + } + + if (theKey == 27) { // ESC + zoomOut(this, evt); + } +} + +//////////////////////////// +// +// FADE Functions +// + +function fadeOut(elem) { + if (elem.id) { + fadeElementSetup(elem.id, 100, 0, 10); + } +} + +function fadeIn(elem) { + if (elem.id) { + fadeElementSetup(elem.id, 0, 100, 10); + } +} + +// Fade: Initialize the fade function + +var fadeActive = new Array(); +var fadeQueue = new Array(); +var fadeTimer = new Array(); +var fadeClose = new Array(); +var fadeMode = new Array(); + +function fadeElementSetup(theID, fdStart, fdEnd, fdSteps, fdClose, fdMode) { + + // alert("Fading: "+theID+" Steps: "+fdSteps+" Mode: "+fdMode); + + if (fadeActive[theID] == true) { + // Already animating, queue up this command + fadeQueue[theID] = new Array(theID, fdStart, fdEnd, fdSteps); + } else { + fadeSteps = fdSteps; + fadeCurrent = 0; + fadeAmount = (fdStart - fdEnd) / fadeSteps; + fadeTimer[theID] = setInterval("fadeElement('"+theID+"', '"+fadeCurrent+"', '"+fadeAmount+"', '"+fadeSteps+"')", 15); + fadeActive[theID] = true; + fadeMode[theID] = fdMode; + + if (fdClose == 1) { + fadeClose[theID] = true; + } else { + fadeClose[theID] = false; + } + } +} + +// Fade: Do the fade. This function will call itself, modifying the parameters, so +// many instances can run concurrently. Can fade using opacity, or fade using a box-shadow. + +function fadeElement(theID, fadeCurrent, fadeAmount, fadeSteps) { + + if (fadeCurrent == fadeSteps) { + + // We're done, so clear. + + clearInterval(fadeTimer[theID]); + fadeActive[theID] = false; + fadeTimer[theID] = false; + + // Should we close it once the fade is complete? + + if (fadeClose[theID] == true) { + document.getElementById(theID).style.visibility = "hidden"; + } + + // Hang on.. did a command queue while we were working? If so, make it happen now + + if (fadeQueue[theID] && fadeQueue[theID] != false) { + fadeElementSetup(fadeQueue[theID][0], fadeQueue[theID][1], fadeQueue[theID][2], fadeQueue[theID][3]); + fadeQueue[theID] = false; + } + } else { + + fadeCurrent++; + + // Now actually do the fade adjustment. + + if (fadeMode[theID] == "shadow") { + + // Do a special fade on the webkit-box-shadow of the object + + if (fadeAmount < 0) { + document.getElementById(theID).style.webkitBoxShadow = shadowSettings + (Math.abs(fadeCurrent * fadeAmount)) + ')'; + } else { + document.getElementById(theID).style.webkitBoxShadow = shadowSettings + (100 - (fadeCurrent * fadeAmount)) + ')'; + } + + } else { + + // Set the opacity depending on if we're adding or subtracting (pos or neg) + + if (fadeAmount < 0) { + setOpacity(Math.abs(fadeCurrent * fadeAmount), theID); + } else { + setOpacity(100 - (fadeCurrent * fadeAmount), theID); + } + } + + // Keep going, and send myself the updated variables + clearInterval(fadeTimer[theID]); + fadeTimer[theID] = setInterval("fadeElement('"+theID+"', '"+fadeCurrent+"', '"+fadeAmount+"', '"+fadeSteps+"')", 15); + } +} + +//////////////////////////// +// +// UTILITY functions +// + +// Utility: Set the opacity, compatible with a number of browsers. Value from 0 to 100. + +function setOpacity(opacity, theID) { + + var object = document.getElementById(theID).style; + + // If it's 100, set it to 99 for Firefox. + + if (navigator.userAgent.indexOf("Firefox") != -1) { + if (opacity == 100) { opacity = 99.9999; } // This is majorly awkward + } + + // Multi-browser opacity setting + + object.filter = "alpha(opacity=" + opacity + ")"; // IE/Win + object.opacity = (opacity / 100); // Safari 1.2, Firefox+Mozilla + +} + +// Utility: Math functions for animation calucations - From http://www.robertpenner.com/easing/ +// +// t = time, b = begin, c = change, d = duration +// time = current frame, begin is fixed, change is basically finish - begin, duration is fixed (frames), + +function linear(t, b, c, d) +{ + return c*t/d + b; +} + +function sineInOut(t, b, c, d) +{ + return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; +} + +function cubicIn(t, b, c, d) { + return c*(t/=d)*t*t + b; +} + +function cubicOut(t, b, c, d) { + return c*((t=t/d-1)*t*t + 1) + b; +} + +function cubicInOut(t, b, c, d) +{ + if ((t/=d/2) < 1) return c/2*t*t*t + b; + return c/2*((t-=2)*t*t + 2) + b; +} + +function bounceOut(t, b, c, d) +{ + if ((t/=d) < (1/2.75)){ + return c*(7.5625*t*t) + b; + } else if (t < (2/2.75)){ + return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; + } else if (t < (2.5/2.75)){ + return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; + } else { + return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; + } +} + + +// Utility: Get the size of the window, and set myWidth and myHeight +// Credit to quirksmode.org + +function getSize() { + + // Window Size + + if (self.innerHeight) { // Everyone but IE + myWidth = window.innerWidth; + myHeight = window.innerHeight; + myScroll = window.pageYOffset; + } else if (document.documentElement && document.documentElement.clientHeight) { // IE6 Strict + myWidth = document.documentElement.clientWidth; + myHeight = document.documentElement.clientHeight; + myScroll = document.documentElement.scrollTop; + } else if (document.body) { // Other IE, such as IE7 + myWidth = document.body.clientWidth; + myHeight = document.body.clientHeight; + myScroll = document.body.scrollTop; + } + + // Page size w/offscreen areas + + if (window.innerHeight && window.scrollMaxY) { + myScrollWidth = document.body.scrollWidth; + myScrollHeight = window.innerHeight + window.scrollMaxY; + } else if (document.body.scrollHeight > document.body.offsetHeight) { // All but Explorer Mac + myScrollWidth = document.body.scrollWidth; + myScrollHeight = document.body.scrollHeight; + } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari + myScrollWidth = document.body.offsetWidth; + myScrollHeight = document.body.offsetHeight; + } +} + +// Utility: Get Shift Key Status +// IE events don't seem to get passed through the function, so grab it from the window. + +function getShift(evt) { + var shift = false; + if (! evt && window.event) { + shift = window.event.shiftKey; + } else if (evt) { + shift = evt.shiftKey; + if (shift) evt.stopPropagation(); // Prevents Firefox from doing shifty things + } + return shift; +} + +// Utility: Find the Y position of an element on a page. Return Y and X as an array + +function findElementPos(elemFind) +{ + var elemX = 0; + var elemY = 0; + do { + elemX += elemFind.offsetLeft; + elemY += elemFind.offsetTop; + } while ( elemFind = elemFind.offsetParent ) + + return Array(elemX, elemY); +} \ No newline at end of file diff --git a/js-global/FancyZoomHTML.js b/js-global/FancyZoomHTML.js new file mode 100644 index 0000000..7644a9a --- /dev/null +++ b/js-global/FancyZoomHTML.js @@ -0,0 +1,318 @@ +// FancyZoomHTML.js - v1.0 +// Used to draw necessary HTML elements for FancyZoom +// +// Copyright (c) 2008 Cabel Sasser / Panic Inc +// All rights reserved. + +function insertZoomHTML() { + + // All of this junk creates the three
's used to hold the closebox, image, and zoom shadow. + + var inBody = document.getElementsByTagName("body").item(0); + + // WAIT SPINNER + + var inSpinbox = document.createElement("div"); + inSpinbox.setAttribute('id', 'ZoomSpin'); + inSpinbox.style.position = 'absolute'; + inSpinbox.style.left = '10px'; + inSpinbox.style.top = '10px'; + inSpinbox.style.visibility = 'hidden'; + inSpinbox.style.zIndex = '525'; + inBody.insertBefore(inSpinbox, inBody.firstChild); + + var inSpinImage = document.createElement("img"); + inSpinImage.setAttribute('id', 'SpinImage'); + inSpinImage.setAttribute('src', zoomImagesURI+'zoom-spin-1.png'); + inSpinbox.appendChild(inSpinImage); + + // ZOOM IMAGE + // + //
+ // + //
+ // + //
+ //
+ + var inZoombox = document.createElement("div"); + inZoombox.setAttribute('id', 'ZoomBox'); + + inZoombox.style.position = 'absolute'; + inZoombox.style.left = '10px'; + inZoombox.style.top = '10px'; + inZoombox.style.visibility = 'hidden'; + inZoombox.style.zIndex = '499'; + + inBody.insertBefore(inZoombox, inSpinbox.nextSibling); + + var inImage1 = document.createElement("img"); + inImage1.onclick = function (event) { zoomOut(this, event); return false; }; + inImage1.setAttribute('src',zoomImagesURI+'spacer.gif'); + inImage1.setAttribute('id','ZoomImage'); + inImage1.setAttribute('border', '0'); + // inImage1.setAttribute('onMouseOver', 'zoomMouseOver();') + // inImage1.setAttribute('onMouseOut', 'zoomMouseOut();') + + // This must be set first, so we can later test it using webkitBoxShadow. + inImage1.setAttribute('style', '-webkit-box-shadow: '+shadowSettings+'0.0)'); + inImage1.style.display = 'block'; + inImage1.style.width = '10px'; + inImage1.style.height = '10px'; + inImage1.style.cursor = 'pointer'; // -webkit-zoom-out? + inZoombox.appendChild(inImage1); + + var inClosebox = document.createElement("div"); + inClosebox.setAttribute('id', 'ZoomClose'); + inClosebox.style.position = 'absolute'; + + // In MSIE, we need to put the close box inside the image. + // It's 2008 and I'm having to do a browser detect? Sigh. + if (browserIsIE) { + inClosebox.style.left = '-1px'; + inClosebox.style.top = '0px'; + } else { + inClosebox.style.left = '-15px'; + inClosebox.style.top = '-15px'; + } + + inClosebox.style.visibility = 'hidden'; + inZoombox.appendChild(inClosebox); + + var inImage2 = document.createElement("img"); + inImage2.onclick = function (event) { zoomOut(this, event); return false; }; + inImage2.setAttribute('src',zoomImagesURI+'closebox.png'); + inImage2.setAttribute('width','30'); + inImage2.setAttribute('height','30'); + inImage2.setAttribute('border','0'); + inImage2.style.cursor = 'pointer'; + inClosebox.appendChild(inImage2); + + // SHADOW + // Only draw the table-based shadow if the programatic webkitBoxShadow fails! + // Also, don't draw it if we're IE -- it wouldn't look quite right anyway. + + if (! document.getElementById('ZoomImage').style.webkitBoxShadow && ! browserIsIE) { + + // SHADOW BASE + + var inFixedBox = document.createElement("div"); + inFixedBox.setAttribute('id', 'ShadowBox'); + inFixedBox.style.position = 'absolute'; + inFixedBox.style.left = '50px'; + inFixedBox.style.top = '50px'; + inFixedBox.style.width = '100px'; + inFixedBox.style.height = '100px'; + inFixedBox.style.visibility = 'hidden'; + inFixedBox.style.zIndex = '498'; + inBody.insertBefore(inFixedBox, inZoombox.nextSibling); + + // SHADOW + // Now, the shadow table. Skip if not compatible, or irrevelant with -box-shadow. + + //
X + // + // + // + // + // + + var inShadowTable = document.createElement("table"); + inShadowTable.setAttribute('border', '0'); + inShadowTable.setAttribute('width', '100%'); + inShadowTable.setAttribute('height', '100%'); + inShadowTable.setAttribute('cellpadding', '0'); + inShadowTable.setAttribute('cellspacing', '0'); + inFixedBox.appendChild(inShadowTable); + + var inShadowTbody = document.createElement("tbody"); // Needed for IE (for HTML4). + inShadowTable.appendChild(inShadowTbody); + + var inRow1 = document.createElement("tr"); + inRow1.style.height = '25px'; + inShadowTbody.appendChild(inRow1); + + var inCol1 = document.createElement("td"); + inCol1.style.width = '27px'; + inRow1.appendChild(inCol1); + var inShadowImg1 = document.createElement("img"); + inShadowImg1.setAttribute('src', zoomImagesURI+'zoom-shadow1.png'); + inShadowImg1.setAttribute('width', '27'); + inShadowImg1.setAttribute('height', '25'); + inShadowImg1.style.display = 'block'; + inCol1.appendChild(inShadowImg1); + + var inCol2 = document.createElement("td"); + inCol2.setAttribute('background', zoomImagesURI+'zoom-shadow2.png'); + inRow1.appendChild(inCol2); + // inCol2.innerHTML = ' + // + // + // + // + + inRow2 = document.createElement("tr"); + inShadowTbody.appendChild(inRow2); + + var inCol4 = document.createElement("td"); + inCol4.setAttribute('background', zoomImagesURI+'zoom-shadow4.png'); + inRow2.appendChild(inCol4); + // inCol4.innerHTML = ' '; + var inSpacer2 = document.createElement("img"); + inSpacer2.setAttribute('src',zoomImagesURI+'spacer.gif'); + inSpacer2.setAttribute('height', '1'); + inSpacer2.setAttribute('width', '1'); + inSpacer2.style.display = 'block'; + inCol4.appendChild(inSpacer2); + + var inCol5 = document.createElement("td"); + inCol5.setAttribute('bgcolor', '#ffffff'); + inRow2.appendChild(inCol5); + // inCol5.innerHTML = ' '; + var inSpacer3 = document.createElement("img"); + inSpacer3.setAttribute('src',zoomImagesURI+'spacer.gif'); + inSpacer3.setAttribute('height', '1'); + inSpacer3.setAttribute('width', '1'); + inSpacer3.style.display = 'block'; + inCol5.appendChild(inSpacer3); + + var inCol6 = document.createElement("td"); + inCol6.setAttribute('background', zoomImagesURI+'zoom-shadow5.png'); + inRow2.appendChild(inCol6); + // inCol6.innerHTML = ' '; + var inSpacer4 = document.createElement("img"); + inSpacer4.setAttribute('src',zoomImagesURI+'spacer.gif'); + inSpacer4.setAttribute('height', '1'); + inSpacer4.setAttribute('width', '1'); + inSpacer4.style.display = 'block'; + inCol6.appendChild(inSpacer4); + + // + // + // + // + //
 
   
+ //  
+ + var inRow3 = document.createElement("tr"); + inRow3.style.height = '26px'; + inShadowTbody.appendChild(inRow3); + + var inCol7 = document.createElement("td"); + inCol7.style.width = '27px'; + inRow3.appendChild(inCol7); + var inShadowImg7 = document.createElement("img"); + inShadowImg7.setAttribute('src', zoomImagesURI+'zoom-shadow6.png'); + inShadowImg7.setAttribute('width', '27'); + inShadowImg7.setAttribute('height', '26'); + inShadowImg7.style.display = 'block'; + inCol7.appendChild(inShadowImg7); + + var inCol8 = document.createElement("td"); + inCol8.setAttribute('background', zoomImagesURI+'zoom-shadow7.png'); + inRow3.appendChild(inCol8); + // inCol8.innerHTML = ' '; + var inSpacer5 = document.createElement("img"); + inSpacer5.setAttribute('src',zoomImagesURI+'spacer.gif'); + inSpacer5.setAttribute('height', '1'); + inSpacer5.setAttribute('width', '1'); + inSpacer5.style.display = 'block'; + inCol8.appendChild(inSpacer5); + + var inCol9 = document.createElement("td"); + inCol9.style.width = '27px'; + inRow3.appendChild(inCol9); + var inShadowImg9 = document.createElement("img"); + inShadowImg9.setAttribute('src', zoomImagesURI+'zoom-shadow8.png'); + inShadowImg9.setAttribute('width', '27'); + inShadowImg9.setAttribute('height', '26'); + inShadowImg9.style.display = 'block'; + inCol9.appendChild(inShadowImg9); + } + + if (includeCaption) { + + // CAPTION + // + //
+ // + // + // + // + // + // + //
+ //
+ + var inCapDiv = document.createElement("div"); + inCapDiv.setAttribute('id', 'ZoomCapDiv'); + inCapDiv.style.position = 'absolute'; + inCapDiv.style.visibility = 'hidden'; + inCapDiv.style.marginLeft = 'auto'; + inCapDiv.style.marginRight = 'auto'; + inCapDiv.style.zIndex = '501'; + + inBody.insertBefore(inCapDiv, inZoombox.nextSibling); + + var inCapTable = document.createElement("table"); + inCapTable.setAttribute('border', '0'); + inCapTable.setAttribute('cellPadding', '0'); // Wow. These honestly need to + inCapTable.setAttribute('cellSpacing', '0'); // be intercapped to work in IE. WTF? + inCapDiv.appendChild(inCapTable); + + var inTbody = document.createElement("tbody"); // Needed for IE (for HTML4). + inCapTable.appendChild(inTbody); + + var inCapRow1 = document.createElement("tr"); + inTbody.appendChild(inCapRow1); + + var inCapCol1 = document.createElement("td"); + inCapCol1.setAttribute('align', 'right'); + inCapRow1.appendChild(inCapCol1); + var inCapImg1 = document.createElement("img"); + inCapImg1.setAttribute('src', zoomImagesURI+'zoom-caption-l.png'); + inCapImg1.setAttribute('width', '13'); + inCapImg1.setAttribute('height', '26'); + inCapImg1.style.display = 'block'; + inCapCol1.appendChild(inCapImg1); + + var inCapCol2 = document.createElement("td"); + inCapCol2.setAttribute('background', zoomImagesURI+'zoom-caption-fill.png'); + inCapCol2.setAttribute('id', 'ZoomCaption'); + inCapCol2.setAttribute('valign', 'middle'); + inCapCol2.style.fontSize = '14px'; + inCapCol2.style.fontFamily = 'Helvetica'; + inCapCol2.style.fontWeight = 'bold'; + inCapCol2.style.color = '#ffffff'; + inCapCol2.style.textShadow = '0px 2px 4px #000000'; + inCapCol2.style.whiteSpace = 'nowrap'; + inCapRow1.appendChild(inCapCol2); + + var inCapCol3 = document.createElement("td"); + inCapRow1.appendChild(inCapCol3); + var inCapImg2 = document.createElement("img"); + inCapImg2.setAttribute('src', zoomImagesURI+'zoom-caption-r.png'); + inCapImg2.setAttribute('width', '13'); + inCapImg2.setAttribute('height', '26'); + inCapImg2.style.display = 'block'; + inCapCol3.appendChild(inCapImg2); + } +} \ No newline at end of file