1 /** 2 * Event 3 * 4 * Event api wrapper 5 */ 6 (function (){ 7 8 "use strict"; 9 10 // Property name for expandos on DOM objects 11 var kis_expando = "KIS_0_5_0"; 12 13 var _attach, _remove, _add_remove, e, _attach_delegate; 14 15 // Define the proper _attach and _remove functions 16 // based on browser support 17 if(typeof document.addEventListener !== "undefined") 18 { 19 /** 20 * @private 21 */ 22 _attach = function (sel, event, callback) 23 { 24 if(typeof sel.addEventListener !== "undefined") 25 { 26 //Duplicated events are dropped, per the specification 27 sel.addEventListener(event, callback, false); 28 } 29 }; 30 /** 31 * @private 32 */ 33 _remove = function (sel, event, callback) 34 { 35 if(typeof sel.removeEventListener !== "undefined") 36 { 37 sel.removeEventListener(event, callback, false); 38 } 39 }; 40 } 41 //typeof function doesn't work in IE where _attachEvent is available: brute force it 42 else if(typeof document.attachEvent !== "undefined") 43 { 44 /** 45 * @private 46 */ 47 _attach = function (sel, event, callback) 48 { 49 function listener () { 50 // Internet Explorer fails to correctly set the 'this' object 51 // for event listeners, so we need to set it ourselves. 52 callback.apply(arguments[0]); 53 } 54 55 if (typeof sel.attachEvent !== "undefined") 56 { 57 _remove(event, callback); // Make sure we don't have duplicate listeners 58 59 sel.attachEvent("on" + event, listener); 60 // Store our listener so we can _remove it later 61 var expando = sel[kis_expando] = sel[kis_expando] || {}; 62 expando.listeners = expando.listeners || {}; 63 expando.listeners[event] = expando.listeners[event] || []; 64 expando.listeners[event].push({ 65 callback: callback, 66 listener: listener 67 }); 68 } 69 else 70 { 71 console.log("Failed to _attach event:"+event+" on "+sel); 72 } 73 }; 74 /** 75 * @private 76 */ 77 _remove = function (sel, event, callback) 78 { 79 if(typeof sel.detachEvent !== "undefined") 80 { 81 var expando = sel[kis_expando]; 82 if (expando && expando.listeners 83 && expando.listeners[event]) 84 { 85 var listeners = expando.listeners[event]; 86 var len = listeners.length; 87 for (var i=0; i<len; i++) 88 { 89 if (listeners[i].callback === callback) 90 { 91 sel.detachEvent("on" + event, listeners[i].listener); 92 listeners.splice(i, 1); 93 if(listeners.length === 0) 94 { 95 delete expando.listeners[event]; 96 } 97 return; 98 } 99 } 100 } 101 } 102 }; 103 } 104 105 _add_remove = function (sel, event, callback, add) 106 { 107 var i, len; 108 109 if(typeof sel === "undefined") 110 { 111 console.log(arguments); 112 console.log(event); 113 return false; 114 } 115 116 //Multiple events? Run recursively! 117 if (!event.match(/^([\w\-]+)$/)) 118 { 119 event = event.split(" "); 120 121 len = event.length; 122 123 for (i = 0; i < len; i++) 124 { 125 _add_remove(sel, event[i], callback, add); 126 } 127 128 return; 129 } 130 131 132 if(add === true) 133 { 134 _attach(sel, event, callback); 135 } 136 else 137 { 138 _remove(sel, event, callback); 139 } 140 }; 141 142 _attach_delegate = function(sel, target, event, callback) 143 { 144 //_attach the listener to the parent object 145 _add_remove(target, event, function(e){ 146 147 var i, t; 148 149 //Get the live version of the target selector 150 t = $_.$(target); 151 152 console.log(t); 153 154 //Check each element to see if it matches the target 155 for(i in t) 156 { 157 if(t.hasOwnProperty(i)) 158 { 159 //Fire target callback when event bubbles from target 160 if(e.target == i) 161 { 162 //Trigger the event callback 163 callback.call(i, e); 164 165 //Stop event propegation 166 e.stopPropagation(); 167 } 168 } 169 } 170 171 172 }, true); 173 }; 174 175 // -------------------------------------------------------------------------- 176 177 /** 178 * @namespace 179 * @name event 180 * @memberOf $_ 181 */ 182 e = { 183 /** 184 * Adds an event that returns a callback when triggered on the selected 185 * event and selector 186 * 187 * @memberOf $_.event 188 * @name add 189 * @function 190 * @example Eg. $_("#selector").event.add("click", do_something()); 191 * @param string event 192 * @param function callback 193 * @return void 194 */ 195 add: function (event, callback) 196 { 197 $_.each(function(e){ 198 _add_remove(e, event, callback, true); 199 }); 200 }, 201 /** 202 * Removes an event bound the the specified selector, event type, and callback 203 * 204 * @memberOf $_.event 205 * @name remove 206 * @function 207 * @example Eg. $_("#selector").event.remove("click", do_something()); 208 * @param string event 209 * @param string callback 210 * @return void 211 */ 212 remove: function (event, callback) 213 { 214 $_.each(function(e){ 215 _add_remove(e, event, callback, false); 216 }); 217 }, 218 /** 219 * Binds a persistent, delegated event 220 * 221 * @memberOf $_.event 222 * @name live 223 * @function 224 * @example Eg. $_.event.live(".button", "click", do_something()); 225 * @param string target 226 * @param string event 227 * @param function callback 228 * @return void 229 */ 230 live: function (target, event, callback) 231 { 232 _attach_delegate(document.documentElement, target, event, callback); 233 }, 234 /** 235 * Binds an event to a parent object 236 * 237 * @memberOf $_.event 238 * @name delegate 239 * @function 240 * @example Eg. $_("#parent").delegate(".button", "click", do_something()); 241 * @param string target 242 * @param string event_type 243 * @parma function callback 244 * @return void 245 */ 246 delegate: function(target, event, callback) 247 { 248 $_.each(function(e){ 249 _attach_delegate(e, target, event, callback); 250 }); 251 } 252 }; 253 254 $_.ext('event', e); 255 256 }());