Monday, February 10, 2014

Deciphering IE10 popular check syntax

Lovely Microsoft decided to remove support for conditional comments in IE10. So what to do when for whatever reason we need to target this browser and only this browser? There are different ways. One interesting method I would like to discuss is use of self invoking function as:

Function('/*@cc_on return document.documentMode===10@*/')()

In IE10 this will return true and in a code might be used as:

if(Function('/*@cc_on return document.documentMode===10@*/')()) {

$("html").addClass("ie10");
ie10=true;
}

If you are after quick solution its as easy as copy and paste (or try this if(/*@cc_on!@*/false && document.documentMode===10){}). Some might wonder though what exactly this twisted syntax is. Lets try to decipher it step by step. So we trying to understand:

Function('/*@cc_on return document.documentMode===10@*/')()

Right, lots happening here, self invoking function, conditional compilation and what not. Lets start from something easy, consider the code:

var doh=function() {
         alert('DOH!');
}

doh();

This will create a function object and alert DOH! on the screen. Because its a function JS allows us to call it as doh(). Another way of creating function object is via Function constructor as below.

var doh=Function("alert('DOH!')");

doh();

We can still call doh() with no problem. The difference is that this time the body of a function is passed as an argument to Function constructor. 

Keep in mind that there are more differences that you need to be aware when deciding on using constructor syntax. For details I would recommend reading MDN docs for our purposes however all you need to understand is that body of a function can be passed as an argument to a Function constructor.

Easy stuff so far. Now lets make this function self invoking. All we need to do is:

Function("alert('DOH!')")();

We simply instantiating a function object and invoking it right away. When you execute the line it will pop alert on the screen as in previous examples. Very useful construct indeed. Now we might as well replace our alert with /*@cc_on return document.documentMode===10@*/ getting back to our original code:

Function('/*@cc_on return document.documentMode===10@*/')()

Now, what exactly is all this /*@cc.... voodoo you ask? Well, Microsoft folks came up with JScript which is their implementation of JavaScript. JScript also supports something called conditional compilation. You can think of it as sort of conditional comments but for JavaScript (in IE). As per MSDN @cc_on activates conditional compilation within comments in a script so in IE<11:

Function("/*@cc_on alert('DOH!')@*/")()

Will alert DOH!, all other browsers will recognise the function body as a comment only. Now replace alert with our return statement and you got yourself check for IE10 ready to use. 

Furthermore, as I found out skipping cc_on still gives the same results so in my code Function("/*@ alert('DOH!')@*/")() also does the trick. 

I know what you thinking now.. You can check for any IE with this method. From my experiments however, despite of what MSDN documentation is saying I learned that conditional compilation is not supported in IE11. Oh well, I'm sure MS will come up with more conditional improvements soon that will make our lives (not necessarily) easier.

No comments:

Post a Comment