1 /**
  2  * Event
  3  *
  4  * Event api wrapper
  5  * @todo Add method for triggering events
  6  */
  7 (function (){
  8 
  9 	"use strict";
 10 
 11 	var _add_remove, e, _attach_delegate;
 12 
 13 	// Don't bother defining the methods if event api isn't supports
 14 	if (typeof document.addEventListener === "undefined")
 15 	{
 16 		return false;
 17 	}
 18 
 19 	_add_remove = function (sel, event, callback, add)
 20 	{
 21 		var i, len;
 22 
 23 		if(typeof sel === "undefined")
 24 		{
 25 			return null;
 26 		}
 27 
 28 		// Multiple events? Run recursively!
 29 		if ( ! event.match(/^([\w\-]+)$/))
 30 		{
 31 			event = event.split(" ");
 32 
 33 			len = event.length;
 34 
 35 			for (i = 0; i < len; i++)
 36 			{
 37 				_add_remove(sel, event[i], callback, add);
 38 			}
 39 
 40 			return;
 41 		}
 42 
 43 		// Bind the event
 44 		(add === true)
 45 			? sel.addEventListener(event, callback, false)
 46 			: sel.removeEventListener(event, callback, false);
 47 	};
 48 
 49 	_attach_delegate = function(sel, target, event, callback)
 50 	{
 51 		// attach the listener to the parent object
 52 		_add_remove(sel, event, function(e){
 53 
 54 			var elem, t;
 55 
 56 			// Get the live version of the target selector
 57 			t = $_.$(target, sel);
 58 
 59 			// Check each element to see if it matches the target
 60 			for(elem in t)
 61 			{
 62 				// Fire target callback when event bubbles from target
 63 				if(e.target == t[elem])
 64 				{
 65 					// Trigger the event callback
 66 					callback.call(t[elem], e);
 67 
 68 					// Stop event propegation
 69 					e.stopPropagation();
 70 				}
 71 			}
 72 
 73 		}, true);
 74 	};
 75 
 76 	// --------------------------------------------------------------------------
 77 
 78 	/**
 79 	 * Event Listener module
 80 	 *
 81 	 * @namespace
 82 	 * @name event
 83 	 * @memberOf $_
 84 	 */
 85 	e = {
 86 		/**
 87 		 * Adds an event that returns a callback when triggered on the selected
 88 		 * event and selector
 89 		 *
 90 		 * @memberOf $_.event
 91 		 * @name add
 92 		 * @function
 93 		 * @example Eg. $_("#selector").event.add("click", do_something());
 94 		 * @param string event
 95 		 * @param function callback
 96 		 */
 97 		add: function (event, callback)
 98 		{
 99 			$_.each(function(e){
100 				_add_remove(e, event, callback, true);
101 			});
102 		},
103 		/**
104 		 * Removes an event bound the the specified selector, event type, and callback
105 		 *
106 		 * @memberOf $_.event
107 		 * @name remove
108 		 * @function
109 		 * @example Eg. $_("#selector").event.remove("click", do_something());
110 		 * @param string event
111 		 * @param string callback
112 		 */
113 		remove: function (event, callback)
114 		{
115 			$_.each(function(e){
116 				_add_remove(e, event, callback, false);
117 			});
118 		},
119 		/**
120 		 * Binds a persistent event to the document
121 		 *
122 		 * @memberOf $_.event
123 		 * @name live
124 		 * @function
125 		 * @example Eg. $_.event.live(".button", "click", do_something());
126 		 * @param string target
127 		 * @param string event
128 		 * @param function callback
129 		 */
130 		live: function (target, event, callback)
131 		{
132 			_attach_delegate(document.documentElement, target, event, callback);
133 		},
134 		/**
135 		 * Binds an event to a parent object
136 		 *
137 		 * @memberOf $_.event
138 		 * @name delegate
139 		 * @function
140 		 * @example Eg. $_("#parent").delegate(".button", "click", do_something());
141 		 * @param string target
142 		 * @param string event_type
143 		 * @param function callback
144 		 */
145 		delegate: function (target, event, callback)
146 		{
147 			$_.each(function(e){
148 				_attach_delegate(e, target, event, callback);
149 			});
150 		}
151 	};
152 
153 	$_.ext('event', e);
154 
155 }());