Monday, September 15, 2014

The Mobile Web Handbook Review

Nobody asked for it, nobody paid me, and I've personally met @ppk no more than once in Warsaw 'cause we both have been speakers at the same conference, but I've kept following him since his beginning with Mobile Web, time that is approximately equivalent to the same I've started with Mobile Web development too.
Beside his well known quirksmode blog, he collaborated with Vodafone, NOKIA, and many others, while I've worked in the meanwhile on Mobile HTML5 NOKIA Maps, for a short time at Mobile Facebook site as well as Mobile Twitter site for the last couple of years so ... we both kinda come from the same multitude of devices, OSs, immature browsers and APIs, passing through the dream and the partial lie behind Mobile HTML5 Development and its ability to replace native.
This review will be somehow short and targeted, but hopefully great for the future of the Mobile Web itself ... uh wait, I've forgot the book name and link: The Mobile Web Handbook

As a Manager, you should read it!

The bold approach of the book is enlightening reaching the point even big corporates are mentioned in all their faults in terms of management and/or focus and/or outdated vision.
As a manager, you can learn how not to loose focus and/or screw up not just your team but potentially the entire company you are working for ... which you know, it's in your best interests!
First couple of chapters would be enough to understand what I am talking about, but being the book not that technical at all, you will learn and enjoy everything else too, or at least its key/core concepts, specially when it comes to write down pros and cons behind HTML5 and the Mobile Web.

As a Web Developer, you should read it!

Specially behind "the must have frameworks or libraries" culture, there are too many developers thinking there is "just one web" and every approach will scale across all platforms and devices ... you have no idea how deadly wrong you could be, and if you have no experience with the Mobile world but you do Web, you inevitably need to learn more from this parallel world because it's so different in all concepts we know and learned online so far, the day you'll have to create something mobile, you don't want to be the last ignorant in the universe that "didn't think about that problem" or believed that, as example, holding everything in RAM 'cause modern laptops have a huge amount of it, it's a good idea that scales out there ... read this book and double check your practices, you might realize there's so much you could actually drop instead of keeping bloating your dependencies!
You've seriously nothing to loose here, only to grow in terms of Web related knowledge, for today or tomorrow devices or just laptops (e.g. do you really know what do you need for a touch screen? Quick hint: no)

As a Mobile Developer, you should read it!

I have to be honest here, being exactly that kind of Mobile Web developer Peter describes in his book, most of the concepts and hints were not new to me but I have learned a lot regardless my experience on basically all mentioned OSs and devices in the book (tons of them, not just the silly Android or iPhone scene).
There are few concept explained behind way deeper analysis that I could have ever thought about, like the one after Who Killed My Battery, a study from Stanford University about how bad could be libraries such jQuery or others for your phone battery life ... I let you read the book in order to understand all takeaways here.

Things I disagreed

The plural is actually too much since there's basically only one concept I don't agree with Peter and it's about Pointer Events. Not only I've written already what I think about them and what's their current state, but Peter himself re-convinced me touch and mouse are completely different beasts, unfortunately struggling later on to counter-proof it makes sense to have both in a single stream ... no, it doesn't, IMO, it's just a mess at the end of the day, due all things you need to take care of inside the stream behind a single "eventname" instead of separating concerns outside it through those meaningful and semantic events. He even ended up suggesting mouseout and mouveover as events a part and beside pointer events, so that he basically described everything I think is wrong with these pointer events themselves! However, he did argument properly his point of view so I'll let you judge by your own the touch VS mouse VS pen VS new iWatch wheel VS ... how screwed is that part of the story.

... and not even that technical

So here the extra, there's no code to follow or test, rather many concepts to understand, learn, and stick in our mind as web developers. The book is an easy read that does not require special skills in HTML5, CSS, or JavaScript, it simply describes problems and solutions in a very pragmatic and documented way.

As summary

The price is not that high at all and if you want to live in 2014 and the future, instead of keep believing dogmas of the old Desktop oriented Web development, I do suggest you to give The Mobile Web Handbook a read: totally worth it!

Wednesday, September 10, 2014

A simple CSS page watermark

This is a very quick one about watermarking a generic website.

via CSS only

Add the following snippet to your CSS and adjust if you want custom properties.
html:after {

  /* common custom values */
  content: "© Water Mark"; /* your site name */
  font-size: 720%;         /* font size */
  color: rgba(0, 0, 0, .1);
  /* alpha, could be even rgba(0,0,0,.05) */

  /* rest of the logic */
  z-index: 9999;
  cursor: default;
  display: block;
  position: fixed;
  top: 33%;
  right: 0;
  bottom: 0;
  left: 15%;
  font-family: sans-serif;
  font-weight: bold;
  font-style: italic;
  text-align: center;
  line-height: 100%;

  /* not sure about who implemented what ..
    ... so bring it all */
  -webkit-pointer-events: none;
  -moz-pointer-events: none;
  -ms-pointer-events: none;
  -o-pointer-events: none;
  pointer-events: none;

  -webkit-transform: rotate(-45deg);
  -moz-transform: rotate(-45deg);
  -ms-transform: rotate(-45deg);
  -o-transform: rotate(-45deg);
  transform: rotate(-45deg);

  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  -o-user-select: none;
  user-select: none;
}

via restyle({}) at runtime

Place restyle.js in scope, then:
restyle({
  'html:after': {

    /* common custom values */
    content: '"© Water Mark"',  /* show what ? */
    fontSize: '720%',           /* how big ? */
    color: 'rgba(0, 0, 0, .1)', /* how visible ? */

    /* rest of the logic */
    zIndex: '9999',
    cursor: 'default',
    display: 'block',
    position: 'fixed',
    top: '33%',
    right: 0,
    bottom: 0,
    left: '15%',
    fontFamily: 'sans-serif',
    fontWeight: 'bold',
    fontStyle: 'italic',
    textAlign: 'center',
    lineHeight: '100%',
    pointerEvents: 'none',
    transform: 'rotate(-45deg)',
    userSelect: 'none'
  }
});
I've quickly tested this even on Google Maps and it worked like a charm and I don't know yet how many browsers will support this CSS approach but it seems that all modern browsers are just fine.
Enjoy

Sunday, August 17, 2014

Self contained Custom Elements via restyle()

There is an ongoing discussion about import link for both dependencies and Web Components, here my quick take on it: drop them! Just trash the fluff and use the DOM, it's freaking awesome these days and it works in every browser, you will rarely regret this choice!

However ...

Some dependency could be given for granted, which is actually the best we could do in order to simplify the mess (i.e. you use jQuery all over, don't include it in your file, assume it's there and mark it explicitly as must have in your component documentation).
Be sure that polyfills and/or dependencies are loaded upfront, which also means you should forget about async and other tricks if you want to rely these libraries are in.

restyle() and Custom Elements

Assuming this tiny library is in place, slightly more than just 1KB once minified and gzipped in its latest version, you might end up being able to confine the entire custom element behavior in just a javascript file. Have a look at this demo, based on same CSS and mostly same JS used in this post.
Yes, you got it right, custom elements are entirely confined in a single JS file.

A little helper for huge results!

The changes I've made in restyle are basically components oriented so that it's now possible to automatically confine some CSS inside a rule:
var style = restyle('my-element', {
  div: {
    border: '1px solid black'
  },
  i: {display: 'none'}
});

// will result in 
my-element div {
  border: 1px solid black;
}
my-element i {
  display: none;
}
Having somehow "sandboxed" all nodes also simplify the concept behind any Shadow Dom, except it works today with all browsers compatible with my document.registerElement and restyle code, basically all browsers you can think of except IE8 due Custom Element limits in this browser.

As Summary

Using little tools like restyle could give us the opportunity to use today Custom Elements without needing to wait a universally good, fast, and reliable solution via HTML5 imports combined with ES6 too, we can already place in a semantically similar way CSS into JS thanks to restyle and via JS also solve dependencies when appropriate. Feel free to play with the freshly new version of restyle and please don't hesitate to file bugs or suggest improvements: these are early days for Custom Elements and Web Components, this is the right time to nail it right!

Saturday, August 16, 2014

PointerEvents No More

It is stated and reasoned in this bug related comment that PointerEvents will not land in Blink, the Chrome/ium DOM related engine.
The brief summary, from the technical point of view, is the following:
  1. Touch events already demonstrated to work on the Mobile Web, no need to have more complex and, for mobile Web purpose, redundant API
  2. The hit-test model proposed by PointerEvents will penalize performance. Being such model not even available in Android or iOS it makes no sense to further penalize the Web against native.
  3. More complexity but less power, since it's not possible to intercept touch move while scrolling an element, being PointerEvents and scrolling mutually exclusive.
There are other reasons in the related thread and one of most important sentence, in my opinion, is summarized here:
The main shift in thinking for us has been from a position of a desktop-dominated web evolving slowly to enable mobile scenarios, to the realization that phones/tablets will soon dominate Internet usage and that the web is loosing to native mobile platforms.

Where PointerEvents failed

This is the most important argument against PointerEvents: touch capable Mobile Web has been around for 6+ years now and that Hardware still works properly with modern websites. Having 2 ways to end up dealing in the same exact way touch actions is redundant/duplicated code nobody wants to implement for a Mobile interface.

more complexity to do the same thing

If you have some experience with PoitnerEvents you know you ended up writing code like this:
// Handler => https://gist.github.com/WebReflection/9814013
// just a basic utility to simplify events managment
Handler.add(node, {
  // simulating touchstart and mousedown
  pointerdown: function (e) {
    if (e.pointerType == 'touch' ||
        e.pointerType == e.MSPOINTER_TYPE_TOUCH) {
      e.currentTarget.setPointerCapture(e.pointerId);
      e.preventDefault();
      // now prepare to move
    } else if(e.pointerType == 'mouse') {
      // mousedown, maybe start dragging?
    }
  },
  // simulating touchmove and mousemove
  pointermove: function (e) {
    if (e.pointerType == 'touch' ||
        e.pointerType == e.MSPOINTER_TYPE_TOUCH) {
      e.preventDefault();
      // do the touchmove like thing
    } else if(e.pointerType == 'mouse') {
      // mousemove, drag
    }
  },
  // simulating touchend
  pointerup: function (e) {
    if (e.pointerType == 'touch' ||
        e.pointerType == e.MSPOINTER_TYPE_TOUCH) {
      e.currentTarget.releasePointerCapture(e.pointerId);
      e.preventDefault();
      // clear state
    } else if(e.pointerType == 'mouse') {
      // mouseup, stop drag
    }
  },

  // for backward compatibility
  _fixed: function(e, method, pointerType) {
    e.setPointerCapture = e.msSetPointerCapture;
    return e;
  },
  MSPointerDown: function (e) {
    this.pointerdown(this._fixed(e));
  },
  MSPointerMove: function (e) {
    this.pointermove(this._fixed(e));
  },
  MSPointerUp: function (e) {
    this.pointerup(this._fixed(e));
  }
});
Not only we have coupled different meaning into a single stream of events, inevitably messing up readability and merging concerns because of different behaviors, but what we basically did on touch side is reflecting exactly this logic:
Handler.add(node, {
  touchstart: function (e) {
    // to also avoid dispatched mouse listeners
    e.preventDefault();
    // prepare to move
  },
  touchmove: function (e) {
    e.preventDefault();
    // do the touchmove thing
  },
  touchend: function (e) {
    e.preventDefault();
    // clear state
  }
});
If we want to also implement mouse events, how about doing in the universally compatible way we all know since 90s ?
Handler.add(node, {
  mousedown: function (e) {
    // prepare for dragging
  },
  mousemove: function (e) {
    // drag
  },
  mouseup: function (e) {
    // drop
  }
});
How cleaner is the code we all understand, write, and read compared with the PointerEvents counterpart?

no reliable polyfills

Despite the amount of attempts out there, setPointerCapture is implicitly invoked by default in every Touch based device. This basically means that unless that polyfill takes over the entire DOM interaction, killing performance already problematic even if implemented natively also due that hit-test target mentioned at the beginning, there is no way to have the exact same, default, behavior IE10 or IE11 implement.
This is not true the other way round, we can use PointerEvents to simulate Touch as shown before acting by default like them.
// demo only; don't use this code in prod!
Handler.add(node, {
  touchstart: function (e) {
    // prepare for move
  },
  touchmove: function (e) {
    // move
  },
  touchend: function (e) {
    // that's it
  },

  // use IE events to simulate touch
  pointerdown: function (e) {
    if (e.pointerType == 'touch') {
      e.currentTarget.setPointerCapture(e.pointerId);
      e.touchlist = [e];
      this.touchstart(e);
    }
  }

});
Luckily we don't have to take care about this mess, we should just use touch events that finally landed in IE11 Update 1 and eventually, if strictly necessary, we can put upfront a polyfill like ie-touch until all Windows Phone will get the update 1 installed (AFAIK this should happen around the end of August or beginning of September).

Tablet or Desktop ?

If we want to support special or different behaviors between touch and mouse we can simply split the logic and better organize it as shown before. Basically, instead of doing this per each bloody event:
node.addEventListener('pointerdown', function (e) {
  switch(e.pointerType) {
    case 'touch':
    case 'pen':
    case e.MSPOINTER_TYPE_TOUCH:
    case e.MSPOINTER_TYPE_PEN:
      // do touch things
      break;
    case 'mouse':
    case e.MSPOINTER_TYPE_MOUSE:
      // do mouse things
      break;
  }
});
We do this + that:
node.addEventListener('touchstart', function (e) {
  // finger or pen
});
node.addEventListener('mousedown', function (e) {
  // mouse indeed
});
This will also avoid O(n) checks multiplied by every input device event that will trigger on the browser.

So no "pen" anymore ?

I think pen is rather OK as touch device and it's in this event that I'd implement eventually pressure and angle for a simplified graceful enhancement over incompatible old systems that still will work as regular touch events.

Very different worlds

About Table VS Desktop there is another basic concept to consider: nobody drags with touch events, everyone drags with mouse. This is a fundamental split logic we should not underestimate. With touch screens we swipe, spread, pinch, tap, double tap, longpress to action while we right click instead or just point and click, or double click, with possible drag. Accordingly, The only event that has similar intent is click, irony wants that such event already works as expected with every device ... put in click what should have a click behavior, do not merge together any other gesture or intent into a single stream if you don't want to end up with spaghetti listeners hell.

In a nutshell

The initial idea behind PointerEvents was great but it was already showing how confined in an old mouse based world it was. Having all sort of events that might or might not be fired, just consider pointerover that won't happen the way we imagine if we touch the screen, was making the API itself inconsistent with developer expectations.
Moving the problem from a proper listener name, touch or mouse, into a pointerType event property hasn't solved a thing, hasn't worked as expected, hasn't improved performance, hasn't made the code easier to maintain or write ... it messed up listeners instead, adding extra complexity or unexpected default behaviors (i.e. the NON capture for touch events unshimmable as it is) where all we'll end up doing, as developers, is to simplify the logic down to what is possible already with Touch events.

This is Great!

I would like to underline that having specs like that and having played around even in production with those specs has been a great way to evaluate how nicely implemented, or how much troublesome, would these specs have been.
Seeing Microsoft recognizing it was important to support what devs wrote already and what mobile web is these days, bringing Touch events into IE11 Update 1, has been a very welcome and nice move we should all thank them about.
This is the web I like, where instead of silly pointless and endless discussions, we can go down to the concrete and not at all costs stubborn de-facto solution that everyone already used and is happy with and eventually change, or add, something documented and easy to use instead of playing "who's got the lauder voice".
Thanks to all people that helped with PointerEvents and their failure, now please let's make Touch and TouchList as cross platform as possible, including all micro gotchas with preventDefault and scrolling behaviors.

Thursday, August 14, 2014

Can we please stop moaning ?

OK here's the catch: software development is not something I do just for living, it's a passion I have since literarily ever and here's the story.
I'm absolutely envious of modern kids able to put their hands on a Raspberry PI, as example, and develop with Python, nodejs, or pretty much any other programming language available these days using an affordable board that does not need a music-cassette like player and at least half minute of potential personal epileptic attack with multi colors on screen plus noise before being able to show you something on the same screen (yes, I come from Commodore 64 era, a platform I couldn't afford at that time, and yet I feel lucky for owning a MSX and developing/experimenting on it via QBasic when I was between 8 and 11 ... then I've met by accident an Olivetti PC and it has been love since!).

Being greedy about learning!

When in 1998 I've finished high-school in Italy there was not a single University in the entire country that was even "10 years after" close to prepare people for real-world about the World Wide Web.
Those days, and bear in mind this is still the current situation in many "modern" Universities, Computer Science studies were only about some C, Java, or DBRM basics and nothing else; possibly even with an obsolete or deprecated versions of Java itself, nothing like nashorn these days, and just to shout one example.
All I could do in that scenario in order to prepare myself and learn about the Web, was to go online and study by my own everything available on the Internet!
All of this beside some unrelated University class that supposed to give me basis about programming (it kinda didn't for what I needed, it was too early to pretend to teach me Web in Italy at that time) ... guess what, I never completed that course or the one I've done few years after 'cause I was already ways ahead of them at that time.

However, I've been spending my career giving back to the Internet what I've learned contributing with Web specifications, ES specifications, creating libraries, or contributing to them ... this is me, online, today, and since ever!

.. and learning, and learning ...

Back in those days, every time I mastered some topic, another one was coming up harder to understand, harder to find proper online documentation, something we take for granted these days, and harder due concrete lack of time: I was a full time employee already and I needed to work because my studies were not cheap at all and internet was not cheap too, and in order to have a better connection I had to pay extra so that dual channel ISDN could have been possible and I could surf at the amazing speed of 128Kbps in download and 64Kbps in upload!
You read that right: 128 Kilobits per seconds, enough to also feel some sort of realtime zero-lag connection on Quake 3 Arena, a game part of my history too, and more than that, an inspiration about what's possible online even with very low bandwidth connections!
Anyway, my will to learn software and improve daily my skills was at its highest peaks, probably because it was the beginning of my career, most likely and also because it is still required, if you want to survive and be a good, updated, developer at any time in the SW history, to know what's going on around and where Software and Hardware are heading these days, your days, whenever you are reading this!
In few words Welcome to Software Development, nothing like you learn VBScript at Uni or at work once and you are good forever in your lifetime with your job ... if that's what were you looking for, I think I've bad news for you ...

Are *You* willing to learn ?

Apparently in modern software development, and somehow specially in one of the easiest out there, JavaScript development, the worst "curse" ever or the most used example about how hard is to be a software developer is represented by a tilde, a single ~ char apparently full of shame because developers don't understand what it means ... well, I don't want to start swearing randomly here, so I'll try to be calm and explain ...

As easy as this

The only possible falsy value in JS with a tilde, is the number -1 .. repeat with me:
the only falsy value with a tilde is -1
the only falsy value with a tilde is -1
the only falsy value with a tilde is -1

~(-1) === 0; // true
~(-1) == false; // true
Say that 3 times and Crockford will appear on the mirror!
Jokes a part, what does it mean? It simply means that every JavaScript method that returns -1 instead of a boolean false PHP style over a search, or an indexOf is performed over a string or an Array will result falsy when checked against the following:
if (~[1,2,3].indexOf(2)) {
  // YES, 2 is there!!!
  // because the result was !== -1
}

if (!~[1,2,3].indexOf(4)) {
  // NO, there's a NOT "!"
  // of course it's NOT there
  // !~ === NOT
  [1,2,3].push(4);
  // metaphorically speaking ... 
}
This is also usually called a semantic operation for the simple reason that:
  • you didn't put a not "!" operator upfront so you expect that to return truthy result
  • in case you did put a not "!" operator upfront, you'll see 99% of the time a arr.push(missingValue) following ...
so what are you exactly complaining about? The funniest thing ever is that people usually ask you to write this instead:
// they tell you not to write this:
if (~[1,2,3].indexOf(2)) {
  // yeah, it's there
}

// but to write this:
if ([1,2,3].indexOf(2) !== -1) {
  // yeah, it's there
}
Today you must have realized that comparing against !== -1 is the exact equivalent of verifying that the result was not -1 via tilde, because once again: only -1 is falsy after a tilde so indexOf result is truthy only when it's !== -1!

And this is not about being smart

It's rather about learning that some language does not use only +, -, *, and / operators as they taught us at elementary school ... the language has more and you should know more about the language you develop and work with instead of going "I don't understand! OMG, why is that and what it does" first time you see a different operator ... long story short: are you still willing to learn?
'cause next thing you gonna have problems with wil most likely be the proposed power operator, for all those times you didn't want to use Math.pow(num, radix) and you'll find handy to do x**radix instead ... uh wait, you don't know that symbol, it must be evil and/or smart, right?
What are you saying? Python did that before so it's OK? Then you learned something new anyway about the tilde today and in JavaScript, you should actually be happy if that's the case instead of moaning about it?

Not only the tilde

I've been working for many small, medium, and big companies, and the constant scenario is that someone, at some point, will mention sentences like the following one:
I had a problem and I decided to use regular expressions to solve it, so now I have two problems ...
... of course you have two problems if you don't understand regular expressions or you didn't think enough if that was the right case to use them ... here the simple proof: do this in a more efficient way (didn't mention easier, shorter, faster for argument sake but you know it):
function dropA(str) {
  return str.replace(/a/ig, '');
}

// later on in dante.js ...
dropA(divineComedy);
I am waiting here to see how better, faster, shorter, etc plus absolutely not error prone your logic avoided regular expressions ...

Master them instead

Yes, some dev probably does not know, need, or understand, regular expressions, and this is OK, as long as they are not trying at all costs to avoid them!
That would be the most unproductive, error prone, slower, and stubborn approach for a single or a team in case they do not just understand regular expressions ... I mean: no fucking body understand them after born, we all had to learn them so you can continue with your argument about "having two problems" but actually unless you really know regexp you should be the last one to complain about them.

back to tilde

Yes, if you are that good that not only you managed to successfully copy and paste some code that used a tilde but you actually investigated about its meaning in binary terms, you'll also realize that when an Array might contain a huge number of items that could grow unexpectedly, tilde is not what you are looking for *but* only in that case, even if we all like to dream our code will be used up to Math.pow(2, 32) times per each Array we create.

Long story short, if this is your problem, you are actually lucky you never had to deal with WebGL so far, because trust me tilde it's going to be the very last thing you could complain about if all this is about "things you just don't understand"! ( GLES wizardry! )

About the "copy and paste" tribe

Many times I've seen people demanding, complaining, insulting, after some code they copied and pasted from Stack Overflow or any other slightly CS related forum ... I wish we could consider these kind of persons outside the actual Software Developer circle and happily ignore them instead of promoting "write dumb to rule them all" articles all over?
How about we keep promoting Software for everyone to jump in and start ignoring or ditching people that are indirectly ruining this beautiful sector full of research, sometimes sacrifices, and luckily still most of the time: passion?

About daily tasks

When it comes to code reviews and developers that actually know what are doing, I also suggest to go easy with nitpicks because I've realized in my career nitpicks are so light and pointless in a product lifecycle that could only waste time for the product growth instead of actually helping code quality.
As example, if a Senior SW Engineer in your team writes:
if (!worked) return;
instead of:
if (!worked) {
    return;
}
without the JShint even complaining, that is fine and you should probably think about how many minutes, or hours, these silly things, when everyone absolutely understand in first place what's going on with the code, have been wasted just to nitpick stuff that for new comers, might actually be a chance to better learn what they are doing, instead of letting them think brackets solved the world ... of course they did when no tests were in place, if that's your only argument because something bad unrelated with brackets happened before :P

As summary

Please respect SW Developers and, if you consider that your job, respect yourself too.
So please let's all moaning less about basic SW Development concepts ... let's all talk about how to improve what's working already instead of how to welcome new copy and paste people.


Thank You!

Sunday, August 10, 2014

Auto instance via "use strict"

This is a very simple trick that works if you are sure your minifier will not remove any 'use strict' declarations in your scripts.

As seen in jQuery

This library is the most known/common example where $(something) will actually generate an instanceof jQuery variable even without using new.

Some background

Since basically ever, JavaScript constructors such Array, Object, Function and RegExp do not distinguish between new Array/Object/Function/RegExp or just the same without new, and there are exceptions for Date, where it always returns the same instance if invoked without new, and primitives wrappers such Boolean, Number, or String, where the meaning is very different: it's casting VS value wrapper when new is used.
This behavior could be somehow desired when we'd like to obtain the exact same return type when a generic constructor is invoked either via new or not.

Handy "use strict"

Because of its guard against the execution context, where this would be undefined instead of the global window object, we can use such behavior to simplify the famous pattern.
// basic use strict feature
function Constructor() {'use strict';
  return this || new Constructor;
}
This is basically the easiest way to replicate this pre-use-strict era pattern:
function Constructor() {
  return this instanceof Constructor ?
    this : new Constructor
  ;
}
The benchmark shows no impact on Safari, but quite a gap between the old and the new pattern in Chrome. Good news is, who cares, the trick is to write less and reduce code size so if it's even faster, it's just a strawberry on top.

A different behavior

In case somebody will use Constructor.call(anotherObject) the instance will be used inside the constructor instead of being ignored via good old pattern.
This is actually not necessarily an undesired side effect because it actually lets us reuse constructors to initialize properties with mixins too, in case the initializzation is needed.
// old pattern ...
function Constructor(value) {
  if (!(this instanceof Constructor)) {
    return new Constructor(value);
  }
  this.property = value;
}

// later on ...
var mixedObject = {};
Constructor.call(mixedObject, 123);
mixedObject.property; // undefined
Using initial pattern we basically do nothing except creating a new instance that will be lost in the process while with the pattern suggested via use strict things play nicer than before!
// use strict
function Constructor(value) {'use strict';
  if (!this) return new Constructor(value);
  this.property = value;
}

// later on ...
var mixedObject = {};
Constructor.call(mixedObject, 123);
mixedObject.property; // 123 <=== yeah!

No backward compatible!

As easy as that, in order to be able to use this pattern the engine must be compatible with use strict directive, which is actually not a big deal in nodejs or other modern server side engines, as well as most common browsers targeted for mobile apps or extensions.
In case you don't know about some target, do you remember the trick to know if the JS engine is compatible?
var hasUseStrict = (function(){'use strict';return!this}());
Please note that use strict brings other features too so be sure other behaviors won't affect your code logic.

Wait ... what about arguments?

There are two scenarios here, the one when it does not matter:
// use strict
function Constructor(a, b, c) {'use strict';
  if (!this) return new Constructor(a, b, c);
  // go on ... 
}
and the one where exact number of arguments matter:
// use strict
function Constructor(a, b, c) {'use strict';
  if (!this) {
    return Constructor.apply(
      Object.create(Constructor.prototype),
      arguments
    );
  }
  // go on ... 
}
Take care

Tuesday, July 15, 2014

A W3C Custom Elements Alternative

This W3C specification is awesome, and if you follow Alex Russell you know this has been probably his biggest obsession for years now: custom Web components, something even Internet Explorer 5.5 had, thanks to its Element Behaviors capability!

Many Articles, Poor Support :-(

Regardless the amount of articles about Web Components and a dedicated website for Custom Elements, browsers capable of supporting them natively are ... well, most likely none of them, specially on Mobile world.
This has at least 2 side effects:
  1. delayed adoption and/or interest from developers
  2. need for performant, not obtrusive, and reliable polyfills
Unfortunately, today there's no such thing ... like a plural of choices, and even Mozilla x-tag project, when it comes to Custom Elements, is based on the only polyfill you can find out there, the one proposed by Polymer framework ... however ...

Polymer Is NOT Standard .

Every developer I've talked about Custom Elements replied some how like "yeah, Polymer, I've heard about it ..." ... well, the bad news is that if you think about Polymer you have no idea about the proposed standard.
True is that the entire Web Components and Custom Elements "affair" comes from Google, and in the Custom Elements case, Dimitri Glazkov, a very nice dev that already helped me with few hints, is the main specs editor.

The Misleading Piece

Unfortunately most web articles about Web Components and Custom Elements end up talking or pointing at Polymer platform but this is indeed a platform a part, same as X-Tag, Ember or Angular would be, it's not the standard itself!
As result, most example you can read online are not exactly what W3C is proposing, rather what Polymer platform provides!
Also bear in mind, Custom Elements does not mean Web Components, the proposal is huge and we should rather learn more and be able to distinguish between these standards.

Custom Elements As In Polymer

The provided polyfill is a very nice piece of code, well documented, I believe well tested, but unfortunately incomplete.
As example, if you follow its building instructions you will end up requiring an extra MutationObservers polyfill that as first line assumes you are in ES6 and the WeakMap constructor is available.
The amount of code required to provide a proper WeakMap polyfill in engines where WeakMap is not supported results into an overbloated, probably unnecessary, and not so welcome entire new library to the plate ...
... and then there are web developers that actually care about code size and compatibility with not that old browsers too ... not willing to bring 2 third parts libraries in order to better support this brand new API ...

A Lightweight Alternative

During last week I've had a chance to experiment with some sort of cross domain Custom Element and I won't bother you with details since I'd like to share instead the library that only today I've managed to organize in a repository and test with all devices and browsers I could: let me introduce you my W3C Custom Elements Polyfill, and these are few features:
  • less than 2KB minified and gzipped without extra dependencies, you serve this file, you have it!
  • a wide range of old to modern mobile devices support ... iOS 5 and Android 2 are only few of them, IE9 for Windows Phone 7 made it too together with webOS 2!
  • focus on one task ... and while this sounds obvious, I don't think to use Custom Elements we need a proper, partial, cross browser fix for both MutationObservers and WeakMap ... but good news is, if you have already a patch for MutationObservers these will be used instead of old Mutation events API: it's a win-win!

Try It Yourself!

Not only you can test it directly, you can also read most famous articles and experiment just including the single file.

As usual, contributions are welcome, and I'll put your name in the MIT license too, no CLA required ;-)