if (typeof countUp == "undefined") {
  /*
      countUp.js
      by @inorganik
      v 1.1.0
  */
  function countUp(target, startVal, endVal, decimals, duration, options) {
      'use strict';

      // default options
      this.options = options || {
          useEasing : true, // toggle easing
          useGrouping : true, // 1,000,000 vs 1000000
          separator : ',', // character to use as a separator
          decimal : '.' // character to use as a decimal
      }
      // make sure requestAnimationFrame and cancelAnimationFrame are defined
      // polyfill for browsers without native support
      // by Opera engineer Erik Möller
      var lastTime = 0;
      var vendors = ['webkit', 'moz', 'ms'];
      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);
          }
      }
      var self = this;
      this.d = (typeof target === 'string') ? document.getElementById(target) : target;
      this.startVal = Number(startVal);
      this.endVal = Number(endVal);
      this.countDown = (this.startVal > this.endVal) ? true : false;
      this.startTime = null;
      this.timestamp = null;
      this.remaining = null;
      this.frameVal = this.startVal;
      this.rAF = null;
      this.decimals = Math.max(0, decimals || 0);
      this.dec = Math.pow(10, this.decimals);
      this.duration = duration * 1000 || 2000;
      // Robert Penner's easeOutExpo
      this.easeOutExpo = function(t, b, c, d) {
          return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
      }
      this.count = function(timestamp) {
          if (self.startTime === null) self.startTime = timestamp;
          self.timestamp = timestamp;
          var progress = timestamp - self.startTime;
          self.remaining = self.duration - progress;
          // to ease or not to ease
          if (self.options.useEasing) {
              if (self.countDown) {
                  var i = self.easeOutExpo(progress, 0, self.startVal - self.endVal, self.duration);
                  self.frameVal = self.startVal - i;
              } else {
                  self.frameVal = self.easeOutExpo(progress, self.startVal, self.endVal - self.startVal, self.duration);
              }
          } else {
              if (self.countDown) {
                  var i = (self.startVal - self.endVal) * (progress / self.duration);
                  self.frameVal = self.startVal - i;
              } else {
                  self.frameVal = self.startVal + (self.endVal - self.startVal) * (progress / self.duration);
              }
          }
          // decimal
          self.frameVal = Math.round(self.frameVal*self.dec)/self.dec;
          // don't go past endVal since progress can exceed duration in the last frame
          if (self.countDown) {
              self.frameVal = (self.frameVal < self.endVal) ? self.endVal : self.frameVal;
          } else {
              self.frameVal = (self.frameVal > self.endVal) ? self.endVal : self.frameVal;
          }
          // format and print value
          self.d.innerHTML = self.formatNumber(self.frameVal.toFixed(self.decimals));
          // whether to continue
          if (progress < self.duration) {
              self.rAF = requestAnimationFrame(self.count);
          } else {
              if (self.callback != null) self.callback();
          }
      }  
      this.start = function(callback) {
          self.callback = callback;
          // make sure values are valid
          if (!isNaN(self.endVal) && !isNaN(self.startVal)) {
              self.rAF = requestAnimationFrame(self.count);
          } else {
              console.log('countUp error: startVal or endVal is not a number');
              self.d.innerHTML = '--';
          }
          return false;
      }
      this.stop = function() {
          cancelAnimationFrame(self.rAF);
      }
      this.reset = function() {
          self.startTime = null;
          cancelAnimationFrame(self.rAF);
          self.d.innerHTML = self.formatNumber(self.startVal.toFixed(self.decimals));
      }
      this.resume = function() {
          self.startTime = null;
          self.duration = self.remaining;
          self.startVal = self.frameVal;
          requestAnimationFrame(self.count);
      }
      this.formatNumber = function(nStr) {
          nStr += '';
          var x, x1, x2, rgx;
          x = nStr.split('.');
          x1 = x[0];
          x2 = x.length > 1 ? self.options.decimal + x[1] : '';
          rgx = /(\d+)(\d{3})/;
          if (self.options.useGrouping) {
              while (rgx.test(x1)) {
                  x1 = x1.replace(rgx, '$1' + self.options.separator + '$2');
              }
          }
          return x1 + x2;
      }
      // format startVal on initialization
      self.d.innerHTML = self.formatNumber(self.startVal.toFixed(self.decimals));
  }
}