diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..fedb072 --- /dev/null +++ b/license.txt @@ -0,0 +1,29 @@ +Software License Agreement (BSD License) + +Copyright (c) 2003, Scott Schiller (schillmania.com) +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +* Neither the name of schillmania.com nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission from schillmania.com. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/plugin.json b/plugin.json new file mode 100644 index 0000000..306ca3e --- /dev/null +++ b/plugin.json @@ -0,0 +1,210 @@ +{ + "name": "Snowstorm", + "description": "DHTML Snowstorm! JavaScript-based snow for web pages. Making it snow on Koken since 2015.", + "version": "1.0.0", + "demo": "http://kokensupport.com/demo/", + "author": { + "name": "Bjarne Varoystrand", + "link": "http://kokensupport.com/" + }, + + "data": { + "snowStorm_mobile": { + "label": "Exclude on mobile", + "info": "Snow is likely to be bad news for mobile phones CPUs (and batteries.) Enable at your own risk.", + "type": "select", + "options": [ + { "value": "true", "label": "True" }, + { "value": "false", "label": "False" } + ], + "value": "true" + }, + "snowStorm_flakemax": { + "label": "Max flakes on screen", + "info": "Limit total amount of snow made (falling + sticking)", + "type": "number", + "value": 128 + }, + "snowStorm_flakemaxactive": { + "label": "Max flakes active", + "info": "Limit amount of snow falling at once (less = lower CPU use)", + "type": "number", + "value": 64 + }, + "snowStorm_animationinterval": { + "label": "Update interval", + "info": "Theoretical miliseconds per frame measurement. 20 = fast + smooth, but high CPU use. 50 = more conservative, but slower.", + "type": "number", + "value": 33 + }, + "snowStorm_gpu": { + "label": "Use hardware acceleration", + "info": "Enable transform-based hardware acceleration, reduce CPU load.", + "type": "select", + "options": [ + { "value": "true", "label": "True" }, + { "value": "false", "label": "False" } + ], + "value": "true" + }, + "snowStorm_flakebottom": { + "label": "Flake bottom", + "info": "Integer for Y axis snow limit, 0 or null for full-screen snow effect", + "type": "string", + "value": "0" + }, + "snowStorm_followmouse": { + "label": "Follow mouse", + "info": "Snow movement can respond to the user's mouse", + "type": "select", + "options": [ + { "value": "true", "label": "True" }, + { "value": "false", "label": "False" } + ], + "value": "true" + }, + "snowStorm_color": { + "label": "Snowflake color", + "info": "Remember: Don't eat (or use?) yellow snow!", + "type": "color", + "value": "#FFFFFF" + }, + "snowStorm_char": { + "label": "Flake character", + "info": "Character used for the flake. See http://www.w3schools.com/charsets/ref_utf_dingbats.asp for reference.", + "type": "select", + "options": [ + { "label": "Bullet", "value": "•" }, + { "label": "Sparkles", "value": "✨" }, + { "label": "Open centre asterisk", "value": "✲" }, + { "label": "Eight spoked asterisk", "value": "✳" }, + { "label": "Eight pointed pinwheel star", "value": "✵" }, + { "label": "Teardrop-spoked asterisk", "value": "✻" }, + { "label": "Open centre teardrop-spoked asterisk", "value": "✼" }, + { "label": "Heavy teardrop-spoked asterisk", "value": "✽" }, + { "label": "Six petalled black and white florette", "value": "✾" }, + { "label": "Black florette", "value": "✿" }, + { "label": "White florette", "value": "❀" }, + { "label": "Eight petalled outlined black florette", "value": "❁" }, + { "label": "Heavy teardrop-spoked pinwheel asterisk", "value": "❃" }, + { "label": "Snowflake", "value": "❄" }, + { "label": "Tight trifoliate snowflake", "value": "❅" }, + { "label": "Heavy chevron snowflake", "value": "❆" }, + { "label": "Sparkle", "value": "❇" }, + { "label": "Heavy sparkle", "value": "❈" }, + { "label": "Balloon-spoked asterisk", "value": "❉" }, + { "label": "Eight teardrop-spoked propeller asterisk", "value": "❊" }, + { "label": "Heavy eight teardrop-spoked propeller asterisk", "value": "❋" } + ], + "value": "❄" + }, + "snowStorm_snowstick": { + "label": "Stick to bottom?", + "info": "Whether or not snow should 'stick' at the bottom. When off, will never collect.", + "type": "select", + "options": [ + { "value": "true", "label": "True" }, + { "value": "false", "label": "False" } + ], + "value": "true" + }, + "snowStorm_targetelement": { + "label": "Target element", + "info": "Element which snow will be appended to (null = document.body) - can be an element ID eg. 'myDiv', or a DOM node reference", + "type": "string", + "value": "null" + }, + "snowStorm_usemelteffect": { + "label": "Melting effect", + "info": "When recycling fallen snow (or rarely, when falling), have it 'melt' and fade out if browser supports it", + "type": "select", + "options": [ + { "value": "true", "label": "True" }, + { "value": "false", "label": "False" } + ], + "value": "true" + }, + "snowStorm_twinkeleffect": { + "label": "Flicker effect", + "info": "Allow snow to randomly 'flicker' in and out of view while falling", + "type": "select", + "options": [ + { "value": "true", "label": "True" }, + { "value": "false", "label": "False" } + ], + "value": "false" + }, + "snowStorm_positionfixed": { + "label": "Snow Position", + "info": "true = snow does not shift vertically when scrolling. May increase CPU load, disabled by default - if enabled, used only where supported", + "type": "select", + "options": [ + { "value": "true", "label": "True" }, + { "value": "false", "label": "False" } + ], + "value": "false" + }, + "snowStorm_pixelposition": { + "label": "Pixel position", + "info": "Whether to use pixel values for snow top/left vs. percentages. Auto-enabled if body is position:relative or targetElement is specified.", + "type": "select", + "options": [ + { "value": "true", "label": "True" }, + { "value": "false", "label": "False" } + ], + "value": "false" + }, + "snowStorm_freezeonblur": { + "label": "Stop when not in focus", + "info": "Only snow when the window is in focus (foreground.) Saves CPU.", + "type": "select", + "options": [ + { "value": "true", "label": "True" }, + { "value": "false", "label": "False" } + ], + "value": "true" + }, + "snowStorm_flakeleftoffset": { + "label": "Left margin space", + "info": "Left margin/gutter space on edge of container (eg. browser window.) Bump up these values if seeing horizontal scrollbars.", + "type": "number", + "value": 0 + }, + "snowStorm_flakerightoffset": { + "label": "Right margin space", + "info": "Right margin/gutter space on edge of container", + "type": "number", + "value": 0 + }, + "snowStorm_flakewidth": { + "label": "Flake width", + "info": "Max pixel width reserved for snow element", + "type": "number", + "value": 50 + }, + "snowStorm_flakeheight": { + "label": "Flake height", + "info": "Max pixel height reserved for snow element", + "type": "number", + "value": 50 + }, + "snowStorm_vmaxx": { + "label": "Maximum X velocity", + "info": "Maximum X velocity range for snow", + "type": "number", + "value": 5 + }, + "snowStorm_vmaxy": { + "label": "Maximum Y velocity", + "info": "Maximum Y velocity range for snow", + "type": "number", + "value": 4 + }, + "snowStorm_zindex": { + "label": "Stacking order", + "info": "CSS stacking order (z-index) applied to each snowflake", + "type": "number", + "value": 0 + } + } +} \ No newline at end of file diff --git a/plugin.php b/plugin.php new file mode 100644 index 0000000..f1cbc8a --- /dev/null +++ b/plugin.php @@ -0,0 +1,69 @@ +require_setup = false; + $this->register_hook('before_closing_head', 'render'); + } + + function render() + { + + $excludeMobile = $this->data->snowStorm_mobile; + $flakesMax = $this->data->snowStorm_flakemax; + $flakesMaxActive = $this->data->snowStorm_flakemaxactive; + $animationInterval = $this->data->snowStorm_animationinterval; + $useGPU = $this->data->snowStorm_gpu; + $flakeBottom = $this->data->snowStorm_flakebottom; + $followMouse = $this->data->snowStorm_followmouse; + $snowColor = $this->data->snowStorm_color; + $snowCharacter = $this->data->snowStorm_char; + $snowStick = $this->data->snowStorm_snowstick; + $targetElement = $this->data->snowStorm_targetelement; + $useMeltEffect = $this->data->snowStorm_usemelteffect; + $useTwinkleEffect = $this->data->snowStorm_twinkeleffect; + $usePositionFixed = $this->data->snowStorm_positionfixed; + $usePixelPosition = $this->data->snowStorm_pixelposition; + $freezeOnBlur = $this->data->snowStorm_freezeonblur; + $flakeLeftOffset = $this->data->snowStorm_flakeleftoffset; + $flakeRightOffset = $this->data->snowStorm_flakerightoffset; + $flakeWidth = $this->data->snowStorm_flakewidth; + $flakeHeight = $this->data->snowStorm_flakeheight; + $vMaxX = $this->data->snowStorm_vmaxx; + $vMaxY = $this->data->snowStorm_vmaxy; + $zIndex = $this->data->snowStorm_zindex; + $path = $this->get_path(); + +echo << + +OUT; + } +} diff --git a/snowstorm.js b/snowstorm.js new file mode 100644 index 0000000..a6df1a4 --- /dev/null +++ b/snowstorm.js @@ -0,0 +1,666 @@ +/** @license + * DHTML Snowstorm! JavaScript-based snow for web pages + * Making it snow on the internets since 2003. You're welcome. + * ----------------------------------------------------------- + * Version 1.44.20131208 (Previous rev: 1.44.20131125) + * Copyright (c) 2007, Scott Schiller. All rights reserved. + * Code provided under the BSD License + * http://schillmania.com/projects/snowstorm/license.txt + */ + +/*jslint nomen: true, plusplus: true, sloppy: true, vars: true, white: true */ +/*global window, document, navigator, clearInterval, setInterval */ + +var snowStorm = (function(window, document) { + + // --- common properties --- + + this.autoStart = true; // Whether the snow should start automatically or not. + this.excludeMobile = true; // Snow is likely to be bad news for mobile phones' CPUs (and batteries.) Enable at your own risk. + this.flakesMax = 128; // Limit total amount of snow made (falling + sticking) + this.flakesMaxActive = 64; // Limit amount of snow falling at once (less = lower CPU use) + this.animationInterval = 33; // Theoretical "miliseconds per frame" measurement. 20 = fast + smooth, but high CPU use. 50 = more conservative, but slower + this.useGPU = true; // Enable transform-based hardware acceleration, reduce CPU load. + this.className = null; // CSS class name for further customization on snow elements + this.excludeMobile = true; // Snow is likely to be bad news for mobile phones' CPUs (and batteries.) By default, be nice. + this.flakeBottom = null; // Integer for Y axis snow limit, 0 or null for "full-screen" snow effect + this.followMouse = true; // Snow movement can respond to the user's mouse + this.snowColor = '#fff'; // Don't eat (or use?) yellow snow. + this.snowCharacter = '•'; // • = bullet, · is square on some systems etc. + this.snowStick = true; // Whether or not snow should "stick" at the bottom. When off, will never collect. + 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 + this.useMeltEffect = true; // When recycling fallen snow (or rarely, when falling), have it "melt" and fade out if browser supports it + this.useTwinkleEffect = false; // Allow snow to randomly "flicker" in and out of view while falling + this.usePositionFixed = false; // true = snow does not shift vertically when scrolling. May increase CPU load, disabled by default - if enabled, used only where supported + 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. + + // --- less-used bits --- + + this.freezeOnBlur = true; // Only snow when the window is in focus (foreground.) Saves CPU. + this.flakeLeftOffset = 0; // Left margin/gutter space on edge of container (eg. browser window.) Bump up these values if seeing horizontal scrollbars. + this.flakeRightOffset = 0; // Right margin/gutter space on edge of container + this.flakeWidth = 8; // Max pixel width reserved for snow element + this.flakeHeight = 8; // Max pixel height reserved for snow element + this.vMaxX = 5; // Maximum X velocity range for snow + this.vMaxY = 4; // Maximum Y velocity range for snow + this.zIndex = 0; // CSS stacking order applied to each snowflake + + // --- "No user-serviceable parts inside" past this point, yadda yadda --- + + var storm = this, + features, + // UA sniffing and backCompat rendering mode checks for fixed position, etc. + isIE = navigator.userAgent.match(/msie/i), + isIE6 = navigator.userAgent.match(/msie 6/i), + isMobile = navigator.userAgent.match(/mobile|opera m(ob|in)/i), + isBackCompatIE = (isIE && document.compatMode === 'BackCompat'), + noFixed = (isBackCompatIE || isIE6), + screenX = null, screenX2 = null, screenY = null, scrollY = null, docHeight = null, vRndX = null, vRndY = null, + windOffset = 1, + windMultiplier = 2, + flakeTypes = 6, + fixedForEverything = false, + targetElementIsRelative = false, + opacitySupported = (function(){ + try { + document.createElement('div').style.opacity = '0.5'; + } catch(e) { + return false; + } + return true; + }()), + didInit = false, + docFrag = document.createDocumentFragment(); + + features = (function() { + + var getAnimationFrame; + + /** + * hat tip: paul irish + * http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + * https://gist.github.com/838785 + */ + + function timeoutShim(callback) { + window.setTimeout(callback, 1000/(storm.animationInterval || 20)); + } + + var _animationFrame = (window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + timeoutShim); + + // apply to window, avoid "illegal invocation" errors in Chrome + getAnimationFrame = _animationFrame ? function() { + return _animationFrame.apply(window, arguments); + } : null; + + var testDiv; + + testDiv = document.createElement('div'); + + function has(prop) { + + // test for feature support + var result = testDiv.style[prop]; + return (result !== undefined ? prop : null); + + } + + // note local scope. + var localFeatures = { + + transform: { + ie: has('-ms-transform'), + moz: has('MozTransform'), + opera: has('OTransform'), + webkit: has('webkitTransform'), + w3: has('transform'), + prop: null // the normalized property value + }, + + getAnimationFrame: getAnimationFrame + + }; + + localFeatures.transform.prop = ( + localFeatures.transform.w3 || + localFeatures.transform.moz || + localFeatures.transform.webkit || + localFeatures.transform.ie || + localFeatures.transform.opera + ); + + testDiv = null; + + return localFeatures; + + }()); + + this.timer = null; + this.flakes = []; + this.disabled = false; + this.active = false; + this.meltFrameCount = 20; + this.meltFrames = []; + + this.setXY = function(o, x, y) { + + if (!o) { + return false; + } + + if (storm.usePixelPosition || targetElementIsRelative) { + + o.style.left = (x - storm.flakeWidth) + 'px'; + o.style.top = (y - storm.flakeHeight) + 'px'; + + } else if (noFixed) { + + o.style.right = (100-(x/screenX*100)) + '%'; + // avoid creating vertical scrollbars + o.style.top = (Math.min(y, docHeight-storm.flakeHeight)) + 'px'; + + } else { + + if (!storm.flakeBottom) { + + // if not using a fixed bottom coordinate... + o.style.right = (100-(x/screenX*100)) + '%'; + o.style.bottom = (100-(y/screenY*100)) + '%'; + + } else { + + // absolute top. + o.style.right = (100-(x/screenX*100)) + '%'; + o.style.top = (Math.min(y, docHeight-storm.flakeHeight)) + 'px'; + + } + + } + + }; + + this.events = (function() { + + var old = (!window.addEventListener && window.attachEvent), slice = Array.prototype.slice, + evt = { + add: (old?'attachEvent':'addEventListener'), + remove: (old?'detachEvent':'removeEventListener') + }; + + function getArgs(oArgs) { + var args = slice.call(oArgs), len = args.length; + if (old) { + args[1] = 'on' + args[1]; // prefix + if (len > 3) { + args.pop(); // no capture + } + } else if (len === 3) { + args.push(false); + } + return args; + } + + function apply(args, sType) { + var element = args.shift(), + method = [evt[sType]]; + if (old) { + element[method](args[0], args[1]); + } else { + element[method].apply(element, args); + } + } + + function addEvent() { + apply(getArgs(arguments), 'add'); + } + + function removeEvent() { + apply(getArgs(arguments), 'remove'); + } + + return { + add: addEvent, + remove: removeEvent + }; + + }()); + + function rnd(n,min) { + if (isNaN(min)) { + min = 0; + } + return (Math.random()*n)+min; + } + + function plusMinus(n) { + return (parseInt(rnd(2),10)===1?n*-1:n); + } + + this.randomizeWind = function() { + var i; + vRndX = plusMinus(rnd(storm.vMaxX,0.2)); + vRndY = rnd(storm.vMaxY,0.2); + if (this.flakes) { + for (i=0; i=0 && s.vX<0.2) { + s.vX = 0.2; + } else if (s.vX<0 && s.vX>-0.2) { + s.vX = -0.2; + } + if (s.vY>=0 && s.vY<0.2) { + s.vY = 0.2; + } + }; + + this.move = function() { + var vX = s.vX*windOffset, yDiff; + s.x += vX; + s.y += (s.vY*s.vAmp); + if (s.x >= screenX || screenX-s.x < storm.flakeWidth) { // X-axis scroll check + s.x = 0; + } else if (vX < 0 && s.x-storm.flakeLeftOffset < -storm.flakeWidth) { + s.x = screenX-storm.flakeWidth-1; // flakeWidth; + } + s.refresh(); + yDiff = screenY+scrollY-s.y+storm.flakeHeight; + if (yDiff0.998) { + // ~1/1000 chance of melting mid-air, with each frame + s.melting = true; + s.melt(); + // only incrementally melt one frame + // s.melting = false; + } + if (storm.useTwinkleEffect) { + if (s.twinkleFrame < 0) { + if (Math.random() > 0.97) { + s.twinkleFrame = parseInt(Math.random() * 8, 10); + } + } else { + s.twinkleFrame--; + if (!opacitySupported) { + s.o.style.visibility = (s.twinkleFrame && s.twinkleFrame % 2 === 0 ? 'hidden' : 'visible'); + } else { + s.o.style.opacity = (s.twinkleFrame && s.twinkleFrame % 2 === 0 ? 0 : 1); + } + } + } + } + }; + + this.animate = function() { + // main animation loop + // move, check status, die etc. + s.move(); + }; + + this.setVelocities = function() { + s.vX = vRndX+rnd(storm.vMaxX*0.12,0.1); + s.vY = vRndY+rnd(storm.vMaxY*0.12,0.1); + }; + + this.setOpacity = function(o,opacity) { + if (!opacitySupported) { + return false; + } + o.style.opacity = opacity; + }; + + this.melt = function() { + if (!storm.useMeltEffect || !s.melting) { + s.recycle(); + } else { + if (s.meltFrame < s.meltFrameCount) { + s.setOpacity(s.o,s.meltFrames[s.meltFrame]); + s.o.style.fontSize = s.fontSize-(s.fontSize*(s.meltFrame/s.meltFrameCount))+'px'; + s.o.style.lineHeight = storm.flakeHeight+2+(storm.flakeHeight*0.75*(s.meltFrame/s.meltFrameCount))+'px'; + s.meltFrame++; + } else { + s.recycle(); + } + } + }; + + this.recycle = function() { + s.o.style.display = 'none'; + s.o.style.position = (fixedForEverything?'fixed':'absolute'); + s.o.style.bottom = 'auto'; + s.setVelocities(); + s.vCheck(); + s.meltFrame = 0; + s.melting = false; + s.setOpacity(s.o,1); + s.o.style.padding = '0px'; + s.o.style.margin = '0px'; + s.o.style.fontSize = s.fontSize+'px'; + s.o.style.lineHeight = (storm.flakeHeight+2)+'px'; + s.o.style.textAlign = 'center'; + s.o.style.verticalAlign = 'baseline'; + s.x = parseInt(rnd(screenX-storm.flakeWidth-20),10); + s.y = parseInt(rnd(screenY)*-1,10)-storm.flakeHeight; + s.refresh(); + s.o.style.display = 'block'; + s.active = 1; + }; + + this.recycle(); // set up x/y coords etc. + this.refresh(); + + }; + + this.snow = function() { + var active = 0, flake = null, i, j; + for (i=0, j=storm.flakes.length; istorm.flakesMaxActive) { + storm.flakes[storm.flakes.length-1].active = -1; + } + } + storm.targetElement.appendChild(docFrag); + }; + + this.timerInit = function() { + storm.timer = true; + storm.snow(); + }; + + this.init = function() { + var i; + for (i=0; i3&&t.pop()):3===i&&t.push(!1),t}function i(e,t){var i=e.shift(),s=[a[t]];l?i[s](e[0],e[1]):i[s].apply(i,e)}function s(){i(t(arguments),"add")}function n(){i(t(arguments),"remove")}var l=!e.addEventListener&&e.attachEvent,o=Array.prototype.slice,a={add:l?"attachEvent":"addEventListener",remove:l?"detachEvent":"removeEventListener"};return{add:s,remove:n}}(),this.randomizeWind=function(){var e;if(k=s(i(a.vMaxX,.2)),g=i(a.vMaxY,.2),this.flakes)for(e=0;e=0&&l.vX<.2?l.vX=.2:l.vX<0&&l.vX>-.2&&(l.vX=-.2),l.vY>=0&&l.vY<.2&&(l.vY=.2)},this.move=function(){var e,t=l.vX*x;l.x+=t,l.y+=l.vY*l.vAmp,l.x>=c||c-l.xt&&l.x-a.flakeLeftOffset<-a.flakeWidth&&(l.x=c-a.flakeWidth-1),l.refresh(),e=v+p-l.y+a.flakeHeight,e.998&&(l.melting=!0,l.melt()),a.useTwinkleEffect&&(l.twinkleFrame<0?Math.random()>.97&&(l.twinkleFrame=parseInt(8*Math.random(),10)):(l.twinkleFrame--,z?l.o.style.opacity=l.twinkleFrame&&l.twinkleFrame%2===0?0:1:l.o.style.visibility=l.twinkleFrame&&l.twinkleFrame%2===0?"hidden":"visible")))},this.animate=function(){l.move()},this.setVelocities=function(){l.vX=k+i(.12*a.vMaxX,.1),l.vY=g+i(.12*a.vMaxY,.1)},this.setOpacity=function(e,t){return z?void(e.style.opacity=t):!1},this.melt=function(){a.useMeltEffect&&l.melting&&l.meltFramee;e++)1===a.flakes[e].active&&(a.flakes[e].move(),s++),a.flakes[e].melting&&a.flakes[e].melt();st?x=-w+t/d*w:(t-=d,x=t/d*w)},this.createSnow=function(e,t){var s;for(s=0;e>s;s++)a.flakes[a.flakes.length]=new a.SnowFlake(parseInt(i(F),10)),(t||s>a.flakesMaxActive)&&(a.flakes[a.flakes.length-1].active=-1);a.targetElement.appendChild(M)},this.timerInit=function(){a.timer=!0,a.snow()},this.init=function(){var i;for(i=0;i