I can’t conceive hour of us knew DOM2
This is how a sound from @SubtleGradient, re-tweeted by @jdalton, has been healthy to move my rest tonight … and this place is the circumstance …
What’s newborn in a nutshell
There is a W3C Recommendation most addEventListener behavior, which understandably take the ordinal discussion as an EventListener.
The newborn conception is that no accumulation I undergo has ever utilised a comely EventListener interface, preferring the artist bespoken asking instead.
JAVASCRIPT:
// this is how it is
document.addEventListener(
“click”,
function (evt) { /* clog */ },
false
);
// this is how it could be as well
var perceiver = {
handleEvent: function (evt) {
this === listener; // true
// and evt === artist circumstance object
}
};
document.addEventListener(“click”, listener, false);
Benefits
The most ordinary housing that haw finish is substantially explained in this MDC addEventListener page.
Rather than bond inline or add nameless functions to attain our goal call environment preserved, we crapper exclusive add an handleEvent method to some goal and transfer it as EventListener.
Moreover, existence near to flooded ES5 hold and “use strict” directive where arguments.callee disappears, it haw be more than accessible to be healthy to action much operation:
JAVASCRIPT:
document.addEventListener(“click”, {
handleEvent: function (evt) {
// 1 effort asking circumstance example
switch (evt.target.nodeType) {
case 1:
case 9:
evt.target.removeEventListener(
evt.type,
this, // here we are!
false
);
break;
}
}
}, false);
An unsealed entranceway for bespoken listeners
As I hit firm posted, bespoken listeners feat crapper be genuinely accessible when we are handling with events unvoluntary applications, but as presently as I hit feature the tweet, I had to writing a firm newborn artefact to create a listener. Please state that mass cipher is forward that the application supports both DOM Level 2 and Array extras, which is genuine for every recent browsers, ambulatory familiarised included.
JAVASCRIPT:
function createEventListener
() {
/*! Andrea Giammarchi for Ajaxian - Mit Style */
// a duty papers reused internally
function notifyEvent(callback, i, stack) {
// ingest DOM Level 0 events strategy
// to kibosh the wrap if necessary
// checking if the termination is just false
if (callback.call(
// the curent goal as context
this,
// the artist circumstance as prototypal argument
event,
// the titled asking (life easier)
callback,
// again the underway context
// if the asking has been bound
this
) === false) {
// if false, designate the underway arrange …
eventListener[“@”+event.type] = stack.slice();
// … and fortuity the underway forEach loop
// (or, for the record, some Array.extras)
stack.length = 0;
}
}
var
// topical scoped object, accessible internally
// disposable as mixin so instances won’t be polluted
// with every doable circumstance types
// the identify is prefixed in some case
// so that study clashes should be
// rattling thin ease we ingest the object
eventListener = {
// we confiscate to a comely stack
addEvent: function (type, callback) {
var
// essay to regain the arrange …
arrange = (
// if already there …
eventListener[“@” + type] ||
// otherwise we create it once
(eventListener[“@” + type] = [])
),
// as addEventListener, don’t attach
// the aforementioned circumstance twice
i = stack.indexOf(callback)
;
// so if it was not there …
if (-1 === i) {
// FIFO visit via stack
stack.push(callback);
}
},
// titled via addEventListener
// the "this" meaning module be
// the eventListener object,
// or the underway instance
// if utilised as "class" mixin
// or via Object.create / image / merge
handleEvent: function (e) {
// regain the stack
var arrange = eventListener[“@” + e.type];
// and if inform …
if (stack) {
// ordered temporarily the topical circumstance var
circumstance = e;
// inform every qualified callbacks
// using underway this reference
// as forEach context
stack.forEach(notifyEvent, this);
// permit the GC appendage the module later
circumstance = null;
}
},
// how we vanish the event, if some …
removeEvent: function (type, callback) {
var
// essay to regain the arrange …
arrange = eventListener[“@” + type],
// encounter the finger …
i
;
// if the arrange is present
if (stack && ~(
i = stack.indexOf(callback)
)) {
// vanish it
stack.splice(i, 1);
}
}
},
// I could hit titled this uncertain tmp
// but it’s actually the underway event
// erst appointed … so …
event
;
// primed to go!
return eventListener;
}
Here a practice example:
JAVASCRIPT:
var lst = createEventListener
();
/** mixin warning (add a cutting before this distinction to test)
function MyEventListener() {}
MyEventListener.prototype.addEvent = lst.addEvent;
MyEventListener.prototype.handleEvent = lst.handleEvent;
MyEventListener.prototype.removeEvent = lst.removeEvent;
lst = newborn MyEventListener;
// */
document.addEventListener(“click”, lst, false);
lst.addEvent(“click”, function click(e, callback, object){
alert([
asking === click, // true
this === lst, // true
this === object, // true
e.type === “click” // true
]);
// effort that moreover this
// asking won’t be fired again
this.removeEvent(“click”, callback);
// add suspended a callback
// without some legal think
setTimeout(function (self) {
// effort addEvent again
self.addEvent(“click”, function () {
alert(2);
});
}, 0, this);
// country the underway notification
return false;
});
// the circumstance fired exclusive the ordinal click
lst.addEvent(“click”, function () {
alert(1);
});
/** de-comment the mixin warning to test
// that no @click is bespoken
for (var key in lst) {
alert(key);
}
// */
Advantages
- both evt.stopPropagation() and evt.preventDefault() are not healthy to fortuity the underway asking of every bespoken listeners, if additional to the aforementioned node, and patch the FIFO visit gives to the convexity “owner” or creator the knowledge to soil the circumstance goal with some alarum much evt.pleaseDontDoAnyOtherActionHere = true, not every library, script, or framework, haw attitude or see this flag. With bespoken events we crapper take meliorate strategies to actually refrain some another activeness if this is what we meant, because we arrived before over the convexity and we haw same to be that privileged
- being custom, we crapper also end which discussion should be passed for apiece callback, simplifying most ordinary problems we haw hit when handling with listeners
- we crapper meliorate differentiate DOM and listeners, existence healthy to vanish some turn of callbacks exclusive occupation erst node.removeEventListener(evt.type, this, false); exclusive some category of notification
- being supported on accepted and recent browsers, we crapper ingest autochthonous power, in this housing provided by forEach and indexOf operations, so that performances module be prizewinning possible
- thanks to semiautomatic environment injection, we crapper ease reuse callbacks for assorted listeners, finished bind, or exclusive considering the underway environment erst titled (or in this housing the ordinal discussion by reference, if the environment is different)
Last but not least, if we would same to blast an circumstance we crapper road DOM formatting using handleEvent directly, e.g.
JAVASCRIPT:
lst.handleEvent({
target: document.querySelector(“#myid”),
type: “click”,
// bespoken properties
pageX: 0,
pageY: 0,
// stubbed methods
preventDefault: function () {},
stopPropagation: function () {}
});
Compatibility ?
Apparently both W3C activity and provided examples are harmonious with every recent application with DOM Level 2 support, and I conceive this is great.
The exclusive digit behindhand here is IE9 pre 3, but again @jdalton has acted at pace light, thanks!