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);