Friday, January 23, 2015

JavaScript and the living ECMAScript Standard

ECMAScript 2015, aka ES6

For those who don't know yet, ECMAScript, also known as ES, is the specification that defines semantics, syntax, and behaviour of the JavaScript programming language.
The versioning of such specification has historically been represented by edition numbers: ES3, or 3rd edition, is the most used and compatible ECMAScript specification ever, making JavaScript virtually the most deployed programming language in the world, compatible and often mandatory on the Web, embedded or translated in IoT devices and developer boards, available on the server through various implementations and engines since 1999.
It has also been decided, when the current standard went out, that one of the prime-goals of the ES specification is to not break the Web, meaning being enriched in a backward compatibility way.

We are virtually in 2011 2009 under ES5.1 umbrella

The current "running" version of JavaScript is based on a modification of the original ES5 specification, called ES5.1.
ES 5.1 is dated 2011 but it's just a typo/fixing version of ES5 dated 2009.
It's the first specification that has been officially adopted in IE ditching the historically slightly different JScript engine used in IE8 and lower.

Despite it's been 6 years since it has been officially published, and considering that it took long time to be finalized since it came out after a "never made it" ES4 version, there are still few quirks in modern engines as you can see in this table. We are almost fully compatible cross platform with such specification dated 2009.
To give yourself a better idea on how long it takes to fully match a specification, regardless it's almost complete and out, just have a look at version 6 of the same table.

A confusing last minute naming change ... for good

As some sort of curse, the JavaScript name and everything around it has been confusing since the beginning of the time:
from The World's Most Misunderstood Programming Language by Douglas Crockford

JavaScript, aka Mocha, aka LiveScript, aka JScript, aka ECMAScript, is one of the world's most popular programming languages. ...

The Name
The Java- prefix suggests that JavaScript is somehow related to Java, that it is a subset or less capable version of Java. It seems that the name was intentionally selected to create confusion, and from confusion comes misunderstanding. JavaScript is not interpreted Java. Java is interpreted Java. JavaScript is a different language.

JavaScript has a syntactic similarity to Java, much as Java has to C. But it is no more a subset of Java than Java is a subset of C. It is better than Java in the applications that Java (fka Oak) was originally intended for.

JavaScript was not developed at Sun Microsystems, the home of Java. JavaScript was developed at Netscape. It was originally called LiveScript, but that name wasn't confusing enough.

The -Script suffix suggests that it is not a real programming language, that a scripting language is less than a programming language. But it is really a matter of specialization. Compared to C, JavaScript trades performance for expressive power and dynamism.
Now ... think about it ...
Once finally clarified for some, but not for everyone, what JavaScript is, It took years of community effort to explain what ECMAScript is about, and how to reference a specific version of it so that in 3 letters we can describe the past, ES3, the present, ES5, and the future, ES6.
People keep posting ES6 related things on the web! There are websites named after ES6, there are talks on YouTube, and in Dr. Axel Rauschmayer case, as well as other authors, there are books titles that would like to be as accurate as possible for credibility sake of the author, at least, and for converging within the community about a single name to specify a list of expected features.

This is not just me being a drama queen as someone might think or even laugh reading that Axel's question in es-discuss related thread, this is also a concern for libraries shelves or articles and blog posts that will be considered outdated before vendors will even be fully compatible with the mentioned year.
It will take years indeed before the ES6 table will become as green as the ES5 one, and it will take years to explain that to look at what the web called ES6 for 2 years has been renamed into ECMAScript 2015.

Apparently toward a year-based label naming convention anyway

So the reason behind this renaming is not to convince the rest of the world that in es-discuss they sell good stuff to smoke, rather to promote a faster rolling release cycles which is actually good since browsers implement whatever they want in the order they want anyway.
Chromium has already a presumably "ES7" Object.observe but still no bloody Proxy in its engine, so saying Chrome is targeting ES6 is basically telling a lie.
Going to a year-based naming convention might be more confusing for developers, they have to master features detections more and more moving forward with engines fragmentation based on rolling specifications anyway, but it could be good to define matching point for vendors and their engines.

What's the bummer

ES5 was the first attempt to improve JavaScript since 1999. 10 years later it came out nice, non breaking, and with tons of good new features most books and blog posts still don't fully know. ES6 race, together with the already widely discussed ES7 or however it will be called, is being a bit more anarchic.
JavaScript is probably the closest programming language to the utopia "write once, run everywhere". The amount of fragmentation that tripled with the Mobile Web era has never played a "fun to deal with" role for developers. They are sick of inconsistencies across platforms, they also are sick of engines stack in the past, as the io.js effort already demonstrated.
The community knows what it wants, and we are all thankful for the incredible effort TC39 and es-discuss ML is putting to keep developers updated, part of the specification, and informed of what's going on, but deciding that specs MUST roll out no matter what each year does not give me any more confidence I can actually use anything cross platform anymore.
Numeric edition of the specifications were probably not perfect, but as main milestones, as main deadline, these have done a pretty good job in describing expectations and set of features ... a year ? What a year would tell you, every year is just another year ... no milestone achieved, no idea how to measure compatibility, and not feeling like the following way to talk about features would be better than what we have now. Well, put in this way, at least now there will be less surprise whenever we'll find out that people started talking about ECMAScript in YYYY units.h3

... and the ISO Standard ...

As Allen pointed out in his comment there is also a document representing the third submission of the ECMAScript as ISO/IEC 16262 standard, marking the current standard known as 16262:2011 which is about ES 5.1.
For those thinking that it would then be that simple and fair to name JS same as C++ not only the current JS should be called JS11, just to create some extra branding confusion, but there are already versions of JS called js17 and js24, these are SpiderMonkey implementation of the JS engine, often used as utilities in Linux.
If ES6 will be proposed as ISO standard it will be known as the fourth submission for ECMA-262-6 document as standard ISO/IEC 16262 in 2015.
So what's the other problem with year-based release? Mostly this: And at this point, if ES7 or 7.1 will be submitted in 2017 then we'll already have confusion with JS17 as mentioned before but the good news is that at least, the official ISO standard could play the milestone role I'd like to refer when I am talking about features.
In that sense, in that case, I personally wouldn't mind calling it ES15, ES17, ES20, referring to the ISO standard.

Wednesday, December 03, 2014

Toward New Adventures

TL;DR this is some sort of biography of mine which aim is to explain my decision to leave Twitter.

When in 2007 I moved to London without any concrete job offer it was after 6 months in Lugano, Switzerland, and 2 years of freelancing attempt made in Italy, a country at that time not really prepared for modern Web standards or the Mobile / IoT era.

The Great London

In those days when I was already writing and reading everything in Engligh (or some sort of) I could not speak a word of it and decided to do that kind of full immersion you have to do if you really want to learn a new language: avoid at all costs people that speak your language => avoid italians!!!
I was doing it well while I was paying by my own a full time English course, surviving in London as best as I could, considering how freaking expensive this city has always been!

Not only it has been a great new open minded experience, I've actually met best international mates at that time!
I've also passed my first job interview in a foreign language ... actually, my first technical job interview of all times since in Italy, back in those days, these were not common in this field and you could not find much if not being friend of a friend or relative to the random boss ... anyway ...

The career possibilities and the amount of overall opportunities this city offered to me those days were amazing, so amazing, that other companies from other European countries started contacting me; probably after seeing some result of my improved technical skills together with my improved foreign spoken language (still sort of).

In 2008 I was already dealing with the Mobile Web world and devices running something like Android 1.5 ... devices you cannot believe how ugly could be! Actually, let me disturb your mind with the following image representing my precious in those days:

you are welcome!

The Amazing Berlin

When the HR contacted me from Germany asking me to relocate to Berlin, in a city I've never seen before, for a language I've never ever learned properly even living there (almost everyone speaks English there, yay lazy me!), I haven't thought twice about the offered opportunity.

NOKIA has been indeed the biggest corporate I've worked for so far and its Berlin's offices a great place to work. I've been doing Maps and Mobile Web R&D for years there, ending up starting with other buddies the first large scale and Mobile Web performance oriented HTML5 Map application these days still known as here.com

That being said, when you're contacted from the number one portal of all social networks, and to live in a sunny and beautiful country as California is, it's hard to not try and see how it goes ... right ?

meanwhile ... in Dublin

I've been in Palo Alto for no longer than a weekend + a Monday and I should have realized going in the US ain't simple matter: almost every new recruited developer of the "rest of the world" have to be "parked" somewhere in the world until that day US opens door to H1-B visa applications, also with the possibility to not be accepted, having a blocked Passport at the US Embassy or similar stuff ... oh dear ... at least I've had the opportunity to spend 3 months in Dublin, which is a beautiful city in a crazy "wonderland like" country: Ireland!!! I've been traveling this country every weekend I could and there's not a single boring or not extraordinary place I remember ... just go there and visit it 'cause no words of mine could describe its beauty!

... passing through the Bay Area

As opposite to the never sleeping, rightly chilled and windy San Francisco, Menlo Park, where I've been working at Facebook Head Quarter, and Mountain View, where I've been living for few weeks, can be described as the most quiet places in one of the most welcoming climate I could experience so far. So quiet that if you like going out without having the paranoia to drive a car, you can shoot yourself on your toes just to have some extra fun ... no, really ... too damn quiet!!!

Incredible San Francisco

Once moved into SF in a lovely flat from year 1900 and at the starting of Haight & Ashbury, I started commuting to MP every day without problems since all evenings and weekends in the city were the best I could ask for!

During those days I was working together with the great team behind the Mobile Web oriented m. Facebook site. At the time I just joined the team for few weeks and things were exciting as hell but then something happened, something I wasn't expecting at all ... something that let me think a lot about why I was there and what I've been working on for years: Web standards and HTML5, in order to reach every person on the world, where every person means also all without a bloody expensive mobile device!

There have been honestly more to this single fact that made me change direction but let's say that knowing I would not have been stayed in the US for long time, I could choose between FB or a company strongly present on Web and its Mobile counterpart, which aim is to reach every person on the planet, and which Head Quarter was basically beside my door bell ... Ding Dong ... oh, Hi Mobile Web at Twitter !!!

what's cool about Mobile and IoT

First of all, you have to really forget all solutions developed last 20 years for Desktops: these don't work, are mostly superfluous since it's a relatively new start based on modern standards, and constrains are completely different.
Screen size, interaction, all possible quirks, premature APIs but way more reliable DOM, a small amount of RAM and slower possibly single core CPUs; if you've been developing for Desktop sites only you have basically no idea how different is the Mobile world, and if you think about Internet Of Things devices you are even further: every superfluous JSON.parse or generic object copy/clone for often redundant abstraction reasons *will* be a problem!!!

The TL;DR story behind mobile and IoT development is that it's challenging: you have to reduce operations and bytes at their possible minimum, also eventually resulting in blazing fast applications that will run smooth as hell on every cheap Desktop you can imagine so ... it's actually a win/win if you think about it!

There is also a lot of daily inevitable myth buster about most micro benchmarking people are so secure about, where "getters are slower than properties" arguments might cause a huge laugh since functions can be executed million times per second on crappy HardWare and, if everything else is badly architected, a getter is just the last problem you have for your business.
I remember me implementing a lazy runtime .super(argN) property resolver that never slowed down a thing and was relying on the arguments.callee.caller property to discover at runtime inheritance when necessary and as lazy utility ... no kidding, you've probably been worried or been told to avoid these things like poison, you don't know these have been used in production on the worst possible Mobile Hardware and without causing a glitch for years in one of the most visited existing sites!

Back to my story ...

US visa: a double face monster

While I'm very grateful for the incredible opportunity these US companies gave to me, I must say the visa situation in the United States is just ridiculous as fuck.
Not only after taking 6 months to collect all possible needed documentation in order to be approved for a H1-B, the green card process asked me even more documents, as if it was OK for me to be a tax payer without them being sure about who I was and what I was doing ( why asking again same shit otherwise ... ) but due these kind or improbable operations it took 2 years only to hear the message: "we can start with the Green Card process, it'll take probably a year and they might ask more documents" ... well, you know what US? Keep it for now, thanks!

If you work on Mobile Web, in a field that has seen its first immature light in 2005, and you are applying for a green Card as Mobile Web Expert, you must know that if you don't have a non existent in this world Mobile Web related degree, US offices will ask you to provide at least 8 years of experience on the field with old time companies original labelled papers, but with today dates and signatures ... as if nobody knows this is the fastest field on earth and companies I've been working for *ages ago* might not even exist anymore ... right?

Moreover, if it happens that you are married, your partner will have a lovely H4 visa which is the most ridiculous permit ever: your partner cannot do interviews, cannot work, cannot even do charity or put anything work related in the CV ... it can only eventually study and ... I guess cook and clean the house or make babies as I believe a H4 person is suppose to do ... I call it bullshit!

As summary, if you sum up the inability to provide concrete and real Mobile Web experience since 2005 and have to wait at least another year plus a partner once upon a time completely independent and with already two masters and 4 fluently spoken languages, so that going back to school wasn't exactly the most desired situation, and after dropping already a career in order to follow me, you realize that having the opportunity to go back in Europe and be free from all this would most likely come into your mind ...

Back in London!

Twitter have demonstrated once again to be awesome and to truly care, giving me the opportunity to join the amazing TweetDeck team in London that luckily was looking for a Web dev.
You know, they could have told me: "you know what? bye bye!" instead and I would have understood.
I must admit that after leaving Twitter, and after years of job offers from any company I could think of, I wasn't sure I would have gone anywhere else. Twitter is a great place to be and I've met great people in both San Francisco and London office. Tons of shit to learn, tons of challenges and a lot of freedom within the company where you can decide what to do and with who, in my case I've been lucky enough to even choose the place: London!

Toward New Adventures

These few months spent with a team able to create one of the coolest Desktop Web App I've ever dealt with has been surely memorable and also extremely intense. Going back from 6 years of Mobile to Desktop thought ... also brought me back to a place I've happily abandoned, but obviously not forgotten, years ago.
I can really work on Desktop web, I've even created polyfills for IE8 and IE9+ on DOM4 but unless it's for fun for some crazy new project, I am not sure I am capable of working on Desktop for long time so ...

I had to be honest to myself: the day I've realized I was working against my real interests, also putting less enthusiasm and effort than I'm used to, possibly affecting the team of excited and caring developers around me, I decided to be honest with the company that took care of me for the last two years and communicate it was time for me to go!

I will start fresh in 2015 by my own writing a book first, since few editors already asked me to for months now, and go on with Mobile and IoT development ( I am compiling natively on a Raspberry Pi my own JS oriented Operating System right now ... I mean, this is who I am, time for Web Desktop Apps is kinda gone for me but I love everything about Web and will support it anyway! )
Sometimes I guess one has to follow its instinct, and since this city has been my start point for 6 years of corporate related development, maybe it'll be a great start point for next 6 years of mobile revolution?

Put in this way, at least I'll have more time to blog about all crazy things I've been blogging these years :D

Thank you Twitter and thanks to all colleagues I've been hacking with last years!

Tuesday, October 14, 2014

Unusual tricks via Array .some()

A very good reason to use Array#some instead of forEach is that once a single truthy value is returned the loop simply stops.

This is not only more efficient, but also way more powerful than .indexOf(value) or eventually .contains(value) thanks to the callback that gives us the ability to perform any sort of synchronous check:
// entering in a chat room
if (chatRoomUsers.some(function admin(user, i) {
  return user.isAdmin;
})) {
  console.log('Watch out, this room is moderated!');
}
chatRoomUsers.push(you);
chatRoomUsers.forEach(
  room.sendEachMessage,
  you.name + ' entered the room'
);

/* example of room.sendEachMessage
Room.prototype.sendEachMessage = function (user) {
  user.sendMessage(this);
};
*/
The inevitable unfortunate caveat with .some(), compared to an .indexOf() approach, is that the returned value is either true or false, but when it is true we need eventually to loop that very same collection again in order to find the element we might want to keep in any sort of "should contain only one element per type" situation, as a list of users or products usually is.

1. A classic outer scope variable approach

The most obvious but tedious, boring, and quite error prone approach we could think about is the following:
// generic list of users
var lotteryUsers = [
  {ticket: 'Z1023', name: 'Z'},
  {ticket: 'AR1J5', name: 'F'},
  {ticket: 'F89DD', name: 'X'}
];

// the outer scope variable
var index;
if (lotteryUsers.some(function (user, i) {
  index = i;
  return user.ticket == this;
}, 'AR1J5')) {
  console.log(
    'Congratulation ' +
    lotteryUsers[index].name
  );
}
A simple way to avoid that reassignment each time could be doing it only on success.
lotteryUsers.some(function (user, i) {
  return user.ticket == this &&
         ~(index = i);
})
The ~ will simply ensure that the returned value will still be truthy, since any index, zero included, will be converted into its (i + 1) * -1 counter part so that 0 will be -1, a truthy value, 1 will be -2, still truthy ... and so on. We'll check later performance against always reassigning.
Another alternative could be used when functions are recycled instead of created each time.
if (lotteryUsers.some(lotteryWinner, ticket)) {
  console.log(
    'Congratulations ' +
     lotteryUsers[lotteryWinner.index].name
  );
}

// anywhere it is defined
function lotteryWinner(user, i) {
  return user.ticket == this &&
         ~(lotteryWinner.index = i);
}
In latter case the win over the outer scope variable and the tilde ~ trick works pretty well combined.

2. A common case based on RegExp

Since regular expressions update results in the global object each time, we can actually use this code to understand, as example, if a node program.js has been called with -j4 or --cpus=2 arguments, in order to limit the usage of the cluster module:
var numOfCPUs = process.argv.some(
  // the testing function, same RegExp each arg
  function(arg){return this.test(arg)},
  /(?:-j|--cpus=)(\d+)/
) ?
  // if it was true, we can use
  // the value contained in the $1 match
  parseInt(RegExp.$1, 10) :
  // otherwise we can require a module
  // and grab all the CPUs
  require('os').cpus().length
;

// in case we are in multi core env
if (1 < numOfCPUs) {
  var i = 0, cluster = require('cluster');
  if (cluster.isMaster) {
    // go multi core
    while(i++ < numOfCPUs) cluster.fork();
  }
}
Since the nature of the RegExp is this one since about ever, I wouldn't mind using a convenient and semantic approach recyclable per each different case:
// it would be untouched anyway ...
RegExp.test = function (v) { return this.test(v); };

// for any similar case 
var numOfCPUs = process.argv.some(
  // same function, different tests
  RegExp.test,      /(?:-j|--cpus=)(\d+)/
) ?
  parseInt(RegExp.$1, 10) :
  require('os').cpus().length
;

3. An index solution based on RegExp

We have reached the final trick of this post, the one that will combine the need to verify a generic value of an Array and store the index without bothering the outer scope or the function itself, suitable then with inline functions too.
if (lotteryUsers.some(function (user, i) {
  return user.ticket == this &&
         /\d+/.test(i); // <== see this ?
}, 'AR1J5')) {
  console.log(
    'Congratulation ' +
    // this is how you grab it ;-)
    lotteryUsers[RegExp['$&']].name
  );
}
Not only the regular expression inside the some(cb) loop will be created only if a check will be truthy, but we don't need to create outer scope variables or reachable callbacks since RegExp at the end will instantly give us that result.

Caveat

This works only if absolutely nothing else creates or use regular expressions between some() and the moment you address the result so ... do not ever call something else before you have retrieved the expected object, others pieces of code might be based on the same trick.
// GOOD
var value = arr.some(check) ? arr[RegExp['$&']] : null;

// BAD
if (arr.some(check)) {
  update(somethingElse);
  controller.emit('found', arr[RegExp['$&']]);
}

Performance

In order to have as many random cases as possible, I've added a test in jsperf.com which aim is to try all these approaches and see which one wins.
I think that's very irrelevant this time, since all approaches are mostly equivalent, but at least we have some little proof whatever we need, will be good for that case.

P.S. yes, you might have different results every single time you run that bench, it's part of the real world ;-)

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.