J.D.M.

  • Revision slug: User:fusionchess/Sandbox/Daemon
  • Revision title: setInterval - a little framework (Daemon)
  • Revision id: 347941
  • Created:
  • Creator: fusionchess
  • Is current revision? No
  • Comment

Revision Content

This page is under construction

The code

fork.js

 /*\
 |*|
 |*|                     *******************************
 |*|                     *           fork.js           *
 |*|                     *******************************
 |*|
 |*|
 |*|
 |*|  A JAVASCRIPT HIGLY SCALABLE DAEMONS MANAGER.
 |*|
 |*|  https://developer.mozilla.org/en-US/docs/DOM/window.setInterval
 |*|  https://developer.mozilla.org/User:fusionchess
 |*|
 |*|  This framework is released under the GNU Public License, version 3 or later.
 |*|  http://www.gnu.org/licenses/gpl-3.0-standalone.html
 |*|
 |*|
 |*|  :: Content of this file ::
 |*|
 |*|
 |*|  The Daemon base system.
 |*|
 |*|
 |*|  :: The constructor ::
 |*|
 |*|
 |*|  Syntax
 |*|
 |*|       var myDaemon = new Daemon(@thisObject, @callback[, @length, @rate, @init, @onstart]);
 |*|
 |*|
 |*|  Description
 |*|
 |*|  Constructs a JavaScript Object containing all informations needed by an animation (like the "this"
 |*|  object, the callback function, the length, the frame-rate, the number of cycles, the "init" and
 |*|  the "onstart" functions).
 |*|
 |*|
 |*|  Arguments
 |*|
 |*|  - @thisObject -
 |*|  The "this" object on which will be called the callback function. It can be an object or null. If
 |*|  is null, the "this" object will point to the global "Deamon.context" object (see below).
 |*|
 |*|  - @callback -
 |*|  The function which will be invoked repeatedly. It will be called with three parameters: @index
 |*|  (the iterative index of each invocation), @length (the number of total invocations assigned to the
 |*|  daemon - finite or Infinity) and @backwards (a boolean expressing whether the process is going
 |*|  backwards or not).
 |*|  It will be something like @callback.call(@thisObject, @index, @length, @backwards).
 |*|  If the @callback function returns a "false" value the Daemon will be paused.
 |*|
 |*|  - @length (optional) -
 |*|  The total number of invocations. It can be a positive integer or Infinity. The default value is
 |*|  Infinity.
 |*|
 |*|  - @rate (optional) -
 |*|  The time lapse (in number of milliseconds) between each invocation. The default value is 100.
 |*|
 |*|  - @init (optional) -
 |*|  The function which will be synchronously invoked once during the creation of the daemon and
 |*|  then assigned to the "onstop" property.
 |*|  It will be called with the same three arguments of the @callback function. They will also have the
 |*|  same values of the last invocation of the @callback function.
 |*|
 |*|  - @onstart -
 |*|  The function which will be synchronously invoked on whenever the "start" event occurs. It will be
 |*|  assigned to the "onstart" property.
 |*|  It will be called with three arguments: @index (the actual index), @length (the number of total
 |*|  invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing
 |*|  whether the @index will go decreasing or not).
 |*|
 |*|
 |*|  :: Daemon global object properties ::
 |*|
 |*|
 |*|  - Daemon.context -
 |*|  An empty object used as default *this* object when the @thisObject is not specified during the
 |*|  construction of the daemon. If you want your callback function to be invoked with a "null" *this*
 |*|  object you have to manually set the "owner" property to "null".
 |*|
 |*|
 |*|  :: Daemon global object methods ::
 |*|
 |*|
 |*|  - Daemon.forceCall(@daemonInstance) -
 |*|  Forces a callback to the @daemonInstance.task function regardless of the fact that the end has
 |*|  been reached or not. In any case the internal "INDEX" property will be increased/decreased
 |*|  (depending on the actual direction of the daemon).
 |*|
 |*|  - Daemon.construct(@array_of_arguments) -
 |*|  Returns a new daemon constructed upon an array of arguments. It is very similar to the
 |*|  Function.prototype.apply() method.
 |*|
 |*|  - Daemon.buildAround(@context[, @length, @rate]) -
 |*|  Returns a new daemon built around a @context object. The @context object must cointain *at least*
 |*|  a "perform" property pointing to what you want to be the @callback function of the daemon.
 |*|  It can also optionally contain a "create" and a "prepare" properties pointing respectively the
 |*|  two functions you want to be the @init and @onstart functions of Daemon constructor's arguments.
 |*|  The @context object will be also the *this* object of your callback function. So you can populate
 |*|  it with all your custom properties. and methods. The only required one property is "perform".
 |*|    
 |*|    Sample usage:
 |*|
 |*|      var myDaemon = Daemon.buildAround({
 |*|        "create": function () { [custom code] },  // optional
 |*|        "prepare": function () { [custom code] },  // optional
 |*|        "perform": function () { [custom code] },  // required
 |*|        "customProperty": [custom value],
 |*|        "myCustomMethod": function () { [custom code] },
 |*|        "anotherCustomProperty": [custom value],
 |*|        "etc.": "etc."
 |*|      }, 30, 200);
 |*|    
 |*|
 |*|  - Daemon.incorporate(@function) -
 |*|  The @function.prototype property will replaced with a *new Daemon()* object. The old replaced
 |*|  prototype will be preserved within a new property of the new @function.prototype named "legacy".
 |*|
 |*|
 |*|  :: Other constructors ::
 |*|
 |*|
 |*|  - Daemon.blank -
 |*|  Constructs a new instance of Daemon without own properties. This constructor is useful in order to
 |*|  create your own *MySomeDaemon* constructors through the *MySomeDaemon.prototype = new Daemon.blank();*
 |*|  assignment.
 |*|
 |*|  - Daemon.crazy [optional module] -
 |*|  A clone of the Daemon constructor based on setTimeout rather than on setInterval. See the Daemon.crazy
 |*|  module for details.
 |*|  NOTE: The Daemon.crazy constructor is not part of the base system.
 |*|
 |*|  - Daemon.crazy.blank [optional module] -
 |*|  The same as for Daemon.blank, but applied to the Daemon.crazy constructor.
 |*|  NOTE: The Daemon.crazy constructor is not part of the base system.
 |*|
 |*|
 |*|  :: Daemon instances properties ::
 |*|
 |*|
 |*|  - myDaemon.owner -
 |*|  The "this" object on which is executed the daemon (read/write). It can be an object or null. Its default
 |*|  value is Daemon.context.
 |*|
 |*|  - myDaemon.task -
 |*|  The function which will be repeatedly invoked (read/write). It will be called with three
 |*|  arguments: @index (the iterative index of each invocation), @length (the number of total
 |*|  invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing
 |*|  whether the @index is decreasing or not). See above.
 |*|  If the myDaemon.task function returns a "false" the Daemon will be paused.
 |*|
 |*|  - myDaemon.length -
 |*|  The total number of invocations. It can be a positive integer or Infinity (read/write).
 |*|
 |*|  - myDaemon.rate -
 |*|  The time lapse (in number of milliseconds) between each invocation (read/write).
 |*|
 |*|  - myDaemon.reversals -
 |*|  Blabla (read/write).
 |*|
 |*|  - myDaemon.onstart -
 |*|  The "start" listener (read/write).
 |*|  It will be called with three arguments: @index (the actual index), @length (the number of total
 |*|  invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing
 |*|  whether the @index will go decreasing or not).
 |*|
 |*|  - myDaemon.onstop -
 |*|  The "stop" listener (read/write).
 |*|  It will be called with three arguments: @index (the index of the last invocation), @length (the
 |*|  number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean
 |*|  expressing whether the @index of the last execution was decreasing or not).
 |*|  NOTE: The stop() method is not part of the base system.
 |*|
 |*|
 |*|  :: Daemon instances methods ::
 |*|
 |*|
 |*|  - myDaemon.isAtEnd() -
 |*|  Returns a boolean expressing whether the daemon is at the start/end position or not.
 |*|
 |*|  - myDaemon.synchronize() -
 |*|  Synchronize the timer of a started daemon with the time of invocation of myDaemon.synchronize(). If
 |*|  the rate property has been changed the daemon will be updated with the new rate value.
 |*|
 |*|  - myDaemon.pause() -
 |*|  Pauses the daemon.
 |*|
 |*|  - myDaemon.start([@backwards]) -
 |*|  Starts the daemon forward (index of each invocation increasing) or backwards (index decreasing).
 |*|
 \*/

"use strict";


      /****************************
      *     THE DAEMON SYSTEM     *
      ****************************/



/* The global "Daemon" constructor */

  function Daemon (oOwner, fTask, nLen, nRate, fInit, fOnstart) {
    if (!(this && this instanceof Daemon)) { return; }
    if (arguments.length < 2) { throw new TypeError("Daemon - not enough arguments"); }
    if (oOwner) { this.owner = oOwner };
    this.task = fTask;
    if (nLen > 0) { this.length = Math.floor(nLen); }
    if (isFinite(nRate) && nRate > 0) { this.rate = Math.floor(nRate); }
    if (fOnstart) { this.onstart = fOnstart; }
    if (fInit) {
      this.onstop = fInit;
      fInit.call(oOwner, this.INDEX, this.length, this.BACKW);
    }
  }

    /* Create the Daemon.blank() constructor and the global Daemon.context object */

  Daemon.blank = function () {};
  Daemon.context = Daemon.blank.prototype; /* Make love with the GC :-) */
  Daemon.blank.prototype = /* Important! */ Daemon.prototype;
  Daemon.context.constructor = Object;

    /* These properties can be manually reconfigured after the creation of the daemon */

  Daemon.prototype.owner = Daemon.context;
  Daemon.prototype.task = null;
  Daemon.prototype.length = Infinity;
  Daemon.prototype.rate = 100;
  Daemon.prototype.reversals = 0;
  Daemon.prototype.onstart = null;
  Daemon.prototype.onstop = null;

    /* These properties should be read-only after the creation of the daemon */

  Daemon.prototype.SESSION = -1;
  Daemon.prototype.INDEX = 0;
  Daemon.prototype.PAUSED = true;
  Daemon.prototype.BACKW = true;


/* SYSTEM REQUIRED Daemon global object methods */

  Daemon.forceCall = function (oDmn) {

    oDmn.INDEX += oDmn.BACKW ? -1 : 1;

    var
      bBreak = oDmn.task.call(oDmn.owner, oDmn.INDEX, oDmn.length, oDmn.BACKW) === false,
      bEnd = oDmn.isAtEnd(), bInvert = oDmn.reversals > 0;

    if (bEnd && !bInvert || bBreak) {
      oDmn.pause();
      return false;
    }

    if (bEnd && bInvert) {
      oDmn.BACKW = !oDmn.BACKW;
      oDmn.reversals--;
    }

    return true;

  };


/* SYSTEM NOT REQUIRED Daemon global object methods */

  /**
  * Daemon global object optional methods (shortcurts). You could safely remove all or some of them,
  * depending on your needs. If you want to remove them and are using the Daemon.crazy subsystem you
  * should remove also the Daemon.crazy global object methods which require them.
  **/

  Daemon.construct = function (aArgs) {
    var oDmn = new this.blank();
    this.apply(oDmn, aArgs);
    return oDmn;
  };

  Daemon.buildAround = function (oCtx, nLen, nRate) {
    if (!oCtx.perform) { throw new TypeError("You can not create a daemon around an object devoid of a \"perform\" function"); }
    return new this(oCtx, oCtx.perform, nLen || null, nRate || null, oCtx.create || null, oCtx.prepare || null);
  };

    /* Warning! Calling Daemon.incorporate(@func) will modify the @func.prototype property! */

  Daemon.incorporate = function (fConstr) {
    var oLegacy = fConstr.prototype;
    fConstr.prototype = new Daemon.blank();
    fConstr.prototype.legacy = oLegacy;
    return fConstr;
  };


/* SYSTEM REQUIRED Daemon instances methods */

  Daemon.prototype.isAtEnd = function () {
    return this.BACKW ? isFinite(this.length) && this.INDEX < 1 : this.INDEX + 1 > this.length;
  };

  Daemon.prototype.synchronize = function () {
    if (this.PAUSED) { return; }
    clearInterval(this.SESSION);
    this.SESSION = setInterval(Daemon.forceCall, this.rate, this);
  };

  Daemon.prototype.pause = function () {
    clearInterval(this.SESSION);
    this.PAUSED = true;
  };


/* SYSTEM NOT REQUIRED Daemon instances methods */

  /**
  * Basical user interface. You could remove this method, but your daemon will be virtually unusable.
  * All other optional instances methods depend on this one or on the previous ones.
  **/

  Daemon.prototype.start = function (bReverse) {
    var bBackw = Boolean(bReverse);
    if (this.BACKW === bBackw && (this.isAtEnd() || !this.PAUSED)) { return false; }
    this.BACKW = bBackw;
    this.PAUSED = false;
    if (this.onstart) { this.onstart.call(this.owner, this.INDEX, this.length, this.BACKW); }
    this.synchronize();
    return true;
  };



      /*******************************
      *     DAEMON IS NOW READY!     *
      *******************************/




      /*******************************
      *          POLYFILLS           *
      *******************************/



 /*\
 |*|
 |*|  IE-specific polyfill which enables the passage of arbitrary arguments to the
 |*|  callback functions of JavaScript timers (HTML5 standard syntax).
 |*|
 |*|  https://developer.mozilla.org/en-US/docs/DOM/window.setInterval
 |*|
 |*|  Syntax:
 |*|  var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
 |*|  var timeoutID = window.setTimeout(code, delay);
 |*|  var intervalID = window.setInterval(func, delay[, param1, param2, ...]);
 |*|  var intervalID = window.setInterval(code, delay);
 |*|
 \*/
 
  if (document.all && !window.setTimeout.isPolyfill) {
    var __nativeST__ = window.setTimeout;
    window.setTimeout = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) {
      var aArgs = Array.prototype.slice.call(arguments, 2);
      return __nativeST__(vCallback instanceof Function ? function () {
        vCallback.apply(null, aArgs);
      } : vCallback, nDelay);
    };
    window.setTimeout.isPolyfill = true;
  }
   
  if (document.all && !window.setInterval.isPolyfill) {
    var __nativeSI__ = window.setInterval;
    window.setInterval = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) {
      var aArgs = Array.prototype.slice.call(arguments, 2);
      return __nativeSI__(vCallback instanceof Function ? function () {
        vCallback.apply(null, aArgs);
      } : vCallback, nDelay);
    };
    window.setInterval.isPolyfill = true;
  }

crazy.js

 /*\
 |*|
 |*|                     *******************************
 |*|                     *          crazy.js           *
 |*|                     *******************************
 |*|
 |*|
 |*|
 |*|  A JAVASCRIPT HIGLY SCALABLE DAEMONS MANAGER
 |*|
 |*|  https://developer.mozilla.org/en-US/docs/DOM/window.setInterval
 |*|  https://developer.mozilla.org/User:fusionchess
 |*|
 |*|  This framework is released under the GNU Public License, version 3 or later.
 |*|  http://www.gnu.org/licenses/gpl-3.0-standalone.html
 |*|
 |*|
 |*|  :: Content of this file ::
 |*|
 |*|
 |*|  The Daemon.crazy sub-system. This library requires "fork.js".
 |*|  Daemon.crazy constructor is as a dependent-clone of Daemon which uses a recursive invocation of the
 |*|  setTimeout() timer rather than a single invocation of setInterval().
 |*|
 |*|
 |*|  :: The constructor ::
 |*|
 |*|
 |*|  Syntax
 |*|
 |*|       var myCrazyDaemon = new Daemon.crazy(@thisObject, @callback[, @length, @rate, @init, @onstart]);
 |*|
 |*|
 |*|  Description
 |*|
 |*|  Constructs a JavaScript Object containing all informations needed by an animation (see the Daemon
 |*|  constructor for details).
 |*|
 |*|
 |*|  Arguments
 |*|
 |*|  [the same as Daemon]
 |*|
 |*|
 |*|  :: Daemon.crazy global object properties ::
 |*|
 |*|
 |*|  - Daemon.crazy.context -
 |*|  See: Daemon.context.
 |*|  This context will not used by default. It will be used the global Daemon.context instead.
 |*|
 |*|
 |*|  :: Daemon.crazy global object methods ::
 |*|
 |*|
 |*|  - Daemon.crazy.forceCall(@daemonInstance) -
 |*|  See: Daemon.forceCall()
 |*|
 |*|  - Daemon.crazy.construct(@array_of_arguments) -
 |*|  See: Daemon.construct()
 |*|
 |*|  - Daemon.crazy.buildAround(@object) -
 |*|  See: Daemon.buildAround()
 |*|
 |*|  - Daemon.crazy.incorporate(@function) -
 |*|  See: Daemon.incorporate()
 |*|
 |*|
 |*|  :: Other constructors ::
 |*|
 |*|
 |*|  - Daemon.crazy.blank -
 |*|  The same as Daemon.blank, but applied to the Daemon.crazy constructor.
 |*|
 |*|
 |*|  :: Daemon.crazy instances properties ::
 |*|
 |*|  [inherited from Daemon.prototype]
 |*|
 |*|
 |*|  :: Daemon.crazy instances methods ::
 |*|
 |*|  [inherited from Daemon.prototype]
 |*|
 \*/

"use strict";


      /**************************************
      *     THE CRAZY-DAEMON SUB-SYSTEM     *
      **************************************/



/* The "Daemon.crazy" constructor */

  Daemon.crazy = function () { Daemon.apply(this, arguments); };

    /* Create the Daemon.crazy.blank() constructor and the Daemon.crazy.context object */

  Daemon.crazy.blank = function () {};
  Daemon.HELLODARKNESSMYOLDFRIEND = Daemon.crazy.prototype;
  Daemon.crazy.context = Daemon.crazy.blank.prototype; /* Make love with the GC :-) */
  Daemon.crazy.blank.prototype = /* Important! */ Daemon.crazy.prototype = /* Important! */ new Daemon.blank();
  Daemon.crazy.prototype.constructor = Daemon.crazy;
  Daemon.HELLODARKNESSMYOLDFRIEND.constructor = Daemon.crazy.context.constructor = Object;


/* SYSTEM REQUIRED Daemon.crazy global object methods */

  Daemon.crazy.forceCall = function (oDmn) {

    oDmn.INDEX += oDmn.BACKW ? -1 : 1;

    var
      bBreak = oDmn.task.call(oDmn.owner, oDmn.INDEX, oDmn.length, oDmn.BACKW) === false,
      bEnd = oDmn.isAtEnd(), bInvert = oDmn.reversals > 0;

    if (bEnd && !bInvert || bBreak) {
      oDmn.PAUSED = true;
      return false;
    }

    if (bEnd && bInvert) {
      oDmn.BACKW = !oDmn.BACKW;
      oDmn.reversals--;
    }

    oDmn.synchronize();

    return true;

  };


/* SYSTEM NOT REQUIRED Daemon.crazy global object methods */

  /**
  * Daemon.crazy global object optional methods (shortcurts). You could safely remove all or some of
  * them, depending on your needs.
  **/

    /* Warnign: this method requires the global Daemon.construct() method */
  Daemon.crazy.construct = Daemon.construct;

    /* Warnign: this method requires the global Daemon.buildAround() method */
  Daemon.crazy.buildAround = Daemon.buildAround;

    /* Warnign: this method requires the global Daemon.incorporate() method */
  Daemon.crazy.incorporate = Daemon.incorporate;


/* SYSTEM REQUIRED Daemon.crazy instances methods */

  Daemon.crazy.prototype.synchronize = function () {
    if (this.PAUSED) { return; }
    clearTimeout(this.SESSION);
    this.SESSION = setTimeout(Daemon.crazy.forceCall, this.rate, this);
  };

  Daemon.crazy.prototype.pause = function () {
    clearTimeout(this.SESSION);
    this.PAUSED = true;
  };


/* SYSTEM NOT REQUIRED Daemon.crazy instances methods */

  /* [inherited from Daemon.prototype] */



      /*****************************************
      *     THE CRAZY-DAEMON IS NOW READY!     *
      *****************************************/

methods.js

 /*\
 |*|
 |*|                     *******************************
 |*|                     *          daemon.js          *
 |*|                     *******************************
 |*|
 |*|
 |*|
 |*|  A JAVASCRIPT HIGLY SCALABLE DAEMONS MANAGER
 |*|
 |*|  https://developer.mozilla.org/en-US/docs/DOM/window.setInterval
 |*|  https://developer.mozilla.org/User:fusionchess
 |*|
 |*|  This framework is released under the GNU Public License, version 3 or later.
 |*|  http://www.gnu.org/licenses/gpl-3.0-standalone.html
 |*|
 |*|
 |*|  :: Content of this file ::
 |*|
 |*|
 |*|  Additional methods for Daemon instances. This library requires "daemon.js".
 |*|  You can safely remove all or some of these methods, depending on your needs.
 |*|  When a method requires the presence of another method (it is relatively rare) there is a comment
 |*|  which explains it. If there are not comments to that method it depends only on the base system.
 |*|
 |*|
 |*|  :: Daemon instances methods ::
 |*|
 |*|
 |*|  - myDaemon.stop() -
 |*|  Stops the daemon. All original properties will be restored. If it exists a "stop" listener it will
 |*|  be called with three arguments: @index (the index of the last invocation), @length (the number of
 |*|  total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing
 |*|  whether the @index of the last execution was decreasing or not).
 |*|
 |*|  - myDaemon.syncStart([@backwards]) -
 |*|  Starts the daemon with the first callback synchronous.
 |*|
 |*|  - myDaemon.play([@synchronous]) -
 |*|  Starts the daemon forward. If the daemon is running in the same direction nothing will happen.
 |*|  If the argument is "true" the first callback will be synchronous.
 |*|
 |*|  - myDaemon.reversePlay([@synchronous]) -
 |*|  Starts the daemon backwards. If the daemon is running in the same direction nothing will happen.
 |*|  If the argument is "true" the first callback will be synchronous.
 |*|
 |*|  - myDaemon.move([@synchronous, @reversals, @backwards]) -
 |*|  Starts a daemon synchronously or not.
 |*|  If the @reversals argument is specified the myDaemon.reversals property will be setted on it.
 |*|  If the @bacwards argument is specified the daemon will move forward (false) or backwards (true). If
 |*|  it is not specified the daemon will start in the same direction in which it has been left. If the
 |*|  daemon was running in the same direction, only the reversals property will be possibly updated.
 |*|
 |*|  - myDaemon.turn() -
 |*|  Inverts the direction of the daemon. The reversals property will not be decreased.
 |*|
 |*|  - myDaemon.makeLoop() -
 |*|  Sets the reversals property to Infinity.
 |*|
 |*|  - myDaemon.unmakeLoop() -
 |*|  Sets the reversals property to 0.
 |*|
 |*|  - myDaemon.setRate(@milliseconds) -
 |*|  Sets the time lapse between calls (in milliseconds). If the daemon is running it will be immediately
 |*|  updated with the new property.
 |*|
 |*|  - myDaemon.forcePosition(@index) -
 |*|  Sets the internal INDEX property equal to the @index argument without control about the range.
 |*|
 |*|  - myDaemon.getDuration() -
 |*|  Returns the duration of the daemon in milliseconds.
 |*|
 |*|  - myDaemon.getPosition() -
 |*|  Returns the internal INDEX property.
 |*|
 |*|  - myDaemon.makeSteps(@howmany[, @backwards, @force]) -
 |*|  Calls synchronously the callback function @howmany times. Forwards or backwards. If the argument
 |*|  @force is setted to"true" the possible "return false" of the callback function will be ignored.
 |*|
 |*|  - myDaemon.skipTo(@index[, @force]) -
 |*|  Calls synchronously the callback function the number of times needed to reach the @index position.
 |*|  If the argument @force is setted to"true" the possible "return false" of the callback function will
 |*|  be ignored.
 |*|
 |*|  - myDaemon.skipFor(@delta[, @force]) -
 |*|  Calls synchronously the callback function @howmany times in the same direction in which it was
 |*|  oriented. If the argument @force is setted to"true" the possible "return false" of the callback
 |*|  function will be ignored.
 |*|
 |*|  - myDaemon.close([@backwards, @force]) -
 |*|  Closes the daemon, doing SYNCHRONOUSLY all pending operations forward (index of each invocation
 |*|  increasing) or backwards (index decreasing). If the argument @force is setted to "true" the
 |*|  possible "return false" of the callback function will be ignored.
 |*|
 |*|  - myDaemon.reclose([@force]) -
 |*|  Closes the daemon, doing SYNCHRONOUSLY all pending operations in the same direction in which is
 |*|  oriented the daemon. If the argument @force is setted to"true" the possible "return false" of the
 |*|  callback function will be ignored.
 |*|
 |*|  - myDaemon.restart() -
 |*|  Stops and restarts the daemon.
 |*|
 |*|  - myDaemon.loopUntil(@date) -
 |*|  Sets the reversals property in function of a future @date. The @date can be a Date object, a String
 |*|  expressing the date in GMTString format, or a Number expressing the number of milliseconds since
 |*|  January 1, 1970, 00:00:00 UTC.
 |*|
 |*|  - myDaemon.spread(@milliseconds) -
 |*|  Sets the the total duration of the daemon in milliseconds. Only the rate property will be modified.
 |*|
 |*|  - myDaemon.adaptLength(@milliseconds) -
 |*|  Sets the internal length property equal to milliseconds/rate.
 |*|
 |*|  - myDaemon.playUntil(@date) -
 |*|  Starts the daemon forward and sets the the total duration of it in function of a future date. The
 |*|  @date can be a Date object, a String expressing the date in GMTString format, or a Number expressing
 |*|  the number of milliseconds since January 1, 1970, 00:00:00 UTC. Only the length property will be
 |*|  modified.
 |*|
 \*/

"use strict";


/* SYSTEM NOT REQUIRED Daemon instances methods */

    /* Status */

  Daemon.prototype.stop = function () {
    this.pause();
    if (this.onstop) { this.onstop.call(this.owner, this.INDEX, this.length, this.BACKW); }
    delete this.INDEX;
    delete this.BACKW;
    delete this.reversals;
  };

    /* Movement */

  Daemon.prototype.syncStart = function (bReverse) {
    this.synchronize();
    if (this.start(bReverse || false)) {
      Daemon.forceCall(this);
      return true;
    }
    return false;
  };

  Daemon.prototype.play = function (bSync) {
    /* Warnign: this method OPTIONALLY requires the Daemon.prototype.syncStart() method */
    return this[bSync ? "start" : "syncStart"]();
  };

  Daemon.prototype.reversePlay = function (bSync) {
    /* Warnign: this method OPTIONALLY requires the Daemon.prototype.syncStart() method */
    return this[bSync ? "start" : "syncStart"](true);
  };

  Daemon.prototype.move = function (bSync, nCycles, bDirection) {
    /* Warnign: this method OPTIONALLY requires the Daemon.prototype.syncStart() method */
    if (arguments.length > 1 && !isNaN(nCycles)) { this.reversals = Number(nCycles); }
    this[bSync ? "start" : "syncStart"](arguments.length > 2 ? bDirection : this.isAtEnd() !== this.BACKW);
  };

  Daemon.prototype.turn = function (bSync) {
    /* Warnign: this method OPTIONALLY requires the Daemon.prototype.syncStart() method */
    this[bSync ? "start" : "syncStart"](!this.BACKW);
  };

    /* Settings tools */

  Daemon.prototype.makeLoop = function () {
    this.reversals = Infinity;
  };

  Daemon.prototype.unmakeLoop = function () {
    this.reversals = 0;
  };

  Daemon.prototype.setRate = function (vTo) {
    var nRate = Number(vTo);
    if (!isFinite(nRate) || nRate < 1) { return; }
    this.rate = nRate;
    this.synchronize();
  };

  Daemon.prototype.forcePosition = function (vTo) {
    if (isFinite(vTo)) { this.INDEX = Math.round(Math.abs(vTo)); }
  };

  Daemon.prototype.getDuration = function () {
    return this.rate * this.length;
  };

  Daemon.prototype.getDirection = function () {
    return this.isAtEnd() !== this.BACKW;
  };

  Daemon.prototype.getPosition = function () {
    return this.INDEX;
  };

    /* Instantaneous movement (synchronous). */

  Daemon.prototype.makeSteps = function (nHowMany, bReverse, bForce) {
    if (nHowMany === 0) { return true; }
    if (isNaN(nHowMany)) { return false; }
    var nIdx = 0, nLen = Math.round(Math.abs(nHowMany)), bContinue = true, bBackw = nHowMany > 0 === Boolean(bReverse);
    this.BACKW = bBackw;
    for (nIdx; nIdx < nLen && bContinue; nIdx++) {
      if (this.BACKW === bBackw && this.isAtEnd()) {
        if (this.reversals > 0) { this.BACKW = bBackw = !this.BACKW; }
        else { break; }
      }
      bContinue = Daemon.forceCall(this) || bForce;
    }
    return nIdx === nLen;
  };

  Daemon.prototype.skipTo = function (nIdx, bForce) {
    /* Warnign: this method requires the Daemon.prototype.makeSteps() method */
    if (nIdx === this.INDEX) { return; }
    if (isFinite(this.length) && nIdx < 0 || nIdx > this.length) { return; }

    var
      bDirection = (this.INDEX !== 0 && this.INDEX !== this.length) === this.BACKW,
      bSuccess = this.makeSteps(this.INDEX - nIdx, true, bForce);

    if (this.INDEX !== 0 && this.INDEX !== this.length) { this.BACKW = bDirection; }
    return bSuccess;
  };

  Daemon.prototype.skipFor = function (nDelta, bForce) {
    /* Warnign: this method requires the Daemon.prototype.makeSteps() method */
    return this.makeSteps(nDelta, this.isAtEnd() !== this.BACKW, bForce);
  };

  Daemon.prototype.close = function (bReverse, bForce) {
    /* Warnign: this method requires the Daemon.prototype.makeSteps() method */
    if (!isFinite(this.length)) { return false; }
    this.pause();
    this.reversals = 0;
    return this.makeSteps(bReverse ? this.INDEX : this.length - this.INDEX, bReverse, bForce);
  };

  Daemon.prototype.reclose = function (bForce) {
    /* Warnign: this method requires the Daemon.prototype.makeSteps() and Daemon.prototype.close() methods */
    return this.close(this.isAtEnd() !== this.BACKW, bForce || false);
  };

  /* Others */

  Daemon.prototype.restart = function () {
    this.stop();
    this.start();
  };

  Daemon.prototype.loopUntil = function (vDate) {
    if (!isFinite(this.length)) { return; }
    var nTime = vDate.constructor === Date ? vDate.getTime() : isNaN(vDate) ? Date.parse(vDate) : vDate;
    if (isFinite(nTime) && nTime > Date.now()) {
      this.reversals = Math.floor((nTime - Date.now() - (this.BACKW ? this.INDEX : this.length - this.INDEX) * this.rate) / (this.length * this.rate));
      this.start(this.isAtEnd() !== this.BACKW);
    }
  };

  Daemon.prototype.spread = function (nTime) {
    if (!isFinite(this.length)) { throw new TypeError("Daemon.prototype.spread - the length is not a finite number. Use Daemon.prototype.adaptLength()."); }
    if (nTime > 0) {
      this.rate = Math.floor(nTime / this.length);
      this.synchronize();
    }
    return this.rate;
  };

  Daemon.prototype.adaptLength = function (nTime) {
    this.length = Math.floor(nTime / this.rate);
    return this.length;
  };

  Daemon.prototype.playUntil = function (vDate) {
    var nTime = vDate.constructor === Date ? vDate.getTime() : isNaN(vDate) ? Date.parse(vDate) : vDate;
    if (isFinite(nTime) && nTime > Date.now()) {
      this.length = Math.floor((nTime - Date.now()) / this.rate) + this.INDEX;
      this.pause();
      this.start();
    }
    return this.length;
  };

The manual

The constructor

Syntax

var myDaemon = new Daemon(@thisObject, @callback[, @length, @rate, @init, @onstart]);

Description

Constructs a JavaScript Object containing all informations needed by an animation (like the "this" object, the callback function, the length, the frame-rate, the number of cycles, the "init" and the "onstart" functions).

Arguments

@thisObject
The "this" object on which will be called the callback function. It can be an object or null. If is null, the "this" object will point to the global "Deamon.context" object (see below).
@callback
The function which will be invoked repeatedly. It will be called with three parameters: @index (the iterative index of each invocation), @length (the number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing whether the process is going backwards or not). It will be something like @callback.call(@thisObject, @index, @length, @backwards). If the @callback function returns a "false" value the Daemon will be paused.
@length (optional)
The total number of invocations. It can be a positive integer or Infinity. The default value is Infinity.
@rate (optional)
The time lapse (in number of milliseconds) between each invocation. The default value is 100.
@init (optional)
The function which will be synchronously invoked once during the creation of the daemon and then assigned to the "onstop" property. It will be called with the same three arguments of the @callback function. They will also have the same values of the last invocation of the @callback function.
@onstart
The function which will be synchronously invoked on whenever the "start" event occurs. It will be assigned to the "onstart" property. It will be called with three arguments: @index (the actual index), @length (the number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing whether the @index will go decreasing or not).

Daemon global object properties

Daemon.context
An empty object used as default *this* object when the @thisObject is not specified during the construction of the daemon. If you want your callback function to be invoked with a "null" *this* object you have to manually set the "owner" property to "null".

Daemon global object methods

Daemon.forceCall(@daemonInstance)
Forces a callback to the @daemonInstance.task function regardless of the fact that the end has been reached or not. In any case the internal "INDEX" property will be increased/decreased (depending on the actual direction of the daemon).
Daemon.construct(@array_of_arguments)
Returns a new daemon constructed upon an array of arguments. It is very similar to the Function.prototype.apply() method.
Daemon.buildAround(@context[, @length, @rate])
Returns a new daemon built around a @context object. The @context object must cointain *at least* a "perform" property pointing to what you want to be the @callback function of the daemon. It can also optionally contain a "create" and a "prepare" properties pointing respectively the two functions you want to be the @init and @onstart functions of Daemon constructor's arguments. The @context object will be also the *this* object of your callback function. So you can populate it with all your custom properties. and methods. The only required one property is "perform".
Sample usage:
var myDaemon = Daemon.buildAround({
	"create": function () { [custom code] },  // optional
	"prepare": function () { [custom code] },  // optional
	"perform": function () { [custom code] },  // required
	"customProperty": [custom value],
	"myCustomMethod": function () { [custom code] },
	"anotherCustomProperty": [custom value],
	"etc.": "etc."
}, 30, 200);
Daemon.incorporate(@function)
The @function.prototype property will replaced with a *new Daemon()* object. The old replaced prototype will be preserved within a new property of the new @function.prototype named "legacy".

Other constructors

Daemon.blank
Constructs a new instance of Daemon without own properties. This constructor is useful in order to create your own *MySomeDaemon* constructors through the *MySomeDaemon.prototype = new Daemon.blank();* assignment.
Daemon.crazy [optional module crazy.js]
A clone of the Daemon constructor based on setTimeout rather than on setInterval. See the Daemon.crazy module for details. NOTE: The Daemon.crazy constructor is not part of the base system.
Daemon.crazy.blank [optional module crazy.js]
The same as for Daemon.blank, but applied to the Daemon.crazy constructor. NOTE: The Daemon.crazy constructor is not part of the base system.

Daemon instances properties

myDaemon.owner
The "this" object on which is executed the daemon (read/write). It can be an object or null. Its default value is Daemon.context.
myDaemon.task
The function which will be repeatedly invoked (read/write). It will be called with three arguments: @index (the iterative index of each invocation), @length (the number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing whether the @index is decreasing or not). See above. If the myDaemon.task function returns a "false" the Daemon will be paused.
myDaemon.length
The total number of invocations. It can be a positive integer or Infinity (read/write).
myDaemon.rate
The time lapse (in number of milliseconds) between each invocation (read/write).
myDaemon.reversals
Blabla (read/write).
myDaemon.onstart
The "start" listener (read/write). It will be called with three arguments: @index (the actual index), @length (the number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing whether the @index will go decreasing or not).
myDaemon.onstop
The "stop" listener (read/write). It will be called with three arguments: @index (the index of the last invocation), @length (the number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing whether the @index of the last execution was decreasing or not). NOTE: The stop() method is not part of the base system.

Daemon instances methods

myDaemon.isAtEnd()
Returns a boolean expressing whether the daemon is at the start/end position or not.
myDaemon.synchronize()
Synchronize the timer of a started daemon with the time of invocation of myDaemon.synchronize(). If the rate property has been changed the daemon will be updated with the new rate value.
myDaemon.pause()
Pauses the daemon.
myDaemon.start([@backwards])
Starts the daemon forward (index of each invocation increasing) or backwards (index decreasing).

methods.js

Additional instances methods [optional module methods.js]

myDaemon.stop()
Stops the daemon. All original properties will be restored. If it exists a "stop" listener it will be called with three arguments: @index (the index of the last invocation), @length (the number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing whether the @index of the last execution was decreasing or not).
myDaemon.syncStart([@backwards])
Starts the daemon with the first callback synchronous.
myDaemon.play([@synchronous])
Starts the daemon forward. If the daemon is running in the same direction nothing will happen. If the argument is "true" the first callback will be synchronous.
myDaemon.reversePlay([@synchronous])
Starts the daemon backwards. If the daemon is running in the same direction nothing will happen. If the argument is "true" the first callback will be synchronous.
myDaemon.move([@synchronous, @reversals, @backwards])
Starts a daemon synchronously or not. If the @reversals argument is specified the myDaemon.reversals property will be setted on it. If the @bacwards argument is specified the daemon will move forward (false) or backwards (true). If it is not specified the daemon will start in the same direction in which it has been left. If the daemon was running in the same direction, only the reversals property will be possibly updated.
myDaemon.turn()
Inverts the direction of the daemon. The reversals property will not be decreased.
myDaemon.makeLoop()
Sets the reversals property to Infinity.
myDaemon.unmakeLoop()
Sets the reversals property to 0.
myDaemon.setRate(@milliseconds)
Sets the time lapse between calls (in milliseconds). If the daemon is running it will be immediately updated with the new property.
myDaemon.forcePosition(@index)
Sets the internal INDEX property equal to the @index argument without control about the range.
myDaemon.getDuration()
Returns the duration of the daemon in milliseconds.
myDaemon.getPosition()
Returns the internal INDEX property.
myDaemon.makeSteps(@howmany[, @backwards, @force])
Calls synchronously the callback function @howmany times. Forwards or backwards. If the argument @force is setted to"true" the possible "return false" of the callback function will be ignored.
myDaemon.skipTo(@index[, @force])
Calls synchronously the callback function the number of times needed to reach the @index position. If the argument @force is setted to"true" the possible "return false" of the callback function will be ignored.
myDaemon.skipFor(@delta[, @force])
Calls synchronously the callback function @howmany times in the same direction in which it was oriented. If the argument @force is setted to"true" the possible "return false" of the callback function will be ignored.
myDaemon.close([@backwards, @force])
Closes the daemon, doing SYNCHRONOUSLY all pending operations forward (index of each invocation increasing) or backwards (index decreasing). If the argument @force is setted to "true" the possible "return false" of the callback function will be ignored.
myDaemon.reclose([@force])
Closes the daemon, doing SYNCHRONOUSLY all pending operations in the same direction in which is oriented the daemon. If the argument @force is setted to"true" the possible "return false" of the callback function will be ignored.
myDaemon.restart()
Stops and restarts the daemon.
myDaemon.loopUntil(@date)
Sets the reversals property in function of a future @date. The @date can be a Date object, a String expressing the date in GMTString format, or a Number expressing the number of milliseconds since January 1, 1970, 00:00:00 UTC.
myDaemon.spread(@milliseconds)
Sets the the total duration of the daemon in milliseconds. Only the rate property will be modified.
myDaemon.adaptLength(@milliseconds)
Sets the internal length property equal to milliseconds/rate.
myDaemon.playUntil(@date)
Starts the daemon forward and sets the the total duration of it in function of a future date. The @date can be a Date object, a String expressing the date in GMTString format, or a Number expressing the number of milliseconds since January 1, 1970, 00:00:00 UTC. Only the length property will be modified.

This page is under construction

Revision Source

<p>This page is under construction</p>
<h2>The code</h2>
<h4>fork.js</h4>
<div style="height: 500px; margin-bottom: 12px; overflow: auto;">
  <pre class="brush: js">
&nbsp;/*\
&nbsp;|*|
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *******************************
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fork.js&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *******************************
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; A JAVASCRIPT HIGLY SCALABLE DAEMONS MANAGER.
&nbsp;|*|
&nbsp;|*|&nbsp; https://developer.mozilla.org/en-US/docs/DOM/window.setInterval
 |*|  https://developer.mozilla.org/User:fusionchess
 |*|
 |*|  This framework is released under the GNU Public License, version 3 or later.
 |*|  http://www.gnu.org/licenses/gpl-3.0-standalone.html
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Content of this file ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; The Daemon base system.
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: The constructor ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; Syntax
&nbsp;|*|
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var myDaemon = new Daemon(@thisObject, @callback[, @length, @rate, @init, @onstart]);
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; Description
&nbsp;|*|
&nbsp;|*|&nbsp; Constructs a JavaScript Object containing all informations needed by an animation (like the "this"
&nbsp;|*|&nbsp; object, the callback function, the length, the frame-rate, the number of cycles, the "init" and
&nbsp;|*|&nbsp; the "onstart" functions).
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; Arguments
&nbsp;|*|
&nbsp;|*|&nbsp; - @thisObject -
&nbsp;|*|&nbsp; The "this" object on which will be called the callback function. It can be an object or null. If
&nbsp;|*|&nbsp; is null, the "this" object will point to the global "Deamon.context" object (see below).
&nbsp;|*|
&nbsp;|*|&nbsp; - @callback -
&nbsp;|*|&nbsp; The function which will be invoked repeatedly. It will be called with three parameters: @index
&nbsp;|*|&nbsp; (the iterative index of each invocation), @length (the number of total invocations assigned to the
&nbsp;|*|&nbsp; daemon - finite or Infinity) and @backwards (a boolean expressing whether the process is going
&nbsp;|*|&nbsp; backwards or not).
&nbsp;|*|&nbsp; It will be something like @callback.call(@thisObject, @index, @length, @backwards).
&nbsp;|*|&nbsp; If the @callback function returns a "false" value the Daemon will be paused.
&nbsp;|*|
&nbsp;|*|&nbsp; - @length (optional) -
&nbsp;|*|&nbsp; The total number of invocations. It can be a positive integer or Infinity. The default value is
&nbsp;|*|&nbsp; Infinity.
&nbsp;|*|
&nbsp;|*|&nbsp; - @rate (optional) -
&nbsp;|*|&nbsp; The time lapse (in number of milliseconds) between each invocation. The default value is 100.
&nbsp;|*|
&nbsp;|*|&nbsp; - @init (optional) -
&nbsp;|*|&nbsp; The function which will be synchronously invoked once during the creation of the daemon and
&nbsp;|*|&nbsp; then assigned to the "onstop" property.
&nbsp;|*|&nbsp; It will be called with the same three arguments of the @callback function. They will also have the
&nbsp;|*|&nbsp; same values of the last invocation of the @callback function.
&nbsp;|*|
&nbsp;|*|&nbsp; - @onstart -
&nbsp;|*|&nbsp; The function which will be synchronously invoked on whenever the "start" event occurs. It will be
&nbsp;|*|&nbsp; assigned to the "onstart" property.
&nbsp;|*|&nbsp; It will be called with three arguments: @index (the actual index), @length (the number of total
&nbsp;|*|&nbsp; invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing
&nbsp;|*|&nbsp; whether the @index will go decreasing or not).
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Daemon global object properties ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.context -
&nbsp;|*|&nbsp; An empty object used as default *this* object when the @thisObject is not specified during the
&nbsp;|*|&nbsp; construction of the daemon. If you want your callback function to be invoked with a "null" *this*
&nbsp;|*|&nbsp; object you have to manually set the "owner" property to "null".
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Daemon global object methods ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.forceCall(@daemonInstance) -
&nbsp;|*|&nbsp; Forces a callback to the @daemonInstance.task function regardless of the fact that the end has
&nbsp;|*|&nbsp; been reached or not. In any case the internal "INDEX" property will be increased/decreased
&nbsp;|*|&nbsp; (depending on the actual direction of the daemon).
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.construct(@array_of_arguments) -
&nbsp;|*|&nbsp; Returns a new daemon constructed upon an array of arguments. It is very similar to the
&nbsp;|*|&nbsp; Function.prototype.apply() method.
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.buildAround(@context[, @length, @rate]) -
&nbsp;|*|&nbsp; Returns a new daemon built around a @context object. The @context object must cointain *at least*
&nbsp;|*|&nbsp; a "perform" property pointing to what you want to be the @callback function of the daemon.
&nbsp;|*|&nbsp; It can also optionally contain a "create" and a "prepare" properties pointing respectively the
&nbsp;|*|&nbsp; two functions you want to be the @init and @onstart functions of Daemon constructor's arguments.
&nbsp;|*|&nbsp; The @context object will be also the *this* object of your callback function. So you can populate
&nbsp;|*|&nbsp; it with all your custom properties. and methods. The only required one property is "perform".
&nbsp;|*|&nbsp;&nbsp; &nbsp;
&nbsp;|*|&nbsp;&nbsp;&nbsp; Sample usage:
&nbsp;|*|
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var myDaemon = Daemon.buildAround({
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "create": function () { [custom code] },&nbsp; // optional
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "prepare": function () { [custom code] },&nbsp; // optional
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "perform": function () { [custom code] },&nbsp; // required
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "customProperty": [custom value],
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "myCustomMethod": function () { [custom code] },
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "anotherCustomProperty": [custom value],
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "etc.": "etc."
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }, 30, 200);
&nbsp;|*|&nbsp;&nbsp; &nbsp;
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.incorporate(@function) -
&nbsp;|*|&nbsp; The @function.prototype property will replaced with a *new Daemon()* object. The old replaced
&nbsp;|*|&nbsp; prototype will be preserved within a new property of the new @function.prototype named "legacy".
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Other constructors ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.blank -
&nbsp;|*|&nbsp; Constructs a new instance of Daemon without own properties. This constructor is useful in order to
&nbsp;|*|&nbsp; create your own *MySomeDaemon* constructors through the *MySomeDaemon.prototype = new Daemon.blank();*
&nbsp;|*|&nbsp; assignment.
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.crazy [optional module] -
&nbsp;|*|&nbsp; A clone of the Daemon constructor based on setTimeout rather than on setInterval. See the Daemon.crazy
&nbsp;|*|&nbsp; module for details.
&nbsp;|*|&nbsp; NOTE: The Daemon.crazy constructor is not part of the base system.
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.crazy.blank [optional module] -
&nbsp;|*|&nbsp; The same as for Daemon.blank, but applied to the Daemon.crazy constructor.
&nbsp;|*|&nbsp; NOTE: The Daemon.crazy constructor is not part of the base system.
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Daemon instances properties ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.owner -
&nbsp;|*|&nbsp; The "this" object on which is executed the daemon (read/write). It can be an object or null. Its default
&nbsp;|*|&nbsp; value is Daemon.context.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.task -
&nbsp;|*|&nbsp; The function which will be repeatedly invoked (read/write). It will be called with three
&nbsp;|*|&nbsp; arguments: @index (the iterative index of each invocation), @length (the number of total
&nbsp;|*|&nbsp; invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing
&nbsp;|*|&nbsp; whether the @index is decreasing or not). See above.
&nbsp;|*|&nbsp; If the myDaemon.task function returns a "false" the Daemon will be paused.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.length -
&nbsp;|*|&nbsp; The total number of invocations. It can be a positive integer or Infinity (read/write).
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.rate -
&nbsp;|*|&nbsp; The time lapse (in number of milliseconds) between each invocation (read/write).
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.reversals -
&nbsp;|*|&nbsp; Blabla (read/write).
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.onstart -
&nbsp;|*|&nbsp; The "start" listener (read/write).
&nbsp;|*|&nbsp; It will be called with three arguments: @index (the actual index), @length (the number of total
&nbsp;|*|&nbsp; invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing
&nbsp;|*|&nbsp; whether the @index will go decreasing or not).
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.onstop -
&nbsp;|*|&nbsp; The "stop" listener (read/write).
&nbsp;|*|&nbsp; It will be called with three arguments: @index (the index of the last invocation), @length (the
&nbsp;|*|&nbsp; number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean
&nbsp;|*|&nbsp; expressing whether the @index of the last execution was decreasing or not).
&nbsp;|*|&nbsp; NOTE: The stop() method is not part of the base system.
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Daemon instances methods ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.isAtEnd() -
&nbsp;|*|&nbsp; Returns a boolean expressing whether the daemon is at the start/end position or not.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.synchronize() -
&nbsp;|*|&nbsp; Synchronize the timer of a started daemon with the time of invocation of myDaemon.synchronize(). If
&nbsp;|*|&nbsp; the rate property has been changed the daemon will be updated with the new rate value.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.pause() -
&nbsp;|*|&nbsp; Pauses the daemon.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.start([@backwards]) -
&nbsp;|*|&nbsp; Starts the daemon forward (index of each invocation increasing) or backwards (index decreasing).
&nbsp;|*|
&nbsp;\*/

"use strict";


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /****************************
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; THE DAEMON SYSTEM&nbsp;&nbsp;&nbsp;&nbsp; *
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ****************************/



/* The global "Daemon" constructor */

&nbsp; function Daemon (oOwner, fTask, nLen, nRate, fInit, fOnstart) {
&nbsp;&nbsp;&nbsp; if (!(this &amp;&amp; this instanceof Daemon)) { return; }
&nbsp;&nbsp;&nbsp; if (arguments.length &lt; 2) { throw new TypeError("Daemon - not enough arguments"); }
&nbsp;&nbsp;&nbsp; if (oOwner) { this.owner = oOwner };
&nbsp;&nbsp;&nbsp; this.task = fTask;
&nbsp;&nbsp;&nbsp; if (nLen &gt; 0) { this.length = Math.floor(nLen); }
&nbsp;&nbsp;&nbsp; if (isFinite(nRate) &amp;&amp; nRate &gt; 0) { this.rate = Math.floor(nRate); }
&nbsp;&nbsp;&nbsp; if (fOnstart) { this.onstart = fOnstart; }
&nbsp;&nbsp;&nbsp; if (fInit) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.onstop = fInit;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fInit.call(oOwner, this.INDEX, this.length, this.BACKW);
&nbsp;&nbsp;&nbsp; }
&nbsp; }

&nbsp;&nbsp;&nbsp; /* Create the Daemon.blank() constructor and the global Daemon.context object */

&nbsp; Daemon.blank = function () {};
&nbsp; Daemon.context = Daemon.blank.prototype; /* Make love with the GC :-) */
&nbsp; Daemon.blank.prototype = /* Important! */ Daemon.prototype;
&nbsp; Daemon.context.constructor = Object;

&nbsp;&nbsp;&nbsp; /* These properties can be manually reconfigured after the creation of the daemon */

&nbsp; Daemon.prototype.owner = Daemon.context;
&nbsp; Daemon.prototype.task = null;
&nbsp; Daemon.prototype.length = Infinity;
&nbsp; Daemon.prototype.rate = 100;
&nbsp; Daemon.prototype.reversals = 0;
&nbsp; Daemon.prototype.onstart = null;
&nbsp; Daemon.prototype.onstop = null;

&nbsp;&nbsp;&nbsp; /* These properties should be read-only after the creation of the daemon */

&nbsp; Daemon.prototype.SESSION = -1;
&nbsp; Daemon.prototype.INDEX = 0;
&nbsp; Daemon.prototype.PAUSED = true;
&nbsp; Daemon.prototype.BACKW = true;


/* SYSTEM REQUIRED Daemon global object methods */

&nbsp; Daemon.forceCall = function (oDmn) {

&nbsp;&nbsp;&nbsp; oDmn.INDEX += oDmn.BACKW ? -1 : 1;

&nbsp;&nbsp;&nbsp; var
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bBreak = oDmn.task.call(oDmn.owner, oDmn.INDEX, oDmn.length, oDmn.BACKW) === false,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bEnd = oDmn.isAtEnd(), bInvert = oDmn.reversals &gt; 0;

&nbsp;&nbsp;&nbsp; if (bEnd &amp;&amp; !bInvert || bBreak) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oDmn.pause();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; if (bEnd &amp;&amp; bInvert) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oDmn.BACKW = !oDmn.BACKW;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oDmn.reversals--;
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; return true;

&nbsp; };


/* SYSTEM NOT REQUIRED Daemon global object methods */

&nbsp; /**
&nbsp; * Daemon global object optional methods (shortcurts). You could safely remove all or some of them,
&nbsp; * depending on your needs. If you want to remove them and are using the Daemon.crazy subsystem you
&nbsp; * should remove also the Daemon.crazy global object methods which require them.
&nbsp; **/

&nbsp; Daemon.construct = function (aArgs) {
&nbsp;&nbsp;&nbsp; var oDmn = new this.blank();
&nbsp;&nbsp;&nbsp; this.apply(oDmn, aArgs);
&nbsp;&nbsp;&nbsp; return oDmn;
&nbsp; };

&nbsp; Daemon.buildAround = function (oCtx, nLen, nRate) {
&nbsp;&nbsp;&nbsp; if (!oCtx.perform) { throw new TypeError("You can not create a daemon around an object devoid of a \"perform\" function"); }
&nbsp;&nbsp;&nbsp; return new this(oCtx, oCtx.perform, nLen || null, nRate || null, oCtx.create || null, oCtx.prepare || null);
&nbsp; };

&nbsp;&nbsp;&nbsp; /* Warning! Calling Daemon.incorporate(@func) will modify the @func.prototype property! */

&nbsp; Daemon.incorporate = function (fConstr) {
&nbsp;&nbsp;&nbsp; var oLegacy = fConstr.prototype;
&nbsp;&nbsp;&nbsp; fConstr.prototype = new Daemon.blank();
&nbsp;&nbsp;&nbsp; fConstr.prototype.legacy = oLegacy;
&nbsp;&nbsp;&nbsp; return fConstr;
&nbsp; };


/* SYSTEM REQUIRED Daemon instances methods */

&nbsp; Daemon.prototype.isAtEnd = function () {
&nbsp;&nbsp;&nbsp; return this.BACKW ? isFinite(this.length) &amp;&amp; this.INDEX &lt; 1 : this.INDEX + 1 &gt; this.length;
&nbsp; };

&nbsp; Daemon.prototype.synchronize = function () {
&nbsp;&nbsp;&nbsp; if (this.PAUSED) { return; }
&nbsp;&nbsp;&nbsp; clearInterval(this.SESSION);
&nbsp;&nbsp;&nbsp; this.SESSION = setInterval(Daemon.forceCall, this.rate, this);
&nbsp; };

&nbsp; Daemon.prototype.pause = function () {
&nbsp;&nbsp;&nbsp; clearInterval(this.SESSION);
&nbsp;&nbsp;&nbsp; this.PAUSED = true;
&nbsp; };


/* SYSTEM NOT REQUIRED Daemon instances methods */

&nbsp; /**
&nbsp; * Basical user interface. You could remove this method, but your daemon will be virtually unusable.
&nbsp; * All other optional instances methods depend on this one or on the previous ones.
&nbsp; **/

&nbsp; Daemon.prototype.start = function (bReverse) {
&nbsp;&nbsp;&nbsp; var bBackw = Boolean(bReverse);
&nbsp;&nbsp;&nbsp; if (this.BACKW === bBackw &amp;&amp; (this.isAtEnd() || !this.PAUSED)) { return false; }
&nbsp;&nbsp;&nbsp; this.BACKW = bBackw;
&nbsp;&nbsp;&nbsp; this.PAUSED = false;
&nbsp;&nbsp;&nbsp; if (this.onstart) { this.onstart.call(this.owner, this.INDEX, this.length, this.BACKW); }
&nbsp;&nbsp;&nbsp; this.synchronize();
&nbsp;&nbsp;&nbsp; return true;
&nbsp; };



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*******************************
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; DAEMON IS NOW READY!&nbsp;&nbsp;&nbsp;&nbsp; *
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *******************************/




&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*******************************
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POLYFILLS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *******************************/



&nbsp;/*\
&nbsp;|*|
&nbsp;|*|&nbsp; IE-specific polyfill which enables the passage of arbitrary arguments to the
&nbsp;|*|&nbsp; callback functions of JavaScript timers (HTML5 standard syntax).
&nbsp;|*|
&nbsp;|*|&nbsp; https://developer.mozilla.org/en-US/docs/DOM/window.setInterval
&nbsp;|*|
&nbsp;|*|&nbsp; Syntax:
&nbsp;|*|&nbsp; var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
&nbsp;|*|&nbsp; var timeoutID = window.setTimeout(code, delay);
&nbsp;|*|&nbsp; var intervalID = window.setInterval(func, delay[, param1, param2, ...]);
&nbsp;|*|&nbsp; var intervalID = window.setInterval(code, delay);
&nbsp;|*|
&nbsp;\*/
&nbsp;
&nbsp; if (document.all &amp;&amp; !window.setTimeout.isPolyfill) {
&nbsp;&nbsp;&nbsp; var __nativeST__ = window.setTimeout;
&nbsp;&nbsp;&nbsp; window.setTimeout = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var aArgs = Array.prototype.slice.call(arguments, 2);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return __nativeST__(vCallback instanceof Function ? function () {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vCallback.apply(null, aArgs);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } : vCallback, nDelay);
&nbsp;&nbsp;&nbsp; };
&nbsp;&nbsp;&nbsp; window.setTimeout.isPolyfill = true;
&nbsp; }
&nbsp; &nbsp;
&nbsp; if (document.all &amp;&amp; !window.setInterval.isPolyfill) {
&nbsp;&nbsp;&nbsp; var __nativeSI__ = window.setInterval;
&nbsp;&nbsp;&nbsp; window.setInterval = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var aArgs = Array.prototype.slice.call(arguments, 2);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return __nativeSI__(vCallback instanceof Function ? function () {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vCallback.apply(null, aArgs);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } : vCallback, nDelay);
&nbsp;&nbsp;&nbsp; };
&nbsp;&nbsp;&nbsp; window.setInterval.isPolyfill = true;
&nbsp; }</pre>
</div>
<h4>crazy.js</h4>
<div style="height: 500px; margin-bottom: 12px; overflow: auto;">
  <pre class="brush: js">
&nbsp;/*\
&nbsp;|*|
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *******************************
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; crazy.js&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *******************************
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; A JAVASCRIPT HIGLY SCALABLE DAEMONS MANAGER
&nbsp;|*|
&nbsp;|*|&nbsp; https://developer.mozilla.org/en-US/docs/DOM/window.setInterval
 |*|  https://developer.mozilla.org/User:fusionchess
&nbsp;|*|
 |*|  This framework is released under the GNU Public License, version 3 or later.
 |*|  http://www.gnu.org/licenses/gpl-3.0-standalone.html
 |*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Content of this file ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; The Daemon.crazy sub-system. This library requires "fork.js".
&nbsp;|*|&nbsp; Daemon.crazy constructor is as a dependent-clone of Daemon which uses a recursive invocation of the
&nbsp;|*|&nbsp; setTimeout() timer rather than a single invocation of setInterval().
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: The constructor ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; Syntax
&nbsp;|*|
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var myCrazyDaemon = new Daemon.crazy(@thisObject, @callback[, @length, @rate, @init, @onstart]);
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; Description
&nbsp;|*|
&nbsp;|*|&nbsp; Constructs a JavaScript Object containing all informations needed by an animation (see the Daemon
&nbsp;|*|&nbsp; constructor for details).
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; Arguments
&nbsp;|*|
&nbsp;|*|&nbsp; [the same as Daemon]
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Daemon.crazy global object properties ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.crazy.context -
&nbsp;|*|&nbsp; See: Daemon.context.
&nbsp;|*|&nbsp; This context will not used by default. It will be used the global Daemon.context instead.
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Daemon.crazy global object methods ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.crazy.forceCall(@daemonInstance) -
&nbsp;|*|&nbsp; See: Daemon.forceCall()
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.crazy.construct(@array_of_arguments) -
&nbsp;|*|&nbsp; See: Daemon.construct()
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.crazy.buildAround(@object) -
&nbsp;|*|&nbsp; See: Daemon.buildAround()
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.crazy.incorporate(@function) -
&nbsp;|*|&nbsp; See: Daemon.incorporate()
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Other constructors ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; - Daemon.crazy.blank -
&nbsp;|*|&nbsp; The same as Daemon.blank, but applied to the Daemon.crazy constructor.
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Daemon.crazy instances properties ::
&nbsp;|*|
&nbsp;|*|&nbsp; [inherited from Daemon.prototype]
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Daemon.crazy instances methods ::
&nbsp;|*|
&nbsp;|*|&nbsp; [inherited from Daemon.prototype]
&nbsp;|*|
&nbsp;\*/

"use strict";


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**************************************
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; THE CRAZY-DAEMON SUB-SYSTEM&nbsp;&nbsp;&nbsp;&nbsp; *
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; **************************************/



/* The "Daemon.crazy" constructor */

&nbsp; Daemon.crazy = function () { Daemon.apply(this, arguments); };

&nbsp;&nbsp;&nbsp; /* Create the Daemon.crazy.blank() constructor and the Daemon.crazy.context object */

&nbsp; Daemon.crazy.blank = function () {};
&nbsp; Daemon.HELLODARKNESSMYOLDFRIEND = Daemon.crazy.prototype;
&nbsp; Daemon.crazy.context = Daemon.crazy.blank.prototype; /* Make love with the GC :-) */
&nbsp; Daemon.crazy.blank.prototype = /* Important! */ Daemon.crazy.prototype = /* Important! */ new Daemon.blank();
&nbsp; Daemon.crazy.prototype.constructor = Daemon.crazy;
&nbsp; Daemon.HELLODARKNESSMYOLDFRIEND.constructor = Daemon.crazy.context.constructor = Object;


/* SYSTEM REQUIRED Daemon.crazy global object methods */

&nbsp; Daemon.crazy.forceCall = function (oDmn) {

&nbsp;&nbsp;&nbsp; oDmn.INDEX += oDmn.BACKW ? -1 : 1;

&nbsp;&nbsp;&nbsp; var
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bBreak = oDmn.task.call(oDmn.owner, oDmn.INDEX, oDmn.length, oDmn.BACKW) === false,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bEnd = oDmn.isAtEnd(), bInvert = oDmn.reversals &gt; 0;

&nbsp;&nbsp;&nbsp; if (bEnd &amp;&amp; !bInvert || bBreak) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oDmn.PAUSED = true;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; if (bEnd &amp;&amp; bInvert) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oDmn.BACKW = !oDmn.BACKW;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oDmn.reversals--;
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; oDmn.synchronize();

&nbsp;&nbsp;&nbsp; return true;

&nbsp; };


/* SYSTEM NOT REQUIRED Daemon.crazy global object methods */

&nbsp; /**
&nbsp; * Daemon.crazy global object optional methods (shortcurts). You could safely remove all or some of
&nbsp; * them, depending on your needs.
&nbsp; **/

&nbsp;&nbsp;&nbsp; /* Warnign: this method requires the global Daemon.construct() method */
&nbsp; Daemon.crazy.construct = Daemon.construct;

&nbsp;&nbsp;&nbsp; /* Warnign: this method requires the global Daemon.buildAround() method */
&nbsp; Daemon.crazy.buildAround = Daemon.buildAround;

&nbsp;&nbsp;&nbsp; /* Warnign: this method requires the global Daemon.incorporate() method */
&nbsp; Daemon.crazy.incorporate = Daemon.incorporate;


/* SYSTEM REQUIRED Daemon.crazy instances methods */

&nbsp; Daemon.crazy.prototype.synchronize = function () {
&nbsp;&nbsp;&nbsp; if (this.PAUSED) { return; }
&nbsp;&nbsp;&nbsp; clearTimeout(this.SESSION);
&nbsp;&nbsp;&nbsp; this.SESSION = setTimeout(Daemon.crazy.forceCall, this.rate, this);
&nbsp; };

&nbsp; Daemon.crazy.prototype.pause = function () {
&nbsp;&nbsp;&nbsp; clearTimeout(this.SESSION);
&nbsp;&nbsp;&nbsp; this.PAUSED = true;
&nbsp; };


/* SYSTEM NOT REQUIRED Daemon.crazy instances methods */

&nbsp; /* [inherited from Daemon.prototype] */



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*****************************************
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; THE CRAZY-DAEMON IS NOW READY!&nbsp;&nbsp;&nbsp;&nbsp; *
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *****************************************/</pre>
</div>
<h4>methods.js</h4>
<div style="height: 500px; margin-bottom: 12px; overflow: auto;">
  <pre class="brush: js">
&nbsp;/*\
&nbsp;|*|
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *******************************
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; daemon.js&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *
&nbsp;|*|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *******************************
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; A JAVASCRIPT HIGLY SCALABLE DAEMONS MANAGER
&nbsp;|*|
&nbsp;|*|&nbsp; https://developer.mozilla.org/en-US/docs/DOM/window.setInterval
 |*|  https://developer.mozilla.org/User:fusionchess
 |*|
 |*|  This framework is released under the GNU Public License, version 3 or later.
 |*|  http://www.gnu.org/licenses/gpl-3.0-standalone.html
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Content of this file ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; Additional methods for Daemon instances. This library requires "daemon.js".
&nbsp;|*|&nbsp; You can safely remove all or some of these methods, depending on your needs.
&nbsp;|*|&nbsp; When a method requires the presence of another method (it is relatively rare) there is a comment
&nbsp;|*|&nbsp; which explains it. If there are not comments to that method it depends only on the base system.
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; :: Daemon instances methods ::
&nbsp;|*|
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.stop() -
&nbsp;|*|&nbsp; Stops the daemon. All original properties will be restored. If it exists a "stop" listener it will
&nbsp;|*|&nbsp; be called with three arguments: @index (the index of the last invocation), @length (the number of
&nbsp;|*|&nbsp; total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing
&nbsp;|*|&nbsp; whether the @index of the last execution was decreasing or not).
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.syncStart([@backwards]) -
&nbsp;|*|&nbsp; Starts the daemon with the first callback synchronous.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.play([@synchronous]) -
&nbsp;|*|&nbsp; Starts the daemon forward. If the daemon is running in the same direction nothing will happen.
&nbsp;|*|&nbsp; If the argument is "true" the first callback will be synchronous.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.reversePlay([@synchronous]) -
&nbsp;|*|&nbsp; Starts the daemon backwards. If the daemon is running in the same direction nothing will happen.
&nbsp;|*|&nbsp; If the argument is "true" the first callback will be synchronous.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.move([@synchronous, @reversals, @backwards]) -
&nbsp;|*|&nbsp; Starts a daemon synchronously or not.
&nbsp;|*|&nbsp; If the @reversals argument is specified the myDaemon.reversals property will be setted on it.
&nbsp;|*|&nbsp; If the @bacwards argument is specified the daemon will move forward (false) or backwards (true). If
&nbsp;|*|&nbsp; it is not specified the daemon will start in the same direction in which it has been left. If the
&nbsp;|*|&nbsp; daemon was running in the same direction, only the reversals property will be possibly updated.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.turn() -
&nbsp;|*|&nbsp; Inverts the direction of the daemon. The reversals property will not be decreased.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.makeLoop() -
&nbsp;|*|&nbsp; Sets the reversals property to Infinity.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.unmakeLoop() -
&nbsp;|*|&nbsp; Sets the reversals property to 0.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.setRate(@milliseconds) -
&nbsp;|*|&nbsp; Sets the time lapse between calls (in milliseconds). If the daemon is running it will be immediately
&nbsp;|*|&nbsp; updated with the new property.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.forcePosition(@index) -
&nbsp;|*|&nbsp; Sets the internal INDEX property equal to the @index argument without control about the range.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.getDuration() -
&nbsp;|*|&nbsp; Returns the duration of the daemon in milliseconds.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.getPosition() -
&nbsp;|*|&nbsp; Returns the internal INDEX property.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.makeSteps(@howmany[, @backwards, @force]) -
&nbsp;|*|&nbsp; Calls synchronously the callback function @howmany times. Forwards or backwards. If the argument
&nbsp;|*|&nbsp; @force is setted to"true" the possible "return false" of the callback function will be ignored.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.skipTo(@index[, @force]) -
&nbsp;|*|&nbsp; Calls synchronously the callback function the number of times needed to reach the @index position.
&nbsp;|*|&nbsp; If the argument @force is setted to"true" the possible "return false" of the callback function will
&nbsp;|*|&nbsp; be ignored.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.skipFor(@delta[, @force]) -
&nbsp;|*|&nbsp; Calls synchronously the callback function @howmany times in the same direction in which it was
&nbsp;|*|&nbsp; oriented. If the argument @force is setted to"true" the possible "return false" of the callback
&nbsp;|*|&nbsp; function will be ignored.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.close([@backwards, @force]) -
&nbsp;|*|&nbsp; Closes the daemon, doing SYNCHRONOUSLY all pending operations forward (index of each invocation
&nbsp;|*|&nbsp; increasing) or backwards (index decreasing). If the argument @force is setted to "true" the
&nbsp;|*|&nbsp; possible "return false" of the callback function will be ignored.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.reclose([@force]) -
&nbsp;|*|&nbsp; Closes the daemon, doing SYNCHRONOUSLY all pending operations in the same direction in which is
&nbsp;|*|&nbsp; oriented the daemon. If the argument @force is setted to"true" the possible "return false" of the
&nbsp;|*|&nbsp; callback function will be ignored.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.restart() -
&nbsp;|*|&nbsp; Stops and restarts the daemon.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.loopUntil(@date) -
&nbsp;|*|&nbsp; Sets the reversals property in function of a future @date. The @date can be a Date object, a String
&nbsp;|*|&nbsp; expressing the date in GMTString format, or a Number expressing the number of milliseconds since
&nbsp;|*|&nbsp; January 1, 1970, 00:00:00 UTC.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.spread(@milliseconds) -
&nbsp;|*|&nbsp; Sets the the total duration of the daemon in milliseconds. Only the rate property will be modified.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.adaptLength(@milliseconds) -
&nbsp;|*|&nbsp; Sets the internal length property equal to milliseconds/rate.
&nbsp;|*|
&nbsp;|*|&nbsp; - myDaemon.playUntil(@date) -
&nbsp;|*|&nbsp; Starts the daemon forward and sets the the total duration of it in function of a future date. The
&nbsp;|*|&nbsp; @date can be a Date object, a String expressing the date in GMTString format, or a Number expressing
&nbsp;|*|&nbsp; the number of milliseconds since January 1, 1970, 00:00:00 UTC. Only the length property will be
&nbsp;|*|&nbsp; modified.
&nbsp;|*|
&nbsp;\*/

"use strict";


/* SYSTEM NOT REQUIRED Daemon instances methods */

&nbsp;&nbsp;&nbsp; /* Status */

&nbsp; Daemon.prototype.stop = function () {
&nbsp;&nbsp;&nbsp; this.pause();
&nbsp;&nbsp;&nbsp; if (this.onstop) { this.onstop.call(this.owner, this.INDEX, this.length, this.BACKW); }
&nbsp;&nbsp;&nbsp; delete this.INDEX;
&nbsp;&nbsp;&nbsp; delete this.BACKW;
&nbsp;&nbsp;&nbsp; delete this.reversals;
&nbsp; };

&nbsp;&nbsp;&nbsp; /* Movement */

&nbsp; Daemon.prototype.syncStart = function (bReverse) {
&nbsp;&nbsp;&nbsp; this.synchronize();
&nbsp;&nbsp;&nbsp; if (this.start(bReverse || false)) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Daemon.forceCall(this);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; return false;
&nbsp; };

&nbsp; Daemon.prototype.play = function (bSync) {
&nbsp;&nbsp;&nbsp; /* Warnign: this method OPTIONALLY requires the Daemon.prototype.syncStart() method */
&nbsp;&nbsp;&nbsp; return this[bSync ? "start" : "syncStart"]();
&nbsp; };

&nbsp; Daemon.prototype.reversePlay = function (bSync) {
&nbsp;&nbsp;&nbsp; /* Warnign: this method OPTIONALLY requires the Daemon.prototype.syncStart() method */
&nbsp;&nbsp;&nbsp; return this[bSync ? "start" : "syncStart"](true);
&nbsp; };

&nbsp; Daemon.prototype.move = function (bSync, nCycles, bDirection) {
&nbsp;&nbsp;&nbsp; /* Warnign: this method OPTIONALLY requires the Daemon.prototype.syncStart() method */
&nbsp;&nbsp;&nbsp; if (arguments.length &gt; 1 &amp;&amp; !isNaN(nCycles)) { this.reversals = Number(nCycles); }
&nbsp;&nbsp;&nbsp; this[bSync ? "start" : "syncStart"](arguments.length &gt; 2 ? bDirection : this.isAtEnd() !== this.BACKW);
&nbsp; };

&nbsp; Daemon.prototype.turn = function (bSync) {
&nbsp;&nbsp;&nbsp; /* Warnign: this method OPTIONALLY requires the Daemon.prototype.syncStart() method */
&nbsp;&nbsp;&nbsp; this[bSync ? "start" : "syncStart"](!this.BACKW);
&nbsp; };

&nbsp;&nbsp;&nbsp; /* Settings tools */

&nbsp; Daemon.prototype.makeLoop = function () {
&nbsp;&nbsp;&nbsp; this.reversals = Infinity;
&nbsp; };

&nbsp; Daemon.prototype.unmakeLoop = function () {
&nbsp;&nbsp;&nbsp; this.reversals = 0;
&nbsp; };

&nbsp; Daemon.prototype.setRate = function (vTo) {
&nbsp;&nbsp;&nbsp; var nRate = Number(vTo);
&nbsp;&nbsp;&nbsp; if (!isFinite(nRate) || nRate &lt; 1) { return; }
&nbsp;&nbsp;&nbsp; this.rate = nRate;
&nbsp;&nbsp;&nbsp; this.synchronize();
&nbsp; };

&nbsp; Daemon.prototype.forcePosition = function (vTo) {
&nbsp;&nbsp;&nbsp; if (isFinite(vTo)) { this.INDEX = Math.round(Math.abs(vTo)); }
&nbsp; };

&nbsp; Daemon.prototype.getDuration = function () {
&nbsp;&nbsp;&nbsp; return this.rate * this.length;
&nbsp; };

&nbsp; Daemon.prototype.getDirection = function () {
&nbsp;&nbsp;&nbsp; return this.isAtEnd() !== this.BACKW;
&nbsp; };

&nbsp; Daemon.prototype.getPosition = function () {
&nbsp;&nbsp;&nbsp; return this.INDEX;
&nbsp; };

&nbsp;&nbsp;&nbsp; /* Instantaneous movement (synchronous). */

&nbsp; Daemon.prototype.makeSteps = function (nHowMany, bReverse, bForce) {
&nbsp;&nbsp;&nbsp; if (nHowMany === 0) { return true; }
&nbsp;&nbsp;&nbsp; if (isNaN(nHowMany)) { return false; }
&nbsp;&nbsp;&nbsp; var nIdx = 0, nLen = Math.round(Math.abs(nHowMany)), bContinue = true, bBackw = nHowMany &gt; 0 === Boolean(bReverse);
&nbsp;&nbsp;&nbsp; this.BACKW = bBackw;
&nbsp;&nbsp;&nbsp; for (nIdx; nIdx &lt; nLen &amp;&amp; bContinue; nIdx++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this.BACKW === bBackw &amp;&amp; this.isAtEnd()) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this.reversals &gt; 0) { this.BACKW = bBackw = !this.BACKW; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else { break; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bContinue = Daemon.forceCall(this) || bForce;
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; return nIdx === nLen;
&nbsp; };

&nbsp; Daemon.prototype.skipTo = function (nIdx, bForce) {
&nbsp;&nbsp;&nbsp; /* Warnign: this method requires the Daemon.prototype.makeSteps() method */
&nbsp;&nbsp;&nbsp; if (nIdx === this.INDEX) { return; }
&nbsp;&nbsp;&nbsp; if (isFinite(this.length) &amp;&amp; nIdx &lt; 0 || nIdx &gt; this.length) { return; }

&nbsp;&nbsp;&nbsp; var
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bDirection = (this.INDEX !== 0 &amp;&amp; this.INDEX !== this.length) === this.BACKW,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bSuccess = this.makeSteps(this.INDEX - nIdx, true, bForce);

&nbsp;&nbsp;&nbsp; if (this.INDEX !== 0 &amp;&amp; this.INDEX !== this.length) { this.BACKW = bDirection; }
&nbsp;&nbsp;&nbsp; return bSuccess;
&nbsp; };

&nbsp; Daemon.prototype.skipFor = function (nDelta, bForce) {
&nbsp;&nbsp;&nbsp; /* Warnign: this method requires the Daemon.prototype.makeSteps() method */
&nbsp;&nbsp;&nbsp; return this.makeSteps(nDelta, this.isAtEnd() !== this.BACKW, bForce);
&nbsp; };

&nbsp; Daemon.prototype.close = function (bReverse, bForce) {
&nbsp;&nbsp;&nbsp; /* Warnign: this method requires the Daemon.prototype.makeSteps() method */
&nbsp;&nbsp;&nbsp; if (!isFinite(this.length)) { return false; }
&nbsp;&nbsp;&nbsp; this.pause();
&nbsp;&nbsp;&nbsp; this.reversals = 0;
&nbsp;&nbsp;&nbsp; return this.makeSteps(bReverse ? this.INDEX : this.length - this.INDEX, bReverse, bForce);
&nbsp; };

&nbsp; Daemon.prototype.reclose = function (bForce) {
&nbsp;&nbsp;&nbsp; /* Warnign: this method requires the Daemon.prototype.makeSteps() and Daemon.prototype.close() methods */
&nbsp;&nbsp;&nbsp; return this.close(this.isAtEnd() !== this.BACKW, bForce || false);
&nbsp; };

&nbsp; /* Others */

&nbsp; Daemon.prototype.restart = function () {
&nbsp;&nbsp;&nbsp; this.stop();
&nbsp;&nbsp;&nbsp; this.start();
&nbsp; };

&nbsp; Daemon.prototype.loopUntil = function (vDate) {
&nbsp;&nbsp;&nbsp; if (!isFinite(this.length)) { return; }
&nbsp;&nbsp;&nbsp; var nTime = vDate.constructor === Date ? vDate.getTime() : isNaN(vDate) ? Date.parse(vDate) : vDate;
&nbsp;&nbsp;&nbsp; if (isFinite(nTime) &amp;&amp; nTime &gt; Date.now()) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.reversals = Math.floor((nTime - Date.now() - (this.BACKW ? this.INDEX : this.length - this.INDEX) * this.rate) / (this.length * this.rate));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.start(this.isAtEnd() !== this.BACKW);
&nbsp;&nbsp;&nbsp; }
&nbsp; };

&nbsp; Daemon.prototype.spread = function (nTime) {
&nbsp;&nbsp;&nbsp; if (!isFinite(this.length)) { throw new TypeError("Daemon.prototype.spread - the length is not a finite number. Use Daemon.prototype.adaptLength()."); }
&nbsp;&nbsp;&nbsp; if (nTime &gt; 0) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.rate = Math.floor(nTime / this.length);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.synchronize();
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; return this.rate;
&nbsp; };

&nbsp; Daemon.prototype.adaptLength = function (nTime) {
&nbsp;&nbsp;&nbsp; this.length = Math.floor(nTime / this.rate);
&nbsp;&nbsp;&nbsp; return this.length;
&nbsp; };

&nbsp; Daemon.prototype.playUntil = function (vDate) {
&nbsp;&nbsp;&nbsp; var nTime = vDate.constructor === Date ? vDate.getTime() : isNaN(vDate) ? Date.parse(vDate) : vDate;
&nbsp;&nbsp;&nbsp; if (isFinite(nTime) &amp;&amp; nTime &gt; Date.now()) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.length = Math.floor((nTime - Date.now()) / this.rate) + this.INDEX;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.pause();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.start();
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; return this.length;
&nbsp; };</pre>
</div>
<h2>The manual</h2>
<h3>The constructor</h3>
<h4>Syntax</h4>
<pre>
var myDaemon = new Daemon(@thisObject, @callback[, @length, @rate, @init, @onstart]);</pre>
<h4>Description</h4>
<p>Constructs a JavaScript Object containing all informations needed by an animation (like the "this" object, the callback function, the length, the frame-rate, the number of cycles, the "init" and the "onstart" functions).</p>
<h4>Arguments</h4>
<dl>
  <dt>
    @thisObject</dt>
  <dd>
    The "this" object on which will be called the callback function. It can be an object or null. If is null, the "this" object will point to the global "Deamon.context" object (see below).</dd>
  <dt>
    @callback</dt>
  <dd>
    The function which will be invoked repeatedly. It will be called with three parameters: @index (the iterative index of each invocation), @length (the number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing whether the process is going backwards or not). It will be something like @callback.call(@thisObject, @index, @length, @backwards). If the @callback function returns a "false" value the Daemon will be paused.</dd>
  <dt>
    @length (optional)</dt>
  <dd>
    The total number of invocations. It can be a positive integer or Infinity. The default value is Infinity.</dd>
  <dt>
    @rate (optional)</dt>
  <dd>
    The time lapse (in number of milliseconds) between each invocation. The default value is 100.</dd>
  <dt>
    @init (optional)</dt>
  <dd>
    The function which will be synchronously invoked once during the creation of the daemon and then assigned to the "onstop" property. It will be called with the same three arguments of the @callback function. They will also have the same values of the last invocation of the @callback function.</dd>
  <dt>
    @onstart</dt>
  <dd>
    The function which will be synchronously invoked on whenever the "start" event occurs. It will be assigned to the "onstart" property. It will be called with three arguments: @index (the actual index), @length (the number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing whether the @index will go decreasing or not).</dd>
</dl>
<h3>Daemon global object properties</h3>
<dl>
  <dt>
    Daemon.context</dt>
  <dd>
    An empty object used as default *this* object when the @thisObject is not specified during the construction of the daemon. If you want your callback function to be invoked with a "null" *this* object you have to manually set the "owner" property to "null".</dd>
</dl>
<h3>Daemon global object methods</h3>
<dl>
  <dt>
    Daemon.forceCall(@daemonInstance)</dt>
  <dd>
    Forces a callback to the @daemonInstance.task function regardless of the fact that the end has been reached or not. In any case the internal "INDEX" property will be increased/decreased (depending on the actual direction of the daemon).</dd>
  <dt>
    Daemon.construct(@array_of_arguments)</dt>
  <dd>
    Returns a new daemon constructed upon an array of arguments. It is very similar to the Function.prototype.apply() method.</dd>
  <dt>
    Daemon.buildAround(@context[, @length, @rate])</dt>
  <dd>
    Returns a new daemon built around a @context object. The @context object must cointain *at least* a "perform" property pointing to what you want to be the @callback function of the daemon. It can also optionally contain a "create" and a "prepare" properties pointing respectively the two functions you want to be the @init and @onstart functions of Daemon constructor's arguments. The @context object will be also the *this* object of your callback function. So you can populate it with all your custom properties. and methods. The only required one property is "perform".
    <h5>Sample usage:</h5>
    <pre>
var myDaemon = Daemon.buildAround({
	"create": function () { [custom code] },  // optional
	"prepare": function () { [custom code] },  // optional
	"perform": function () { [custom code] },  // required
	"customProperty": [custom value],
	"myCustomMethod": function () { [custom code] },
	"anotherCustomProperty": [custom value],
	"etc.": "etc."
}, 30, 200);
</pre>
  </dd>
  <dt>
    Daemon.incorporate(@function)</dt>
  <dd>
    The @function.prototype property will replaced with a *new Daemon()* object. The old replaced prototype will be preserved within a new property of the new @function.prototype named "legacy".</dd>
</dl>
<h3>Other constructors</h3>
<dl>
  <dt>
    Daemon.blank</dt>
  <dd>
    Constructs a new instance of Daemon without own properties. This constructor is useful in order to create your own *MySomeDaemon* constructors through the *MySomeDaemon.prototype = new Daemon.blank();* assignment.</dd>
  <dt>
    Daemon.crazy [optional module crazy.js]</dt>
  <dd>
    A clone of the Daemon constructor based on setTimeout rather than on setInterval. See the Daemon.crazy module for details. NOTE: The Daemon.crazy constructor is not part of the base system.</dd>
  <dt>
    Daemon.crazy.blank [optional module crazy.js]</dt>
  <dd>
    The same as for Daemon.blank, but applied to the Daemon.crazy constructor. NOTE: The Daemon.crazy constructor is not part of the base system.</dd>
</dl>
<h3>Daemon instances properties</h3>
<dl>
  <dt>
    myDaemon.owner</dt>
  <dd>
    The "this" object on which is executed the daemon (read/write). It can be an object or null. Its default value is Daemon.context.</dd>
  <dt>
    myDaemon.task</dt>
  <dd>
    The function which will be repeatedly invoked (read/write). It will be called with three arguments: @index (the iterative index of each invocation), @length (the number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing whether the @index is decreasing or not). See above. If the myDaemon.task function returns a "false" the Daemon will be paused.</dd>
  <dt>
    myDaemon.length</dt>
  <dd>
    The total number of invocations. It can be a positive integer or Infinity (read/write).</dd>
  <dt>
    myDaemon.rate</dt>
  <dd>
    The time lapse (in number of milliseconds) between each invocation (read/write).</dd>
  <dt>
    myDaemon.reversals</dt>
  <dd>
    Blabla (read/write).</dd>
  <dt>
    myDaemon.onstart</dt>
  <dd>
    The "start" listener (read/write). It will be called with three arguments: @index (the actual index), @length (the number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing whether the @index will go decreasing or not).</dd>
  <dt>
    myDaemon.onstop</dt>
  <dd>
    The "stop" listener (read/write). It will be called with three arguments: @index (the index of the last invocation), @length (the number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing whether the @index of the last execution was decreasing or not). NOTE: The stop() method is not part of the base system.</dd>
</dl>
<h3>Daemon instances methods</h3>
<dl>
  <dt>
    myDaemon.isAtEnd()</dt>
  <dd>
    Returns a boolean expressing whether the daemon is at the start/end position or not.</dd>
  <dt>
    myDaemon.synchronize()</dt>
  <dd>
    Synchronize the timer of a started daemon with the time of invocation of myDaemon.synchronize(). If the rate property has been changed the daemon will be updated with the new rate value.</dd>
  <dt>
    myDaemon.pause()</dt>
  <dd>
    Pauses the daemon.</dd>
  <dt>
    myDaemon.start([@backwards])</dt>
  <dd>
    Starts the daemon forward (index of each invocation increasing) or backwards (index decreasing).</dd>
</dl>
<p>methods.js</p>
<h3>Additional instances methods [optional module methods.js]</h3>
<dl>
  <dt>
    myDaemon.stop()</dt>
  <dd>
    Stops the daemon. All original properties will be restored. If it exists a "stop" listener it will be called with three arguments: @index (the index of the last invocation), @length (the number of total invocations assigned to the daemon - finite or Infinity) and @backwards (a boolean expressing whether the @index of the last execution was decreasing or not).</dd>
  <dt>
    myDaemon.syncStart([@backwards])</dt>
  <dd>
    Starts the daemon with the first callback synchronous.</dd>
  <dt>
    myDaemon.play([@synchronous])</dt>
  <dd>
    Starts the daemon forward. If the daemon is running in the same direction nothing will happen. If the argument is "true" the first callback will be synchronous.</dd>
  <dt>
    myDaemon.reversePlay([@synchronous])</dt>
  <dd>
    Starts the daemon backwards. If the daemon is running in the same direction nothing will happen. If the argument is "true" the first callback will be synchronous.</dd>
  <dt>
    myDaemon.move([@synchronous, @reversals, @backwards])</dt>
  <dd>
    Starts a daemon synchronously or not. If the @reversals argument is specified the myDaemon.reversals property will be setted on it. If the @bacwards argument is specified the daemon will move forward (false) or backwards (true). If it is not specified the daemon will start in the same direction in which it has been left. If the daemon was running in the same direction, only the reversals property will be possibly updated.</dd>
  <dt>
    myDaemon.turn()</dt>
  <dd>
    Inverts the direction of the daemon. The reversals property will not be decreased.</dd>
  <dt>
    myDaemon.makeLoop()</dt>
  <dd>
    Sets the reversals property to Infinity.</dd>
  <dt>
    myDaemon.unmakeLoop()</dt>
  <dd>
    Sets the reversals property to 0.</dd>
  <dt>
    myDaemon.setRate(@milliseconds)</dt>
  <dd>
    Sets the time lapse between calls (in milliseconds). If the daemon is running it will be immediately updated with the new property.</dd>
  <dt>
    myDaemon.forcePosition(@index)</dt>
  <dd>
    Sets the internal INDEX property equal to the @index argument without control about the range.</dd>
  <dt>
    myDaemon.getDuration()</dt>
  <dd>
    Returns the duration of the daemon in milliseconds.</dd>
  <dt>
    myDaemon.getPosition()</dt>
  <dd>
    Returns the internal INDEX property.</dd>
  <dt>
    myDaemon.makeSteps(@howmany[, @backwards, @force])</dt>
  <dd>
    Calls synchronously the callback function @howmany times. Forwards or backwards. If the argument @force is setted to"true" the possible "return false" of the callback function will be ignored.</dd>
  <dt>
    myDaemon.skipTo(@index[, @force])</dt>
  <dd>
    Calls synchronously the callback function the number of times needed to reach the @index position. If the argument @force is setted to"true" the possible "return false" of the callback function will be ignored.</dd>
  <dt>
    myDaemon.skipFor(@delta[, @force])</dt>
  <dd>
    Calls synchronously the callback function @howmany times in the same direction in which it was oriented. If the argument @force is setted to"true" the possible "return false" of the callback function will be ignored.</dd>
  <dt>
    myDaemon.close([@backwards, @force])</dt>
  <dd>
    Closes the daemon, doing SYNCHRONOUSLY all pending operations forward (index of each invocation increasing) or backwards (index decreasing). If the argument @force is setted to "true" the possible "return false" of the callback function will be ignored.</dd>
  <dt>
    myDaemon.reclose([@force])</dt>
  <dd>
    Closes the daemon, doing SYNCHRONOUSLY all pending operations in the same direction in which is oriented the daemon. If the argument @force is setted to"true" the possible "return false" of the callback function will be ignored.</dd>
  <dt>
    myDaemon.restart()</dt>
  <dd>
    Stops and restarts the daemon.</dd>
  <dt>
    myDaemon.loopUntil(@date)</dt>
  <dd>
    Sets the reversals property in function of a future @date. The @date can be a Date object, a String expressing the date in GMTString format, or a Number expressing the number of milliseconds since January 1, 1970, 00:00:00 UTC.</dd>
  <dt>
    myDaemon.spread(@milliseconds)</dt>
  <dd>
    Sets the the total duration of the daemon in milliseconds. Only the rate property will be modified.</dd>
  <dt>
    myDaemon.adaptLength(@milliseconds)</dt>
  <dd>
    Sets the internal length property equal to milliseconds/rate.</dd>
  <dt>
    myDaemon.playUntil(@date)</dt>
  <dd>
    Starts the daemon forward and sets the the total duration of it in function of a future date. The @date can be a Date object, a String expressing the date in GMTString format, or a Number expressing the number of milliseconds since January 1, 1970, 00:00:00 UTC. Only the length property will be modified.</dd>
</dl>
<p>This page is under construction</p>
Revert to this revision