My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Friday, October 04, 2013

Web Development Has Never Been So Beautiful !

In an era where iOS7 does many steps backward while Chrome adopt a full Home Screen App like solution, it's kinda normal to be confused about the current status of Web Development.
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 via el.dispatchEvent(new CustomEvent('type', {bubbles:true, detail:object}))
I could talk about every single new feature that makes the DOM L4 awesome and the good news is that everything has been tested in every browser and it works, included the infamous Internet Explorer 8, thanks to this repo!

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 only Object.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 use on, 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 ^_^

7 comments:

Unknown said...

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.

Frankly 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.

Unknown said...

Nice one Andrea .. Always Love to read your articles

Andrea Giammarchi said...

no 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.

Now you can forget that there are browsers without addEventListener, which is the point I've made in here.

Regards

Unknown said...

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...

Andrea Giammarchi said...

Maksim ... 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.

You 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.

Andrea Giammarchi said...

ie8 fixes that too ... and if you use eddy.js, you'll forget other problems too since everything works as expected everywhere.

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

Unknown said...

Andrea I got your opinion. ie8 is an interesting project, just created an issue there.

This is true that using polyfills could potentially simplify libraries like my own. It's jus so difficult to find something with a good quality.