Created
October 16, 2010 20:05
-
-
Save avit/630216 to your computer and use it in GitHub Desktop.
A model of DOM event handling from http://jupiterit.com/news/a-crash-course-in-how-dom-events-work
This file contains hidden or 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
// Gets called whenever an en event is fired | |
Handle = function(ev){ | |
// Step 1: Event 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: Calculate parent node path | |
// Loop up through the DOM and collect all of the | |
// parent nodes into the 'elements' array | |
var elements = []; | |
do{ | |
elements.push(target); | |
}while((target = target.parentNode)); | |
// Reverse the list so it's a bit easier to read | |
// in the following for loop | |
elements.reverse(); | |
// Step 3: Execute Capture Phase 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 DOM Level 1 event handler | |
// If propagation was not stopped, execute | |
// the DOM level 1 event handler | |
if(!isPropagationStopped){ | |
ev.target["on" + ev.type].call(ev.target, ev); | |
} | |
elements.reverse(); | |
ev.eventPhase = 1; | |
// Step 5: Execute Bubble Phase 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.__handlers | |
&& 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 default browser behavior | |
// 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... | |
// (submit, etc.) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment