/** * Event * * Event api wrapper * @todo Add method for triggering events */ (function (undefined){ "use strict"; var _add_remove, e, _attach_delegate; _add_remove = function (sel, event, callback, add) { var i, len; // Multiple events? Run recursively! if ( ! event.match(/^([\w\-]+)$/)) { event = event.split(" "); len = event.length; for (i = 0; i < len; i++) { _add_remove(sel, event[i], callback, add); } return; } // Bind the event (add === true) ? sel.addEventListener(event, callback, false) : sel.removeEventListener(event, callback, false); }; _attach_delegate = function(sel, target, event, callback) { // attach the listener to the parent object _add_remove(sel, event, function(e){ var elem, t; // Get the live version of the target selector t = $_.$(target, sel); // Check each element to see if it matches the target for(elem in t) { // Fire target callback when event bubbles from target if(e.target == t[elem]) { // Trigger the event callback callback.call(t[elem], e); // Stop event propegation e.stopPropagation(); } } }, true); }; // -------------------------------------------------------------------------- /** * Event Listener module * * @namespace * @name event * @memberOf $_ */ e = { /** * Create a custom event * * @memberOf $_.event * @name create * @function * @example var event = $_("#selector").event.create('foo', {}); * @param {string} name * @param {object} [data] * @return {Object} */ create: function(name, data) { data = data || {}; // Okay, I guess we have to do this the hard way... :( var e = document.createEvent('CustomEvent'); e.initCustomEvent(name, true, true, data); return e; }, /** * Adds an event that returns a callback when triggered on the selected * event and selector * * @memberOf $_.event * @name add * @function * @example $_("#selector").event.add("click", do_something()); * @param {string} event * @param {function} callback */ add: function (event, callback) { $_.each(function(e){ _add_remove(e, event, callback, true); }); }, /** * Removes an event bound the the specified selector, event type, and callback * * @memberOf $_.event * @name remove * @function * @example $_("#selector").event.remove("click", do_something()); * @param {string} event * @param {string} callback */ remove: function (event, callback) { $_.each(function(e){ _add_remove(e, event, callback, false); }); }, /** * Binds a persistent event to the document * * @memberOf $_.event * @name live * @function * @example $_.event.live(".button", "click", do_something()); * @param {string} target * @param {string} event * @param {function} callback */ live: function (target, event, callback) { _attach_delegate(document.documentElement, target, event, callback); }, /** * Binds an event to a parent object * * @memberOf $_.event * @name delegate * @function * @example $_("#parent").delegate(".button", "click", do_something()); * @param {string} target * @param {string} event * @param {function} callback */ delegate: function (target, event, callback) { $_.each(function(e){ _attach_delegate(e, target, event, callback); }); }, /** * Trigger an event to fire * * @memberOf $_.event * @name trigger * @function * @example $_("#my_id").trigger('click'); * @param {object} event * @return {boolean} */ trigger: function(event) { return this.el.dispatchEvent(event); } }; $_.ext('event', e); }());