1. var Timer = function (a, b) {
  2.         return this._init(a, b)
  3.     };
  4. Timer.prototype = {
  5.     VERSION: 1,
  6.     _init: function (a, b) {
  7.         this._interval = 1000;
  8.         this._timer = null;
  9.         this._cbs = [];
  10.         this._multipliers = [];
  11.         this._tickCounts = [];
  12.         this._canRun = [];
  13.         this._stoppedThreads = 0;
  14.         this._runOnce = false;
  15.         this._startedAt = -1;
  16.         this._pausedAt = -1;
  17.         if (typeof (a) == "number") {
  18.             this._interval = a
  19.         }
  20.         this.addCallback(b);
  21.         return this
  22.     },
  23.     _preset: function () {
  24.         this._stoppedThreads = 0;
  25.         this._startedAt = -1;
  26.         this._pausedAt = -1;
  27.         for (var a = 0; a < this._cbs.length; a++) {
  28.             this._canRun[a] = true;
  29.             this._tickCounts[a] = 0
  30.         }
  31.     },
  32.     _ticks: function (b) {
  33.         var c = this;
  34.         for (var a = 0; a < this._cbs.length; a++) {
  35.             if (typeof (this._cbs[a]) == "function" && this._canRun[a]) {
  36.                 this._tickCounts[a]++;
  37.                 if (this._tickCounts[a] == this._multipliers[a]) {
  38.                     this._tickCounts[a] = 0;
  39.                     if (this.runOnce()) {
  40.                         this._canRun[a] = false;
  41.                         this._stoppedThreads++
  42.                     }
  43.                     window.setTimeout(c._cbs[a], 0)
  44.                 }
  45.             }
  46.         }
  47.         if (this.runOnce() && this._stoppedThreads == this._cbs.length) {
  48.             this.stop()
  49.         }
  50.         if (typeof (b) == "number") {
  51.             this.stop().start(null, true)
  52.         }
  53.     },
  54.     runOnce: function (a) {
  55.         if (typeof (a) == "undefined") {
  56.             return this._runOnce
  57.         } else {
  58.             if (typeof (a) == "boolean") {
  59.                 this._runOnce = a
  60.             } else {
  61.                 alert("Invalid argument for runOnce(...).\n\nUsage: runOnce(true | false) /*Default value: false*/\nor, runOnce() to get status")
  62.             }
  63.         }
  64.         return this
  65.     },
  66.     interval: function (a) {
  67.         if (typeof (a) == "undefined") {
  68.             return this._interval
  69.         } else {
  70.             if (typeof (a) == "number") {
  71.                 this._interval = Math.floor(a)
  72.             }
  73.         }
  74.         return this
  75.     },
  76.     stop: function (a) {
  77.         if (this._timer) {
  78.             if (!a) {
  79.                 this._pausedAt = -1
  80.             }
  81.             try {
  82.                 window.clearInterval(this._timer)
  83.             } catch (b) {}
  84.             this._timer = null
  85.         }
  86.         return this
  87.     },
  88.     isStopped: function () {
  89.         return ((this._timer == null) && !this.isPaused())
  90.     },
  91.     start: function (c, a) {
  92.         if (this.isPaused()) {
  93.             return this.resume()
  94.         }
  95.         if (!this.isStopped()) {
  96.             return this
  97.         }
  98.         if (!a) {
  99.             this._preset()
  100.         }
  101.         var b = this._interval;
  102.         if (typeof (c) == "number") {
  103.             b = c
  104.         }
  105.         var d = this;
  106.         this._timer = window.setInterval(function () {
  107.             d._ticks(c)
  108.         }, b);
  109.         this._startedAt = (new Date()).getTime();
  110.         this._startedAt -= (this._interval - b);
  111.         return this
  112.     },
  113.     pause: function () {
  114.         if (this._timer) {
  115.             this._pausedAt = (new Date()).getTime();
  116.             this.stop(true)
  117.         }
  118.         return this
  119.     },
  120.     isPaused: function () {
  121.         return (this._pausedAt >= 0)
  122.     },
  123.     resume: function () {
  124.         if (this.isPaused()) {
  125.             var a = this._interval - ((this._pausedAt - this._startedAt) % this._interval);
  126.             this._pausedAt = -1;
  127.             this.start(a, true)
  128.         }
  129.         return this
  130.     },
  131.     restart: function () {
  132.         return this.stop().start()
  133.     },
  134.     addCallback: function (b, a) {
  135.         if (typeof (b) == "function") {
  136.             this._cbs.push(b);
  137.             if (typeof (a) == "number") {
  138.                 a = Math.floor(a);
  139.                 this._multipliers.push((a < 1 ? 1 : a))
  140.             } else {
  141.                 this._multipliers.push(1)
  142.             }
  143.             this._tickCounts.push(0);
  144.             this._canRun.push(true)
  145.         }
  146.         return this
  147.     },
  148.     clearCallbacks: function () {
  149.         this._cbs.length = 0;
  150.         this._multipliers.length = 0;
  151.         this._canRun.length = 0;
  152.         this._tickCounts.length = 0;
  153.         this._stoppedThreads = 0;
  154.         return this
  155.     }
  156. };
  157.  
  158.