<commit_before>/**
 * Particleground
 *
 * @author Jonathan Nicol - @mrjnicol
 * @version 1.0.1
 * @description Creates a canvas based particle system background
 *
 * Inspired by:
 * http://requestlab.fr/
 * http://disruptivebydesign.com/
 *
 * @license The MIT License (MIT)
 *
 * Copyright (c) 2014 Jonathan Nicol - @mrjnicol
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

;(function($) {
  var pluginName = 'particleground';

  function Plugin(element, options) {
    var el = element;
    var $el = $(element);
    var canvasSupport = !!document.createElement('canvas').getContext;
    var canvas;
    var ctx;
    var particles = [];
    var raf;
    var mouseX = 0;
    var mouseY = 0;
    var winW;
    var winH;
    var desktop = !navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|BB10|mobi|tablet|opera mini|nexus 7)/i);
    var orientationSupport = !!window.DeviceOrientationEvent;
    var tiltX = 0;
    var tiltY = 0;
    var paused = false;

    options = $.extend({}, $.fn[pluginName].defaults, options);

    /**
     * Init
     */
    function init() {
      if (!canvasSupport) { return; }

      //Create canvas
      $canvas = $('<canvas class="pg-canvas"></canvas>');
      $el.prepend($canvas);
      canvas = $canvas[0];
      ctx = canvas.getContext('2d');
      styleCanvas();

      // Create particles
      var numParticles = Math.round((canvas.width * canvas.height) / options.density);
      for (var i = 0; i < numParticles; i++) {
        var p = new Particle();
        p.setStackPos(i);
        particles.push(p);
      };

      $(window).on('resize', function() {
        resizeHandler();
      });

      $(document).on('mousemove', function(e) {
        mouseX = e.pageX;
        mouseY = e.pageY;
      });

      if (orientationSupport && !desktop) {
        window.addEventListener('deviceorientation', function () {
          // Contrain tilt range to [-30,30]
          tiltY = Math.min(Math.max(-event.beta, -30), 30);
          tiltX = Math.min(Math.max(-event.gamma, -30), 30);
        }, true);
      }

      draw();
      hook('onInit');
    }

    /**
     * Style the canvas
     */
    function styleCanvas() {
      canvas.width = $el.width();;
      canvas.height = $el.height();;
      ctx.fillStyle = options.dotColor;
      ctx.strokeStyle = options.lineColor;
      ctx.lineWidth = options.lineWidth;
    }

    /**
     * Draw particles
     */
    function draw() {
      if (!canvasSupport) { return; }

      winW = $(window).width();
      winH = $(window).height();

      // Wipe canvas
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // Update particle positions
      for (var i = 0; i < particles.length; i++) {
        particles[i].updatePosition();
      };
      // Draw particles
      for (var i = 0; i < particles.length; i++) {
        particles[i].draw();
      };

      // Call this function next time screen is redrawn
      if (!paused) {
        raf = requestAnimationFrame(draw);
      }
    }

    /**
     * Add/remove particles.
     */
    function resizeHandler() {
      // Resize the canvas
      styleCanvas();

      // Remove particles that are outside the canvas
      for (i = particles.length - 1; i >= 0; i--) {
        if (particles[i].position.x > $el.width() || particles[i].position.y > $el.height()) {
          particles.splice(i, 1);
        }
      };

      // Adjust partivcle density
      var numParticles = Math.round((canvas.width * canvas.height) / options.density);
      if (numParticles > particles.length) {
        while (numParticles > particles.length) {
          var p = new Particle();
          particles.push(p);
        }
      } else if (numParticles < particles.length) {
        particles.splice(numParticles);
      }

      // Re-index particles
      for (i = particles.length - 1; i >= 0; i--) {
        particles[i].setStackPos(i);
      };
    }

    /**
     * Pause particle system
     */
    function pause() {
      paused = true;
    }

    /**
     * Start particle system
     */
    function start() {
      paused = false;
      draw();
    }

    /**
     * Particle
     */
    function Particle() {
      this.stackPos;
      this.active = true;
      this.layer = Math.ceil(Math.random() * 3);
      this.parallaxOffsetX = 0;
      this.parallaxOffsetY = 0;
      // Initial particle position
      this.position = {
        x: Math.ceil(Math.random() * canvas.width),
        y: Math.ceil(Math.random() * canvas.height)
      }
      // Random particle speed, within min and max values
      this.speed = {}
      switch (options.directionX) {
        case 'left':
          this.speed.x = +(-options.maxSpeedX + (Math.random() * options.maxSpeedX) - options.minSpeedX).toFixed(2);
          break;
        case 'right':
          this.speed.x = +((Math.random() * options.maxSpeedX) + options.minSpeedX).toFixed(2);
          break;
        default:
          this.speed.x = +((-options.maxSpeedX / 2) + (Math.random() * options.maxSpeedX)).toFixed(2);
          this.speed.x += this.speed.x > 0 ? options.minSpeedX : -options.minSpeedX;
          break;
      }
      switch (options.directionY) {
        case 'up':
          this.speed.y = +(-options.maxSpeedY + (Math.random() * options.maxSpeedY) - options.minSpeedY).toFixed(2);
          break;
        case 'down':
          this.speed.y = +((Math.random() * options.maxSpeedY) + options.minSpeedY).toFixed(2);
          break;
        default:
          this.speed.y = +((-options.maxSpeedY / 2) + (Math.random() * options.maxSpeedY)).toFixed(2);
          this.speed.x += this.speed.y > 0 ? options.minSpeedY : -options.minSpeedY;
          break;
      }
    }

    /**
     * Draw particle
     */
    Particle.prototype.draw = function() {
      // Draw circle
      ctx.beginPath();
      ctx.arc(this.position.x + this.parallaxOffsetX, this.position.y + this.parallaxOffsetY, options.particleRadius / 2, 0, Math.PI * 2, true);
      ctx.closePath();
      ctx.fill();

      // Draw lines
      ctx.beginPath();
      // Iterate over all particles which are higher in the stack than this one
      for (var i = particles.length - 1; i > this.stackPos; i--) {
        var p2 = particles[i];

        // Pythagorus theorum to get distance between two points
        var a = this.position.x - p2.position.x
        var b = this.position.y - p2.position.y
        var dist = Math.sqrt((a * a) + (b * b)).toFixed(2);

        // If the two particles are in proximity, join them
        if (dist < options.proximity) {
          ctx.moveTo(this.position.x + this.parallaxOffsetX, this.position.y + this.parallaxOffsetY);
          if (options.curvedLines) {
            ctx.quadraticCurveTo(Math.max(p2.position.x, p2.position.x), Math.min(p2.position.y, p2.position.y), p2.position.x + p2.parallaxOffsetX, p2.position.y + p2.parallaxOffsetY);
          } else {
            ctx.lineTo(p2.position.x + p2.parallaxOffsetX, p2.position.y + p2.parallaxOffsetY);
          }
        }
      }
      ctx.stroke();
      ctx.closePath();
    }

    /**
     * update particle position
     */
    Particle.prototype.updatePosition = function() {
      if (options.parallax) {
        if (orientationSupport && !desktop) {
          // Map tiltX range [-30,30] to range [0,winW]
          var ratioX = (winW - 0) / (30 - -30);
          pointerX = (tiltX - -30) * ratioX + 0;
          // Map tiltY range [-30,30] to range [0,winH]
          var ratioY = (winH - 0) / (30 - -30);
          pointerY = (tiltY - -30) * ratioY + 0;
        } else {
          pointerX = mouseX;
          pointerY = mouseY;
        }
        // Calculate parallax offsets
        this.parallaxTargX = (pointerX - (winW / 2)) / (options.parallaxMultiplier * this.layer);
        this.parallaxOffsetX += (this.parallaxTargX - this.parallaxOffsetX) / 10; // Easing equation
        this.parallaxTargY = (pointerY - (winH / 2)) / (options.parallaxMultiplier * this.layer);
        this.parallaxOffsetY += (this.parallaxTargY - this.parallaxOffsetY) / 10; // Easing equation
      }

      switch (options.directionX) {
        case 'left':
          if (this.position.x + this.speed.x + this.parallaxOffsetX < 0) {
            this.position.x = $el.width() - this.parallaxOffsetX;
          }
          break;
        case 'right':
          if (this.position.x + this.speed.x + this.parallaxOffsetX > $el.width()) {
            this.position.x = 0 - this.parallaxOffsetX;
          }
          break;
        default:
          // If particle has reached edge of canvas, reverse its direction
          if (this.position.x + this.speed.x + this.parallaxOffsetX > $el.width() || this.position.x + this.speed.x + this.parallaxOffsetX < 0) {
            this.speed.x = -this.speed.x;
          }
          break;
      }

      switch (options.directionY) {
        case 'up':
          if (this.position.y + this.speed.y + this.parallaxOffsetY < 0) {
            this.position.y = $el.height() - this.parallaxOffsetY;
          }
          break;
        case 'down':
          if (this.position.y + this.speed.y + this.parallaxOffsetY > $el.height()) {
            this.position.y = 0 - this.parallaxOffsetY;
          }
          break;
        default:
          // If particle has reached edge of canvas, reverse its direction
          if (this.position.y + this.speed.y + this.parallaxOffsetY > $el.height() || this.position.y + this.speed.y + this.parallaxOffsetY < 0) {
            this.speed.y = -this.speed.y;
          }
          break;
      }

      // Move particle
      this.position.x += this.speed.x;
      this.position.y += this.speed.y;
    }

    /**
     * Setter: particle stacking position
     */
    Particle.prototype.setStackPos = function(i) {
      this.stackPos = i;
    }

    function option (key, val) {
      if (val) {
        options[key] = val;
      } else {
        return options[key];
      }
    }

    function destroy() {
      $el.find('.pg-canvas').remove();
      hook('onDestroy');
      $el.removeData('plugin_' + pluginName);
    }

    function hook(hookName) {
      if (options[hookName] !== undefined) {
        options[hookName].call(el);
      }
    }

    init();

    return {
      option: option,
      destroy: destroy,
      start: start,
      pause: pause
    };
  }

  $.fn[pluginName] = function(options) {
    if (typeof arguments[0] === 'string') {
      var methodName = arguments[0];
      var args = Array.prototype.slice.call(arguments, 1);
      var returnVal;
      this.each(function() {
        if ($.data(this, 'plugin_' + pluginName) && typeof $.data(this, 'plugin_' + pluginName)[methodName] === 'function') {
          returnVal = $.data(this, 'plugin_' + pluginName)[methodName].apply(this, args);
        }
      });
      if (returnVal !== undefined){
        return returnVal;
      } else {
        return this;
      }
    } else if (typeof options === "object" || !options) {
      return this.each(function() {
        if (!$.data(this, 'plugin_' + pluginName)) {
          $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
        }
      });
    }
  };

  $.fn[pluginName].defaults = {
    minSpeedX: 0.1,
    maxSpeedX: 0.7,
    minSpeedY: 0.1,
    maxSpeedY: 0.7,
    directionX: 'center', // 'center', 'left' or 'right'. 'center' = dots bounce off edges
    directionY: 'center', // 'center', 'up' or 'down'. 'center' = dots bounce off edges
    density: 10000, // How many particles will be generated: one particle every n pixels
    dotColor: '#666666',
    lineColor: '#666666',
    particleRadius: 7, // Dot size
    lineWidth: 1,
    curvedLines: false,
    proximity: 100, // How close two dots need to be before they join
    parallax: true,
    parallaxMultiplier: 5, // The lower the number, the more extreme the parallax effect
    onInit: function() {},
    onDestroy: function() {}
  };

})(jQuery);

/**
 * requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
 * @see: http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 * @see: http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
 * @license: MIT license
 */
(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());<commit_msg>fixed typo – partivcle -> particle<commit_after>/**
 * Particleground
 *
 * @author Jonathan Nicol - @mrjnicol
 * @version 1.0.1
 * @description Creates a canvas based particle system background
 *
 * Inspired by:
 * http://requestlab.fr/
 * http://disruptivebydesign.com/
 *
 * @license The MIT License (MIT)
 *
 * Copyright (c) 2014 Jonathan Nicol - @mrjnicol
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

;(function($) {
  var pluginName = 'particleground';

  function Plugin(element, options) {
    var el = element;
    var $el = $(element);
    var canvasSupport = !!document.createElement('canvas').getContext;
    var canvas;
    var ctx;
    var particles = [];
    var raf;
    var mouseX = 0;
    var mouseY = 0;
    var winW;
    var winH;
    var desktop = !navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|BB10|mobi|tablet|opera mini|nexus 7)/i);
    var orientationSupport = !!window.DeviceOrientationEvent;
    var tiltX = 0;
    var tiltY = 0;
    var paused = false;

    options = $.extend({}, $.fn[pluginName].defaults, options);

    /**
     * Init
     */
    function init() {
      if (!canvasSupport) { return; }

      //Create canvas
      $canvas = $('<canvas class="pg-canvas"></canvas>');
      $el.prepend($canvas);
      canvas = $canvas[0];
      ctx = canvas.getContext('2d');
      styleCanvas();

      // Create particles
      var numParticles = Math.round((canvas.width * canvas.height) / options.density);
      for (var i = 0; i < numParticles; i++) {
        var p = new Particle();
        p.setStackPos(i);
        particles.push(p);
      };

      $(window).on('resize', function() {
        resizeHandler();
      });

      $(document).on('mousemove', function(e) {
        mouseX = e.pageX;
        mouseY = e.pageY;
      });

      if (orientationSupport && !desktop) {
        window.addEventListener('deviceorientation', function () {
          // Contrain tilt range to [-30,30]
          tiltY = Math.min(Math.max(-event.beta, -30), 30);
          tiltX = Math.min(Math.max(-event.gamma, -30), 30);
        }, true);
      }

      draw();
      hook('onInit');
    }

    /**
     * Style the canvas
     */
    function styleCanvas() {
      canvas.width = $el.width();;
      canvas.height = $el.height();;
      ctx.fillStyle = options.dotColor;
      ctx.strokeStyle = options.lineColor;
      ctx.lineWidth = options.lineWidth;
    }

    /**
     * Draw particles
     */
    function draw() {
      if (!canvasSupport) { return; }

      winW = $(window).width();
      winH = $(window).height();

      // Wipe canvas
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // Update particle positions
      for (var i = 0; i < particles.length; i++) {
        particles[i].updatePosition();
      };
      // Draw particles
      for (var i = 0; i < particles.length; i++) {
        particles[i].draw();
      };

      // Call this function next time screen is redrawn
      if (!paused) {
        raf = requestAnimationFrame(draw);
      }
    }

    /**
     * Add/remove particles.
     */
    function resizeHandler() {
      // Resize the canvas
      styleCanvas();

      // Remove particles that are outside the canvas
      for (i = particles.length - 1; i >= 0; i--) {
        if (particles[i].position.x > $el.width() || particles[i].position.y > $el.height()) {
          particles.splice(i, 1);
        }
      };

      // Adjust particle density
      var numParticles = Math.round((canvas.width * canvas.height) / options.density);
      if (numParticles > particles.length) {
        while (numParticles > particles.length) {
          var p = new Particle();
          particles.push(p);
        }
      } else if (numParticles < particles.length) {
        particles.splice(numParticles);
      }

      // Re-index particles
      for (i = particles.length - 1; i >= 0; i--) {
        particles[i].setStackPos(i);
      };
    }

    /**
     * Pause particle system
     */
    function pause() {
      paused = true;
    }

    /**
     * Start particle system
     */
    function start() {
      paused = false;
      draw();
    }

    /**
     * Particle
     */
    function Particle() {
      this.stackPos;
      this.active = true;
      this.layer = Math.ceil(Math.random() * 3);
      this.parallaxOffsetX = 0;
      this.parallaxOffsetY = 0;
      // Initial particle position
      this.position = {
        x: Math.ceil(Math.random() * canvas.width),
        y: Math.ceil(Math.random() * canvas.height)
      }
      // Random particle speed, within min and max values
      this.speed = {}
      switch (options.directionX) {
        case 'left':
          this.speed.x = +(-options.maxSpeedX + (Math.random() * options.maxSpeedX) - options.minSpeedX).toFixed(2);
          break;
        case 'right':
          this.speed.x = +((Math.random() * options.maxSpeedX) + options.minSpeedX).toFixed(2);
          break;
        default:
          this.speed.x = +((-options.maxSpeedX / 2) + (Math.random() * options.maxSpeedX)).toFixed(2);
          this.speed.x += this.speed.x > 0 ? options.minSpeedX : -options.minSpeedX;
          break;
      }
      switch (options.directionY) {
        case 'up':
          this.speed.y = +(-options.maxSpeedY + (Math.random() * options.maxSpeedY) - options.minSpeedY).toFixed(2);
          break;
        case 'down':
          this.speed.y = +((Math.random() * options.maxSpeedY) + options.minSpeedY).toFixed(2);
          break;
        default:
          this.speed.y = +((-options.maxSpeedY / 2) + (Math.random() * options.maxSpeedY)).toFixed(2);
          this.speed.x += this.speed.y > 0 ? options.minSpeedY : -options.minSpeedY;
          break;
      }
    }

    /**
     * Draw particle
     */
    Particle.prototype.draw = function() {
      // Draw circle
      ctx.beginPath();
      ctx.arc(this.position.x + this.parallaxOffsetX, this.position.y + this.parallaxOffsetY, options.particleRadius / 2, 0, Math.PI * 2, true);
      ctx.closePath();
      ctx.fill();

      // Draw lines
      ctx.beginPath();
      // Iterate over all particles which are higher in the stack than this one
      for (var i = particles.length - 1; i > this.stackPos; i--) {
        var p2 = particles[i];

        // Pythagorus theorum to get distance between two points
        var a = this.position.x - p2.position.x
        var b = this.position.y - p2.position.y
        var dist = Math.sqrt((a * a) + (b * b)).toFixed(2);

        // If the two particles are in proximity, join them
        if (dist < options.proximity) {
          ctx.moveTo(this.position.x + this.parallaxOffsetX, this.position.y + this.parallaxOffsetY);
          if (options.curvedLines) {
            ctx.quadraticCurveTo(Math.max(p2.position.x, p2.position.x), Math.min(p2.position.y, p2.position.y), p2.position.x + p2.parallaxOffsetX, p2.position.y + p2.parallaxOffsetY);
          } else {
            ctx.lineTo(p2.position.x + p2.parallaxOffsetX, p2.position.y + p2.parallaxOffsetY);
          }
        }
      }
      ctx.stroke();
      ctx.closePath();
    }

    /**
     * update particle position
     */
    Particle.prototype.updatePosition = function() {
      if (options.parallax) {
        if (orientationSupport && !desktop) {
          // Map tiltX range [-30,30] to range [0,winW]
          var ratioX = (winW - 0) / (30 - -30);
          pointerX = (tiltX - -30) * ratioX + 0;
          // Map tiltY range [-30,30] to range [0,winH]
          var ratioY = (winH - 0) / (30 - -30);
          pointerY = (tiltY - -30) * ratioY + 0;
        } else {
          pointerX = mouseX;
          pointerY = mouseY;
        }
        // Calculate parallax offsets
        this.parallaxTargX = (pointerX - (winW / 2)) / (options.parallaxMultiplier * this.layer);
        this.parallaxOffsetX += (this.parallaxTargX - this.parallaxOffsetX) / 10; // Easing equation
        this.parallaxTargY = (pointerY - (winH / 2)) / (options.parallaxMultiplier * this.layer);
        this.parallaxOffsetY += (this.parallaxTargY - this.parallaxOffsetY) / 10; // Easing equation
      }

      switch (options.directionX) {
        case 'left':
          if (this.position.x + this.speed.x + this.parallaxOffsetX < 0) {
            this.position.x = $el.width() - this.parallaxOffsetX;
          }
          break;
        case 'right':
          if (this.position.x + this.speed.x + this.parallaxOffsetX > $el.width()) {
            this.position.x = 0 - this.parallaxOffsetX;
          }
          break;
        default:
          // If particle has reached edge of canvas, reverse its direction
          if (this.position.x + this.speed.x + this.parallaxOffsetX > $el.width() || this.position.x + this.speed.x + this.parallaxOffsetX < 0) {
            this.speed.x = -this.speed.x;
          }
          break;
      }

      switch (options.directionY) {
        case 'up':
          if (this.position.y + this.speed.y + this.parallaxOffsetY < 0) {
            this.position.y = $el.height() - this.parallaxOffsetY;
          }
          break;
        case 'down':
          if (this.position.y + this.speed.y + this.parallaxOffsetY > $el.height()) {
            this.position.y = 0 - this.parallaxOffsetY;
          }
          break;
        default:
          // If particle has reached edge of canvas, reverse its direction
          if (this.position.y + this.speed.y + this.parallaxOffsetY > $el.height() || this.position.y + this.speed.y + this.parallaxOffsetY < 0) {
            this.speed.y = -this.speed.y;
          }
          break;
      }

      // Move particle
      this.position.x += this.speed.x;
      this.position.y += this.speed.y;
    }

    /**
     * Setter: particle stacking position
     */
    Particle.prototype.setStackPos = function(i) {
      this.stackPos = i;
    }

    function option (key, val) {
      if (val) {
        options[key] = val;
      } else {
        return options[key];
      }
    }

    function destroy() {
      $el.find('.pg-canvas').remove();
      hook('onDestroy');
      $el.removeData('plugin_' + pluginName);
    }

    function hook(hookName) {
      if (options[hookName] !== undefined) {
        options[hookName].call(el);
      }
    }

    init();

    return {
      option: option,
      destroy: destroy,
      start: start,
      pause: pause
    };
  }

  $.fn[pluginName] = function(options) {
    if (typeof arguments[0] === 'string') {
      var methodName = arguments[0];
      var args = Array.prototype.slice.call(arguments, 1);
      var returnVal;
      this.each(function() {
        if ($.data(this, 'plugin_' + pluginName) && typeof $.data(this, 'plugin_' + pluginName)[methodName] === 'function') {
          returnVal = $.data(this, 'plugin_' + pluginName)[methodName].apply(this, args);
        }
      });
      if (returnVal !== undefined){
        return returnVal;
      } else {
        return this;
      }
    } else if (typeof options === "object" || !options) {
      return this.each(function() {
        if (!$.data(this, 'plugin_' + pluginName)) {
          $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
        }
      });
    }
  };

  $.fn[pluginName].defaults = {
    minSpeedX: 0.1,
    maxSpeedX: 0.7,
    minSpeedY: 0.1,
    maxSpeedY: 0.7,
    directionX: 'center', // 'center', 'left' or 'right'. 'center' = dots bounce off edges
    directionY: 'center', // 'center', 'up' or 'down'. 'center' = dots bounce off edges
    density: 10000, // How many particles will be generated: one particle every n pixels
    dotColor: '#666666',
    lineColor: '#666666',
    particleRadius: 7, // Dot size
    lineWidth: 1,
    curvedLines: false,
    proximity: 100, // How close two dots need to be before they join
    parallax: true,
    parallaxMultiplier: 5, // The lower the number, the more extreme the parallax effect
    onInit: function() {},
    onDestroy: function() {}
  };

})(jQuery);

/**
 * requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
 * @see: http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 * @see: http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
 * @license: MIT license
 */
(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());
<|endoftext|>


<commit_before>import React from 'react';
import Card from './Card';
import CurrentWeather from './CurrentWeather';
import SevenHour from './SevenHour';
import TenDay from './TenDay';
import Search from './Search';
import WelcomePage from './WelcomePage';
import RecentCities from './RecentCities';
import Nav from './Nav';
import key from './keys'
import './Styles.css';
import Trie from './Trie';
import Citylist from './Citylist';
import Node from './Node';

const trie = new Trie();
trie.populate(Citylist);

export default class App extends React.Component {
  constructor() {
    super();
    this.state = {
      city: '',
      condition: '',
      date: '',
      fullLocal: '',
      high: '',
      icon: '',
      location: '',
      low: '',
      message: '',
      temp: '',
      zipCode: '',
      day: [],
      hourly: [],
      suggestions: [],
      tempCities: [],
      cityClicked: false,
      displayWelcome: true,
      searchClicked: false,
      sevenClicked: false,
      tenClicked: false,
    };
  }

  clickCity(newCity) {
    trie.select(newCity);
    this.setState({
      city: newCity,
      suggestions: [],
    });
  }

  componentWillMount() {
    const oldLocation = localStorage.getItem('currentCity');
    if (oldLocation) {
      this.setState({
        city: oldLocation,
      }, this.submitClicked);
    }
  }

  dayClicked() {
    this.setState({
      sevenClicked: false,
      tenClicked: true,
      cityClicked: false,
    });
  }

  getWeatherInfo() {
    fetch(`http://api.wunderground.com/api/${key.weathergroundKey}/conditions/hourly/forecast10day/q/${this.state.city}.json`)
    .then(data => data.json())
    .then(data => this.setState({
      location: data.current_observation.display_location.city,
      fullLocal: data.current_observation.display_location.full,
      temp: data.current_observation.temp_f,
      zipCode: data.current_observation.display_location.zip,
      condition: data.current_observation.weather,
      high: data.forecast.simpleforecast.forecastday[0].high.fahrenheit,
      low: data.forecast.simpleforecast.forecastday[0].low.fahrenheit,
      day: data.forecast.simpleforecast.forecastday,
      hourly: data.hourly_forecast,
      icon: data.current_observation.icon,
    })
    // .catch(() => {
    //   this.setState({
    //     city: 'DENVER, CO'
    //   });
    // })
  )}

  hourClicked() {
    this.setState({
      sevenClicked: true,
      tenClicked: false,
      cityClicked: false,
    });
  }

  setCity(newCity) {
    this.setState({
      suggestions: trie.suggest(newCity),
      city: newCity,
    });
  }

  setToLocal() {
    const locale = this.state.city;
    const topCities = JSON.parse(localStorage.getItem('recentCities')) || [];

    topCities.unshift(locale);

    this.setState({
      tempCities: JSON.parse(localStorage.getItem('recentCities'))
    });

    const currentCity = locale;
    const recentCities = JSON.stringify(topCities);

    localStorage.setItem('currentCity', currentCity);
    localStorage.setItem('recentCities', recentCities);
  }

  submitClicked() {
    this.setToLocal();
    this.getWeatherInfo();
    this.setState({
      searchClicked: true,
      sevenClicked: true,
      tenClicked: false,
      cityClicked: false,
      displayWelcome: false,
    });
  }

  topClicked() {
    this.setState({
      sevenClicked: false,
      tenClicked: false,
      cityClicked: true,
    });
  }

  render() {
    const { city,
      cityClicked,
      condition,
      date,
      day,
      displayWelcome,
      fullLocal,
      high,
      hourly,
      icon,
      low,
      message,
      searchClicked,
      sevenClicked,
      suggestions,
      tempCities,
      tenClicked,
      temp,
      zipCode } = this.state

    return (

        {
          displayWelcome &&
          <WelcomePage
            clickedSubmit = {this.submitClicked.bind(this) }
            setCity = { this.setCity.bind(this) }
            suggestions = { suggestions }
            clickCity = { this.clickCity.bind(this) }
            inputValue = { city }
            message = { message } />
        }
        {
          searchClicked &&
        <Search
        inputValue = { city }
        clickedSubmit = { this.submitClicked.bind(this) }
        setCity = { this.setCity.bind(this) }
        suggestions = { suggestions }
        clickCity = { this.clickCity.bind(this) }
        message = { message } />
        }
        { searchClicked &&

        }

          {
            searchClicked &&
            <CurrentWeather
            location= { fullLocal }
            date = { date }
            temp = { temp }
            zipCode = { zipCode }
            condition = { condition }
            high = { high }
            low = { low }
            icon = { icon }
            message = { message }/>
          }
          {
            sevenClicked &&
            <SevenHour
            sevenHourInfo = { hourly }
            icon = { icon } />
          }
        {
          tenClicked &&
          <TenDay
          tenDayInfo = { day }
          icon = { icon }
          />
        }
        {
          cityClicked &&
          <RecentCities
          searchedCities = { tempCities }
          clickCity = { this.clickCity.bind(this) } />
        }

    );
  }
}
<commit_msg>Refactor weather info<commit_after>import React from 'react';
import Card from './Card';
import CurrentWeather from './CurrentWeather';
import SevenHour from './SevenHour';
import TenDay from './TenDay';
import Search from './Search';
import WelcomePage from './WelcomePage';
import RecentCities from './RecentCities';
import Nav from './Nav';
import key from './keys'
import './Styles.css';
import Trie from './Trie';
import Citylist from './Citylist';
import Node from './Node';

const trie = new Trie();
trie.populate(Citylist);

export default class App extends React.Component {
  constructor() {
    super();
    this.state = {
      city: '',
      condition: '',
      date: '',
      fullLocal: '',
      high: '',
      icon: '',
      location: '',
      low: '',
      message: '',
      temp: '',
      zipCode: '',
      day: [],
      hourly: [],
      suggestions: [],
      tempCities: [],
      cityClicked: false,
      displayWelcome: true,
      searchClicked: false,
      sevenClicked: false,
      tenClicked: false,
    };
  }

  clickCity(newCity) {
    trie.select(newCity);
    this.setState({
      city: newCity,
      suggestions: [],
    });
  }

  componentWillMount() {
    const oldLocation = localStorage.getItem('currentCity');
    if (oldLocation) {
      this.setState({
        city: oldLocation,
      }, this.submitClicked);
    }
  }

  dayClicked() {
    this.setState({
      sevenClicked: false,
      tenClicked: true,
      cityClicked: false,
    });
  }

  getWeatherInfo() {
    fetch(`http://api.wunderground.com/api/${key.weathergroundKey}/conditions/hourly/forecast10day/q/${this.state.city}.json`)
    .then(data => data.json())
    .then(data => this.stateSet(data)
  )}

  hourClicked() {
    this.setState({
      sevenClicked: true,
      tenClicked: false,
      cityClicked: false,
    });
  }

  setCity(newCity) {
    this.setState({
      suggestions: trie.suggest(newCity),
      city: newCity,
    });
  }

  setToLocal() {
    const locale = this.state.city;
    const topCities = JSON.parse(localStorage.getItem('recentCities')) || [];

    topCities.unshift(locale);

    this.setState({
      tempCities: JSON.parse(localStorage.getItem('recentCities'))
    });

    const currentCity = locale;
    const recentCities = JSON.stringify(topCities);

    localStorage.setItem('currentCity', currentCity);
    localStorage.setItem('recentCities', recentCities);
  }

  stateSet(data) {
    this.setState({
      location: data.current_observation.display_location.city,
      fullLocal: data.current_observation.display_location.full,
      temp: data.current_observation.temp_f,
      zipCode: data.current_observation.display_location.zip,
      condition: data.current_observation.weather,
      high: data.forecast.simpleforecast.forecastday[0].high.fahrenheit,
      low: data.forecast.simpleforecast.forecastday[0].low.fahrenheit,
      day: data.forecast.simpleforecast.forecastday,
      hourly: data.hourly_forecast,
      icon: data.current_observation.icon,
      searchClicked: true,
      sevenClicked: true,
      tenClicked: false,
      cityClicked: false,
      displayWelcome: false,
    })
  }

  submitClicked() {
    this.setToLocal();
    this.getWeatherInfo();
  }

  topClicked() {
    this.setState({
      sevenClicked: false,
      tenClicked: false,
      cityClicked: true,
    });
  }

  render() {
    const { city,
      cityClicked,
      condition,
      date,
      day,
      displayWelcome,
      fullLocal,
      high,
      hourly,
      icon,
      low,
      message,
      searchClicked,
      sevenClicked,
      suggestions,
      tempCities,
      tenClicked,
      temp,
      zipCode } = this.state

    return (

        {
          displayWelcome &&
          <WelcomePage
            clickedSubmit = {this.submitClicked.bind(this) }
            setCity = { this.setCity.bind(this) }
            suggestions = { suggestions }
            clickCity = { this.clickCity.bind(this) }
            inputValue = { city }
            message = { message } />
        }
        {
          searchClicked &&
        <Search
        inputValue = { city }
        clickedSubmit = { this.submitClicked.bind(this) }
        setCity = { this.setCity.bind(this) }
        suggestions = { suggestions }
        clickCity = { this.clickCity.bind(this) }
         />
        }
        { searchClicked &&

        }

          {
            searchClicked &&
            <CurrentWeather
            location= { fullLocal }
            date = { date }
            temp = { temp }
            zipCode = { zipCode }
            condition = { condition }
            high = { high }
            low = { low }
            icon = { icon }
            />
          }
          {
            sevenClicked &&
            <SevenHour
            sevenHourInfo = { hourly }
            icon = { icon } />
          }
        {
          tenClicked &&
          <TenDay
          tenDayInfo = { day }
          icon = { icon }
          />
        }
        {
          cityClicked &&
          <RecentCities
          searchedCities = { tempCities }
          clickCity = { this.clickCity.bind(this) } />
        }

    );
  }
}
<|endoftext|>


<commit_before>//Like cube but not subdivided and continuous on edges

//## Parent class : [Geometry](../Geometry.html)

//## Example use
//      var cube = new Box(1, 1, 1);
//      var cubeMesh = new Mesh(cube, new Materials.TestMaterial());

var geom = require('pex-geom');
var Vec2 = geom.Vec2;
var Vec3 = geom.Vec3;
var Geometry = geom.Geometry;

//### Box ( sx, sy, sz )
//`sx` - size x / width *{ Number }*
//`sy` - size y / height *{ Number }*
//`sz` - size z / depth *{ Number }*
function Box(sx, sy, sz) {
  sx = sx != null ? sx : 1;
  sy = sy != null ? sy : sx != null ? sx : 1;
  sz = sz != null ? sz : sx != null ? sx : 1;

  Geometry.call(this, { vertices: true, faces: true });

  var vertices = this.vertices;
  var faces = this.faces;

  var x = sx/2;
  var y = sy/2;
  var z = sz/2;

  //bottom
  vertices.push(new Vec3(-x, -y, -z));
  vertices.push(new Vec3(-x, -y,  z));
  vertices.push(new Vec3( x, -y,  z));
  vertices.push(new Vec3( x, -y, -z));

  //top
  vertices.push(new Vec3(-x,  y, -z));
  vertices.push(new Vec3(-x,  y,  z));
  vertices.push(new Vec3( x,  y,  z));
  vertices.push(new Vec3( x,  y, -z));

  //     4----7
  //    /:   /|
  //   5----6 |
  //   | 0..|.3
  //   |,   |/
  //   1----2

  faces.push([0, 3, 2, 1]); //bottom
  faces.push([4, 5, 6, 7]); //top
  faces.push([0, 1, 5, 4]); //left
  faces.push([2, 3, 7, 6]); //right
  faces.push([1, 2, 6, 5]); //front
  faces.push([3, 0, 4, 7]); //back

  this.computeSmoothNormals();
}

Box.prototype = Object.create(Geometry.prototype);

module.exports = Box;
<commit_msg>Renamed computeSmoothNormals<commit_after>//Like cube but not subdivided and continuous on edges

//## Parent class : [Geometry](../Geometry.html)

//## Example use
//      var cube = new Box(1, 1, 1);
//      var cubeMesh = new Mesh(cube, new Materials.TestMaterial());

var geom = require('pex-geom');
var Vec2 = geom.Vec2;
var Vec3 = geom.Vec3;
var Geometry = geom.Geometry;

//### Box ( sx, sy, sz )
//`sx` - size x / width *{ Number }*
//`sy` - size y / height *{ Number }*
//`sz` - size z / depth *{ Number }*
function Box(sx, sy, sz) {
  sx = sx != null ? sx : 1;
  sy = sy != null ? sy : sx != null ? sx : 1;
  sz = sz != null ? sz : sx != null ? sx : 1;

  Geometry.call(this, { vertices: true, faces: true });

  var vertices = this.vertices;
  var faces = this.faces;

  var x = sx/2;
  var y = sy/2;
  var z = sz/2;

  //bottom
  vertices.push(new Vec3(-x, -y, -z));
  vertices.push(new Vec3(-x, -y,  z));
  vertices.push(new Vec3( x, -y,  z));
  vertices.push(new Vec3( x, -y, -z));

  //top
  vertices.push(new Vec3(-x,  y, -z));
  vertices.push(new Vec3(-x,  y,  z));
  vertices.push(new Vec3( x,  y,  z));
  vertices.push(new Vec3( x,  y, -z));

  //     4----7
  //    /:   /|
  //   5----6 |
  //   | 0..|.3
  //   |,   |/
  //   1----2

  faces.push([0, 3, 2, 1]); //bottom
  faces.push([4, 5, 6, 7]); //top
  faces.push([0, 1, 5, 4]); //left
  faces.push([2, 3, 7, 6]); //right
  faces.push([1, 2, 6, 5]); //front
  faces.push([3, 0, 4, 7]); //back

  this.computeNormals();
}

Box.prototype = Object.create(Geometry.prototype);

module.exports = Box;
<|endoftext|>


<commit_before>(function(){
	'use strict';

	angular
		.module('shipyard.containers')
		.controller('ContainerStatsController', ContainerStatsController);

	ContainerStatsController.$inject = ['$stateParams'];
	function ContainerStatsController($stateParams) {
            var vm = this;
            var graphCpuStats;
            var graphMemoryStats;
            var graphNetStats;
            vm.refreshInterval = 5;
            vm.id = $stateParams.id;

            vm.cpuStats = [{
                key: "CPU",
                values: []
            }];

            vm.memoryStats = [{
                key: "Memory",
                color: '#ffa500',
                values: []
            }];

            vm.netStats = [
                {
                    key: "Network (rx)",
                    values: []
                },
                {
                    key: "Network (tx)",
                    values: []
                }
            ];

            vm.x = 0;

            var previousCpuUsage = 0;
            var previousSystemCpuUsage = 0;
            function addCpuUsage(date, systemUsage, usage, cpuCores) {
                if(previousCpuUsage == 0 || previousSystemCpuUsage == 0) {
                    previousCpuUsage = usage;
                    previousSystemCpuUsage = systemUsage;
                    return;
                }

                var usageSample = usage - previousCpuUsage
                previousCpuUsage = usage;

                var systemUsageSample = systemUsage - previousSystemCpuUsage;
                previousSystemCpuUsage = systemUsage;

                var cpuPercent = 0.0;
                if(usageSample > 0.0 && systemUsageSample > 0.0) {
                    cpuPercent = (usageSample / systemUsageSample) * cpuCores * 100.0;
                }

                var stat = { x: date, y: cpuPercent };
                vm.cpuStats[0].values.push(stat);
                if (vm.cpuStats[0].values.length > 20) {
                    vm.cpuStats[0].values.shift();
                }

            }

            function addMemoryUsage(date, usage) {
                var stat = { x: date, y: usage };
                vm.memoryStats[0].values.push(stat);
                if (vm.memoryStats[0].values.length > 20) {
                    vm.memoryStats[0].values.shift();
                }
            }

            function addNetworkUsage(date, rxUsage, txUsage) {
                var rxStat = { x: date, y: rxUsage };
                vm.netStats[0].values.push(rxStat);
                if (vm.netStats[0].values.length > 20) {
                    vm.netStats[0].values.shift();
                }

                var txStat = { x: date, y: txUsage };
                vm.netStats[1].values.push(txStat);
                if (vm.netStats[1].values.length > 20) {
                    vm.netStats[1].values.shift();
                }
            }

            nv.addGraph(function() {
                graphCpuStats = nv.models.lineChart()
                    .options({
                        transitionDuration: 300,
                        noData: "Loading...",
                    })
                    ;
                graphCpuStats
                    .x(function(d,i) { return d.x });
                graphCpuStats.xAxis // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately
                    .tickFormat(function(d) { return d3.time.format('%H:%M:%S')(new Date(d));  })
                    .axisLabel("")
                    ;
                graphCpuStats
                graphCpuStats.yAxis
                    .axisLabel('')
                    .tickFormat(d3.format(',.4f'));
                graphCpuStats.showXAxis(true).showYAxis(true).rightAlignYAxis(true).margin({right: 90});
                d3.select('#graphCpuStats svg')
                    .datum(vm.cpuStats)
                    .transition().duration(500)
                    .call(graphCpuStats);
                nv.utils.windowResize(graphCpuStats.update);
                return graphCpuStats;
            });

            nv.addGraph(function() {
                graphMemoryStats = nv.models.lineChart()
                    .options({
                        transitionDuration: 300,
                        noData: "Loading...",
                    })
                    .forceY([0,1])
                    ;
                graphMemoryStats
                    .x(function(d,i) { return d.x });
                graphMemoryStats.xAxis // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately
                    .tickFormat(function(d) { return d3.time.format('%H:%M:%S')(new Date(d));  })
                    .axisLabel("")
                    ;
                graphMemoryStats
                graphMemoryStats.yAxis
                    .axisLabel('')
                    .tickFormat(d3.format(',.4f'));
                graphMemoryStats.showXAxis(true).showYAxis(true).rightAlignYAxis(true).margin({right: 90});
                d3.select('#graphMemoryStats svg')
                    .datum(vm.memoryStats)
                    .transition().duration(500)
                    .call(graphMemoryStats);
                nv.utils.windowResize(graphMemoryStats.update);
                return graphMemoryStats;
            });

            nv.addGraph(function() {
                graphNetStats = nv.models.lineChart()
                    .options({
                        transitionDuration: 300,
                        noData: "Loading...",
                    })
                    ;
                graphNetStats
                    .x(function(d,i) { return d.x });
                graphNetStats.xAxis // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately
                    .tickFormat(function(d) { return d3.time.format('%H:%M:%S')(new Date(d));  })
                    .axisLabel("")
                    ;
                graphNetStats
                graphNetStats.yAxis
                    .axisLabel('')
                    .tickFormat(d3.format(',.4f'));
                graphNetStats.showXAxis(true).showYAxis(true).rightAlignYAxis(true).margin({right: 90});
                d3.select('#graphNetStats svg')
                    .datum(vm.netStats)
                    .transition().duration(500)
                    .call(graphNetStats);
                nv.utils.windowResize(graphNetStats.update);
                return graphNetStats;
            });

            oboe({
                url: '/containers/' + vm.id + '/stats',
                withCredentials: true,
                headers: {
                    'X-Access-Token': localStorage.getItem("X-Access-Token")
                }
            })
            .done(function(node) {
                // stats come every 1 second; only update every 5
                if (vm.x % vm.refreshInterval === 0) {
                    var timestamp = Date.parse(node.read);
                    addCpuUsage(timestamp, node.cpu_stats.system_cpu_usage, node.cpu_stats.cpu_usage.total_usage, node.cpu_stats.cpu_usage.percpu_usage.length);
                    addMemoryUsage(timestamp, node.memory_stats.usage);
                    addNetworkUsage(timestamp, node.network.rx_bytes, node.network.tx_bytes);
                    refreshGraphs();
                }
                vm.x++;
            })
            .fail(function(err) {
                vm.error = err;
            });

            function refreshGraphs() {
                graphCpuStats.update();
                graphMemoryStats.update();
                graphNetStats.update();
            }

	}
})();
<commit_msg>Terminate stream when navigating away from stats page<commit_after>(function(){
    'use strict';

    angular
        .module('shipyard.containers')
        .controller('ContainerStatsController', ContainerStatsController);

    ContainerStatsController.$inject = ['$stateParams', '$scope'];
    function ContainerStatsController($stateParams, $scope) {
        var vm = this;
        var graphCpuStats;
        var graphMemoryStats;
        var graphNetStats;
        vm.refreshInterval = 5;
        vm.id = $stateParams.id;

        vm.cpuStats = [{
            key: "CPU",
            values: []
        }];

        vm.memoryStats = [{
            key: "Memory",
            color: '#ffa500',
            values: []
        }];

        vm.netStats = [
        {
            key: "Network (rx)",
            values: []
        },
        {
            key: "Network (tx)",
            values: []
        }
        ];

        vm.x = 0;

        var previousCpuUsage = 0;
        var previousSystemCpuUsage = 0;
        function addCpuUsage(date, systemUsage, usage, cpuCores) {
            if(previousCpuUsage == 0 || previousSystemCpuUsage == 0) {
                previousCpuUsage = usage;
                previousSystemCpuUsage = systemUsage;
                return;
            }

            var usageSample = usage - previousCpuUsage
                previousCpuUsage = usage;

            var systemUsageSample = systemUsage - previousSystemCpuUsage;
            previousSystemCpuUsage = systemUsage;

            var cpuPercent = 0.0;
            if(usageSample > 0.0 && systemUsageSample > 0.0) {
                cpuPercent = (usageSample / systemUsageSample) * cpuCores * 100.0;
            }

            var stat = { x: date, y: cpuPercent };
            vm.cpuStats[0].values.push(stat);
            if (vm.cpuStats[0].values.length > 20) {
                vm.cpuStats[0].values.shift();
            }

        }

        function addMemoryUsage(date, usage) {
            var stat = { x: date, y: usage };
            vm.memoryStats[0].values.push(stat);
            if (vm.memoryStats[0].values.length > 20) {
                vm.memoryStats[0].values.shift();
            }
        }

        function addNetworkUsage(date, rxUsage, txUsage) {
            var rxStat = { x: date, y: rxUsage };
            vm.netStats[0].values.push(rxStat);
            if (vm.netStats[0].values.length > 20) {
                vm.netStats[0].values.shift();
            }

            var txStat = { x: date, y: txUsage };
            vm.netStats[1].values.push(txStat);
            if (vm.netStats[1].values.length > 20) {
                vm.netStats[1].values.shift();
            }
        }

        nv.addGraph(function() {
            graphCpuStats = nv.models.lineChart()
                .options({
                    transitionDuration: 300,
                    noData: "Loading...",
                })
            ;
            graphCpuStats
                .x(function(d,i) { return d.x });
            graphCpuStats.xAxis // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately
                .tickFormat(function(d) { return d3.time.format('%H:%M:%S')(new Date(d));  })
                .axisLabel("")
                ;
            graphCpuStats
                graphCpuStats.yAxis
                .axisLabel('')
                .tickFormat(d3.format(',.4f'));
            graphCpuStats.showXAxis(true).showYAxis(true).rightAlignYAxis(true).margin({right: 90});
            d3.select('#graphCpuStats svg')
                .datum(vm.cpuStats)
                .transition().duration(500)
                .call(graphCpuStats);
            nv.utils.windowResize(graphCpuStats.update);
            return graphCpuStats;
        });

        nv.addGraph(function() {
            graphMemoryStats = nv.models.lineChart()
                .options({
                    transitionDuration: 300,
                    noData: "Loading...",
                })
            .forceY([0,1])
                ;
            graphMemoryStats
                .x(function(d,i) { return d.x });
            graphMemoryStats.xAxis // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately
                .tickFormat(function(d) { return d3.time.format('%H:%M:%S')(new Date(d));  })
                .axisLabel("")
                ;
            graphMemoryStats
                graphMemoryStats.yAxis
                .axisLabel('')
                .tickFormat(d3.format(',.4f'));
            graphMemoryStats.showXAxis(true).showYAxis(true).rightAlignYAxis(true).margin({right: 90});
            d3.select('#graphMemoryStats svg')
                .datum(vm.memoryStats)
                .transition().duration(500)
                .call(graphMemoryStats);
            nv.utils.windowResize(graphMemoryStats.update);
            return graphMemoryStats;
        });

        nv.addGraph(function() {
            graphNetStats = nv.models.lineChart()
                .options({
                    transitionDuration: 300,
                    noData: "Loading...",
                })
            ;
            graphNetStats
                .x(function(d,i) { return d.x });
            graphNetStats.xAxis // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately
                .tickFormat(function(d) { return d3.time.format('%H:%M:%S')(new Date(d));  })
                .axisLabel("")
                ;
            graphNetStats
                graphNetStats.yAxis
                .axisLabel('')
                .tickFormat(d3.format(',.4f'));
            graphNetStats.showXAxis(true).showYAxis(true).rightAlignYAxis(true).margin({right: 90});
            d3.select('#graphNetStats svg')
                .datum(vm.netStats)
                .transition().duration(500)
                .call(graphNetStats);
            nv.utils.windowResize(graphNetStats.update);
            return graphNetStats;
        });

        var stream = oboe({
            url: '/containers/' + vm.id + '/stats',
            withCredentials: true,
            headers: {
                'X-Access-Token': localStorage.getItem("X-Access-Token")
            }
        })
        .done(function(node) {
            // stats come every 1 second; only update every 5
            if (vm.x % vm.refreshInterval === 0) {
                var timestamp = Date.parse(node.read);
                addCpuUsage(timestamp, node.cpu_stats.system_cpu_usage, node.cpu_stats.cpu_usage.total_usage, node.cpu_stats.cpu_usage.percpu_usage.length);
                addMemoryUsage(timestamp, node.memory_stats.usage);
                addNetworkUsage(timestamp, node.network.rx_bytes, node.network.tx_bytes);
                refreshGraphs();
            }
            vm.x++;
        })
        .fail(function(err) {
            vm.error = err;
        })

        function refreshGraphs() {
            graphCpuStats.update();
            graphMemoryStats.update();
            graphNetStats.update();
        }

        $scope.$on("$destroy", function() {
            stream.abort();
        });

    }
})();
<|endoftext|>


<commit_before>var redis = require('redis');
var wrapRedisMethod = require('./utils/wrapRedisMethod');

module.exports = RedisKey;

function RedisKey (key, opts) {
  if (!key) {
    throw new Error('key is required');
  }
  this.key = key;
  if (opts && opts.redisClient) {
    this.redisClient = opts.redisClient;
  }
}

[
  'DEL',
  'DUMP',
  'EXISTS',
  'EXPIRE',
  'EXPIREAT',
  // 'KEYS',      // N/A
  // 'MIGRATE',   // N/A
  'MOVE',
  // 'OBJECT',    // N/A
  'PERSIST',
  'PEXPIRE',
  'PEXPIREAT',
  'PTTL',
  // 'RANDOMKEY', // N/A
  'RENAME',       // TODO: support RedisKey as arg
  'RENAMENX',     // TODO: support RedisKey as arg
  'RESTORE',
  'SET',
  'SORT',
  'TTL',
  'TYPE',
  // 'SCAN'       // N/A
].forEach(wrapRedisMethod(RedisKey));
<commit_msg>better error<commit_after>var wrapRedisMethod = require('./utils/wrapRedisMethod');

module.exports = RedisKey;

function RedisKey (key, opts) {
  if (!key) {
    throw new Error('key is required');
  }
  this.key = key;
  if (opts && opts.redisClient) {
    this.redisClient = opts.redisClient;
  }
  if (!this.redisClient) {
    throw new Error('redis client was not provided');
  }
}

[
  'DEL',
  'DUMP',
  'EXISTS',
  'EXPIRE',
  'EXPIREAT',
  // 'KEYS',      // N/A
  // 'MIGRATE',   // N/A
  'MOVE',
  // 'OBJECT',    // N/A
  'PERSIST',
  'PEXPIRE',
  'PEXPIREAT',
  'PTTL',
  // 'RANDOMKEY', // N/A
  'RENAME',       // TODO: support RedisKey as arg
  'RENAMENX',     // TODO: support RedisKey as arg
  'RESTORE',
  'SET',
  'SORT',
  'TTL',
  'TYPE',
  // 'SCAN'       // N/A
].forEach(wrapRedisMethod(RedisKey));
<|endoftext|>


<commit_before>
window.onload = function initialize() {

    var choices = { '': 'please select', projects :'trials', years : 'years', locations : 'locations', traits: 'traits' };

    var html = '';
    var c1_html = '';
    var stock_data;
    html = html + format_options(choices);

    if (isLoggedIn()) {
	var lo = new CXGN.List();

	for (var i=0; i<choices.length; i++) {
	    if (!typeof(choices[i])=='undefined') {
		var lists = lo.availableLists(choices[i]);

		var options = [];
		for (var n=0; n<lists.length; n++) {
		    options[lists[n][0]] = lists[n][1]+" ("+lists[n][5]+")";
		    html += "<optgroup>\n";
		    html += format_options(options);
		    html += "</optgroup>\n";
		}
	    }
	}
    }

    jQuery('#select1').html(html);

    jQuery('#select1').change(function() {
	var select1 = jQuery( this ).val();
	var select4 = jQuery('#select4').val();

	disable_ui();

	var list = new Array();

	if (parseInt(select1)) {
	    var lo = new CXGN.List();
	    var list_data = lo.getListData(select1);
	    var id_data = lo.transform2Ids(select1);
	    var dump = JSON.stringify(id_data);
	}

	var stocks;
	var message;

	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    async: false,
	    timeout: 60000,
	    method: 'POST',
	    data: {'select1':select1, 'select4': select4 },
	    success: function(response) {
		if (response.error) {
		    alert(response.error);
		    return;
		}
		else {
		    list = response.list;
		    stocks = response.stocks;
		    message = response.message;
		}
	    }
	});

	c1_html = format_options_list(list);
	show_list_total_count('#c1_data_count', list.length);
	update_stocks(stocks, message);

	jQuery('#c1_data_text').html(retrieve_sublist(list, 1).join("\n"));
	jQuery('#c1_data').html(c1_html);
	jQuery('#c2_data').html('');
	jQuery('#c3_data').html('');
	jQuery('#select2').html('');
	jQuery('#select3').html('');

	if (isLoggedIn()) {
	    addToListMenu('c1_to_list_menu', 'c1_data', {
		selectText: true,
		typeSourceDiv: 'select1' });
	}
	enable_ui();
    });

    jQuery('#c1_data').change(function() {

	disable_ui();

	jQuery('#select2').val('please select');
	jQuery('#select3').html('');
	jQuery('#c2_data').html('');
	jQuery('#c3_data').html('');
	jQuery('#stock_data').html('');
	var select1 = jQuery('#select1').val();
	var select4 = jQuery('#select4').val();
	var c1_data = jQuery('#c1_data').val() || [];

	// as soon as a data item is selected, show the next menu select
	//
	var second_choices = copy_hash(choices);
	delete second_choices[select1];
	var html = format_options(second_choices);
	jQuery('#select2').html(html);

	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    async: false,
	    timeout: 60000,
	    method: 'POST',
	    data: {'select1':select1, 'c1_data': c1_data.join(","), 'select4':select4  },
	    success: function(response) {
		if (response.error) {
		    alert(response.error);
		}
		else {
		    update_stocks(response.stocks, response.message);

		    enable_ui();
		}
	    }
	});

	show_list_total_count('#c1_data_count', jQuery('#c1_data').text().split("\n").length-1, jQuery('#c1_data').val().length);
	show_list_total_count('#c2_data_count', 0, 0);
	show_list_total_count('#c3_data_count', 0, 0);
	enable_ui();
    });

    jQuery('#select2').change(function() {
 	var select1 = jQuery('#select1').val();
	var select2 = jQuery('#select2').val();
	var select4 = jQuery('#select4').val();
	var c1_data = jQuery('#c1_data').val() || [];
	jQuery('#select3').val('please select');
	jQuery('#c2_data').val('');

	var c2_data = '';
	var stock_data = '';

	disable_ui();

	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    async: false,
	    timeout: 60000,
	    method: 'POST',
	    data: {'select1':select1, 'select2':select2, 'c1_data': c1_data.join(","), 'select4':select4 },
	    success: function(response) {
		if (response.error) {
		    alert("ERROR: "+response.error);
		}
		else {
		    c2_html = format_options_list(response.list);

		    jQuery('#c2_data').html(c2_html);
		    show_list_total_count('#c2_data_count', response.list.length);
		    update_stocks(response.stocks);
		    enable_ui();
		}
	    }
	});

	if (isLoggedIn()) {
	    addToListMenu('c2_to_list_menu', 'c2_data', {
		selectText: true,
		typeSourceDiv: 'select2' });
	}
	enable_ui();
    });

    jQuery('#c2_data').change(function() {
	jQuery('#c3_data').html('');
	jQuery('#stock_data').html('');

	var select1 = jQuery('#select1').val();
	var select2 = jQuery('#select2').val();
	var select4 = jQuery('#select4').val();
	var c1_data = jQuery('#c1_data').val() || [];
	var c2_data = jQuery('#c2_data').val() || [];

	var third_choices = copy_hash(choices);
	delete third_choices[select1];
	delete third_choices[select2];
	var html = format_options(third_choices);
	jQuery('#select3').html(html);

	disable_ui();
	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    async: false,
	    timeout: 60000,
	    method: 'POST',
	    data: {'select1':select1, 'c1_data': c1_data.join(","), 'select2':select2, 'c2_data':c2_data.join(","), 'select4':select4  },
	    success: function(response) {
		if (response.error) {
		    alert(response.error);
		}
		else {
		    c3_html = format_options_list(response.list);
		    update_stocks(response.stocks);
		    enable_ui();
		    //jQuery('#c3_data').html(c3_html);
		}
	    }
	});

	show_list_total_count('#c2_data_count', jQuery('#c2_data').text().split("\n").length-1, jQuery('#c2_data').val().length);
	show_list_total_count('#c3_data_count', 0, 0);
	enable_ui();
    });

    jQuery('#select3').change( function() {
 	var select1 = jQuery('#select1').val();
	var select2 = jQuery('#select2').val();
	var select3 = jQuery('#select3').val();
	var select4 = jQuery('#select4').val();
	var c1_data = jQuery('#c1_data').val() || [];
	var c2_data = jQuery('#c2_data').val() || [];

	var stock_data = '';

	jQuery('#stock_data').html('');

	disable_ui();

	var list;

	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    async: false,
	    timeout: 60000,
	    method: 'POST',
	    data: {'select1':select1, 'select2':select2, 'c1_data': c1_data.join(","),  'c2_data': c2_data.join(","), 'select3':select3, 'select4': select4 },
	    success: function(response) {
		if (response.error) {
		    alert(response.error);
		}
		else {
		    c3_html = format_options_list(response.list);
		    list = response.list;
		    update_stocks(response.stocks);
		    jQuery('#c3_data').html(c3_html);
		}
	    },
	    error: function(response) {
		alert("An error occurred. Timeout?");
	    }
	});

	show_list_total_count('#c3_data_count', jQuery('#c3_data').text().split("\n").length-1, 0);

	if (isLoggedIn()) {
	    addToListMenu('c3_to_list_menu', 'c3_data', {
		selectText: true,
		typeSourceDiv: 'select3' });
	}

	enable_ui();
    });

    jQuery('#c3_data').change(function() {
	jQuery('#stock_data').html('');

	var select1 = jQuery('#select1').val();
	var select2 = jQuery('#select2').val();
	var select3 = jQuery('#select3').val();
	var select4 = jQuery('#select4').val();
	var c1_data = jQuery('#c1_data').val() || [];
	var c2_data = jQuery('#c2_data').val() || [];
	var c3_data = jQuery('#c3_data').val() || [];

	var stock_data;

	disable_ui();

    	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    async: false,
	    timeout: 30000,
	    method: 'POST',
	    data: {'select1':select1, 'select2':select2, 'c1_data': c1_data.join(","),  'c2_data': c2_data.join(","), 'select3':select3, 'c3_data': c3_data.join(","), 'select4' : select4 },
	    success: function(response) {
		if (response.error) {
		    alert(response.error);
		}
		else {
		    update_stocks(response.stocks);
		    enable_ui();
		}
	    },
	    error: function(response) {
		alert("an error occurred. (possible timeout)");
	    }
	});

	show_list_total_count('#c3_data_count', jQuery('#c3_data').text().split("\n").length-1, jQuery('#c3_data').val().length);
	enable_ui();
    });

    jQuery('#select4').change(function() {
	//jQuery('#stock_data').html('');

	var select1 = jQuery('#select1').val();
	var select2 = jQuery('#select2').val();
	var select3 = jQuery('#select3').val();
	var select4 = jQuery('#select4').val();
	var c1_data = jQuery('#c1_data').val() || [];
	var c2_data = jQuery('#c2_data').val() || [];
	var c3_data = jQuery('#c3_data').val() || [];

	var stock_data;

	if (typeof select3 != 'string') { select3 = ''; }

	var c1_str = '';
	var c2_str = '';
	var c3_str = '';

	if (c1_data.length > 0) { c1_str = c1_data.join(","); }
	if (c2_data.length > 0) { c2_str = c2_data.join(","); }
	if (c3_data.length > 0) { c3_str = c3_data.join(","); }

	disable_ui();

    	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    async: false,
	    timeout: 30000,
	    method: 'POST',
	    data: {'select1':select1, 'c1_data': c1_str, 'select2': select2, 'c2_data': c2_str, 'select3':select3, 'c3_data': c3_str, 'select4' : select4 },
	    success: function(response) {
		if (response.error) {
		    alert(response.error);
		}
		else {
		    update_stocks(response.stocks);
		    enable_ui();
		}
	    },
	    error: function(message) {
		alert("an error occurred. ("+ message.responseText +")");
	    }
	});

	if (isLoggedIn()) {
	    addToListMenu('add_to_list_menu', 'stock_data', {
		selectText: true,
		typeSourceDiv: 'select4' });
	}

	enable_ui();
    });
}

function update_stocks(stocks, message) {
    if (! message) {
	var stock_data = format_options_list(stocks);
	jQuery('#stock_data').html(stock_data);
    }
    if (stocks) {
	jQuery('#stock_count').html(stocks.length+' items');
    }
    else {
	jQuery('#stock_count').html(message);
    }
}

function format_options(items) {
    var html = '';
    for (var key in items) {
	html = html + '<option value="'+key+'">'+items[key]+'\n';
    }
    return html;
}

function retrieve_sublist(list, sublist_index) {
    var new_list = new Array();
    for(var i=0; i<list.length; i++) {
	new_list.push(list[i][sublist_index]);
    }
    return new_list;
}

function format_options_list(items) {
    var html = '';
    if (items) {
	for(var i=0; i<items.length; i++) {
	    html = html + '<option value="'+items[i][0]+'">'+items[i][1]+'\n';
	}
	return html;
    }
    return "no data";
}

function copy_hash(hash) {
    var new_hash = new Array();

    for (var key in hash) {
	new_hash[key] = hash[key];
    }
    return new_hash;
}

function disable_ui() {
    jQuery('#working').dialog("open");
}

function enable_ui() {
     jQuery('#working').dialog("close");
}

function show_list_total_count(count_div, total_count, selected) {
    var html = 'Items: '+total_count+'
';
    if (selected) {
	html += 'Selected: '+selected;
    }
    jQuery(count_div).html(html);
}

function show_list_selected_count(select_div, selected_count_div) {
    var selected_count = 0;
    var selected = jQuery(select_div).val();
    if (selected != undefined) { selected_count = selected.count; }

    jQuery(count_div).html('selected: '+selected_count);
}
<commit_msg>use async to make throbber work<commit_after>
window.onload = function initialize() {

    var choices = { '': 'please select', projects :'trials', years : 'years', locations : 'locations', traits: 'traits' };

    var html = '';
    var c1_html = '';
    var stock_data;
    html = html + format_options(choices);

    if (isLoggedIn()) {
	var lo = new CXGN.List();

	for (var i=0; i<choices.length; i++) {
	    if (!typeof(choices[i])=='undefined') {
		var lists = lo.availableLists(choices[i]);

		var options = [];
		for (var n=0; n<lists.length; n++) {
		    options[lists[n][0]] = lists[n][1]+" ("+lists[n][5]+")";
		    html += "<optgroup>\n";
		    html += format_options(options);
		    html += "</optgroup>\n";
		}
	    }
	}
    }

    jQuery('#select1').html(html);

    jQuery('#select1').change(function() {
	var select1 = jQuery( this ).val();
	var select4 = jQuery('#select4').val();

	//disable_ui();

	var list = new Array();

	if (parseInt(select1)) {
	    var lo = new CXGN.List();
	    var list_data = lo.getListData(select1);
	    var id_data = lo.transform2Ids(select1);
	    var dump = JSON.stringify(id_data);
	}

	var stocks;
	var message;

	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    //async: false,
	    timeout: 60000,
	    method: 'POST',
	    data: {'select1':select1, 'select4': select4 },
	    beforeSend: function(){
		disable_ui();
            },
            complete : function(){
		enable_ui();
            },
	    success: function(response) {
		if (response.error) {
		    alert(response.error);
		    return;
		}
		else {
		    list = response.list;
		    stocks = response.stocks;
		    message = response.message;
		    c1_html = format_options_list(list);
		    show_list_total_count('#c1_data_count', list.length);
		    update_stocks(stocks, message);

		    jQuery('#c1_data_text').html(retrieve_sublist(list, 1).join("\n"));
		    jQuery('#c1_data').html(c1_html);
		    jQuery('#c2_data').html('');
		    jQuery('#c3_data').html('');
		    jQuery('#select2').html('');
		    jQuery('#select3').html('');

		    if (isLoggedIn()) {
			addToListMenu('c1_to_list_menu', 'c1_data', {
			    selectText: true,
			    typeSourceDiv: 'select1' });
		    }
		}
	    }
	});

	//enable_ui();
    });

    jQuery('#c1_data').change(function() {

	//disable_ui();

	jQuery('#select2').val('please select');
	jQuery('#select3').html('');
	jQuery('#c2_data').html('');
	jQuery('#c3_data').html('');
	jQuery('#stock_data').html('');
	var select1 = jQuery('#select1').val();
	var select4 = jQuery('#select4').val();
	var c1_data = jQuery('#c1_data').val() || [];

	// as soon as a data item is selected, show the next menu select
	//
	var second_choices = copy_hash(choices);
	delete second_choices[select1];
	var html = format_options(second_choices);
	jQuery('#select2').html(html);

	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    //async: false,
	    timeout: 60000,
	    method: 'POST',
	    data: {'select1':select1, 'c1_data': c1_data.join(","), 'select4':select4  },
	    beforeSend: function(){
		disable_ui();
            },
            complete : function(){
		enable_ui();
            },
	    success: function(response) {
		if (response.error) {
		    alert(response.error);
		}
		else {
		    update_stocks(response.stocks, response.message);
		    show_list_total_count('#c1_data_count', jQuery('#c1_data').text().split("\n").length-1, jQuery('#c1_data').val().length);
		    show_list_total_count('#c2_data_count', 0, 0);
		    show_list_total_count('#c3_data_count', 0, 0);
		    //enable_ui();
		}
	    }
	});

	//enable_ui();
    });

    jQuery('#select2').change(function() {
 	var select1 = jQuery('#select1').val();
	var select2 = jQuery('#select2').val();
	var select4 = jQuery('#select4').val();
	var c1_data = jQuery('#c1_data').val() || [];
	jQuery('#select3').val('please select');
	jQuery('#c2_data').val('');

	var c2_data = '';
	var stock_data = '';

	//disable_ui();

	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    //async: false,
	    timeout: 60000,
	    method: 'POST',
	    data: {'select1':select1, 'select2':select2, 'c1_data': c1_data.join(","), 'select4':select4 },
	    beforeSend: function(){
		disable_ui();
            },
            complete : function(){
		enable_ui();
            },
	    success: function(response) {
		if (response.error) {
		    alert("ERROR: "+response.error);
		}
		else {
		    c2_html = format_options_list(response.list);

		    jQuery('#c2_data').html(c2_html);
		    show_list_total_count('#c2_data_count', response.list.length);
		    update_stocks(response.stocks);
		    if (isLoggedIn()) {
			addToListMenu('c2_to_list_menu', 'c2_data', {
			    selectText: true,
			    typeSourceDiv: 'select2' });
		    }
		    //enable_ui();
		}
	    }
	});

	//enable_ui();
    });

    jQuery('#c2_data').change(function() {
	jQuery('#c3_data').html('');
	jQuery('#stock_data').html('');

	var select1 = jQuery('#select1').val();
	var select2 = jQuery('#select2').val();
	var select4 = jQuery('#select4').val();
	var c1_data = jQuery('#c1_data').val() || [];
	var c2_data = jQuery('#c2_data').val() || [];

	var third_choices = copy_hash(choices);
	delete third_choices[select1];
	delete third_choices[select2];
	var html = format_options(third_choices);
	jQuery('#select3').html(html);

	//disable_ui();
	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    //async: false,
	    timeout: 60000,
	    method: 'POST',
	    data: {'select1':select1, 'c1_data': c1_data.join(","), 'select2':select2, 'c2_data':c2_data.join(","), 'select4':select4  },
	    beforeSend: function(){
		disable_ui();
            },
            complete : function(){
		enable_ui();
            },
	    success: function(response) {
		if (response.error) {
		    alert(response.error);
		}
		else {
		    c3_html = format_options_list(response.list);
		    update_stocks(response.stocks);
		    show_list_total_count('#c2_data_count', jQuery('#c2_data').text().split("\n").length-1, jQuery('#c2_data').val().length);
		    show_list_total_count('#c3_data_count', 0, 0);
		    //enable_ui();
		    //jQuery('#c3_data').html(c3_html);
		}
	    }
	});

	//enable_ui();
    });

    jQuery('#select3').change( function() {
 	var select1 = jQuery('#select1').val();
	var select2 = jQuery('#select2').val();
	var select3 = jQuery('#select3').val();
	var select4 = jQuery('#select4').val();
	var c1_data = jQuery('#c1_data').val() || [];
	var c2_data = jQuery('#c2_data').val() || [];

	var stock_data = '';

	jQuery('#stock_data').html('');

	//disable_ui();

	var list;

	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    //async: false,
	    timeout: 60000,
	    method: 'POST',
	    data: {'select1':select1, 'select2':select2, 'c1_data': c1_data.join(","),  'c2_data': c2_data.join(","), 'select3':select3, 'select4': select4 },
	    beforeSend: function(){
		disable_ui();
            },
            complete : function(){
		enable_ui();
            },
	    success: function(response) {
		if (response.error) {
		    alert(response.error);
		}
		else {
		    c3_html = format_options_list(response.list);
		    list = response.list;
		    update_stocks(response.stocks);
		    jQuery('#c3_data').html(c3_html);
		    show_list_total_count('#c3_data_count', jQuery('#c3_data').text().split("\n").length-1, 0);

		    if (isLoggedIn()) {
			addToListMenu('c3_to_list_menu', 'c3_data', {
			    selectText: true,
			    typeSourceDiv: 'select3' });
		    }
		}
	    },
	    error: function(response) {
		alert("An error occurred. Timeout?");
	    }
	});

	//enable_ui();
    });

    jQuery('#c3_data').change(function() {
	jQuery('#stock_data').html('');

	var select1 = jQuery('#select1').val();
	var select2 = jQuery('#select2').val();
	var select3 = jQuery('#select3').val();
	var select4 = jQuery('#select4').val();
	var c1_data = jQuery('#c1_data').val() || [];
	var c2_data = jQuery('#c2_data').val() || [];
	var c3_data = jQuery('#c3_data').val() || [];

	var stock_data;

	//disable_ui();

    	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    //async: false,
	    timeout: 30000,
	    method: 'POST',
	    data: {'select1':select1, 'select2':select2, 'c1_data': c1_data.join(","),  'c2_data': c2_data.join(","), 'select3':select3, 'c3_data': c3_data.join(","), 'select4' : select4 },
	    beforeSend: function(){
		disable_ui();
            },
            complete : function(){
		enable_ui();
            },
	    success: function(response) {
		if (response.error) {
		    alert(response.error);
		}
		else {
		    update_stocks(response.stocks);
		    show_list_total_count('#c3_data_count', jQuery('#c3_data').text().split("\n").length-1, jQuery('#c3_data').val().length);
		    //enable_ui();
		}
	    },
	    error: function(response) {
		alert("an error occurred. (possible timeout)");
	    }
	});

	//enable_ui();
    });

    jQuery('#select4').change(function() {
	//jQuery('#stock_data').html('');

	var select1 = jQuery('#select1').val();
	var select2 = jQuery('#select2').val();
	var select3 = jQuery('#select3').val();
	var select4 = jQuery('#select4').val();
	var c1_data = jQuery('#c1_data').val() || [];
	var c2_data = jQuery('#c2_data').val() || [];
	var c3_data = jQuery('#c3_data').val() || [];

	var stock_data;

	if (typeof select3 != 'string') { select3 = ''; }

	var c1_str = '';
	var c2_str = '';
	var c3_str = '';

	if (c1_data.length > 0) { c1_str = c1_data.join(","); }
	if (c2_data.length > 0) { c2_str = c2_data.join(","); }
	if (c3_data.length > 0) { c3_str = c3_data.join(","); }

	//disable_ui();

    	jQuery.ajax( {
	    url: '/ajax/breeder/search',
	    //async: false,
	    timeout: 30000,
	    method: 'POST',
	    data: {'select1':select1, 'c1_data': c1_str, 'select2': select2, 'c2_data': c2_str, 'select3':select3, 'c3_data': c3_str, 'select4' : select4 },
	    beforeSend: function(){
		disable_ui();
            },
            complete : function(){
		enable_ui();
            },
	    success: function(response) {
		if (response.error) {
		    alert(response.error);
		}
		else {
		    update_stocks(response.stocks);

		    if (isLoggedIn()) {
			addToListMenu('add_to_list_menu', 'stock_data', {
			    selectText: true,
			    typeSourceDiv: 'select4' });
		    }
		    //enable_ui();
		}
	    },
	    error: function(message) {
		alert("an error occurred. ("+ message.responseText +")");
	    }
	});

	//enable_ui();
    });
}

function update_stocks(stocks, message) {
    if (! message) {
	var stock_data = format_options_list(stocks);
	jQuery('#stock_data').html(stock_data);
    }
    if (stocks) {
	jQuery('#stock_count').html(stocks.length+' items');
    }
    else {
	jQuery('#stock_count').html(message);
    }
}

function format_options(items) {
    var html = '';
    for (var key in items) {
	html = html + '<option value="'+key+'">'+items[key]+'\n';
    }
    return html;
}

function retrieve_sublist(list, sublist_index) {
    var new_list = new Array();
    for(var i=0; i<list.length; i++) {
	new_list.push(list[i][sublist_index]);
    }
    return new_list;
}

function format_options_list(items) {
    var html = '';
    if (items) {
	for(var i=0; i<items.length; i++) {
	    html = html + '<option value="'+items[i][0]+'">'+items[i][1]+'\n';
	}
	return html;
    }
    return "no data";
}

function copy_hash(hash) {
    var new_hash = new Array();

    for (var key in hash) {
	new_hash[key] = hash[key];
    }
    return new_hash;
}

function disable_ui() {
    jQuery('#working').dialog("open");
}

function enable_ui() {
     jQuery('#working').dialog("close");
}

function show_list_total_count(count_div, total_count, selected) {
    var html = 'Items: '+total_count+'
';
    if (selected) {
	html += 'Selected: '+selected;
    }
    jQuery(count_div).html(html);
}

function show_list_selected_count(select_div, selected_count_div) {
    var selected_count = 0;
    var selected = jQuery(select_div).val();
    if (selected != undefined) { selected_count = selected.count; }

    jQuery(count_div).html('selected: '+selected_count);
}
<|endoftext|>


<commit_before>var monitis = require("./api/api.js");

var flush_stats = function monitis_flush(ts, metrics) {
  console.log("Called flush_stats");
}

var backend_status = function monitis_status(writeCb) {
  console.log("Called backend_status");

}

exports.init = function monitis_init(startup_time, config, events) {
  debug = config.debug;
  flushInterval = config.flushInterval;

  // read monitis config
  apikey = config.apikey;
  secretkey = config.secretkey;
  host = typeof config.host != 'undefined'? config.host : 'monitis.com';
  path = typeof config.path != 'undefined'? config.path : '/customMonitorApi';

  events.on('flush', flush_stats);
  events.on('status', backend_status);

  return true;
};
<commit_msg>Implementation of flush_stats<commit_after>var monitis = require("./api/api.js");

function print_body(body) {
  console.log(body);
}

function missing_monitor_cb (name, type, body) {
  // if recording a metric finds a monitor doesn't exist, add it
  // note that we lose one datapoint, since we don't retry the post
  return function(body) {
    if(body.status == 'no such monitor') {
      console.log("Adding missing custom monitor: ", name, ":", type);
      monitis.add_statsd_monitor(name, type, print_body);
    }
  }
}

var flush_stats = function monitis_flush(ts, metrics) {
  console.log("Called flush_stats");
  console.log(metrics);
  for (key in metrics.counters) {
    monitis.add_result_by_name(
      key, {count: metrics.counters[key]}, missing_monitor_cb(key,'counter'));
  }
  for (key in metrics.gauges) {
    monitis.add_result_by_name(
      key, {gauge: metrics.counters[key]}, missing_monitor_cb(key,'gauge'));
  }
  for (key in metrics.timers) {
    var sum = 0;
    var avg = 0;
    times = metrics.timers[key];
    for(var i=0;i<times.length; i++) {
      sum += times[i];
    }
    if (times.length > 0) {
      avg = sum / times.length;
    }
    monitis.add_result_by_name(
      key, {sum: sum, avg: avg}, missing_monitor_cb(key,'timer'));
    console.log(metrics.timers)
  }

}

var backend_status = function monitis_status(writeCb) {
  console.log("Called backend_status");

}

exports.init = function monitis_init(startup_time, config, events) {
  debug = config.debug;
  flushInterval = config.flushInterval;

  // read monitis config
  apikey = config.apikey;
  secretkey = config.secretkey;
  host = typeof config.host != 'undefined'? config.host : 'monitis.com';
  path = typeof config.path != 'undefined'? config.path : '/customMonitorApi';

  events.on('flush', flush_stats);
  events.on('status', backend_status);

  return true;
};
<|endoftext|>