From 9cf66cc6c58407e89426de64e887e1d5149330e1 Mon Sep 17 00:00:00 2001 From: Vincent Vanwaelscappel Date: Mon, 17 Jun 2013 11:22:15 +0000 Subject: [PATCH 1/1] --- .htaccess | 21 + PROD | 1 + _index.html | 52 + images/arrow-button.png | Bin 0 -> 1370 bytes images/chapters-arrow.png | Bin 0 -> 608 bytes images/cur-zoom-in.png | Bin 0 -> 1018 bytes images/cur-zoom-out.png | Bin 0 -> 1093 bytes images/shadeleft-reflet.png | Bin 0 -> 6405 bytes images/shadeleft.png | Bin 0 -> 4032 bytes images/shaderight-reflet.png | Bin 0 -> 6421 bytes images/shaderight.png | Bin 0 -> 1369 bytes js/libs/Three.js | 794 ++ js/libs/cube/fb.js | 45 + js/libs/cube/util.js | 89 + js/libs/fix/detect-zoom.js | 242 + js/libs/fix/ios-orientation.js | 56 + js/libs/flashdetect.js | 200 + js/libs/fluidbook/fluidbook.background.js | 58 + js/libs/fluidbook/fluidbook.bookmarks.js | 440 + js/libs/fluidbook/fluidbook.cache.js | 62 + js/libs/fluidbook/fluidbook.coquillette.js | 65 + js/libs/fluidbook/fluidbook.desktop.js | 113 + js/libs/fluidbook/fluidbook.help.js | 235 + js/libs/fluidbook/fluidbook.js | 1305 +++ js/libs/fluidbook/fluidbook.l10n.js | 65 + js/libs/fluidbook/fluidbook.loader.js | 247 + js/libs/fluidbook/fluidbook.nav.js | 186 + js/libs/fluidbook/fluidbook.pad.js | 73 + js/libs/fluidbook/fluidbook.resize.js | 269 + js/libs/fluidbook/fluidbook.search.js | 109 + js/libs/fluidbook/fluidbook.service.js | 30 + js/libs/fluidbook/fluidbook.stats.js | 66 + js/libs/fluidbook/fluidbook.support.js | 130 + js/libs/fluidbook/fluidbook.touch.js | 219 + js/libs/fluidbook/fluidbook.utils.js | 40 + js/libs/fluidbook/fluidbook.video.js | 163 + js/libs/fluidbook/fluidbook.viewport.js | 27 + js/libs/fluidbook/views/fluidbook.chapters.js | 95 + js/libs/fluidbook/views/fluidbook.index.js | 67 + js/libs/gsap/TimelineLite.js | 611 ++ js/libs/gsap/TimelineMax.js | 1045 ++ js/libs/gsap/TweenLite.js | 1604 +++ js/libs/gsap/TweenMax.js | 6538 ++++++++++++ js/libs/gsap/easing/EasePack.js | 343 + js/libs/gsap/jquery.gsap.js | 167 + js/libs/gsap/plugins/AttrPlugin.js | 49 + js/libs/gsap/plugins/BezierPlugin.js | 575 ++ js/libs/gsap/plugins/CSSPlugin.js | 2213 +++++ js/libs/gsap/plugins/CSSRulePlugin.js | 94 + js/libs/gsap/plugins/ColorPropsPlugin.js | 122 + .../gsap/plugins/DirectionalRotationPlugin.js | 79 + js/libs/gsap/plugins/EaselPlugin.js | 291 + js/libs/gsap/plugins/KineticPlugin.js | 298 + js/libs/gsap/plugins/RaphaelPlugin.js | 367 + js/libs/gsap/plugins/RoundPropsPlugin.js | 73 + js/libs/gsap/plugins/ScrollToPlugin.js | 112 + js/libs/gsap/plugins/TEMPLATE_Plugin.js | 74 + js/libs/gsap/plugins/TextPlugin.js | 97 + js/libs/jquery/jquery.hashchange.js | 290 + js/libs/jquery/jquery.js | 8842 +++++++++++++++++ js/libs/jquery/jquery.localscroll.js | 133 + js/libs/jquery/jquery.migrate.js | 521 + js/libs/jquery/jquery.mousewheel.js | 84 + js/libs/jquery/jquery.scrollto.js | 218 + js/libs/jquery/jquery.transform.js | 1951 ++++ js/libs/jquery/jquery.transit.js | 674 ++ js/libs/json2.js | 486 + js/libs/modernizr/modernizr.js | 815 ++ js/libs/modernizr/tests.js | 32 + js/libs/phonegap/2.8.1/cordova-android.js | 6878 +++++++++++++ js/libs/phonegap/2.8.1/cordova-ios.js | 6452 ++++++++++++ js/libs/phonegap/plugins/android/webintent.js | 71 + .../phonegap/plugins/ios/ExternalFileUtil.js | 18 + js/main.js | 289 + js/tester.js | 31 + js/widget.js | 359 + plugins/com/promotal/catalogue/plugin.css | 105 + plugins/com/promotal/catalogue/plugin.js | 273 + style/fluidbook.css | 1323 +++ style/fonts/Ubuntu-B-webfont.ttf | Bin 0 -> 44496 bytes style/fonts/Ubuntu-B-webfont.woff | Bin 0 -> 25168 bytes style/fonts/Ubuntu-BI-webfont.ttf | Bin 0 -> 52880 bytes style/fonts/Ubuntu-BI-webfont.woff | Bin 0 -> 27996 bytes style/fonts/Ubuntu-L-webfont.ttf | Bin 0 -> 46168 bytes style/fonts/Ubuntu-L-webfont.woff | Bin 0 -> 25684 bytes style/fonts/Ubuntu-LI-webfont.ttf | Bin 0 -> 55128 bytes style/fonts/Ubuntu-LI-webfont.woff | Bin 0 -> 29200 bytes style/fonts/Ubuntu-M-webfont.ttf | Bin 0 -> 44176 bytes style/fonts/Ubuntu-M-webfont.woff | Bin 0 -> 25756 bytes style/fonts/Ubuntu-MI-webfont.ttf | Bin 0 -> 52764 bytes style/fonts/Ubuntu-MI-webfont.woff | Bin 0 -> 28500 bytes style/fonts/Ubuntu-R-webfont.ttf | Bin 0 -> 45652 bytes style/fonts/Ubuntu-R-webfont.woff | Bin 0 -> 25816 bytes style/fonts/Ubuntu-RI-webfont.ttf | Bin 0 -> 55748 bytes style/fonts/Ubuntu-RI-webfont.woff | Bin 0 -> 28888 bytes style/fonts/slkscr-webfont.ttf | Bin 0 -> 17172 bytes style/fonts/slkscr-webfont.woff | Bin 0 -> 5892 bytes style/widget.css | 161 + swf/_src/Fluidbook Video Player.as3proj | 90 + web.config | 35 + widget.html | 17 + 101 files changed, 50464 insertions(+) create mode 100644 .htaccess create mode 100644 PROD create mode 100644 _index.html create mode 100644 images/arrow-button.png create mode 100644 images/chapters-arrow.png create mode 100644 images/cur-zoom-in.png create mode 100644 images/cur-zoom-out.png create mode 100644 images/shadeleft-reflet.png create mode 100644 images/shadeleft.png create mode 100644 images/shaderight-reflet.png create mode 100644 images/shaderight.png create mode 100644 js/libs/Three.js create mode 100644 js/libs/cube/fb.js create mode 100644 js/libs/cube/util.js create mode 100644 js/libs/fix/detect-zoom.js create mode 100644 js/libs/fix/ios-orientation.js create mode 100644 js/libs/flashdetect.js create mode 100644 js/libs/fluidbook/fluidbook.background.js create mode 100644 js/libs/fluidbook/fluidbook.bookmarks.js create mode 100644 js/libs/fluidbook/fluidbook.cache.js create mode 100644 js/libs/fluidbook/fluidbook.coquillette.js create mode 100644 js/libs/fluidbook/fluidbook.desktop.js create mode 100644 js/libs/fluidbook/fluidbook.help.js create mode 100644 js/libs/fluidbook/fluidbook.js create mode 100644 js/libs/fluidbook/fluidbook.l10n.js create mode 100644 js/libs/fluidbook/fluidbook.loader.js create mode 100644 js/libs/fluidbook/fluidbook.nav.js create mode 100644 js/libs/fluidbook/fluidbook.pad.js create mode 100644 js/libs/fluidbook/fluidbook.resize.js create mode 100644 js/libs/fluidbook/fluidbook.search.js create mode 100644 js/libs/fluidbook/fluidbook.service.js create mode 100644 js/libs/fluidbook/fluidbook.stats.js create mode 100644 js/libs/fluidbook/fluidbook.support.js create mode 100644 js/libs/fluidbook/fluidbook.touch.js create mode 100644 js/libs/fluidbook/fluidbook.utils.js create mode 100644 js/libs/fluidbook/fluidbook.video.js create mode 100644 js/libs/fluidbook/fluidbook.viewport.js create mode 100644 js/libs/fluidbook/views/fluidbook.chapters.js create mode 100644 js/libs/fluidbook/views/fluidbook.index.js create mode 100644 js/libs/gsap/TimelineLite.js create mode 100644 js/libs/gsap/TimelineMax.js create mode 100644 js/libs/gsap/TweenLite.js create mode 100644 js/libs/gsap/TweenMax.js create mode 100644 js/libs/gsap/easing/EasePack.js create mode 100644 js/libs/gsap/jquery.gsap.js create mode 100644 js/libs/gsap/plugins/AttrPlugin.js create mode 100644 js/libs/gsap/plugins/BezierPlugin.js create mode 100644 js/libs/gsap/plugins/CSSPlugin.js create mode 100644 js/libs/gsap/plugins/CSSRulePlugin.js create mode 100644 js/libs/gsap/plugins/ColorPropsPlugin.js create mode 100644 js/libs/gsap/plugins/DirectionalRotationPlugin.js create mode 100644 js/libs/gsap/plugins/EaselPlugin.js create mode 100644 js/libs/gsap/plugins/KineticPlugin.js create mode 100644 js/libs/gsap/plugins/RaphaelPlugin.js create mode 100644 js/libs/gsap/plugins/RoundPropsPlugin.js create mode 100644 js/libs/gsap/plugins/ScrollToPlugin.js create mode 100644 js/libs/gsap/plugins/TEMPLATE_Plugin.js create mode 100644 js/libs/gsap/plugins/TextPlugin.js create mode 100644 js/libs/jquery/jquery.hashchange.js create mode 100644 js/libs/jquery/jquery.js create mode 100644 js/libs/jquery/jquery.localscroll.js create mode 100644 js/libs/jquery/jquery.migrate.js create mode 100644 js/libs/jquery/jquery.mousewheel.js create mode 100644 js/libs/jquery/jquery.scrollto.js create mode 100644 js/libs/jquery/jquery.transform.js create mode 100644 js/libs/jquery/jquery.transit.js create mode 100644 js/libs/json2.js create mode 100644 js/libs/modernizr/modernizr.js create mode 100644 js/libs/modernizr/tests.js create mode 100644 js/libs/phonegap/2.8.1/cordova-android.js create mode 100644 js/libs/phonegap/2.8.1/cordova-ios.js create mode 100644 js/libs/phonegap/plugins/android/webintent.js create mode 100644 js/libs/phonegap/plugins/ios/ExternalFileUtil.js create mode 100644 js/main.js create mode 100644 js/tester.js create mode 100644 js/widget.js create mode 100644 plugins/com/promotal/catalogue/plugin.css create mode 100644 plugins/com/promotal/catalogue/plugin.js create mode 100644 style/fluidbook.css create mode 100644 style/fonts/Ubuntu-B-webfont.ttf create mode 100644 style/fonts/Ubuntu-B-webfont.woff create mode 100644 style/fonts/Ubuntu-BI-webfont.ttf create mode 100644 style/fonts/Ubuntu-BI-webfont.woff create mode 100644 style/fonts/Ubuntu-L-webfont.ttf create mode 100644 style/fonts/Ubuntu-L-webfont.woff create mode 100644 style/fonts/Ubuntu-LI-webfont.ttf create mode 100644 style/fonts/Ubuntu-LI-webfont.woff create mode 100644 style/fonts/Ubuntu-M-webfont.ttf create mode 100644 style/fonts/Ubuntu-M-webfont.woff create mode 100644 style/fonts/Ubuntu-MI-webfont.ttf create mode 100644 style/fonts/Ubuntu-MI-webfont.woff create mode 100644 style/fonts/Ubuntu-R-webfont.ttf create mode 100644 style/fonts/Ubuntu-R-webfont.woff create mode 100644 style/fonts/Ubuntu-RI-webfont.ttf create mode 100644 style/fonts/Ubuntu-RI-webfont.woff create mode 100644 style/fonts/slkscr-webfont.ttf create mode 100644 style/fonts/slkscr-webfont.woff create mode 100644 style/widget.css create mode 100644 swf/_src/Fluidbook Video Player.as3proj create mode 100644 web.config create mode 100644 widget.html diff --git a/.htaccess b/.htaccess new file mode 100644 index 00000000..f99e52e4 --- /dev/null +++ b/.htaccess @@ -0,0 +1,21 @@ + + AddType video/ogg .ogm + AddType video/ogg .ogv + AddType video/ogg .ogg + AddType video/mp4 .mp4 + AddType video/webm .webm + AddType image/svg+xml .svg + AddType image/svg+xml .svgz + AddType application/json .json + AddType application/vnd.ms-fontobject .eot + AddType application/octet-stream .otf + AddType application/octet-stream .ttf + AddType application/x-font-woff .woff + AddType text/cache-manifest .appcache + + AddEncoding gzip svgz + + + + ExpiresByType text/cache-manifest "access plus 0 seconds" + \ No newline at end of file diff --git a/PROD b/PROD new file mode 100644 index 00000000..e5517e4c --- /dev/null +++ b/PROD @@ -0,0 +1 @@ +HEAD \ No newline at end of file diff --git a/_index.html b/_index.html new file mode 100644 index 00000000..60bb4781 --- /dev/null +++ b/_index.html @@ -0,0 +1,52 @@ + + + + <!-- $titre --> + + + + + + + + + + + +
+ +
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+ + \ No newline at end of file diff --git a/images/arrow-button.png b/images/arrow-button.png new file mode 100644 index 0000000000000000000000000000000000000000..e4ff2f8227ae0cef7321e429dda09460b2a2055b GIT binary patch literal 1370 zcmeAS@N?(olHy`uVBq!ia0vp^;y^6S!3HF&cTd{}q$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~;1Ffc1*hD4M^`1)8S=jZArg4F0$^BXQ!4Z zB&DWj=GiK}-@RW+Av48RDcsc8z_-9TH6zobswg$M$}c3jDm&RSMakYy!KT6rXh3di zNuokUZcbjYRfVk**jy_h8zii+qySb@l5ML5aa4qFfP!;=QL2Keo`G(%fti7VnW3Jc zv5C34xsHO7fuVuEfswwUk*=Y+m9dePfq?=PC;@FNN=dT{a&d#&1?1T(Wt5Z@Sn2DR zmzV368|&p4rRy77T3Uk4Ff!5ws?aU2%qvN((9J7WhMC}!TAW;zSx}OhpQivaF)=B> zw8T~k=u(Imatq+b<`qMO2^e7d6^RA4NhK8<27G`E{F6NE~&ITqf zt_F@~FugAM$)&lec_lEtDR8~!1~~PC5<+eP&}Ns^qRg_?6t|-MTm`U)tuk@D#RaE% zP`xQQ-D2j7Q?EYIG5VlrMT%ya5HRh4nD9gkr%@jtp71@q$MXIW*C)dX9 zy=ADV=qPvMIa^ZL3Mn=(od+{53Kv~nAHP42Y45N9$NS~iTUlGrZG7b9aHdTxM&n=; zzp+EJ^MiYPtA+n7H=dtwf8WsD{5sRAkIJm_C)=81&h1Y>KX1$bj0YbdAD`V=RHQK9 zQPy$OLk0cfMxM&=@9w&maQn@%xX3nTGE0)*mk;X43fMA^aO%hIG7-D`VSoMqfAh@q z<19SnZ2xqc&f$Fa>-qWl@^0H7{Qmx4zd`c^gOrWW5~*_xrBf@Mot;mB)GvxI`26f_ zT)+|Kc3Z{67cUzuo-}C^hqAJ=+byDSe_ifBf8FaBFEpH+ z`<^5)vUZ+W7rVRbA}?Fo8voML(gi%K9K98nCNJ8tW5=cI>*M7YN$)Fse2izo9tnZs z1?*dk6l=D+{^ReQ4UjvCr*ay>gp4+k2cQWkMH#8dD!D&Dqt*P l>~#5ayv9HOJYN=p1O}dkO&Q6j)xUyDJ5N_Xmvv4FO#s5%_5%O_ literal 0 HcmV?d00001 diff --git a/images/chapters-arrow.png b/images/chapters-arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..7dad456582b6a8eb9027d8289846feb55054ce32 GIT binary patch literal 608 zcmV-m0-ybfP)P000>X1^@s6#OZ}&0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!0!c(cRCwCFR!d6)Q52q;EbVDzX(_g7 zCAA14an(j_lelsd{e*UITv@Gb74#njmkELN16-s;3thOd2z)FGLQ;vG=GnP$h1+c! zXB_gt#|-xj=R4=z^B7K5Rp!58V>E9m<4VR1C>VzGFpYDlS6I!DpcX){AIjAqH@as_(5 z-V;qC%QBxzrS@>OX_6S}c*Lr7I-RdZqjCSs1CF!DVzFK93_DJrFu3WK6Ny9^s;o~( z0(bQqkH-Ugkr=rXRL0(Vy`I%bm6*+Dk3sLkjXT!GqbQuoWO5%Fq)E!<@&)exSu53r zD#p`lwXSJ`cDsEGx=l3KwC0$pj`w=Keo2x(sYZN8y@R6sYm%EGu>;n5o_`@nN+y#z z&>JacNsyP$TrPLm?RM_~5BYrl2+mgZh9gbFYLqOweuoRoL3k|ycz~$4xJbLBHlsoq uCHsY0cA@!-J+f_f12(wm|O>!muICaDMG!t6ZwzVHA3fBw0a&kgr< z9q6JcswX?56v(_M7@-~Hf9S_=jZFJ-x`ap3IId|fq*4YdLy)z!30Q!dQNQ#8CMaqv zFpDKzQqM>_vKTGEFuvswHbo@{eMi$LAqHhQVcJRh>yu>~m`0Kwi>jRJ$gpCL%(!rL zCRfyFCUw!E2Ty^7FA)I?Vh#A#lPx{-qAv}J9tSte32 z*4G@CXSg7x7Eo3H54Ef|+QS97>Gz+)Ua{^#wg5d;b#-!aN0MErVdNGOnrc-s zUqKjo732VUGz!K{+dwt1fmT&1YkOF;b(mF>G~qL*X-GqSEEAQ}X*niFc|Ogh(y53j zrbStda;X79XmJ&!S1oAc7T4J1W;$|%Mz9)cLdajodz-m>?2AGI{MbVCRoTbSEDFq>QG{kSq*o=ZI6zWTQB@%NR7Zy4!x zxAkp(`PsYP^Mjv{ej133yfVtu^Yxp1jm6=$o_o~6`@2d;cm7V*331fZ!}DKeSKq%3 OUSl?$Q|=C3xbg?KzDLCX literal 0 HcmV?d00001 diff --git a/images/cur-zoom-out.png b/images/cur-zoom-out.png new file mode 100644 index 0000000000000000000000000000000000000000..c8c14850c75fe2e30afec34d888c3abed8b008c5 GIT binary patch literal 1093 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 literal 0 HcmV?d00001 diff --git a/images/shaderight-reflet.png b/images/shaderight-reflet.png new file mode 100644 index 0000000000000000000000000000000000000000..7b5dd6ef6d11d782615249aeaa581205931ae128 GIT binary patch literal 6421 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 literal 0 HcmV?d00001 diff --git a/images/shaderight.png b/images/shaderight.png new file mode 100644 index 0000000000000000000000000000000000000000..49a0e678107f938ca6b81f7f16b589255a8641d9 GIT binary patch literal 1369 zcmeAS@N?(olHy`uVBq!ia0vp^OBfiK=5eqAS=y&JECy1NC9V-A!TD(=<%vb942~)J zNvR5+xryniL8*x;m4zo$Z5S9>etWt&hE&{obIF^F$xy)c;-$AKvG3}aWiFoDcgcyv zLfn$Q>mQH&_Ykk0ciN&}m)_aCbz5(CzoPMdal!MC#oq@-Okd z>-YZ*PZw735Kw7iaa2N3972vw3W6%gl;Z>rA(l=BWQw!NWrBhS3krp963|?9lR)O8 znFKNy-6WPwCRC$=JQPPldB~20IvLrKP$#1}5^65FZuMiu6{1-oD!M>16&255)/255;this.g=(a>>8&255)/255;this.b=(a&255)/255;return this},getHex:function(){return Math.floor(255*this.r)<<16^Math.floor(255*this.g)<<8^Math.floor(255*this.b)},getContextStyle:function(){return"rgb("+Math.floor(255*this.r)+","+Math.floor(255*this.g)+","+Math.floor(255*this.b)+")"},clone:function(){return(new THREE.Color).setRGB(this.r,this.g,this.b)}};THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0}; +THREE.Vector2.prototype={constructor:THREE.Vector2,set:function(a,b){this.x=a;this.y=b;return this},copy:function(a){this.x=a.x;this.y=a.y;return this},clone:function(){return new THREE.Vector2(this.x,this.y)},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},addSelf:function(a){this.x+=a.x;this.y+=a.y;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},subSelf:function(a){this.x-=a.x;this.y-=a.y;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;return this}, +divideScalar:function(a){a?(this.x/=a,this.y/=a):this.set(0,0);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.lengthSq())},normalize:function(){return this.divideScalar(this.length())},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){var b=this.x-a.x,a=this.y-a.y;return b*b+a*a},setLength:function(a){return this.normalize().multiplyScalar(a)}, +lerpSelf:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;return this},equals:function(a){return a.x===this.x&&a.y===this.y},isZero:function(){return 1.0E-4>this.lengthSq()}};THREE.Vector3=function(a,b,c){this.x=a||0;this.y=b||0;this.z=c||0}; +THREE.Vector3.prototype={constructor:THREE.Vector3,set:function(a,b,c){this.x=a;this.y=b;this.z=c;return this},setX:function(a){this.x=a;return this},setY:function(a){this.y=a;return this},setZ:function(a){this.z=a;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addSelf:function(a){this.x+=a.x;this.y+=a.y;this.z+=a.z;return this}, +addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},subSelf:function(a){this.x-=a.x;this.y-=a.y;this.z-=a.z;return this},multiply:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},multiplySelf:function(a){this.x*=a.x;this.y*=a.y;this.z*=a.z;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;return this},divideSelf:function(a){this.x/=a.x;this.y/=a.y;this.z/=a.z;return this}, +divideScalar:function(a){a?(this.x/=a,this.y/=a,this.z/=a):this.z=this.y=this.x=0;return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.lengthSq())},lengthManhattan:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.normalize().multiplyScalar(a)}, +lerpSelf:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;return this},cross:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},crossSelf:function(a){var b=this.x,c=this.y,d=this.z;this.x=c*a.z-d*a.y;this.y=d*a.x-b*a.z;this.z=b*a.y-c*a.x;return this},distanceTo:function(a){return Math.sqrt(this.distanceToSquared(a))},distanceToSquared:function(a){return(new THREE.Vector3).sub(this,a).lengthSq()},getPositionFromMatrix:function(a){this.x= +a.n14;this.y=a.n24;this.z=a.n34;return this},getRotationFromMatrix:function(a,b){var c=b?b.x:1,d=b?b.y:1,f=b?b.z:1,g=a.n11/c,e=a.n12/d,c=a.n21/c,d=a.n22/d,h=a.n23/f,i=a.n33/f;this.y=Math.asin(a.n13/f);f=Math.cos(this.y);1.0E-5this.lengthSq()}};THREE.Vector4=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=void 0!==d?d:1}; +THREE.Vector4.prototype={constructor:THREE.Vector4,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=void 0!==a.w?a.w:1;return this},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},addSelf:function(a){this.x+=a.x;this.y+=a.y;this.z+=a.z;this.w+=a.w;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y; +this.z=a.z-b.z;this.w=a.w-b.w;return this},subSelf:function(a){this.x-=a.x;this.y-=a.y;this.z-=a.z;this.w-=a.w;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;this.w*=a;return this},divideScalar:function(a){a?(this.x/=a,this.y/=a,this.z/=a,this.w/=a):(this.z=this.y=this.x=0,this.w=1);return this},negate:function(){return this.multiplyScalar(-1)},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z+this.w*a.w},lengthSq:function(){return this.dot(this)},length:function(){return Math.sqrt(this.lengthSq())}, +normalize:function(){return this.divideScalar(this.length())},setLength:function(a){return this.normalize().multiplyScalar(a)},lerpSelf:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;this.w+=(a.w-this.w)*b;return this}};THREE.Frustum=function(){this.planes=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4]}; +THREE.Frustum.prototype.setFromMatrix=function(a){var b,c=this.planes;c[0].set(a.n41-a.n11,a.n42-a.n12,a.n43-a.n13,a.n44-a.n14);c[1].set(a.n41+a.n11,a.n42+a.n12,a.n43+a.n13,a.n44+a.n14);c[2].set(a.n41+a.n21,a.n42+a.n22,a.n43+a.n23,a.n44+a.n24);c[3].set(a.n41-a.n21,a.n42-a.n22,a.n43-a.n23,a.n44-a.n24);c[4].set(a.n41-a.n31,a.n42-a.n32,a.n43-a.n33,a.n44-a.n34);c[5].set(a.n41+a.n31,a.n42+a.n32,a.n43+a.n33,a.n44+a.n34);for(a=0;6>a;a++)b=c[a],b.divideScalar(Math.sqrt(b.x*b.x+b.y*b.y+b.z*b.z))}; +THREE.Frustum.prototype.contains=function(a){for(var b=this.planes,c=a.matrixWorld,d=THREE.Frustum.__v1.set(c.getColumnX().length(),c.getColumnY().length(),c.getColumnZ().length()),d=-a.geometry.boundingSphere.radius*Math.max(d.x,Math.max(d.y,d.z)),f=0;6>f;f++)if(a=b[f].x*c.n14+b[f].y*c.n24+b[f].z*c.n34+b[f].w,a<=d)return!1;return!0};THREE.Frustum.__v1=new THREE.Vector3; +THREE.Ray=function(a,b){function c(a,b,c){p.sub(c,a);s=p.dot(b);t=n.add(a,r.copy(b).multiplyScalar(s));return w=c.distanceTo(t)}function d(a,b,c,d){p.sub(d,b);n.sub(c,b);r.sub(a,b);u=p.dot(p);v=p.dot(n);A=p.dot(r);F=n.dot(n);B=n.dot(r);D=1/(u*F-v*v);H=(F*A-v*B)*D;I=(u*B-v*A)*D;return 0<=H&&0<=I&&1>H+I}this.origin=a||new THREE.Vector3;this.direction=b||new THREE.Vector3;this.intersectObjects=function(a){var b,c,d=[];for(b=0,c=a.length;ba.scale.x)return[];b={distance:p,point:a.position,face:null,object:a}; +n.push(b)}else if(a instanceof THREE.Mesh){var p=c(this.origin,this.direction,a.matrixWorld.getPosition()),r=THREE.Frustum.__v1.set(a.matrixWorld.getColumnX().length(),a.matrixWorld.getColumnY().length(),a.matrixWorld.getColumnZ().length());if(p>a.geometry.boundingSphere.radius*Math.max(r.x,Math.max(r.y,r.z)))return n;var s,l,t=a.geometry,u=t.vertices,E;a.matrixRotationWorld.extractRotation(a.matrixWorld);for(p=0,r=t.faces.length;pl)&&(a.doubleSided||(a.flipSided?0s))))if(o.add(j,k.multiplyScalar(l)),b instanceof THREE.Face3)g=E.multiplyVector3(g.copy(u[b.a].position)),e=E.multiplyVector3(e.copy(u[b.b].position)),h=E.multiplyVector3(h.copy(u[b.c].position)),d(o,g,e,h)&&(b={distance:j.distanceTo(o),point:o.clone(),face:b,object:a},n.push(b));else if(b instanceof +THREE.Face4&&(g=E.multiplyVector3(g.copy(u[b.a].position)),e=E.multiplyVector3(e.copy(u[b.b].position)),h=E.multiplyVector3(h.copy(u[b.c].position)),i=E.multiplyVector3(i.copy(u[b.d].position)),d(o,g,e,i)||d(o,e,h,i)))b={distance:j.distanceTo(o),point:o.clone(),face:b,object:a},n.push(b)}return n};var p=new THREE.Vector3,n=new THREE.Vector3,r=new THREE.Vector3,s,t,w,u,v,A,F,B,D,H,I}; +THREE.Rectangle=function(){function a(){g=d-b;e=f-c}var b,c,d,f,g,e,h=!0;this.getX=function(){return b};this.getY=function(){return c};this.getWidth=function(){return g};this.getHeight=function(){return e};this.getLeft=function(){return b};this.getTop=function(){return c};this.getRight=function(){return d};this.getBottom=function(){return f};this.set=function(g,e,k,q){h=!1;b=g;c=e;d=k;f=q;a()};this.addPoint=function(g,e){h?(h=!1,b=g,c=e,d=g,f=e):(b=bg?d:g,f=f>e?f:e);a()};this.add3Points= +function(g,e,k,q,m,o){h?(h=!1,b=gk?g>m?g:m:k>m?k:m,f=e>q?e>o?e:o:q>o?q:o):(b=gk?g>m?g>d?g:d:m>d?m:d:k>m?k>d?k:d:m>d?m:d,f=e>q?e>o?e>f?e:f:o>f?o:f:q>o?q>f?q:f:o>f?o:f);a()};this.addRectangle=function(g){h?(h=!1,b=g.getLeft(),c=g.getTop(),d=g.getRight(),f=g.getBottom()):(b=bg.getRight()?d:g.getRight(),f=f> +g.getBottom()?f:g.getBottom());a()};this.inflate=function(g){b-=g;c-=g;d+=g;f+=g;a()};this.minSelf=function(g){b=b>g.getLeft()?b:g.getLeft();c=c>g.getTop()?c:g.getTop();d=da.getRight()||fa.getBottom()?!1:!0};this.empty=function(){h=!0;f=d=c=b=0;a()};this.isEmpty=function(){return h}}; +THREE.Math={clamp:function(a,b,c){return ac?c:a},clampBottom:function(a,b){return aa?-1:0f&&0>g||0>e&&0>h)return!1;0>f?c=Math.max(c,f/(f-g)):0>g&&(d=Math.min(d,f/(f-g)));0>e?c=Math.max(c,e/(e-h)):0>h&&(d=Math.min(d,e/(e-h)));if(de&&h.positionScreen.z(ka.positionScreen.x-R.positionScreen.x)*(ca.positionScreen.y-R.positionScreen.y)-(ka.positionScreen.y-R.positionScreen.y)*(ca.positionScreen.x-R.positionScreen.x), +N.doubleSided||l!=N.flipSided)ia=m[q]=m[q]||new THREE.RenderableFace3,q++,k=ia,k.v1.copy(R),k.v2.copy(ca),k.v3.copy(ka);else continue;else continue;else if(E instanceof THREE.Face4)if(R=j[E.a],ca=j[E.b],ka=j[E.c],ia=j[E.d],R.visible&&ca.visible&&ka.visible&&ia.visible)if(l=0>(ia.positionScreen.x-R.positionScreen.x)*(ca.positionScreen.y-R.positionScreen.y)-(ia.positionScreen.y-R.positionScreen.y)*(ca.positionScreen.x-R.positionScreen.x)||0>(ca.positionScreen.x-ka.positionScreen.x)*(ia.positionScreen.y- +ka.positionScreen.y)-(ca.positionScreen.y-ka.positionScreen.y)*(ia.positionScreen.x-ka.positionScreen.x),N.doubleSided||l!=N.flipSided)Ja=p[o]=p[o]||new THREE.RenderableFace4,o++,k=Ja,k.v1.copy(R),k.v2.copy(ca),k.v3.copy(ka),k.v4.copy(ia);else continue;else continue;k.normalWorld.copy(E.normal);!l&&(N.flipSided||N.doubleSided)&&k.normalWorld.negate();U.multiplyVector3(k.normalWorld);k.centroidWorld.copy(E.centroid);aa.multiplyVector3(k.centroidWorld);k.centroidScreen.copy(k.centroidWorld);B.multiplyVector3(k.centroidScreen); +ka=E.vertexNormals;for(R=0,ca=ka.length;RF.z))e=u[w]=u[w]||new THREE.RenderableParticle,w++,t=e,t.x=F.x/F.w,t.y=F.y/F.w,t.z=F.z,t.rotation=N.rotation.z,t.scale.x=N.scale.x*Math.abs(t.x-(F.x+f.projectionMatrix.n11)/(F.w+f.projectionMatrix.n14)),t.scale.y=N.scale.y*Math.abs(t.y-(F.y+f.projectionMatrix.n22)/(F.w+f.projectionMatrix.n24)),t.material=N.material,v.elements.push(t);g&&v.elements.sort(c);return v}}; +THREE.Quaternion=function(a,b,c,d){this.x=a||0;this.y=b||0;this.z=c||0;this.w=void 0!==d?d:1}; +THREE.Quaternion.prototype={constructor:THREE.Quaternion,set:function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.w=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w;return this},clone:function(){return new THREE.Quaternion(this.x,this.y,this.z,this.w)},setFromEuler:function(a){var b=Math.PI/360,c=a.x*b,d=a.y*b,f=a.z*b,a=Math.cos(d),d=Math.sin(d),b=Math.cos(-f),f=Math.sin(-f),g=Math.cos(c),c=Math.sin(c),e=a*b,h=d*f;this.w=e*g-h*c;this.x=e*c+h*g;this.y=d*b*g+a*f*c;this.z=a*f* +g-d*b*c;return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c);this.x=a.x*d;this.y=a.y*d;this.z=a.z*d;this.w=Math.cos(c);return this},setFromRotationMatrix:function(a){var b=Math.pow(a.determinant(),1/3);this.w=Math.sqrt(Math.max(0,b+a.n11+a.n22+a.n33))/2;this.x=Math.sqrt(Math.max(0,b+a.n11-a.n22-a.n33))/2;this.y=Math.sqrt(Math.max(0,b-a.n11+a.n22-a.n33))/2;this.z=Math.sqrt(Math.max(0,b-a.n11-a.n22+a.n33))/2;this.x=0>a.n32-a.n23?-Math.abs(this.x):Math.abs(this.x);this.y=0>a.n13-a.n31? +-Math.abs(this.y):Math.abs(this.y);this.z=0>a.n21-a.n12?-Math.abs(this.z):Math.abs(this.z);this.normalize();return this},calculateW:function(){this.w=-Math.sqrt(Math.abs(1-this.x*this.x-this.y*this.y-this.z*this.z));return this},inverse:function(){this.x*=-1;this.y*=-1;this.z*=-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a=Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);0===a?this.w=this.z= +this.y=this.x=0:(a=1/a,this.x*=a,this.y*=a,this.z*=a,this.w*=a);return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,f=this.w,g=a.x,e=a.y,h=a.z,a=a.w;this.x=b*a+f*g+c*h-d*e;this.y=c*a+f*e+d*g-b*h;this.z=d*a+f*h+b*e-c*g;this.w=f*a-b*g-c*e-d*h;return this},multiply:function(a,b){this.x=a.x*b.w+a.y*b.z-a.z*b.y+a.w*b.x;this.y=-a.x*b.z+a.y*b.w+a.z*b.x+a.w*b.y;this.z=a.x*b.y-a.y*b.x+a.z*b.w+a.w*b.z;this.w=-a.x*b.x-a.y*b.y-a.z*b.z+a.w*b.w;return this},multiplyVector3:function(a,b){b||(b= +a);var c=a.x,d=a.y,f=a.z,g=this.x,e=this.y,h=this.z,i=this.w,j=i*c+e*f-h*d,k=i*d+h*c-g*f,q=i*f+g*d-e*c,c=-g*c-e*d-h*f;b.x=j*i+c*-g+k*-h-q*-e;b.y=k*i+c*-e+q*-g-j*-h;b.z=q*i+c*-h+j*-e-k*-g;return b}}; +THREE.Quaternion.slerp=function(a,b,c,d){var f=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;0>f?(c.w=-b.w,c.x=-b.x,c.y=-b.y,c.z=-b.z,f=-f):c.copy(b);if(1<=Math.abs(f))return c.w=a.w,c.x=a.x,c.y=a.y,c.z=a.z,c;var g=Math.acos(f),f=Math.sqrt(1-f*f);if(0.001>Math.abs(f))return c.w=0.5*(a.w+b.w),c.x=0.5*(a.x+b.x),c.y=0.5*(a.y+b.y),c.z=0.5*(a.z+b.z),c;b=Math.sin((1-d)*g)/f;d=Math.sin(d*g)/f;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(a){this.position=a||new THREE.Vector3}; +THREE.Vertex.prototype={constructor:THREE.Vertex,clone:function(){return new THREE.Vertex(this.position.clone())}};THREE.Face3=function(a,b,c,d,f,g){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=f instanceof THREE.Color?f:new THREE.Color;this.vertexColors=f instanceof Array?f:[];this.vertexTangents=[];this.materialIndex=g;this.centroid=new THREE.Vector3}; +THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;for(b=0,c=this.vertexNormals.length;bf?-1:1,g.vertexTangents[d]=new THREE.Vector4(P.x,P.y,P.z,f)}this.hasTangents=!0},computeBoundingBox:function(){if(!this.boundingBox)this.boundingBox={min:new THREE.Vector3,max:new THREE.Vector3};if(0c.x)c.x=a.x;if(a.yc.y)c.y=a.y;if(a.zc.z)c.z=a.z}}else this.boundingBox.min.set(0,0,0),this.boundingBox.max.set(0,0,0)},computeBoundingSphere:function(){if(!this.boundingSphere)this.boundingSphere={radius:0};for(var a,b=0,c=0,d=this.vertices.length;cb&&(b=a);this.boundingSphere.radius=b},mergeVertices:function(){var a={},b=[],c=[],d,f=Math.pow(10, +4),g,e;for(g=0,e=this.vertices.length;gthis.points.length-2?g:g+1;c[3]=g>this.points.length-3?g:g+2;j=this.points[c[0]];k=this.points[c[1]]; +q=this.points[c[2]];m=this.points[c[3]];h=e*e;i=e*h;d.x=b(j.x,k.x,q.x,m.x,e,h,i);d.y=b(j.y,k.y,q.y,m.y,e,h,i);d.z=b(j.z,k.z,q.z,m.z,e,h,i);return d};this.getControlPointsArray=function(){var a,b,c=this.points.length,d=[];for(a=0;ah.end)h.end=f;b||(b=e)}}a.firstAnimation=b}; +THREE.MorphAnimMesh.prototype.setAnimationLabel=function(a,b,c){if(!this.geometry.animations)this.geometry.animations={};this.geometry.animations[a]={start:b,end:c}};THREE.MorphAnimMesh.prototype.playAnimation=function(a,b){var c=this.geometry.animations[a];c?(this.setFrameRange(c.start,c.end),this.duration=1E3*((c.end-c.start)/b),this.time=0):console.warn("animation["+a+"] undefined")}; +THREE.MorphAnimMesh.prototype.updateAnimation=function(a){var b=this.duration/this.length;this.time+=this.direction*a;if(this.mirroredLoop){if(this.time>this.duration||0>this.time){this.direction*=-1;if(this.time>this.duration)this.time=this.duration,this.directionBackwards=!0;if(0>this.time)this.time=0,this.directionBackwards=!1}}else this.time%=this.duration,0>this.time&&(this.time+=this.duration);a=this.startKeyframe+THREE.Math.clamp(Math.floor(this.time/b),0,this.length-1);if(a!==this.currentKeyframe)this.morphTargetInfluences[this.lastKeyframe]= +0,this.morphTargetInfluences[this.currentKeyframe]=1,this.morphTargetInfluences[a]=0,this.lastKeyframe=this.currentKeyframe,this.currentKeyframe=a;b=this.time%b/b;this.directionBackwards&&(b=1-b);this.morphTargetInfluences[this.currentKeyframe]=b;this.morphTargetInfluences[this.lastKeyframe]=1-b};THREE.Ribbon=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.material=b};THREE.Ribbon.prototype=new THREE.Object3D;THREE.Ribbon.prototype.constructor=THREE.Ribbon; +THREE.LOD=function(){THREE.Object3D.call(this);this.LODs=[]};THREE.LOD.prototype=new THREE.Object3D;THREE.LOD.prototype.constructor=THREE.LOD;THREE.LOD.prototype.supr=THREE.Object3D.prototype;THREE.LOD.prototype.addLevel=function(a,b){void 0===b&&(b=0);for(var b=Math.abs(b),c=0;c=this.LODs[b].visibleAtDistance)this.LODs[b-1].object3D.visible=!1,this.LODs[b].object3D.visible=!0;else break;for(;bs&&n.clearRect(Math.floor(sa.getX()),Math.floor(sa.getY()),Math.floor(sa.getWidth()),Math.floor(sa.getHeight())),0=i||(i*=e.intensity,d.r+=h.r*i,d.g+=h.g*i,d.b+=h.b*i)):e instanceof THREE.PointLight&&(l=e.matrixWorld.getPosition(),i=c.dot(Z.sub(l,b).normalize()),0>=i||(i*=0==e.distance?1:1-Math.min(b.distanceTo(l)/e.distance,1),0!=i&&(i*=e.intensity,d.r+=h.r*i,d.g+=h.g*i,d.b+=h.b*i)))}function r(a,g,e){b(e.opacity);c(e.blending);var Z,h,l,i,k,j;if(e instanceof THREE.ParticleBasicMaterial){if(e.map)i= +e.map.image,k=i.width>>1,j=i.height>>1,e=g.scale.x*o,l=g.scale.y*p,Z=e*k,h=l*j,za.set(a.x-Z,a.y-h,a.x+Z,a.y+h),La.intersects(za)&&(n.save(),n.translate(a.x,a.y),n.rotate(-g.rotation),n.scale(e,-l),n.translate(-k,-j),n.drawImage(i,0,0),n.restore())}else e instanceof THREE.ParticleCanvasMaterial&&(Z=g.scale.x*o,h=g.scale.y*p,za.set(a.x-Z,a.y-h,a.x+Z,a.y+h),La.intersects(za)&&(d(e.color.getContextStyle()),f(e.color.getContextStyle()),n.save(),n.translate(a.x,a.y),n.rotate(-g.rotation),n.scale(Z,h),e.program(n), +n.restore()))}function s(a,f,g,e){b(e.opacity);c(e.blending);n.beginPath();n.moveTo(a.positionScreen.x,a.positionScreen.y);n.lineTo(f.positionScreen.x,f.positionScreen.y);n.closePath();if(e instanceof THREE.LineBasicMaterial){a=e.linewidth;if(A!=a)n.lineWidth=A=a;a=e.linecap;if(F!=a)n.lineCap=F=a;a=e.linejoin;if(B!=a)n.lineJoin=B=a;d(e.color.getContextStyle());n.stroke();za.inflate(2*e.linewidth)}}function t(a,d,f,e,h,j,n,T){g.info.render.vertices+=3;g.info.render.faces++;b(T.opacity);c(T.blending); +K=a.positionScreen.x;O=a.positionScreen.y;y=d.positionScreen.x;l=d.positionScreen.y;$=f.positionScreen.x;C=f.positionScreen.y;v(K,O,y,l,$,C);if(T instanceof THREE.MeshBasicMaterial)if(T.map)T.map.mapping instanceof THREE.UVMapping&&(ha=n.uvs[0],Vc(K,O,y,l,$,C,ha[e].u,ha[e].v,ha[h].u,ha[h].v,ha[j].u,ha[j].v,T.map));else if(T.envMap){if(T.envMap.mapping instanceof THREE.SphericalReflectionMapping)a=k.matrixWorldInverse,Z.copy(n.vertexNormalsWorld[e]),ib=0.5*(Z.x*a.n11+Z.y*a.n12+Z.z*a.n13)+0.5,db=0.5* +-(Z.x*a.n21+Z.y*a.n22+Z.z*a.n23)+0.5,Z.copy(n.vertexNormalsWorld[h]),lb=0.5*(Z.x*a.n11+Z.y*a.n12+Z.z*a.n13)+0.5,cb=0.5*-(Z.x*a.n21+Z.y*a.n22+Z.z*a.n23)+0.5,Z.copy(n.vertexNormalsWorld[j]),Za=0.5*(Z.x*a.n11+Z.y*a.n12+Z.z*a.n13)+0.5,Sa=0.5*-(Z.x*a.n21+Z.y*a.n22+Z.z*a.n23)+0.5,Vc(K,O,y,l,$,C,ib,db,lb,cb,Za,Sa,T.envMap)}else T.wireframe?Mb(T.color,T.wireframeLinewidth,T.wireframeLinecap,T.wireframeLinejoin):Gb(T.color);else if(T instanceof THREE.MeshLambertMaterial)T.map&&!T.wireframe&&(T.map.mapping instanceof +THREE.UVMapping&&(ha=n.uvs[0],Vc(K,O,y,l,$,C,ha[e].u,ha[e].v,ha[h].u,ha[h].v,ha[j].u,ha[j].v,T.map)),c(THREE.SubtractiveBlending)),Ea?!T.wireframe&&T.shading==THREE.SmoothShading&&3==n.vertexNormalsWorld.length?(aa.r=U.r=ba.r=Fa.r,aa.g=U.g=ba.g=Fa.g,aa.b=U.b=ba.b=Fa.b,q(i,n.v1.positionWorld,n.vertexNormalsWorld[0],aa),q(i,n.v2.positionWorld,n.vertexNormalsWorld[1],U),q(i,n.v3.positionWorld,n.vertexNormalsWorld[2],ba),aa.r=Math.max(0,Math.min(T.color.r*aa.r,1)),aa.g=Math.max(0,Math.min(T.color.g*aa.g, +1)),aa.b=Math.max(0,Math.min(T.color.b*aa.b,1)),U.r=Math.max(0,Math.min(T.color.r*U.r,1)),U.g=Math.max(0,Math.min(T.color.g*U.g,1)),U.b=Math.max(0,Math.min(T.color.b*U.b,1)),ba.r=Math.max(0,Math.min(T.color.r*ba.r,1)),ba.g=Math.max(0,Math.min(T.color.g*ba.g,1)),ba.b=Math.max(0,Math.min(T.color.b*ba.b,1)),ea.r=0.5*(U.r+ba.r),ea.g=0.5*(U.g+ba.g),ea.b=0.5*(U.b+ba.b),qa=Dc(aa,U,ba,ea),gc(K,O,y,l,$,C,0,0,1,0,0,1,qa)):(N.r=Fa.r,N.g=Fa.g,N.b=Fa.b,q(i,n.centroidWorld,n.normalWorld,N),N.r=Math.max(0,Math.min(T.color.r* +N.r,1)),N.g=Math.max(0,Math.min(T.color.g*N.g,1)),N.b=Math.max(0,Math.min(T.color.b*N.b,1)),T.wireframe?Mb(N,T.wireframeLinewidth,T.wireframeLinecap,T.wireframeLinejoin):Gb(N)):T.wireframe?Mb(T.color,T.wireframeLinewidth,T.wireframeLinecap,T.wireframeLinejoin):Gb(T.color);else if(T instanceof THREE.MeshDepthMaterial)Ka=k.near,Ga=k.far,aa.r=aa.g=aa.b=1-ac(a.positionScreen.z,Ka,Ga),U.r=U.g=U.b=1-ac(d.positionScreen.z,Ka,Ga),ba.r=ba.g=ba.b=1-ac(f.positionScreen.z,Ka,Ga),ea.r=0.5*(U.r+ba.r),ea.g=0.5* +(U.g+ba.g),ea.b=0.5*(U.b+ba.b),qa=Dc(aa,U,ba,ea),gc(K,O,y,l,$,C,0,0,1,0,0,1,qa);else if(T instanceof THREE.MeshNormalMaterial)N.r=hc(n.normalWorld.x),N.g=hc(n.normalWorld.y),N.b=hc(n.normalWorld.z),T.wireframe?Mb(N,T.wireframeLinewidth,T.wireframeLinecap,T.wireframeLinejoin):Gb(N)}function u(a,d,f,e,Z,h,T,j,n){g.info.render.vertices+=4;g.info.render.faces++;b(j.opacity);c(j.blending);if(j.map||j.envMap)t(a,d,e,0,1,3,T,j,n),t(Z,f,h,1,2,3,T,j,n);else if(K=a.positionScreen.x,O=a.positionScreen.y,y=d.positionScreen.x, +l=d.positionScreen.y,$=f.positionScreen.x,C=f.positionScreen.y,E=e.positionScreen.x,S=e.positionScreen.y,R=Z.positionScreen.x,ca=Z.positionScreen.y,ka=h.positionScreen.x,ia=h.positionScreen.y,j instanceof THREE.MeshBasicMaterial)w(K,O,y,l,$,C,E,S),j.wireframe?Mb(j.color,j.wireframeLinewidth,j.wireframeLinecap,j.wireframeLinejoin):Gb(j.color);else if(j instanceof THREE.MeshLambertMaterial)Ea?!j.wireframe&&j.shading==THREE.SmoothShading&&4==T.vertexNormalsWorld.length?(aa.r=U.r=ba.r=ea.r=Fa.r,aa.g= +U.g=ba.g=ea.g=Fa.g,aa.b=U.b=ba.b=ea.b=Fa.b,q(i,T.v1.positionWorld,T.vertexNormalsWorld[0],aa),q(i,T.v2.positionWorld,T.vertexNormalsWorld[1],U),q(i,T.v4.positionWorld,T.vertexNormalsWorld[3],ba),q(i,T.v3.positionWorld,T.vertexNormalsWorld[2],ea),aa.r=Math.max(0,Math.min(j.color.r*aa.r,1)),aa.g=Math.max(0,Math.min(j.color.g*aa.g,1)),aa.b=Math.max(0,Math.min(j.color.b*aa.b,1)),U.r=Math.max(0,Math.min(j.color.r*U.r,1)),U.g=Math.max(0,Math.min(j.color.g*U.g,1)),U.b=Math.max(0,Math.min(j.color.b*U.b,1)), +ba.r=Math.max(0,Math.min(j.color.r*ba.r,1)),ba.g=Math.max(0,Math.min(j.color.g*ba.g,1)),ba.b=Math.max(0,Math.min(j.color.b*ba.b,1)),ea.r=Math.max(0,Math.min(j.color.r*ea.r,1)),ea.g=Math.max(0,Math.min(j.color.g*ea.g,1)),ea.b=Math.max(0,Math.min(j.color.b*ea.b,1)),qa=Dc(aa,U,ba,ea),v(K,O,y,l,E,S),gc(K,O,y,l,E,S,0,0,1,0,0,1,qa),v(R,ca,$,C,ka,ia),gc(R,ca,$,C,ka,ia,1,0,1,1,0,1,qa)):(N.r=Fa.r,N.g=Fa.g,N.b=Fa.b,q(i,T.centroidWorld,T.normalWorld,N),N.r=Math.max(0,Math.min(j.color.r*N.r,1)),N.g=Math.max(0, +Math.min(j.color.g*N.g,1)),N.b=Math.max(0,Math.min(j.color.b*N.b,1)),w(K,O,y,l,$,C,E,S),j.wireframe?Mb(N,j.wireframeLinewidth,j.wireframeLinecap,j.wireframeLinejoin):Gb(N)):(w(K,O,y,l,$,C,E,S),j.wireframe?Mb(j.color,j.wireframeLinewidth,j.wireframeLinecap,j.wireframeLinejoin):Gb(j.color));else if(j instanceof THREE.MeshNormalMaterial)N.r=hc(T.normalWorld.x),N.g=hc(T.normalWorld.y),N.b=hc(T.normalWorld.z),w(K,O,y,l,$,C,E,S),j.wireframe?Mb(N,j.wireframeLinewidth,j.wireframeLinecap,j.wireframeLinejoin): +Gb(N);else if(j instanceof THREE.MeshDepthMaterial)Ka=k.near,Ga=k.far,aa.r=aa.g=aa.b=1-ac(a.positionScreen.z,Ka,Ga),U.r=U.g=U.b=1-ac(d.positionScreen.z,Ka,Ga),ba.r=ba.g=ba.b=1-ac(e.positionScreen.z,Ka,Ga),ea.r=ea.g=ea.b=1-ac(f.positionScreen.z,Ka,Ga),qa=Dc(aa,U,ba,ea),v(K,O,y,l,E,S),gc(K,O,y,l,E,S,0,0,1,0,0,1,qa),v(R,ca,$,C,ka,ia),gc(R,ca,$,C,ka,ia,1,0,1,1,0,1,qa)}function v(a,b,c,d,f,e){n.beginPath();n.moveTo(a,b);n.lineTo(c,d);n.lineTo(f,e);n.lineTo(a,b);n.closePath()}function w(a,b,c,d,f,e,g,Z){n.beginPath(); +n.moveTo(a,b);n.lineTo(c,d);n.lineTo(f,e);n.lineTo(g,Z);n.lineTo(a,b);n.closePath()}function Mb(a,b,c,f){if(A!=b)n.lineWidth=A=b;if(F!=c)n.lineCap=F=c;if(B!=f)n.lineJoin=B=f;d(a.getContextStyle());n.stroke();za.inflate(2*b)}function Gb(a){f(a.getContextStyle());n.fill()}function Vc(a,b,c,d,e,g,Z,h,l,i,j,T,k){if(0!=k.image.width){if(!0==k.needsUpdate||void 0==Ta[k.id]){var m=k.wrapS==THREE.RepeatWrapping,o=k.wrapT==THREE.RepeatWrapping;Ta[k.id]=n.createPattern(k.image,m&&o?"repeat":m&&!o?"repeat-x": +!m&&o?"repeat-y":"no-repeat");k.needsUpdate=!1}f(Ta[k.id]);var m=k.offset.x/k.repeat.x,o=k.offset.y/k.repeat.y,p=k.image.width*k.repeat.x,Fb=k.image.height*k.repeat.y,Z=(Z+m)*p,h=(h+o)*Fb,c=c-a,d=d-b,e=e-a,g=g-b,l=(l+m)*p-Z,i=(i+o)*Fb-h,j=(j+m)*p-Z,T=(T+o)*Fb-h,m=l*T-j*i;if(0==m){if(void 0===Ja[k.id])b=document.createElement("canvas"),b.width=k.image.width,b.height=k.image.height,b=b.getContext("2d"),b.drawImage(k.image,0,0),Ja[k.id]=b.getImageData(0,0,k.image.width,k.image.height).data;b=Ja[k.id]; +Z=4*(Math.floor(Z)+Math.floor(h)*k.image.width);N.setRGB(b[Z]/255,b[Z+1]/255,b[Z+2]/255);Gb(N)}else m=1/m,k=(T*c-i*e)*m,i=(T*d-i*g)*m,c=(l*e-j*c)*m,d=(l*g-j*d)*m,a=a-k*Z-c*h,Z=b-i*Z-d*h,n.save(),n.transform(k,i,c,d,a,Z),n.fill(),n.restore()}}function gc(a,b,c,d,f,e,g,Z,h,l,i,j,T){var k,m;k=T.width-1;m=T.height-1;g*=k;Z*=m;c-=a;d-=b;f-=a;e-=b;h=h*k-g;l=l*m-Z;i=i*k-g;j=j*m-Z;m=1/(h*j-i*l);k=(j*c-l*f)*m;l=(j*d-l*e)*m;c=(h*f-i*c)*m;d=(h*e-i*d)*m;a=a-k*g-c*Z;b=b-l*g-d*Z;n.save();n.transform(k,l,c,d,a, +b);n.clip();n.drawImage(T,0,0);n.restore()}function Dc(a,b,c,d){var f=~~(255*a.r),e=~~(255*a.g),a=~~(255*a.b),g=~~(255*b.r),Z=~~(255*b.g),b=~~(255*b.b),h=~~(255*c.r),l=~~(255*c.g),c=~~(255*c.b),i=~~(255*d.r),j=~~(255*d.g),d=~~(255*d.b);eb[0]=0>f?0:255e?0:255a?0:255g?0:255Z?0:255b?0:255h?0:255l?0:255c?0:255i?0:255j?0:255d?0:255a?0:1=j||(j*=g.intensity,d.r+=h.r*j,d.g+=h.g*j,d.b+=h.b*j)):g instanceof THREE.PointLight&&(i=g.matrixWorld.getPosition(),j=c.dot(D.sub(i,b).normalize()),0>=j||(j*=0==g.distance?1:1-Math.min(b.distanceTo(i)/g.distance,1),0!=j&&(j*=g.intensity,d.r+=h.r*j,d.g+=h.g*j,d.b+=h.b*j)))}function b(a){null==H[a]&&(H[a]=document.createElementNS("http://www.w3.org/2000/svg", +"path"),0==K&&H[a].setAttribute("shape-rendering","crispEdges"));return H[a]}function c(a){a=0.5*(a+1);return 0>a?0:1 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif", +lights_lambert_vertex:"vLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\nvLightBack = vec3( 0.0 );\n#endif\ntransformedNormal = normalize( transformedNormal );\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( transformedNormal, dirVector );\nvec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\ndirectionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\ndirectionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += directionalLightColor[ i ] * directionalLightWeighting;\n#ifdef DOUBLE_SIDED\nvLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;\n#endif\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nfloat dotProduct = dot( transformedNormal, lVector );\nvec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );\n#ifdef DOUBLE_SIDED\nvec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );\n#endif\n#endif\n#ifdef WRAP_AROUND\nvec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );\npointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );\n#ifdef DOUBLE_SIDED\npointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );\n#endif\n#endif\nvLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;\n#ifdef DOUBLE_SIDED\nvLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;\n#endif\n}\n#endif\nvLightFront = vLightFront * diffuse + ambient * ambientLightColor;\n#ifdef DOUBLE_SIDED\nvLightBack = vLightBack * diffuse + ambient * ambientLightColor;\n#endif", +lights_phong_pars_vertex:"#if MAX_POINT_LIGHTS > 0\n#ifndef PHONG_PER_PIXEL\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif",lights_phong_vertex:"#if MAX_POINT_LIGHTS > 0\n#ifndef PHONG_PER_PIXEL\nfor( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#endif", +lights_phong_pars_fragment:"uniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n#ifdef PHONG_PER_PIXEL\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n#else\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;", +lights_phong_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#ifdef DOUBLE_SIDED\nnormal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n#endif\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n#ifdef PHONG_PER_PIXEL\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz + vViewPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\n#else\nvec3 lVector = normalize( vPointLight[ i ].xyz );\nfloat lDistance = vPointLight[ i ].w;\n#endif\nfloat dotProduct = dot( normal, lVector );\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dotProduct, 0.0 );\n#endif\npointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;\nvec3 pointHalfVector = normalize( lVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = max( pow( pointDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( dot( lVector, pointHalfVector ), 5.0 );\npointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;\n#else\npointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;\n#endif\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nfloat dotProduct = dot( normal, dirVector );\n#ifdef WRAP_AROUND\nfloat dirDiffuseWeightFull = max( dotProduct, 0.0 );\nfloat dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dotProduct, 0.0 );\n#endif\ndirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = max( pow( dirDotNormalHalf, shininess ), 0.0 );\n#ifdef PHYSICALLY_BASED_SHADING\nvec3 schlick = specular + vec3( 1.0 - specular ) * pow( dot( dirVector, dirHalfVector ), 5.0 );\ndirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;\n#else\ndirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;\n#endif\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\n#ifdef METAL\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * ambient + totalSpecular );\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * ambient ) + totalSpecular;\n#endif", +color_pars_fragment:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_fragment:"#ifdef USE_COLOR\ngl_FragColor = gl_FragColor * vec4( vColor, opacity );\n#endif",color_pars_vertex:"#ifdef USE_COLOR\nvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n#ifdef GAMMA_INPUT\nvColor = color * color;\n#else\nvColor = color;\n#endif\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\nuniform mat4 boneGlobalMatrices[ MAX_BONES ];\n#endif",skinning_vertex:"#ifdef USE_SKINNING\ngl_Position = ( boneGlobalMatrices[ int( skinIndex.x ) ] * skinVertexA ) * skinWeight.x;\ngl_Position += ( boneGlobalMatrices[ int( skinIndex.y ) ] * skinVertexB ) * skinWeight.y;\ngl_Position = projectionMatrix * modelViewMatrix * gl_Position;\n#endif", +morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n#ifndef USE_MORPHNORMALS\nuniform float morphTargetInfluences[ 8 ];\n#else\nuniform float morphTargetInfluences[ 4 ];\n#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\nvec3 morphed = vec3( 0.0 );\nmorphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\nmorphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\nmorphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\nmorphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n#ifndef USE_MORPHNORMALS\nmorphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\nmorphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\nmorphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\nmorphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n#endif\nmorphed += position;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );\n#endif", +default_vertex:"#ifndef USE_MORPHTARGETS\n#ifndef USE_SKINNING\ngl_Position = projectionMatrix * mvPosition;\n#endif\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\nvec3 morphedNormal = vec3( 0.0 );\nmorphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\nmorphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\nmorphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\nmorphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\nmorphedNormal += normal;\nvec3 transformedNormal = normalMatrix * morphedNormal;\n#else\nvec3 transformedNormal = normalMatrix * normal;\n#endif", +shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\nuniform sampler2D shadowMap[ MAX_SHADOWS ];\nuniform vec2 shadowMapSize[ MAX_SHADOWS ];\nuniform float shadowDarkness[ MAX_SHADOWS ];\nuniform float shadowBias[ MAX_SHADOWS ];\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nfloat unpackDepth( const in vec4 rgba_depth ) {\nconst vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\nfloat depth = dot( rgba_depth, bit_shift );\nreturn depth;\n}\n#endif",shadowmap_fragment:"#ifdef USE_SHADOWMAP\n#ifdef SHADOWMAP_DEBUG\nvec3 frustumColors[3];\nfrustumColors[0] = vec3( 1.0, 0.5, 0.0 );\nfrustumColors[1] = vec3( 0.0, 1.0, 0.8 );\nfrustumColors[2] = vec3( 0.0, 0.5, 1.0 );\n#endif\n#ifdef SHADOWMAP_CASCADE\nint inFrustumCount = 0;\n#endif\nfloat fDepth;\nvec3 shadowColor = vec3( 1.0 );\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\nvec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\nbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\nbool inFrustum = all( inFrustumVec );\n#ifdef SHADOWMAP_CASCADE\ninFrustumCount += int( inFrustum );\nbvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );\n#else\nbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n#endif\nbool frustumTest = all( frustumTestVec );\nif ( frustumTest ) {\nshadowCoord.z += shadowBias[ i ];\n#ifdef SHADOWMAP_SOFT\nfloat shadow = 0.0;\nconst float shadowDelta = 1.0 / 9.0;\nfloat xPixelOffset = 1.0 / shadowMapSize[ i ].x;\nfloat yPixelOffset = 1.0 / shadowMapSize[ i ].y;\nfloat dx0 = -1.25 * xPixelOffset;\nfloat dy0 = -1.25 * yPixelOffset;\nfloat dx1 = 1.25 * xPixelOffset;\nfloat dy1 = 1.25 * yPixelOffset;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nfDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\nif ( fDepth < shadowCoord.z ) shadow += shadowDelta;\nshadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );\n#else\nvec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\nfloat fDepth = unpackDepth( rgbaDepth );\nif ( fDepth < shadowCoord.z )\nshadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );\n#endif\n}\n#ifdef SHADOWMAP_DEBUG\n#ifdef SHADOWMAP_CASCADE\nif ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];\n#else\nif ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];\n#endif\n#endif\n}\n#ifdef GAMMA_OUTPUT\nshadowColor *= shadowColor;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * shadowColor;\n#endif", +shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\nvarying vec4 vShadowCoord[ MAX_SHADOWS ];\nuniform mat4 shadowMatrix[ MAX_SHADOWS ];\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\nfor( int i = 0; i < MAX_SHADOWS; i ++ ) {\n#ifdef USE_MORPHTARGETS\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( morphed, 1.0 );\n#else\nvShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( position, 1.0 );\n#endif\n}\n#endif",alphatest_fragment:"#ifdef ALPHATEST\nif ( gl_FragColor.a < ALPHATEST ) discard;\n#endif", +linear_to_gamma_fragment:"#ifdef GAMMA_OUTPUT\ngl_FragColor.xyz = sqrt( gl_FragColor.xyz );\n#endif"}; +THREE.UniformsUtils={merge:function(a){var b,c,d,f={};for(b=0;bn;n++){m=k;r=n;if(y.autoScaleCubemaps){if(s=h.image[n],E=Ea,!(s.width<=E&&s.height<=E))u=Math.max(s.width, +s.height),t=Math.floor(s.width*E/u),E=Math.floor(s.height*E/u),u=document.createElement("canvas"),u.width=t,u.height=E,u.getContext("2d").drawImage(s,0,0,s.width,s.height,0,0,t,E),s=u}else s=h.image[n];m[r]=s}n=k[0];m=0===(n.width&n.width-1)&&0===(n.height&n.height-1);r=A(h.format);s=A(h.type);w(l.TEXTURE_CUBE_MAP,h,m);for(n=0;6>n;n++)l.texImage2D(l.TEXTURE_CUBE_MAP_POSITIVE_X+n,0,r,r,s,k[n]);h.generateMipmaps&&m&&l.generateMipmap(l.TEXTURE_CUBE_MAP);h.needsUpdate=!1;if(h.onUpdate)h.onUpdate()}else l.activeTexture(l.TEXTURE0+ +k),l.bindTexture(l.TEXTURE_CUBE_MAP,h.image.__webglTextureCube)}else n instanceof THREE.WebGLRenderTargetCube?(h=n,l.activeTexture(l.TEXTURE0+k),l.bindTexture(l.TEXTURE_CUBE_MAP,h.__webglTexture)):y.setTexture(n,k)}else if("tv"===m){if(!h._array){h._array=[];for(m=0,r=h.texture.length;mj&&(k=m,j=h[k]);l.bindBuffer(l.ARRAY_BUFFER,f.__webglMorphTargetsBuffers[k]);l.vertexAttribPointer(c["morphTarget"+g],3,l.FLOAT,!1,0,0);d.morphNormals&&(l.bindBuffer(l.ARRAY_BUFFER,f.__webglMorphNormalsBuffers[k]),l.vertexAttribPointer(c["morphNormal"+ +g],3,l.FLOAT,!1,0,0));e.__webglMorphTargetInfluences[g]=j;i[k]=1;j=-1;g++}}null!==d.program.uniforms.morphTargetInfluences&&l.uniform1fv(d.program.uniforms.morphTargetInfluences,e.__webglMorphTargetInfluences)}if(a){if(f.__webglCustomAttributesList)for(g=0,h=f.__webglCustomAttributesList.length;gla;la++)Vb=jc[la],hb[Ra]=Vb.x,hb[Ra+1]=Vb.y,hb[Ra+2]=Vb.z,Ra+=3;else for(la=0;3>la;la++)hb[Ra]=Ob.x,hb[Ra+1]=Ob.y,hb[Ra+2]=Ob.z,Ra+=3;for(G=0,V=na.length;Gla;la++)Vb=jc[la], +hb[Ra]=Vb.x,hb[Ra+1]=Vb.y,hb[Ra+2]=Vb.z,Ra+=3;else for(la=0;4>la;la++)hb[Ra]=Ob.x,hb[Ra+1]=Ob.y,hb[Ra+2]=Ob.z,Ra+=3;l.bindBuffer(l.ARRAY_BUFFER,fa.__webglNormalBuffer);l.bufferData(l.ARRAY_BUFFER,hb,$a)}if(kd&&bd&&hd){for(G=0,V=ma.length;Gla;la++)mc=kc[la],wc[Jb]=mc.u,wc[Jb+1]=mc.v,Jb+=2;for(G=0,V=na.length;Gla;la++)mc=kc[la],wc[Jb]=mc.u,wc[Jb+1]=mc.v,Jb+=2;0la;la++)nc=lc[la],xc[Kb]=nc.u,xc[Kb+1]=nc.v,Kb+=2;for(G=0,V=na.length;Gla;la++)nc=lc[la],xc[Kb]=nc.u,xc[Kb+1]=nc.v,Kb+=2;0c;c++){a.__webglFramebuffer[c]=l.createFramebuffer();a.__webglRenderbuffer[c]=l.createRenderbuffer();l.texImage2D(l.TEXTURE_CUBE_MAP_POSITIVE_X+c,0,d,a.width,a.height,0,d,f,null);var e=a,g=l.TEXTURE_CUBE_MAP_POSITIVE_X+c;l.bindFramebuffer(l.FRAMEBUFFER,a.__webglFramebuffer[c]);l.framebufferTexture2D(l.FRAMEBUFFER,l.COLOR_ATTACHMENT0,g,e.__webglTexture,0);u(a.__webglRenderbuffer[c],a)}}else a.__webglFramebuffer=l.createFramebuffer(),a.__webglRenderbuffer= +l.createRenderbuffer(),l.bindTexture(l.TEXTURE_2D,a.__webglTexture),w(l.TEXTURE_2D,a,c),l.texImage2D(l.TEXTURE_2D,0,d,a.width,a.height,0,d,f,null),d=l.TEXTURE_2D,l.bindFramebuffer(l.FRAMEBUFFER,a.__webglFramebuffer),l.framebufferTexture2D(l.FRAMEBUFFER,l.COLOR_ATTACHMENT0,d,a.__webglTexture,0),u(a.__webglRenderbuffer,a);b?l.bindTexture(l.TEXTURE_CUBE_MAP,null):l.bindTexture(l.TEXTURE_2D,null);l.bindRenderbuffer(l.RENDERBUFFER,null);l.bindFramebuffer(l.FRAMEBUFFER,null)}a?(b=b?a.__webglFramebuffer[a.activeCubeFace]: +a.__webglFramebuffer,d=a.width,a=a.height,c=f=0):(b=null,d=ha,a=ib,f=Ga,c=qa);b!==E&&(l.bindFramebuffer(l.FRAMEBUFFER,b),l.viewport(f,c,d,a),E=b);db=d;lb=a};this.shadowMapPlugin=new THREE.ShadowMapPlugin;this.addPrePlugin(this.shadowMapPlugin);this.addPostPlugin(new THREE.SpritePlugin);this.addPostPlugin(new THREE.LensFlarePlugin)}; +THREE.WebGLRenderTarget=function(a,b,c){this.width=a;this.height=b;c=c||{};this.wrapS=void 0!==c.wrapS?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=void 0!==c.wrapT?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=void 0!==c.magFilter?c.magFilter:THREE.LinearFilter;this.minFilter=void 0!==c.minFilter?c.minFilter:THREE.LinearMipMapLinearFilter;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=void 0!==c.format?c.format:THREE.RGBAFormat;this.type=void 0!==c.type?c.type: +THREE.UnsignedByteType;this.depthBuffer=void 0!==c.depthBuffer?c.depthBuffer:!0;this.stencilBuffer=void 0!==c.stencilBuffer?c.stencilBuffer:!0;this.generateMipmaps=!0}; +THREE.WebGLRenderTarget.prototype.clone=function(){var a=new THREE.WebGLRenderTarget(this.width,this.height);a.wrapS=this.wrapS;a.wrapT=this.wrapT;a.magFilter=this.magFilter;a.minFilter=this.minFilter;a.offset.copy(this.offset);a.repeat.copy(this.repeat);a.format=this.format;a.type=this.type;a.depthBuffer=this.depthBuffer;a.stencilBuffer=this.stencilBuffer;return a};THREE.WebGLRenderTargetCube=function(a,b,c){THREE.WebGLRenderTarget.call(this,a,b,c);this.activeCubeFace=0}; +THREE.WebGLRenderTargetCube.prototype=new THREE.WebGLRenderTarget;THREE.WebGLRenderTargetCube.prototype.constructor=THREE.WebGLRenderTargetCube;THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=!0};THREE.RenderableVertex.prototype.copy=function(a){this.positionWorld.copy(a.positionWorld);this.positionScreen.copy(a.positionScreen)}; +THREE.RenderableFace3=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null}; +THREE.RenderableFace4=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.v4=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterial=this.material=null;this.uvs=[[]];this.z=null};THREE.RenderableObject=function(){this.z=this.object=null}; +THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=null;this.scale=new THREE.Vector2;this.material=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.material=null}; +THREE.ColorUtils={adjustHSV:function(a,b,c,d){var f=THREE.ColorUtils.__hsv;THREE.ColorUtils.rgbToHsv(a,f);f.h=THREE.Math.clamp(f.h+b,0,1);f.s=THREE.Math.clamp(f.s+c,0,1);f.v=THREE.Math.clamp(f.v+d,0,1);a.setHSV(f.h,f.s,f.v)},rgbToHsv:function(a,b){var c=a.r,d=a.g,f=a.b,g=Math.max(Math.max(c,d),f),e=Math.min(Math.min(c,d),f);if(e===g)e=c=0;else{var h=g-e,e=h/g,c=(c===g?(d-f)/h:d===g?2+(f-c)/h:4+(c-d)/h)/6;0>c&&(c+=1);1a?b(c,f-1):j[f]b||o>b||q>b){h=a.vertices.length;t=d.clone();d=d.clone();m>=o&&m>=q?(i=i.clone(),i.position.lerpSelf(j.position,0.5),t.a=f,t.b=h,t.c=e,d.a=h,d.b=g,d.c=e,f= +0):o>=m&&o>=q?(i=j.clone(),i.position.lerpSelf(k.position,0.5),t.a=f,t.b=g,t.c=h,d.a=h,d.b=e,d.c=f,f=1):(i=i.clone(),i.position.lerpSelf(k.position,0.5),t.a=f,t.b=g,t.c=h,d.a=h,d.b=g,d.c=e,f=2);a.faces.splice(c,1,t,d);a.vertices.push(i);for(g=0;gb||o>b||p>b||n>b){r=a.vertices.length;s=a.vertices.length+1;t=d.clone(); +d=d.clone();m>=o&&m>=p&&m>=n||p>=o&&p>=m&&p>=n?(m=i.clone(),m.position.lerpSelf(j.position,0.5),j=k.clone(),j.position.lerpSelf(q.position,0.5),t.a=f,t.b=r,t.c=s,t.d=h,d.a=r,d.b=g,d.c=e,d.d=s,f=0):(m=j.clone(),m.position.lerpSelf(k.position,0.5),j=q.clone(),j.position.lerpSelf(i.position,0.5),t.a=f,t.b=g,t.c=r,t.d=s,d.a=s,d.b=r,d.c=e,d.d=h,f=1);a.faces.splice(c,1,t,d);a.vertices.push(m);a.vertices.push(j);for(g=0;gq-1?f-1:q-1,o=(q+1)%f,p=0>k-1?d-1:k-1,n=(k+1)%d,r=[],s=[0,0,h[4*(q*d+k)]/255*b];r.push([-1,0,h[4*(q*d+p)]/255*b]);r.push([-1,-1,h[4*(m*d+p)]/255*b]);r.push([0,-1, +h[4*(m*d+k)]/255*b]);r.push([1,-1,h[4*(m*d+n)]/255*b]);r.push([1,0,h[4*(q*d+n)]/255*b]);r.push([1,1,h[4*(o*d+n)]/255*b]);r.push([0,1,h[4*(o*d+k)]/255*b]);r.push([-1,1,h[4*(o*d+p)]/255*b]);m=[];p=r.length;for(o=0;o 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\n#ifdef WRAP_AROUND\nuniform vec3 wrapRGB;\n#endif\nvarying vec3 vViewPosition;", +THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,"void main() {\ngl_FragColor = vec4( vec3( 1.0 ), uOpacity );\nvec3 specularTex = vec3( 1.0 );\nvec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;\nnormalTex.xy *= uNormalScale;\nnormalTex = normalize( normalTex );\nif( enableDiffuse ) {\n#ifdef GAMMA_INPUT\nvec4 texelColor = texture2D( tDiffuse, vUv );\ntexelColor.xyz *= texelColor.xyz;\ngl_FragColor = gl_FragColor * texelColor;\n#else\ngl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );\n#endif\n}\nif( enableAO ) {\n#ifdef GAMMA_INPUT\nvec4 aoColor = texture2D( tAO, vUv );\naoColor.xyz *= aoColor.xyz;\ngl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;\n#else\ngl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;\n#endif\n}\nif( enableSpecular )\nspecularTex = texture2D( tSpecular, vUv ).xyz;\nmat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );\nvec3 finalNormal = tsb * normalTex;\nvec3 normal = normalize( finalNormal );\nvec3 viewPosition = normalize( vViewPosition );\n#if MAX_POINT_LIGHTS > 0\nvec3 pointDiffuse = vec3( 0.0 );\nvec3 pointSpecular = vec3( 0.0 );\nfor ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\nvec3 pointVector = normalize( vPointLight[ i ].xyz );\nfloat pointDistance = vPointLight[ i ].w;\n#ifdef WRAP_AROUND\nfloat pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );\nfloat pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );\nvec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n#else\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\n#endif\npointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;\nvec3 pointHalfVector = normalize( pointVector + viewPosition );\nfloat pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\nfloat pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );\npointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec3 dirDiffuse = vec3( 0.0 );\nvec3 dirSpecular = vec3( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\n#ifdef WRAP_AROUND\nfloat directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );\nfloat directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );\nvec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );\n#else\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\n#endif\ndirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;\nvec3 dirHalfVector = normalize( dirVector + viewPosition );\nfloat dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\nfloat dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );\ndirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;\n}\n#endif\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n#if MAX_DIR_LIGHTS > 0\ntotalDiffuse += dirDiffuse;\ntotalSpecular += dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalDiffuse += pointDiffuse;\ntotalSpecular += pointSpecular;\n#endif\ngl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor) + totalSpecular;\nif ( enableReflection ) {\nvec3 wPos = cameraPosition - vViewPosition;\nvec3 vReflect = reflect( normalize( wPos ), normal );\nvec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\n#ifdef GAMMA_INPUT\ncubeColor.xyz *= cubeColor.xyz;\n#endif\ngl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );\n}", +THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\nvarying vec3 vViewPosition;", +THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvViewPosition = -mvPosition.xyz;\nvNormal = normalMatrix * normal;\nvTangent = normalMatrix * tangent.xyz;\nvBinormal = cross( vNormal, vTangent ) * tangent.w;\nvUv = uv * uRepeat + uOffset;\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#ifdef VERTEX_TEXTURES\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\nvec4 displacedPosition = vec4( normalize( vNormal.xyz ) * df, 0.0 ) + mvPosition;\ngl_Position = projectionMatrix * displacedPosition;\n#else\ngl_Position = projectionMatrix * mvPosition;\n#endif", +THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n")},cube:{uniforms:{tCube:{type:"t",value:1,texture:null},tFlip:{type:"f",value:-1}},vertexShader:"varying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vViewPosition;\nvoid main() {\nvec3 wPos = cameraPosition - vViewPosition;\ngl_FragColor = textureCube( tCube, vec3( tFlip * wPos.x, wPos.yz ) );\n}"}}}; +THREE.BufferGeometry=function(){this.id=THREE.GeometryCount++;this.vertexColorArray=this.vertexUvArray=this.vertexNormalArray=this.vertexPositionArray=this.vertexIndexArray=this.vertexColorBuffer=this.vertexUvBuffer=this.vertexNormalBuffer=this.vertexPositionBuffer=this.vertexIndexBuffer=null;this.dynamic=!1;this.boundingSphere=this.boundingBox=null;this.morphTargets=[]};THREE.BufferGeometry.prototype={constructor:THREE.BufferGeometry,computeBoundingBox:function(){},computeBoundingSphere:function(){}}; +THREE.Curve=function(){};THREE.Curve.prototype.getPoint=function(){console.log("Warning, getPoint() not implemented!");return null};THREE.Curve.prototype.getPointAt=function(a){return this.getPoint(this.getUtoTmapping(a))};THREE.Curve.prototype.getPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPoint(b/a));return c};THREE.Curve.prototype.getSpacedPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPointAt(b/a));return c}; +THREE.Curve.prototype.getLength=function(){var a=this.getLengths();return a[a.length-1]};THREE.Curve.prototype.getLengths=function(a){a||(a=200);if(this.cacheArcLengths&&this.cacheArcLengths.length==a+1)return this.cacheArcLengths;var b=[],c,d=this.getPoint(0),f,g=0;b.push(0);for(f=1;f<=a;f++)c=this.getPoint(f/a),g+=c.distanceTo(d),b.push(g),d=c;return this.cacheArcLengths=b}; +THREE.Curve.prototype.getUtoTmapping=function(a,b){var c=this.getLengths(),d=0,f=c.length,g;g=b?b:a*c[f-1];for(var e=0,h=f-1,i;e<=h;)if(d=Math.floor(e+(h-e)/2),i=c[d]-g,0>i)e=d+1;else if(0b&&(b=0);1d.length-2?a:a+1;c[3]=a>d.length-3?a:a+2;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,f);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,f);return b};THREE.ArcCurve=function(a,b,c,d,f,g){this.aX=a;this.aY=b;this.aRadius=c;this.aStartAngle=d;this.aEndAngle=f;this.aClockwise=g}; +THREE.ArcCurve.prototype=new THREE.Curve;THREE.ArcCurve.prototype.constructor=THREE.ArcCurve;THREE.ArcCurve.prototype.getPoint=function(a){var b=this.aEndAngle-this.aStartAngle;this.aClockwise||(a=1-a);b=this.aStartAngle+a*b;a=this.aX+this.aRadius*Math.cos(b);b=this.aY+this.aRadius*Math.sin(b);return new THREE.Vector2(a,b)}; +THREE.Curve.Utils={tangentQuadraticBezier:function(a,b,c,d){return 2*(1-a)*(c-b)+2*a*(d-c)},tangentCubicBezier:function(a,b,c,d,f){return-3*b*(1-a)*(1-a)+3*c*(1-a)*(1-a)-6*a*c*(1-a)+6*a*d*(1-a)-3*a*a*d+3*a*a*f},tangentSpline:function(a){return 6*a*a-6*a+(3*a*a-4*a+1)+(-6*a*a+6*a)+(3*a*a-2*a)},interpolate:function(a,b,c,d,f){var a=0.5*(c-a),d=0.5*(d-b),g=f*f;return(2*b-2*c+a+d)*f*g+(-3*b+3*c-2*a-d)*g+a*f+b}}; +THREE.Curve.create=function(a,b){a.prototype=new THREE.Curve;a.prototype.constructor=a;a.prototype.getPoint=b;return a};THREE.LineCurve3=THREE.Curve.create(function(a,b){this.v1=a;this.v2=b},function(a){var b=new THREE.Vector3;b.sub(this.v2,this.v1);b.multiplyScalar(a);b.addSelf(this.v1);return b}); +THREE.QuadraticBezierCurve3=THREE.Curve.create(function(a,b,c){this.v0=a;this.v1=b;this.v2=c},function(a){var b,c;b=THREE.Shape.Utils.b2(a,this.v0.x,this.v1.x,this.v2.x);c=THREE.Shape.Utils.b2(a,this.v0.y,this.v1.y,this.v2.y);a=THREE.Shape.Utils.b2(a,this.v0.z,this.v1.z,this.v2.z);return new THREE.Vector3(b,c,a)}); +THREE.CubicBezierCurve3=THREE.Curve.create(function(a,b,c,d){this.v0=a;this.v1=b;this.v2=c;this.v3=d},function(a){var b,c;b=THREE.Shape.Utils.b3(a,this.v0.x,this.v1.x,this.v2.x,this.v3.x);c=THREE.Shape.Utils.b3(a,this.v0.y,this.v1.y,this.v2.y,this.v3.y);a=THREE.Shape.Utils.b3(a,this.v0.z,this.v1.z,this.v2.z,this.v3.z);return new THREE.Vector3(b,c,a)}); +THREE.SplineCurve3=THREE.Curve.create(function(a){this.points=void 0==a?[]:a},function(a){var b=new THREE.Vector3,c=[],d=this.points,f;f=(d.length-1)*a;a=Math.floor(f);f-=a;c[0]=0==a?a:a-1;c[1]=a;c[2]=a>d.length-2?a:a+1;c[3]=a>d.length-3?a:a+2;b.x=THREE.Curve.Utils.interpolate(d[c[0]].x,d[c[1]].x,d[c[2]].x,d[c[3]].x,f);b.y=THREE.Curve.Utils.interpolate(d[c[0]].y,d[c[1]].y,d[c[2]].y,d[c[3]].y,f);b.z=THREE.Curve.Utils.interpolate(d[c[0]].z,d[c[1]].z,d[c[2]].z,d[c[3]].z,f);return b}); +THREE.CurvePath=function(){this.curves=[];this.bends=[];this.autoClose=!1};THREE.CurvePath.prototype=new THREE.Curve;THREE.CurvePath.prototype.constructor=THREE.CurvePath;THREE.CurvePath.prototype.add=function(a){this.curves.push(a)};THREE.CurvePath.prototype.checkConnection=function(){};THREE.CurvePath.prototype.closePath=function(){var a=this.curves[0].getPoint(0),b=this.curves[this.curves.length-1].getPoint(1);a.equals(b)||this.curves.push(new THREE.LineCurve(b,a))}; +THREE.CurvePath.prototype.getPoint=function(a){for(var b=a*this.getLength(),c=this.getCurveLengths(),a=0;a=b)return b=c[a]-b,a=this.curves[a],b=1-b/a.getLength(),a.getPointAt(b);a++}return null};THREE.CurvePath.prototype.getLength=function(){var a=this.getCurveLengths();return a[a.length-1]}; +THREE.CurvePath.prototype.getCurveLengths=function(){if(this.cacheLengths&&this.cacheLengths.length==this.curves.length)return this.cacheLengths;var a=[],b=0,c,d=this.curves.length;for(c=0;cb)b=g.x;else if(g.xc)c=g.y;else if(g.y +h&&(h+=c.length);h%=c.length;0>e&&(e+=j.length);e%=j.length;f=0<=h-1?h-1:c.length-1;g=0<=e-1?e-1:j.length-1;n=[j[e],c[h],c[f]];n=THREE.FontUtils.Triangulate.area(n);r=[j[e],j[g],c[h]];r=THREE.FontUtils.Triangulate.area(r);q+m>n+r&&(h=o,e=k,0>h&&(h+=c.length),h%=c.length,0>e&&(e+=j.length),e%=j.length,f=0<=h-1?h-1:c.length-1,g=0<=e-1?e-1:j.length-1);q=c.slice(0,h);m=c.slice(h);o=j.slice(e);k=j.slice(0,e);g=[j[e],j[g],c[h]];p.push([j[e],c[h],c[f]]);p.push(g);c=q.concat(o).concat(k).concat(m)}return{shape:c, +isolatedPts:p,allpoints:d}},triangulateShape:function(a,b){var c=THREE.Shape.Utils.removeHoles(a,b),d=c.allpoints,f=c.isolatedPts,c=THREE.FontUtils.Triangulate(c.shape,!1),g,e,h,i,j={};for(g=0,e=d.length;gd;d++)i=h[d].x+":"+h[d].y,i=j[i],void 0!==i&&(h[d]=i)}for(g=0,e=f.length;gd;d++)i=h[d].x+":"+h[d].y,i=j[i],void 0!==i&&(h[d]=i)}return c.concat(f)}, +isClockWise:function(a){return 0>THREE.FontUtils.Triangulate.area(a)},b2p0:function(a,b){var c=1-a;return c*c*b},b2p1:function(a,b){return 2*(1-a)*a*b},b2p2:function(a,b){return a*a*b},b2:function(a,b,c,d){return this.b2p0(a,b)+this.b2p1(a,c)+this.b2p2(a,d)},b3p0:function(a,b){var c=1-a;return c*c*c*b},b3p1:function(a,b){var c=1-a;return 3*c*c*a*b},b3p2:function(a,b){return 3*(1-a)*a*a*b},b3p3:function(a,b){return a*a*a*b},b3:function(a,b,c,d,f){return this.b3p0(a,b)+this.b3p1(a,c)+this.b3p2(a,d)+ +this.b3p3(a,f)}};THREE.TextPath=function(a,b){THREE.Path.call(this);this.parameters=b||{};this.set(a)};THREE.TextPath.prototype.set=function(a,b){b=b||this.parameters;this.text=a;var c=void 0!==b.curveSegments?b.curveSegments:4,d=void 0!==b.font?b.font:"helvetiker",f=void 0!==b.weight?b.weight:"normal",g=void 0!==b.style?b.style:"normal";THREE.FontUtils.size=void 0!==b.size?b.size:100;THREE.FontUtils.divisions=c;THREE.FontUtils.face=d;THREE.FontUtils.weight=f;THREE.FontUtils.style=g}; +THREE.TextPath.prototype.toShapes=function(){for(var a=THREE.FontUtils.drawText(this.text).paths,b=[],c=0,d=a.length;ca.hierarchy[c].keys[d].time)a.hierarchy[c].keys[d].time= +0;if(void 0!==a.hierarchy[c].keys[d].rot&&!(a.hierarchy[c].keys[d].rot instanceof THREE.Quaternion)){var h=a.hierarchy[c].keys[d].rot;a.hierarchy[c].keys[d].rot=new THREE.Quaternion(h[0],h[1],h[2],h[3])}}if(a.hierarchy[c].keys.length&&void 0!==a.hierarchy[c].keys[0].morphTargets){h={};for(d=0;dn;n++){c=b[n];e=i.prevKey[c];h=i.nextKey[c];if(h.time<=m){if(qd||1d?0:1;if("pos"===c)if(c=a.position,this.interpolationType===THREE.AnimationHandler.LINEAR)c.x=f[0]+(g[0]-f[0])*d,c.y=f[1]+(g[1]-f[1])*d,c.z=f[2]+(g[2]-f[2])*d;else{if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD)if(this.points[0]= +this.getPrevKeyWith("pos",o,e.index-1).pos,this.points[1]=f,this.points[2]=g,this.points[3]=this.getNextKeyWith("pos",o,h.index+1).pos,d=0.33*d+0.33,f=this.interpolateCatmullRom(this.points,d),c.x=f[0],c.y=f[1],c.z=f[2],this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD)d=this.interpolateCatmullRom(this.points,1.01*d),this.target.set(d[0],d[1],d[2]),this.target.subSelf(c),this.target.y=0,this.target.normalize(),d=Math.atan2(this.target.x,this.target.z),a.rotation.set(0,d,0)}else if("rot"=== +c)THREE.Quaternion.slerp(f,g,a.quaternion,d);else if("scl"===c)c=a.scale,c.x=f[0]+(g[0]-f[0])*d,c.y=f[1]+(g[1]-f[1])*d,c.z=f[2]+(g[2]-f[2])*d}}if(this.JITCompile&&void 0===k[0][j]){this.hierarchy[0].updateMatrixWorld(!0);for(o=0;oa.length-2?g:g+1;c[3]=g>a.length-3?g:g+2;g=a[c[0]];h=a[c[1]];i=a[c[2]];j=a[c[3]];c=f*f;e=f*c;d[0]=this.interpolate(g[0],h[0],i[0],j[0],f,c,e);d[1]=this.interpolate(g[1],h[1],i[1],j[1],f,c,e);d[2]=this.interpolate(g[2],h[2],i[2],j[2],f,c,e);return d}; +THREE.Animation.prototype.interpolate=function(a,b,c,d,f,g,e){a=0.5*(c-a);d=0.5*(d-b);return(2*(b-c)+a+d)*e+(-3*(b-c)-2*a-d)*g+a*f+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c=e?b.interpolate(c,e):b.interpolate(c,c.time)}this.data.hierarchy[a].node.updateMatrix();d.matrixWorldNeedsUpdate=!0}}if(this.JITCompile&&void 0===g[0][f]){this.hierarchy[0].updateMatrixWorld(!0);for(a=0;a(a*=2)?0.5*a*a:-0.5*(--a*(a-2)-1)}function d(a,b){return function(){b.apply(a,arguments)}}function f(a,b,c,d){var f={name:c,fps:0.6,length:d,hierarchy:[]},e,g=b.getControlPointsArray(),h=b.getLength(),r=g.length,s=0;e=r-1;b={parent:-1,keys:[]};b.keys[0]={time:0,pos:g[0],rot:[0,0,0,1],scl:[1,1,1]};b.keys[e]={time:d,pos:g[e],rot:[0,0,0,1],scl:[1,1,1]};for(e=1;ei)?1:i));this.object.translateX(b*j);this.object.translateY(b*k);e&&(this.roll+=this.rollSpeed*a*h);if(this.forward.y>this.constrainVertical[1])this.forward.y=this.constrainVertical[1],this.forward.normalize();else if(this.forward.yc.maxDistance*c.maxDistance&&c.object.position.setLength(c.maxDistance),e.lengthSq()o;o++)this.materials.push(e)}o=0;r=1;p=2;s= +3;n=4;t=5}else this.materials=[];this.sides={px:!0,nx:!0,py:!0,ny:!0,pz:!0,nz:!0};if(void 0!=h)for(var w in h)void 0!==this.sides[w]&&(this.sides[w]=h[w]);this.sides.px&&i("z","y",-1,-1,c,b,k,o);this.sides.nx&&i("z","y",1,-1,c,b,-k,r);this.sides.py&&i("x","z",1,1,a,c,q,p);this.sides.ny&&i("x","z",1,-1,a,c,-q,s);this.sides.pz&&i("x","y",1,-1,a,b,m,n);this.sides.nz&&i("x","y",-1,-1,a,b,-m,t);this.computeCentroids();this.mergeVertices()};THREE.CubeGeometry.prototype=new THREE.Geometry; +THREE.CubeGeometry.prototype.constructor=THREE.CubeGeometry; +THREE.CylinderGeometry=function(a,b,c,d,f,g){THREE.Geometry.call(this);var a=void 0!==a?a:20,b=void 0!==b?b:20,c=void 0!==c?c:100,e=c/2,d=d||8,f=f||1,h,i,j=[],k=[];for(i=0;i<=f;i++){var q=[],m=[],o=i/f,p=o*(b-a)+a;for(h=0;h<=d;h++){var n=h/d,r=p*Math.sin(2*n*Math.PI),s=-o*c+e,t=p*Math.cos(2*n*Math.PI);this.vertices.push(new THREE.Vertex(new THREE.Vector3(r,s,t)));q.push(this.vertices.length-1);m.push(new THREE.UV(n,o))}j.push(q);k.push(m)}for(i=0;ig?(b=Math.atan2(b.y-a.y,b.x-a.x),a=Math.atan2(c.y-a.y,c.x-a.x),b>a&&(a+=2*Math.PI),c=(b+a)/2,a=-Math.cos(c),c=-Math.sin(c),new THREE.Vector2(a,c)):d.multiplyScalar(g).addSelf(h).subSelf(a).clone()}function f(a){for(y=a.length;0<=--y;){$=y;C=y-1;0>C&&(C=a.length-1);for(var b= +0,c=o+2*k,b=0;bMath.abs(d-l)? +B.faceVertexUvs[0].push([new THREE.UV(f,e),new THREE.UV(j,g),new THREE.UV(m,h),new THREE.UV(q,i)]):B.faceVertexUvs[0].push([new THREE.UV(d,e),new THREE.UV(l,g),new THREE.UV(n,h),new THREE.UV(p,i)])}}}function g(a,b,c){B.vertices.push(new THREE.Vertex(new THREE.Vector3(a,b,c)))}function e(a,b,c){a+=D;b+=D;c+=D;B.faces.push(new THREE.Face3(a,b,c,null,null,w));var d=B.vertices[b].position.x,b=B.vertices[b].position.y,f=B.vertices[c].position.x,c=B.vertices[c].position.y;B.faceVertexUvs[0].push([new THREE.UV(B.vertices[a].position.x, +1-B.vertices[a].position.y),new THREE.UV(d,1-b),new THREE.UV(f,1-c)])}var h=void 0!==b.amount?b.amount:100,i=void 0!==b.bevelThickness?b.bevelThickness:6,j=void 0!==b.bevelSize?b.bevelSize:i-2,k=void 0!==b.bevelSegments?b.bevelSegments:3,q=void 0!==b.bevelEnabled?b.bevelEnabled:!0,m=void 0!==b.curveSegments?b.curveSegments:12,o=void 0!==b.steps?b.steps:1,p=b.bendPath,n=b.extrudePath,r,s=!1,t=void 0!==b.useSpacedPoints?b.useSpacedPoints:!1,w=b.material,u=b.extrudeMaterial;if(n)r=n.getPoints(m),o=r.length, +s=!0,q=!1;q||(j=i=k=0);var v,A,F,B=this,D=this.vertices.length;p&&a.addWrapPath(p);m=t?a.extractAllSpacedPoints(m):a.extractAllPoints(m);p=m.shape;m=m.holes;if(n=!THREE.Shape.Utils.isClockWise(p)){p=p.reverse();for(A=0,F=m.length;Af)return null;var g=[],e=[],h=[],i,j,k;if(0=q--){console.log("Warning, unable to triangulate polygon!");break}i=j;f<=i&&(i=0);j=i+1;f<=j&&(j=0);k=j+1;f<=k&&(k=0);var m;a:{m=a;var o=i,p=j,n=k,r=f,s=e,t=void 0,w=void 0,u=void 0,v=void 0,A=void 0, +F=void 0,B=void 0,D=void 0,H=void 0,w=m[s[o]].x,u=m[s[o]].y,v=m[s[p]].x,A=m[s[p]].y,F=m[s[n]].x,B=m[s[n]].y;if(1.0E-10>(v-w)*(B-u)-(A-u)*(F-w))m=!1;else{for(t=0;td?(d=new THREE.Face3(a.index,b.index,c.index,[a.position.clone(),b.position.clone(),c.position.clone()]),d.centroid.addSelf(a.position).addSelf(b.position).addSelf(c.position).divideScalar(3),d.normal=d.centroid.clone().normalize(), +i.faces.push(d),d=Math.atan2(d.centroid.z,-d.centroid.x),i.faceVertexUvs[0].push([h(a.uv,a.position,d),h(b.uv,b.position,d),h(c.uv,c.position,d)])):(d-=1,g(a,e(a,b),e(a,c),d),g(e(a,b),b,e(b,c),d),g(e(a,c),e(b,c),c,d),g(e(a,b),e(b,c),e(a,c),d))}function e(a,b){q[a.index]||(q[a.index]=[]);q[b.index]||(q[b.index]=[]);var c=q[a.index][b.index];void 0===c&&(q[a.index][b.index]=q[b.index][a.index]=c=f((new THREE.Vector3).add(a.position,b.position).divideScalar(2)));return c}function h(a,b,c){0>c&&1===a.u&& +(a=new THREE.UV(a.u-1,a.v));0===b.x&&0===b.z&&(a=new THREE.UV(c/2/Math.PI+0.5,a.v));return a}THREE.Geometry.call(this);for(var c=c||1,d=d||0,i=this,j=0,k=a.length;jq;q++){o=i[q];k=new THREE.Color;k.setRGB(0,0,0);for(var p=0;pw.length&&(q[o]=!0)}for(o in p)if(w=p[o],s=w[0],w=w[1],v=o.split("_"),A=v[0],v=v[1],r=new THREE.Vector3,q[o]?(r.addSelf(h[A].position),r.addSelf(h[v].position),r.multiplyScalar(0.5)):(r.addSelf(j[s]),r.addSelf(j[w]),r.addSelf(h[A].position),r.addSelf(h[v].position),r.multiplyScalar(0.25)), +k[o]=t+d.length+u,i.push(new THREE.Vertex(r)),u++,e.supportUVs&&0!=m.length)w=new THREE.UV,w.u=m[A].u+m[v].u,w.v=m[A].v+m[v].v,w.u/=2,w.v/=2,m.push(w);var I,Q;v=["123","12","2","23"];r=["123","23","3","31"];var D=["123","31","1","12"],H=["1234","12","2","23"],P=["1234","23","3","34"],L=["1234","34","4","41"],K=["1234","41","1","12"];for(o=0,p=j.length;oa.length?".":a.join("/"))+"/"},initMaterials:function(a,b,c){a.materials=[];for(var d=0;da.opacity)j.transparent=a.transparent;if(void 0!==a.depthTest)j.depthTest=a.depthTest;if(void 0!==a.vertexColors)if("face"==a.vertexColors)j.vertexColors=THREE.FaceColors;else if(a.vertexColors)j.vertexColors= +THREE.VertexColors;if(a.colorDiffuse)j.color=e(a.colorDiffuse);else if(a.DbgColor)j.color=a.DbgColor;if(a.colorSpecular)j.specular=e(a.colorSpecular);if(a.colorAmbient)j.ambient=e(a.colorAmbient);if(a.transparency)j.opacity=a.transparency;if(a.specularCoef)j.shininess=a.specularCoef;a.mapDiffuse&&b&&g(j,"map",a.mapDiffuse,a.mapDiffuseRepeat,a.mapDiffuseOffset,a.mapDiffuseWrap);a.mapLight&&b&&g(j,"lightMap",a.mapLight,a.mapLightRepeat,a.mapLightOffset,a.mapLightWrap);a.mapNormal&&b&&g(j,"normalMap", +a.mapNormal,a.mapNormalRepeat,a.mapNormalOffset,a.mapNormalWrap);a.mapSpecular&&b&&g(j,"specularMap",a.mapSpecular,a.mapSpecularRepeat,a.mapSpecularOffset,a.mapSpecularWrap);if(a.mapNormal){var i=THREE.ShaderUtils.lib.normal,k=THREE.UniformsUtils.clone(i.uniforms);k.tNormal.texture=j.normalMap;if(a.mapNormalFactor)k.uNormalScale.value=a.mapNormalFactor;if(j.map)k.tDiffuse.texture=j.map,k.enableDiffuse.value=!0;if(j.specularMap)k.tSpecular.texture=j.specularMap,k.enableSpecular.value=!0;if(j.lightMap)k.tAO.texture= +j.lightMap,k.enableAO.value=!0;k.uDiffuseColor.value.setHex(j.color);k.uSpecularColor.value.setHex(j.specular);k.uAmbientColor.value.setHex(j.ambient);k.uShininess.value=j.shininess;if(void 0!==j.opacity)k.uOpacity.value=j.opacity;j=new THREE.ShaderMaterial({fragmentShader:i.fragmentShader,vertexShader:i.vertexShader,uniforms:k,lights:!0,fog:!0})}else j=new THREE[i](j);if(void 0!==a.DbgName)j.name=a.DbgName;return j}};THREE.BinaryLoader=function(a){THREE.Loader.call(this,a)}; +THREE.BinaryLoader.prototype=new THREE.Loader;THREE.BinaryLoader.prototype.constructor=THREE.BinaryLoader;THREE.BinaryLoader.prototype.supr=THREE.Loader.prototype;THREE.BinaryLoader.prototype.load=function(a,b,c,d){var c=c?c:this.extractUrlBase(a),d=d?d:this.extractUrlBase(a),f=this.showProgress?THREE.Loader.prototype.updateProgress:null;this.onLoadStart();this.loadAjaxJSON(this,a,b,c,d,f)}; +THREE.BinaryLoader.prototype.loadAjaxJSON=function(a,b,c,d,f,g){var e=new XMLHttpRequest;e.onreadystatechange=function(){if(4==e.readyState)if(200==e.status||0==e.status){var h=JSON.parse(e.responseText);a.loadAjaxBuffers(h,c,f,d,g)}else console.error("THREE.BinaryLoader: Couldn't load ["+b+"] ["+e.status+"]")};e.open("GET",b,!0);e.overrideMimeType&&e.overrideMimeType("text/plain; charset=x-user-defined");e.setRequestHeader("Content-Type","text/plain");e.send(null)}; +THREE.BinaryLoader.prototype.loadAjaxBuffers=function(a,b,c,d,f){var g=new XMLHttpRequest,e=c+"/"+a.buffers,h=0;g.onreadystatechange=function(){4==g.readyState?200==g.status||0==g.status?THREE.BinaryLoader.prototype.createBinModel(g.response,b,d,a.materials):console.error("THREE.BinaryLoader: Couldn't load ["+e+"] ["+g.status+"]"):3==g.readyState?f&&(0==h&&(h=g.getResponseHeader("Content-Length")),f({total:h,loaded:g.responseText.length})):2==g.readyState&&(h=g.getResponseHeader("Content-Length"))}; +g.open("GET",e,!0);g.responseType="arraybuffer";g.send(null)}; +THREE.BinaryLoader.prototype.createBinModel=function(a,b,c,d){var f=function(b){var c,f,i,j,k,q,m,o,p,n,r,s,t,w,u;function v(a){return a%4?4-a%4:0}function A(a,b){return(new Uint8Array(a,b,1))[0]}function F(a,b){return(new Uint32Array(a,b,1))[0]}function B(b,c){var d,e,f,g,h,i,j,k,l=new Uint32Array(a,c,3*b);for(d=0;da.length?".":a.join("/"))+"/");if((a=U.evaluate("//dae:asset",U,E,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null).iterateNext())&&a.childNodes)for(f=0;fp)break}if(!s){s=new l(p);t=-1;u=0;for(v=d.length;u=p&&(t=u);p=t;d.splice(-1==p?d.length: +p,0,s)}s.addTarget(f,j,g,r)}}else console.log('Could not find transform "'+b.sid+'" in node '+this.id)}for(c=0;cthis.set)this.set=0;return this};F.prototype.parse=function(a){this.id=a.getAttribute("id");for(var b=0;bthis.transparency,c;for(c in this)switch(c){case "ambient":case "emission":case "diffuse":case "specular":var d=this[c]; +if(d instanceof D)if(d.isTexture()){if(this.effect.sampler&&this.effect.surface&&this.effect.sampler.source==this.effect.surface.sid){var e=Ka[this.effect.surface.init_from];if(e)e=THREE.ImageUtils.loadTexture(Sa+e.init_from),e.wrapS=d.texOpts.wrapU?THREE.RepeatWrapping:THREE.ClampToEdgeWrapping,e.wrapT=d.texOpts.wrapV?THREE.RepeatWrapping:THREE.ClampToEdgeWrapping,e.offset.x=d.texOpts.offsetU,e.offset.y=d.texOpts.offsetV,e.repeat.x=d.texOpts.repeatU,e.repeat.y=d.texOpts.repeatV,a.map=e}}else"diffuse"== +c?a.color=d.color.getHex():b||(a[c]=d.color.getHex());break;case "shininess":case "reflectivity":a[c]=this[c];break;case "transparency":if(b)a.transparent=!0,a.opacity=this[c],b=!0}a.shading=za;return this.material=new THREE.MeshLambertMaterial(a)};I.prototype.parse=function(a){for(var b=0;bf||1f?0:1;if(h.length)for(var e=[],i=0;ir.parameters.opacity)r.parameters.transparent=!0;if(r.parameters.normalMap){a=THREE.ShaderUtils.lib.normal;k=THREE.UniformsUtils.clone(a.uniforms);n=r.parameters.color;P=r.parameters.specular;c=r.parameters.ambient;K=r.parameters.shininess;k.tNormal.texture=C.textures[r.parameters.normalMap];if(r.parameters.normalMapFactor)k.uNormalScale.value=r.parameters.normalMapFactor;if(r.parameters.map)k.tDiffuse.texture=r.parameters.map,k.enableDiffuse.value=!0;if(r.parameters.lightMap)k.tAO.texture= +r.parameters.lightMap,k.enableAO.value=!0;if(r.parameters.specularMap)k.tSpecular.texture=C.textures[r.parameters.specularMap],k.enableSpecular.value=!0;k.uDiffuseColor.value.setHex(n);k.uSpecularColor.value.setHex(P);k.uAmbientColor.value.setHex(c);k.uShininess.value=K;if(r.parameters.opacity)k.uOpacity.value=r.parameters.opacity;I=new THREE.ShaderMaterial({fragmentShader:a.fragmentShader,vertexShader:a.vertexShader,uniforms:k,lights:!0,fog:!0})}else I=new THREE[r.type](r.parameters);C.materials[q]= +I}f();i.callbackSync(C);h()};THREE.UTF8Loader=function(){}; +THREE.UTF8Loader.prototype.load=function(a,b,c){var d=new XMLHttpRequest,f=void 0!==c.scale?c.scale:1,g=void 0!==c.offsetX?c.offsetX:0,e=void 0!==c.offsetY?c.offsetY:0,h=void 0!==c.offsetZ?c.offsetZ:0;d.onreadystatechange=function(){4==d.readyState?200==d.status||0==d.status?THREE.UTF8Loader.prototype.createModel(d.responseText,b,f,g,e,h):console.error("THREE.UTF8Loader: Couldn't load ["+a+"] ["+d.status+"]"):3!=d.readyState&&2==d.readyState&&d.getResponseHeader("Content-Length")};d.open("GET",a, +!0);d.send(null)};THREE.UTF8Loader.prototype.decompressMesh=function(a){var b=a.charCodeAt(0);57344<=b&&(b-=2048);b++;for(var c=new Float32Array(8*b),d=1,f=0;8>f;f++){for(var g=0,e=0;e>1^-(h&1));c[8*e+f]=g}d+=b}b=a.length-d;g=new Uint16Array(b);for(f=e=0;f=this.maxCount-3&&h(this)};this.begin=function(){this.count=0; +this.hasNormal=this.hasPos=!1};this.end=function(a){if(0!==this.count){for(var b=3*this.count;bq&&(q=1);i=Math.floor(i+h);i>this.size-1&&(i=this.size-1);var m=Math.floor(j-h);1>m&&(m=1);j=Math.floor(j+h);j>this.size-1&&(j=this.size-1);var o=Math.floor(k-h);1>o&&(o=1);h=Math.floor(k+h);h>this.size-1&&(h=this.size- +1);for(var p,n,r,s,t,w,u,k=q;kj&&(o=j);for(f=0;fk&&(p=k);for(g=0;gk&&(p=k);for(e=0;e=b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)?(j=!1,k=a(THREE.ShaderFlares.lensFlare)):(j=!0,k=a(THREE.ShaderFlares.lensFlareVertexTexture));q={};m={};q.vertex=b.getAttribLocation(k,"position");q.uv=b.getAttribLocation(k,"uv");m.renderType=b.getUniformLocation(k,"renderType");m.map=b.getUniformLocation(k,"map");m.occlusionMap=b.getUniformLocation(k,"occlusionMap");m.opacity=b.getUniformLocation(k,"opacity");m.color=b.getUniformLocation(k, +"color");m.scale=b.getUniformLocation(k,"scale");m.rotation=b.getUniformLocation(k,"rotation");m.screenPosition=b.getUniformLocation(k,"screenPosition");o=!1};this.render=function(a,d,f,s){var a=a.__webglFlares,t=a.length;if(t){var w=new THREE.Vector3,u=s/f,v=0.5*f,A=0.5*s,F=16/s,B=new THREE.Vector2(F*u,F),D=new THREE.Vector3(1,1,0),H=new THREE.Vector2(1,1),I=m,F=q;b.useProgram(k);o||(b.enableVertexAttribArray(q.vertex),b.enableVertexAttribArray(q.uv),o=!0);b.uniform1i(I.occlusionMap,0);b.uniform1i(I.map, +1);b.bindBuffer(b.ARRAY_BUFFER,g);b.vertexAttribPointer(F.vertex,2,b.FLOAT,!1,16,0);b.vertexAttribPointer(F.uv,2,b.FLOAT,!1,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,e);b.disable(b.CULL_FACE);b.depthMask(!1);var Q,P,L,K,O;for(Q=0;Qv;v++)s[v]=new THREE.Vector3,n[v]=new THREE.Vector3;s=t.shadowCascadeNearZ[r];t=t.shadowCascadeFarZ[r];n[0].set(-1,-1,s);n[1].set(1,-1,s);n[2].set(-1,1,s);n[3].set(1,1,s);n[4].set(-1,-1,t);n[5].set(1,-1,t);n[6].set(-1,1,t);n[7].set(1,1,t);u.originalCamera=j;n=new THREE.Gyroscope;n.position=m.shadowCascadeOffset;n.add(u);n.add(u.target);j.add(n);m.shadowCascadeArray[p]=u;console.log("Created virtualLight",u)}r=m;s=p;t=r.shadowCascadeArray[s];t.position.copy(r.position); +t.target.position.copy(r.target.position);t.lookAt(t.target);t.shadowCameraVisible=r.shadowCameraVisible;t.shadowDarkness=r.shadowDarkness;t.shadowBias=r.shadowCascadeBias[s];n=r.shadowCascadeNearZ[s];r=r.shadowCascadeFarZ[s];t=t.pointsFrustum;t[0].z=n;t[1].z=n;t[2].z=n;t[3].z=n;t[4].z=r;t[5].z=r;t[6].z=r;t[7].z=r;w[o]=u;o++}else w[o]=m,o++;for(k=0,q=w.length;kr;r++){s=t[r];s.copy(n[r]);THREE.ShadowMapPlugin.__projector.unprojectVector(s, +p);o.matrixWorldInverse.multiplyVector3(s);if(s.xh.x)h.x=s.x;if(s.yh.y)h.y=s.y;if(s.zh.z)h.z=s.z}o.left=e.x;o.right=h.x;o.top=h.y;o.bottom=e.y;o.updateProjectionMatrix()}o=m.shadowMap;n=m.shadowMatrix;p=m.shadowCamera;p.position.copy(m.matrixWorld.getPosition());p.lookAt(m.target.matrixWorld.getPosition());p.updateMatrixWorld();p.matrixWorldInverse.getInverse(p.matrixWorld);if(m.cameraHelper)m.cameraHelper.lines.visible=m.shadowCameraVisible; +m.shadowCameraVisible&&m.cameraHelper.update(m.shadowCamera);n.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);n.multiplySelf(p.projectionMatrix);n.multiplySelf(p.matrixWorldInverse);if(!p._viewMatrixArray)p._viewMatrixArray=new Float32Array(16);p.matrixWorldInverse.flattenToArray(p._viewMatrixArray);if(!p._projectionMatrixArray)p._projectionMatrixArray=new Float32Array(16);p.projectionMatrix.flattenToArray(p._projectionMatrixArray);g.multiply(p.projectionMatrix,p.matrixWorldInverse);f.setFromMatrix(g); +b.setRenderTarget(o);b.clear();t=i.__webglObjects;for(m=0,o=t.length;m= 0; i--) { + if (whitespace.indexOf(str.charAt(i)) === -1) { + str = str.substring(0, i + 1); + break; + } + } + + return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''; +} + + +(function() { + var lastTime = 0; + var vendors = ['ms', 'moz', 'webkit', 'o']; + for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { + window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; + window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] + || window[vendors[x] + 'CancelRequestAnimationFrame']; + } + if (!window.requestAnimationFrame) + window.requestAnimationFrame = function(callback, element) { + var currTime = new Date().getTime(); + var timeToCall = Math.max(0, 16 - (currTime - lastTime)); + var id = window.setTimeout(function() { + callback(currTime + timeToCall); + }, + timeToCall); + lastTime = currTime + timeToCall; + return id; + }; + if (!window.cancelAnimationFrame) + window.cancelAnimationFrame = function(id) { + clearTimeout(id); + }; +}()); \ No newline at end of file diff --git a/js/libs/fix/detect-zoom.js b/js/libs/fix/detect-zoom.js new file mode 100644 index 00000000..01422919 --- /dev/null +++ b/js/libs/fix/detect-zoom.js @@ -0,0 +1,242 @@ +// detect-zoom is dual-licensed under the WTFPL and MIT license, +// at the recipient's choice. +// https://github.com/yonran/detect-zoom/ +var DetectZoom = { + mediaQueryBinarySearch: function( + property, unit, a, b, maxIter, epsilon) { + var matchMedia; + var head, style, div + if (window.matchMedia) { + matchMedia = window.matchMedia; + } else { + head = document.getElementsByTagName('head')[0]; + style = document.createElement('style'); + div = document.createElement('div'); + div.className = 'mediaQueryBinarySearch'; + head.appendChild(style); + div.style.display = 'none'; + document.body.appendChild(div); + matchMedia = function(query) { + style.sheet.insertRule('@media ' + query + + '{.mediaQueryBinarySearch ' + + '{text-decoration: underline} }', 0); + var matched = getComputedStyle(div, null).textDecoration + == 'underline'; + style.sheet.deleteRule(0); + return {matches: matched}; + } + } + var r = binarySearch(a, b, maxIter); + if (div) { + head.removeChild(style); + document.body.removeChild(div); + } + return r; + + function binarySearch(a, b, maxIter) { + var mid = (a + b) / 2; + if (maxIter == 0 || b - a < epsilon) + return mid; + var query = "(" + property + ":" + mid + unit + ")"; + if (matchMedia(query).matches) { + return binarySearch(mid, b, maxIter - 1); + } else { + return binarySearch(a, mid, maxIter - 1); + } + } + }, + _zoomIe7: function() { + // the trick: body's offsetWidth was in CSS pixels, while + // getBoundingClientRect() was in system pixels in IE7. + // Thanks to http://help.dottoro.com/ljgshbne.php + var rect = document.body.getBoundingClientRect(); + var z = (rect.right - rect.left) / document.body.offsetWidth; + z = Math.round(z * 100) / 100; + return {zoom: z, devicePxPerCssPx: z}; + }, + _zoomIe8: function() { + // IE 8+: no trick needed! + // TODO: MSDN says that logicalXDPI and deviceXDPI existed since IE6 + // (which didn't even have whole-page zoom). Check to see whether + // this method would also work in IE7. + var zoom = screen.deviceXDPI / screen.logicalXDPI; + return { + zoom: zoom, + devicePxPerCssPx: zoom + }; + }, + _zoomWebkitMobile: function() { + // the trick: window.innerWIdth is in CSS pixels, while + // screen.width and screen.height are in system pixels. + // And there are no scrollbars to mess up the measurement. + var devicePixelRatio = window.devicePixelRatio != null ? window.devicePixelRatio : 1 + , deviceWidth; + if (Math.abs(window.orientation) == 90) { + deviceWidth = screen.height; + } else { + deviceWidth = screen.width; + } + var z = deviceWidth / window.innerWidth; + // return immediately; don't round at the end. + return {zoom: z, devicePxPerCssPx: z * devicePixelRatio}; + }, + _zoomWebkit: function() { + // the trick: an element's clientHeight is in CSS pixels, while you can + // set its line-height in system pixels using font-size and + // -webkit-text-size-adjust:none. + // device-pixel-ratio: http://www.webkit.org/blog/55/high-dpi-web-sites/ + + // Previous trick (used before http://trac.webkit.org/changeset/100847): + // documentElement.scrollWidth is in CSS pixels, while + // document.width was in system pixels. Note that this is the + // layout width of the document, which is slightly different from viewport + // because document width does not include scrollbars and might be wider + // due to big elements. + + var devicePixelRatio = window.devicePixelRatio != null ? window.devicePixelRatio : 1; + + // The container exists so that the div will be laid out in its own flow + // while not impacting the layout, viewport size, or display of the + // webpage as a whole. + var container = document.createElement('div') + , div = document.createElement('div'); + + // Add !important and relevant CSS rule resets + // so that other rules cannot affect the results. + var important = function(str) { + return str.replace(/;/g, " !important;"); + }; + + container.setAttribute('style', important('width:0; height:0; overflow:hidden; visibility:hidden; position: absolute;')); + div.innerHTML = "1
2
3
4
5
6
7
8
9
0"; + div.setAttribute('style', important('font: 100px/1em sans-serif; -webkit-text-size-adjust: none; height: auto; width: 1em; padding: 0; overflow: visible;')); + + container.appendChild(div); + document.body.appendChild(container); + var z = 1000 / div.clientHeight; + z = Math.round(z * 100) / 100; + var r = { + zoom: z, + devicePxPerCssPx: devicePixelRatio * z + }; + document.body.removeChild(container); + return r; + }, + _zoomFF35: function() { + // the trick for FF3.5 ONLY: device-width gives CSS pixels, while + // screen.width gave system pixels. Thanks to QuirksMode's widths table, + // which called it a bug. http://www.quirksmode.org/m/widths.html + var z = screen.width / + this.mediaQueryBinarySearch('min-device-width', 'px', 0, 6000, 20, .0001); + z = Math.round(z * 100) / 100; + return {zoom: z, devicePxPerCssPx: z}; + }, + _zoomFF36: function() { + // the hack for FF3.6: you can measure scrollbar's width in CSS pixels, + // while in system pixels it's 15px (verified in Ubuntu). + + // TODO: verify for every platform that a scrollbar is exactly 15px wide. + var container = document.createElement('div') + , outerDiv = document.createElement('div'); + // The container exists so that the div will be laid out in its own flow + // while not impacting the layout, viewport size, or display of the + // webpage as a whole. + container.setAttribute('style', 'width:0; height:0; overflow:hidden;' + + 'visibility:hidden; position: absolute'); + outerDiv.style.width = outerDiv.style.height = '500px'; // enough for all the scrollbars + var div = outerDiv; + for (var i = 0; i < 10; ++i) { + var child = document.createElement('div'); + child.style.overflowY = 'scroll'; + div.appendChild(child); + div = child; + } + container.appendChild(outerDiv); + document.body.appendChild(container); + var outerDivWidth = outerDiv.clientWidth; + var innerDivWidth = div.clientWidth; + var scrollbarWidthCss = (outerDivWidth - innerDivWidth) / 10; + document.body.removeChild(container); + var scrollbarWidthDevice = 15; // Mac and Linux: scrollbars are 15px wide + if (-1 != navigator.platform.indexOf('Win')) { + scrollbarWidthDevice = 17; + } + var z = scrollbarWidthDevice / scrollbarWidthCss; + z = Math.round(z * 100) / 100; + return {zoom: z, devicePxPerCssPx: z}; + }, + _zoomFF4: function() { + // no real trick; device-pixel-ratio is the ratio of device dpi / css dpi. + // (Note that this is a different interpretation than Webkit's device + // pixel ratio, which is the ratio device dpi / system dpi). + // TODO: is mozmm vs. mm promising? + var z = this.mediaQueryBinarySearch( + 'min--moz-device-pixel-ratio', + '', 0, 10, 20, .0001); + z = Math.round(z * 100) / 100; + return {zoom: z, devicePxPerCssPx: z}; + }, + _zoomOperaOlder: function() { + // 10.00 (or before) to 11.01: + // the trick: a div with position:fixed;width:100%'s offsetWidth is the + // viewport width in CSS pixels, while window.innerWidth was in system + // pixels. Thanks to: + // http://virtuelvis.com/2005/05/how-to-detect-zoom-level-in-opera/ + // TODO: fix bug: when there is a scrollbar, fixed div does NOT + // include the scrollbar, while window.outerWidth DOES. This causes the + // calculation to be off by a few percent. + var fixedDiv = document.createElement('div'); + fixedDiv.style.position = 'fixed'; + fixedDiv.style.width = '100%'; + fixedDiv.style.height = '100%'; + fixedDiv.style.top = fixedDiv.style.left = '0'; + fixedDiv.style.visibility = 'hidden'; + document.body.appendChild(fixedDiv); + var z = window.innerWidth / fixedDiv.offsetWidth; + document.body.removeChild(fixedDiv); + return {zoom: z, devicePxPerCssPx: z}; + }, + _zoomOpera11: function() { + // works starting Opera 11.11 + // the trick: outerWidth is the viewport width including scrollbars in + // system px, while innerWidth is the viewport width including scrollbars + // in CSS px; + var z = window.outerWidth / window.innerWidth; + z = Math.round(z * 100) / 100; + return {zoom: z, devicePxPerCssPx: z}; + }, + ratios: function() { + var r; + if (Modernizr.ftouch) { + return this._zoomWebkitMobile(); + } else if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { + return this._zoomIe8(); + } else if ('ontouchstart' in window && document.body.style.webkitTextSizeAdjust != null) { + return this._zoomWebkitMobile(); + } else if (document.body.style.webkitTextSizeAdjust != null) { // webkit + return this._zoomWebkit(); + } else if (-1 != navigator.userAgent.indexOf('Firefox/3.5')) { + return this._zoomFF35(); + } else if (-1 != navigator.userAgent.indexOf('Firefox/3.6')) { + return this._zoomFF36(); + } else if (-1 != navigator.appVersion.indexOf("MSIE 7.")) { + return this._zoomIe7(); + } else if (-1 != navigator.userAgent.indexOf('Opera')) { + var versionIdx = navigator.userAgent.indexOf('Version/'); + if (11.01 < parseFloat(navigator.userAgent.substr(versionIdx + 8))) + return this._zoomOpera11(); + else + return this._zoomOperaOlder(); + } else if (0.001 < (r = this._zoomFF4()).zoom) { + return r; + } else { + return {zoom: 1, devicePxPerCssPx: 1} + } + }, + zoom: function() { + return this.ratios().zoom; + }, + device: function() { + return this.ratios().devicePxPerCssPx; + } +}; \ No newline at end of file diff --git a/js/libs/fix/ios-orientation.js b/js/libs/fix/ios-orientation.js new file mode 100644 index 00000000..1d5bd272 --- /dev/null +++ b/js/libs/fix/ios-orientation.js @@ -0,0 +1,56 @@ +(function(w) { + + // This fix addresses an iOS bug, so return early if the UA claims it's something else. + var ua = navigator.userAgent; + if (!(/iPhone|iPad|iPod/.test(navigator.platform))) { + //return; + } + + var doc = w.document; + + if (!doc.querySelector) { + return; + } + + var meta = doc.querySelector("meta[name=viewport]"), + initialContent = meta && meta.getAttribute("content"), + disabledZoom = initialContent + ",maximum-scale=1", + enabledZoom = initialContent + ",maximum-scale=1", + enabled = true, + x, y, z, aig; + + if (!meta) { + return; + } + + function restoreZoom() { + meta.setAttribute("content", enabledZoom); + enabled = true; + } + + function disableZoom() { + meta.setAttribute("content", disabledZoom); + enabled = false; + } + + function checkTilt(e) { + aig = e.accelerationIncludingGravity; + x = Math.abs(aig.x); + y = Math.abs(aig.y); + z = Math.abs(aig.z); + + // If portrait orientation and in one of the danger zones + if ((!w.orientation || w.orientation === 180) && (x > 7 || ((z > 6 && y < 8 || z < 8 && y > 6) && x > 5))) { + if (enabled) { + disableZoom(); + } + } + else if (!enabled) { + restoreZoom(); + } + } + + w.addEventListener("orientationchange", restoreZoom, false); + w.addEventListener("devicemotion", checkTilt, false); + +})(this); \ No newline at end of file diff --git a/js/libs/flashdetect.js b/js/libs/flashdetect.js new file mode 100644 index 00000000..689a6e30 --- /dev/null +++ b/js/libs/flashdetect.js @@ -0,0 +1,200 @@ +/* +Copyright (c) Copyright (c) 2007, Carl S. Yestrau All rights reserved. +Code licensed under the BSD License: http://www.featureblend.com/license.txt +Version: 1.0.4 +*/ +var FlashDetect = new function(){ + var self = this; + self.installed = false; + self.raw = ""; + self.major = -1; + self.minor = -1; + self.revision = -1; + self.revisionStr = ""; + var activeXDetectRules = [ + { + "name":"ShockwaveFlash.ShockwaveFlash.7", + "version":function(obj){ + return getActiveXVersion(obj); + } + }, + { + "name":"ShockwaveFlash.ShockwaveFlash.6", + "version":function(obj){ + var version = "6,0,21"; + try{ + obj.AllowScriptAccess = "always"; + version = getActiveXVersion(obj); + }catch(err){} + return version; + } + }, + { + "name":"ShockwaveFlash.ShockwaveFlash", + "version":function(obj){ + return getActiveXVersion(obj); + } + } + ]; + /** + * Extract the ActiveX version of the plugin. + * + * @param {Object} The flash ActiveX object. + * @type String + */ + var getActiveXVersion = function(activeXObj){ + var version = -1; + try{ + version = activeXObj.GetVariable("$version"); + }catch(err){} + return version; + }; + /** + * Try and retrieve an ActiveX object having a specified name. + * + * @param {String} name The ActiveX object name lookup. + * @return One of ActiveX object or a simple object having an attribute of activeXError with a value of true. + * @type Object + */ + var getActiveXObject = function(name){ + var obj = -1; + try{ + obj = new ActiveXObject(name); + }catch(err){ + obj = {activeXError:true}; + } + return obj; + }; + /** + * Parse an ActiveX $version string into an object. + * + * @param {String} str The ActiveX Object GetVariable($version) return value. + * @return An object having raw, major, minor, revision and revisionStr attributes. + * @type Object + */ + var parseActiveXVersion = function(str){ + var versionArray = str.split(",");//replace with regex + return { + "raw":str, + "major":parseInt(versionArray[0].split(" ")[1], 10), + "minor":parseInt(versionArray[1], 10), + "revision":parseInt(versionArray[2], 10), + "revisionStr":versionArray[2] + }; + }; + /** + * Parse a standard enabledPlugin.description into an object. + * + * @param {String} str The enabledPlugin.description value. + * @return An object having raw, major, minor, revision and revisionStr attributes. + * @type Object + */ + var parseStandardVersion = function(str){ + var descParts = str.split(/ +/); + var majorMinor = descParts[2].split(/\./); + var revisionStr = descParts[3]; + return { + "raw":str, + "major":parseInt(majorMinor[0], 10), + "minor":parseInt(majorMinor[1], 10), + "revisionStr":revisionStr, + "revision":parseRevisionStrToInt(revisionStr) + }; + }; + /** + * Parse the plugin revision string into an integer. + * + * @param {String} The revision in string format. + * @type Number + */ + var parseRevisionStrToInt = function(str){ + return parseInt(str.replace(/[a-zA-Z]/g, ""), 10) || self.revision; + }; + /** + * Is the major version greater than or equal to a specified version. + * + * @param {Number} version The minimum required major version. + * @type Boolean + */ + self.majorAtLeast = function(version){ + return self.major >= version; + }; + /** + * Is the minor version greater than or equal to a specified version. + * + * @param {Number} version The minimum required minor version. + * @type Boolean + */ + self.minorAtLeast = function(version){ + return self.minor >= version; + }; + /** + * Is the revision version greater than or equal to a specified version. + * + * @param {Number} version The minimum required revision version. + * @type Boolean + */ + self.revisionAtLeast = function(version){ + return self.revision >= version; + }; + /** + * Is the version greater than or equal to a specified major, minor and revision. + * + * @param {Number} major The minimum required major version. + * @param {Number} (Optional) minor The minimum required minor version. + * @param {Number} (Optional) revision The minimum required revision version. + * @type Boolean + */ + self.versionAtLeast = function(major){ + var properties = [self.major, self.minor, self.revision]; + var len = Math.min(properties.length, arguments.length); + for(i=0; i=arguments[i]){ + if(i+10){ + var type = 'application/x-shockwave-flash'; + var mimeTypes = navigator.mimeTypes; + if(mimeTypes && mimeTypes[type] && mimeTypes[type].enabledPlugin && mimeTypes[type].enabledPlugin.description){ + var version = mimeTypes[type].enabledPlugin.description; + var versionObj = parseStandardVersion(version); + self.raw = versionObj.raw; + self.major = versionObj.major; + self.minor = versionObj.minor; + self.revisionStr = versionObj.revisionStr; + self.revision = versionObj.revision; + self.installed = true; + } + }else if(navigator.appVersion.indexOf("Mac")==-1 && window.execScript){ + var version = -1; + for(var i=0; i'); + + fb([Fluidbook.REPEAT,Fluidbook.STRETCH]); + + + if (this.fluidbook.datas.links.background != undefined + && this.fluidbook.datas.repeat != Fluidbook.REPEAT + && this.fluidbook.datas.repeat != Fluidbook.STRETCH + && this.fluidbook.datas.links.background != '') { + $("#background").prepend(''); + hasLinks = true; + } + }, + resize: function(w, h) { + if (!this.hasLinks) { + return; + } + + var left, top, iw, ih; + if (this.fluidbook.datas.repeat == Fluidbook.NONE) { + iw = this.fluidbook.datas.backgroundImageDimensions.width; + ih = this.fluidbook.datas.backgroundImageDimensions.height; + } + + + + if (this.fluidbook.datas.backgroundHAlign == Fluidbook.LEFT) { + left = 0 + } else if (this.fluidbook.datas.backgroundHAlign == Fluidbook.RIGHT) { + left = w - iw; + } else if (this.fluidbook.datas.backgroundHAlign == Fluidbook.CENTER) { + left = (w - iw) / 2; + } + + + if (this.fluidbook.datas.backgroundVAlign == Fluidbook.TOP) { + top = 0 + } else if (this.fluidbook.datas.backgroundVAlign == Fluidbook.BOTTOM) { + top = h - ih; + } else if (this.fluidbook.datas.backgroundVAlign == Fluidbook.MIDDLE) { + top = (h - ih) / 2; + } + + $("#background .links").css({ + top: top, + left: left + }); + } +}; + diff --git a/js/libs/fluidbook/fluidbook.bookmarks.js b/js/libs/fluidbook/fluidbook.bookmarks.js new file mode 100644 index 00000000..dc35c8e0 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.bookmarks.js @@ -0,0 +1,440 @@ +function FluidbookBookmarks(fluidbook) { + this.fluidbook = fluidbook; + this.enabled = false; + this.bookmarks = []; + + this._pagesToGroup = []; + this._groupNames = []; + this._groups = 0; + this._groupOrder = []; + + this._cornersIndex = []; + this._cornersPages = []; + + this.enabled = this.fluidbook.datas.bookmark; + this.init(); +} + +FluidbookBookmarks.prototype = { + init: function() { + var $this = this; + $(document).on('click', '.bookmark', function() { + $this.toggleBookmark(parseInt($(this).attr('data-page'))); + return false; + }); + + $(document).on('click', '.bookmarkssub a.send', function() { + var subject = '%title%'; + if ($this.fluidbook.datas.bookmark_email_title != '') { + subject = $this.fluidbook.datas.bookmark_email_title; + } + + + var body = $this.fluidbook.l10n.__('Please see the attached files from "%title%".'); + if ($this.fluidbook.datas.bookmark_email_body != '') { + body = $this.fluidbook.datas.bookmark_email_body; + } + + subject = subject.replace(/\%title\%/gi, $this.fluidbook.datas.title); + body = trim(body.replace(/\%title\%/gi, $this.fluidbook.datas.title), ' .'); + body += " : " + $this.getPDF(); + + $this.fluidbook.intentShare(subject, body); + return false; + }); + + $(document).on('click', '.bookmarkssub a.print', function() { + $this.fluidbook._openFile($this.getPDF(), $(this), 'pdf', $this.getBookmarksCompacted() + '.pdf'); + return false; + }); + + for (var g in this.fluidbook.datas.bookmarkGroups) { + + var group = this.fluidbook.datas.bookmarkGroups[g]; + this.addGroup(group.page, group.nb, group.name); + } + this.completeGroups(); + this._groupOrder.sort($.proxy(this.sortGroup, this)); + + this.bookmarks = this.getSavedBookmarks(); + for (var i in this.bookmarks) { + this.addBookmark(this.bookmarks[i], true); + } + }, + sortGroup: function(a, b) { + var p_a = this.getPagesOfGroup(a)[0]; + var p_b = this.getPagesOfGroup(b)[0]; + return p_a - p_b; + }, + sortnumeric: function(a, b) { + return a - b; + }, + getPDF: function() { + return 'http://workshop.fluidbook.com/s/e/' + this.fluidbook.datas.cid + '/' + this.getBookmarksCompacted(); + }, + getBookmarksCompacted: function() { + this.bookmarks.sort(this.sortnumeric); + + var g = []; + var rs = 0; + var re = 0; + for (var i = 0; i < this.bookmarks.length; i++) { + var b = this.bookmarks[i]; + if (rs == 0) { + rs = re = b; + continue; + } + if (re + 1 == b) { + re = b; + continue; + } + if (rs == re) { + g.push('' + rs); + } else { + g.push(rs + '-' + re); + } + + rs = re = b; + } + + if (rs != 0) { + if (rs == re) { + g.push('' + rs); + } else { + g.push(rs + '-' + re); + } + } + + return g.join(','); + }, + addGroup: function(from, nb, name) { + var to = Math.min(from + (nb - 1), this.fluidbook.datas.pages); + for (var i = from; i <= to; i++) + { + this._pagesToGroup[i] = this._groups; + } + this._groupNames[this._groups] = name; + this._groupOrder.push(this._groups); + this._groups++; + }, + completeGroups: function() { + for (var i = 1; i <= this.fluidbook.datas.pages; i++) { + if (this._pagesToGroup[i] == undefined || this._pagesToGroup[i] == null) { + this._pagesToGroup[i] = this._groups; + this._groupOrder.push(this._groups); + this._groups++; + } + } + }, + getPreviousGroup: function(group) { + var o = this.getOrderGroup(group); + if (o == -1) { + return false; + } + o--; + return this._groupOrder[o]; + }, + getNextGroup: function(group) { + var o = this.getOrderGroup(group); + if (o == -1) { + return false; + } + o++; + return this._groupOrder[o]; + }, + getOrderGroup: function(group) { + return this._groupOrder.indexOf(group); + }, + getGroupName: function(groupId) + { + var res = ''; + if (this._groupNames[groupId] != undefined) { + res = this._groupNames[groupId]; + } + if (res == '') { + var pages = this.getPagesOfGroup(groupId); + res = this.fluidbook.physicalToVirtual(pages[0]); + if (pages.length == 1) { + return res; + } + res += " - " + this.fluidbook.physicalToVirtual(pages[pages.length - 1]); + } + return res; + }, + getPagesOfGroup: function(groupId) + { + var res = []; + for (var i = 1; i <= this.fluidbook.datas.pages; i++) { + if (this._pagesToGroup[i] == groupId) { + res.push(i); + } + } + return res; + }, + getPagesNumberInGroup: function(groupId) { + return this.getPagesOfGroup(groupId).length; + }, + getBookmarkedGroups: function(onlyBookmarked) + { + if (onlyBookmarked == undefined) { + onlyBookmarked = true; + } + + var res = []; + var nb; + var groupId; + for (var i = 1; i <= this.fluidbook.datas.pages; ) { + if (this.isBookmarked(i) || !onlyBookmarked) { + groupId = this.getGroupOfPage(i); + nb = this.getPagesNumberInGroup(groupId); + res.push({page: i, nb: nb, name: this.getGroupName(groupId)}); + i += nb; + continue; + } + i++; + } + return res; + }, + getOrderedGroups: function() { + return this.getBookmarkedGroups(false); + }, + getGroupOfPage: function(page) { + return this._pagesToGroup[page]; + }, + getNextPageInGroupOfPage: function(page) { + var group = this.getLinkedPages(page); + var index = group.indexOf(page); + if (index == group.length - 1) { + return false; + } + return group[index + 1]; + }, + getPreviousPageInGroupOfPage: function(page) { + var group = this.getLinkedPages(page); + var index = group.indexOf(page); + if (index == 0) { + return false; + } + return group[index - 1]; + }, + getNextGroupCover: function(page) { + var group = this.getGroupOfPage(page); + group = this.getNextGroup(group); + if (group === false) { + return false; + } + return this.getCoverOfGroup(group); + }, + getPreviousGroupCover: function(page) { + var group = this.getGroupOfPage(page); + group = this.getPreviousGroup(group); + if (group === false) { + return false; + } + return this.getCoverOfGroup(group); + }, + getCoverOfGroup: function(group) { + var pages = this.getPagesOfGroup(group); + if (pages.length) { + return pages[0]; + } + return false; + }, + hasNextPageInGroup: function(page) { + var group = this.getGroupOfPage(page); + var pages = this.getPagesOfGroup(group); + var i = pages.indexOf(page); + if (i == pages.length - 1) { + return false; + } + return true; + }, + getLinkedPages: function(page) { + var group = this.getGroupOfPage(page); + if (group == -1 || isNaN(group)) { + return []; + } + return this.getPagesOfGroup(group); + }, + addBookmark: function(page, cornersOnly) + { + if (cornersOnly == undefined) { + cornersOnly = false; + } + var pages = this.getLinkedPages(page); + for (i in pages) + { + var page = pages[i]; + if (!cornersOnly) { + this.bookmarks.push(page); + } + } + if (!cornersOnly) { + this.updateBookmarks(); + // TODO add stats call + } + }, + setCornersEnabled: function(page, enabled) { + var bookmarks = $('.bookmark[data-page="' + page + '"]'); + if (enabled) { + $(bookmarks).attr('data-enabled', 'enabled'); + } else { + $(bookmarks).attr('data-enabled', null); + } + }, + disableCorners: function() { + $(".bookmark").attr('data-enabled', null); + }, + toggleBookmark: function(page) { + + var pages = this.getLinkedPages(page); + var add = false; + for (var i in pages) { + var p = pages[i]; + if (this.bookmarks.indexOf(p) > -1) { + add = true; + break; + } + } + if (add) { + this.removeBookmark(page); + } else { + this.addBookmark(page); + } + }, + removeBookmark: function(page) { + var pages = this.getLinkedPages(page); + for (var i in pages) { + this.bookmarks = arrayRemove(this.bookmarks, pages[i]); + } + this.updateBookmarks(); + }, + updateBookmarks: function() { + this.saveBookmarks(); + var $this = this; + + this.disableCorners(); + $.each(this.bookmarks, function(k, v) { + $this.setCornersEnabled(v, true); + }); + }, + saveBookmarks: function() { + this.fluidbook.cache.set('bookmarks', this.bookmarks); + }, + getSavedBookmarks: function() { + if (this.fluidbook.cache.isset('bookmarks')) { + return this.fluidbook.cache.get('bookmarks'); + } + return []; + }, + isBookmarked: function(page) { + return this.bookmarks.indexOf(page) > -1; + }, + getBookmarkForPage: function(pageNr, onlyOne, allwaysAtRight) { + if (onlyOne == undefined) { + onlyOne = false; + } + if (allwaysAtRight == undefined) { + allwaysAtRight = false; + } + + var to = pageNr; + if (!onlyOne) { + to++; + } + + var bookmarks = ""; + for (var i = pageNr; i <= to; i++) { + if (i > 0 && i <= this.fluidbook.datas.pages) { + var side; + if (allwaysAtRight) { + side = 'right'; + } else { + side = (i % 2 == 0) ? 'left' : 'right'; + } + + bookmarks += "

' + this.fluidbook.l10n.__('bookmarks') + '

'; + index += '
'; + if (this.fluidbook.datas.friend) { + index += '' + this.fluidbook.l10n.__('send') + ''; + + } + if (this.fluidbook.datas.print || this.fluidbook.datas.pdf) { + index += '' + this.fluidbook.l10n.__('download') + ''; + } + index += '
'; + index += ''; + index += '' + c + ''; + return index; + }, + getIndex: function(all, onlyGroup) { + if (all == undefined) { + all = false; + } + var groups; + + if (all == false) { + groups = this.getBookmarkedGroups(); + } else { + groups = this.getOrderedGroups(); + } + + if (groups.length == 0) { + return false; + } + + var index = '
'; + + if (onlyGroup == undefined) { + for (var g = 0; g < groups.length; g++) { + var group = groups[g]; + var pages = []; + for (var i = 0; i < group.nb; i++) { + pages.push(group.page + i); + } + + index += '
'; + index += '
' + group.name + ''; + if (this.fluidbook.bookmarks.enabled) { + index += this.fluidbook.bookmarks.getBookmarkForPage(group.page, true, true); + } + index += '
'; + index += '
'; + } + } else { + var group = groups[this.getGroupOfPage(onlyGroup)]; + + var pages = []; + for (var i = 0; i < group.nb; i++) { + pages.push(group.page + i); + } + + for (i in pages) { + var p = pages[i]; + index += '
'; + index += '
' + this.fluidbook.physicalToVirtual(p) + ''; + if (this.fluidbook.bookmarks.enabled) { + index += this.fluidbook.bookmarks.getBookmarkForPage(p, true, true); + } + index += '
'; + index += '
'; + } + } + index += '
'; + return index; + } +}; \ No newline at end of file diff --git a/js/libs/fluidbook/fluidbook.cache.js b/js/libs/fluidbook/fluidbook.cache.js new file mode 100644 index 00000000..52c2de15 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.cache.js @@ -0,0 +1,62 @@ +function FluidbookCache(options) { + this._cache = {}; + this.options = options; + this._prefix ='fluidbook.' + this.options.id + '.'; + this._support = false; + this._date = this.options.cacheDate; + this._support=Modernizr.localstorage; + this.init(); + +} + +FluidbookCache.prototype = { + init: function() { + if (this._support) { + this.checkValidity(); + } + }, + clear: function() { + if (this._support) { + localStorage.clear(); + } else { + this._cache = {}; + } + }, + isset: function(key) { + if (this._support) { + var res= localStorage.getItem(this._prefix + key) != null; + return res; + } else { + return this._cache[key] != null; + } + }, + get: function(key) { + var res; + if (this._support) { + res = localStorage.getItem(this._prefix + key); + } else { + res = this._cache[key]; + } + var f = res.substr(0, 1); + if (f == '[' || f == '{') { + res = JSON.parse(res); + } + return res; + }, + set: function(key, value) { + if (typeof value !== "string") { + value = JSON.stringify(value); + } + if (this._support) { + localStorage.setItem(this._prefix + key, value); + } else { + this._cache[key] = value; + } + }, + checkValidity: function() { + if (!this.isset('validity') || this.get('validity') != this._date) { + this.clear(); + this.set('validity', this._date); + } + } +} \ No newline at end of file diff --git a/js/libs/fluidbook/fluidbook.coquillette.js b/js/libs/fluidbook/fluidbook.coquillette.js new file mode 100644 index 00000000..12b19d9c --- /dev/null +++ b/js/libs/fluidbook/fluidbook.coquillette.js @@ -0,0 +1,65 @@ +function FluidbookCoquillette(fluidbook) { + this.fluidbook = fluidbook; + this.size = 60; + this.element = $("#coquillette"); + this.rotation = 0; + this.speed = 1; // 1/2 tours / sec + this.deg360 = Math.PI * 2; + this.init(); + this.raf; + this.start; +} + +FluidbookCoquillette.prototype = { + init: function() { + var $this = this; + this.element.append(''); + var canvas = this.element.find('canvas').get(0); + this.ctx = canvas.getContext('2d'); + }, + show: function() { + this.element.show(); + this.resume(); + }, + hide: function() { + this.element.hide(); + this.pause(); + }, + resume: function() { + var $this = this; + this.rotation = 0; + TweenMax.to(this, 1 / this.speed, {rotation: this.deg360, repeat: -1, ease: Linear.easeNone, onUpdate: $.proxy(this.step, this)}); + }, + step: function() { + var radius = this.size / 2; + + // Clear the whole canvas + this.ctx.clearRect(0, 0, this.size, this.size); + // Set the background + this.ctx.fillStyle = this.fluidbook.datas.coquilletteBack; + this.ctx.beginPath(); + this.ctx.arc(radius, radius, radius, 0, this.deg360, false); + this.ctx.closePath(); + this.ctx.fill(); + // Set stroke style + this.ctx.strokeStyle = this.fluidbook.datas.coquilletteFront; + this.ctx.lineWidth = Math.round(this.size * 0.13); + this.ctx.lineCap = 'round'; + this.ctx.lineJoin = 'mitter'; + this.ctx.beginPath(); + this.ctx.arc(radius, radius, radius * 0.65, this.rotation, this.rotation + Math.PI * 1.4, false); + + // Apply the stroke + this.ctx.stroke(); + }, + pause: function() { + window.cancelAnimationFrame(this.raf); + }, + resize: function(ww, hh) { + this.element.css({ + left: (ww - this.size) / 2, + top: (hh - this.size) / 2 + }) + } +}; + diff --git a/js/libs/fluidbook/fluidbook.desktop.js b/js/libs/fluidbook/fluidbook.desktop.js new file mode 100644 index 00000000..6ba6aaf3 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.desktop.js @@ -0,0 +1,113 @@ +function FluidbookDesktop(fluidbook) { + this.fluidbook = fluidbook; + this.updateDesktopScale(1); + this.origin = ['50%', '50%']; + this.init(); +} + +FluidbookDesktop.prototype = { + init: function() { + var $this = this; + $(document).on('click', '#links', function(e) { + $this.clickZoom(e); + }); + $(document).on('click', '#links .link', function(e) { + e.stopPropagation(); + }) + + $("body").mousewheel(function(e, delta, deltaX, deltaY) { + $this.wheelZoom(deltaY); + }) + + $(document).on('mousemove', 'body', function(e) { + $this.moveZoom(e); + }); + }, + moveZoom: function(e) { + var x = 100 * e.pageX / $(window).width(); + var y = 100 * e.pageY / $(window).height(); + this.origin = [x + '%', y + '%']; + if (this.desktopScale == 1) { + return; + } else { + + $("#fluidbook").transform({ + origin: this.origin + }, { + preserve: true + }) + } + }, + clickZoom: function(e) { + var newScale; + if (this.desktopScale == 1) { + newScale = (this.fluidbook.datas.zoom / 100) / this.fluidbook.resize.bookScale; + } else { + newScale = 1; + } + this.updateDesktopScale(newScale); + return false; + }, + wheelZoom: function(delta) { + if ($("body").hasClass('view')) { + return; + } + this.updateDesktopScale(this.desktopScale + delta / 3, delta > 0); + }, + updateDesktopScale: function(v, zoomIn) { + var $this = this; + if (this.fluidbook.viewMode()) { + v = 1; + } + + var max = (this.fluidbook.datas.zoomw / 100) / this.fluidbook.resize.bookScale; + + v = Math.max(Math.min(v, max), 1); + + if (zoomIn === true) { + if (v < 1.5) { + v = 2; + } + } else if (zoomIn === false) { + if (v < 1.5) { + v = 1; + } + } + + + if (v == this.desktopScale) { + return false; + } + this.desktopScale = v; + + + var animation = { + scale: [this.desktopScale * this.fluidbook.resize.bookScale, this.desktopScale * this.fluidbook.resize.bookScale] + }; + if (this.desktopScale == 1) { + animation.origin = ['50%', '50%']; + } else { + animation.origin = this.origin; + } + + if (this.desktopScale != 1) { + $("header,footer,#interface").addClass('hidden'); + + } else { + $("header,footer,#interface").removeClass('hidden'); + } + $("#fluidbook").addClass('animate').transform(animation); + setTimeout(function() { + $("#fluidbook").removeClass('animate'); + }, 1000); + + if (this.desktopScale > 1) { + $("body").addClass('zoomed'); + } else { + $("body").removeClass('zoomed'); + } + + return true; + } + +}; \ No newline at end of file diff --git a/js/libs/fluidbook/fluidbook.help.js b/js/libs/fluidbook/fluidbook.help.js new file mode 100644 index 00000000..21db77e5 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.help.js @@ -0,0 +1,235 @@ +function FluidbookHelp(fluidbook) { + this.autoTimeout; + this.fluidbook = fluidbook; + this.view = $("#helpView"); + this.initEvents(); + this.interfaceTop; +} + +FluidbookHelp.prototype = { + init: function() { + var $this = this; + var help = ''; + + // Image centrale + var ext = ''; + if (this.fluidbook.support.SVG) { + ext = 'svg'; + } else { + ext = 'png'; + } + + var name = ''; + var width = 100; + var height = 200; + var text; + var zoom = 1; + if (this.fluidbook.support.isMobile) { + width = 400; + height = 200; + zoom = 2; + name = 'fingers'; + text = this.fluidbook.l10n.__("tap twice or spread your fingers to zoom in"); + } else { + name = 'mouse'; + text = this.fluidbook.l10n.__('click once to zoom in, click again to zoom out') + '
' + this.fluidbook.l10n.__('roll the mouse wheel to zoom in/out'); + } + + help += '
'; + help += '

' + text + '

'; + help += '
'; + + + // Icons + help += '
'; + var scale = $("#nav").transform('scaleX'); + $("#nav").transform({ + scale: [1, 1] + }, { + preserve: true + }); + var h = 40 + ($("#nav>a").length - 1) * 25; + $("nav>a").each(function() { + var text = $(this).attr('help'); + if (text == '') { + return; + } + var offset = $(this).position(); + var left = 30 + offset.left; + help += '
' + $this.fluidbook.l10n.__(text) + '
'; + h -= 25; + }); + $("#nav").transform({ + scale: [scale, scale] + }, { + preserve: true + }); + help += '
'; + + // Interface + + var next = this.fluidbook.l10n.__('next double page'); + var previous = this.fluidbook.l10n.__('previous double page'); + if (this.fluidbook.pad.enabled) { + next = this.fluidbook.l10n.__('next chapter'); + previous = this.fluidbook.l10n.__('previous chapter'); + } + + help += '
'; + help += ''; + help += '
' + this.fluidbook.l10n.__('last page') + '
'; + help += ''; + help += '

' + this.fluidbook.l10n.__('frontpage') + '
'; + help += '
'; + + if (this.fluidbook.pad.enabled) { + help += '
' + this.fluidbook.l10n.__('read more') + '
'; + } + + this.view.html(help); + resize(); + }, + initEvents: function() { + var $this = this; + if (!this.fluidbook.support.isMobile) { + $("#help").hover(function() { + $this.show(); + }, function() { + $this.hide(); + }).click(function() { + return false; + }); + } else { + $("#help").click(function() { + $this.toggle(); + return false; + }); + } + }, + show: function(time) { + this.clearTimeout(); + if (time == undefined) { + time = 0; + } + + if (this.view.is(":visible")) { + return false; + } + + if (this.view.html() == '') { + this.init(); + } + + var $this = this; + + this.view.show(); + this.fluidbook.showAllButtons(); + if (this.fluidbook.support.isMobile) { + $(document).one('click touchend', function() { + $this.hide(); + }); + } else { + if (time != 0) { + this.autoTimeout = setTimeout(function() { + $this.hide(); + }, time * 1000); + } + } + return false; + }, + hide: function() { + this.clearTimeout(); + var $this = this; + if (this.view.is(':visible')) { + this.view.hide(); + this.fluidbook.hideUnnecessaryButtons(); + if (this.fluidbook.support.isMobile) { + $("*").unbind('click', function() { + $this.hide(); + }); + } + } + return false; + }, + toggle: function() { + if (this.view.is(':visible')) { + this.hide(); + } else { + this.show(); + } + }, + resize: function(ww, hh, interfaceScale, navScale) { + this.hide(); + var menuHeightScaled = (this.fluidbook.datas.menuHeight) * navScale + this.view.css({ + width: ww, + minHeight: hh - menuHeightScaled, + top: menuHeightScaled + }); + + + this.interfaceTop = (hh - 100 * interfaceScale) / 2 + 30 * interfaceScale; + this.view.find(".interface>div").css({ + top: this.interfaceTop - menuHeightScaled + }); + + $("#helpView #icons").transform({ + scale: [navScale, navScale], + origin: ['0%', '0%'] + }); + + $("#helpView #icons").css({ + fontSize: (16 / navScale) * interfaceScale + }); + + $("#helpView .illustration").transform({ + scale: [interfaceScale, interfaceScale], + origin: ['50%', '50%'] + }); + + $("#helpView .interface").find('.last,.next,.first,.previous').transform({ + scale: [interfaceScale, interfaceScale] + }) + + $("#helpView .interface").find('.last').transform({ + origin: ['100%', '100%'] + }, { + preserve: true + }); + + $("#helpView .interface").find('.first').transform({ + origin: ['0%', '100%'] + }, { + preserve: true + }); + + $("#helpView .interface").find('.next').transform({ + origin: ['100%', '0%'] + }, { + preserve: true + }); + + + $("#helpView .interface").find('.previous').transform({ + origin: ['0%', '0%'] + }, { + preserve: true + }); + + this.view.find('.illustration').css('margin-top', (this.view.height() - 400 * interfaceScale) / 2); + }, + clearTimeout: function() { + clearTimeout(this.autoTimeout); + }, + displayAtStartup: function() { + var $this = this; + if (this.fluidbook.datas.helpStartup) { + + $this.show(parseInt($this.fluidbook.datas.helpStartupTime)); + if ($this.fluidbook.pad.enabled) { + $this.fluidbook.pad.displayInterface(); + } + } + } +}; + diff --git a/js/libs/fluidbook/fluidbook.js b/js/libs/fluidbook/fluidbook.js new file mode 100644 index 00000000..44337859 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.js @@ -0,0 +1,1305 @@ +function Fluidbook(datas) { + this.init(datas); +} + +// Constantes +// Background dispoition +Fluidbook.NONE = 3; +Fluidbook.STRETCH = 0; +Fluidbook.RATIO = 2; +Fluidbook.REPEAT = 1; +// Horizontal alignments +Fluidbook.CENTER = 4; +Fluidbook.LEFT = 5; +Fluidbook.RIGHT = 6; +// Vertical alignments +Fluidbook.MIDDLE = 7; +Fluidbook.TOP = 8; +Fluidbook.BOTTOM = 9; + +Fluidbook.prototype = { + init: function(datas) { + this.datas = datas; + this.junk = datas.cacheDate; + this.cache = new FluidbookCache(datas); + this.service = new FluidbookService(this, datas.id); + this.support = new FluidbookSupport(this); + this.loader = new FluidbookLoader(this); + this.search = new FluidbookSearch(this); + this.pad = new FluidbookPad(this); + if (Modernizr.ftouch && this.support.transitions2d && this.datas.mobileTransitions != 'none') { + this.touch = new FluidbookTouch(this); + } + this.background = new FluidbookBackground(this); + this.viewport = new FluidbookViewport(this.support) + this.l10n = new FluidbookL10N(this, $_GET['lang']); + this.nav = new FluidbookNav(this); + this.video = new FluidbookVideo(this); + this.bookmarks = new FluidbookBookmarks(this); + this.index = new FluidbookIndex(this); + this.refw = 0; + this.refh = 0; + this.zoom = 1; + this.searchHintXHR = null; + this.searchString = ''; + this.termsToHighlight = ''; + this.imagesVersion = (this.datas.mobileVersion == 'html5-images' || !this.support.SVG); + this.vectorTexts = !this.imagesVersion; + this.displayOnePage = false; + this.indexHTML = ''; + this.transitionning = false; + + this.transitionAxis = 'x'; + + if (this.support.isMobile) { + $("body").addClass('mobile'); + } + else { + $("body").addClass('desktop'); + } + + if (this.pad.enabled) { + $("body").addClass('pad'); + } + $('html').addClass(this.datas.mobileLVersion); + + this.currentPage = -1; + + this.resize = new FluidbookResize(this); + this.help = new FluidbookHelp(this); + this.coquillette = new FluidbookCoquillette(this); + + + this.stats = new FluidbookStats(this); + this.stats.track(10); + if (!this.support.isMobile) { + this.desktop = new FluidbookDesktop(this); + } + + this.initLoading(); + + }, + initLoading: function() { + this.displayLoader(); + + }, + hideSplash: function() { + if ($("#splash").length == 0) { + return; + } + var $this = this; + setTimeout(function() { + $this._hideSplash(); + }, 3000); + }, + _hideSplash: function() { + this.ready(); + $("#main").css('visibility', 'visible'); + this.hideLoader(0, true); + $("#splash").css('opacity', 0).one(this.support.transitionendevents, function() { + $(this).remove(); + }); + }, + ready: function() { + this.help.displayAtStartup(); + }, + loadPlugins: function() { + $.each(this.datas.plugins, function(k, plugin) { + try { + var functionName = plugin.replace(/\./g, '_'); + eval(functionName + '();'); + } catch (err) { + } + }); + $.each(this.datas.htmlmultimedia, function(k, code) { + try { + eval(code); + } catch (err) { + } + }); + }, + resetZoom: function() { + var $this = this; + if (this.support.iOS) { + } else if (!this.support.isMobile) { + this.desktop.updateDesktopScale(1); + } + + }, + setZoom: function(zoom) { + if (zoom) { + $("#pages").addClass('zoom'); + } else { + $("#pages").removeClass('zoom'); + } + }, + initPage: function(pageNr, doublePage, position) { + if ($("#page_" + pageNr).length > 0) { + return; + } + $(doublePage).find('.' + position).remove(); + + var page = '
'; + $(doublePage).append(page); + }, + hidePage: function(position) { + $("#pages ." + position).hide(); + }, + initLinks: function(pageNr) { + if (pageNr == undefined) { + pageNr = this.currentPage; + } + + var lClass = 'left'; + if (this.displayOnePage && pageNr % 2 == 1) { + lClass = 'right'; + } + + if (pageNr % 2 == 1) { + pageNr--; + } + + $("#links").removeClass('left').removeClass('right').addClass(lClass).html(this.datas.links[pageNr]).show(); + if (this.datas.bookmark) { + + $("#links").append(this.bookmarks.getBookmarkForPage(pageNr)); + } + $("#links").prepend(''); + + var $this = this; + if (this.datas.linkBlinkTime > 0) { + //this.animateLinks(); + } + setTimeout(function() { + $this.initVideos(); + }, 1000); + }, + animateLinks: function() { + var links = $(".link a.displayArea"); + var bookmarks = $("#links .bookmark:not([data-enabled])"); + if (Modernizr.csstransitions) { + $(links).addClass('animating'); + $(bookmarks).css('opacity', 1).addClass('animating'); + setTimeout(function() { + $(links).css('opacity', 0); + $(bookmarks).css('opacity', 0); + setTimeout(function() { + $(links).removeClass('animating').css('opacity', 1); + $(bookmarks).removeClass('animating').css('opacity', ""); + }, 1100); + }, 50); + } else { + $(links).addClass('animating').fadeOut(1000, function() { + $(links).removeClass('animating').show(); + }).mouseover(function() { + $(links).stop().removeClass('animating').css('opacity', 1).show(); + return true; + }); + } + }, + initVideos: function() { + var $this = this; + $(".videoContainer").each(function() { + $this.video.initVideo(this); + }); + }, + getNextOffset: function() { + var offset = 2; + if (this.displayOnePage) { + offset = 1; + } + this.transitionAxis = 'x'; + return offset; + }, + goNextPage: function() { + if (this.transitionning) { + return; + } + this.transitionAxis = 'x'; + this.setCurrentPage(this.normalizePage(this.currentPage) + this.getNextOffset()); + }, + goFirstPage: function() { + if (this.transitionning) { + return; + } + this.transitionAxis = 'x'; + this.setCurrentPage(1); + }, + goPreviousPage: function() { + if (this.transitionning) { + return; + } + this.transitionAxis = 'x'; + this.setCurrentPage(this.normalizePage(this.currentPage) - this.getNextOffset()); + }, + goLastPage: function() { + if (this.transitionning) { + return; + } + this.transitionAxis = 'x'; + this.setCurrentPage(this.datas.pages); + }, + goNextChapter: function() { + if (this.transitionning) { + return; + } + var next = this.bookmarks.getNextGroupCover(this.currentPage); + if (next === false) { + return; + } + this.transitionAxis = 'x'; + this.setCurrentPage(this.normalizePage(next)); + + }, + goPreviousChapter: function() { + if (this.transitionning) { + return; + } + var prev = this.bookmarks.getPreviousGroupCover(this.currentPage); + if (prev === false) { + return; + } + this.transitionAxis = 'x'; + this.setCurrentPage(this.normalizePage(prev)); + }, + goNextChapterPage: function() { + if (this.transitionning) { + return; + } + + var next = this.bookmarks.getNextPageInGroupOfPage(this.currentPage); + if (next === false) { + return; + } + this.transitionAxis = 'y'; + this.setCurrentPage(this.normalizePage(next)); + }, + goPreviousChapterPage: function() { + if (this.transitionning) { + return; + } + + var prev = this.bookmarks.getPreviousPageInGroupOfPage(this.currentPage); + if (prev === false) { + return; + } + this.transitionAxis = 'y'; + this.setCurrentPage(this.normalizePage(prev)); + }, + normalizePage: function(page) { + page = Math.max(1, Math.min(page, this.datas.pages)); + if (!this.displayOnePage && page % 2 == 1) { + page--; + } + return page; + }, + setCurrentPage: function(page) { + window.location.hash = "#/page/" + this.normalizePage(page); + }, + changeAddress: function() { + var $this = this; + var page; + var args = window.location.hash.split('/'); + if (args.length <= 1 || args[1] == '' || args[1] == undefined) { + return this.setCurrentPage('1'); + } else if (args[1] == 'page') { + page = parseInt(args[2]); + if (isNaN(page) || page == undefined) { + return this.setCurrentPage('1'); + } + if (this.pad.enabled) { + this.transitionAxis = this.pad.getTransitionAxis(this.currentPage, page); + } else { + this.transitionAxis = 'x'; + } + + $($this).trigger('changePage', [page]); + + this.closeView(function() { + $this.pageTransition(page); + $this.resetZoom(); + $this.stats.track(0, page); + $this.hideSplash(); + }, true); + } + else { + this.openView(args[1], args[2], args[3], function() { + $this.hideSplash(); + }); + this.resetZoom(); + } + + return; + }, + pageTransition: function(pageNr) { + if (pageNr == undefined) { + pageNr = this.currentPage; + if (pageNr == -1) { + pageNr = 1; + } + } + pageNr = this.normalizePage(pageNr); + if (pageNr == this.normalizePage(this.currentPage) || this.currentPage == -1) { + // No page change, just reload + this.pageTransition1D(pageNr); + return; + } + if (!this.displayOnePage && this.datas.mobileTransitions == 'flip') { + if (this.support.transitions3d) { + this.pageTransition3D(pageNr); + } else if (this.support.transitions2d) { + this.pageTransition2D(pageNr); + } else { + this.pageTransition1D(pageNr); + } + } else if ((this.displayOnePage && this.datas.mobileTransitions == 'flip')) { + if (this.support.transitions2d) { + this.pageTransition2DPortrait(pageNr); + } else { + this.pageTransition1D(pageNr); + } + } else if (this.datas.mobileTransitions == 'slide') { + if (this.support.transitions2d) { + this.pageTransition2D(pageNr); + } else { + this.pageTransition1D(pageNr); + } + + + } + else { + this.pageTransition1D(pageNr); + } + }, + pageTransition3D: function(pageNr) { + + var $this = this; + if ($("#pages").hasClass('_3dtransition')) { + return; + } + this.transitionning = true; + var nextFromClass; + var $this = this; + if (pageNr > this.currentPage) { + nextFromClass = 'next'; + } else { + nextFromClass = 'prev'; + } + + $("#pages").prepend('
'); + var doublePage = $("#nextDoublePage"); + var currentDoublePage = $("#currentDoublePage"); + + var currentLeft = this.currentPage - this.currentPage % 2; + var currentRight = currentLeft + 1; + + var dir = 1; + if (pageNr < this.currentPage) { + dir = -1; + } + + + var preload = [pageNr, pageNr + 1]; + + this.displayLoader(); + + this.loader.preloadPagesBeforeTransition(preload, function() { + var pages; + $("#pages").addClass('_3dtransition'); + // Set contents of flat part + if (dir == 1) { + pages = [currentLeft, pageNr + 1]; + } else { + pages = [pageNr, currentRight]; + } + $this.loader.setContentsInDoublePage(currentDoublePage, pages, true, function() { + // Set the contents of fliping part + if (dir == 1) { + pages = [pageNr, currentRight]; + } else { + pages = [currentLeft, pageNr + 1]; + } + + $this.loader.setContentsInDoublePage(doublePage, pages, true, function() { + $this.beforeTransition(pageNr); + // Do the transition + + $(doublePage).addClass(nextFromClass + 'end').one($this.support.transitionendevents, function() { + if ($("#nextDoublePage").length == 0) { + $("#pages").removeClass('_3dtransition'); + this.transitionning = false; + return; + } + $(this).off($this.support.transitionendevents); + // Set the flat contents with the new page + $this.loader.setContentsInDoublePage(doublePage, [pageNr, pageNr + 1], false, function() { + $(doublePage).removeClass('_3d').removeClass(nextFromClass + 'start').removeClass(nextFromClass + 'end'); + // Remove former part + $("#currentDoublePage").remove(); + $(doublePage).attr('id', 'currentDoublePage'); + + $("#pages").removeClass('_3dtransition'); + $this.afterTransition(pageNr); + + }); + + }); + }); + }); + }); + }, + reloadCurrentPage: function() { + this.pageTransition(this.currentPage); + }, + readingPage: function(side) { + if (!this.displayOnePage) { + var page = this.currentPage; + var change = false; + if (side == 'left' && page % 2 == 1) { + page--; + change = true; + } else if (side == 'right' && page % 2 == 0) { + page++; + change = true; + } + if (change) { + window.location.hash = "/page/" + page; + } + } + }, + hideUnnecessaryButtons: function(page) { + var speed = 500; + if (page == undefined) { + page = this.currentPage; + speed = 0; + } + + $("#previous,#next").removeClass('help'); + if (Modernizr.csstransitions) { + if (page <= 1) { + $("#previous").addClass('hidden'); + } else { + $("#previous").removeClass('hidden'); + } + + if (page >= this.datas.pages) { + $("#next").addClass('hidden'); + } else { + $("#next").removeClass('hidden'); + } + + } else { + $("#previous,#next").removeClass('hidden'); + + if (page <= 1) { + $("#previous:visible").fadeOut(speed); + } else { + $("#previous:hidden").fadeIn(speed); + } + + if (page >= this.datas.pages) { + $("#next:visible").fadeOut(speed); + } else { + $("#next:hidden").fadeIn(speed); + } + } + + if (page <= 1) { + $("#shadow").removeClass('double'); + $("#shadow").removeClass('left'); + $("#shadow").addClass('right'); + $("#shadow").addClass('single'); + } else if (page >= this.datas.pages) { + $("#shadow").removeClass('double'); + $("#shadow").removeClass('right'); + $("#shadow").addClass('left'); + $("#shadow").addClass('single'); + } + else { + $("#shadow").removeClass('single'); + $("#shadow").addClass('double'); + } + + }, + showAllButtons: function() { + $("#next,#previous").addClass('help').show(); + }, + pageTransition2D: function(pageNr) { + this.transitionning = true; + var currentFromClass, currentToClass; + var $this = this; + if (pageNr > this.currentPage) { + currentToClass = 'prev'; + nextFromClass = 'next'; + } + else { + currentToClass = 'next'; + nextFromClass = 'prev'; + } + + + $("#pages").append('
'); + var doublePage = $("#nextDoublePage"); + this.displayLoader(); + this.loader.preloadPagesBeforeTransition([pageNr, pageNr + 1], function() { + $this.loader.setContentsInDoublePage(doublePage, [pageNr, pageNr + 1], true, function() { + $this.beforeTransition(pageNr); + $("#currentDoublePage").addClass('_2d').addClass('axis_' + $this.transitionAxis).addClass(currentToClass); + $(doublePage).removeClass(nextFromClass).one($this.support.transitionendevents, function(event) { + $("#currentDoublePage").remove(); + $("#nextDoublePage").attr('id', 'currentDoublePage'); + $this.afterTransition(pageNr); + $(this).off($this.support.transitionendevents); + }); + }); + }); + }, + pageTransition2DPortrait: function(pageNr) { + this.transitionning = true; + var currentFromClass, currentToClass; + var $this = this; + if (pageNr > this.currentPage) { + currentToClass = 'prev'; + nextFromClass = 'next'; + } + else { + currentToClass = 'next'; + nextFromClass = 'prev'; + } + + + $("#pages").append('
'); + var doublePage = $("#nextDoublePage"); + + if (this.displayOnePage) { + this.hidePage('right'); + } + + this.displayLoader(); + this.loader.preloadPagesBeforeTransition([pageNr, pageNr + 1], function() { + $this.loader.setContentsInDoublePage(doublePage, [pageNr, pageNr + 1], true, function() { + $this.beforeTransition(pageNr); + $("#currentDoublePage").addClass('axis_' + $this.transitionAxis).addClass('_2d').addClass(currentToClass); + $(doublePage).removeClass(nextFromClass).one($this.support.transitionendevents, function() { + $("#currentDoublePage").remove(); + $("#nextDoublePage").attr('id', 'currentDoublePage'); + $this.afterTransition(pageNr); + $(this).off($this.support.transitionendevents); + }); + }); + }); + }, + pageTransition1D: function(pageNr) { + var page = pageNr; + var doublePage = $("#currentDoublePage"); + var $this = this; + + if (this.displayOnePage) { + this.hidePage('right'); + } + this.beforeTransition(pageNr); + this.loader.setContentsInDoublePage(doublePage, [page, page + 1], true, function() { + $this.afterTransition(page); + }); + + }, + beforeTransition: function(page) { + $(".axis_y").removeClass('axis_y'); + $(".axis_x").removeClass('axis_x'); + $("#links").hide(); + this.hideLoader(); + this.hideUnnecessaryButtons(page); + }, + afterTransition: function(page) { + if (this.transitionning === false) { + //return; + } + var $this = this; + this.currentPage = page; + + this.setPageNumbers(); + setTimeout(function() { + $this.loader.preloadAround(page); + }, 1000); + this.initLinks(); + this.hideLoader(); + + // Clean messy stuffs + $("#pages").removeClass('_3dtransition'); + if ($("#nextDoublePage").length > 0) { + $("#currentDoublePage").remove(); + $("#nextDoublePage").attr('id', 'currentDoublePage'); + } + if ($("#currentDoublePage").length > 1) { + $("#currentDoublePage:gt(0)").remove(); + } + this.transitionning = false; + + if (this.pad.enabled) { + if (this.currentPage == this.datas.pages) { + $("#down").css('opacity', 0); + } else { + $("#down").css('opacity', 1); + if (!this.bookmarks.hasNextPageInGroup(this.currentPage)) { + $("#down").addClass('right'); + } else { + $("#down").removeClass('right'); + } + } + } else { + $("#down").css('opacity', 0); + } + + }, + setPageNumbers: function() { + var page = this.currentPage; + if (page > 0) { + $("#pagesnumbers .left").html(this.physicalToVirtual(page)); + } else { + $("#pagesnumbers .left").html(''); + } + + if (!this.displayOnePage) { + page++; + if (page <= this.datas.pages) { + $("#pagesnumbers .right").html(this.physicalToVirtual(page)); + $("#pagesnumbers .right").show(); + } else { + $("#pagesnumbers .right").html(''); + $("#pagesnumbers .right").hide(); + } + } + }, + clickLogo: function() { + if (this.datas.url_link == '' || this.datas.url_link == 'http://') { + return; + } + this.wopen(this.datas.url_link, '_blank'); + }, + viewMode: function() { + return $("#view .mview").length > 0; + }, + openView: function(view, param1, param2, callback) { + var $this = this; + + this.displayLoader(); + + setTimeout(function() { + $this._openView(view, param1, param2, callback); + }, 20); + }, + _openView: function(view, param1, param2, callback) { + var $this = this; + var camelView = view.charAt(0).toUpperCase() + view.substr(1); + + /*if ($('.mview:visible').length > 0) { + this.closeView(function() { + $this._openView(view, param1, param2, callback); + }); + return; + }*/ + var cb = function() { + $this.openingView(callback); + }; + + if (view == 'index') { + this.openIndex(this.l10n.__('overview'), undefined, true, cb); + } else if (view == 'search') { + this.searchString = param1; + var group = param2; + $("#q").val(param1); + this.displayResults(this.search.find(param1), group, cb); + if (group == undefined) { + this.stats.track(1, 0, param1); + } + } else if (view == 'video') { + this.openVideo(param1, cb); + } else if (view == 'webvideo') { + this.openWebVideo(param1, param2, cb); + } else if (view == 'chapters') { + this.openChapters(cb); + } else if (view == 'archives') { + this.openArchives(this.l10n.__($("#nav #archives").attr('help')), cb); + } else { + this['open' + camelView](param1, param2, cb); + } + }, + openingView: function(callback) { + var $this = this; + this.resize.resizeView(); + + var mview = $('#view .mview:last'); + + if (this.support.transitions2d) { + var vertFrom = { + translateY: $(window).height() + 'px' + }; + var vertTo = { + translateY: '0px' + }; + var horiFrom = { + translateX: $(window).width() + 'px' + }; + var horiTo = { + translateX: '0px' + }; + var from = vertFrom; + var to = vertTo; + if ($(mview).hasClass('hori')) { + from = horiFrom; + to = horiTo; + } + + $(mview).show().removeClass('animate').transform(from); + + setTimeout(function() { + $(mview).one($this.support.transitionendevents, function() { + $("#main").hide(); + $('body').addClass('view'); + $(mview).removeClass('animate'); + callback(); + $this.hideLoader(); + resize(); + }).addClass('animate').transform(to); + }, 50); + + } else { + $("#main").hide(); + $('body').addClass('view'); + $(mview).show(); + callback(); + this.hideLoader(); + resize(); + } + }, + displayResults: function(data, group, callback) { + var $this = this; + var results = data.results; + var hideNoResults = !this.datas.searchShowNoResultsPages; + if (data.total <= 0) { + alert(this.l10n.__('no result found')); + window.location = "#/page/" + this.currentPage; + return; + } + + this.openIndex(this.l10n.__('search results for') + ' « ' + this.searchString + " »", group, false, function() { + var hits = []; + for (var i = 0; i <= $this.datas.pages; i++) { + hits[i] = 0; + } + + $.each(results, function(k, v) { + hits[k] += v; + }); + + var e = encodeURIComponent($this.searchString); + + $(".doubleThumb").each(function() { + var pages = $(this).data('pages').toString().split(','); + var hitsp = 0; + var pagesWithHits = 0; + for (var i in pages) { + var n = parseInt(pages[i]); + if (hits[n] > 0) { + hitsp += hits[n]; + pagesWithHits++; + } + } + + if ($(this).find('.hits').length > 0) { + return; + } + + if (hitsp == 0) { + if (hideNoResults) { + $(this).remove(); + return; + } + $(this).append('
'); + $(this).append('
' + $this.l10n.__('no result found') + '
'); + } else { + $(this).append('
' + hitsp + ' ' + $this.l10n.__('hit(s)') + '
'); + if (pagesWithHits <= 1) { + $(this).find('a').attr('href', '#/page/' + $(this).attr('page')); + } else { + $(this).find('a').attr('href', '#/search/' + e + '/' + $(this).attr('page')); + } + } + }); + + $this.termsToHighlight = data.terms; + + if (callback != undefined) { + callback(); + } + }); + }, + openVideo: function(video, callback) { + var a = $('a[href="#/video/' + video + '"]'); + var markup = decodeURIComponent($(a).attr('data-video')); + + var view = ''; + view += '
'; + view += markup; + view += '
'; + + $("#view").append('
' + view + '
'); + + this.stats.track(11); + + this.initVideos(); + var $this = this; + var times = [250, 500, 750, 1000, 1250]; + $.each(times, function(k, v) { + setTimeout(function() { + $this.resize.resizePopupVideos(); + }, v); + }); + if (callback != undefined) { + callback(); + } + }, + openWebVideo: function(service, video, callback) { + + var view = ''; + view += '
'; + if (service == 'youtube') { + view += ''; + } else if (service == 'dailymotion') { + view += '' + } + view += '
'; + $("#view").append('
' + view + '
'); + + $("#view .mview:last iframe").each(function() { + $(this).attr('height', ($(this).width() * 9) / 16); + }); + this.stats.track(11); + if (callback != undefined) { + callback(); + } + }, + openLocales: function(p1, p2, callback) { + var view = ''; + view += '
'; + view += '
    '; + var $this = this; + $.each(this.l10n.multilang, function(k, v) { + var url = v.url; + if (url.substr(0, 3) == '../' && !$this.datas.standalone) { + url = '../' + url; + } + view += '
  • ' + v.name + '' + v.name + '
  • '; + }); + view += '
'; + view += '
'; + + $("#view").append('
' + view + '
'); + if (callback != undefined) { + callback(); + } + }, + openShare: function(p1, p2, callback) { + var view = '
' + this.l10n.__('back') + '

' + this.l10n.__('share') + '

'; + view += '
'; + view += '
    '; + var $this = this; + if (this.datas.friend) { + view += '
  • '; + } + if (this.datas.facebook) { + view += '
  • '; + } + if (this.datas.twitter) { + view += '
  • '; + } + if (this.datas.googleplus) { + view += '
  • '; + } + if (this.datas.linkedin) { + view += '
  • '; + } + if (this.datas.viadeo) { + view += '
  • '; + } + view += '
'; + view += '
'; + + $("#view").append('
' + view + '
'); + if (callback != undefined) { + callback(); + } + }, + openBookmark: function(p1, p2, callback) { + var view = this.bookmarks.getView(); + if (view !== false) { + $("#view").append('
' + view + '
'); + if (callback != undefined) { + callback(); + } + } else { + window.alert(this.l10n.__("you don't have any bookmarks")); + window.history.back(); + this.hideLoader(); + } + }, + openChapters: function(callback) { + if (this.chapters == undefined) { + this.chapters = new FluidbookChapters(this, this.datas.chapters); + } + + var view = '
' + this.l10n.__('back') + '

' + this.l10n.__('chapters') + '

'; + view += '
'; + view += this.chapters.getView(); + view += '
'; + + $("#view").append('
' + view + '
'); + if (callback != undefined) { + callback(); + } + }, + openIndex: function(title, group, closeAll, callback) { + var c = !closeAll ? ' one' : ''; + var index = ''; + index += this.index.getView(group); + $("#view").append('
' + index + '
'); + + this.bookmarks.updateBookmarks(); + if (callback != undefined) { + callback(); + } + }, + openArchives: function(title, callback) { + var archives = ''; + archives += '
'; + $("#view").append('
' + archives + '
'); + if (callback != undefined) { + callback(); + } + }, + physicalToVirtual: function(page) { + return this.datas.numerotation[page - 1]; + }, + virtualToPhysical: function(page) { + return this.datas.numerotation.indexOf(page) + 1; + }, + closeView: function(callback, all, animate) { + var $this = this; + if (all == undefined) { + all = false; + } + if (animate == undefined) { + animate = true; + } + if ($('.mview').scrollTop() > 0) { + $('.mview').scrollTo(0, 500, function() { + $this.closeView(callback, all, animate); + }); + return; + } + + all = all || ($("#view .mview").length <= 1); + if (!this.viewMode()) { + callback(); + return; + } + + var mview = $("#view .mview:last"); + if (all) { + $("#view .mview:not(:last)").remove(); + } + + var to = { + translateY: $(window).height() + 'px' + }; + + if ($(mview).hasClass('hori')) { + to = {translateX: $(window).width() + 'px'} + } + + if (animate && this.support.transitions2d) { + setTimeout(function() { + $(mview).one($this.support.transitionendevents, function() { + $(this).remove(); + callback(); + }).addClass('animate').transform(to); + }, 50); + + } else { + $(mview).remove() + callback(); + } + if (all) { + $("#main").show(); + $('body').removeClass('view'); + } + resize(); + }, + getSearchHints: function(q) { + this.killLastSearchHint(); + this.displaySearchHints(this.search.getHints(q)); + }, + displaySearchHints: function(hints) { + + this.hideSearchHints(); + if (hints.length == 0) { + return; + } + $.each(hints, function(k, v) { + $("#searchHints").append('' + v[0] + ' (' + v[1] + ')'); + }); + $("#searchHints").show(); + }, + killLastSearchHint: function() { + this.search.kill(); + }, + hideSearchHints: function() { + this.killLastSearchHint(); + $("#searchHints").html(''); + $("#searchHints").hide(); + }, + getLocationToShare: function() { + if (this.datas.phonegap) { + return this.datas.offlineLink; + } else { + var l = window.location.toString(); + var e = l.split("#"); + return e[0]; + } + }, + sendEmail: function() { + window.location = 'mailto:?subject=' + this.datas.title + '&body=' + this.datas.title + ' : ' + this.getLocationToShare(); + this.stats.track(5); + }, + sendTwitter: function() { + this.service.open('twitterShare', { + url: this.getLocationToShare(), + post: this.datas.twitter_description.replace('%title%', this.datas.title) + }); + this.stats.track(13); + }, + sendFacebook: function() { + this.service.open('facebookShare', { + url: this.getLocationToShare() + }); + this.stats.track(12); + }, + sendGoogleplus: function() { + this.service.open('googleplusShare', { + url: this.getLocationToShare() + }); + this.stats.track(12); + }, + sendLinkedin: function() { + this.service.open('linkedinShare', { + url: this.getLocationToShare() + }); + this.stats.track(12); + }, + sendViadeo: function() { + this.service.open('viadeoShare', { + url: this.getLocationToShare() + }); + this.stats.track(12); + }, + print: function() { + var pdf = getBaseURL() + '/data/' + this.datas.pdfName; + this._openFile(pdf, $("#print"), 'pdf', this.datas.pdfName); + }, + _openFile: function(url, e, type, localname) { + var $this = this; + + if (this.datas.phonegap != false) { + if (type == undefined) { + var e = url.split('.'); + type = e.pop(); + } + + if (url.indexOf('http') == 0) { + return this._downloadFilePhonegap(url, localname, LocalFileSystem.TEMPORARY, this._openFilePhonegap, [url, e, type]); + } else { + if (this._openFilePhonegap(url, e, type)) { + return; + } + } + + } + this.wopen(url); + }, + _downloadFilePhonegap: function(url, localname, fs, callback, callbackArgs) { + var $this = this; + if (fs == undefined) { + fs = LocalFileSystem.PERSISTENT; + } + + window.requestFileSystem(fs, 0, function(fileSystem) { + fileSystem.root.getFile("dummy.html", {create: true, exclusive: false}, function(fileEntry) { + var filePath = fileEntry.fullPath.replace("dummy.html", "") + localname; + var fileTransfer = new FileTransfer(); + var uri = encodeURI(url); + fileTransfer.download( + uri, + filePath, + function(entry) { + console.log("download complete: " + entry.fullPath); + if (callback != undefined) { + if (callbackArgs == undefined) { + callbackArgs = []; + } + callbackArgs[0] = entry.toURL(); + callback.apply($this, callbackArgs); + } + }, + function(error) { + console.log("download error source " + error.source); + console.log("download error target " + error.target); + console.log("upload error code" + error.code); + } + ); + }); + }, function() { + + }); + }, + _openFilePhonegap: function(url, e, type) { + var $this = this; + var types_ios = {pdf: 'com.adobe.pdf'}; + var types_android = {pdf: 'application/pdf'}; + if (this.datas.phonegap == 'ios') { + this.displayLoader(); + if (types_ios[type] != undefined) { + var offset = $(e).offset(); + offset.left += ($(e).width() / 2); + offset.top += ($(e).height()); + ExternalFileUtil.openWith(url, types_ios[type], function() { + $this.hideLoader(); + }, function() { + $this.wopen(url, "_blank", 'location=no'); + $this.hideLoader(); + }, offset); + return true; + } + } + if (this.datas.phonegap == 'android') { + if (types_android[type] != undefined) { + this.displayLoader(); + setTimeout(function() { + window.webintent.startActivity({ + action: WebIntent.ACTION_VIEW, + type: types_android[type], + url: url + }, function(args) { + $this.hideLoader(5); + }, function(args) { + $this.hideLoader(5); + }); + }, 100); + + } + return true; + + } + return false; + }, + highlightSearchTerms: function(pageNr) { + return; + }, + touchOffset: function(offset) { + offset *= $("#currentDoublePage").width(); + $("#currentDoublePage").addClass('sliding'); + $("#currentDoublePage").css({ + translateX: offset + }); + }, + displayLoader: function() { + if (this.support.isMobile) { + this.coquillette.show(); + } else { + this.coquillette.show(); + $('body').addClass('loading'); + } + }, + hideLoader: function(delay, force) { + if (force == undefined) { + force = false; + } + if (delay == undefined) { + delay = 0; + } + var $this = this; + if (delay == 0) { + return this._hideLoader(force); + } + setTimeout(function() { + $this._hideLoader(force); + }, delay * 1000); + }, + _hideLoader: function(force) { + if (force == undefined) { + force = false; + } + if (!force && $('#splash').css('visibility') == 'visible') { + return; + } + if (this.support.isMobile) { + this.coquillette.hide(); + } else { + this.coquillette.hide(); + $('body').removeClass('loading'); + } + }, + pollZoom: function() { + var z = this.support.getZoomLevel(); + //console.log(z); + $('html').attr('data-zoom', z); + if (z <= 1) { + $("html").removeClass('pan'); + } else { + $("html").addClass('pan'); + } + }, + intentShare: function(subject, body) { + if (subject == undefined) { + subject = this.datas.title; + } + if (body == undefined) { + body = this.datas.title + ' : ' + this.getLocationToShare(); + } + + if (this.datas.phonegap == 'android') { + var extras = {}; + extras[WebIntent.EXTRA_SUBJECT] = subject; + extras[WebIntent.EXTRA_TEXT] = body; + window.webintent.startActivity({ + action: WebIntent.ACTION_SEND, + type: 'text/plain', + extras: extras + }, function(args) { + }, function(args) { + }); + } else { + window.location = 'mailto:?subject=' + subject + '&body=' + body; + } + this.stats.track(5); + }, + wopen: function(url, target, options) { + if (target == undefined) { + target = '_self'; + } + if (options == undefined) { + options = ''; + } + + var locationdefault = 'yes'; + if (this.datas.phonegap) { + locationdefault = 'no'; + } + + if (options == '') { + options = 'location=' + locationdefault; + } else if (options.indexOf('location=') == -1) { + options += ',location=' + locationdefault; + } + window.open(url, target, options); + } +} diff --git a/js/libs/fluidbook/fluidbook.l10n.js b/js/libs/fluidbook/fluidbook.l10n.js new file mode 100644 index 00000000..09da0a8f --- /dev/null +++ b/js/libs/fluidbook/fluidbook.l10n.js @@ -0,0 +1,65 @@ +function FluidbookL10N(fluidbook, lang) { + this.translations = {}; + this.multilang = {}; + this.multilangEnabled = false; + this.fluidbook = fluidbook; + + this.load(lang); + this.initMultilang(); +} + +FluidbookL10N.prototype = { + load: function(lang) { + if (lang == undefined || lang == null || lang == '') { + lang = 'default'; + } + this.lang = lang; + + this.translations = this.fluidbook.datas.l10n[lang]; + this.updateTranslations(); + }, + getActiveLang: function() { + if (this.lang != 'default') { + return this.lang; + } + return this.fluidbook.datas.defaultLang; + }, + initMultilang: function() { + if (this.fluidbook.datas.multilang == '') { + return; + } + this.multilangEnabled = true; + var $this = this; + var ml = this.fluidbook.datas.multilang.replace(/\r/g, "\n").replace(/\n+/g, "\n"); + + var e = ml.split("\n"); + $.each(e, function(k, v) { + var l = v.split(','); + var o = {lang: l[0], flag: l[1], url: l[2], name: l[3]}; + $this.multilang[l[0]] = o; + }); + }, + updateTranslations: function() { + var $this = this; + $("#q").attr('placeholder', this.__('search')); + $("i.l10n").each(function() { + var t = $this.fluidbook.l10n.__($(this).attr('str')); + $(this).replaceWith(t); + }); + }, + __: function(str, markupIfNonAvailable) { + if (str.substr(0, 1) == '!') { + return str.substr(1); + } + + + if (this.translations[str] == undefined || this.translations[str] == null || this.translations[str] == '') { + if (markupIfNonAvailable == undefined || markupIfNonAvailable) { + return '~ ' + str + ' ~'; + } else { + return str; + } + } + return this.translations[str]; + } +}; \ No newline at end of file diff --git a/js/libs/fluidbook/fluidbook.loader.js b/js/libs/fluidbook/fluidbook.loader.js new file mode 100644 index 00000000..3859afb5 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.loader.js @@ -0,0 +1,247 @@ +function FluidbookLoader(fluidbook) { + this.fluidbook = fluidbook; + this.texts = []; + this.backgrounds = []; + this.links = []; + this.toPreload = []; + this.numPreload = 6; + if (this.fluidbook.imagesVersion) { + this.numPreload += 6; + } +} + +FluidbookLoader.prototype = { + preloadPagesBeforeTransition: function(pages, callback) { + var $this = this; + if (pages.length == 0) { + callback(); + return; + } + var $pages = pages; + var $callback = callback; + var $page = pages.shift(); + if ($page > this.fluidbook.datas.pages || $page < 1) { + $this.preloadPagesBeforeTransition($pages, $callback); + return; + } + this._loadBackground($page, function() { + if ($this.fluidbook.vectorsVersion) { + $this._loadTexts($page, function() { + $this.preloadPagesBeforeTransition($pages, $callback); + }); + } else { + $this.preloadPagesBeforeTransition($pages, $callback); + } + }) + }, + preloadPages: function() { + if (this.toPreload.length == 0) { + return; + } + + var $this = this; + var preloadingPage = this.toPreload.shift(); + + if (this.backgrounds[preloadingPage] != undefined) { + $this.preloadPages(); + return; + } + + var imgback = new Image(); + $(imgback).one('load', function() { + if ($this.fluidbook.vectorTexts) { + $this._loadTexts(preloadingPage, function() { + $this.preloadPages(); + }); + } else { + $this.preloadPages(); + } + }); + imgback.src = this.getBackgroundURL(preloadingPage); + this.backgrounds[preloadingPage] = imgback; + }, + preloadAround: function(page) { + var min = Math.max(1, page - 1); + var max = Math.min(min + this.numPreload, this.fluidbook.datas.pages); + min = max - (this.numPreload); + this.toPreload = []; + for (var i = min; i <= max; i++) { + this.toPreload.push(i); + } + + this.cleanPreloaded(); + this.preloadPages(); + }, + cleanPreloaded: function() { + for (var i = 1; i <= this.fluidbook.datas.pages; i++) { + if (this.backgrounds[i] != undefined && this.toPreload.indexOf(i) == -1) { + this.deletePage(i); + } + } + }, + deletePage: function(page) { + delete this.backgrounds[page]; + delete this.texts[page]; + delete this.links[page]; + }, + setContentsInDoublePage: function(doublePage, pages, immediate, callback) { + var $this = this; + + var leftPage = pages[0]; + var rightPage = pages[1]; + + if (!immediate) { + this.loadLeftPage(leftPage, $(doublePage), function() { + $this.loadRightPage(rightPage, $(doublePage), callback); + }) + + } else { + this.loadLeftPage(leftPage, $(doublePage), function() { + }) + this.loadRightPage(rightPage, $(doublePage), function() { + }); + callback(); + } + }, + loadPage: function(pageNr, doublePage, position, callback) { + // Si une page de gauche existe déjà dans la double page, on la retire + $(doublePage).find('.' + position).each(function() { + if ($(this).attr('id') != 'page_' + pageNr || pageNr == 0) { + $(this).remove(); + } + }) + + var page; + var shade; + // Si la page existe déjà, on la place à la bonne position et on l'affiche + if ($("#page_" + pageNr).length > 0) { + page = $("#page_" + pageNr); + if ($(doublePage).find("#page_" + pageNr).length == 0) { + $(doublePage).append(page); + } + if (!$(page).hasClass(position)) { + if (position == 'left') { + $(page).removeClass('right'); + } + else { + $(page).removeClass('left'); + } + $(page).addClass(position); + } + if (!$(page).is(':visible')) { + $(page).show(); + } + shade = 'shade' + position; + if (this.fluidbook.datas.pageReflection) { + shade += '-reflet'; + } + shade += '.png'; + + $(page).children(".shade").html(''); + $(page).children('.clinks').html(this.fluidbook.datas.clinks[pageNr]); + this.fluidbook.highlightSearchTerms(pageNr); + callback(); + return; + } + + this.fluidbook.initPage(pageNr, doublePage, position); + page = $("#page_" + pageNr); + $(doublePage).append(page); + $(page).show(); + $(page).addClass(position); + var back = $(page).children(".background")[0]; + this.loadDatas(pageNr, callback); + $(page).addClass(position); + + shade = 'shade' + position; + if (this.fluidbook.datas.pageReflection) { + shade += '-reflet'; + } + shade += '.png'; + $(page).children('.clinks').html(this.fluidbook.datas.clinks[pageNr]); + $(page).children(".shade").html(''); +}, + loadLeftPage: function(page, doublePage, callback) { + if (page > 0) { + this.loadPage(page, doublePage, 'left', callback); + } else { + $(doublePage).find('.left').remove(); + callback(); + } + }, + loadRightPage: function(page, doublePage, callback) { + if (!this.fluidbook.displayOnePage && page <= this.fluidbook.datas.pages) { + this.loadPage(page, doublePage, 'right', callback); + } else { + $(doublePage).find('.right').remove(); + callback(); + } +}, + getBackgroundURL: function(page) { + var prefix = 'p'; + if (this.fluidbook.imagesVersion) { + prefix = 't'; + } + + return 'data/background/150/' + prefix + page + '.jpg'; + }, + getTextsURL: function(page) { + return 'data/contents/p' + page + '.svg'; + }, + setBackground: function(page, callback) { + var $this = this; + var back = $("#page_" + page + ' .background'); + this._loadBackground(page, function() { + $(back).addClass('r150'); + $(back).append($this.backgrounds[page]); + }); + }, + _loadBackground: function(page, callback) { + if (this.backgrounds[page] != undefined) { + callback(); + } else { + var img = new Image(); + $(img).one('load', function() { + callback(); + }); + img.src = this.getBackgroundURL(page); + this.backgrounds[page] = img; + } + }, + loadTexts: function(pageNr, callback) { + if (this.fluidbook.imagesVersion) { + callback(); + return; + } + + if (this.texts[pageNr] != undefined) { + $("#page_" + pageNr + ' .texts').append(this.texts[pageNr]); + callback(); + } else { + this._loadTexts(pageNr, function() { + var content; + content = this; + $("#page_" + pageNr + ' .texts').append(content); + callback(); + }); + } + }, + _loadTexts: function(pageNr, callback) { + var w = this.fluidbook.datas.width / 0.75; + var h = this.fluidbook.datas.height / 0.75; + + var img = new Image(); + img.width = w * 2; + img.height = h * 2; + img.type = 'image/svg+xml'; + $(img).one('load', callback); + img.src = this.getTextsURL(pageNr); + this.texts[pageNr] = img; + }, + loadDatas: function(pageNr, callback) { + var $this = this; + this.loadTexts(pageNr, function() { + $this.setBackground(pageNr, callback); + }); + } +}; \ No newline at end of file diff --git a/js/libs/fluidbook/fluidbook.nav.js b/js/libs/fluidbook/fluidbook.nav.js new file mode 100644 index 00000000..17b3ac66 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.nav.js @@ -0,0 +1,186 @@ +function FluidbookNav(fluidbook) { + this.fluidbook = fluidbook; + this._dimensions = this.fluidbook.datas.iconsDimensions; + + this.setNav(); +} + +FluidbookNav.prototype = { + getIcon: function(name) { + var src = 'data/images/' + name + '.'; + if (this.fluidbook.support.SVG) { + src += 'svg'; + } else { + src += 'png'; + } + if (this._dimensions[name] == undefined) { + return ''; + } + + return ''; + }, + addLink: function(name, href, id, help, before, c) { + if ($("#nav").find('#' + id).length > 0) { + return; + } + var l = this.getLink(name, href, id, help, c); + if (before == undefined) { + $("#nav").append(l); + } else { + $("#nav #" + before).before(l); + } + }, + getLink: function(name, href, id, help, className) { + var res = ' 0) { + this.addLink('nav-sommaire', '#/chapters', 'chapters', 'chapters'); + } + } + } else if (icon == 'friend') { + if (this.fluidbook.datas.share) { + this.addLink('nav-friend', '#/share', 'share', 'share'); + $("#share").click(function() { + if ($this.fluidbook.datas.phonegap != 'android') { + return true; + } + $this.fluidbook.intentShare(); + return false; + }); + } + } else if (icon == 'bookmark') { + if (this.fluidbook.datas.bookmark) { + this.addLink('nav-bookmark', '#/bookmark', 'bookmarks', 'bookmarks'); + } + } else if (icon == 'pdf' || icon == 'print') { + if (this.fluidbook.datas.print || this.fluidbook.datas.pdf) { + this.addLink('nav-print', '#', 'print', '!' + this.fluidbook.l10n.__('print') + ' | ' + this.fluidbook.l10n.__('download pdf')); + $("#print").click(function() { + $this.fluidbook.print(); + return false; + }); + } + } else if (icon == 'lang') { + if (this.fluidbook.l10n.multilangEnabled) { + this.addMultilangLink(); + } + } else if (icon == 'archives') { + if (this.fluidbook.datas.archivesLink != '') { + this.addLink('nav-archives', this.fluidbook.datas.archivesLink, 'archives', '!' + this.fluidbook.datas.archivesLabel); + } else if (this.fluidbook.datas.externalArchives != '') { + this.addLink('nav-archives', '#/archives', 'archives', '!' + this.fluidbook.datas.archivesLabel); + } + } else if (icon == 'help') { + this.addLink('nav-help', '#', 'help', ''); + } + } + + if (this.fluidbook.datas.search) { + this.setSearch(); + } + if (this.fluidbook.datas.afterSearch != '') { + this.setAfterSearch(); + } + this.setInterface(); + }, + addMultilangLink: function(langs) { + var l = ''; + + var flag = this.fluidbook.l10n.multilang[this.fluidbook.l10n.getActiveLang()].flag; + + $("#nav").append(l); + $("#nav #locales").css('background-image', 'url("images/flags/' + flag + '.png")'); + }, + setSearch: function() { + var $this = this; + + var res = '
'; + res += ''; + res += this.getLink('interface-search', '#', 'submitSearch'); + res += '
'; + res += '
'; + + $("#search").append(res); + + $("#submitSearch").click(function() { + $("#searchForm").submit(); + return false; + }) + + // Search form + $("#searchForm").submit(function() { + var q = $("#q").val(); + if (q == '') { + return false; + } + window.location.hash = '/search/' + q; + return false; + }); + + $("#q").keyup(searchHints); + + $(document).on('click', ".hint", function() { + var e = $("#q").val().split(' '); + e.pop(); + e.push($(this).attr('term')); + $("#q").val(e.join(' ')); + $("#searchForm").submit(); + return false; + }) + + $("#q").blur(function(e) { + setTimeout(function() { + $this.fluidbook.hideSearchHints(); + }, 250); + }); + + $("#nav").append($("#search")); + }, + setAfterSearch: function() { + $("#nav").append('
'); + }, + setInterface: function() { + + var res = this.getLink('interface-previous', '#', 'previous', '', 'hidden'); + res += this.getLink('interface-next', '#', 'next'); + + $('#interface').append(res); + + $(document).on('click', '#next', goNextPage); + $(document).on('click', '#previous', goPreviousPage); + } +}; \ No newline at end of file diff --git a/js/libs/fluidbook/fluidbook.pad.js b/js/libs/fluidbook/fluidbook.pad.js new file mode 100644 index 00000000..ac134ba0 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.pad.js @@ -0,0 +1,73 @@ +function FluidbookPad(fluidbook) { + this.fluidbook = fluidbook; + this.enabled = this.fluidbook.datas.mobileNavigationType == 'tab'; + this.tapHoldTimeout; + this.visibleTimeout; + this.visibleTime = 5000; + this.interfaceVisible = false; + if (this.enabled) { + this.init(); + } +} + +FluidbookPad.prototype = { + init: function() { + this.initEvents(); + + }, + initEvents: function() { + var $this = this; + $(document).on('click', '#down', function() { + if ($(this).hasClass('right')) { + $this.fluidbook.goNextChapter(); + } else { + $this.fluidbook.goNextChapterPage(); + } + return false; + }); + + $(document).on('click', '.nonlinkarea', function() { + $this.toggleInterface(); + return false; + }); + }, + toggleInterface: function() { + if (this.interfaceVisible) { + return this.hideInterface(); + } else { + return this.displayInterface(); + } + }, + displayInterface: function() { + this.interfaceVisible = true; + $("header,#interface").css({visibility: 'visible', opacity: 1}); + this.resetTimeout(); + }, + resetTimeout: function() { + var $this = this; + this.clearTimeout(); + this.visibleTimeout = setTimeout(function() { + $this.hideInterface(); + }, this.visibleTime); + }, + hideInterface: function() { + this.interfaceVisible = false; + if ($("#helpView").is(':visible') || document.activeElement.tagName.toLowerCase() === 'input') { + this.resetTimeout(); + return; + } + $("header,#interface").css({opacity: 0}).delay(1100).css('visibility', 'hidden'); + this.clearTimeout(); + }, + clearTimeout: function() { + clearTimeout(this.visibleTimeout); + }, + getTransitionAxis: function(currentPage, nextPage) { + var linkedPages = this.fluidbook.bookmarks.getLinkedPages(currentPage); + if (linkedPages.indexOf(nextPage) == -1) { + return 'x'; + } + return 'y'; + } +}; + diff --git a/js/libs/fluidbook/fluidbook.resize.js b/js/libs/fluidbook/fluidbook.resize.js new file mode 100644 index 00000000..026bc9ae --- /dev/null +++ b/js/libs/fluidbook/fluidbook.resize.js @@ -0,0 +1,269 @@ +function FluidbookResize(fluidbook) { + this.fluidbook = fluidbook; + this.marginw = 50; + this.marginh = 20; + this.corr = 0.8; + this.referenceWidthLandscape = 1024; + this.referenceWidthPortrait = 600; + this.referenceHeight = 600; + this.orientation = ''; + this.textScale = 2; + this.bookScale = 1; + this.ww = $(window).width(); + this.hh = $(window).height(); + this.init(); + this.navresizeTimeout = 0; +} + +FluidbookResize.prototype = { + init: function() { + $("#nav").transform({ + origin: ['0%', '0%'] + }); + + $("#logo").transform({ + origin: ['100%', '0%'] + }); + + $("#footer").transform({ + origin: ['100%', '100%'] + }); + + $("#next").transform({ + origin: ['100%', '50%'] + }); + + $("#previous").transform({ + origin: ['0%', '50%'] + }); + }, + resize: function(init) { + if (init == undefined || init == null) { + init = false; + } + + var $this = this; + this.updateWindow(); + this.handleOrientation(); + + var interfaceScale; + if (this.orientation == 'landscape') { + interfaceScale = Math.min(1, this.ww / this.referenceWidthLandscape, this.hh / this.referenceHeight); + } else if (this.orientation == 'portrait') { + interfaceScale = Math.min(1, this.ww / this.referenceWidthPortrait, this.hh / this.referenceHeight); + } + var navScale = interfaceScale * parseInt(this.fluidbook.datas.mobileNavScale) / 100; + var cssInterfaceScale = [interfaceScale, interfaceScale]; + var cssNavScale = [navScale, navScale]; + + + $("#main").css({ + width: this.ww, + height: this.hh + }); + + this.resizeView(); + + $("#next").css({ + right: 0 + }); + + var marginY, marginX, marginTop, marginBottom, marginLeft, marginRight; + + if (this.fluidbook.pad.enabled) { + marginY = 0; + marginX = 0; + extraX = 0; + marginTop = 0; + marginBottom = 0; + marginLeft = 0; + marginRight = 0; + } else { + marginX = 50; + marginY = 20; + + var extraX = parseInt(this.fluidbook.datas.mobileExtraXSpace); + if (isNaN(extraX)) { + extraX = 0; + } + + marginTop = (this.fluidbook.datas.menuHeight + marginY) * interfaceScale; + marginBottom = (10 + marginY) * interfaceScale; + marginLeft = (marginX + extraX) * interfaceScale; + marginRight = marginLeft; + } + + var aw = this.ww - marginLeft - marginRight; + var ah = this.hh - marginTop - marginBottom; + var fhh = this.fluidbook.datas.height; + var fww = this.fluidbook.datas.width; + if (this.orientation == 'landscape') { + fww *= 2; + } + + this.bookScale = Math.min(aw / fww, ah / fhh); + var fw = this.bookScale * fww; + var fh = this.bookScale * fhh; + $("#fluidbook").transform({ + scale: [this.bookScale, this.bookScale], + origin: ['50%', '50%'] + }); + $("#fluidbook").css({ + top: marginTop + (ah - fhh) / 2, + left: marginLeft + (aw - fww) / 2, + width: fww, + height: fhh + }); + + + $("#next,#previous").transform({ + scale: cssInterfaceScale + }); + + $("#nav,#logo,footer").transform({ + scale: navScale + }); + + var headerHeight = this.fluidbook.datas.menuHeight * navScale; + $('header').css({ + height: headerHeight, + backgroundSize: '100% ' + headerHeight + 'px' + }); + + this.refw = fw; + this.refh = fh; + + this.fluidbook.help.resize(this.ww, this.hh, interfaceScale, navScale); + this.fluidbook.coquillette.resize(this.ww, this.hh); + this.fluidbook.background.resize(this.ww, this.hh); + + var timeout = 0; + if (this.fluidbook.support.android) { + timeout = 1000; + } + + if (timeout > 0) { + $("#next,#previous").hide(); + clearTimeout(this.navresizeTimeout); + this.navresizeTimeout = setTimeout(function() { + $this.resizeNav(interfaceScale) + }, timeout); + } else { + this.resizeNav(interfaceScale); + } + + this.resizePopupVideos(); + this.resizeSplash(); + }, + resizeNav: function(interfaceScale) { + var topNext = (this.hh - 100 * interfaceScale) / 2; + $("#next,#previous").css({ + top: topNext + }); + $("#next,#previous").show(); + }, + resizePopupVideos: function() { + var maxh = this.hh - 80; + $(".mview .videoContainer video").each(function() { + var w = $(window).width() - 40; + + var ratio = parseInt($(this).attr('data-width')) / parseInt($(this).attr('data-height')); + var h = w / ratio; + $(this).css({ + height: h, + maxHeight: maxh + }); + }); + }, + resizeSplash: function() { + $("#splash").css({ + width: this.ww, + height: this.hh + }); + + if ($("#splash").css('opacity') == 0) { + $("#splash").css('opacity', 1); + } + + var lw = $("#splash .logo").width(); + var lh = $("#splash .logo").height(); + + $("#splash .logo").css({ + top: (this.hh / 2) - 30 - lh - 10, + left: (this.ww - lw) / 2 + }); + }, + updateWindow: function() { + this.ww = $(window).width(); + this.hh = $(window).height(); + }, + resizeView: function() { + var $this = this; + this.updateWindow(); + + $(".mview").css({ + width: this.ww, + minHeight: this.hh, + maxHeight: this.hh, + height: this.hh + }); + + $(".mview").find('.caption,.content').css({ + width: this.ww + }); + + + $(".mview .caption h2").each(function() { + var wavailable = $this.ww; + $(this).parent().find('a.back').each(function() { + wavailable -= ($(this).outerWidth() + 10) * 2; + }); + $(this).css('max-width', wavailable); + }); + + if ($("#archivesview").length == 1) { + var w = this.fluidbook.datas.filesInfos.archives.width; + var ratio = $("#archivesview img").width() / w; + $("#archivesview .links").transform({scale: [ratio]}); + } + + $(".bookmarkView").each(function() { + var w = $(this).parent().width(); + var perCol = Math.floor(w / 120); + + var uw = perCol * 120; + var m = (w - uw) / 2; + $(this).css({ + width: uw, + margin: '0 auto' + }) + }); + }, + handleOrientation: function() { + var changeOrientation = this.orientation != ''; + var o = this.fluidbook.support.getOrientation(); + var newo; + if (o == 0 || o == 180) { + newo = 'portrait'; + $('body').removeClass('landscape'); + } else { + newo = 'landscape'; + $('body').removeClass('portrait'); + } + + if (this.orientation == newo) { + return; + } + this.orientation = newo; + + $('body').addClass(this.orientation); + + this.fluidbook.displayOnePage = (this.orientation == 'portrait'); + + if (changeOrientation) { + this.fluidbook.resetZoom(); + this.fluidbook.pageTransition(); + } + } +}; + diff --git a/js/libs/fluidbook/fluidbook.search.js b/js/libs/fluidbook/fluidbook.search.js new file mode 100644 index 00000000..8b50d207 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.search.js @@ -0,0 +1,109 @@ +function FluidbookSearch() { +} + +FluidbookSearch.prototype = { + getHints: function(q) { + var words = this.normalizeQuery(q); + q = words.pop(); + var res = []; + + if (q.length < 3) { + return res; + } + + var v; + for (var k in INDEX) { + v = INDEX[k]; + if (k.indexOf(q) != 0) { + continue; + } + res.push([k, v.t]); + } + + res.sort(this.sortHints); + return res.slice(0, 12); + }, + find: function(q) { + var words = this.normalizeQuery(q); + + var res = {}; + var terms = []; + var total=0; + + var q, v, k, kk, word, wordata, page, occurences; + for (kk in words) { + q = words[kk]; + + for (k in INDEX) { + v = INDEX[k]; + if (k.indexOf(q) != 0) { + continue; + } + for (word in v.w) { + wordata = v.w[word]; + terms.push(word); + for (page in wordata.p) { + + occurences = wordata.p[page]; + + page = parseInt(page); + + + if (res[page] == undefined) { + res[page] = 0; + } + res[page] += occurences; + total+=occurences; + } + } + } + } + + return { + total:total, + results: res, + terms: terms.join(' ') + }; + }, + sortHints: function(a, b) { + return b[1] - a[1]; + }, + kill: function() { + + }, + normalizeQuery: function(q) { + q = this.noAccents(q); + q = q.toLowerCase(); + return q.split(' '); + }, + noAccents: function(source) { + source = source.replace(/[àáâãäå]/g, "a"); + source = source.replace(/[ÀÁÂÃÄÅ]/g, "A"); + source = source.replace(/[èéêë]/g, "e"); + source = source.replace(/[ËÉÊÈ]/g, "E"); + source = source.replace(/[ìíîï]/g, "i"); + source = source.replace(/[ÌÍÎÏ]/g, "I"); + source = source.replace(/[ðòóôõöø]/g, "o"); + source = source.replace(/[ÐÒÓÔÕÖØ]/g, "O"); + source = source.replace(/[ùúûü]/g, "u"); + source = source.replace(/[ÙÚÛÜ]/g, "U"); + source = source.replace(/[ýýÿ]/g, "y"); + source = source.replace(/[ÝÝŸ]/g, "Y"); + source = source.replace(/[ç]/g, "c"); + source = source.replace(/[Ç]/g, "C"); + source = source.replace(/[ñ]/g, "n"); + source = source.replace(/[Ñ]/g, "N"); + source = source.replace(/[š]/g, "s"); + source = source.replace(/[Š]/g, "S"); + source = source.replace(/[ž]/g, "z"); + source = source.replace(/[Ž]/g, "Z"); + source = source.replace(/[æ]/g, "ae"); + source = source.replace(/[Æ]/g, "AE"); + source = source.replace(/[œ]/g, "oe"); + source = source.replace(/[Œ]/g, "OE"); + return source; + + } +}; + + \ No newline at end of file diff --git a/js/libs/fluidbook/fluidbook.service.js b/js/libs/fluidbook/fluidbook.service.js new file mode 100644 index 00000000..ce53aa6d --- /dev/null +++ b/js/libs/fluidbook/fluidbook.service.js @@ -0,0 +1,30 @@ +function FluidbookService(fluidbook, id) { + this.fluidbook = fluidbook; + this.baseURL = 'http://workshop.fluidbook.com/services/'; + this.id = id; +} + +FluidbookService.prototype = { + call: function(func, datas, handler, context) { + datas['id'] = this.id; + return $.ajax({ + url: this.baseURL + func, + context: context, + format: 'xml', + crossDomain: true, + data: datas, + success: function(data) { + handler.call(this, data) + } + }); + }, + open: function(func, datas) { + datas['id'] = this.id; + var u = []; + $.each(datas, function(k, v) { + u.push(k + '=' + encodeURIComponent(v)); + }); + var url = this.baseURL + func + '?' + u.join('&'); + this.fluidbook.wopen(url, '_blank'); + } +} \ No newline at end of file diff --git a/js/libs/fluidbook/fluidbook.stats.js b/js/libs/fluidbook/fluidbook.stats.js new file mode 100644 index 00000000..7cb5b8fd --- /dev/null +++ b/js/libs/fluidbook/fluidbook.stats.js @@ -0,0 +1,66 @@ +function FluidbookStats(fluidbook) { + this.fluidbook = fluidbook; + this.id = this.fluidbook.datas.id; + this.init(); +} + +FluidbookStats.prototype = { + init: function() { + var $this = this; + $(document).on('click', 'a[data-track]', function() { + $this.track(6, 0, $(this).attr('data-track')); + return true; + }); + }, + trackPageChange: function() { + if (!this.fluidbook.support.hasNetwork()) { + return; + } + try { + if (_gaq == undefined) { + return; + } + var page = location.pathname + location.search + location.hash; + if (_gatrackers != undefined) { + $.each(_gatrackers, function(k, v) { + _gaq.push([v + '._trackPageview', page]); + }); + } else { + _gaq.push(['_trackPageview', page]); + } + } catch (err) { + + } + }, + track: function(type, page, extra) { + if (!this.fluidbook.support.hasNetwork()) { + return; + } + + if (page == undefined) { + page = 0; + } + if (extra == undefined) { + extra = ''; + } + + $.ajax({ + url: 'http://stats.fluidbook.com/stats2.php', + type: 'GET', + data: { + id: this.id, + type: type, + page: page, + str: extra, + time: new Date().getTime() + }, + success: function() { + + }, + error: function() { + + } + }); + } +}; + diff --git a/js/libs/fluidbook/fluidbook.support.js b/js/libs/fluidbook/fluidbook.support.js new file mode 100644 index 00000000..cb4189a5 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.support.js @@ -0,0 +1,130 @@ +function FluidbookSupport(fluidbook) { + this.fluidbook = fluidbook; + this.userAgent = navigator.userAgent; + this.android = this.fitScreenAtZero = this.userAgent.search(/android/i) > -1 || this.userAgent.search(/galaxy/i) > -1; + this.android3 = this.android && this.userAgent.search(/android 3/i) > -1; + this.iOS = this.userAgent.search(/ipad/i) > -1 || this.userAgent.search(/iphone/i) > -1 || this.userAgent.search(/ipod/i) > -1; + + this.transitions3d = Modernizr.csstransforms3d && Modernizr.csstransitions && Modernizr.csstransformspreserve3d; + this.transitions2d = Modernizr.csstransforms && Modernizr.csstransitions; + this.transitionendevents = ['transitionEnd', 'transitionend', 'mozTransitionEnd', 'webkitTransitionEnd', 'oTransitionEnd', 'msTransitionEnd'].join(' '); + + this.initialResolution = 150; + + this.isMobile = isMobile(); + this.SVG = Modernizr.svg && this.fluidbook.datas.mobileIconVector; + + this._orientation = this.getOrientation(); + this.initialZoomPortrait = 0; + this.initialZoomLandscape = 0; + var z = DetectZoom.zoom(); + if (this._orientation == 0) { + this.initialZoomPortrait = z; + } else { + this.initialZoomLandscape = z; + } + this.initEvents(); +} + +FluidbookSupport.prototype = { + hasNetwork: function() { + if (navigator.onLine != undefined) { + return navigator.onLine; + } else { + return networkState() != 'none'; + } + }, + networkState: function() { + var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection || { + type: 'unknown' + }; + var t = connetion.type; + + if (t == undefined) { + t = 'unknown'; + } else if (t == 0) { + t = 'unknown'; + } else if (t == 1) { + t = 'ethernet'; + } else if (t == 2) { + t = 'wifi'; + } else if (t == 3) { + t = '2g'; + } else if (t == 4) { + t = '3g'; + } else if (t == 5) { + t = '4g'; + } else { + t = 'none'; + } + return t; + }, + initEvents: function() { + + if (!this.isMobile) { + $(window).resize(function() { + resize(); + }); + return; + } + + if ("onorientationchange" in window) { + window.addEventListener('orientationchange', function() { + if (this.iOS) { + resize(); + } else { + resize(); + setTimeout(function() { + resize(); + }, 750); + } + }, false); + } else { + var $this = this; + setInterval(function() { + $this.checkOrientation(); + }, 100); + } + + }, + checkOrientation: function() { + var o = this.getOrientation(); + if (o != this._orientation) { + this._orientation = o; + resize(); + } + }, + getOrientation: function() { + try { + var mql = window.matchMedia("(orientation: portrait)"); + if (mql.matches) { + return 0; + } else { + return 90; + } + } catch (err) { + + } + if ($("#op").is(':visible')) { + return 0; + } else { + return 90; + } + }, + getZoomLevel: function() { + var tzoom = DetectZoom.zoom(); + var iz; + if (this._orientation == 0) { + iz=this.initialZoomPortrait; + if(iz==0){ + iz=this.initialZoomPortrait=tzoom; + } + }else{ + iz=this.initialZoomLandscape; + if(iz==0){ + iz=this.initialZoomLandscape=tzoom; + } + } + return tzoom / iz; + } +} diff --git a/js/libs/fluidbook/fluidbook.touch.js b/js/libs/fluidbook/fluidbook.touch.js new file mode 100644 index 00000000..61404284 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.touch.js @@ -0,0 +1,219 @@ +function FluidbookTouch(fluidbook) { + this.fluidbook = fluidbook; + this.scale = 1; + + this.startX = 0; + this.startY = 0; + this.offsetX = 0; + this.offsetY = 0; + + this.triggerOffset = 0.05; + this.triggered = false; + this.gesturing = false; + + this.init(); +} + +FluidbookTouch.prototype = { + init: function() { + this.reset(); + + $(document).on('touchstart', $.proxy(this.start, this)); + $(document).on('touchend', $.proxy(this.end, this)); + $(document).on('touchmove', $.proxy(this.move, this)); + $(document).on('touchcancel', $.proxy(this.cancel, this)); + $(document).on('gesturestart', $.proxy(this.gesturestart, this)); + $(document).on('gesturechange', $.proxy(this.gesturechange, this)); + $(document).on('gestureend', $.proxy(this.gestureend, this)); + + $(document).on('MSPointerDown', $.proxy(this.msdown, this)); + $(document).on('MSPointerUp', $.proxy(this.msup, this)); + $(document).on('MSPointerMove', $.proxy(this.msmove, this)); + }, + msdown: function(event) { + var e = event.originalEvent; + if (e.pointerType != e.MSPOINTER_TYPE_TOUCH) { + return true; + } + this._start(e.screenX, e.screenY); + return true; + }, + msup: function(event) { + var e = event.originalEvent; + if (e.pointerType != e.MSPOINTER_TYPE_TOUCH) { + return true; + } + this._end(); + }, + msmove: function(event) { + var e = event.originalEvent; + if (e.pointerType != e.MSPOINTER_TYPE_TOUCH) { + return true; + } + return this._move(e.screenX, e.screenY); + }, + allowMove: function() { + return !(this.fluidbook.support.getZoomLevel() <= 1 && !this.fluidbook.viewMode()); + }, + allowSlide: function() { + return !(this.gesturing || this.fluidbook.support.getZoomLevel() > 1 || this.fluidbook.viewMode()); + }, + reset: function() { + this.startX = 0; + this.startY = 0; + this.offsetX = 0; + this.offsetY = 0; + this.triggered = false; + }, + gesturestart: function(event) { + if (this.fluidbook.pad.enabled) { + return false; + } + var e = event.originalEvent; + this.enableUserScale(); + this.gesturing = true; + return true; + }, + gesturechange: function(event) { + if (this.fluidbook.pad.enabled) { + return false; + } + var e = event.originalEvent; + this.gesturing = true; + return true; + }, + gestureend: function(event) { + if (this.fluidbook.pad.enabled) { + return false; + } + + var e = event.originalEvent; + this.gesturing = false; + + if (DetectZoom.zoom() > 1) { + $('html').addClass('nopan'); + } else { + $('html').removeClass('nopan'); + } + return true; + }, + start: function(event) { + var e = event.originalEvent; + var touches = e.touches; + + if (touches.length > 1) { + this.enableUserScale(); + return true; + } + + this._start(touches[0].pageX, touches[0].pageY); + return true; + }, + end: function(event) { + var e = event.originalEvent; + var touches = e.touches; + + if (touches.length == 0) { + this._end(); + } + return true; + }, + testOffset: function() { + if (this.triggered) { + return false; + } + if (this.allowMove()) { + return false; + } + if (!this.fluidbook.pad.enabled) { + if (Math.abs(this.offsetX) < Math.abs(this.offsetY)) { + return false; + } + if (this.allowSlide()) { + if (this.offsetX < -this.triggerOffset) { + this.fluidbook.goNextPage(); + return true; + } else if (this.offsetX > this.triggerOffset) { + this.fluidbook.goPreviousPage(); + return true; + } + } + } else { + // Mode mag pad + if (this.allowSlide()) { + var offset = this.offsetX; + var way = 'x'; + if (Math.abs(this.offsetX) < Math.abs(this.offsetY)) { + offset = this.offsetY; + way = 'y'; + } + + if (Math.abs(offset) < this.triggerOffset) { + return false; + } + + if (offset < -this.triggerOffset) { + if (way == 'x') { + this.fluidbook.goNextChapter(); + } else { + this.fluidbook.goNextChapterPage(); + } + } else { + if (way == 'x') { + this.fluidbook.goPreviousChapter(); + } else { + this.fluidbook.goPreviousChapterPage(); + } + } + return true; + } + } + return false; + }, + cancel: function(event) { + this.end(event); + return true; + }, + move: function(event) { + var e = event.originalEvent; + + var touches = e.touches; + + if (touches.length > 1) { + return true; + } + + return this._move(touches[0].pageX, touches[0].pageY); + }, + _start: function(x, y) { + this.startX = x; + this.startY = y; + }, + _move: function(x, y) { + if (!isNaN(this.startX)) { + this.offsetX = (x - this.startX) / $(window).width(); + } + + if (!isNaN(this.startY)) { + this.offsetY = (y - this.startY) / $(window).height(); + } + + this.testOffset(); + return this.allowMove(); + }, + _end: function() { + this.testOffset(); + this.reset(); + }, + enableUserScale: function() { + if (this.fluidbook.pad.enabled) { + this.fluidbook.viewport.maxScale = 1; + this.fluidbook.viewport.userScalable = false; + } else { + this.fluidbook.viewport.maxScale = 8; + this.fluidbook.viewport.userScalable = true; + } + this.fluidbook.viewport.updateViewport(); + } +}; + diff --git a/js/libs/fluidbook/fluidbook.utils.js b/js/libs/fluidbook/fluidbook.utils.js new file mode 100644 index 00000000..aa19a5d4 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.utils.js @@ -0,0 +1,40 @@ +function isMobile() { + var ua = navigator.userAgent; + var devices = ['iphone', 'ipad', 'ipod', 'droid', 'blackberry', 'mobile', 'htc', 'samsung', 'nokia', 'archos', 'galaxy', 'motorola', 'pad', 'tab', 'slate', 'motorola', 'symbian', 'phone', 'nintendo', 'playstation', 'touch', 'webos', 'ericsson']; + var pattern; + + if (Modernizr.ftouch) { + return true; + } + + for (i = 0; i < devices.length; i++) { + pattern = new RegExp(devices[i], 'i'); + if (ua.search(pattern) > -1) { + return true; + } + } + return false; +} + +function parseGet() { + var couples = window.location.search.substr(1).split('&'); + var res = new Array(); + var couple = new Array(); + for (var i = 0; i < couples.length; i++) { + couple = couples[i].split('='); + res[couple[0]] = couple[1]; + } + return res; +} + +function getBaseURL() { + var l = window.location.toString(); + var e = l.split("#"); + var l = e[0]; + if (l.indexOf('.') != -1) { + e = l.split('/'); + e.pop(); + l=e.join('/'); + } + return l; +} \ No newline at end of file diff --git a/js/libs/fluidbook/fluidbook.video.js b/js/libs/fluidbook/fluidbook.video.js new file mode 100644 index 00000000..b89b4d67 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.video.js @@ -0,0 +1,163 @@ +function FluidbookVideo(fluidbook) { + this.fluidbook = fluidbook; + this.flash = FlashDetect.installed && FlashDetect.major >= 9; + this.video = (Modernizr.video && (Modernizr.video.h264 || Modernizr.video.webm || Modernizr.video.ogg)) != false; + + this.videoFormats = []; + + var probably = []; + var maybe = []; + var not = []; + if (Modernizr.ftouch) { + if (this.flash) { + probably.push('flv'); + } + } + + if (this.video) { + var formats = this.fluidbook.datas.videoFormats; + for (var i = 0; i < formats.length; i++) { + var f = formats[i]; + if (f == 'mp4') { + f = 'h264'; + } + if (f == 'ogv') { + f = 'ogg'; + } + var support = Modernizr.video[f]; + if (f == 'ogg') { + f = 'ogv'; + } + if (f == 'h264') { + f = 'mp4'; + } + if (support == 'probably') { + probably.push(f); + } else if (support == 'maybe') { + maybe.push(f); + } else { + not.push(f); + } + } + } + if (!Modernizr.ftouch) { + if (this.flash) { + probably.push('flv'); + } + } + + + this.videoFormats = $.merge(probably, maybe, not); + this.preferedFormat = this.videoFormats[0]; + //fb("Video prefered format : " + this.preferedFormat+" ("+this.videoFormats.join(', ')+")"); +} + +FluidbookVideo.prototype = { + initVideo: function(e) { + if ($(e).html() != '') { + return; + } + var width = parseFloat($(e).attr('data-width')); + var height = parseFloat($(e).attr('data-height')); + var name = $(e).attr('data-name'); + var controls = $(e).attr('data-controls'); + var loop = $(e).attr('data-loop'); + var sound = $(e).attr('data-sound'); + var autoplay = $(e).attr('data-autoplay'); + + var path; + if (fluidbook.datas.mobileVideosPath == '') { + path = "data/links/" + name; + } else { + path = fluidbook.datas.mobileVideosPath + name; + if (!fluidbook.datas.standalone && path.substr(0, 3) == '../') { + path = '../' + path; + } + } + var poster = path + '.jpg'; + + if (this.preferedFormat == 'flv') { + var fv = {}; + fv.video = '../' + path + '.flv'; + fv.poster = '../' + poster; + fv.controls = controls; + fv.autoPlay = autoplay; + fv.loop = loop; + fv.soundOn = sound; + var flashvars = []; + $.each(fv, function(k, v) { + flashvars.push(k + '=' + encodeURIComponent(v)); + }); + + if (isNaN(width)) { + width = '100%'; + } + if (isNaN(height)) { + height = '100%'; + } + + html = ''; + html += ''; + } else if (this.preferedFormat != 'img') { + html = ''; + } else { + html = ''; + html += ''; + html += ''; + } + + $(e).html(html); + }, + initCache: function() { + var $this = this; + $('body').append(''); + $("#videoframe").load(function() { + var w = this.contentWindow; + var cache = w.applicationCache; + cache.addEventListener('downloading', $this.logCacheEvent, false); + cache.addEventListener('checking', $this.logCacheEvent, false); + cache.addEventListener('cached', $this.logCacheEvent, false); + cache.addEventListener('downloading', $this.logCacheEvent, false); + cache.addEventListener('noupdate', $this.logCacheEvent, false); + cache.addEventListener('updateready', $this.logCacheEvent, false); + cache.addEventListener('error', $this.logCacheEvent, false); + $(this).hide(); + }); + }, + logCacheEvent: function(e) { + fb('video :' + e.type); + } +}; \ No newline at end of file diff --git a/js/libs/fluidbook/fluidbook.viewport.js b/js/libs/fluidbook/fluidbook.viewport.js new file mode 100644 index 00000000..33657a08 --- /dev/null +++ b/js/libs/fluidbook/fluidbook.viewport.js @@ -0,0 +1,27 @@ +function FluidbookViewport(support){ + this.support=support; + this.width=null; + this.height=null; + this.minScale=1; + this.maxScale=10; + this.initialScale=1; + this.userScalable=false; + this.meta=$('meta[name="viewport"]'); +} + +FluidbookViewport.prototype={ + updateViewport:function(){ + var w=''; + if(this.width!=null){ + w='width='+this.width+', '; + } + var h=''; + if(this.height!=null){ + h='height='+this.height+', '; + } + var us=this.userScalable==true?'yes':'no'; + + var value=w+h+'initial-scale='+this.initialScale+', minimum-scale='+Math.max(0.25,this.minScale)+', maximum-scale='+Math.min(10,this.maxScale)+', user-scalable='+us; + this.meta.attr('content',value); + } +} \ No newline at end of file diff --git a/js/libs/fluidbook/views/fluidbook.chapters.js b/js/libs/fluidbook/views/fluidbook.chapters.js new file mode 100644 index 00000000..21ef909e --- /dev/null +++ b/js/libs/fluidbook/views/fluidbook.chapters.js @@ -0,0 +1,95 @@ +function FluidbookChapters(fluidbook, chapters) { + this.fluidbook = fluidbook; + this.chapters = chapters; + this.html = ''; + this.lastColor; +} + +FluidbookChapters.prototype = { + getView: function() { + if (this.html == '') { + this.makeView(); + } + return this.html; + }, + makeView: function() { + this.makeClassicMenu(); + if (this.fluidbook.datas.chaptersCascade) { + this.makeCascadeMenu(); + } + }, + makeCascadeMenu: function() { + var h = $(this.html); + + for (var i = 3; i >= 0; i--) { + $(h).find('li[data-level=' + i + ']').each(function() { + var siblings = $(this).nextUntil('li[data-level!=' + (i + 1) + ']', 'li[data-level=' + (i + 1) + ']'); + if (siblings.length > 0) { + $(this).append('
    '); + var nav = $(this).find('ul'); + $(nav).append(siblings); + $(nav).hide(); + } + }); + } + this.html = $(h).get(0).outerHTML; + + $(document).on('click', 'ul.chapters a', function() { + var li = $(this).parent(); + var subnav = $(li).children('ul'); + if ($(subnav).length) { + $(subnav).slideToggle(); + return false; + } else { + return true; + } + }); + }, + makeClassicMenu: function() { + var $this = this; + this.html = '
      '; + $.each(this.chapters, function(k, v) { + $this.html += $this.addItem(v); + }); + this.html += '
    '; + }, + addItem: function(chapter) { + if (chapter.label == '--' || chapter.label == '++') { + return ""; + + } + var color = chapter.color; + if (color == '') { + if (this.lastColor != undefined) { + color = this.lastColor; + } + } + if (color != '') { + this.lastColor = color; + } + + + if (chapter.label.substr(0, 3) == '!!!') { + chapter.label = chapter.label.substring(3); + chapter.level='-1'; + } + + + + var res = '
  • '; + res += chapter.label; + res += '
    '; + if (color == '') { + res += chapter.page; + } else { + res += '
    '; + } + res += '
    ' + res += '
  • '; + + return res; + } + + +}; + diff --git a/js/libs/fluidbook/views/fluidbook.index.js b/js/libs/fluidbook/views/fluidbook.index.js new file mode 100644 index 00000000..8255d3fd --- /dev/null +++ b/js/libs/fluidbook/views/fluidbook.index.js @@ -0,0 +1,67 @@ +function FluidbookIndex(fluidbook) { + this.fluidbook = fluidbook; + this.init(); +} + +FluidbookIndex.prototype = { + init: function() { + this.normalHTML = ''; + this.padHTML = ''; + }, + getView: function(group) { + if (this.fluidbook.pad.enabled) { + return this.getPadView(group); + } else { + return this.getNormalView(); + } + }, + getPadView: function(group) { + return this.fluidbook.bookmarks.getIndex(true, group); + }, + getNormalView: function() { + + if (this.normalHTML == '') { + this.normalHTML += '
    '; + var j = 0; + var ix = ''; + var c = ''; + + for (var i = 0; i <= this.fluidbook.datas.pages; i += 2) { + var pages = []; + j = i + 1; + ix = ''; + c = ''; + if (i > 0) { + ix += '
    ' + this.fluidbook.physicalToVirtual(i) + ''; + if (this.fluidbook.bookmarks.enabled) { + ix += this.fluidbook.bookmarks.getBookmarkForPage(i, true); + } + pages.push(i); + ix += '
    '; + + } else { + c = ' simple right'; + } + if (j < this.fluidbook.datas.pages) { + ix += '
    ' + this.fluidbook.physicalToVirtual(j) + ''; + if (this.fluidbook.bookmarks.enabled) { + ix += this.fluidbook.bookmarks.getBookmarkForPage(j, true); + } + ix += '
    '; + pages.push(j); + } else { + c = ' simple left'; + } + + this.normalHTML += '
    ' + ix; + this.normalHTML += '
    '; + } + for (i = 0; i < 5; i++) { + this.normalHTML += '
    '; + } + this.normalHTML += '
    '; + } + + return this.normalHTML; + } +} diff --git a/js/libs/gsap/TimelineLite.js b/js/libs/gsap/TimelineLite.js new file mode 100644 index 00000000..1128f444 --- /dev/null +++ b/js/libs/gsap/TimelineLite.js @@ -0,0 +1,611 @@ +/*! + * VERSION: beta 1.9.8 + * DATE: 2013-06-05 + * UPDATES AND DOCS AT: http://www.greensock.com + * + * @license Copyright (c) 2008-2013, GreenSock. All rights reserved. + * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for + * Club GreenSock members, the software agreement that was issued with your membership. + * + * @author: Jack Doyle, jack@greensock.com + */ + +(window._gsQueue || (window._gsQueue = [])).push( function() { + + "use strict"; + + window._gsDefine("TimelineLite", ["core.Animation","core.SimpleTimeline","TweenLite"], function(Animation, SimpleTimeline, TweenLite) { + + var TimelineLite = function(vars) { + SimpleTimeline.call(this, vars); + this._labels = {}; + this.autoRemoveChildren = (this.vars.autoRemoveChildren === true); + this.smoothChildTiming = (this.vars.smoothChildTiming === true); + this._sortChildren = true; + this._onUpdate = this.vars.onUpdate; + var v = this.vars, + i = _paramProps.length, + j, a; + while (--i > -1) { + a = v[_paramProps[i]]; + if (a) { + j = a.length; + while (--j > -1) { + if (a[j] === "{self}") { + a = v[_paramProps[i]] = a.concat(); //copy the array in case the user referenced the same array in multiple timelines/tweens (each {self} should be unique) + a[j] = this; + } + } + } + } + if (v.tweens instanceof Array) { + this.add(v.tweens, 0, v.align, v.stagger); + } + }, + _paramProps = ["onStartParams","onUpdateParams","onCompleteParams","onReverseCompleteParams","onRepeatParams"], + _blankArray = [], + _copy = function(vars) { + var copy = {}, p; + for (p in vars) { + copy[p] = vars[p]; + } + return copy; + }, + _slice = _blankArray.slice, + p = TimelineLite.prototype = new SimpleTimeline(); + + TimelineLite.version = "1.9.8"; + p.constructor = TimelineLite; + p.kill()._gc = false; + + p.to = function(target, duration, vars, position) { + return duration ? this.add( new TweenLite(target, duration, vars), position) : this.set(target, vars, position); + }; + + p.from = function(target, duration, vars, position) { + return this.add( TweenLite.from(target, duration, vars), position); + }; + + p.fromTo = function(target, duration, fromVars, toVars, position) { + return duration ? this.add( TweenLite.fromTo(target, duration, fromVars, toVars), position) : this.set(target, toVars, position); + }; + + p.staggerTo = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) { + var tl = new TimelineLite({onComplete:onCompleteAll, onCompleteParams:onCompleteAllParams, onCompleteScope:onCompleteAllScope}), + i; + if (typeof(targets) === "string") { + targets = TweenLite.selector(targets) || targets; + } + if (!(targets instanceof Array) && targets.length && targets[0] && targets[0].nodeType && targets[0].style) { //senses if the targets object is a selector. If it is, we should translate it into an array. + targets = _slice.call(targets, 0); + } + stagger = stagger || 0; + for (i = 0; i < targets.length; i++) { + if (vars.startAt) { + vars.startAt = _copy(vars.startAt); + } + tl.to(targets[i], duration, _copy(vars), i * stagger); + } + return this.add(tl, position); + }; + + p.staggerFrom = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) { + vars.immediateRender = (vars.immediateRender != false); + vars.runBackwards = true; + return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope); + }; + + p.staggerFromTo = function(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) { + toVars.startAt = fromVars; + toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false); + return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope); + }; + + p.call = function(callback, params, scope, position) { + return this.add( TweenLite.delayedCall(0, callback, params, scope), position); + }; + + p.set = function(target, vars, position) { + position = this._parseTimeOrLabel(position, 0, true); + if (vars.immediateRender == null) { + vars.immediateRender = (position === this._time && !this._paused); + } + return this.add( new TweenLite(target, 0, vars), position); + }; + + TimelineLite.exportRoot = function(vars, ignoreDelayedCalls) { + vars = vars || {}; + if (vars.smoothChildTiming == null) { + vars.smoothChildTiming = true; + } + var tl = new TimelineLite(vars), + root = tl._timeline, + tween, next; + if (ignoreDelayedCalls == null) { + ignoreDelayedCalls = true; + } + root._remove(tl, true); + tl._startTime = 0; + tl._rawPrevTime = tl._time = tl._totalTime = root._time; + tween = root._first; + while (tween) { + next = tween._next; + if (!ignoreDelayedCalls || !(tween instanceof TweenLite && tween.target === tween.vars.onComplete)) { + tl.add(tween, tween._startTime - tween._delay); + } + tween = next; + } + root.add(tl, 0); + return tl; + }; + + p.add = function(value, position, align, stagger) { + var curTime, l, i, child, tl; + if (typeof(position) !== "number") { + position = this._parseTimeOrLabel(position, 0, true, value); + } + if (!(value instanceof Animation)) { + if (value instanceof Array) { + align = align || "normal"; + stagger = stagger || 0; + curTime = position; + l = value.length; + for (i = 0; i < l; i++) { + if ((child = value[i]) instanceof Array) { + child = new TimelineLite({tweens:child}); + } + this.add(child, curTime); + if (typeof(child) !== "string" && typeof(child) !== "function") { + if (align === "sequence") { + curTime = child._startTime + (child.totalDuration() / child._timeScale); + } else if (align === "start") { + child._startTime -= child.delay(); + } + } + curTime += stagger; + } + return this._uncache(true); + } else if (typeof(value) === "string") { + return this.addLabel(value, position); + } else if (typeof(value) === "function") { + value = TweenLite.delayedCall(0, value); + } else { + throw("Cannot add " + value + " into the timeline; it is neither a tween, timeline, function, nor a string."); + } + } + + SimpleTimeline.prototype.add.call(this, value, position); + + //if the timeline has already ended but the inserted tween/timeline extends the duration, we should enable this timeline again so that it renders properly. + if (this._gc) if (!this._paused) if (this._time === this._duration) if (this._time < this.duration()) { + //in case any of the anscestors had completed but should now be enabled... + tl = this; + while (tl._gc && tl._timeline) { + if (tl._timeline.smoothChildTiming) { + tl.totalTime(tl._totalTime, true); //also enables them + } else { + tl._enabled(true, false); + } + tl = tl._timeline; + } + } + + return this; + }; + + p.remove = function(value) { + if (value instanceof Animation) { + return this._remove(value, false); + } else if (value instanceof Array) { + var i = value.length; + while (--i > -1) { + this.remove(value[i]); + } + return this; + } else if (typeof(value) === "string") { + return this.removeLabel(value); + } + return this.kill(null, value); + }; + + p._remove = function(tween, skipDisable) { + SimpleTimeline.prototype._remove.call(this, tween, skipDisable); + if (!this._last) { + this._time = this._totalTime = 0; + } else if (this._time > this._last._startTime) { + this._time = this.duration(); + this._totalTime = this._totalDuration; + } + return this; + }; + + p.append = function(value, offsetOrLabel) { + return this.add(value, this._parseTimeOrLabel(null, offsetOrLabel, true, value)); + }; + + p.insert = p.insertMultiple = function(value, position, align, stagger) { + return this.add(value, position || 0, align, stagger); + }; + + p.appendMultiple = function(tweens, offsetOrLabel, align, stagger) { + return this.add(tweens, this._parseTimeOrLabel(null, offsetOrLabel, true, tweens), align, stagger); + }; + + p.addLabel = function(label, position) { + this._labels[label] = this._parseTimeOrLabel(position); + return this; + }; + + p.removeLabel = function(label) { + delete this._labels[label]; + return this; + }; + + p.getLabelTime = function(label) { + return (this._labels[label] != null) ? this._labels[label] : -1; + }; + + p._parseTimeOrLabel = function(timeOrLabel, offsetOrLabel, appendIfAbsent, ignore) { + var i; + //if we're about to add a tween/timeline (or an array of them) that's already a child of this timeline, we should remove it first so that it doesn't contaminate the duration(). + if (ignore instanceof Animation && ignore.timeline === this) { + this.remove(ignore); + } else if (ignore instanceof Array) { + i = ignore.length; + while (--i > -1) { + if (ignore[i] instanceof Animation && ignore[i].timeline === this) { + this.remove(ignore[i]); + } + } + } + if (typeof(offsetOrLabel) === "string") { + return this._parseTimeOrLabel(offsetOrLabel, (appendIfAbsent && typeof(timeOrLabel) === "number" && this._labels[offsetOrLabel] == null) ? timeOrLabel - this.duration() : 0, appendIfAbsent); + } + offsetOrLabel = offsetOrLabel || 0; + if (typeof(timeOrLabel) === "string" && (isNaN(timeOrLabel) || this._labels[timeOrLabel] != null)) { //if the string is a number like "1", check to see if there's a label with that name, otherwise interpret it as a number (absolute value). + i = timeOrLabel.indexOf("="); + if (i === -1) { + if (this._labels[timeOrLabel] == null) { + return appendIfAbsent ? (this._labels[timeOrLabel] = this.duration() + offsetOrLabel) : offsetOrLabel; + } + return this._labels[timeOrLabel] + offsetOrLabel; + } + offsetOrLabel = parseInt(timeOrLabel.charAt(i-1) + "1", 10) * Number(timeOrLabel.substr(i+1)); + timeOrLabel = (i > 1) ? this._parseTimeOrLabel(timeOrLabel.substr(0, i-1), 0, appendIfAbsent) : this.duration(); + } else if (timeOrLabel == null) { + timeOrLabel = this.duration(); + } + return Number(timeOrLabel) + offsetOrLabel; + }; + + p.seek = function(position, suppressEvents) { + return this.totalTime((typeof(position) === "number") ? position : this._parseTimeOrLabel(position), (suppressEvents !== false)); + }; + + p.stop = function() { + return this.paused(true); + }; + + p.gotoAndPlay = function(position, suppressEvents) { + return this.play(position, suppressEvents); + }; + + p.gotoAndStop = function(position, suppressEvents) { + return this.pause(position, suppressEvents); + }; + + p.render = function(time, suppressEvents, force) { + if (this._gc) { + this._enabled(true, false); + } + this._active = !this._paused; + var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(), + prevTime = this._time, + prevStart = this._startTime, + prevTimeScale = this._timeScale, + prevPaused = this._paused, + tween, isComplete, next, callback, internalForce; + if (time >= totalDur) { + this._totalTime = this._time = totalDur; + if (!this._reversed) if (!this._hasPausedChild()) { + isComplete = true; + callback = "onComplete"; + if (this._duration === 0) if (time === 0 || this._rawPrevTime < 0) if (this._rawPrevTime !== time && this._first) { //In order to accommodate zero-duration timelines, we must discern the momentum/direction of time in order to render values properly when the "playhead" goes past 0 in the forward direction or lands directly on it, and also when it moves past it in the backward direction (from a postitive time to a negative time). + internalForce = true; + if (this._rawPrevTime > 0) { + callback = "onReverseComplete"; + } + } + } + this._rawPrevTime = time; + time = totalDur + 0.000001; //to avoid occasional floating point rounding errors - sometimes child tweens/timelines were not being fully completed (their progress might be 0.999999999999998 instead of 1 because when _time - tween._startTime is performed, floating point errors would return a value that was SLIGHTLY off) + + } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0. + this._totalTime = this._time = 0; + if (prevTime !== 0 || (this._duration === 0 && this._rawPrevTime > 0)) { + callback = "onReverseComplete"; + isComplete = this._reversed; + } + if (time < 0) { + this._active = false; + if (this._duration === 0) if (this._rawPrevTime >= 0 && this._first) { //zero-duration timelines are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered. + internalForce = true; + } + } else if (!this._initted) { + internalForce = true; + } + this._rawPrevTime = time; + time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline) + + } else { + this._totalTime = this._time = this._rawPrevTime = time; + } + if ((this._time === prevTime || !this._first) && !force && !internalForce) { + return; + } else if (!this._initted) { + this._initted = true; + } + if (prevTime === 0) if (this.vars.onStart) if (this._time !== 0) if (!suppressEvents) { + this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray); + } + + if (this._time >= prevTime) { + tween = this._first; + while (tween) { + next = tween._next; //record it here because the value could change after rendering... + if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering + break; + } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) { + + if (!tween._reversed) { + tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force); + } else { + tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force); + } + + } + tween = next; + } + } else { + tween = this._last; + while (tween) { + next = tween._prev; //record it here because the value could change after rendering... + if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering + break; + } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) { + + if (!tween._reversed) { + tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force); + } else { + tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force); + } + + } + tween = next; + } + } + + if (this._onUpdate) if (!suppressEvents) { + this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray); + } + + if (callback) if (!this._gc) if (prevStart === this._startTime || prevTimeScale !== this._timeScale) if (this._time === 0 || totalDur >= this.totalDuration()) { //if one of the tweens that was rendered altered this timeline's startTime (like if an onComplete reversed the timeline), it probably isn't complete. If it is, don't worry, because whatever call altered the startTime would complete if it was necessary at the new time. The only exception is the timeScale property. Also check _gc because there's a chance that kill() could be called in an onUpdate + if (isComplete) { + if (this._timeline.autoRemoveChildren) { + this._enabled(false, false); + } + this._active = false; + } + if (!suppressEvents && this.vars[callback]) { + this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray); + } + } + }; + + p._hasPausedChild = function() { + var tween = this._first; + while (tween) { + if (tween._paused || ((tween instanceof TimelineLite) && tween._hasPausedChild())) { + return true; + } + tween = tween._next; + } + return false; + }; + + p.getChildren = function(nested, tweens, timelines, ignoreBeforeTime) { + ignoreBeforeTime = ignoreBeforeTime || -9999999999; + var a = [], + tween = this._first, + cnt = 0; + while (tween) { + if (tween._startTime < ignoreBeforeTime) { + //do nothing + } else if (tween instanceof TweenLite) { + if (tweens !== false) { + a[cnt++] = tween; + } + } else { + if (timelines !== false) { + a[cnt++] = tween; + } + if (nested !== false) { + a = a.concat(tween.getChildren(true, tweens, timelines)); + cnt = a.length; + } + } + tween = tween._next; + } + return a; + }; + + p.getTweensOf = function(target, nested) { + var tweens = TweenLite.getTweensOf(target), + i = tweens.length, + a = [], + cnt = 0; + while (--i > -1) { + if (tweens[i].timeline === this || (nested && this._contains(tweens[i]))) { + a[cnt++] = tweens[i]; + } + } + return a; + }; + + p._contains = function(tween) { + var tl = tween.timeline; + while (tl) { + if (tl === this) { + return true; + } + tl = tl.timeline; + } + return false; + }; + + p.shiftChildren = function(amount, adjustLabels, ignoreBeforeTime) { + ignoreBeforeTime = ignoreBeforeTime || 0; + var tween = this._first, + labels = this._labels, + p; + while (tween) { + if (tween._startTime >= ignoreBeforeTime) { + tween._startTime += amount; + } + tween = tween._next; + } + if (adjustLabels) { + for (p in labels) { + if (labels[p] >= ignoreBeforeTime) { + labels[p] += amount; + } + } + } + return this._uncache(true); + }; + + p._kill = function(vars, target) { + if (!vars && !target) { + return this._enabled(false, false); + } + var tweens = (!target) ? this.getChildren(true, true, false) : this.getTweensOf(target), + i = tweens.length, + changed = false; + while (--i > -1) { + if (tweens[i]._kill(vars, target)) { + changed = true; + } + } + return changed; + }; + + p.clear = function(labels) { + var tweens = this.getChildren(false, true, true), + i = tweens.length; + this._time = this._totalTime = 0; + while (--i > -1) { + tweens[i]._enabled(false, false); + } + if (labels !== false) { + this._labels = {}; + } + return this._uncache(true); + }; + + p.invalidate = function() { + var tween = this._first; + while (tween) { + tween.invalidate(); + tween = tween._next; + } + return this; + }; + + p._enabled = function(enabled, ignoreTimeline) { + if (enabled === this._gc) { + var tween = this._first; + while (tween) { + tween._enabled(enabled, true); + tween = tween._next; + } + } + return SimpleTimeline.prototype._enabled.call(this, enabled, ignoreTimeline); + }; + + p.progress = function(value) { + return (!arguments.length) ? this._time / this.duration() : this.totalTime(this.duration() * value, false); + }; + + p.duration = function(value) { + if (!arguments.length) { + if (this._dirty) { + this.totalDuration(); //just triggers recalculation + } + return this._duration; + } + if (this.duration() !== 0 && value !== 0) { + this.timeScale(this._duration / value); + } + return this; + }; + + p.totalDuration = function(value) { + if (!arguments.length) { + if (this._dirty) { + var max = 0, + tween = this._last, + prevStart = 999999999999, + prev, end; + while (tween) { + prev = tween._prev; //record it here in case the tween changes position in the sequence... + if (tween._dirty) { + tween.totalDuration(); //could change the tween._startTime, so make sure the tween's cache is clean before analyzing it. + } + if (tween._startTime > prevStart && this._sortChildren && !tween._paused) { //in case one of the tweens shifted out of order, it needs to be re-inserted into the correct position in the sequence + this.add(tween, tween._startTime - tween._delay); + } else { + prevStart = tween._startTime; + } + if (tween._startTime < 0 && !tween._paused) { //children aren't allowed to have negative startTimes unless smoothChildTiming is true, so adjust here if one is found. + max -= tween._startTime; + if (this._timeline.smoothChildTiming) { + this._startTime += tween._startTime / this._timeScale; + } + this.shiftChildren(-tween._startTime, false, -9999999999); + prevStart = 0; + } + end = tween._startTime + (tween._totalDuration / tween._timeScale); + if (end > max) { + max = end; + } + tween = prev; + } + this._duration = this._totalDuration = max; + this._dirty = false; + } + return this._totalDuration; + } + if (this.totalDuration() !== 0) if (value !== 0) { + this.timeScale(this._totalDuration / value); + } + return this; + }; + + p.usesFrames = function() { + var tl = this._timeline; + while (tl._timeline) { + tl = tl._timeline; + } + return (tl === Animation._rootFramesTimeline); + }; + + p.rawTime = function() { + return (this._paused || (this._totalTime !== 0 && this._totalTime !== this._totalDuration)) ? this._totalTime : (this._timeline.rawTime() - this._startTime) * this._timeScale; + }; + + return TimelineLite; + + }, true); + + +}); if (window._gsDefine) { window._gsQueue.pop()(); } \ No newline at end of file diff --git a/js/libs/gsap/TimelineMax.js b/js/libs/gsap/TimelineMax.js new file mode 100644 index 00000000..9c20e673 --- /dev/null +++ b/js/libs/gsap/TimelineMax.js @@ -0,0 +1,1045 @@ +/*! + * VERSION: beta 1.9.8 + * DATE: 2013-06-05 + * UPDATES AND DOCS AT: http://www.greensock.com + * + * @license Copyright (c) 2008-2013, GreenSock. All rights reserved. + * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for + * Club GreenSock members, the software agreement that was issued with your membership. + * + * @author: Jack Doyle, jack@greensock.com + */ + +(window._gsQueue || (window._gsQueue = [])).push( function() { + + window._gsDefine("TimelineMax", ["TimelineLite","TweenLite","easing.Ease"], function(TimelineLite, TweenLite, Ease) { + + var TimelineMax = function(vars) { + TimelineLite.call(this, vars); + this._repeat = this.vars.repeat || 0; + this._repeatDelay = this.vars.repeatDelay || 0; + this._cycle = 0; + this._yoyo = (this.vars.yoyo === true); + this._dirty = true; + }, + _blankArray = [], + _easeNone = new Ease(null, null, 1, 0), + _getGlobalPaused = function(tween) { + while (tween) { + if (tween._paused) { + return true; + } + tween = tween._timeline; + } + return false; + }, + p = TimelineMax.prototype = new TimelineLite(); + + p.constructor = TimelineMax; + p.kill()._gc = false; + TimelineMax.version = "1.9.8"; + + p.invalidate = function() { + this._yoyo = (this.vars.yoyo === true); + this._repeat = this.vars.repeat || 0; + this._repeatDelay = this.vars.repeatDelay || 0; + this._uncache(true); + return TimelineLite.prototype.invalidate.call(this); + }; + + p.addCallback = function(callback, position, params, scope) { + return this.add( TweenLite.delayedCall(0, callback, params, scope), position); + }; + + p.removeCallback = function(callback, position) { + if (callback) { + if (position == null) { + this._kill(null, callback); + } else { + var a = this.getTweensOf(callback, false), + i = a.length, + time = this._parseTimeOrLabel(position); + while (--i > -1) { + if (a[i]._startTime === time) { + a[i]._enabled(false, false); + } + } + } + } + return this; + }; + + p.tweenTo = function(position, vars) { + vars = vars || {}; + var copy = {ease:_easeNone, overwrite:2, useFrames:this.usesFrames(), immediateRender:false}, p, t; + for (p in vars) { + copy[p] = vars[p]; + } + copy.time = this._parseTimeOrLabel(position); + t = new TweenLite(this, (Math.abs(Number(copy.time) - this._time) / this._timeScale) || 0.001, copy); + copy.onStart = function() { + t.target.paused(true); + if (t.vars.time !== t.target.time()) { //don't make the duration zero - if it's supposed to be zero, don't worry because it's already initting the tween and will complete immediately, effectively making the duration zero anyway. If we make duration zero, the tween won't run at all. + t.duration( Math.abs( t.vars.time - t.target.time()) / t.target._timeScale ); + } + if (vars.onStart) { //in case the user had an onStart in the vars - we don't want to overwrite it. + vars.onStart.apply(vars.onStartScope || t, vars.onStartParams || _blankArray); + } + }; + return t; + }; + + p.tweenFromTo = function(fromPosition, toPosition, vars) { + vars = vars || {}; + fromPosition = this._parseTimeOrLabel(fromPosition); + vars.startAt = {onComplete:this.seek, onCompleteParams:[fromPosition], onCompleteScope:this}; + vars.immediateRender = (vars.immediateRender !== false); + var t = this.tweenTo(toPosition, vars); + return t.duration((Math.abs( t.vars.time - fromPosition) / this._timeScale) || 0.001); + }; + + p.render = function(time, suppressEvents, force) { + if (this._gc) { + this._enabled(true, false); + } + this._active = !this._paused; + var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(), + dur = this._duration, + prevTime = this._time, + prevTotalTime = this._totalTime, + prevStart = this._startTime, + prevTimeScale = this._timeScale, + prevRawPrevTime = this._rawPrevTime, + prevPaused = this._paused, + prevCycle = this._cycle, + tween, isComplete, next, callback, internalForce, cycleDuration; + if (time >= totalDur) { + if (!this._locked) { + this._totalTime = totalDur; + this._cycle = this._repeat; + } + if (!this._reversed) if (!this._hasPausedChild()) { + isComplete = true; + callback = "onComplete"; + if (dur === 0) if (time === 0 || this._rawPrevTime < 0) if (this._rawPrevTime !== time && this._first) { //In order to accommodate zero-duration timelines, we must discern the momentum/direction of time in order to render values properly when the "playhead" goes past 0 in the forward direction or lands directly on it, and also when it moves past it in the backward direction (from a postitive time to a negative time). + internalForce = true; + if (this._rawPrevTime > 0) { + callback = "onReverseComplete"; + } + } + } + this._rawPrevTime = time; + if (this._yoyo && (this._cycle & 1) !== 0) { + this._time = time = 0; + } else { + this._time = dur; + time = dur + 0.000001; //to avoid occasional floating point rounding errors + } + + } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0. + if (!this._locked) { + this._totalTime = this._cycle = 0; + } + this._time = 0; + if (prevTime !== 0 || (dur === 0 && this._rawPrevTime > 0 && !this._locked)) { + callback = "onReverseComplete"; + isComplete = this._reversed; + } + if (time < 0) { + this._active = false; + if (dur === 0) if (this._rawPrevTime >= 0 && this._first) { //zero-duration timelines are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered. + internalForce = true; + } + } else if (!this._initted) { + internalForce = true; + } + this._rawPrevTime = time; + time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline) + + } else { + this._time = this._rawPrevTime = time; + if (!this._locked) { + this._totalTime = time; + if (this._repeat !== 0) { + cycleDuration = dur + this._repeatDelay; + this._cycle = (this._totalTime / cycleDuration) >> 0; //originally _totalTime % cycleDuration but floating point errors caused problems, so I normalized it. (4 % 0.8 should be 0 but it gets reported as 0.79999999!) + if (this._cycle !== 0) if (this._cycle === this._totalTime / cycleDuration) { + this._cycle--; //otherwise when rendered exactly at the end time, it will act as though it is repeating (at the beginning) + } + this._time = this._totalTime - (this._cycle * cycleDuration); + if (this._yoyo) if ((this._cycle & 1) !== 0) { + this._time = dur - this._time; + } + if (this._time > dur) { + this._time = dur; + time = dur + 0.000001; //to avoid occasional floating point rounding error + } else if (this._time < 0) { + this._time = time = 0; + } else { + time = this._time; + } + } + } + } + + if (this._cycle !== prevCycle) if (!this._locked) { + /* + make sure children at the end/beginning of the timeline are rendered properly. If, for example, + a 3-second long timeline rendered at 2.9 seconds previously, and now renders at 3.2 seconds (which + would get transated to 2.8 seconds if the timeline yoyos or 0.2 seconds if it just repeats), there + could be a callback or a short tween that's at 2.95 or 3 seconds in which wouldn't render. So + we need to push the timeline to the end (and/or beginning depending on its yoyo value). Also we must + ensure that zero-duration tweens at the very beginning or end of the TimelineMax work. + */ + var backwards = (this._yoyo && (prevCycle & 1) !== 0), + wrap = (backwards === (this._yoyo && (this._cycle & 1) !== 0)), + recTotalTime = this._totalTime, + recCycle = this._cycle, + recRawPrevTime = this._rawPrevTime, + recTime = this._time; + + this._totalTime = prevCycle * dur; + if (this._cycle < prevCycle) { + backwards = !backwards; + } else { + this._totalTime += dur; + } + this._time = prevTime; //temporarily revert _time so that render() renders the children in the correct order. Without this, tweens won't rewind correctly. We could arhictect things in a "cleaner" way by splitting out the rendering queue into a separate method but for performance reasons, we kept it all inside this method. + + this._rawPrevTime = (dur === 0) ? prevRawPrevTime - 0.00001 : prevRawPrevTime; + this._cycle = prevCycle; + this._locked = true; //prevents changes to totalTime and skips repeat/yoyo behavior when we recursively call render() + prevTime = (backwards) ? 0 : dur; + this.render(prevTime, suppressEvents, (dur === 0)); + if (!suppressEvents) if (!this._gc) { + if (this.vars.onRepeat) { + this.vars.onRepeat.apply(this.vars.onRepeatScope || this, this.vars.onRepeatParams || _blankArray); + } + } + if (wrap) { + prevTime = (backwards) ? dur + 0.000001 : -0.000001; + this.render(prevTime, true, false); + } + this._locked = false; + if (this._paused && !prevPaused) { //if the render() triggered callback that paused this timeline, we should abort (very rare, but possible) + return; + } + this._time = recTime; + this._totalTime = recTotalTime; + this._cycle = recCycle; + this._rawPrevTime = recRawPrevTime; + } + + if ((this._time === prevTime || !this._first) && !force && !internalForce) { + if (prevTotalTime !== this._totalTime) if (this._onUpdate) if (!suppressEvents) { //so that onUpdate fires even during the repeatDelay - as long as the totalTime changed, we should trigger onUpdate. + this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray); + } + return; + } else if (!this._initted) { + this._initted = true; + } + + if (prevTotalTime === 0) if (this.vars.onStart) if (this._totalTime !== 0) if (!suppressEvents) { + this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray); + } + + if (this._time >= prevTime) { + tween = this._first; + while (tween) { + next = tween._next; //record it here because the value could change after rendering... + if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering + break; + } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) { + if (!tween._reversed) { + tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force); + } else { + tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force); + } + + } + tween = next; + } + } else { + tween = this._last; + while (tween) { + next = tween._prev; //record it here because the value could change after rendering... + if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering + break; + } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) { + if (!tween._reversed) { + tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force); + } else { + tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force); + } + + } + tween = next; + } + } + + if (this._onUpdate) if (!suppressEvents) { + this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray); + } + if (callback) if (!this._locked) if (!this._gc) if (prevStart === this._startTime || prevTimeScale !== this._timeScale) if (this._time === 0 || totalDur >= this.totalDuration()) { //if one of the tweens that was rendered altered this timeline's startTime (like if an onComplete reversed the timeline), it probably isn't complete. If it is, don't worry, because whatever call altered the startTime would complete if it was necessary at the new time. The only exception is the timeScale property. Also check _gc because there's a chance that kill() could be called in an onUpdate + if (isComplete) { + if (this._timeline.autoRemoveChildren) { + this._enabled(false, false); + } + this._active = false; + } + if (!suppressEvents && this.vars[callback]) { + this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray); + } + } + }; + + p.getActive = function(nested, tweens, timelines) { + if (nested == null) { + nested = true; + } + if (tweens == null) { + tweens = true; + } + if (timelines == null) { + timelines = false; + } + var a = [], + all = this.getChildren(nested, tweens, timelines), + cnt = 0, + l = all.length, + i, tween; + for (i = 0; i < l; i++) { + tween = all[i]; + //note: we cannot just check tween.active because timelines that contain paused children will continue to have "active" set to true even after the playhead passes their end point (technically a timeline can only be considered complete after all of its children have completed too, but paused tweens are...well...just waiting and until they're unpaused we don't know where their end point will be). + if (!tween._paused) if (tween._timeline._time >= tween._startTime) if (tween._timeline._time < tween._startTime + tween._totalDuration / tween._timeScale) if (!_getGlobalPaused(tween._timeline)) { + a[cnt++] = tween; + } + } + return a; + }; + + + p.getLabelAfter = function(time) { + if (!time) if (time !== 0) { //faster than isNan() + time = this._time; + } + var labels = this.getLabelsArray(), + l = labels.length, + i; + for (i = 0; i < l; i++) { + if (labels[i].time > time) { + return labels[i].name; + } + } + return null; + }; + + p.getLabelBefore = function(time) { + if (time == null) { + time = this._time; + } + var labels = this.getLabelsArray(), + i = labels.length; + while (--i > -1) { + if (labels[i].time < time) { + return labels[i].name; + } + } + return null; + }; + + p.getLabelsArray = function() { + var a = [], + cnt = 0, + p; + for (p in this._labels) { + a[cnt++] = {time:this._labels[p], name:p}; + } + a.sort(function(a,b) { + return a.time - b.time; + }); + return a; + }; + + +//---- GETTERS / SETTERS ------------------------------------------------------------------------------------------------------- + + p.progress = function(value) { + return (!arguments.length) ? this._time / this.duration() : this.totalTime( this.duration() * ((this._yoyo && (this._cycle & 1) !== 0) ? 1 - value : value) + (this._cycle * (this._duration + this._repeatDelay)), false); + }; + + p.totalProgress = function(value) { + return (!arguments.length) ? this._totalTime / this.totalDuration() : this.totalTime( this.totalDuration() * value, false); + }; + + p.totalDuration = function(value) { + if (!arguments.length) { + if (this._dirty) { + TimelineLite.prototype.totalDuration.call(this); //just forces refresh + //Instead of Infinity, we use 999999999999 so that we can accommodate reverses. + this._totalDuration = (this._repeat === -1) ? 999999999999 : this._duration * (this._repeat + 1) + (this._repeatDelay * this._repeat); + } + return this._totalDuration; + } + return (this._repeat === -1) ? this : this.duration( (value - (this._repeat * this._repeatDelay)) / (this._repeat + 1) ); + }; + + p.time = function(value, suppressEvents) { + if (!arguments.length) { + return this._time; + } + if (this._dirty) { + this.totalDuration(); + } + if (value > this._duration) { + value = this._duration; + } + if (this._yoyo && (this._cycle & 1) !== 0) { + value = (this._duration - value) + (this._cycle * (this._duration + this._repeatDelay)); + } else if (this._repeat !== 0) { + value += this._cycle * (this._duration + this._repeatDelay); + } + return this.totalTime(value, suppressEvents); + }; + + p.repeat = function(value) { + if (!arguments.length) { + return this._repeat; + } + this._repeat = value; + return this._uncache(true); + }; + + p.repeatDelay = function(value) { + if (!arguments.length) { + return this._repeatDelay; + } + this._repeatDelay = value; + return this._uncache(true); + }; + + p.yoyo = function(value) { + if (!arguments.length) { + return this._yoyo; + } + this._yoyo = value; + return this; + }; + + p.currentLabel = function(value) { + if (!arguments.length) { + return this.getLabelBefore(this._time + 0.00000001); + } + return this.seek(value, true); + }; + + return TimelineMax; + + }, true); + + + + + + + +/* + * ---------------------------------------------------------------- + * TimelineLite + * ---------------------------------------------------------------- + */ + + window._gsDefine("TimelineLite", ["core.Animation","core.SimpleTimeline","TweenLite"], function(Animation, SimpleTimeline, TweenLite) { + + var TimelineLite = function(vars) { + SimpleTimeline.call(this, vars); + this._labels = {}; + this.autoRemoveChildren = (this.vars.autoRemoveChildren === true); + this.smoothChildTiming = (this.vars.smoothChildTiming === true); + this._sortChildren = true; + this._onUpdate = this.vars.onUpdate; + var v = this.vars, + i = _paramProps.length, + j, a; + while (--i > -1) { + a = v[_paramProps[i]]; + if (a) { + j = a.length; + while (--j > -1) { + if (a[j] === "{self}") { + a = v[_paramProps[i]] = a.concat(); //copy the array in case the user referenced the same array in multiple timelines/tweens (each {self} should be unique) + a[j] = this; + } + } + } + } + if (v.tweens instanceof Array) { + this.add(v.tweens, 0, v.align, v.stagger); + } + }, + _paramProps = ["onStartParams","onUpdateParams","onCompleteParams","onReverseCompleteParams","onRepeatParams"], + _blankArray = [], + _copy = function(vars) { + var copy = {}, p; + for (p in vars) { + copy[p] = vars[p]; + } + return copy; + }, + _slice = _blankArray.slice, + p = TimelineLite.prototype = new SimpleTimeline(); + + TimelineLite.version = "1.9.8"; + p.constructor = TimelineLite; + p.kill()._gc = false; + + p.to = function(target, duration, vars, position) { + return duration ? this.add( new TweenLite(target, duration, vars), position) : this.set(target, vars, position); + }; + + p.from = function(target, duration, vars, position) { + return this.add( TweenLite.from(target, duration, vars), position); + }; + + p.fromTo = function(target, duration, fromVars, toVars, position) { + return duration ? this.add( TweenLite.fromTo(target, duration, fromVars, toVars), position) : this.set(target, toVars, position); + }; + + p.staggerTo = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) { + var tl = new TimelineLite({onComplete:onCompleteAll, onCompleteParams:onCompleteAllParams, onCompleteScope:onCompleteAllScope}), + i; + if (typeof(targets) === "string") { + targets = TweenLite.selector(targets) || targets; + } + if (!(targets instanceof Array) && targets.length && targets[0] && targets[0].nodeType && targets[0].style) { //senses if the targets object is a selector. If it is, we should translate it into an array. + targets = _slice.call(targets, 0); + } + stagger = stagger || 0; + for (i = 0; i < targets.length; i++) { + if (vars.startAt) { + vars.startAt = _copy(vars.startAt); + } + tl.to(targets[i], duration, _copy(vars), i * stagger); + } + return this.add(tl, position); + }; + + p.staggerFrom = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) { + vars.immediateRender = (vars.immediateRender != false); + vars.runBackwards = true; + return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope); + }; + + p.staggerFromTo = function(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) { + toVars.startAt = fromVars; + toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false); + return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope); + }; + + p.call = function(callback, params, scope, position) { + return this.add( TweenLite.delayedCall(0, callback, params, scope), position); + }; + + p.set = function(target, vars, position) { + position = this._parseTimeOrLabel(position, 0, true); + if (vars.immediateRender == null) { + vars.immediateRender = (position === this._time && !this._paused); + } + return this.add( new TweenLite(target, 0, vars), position); + }; + + TimelineLite.exportRoot = function(vars, ignoreDelayedCalls) { + vars = vars || {}; + if (vars.smoothChildTiming == null) { + vars.smoothChildTiming = true; + } + var tl = new TimelineLite(vars), + root = tl._timeline, + tween, next; + if (ignoreDelayedCalls == null) { + ignoreDelayedCalls = true; + } + root._remove(tl, true); + tl._startTime = 0; + tl._rawPrevTime = tl._time = tl._totalTime = root._time; + tween = root._first; + while (tween) { + next = tween._next; + if (!ignoreDelayedCalls || !(tween instanceof TweenLite && tween.target === tween.vars.onComplete)) { + tl.add(tween, tween._startTime - tween._delay); + } + tween = next; + } + root.add(tl, 0); + return tl; + }; + + p.add = function(value, position, align, stagger) { + var curTime, l, i, child, tl; + if (typeof(position) !== "number") { + position = this._parseTimeOrLabel(position, 0, true, value); + } + if (!(value instanceof Animation)) { + if (value instanceof Array) { + align = align || "normal"; + stagger = stagger || 0; + curTime = position; + l = value.length; + for (i = 0; i < l; i++) { + if ((child = value[i]) instanceof Array) { + child = new TimelineLite({tweens:child}); + } + this.add(child, curTime); + if (typeof(child) !== "string" && typeof(child) !== "function") { + if (align === "sequence") { + curTime = child._startTime + (child.totalDuration() / child._timeScale); + } else if (align === "start") { + child._startTime -= child.delay(); + } + } + curTime += stagger; + } + return this._uncache(true); + } else if (typeof(value) === "string") { + return this.addLabel(value, position); + } else if (typeof(value) === "function") { + value = TweenLite.delayedCall(0, value); + } else { + throw("Cannot add " + value + " into the timeline; it is neither a tween, timeline, function, nor a string."); + } + } + + SimpleTimeline.prototype.add.call(this, value, position); + + //if the timeline has already ended but the inserted tween/timeline extends the duration, we should enable this timeline again so that it renders properly. + if (this._gc) if (!this._paused) if (this._time === this._duration) if (this._time < this.duration()) { + //in case any of the anscestors had completed but should now be enabled... + tl = this; + while (tl._gc && tl._timeline) { + if (tl._timeline.smoothChildTiming) { + tl.totalTime(tl._totalTime, true); //also enables them + } else { + tl._enabled(true, false); + } + tl = tl._timeline; + } + } + + return this; + }; + + p.remove = function(value) { + if (value instanceof Animation) { + return this._remove(value, false); + } else if (value instanceof Array) { + var i = value.length; + while (--i > -1) { + this.remove(value[i]); + } + return this; + } else if (typeof(value) === "string") { + return this.removeLabel(value); + } + return this.kill(null, value); + }; + + p._remove = function(tween, skipDisable) { + SimpleTimeline.prototype._remove.call(this, tween, skipDisable); + if (!this._last) { + this._time = this._totalTime = 0; + } else if (this._time > this._last._startTime) { + this._time = this.duration(); + this._totalTime = this._totalDuration; + } + return this; + }; + + p.append = function(value, offsetOrLabel) { + return this.add(value, this._parseTimeOrLabel(null, offsetOrLabel, true, value)); + }; + + p.insert = p.insertMultiple = function(value, position, align, stagger) { + return this.add(value, position || 0, align, stagger); + }; + + p.appendMultiple = function(tweens, offsetOrLabel, align, stagger) { + return this.add(tweens, this._parseTimeOrLabel(null, offsetOrLabel, true, tweens), align, stagger); + }; + + p.addLabel = function(label, position) { + this._labels[label] = this._parseTimeOrLabel(position); + return this; + }; + + p.removeLabel = function(label) { + delete this._labels[label]; + return this; + }; + + p.getLabelTime = function(label) { + return (this._labels[label] != null) ? this._labels[label] : -1; + }; + + p._parseTimeOrLabel = function(timeOrLabel, offsetOrLabel, appendIfAbsent, ignore) { + var i; + //if we're about to add a tween/timeline (or an array of them) that's already a child of this timeline, we should remove it first so that it doesn't contaminate the duration(). + if (ignore instanceof Animation && ignore.timeline === this) { + this.remove(ignore); + } else if (ignore instanceof Array) { + i = ignore.length; + while (--i > -1) { + if (ignore[i] instanceof Animation && ignore[i].timeline === this) { + this.remove(ignore[i]); + } + } + } + if (typeof(offsetOrLabel) === "string") { + return this._parseTimeOrLabel(offsetOrLabel, (appendIfAbsent && typeof(timeOrLabel) === "number" && this._labels[offsetOrLabel] == null) ? timeOrLabel - this.duration() : 0, appendIfAbsent); + } + offsetOrLabel = offsetOrLabel || 0; + if (typeof(timeOrLabel) === "string" && (isNaN(timeOrLabel) || this._labels[timeOrLabel] != null)) { //if the string is a number like "1", check to see if there's a label with that name, otherwise interpret it as a number (absolute value). + i = timeOrLabel.indexOf("="); + if (i === -1) { + if (this._labels[timeOrLabel] == null) { + return appendIfAbsent ? (this._labels[timeOrLabel] = this.duration() + offsetOrLabel) : offsetOrLabel; + } + return this._labels[timeOrLabel] + offsetOrLabel; + } + offsetOrLabel = parseInt(timeOrLabel.charAt(i-1) + "1", 10) * Number(timeOrLabel.substr(i+1)); + timeOrLabel = (i > 1) ? this._parseTimeOrLabel(timeOrLabel.substr(0, i-1), 0, appendIfAbsent) : this.duration(); + } else if (timeOrLabel == null) { + timeOrLabel = this.duration(); + } + return Number(timeOrLabel) + offsetOrLabel; + }; + + p.seek = function(position, suppressEvents) { + return this.totalTime((typeof(position) === "number") ? position : this._parseTimeOrLabel(position), (suppressEvents !== false)); + }; + + p.stop = function() { + return this.paused(true); + }; + + p.gotoAndPlay = function(position, suppressEvents) { + return this.play(position, suppressEvents); + }; + + p.gotoAndStop = function(position, suppressEvents) { + return this.pause(position, suppressEvents); + }; + + p.render = function(time, suppressEvents, force) { + if (this._gc) { + this._enabled(true, false); + } + this._active = !this._paused; + var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(), + prevTime = this._time, + prevStart = this._startTime, + prevTimeScale = this._timeScale, + prevPaused = this._paused, + tween, isComplete, next, callback, internalForce; + if (time >= totalDur) { + this._totalTime = this._time = totalDur; + if (!this._reversed) if (!this._hasPausedChild()) { + isComplete = true; + callback = "onComplete"; + if (this._duration === 0) if (time === 0 || this._rawPrevTime < 0) if (this._rawPrevTime !== time && this._first) { //In order to accommodate zero-duration timelines, we must discern the momentum/direction of time in order to render values properly when the "playhead" goes past 0 in the forward direction or lands directly on it, and also when it moves past it in the backward direction (from a postitive time to a negative time). + internalForce = true; + if (this._rawPrevTime > 0) { + callback = "onReverseComplete"; + } + } + } + this._rawPrevTime = time; + time = totalDur + 0.000001; //to avoid occasional floating point rounding errors - sometimes child tweens/timelines were not being fully completed (their progress might be 0.999999999999998 instead of 1 because when _time - tween._startTime is performed, floating point errors would return a value that was SLIGHTLY off) + + } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0. + this._totalTime = this._time = 0; + if (prevTime !== 0 || (this._duration === 0 && this._rawPrevTime > 0)) { + callback = "onReverseComplete"; + isComplete = this._reversed; + } + if (time < 0) { + this._active = false; + if (this._duration === 0) if (this._rawPrevTime >= 0 && this._first) { //zero-duration timelines are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered. + internalForce = true; + } + } else if (!this._initted) { + internalForce = true; + } + this._rawPrevTime = time; + time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline) + + } else { + this._totalTime = this._time = this._rawPrevTime = time; + } + if ((this._time === prevTime || !this._first) && !force && !internalForce) { + return; + } else if (!this._initted) { + this._initted = true; + } + if (prevTime === 0) if (this.vars.onStart) if (this._time !== 0) if (!suppressEvents) { + this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray); + } + + if (this._time >= prevTime) { + tween = this._first; + while (tween) { + next = tween._next; //record it here because the value could change after rendering... + if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering + break; + } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) { + + if (!tween._reversed) { + tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force); + } else { + tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force); + } + + } + tween = next; + } + } else { + tween = this._last; + while (tween) { + next = tween._prev; //record it here because the value could change after rendering... + if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering + break; + } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) { + + if (!tween._reversed) { + tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force); + } else { + tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force); + } + + } + tween = next; + } + } + + if (this._onUpdate) if (!suppressEvents) { + this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray); + } + + if (callback) if (!this._gc) if (prevStart === this._startTime || prevTimeScale !== this._timeScale) if (this._time === 0 || totalDur >= this.totalDuration()) { //if one of the tweens that was rendered altered this timeline's startTime (like if an onComplete reversed the timeline), it probably isn't complete. If it is, don't worry, because whatever call altered the startTime would complete if it was necessary at the new time. The only exception is the timeScale property. Also check _gc because there's a chance that kill() could be called in an onUpdate + if (isComplete) { + if (this._timeline.autoRemoveChildren) { + this._enabled(false, false); + } + this._active = false; + } + if (!suppressEvents && this.vars[callback]) { + this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray); + } + } + }; + + p._hasPausedChild = function() { + var tween = this._first; + while (tween) { + if (tween._paused || ((tween instanceof TimelineLite) && tween._hasPausedChild())) { + return true; + } + tween = tween._next; + } + return false; + }; + + p.getChildren = function(nested, tweens, timelines, ignoreBeforeTime) { + ignoreBeforeTime = ignoreBeforeTime || -9999999999; + var a = [], + tween = this._first, + cnt = 0; + while (tween) { + if (tween._startTime < ignoreBeforeTime) { + //do nothing + } else if (tween instanceof TweenLite) { + if (tweens !== false) { + a[cnt++] = tween; + } + } else { + if (timelines !== false) { + a[cnt++] = tween; + } + if (nested !== false) { + a = a.concat(tween.getChildren(true, tweens, timelines)); + cnt = a.length; + } + } + tween = tween._next; + } + return a; + }; + + p.getTweensOf = function(target, nested) { + var tweens = TweenLite.getTweensOf(target), + i = tweens.length, + a = [], + cnt = 0; + while (--i > -1) { + if (tweens[i].timeline === this || (nested && this._contains(tweens[i]))) { + a[cnt++] = tweens[i]; + } + } + return a; + }; + + p._contains = function(tween) { + var tl = tween.timeline; + while (tl) { + if (tl === this) { + return true; + } + tl = tl.timeline; + } + return false; + }; + + p.shiftChildren = function(amount, adjustLabels, ignoreBeforeTime) { + ignoreBeforeTime = ignoreBeforeTime || 0; + var tween = this._first, + labels = this._labels, + p; + while (tween) { + if (tween._startTime >= ignoreBeforeTime) { + tween._startTime += amount; + } + tween = tween._next; + } + if (adjustLabels) { + for (p in labels) { + if (labels[p] >= ignoreBeforeTime) { + labels[p] += amount; + } + } + } + return this._uncache(true); + }; + + p._kill = function(vars, target) { + if (!vars && !target) { + return this._enabled(false, false); + } + var tweens = (!target) ? this.getChildren(true, true, false) : this.getTweensOf(target), + i = tweens.length, + changed = false; + while (--i > -1) { + if (tweens[i]._kill(vars, target)) { + changed = true; + } + } + return changed; + }; + + p.clear = function(labels) { + var tweens = this.getChildren(false, true, true), + i = tweens.length; + this._time = this._totalTime = 0; + while (--i > -1) { + tweens[i]._enabled(false, false); + } + if (labels !== false) { + this._labels = {}; + } + return this._uncache(true); + }; + + p.invalidate = function() { + var tween = this._first; + while (tween) { + tween.invalidate(); + tween = tween._next; + } + return this; + }; + + p._enabled = function(enabled, ignoreTimeline) { + if (enabled === this._gc) { + var tween = this._first; + while (tween) { + tween._enabled(enabled, true); + tween = tween._next; + } + } + return SimpleTimeline.prototype._enabled.call(this, enabled, ignoreTimeline); + }; + + p.progress = function(value) { + return (!arguments.length) ? this._time / this.duration() : this.totalTime(this.duration() * value, false); + }; + + p.duration = function(value) { + if (!arguments.length) { + if (this._dirty) { + this.totalDuration(); //just triggers recalculation + } + return this._duration; + } + if (this.duration() !== 0 && value !== 0) { + this.timeScale(this._duration / value); + } + return this; + }; + + p.totalDuration = function(value) { + if (!arguments.length) { + if (this._dirty) { + var max = 0, + tween = this._last, + prevStart = 999999999999, + prev, end; + while (tween) { + prev = tween._prev; //record it here in case the tween changes position in the sequence... + if (tween._dirty) { + tween.totalDuration(); //could change the tween._startTime, so make sure the tween's cache is clean before analyzing it. + } + if (tween._startTime > prevStart && this._sortChildren && !tween._paused) { //in case one of the tweens shifted out of order, it needs to be re-inserted into the correct position in the sequence + this.add(tween, tween._startTime - tween._delay); + } else { + prevStart = tween._startTime; + } + if (tween._startTime < 0 && !tween._paused) { //children aren't allowed to have negative startTimes unless smoothChildTiming is true, so adjust here if one is found. + max -= tween._startTime; + if (this._timeline.smoothChildTiming) { + this._startTime += tween._startTime / this._timeScale; + } + this.shiftChildren(-tween._startTime, false, -9999999999); + prevStart = 0; + } + end = tween._startTime + (tween._totalDuration / tween._timeScale); + if (end > max) { + max = end; + } + tween = prev; + } + this._duration = this._totalDuration = max; + this._dirty = false; + } + return this._totalDuration; + } + if (this.totalDuration() !== 0) if (value !== 0) { + this.timeScale(this._totalDuration / value); + } + return this; + }; + + p.usesFrames = function() { + var tl = this._timeline; + while (tl._timeline) { + tl = tl._timeline; + } + return (tl === Animation._rootFramesTimeline); + }; + + p.rawTime = function() { + return (this._paused || (this._totalTime !== 0 && this._totalTime !== this._totalDuration)) ? this._totalTime : (this._timeline.rawTime() - this._startTime) * this._timeScale; + }; + + return TimelineLite; + + }, true); + +}); if (window._gsDefine) { window._gsQueue.pop()(); } \ No newline at end of file diff --git a/js/libs/gsap/TweenLite.js b/js/libs/gsap/TweenLite.js new file mode 100644 index 00000000..cbab8978 --- /dev/null +++ b/js/libs/gsap/TweenLite.js @@ -0,0 +1,1604 @@ +/*! + * VERSION: beta 1.9.8 + * DATE: 2013-06-05 + * UPDATES AND DOCS AT: http://www.greensock.com + * + * @license Copyright (c) 2008-2013, GreenSock. All rights reserved. + * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for + * Club GreenSock members, the software agreement that was issued with your membership. + * + * @author: Jack Doyle, jack@greensock.com + */ +(function(window) { + + "use strict"; + var _globals = window.GreenSockGlobals || window, + _namespace = function(ns) { + var a = ns.split("."), + p = _globals, i; + for (i = 0; i < a.length; i++) { + p[a[i]] = p = p[a[i]] || {}; + } + return p; + }, + gs = _namespace("com.greensock"), + _slice = [].slice, + _emptyFunc = function() {}, + a, i, p, _ticker, _tickerActive, + _defLookup = {}, + + /** + * @constructor + * Defines a GreenSock class, optionally with an array of dependencies that must be instantiated first and passed into the definition. + * This allows users to load GreenSock JS files in any order even if they have interdependencies (like CSSPlugin extends TweenPlugin which is + * inside TweenLite.js, but if CSSPlugin is loaded first, it should wait to run its code until TweenLite.js loads and instantiates TweenPlugin + * and then pass TweenPlugin to CSSPlugin's definition). This is all done automatically and internally. + * + * Every definition will be added to a "com.greensock" global object (typically window, but if a window.GreenSockGlobals object is found, + * it will go there as of v1.7). For example, TweenLite will be found at window.com.greensock.TweenLite and since it's a global class that should be available anywhere, + * it is ALSO referenced at window.TweenLite. However some classes aren't considered global, like the base com.greensock.core.Animation class, so + * those will only be at the package like window.com.greensock.core.Animation. Again, if you define a GreenSockGlobals object on the window, everything + * gets tucked neatly inside there instead of on the window directly. This allows you to do advanced things like load multiple versions of GreenSock + * files and put them into distinct objects (imagine a banner ad uses a newer version but the main site uses an older one). In that case, you could + * sandbox the banner one like: + * + * + * + * + * + * + * + * @param {!string} ns The namespace of the class definition, leaving off "com.greensock." as that's assumed. For example, "TweenLite" or "plugins.CSSPlugin" or "easing.Back". + * @param {!Array.} dependencies An array of dependencies (described as their namespaces minus "com.greensock." prefix). For example ["TweenLite","plugins.TweenPlugin","core.Animation"] + * @param {!function():Object} func The function that should be called and passed the resolved dependencies which will return the actual class for this definition. + * @param {boolean=} global If true, the class will be added to the global scope (typically window unless you define a window.GreenSockGlobals object) + */ + Definition = function(ns, dependencies, func, global) { + this.sc = (_defLookup[ns]) ? _defLookup[ns].sc : []; //subclasses + _defLookup[ns] = this; + this.gsClass = null; + this.func = func; + var _classes = []; + this.check = function(init) { + var i = dependencies.length, + missing = i, + cur, a, n, cl; + while (--i > -1) { + if ((cur = _defLookup[dependencies[i]] || new Definition(dependencies[i], [])).gsClass) { + _classes[i] = cur.gsClass; + missing--; + } else if (init) { + cur.sc.push(this); + } + } + if (missing === 0 && func) { + a = ("com.greensock." + ns).split("."); + n = a.pop(); + cl = _namespace(a.join("."))[n] = this.gsClass = func.apply(func, _classes); + + //exports to multiple environments + if (global) { + _globals[n] = cl; //provides a way to avoid global namespace pollution. By default, the main classes like TweenLite, Power1, Strong, etc. are added to window unless a GreenSockGlobals is defined. So if you want to have things added to a custom object instead, just do something like window.GreenSockGlobals = {} before loading any GreenSock files. You can even set up an alias like window.GreenSockGlobals = windows.gs = {} so that you can access everything like gs.TweenLite. Also remember that ALL classes are added to the window.com.greensock object (in their respective packages, like com.greensock.easing.Power1, com.greensock.TweenLite, etc.) + if (typeof(define) === "function" && define.amd){ //AMD + define((window.GreenSockAMDPath ? window.GreenSockAMDPath + "/" : "") + ns.split(".").join("/"), [], function() { return cl; }); + } else if (typeof(module) !== "undefined" && module.exports){ //node + module.exports = cl; + } + } + for (i = 0; i < this.sc.length; i++) { + this.sc[i].check(); + } + } + }; + this.check(true); + }, + + //used to create Definition instances (which basically registers a class that has dependencies). + _gsDefine = window._gsDefine = function(ns, dependencies, func, global) { + return new Definition(ns, dependencies, func, global); + }, + + //a quick way to create a class that doesn't have any dependencies. Returns the class, but first registers it in the GreenSock namespace so that other classes can grab it (other classes might be dependent on the class). + _class = gs._class = function(ns, func, global) { + func = func || function() {}; + _gsDefine(ns, [], function(){ return func; }, global); + return func; + }; + + _gsDefine.globals = _globals; + + + +/* + * ---------------------------------------------------------------- + * Ease + * ---------------------------------------------------------------- + */ + var _baseParams = [0, 0, 1, 1], + _blankArray = [], + Ease = _class("easing.Ease", function(func, extraParams, type, power) { + this._func = func; + this._type = type || 0; + this._power = power || 0; + this._params = extraParams ? _baseParams.concat(extraParams) : _baseParams; + }, true), + _easeMap = Ease.map = {}, + _easeReg = Ease.register = function(ease, names, types, create) { + var na = names.split(","), + i = na.length, + ta = (types || "easeIn,easeOut,easeInOut").split(","), + e, name, j, type; + while (--i > -1) { + name = na[i]; + e = create ? _class("easing."+name, null, true) : gs.easing[name] || {}; + j = ta.length; + while (--j > -1) { + type = ta[j]; + _easeMap[name + "." + type] = _easeMap[type + name] = e[type] = ease.getRatio ? ease : ease[type] || new ease(); + } + } + }; + + p = Ease.prototype; + p._calcEnd = false; + p.getRatio = function(p) { + if (this._func) { + this._params[0] = p; + return this._func.apply(null, this._params); + } + var t = this._type, + pw = this._power, + r = (t === 1) ? 1 - p : (t === 2) ? p : (p < 0.5) ? p * 2 : (1 - p) * 2; + if (pw === 1) { + r *= r; + } else if (pw === 2) { + r *= r * r; + } else if (pw === 3) { + r *= r * r * r; + } else if (pw === 4) { + r *= r * r * r * r; + } + return (t === 1) ? 1 - r : (t === 2) ? r : (p < 0.5) ? r / 2 : 1 - (r / 2); + }; + + //create all the standard eases like Linear, Quad, Cubic, Quart, Quint, Strong, Power0, Power1, Power2, Power3, and Power4 (each with easeIn, easeOut, and easeInOut) + a = ["Linear","Quad","Cubic","Quart","Quint,Strong"]; + i = a.length; + while (--i > -1) { + p = a[i]+",Power"+i; + _easeReg(new Ease(null,null,1,i), p, "easeOut", true); + _easeReg(new Ease(null,null,2,i), p, "easeIn" + ((i === 0) ? ",easeNone" : "")); + _easeReg(new Ease(null,null,3,i), p, "easeInOut"); + } + _easeMap.linear = gs.easing.Linear.easeIn; + _easeMap.swing = gs.easing.Quad.easeInOut; //for jQuery folks + + +/* + * ---------------------------------------------------------------- + * EventDispatcher + * ---------------------------------------------------------------- + */ + var EventDispatcher = _class("events.EventDispatcher", function(target) { + this._listeners = {}; + this._eventTarget = target || this; + }); + p = EventDispatcher.prototype; + + p.addEventListener = function(type, callback, scope, useParam, priority) { + priority = priority || 0; + var list = this._listeners[type], + index = 0, + listener, i; + if (list == null) { + this._listeners[type] = list = []; + } + i = list.length; + while (--i > -1) { + listener = list[i]; + if (listener.c === callback && listener.s === scope) { + list.splice(i, 1); + } else if (index === 0 && listener.pr < priority) { + index = i + 1; + } + } + list.splice(index, 0, {c:callback, s:scope, up:useParam, pr:priority}); + if (this === _ticker && !_tickerActive) { + _ticker.wake(); + } + }; + + p.removeEventListener = function(type, callback) { + var list = this._listeners[type], i; + if (list) { + i = list.length; + while (--i > -1) { + if (list[i].c === callback) { + list.splice(i, 1); + return; + } + } + } + }; + + p.dispatchEvent = function(type) { + var list = this._listeners[type], + i, t, listener; + if (list) { + i = list.length; + t = this._eventTarget; + while (--i > -1) { + listener = list[i]; + if (listener.up) { + listener.c.call(listener.s || t, {type:type, target:t}); + } else { + listener.c.call(listener.s || t); + } + } + } + }; + + +/* + * ---------------------------------------------------------------- + * Ticker + * ---------------------------------------------------------------- + */ + var _reqAnimFrame = window.requestAnimationFrame, + _cancelAnimFrame = window.cancelAnimationFrame, + _getTime = Date.now || function() {return new Date().getTime();}; + + //now try to determine the requestAnimationFrame and cancelAnimationFrame functions and if none are found, we'll use a setTimeout()/clearTimeout() polyfill. + a = ["ms","moz","webkit","o"]; + i = a.length; + while (--i > -1 && !_reqAnimFrame) { + _reqAnimFrame = window[a[i] + "RequestAnimationFrame"]; + _cancelAnimFrame = window[a[i] + "CancelAnimationFrame"] || window[a[i] + "CancelRequestAnimationFrame"]; + } + + _class("Ticker", function(fps, useRAF) { + var _self = this, + _startTime = _getTime(), + _useRAF = (useRAF !== false && _reqAnimFrame), + _fps, _req, _id, _gap, _nextTime, + _tick = function(manual) { + _self.time = (_getTime() - _startTime) / 1000; + var id = _id, + overlap = _self.time - _nextTime; + if (!_fps || overlap > 0 || manual === true) { + _self.frame++; + _nextTime += overlap + (overlap >= _gap ? 0.004 : _gap - overlap); + _self.dispatchEvent("tick"); + } + if (manual !== true && id === _id) { //make sure the ids match in case the "tick" dispatch triggered something that caused the ticker to shut down or change _useRAF or something like that. + _id = _req(_tick); + } + }; + + EventDispatcher.call(_self); + this.time = this.frame = 0; + this.tick = function() { + _tick(true); + }; + + this.sleep = function() { + if (_id == null) { + return; + } + if (!_useRAF || !_cancelAnimFrame) { + clearTimeout(_id); + } else { + _cancelAnimFrame(_id); + } + _req = _emptyFunc; + _id = null; + if (_self === _ticker) { + _tickerActive = false; + } + }; + + this.wake = function() { + if (_id !== null) { + _self.sleep(); + } + _req = (_fps === 0) ? _emptyFunc : (!_useRAF || !_reqAnimFrame) ? function(f) { return setTimeout(f, ((_nextTime - _self.time) * 1000 + 1) | 0); } : _reqAnimFrame; + if (_self === _ticker) { + _tickerActive = true; + } + _tick(2); + }; + + this.fps = function(value) { + if (!arguments.length) { + return _fps; + } + _fps = value; + _gap = 1 / (_fps || 60); + _nextTime = this.time + _gap; + _self.wake(); + }; + + this.useRAF = function(value) { + if (!arguments.length) { + return _useRAF; + } + _self.sleep(); + _useRAF = value; + _self.fps(_fps); + }; + _self.fps(fps); + + //a bug in iOS 6 Safari occasionally prevents the requestAnimationFrame from working initially, so we use a 1.5-second timeout that automatically falls back to setTimeout() if it senses this condition. + setTimeout(function() { + if (_useRAF && (!_id || _self.frame < 5)) { + _self.useRAF(false); + } + }, 1500); + }); + + p = gs.Ticker.prototype = new gs.events.EventDispatcher(); + p.constructor = gs.Ticker; + + +/* + * ---------------------------------------------------------------- + * Animation + * ---------------------------------------------------------------- + */ + var Animation = _class("core.Animation", function(duration, vars) { + this.vars = vars || {}; + this._duration = this._totalDuration = duration || 0; + this._delay = Number(this.vars.delay) || 0; + this._timeScale = 1; + this._active = (this.vars.immediateRender === true); + this.data = this.vars.data; + this._reversed = (this.vars.reversed === true); + + if (!_rootTimeline) { + return; + } + if (!_tickerActive) { + _ticker.wake(); + } + + var tl = this.vars.useFrames ? _rootFramesTimeline : _rootTimeline; + tl.add(this, tl._time); + + if (this.vars.paused) { + this.paused(true); + } + }); + + _ticker = Animation.ticker = new gs.Ticker(); + p = Animation.prototype; + p._dirty = p._gc = p._initted = p._paused = false; + p._totalTime = p._time = 0; + p._rawPrevTime = -1; + p._next = p._last = p._onUpdate = p._timeline = p.timeline = null; + p._paused = false; + + p.play = function(from, suppressEvents) { + if (arguments.length) { + this.seek(from, suppressEvents); + } + return this.reversed(false).paused(false); + }; + + p.pause = function(atTime, suppressEvents) { + if (arguments.length) { + this.seek(atTime, suppressEvents); + } + return this.paused(true); + }; + + p.resume = function(from, suppressEvents) { + if (arguments.length) { + this.seek(from, suppressEvents); + } + return this.paused(false); + }; + + p.seek = function(time, suppressEvents) { + return this.totalTime(Number(time), suppressEvents !== false); + }; + + p.restart = function(includeDelay, suppressEvents) { + return this.reversed(false).paused(false).totalTime(includeDelay ? -this._delay : 0, (suppressEvents !== false), true); + }; + + p.reverse = function(from, suppressEvents) { + if (arguments.length) { + this.seek((from || this.totalDuration()), suppressEvents); + } + return this.reversed(true).paused(false); + }; + + p.render = function() { + + }; + + p.invalidate = function() { + return this; + }; + + p._enabled = function (enabled, ignoreTimeline) { + if (!_tickerActive) { + _ticker.wake(); + } + this._gc = !enabled; + this._active = (enabled && !this._paused && this._totalTime > 0 && this._totalTime < this._totalDuration); + if (ignoreTimeline !== true) { + if (enabled && !this.timeline) { + this._timeline.add(this, this._startTime - this._delay); + } else if (!enabled && this.timeline) { + this._timeline._remove(this, true); + } + } + return false; + }; + + + p._kill = function(vars, target) { + return this._enabled(false, false); + }; + + p.kill = function(vars, target) { + this._kill(vars, target); + return this; + }; + + p._uncache = function(includeSelf) { + var tween = includeSelf ? this : this.timeline; + while (tween) { + tween._dirty = true; + tween = tween.timeline; + } + return this; + }; + +//----Animation getters/setters -------------------------------------------------------- + + p.eventCallback = function(type, callback, params, scope) { + if (type == null) { + return null; + } else if (type.substr(0,2) === "on") { + var v = this.vars, + i; + if (arguments.length === 1) { + return v[type]; + } + if (callback == null) { + delete v[type]; + } else { + v[type] = callback; + v[type + "Params"] = params; + v[type + "Scope"] = scope; + if (params) { + i = params.length; + while (--i > -1) { + if (params[i] === "{self}") { + params = v[type + "Params"] = params.concat(); //copying the array avoids situations where the same array is passed to multiple tweens/timelines and {self} doesn't correctly point to each individual instance. + params[i] = this; + } + } + } + } + if (type === "onUpdate") { + this._onUpdate = callback; + } + } + return this; + }; + + p.delay = function(value) { + if (!arguments.length) { + return this._delay; + } + if (this._timeline.smoothChildTiming) { + this.startTime( this._startTime + value - this._delay ); + } + this._delay = value; + return this; + }; + + p.duration = function(value) { + if (!arguments.length) { + this._dirty = false; + return this._duration; + } + this._duration = this._totalDuration = value; + this._uncache(true); //true in case it's a TweenMax or TimelineMax that has a repeat - we'll need to refresh the totalDuration. + if (this._timeline.smoothChildTiming) if (this._time > 0) if (this._time < this._duration) if (value !== 0) { + this.totalTime(this._totalTime * (value / this._duration), true); + } + return this; + }; + + p.totalDuration = function(value) { + this._dirty = false; + return (!arguments.length) ? this._totalDuration : this.duration(value); + }; + + p.time = function(value, suppressEvents) { + if (!arguments.length) { + return this._time; + } + if (this._dirty) { + this.totalDuration(); + } + return this.totalTime((value > this._duration) ? this._duration : value, suppressEvents); + }; + + p.totalTime = function(time, suppressEvents, uncapped) { + if (!_tickerActive) { + _ticker.wake(); + } + if (!arguments.length) { + return this._totalTime; + } + if (this._timeline) { + if (time < 0 && !uncapped) { + time += this.totalDuration(); + } + if (this._timeline.smoothChildTiming) { + if (this._dirty) { + this.totalDuration(); + } + var totalDuration = this._totalDuration, + tl = this._timeline; + if (time > totalDuration && !uncapped) { + time = totalDuration; + } + this._startTime = (this._paused ? this._pauseTime : tl._time) - ((!this._reversed ? time : totalDuration - time) / this._timeScale); + if (!tl._dirty) { //for performance improvement. If the parent's cache is already dirty, it already took care of marking the anscestors as dirty too, so skip the function call here. + this._uncache(false); + } + if (!tl._active) { + //in case any of the anscestors had completed but should now be enabled... + while (tl._timeline) { + tl.totalTime(tl._totalTime, true); + tl = tl._timeline; + } + } + } + if (this._gc) { + this._enabled(true, false); + } + if (this._totalTime !== time) { + this.render(time, suppressEvents, false); + } + } + return this; + }; + + p.startTime = function(value) { + if (!arguments.length) { + return this._startTime; + } + if (value !== this._startTime) { + this._startTime = value; + if (this.timeline) if (this.timeline._sortChildren) { + this.timeline.add(this, value - this._delay); //ensures that any necessary re-sequencing of Animations in the timeline occurs to make sure the rendering order is correct. + } + } + return this; + }; + + p.timeScale = function(value) { + if (!arguments.length) { + return this._timeScale; + } + value = value || 0.000001; //can't allow zero because it'll throw the math off + if (this._timeline && this._timeline.smoothChildTiming) { + var pauseTime = this._pauseTime, + t = (pauseTime || pauseTime === 0) ? pauseTime : this._timeline.totalTime(); + this._startTime = t - ((t - this._startTime) * this._timeScale / value); + } + this._timeScale = value; + return this._uncache(false); + }; + + p.reversed = function(value) { + if (!arguments.length) { + return this._reversed; + } + if (value != this._reversed) { + this._reversed = value; + this.totalTime(this._totalTime, true); + } + return this; + }; + + p.paused = function(value) { + if (!arguments.length) { + return this._paused; + } + if (value != this._paused) if (this._timeline) { + if (!_tickerActive && !value) { + _ticker.wake(); + } + var raw = this._timeline.rawTime(), + elapsed = raw - this._pauseTime; + if (!value && this._timeline.smoothChildTiming) { + this._startTime += elapsed; + this._uncache(false); + } + this._pauseTime = value ? raw : null; + this._paused = value; + this._active = (!value && this._totalTime > 0 && this._totalTime < this._totalDuration); + if (!value && elapsed !== 0 && this._duration !== 0) { + this.render(this._totalTime, true, true); + } + } + if (this._gc && !value) { + this._enabled(true, false); + } + return this; + }; + + +/* + * ---------------------------------------------------------------- + * SimpleTimeline + * ---------------------------------------------------------------- + */ + var SimpleTimeline = _class("core.SimpleTimeline", function(vars) { + Animation.call(this, 0, vars); + this.autoRemoveChildren = this.smoothChildTiming = true; + }); + + p = SimpleTimeline.prototype = new Animation(); + p.constructor = SimpleTimeline; + p.kill()._gc = false; + p._first = p._last = null; + p._sortChildren = false; + + p.add = p.insert = function(child, position, align, stagger) { + var prevTween, st; + child._startTime = Number(position || 0) + child._delay; + if (child._paused) if (this !== child._timeline) { //we only adjust the _pauseTime if it wasn't in this timeline already. Remember, sometimes a tween will be inserted again into the same timeline when its startTime is changed so that the tweens in the TimelineLite/Max are re-ordered properly in the linked list (so everything renders in the proper order). + child._pauseTime = child._startTime + ((this.rawTime() - child._startTime) / child._timeScale); + } + if (child.timeline) { + child.timeline._remove(child, true); //removes from existing timeline so that it can be properly added to this one. + } + child.timeline = child._timeline = this; + if (child._gc) { + child._enabled(true, true); + } + prevTween = this._last; + if (this._sortChildren) { + st = child._startTime; + while (prevTween && prevTween._startTime > st) { + prevTween = prevTween._prev; + } + } + if (prevTween) { + child._next = prevTween._next; + prevTween._next = child; + } else { + child._next = this._first; + this._first = child; + } + if (child._next) { + child._next._prev = child; + } else { + this._last = child; + } + child._prev = prevTween; + if (this._timeline) { + this._uncache(true); + } + return this; + }; + + p._remove = function(tween, skipDisable) { + if (tween.timeline === this) { + if (!skipDisable) { + tween._enabled(false, true); + } + tween.timeline = null; + + if (tween._prev) { + tween._prev._next = tween._next; + } else if (this._first === tween) { + this._first = tween._next; + } + if (tween._next) { + tween._next._prev = tween._prev; + } else if (this._last === tween) { + this._last = tween._prev; + } + + if (this._timeline) { + this._uncache(true); + } + } + return this; + }; + + p.render = function(time, suppressEvents, force) { + var tween = this._first, + next; + this._totalTime = this._time = this._rawPrevTime = time; + while (tween) { + next = tween._next; //record it here because the value could change after rendering... + if (tween._active || (time >= tween._startTime && !tween._paused)) { + if (!tween._reversed) { + tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force); + } else { + tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force); + } + } + tween = next; + } + }; + + p.rawTime = function() { + if (!_tickerActive) { + _ticker.wake(); + } + return this._totalTime; + }; + + +/* + * ---------------------------------------------------------------- + * TweenLite + * ---------------------------------------------------------------- + */ + var TweenLite = _class("TweenLite", function(target, duration, vars) { + Animation.call(this, duration, vars); + + if (target == null) { + throw "Cannot tween a null target."; + } + + this.target = target = (typeof(target) !== "string") ? target : TweenLite.selector(target) || target; + + var isSelector = (target.jquery || (target.length && target[0] && target[0].nodeType && target[0].style && !target.nodeType)), + overwrite = this.vars.overwrite, + i, targ, targets; + + this._overwrite = overwrite = (overwrite == null) ? _overwriteLookup[TweenLite.defaultOverwrite] : (typeof(overwrite) === "number") ? overwrite >> 0 : _overwriteLookup[overwrite]; + + if ((isSelector || target instanceof Array) && typeof(target[0]) !== "number") { + this._targets = targets = _slice.call(target, 0); + this._propLookup = []; + this._siblings = []; + for (i = 0; i < targets.length; i++) { + targ = targets[i]; + if (!targ) { + targets.splice(i--, 1); + continue; + } else if (typeof(targ) === "string") { + targ = targets[i--] = TweenLite.selector(targ); //in case it's an array of strings + if (typeof(targ) === "string") { + targets.splice(i+1, 1); //to avoid an endless loop (can't imagine why the selector would return a string, but just in case) + } + continue; + } else if (targ.length && targ[0] && targ[0].nodeType && targ[0].style && !targ.nodeType) { //in case the user is passing in an array of selector objects (like jQuery objects), we need to check one more level and pull things out if necessary. Also note that elements pass all the criteria regarding length and the first child having style, so we must also check to ensure the target isn't an HTML node itself. + targets.splice(i--, 1); + this._targets = targets = targets.concat(_slice.call(targ, 0)); + continue; + } + this._siblings[i] = _register(targ, this, false); + if (overwrite === 1) if (this._siblings[i].length > 1) { + _applyOverwrite(targ, this, null, 1, this._siblings[i]); + } + } + + } else { + this._propLookup = {}; + this._siblings = _register(target, this, false); + if (overwrite === 1) if (this._siblings.length > 1) { + _applyOverwrite(target, this, null, 1, this._siblings); + } + } + if (this.vars.immediateRender || (duration === 0 && this._delay === 0 && this.vars.immediateRender !== false)) { + this.render(-this._delay, false, true); + } + }, true), + _isSelector = function(v) { + return (v.length && v[0] && v[0].nodeType && v[0].style && !v.nodeType); + }, + _autoCSS = function(vars, target) { + var css = {}, + p; + for (p in vars) { + if (!_reservedProps[p] && (!(p in target) || p === "x" || p === "y" || p === "width" || p === "height" || p === "className") && (!_plugins[p] || (_plugins[p] && _plugins[p]._autoCSS))) { //note: elements contain read-only "x" and "y" properties. We should also prioritize editing css width/height rather than the element's properties. + css[p] = vars[p]; + delete vars[p]; + } + } + vars.css = css; + }; + + p = TweenLite.prototype = new Animation(); + p.constructor = TweenLite; + p.kill()._gc = false; + +//----TweenLite defaults, overwrite management, and root updates ---------------------------------------------------- + + p.ratio = 0; + p._firstPT = p._targets = p._overwrittenProps = p._startAt = null; + p._notifyPluginsOfEnabled = false; + + TweenLite.version = "1.9.8"; + TweenLite.defaultEase = p._ease = new Ease(null, null, 1, 1); + TweenLite.defaultOverwrite = "auto"; + TweenLite.ticker = _ticker; + TweenLite.autoSleep = true; + TweenLite.selector = window.$ || window.jQuery || function(e) { if (window.$) { TweenLite.selector = window.$; return window.$(e); } return window.document ? window.document.getElementById((e.charAt(0) === "#") ? e.substr(1) : e) : e; }; + + var _internals = TweenLite._internals = {}, //gives us a way to expose certain private values to other GreenSock classes without contaminating tha main TweenLite object. + _plugins = TweenLite._plugins = {}, + _tweenLookup = TweenLite._tweenLookup = {}, + _tweenLookupNum = 0, + _reservedProps = _internals.reservedProps = {ease:1, delay:1, overwrite:1, onComplete:1, onCompleteParams:1, onCompleteScope:1, useFrames:1, runBackwards:1, startAt:1, onUpdate:1, onUpdateParams:1, onUpdateScope:1, onStart:1, onStartParams:1, onStartScope:1, onReverseComplete:1, onReverseCompleteParams:1, onReverseCompleteScope:1, onRepeat:1, onRepeatParams:1, onRepeatScope:1, easeParams:1, yoyo:1, immediateRender:1, repeat:1, repeatDelay:1, data:1, paused:1, reversed:1, autoCSS:1}, + _overwriteLookup = {none:0, all:1, auto:2, concurrent:3, allOnStart:4, preexisting:5, "true":1, "false":0}, + _rootFramesTimeline = Animation._rootFramesTimeline = new SimpleTimeline(), + _rootTimeline = Animation._rootTimeline = new SimpleTimeline(); + + _rootTimeline._startTime = _ticker.time; + _rootFramesTimeline._startTime = _ticker.frame; + _rootTimeline._active = _rootFramesTimeline._active = true; + + Animation._updateRoot = function() { + _rootTimeline.render((_ticker.time - _rootTimeline._startTime) * _rootTimeline._timeScale, false, false); + _rootFramesTimeline.render((_ticker.frame - _rootFramesTimeline._startTime) * _rootFramesTimeline._timeScale, false, false); + if (!(_ticker.frame % 120)) { //dump garbage every 120 frames... + var i, a, p; + for (p in _tweenLookup) { + a = _tweenLookup[p].tweens; + i = a.length; + while (--i > -1) { + if (a[i]._gc) { + a.splice(i, 1); + } + } + if (a.length === 0) { + delete _tweenLookup[p]; + } + } + //if there are no more tweens in the root timelines, or if they're all paused, make the _timer sleep to reduce load on the CPU slightly + p = _rootTimeline._first; + if (!p || p._paused) if (TweenLite.autoSleep && !_rootFramesTimeline._first && _ticker._listeners.tick.length === 1) { + while (p && p._paused) { + p = p._next; + } + if (!p) { + _ticker.sleep(); + } + } + } + }; + + _ticker.addEventListener("tick", Animation._updateRoot); + + var _register = function(target, tween, scrub) { + var id = target._gsTweenID, a, i; + if (!_tweenLookup[id || (target._gsTweenID = id = "t" + (_tweenLookupNum++))]) { + _tweenLookup[id] = {target:target, tweens:[]}; + } + if (tween) { + a = _tweenLookup[id].tweens; + a[(i = a.length)] = tween; + if (scrub) { + while (--i > -1) { + if (a[i] === tween) { + a.splice(i, 1); + } + } + } + } + return _tweenLookup[id].tweens; + }, + + _applyOverwrite = function(target, tween, props, mode, siblings) { + var i, changed, curTween, l; + if (mode === 1 || mode >= 4) { + l = siblings.length; + for (i = 0; i < l; i++) { + if ((curTween = siblings[i]) !== tween) { + if (!curTween._gc) if (curTween._enabled(false, false)) { + changed = true; + } + } else if (mode === 5) { + break; + } + } + return changed; + } + //NOTE: Add 0.0000000001 to overcome floating point errors that can cause the startTime to be VERY slightly off (when a tween's time() is set for example) + var startTime = tween._startTime + 0.0000000001, + overlaps = [], + oCount = 0, + zeroDur = (tween._duration === 0), + globalStart; + i = siblings.length; + while (--i > -1) { + if ((curTween = siblings[i]) === tween || curTween._gc || curTween._paused) { + //ignore + } else if (curTween._timeline !== tween._timeline) { + globalStart = globalStart || _checkOverlap(tween, 0, zeroDur); + if (_checkOverlap(curTween, globalStart, zeroDur) === 0) { + overlaps[oCount++] = curTween; + } + } else if (curTween._startTime <= startTime) if (curTween._startTime + curTween.totalDuration() / curTween._timeScale + 0.0000000001 > startTime) if (!((zeroDur || !curTween._initted) && startTime - curTween._startTime <= 0.0000000002)) { + overlaps[oCount++] = curTween; + } + } + + i = oCount; + while (--i > -1) { + curTween = overlaps[i]; + if (mode === 2) if (curTween._kill(props, target)) { + changed = true; + } + if (mode !== 2 || (!curTween._firstPT && curTween._initted)) { + if (curTween._enabled(false, false)) { //if all property tweens have been overwritten, kill the tween. + changed = true; + } + } + } + return changed; + }, + + _checkOverlap = function(tween, reference, zeroDur) { + var tl = tween._timeline, + ts = tl._timeScale, + t = tween._startTime, + min = 0.0000000001; //we use this to protect from rounding errors. + while (tl._timeline) { + t += tl._startTime; + ts *= tl._timeScale; + if (tl._paused) { + return -100; + } + tl = tl._timeline; + } + t /= ts; + return (t > reference) ? t - reference : ((zeroDur && t === reference) || (!tween._initted && t - reference < 2 * min)) ? min : ((t += tween.totalDuration() / tween._timeScale / ts) > reference + min) ? 0 : t - reference - min; + }; + + +//---- TweenLite instance methods ----------------------------------------------------------------------------- + + p._init = function() { + var v = this.vars, + op = this._overwrittenProps, + dur = this._duration, + ease = v.ease, + i, initPlugins, pt, p; + if (v.startAt) { + v.startAt.overwrite = 0; + v.startAt.immediateRender = true; + this._startAt = TweenLite.to(this.target, 0, v.startAt); + if (v.immediateRender) { + this._startAt = null; //tweens that render immediately (like most from() and fromTo() tweens) shouldn't revert when their parent timeline's playhead goes backward past the startTime because the initial render could have happened anytime and it shouldn't be directly correlated to this tween's startTime. Imagine setting up a complex animation where the beginning states of various objects are rendered immediately but the tween doesn't happen for quite some time - if we revert to the starting values as soon as the playhead goes backward past the tween's startTime, it will throw things off visually. Reversion should only happen in TimelineLite/Max instances where immediateRender was false (which is the default in the convenience methods like from()). + if (this._time === 0 && dur !== 0) { + return; //we skip initialization here so that overwriting doesn't occur until the tween actually begins. Otherwise, if you create several immediateRender:true tweens of the same target/properties to drop into a TimelineLite or TimelineMax, the last one created would overwrite the first ones because they didn't get placed into the timeline yet before the first render occurs and kicks in overwriting. + } + } + } else if (v.runBackwards && v.immediateRender && dur !== 0) { + //from() tweens must be handled uniquely: their beginning values must be rendered but we don't want overwriting to occur yet (when time is still 0). Wait until the tween actually begins before doing all the routines like overwriting. At that time, we should render at the END of the tween to ensure that things initialize correctly (remember, from() tweens go backwards) + if (this._startAt) { + this._startAt.render(-1, true); + this._startAt = null; + } else if (this._time === 0) { + pt = {}; + for (p in v) { //copy props into a new object and skip any reserved props, otherwise onComplete or onUpdate or onStart could fire. We should, however, permit autoCSS to go through. + if (!_reservedProps[p] || p === "autoCSS") { + pt[p] = v[p]; + } + } + pt.overwrite = 0; + this._startAt = TweenLite.to(this.target, 0, pt); + return; + } + } + if (!ease) { + this._ease = TweenLite.defaultEase; + } else if (ease instanceof Ease) { + this._ease = (v.easeParams instanceof Array) ? ease.config.apply(ease, v.easeParams) : ease; + } else { + this._ease = (typeof(ease) === "function") ? new Ease(ease, v.easeParams) : _easeMap[ease] || TweenLite.defaultEase; + } + this._easeType = this._ease._type; + this._easePower = this._ease._power; + this._firstPT = null; + + if (this._targets) { + i = this._targets.length; + while (--i > -1) { + if ( this._initProps( this._targets[i], (this._propLookup[i] = {}), this._siblings[i], (op ? op[i] : null)) ) { + initPlugins = true; + } + } + } else { + initPlugins = this._initProps(this.target, this._propLookup, this._siblings, op); + } + + if (initPlugins) { + TweenLite._onPluginEvent("_onInitAllProps", this); //reorders the array in order of priority. Uses a static TweenPlugin method in order to minimize file size in TweenLite + } + if (op) if (!this._firstPT) if (typeof(this.target) !== "function") { //if all tweening properties have been overwritten, kill the tween. If the target is a function, it's probably a delayedCall so let it live. + this._enabled(false, false); + } + if (v.runBackwards) { + pt = this._firstPT; + while (pt) { + pt.s += pt.c; + pt.c = -pt.c; + pt = pt._next; + } + } + this._onUpdate = v.onUpdate; + this._initted = true; + }; + + p._initProps = function(target, propLookup, siblings, overwrittenProps) { + var p, i, initPlugins, plugin, a, pt, v; + if (target == null) { + return false; + } + if (!this.vars.css) if (target.style) if (target.nodeType) if (_plugins.css) if (this.vars.autoCSS !== false) { //it's so common to use TweenLite/Max to animate the css of DOM elements, we assume that if the target is a DOM element, that's what is intended (a convenience so that users don't have to wrap things in css:{}, although we still recommend it for a slight performance boost and better specificity) + _autoCSS(this.vars, target); + } + for (p in this.vars) { + if (_reservedProps[p]) { + if (p === "onStartParams" || p === "onUpdateParams" || p === "onCompleteParams" || p === "onReverseCompleteParams" || p === "onRepeatParams") if ((a = this.vars[p])) { + i = a.length; + while (--i > -1) { + if (a[i] === "{self}") { + a = this.vars[p] = a.concat(); //copy the array in case the user referenced the same array in multiple tweens/timelines (each {self} should be unique) + a[i] = this; + } + } + } + + } else if (_plugins[p] && (plugin = new _plugins[p]())._onInitTween(target, this.vars[p], this)) { + + //t - target [object] + //p - property [string] + //s - start [number] + //c - change [number] + //f - isFunction [boolean] + //n - name [string] + //pg - isPlugin [boolean] + //pr - priority [number] + this._firstPT = pt = {_next:this._firstPT, t:plugin, p:"setRatio", s:0, c:1, f:true, n:p, pg:true, pr:plugin._priority}; + i = plugin._overwriteProps.length; + while (--i > -1) { + propLookup[plugin._overwriteProps[i]] = this._firstPT; + } + if (plugin._priority || plugin._onInitAllProps) { + initPlugins = true; + } + if (plugin._onDisable || plugin._onEnable) { + this._notifyPluginsOfEnabled = true; + } + + } else { + this._firstPT = propLookup[p] = pt = {_next:this._firstPT, t:target, p:p, f:(typeof(target[p]) === "function"), n:p, pg:false, pr:0}; + pt.s = (!pt.f) ? parseFloat(target[p]) : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ](); + v = this.vars[p]; + pt.c = (typeof(v) === "string" && v.charAt(1) === "=") ? parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) : (Number(v) - pt.s) || 0; + } + if (pt) if (pt._next) { + pt._next._prev = pt; + } + } + + if (overwrittenProps) if (this._kill(overwrittenProps, target)) { //another tween may have tried to overwrite properties of this tween before init() was called (like if two tweens start at the same time, the one created second will run first) + return this._initProps(target, propLookup, siblings, overwrittenProps); + } + if (this._overwrite > 1) if (this._firstPT) if (siblings.length > 1) if (_applyOverwrite(target, this, propLookup, this._overwrite, siblings)) { + this._kill(propLookup, target); + return this._initProps(target, propLookup, siblings, overwrittenProps); + } + return initPlugins; + }; + + p.render = function(time, suppressEvents, force) { + var prevTime = this._time, + isComplete, callback, pt; + if (time >= this._duration) { + this._totalTime = this._time = this._duration; + this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1; + if (!this._reversed) { + isComplete = true; + callback = "onComplete"; + } + if (this._duration === 0) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered. + if (time === 0 || this._rawPrevTime < 0) if (this._rawPrevTime !== time) { + force = true; + if (this._rawPrevTime > 0) { + callback = "onReverseComplete"; + if (suppressEvents) { + time = -1; //when a callback is placed at the VERY beginning of a timeline and it repeats (or if timeline.seek(0) is called), events are normally suppressed during those behaviors (repeat or seek()) and without adjusting the _rawPrevTime back slightly, the onComplete wouldn't get called on the next render. This only applies to zero-duration tweens/callbacks of course. + } + } + } + this._rawPrevTime = time; + } + + } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0. + this._totalTime = this._time = 0; + this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0; + if (prevTime !== 0 || (this._duration === 0 && this._rawPrevTime > 0)) { + callback = "onReverseComplete"; + isComplete = this._reversed; + } + if (time < 0) { + this._active = false; + if (this._duration === 0) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered. + if (this._rawPrevTime >= 0) { + force = true; + } + this._rawPrevTime = time; + } + } else if (!this._initted) { //if we render the very beginning (time == 0) of a fromTo(), we must force the render (normal tweens wouldn't need to render at a time of 0 when the prevTime was also 0). This is also mandatory to make sure overwriting kicks in immediately. + force = true; + } + + } else { + this._totalTime = this._time = time; + + if (this._easeType) { + var r = time / this._duration, type = this._easeType, pow = this._easePower; + if (type === 1 || (type === 3 && r >= 0.5)) { + r = 1 - r; + } + if (type === 3) { + r *= 2; + } + if (pow === 1) { + r *= r; + } else if (pow === 2) { + r *= r * r; + } else if (pow === 3) { + r *= r * r * r; + } else if (pow === 4) { + r *= r * r * r * r; + } + + if (type === 1) { + this.ratio = 1 - r; + } else if (type === 2) { + this.ratio = r; + } else if (time / this._duration < 0.5) { + this.ratio = r / 2; + } else { + this.ratio = 1 - (r / 2); + } + + } else { + this.ratio = this._ease.getRatio(time / this._duration); + } + + } + + if (this._time === prevTime && !force) { + return; + } else if (!this._initted) { + this._init(); + if (!this._initted) { //immediateRender tweens typically won't initialize until the playhead advances (_time is greater than 0) in order to ensure that overwriting occurs properly. + return; + } + //_ease is initially set to defaultEase, so now that init() has run, _ease is set properly and we need to recalculate the ratio. Overall this is faster than using conditional logic earlier in the method to avoid having to set ratio twice because we only init() once but renderTime() gets called VERY frequently. + if (this._time && !isComplete) { + this.ratio = this._ease.getRatio(this._time / this._duration); + } else if (isComplete && this._ease._calcEnd) { + this.ratio = this._ease.getRatio((this._time === 0) ? 0 : 1); + } + } + + if (!this._active) if (!this._paused) { + this._active = true; //so that if the user renders a tween (as opposed to the timeline rendering it), the timeline is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the tween already finished but the user manually re-renders it as halfway done. + } + if (prevTime === 0) { + if (this._startAt) { + if (time >= 0) { + this._startAt.render(time, suppressEvents, force); + } else if (!callback) { + callback = "_dummyGS"; //if no callback is defined, use a dummy value just so that the condition at the end evaluates as true because _startAt should render AFTER the normal render loop when the time is negative. We could handle this in a more intuitive way, of course, but the render loop is the MOST important thing to optimize, so this technique allows us to avoid adding extra conditional logic in a high-frequency area. + } + } + if (this.vars.onStart) if (this._time !== 0 || this._duration === 0) if (!suppressEvents) { + this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray); + } + } + + pt = this._firstPT; + while (pt) { + if (pt.f) { + pt.t[pt.p](pt.c * this.ratio + pt.s); + } else { + pt.t[pt.p] = pt.c * this.ratio + pt.s; + } + pt = pt._next; + } + + if (this._onUpdate) { + if (time < 0) if (this._startAt) { + this._startAt.render(time, suppressEvents, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete. + } + if (!suppressEvents) { + this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray); + } + } + + if (callback) if (!this._gc) { //check _gc because there's a chance that kill() could be called in an onUpdate + if (time < 0 && this._startAt && !this._onUpdate) { + this._startAt.render(time, suppressEvents, force); + } + if (isComplete) { + if (this._timeline.autoRemoveChildren) { + this._enabled(false, false); + } + this._active = false; + } + if (!suppressEvents && this.vars[callback]) { + this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray); + } + } + + }; + + p._kill = function(vars, target) { + if (vars === "all") { + vars = null; + } + if (vars == null) if (target == null || target === this.target) { + return this._enabled(false, false); + } + target = (typeof(target) !== "string") ? (target || this._targets || this.target) : TweenLite.selector(target) || target; + var i, overwrittenProps, p, pt, propLookup, changed, killProps, record; + if ((target instanceof Array || _isSelector(target)) && typeof(target[0]) !== "number") { + i = target.length; + while (--i > -1) { + if (this._kill(vars, target[i])) { + changed = true; + } + } + } else { + if (this._targets) { + i = this._targets.length; + while (--i > -1) { + if (target === this._targets[i]) { + propLookup = this._propLookup[i] || {}; + this._overwrittenProps = this._overwrittenProps || []; + overwrittenProps = this._overwrittenProps[i] = vars ? this._overwrittenProps[i] || {} : "all"; + break; + } + } + } else if (target !== this.target) { + return false; + } else { + propLookup = this._propLookup; + overwrittenProps = this._overwrittenProps = vars ? this._overwrittenProps || {} : "all"; + } + + if (propLookup) { + killProps = vars || propLookup; + record = (vars !== overwrittenProps && overwrittenProps !== "all" && vars !== propLookup && (vars == null || vars._tempKill !== true)); //_tempKill is a super-secret way to delete a particular tweening property but NOT have it remembered as an official overwritten property (like in BezierPlugin) + for (p in killProps) { + if ((pt = propLookup[p])) { + if (pt.pg && pt.t._kill(killProps)) { + changed = true; //some plugins need to be notified so they can perform cleanup tasks first + } + if (!pt.pg || pt.t._overwriteProps.length === 0) { + if (pt._prev) { + pt._prev._next = pt._next; + } else if (pt === this._firstPT) { + this._firstPT = pt._next; + } + if (pt._next) { + pt._next._prev = pt._prev; + } + pt._next = pt._prev = null; + } + delete propLookup[p]; + } + if (record) { + overwrittenProps[p] = 1; + } + } + if (!this._firstPT && this._initted) { //if all tweening properties are killed, kill the tween. Without this line, if there's a tween with multiple targets and then you killTweensOf() each target individually, the tween would technically still remain active and fire its onComplete even though there aren't any more properties tweening. + this._enabled(false, false); + } + } + } + return changed; + }; + + p.invalidate = function() { + if (this._notifyPluginsOfEnabled) { + TweenLite._onPluginEvent("_onDisable", this); + } + this._firstPT = null; + this._overwrittenProps = null; + this._onUpdate = null; + this._startAt = null; + this._initted = this._active = this._notifyPluginsOfEnabled = false; + this._propLookup = (this._targets) ? {} : []; + return this; + }; + + p._enabled = function(enabled, ignoreTimeline) { + if (!_tickerActive) { + _ticker.wake(); + } + if (enabled && this._gc) { + var targets = this._targets, + i; + if (targets) { + i = targets.length; + while (--i > -1) { + this._siblings[i] = _register(targets[i], this, true); + } + } else { + this._siblings = _register(this.target, this, true); + } + } + Animation.prototype._enabled.call(this, enabled, ignoreTimeline); + if (this._notifyPluginsOfEnabled) if (this._firstPT) { + return TweenLite._onPluginEvent((enabled ? "_onEnable" : "_onDisable"), this); + } + return false; + }; + + +//----TweenLite static methods ----------------------------------------------------- + + TweenLite.to = function(target, duration, vars) { + return new TweenLite(target, duration, vars); + }; + + TweenLite.from = function(target, duration, vars) { + vars.runBackwards = true; + vars.immediateRender = (vars.immediateRender != false); + return new TweenLite(target, duration, vars); + }; + + TweenLite.fromTo = function(target, duration, fromVars, toVars) { + toVars.startAt = fromVars; + toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false); + return new TweenLite(target, duration, toVars); + }; + + TweenLite.delayedCall = function(delay, callback, params, scope, useFrames) { + return new TweenLite(callback, 0, {delay:delay, onComplete:callback, onCompleteParams:params, onCompleteScope:scope, onReverseComplete:callback, onReverseCompleteParams:params, onReverseCompleteScope:scope, immediateRender:false, useFrames:useFrames, overwrite:0}); + }; + + TweenLite.set = function(target, vars) { + return new TweenLite(target, 0, vars); + }; + + TweenLite.killTweensOf = TweenLite.killDelayedCallsTo = function(target, vars) { + var a = TweenLite.getTweensOf(target), + i = a.length; + while (--i > -1) { + a[i]._kill(vars, target); + } + }; + + TweenLite.getTweensOf = function(target) { + if (target == null) { return []; } + target = (typeof(target) !== "string") ? target : TweenLite.selector(target) || target; + var i, a, j, t; + if ((target instanceof Array || _isSelector(target)) && typeof(target[0]) !== "number") { + i = target.length; + a = []; + while (--i > -1) { + a = a.concat(TweenLite.getTweensOf(target[i])); + } + i = a.length; + //now get rid of any duplicates (tweens of arrays of objects could cause duplicates) + while (--i > -1) { + t = a[i]; + j = i; + while (--j > -1) { + if (t === a[j]) { + a.splice(i, 1); + } + } + } + } else { + a = _register(target).concat(); + i = a.length; + while (--i > -1) { + if (a[i]._gc) { + a.splice(i, 1); + } + } + } + return a; + }; + + + +/* + * ---------------------------------------------------------------- + * TweenPlugin (could easily be split out as a separate file/class, but included for ease of use (so that people don't need to include another