Code coverage report for lib/runloop.js

Statements: 92.31% (36 / 39)      Branches: 77.27% (17 / 22)      Functions: 85.71% (6 / 7)      Lines: 91.89% (34 / 37)      Ignored: 3 statements, 2 functions, 1 branch     

All files » lib/ » runloop.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 1011   1           1 1 1     1 1             1 1 1 1     1                                       7   7 1     1     6     6     6 4 4     4 4 4               9 9 9       9 6 6 6       6         9       1  
var protoclass = require("protoclass");
 
var rAF = (global.requestAnimationFrame      ||
          global.webkitRequestAnimationFrame ||
          global.mozRequestAnimationFrame    ||
          process.nextTick).bind(global);
 
/* istanbul ignore next */
Iif (process.browser) {
  var defaultTick = function(next) {
    rAF(next);
  };
} else {
  var defaultTick = function(next) {
    next();
  };
}
 
/**
 */
 
function RunLoop(options) {
  this._animationQueue = [];
  this.tick = options.tick || defaultTick;
  this._id = options._id || 2;
}
 
protoclass(RunLoop, {
 
  /**
   * child runloop in-case we get into recursive loops
   */
 
  child: function() {
    return this.__child || (this.__child = new RunLoop({ tick: this.tick, _id: this._id << 2 }));
  },
 
  /**
   * Runs animatable object on requestAnimationFrame. This gets
   * called whenever the UI state changes.
   *
   * @method animate
   * @param {Object} animatable object. Must have `update()`
   */
 
  deferOnce: function(context) {
 
    if (!context.__running) context.__running = 1;
 
    if (context.__running & this._id) {
      Iif (this._running) {
        this.child().deferOnce(context);
      }
      return;
    }
 
    context.__running |= this._id;
 
    // push on the animatable object
    this._animationQueue.push(context);
 
    // if animating, don't continue
    if (this._requestingFrame) return;
    this._requestingFrame = true;
    var self = this;
 
    // run the animation frame, and callback all the animatable objects
    this.tick(function() {
      self.runNow();
      self._requestingFrame = false;
    });
  },
 
  /**
   */
 
  runNow: function() {
    var queue = this._animationQueue;
    this._animationQueue = [];
    this._running = true;
 
    // queue.length is important here, because animate() can be
    // called again immediately after an update
    for (var i = 0; i < queue.length; i++) {
      var item = queue[i];
      item.update();
      item.__running &= ~this._id;
 
      // check for anymore animations - need to run
      // them in order
      Iif (this._animationQueue.length) {
        this.runNow();
      }
    }
 
    this._running = false;
  }
});
 
module.exports = RunLoop;