/*
 * jQuery.appear
 * http://github.com/bas2k/jquery.appear/
 * http://code.google.com/p/jquery-appear/
 *
 * Copyright (c) 2009 Michael Hixson
 * Copyright (c) 2012 Alexander Brovikov
 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
 */
(function ($) {
    $.fn.appear = function (fn, options) {
  
      var settings = $.extend({
  
        //arbitrary data to pass to fn
        data: undefined,
  
        //call fn only on the first appear?
        one: true,
  
        // X & Y accuracy
        accX: 0,
        accY: 0
  
      }, options);
  
      return this.each(function () {
  
        var t = $(this);
  
        //whether the element is currently visible
        t.appeared = false;
  
        if (!fn) {
  
          //trigger the custom event
          t.trigger('appear', settings.data);
          return;
        }
  
        var w = $(window);
  
        //fires the appear event when appropriate
        var check = function () {
  
          //is the element hidden?
          if (!t.is(':visible')) {
  
            //it became hidden
            t.appeared = false;
            return;
          }
  
          //is the element inside the visible window?
          var a = w.scrollLeft();
          var b = w.scrollTop();
          var o = t.offset();
          var x = o.left;
          var y = o.top;
  
          var ax = settings.accX;
          var ay = settings.accY;
          var th = t.height();
          var wh = w.height();
          var tw = t.width();
          var ww = w.width();
  
          if (y + th + ay >= b &&
            y <= b + wh + ay &&
            x + tw + ax >= a &&
            x <= a + ww + ax) {
  
            //trigger the custom event
            if (!t.appeared) t.trigger('appear', settings.data);
  
          } else {
  
            //it scrolled out of view
            t.appeared = false;
          }
        };
  
        //create a modified fn with some additional logic
        var modifiedFn = function () {
  
          //mark the element as visible
          t.appeared = true;
  
          //is this supposed to happen only once?
          if (settings.one) {
  
            //remove the check
            w.unbind('scroll', check);
            var i = $.inArray(check, $.fn.appear.checks);
            if (i >= 0) $.fn.appear.checks.splice(i, 1);
          }
  
          //trigger the original fn
          fn.apply(this, arguments);
        };
  
        //bind the modified fn to the element
        if (settings.one) t.one('appear', settings.data, modifiedFn);
        else t.bind('appear', settings.data, modifiedFn);
  
        //check whenever the window scrolls
        w.scroll(check);
  
        //check whenever the dom changes
        $.fn.appear.checks.push(check);
  
        //check now
        (check)();
      });
    };
  
    //keep a queue of appearance checks
    $.extend($.fn.appear, {
  
      checks: [],
      timeout: null,
  
      //process the queue
      checkAll: function () {
        var length = $.fn.appear.checks.length;
        if (length > 0)
          while (length--)($.fn.appear.checks[length])();
      },
  
      //check the queue asynchronously
      run: function () {
        if ($.fn.appear.timeout) clearTimeout($.fn.appear.timeout);
        $.fn.appear.timeout = setTimeout($.fn.appear.checkAll, 20);
      }
    });
  
    //run checks when these methods are called
    $.each(['append', 'prepend', 'after', 'before', 'attr',
      'removeAttr', 'addClass', 'removeClass', 'toggleClass',
      'remove', 'css', 'show', 'hide'
    ], function (i, n) {
      var old = $.fn[n];
      if (old) {
        $.fn[n] = function () {
          var r = old.apply(this, arguments);
          $.fn.appear.run();
          return r;
        }
      }
    });
  
  })(jQuery);
  
  
  
  
  
  (function (factory) {
    if (typeof define === 'function' && define.amd) {
      // AMD
      define(['jquery'], factory);
    } else if (typeof exports === 'object') {
      // CommonJS
      factory(require('jquery'));
    } else {
      // Browser globals
      factory(jQuery);
    }
  }(function ($) {
    var CountTo = function (element, options) {
      this.$element = $(element);
      this.options = $.extend({}, CountTo.DEFAULTS, this.dataOptions(), options);
      this.init();
    };
  
    CountTo.DEFAULTS = {
      from: 0, // the number the element should start at
      to: 0, // the number the element should end at
      speed: 1000, // how long it should take to count between the target numbers
      refreshInterval: 100, // how often the element should be updated
      decimals: 0, // the number of decimal places to show
      formatter: formatter, // handler for formatting the value before rendering
      onUpdate: null, // callback method for every time the element is updated
      onComplete: null // callback method for when the element finishes updating
    };
  
    CountTo.prototype.init = function () {
      this.value = this.options.from;
      this.loops = Math.ceil(this.options.speed / this.options.refreshInterval);
      this.loopCount = 0;
      this.increment = (this.options.to - this.options.from) / this.loops;
    };
  
    CountTo.prototype.dataOptions = function () {
      var from = 0;
      var to = parseFloat(this.$element.text().toString().replace(/,/g, ""));
      if(this.$element.data("from")){
        from = parseFloat(this.$element.data("from").toString().replace(/,/g, ""));
      };
      if(this.$element.data("to")){
        to = parseFloat(this.$element.data("to").toString().replace(/,/g, ""));
      };
      var decimals = 0;
      var decimalsArr = to.toString().split(".");
      if (decimalsArr[1]) {
        decimals = decimalsArr[1].toString().length;
      };
  
      var options = {
        from: from,
        to: to,
        speed: this.$element.data('speed'),
        refreshInterval: this.$element.data('refresh-interval'),
        decimals: decimals
      };
  
      var keys = Object.keys(options);
  
      for (var i in keys) {
        var key = keys[i];
  
        if (typeof (options[key]) === 'undefined') {
          delete options[key];
        }
      }
  
      return options;
    };
  
    CountTo.prototype.update = function () {
      this.value += this.increment;
      this.loopCount++;
  
      this.render();
  
      if (typeof (this.options.onUpdate) == 'function') {
        this.options.onUpdate.call(this.$element, this.value);
      }
  
      if (this.loopCount >= this.loops) {
        clearInterval(this.interval);
        this.value = this.options.to;
  
        if (typeof (this.options.onComplete) == 'function') {
          this.options.onComplete.call(this.$element, this.value);
        }
      }
    };
  
    CountTo.prototype.render = function () {
      var formattedValue = this.options.formatter.call(this.$element, this.value, this.options);
      this.$element.text(formattedValue);
    };
  
    CountTo.prototype.restart = function () {
      this.stop();
      this.init();
      this.start();
    };
  
    CountTo.prototype.start = function () {
      this.stop();
      this.render();
      this.interval = setInterval(this.update.bind(this), this.options.refreshInterval);
    };
  
    CountTo.prototype.stop = function () {
      if (this.interval) {
        clearInterval(this.interval);
      }
    };
  
    CountTo.prototype.toggle = function () {
      if (this.interval) {
        this.stop();
      } else {
        this.start();
      }
    };
  
    function formatter(value, options) {
      return value.toFixed(options.decimals);
    }
  
    $.fn.countTo = function (option) {
      return this.each(function () {
        var $this = $(this);
        var data = $this.data('countTo');
        var init = !data || typeof (option) === 'object';
        var options = typeof (option) === 'object' ? option : {};
        var method = typeof (option) === 'string' ? option : 'start';
  
        if (init) {
          if (data) data.stop();
          $this.data('countTo', data = new CountTo(this, options));
        }
  
        data[method].call(data);
      });
    };
  }));