TriggerManager:

Copyright(c) 2012 Stefano Balietti MIT Licensed

Manages a collection of trigger functions to be called sequentially

Note for developers

Triggers are functions that operate on a common object, and each sequentially adds further modifications to it.

If the TriggerManager were a beauty saloon, the first trigger function would wash the hair, the second would cut the washed hair, and the third would style it. All these operations needs to be done sequentially, and the TriggerManager takes care of handling this process.

If TriggerManager.returnAt is set equal to TriggerManager.first, the first trigger function returning a truthy value will stop the process and the target object will be immediately returned. In these settings, if a trigger function returns undefined, the target is passed to the next trigger function.

Notice: TriggerManager works as a LIFO queue, i.e. new trigger functions will be executed first.


(function(exports, node){

Global scope

  
exports.TriggerManager = TriggerManager;

TriggerManager.first = 'first';
TriggerManager.last = 'last';

TriggerManager constructor

Creates a new instance of TriggerManager

function TriggerManager (options) {

Public properties

  
  

TriggerManager.triggers

Array of trigger functions

this.triggers = [];
  

Public properties

TriggerManager.options

Reference to current configuration

  this.options = options || {};

TriggerManager.returnAt

Controls the behavior of TriggerManager.pullTriggers

By default it is equal to TriggerManager.first

  var returnAt = TriggerManager.first;
  Object.defineProperty(this, 'returnAt', {
    set: function(at){
      if (!at || (at !== TriggerManager.first && at !== TriggerManager.last)) {
        node.log('Invalid returnAt type: ' + at);
        return false;
      }
      returnAt = at;
      return at;
    },
    get: function(){
      return returnAt;
    },
    configurable: true,
    enumerable: true
  });

TriggerManager.length

The number of registered trigger functions

  Object.defineProperty(this, 'length', {
    set: function(){},
    get: function(){
      return this.triggers.length;
    },
    configurable: true
  });
  
  this.init();
};

TriggerManager methods

TriggerManager.init

Configures the TriggerManager instance

Takes the configuration as an input parameter or recycles the settings in this.options.

The configuration object is of the type

var options = { returnAt: 'first', // or 'last' triggers: [ myFunc, myFunc2 ], }

Params
options object Optional. Configuration object
TriggerManager.prototype.init = function (options) {
  this.options = options || this.options;
  if (this.options.returnAt === TriggerManager.first || this.options.returnAt === TriggerManager.last) {
    this.returnAt = this.options.returnAt;
  }
  this.resetTriggers();
};

TriggerManager.initTriggers

Adds a collection of trigger functions to the trigger array

Params
triggers function array An array of trigger functions or a single function
TriggerManager.prototype.initTriggers = function (triggers) {
  if (!triggers) return;
  if (!(triggers instanceof Array)) {
    triggers = [triggers];
  }
  for (var i=0; i< triggers.length; i++) {
    this.triggers.push(triggers[i]);
  }
  };
  

TriggerManager.resetTriggers

Resets the trigger array to initial configuration

Delete existing trigger functions and re-add the ones contained in TriggerManager.options.triggers

TriggerManager.prototype.resetTriggers = function () {
  this.triggers = [];
  this.initTriggers(this.options.triggers);
};

TriggerManager.clear

Clears the trigger array

Requires a boolean parameter to be passed for confirmation

Params
clear boolean TRUE, to confirm clearing
Returns
boolean TRUE, if clearing was successful
TriggerManager.prototype.clear = function (clear) {
  if (!clear) {
    node.log('Do you really want to clear the current TriggerManager obj? Please use clear(true)', 'WARN');
    return false;
  }
  this.triggers = [];
  return clear;
};
  

TriggerManager.addTrigger

Pushes a trigger into the trigger array

Params
trigger function The function to add
pos number Optional. The index of the trigger in the array
Returns
boolean TRUE, if insertion is successful
TriggerManager.prototype.addTrigger = function (trigger, pos) {
  if (!trigger) return false;
  if (!('function' === typeof trigger)) return false;
  if (!pos) {
    this.triggers.push(trigger);
  }
  else {
    this.triggers.splice(pos, 0, trigger);
  }
  return true;
};
    

TriggerManager.removeTrigger

Removes a trigger from the trigger array

Params
trigger function The function to remove
Returns
boolean TRUE, if removal is successful
TriggerManager.prototype.removeTrigger = function (trigger) {
  if (!trigger) return false;
  for (var i=0; i< this.triggers.length; i++) {
    if (this.triggers[i] == trigger) {
      return this.triggers.splice(i,1);
    }
  }  
  return false;
};

TriggerManager.pullTriggers

Fires the collection of trigger functions on the target object

Triggers are fired according to a LIFO queue, i.e. new trigger functions are fired first.

Depending on the value of TriggerManager.returnAt, some trigger functions may not be called. In fact a value is returned

  • 'first': after the first trigger returns a truthy value
  • 'last': after all triggers have been executed

If no trigger is registered the target object is returned unchanged

Params
o object The target object
Returns
object The target object after the triggers have been fired
TriggerManager.prototype.pullTriggers = function (o) {
  if ('undefined' === typeof o) return;
  if (!this.length) return o;
  
  for (var i = this.triggers.length; i > 0; i--) {
    var out = this.triggers[(i-1)].call(this, o);
    if ('undefined' !== typeof out) {
      if (this.returnAt === TriggerManager.first) {
        return out;
      }
    }
  }

Safety return

  return ('undefined' !== typeof out) ? out : o;
};

TriggerManager.size

Returns the number of registered trigger functions

Use TriggerManager.length instead

TriggerManager.prototype.size = function () {
  return this.triggers.length;
};
  

Closure

})(
  ('undefined' !== typeof node) ? node : module.exports
  , ('undefined' !== typeof node) ? node : module.parent.exports
);