1 /**
  2  * Event
  3  *
  4  * Event api wrapper
  5  * @todo Add method for triggering events
  6  */
  7 (function (undefined){
  8 
  9 	"use strict";
 10 
 11 	var _add_remove, e, _attach_delegate;
 12 
 13 	_add_remove = function (sel, event, callback, add)
 14 	{
 15 		var i, len;
 16 
 17 		// Multiple events? Run recursively!
 18 		if ( ! event.match(/^([\w\-]+)$/))
 19 		{
 20 			event = event.split(" ");
 21 
 22 			len = event.length;
 23 
 24 			for (i = 0; i < len; i++)
 25 			{
 26 				_add_remove(sel, event[i], callback, add);
 27 			}
 28 
 29 			return;
 30 		}
 31 
 32 		// Bind the event
 33 		(add === true)
 34 			? sel.addEventListener(event, callback, false)
 35 			: sel.removeEventListener(event, callback, false);
 36 	};
 37 
 38 	_attach_delegate = function(sel, target, event, callback)
 39 	{
 40 		// attach the listener to the parent object
 41 		_add_remove(sel, event, function(e){
 42 
 43 			var elem, t;
 44 
 45 			// Get the live version of the target selector
 46 			t = $_.$(target, sel);
 47 
 48 			// Check each element to see if it matches the target
 49 			for(elem in t)
 50 			{
 51 				// Fire target callback when event bubbles from target
 52 				if(e.target == t[elem])
 53 				{
 54 					// Trigger the event callback
 55 					callback.call(t[elem], e);
 56 
 57 					// Stop event propegation
 58 					e.stopPropagation();
 59 				}
 60 			}
 61 
 62 		}, true);
 63 	};
 64 
 65 	// --------------------------------------------------------------------------
 66 
 67 	/**
 68 	 * Event Listener module
 69 	 *
 70 	 * @namespace
 71 	 * @name event
 72 	 * @memberOf $_
 73 	 */
 74 	e = {
 75 		/**
 76 		 * Create a custom event
 77 		 *
 78 		 * @memberOf $_.event
 79 		 * @name create
 80 		 * @function
 81 		 * @example Eg. var event = $_("#selector").event.create('foo', {});
 82 		 * @param string name
 83 		 * @param [object] data
 84 		 * @return object
 85 		 */
 86 		create: function(name, data)
 87 		{
 88 			// Do a terrible browser-sniffic hack because I don't know of a good 
 89 			// feature test
 90 			if (/MSIE|Trident/i.test(navigator.userAgent))
 91 			{
 92 				// Okay, I guess we have to do this the hard way... :(
 93 				// Microsoft, your browser still sucks
 94 				var e = document.createEvent('CustomEvent');
 95 				e.initCustomEvent(name, true, true, data);
 96 				
 97 				return e;
 98 			}
 99 			else
100 			{
101 				return new CustomEvent(name, data);
102 			}
103 		},
104 		/**
105 		 * Adds an event that returns a callback when triggered on the selected
106 		 * event and selector
107 		 *
108 		 * @memberOf $_.event
109 		 * @name add
110 		 * @function
111 		 * @example Eg. $_("#selector").event.add("click", do_something());
112 		 * @param string event
113 		 * @param function callback
114 		 */
115 		add: function (event, callback)
116 		{
117 			$_.each(function(e){
118 				_add_remove(e, event, callback, true);
119 			});
120 		},
121 		/**
122 		 * Removes an event bound the the specified selector, event type, and callback
123 		 *
124 		 * @memberOf $_.event
125 		 * @name remove
126 		 * @function
127 		 * @example Eg. $_("#selector").event.remove("click", do_something());
128 		 * @param string event
129 		 * @param string callback
130 		 */
131 		remove: function (event, callback)
132 		{
133 			$_.each(function(e){
134 				_add_remove(e, event, callback, false);
135 			});
136 		},
137 		/**
138 		 * Binds a persistent event to the document
139 		 *
140 		 * @memberOf $_.event
141 		 * @name live
142 		 * @function
143 		 * @example Eg. $_.event.live(".button", "click", do_something());
144 		 * @param string target
145 		 * @param string event
146 		 * @param function callback
147 		 */
148 		live: function (target, event, callback)
149 		{
150 			_attach_delegate(document.documentElement, target, event, callback);
151 		},
152 		/**
153 		 * Binds an event to a parent object
154 		 *
155 		 * @memberOf $_.event
156 		 * @name delegate
157 		 * @function
158 		 * @example Eg. $_("#parent").delegate(".button", "click", do_something());
159 		 * @param string target
160 		 * @param string event_type
161 		 * @param function callback
162 		 */
163 		delegate: function (target, event, callback)
164 		{
165 			$_.each(function(e){
166 				_attach_delegate(e, target, event, callback);
167 			});
168 		},
169 		/**
170 		 * Trigger an event to fire
171 		 *
172 		 * @memberOf $_.event
173 		 * @name trigger
174 		 * @function
175 		 * @example Eg. $_("#my_id").trigger('click');
176 		 * @param string target
177 		 * @param object event
178 		 * @return bool
179 		 */
180 		trigger: function(event)
181 		{
182 			var target = this.el;
183 			return target.dispatchEvent(event);
184 		}
185 	};
186 
187 	$_.ext('event', e);
188 
189 }());