├── .gitignore ├── lights ├── image │ ├── blank.png │ ├── bg-strip-dark.png │ ├── bulbs-32x32-top.png │ ├── bulbs-50x50-top.png │ ├── bulbs-64x64-top.png │ ├── bulbs-72x72-top.png │ ├── bulbs-96x96-top.png │ └── bulbs-50x50-fragments.png ├── sound │ ├── glass0.mp3 │ ├── glass1.mp3 │ ├── glass2.mp3 │ ├── glass3.mp3 │ ├── glass4.mp3 │ └── glass5.mp3 ├── soundmanager2.swf ├── soundmanager2_flash9.swf ├── index.html ├── christmaslights.css ├── christmaslights.js └── soundmanager2-nodebug-jsmin.js ├── demo ├── demo_background.gif ├── basic-html5-example.html ├── basic-html4-example.html └── demo_default.css ├── README ├── basic-example.html ├── basic-example-customized.html ├── target-element-relative-example.html ├── license.txt ├── target-element-absolute-example.html ├── snowstorm-min.js ├── index.html └── snowstorm.js /.gitignore: -------------------------------------------------------------------------------- 1 | build.* 2 | .DS_Store 3 | *.zip 4 | -------------------------------------------------------------------------------- /lights/image/blank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/image/blank.png -------------------------------------------------------------------------------- /demo/demo_background.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/demo/demo_background.gif -------------------------------------------------------------------------------- /lights/sound/glass0.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/sound/glass0.mp3 -------------------------------------------------------------------------------- /lights/sound/glass1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/sound/glass1.mp3 -------------------------------------------------------------------------------- /lights/sound/glass2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/sound/glass2.mp3 -------------------------------------------------------------------------------- /lights/sound/glass3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/sound/glass3.mp3 -------------------------------------------------------------------------------- /lights/sound/glass4.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/sound/glass4.mp3 -------------------------------------------------------------------------------- /lights/sound/glass5.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/sound/glass5.mp3 -------------------------------------------------------------------------------- /lights/soundmanager2.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/soundmanager2.swf -------------------------------------------------------------------------------- /lights/image/bg-strip-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/image/bg-strip-dark.png -------------------------------------------------------------------------------- /lights/image/bulbs-32x32-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/image/bulbs-32x32-top.png -------------------------------------------------------------------------------- /lights/image/bulbs-50x50-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/image/bulbs-50x50-top.png -------------------------------------------------------------------------------- /lights/image/bulbs-64x64-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/image/bulbs-64x64-top.png -------------------------------------------------------------------------------- /lights/image/bulbs-72x72-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/image/bulbs-72x72-top.png -------------------------------------------------------------------------------- /lights/image/bulbs-96x96-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/image/bulbs-96x96-top.png -------------------------------------------------------------------------------- /lights/soundmanager2_flash9.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/soundmanager2_flash9.swf -------------------------------------------------------------------------------- /lights/image/bulbs-50x50-fragments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottschiller/Snowstorm/HEAD/lights/image/bulbs-50x50-fragments.png -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | /** 2 | * DHTML Snowstorm! JavaScript-based Snow for web pages 3 | * -------------------------------------------------------- 4 | * Version 1.44.20131208 (Previous rev: 1.43.2011125) 5 | * Copyright (c) 2007, Scott Schiller. All rights reserved. 6 | * Code provided under the BSD License: 7 | * http://schillmania.com/projects/snowstorm/license.txt 8 | */ 9 | 10 | Homepage, demo, downloads etc.: 11 | http://www.schillmania.com/projects/snowstorm/ 12 | 13 | -------------------------------------------------------------------------------- /basic-example.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | DHTML SnowStorm: Basic Example 6 | 7 | 8 | 9 | 10 | 11 |

Example SnowStorm page

12 | 13 |

14 | A single Javascript reference in the <head> tag is required for SnowStorm to work. 15 |

16 | 17 |

18 | View the source of this page for reference. 19 |

20 | 21 | 22 | -------------------------------------------------------------------------------- /demo/basic-html5-example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | DHTML SnowStorm: Basic Example (HTML5 DTD) 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Example SnowStorm page

12 | 13 |

14 | A single Javascript reference in the <head> tag is required for SnowStorm to work.
15 | View the source of this page for reference. 16 |

17 | 18 |

This page uses a HTML 5 DTD. Older versions of IE should render this page in standards mode, where supported.

19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /demo/basic-html4-example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | DHTML SnowStorm: Basic Example (HTML4 DTD) 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Example SnowStorm page

12 | 13 |

14 | A single Javascript reference in the <head> tag is required for SnowStorm to work.
15 | View the source of this page for reference. 16 |

17 | 18 |

This page uses a HTML 4.01 transitional DTD, and thus Internet Explorer doesn't support position:fixed in "backCompat" rendering mode. The script should handle this case properly.

19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /lights/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Smashable Christmas Lights 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 |
17 | 18 |
19 |

Christmas Light Smashfest 2008: Prototype

20 |

Rendering...

21 |
22 | 23 |
24 | 25 |
26 | 27 |
28 | pico | tiny | small | medium | large 29 |
30 | 31 |
32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /basic-example-customized.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | DHTML SnowStorm: Basic Example 6 | 7 | 12 | 13 | 14 | 15 | 16 |

Example SnowStorm page

17 | 18 |

19 | A single Javascript reference in the <head> tag is required for SnowStorm to work. 20 |

21 | 22 |

23 | As well, some customized options are specified which override the SnowStorm defaults. 24 |

25 | 26 |

27 | View the source of this page for reference. 28 |

29 | 30 |
31 | <!-- required, default behaviour -->
32 | <script src="snowstorm.js"></script>
33 | 
34 | <!-- now, we'll customize the snowStorm object -->
35 | <script>
36 | snowStorm.snowColor = '#99ccff';   // blue-ish snow!?
37 | snowStorm.flakesMaxActive = 96;    // show more snow on screen at once
38 | snowStorm.useTwinkleEffect = true; // let the snow flicker in and out of view
39 | </script>
40 | 
41 | 42 | 43 | -------------------------------------------------------------------------------- /target-element-relative-example.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | DHTML SnowStorm: targetElement example 6 | 19 | 20 | 21 | 22 | 31 | 32 | 33 | 34 | 35 |

SnowStorm: targetElement example (relative positioning)

36 | 37 |
38 | 39 |
40 | 41 |

42 | This example has snow moving in a relatively-positioned <div> element, using snowStorm.targetElement. Applying CSS overflow: hidden to the target element is required for best effect. 43 |

44 | 45 |

46 | View the source of this page for reference. 47 |

48 | 49 |
50 | 51 |
52 | 53 | 54 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD License) 2 | 3 | Copyright (c) 2003, Scott Schiller (schillmania.com) 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, this 13 | list of conditions and the following disclaimer in the documentation and/or 14 | other materials provided with the distribution. 15 | 16 | * Neither the name of schillmania.com nor the names of its contributors may be 17 | used to endorse or promote products derived from this software without 18 | specific prior written permission from schillmania.com. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 24 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /target-element-absolute-example.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | DHTML SnowStorm: targetElement example 6 | 24 | 25 | 26 | 27 | 36 | 37 | 38 | 39 | 40 |

SnowStorm: targetElement example (absolute positioning)

41 | 42 |
43 | 44 |
45 | 46 |

47 | This example has snow moving in an absolutely-positioned <div> element, using snowStorm.targetElement. Applying CSS overflow: hidden to the target element is required for best effect. 48 |

49 | 50 |

51 | View the source of this page for reference. 52 |

53 | 54 |
55 | 56 |
57 | 58 | 59 | -------------------------------------------------------------------------------- /lights/christmaslights.css: -------------------------------------------------------------------------------- 1 | /* XLSF 2007 */ 2 | 3 | body { 4 | background:#333 url(image/bg-strip-dark.png) 0px 0px; 5 | font-family:normal,"Century Gothic","Helvetica Neue Light","Helvetica Neue",georgia,"times new roman","Arial Rounded MT Bold",helvetica,verdana,tahoma,arial,"sans serif"; 6 | font-size:75%; 7 | color:#666; 8 | } 9 | 10 | h1, h1 a { 11 | color:#999; 12 | text-decoration:none; 13 | } 14 | 15 | h1 { 16 | color:#999; 17 | margin-bottom:0; 18 | margin-left:-5px; 19 | margin-top:0; 20 | padding-left:5px; 21 | padding-right:5px; 22 | } 23 | 24 | h1, h2, h3 { 25 | clear:both; 26 | float:left; 27 | font-family:normal,"Century Gothic","Helvetica Neue Light","Helvetica Neue",georgia,"times new roman","Arial Rounded MT Bold",helvetica,verdana,tahoma,arial,"sans serif"; 28 | font-size:3em; 29 | font-size-adjust:none; 30 | margin-bottom:0.25em; 31 | padding-bottom:1px; 32 | } 33 | 34 | h1, h2 { 35 | letter-spacing:-1px; 36 | margin-bottom:0; 37 | margin-left:-5px; 38 | margin-top:0; 39 | padding-left:5px; 40 | padding-right:5px; 41 | } 42 | 43 | a { 44 | color:#6699cc; 45 | padding:0px 2px; 46 | text-decoration:none; 47 | } 48 | 49 | a:hover { 50 | background:#6699cc; 51 | color:#fff; 52 | } 53 | 54 | #lights { 55 | position:absolute; 56 | left:0px; 57 | top:0px; 58 | width:100%; 59 | height:100%; 60 | overflow:hidden; 61 | } 62 | 63 | .xlsf-light { 64 | position:absolute; 65 | } 66 | 67 | body.fast .xlsf-light { 68 | opacity:0.9; 69 | } 70 | 71 | .xlsf-fragment { 72 | position:absolute; 73 | background:transparent url(image/bulbs-50x50-fragments.png) no-repeat 0px 0px; 74 | width:50px; 75 | height:50px; 76 | } 77 | 78 | .xlsf-fragment-box { 79 | position:absolute; 80 | left:0px; 81 | top:0px; 82 | width:50px; 83 | height:50px; 84 | *width:100%; 85 | *height:100%; 86 | display:none; 87 | } 88 | 89 | .xlsf-cover { 90 | position:fixed; 91 | left:0px; 92 | top:0px; 93 | width:100%; 94 | height:100%; 95 | background:#fff; 96 | opacity:1; 97 | z-index:999; 98 | display:none; 99 | } 100 | 101 | /* 102 | .xlsf-light.bottom { 103 | height:49px; 104 | border-bottom:1px solid #006600; 105 | } 106 | 107 | .xlsf-light.top { 108 | height:49px; 109 | border-top:1px solid #009900; 110 | } 111 | */ -------------------------------------------------------------------------------- /demo/demo_default.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SnowStorm demo page CSS 4 | ----------------------- 5 | 6 | None of this is needed for the snow effect to work - it's strictly to make the demo/documentation look pretty. 7 | 8 | */ 9 | 10 | body { 11 | margin:0px; 12 | padding:0px; 13 | background:#333 url(../lights/image/bg-strip-dark.png); 14 | color:#eeeeee; 15 | font-family:helvetica,verdana,arial,tahoma,"sans serif"; 16 | font-weight: 300; 17 | font-size:100%; 18 | text-shadow: 0 0 0 #000; /* safari is lame. */ 19 | } 20 | 21 | a { 22 | color:#aaaa00; 23 | text-decoration:none; 24 | } 25 | 26 | a:hover { 27 | color:#ffff33; 28 | } 29 | 30 | h1, h2, h3 { 31 | font-family:"helvetica neue",helvetica,verdana,arial,tahoma,"sans serif"; 32 | margin:0px; 33 | font-weight: 200; 34 | color:#fff; 35 | } 36 | 37 | h1 { 38 | font-size:2.5em; 39 | font-weight: 100; 40 | } 41 | 42 | h2 { 43 | font-size:1.8em; 44 | font-weight: 100; 45 | margin-top:1em; 46 | color:#fff; 47 | } 48 | 49 | h3 { 50 | font-size:1.4em; 51 | margin-top:1em; 52 | margin-bottom:0.5em; 53 | letter-spacing: 0.01em; 54 | color:#99ccff; 55 | } 56 | 57 | h3 + p { 58 | margin-top:0px; 59 | } 60 | 61 | p { 62 | margin:1em 0px 0px 0px; 63 | } 64 | 65 | dd, 66 | p { 67 | line-height:1.6em; 68 | } 69 | 70 | p.first { 71 | margin-top:0.25em; 72 | } 73 | 74 | .noTop { 75 | margin-top:0px !important; 76 | padding-top:0px !important; 77 | line-height:1em; 78 | } 79 | 80 | pre { 81 | font-size:1.2em; 82 | *font-size:1em; 83 | color:#33cc33; 84 | } 85 | 86 | pre span { 87 | color: #999; 88 | } 89 | 90 | pre { 91 | font-size:1.25em; 92 | } 93 | 94 | ul { 95 | margin-left:16px; 96 | padding-left:0px; 97 | margin-top:5px; 98 | margin-bottom:5px; 99 | } 100 | 101 | .bright { 102 | color:#ff6666; 103 | } 104 | 105 | dl { 106 | margin-left:1em; 107 | } 108 | 109 | dl dt { 110 | font-weight:bold; 111 | border-bottom:1px dotted #555; 112 | padding-bottom:4px; 113 | margin-top:1.5em; 114 | margin-right:2%; 115 | } 116 | 117 | dl dd { 118 | margin-top:4px; 119 | margin-left:0px; 120 | margin-bottom:0.5em; 121 | } 122 | 123 | code, 124 | dl dt code { 125 | color:#33cc33; 126 | font-weight:normal; 127 | } 128 | 129 | dl dd code { 130 | color:#ccc; 131 | } 132 | 133 | dl em { 134 | color:#fff; 135 | font-weight:normal; 136 | padding-top:2px; 137 | padding-bottom:0.5em; 138 | } 139 | 140 | code { 141 | font-family:monaco,"VT-100","lucida console",terminal,monospace,courier,system,sans-serif; 142 | font-size:1em; 143 | font-weight:light; 144 | } 145 | 146 | #container { 147 | position:relative; 148 | background-color:#222; 149 | padding:32px 16px 16px 16px; 150 | border:1px solid #111; 151 | max-width:60em; 152 | _width:50em; 153 | margin:0px auto; 154 | } 155 | 156 | #content { 157 | position:relative; 158 | z-index:2; 159 | } 160 | 161 | .alt { 162 | color:#ccc; 163 | } 164 | 165 | /* seasonal decorations */ 166 | 167 | #lights { 168 | position:absolute; 169 | border-top:1px solid #006600; 170 | left:0px; 171 | top:0px; 172 | width:100%; 173 | height:275px; 174 | overflow:hidden; 175 | z-index:1; 176 | display:none; 177 | } 178 | 179 | .xlsf-light { 180 | position:absolute; 181 | margin-top:-1px; 182 | } 183 | 184 | .xlsf-fragment { 185 | position:absolute; 186 | background:transparent url(../lights/image/bulbs-50x50-fragments.png) no-repeat 0px 0px; 187 | width:50px; 188 | height:50px; 189 | } 190 | 191 | .xlsf-fragment-box { 192 | position:absolute; 193 | left:0px; 194 | top:0px; 195 | width:50px; 196 | height:50px; 197 | *width:100%; 198 | *height:100%; 199 | display:none; 200 | } 201 | 202 | .xlsf-cover { 203 | position:fixed; 204 | left:0px; 205 | top:0px; 206 | width:100%; 207 | height:100%; 208 | background:#fff; 209 | opacity:1; 210 | z-index:999; 211 | display:none; 212 | } 213 | 214 | .special { 215 | display:none; 216 | _display: block; /* just you, IE 6. */ 217 | font-size:x-small; 218 | color:#999; 219 | } 220 | 221 | ul li { 222 | line-height:1.75em; 223 | } -------------------------------------------------------------------------------- /snowstorm-min.js: -------------------------------------------------------------------------------- 1 | /** @license 2 | 3 | DHTML Snowstorm! JavaScript-based snow for web pages 4 | Making it snow on the internets since 2003. You're welcome. 5 | ----------------------------------------------------------- 6 | Version 1.44.20131215 (Previous rev: 1.44.20131208) 7 | Copyright (c) 2007, Scott Schiller. All rights reserved. 8 | Code provided under the BSD License 9 | http://schillmania.com/projects/snowstorm/license.txt 10 | */ 11 | var snowStorm=function(g,f){function k(a,d){isNaN(d)&&(d=0);return Math.random()*a+d}function x(){g.setTimeout(function(){a.start(!0)},20);a.events.remove(m?f:g,"mousemove",x)}function y(){(!a.excludeMobile||!D)&&x();a.events.remove(g,"load",y)}this.excludeMobile=this.autoStart=!0;this.flakesMax=128;this.flakesMaxActive=64;this.animationInterval=33;this.useGPU=!0;this.className=null;this.excludeMobile=!0;this.flakeBottom=null;this.followMouse=!0;this.snowColor="#fff";this.snowCharacter="•";this.snowStick= 12 | !0;this.targetElement=null;this.useMeltEffect=!0;this.usePixelPosition=this.usePositionFixed=this.useTwinkleEffect=!1;this.freezeOnBlur=!0;this.flakeRightOffset=this.flakeLeftOffset=0;this.flakeHeight=this.flakeWidth=8;this.vMaxX=5;this.vMaxY=4;this.zIndex=0;var a=this,q,m=navigator.userAgent.match(/msie/i),E=navigator.userAgent.match(/msie 6/i),D=navigator.userAgent.match(/mobile|opera m(ob|in)/i),r=m&&"BackCompat"===f.compatMode||E,h=null,n=null,l=null,p=null,s=null,z=null,A=null,v=1,t=!1,w=!1, 13 | u;a:{try{f.createElement("div").style.opacity="0.5"}catch(F){u=!1;break a}u=!0}var B=!1,C=f.createDocumentFragment();q=function(){function c(b){g.setTimeout(b,1E3/(a.animationInterval||20))}function d(a){return void 0!==h.style[a]?a:null}var e,b=g.requestAnimationFrame||g.webkitRequestAnimationFrame||g.mozRequestAnimationFrame||g.oRequestAnimationFrame||g.msRequestAnimationFrame||c;e=b?function(){return b.apply(g,arguments)}:null;var h;h=f.createElement("div");e={transform:{ie:d("-ms-transform"), 14 | moz:d("MozTransform"),opera:d("OTransform"),webkit:d("webkitTransform"),w3:d("transform"),prop:null},getAnimationFrame:e};e.transform.prop=e.transform.w3||e.transform.moz||e.transform.webkit||e.transform.ie||e.transform.opera;h=null;return e}();this.timer=null;this.flakes=[];this.active=this.disabled=!1;this.meltFrameCount=20;this.meltFrames=[];this.setXY=function(c,d,e){if(!c)return!1;a.usePixelPosition||w?(c.style.left=d-a.flakeWidth+"px",c.style.top=e-a.flakeHeight+"px"):r?(c.style.right=100-100* 15 | (d/h)+"%",c.style.top=Math.min(e,s-a.flakeHeight)+"px"):a.flakeBottom?(c.style.right=100-100*(d/h)+"%",c.style.top=Math.min(e,s-a.flakeHeight)+"px"):(c.style.right=100-100*(d/h)+"%",c.style.bottom=100-100*(e/l)+"%")};this.events=function(){function a(c){c=b.call(c);var d=c.length;e?(c[1]="on"+c[1],3b.vX?b.vX=0.2:0>b.vX&&-0.2b.vY&&(b.vY=0.2)};this.move=function(){var c=b.vX*v;b.x+=c;b.y+=b.vY*b.vAmp;b.x>=h||h-b.xc&&b.x-a.flakeLeftOffset<-a.flakeWidth&&(b.x=h-a.flakeWidth-1);b.refresh();l+p-b.y+a.flakeHeightb.type&&!b.melting&&0.998b.twinkleFrame?0.97a.flakesMaxActive)a.flakes[a.flakes.length-1].active=-1;a.targetElement.appendChild(C)};this.timerInit= 27 | function(){a.timer=!0;a.snow()};this.init=function(){var c;for(c=0;c1800?'small':'pico'); // kind of light to show (32px to 96px square) 51 | 52 | if (window.location.href.match(/size=/i)) { 53 | this.lightClass = window.location.href.substr(window.location.href.indexOf('size=')+5); 54 | } 55 | 56 | this.lightXY = this.lightClasses[this.lightClass]; // shortcut to w/h 57 | 58 | this.lightGroups = { 59 | left: [], 60 | top: [], 61 | right: [], 62 | bottom: [] 63 | } 64 | this.lightSmashCounter = 0; 65 | this.lightIndex = 0; 66 | this.lightInterval = 500; 67 | this.timer = null; 68 | this.bgBaseX = 0; 69 | this.bgBaseY = 0; 70 | this.soundIDs = 0; 71 | this.soundPan = { 72 | panValue: 75, 73 | left: 0, 74 | mid: 481, 75 | right: 962 76 | } 77 | 78 | this.cover = document.createElement('div'); 79 | this.cover.className = 'xlsf-cover'; 80 | document.documentElement.appendChild(this.cover); 81 | 82 | this.initSounds = function() { 83 | for (var i=0; i<6; i++) { 84 | soundManager.createSound({ 85 | id: 'smash'+i, 86 | url: urlBase+'sound/glass'+i+'.mp3', 87 | autoLoad: true, 88 | multiShot: true, 89 | volume:50 90 | }); 91 | } 92 | self.initSounds = function() {} // safety net 93 | } 94 | 95 | this.appendLights = function() { 96 | writeDebug('xlsf.appendLights()'); 97 | self.oTarget.appendChild(self.oFrag); 98 | self.oFrag = document.createDocumentFragment(); 99 | } 100 | 101 | function ExplosionFragment(nType,sClass,x,y,vX,vY) { 102 | var self = this; 103 | this.o = xlsf.oExplosionFrag.cloneNode(true); 104 | this.nType = nType; 105 | this.sClass = sClass; 106 | this.x = x; 107 | this.y = y; 108 | this.w = 50; 109 | this.h = 50; 110 | this.bgBaseX = 0; 111 | this.bgBaseY = this.h*this.nType; 112 | this.vX = vX*(1.5+Math.random()); 113 | this.vY = vY*(1.5+Math.random()); 114 | this.oA = null; 115 | this.oA2 = null; 116 | this.burstPhase = 1; // starting background offset point 117 | this.burstPhases = 4; // 1+offset (ignore large size) 118 | this.o.style.backgroundPosition = ((this.w*-this.burstPhase)+'px '+(this.h*-nType)+'px'); 119 | 120 | // boundary checks 121 | if (self.sClass == 'left') { 122 | this.vX = Math.abs(this.vX); 123 | } else if (self.sClass == 'right') { 124 | this.vX = Math.abs(this.vX)*-1; 125 | } 126 | 127 | this.burstTween = function() { 128 | // determine frame to show 129 | var phase = 1+Math.floor((this.currentFrame/this.totalFrames)*self.burstPhases); 130 | if (phase != self.burstPhase) { 131 | self.burstPhase = phase; 132 | self.o.style.backgroundPosition = ((self.w*-self.burstPhase)+'px '+(self.h*-nType)+'px'); 133 | } 134 | } 135 | 136 | this.burst = function() { 137 | self.oA = new Y.A(self.o,{marginLeft:{to:(self.vX*8)},marginTop:{to:(self.vY*8)}},animDuration,Y.UE.easeOutStrong); 138 | self.oA.onTween.subscribe(self.burstTween); 139 | self.oA.animate(); 140 | } 141 | 142 | this.hide = function() { 143 | if (!isIE) self.o.style.opacity = 0; 144 | } 145 | 146 | this.reset = function() { 147 | self.o.style.left = '0px'; 148 | self.o.style.top = '0px'; 149 | self.o.style.marginLeft = '0px'; 150 | self.o.style.marginTop = '0px'; 151 | if (!isIE) self.o.style.opacity = 1; 152 | } 153 | 154 | this.animate = function() { 155 | self.reset(); 156 | self.burst(); 157 | } 158 | 159 | } 160 | 161 | function Explosion(nType,sClass,x,y) { 162 | var oParent = this; 163 | var self = this; 164 | this.o = null; 165 | this.nType = nType; 166 | this.sClass = sClass; 167 | this.x = x; 168 | this.y = y; 169 | this.boxVX = 0; 170 | this.boxVY = 0; 171 | this.o = xlsf.oExplosionBox.cloneNode(true); 172 | this.o.style.left = x+'px'; 173 | this.o.style.top = y+'px'; 174 | this.fragments = []; 175 | 176 | var mX = x; 177 | var mY = y; 178 | 179 | this.fragments.push(new ExplosionFragment(nType,sClass,mX,mY,-5,-5)); 180 | this.fragments.push(new ExplosionFragment(nType,sClass,mX,mY,0,-5)); 181 | this.fragments.push(new ExplosionFragment(nType,sClass,mX,mY,5,-5)); 182 | 183 | this.fragments.push(new ExplosionFragment(nType,sClass,mX,mY,-5,0)); 184 | this.fragments.push(new ExplosionFragment(nType,sClass,mX,mY,0,0)); 185 | this.fragments.push(new ExplosionFragment(nType,sClass,mX,mY,5,0)); 186 | 187 | this.fragments.push(new ExplosionFragment(nType,sClass,mX,mY,5,-5)); 188 | this.fragments.push(new ExplosionFragment(nType,sClass,mX,mY,5,0)); 189 | this.fragments.push(new ExplosionFragment(nType,sClass,mX,mY,5,5)); 190 | 191 | this.init = function() { 192 | for (var i=self.fragments.length; i--;) { 193 | self.o.appendChild(self.fragments[i].o); 194 | } 195 | if (!IS_MOON_COMPUTER) { 196 | // faster rendering, particles get cropped 197 | xlsf.oFrag.appendChild(self.o); 198 | } else { 199 | // slower rendering, can overlay body 200 | xlsf.oFrag.appendChild(self.o); 201 | } 202 | } 203 | 204 | this.reset = function() { 205 | // clean-up 206 | // self.o.parentNode.removeChild(self.o); 207 | self.o.style.display = 'none'; 208 | self.o.style.marginLeft = '0px'; 209 | self.o.style.marginTop = '0px'; 210 | self.o.style.left = self.x+'px'; 211 | self.o.style.top = self.y+'px'; 212 | if (!isIE) self.o.style.opacity = 1; 213 | for (var i=self.fragments.length; i--;) { 214 | self.fragments[i].reset(); 215 | } 216 | } 217 | 218 | this.trigger = function(boxVX,boxVY) { 219 | self.o.style.display = 'block'; 220 | self.boxVX = boxVX; 221 | self.boxVY = boxVY; 222 | // boundary checks 223 | if (self.sClass == 'right') { 224 | self.boxVX = Math.abs(self.boxVX)*-1; 225 | } else if (self.sClass == 'left') { 226 | self.boxVX = Math.abs(self.boxVX); 227 | } 228 | for (var i=self.fragments.length; i--;) { 229 | self.fragments[i].animate(); 230 | } 231 | if (!isIE && (IS_MOON_COMPUTER)) { 232 | var oAExplode = new Y.A(self.o,{marginLeft:{to:100*self.boxVX},marginTop:{to:150*self.boxVY},opacity:{to:0.01}},animDuration,Y.UE.easeInStrong); 233 | } else { 234 | // even IE 7 sucks w/alpha-transparent PNG + CSS opacity. Boo urns. 235 | var oAExplode = new Y.A(self.o,{marginLeft:{to:100*self.boxVX},marginTop:{to:150*self.boxVY}},animDuration,Y.UE.easeInStrong); 236 | } 237 | oAExplode.onComplete.subscribe(self.reset); 238 | oAExplode.animate(); 239 | } 240 | 241 | this.init(); 242 | 243 | } 244 | 245 | function Light(sSizeClass,sClass,nType,x,y) { 246 | var self = this; 247 | this.o = document.createElement('div'); 248 | this.sClass = sClass; 249 | this.sSizeClass = sSizeClass; 250 | this.nType = (nType||0); 251 | this.useY = (sClass == 'left' || sClass == 'right'); 252 | this.state = null; 253 | this.broken = 0; 254 | this.w = xlsf.lightClasses[sSizeClass]; 255 | this.h = xlsf.lightClasses[sSizeClass]; 256 | this.x = x; 257 | this.y = y; 258 | this.bg = urlBase+'image/bulbs-'+this.w+'x'+this.h+'-'+this.sClass+'.png'; 259 | this.o.style.width = this.w+'px'; 260 | this.o.style.height = this.h+'px'; 261 | this.o.style.background = 'url('+this.bg+') no-repeat 0px 0px'; 262 | this.bgBaseX = (self.useY?-self.w*this.nType:0); 263 | this.bgBaseY = (!self.useY?-self.h*this.nType:0); 264 | this.glassType = parseInt(Math.random()*6); 265 | this.oExplosion = null; 266 | this.soundID = 'smash'+this.glassType; 267 | var panValue = xlsf.soundPan.panValue; // eg. +/- 80% 268 | this.pan = parseInt(this.x<=xlsf.soundPan.mid?-panValue+((this.x/xlsf.soundPan.mid)*panValue):(this.x-xlsf.soundPan.mid)/(xlsf.soundPan.right-xlsf.soundPan.mid)*panValue); 269 | 270 | this.initSound = function() { 271 | } 272 | 273 | this.setBGPos = function(x,y) { 274 | self.o.style.backgroundPosition = ((self.bgBaseX+x)+'px '+(self.bgBaseY+y)+'px'); 275 | } 276 | 277 | this.setLight = function(bOn) { 278 | if (self.broken || self.state == bOn) return false; 279 | if (!self.w || !self.h) self.getDimensions(); 280 | self.state = bOn; 281 | if (self.useY) { 282 | self.setBGPos(0,-this.h*(bOn?0:1)); 283 | } else { 284 | self.setBGPos(-this.w*(bOn?0:1),0); 285 | } 286 | } 287 | 288 | this.getDimensions = function() { 289 | self.w = self.o.offsetWidth; 290 | self.h = self.o.offsetHeight; 291 | self.bgBaseX = (self.useY?-self.w*self.nType:0); 292 | self.bgBaseY = (!self.useY?-self.h*self.nType:0); 293 | } 294 | 295 | this.on = function() { 296 | self.setLight(1); 297 | } 298 | 299 | this.off = function() { 300 | self.setLight(0); 301 | } 302 | 303 | this.flickr = function() { 304 | self.setLight(Math.random()>=0.5?1:0); 305 | } 306 | 307 | this.toggle = function() { 308 | self.setLight(!self.state?1:0); 309 | } 310 | 311 | this.explode = function(e) { 312 | self.oExplosion.trigger(0,1); // boooom! 313 | } 314 | 315 | this.smash = function(e) { 316 | if (self.broken) return false; 317 | self.broken = true; 318 | if (soundManager && soundManager.ok()) { 319 | soundManager.play(self.soundID,{pan:self.pan}); 320 | // soundManager.sounds[self.soundID].play({pan:self.pan}); 321 | // if (self.bonusSound != null) window.setTimeout(self.smashBonus,1000); 322 | } 323 | self.explode(e); 324 | var rndFrame = 2; // +parseInt(Math.random()*3); 325 | if (self.useY) { 326 | self.setBGPos(0,self.h*-rndFrame); 327 | } else { 328 | self.setBGPos(self.w*-rndFrame,0); 329 | } 330 | xlsf.lightSmashCounter++; 331 | } 332 | 333 | this.smashBonus = function() { 334 | // soundManager.play(self.bonusSounds[self.bonusSound],urlBase+'sound/'+self.bonusSounds[self.bonusSound]+'.mp3'); 335 | } 336 | 337 | this.reset = function() { 338 | if (!self.broken) return false; 339 | self.broken = false; 340 | self.state = null; 341 | xlsf.lightSmashCounter--; 342 | self.flickr(); 343 | } 344 | 345 | this.init = function() { 346 | self.o.className = 'xlsf-light '+this.sSizeClass+' '+this.sClass; 347 | self.o.style.left = self.x+'px'; 348 | self.o.style.top = self.y+'px'; 349 | self.o.style.width = self.w+'px'; 350 | self.o.style.height = self.h+'px'; 351 | self.o.onmouseover = self.smash; 352 | self.o.onclick = self.smash; 353 | self.flickr(); 354 | xlsf.oFrag.appendChild(self.o); 355 | self.oExplosion = new Explosion(self.nType,self.sClass,self.x,self.y); 356 | } 357 | 358 | this.init(); 359 | 360 | } // Light() 361 | 362 | this.createLight = function(sClass,nType,x,y) { 363 | var oLight = new Light(self.lightClass,sClass,nType,x,y); 364 | self.lightGroups[sClass].push(oLight); 365 | self.lights.push(oLight); 366 | return oLight; 367 | } 368 | 369 | this.rotateLights = function() { 370 | self.lights[self.lightIndex==self.lights.length?self.lights.length-1:self.lightIndex].off(); 371 | self.lightIndex++; 372 | if (self.lightIndex == self.lights.length) { 373 | self.lightIndex = 0; 374 | } 375 | self.lights[self.lightIndex].on(); 376 | } 377 | 378 | this.randomLights = function() { 379 | self.lights[parseInt(Math.random()*self.lights.length)].toggle(); 380 | } 381 | 382 | 383 | this.destroyLights = function() { 384 | self.startSequence(self.destroyLight,20); 385 | } 386 | 387 | this.destroyLight = function() { 388 | var groupSize = 2; // # to smash at a time 389 | if (self.lightSmashCounter 430 | var offset = 0; // parseInt(document.getElementsByTagName('h1')[0].offsetWidth)+16; 431 | 432 | var jMax = Math.floor((screenX-offset-16)/self.lightXY); 433 | var iMax = Math.floor((screenY-offset-16)/self.lightXY); 434 | 435 | for (j=0; j 3 | 4 | 5 | JavaScript Snow: DHTML Snowstorm. Making it snow on the internets since 2003. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
32 | 33 |
34 | 35 |
36 | 37 |

Snowstorm: A JavaScript Snow Effect for HTML

38 |

Bringing snow to the web since 2003. This version: 1.44.20131208

39 | 40 |

41 | Change Wind | Stop Snowing | Bonus widget: Smash Christmas Lights 42 |

43 |

(Note: Christmas Lights are incompatible with IE 6 because of PNG images.)

44 | 45 |

Let It Snow.

46 | 47 |

So, you want JavaScript snow on your web site, eh?

48 | 49 |

Snowstorm is a JavaScript-driven snow effect that can be easily added to web pages. It is free for use, and easy to set up. A single JavaScript file provides the functionality required. No images are used for the snow effect.

50 | 51 |

I'd like to use this on my site.

52 | 53 |

This is all you need to get started:

54 | 55 |

56 |

<script src="snowstorm.js"></script>
57 |

58 | 59 |

See this basic example for reference.

60 | 61 |

What kind of things can I customize?

62 | 63 |

You can adjust the snow speed, the amount of snow, the "wind", if and where it should stick (and if it should "melt"), and finally, whether the snow can react to the mouse moving (ie., "wind changes.") See Customizing Snowstorm for more.

64 | 65 |

And the Christmas Lights?

66 | 67 |

The christmas lights are a separate experimental script which also has an example. It is undocumented, but the script can be modified to taste if you're the adventurous type.

68 | 69 |

Download

70 |

ZIP file, includes this demo page and source code.

71 | 72 | 75 | 76 |

Also on Github: github.com/scottschiller/snowstorm/

77 | 78 |

License

79 |

Snowstorm is provided under a BSD license.

80 | 81 |

Technical Notes

82 | 83 |

Snowstorm works under modern browsers, and as far back as IE 6 - possibly even 5.5, if you can find a copy!

84 |

If you are seeing snow as you read this, then the script is working as expected.

85 | 86 |

CPU Use

87 | 88 |

Snowstorm can eat up a lot of CPU, even on modern computers, because of the number of elements being moved around the screen at once. The basic example may have notably lower CPU use as it doesn't include the christmas lights, and the page layout is much simpler. Consider raising the animation interval, and lowering the amount of snowflakes (active and max) to help reduce CPU use.

89 | 90 |

Where supported, Snowstorm will attempt to use GPU-based hardware acceleration to draw and animate the snow. Having GPU acceleration can help in reducing CPU load.

91 | 92 |

Mobile Support

93 | 94 |

By default, mobile devices are excluded from the snow effect to be nice to their CPUs (and batteries.) If your local marketing department insists, "This must work on mobile!" despite being warned of the downsides, you can set snowStorm.excludeMobile = false; (or edit the snowstorm.js file directly) to enable Snowstorm on devices like the iPhone, iPad and Android phones etc. This demo page has the effect enabled for mobile devices.

95 | 96 |

Implementation

97 | 98 |

One JavaScript reference is required. Aside from customization, that's it!

99 | 100 |
101 | <script src="snowstorm.js"></script>
102 | 
103 | 104 |

Once you have snowstorm configured, you can use the optimized, minified version of the code (~40% smaller):

105 | 106 |

107 |

<script src="snowstorm-min.js"></script>
108 |

109 | 110 |

Customizing Snowstorm

111 | 112 |

Once you have Snowstorm running in your page, you can customize its properties either by editing the snowstorm.js file directly, or assigning new values to the snowStorm object after snowstorm.js has loaded.

113 | 114 |

For example:

115 | 116 |
117 | <!-- required snowstorm JS, default behaviour -->
118 | <script src="snowstorm.js"></script>
119 | 
120 | <!-- now, we'll customize the snowStorm object -->
121 | <script>
122 | snowStorm.snowColor = '#99ccff';   // blue-ish snow!?
123 | snowStorm.flakesMaxActive = 96;    // show more snow on screen at once
124 | snowStorm.useTwinkleEffect = true; // let the snow flicker in and out of view
125 | </script>
126 | 
127 | 128 |

See this customized example in action.

129 | 130 |

Configurable Properties

131 | 132 |

Snowstorm can be fairly easily customized; some of the major properties are listed below.

133 | 134 |
135 | 136 |
snowStorm.autoStart = true;
137 |
Whether the snow should start automatically or not.
138 | 139 |
snowStorm.animationInterval = 33;
140 |
Theoretical "milliseconds per frame" measurement. 20 = fast + smooth, but high CPU use. 50 = more conservative, but slower
141 | 142 |
snowStorm.flakeBottom = null;
143 |
Limits the "floor" (pixels) of the snow. If unspecified, snow will "stick" to the bottom of the browser window and persists through browser resize/scrolling.
144 | 145 |
snowStorm.flakesMax = 128;
146 |
Sets the maximum number of snowflakes that can exist on the screen at any given time.
147 | 148 |
snowStorm.flakesMaxActive = 64;
149 |
Sets the limit of "falling" snowflakes (ie. moving on the screen, thus considered to be active.)
150 | 151 |
snowStorm.followMouse = true;
152 |
Allows snow to move dynamically with the "wind", relative to the mouse's X (left/right) coordinates.
153 | 154 |
snowStorm.freezeOnBlur = true;
155 |
Stops the snow effect when the browser window goes out of focus, eg., user is in another tab. Saves CPU, nicer to user.
156 | 157 |
snowStorm.snowColor = '#fff';
158 |
Don't eat (or use?) yellow snow.
159 | 160 |
snowStorm.snowCharacter = '•';
161 |
&bull; (•) = bullet. &middot; entity (·) is not used as it's square on some systems etc. Changing this may result in cropping of the character and may require flakeWidth/flakeHeight changes, so be careful.
162 | 163 |
snowStorm.snowStick = true;
164 |
Allows the snow to "stick" to the bottom of the window. When off, snow will never sit at the bottom.
165 | 166 |
snowStorm.targetElement = null;
167 |
An HTML element which snow will be appended to (default: document body.) Can be an element ID string eg. 'myDiv', or a DOM node reference. See relative and absolute-positioned examples.
168 | 169 |
snowStorm.useMeltEffect = true;
170 |
When recycling fallen snow (or rarely, when falling), have it "melt" and fade out if browser supports it
171 | 172 |
snowStorm.useTwinkleEffect = true;
173 |
Allow snow to randomly "flicker" in and out of view while falling
174 | 175 |
snowStorm.usePositionFixed = false;
176 |
true = snow not affected by window scroll. may increase CPU load, disabled by default - if enabled, used only where supported.
177 | 178 |
snowStorm.vMaxX = 8;
snowStorm.vMaxY = 5;
179 |
Defines maximum X and Y velocities for the storm; a random value in this range is selected for each snowflake.
180 | 181 |
182 | 183 |

Methods

184 | 185 |

Snowstorm has a few basic methods for controlling the snow effect.

186 | 187 |
188 | 189 |
snowStorm.randomizeWind()
190 |
Sets the wind speed with a random value relative to vMaxX and vMaxY properties.
191 | 192 |
snowStorm.freeze()
193 |
Stops the snow effect in place.
194 | 195 |
snowStorm.resume()
196 |
Continues snowing from a "frozen" state.
197 | 198 |
snowStorm.toggleSnow()
199 |
Enables or disables the snow effect depending on state, same as calling freeze() or resume().
200 | 201 |
snowStorm.stop()
202 |
Freezes and kills the snowstorm effect, and removes related event handlers. Snowstorm will not work properly if other methods are called after stop().
203 | 204 |
205 | 206 |

Version History

207 | 208 |

Older versions

209 | 223 | 224 |

1.44.20131208

225 |
    226 |
  • Added usePixelPosition to allow forcing of pixels for left/top positioning vs. percentage-based values.
  • 227 |
  • Detect and force pixel-based positioning if targetElement is specified, or body is relatively-positioned.
  • 228 |
  • Adjust positioning logic for targetElement case.
  • 229 |
230 | 231 | 232 |

1.44.20131125

233 |
    234 |
  • Fixed regression where flakeBottom would result in snow not properly sticking.
  • 235 |
  • Percent based left/right positioning is now applied in all browsers, making resizing better.
  • 236 |
237 | 238 |

1.44.20131111

239 |
    240 |
  • GPU (hardware)-accelerated snow, where supported. Faster drawing, less load on CPU.
  • 241 |
  • Percent-based bottom/right positioning of snow, rather than top/left-based pixel-based positioning (where supported.)
  • 242 |
  • JSLint cleanup.
  • 243 |
  • Fixed the color of christmas light fragments to match the lights, finally.
  • 244 |
  • Design/layout tweaks, slightly more modern.
  • 245 |
246 | 247 |

1.43.20111201

248 |
    249 |
  • ImageOptim-optimized image files (byte savings)
  • 250 |
  • Added snowStorm.autoStart, for those who want to start snow at their own leisure
  • 251 |
  • Additional Mobile check: Opera Mobile
  • 252 |
  • cursor:default over snow (instead of text I-beam cursor)
  • 253 |
  • meltFrame animation counter correction (possible JS error fix)
  • 254 |
255 | 256 |

1.42.20111120

257 |
    258 |
  • Tweaked right margin for IE 9 under Windows 7, fixing horizontal scrollbar issue
  • 259 |
  • Re-appeased the jslint gods
  • 260 |
261 | 262 |

1.41.20101113

263 |
    264 |
  • Added formal BSD license (project was previously "free for any use.")
  • 265 |
  • Modernized event add/remove handlers, wait for window.onload() before starting
  • 266 |
  • New excludeMobile option, ignore iPhone etc. by default (high CPU use on mobile is evil for both CPU, and batteries.)
  • 267 |
  • New freezeOnBlur option, allow control of previously-hardcoded behaviour
  • 268 |
  • Focus-based freezeOnBlur now works under IE 6, too
  • 269 |
  • Code cleanup, now passes updated (more-strict) jslint validation
  • 270 |
271 | 272 |

1.4.20091115

273 |
    274 |
  • Text-based snow (and color options) using "bullet" HTML entity • .. no more images!
  • 275 |
  • New snowMelt effect, resize + fade where supported
  • 276 |
  • New twinkle effect (like stars)
  • 277 |
  • New animationInterval, usePositionFixed, snowColor attributes, common attributes now public on snowStorm object eg. snowStorm.stick = true;
  • 278 |
  • Code passes jslint validation (2009-10-04 edition, default settings)
  • 279 |
  • Removed "collect" feature, somewhat-buggy and nobody used it
  • 280 |
  • Fixed sticky/recycle behaviour
  • 281 |
282 | 283 |

1.3.20081215

284 |
    285 |
  • IE doctype rendering tweak: position:absolute used for "BackCompat" (HTML 4 transitional) DOCTYPE in IE.
  • 286 |
  • Fixed an annoying horizontal scrollbar positioning-related bug with wind affecting snow near the right edge.
  • 287 |
288 | 289 |

1.3.20081208

290 |
    291 |
  • New snowStick (snow stickiness) and followMouse (dynamic wind) options.
  • 292 |
  • Four years later, we still have IE 6 and can't use position:fixed globally for "sticky" snow, but we're really close.
  • 293 |
  • Position:fixed used for all more modern browsers.
  • 294 |
  • Improved distribution of initial snow dump, new recycling.
  • 295 |
  • Focus/blur events (minus IE) for graceful pausing of snow, sparing user's CPU when window not in focus.
  • 296 |
  • Bonus smashable christmas lights demo, using SoundManager 2 and YUI DOM/Event libraries
  • 297 |
  • Cleaner, simplified event code, removal of old PNG wrapper stuff.
  • 298 |
299 | 300 |

1.2.20041121a

301 |
    302 |
  • Script moved into one file (snowstorm.js) for simplicity
  • 303 |
  • addEventHandler and PNG support functions updated
  • 304 |
305 | 306 |

1.2.20031218a

307 |
    308 |
  • Opera 7 ("O7") support added.. I think.
  • 309 |
  • Improved initialization speed (less snowflake objects on startup)
  • 310 |
  • Err.. That's about it.
  • 311 |
312 | 313 |

1.2.20031213a

314 |
    315 |
  • Netscape 6.x "sticky" snow behavior fixed (now works)
  • 316 |
  • IE:mac bug event handler bug fixed (script should now work)
  • 317 |
  • Snow collection feature added
  • 318 |
  • Snowflake speed is relative to size (Cheap pseudo-3D effect)
  • 319 |
320 | 321 |

1.1.20031206c

322 |
    323 |
  • Initial release
  • 324 |
325 | 326 |

Feedback

327 |

Comments, suggestions, questions, criticism?

328 |

329 | A few contact options are available. Get in touch via email or IM. 330 |

331 | 332 |

Elsewhere On The Internets

333 |

334 | This is a side project by Scott Schiller. Wacky DHTML/JavaScript experiments and other nonsense can be found at schillmania.com. 335 |

336 | 337 |
338 | 339 |
340 | 341 | 342 | 343 | 348 | 349 | 350 | 351 | -------------------------------------------------------------------------------- /snowstorm.js: -------------------------------------------------------------------------------- 1 | /** @license 2 | * DHTML Snowstorm! JavaScript-based snow for web pages 3 | * Making it snow on the internets since 2003. You're welcome. 4 | * ----------------------------------------------------------- 5 | * Version 1.44.20131215 (Previous rev: 1.44.20131208) 6 | * Copyright (c) 2007, Scott Schiller. All rights reserved. 7 | * Code provided under the BSD License 8 | * http://schillmania.com/projects/snowstorm/license.txt 9 | */ 10 | 11 | /*jslint nomen: true, plusplus: true, sloppy: true, vars: true, white: true */ 12 | /*global window, document, navigator, clearInterval, setInterval */ 13 | 14 | var snowStorm = (function(window, document) { 15 | 16 | // --- common properties --- 17 | 18 | this.autoStart = true; // Whether the snow should start automatically or not. 19 | this.excludeMobile = true; // Snow is likely to be bad news for mobile phones' CPUs (and batteries.) Enable at your own risk. 20 | this.flakesMax = 128; // Limit total amount of snow made (falling + sticking) 21 | this.flakesMaxActive = 64; // Limit amount of snow falling at once (less = lower CPU use) 22 | this.animationInterval = 33; // Theoretical "miliseconds per frame" measurement. 20 = fast + smooth, but high CPU use. 50 = more conservative, but slower 23 | this.useGPU = true; // Enable transform-based hardware acceleration, reduce CPU load. 24 | this.className = null; // CSS class name for further customization on snow elements 25 | this.flakeBottom = null; // Integer for Y axis snow limit, 0 or null for "full-screen" snow effect 26 | this.followMouse = true; // Snow movement can respond to the user's mouse 27 | this.snowColor = '#fff'; // Don't eat (or use?) yellow snow. 28 | this.snowCharacter = '•'; // • = bullet, · is square on some systems etc. 29 | this.snowStick = true; // Whether or not snow should "stick" at the bottom. When off, will never collect. 30 | this.targetElement = null; // element which snow will be appended to (null = document.body) - can be an element ID eg. 'myDiv', or a DOM node reference 31 | this.useMeltEffect = true; // When recycling fallen snow (or rarely, when falling), have it "melt" and fade out if browser supports it 32 | this.useTwinkleEffect = false; // Allow snow to randomly "flicker" in and out of view while falling 33 | this.usePositionFixed = false; // true = snow does not shift vertically when scrolling. May increase CPU load, disabled by default - if enabled, used only where supported 34 | this.usePixelPosition = false; // Whether to use pixel values for snow top/left vs. percentages. Auto-enabled if body is position:relative or targetElement is specified. 35 | this.accessibility = true; // Hide snow from screen readers 36 | 37 | // --- less-used bits --- 38 | 39 | this.freezeOnBlur = true; // Only snow when the window is in focus (foreground.) Saves CPU. 40 | this.flakeLeftOffset = 0; // Left margin/gutter space on edge of container (eg. browser window.) Bump up these values if seeing horizontal scrollbars. 41 | this.flakeRightOffset = 0; // Right margin/gutter space on edge of container 42 | this.flakeWidth = 8; // Max pixel width reserved for snow element 43 | this.flakeHeight = 8; // Max pixel height reserved for snow element 44 | this.vMaxX = 5; // Maximum X velocity range for snow 45 | this.vMaxY = 4; // Maximum Y velocity range for snow 46 | this.zIndex = 0; // CSS stacking order applied to each snowflake 47 | 48 | // --- "No user-serviceable parts inside" past this point, yadda yadda --- 49 | 50 | var storm = this, 51 | features, 52 | // UA sniffing and backCompat rendering mode checks for fixed position, etc. 53 | isIE = navigator.userAgent.match(/msie/i), 54 | isIE6 = navigator.userAgent.match(/msie 6/i), 55 | isMobile = navigator.userAgent.match(/mobile|opera m(ob|in)/i), 56 | isBackCompatIE = (isIE && document.compatMode === 'BackCompat'), 57 | noFixed = (isBackCompatIE || isIE6), 58 | screenX = null, screenX2 = null, screenY = null, scrollY = null, docHeight = null, vRndX = null, vRndY = null, 59 | windOffset = 1, 60 | windMultiplier = 2, 61 | flakeTypes = 6, 62 | fixedForEverything = false, 63 | targetElementIsRelative = false, 64 | opacitySupported = (function(){ 65 | try { 66 | document.createElement('div').style.opacity = '0.5'; 67 | } catch(e) { 68 | return false; 69 | } 70 | return true; 71 | }()), 72 | didInit = false, 73 | docFrag = document.createDocumentFragment(); 74 | 75 | features = (function() { 76 | 77 | var getAnimationFrame; 78 | 79 | /** 80 | * hat tip: paul irish 81 | * http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 82 | * https://gist.github.com/838785 83 | */ 84 | 85 | function timeoutShim(callback) { 86 | window.setTimeout(callback, 1000/(storm.animationInterval || 20)); 87 | } 88 | 89 | var _animationFrame = (window.requestAnimationFrame || 90 | window.webkitRequestAnimationFrame || 91 | window.mozRequestAnimationFrame || 92 | window.oRequestAnimationFrame || 93 | window.msRequestAnimationFrame || 94 | timeoutShim); 95 | 96 | // apply to window, avoid "illegal invocation" errors in Chrome 97 | getAnimationFrame = _animationFrame ? function() { 98 | return _animationFrame.apply(window, arguments); 99 | } : null; 100 | 101 | var testDiv; 102 | 103 | testDiv = document.createElement('div'); 104 | 105 | function has(prop) { 106 | 107 | // test for feature support 108 | var result = testDiv.style[prop]; 109 | return (result !== undefined ? prop : null); 110 | 111 | } 112 | 113 | // note local scope. 114 | var localFeatures = { 115 | 116 | transform: { 117 | ie: has('-ms-transform'), 118 | moz: has('MozTransform'), 119 | opera: has('OTransform'), 120 | webkit: has('webkitTransform'), 121 | w3: has('transform'), 122 | prop: null // the normalized property value 123 | }, 124 | 125 | getAnimationFrame: getAnimationFrame 126 | 127 | }; 128 | 129 | localFeatures.transform.prop = ( 130 | localFeatures.transform.w3 || 131 | localFeatures.transform.moz || 132 | localFeatures.transform.webkit || 133 | localFeatures.transform.ie || 134 | localFeatures.transform.opera 135 | ); 136 | 137 | testDiv = null; 138 | 139 | return localFeatures; 140 | 141 | }()); 142 | 143 | this.timer = null; 144 | this.flakes = []; 145 | this.disabled = false; 146 | this.active = false; 147 | this.meltFrameCount = 20; 148 | this.meltFrames = []; 149 | 150 | this.setXY = function(o, x, y) { 151 | 152 | if (!o) { 153 | return false; 154 | } 155 | 156 | if (storm.usePixelPosition || targetElementIsRelative) { 157 | 158 | o.style.left = (x - storm.flakeWidth) + 'px'; 159 | o.style.top = (y - storm.flakeHeight) + 'px'; 160 | 161 | } else if (noFixed) { 162 | 163 | o.style.right = (100-(x/screenX*100)) + '%'; 164 | // avoid creating vertical scrollbars 165 | o.style.top = (Math.min(y, docHeight-storm.flakeHeight)) + 'px'; 166 | 167 | } else { 168 | 169 | if (!storm.flakeBottom) { 170 | 171 | // if not using a fixed bottom coordinate... 172 | o.style.right = (100-(x/screenX*100)) + '%'; 173 | o.style.bottom = (100-(y/screenY*100)) + '%'; 174 | 175 | } else { 176 | 177 | // absolute top. 178 | o.style.right = (100-(x/screenX*100)) + '%'; 179 | o.style.top = (Math.min(y, docHeight-storm.flakeHeight)) + 'px'; 180 | 181 | } 182 | 183 | } 184 | 185 | }; 186 | 187 | this.events = (function() { 188 | 189 | var old = (!window.addEventListener && window.attachEvent), slice = Array.prototype.slice, 190 | evt = { 191 | add: (old?'attachEvent':'addEventListener'), 192 | remove: (old?'detachEvent':'removeEventListener') 193 | }; 194 | 195 | function getArgs(oArgs) { 196 | var args = slice.call(oArgs), len = args.length; 197 | if (old) { 198 | args[1] = 'on' + args[1]; // prefix 199 | if (len > 3) { 200 | args.pop(); // no capture 201 | } 202 | } else if (len === 3) { 203 | args.push(false); 204 | } 205 | return args; 206 | } 207 | 208 | function apply(args, sType) { 209 | var element = args.shift(), 210 | method = [evt[sType]]; 211 | if (old) { 212 | element[method](args[0], args[1]); 213 | } else { 214 | element[method].apply(element, args); 215 | } 216 | } 217 | 218 | function addEvent() { 219 | apply(getArgs(arguments), 'add'); 220 | } 221 | 222 | function removeEvent() { 223 | apply(getArgs(arguments), 'remove'); 224 | } 225 | 226 | return { 227 | add: addEvent, 228 | remove: removeEvent 229 | }; 230 | 231 | }()); 232 | 233 | function rnd(n,min) { 234 | if (isNaN(min)) { 235 | min = 0; 236 | } 237 | return (Math.random()*n)+min; 238 | } 239 | 240 | function plusMinus(n) { 241 | return (parseInt(rnd(2),10)===1?n*-1:n); 242 | } 243 | 244 | this.randomizeWind = function() { 245 | var i; 246 | vRndX = plusMinus(rnd(storm.vMaxX,0.2)); 247 | vRndY = rnd(storm.vMaxY,0.2); 248 | if (this.flakes) { 249 | for (i=0; i=0 && s.vX<0.2) { 416 | s.vX = 0.2; 417 | } else if (s.vX<0 && s.vX>-0.2) { 418 | s.vX = -0.2; 419 | } 420 | if (s.vY>=0 && s.vY<0.2) { 421 | s.vY = 0.2; 422 | } 423 | }; 424 | 425 | this.move = function() { 426 | var vX = s.vX*windOffset, yDiff; 427 | s.x += vX; 428 | s.y += (s.vY*s.vAmp); 429 | if (s.x >= screenX || screenX-s.x < storm.flakeWidth) { // X-axis scroll check 430 | s.x = 0; 431 | } else if (vX < 0 && s.x-storm.flakeLeftOffset < -storm.flakeWidth) { 432 | s.x = screenX-storm.flakeWidth-1; // flakeWidth; 433 | } 434 | s.refresh(); 435 | yDiff = screenY+scrollY-s.y+storm.flakeHeight; 436 | if (yDiff0.998) { 445 | // ~1/1000 chance of melting mid-air, with each frame 446 | s.melting = true; 447 | s.melt(); 448 | // only incrementally melt one frame 449 | // s.melting = false; 450 | } 451 | if (storm.useTwinkleEffect) { 452 | if (s.twinkleFrame < 0) { 453 | if (Math.random() > 0.97) { 454 | s.twinkleFrame = parseInt(Math.random() * 8, 10); 455 | } 456 | } else { 457 | s.twinkleFrame--; 458 | if (!opacitySupported) { 459 | s.o.style.visibility = (s.twinkleFrame && s.twinkleFrame % 2 === 0 ? 'hidden' : 'visible'); 460 | } else { 461 | s.o.style.opacity = (s.twinkleFrame && s.twinkleFrame % 2 === 0 ? 0 : 1); 462 | } 463 | } 464 | } 465 | } 466 | }; 467 | 468 | this.animate = function() { 469 | // main animation loop 470 | // move, check status, die etc. 471 | s.move(); 472 | }; 473 | 474 | this.setVelocities = function() { 475 | s.vX = vRndX+rnd(storm.vMaxX*0.12,0.1); 476 | s.vY = vRndY+rnd(storm.vMaxY*0.12,0.1); 477 | }; 478 | 479 | this.setOpacity = function(o,opacity) { 480 | if (!opacitySupported) { 481 | return false; 482 | } 483 | o.style.opacity = opacity; 484 | }; 485 | 486 | this.melt = function() { 487 | if (!storm.useMeltEffect || !s.melting) { 488 | s.recycle(); 489 | } else { 490 | if (s.meltFrame < s.meltFrameCount) { 491 | s.setOpacity(s.o,s.meltFrames[s.meltFrame]); 492 | s.o.style.fontSize = s.fontSize-(s.fontSize*(s.meltFrame/s.meltFrameCount))+'px'; 493 | s.o.style.lineHeight = storm.flakeHeight+2+(storm.flakeHeight*0.75*(s.meltFrame/s.meltFrameCount))+'px'; 494 | s.meltFrame++; 495 | } else { 496 | s.recycle(); 497 | } 498 | } 499 | }; 500 | 501 | this.recycle = function() { 502 | s.o.style.display = 'none'; 503 | s.o.style.position = (fixedForEverything?'fixed':'absolute'); 504 | s.o.style.bottom = 'auto'; 505 | s.setVelocities(); 506 | s.vCheck(); 507 | s.meltFrame = 0; 508 | s.melting = false; 509 | s.setOpacity(s.o,1); 510 | s.o.style.padding = '0px'; 511 | s.o.style.margin = '0px'; 512 | s.o.style.fontSize = s.fontSize+'px'; 513 | s.o.style.lineHeight = (storm.flakeHeight+2)+'px'; 514 | s.o.style.textAlign = 'center'; 515 | s.o.style.verticalAlign = 'baseline'; 516 | s.x = parseInt(rnd(screenX-storm.flakeWidth-20),10); 517 | s.y = parseInt(rnd(screenY)*-1,10)-storm.flakeHeight; 518 | s.refresh(); 519 | s.o.style.display = 'block'; 520 | s.active = 1; 521 | }; 522 | 523 | this.recycle(); // set up x/y coords etc. 524 | this.refresh(); 525 | 526 | }; 527 | 528 | this.snow = function() { 529 | var active = 0, flake = null, i, j; 530 | for (i=0, j=storm.flakes.length; istorm.flakesMaxActive) { 568 | storm.flakes[storm.flakes.length-1].active = -1; 569 | } 570 | } 571 | storm.targetElement.appendChild(docFrag); 572 | }; 573 | 574 | this.timerInit = function() { 575 | storm.timer = true; 576 | storm.snow(); 577 | }; 578 | 579 | this.init = function() { 580 | var i; 581 | for (i=0; iopera.version()?new Audio(null):new Audio).canPlayType!==k}catch(ib){Ia=!1}this.hasHTML5=Ia;this.setup=function(b){var e=!c.url;b!==k&&p&&u&&c.ok();oa(b); 20 | b&&(e&&(N&&b.url!==k)&&c.beginDelayedInit(),!N&&(b.url!==k&&"complete"===n.readyState)&&setTimeout(G,1));return c};this.supported=this.ok=function(){return u?p&&!y:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(b){return W(b)||n[b]||g[b]};this.createSound=function(b,e){function d(){a=aa(a);c.sounds[a.id]=new Ja(a);c.soundIDs.push(a.id);return c.sounds[a.id]}var a,f=null;if(!p||!c.ok())return!1;e!==k&&(b={id:b,url:e});a=w(b);a.url=da(a.url);void 0===a.id&&(a.id=c.setupOptions.idPrefix+Ya++);if(r(a.id, 21 | !0))return c.sounds[a.id];if(ea(a))f=d(),f._setup_html5(a);else{if(c.html5Only||c.html5.usingFlash&&a.url&&a.url.match(/data\:/i))return d();8a.instanceCount?(n(),f=a._setup_html5(),a.setPosition(a._iO.position),f.play()):(h=new Audio(a._iO.url),g=function(){t.remove(h,"ended",g);a._onfinish(a);fa(h);h=null},J=function(){t.remove(h,"canplay",J);try{h.currentTime=a._iO.position/1E3}catch(b){}h.play()},t.add(h,"ended",g),void 0!==a._iO.volume&&(h.volume=Math.max(0,Math.min(1,a._iO.volume/100))),a.muted&&(h.muted=!0),a._iO.position? 37 | t.add(h,"canplay",J):h.play()):(f=l._start(a.id,a._iO.loops||1,9===m?a.position:a.position/1E3,a._iO.multiShot||!1),9===m&&!f&&a._iO.onplayerror&&a._iO.onplayerror.apply(a))}return a};this.stop=function(b){var c=a._iO;1===a.playState&&(a._onbufferchange(0),a._resetOnPosition(0),a.paused=!1,a.isHTML5||(a.playState=0),x(),c.to&&a.clearOnPosition(c.to),a.isHTML5?a._a&&(b=a.position,a.setPosition(0),a.position=b,a._a.pause(),a.playState=0,a._onTimer(),g()):(l._stop(a.id,b),c.serverURL&&a.unload()),a.instanceCount= 38 | 0,a._iO={},c.onstop&&c.onstop.apply(a));return a};this.setAutoPlay=function(b){a._iO.autoPlay=b;a.isHTML5||(l._setAutoPlay(a.id,b),b&&!a.instanceCount&&1===a.readyState&&a.instanceCount++)};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPosition=function(b){b===k&&(b=0);var c=a.isHTML5?Math.max(b,0):Math.min(a.duration||a._iO.duration,Math.max(b,0));a.position=c;b=a.position/1E3;a._resetOnPosition(a.position);a._iO.position=c;if(a.isHTML5){if(a._a){if(a._html5_canplay){if(a._a.currentTime!== 39 | b)try{a._a.currentTime=b,(0===a.playState||a.paused)&&a._a.pause()}catch(e){}}else if(b)return a;a.paused&&a._onTimer(!0)}}else b=9===m?a.position:b,a.readyState&&2!==a.readyState&&l._setPosition(a.id,b,a.paused||!a.playState,a._iO.multiShot);return a};this.pause=function(b){if(a.paused||0===a.playState&&1!==a.readyState)return a;a.paused=!0;a.isHTML5?(a._setup_html5().pause(),g()):(b||b===k)&&l._pause(a.id,a._iO.multiShot);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){var b= 40 | a._iO;if(!a.paused)return a;a.paused=!1;a.playState=1;a.isHTML5?(a._setup_html5().play(),n()):(b.isMovieStar&&!b.serverURL&&a.setPosition(a.position),l._pause(a.id,b.multiShot));!s&&b.onplay?(b.onplay.apply(a),s=!0):b.onresume&&b.onresume.apply(a);return a};this.togglePause=function(){if(0===a.playState)return a.play({position:9===m&&!a.isHTML5?a.position:a.position/1E3}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(b,c){b===k&&(b=0);c===k&&(c=!1);a.isHTML5||l._setPan(a.id,b);a._iO.pan= 41 | b;c||(a.pan=b,a.options.pan=b);return a};this.setVolume=function(b,e){b===k&&(b=100);e===k&&(e=!1);a.isHTML5?a._a&&(c.muted&&!a.muted&&(a.muted=!0,a._a.muted=!0),a._a.volume=Math.max(0,Math.min(1,b/100))):l._setVolume(a.id,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;e||(a.volume=b,a.options.volume=b);return a};this.mute=function(){a.muted=!0;a.isHTML5?a._a&&(a._a.muted=!0):l._setVolume(a.id,0);return a};this.unmute=function(){a.muted=!1;var b=a._iO.volume!==k;a.isHTML5?a._a&&(a._a.muted=!1):l._setVolume(a.id, 42 | b?a._iO.volume:a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():a.mute()};this.onposition=this.onPosition=function(b,c,e){p.push({position:parseInt(b,10),method:c,scope:e!==k?e:a,fired:!1});return a};this.clearOnPosition=function(a,b){var c;a=parseInt(a,10);if(isNaN(a))return!1;for(c=0;c=b)return!1;for(b-= 43 | 1;0<=b;b--)c=p[b],!c.fired&&a.position>=c.position&&(c.fired=!0,u++,c.method.apply(c.scope,[c.position]));return!0};this._resetOnPosition=function(a){var b,c;b=p.length;if(!b)return!1;for(b-=1;0<=b;b--)c=p[b],c.fired&&a<=c.position&&(c.fired=!1,u--);return!0};y=function(){var b=a._iO,c=b.from,e=b.to,d,f;f=function(){a.clearOnPosition(e,f);a.stop()};d=function(){if(null!==e&&!isNaN(e))a.onPosition(e,f)};null!==c&&!isNaN(c)&&(b.position=c,b.multiShot=!1,d());return b};q=function(){var b,c=a._iO.onposition; 44 | if(c)for(b in c)if(c.hasOwnProperty(b))a.onPosition(parseInt(b,10),c[b])};x=function(){var b,c=a._iO.onposition;if(c)for(b in c)c.hasOwnProperty(b)&&a.clearOnPosition(parseInt(b,10))};n=function(){a.isHTML5&&Ra(a)};g=function(){a.isHTML5&&Sa(a)};f=function(b){b||(p=[],u=0);s=!1;a._hasTimer=null;a._a=null;a._html5_canplay=!1;a.bytesLoaded=null;a.bytesTotal=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.buffered=[];a.eqData=[];a.eqData.left=[];a.eqData.right=[]; 45 | a.failures=0;a.isBuffering=!1;a.instanceOptions={};a.instanceCount=0;a.loaded=!1;a.metadata={};a.readyState=0;a.muted=!1;a.paused=!1;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.playState=0;a.position=null;a.id3={}};f();this._onTimer=function(b){var c,f=!1,h={};if(a._hasTimer||b){if(a._a&&(b||(0opera.version()?new Audio(null):new Audio,c=a._a,c._called_load=!1,A&&(Ka=c);a.isHTML5=!0;a._a=c;c._s=a;h();a._apply_loop(c,b.loops);b.autoLoad||b.autoPlay?a.load():(c.autobuffer=!1,c.preload="auto");return c};h=function(){if(a._a._added_events)return!1;var b;a._a._added_events=!0;for(b in B)B.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b,B[b],!1);return!0};J=function(){var b;a._a._added_events= 48 | !1;for(b in B)B.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,B[b],!1)};this._onload=function(b){var c=!!b||!a.isHTML5&&8===m&&a.duration;a.loaded=c;a.readyState=c?3:2;a._onbufferchange(0);a._iO.onload&&ga(a,function(){a._iO.onload.apply(a,[c])});return!0};this._onbufferchange=function(b){if(0===a.playState||b&&a.isBuffering||!b&&!a.isBuffering)return!1;a.isBuffering=1===b;a._iO.onbufferchange&&a._iO.onbufferchange.apply(a);return!0};this._onsuspend=function(){a._iO.onsuspend&&a._iO.onsuspend.apply(a); 49 | return!0};this._onfailure=function(b,c,e){a.failures++;if(a._iO.onfailure&&1===a.failures)a._iO.onfailure(a,b,c,e)};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a._resetOnPosition(0);a.instanceCount&&(a.instanceCount--,a.instanceCount||(x(),a.playState=0,a.paused=!1,a.instanceCount=0,a.instanceOptions={},a._iO={},g(),a.isHTML5&&(a.position=0)),(!a.instanceCount||a._iO.multiShotEvents)&&b&&ga(a,function(){b.apply(a)}))};this._whileloading=function(b,c,e,d){var f=a._iO;a.bytesLoaded= 50 | b;a.bytesTotal=c;a.duration=Math.floor(e);a.bufferLength=d;a.durationEstimate=!a.isHTML5&&!f.isMovieStar?f.duration?a.duration>f.duration?a.duration:f.duration:parseInt(a.bytesTotal/a.bytesLoaded*a.duration,10):a.duration;a.isHTML5||(a.buffered=[{start:0,end:a.duration}]);(3!==a.readyState||a.isHTML5)&&f.whileloading&&f.whileloading.apply(a)};this._whileplaying=function(b,c,e,d,f){var h=a._iO;if(isNaN(b)||null===b)return!1;a.position=Math.max(0,b);a._processOnPosition();!a.isHTML5&&8opera.version()?new Audio(null):new Audio:null,d,a,f={},h,g;h=c.audioFormats;for(d in h)if(h.hasOwnProperty(d)&&(a="audio/"+d,f[d]=b(h[d].type),f[a]=f[d],d.match(bb)?(c.flash[d]=!0,c.flash[a]=!0):(c.flash[d]=!1,c.flash[a]=!1),h[d]&&h[d].related))for(g=h[d].related.length-1;0<=g;g--)f["audio/"+h[d].related[g]]=f[d],c.html5[h[d].related[g]]=f[d],c.flash[h[d].related[g]]=f[d];f.canPlayType=e?b:null;c.html5=w(c.html5,f);c.html5.usingFlash= 62 | Va();u=c.html5.usingFlash;return!0};sa={};P=function(){};aa=function(b){8===m&&(1m)&&(c.flashVersion=m=9);c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===m?" (AS3/Flash 9)": 64 | " (AS2/Flash 8)");8b&&(e=!0));setTimeout(function(){b=c.getMoviePercent();if(e)return Q=!1,g.setTimeout(F,1),!1;!p&&ab&&(null===b?c.useFlashBlock||0===c.flashLoadTimeout?c.useFlashBlock&&za():!c.useFlashBlock&&S?qa():D({type:"ontimeout",ignoreInit:!0,error:{type:"INIT_FLASHBLOCK"}}):0!==c.flashLoadTimeout&&(!c.useFlashBlock&&S?qa():xa(!0)))},c.flashLoadTimeout)};Y=function(){if(Ga||!ja)return t.remove(g,"focus", 78 | Y),!0;Ga=ab=!0;Q=!1;F();t.remove(g,"focus",Y);return!0};M=function(b){if(p)return!1;if(c.html5Only)return p=!0,E(),!0;var e=!0,d;if(!c.useFlashBlock||!c.flashLoadTimeout||c.getMoviePercent())p=!0;d={type:!v&&u?"NO_FLASH":"INIT_TIMEOUT"};if(y||b)c.useFlashBlock&&c.oMC&&(c.oMC.className=I()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error")),D({type:"ontimeout",error:d,ignoreInit:!0}),H(d),e=!1;y||(c.waitForWindowLoad&&!na?t.add(g,"load",E):E());return e};Ma=function(){var b,e=c.setupOptions; 79 | for(b in e)e.hasOwnProperty(b)&&(c[b]===k?c[b]=e[b]:c[b]!==e[b]&&(c.setupOptions[b]=c[b]))};ma=function(){if(p)return!1;if(c.html5Only)return p||(t.remove(g,"load",c.beginDelayedInit),c.enabled=!0,M()),!0;Z();try{l._externalInterfaceTest(!1),Oa(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||l._disableDebug(),c.enabled=!0,c.html5Only||t.add(g,"unload",la)}catch(b){return H({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),xa(!0),M(),!1}M();t.remove(g,"load",c.beginDelayedInit);return!0}; 80 | G=function(){if(N)return!1;N=!0;Ma();wa();!v&&c.hasHTML5&&c.setup({useHTML5Audio:!0,preferFlash:!1});Wa();!v&&u&&(Ua.push(sa.needFlash),c.setup({flashLoadTimeout:1}));n.removeEventListener&&n.removeEventListener("DOMContentLoaded",G,!1);Z();return!0};Ba=function(){"complete"===n.readyState&&(G(),n.detachEvent("onreadystatechange",Ba));return!0};ua=function(){na=!0;t.remove(g,"load",ua)};ta=function(){if(Fa&&(c.setupOptions.useHTML5Audio=!0,c.setupOptions.preferFlash=!1,ha||Za&&!s.match(/android\s2\.3/i)))ha&& 81 | (c.ignoreFlash=!0),A=!0};ta();Da();t.add(g,"focus",Y);t.add(g,"load",F);t.add(g,"load",ua);n.addEventListener?n.addEventListener("DOMContentLoaded",G,!1):n.attachEvent?n.attachEvent("onreadystatechange",Ba):H({type:"NO_DOM2_EVENTS",fatal:!0})}var ka=null;if(void 0===g.SM2_DEFER||!SM2_DEFER)ka=new U;g.SoundManager=U;g.soundManager=ka})(window); --------------------------------------------------------------------------------