API Docs for: 1.0.0
Show:

File: src/gallery-instancemanager/js/InstanceManager.js

"use strict";

/**
 * @module gallery-instancemanager
 */

/**********************************************************************
 * <p>Stores instances of JavaScript components.  Allows a constructor or
 * factory method to be passed in place of an instance.  This enables lazy
 * construction on demand.</p>
 * 
 * <p>One use is to create a global repository of JavaScript components
 * attached to DOM id's, e.g., YUI Buttons built on top of HTML
 * buttons.</p>
 * 
 * @main gallery-instancemanager
 * @class InstanceManager
 * @constructor
 */
function InstanceManager()
{
	this._map          = { };
	this._constructors = { };
}

InstanceManager.prototype =
{
	/**
	 * Retrieve an object.
	 * 
	 * @method get
	 * @param id {String} the id of the object to retrieve
	 * @return {Mixed} the stored object, or false if the slot is empty
	 */
	get: function(
		/* string */	id)
	{
		if (this._map[ id ] === null && this._constructors[ id ])
		{
			var c           = this._constructors[ id ];
			var instance    = c.fn.prototype ? Y.Object(c.fn.prototype) : null;
			var obj         = c.fn.apply(instance, c.args);
			this._map[ id ] = Y.Lang.isUndefined(obj) ? instance : obj;
		}

		return this._map[ id ] || false;
	},

	/**
	 * Retrieve an object only if it has already been constructed.
	 * 
	 * @method getIfConstructed
	 * @param id {String} the id of the object to retrieve
	 * @return {Mixed} the stored object, or false if the slot is empty
	 */
	getIfConstructed: function(
		/* string */	id)
	{
		return this._map[ id ] || false;
	},

	/**
	 * Store an object or ctor+args.
	 * 
	 * @method put
	 * @param id {String} the id of the object
	 * @param objOrCtor {Object|Function} the object or the object's constructor or a factory method
	 * @param args {Array} the array of arguments to pass to the constructor
	 * @return {Boolean} false if the id has already been used
	 */
	put: function(
		/* string */	id,
		/* obj/fn */	objOrCtor,
		/* array */		args)
	{
		if (this._map[ id ])
		{
			return false;
		}
		else if (Y.Lang.isFunction(objOrCtor))
		{
			this._constructors[ id ] =
			{
				fn:   objOrCtor,
				args: Y.Lang.isArray(args) ? args : [args]
			};

			this._map[ id ] = null;
			return true;
		}
		else
		{
			this._map[ id ] = objOrCtor;
			return true;
		}
	},

	/**
	 * Remove an object.
	 * 
	 * @method remove
	 * @param id {String} the id of the object
	 * @return {mixed} the object that was removed, or false if the slot was empty
	 */
	remove: function(
		/* string */	id)
	{
		if (this._map[ id ])
		{
			var obj = this._map[ id ];
			delete this._map[ id ];
			return obj;
		}
		else
		{
			return false;
		}
	},

	/**
	 * Remove all objects.
	 * 
	 * @method clear
	 */
	clear: function()
	{
		this._map = {};
	},

	/**
	 * Returns list of all stored keys.
	 * 
	 * @method keys
	 */
	keys: function()
	{
		return Y.Object.keys(this._map);
	},

	/**
	 * Call a function on every object.
	 * 
	 * @method applyToAll
	 * @param behavior {Function|String|Object} the function to call or the name of the function or an object {fn:,scope:}
	 * @param arguments {Array} the arguments to pass to the function
	 * @param skip_unconstructed {boolean} Optional.  Pass <code>true</code> to skip unconstructed slots.
	 */
	applyToAll: function(
		/* string/fn/object */	behavior,
		/* array */				args,
		/* bool */				skip_unconstructed)
	{
		var map        = this._map,
			isFunction = Y.Lang.isFunction(behavior),
			isObject   = Y.Lang.isObject(behavior);

		Y.Object.each(map, function(item, name)
		{
			if (!item && skip_unconstructed)
			{
				return;
			}
			else if (!item)
			{
				item = this.get(name);
			}

			if (isFunction || isObject)
			{
				// apply the function and pass the map item as an argument

				var fn    = isFunction ? behavior : behavior.fn,
					scope = isFunction ? window : behavior.scope;

				fn.apply(scope, [ { key:name, value:item } ].concat( args ) );
			}
			else if (item && Y.Lang.isFunction(item[ behavior ]))
			{
				// the string is the name of a method

				item[ behavior ].apply(item, args);
			}
		},
		this);
	}
};

Y.InstanceManager = InstanceManager;