var esPhinx; (function($) { "use strict"; var nodes = [], mappedListeners = {}, mapped = function(node) { var index = nodes.indexOfEquivalence(node); return mappedListeners[index]; }, mapEventListener = function(node, eventName, runOnListener) { var index, mappedNode = mapped(node), map = {}; if (runOnListener) { map[eventName] = [runOnListener]; if (mappedNode) { if (mappedNode[eventName]) { mappedNode[eventName].push(runOnListener); } else { mappedNode[eventName] = map[eventName]; } return mappedNode[eventName]; } else { nodes.push(node); index = nodes.length - 1; mappedListeners[index] = map; return mappedListeners[index][eventName]; } } else { if (mappedNode) { return mappedNode[eventName]; } else { return []; } } }, removeListener = function(node, eventName, runOnListener) { var mappedNode = mapped(node), callbacks = mappedNode[eventName]; callbacks.delete(runOnListener); }, removeListeners = function(node, eventName) { var mappedNode = mapped(node); delete mappedNode[eventName]; }, mapEach = function(eventName, runOnListener, callback) { var iteratorBlock = function(node) { if (node instanceof window.Node || node == window) { mapEventListener(node, eventName, runOnListener); callback.call(node); } }; this.each(iteratorBlock); }, // qual seria o evento neste caso, para, por exemplo, usar o stopPropagation? onChangeNode = function(runOnListener) { var added, self = this, callback = function(mutation) { added = $(mutation.addedNodes).elements(); if (added.some()) { runOnListener.call(self, added.asArray()); } }, observeCallback = function(mutations) { mutations.forEach(callback); }; mapEach.call(self, "changeNode", runOnListener, function() { $(this).observe(observeCallback); } ); }, // will see how to unbind the node event // offChangeNode = function(runOnListener) { // // disconnect // }, on = function(eventName, capture, runOnListener) { var cloned, runOnLoad, imgs, self = this, html = $("html"), clone = self.clone(true), callback = function(node) { cloned = $(node); cloned.hide(); html.prepend(node); node.addEventListener(eventName, runOnLoad, capture); }, iteratorBlock = function(node) { node.removeEventListener(eventName, runOnLoad, capture); }; if (typeof capture == "function") { runOnListener = capture; capture = false; } else if (typeof capture != "boolean") { capture = false; } switch (eventName) { case "changeNode": return onChangeNode.call(self, runOnListener); case "load": imgs = clone.find("img"); if (imgs.some()) { clone = imgs; } runOnLoad = function(e) { runOnListener.call(this, e); html.remove(clone); clone.each(iteratorBlock); }; clone.each(callback); break; default: mapEach.call(self, eventName, runOnListener, function() { this.addEventListener(eventName, runOnListener, capture); }); } }; $.prototype.extend(true, { on: function(eventName, capture, runOnListener) { on.call(this, eventName, capture, runOnListener); return this; }, off: function(eventName, capture, runOnListener) { var callback, node, iteratorBlock = function(runOnListener) { var booleanIteratorBlock = function(capture) { node.removeEventListener(eventName, runOnListener, capture); }; [true, false].forEach(booleanIteratorBlock); removeListeners(node, eventName); }; if (typeof capture == "function") { runOnListener = capture; capture = false; } else if (typeof capture != "boolean") { capture = false; } if (runOnListener) { callback = function(n) { node = n; node.removeEventListener(eventName, runOnListener, capture); removeListener(node, eventName, runOnListener); }; } else { callback = function(n) { node = n; if (mapped(node)) { mapEventListener(node, eventName) .forEach(iteratorBlock); } }; } this.each(callback); return this; }, attachedEvent: function(eventName) { if (mapped(this.asNode())[eventName]) { return true; } return false; } }); })(esPhinx);