Snowstorm over the dashboard

Adds a snowstorm over your dashboard

taken from:

http://www.schillmania.com/projects/snowstorm/

Just import it and set the UI template group to your chosing.

Merry Christmas!

[{"id":"3584d405.3a2f4c","type":"http in","z":"3dc8ae0.6cb8152","name":"","url":"/snow","method":"get","upload":false,"swaggerDoc":"","x":260,"y":3480,"wires":[["bcb79066.a42d"]]},{"id":"bcb79066.a42d","type":"template","z":"3dc8ae0.6cb8152","name":"snow","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<script type=\"text/javascript\">\n    /** @license\n * DHTML Snowstorm! JavaScript-based snow for web pages\n * Making it snow on the internets since 2003. You're welcome.\n * -----------------------------------------------------------\n * Version 1.44.20131208 (Previous rev: 1.44.20131125)\n * Copyright (c) 2007, Scott Schiller. All rights reserved.\n * Code provided under the BSD License\n * http://schillmania.com/projects/snowstorm/license.txt\n */\n\n/*jslint nomen: true, plusplus: true, sloppy: true, vars: true, white: true */\n/*global window, document, navigator, clearInterval, setInterval */\n\nvar snowStorm = (function(window, document) {\n\n  // --- common properties ---\n\n  this.autoStart = true;          // Whether the snow should start automatically or not.\n  this.excludeMobile = true;      // Snow is likely to be bad news for mobile phones' CPUs (and batteries.) Enable at your own risk.\n  this.flakesMax = 128;           // Limit total amount of snow made (falling + sticking)\n  this.flakesMaxActive = 64;      // Limit amount of snow falling at once (less = lower CPU use)\n  this.animationInterval = 33;    // Theoretical \"miliseconds per frame\" measurement. 20 = fast + smooth, but high CPU use. 50 = more conservative, but slower\n  this.useGPU = true;             // Enable transform-based hardware acceleration, reduce CPU load.\n  this.className = null;          // CSS class name for further customization on snow elements\n  this.excludeMobile = true;      // Snow is likely to be bad news for mobile phones' CPUs (and batteries.) By default, be nice.\n  this.flakeBottom = null;        // Integer for Y axis snow limit, 0 or null for \"full-screen\" snow effect\n  this.followMouse = true;        // Snow movement can respond to the user's mouse\n  this.snowColor = '#fff';        // Don't eat (or use?) yellow snow.\n  this.snowCharacter = '&bull;';  // &bull; = bullet, &middot; is square on some systems etc.\n  this.snowStick = true;          // Whether or not snow should \"stick\" at the bottom. When off, will never collect.\n  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\n  this.useMeltEffect = true;      // When recycling fallen snow (or rarely, when falling), have it \"melt\" and fade out if browser supports it\n  this.useTwinkleEffect = false;  // Allow snow to randomly \"flicker\" in and out of view while falling\n  this.usePositionFixed = false;  // true = snow does not shift vertically when scrolling. May increase CPU load, disabled by default - if enabled, used only where supported\n  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.\n\n  // --- less-used bits ---\n\n  this.freezeOnBlur = true;       // Only snow when the window is in focus (foreground.) Saves CPU.\n  this.flakeLeftOffset = 0;       // Left margin/gutter space on edge of container (eg. browser window.) Bump up these values if seeing horizontal scrollbars.\n  this.flakeRightOffset = 0;      // Right margin/gutter space on edge of container\n  this.flakeWidth = 8;            // Max pixel width reserved for snow element\n  this.flakeHeight = 8;           // Max pixel height reserved for snow element\n  this.vMaxX = 5;                 // Maximum X velocity range for snow\n  this.vMaxY = 4;                 // Maximum Y velocity range for snow\n  this.zIndex = 0;                // CSS stacking order applied to each snowflake\n\n  // --- \"No user-serviceable parts inside\" past this point, yadda yadda ---\n\n  var storm = this,\n  features,\n  // UA sniffing and backCompat rendering mode checks for fixed position, etc.\n  isIE = navigator.userAgent.match(/msie/i),\n  isIE6 = navigator.userAgent.match(/msie 6/i),\n  isMobile = navigator.userAgent.match(/mobile|opera m(ob|in)/i),\n  isBackCompatIE = (isIE && document.compatMode === 'BackCompat'),\n  noFixed = (isBackCompatIE || isIE6),\n  screenX = null, screenX2 = null, screenY = null, scrollY = null, docHeight = null, vRndX = null, vRndY = null,\n  windOffset = 1,\n  windMultiplier = 2,\n  flakeTypes = 6,\n  fixedForEverything = false,\n  targetElementIsRelative = false,\n  opacitySupported = (function(){\n    try {\n      document.createElement('div').style.opacity = '0.5';\n    } catch(e) {\n      return false;\n    }\n    return true;\n  }()),\n  didInit = false,\n  docFrag = document.createDocumentFragment();\n\n  features = (function() {\n\n    var getAnimationFrame;\n\n    /**\n     * hat tip: paul irish\n     * http://paulirish.com/2011/requestanimationframe-for-smart-animating/\n     * https://gist.github.com/838785\n     */\n\n    function timeoutShim(callback) {\n      window.setTimeout(callback, 1000/(storm.animationInterval || 20));\n    }\n\n    var _animationFrame = (window.requestAnimationFrame ||\n        window.webkitRequestAnimationFrame ||\n        window.mozRequestAnimationFrame ||\n        window.oRequestAnimationFrame ||\n        window.msRequestAnimationFrame ||\n        timeoutShim);\n\n    // apply to window, avoid \"illegal invocation\" errors in Chrome\n    getAnimationFrame = _animationFrame ? function() {\n      return _animationFrame.apply(window, arguments);\n    } : null;\n\n    var testDiv;\n\n    testDiv = document.createElement('div');\n\n    function has(prop) {\n\n      // test for feature support\n      var result = testDiv.style[prop];\n      return (result !== undefined ? prop : null);\n\n    }\n\n    // note local scope.\n    var localFeatures = {\n\n      transform: {\n        ie:  has('-ms-transform'),\n        moz: has('MozTransform'),\n        opera: has('OTransform'),\n        webkit: has('webkitTransform'),\n        w3: has('transform'),\n        prop: null // the normalized property value\n      },\n\n      getAnimationFrame: getAnimationFrame\n\n    };\n\n    localFeatures.transform.prop = (\n      localFeatures.transform.w3 || \n      localFeatures.transform.moz ||\n      localFeatures.transform.webkit ||\n      localFeatures.transform.ie ||\n      localFeatures.transform.opera\n    );\n\n    testDiv = null;\n\n    return localFeatures;\n\n  }());\n\n  this.timer = null;\n  this.flakes = [];\n  this.disabled = false;\n  this.active = false;\n  this.meltFrameCount = 20;\n  this.meltFrames = [];\n\n  this.setXY = function(o, x, y) {\n\n    if (!o) {\n      return false;\n    }\n\n    if (storm.usePixelPosition || targetElementIsRelative) {\n\n      o.style.left = (x - storm.flakeWidth) + 'px';\n      o.style.top = (y - storm.flakeHeight) + 'px';\n\n    } else if (noFixed) {\n\n      o.style.right = (100-(x/screenX*100)) + '%';\n      // avoid creating vertical scrollbars\n      o.style.top = (Math.min(y, docHeight-storm.flakeHeight)) + 'px';\n\n    } else {\n\n      if (!storm.flakeBottom) {\n\n        // if not using a fixed bottom coordinate...\n        o.style.right = (100-(x/screenX*100)) + '%';\n        o.style.bottom = (100-(y/screenY*100)) + '%';\n\n      } else {\n\n        // absolute top.\n        o.style.right = (100-(x/screenX*100)) + '%';\n        o.style.top = (Math.min(y, docHeight-storm.flakeHeight)) + 'px';\n\n      }\n\n    }\n\n  };\n\n  this.events = (function() {\n\n    var old = (!window.addEventListener && window.attachEvent), slice = Array.prototype.slice,\n    evt = {\n      add: (old?'attachEvent':'addEventListener'),\n      remove: (old?'detachEvent':'removeEventListener')\n    };\n\n    function getArgs(oArgs) {\n      var args = slice.call(oArgs), len = args.length;\n      if (old) {\n        args[1] = 'on' + args[1]; // prefix\n        if (len > 3) {\n          args.pop(); // no capture\n        }\n      } else if (len === 3) {\n        args.push(false);\n      }\n      return args;\n    }\n\n    function apply(args, sType) {\n      var element = args.shift(),\n          method = [evt[sType]];\n      if (old) {\n        element[method](args[0], args[1]);\n      } else {\n        element[method].apply(element, args);\n      }\n    }\n\n    function addEvent() {\n      apply(getArgs(arguments), 'add');\n    }\n\n    function removeEvent() {\n      apply(getArgs(arguments), 'remove');\n    }\n\n    return {\n      add: addEvent,\n      remove: removeEvent\n    };\n\n  }());\n\n  function rnd(n,min) {\n    if (isNaN(min)) {\n      min = 0;\n    }\n    return (Math.random()*n)+min;\n  }\n\n  function plusMinus(n) {\n    return (parseInt(rnd(2),10)===1?n*-1:n);\n  }\n\n  this.randomizeWind = function() {\n    var i;\n    vRndX = plusMinus(rnd(storm.vMaxX,0.2));\n    vRndY = rnd(storm.vMaxY,0.2);\n    if (this.flakes) {\n      for (i=0; i<this.flakes.length; i++) {\n        if (this.flakes[i].active) {\n          this.flakes[i].setVelocities();\n        }\n      }\n    }\n  };\n\n  this.scrollHandler = function() {\n    var i;\n    // \"attach\" snowflakes to bottom of window if no absolute bottom value was given\n    scrollY = (storm.flakeBottom ? 0 : parseInt(window.scrollY || document.documentElement.scrollTop || (noFixed ? document.body.scrollTop : 0), 10));\n    if (isNaN(scrollY)) {\n      scrollY = 0; // Netscape 6 scroll fix\n    }\n    if (!fixedForEverything && !storm.flakeBottom && storm.flakes) {\n      for (i=0; i<storm.flakes.length; i++) {\n        if (storm.flakes[i].active === 0) {\n          storm.flakes[i].stick();\n        }\n      }\n    }\n  };\n\n  this.resizeHandler = function() {\n    if (window.innerWidth || window.innerHeight) {\n      screenX = window.innerWidth - 16 - storm.flakeRightOffset;\n      screenY = (storm.flakeBottom || window.innerHeight);\n    } else {\n      screenX = (document.documentElement.clientWidth || document.body.clientWidth || document.body.scrollWidth) - (!isIE ? 8 : 0) - storm.flakeRightOffset;\n      screenY = storm.flakeBottom || document.documentElement.clientHeight || document.body.clientHeight || document.body.scrollHeight;\n    }\n    docHeight = document.body.offsetHeight;\n    screenX2 = parseInt(screenX/2,10);\n  };\n\n  this.resizeHandlerAlt = function() {\n    screenX = storm.targetElement.offsetWidth - storm.flakeRightOffset;\n    screenY = storm.flakeBottom || storm.targetElement.offsetHeight;\n    screenX2 = parseInt(screenX/2,10);\n    docHeight = document.body.offsetHeight;\n  };\n\n  this.freeze = function() {\n    // pause animation\n    if (!storm.disabled) {\n      storm.disabled = 1;\n    } else {\n      return false;\n    }\n    storm.timer = null;\n  };\n\n  this.resume = function() {\n    if (storm.disabled) {\n       storm.disabled = 0;\n    } else {\n      return false;\n    }\n    storm.timerInit();\n  };\n\n  this.toggleSnow = function() {\n    if (!storm.flakes.length) {\n      // first run\n      storm.start();\n    } else {\n      storm.active = !storm.active;\n      if (storm.active) {\n        storm.show();\n        storm.resume();\n      } else {\n        storm.stop();\n        storm.freeze();\n      }\n    }\n  };\n\n  this.stop = function() {\n    var i;\n    this.freeze();\n    for (i=0; i<this.flakes.length; i++) {\n      this.flakes[i].o.style.display = 'none';\n    }\n    storm.events.remove(window,'scroll',storm.scrollHandler);\n    storm.events.remove(window,'resize',storm.resizeHandler);\n    if (storm.freezeOnBlur) {\n      if (isIE) {\n        storm.events.remove(document,'focusout',storm.freeze);\n        storm.events.remove(document,'focusin',storm.resume);\n      } else {\n        storm.events.remove(window,'blur',storm.freeze);\n        storm.events.remove(window,'focus',storm.resume);\n      }\n    }\n  };\n\n  this.show = function() {\n    var i;\n    for (i=0; i<this.flakes.length; i++) {\n      this.flakes[i].o.style.display = 'block';\n    }\n  };\n\n  this.SnowFlake = function(type,x,y) {\n    var s = this;\n    this.type = type;\n    this.x = x||parseInt(rnd(screenX-20),10);\n    this.y = (!isNaN(y)?y:-rnd(screenY)-12);\n    this.vX = null;\n    this.vY = null;\n    this.vAmpTypes = [1,1.2,1.4,1.6,1.8]; // \"amplification\" for vX/vY (based on flake size/type)\n    this.vAmp = this.vAmpTypes[this.type] || 1;\n    this.melting = false;\n    this.meltFrameCount = storm.meltFrameCount;\n    this.meltFrames = storm.meltFrames;\n    this.meltFrame = 0;\n    this.twinkleFrame = 0;\n    this.active = 1;\n    this.fontSize = (10+(this.type/5)*10);\n    this.o = document.createElement('div');\n    this.o.innerHTML = storm.snowCharacter;\n    if (storm.className) {\n      this.o.setAttribute('class', storm.className);\n    }\n    this.o.style.color = storm.snowColor;\n    this.o.style.position = (fixedForEverything?'fixed':'absolute');\n    if (storm.useGPU && features.transform.prop) {\n      // GPU-accelerated snow.\n      this.o.style[features.transform.prop] = 'translate3d(0px, 0px, 0px)';\n    }\n    this.o.style.width = storm.flakeWidth+'px';\n    this.o.style.height = storm.flakeHeight+'px';\n    this.o.style.fontFamily = 'arial,verdana';\n    this.o.style.cursor = 'default';\n    this.o.style.overflow = 'hidden';\n    this.o.style.fontWeight = 'normal';\n    this.o.style.zIndex = storm.zIndex;\n    docFrag.appendChild(this.o);\n\n    this.refresh = function() {\n      if (isNaN(s.x) || isNaN(s.y)) {\n        // safety check\n        return false;\n      }\n      storm.setXY(s.o, s.x, s.y);\n    };\n\n    this.stick = function() {\n      if (noFixed || (storm.targetElement !== document.documentElement && storm.targetElement !== document.body)) {\n        s.o.style.top = (screenY+scrollY-storm.flakeHeight)+'px';\n      } else if (storm.flakeBottom) {\n        s.o.style.top = storm.flakeBottom+'px';\n      } else {\n        s.o.style.display = 'none';\n        s.o.style.bottom = '0%';\n        s.o.style.position = 'fixed';\n        s.o.style.display = 'block';\n      }\n    };\n\n    this.vCheck = function() {\n      if (s.vX>=0 && s.vX<0.2) {\n        s.vX = 0.2;\n      } else if (s.vX<0 && s.vX>-0.2) {\n        s.vX = -0.2;\n      }\n      if (s.vY>=0 && s.vY<0.2) {\n        s.vY = 0.2;\n      }\n    };\n\n    this.move = function() {\n      var vX = s.vX*windOffset, yDiff;\n      s.x += vX;\n      s.y += (s.vY*s.vAmp);\n      if (s.x >= screenX || screenX-s.x < storm.flakeWidth) { // X-axis scroll check\n        s.x = 0;\n      } else if (vX < 0 && s.x-storm.flakeLeftOffset < -storm.flakeWidth) {\n        s.x = screenX-storm.flakeWidth-1; // flakeWidth;\n      }\n      s.refresh();\n      yDiff = screenY+scrollY-s.y+storm.flakeHeight;\n      if (yDiff<storm.flakeHeight) {\n        s.active = 0;\n        if (storm.snowStick) {\n          s.stick();\n        } else {\n          s.recycle();\n        }\n      } else {\n        if (storm.useMeltEffect && s.active && s.type < 3 && !s.melting && Math.random()>0.998) {\n          // ~1/1000 chance of melting mid-air, with each frame\n          s.melting = true;\n          s.melt();\n          // only incrementally melt one frame\n          // s.melting = false;\n        }\n        if (storm.useTwinkleEffect) {\n          if (s.twinkleFrame < 0) {\n            if (Math.random() > 0.97) {\n              s.twinkleFrame = parseInt(Math.random() * 8, 10);\n            }\n          } else {\n            s.twinkleFrame--;\n            if (!opacitySupported) {\n              s.o.style.visibility = (s.twinkleFrame && s.twinkleFrame % 2 === 0 ? 'hidden' : 'visible');\n            } else {\n              s.o.style.opacity = (s.twinkleFrame && s.twinkleFrame % 2 === 0 ? 0 : 1);\n            }\n          }\n        }\n      }\n    };\n\n    this.animate = function() {\n      // main animation loop\n      // move, check status, die etc.\n      s.move();\n    };\n\n    this.setVelocities = function() {\n      s.vX = vRndX+rnd(storm.vMaxX*0.12,0.1);\n      s.vY = vRndY+rnd(storm.vMaxY*0.12,0.1);\n    };\n\n    this.setOpacity = function(o,opacity) {\n      if (!opacitySupported) {\n        return false;\n      }\n      o.style.opacity = opacity;\n    };\n\n    this.melt = function() {\n      if (!storm.useMeltEffect || !s.melting) {\n        s.recycle();\n      } else {\n        if (s.meltFrame < s.meltFrameCount) {\n          s.setOpacity(s.o,s.meltFrames[s.meltFrame]);\n          s.o.style.fontSize = s.fontSize-(s.fontSize*(s.meltFrame/s.meltFrameCount))+'px';\n          s.o.style.lineHeight = storm.flakeHeight+2+(storm.flakeHeight*0.75*(s.meltFrame/s.meltFrameCount))+'px';\n          s.meltFrame++;\n        } else {\n          s.recycle();\n        }\n      }\n    };\n\n    this.recycle = function() {\n      s.o.style.display = 'none';\n      s.o.style.position = (fixedForEverything?'fixed':'absolute');\n      s.o.style.bottom = 'auto';\n      s.setVelocities();\n      s.vCheck();\n      s.meltFrame = 0;\n      s.melting = false;\n      s.setOpacity(s.o,1);\n      s.o.style.padding = '0px';\n      s.o.style.margin = '0px';\n      s.o.style.fontSize = s.fontSize+'px';\n      s.o.style.lineHeight = (storm.flakeHeight+2)+'px';\n      s.o.style.textAlign = 'center';\n      s.o.style.verticalAlign = 'baseline';\n      s.x = parseInt(rnd(screenX-storm.flakeWidth-20),10);\n      s.y = parseInt(rnd(screenY)*-1,10)-storm.flakeHeight;\n      s.refresh();\n      s.o.style.display = 'block';\n      s.active = 1;\n    };\n\n    this.recycle(); // set up x/y coords etc.\n    this.refresh();\n\n  };\n\n  this.snow = function() {\n    var active = 0, flake = null, i, j;\n    for (i=0, j=storm.flakes.length; i<j; i++) {\n      if (storm.flakes[i].active === 1) {\n        storm.flakes[i].move();\n        active++;\n      }\n      if (storm.flakes[i].melting) {\n        storm.flakes[i].melt();\n      }\n    }\n    if (active<storm.flakesMaxActive) {\n      flake = storm.flakes[parseInt(rnd(storm.flakes.length),10)];\n      if (flake.active === 0) {\n        flake.melting = true;\n      }\n    }\n    if (storm.timer) {\n      features.getAnimationFrame(storm.snow);\n    }\n  };\n\n  this.mouseMove = function(e) {\n    if (!storm.followMouse) {\n      return true;\n    }\n    var x = parseInt(e.clientX,10);\n    if (x<screenX2) {\n      windOffset = -windMultiplier+(x/screenX2*windMultiplier);\n    } else {\n      x -= screenX2;\n      windOffset = (x/screenX2)*windMultiplier;\n    }\n  };\n\n  this.createSnow = function(limit,allowInactive) {\n    var i;\n    for (i=0; i<limit; i++) {\n      storm.flakes[storm.flakes.length] = new storm.SnowFlake(parseInt(rnd(flakeTypes),10));\n      if (allowInactive || i>storm.flakesMaxActive) {\n        storm.flakes[storm.flakes.length-1].active = -1;\n      }\n    }\n    storm.targetElement.appendChild(docFrag);\n  };\n\n  this.timerInit = function() {\n    storm.timer = true;\n    storm.snow();\n  };\n\n  this.init = function() {\n    var i;\n    for (i=0; i<storm.meltFrameCount; i++) {\n      storm.meltFrames.push(1-(i/storm.meltFrameCount));\n    }\n    storm.randomizeWind();\n    storm.createSnow(storm.flakesMax); // create initial batch\n    storm.events.add(window,'resize',storm.resizeHandler);\n    storm.events.add(window,'scroll',storm.scrollHandler);\n    if (storm.freezeOnBlur) {\n      if (isIE) {\n        storm.events.add(document,'focusout',storm.freeze);\n        storm.events.add(document,'focusin',storm.resume);\n      } else {\n        storm.events.add(window,'blur',storm.freeze);\n        storm.events.add(window,'focus',storm.resume);\n      }\n    }\n    storm.resizeHandler();\n    storm.scrollHandler();\n    if (storm.followMouse) {\n      storm.events.add(isIE?document:window,'mousemove',storm.mouseMove);\n    }\n    storm.animationInterval = Math.max(20,storm.animationInterval);\n    storm.timerInit();\n  };\n\n  this.start = function(bFromOnLoad) {\n    if (!didInit) {\n      didInit = true;\n    } else if (bFromOnLoad) {\n      // already loaded and running\n      return true;\n    }\n    if (typeof storm.targetElement === 'string') {\n      var targetID = storm.targetElement;\n      storm.targetElement = document.getElementById(targetID);\n      if (!storm.targetElement) {\n        throw new Error('Snowstorm: Unable to get targetElement \"'+targetID+'\"');\n      }\n    }\n    if (!storm.targetElement) {\n      storm.targetElement = (document.body || document.documentElement);\n    }\n    if (storm.targetElement !== document.documentElement && storm.targetElement !== document.body) {\n      // re-map handler to get element instead of screen dimensions\n      storm.resizeHandler = storm.resizeHandlerAlt;\n      //and force-enable pixel positioning\n      storm.usePixelPosition = true;\n    }\n    storm.resizeHandler(); // get bounding box elements\n    storm.usePositionFixed = (storm.usePositionFixed && !noFixed && !storm.flakeBottom); // whether or not position:fixed is to be used\n    if (window.getComputedStyle) {\n      // attempt to determine if body or user-specified snow parent element is relatlively-positioned.\n      try {\n        targetElementIsRelative = (window.getComputedStyle(storm.targetElement, null).getPropertyValue('position') === 'relative');\n      } catch(e) {\n        // oh well\n        targetElementIsRelative = false;\n      }\n    }\n    fixedForEverything = storm.usePositionFixed;\n    if (screenX && screenY && !storm.disabled) {\n      storm.init();\n      storm.active = true;\n    }\n  };\n\n  function doDelayedStart() {\n    window.setTimeout(function() {\n      storm.start(true);\n    }, 20);\n    // event cleanup\n    storm.events.remove(isIE?document:window,'mousemove',doDelayedStart);\n  }\n\n  function doStart() {\n    if (!storm.excludeMobile || !isMobile) {\n      doDelayedStart();\n    }\n    // event cleanup\n    storm.events.remove(window, 'load', doStart);\n  }\n\n  // hooks for starting the snow\n  if (storm.autoStart) {\n    storm.events.add(window, 'load', doStart, false);\n  }\n\n  return this;\n\n}(window, document));\n\n</script>\n<script type=\"text/javascript\">\nsnowStorm.snowColor = '#99ccff'; // blue-ish snow!?\nsnowStorm.flakesMaxActive = 96;  // show more snow on screen at once\nsnowStorm.useTwinkleEffect = true; // let the snow flicker in and out of view\n</script>\n<script type=\"text/javascript\">\nsnowStorm.snowColor = '#99ccff'; // blue-ish snow!?\nsnowStorm.flakesMaxActive = 96;  // show more snow on screen at once\nsnowStorm.useTwinkleEffect = true; // let the snow flicker in and out of view\n</script>\n","output":"str","x":410,"y":3480,"wires":[["c6387b80.b7f4c8"]]},{"id":"c6387b80.b7f4c8","type":"http response","z":"3dc8ae0.6cb8152","name":"","statusCode":"","headers":{},"x":550,"y":3480,"wires":[]},{"id":"47cff474.c10abc","type":"ui_template","z":"3dc8ae0.6cb8152","group":"e48cfddb.2a7a6","name":"snow","order":0,"width":"1","height":"1","format":"<style>\n    body {\n    overflow: hidden;\n}\niframe {\n     position: fixed;\n     z-index: 10;\n     top: 0;\n     left: 0;\n     width: 100%;\n     height: 100%;\n     pointer-events: none;\n}\n</style>\n\n<iframe src=\"/snow\"></iframe>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":410,"y":3520,"wires":[[]]},{"id":"e48cfddb.2a7a6","type":"ui_group","z":"","name":"Globals","tab":"52aaa596.768b7c","order":6,"disp":true,"width":"6"},{"id":"52aaa596.768b7c","type":"ui_tab","z":"","name":"Angular UI templates","icon":"dashboard"}]
Hugobox

Flow Info

created 10 months, 3 weeks ago

Node Types

Core
  • http in (x1)
  • http response (x1)
  • template (x1)
Other
  • ui_group (x1)
  • ui_tab (x1)
  • ui_template (x1)

Tags

  • snow
  • snowstorm
  • dashboard
  • ui
  • christmas
  • winter
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option