API Docs for:
Show:

File: ../src/levent.js

/**
* @namespace 
*/

/**
* LEvent is a lightweight events library focused in low memory footprint and fast delivery.
* It works by creating a property called "__levents" inside the object that has the bindings, and storing arrays with all the bindings.
* @class LEvent
* @constructor
*/

var LEvent = global.LEvent = GL.LEvent = {
	//map: new Weakmap(),

	/**
	* Binds an event to an instance
	* @method LEvent.bind
	* @param {Object} instance where to attach the event
	* @param {String} event_name string defining the event name
	* @param {function} callback function to call when the event is triggered
	* @param {Object} target_instance [Optional] instance to call the function (use this instead of .bind method to help removing events)
	**/
	bind: function( instance, event_type, callback, target_instance )
	{
		if(!instance) 
			throw("cannot bind event to null");
		if(!callback) 
			throw("cannot bind to null callback");
		if(instance.constructor === String ) 
			throw("cannot bind event to a string");

		var events = instance.__levents;
		if(!events)
		{
			Object.defineProperty( instance, "__levents", {value: {}, enumerable: false });
			events = instance.__levents;
		}

		if( events.hasOwnProperty( event_type ) )
			events[event_type].push([callback,target_instance]);
		else
			events[event_type] = [[callback,target_instance]];
	},

	/**
	* Unbinds an event from an instance
	* @method LEvent.unbind
	* @param {Object} instance where the event is binded
	* @param {String} event_name string defining the event name
	* @param {function} callback function that was binded
	* @param {Object} target_instance [Optional] target_instance that was binded
	**/
	unbind: function( instance, event_type, callback, target_instance )
	{
		if(!instance) 
			throw("cannot unbind event to null");
		if(!callback) 
			throw("cannot unbind from null callback");
		if(instance.constructor === String ) 
			throw("cannot bind event to a string");

		var events = instance.__levents;
		if(!events)
			return;

		if(!events.hasOwnProperty( event_type ))
			return;

		for(var i = 0, l = events[event_type].length; i < l; ++i)
		{
			var v = events[event_type][i];
			if(v[0] === callback && v[1] === target_instance)
			{
				events[event_type].splice( i, 1 );
				break;
			}
		}

		if (events[event_type].length == 0)
			delete events[event_type];
	},

	/**
	* Unbinds all events from an instance (or the ones that match certain target_instance)
	* @method LEvent.unbindAll
	* @param {Object} instance where the events are binded
	* @param {Object} target_instance [Optional] target_instance of the events to remove
	**/
	unbindAll: function( instance, target_instance )
	{
		if(!instance) 
			throw("cannot unbind events in null");

		var events = instance.__levents;
		if(!events)
			return;

		if(!target_instance) //remove all
		{
			delete instance.__levents;
			return;
		}

		//remove only the target_instance
		//for every property in the instance
		for(var i in events)
		{
			var array = events[i];
			for(var j = array.length - 1; j >= 0; --j) //iterate backwards to avoid problems after removing
			{
				if( array[j][1] != target_instance ) 
					continue;
				array.splice(j,1);//remove
			}

			//if(array.length == 0) //add two passes to avoid read and delete
			//	delete events[i];
		}
	},

	/**
	* Unbinds all callbacks associated to one specific event from this instance
	* @method LEvent.unbindAll
	* @param {Object} instance where the events are binded
	* @param {String} event name of the event you want to remove all binds
	**/
	unbindAllEvent: function( instance, event )
	{
		if(!instance) 
			throw("cannot unbind events in null");

		var events = instance.__levents;
		if(!events)
			return;
		delete events[ event ];
		return;
	},

	/**
	* Tells if there is a binded callback that matches the criteria
	* @method LEvent.isBind
	* @param {Object} instance where the are the events binded
	* @param {String} event_name string defining the event name
	* @param {function} callback the callback
	* @param {Object} target_instance [Optional] instance binded to callback
	**/
	isBind: function( instance, event_type, callback, target_instance )
	{
		if(!instance)
			throw("LEvent cannot have null as instance");

		var events = instance.__levents;
		if( !events )
			return;

		if( !events.hasOwnProperty(event_type) ) 
			return false;

		for(var i = 0, l = events[event_type].length; i < l; ++i)
		{
			var v = events[event_type][i];
			if(v[0] === callback && v[1] === target_instance)
				return true;
		}
		return false;
	},

	/**
	* Tells if there is any callback binded to this event
	* @method LEvent.hasBind
	* @param {Object} instance where the are the events binded
	* @param {String} event_name string defining the event name
	* @return {boolean} true is there is at least one
	**/
	hasBind: function( instance, event_type )
	{
		if(!instance)
			throw("LEvent cannot have null as instance");
		var events = instance.__levents;
		if(!events || !events.hasOwnProperty( event_type ) || !events[event_type].length) 
			return false;
		return true;
	},

	/**
	* Tells if there is any callback binded to this object pointing to a method in the target object
	* @method LEvent.hasBindTo
	* @param {Object} instance where there are the events binded
	* @param {Object} target instance to check to
	* @return {boolean} true is there is at least one
	**/
	hasBindTo: function( instance, target )
	{
		if(!instance)
			throw("LEvent cannot have null as instance");
		var events = instance.__levents;

		//no events binded
		if(!events) 
			return false;

		for(var j in events)
		{
			var binds = events[j];
			for(var i = 0; i < binds.length; ++i)
			{
				if(binds[i][1] === target) //one found
					return true;
			}
		}

		return false;
	},

	/**
	* Triggers and event in an instance
	* @method LEvent.trigger
	* @param {Object} instance that triggers the event
	* @param {String} event_name string defining the event name
	* @param {*} parameters that will be received by the binded function
	**/
	trigger: function( instance, event_type, params )
	{
		if(!instance) 
			throw("cannot trigger event from null");
		if(instance.constructor === String ) 
			throw("cannot bind event to a string");

		var events = instance.__levents;
		if( !events || !events.hasOwnProperty(event_type) )
			return true;

		var inst = events[event_type];
		for(var i = 0, l = inst.length; i < l; ++i)
		{
			var v = inst[i];
			if( v && v[0].call(v[1], event_type, params) == false)// || event.stop)
				return false; //stopPropagation
		}

		return true;
	},

	/**
	* Triggers and event to every element in an array
	* @method LEvent.triggerArray
	* @param {Array} array contains all instances to triggers the event
	* @param {String} event_name string defining the event name
	* @param {*} parameters that will be received by the binded function
	**/
	triggerArray: function( instances, event_type, params )
	{
		for(var i = 0, l = instances.length; i < l; ++i)
		{
			var instance = instances[i];
			if(!instance) 
				throw("cannot trigger event from null");
			if(instance.constructor === String ) 
				throw("cannot bind event to a string");

			var events = instance.__levents;
			if( !events || !events.hasOwnProperty( event_type ) )
				continue;

			for(var j = 0, ll = events[event_type].length; j < ll; ++j)
			{
				var v = events[event_type][j];
				if( v[0].call(v[1], event_type, params) == false)// || event.stop)
					break; //stopPropagation
			}
		}

		return true;
	}
};

// NOT FINISHED, STILL HAS SOME ISSUES TO SOLVE, TEST OR DELETE
//There is a secondary implementation using WeakMap, this implementation clears the events from the objects
//and moves them to one global object, so objects are not constantly changing, but I must test performance.
/*
if(global.WeakMap && 0)
{
	(function(){

	//local scope
	var map = new WeakMap;

	LEvent.bind = function( instance, event_type, callback, target_instance )
	{
		if(!instance) 
			throw("cannot bind event to null");
		if(!callback) 
			throw("cannot bind to null callback");
		if(instance.constructor === String ) 
			throw("cannot bind event to a string");
		var name = event_type;

		var obj = map[instance];
		if(!obj)
			obj = map[instance] = {};

		if(obj.hasOwnProperty(name))
			obj[name].push([callback,target_instance]);
		else
			obj[name] = [[callback,target_instance]];
	}

	LEvent.unbind = function( instance, event_type, callback, target_instance )
	{
		if(!instance) 
			throw("cannot unbind event to null");
		if(!callback) 
			throw("cannot unbind from null callback");
		if(instance.constructor === String ) 
			throw("cannot bind event to a string");

		var obj = map[instance];
		if(!obj)
			return;

		var name = event_type;
		if(!obj[name]) 
			return;

		for(var i = 0, l = obj[name].length; i < l; ++i)
		{
			var v = obj[name][i];
			if(v[0] === callback && v[1] === target_instance)
			{
				obj[name].splice( i, 1);
				break;
			}
		}

		if (obj[name].length == 0)
			delete obj[name];
	},

	LEvent.unbindAll = function(instance, target_instance)
	{
		if(!instance) 
			throw("cannot unbind events in null");
		if(!target_instance) //remove all
		{
			map.delete(instance);
			return;
		}

		//remove only the target_instance
		//for every property in the instance
		var obj = map[instance];
		if(!obj)
			return;

		for(var i in obj)
		{
			var array = obj[i];
			for(var j=0; j < array.length; ++j)
			{
				if( array[j][1] != target_instance ) 
					continue;
				array.splice(j,1);//remove
				--j;//iterate from the gap
			}

			if(array.length == 0)
				delete obj[i];
		}
	}

	LEvent.isBind = function( instance, event_type, callback, target_instance )
	{
		var name = event_type;
		var obj = map[instance];
		if(!obj || !obj.hasOwnProperty(name)) 
			return false;
		for(var i = 0, l = obj[name].length; i < l; ++i)
		{
			var v = obj[name][i];
			if(v[0] === callback && v[1] === target_instance)
				return true;
		}
		return false;
	}

	LEvent.trigger = function( instance, event_type, params, skip_jquery )
	{
		if(!instance) 
			throw("cannot trigger event from null");
		if(instance.constructor === String ) 
			throw("cannot bind event to a string");

		

		//you can resend the events as jQuery events, but to avoid collisions with system events, we use ":" at the begining
		if(LEvent.jQuery && !skip_jquery)
			$(instance).trigger( ":" + event_type, params );

		var name = event_type;

		var obj = map[instance];

		if(!obj.hasOwnProperty(name)) 
			return;
		var inst = obj[name];
		for(var i = 0, l = inst.length; i < l; ++i)
		{
			var v = inst[i];
			if( v[0].call(v[1], event_type, params) == false)// || event.stop)
				break; //stopPropagation
		}
	}

	LEvent.triggerArray = function( instances, event_type, params, skip_jquery )
	{
		for(var i = 0, l = instances.length; i < l; ++i)
		{
			var instance = instances[i];
			if(!instance) 
				throw("cannot trigger event from null");
			if(instance.constructor === String ) 
				throw("cannot bind event to a string");

			var obj = map[instance];

			//you can resend the events as jQuery events, but to avoid collisions with system events, we use ":" at the begining
			if(LEvent.jQuery && !skip_jquery) 
				$(instance).trigger( ":" + event_type, params );

			var name = event_type;
			if(!obj.hasOwnProperty(name)) 
				continue;
			for(var j = 0, l = obj[name].length; j < l; ++j)
			{
				var v = obj[name][j];
				if( v[0].call(v[1], event_type, params) == false)// || event.stop)
					break; //stopPropagation
			}
		}
	}


	})(); //local scope end
}
*/