DOM Events
by mgiuffrida
HTML
<div id="outer">
<div id="inner">
Inner div
</div>
</div>
JavaScript
// Tested with Chrome and FF.
// Some setup.
console.clear();
function assert(x) { if (!x) throw Error(x); }
var log = '';
function assertLog(s) { assert(log.startsWith(s)); log = log.substr(s.length); }
var outer = document.querySelector('#outer');
var inner = document.querySelector('#inner');
//
// Events
// https://dom.spec.whatwg.org/#interface-event
//
// EventTarget lets us fire an Event on an object or manage an object's event
// listeners. Every Node object implements the EventTarget interface.
[].forEach.call(document.childNodes, function checkAll(node) {
assert(node instanceof EventTarget);
[].forEach.call(node.childNodes, checkAll);
});
function outerDivClickHandler(ev) {
// Every Event has a `type` property, set in the constructor or by the user agent.
assert(ev.type == 'click');
// The `target` property returns the object the event was dispatched to.
assert(ev.target === outer);
// Events have four phases:
// NONE: Not currently dispatched
// CAPTURING_PHASE: Dispatched, but hasn't reached target
// AT_TARGET: Dispatched, has reached target
// BUBBLING_PHASE: Dispatched, after reaching target
assert(ev.eventPhase === Event.AT_TARGET);
}
outer.addEventListener('click', outerDivClickHandler);
outer.click();
outer.removeEventListener('click', outerDivClickHandler);
// target vs. currentTarget
// Having explained the dispatch process, we can now define currentTarget: the object whose
// event listener's callback is currently being invoked.
function onClick(ev) {
log += ev.currentTarget.id + ' listener triggered due to click on ' + ev.target.id;
}
outer.addEventListener('click', onClick);
inner.addEventListener('click', onClick);
inner.click();
assertLog('inner listener triggered due to click on inner');
assertLog('outer listener triggered due to click on inner');
outer.removeEventListener('click', onClick);
inner.removeEventListener('click', onClick);