Created
September 29, 2010 21:38
-
-
Save jeremyckahn/603614 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Specify an event handler for a given event and phase | |
HTMLNode.prototype.addEventListener = function(eventName, handler, phase){ | |
// Make a __handlers object on this element if there is none already | |
if(!this.__handlers){ | |
this.__handlers = {}; | |
} | |
// If there are no event handler lists for this event, add them | |
if(!this.__handlers[eventName]){ | |
this.__handlers[eventName] = {capture : [], bubble: []}; | |
} | |
// Add the new handler function to the specified phase list | |
this.__handlers[eventName][phase ? 'capture' : 'bubble'].push(handler); | |
} | |
// Gets called whenever an en event is fired | |
Handle = function(ev){ | |
// Step 1: Initialization and setup | |
var elements = []; | |
target = ev.target; | |
isPropagationStopped = false, | |
isDefaultPrevented = false; | |
// We are on the Capture Phase to start with | |
ev.eventPhase = 0; | |
ev.stopPropagation = function(){ | |
isPropagationStopped = true; | |
} | |
ev.preventDefault = function(){ | |
isDefaultPrevented = true; | |
} | |
// Step 2: Collect the DOM nodes | |
// Loop up through the DOM and collect all of the parent nodes into the 'elements' array | |
do{ | |
elements.push(target); | |
}while((target = target.parentNode)); | |
// Reverse the list so it's a bit easier to read in the following for loop | |
arr.reverse(); | |
// Step 3: Loop through the nodes, and execute the Capture Phase DOM Level 2 event handlers | |
// For all of the elements in the list... | |
for(var i = 0 ; i < elements.length; i++){ | |
// If stopPropagation() was called, end the loop - we're done. | |
if(isPropagationStopped){ | |
break; | |
} | |
var currentElement = elements[i], | |
// If there are any event handlers set for this element, event type and phase, | |
// set that array to 'handlers'. Otherwise, set 'handlers' to an empty array. | |
handlers = currentElement.__handlers | |
&& currentElement.__handlers[ev.type] | |
&& currentElement.__handlers[ev.type].capture | |
|| []; | |
ev.currentTarget = currentElement; | |
// Loop through the handlers we've collected and execute them | |
// in the context of the current element | |
for(var h = 0; i < handlers.length; h++){ | |
handlers[h].call(currentElement, ev); | |
} | |
} | |
// Step 4: Execute the DOM Level 1 event handler and reverse the array | |
// If propagation was not stopped, execute the DOM level 1 event handler | |
if(!isPropagationStopped){ | |
ev.target["on" + ev.type].call(ev.target, ev); | |
} | |
arr.reverse(); | |
ev.eventPhase = 1; | |
// Step 5: Loop through the node collection again and execute the Bubble Phase DOM Level 2 event handlers | |
// Basically, do the same thing as before, but with the 'elements' list reversed... | |
for(var i = 0 ; i < elements.length; i++){ | |
if(isPropagationStopped){ | |
break; | |
} | |
// ... Also, we are working with the 'bubble' phase this time, not 'capture' | |
var currentElement = elements[i], | |
handlers = currentElement.__handler | |
&& currentElement.__handlers[ev.type] | |
&& currentElement.__handlers[ev.type].bubble | |
|| []; | |
ev.currentTarget = currentElement; | |
for(var h = 0 ; i < handlers.length; h++){ | |
handlers[h].call(currentElement,ev); | |
} | |
} | |
// Step 6: Execute the default browser event handler | |
// Default behaviors for HTML elements | |
if(!isDefaultPrevented){ | |
// anchor tag (a link) | |
if(ev.type == "click" && ev.target.nodeName.toLowerCase() == "a"){ | |
window.location = ev.target.href; | |
} | |
// default cases for the rest of the elements go here... | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment