diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0539fe7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/node_modules/ +gator-*.tgz +gator.min.js* diff --git a/gator.js b/gator.js index 25fe1d1..3130457 100644 --- a/gator.js +++ b/gator.js @@ -32,335 +32,330 @@ * _____..' .' * '-._____.-' */ -(function() { - var _matcher, - _level = 0, - _id = 0, - _handlers = {}, - _gatorInstances = {}; - - function _addEvent(gator, type, callback) { - - // blur and focus do not bubble up but if you use event capturing - // then you will get them - var useCapture = type == 'blur' || type == 'focus'; - gator.element.addEventListener(type, callback, useCapture); - } - function _cancel(e) { - e.preventDefault(); - e.stopPropagation(); - } +module.exports = Gator; - /** - * returns function to use for determining if an element - * matches a query selector - * - * @returns {Function} - */ - function _getMatcher(element) { - if (_matcher) { - return _matcher; - } +var _matcher, + _level = 0, + _id = 0, + _handlers = {}, + _gatorInstances = {}; - if (element.matches) { - _matcher = element.matches; - return _matcher; - } +function _addEvent(gator, type, callback) { - if (element.webkitMatchesSelector) { - _matcher = element.webkitMatchesSelector; - return _matcher; - } + // blur and focus do not bubble up but if you use event capturing + // then you will get them + var useCapture = type == 'blur' || type == 'focus'; + gator.element.addEventListener(type, callback, useCapture); +} - if (element.mozMatchesSelector) { - _matcher = element.mozMatchesSelector; - return _matcher; - } +function _cancel(e) { + e.preventDefault(); + e.stopPropagation(); +} - if (element.msMatchesSelector) { - _matcher = element.msMatchesSelector; - return _matcher; - } +/** + * returns function to use for determining if an element + * matches a query selector + * + * @returns {Function} + */ +function _getMatcher(element) { + if (_matcher) { + return _matcher; + } - if (element.oMatchesSelector) { - _matcher = element.oMatchesSelector; - return _matcher; - } + if (element.matches) { + _matcher = element.matches; + return _matcher; + } - // if it doesn't match a native browser method - // fall back to the gator function - _matcher = Gator.matchesSelector; + if (element.webkitMatchesSelector) { + _matcher = element.webkitMatchesSelector; return _matcher; } - /** - * determines if the specified element matches a given selector - * - * @param {Node} element - the element to compare against the selector - * @param {string} selector - * @param {Node} boundElement - the element the listener was attached to - * @returns {void|Node} - */ - function _matchesSelector(element, selector, boundElement) { - - // no selector means this event was bound directly to this element - if (selector == '_root') { - return boundElement; - } + if (element.mozMatchesSelector) { + _matcher = element.mozMatchesSelector; + return _matcher; + } - // if we have moved up to the element you bound the event to - // then we have come too far - if (element === boundElement) { - return; - } + if (element.msMatchesSelector) { + _matcher = element.msMatchesSelector; + return _matcher; + } - // if this is a match then we are done! - if (_getMatcher(element).call(element, selector)) { - return element; - } + if (element.oMatchesSelector) { + _matcher = element.oMatchesSelector; + return _matcher; + } - // if this element did not match but has a parent we should try - // going up the tree to see if any of the parent elements match - // for example if you are looking for a click on an tag but there - // is a inside of the a tag that it is the target, - // it should still work - if (element.parentNode) { - _level++; - return _matchesSelector(element.parentNode, selector, boundElement); - } + // if it doesn't match a native browser method + // fall back to the gator function + _matcher = Gator.matchesSelector; + return _matcher; +} + +/** + * determines if the specified element matches a given selector + * + * @param {Node} element - the element to compare against the selector + * @param {string} selector + * @param {Node} boundElement - the element the listener was attached to + * @returns {void|Node} + */ +function _matchesSelector(element, selector, boundElement) { + + // no selector means this event was bound directly to this element + if (selector == '_root') { + return boundElement; } - function _addHandler(gator, event, selector, callback) { - if (!_handlers[gator.id]) { - _handlers[gator.id] = {}; - } + // if we have moved up to the element you bound the event to + // then we have come too far + if (element === boundElement) { + return; + } - if (!_handlers[gator.id][event]) { - _handlers[gator.id][event] = {}; - } + // if this is a match then we are done! + if (_getMatcher(element).call(element, selector)) { + return element; + } - if (!_handlers[gator.id][event][selector]) { - _handlers[gator.id][event][selector] = []; - } + // if this element did not match but has a parent we should try + // going up the tree to see if any of the parent elements match + // for example if you are looking for a click on an tag but there + // is a inside of the a tag that it is the target, + // it should still work + if (element.parentNode) { + _level++; + return _matchesSelector(element.parentNode, selector, boundElement); + } +} - _handlers[gator.id][event][selector].push(callback); +function _addHandler(gator, event, selector, callback) { + if (!_handlers[gator.id]) { + _handlers[gator.id] = {}; } - function _removeHandler(gator, event, selector, callback) { + if (!_handlers[gator.id][event]) { + _handlers[gator.id][event] = {}; + } - // if there are no events tied to this element at all - // then don't do anything - if (!_handlers[gator.id]) { - return; - } + if (!_handlers[gator.id][event][selector]) { + _handlers[gator.id][event][selector] = []; + } - // if there is no event type specified then remove all events - // example: Gator(element).off() - if (!event) { - for (var type in _handlers[gator.id]) { - if (_handlers[gator.id].hasOwnProperty(type)) { - _handlers[gator.id][type] = {}; - } + _handlers[gator.id][event][selector].push(callback); +} + +function _removeHandler(gator, event, selector, callback) { + + // if there are no events tied to this element at all + // then don't do anything + if (!_handlers[gator.id]) { + return; + } + + // if there is no event type specified then remove all events + // example: Gator(element).off() + if (!event) { + for (var type in _handlers[gator.id]) { + if (_handlers[gator.id].hasOwnProperty(type)) { + _handlers[gator.id][type] = {}; } - return; } + return; + } - // if no callback or selector is specified remove all events of this type - // example: Gator(element).off('click') - if (!callback && !selector) { - _handlers[gator.id][event] = {}; - return; - } + // if no callback or selector is specified remove all events of this type + // example: Gator(element).off('click') + if (!callback && !selector) { + _handlers[gator.id][event] = {}; + return; + } - // if a selector is specified but no callback remove all events - // for this selector - // example: Gator(element).off('click', '.sub-element') - if (!callback) { - delete _handlers[gator.id][event][selector]; - return; - } + // if a selector is specified but no callback remove all events + // for this selector + // example: Gator(element).off('click', '.sub-element') + if (!callback) { + delete _handlers[gator.id][event][selector]; + return; + } - // if we have specified an event type, selector, and callback then we - // need to make sure there are callbacks tied to this selector to - // begin with. if there aren't then we can stop here - if (!_handlers[gator.id][event][selector]) { - return; - } + // if we have specified an event type, selector, and callback then we + // need to make sure there are callbacks tied to this selector to + // begin with. if there aren't then we can stop here + if (!_handlers[gator.id][event][selector]) { + return; + } - // if there are then loop through all the callbacks and if we find - // one that matches remove it from the array - for (var i = 0; i < _handlers[gator.id][event][selector].length; i++) { - if (_handlers[gator.id][event][selector][i] === callback) { - _handlers[gator.id][event][selector].splice(i, 1); - break; - } + // if there are then loop through all the callbacks and if we find + // one that matches remove it from the array + for (var i = 0; i < _handlers[gator.id][event][selector].length; i++) { + if (_handlers[gator.id][event][selector][i] === callback) { + _handlers[gator.id][event][selector].splice(i, 1); + break; } } +} - function _handleEvent(id, e, type) { - if (!_handlers[id][type]) { - return; - } +function _handleEvent(id, e, type) { + if (!_handlers[id][type]) { + return; + } - var target = e.target || e.srcElement, - selector, - match, - matches = {}, - i = 0, - j = 0; - - // find all events that match - _level = 0; - for (selector in _handlers[id][type]) { - if (_handlers[id][type].hasOwnProperty(selector)) { - match = _matchesSelector(target, selector, _gatorInstances[id].element); - - if (match && Gator.matchesEvent(type, _gatorInstances[id].element, match, selector == '_root', e)) { - _level++; - _handlers[id][type][selector].match = match; - matches[_level] = _handlers[id][type][selector]; - } + var target = e.target || e.srcElement, + selector, + match, + matches = {}, + i = 0, + j = 0; + + // find all events that match + _level = 0; + for (selector in _handlers[id][type]) { + if (_handlers[id][type].hasOwnProperty(selector)) { + match = _matchesSelector(target, selector, _gatorInstances[id].element); + + if (match && Gator.matchesEvent(type, _gatorInstances[id].element, match, selector == '_root', e)) { + _level++; + _handlers[id][type][selector].match = match; + matches[_level] = _handlers[id][type][selector]; } } + } - // stopPropagation() fails to set cancelBubble to true in Webkit - // @see http://code.google.com/p/chromium/issues/detail?id=162270 - e.stopPropagation = function() { - e.cancelBubble = true; - }; + // stopPropagation() fails to set cancelBubble to true in Webkit + // @see http://code.google.com/p/chromium/issues/detail?id=162270 + e.stopPropagation = function() { + e.cancelBubble = true; + }; - for (i = 0; i <= _level; i++) { - if (matches[i]) { - for (j = 0; j < matches[i].length; j++) { - if (matches[i][j].call(matches[i].match, e) === false) { - Gator.cancel(e); - return; - } - - if (e.cancelBubble) { - return; - } + for (i = 0; i <= _level; i++) { + if (matches[i]) { + for (j = 0; j < matches[i].length; j++) { + if (matches[i][j].call(matches[i].match, e) === false) { + Gator.cancel(e); + return; + } + + if (e.cancelBubble) { + return; } } } } +} - /** - * binds the specified events to the element - * - * @param {string|Array} events - * @param {string} selector - * @param {Function} callback - * @param {boolean=} remove - * @returns {Object} - */ - function _bind(events, selector, callback, remove) { - - // fail silently if you pass null or undefined as an alement - // in the Gator constructor - if (!this.element) { - return; - } +/** + * binds the specified events to the element + * + * @param {string|Array} events + * @param {string} selector + * @param {Function} callback + * @param {boolean=} remove + * @returns {Object} + */ +function _bind(events, selector, callback, remove) { + + // fail silently if you pass null or undefined as an alement + // in the Gator constructor + if (!this.element) { + return; + } - if (!(events instanceof Array)) { - events = [events]; - } + if (!(events instanceof Array)) { + events = [events]; + } - if (!callback && typeof(selector) == 'function') { - callback = selector; - selector = '_root'; - } + if (!callback && typeof(selector) == 'function') { + callback = selector; + selector = '_root'; + } - var id = this.id, - i; + var id = this.id, + i; - function _getGlobalCallback(type) { - return function(e) { - _handleEvent(id, e, type); - }; - } - - for (i = 0; i < events.length; i++) { - if (remove) { - _removeHandler(this, events[i], selector, callback); - continue; - } + function _getGlobalCallback(type) { + return function(e) { + _handleEvent(id, e, type); + }; + } - if (!_handlers[id] || !_handlers[id][events[i]]) { - Gator.addEvent(this, events[i], _getGlobalCallback(events[i])); - } + for (i = 0; i < events.length; i++) { + if (remove) { + _removeHandler(this, events[i], selector, callback); + continue; + } - _addHandler(this, events[i], selector, callback); + if (!_handlers[id] || !_handlers[id][events[i]]) { + Gator.addEvent(this, events[i], _getGlobalCallback(events[i])); } - return this; + _addHandler(this, events[i], selector, callback); } - /** - * Gator object constructor - * - * @param {Node} element - */ - function Gator(element, id) { - - // called as function - if (!(this instanceof Gator)) { - // only keep one Gator instance per node to make sure that - // we don't create a ton of new objects if you want to delegate - // multiple events from the same node - // - // for example: Gator(document).on(... - for (var key in _gatorInstances) { - if (_gatorInstances[key].element === element) { - return _gatorInstances[key]; - } - } + return this; +} - _id++; - _gatorInstances[_id] = new Gator(element, _id); - - return _gatorInstances[_id]; +/** + * Gator object constructor + * + * @param {Node} element + */ +function Gator(element, id) { + + // called as function + if (!(this instanceof Gator)) { + // only keep one Gator instance per node to make sure that + // we don't create a ton of new objects if you want to delegate + // multiple events from the same node + // + // for example: Gator(document).on(... + for (var key in _gatorInstances) { + if (_gatorInstances[key].element === element) { + return _gatorInstances[key]; + } } - this.element = element; - this.id = id; - } + _id++; + _gatorInstances[_id] = new Gator(element, _id); - /** - * adds an event - * - * @param {string|Array} events - * @param {string} selector - * @param {Function} callback - * @returns {Object} - */ - Gator.prototype.on = function(events, selector, callback) { - return _bind.call(this, events, selector, callback); - }; - - /** - * removes an event - * - * @param {string|Array} events - * @param {string} selector - * @param {Function} callback - * @returns {Object} - */ - Gator.prototype.off = function(events, selector, callback) { - return _bind.call(this, events, selector, callback, true); - }; + return _gatorInstances[_id]; + } - Gator.matchesSelector = function() {}; - Gator.cancel = _cancel; - Gator.addEvent = _addEvent; - Gator.matchesEvent = function() { - return true; - }; + this.element = element; + this.id = id; +} - if (typeof module !== 'undefined' && module.exports) { - module.exports = Gator; - } +/** + * adds an event + * + * @param {string|Array} events + * @param {string} selector + * @param {Function} callback + * @returns {Object} + */ +Gator.prototype.on = function(events, selector, callback) { + return _bind.call(this, events, selector, callback); +}; - window.Gator = Gator; -}) (); +/** + * removes an event + * + * @param {string|Array} events + * @param {string} selector + * @param {Function} callback + * @returns {Object} + */ +Gator.prototype.off = function(events, selector, callback) { + return _bind.call(this, events, selector, callback, true); +}; + +Gator.matchesSelector = function() {}; +Gator.cancel = _cancel; +Gator.addEvent = _addEvent; +Gator.matchesEvent = function() { + return true; +}; diff --git a/gator.min.js b/gator.min.js deleted file mode 100644 index e01fe67..0000000 --- a/gator.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/* gator v1.2.4 craig.is/riding/gators */ -(function(){function t(a){return k?k:a.matches?k=a.matches:a.webkitMatchesSelector?k=a.webkitMatchesSelector:a.mozMatchesSelector?k=a.mozMatchesSelector:a.msMatchesSelector?k=a.msMatchesSelector:a.oMatchesSelector?k=a.oMatchesSelector:k=e.matchesSelector}function q(a,b,c){if("_root"==b)return c;if(a!==c){if(t(a).call(a,b))return a;if(a.parentNode)return m++,q(a.parentNode,b,c)}}function u(a,b,c,e){d[a.id]||(d[a.id]={});d[a.id][b]||(d[a.id][b]={});d[a.id][b][c]||(d[a.id][b][c]=[]);d[a.id][b][c].push(e)} -function v(a,b,c,e){if(d[a.id])if(!b)for(var f in d[a.id])d[a.id].hasOwnProperty(f)&&(d[a.id][f]={});else if(!e&&!c)d[a.id][b]={};else if(!e)delete d[a.id][b][c];else if(d[a.id][b][c])for(f=0;f