I won't hold it any further and tell you it's actually in the best shape ever, a situation rarely seen in the past and probably not so nice in the near feature where massive JavaScript changes will land in some ever green browser.
The DOM Is Awesome !
Developers still learn and code as if IE6 is the only browser to take care of ... well, we are lucky enough today the situation is not that anymore so that IE8 is the latest browser we might want to deal with, if we really care about those people stuck behind such jurassic browser.DOM Level 4 For Every Browser
Not kidding here, the latest DOM Level 4 API is absolutely nice:- events and custom events with bubbling work as expected
- patterns like handleEvent, a universal fast and cross browser solution to callbacks hell and hundreds of pointless
bind
in your code, is available for any sort of browser or event - dispatching events has never been so easy, with possible extra
detail
to carry on through the bubbling process viael.dispatchEvent(new CustomEvent('type', {bubbles:true, detail:object}))
ES5 Is Everywhere
Probably not fully implemented as specs say, ES5 is in any case in every browser we can think of these days.It was already almost fully implemented in webOS, it works like a charm in IE9, it's in every ever green browser plus it has been early adopted almost in every Mobile Browser, from iOS 5.1, the latest update available for old iPad and iPhones, through Android 2.3 and others. Seriously, even Nokia ASHA Xpress Browser scores well when it comes to ES5 support!
ES5 Can Fix The DOM Too
Thanks to its wide adoption and thanks to the fact every ES5 capable browser knows DOM Element prototypes too, included IE8 and its DOM onlyObject.defineProperty()
functionality, the DOM can be fixed in almost all its missing parts.This is how it was possible, as example, to implement classList and DOMTokenList behavior in both IE8 and iOS 5 or Nokia ASHA browser, where the early implementation does not accept multiple arguments and does not respect standards for
toggle
method.
Not Only The DOM
The current status of the web is that everything can be reasonably fixed with available tools. This is the best thing ever happened so far and all goes to the decision made in 2008 to abandon specifications that were breaking the web due different syntax.At that time the decision was to extend ES specs or fix them with what was possible/available at that time.
This is paying back now, after 5 years, where almost everything can be normalized through amazing libraries such es5-shim, including its sham that fixes other aspects of ES5 specs in a reasonable way.
Everything Is Working Now
It sounds overall optimistic but green is what you should see once you click this link, followed by this one.About 140 Tests Of Awesomeness I am going to explain to you after introducing yet another repository ...
The Dreamerplate
Similar to a boilerplate, the dreamerplate is a repo that includes all the needed basics to have an homogeneous environment across all modern and jurassic browsers you can imagine surfing the internet these days.From IE8 to anything else that came after, you can try the base testing page in console, dreaming about an environment where you can:
// use de-facto standards to define methods document.body.on('click', function (e) { this.append(' ' + e.timeStamp); }); // give for grant all you need is there window.on( 'unload', console.log.bind(console, 'bye bye') ); // use widely adopted and future proof standards // instead of needing this or that utility window.dispatchEvent( new CustomEvent('unload') ); // or simply go the way you are used to window.trigger('unload'); // or, if coming from node ... window.emit('unload'); // use a better DOM approach avoiding // memory leaks and the need of WeakMaps // or the need to bind everything [ 'mousedown', 'mousemove', 'mouseup' ].forEach(function (type) { document.documentElement.on(type, this); }, { handleEvent: function (e) { this['on' + e.type](e); }, onmousedown: function (e) { // this is the object, not the node this.dragging = true; }, onmousemove: function (e) { if (this.dragging) { document.body.append([ e.pageX, e.pageY ].join(', ')); document.body.append( document.createElement('br') ); } }, onmouseup: function (e) { this.dragging = false; } }); // use window timers as they are meant to be used // with extra arguments capabilities, i.e. setInterval( requestAnimationFrame, // * not normalized in dreamerplate yet 1000 / 30, // Fixed 30 FPS function () { // the expensive callback to optimize var marginLeft = parseFloat(document.body.style.marginLeft) || 0; document.body.style.marginLeft = (marginLeft + 1) + 'px'; } ); // avoid callback hell with bind and lost references var handler = {method: function (e) { alert(this === handler); e.currentTarget.off(e.type, this.boundTo(this.method)); // bound to create a single bound reference per object // never loose a bound function again and find them // through the bound object these belong! }}; document.body.on('click', handler.boundTo('method'));
Eddy.JS To The Rescue
Most of the event handling magic, fully compatible with node.js too, is an eddy.js enrichment (word you can easily swap with addiction once you start using it ;-))Latest
eddy
news are the ability to be compatible with CustomEvent
, speeding also up the trigger
logic too overbloated until version 0.4
, and the W3C trigger
returned value behavior, always false when any involved listener in the event called preventDefault()
and the event was cancelable
a default when non a native Event object is passed, or regardless when eddy
is not invoked through DOM nodes but rather node.js or just JS scripts.For the DOM version only,
eddy
relies now on dom4
and, if needed to be supported, ie8
upfront.
Eddy Array Extras
One of the most handy parts about eddy is the ability to useon
, off
, emit
, and trigger
recursively within Arrays.
[ document.body, [].slice.call( document.querySelectorAll( 'very.complicated:selector' ) ) ].on('click', function (e) { alert(e.currentTarget); });Being recursive, an Array of objects or DOM elements, containing eventually sub elements, can perform a single
addEventListener
like operation at once, promoting recycling of functions which aim is to provide the same functionality in different events or situations.
Got It, But What Does It Mean In Terms Of Bandwidth ?
The size of both eddy and dom4, the most common configuration you gonna need to provide, is 2.5 KB minzipped. Everything else is browser and sOS file dependent.Enjoy theese days, since those when ES6 will be released will be much harder and confusing than current status as it has been, and probably always been, for the Web when new things arrive and nobody is fully ready ^_^
Yeah, we could fix browsers via patching prototypes but... it's a bad idea. Third party scripts could rely on feature checks that will be broken (for instance they could determine IE by testing existence of addEventListener etc.) In general it's always better to use wrappers for native objects.
ReplyDeleteFrankly I still think that DOM apis are bad designed and confusing. Many useful features are missed. That's why I try to address all issues (instead of just complaining) in my own project better-dom.
Nice one Andrea .. Always Love to read your articles
ReplyDeleteno Maksim, it's not a bad idea. It's like patching Array extras ... if done correctly, there's nothing wrong while wrong would be to do a pointless feature detection as `if(document.addEventListener)` which gives you nothing.
ReplyDeleteNow you can forget that there are browsers without addEventListener, which is the point I've made in here.
Regards
The key phrase is "if done correctly". This is stupid to check old IE via addEventListener (better to use feature checks). But unfortunately there are a lot of bad written code and sometimes you have to use it...
ReplyDeleteMaksim ... ie8 polyfill is the only one done correctly as much as possible, of course, but it requires very few code style changes in order to work as you expect.
ReplyDeleteYou might want to know that ie8 test suite fails in Safari and Chrome because **these browsers** are not W3C compatible as Firefox is, as example.
ie8 fixes that too ... and if you use eddy.js, you'll forget other problems too since everything works as expected everywhere.
ReplyDeleteattachEvent cannot really give you anything else in there, I have normalized that monster and you should just stop detecting such event or keep doing that, if necessary to understand some special event name or case, but use addEventListener instead ;-)
Andrea I got your opinion. ie8 is an interesting project, just created an issue there.
ReplyDeleteThis is true that using polyfills could potentially simplify libraries like my own. It's jus so difficult to find something with a good quality.