Skip to content

Instantly share code, notes, and snippets.

@cowboy
Forked from padolsey/gist:527683
Created August 21, 2010 13:26
Show Gist options
  • Star 35 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save cowboy/542301 to your computer and use it in GitHub Desktop.
Save cowboy/542301 to your computer and use it in GitHub Desktop.
Very small IE detect (aka type coersion ftw)
// ----------------------------------------------------------
// A short snippet for detecting versions of IE in JavaScript
// without resorting to user-agent sniffing
// ----------------------------------------------------------
// If you're not in IE (or IE version is less than 6) then:
// ie === 0
// If you're in IE (>=6) then you can determine which version:
// ie === 7; // IE7
// Thus, to detect IE:
// if (ie) {}
// And to detect the version (after IE has been detected):
// ie === 6 // IE6
// ie > 7 // IE8, IE9 ...
// ie < 9 // Anything less than IE9
// ----------------------------------------------------------
// GOAL: the smallest possible minified size (without using conditional compilation)
// While using `with` makes automatic minification difficult (if not impossible)
// due to the fact that the minifier doesn't necessarily know which identifiers
// reference properties of the specified object versus variables in the scope
// chain, I'm using it here and minifying manually.
with ( document.createElement("b") )
// No curly braces needed for the `with` because only the following `for`
// loop (a single statement) needs to execute inside the `with`.
for (
// Initialize the for loop by declaring the `ie` var, setting its value to
// -1 (which will get incremented at least once).
var ie = -1;
// Increment `ie` and update the innerHTML of the element accordingly. If
// the browser is IE with a version greater than `ie`, "1" will be written
// into the element.
innerHTML = "<!--[if gt IE " + ++ie + "]>1<![endif]-->"
// Unfortunately, because testing innerHTML at the time of assignment is
// inadequate, a separate expression must be used. The comma operator allows
// both the preceding and the following expression to be evaluated, with
// only the last expressions's result affecting the for loop's condition.
,
// If non-IE (or a lower version IE), the innerHTML will be an empty string,
// which gets coerced to 0 (falsy) by the + operator. Otherwise, it will be
// "1" which gets coerced to 1 (truthy). Basically, as long as the innerHTML
// is "1", continue looping.
+innerHTML;
// Because `ie` is incremented in the condition, no increment expression is
// needed here!
);
// (It should go without saying that if the var was named `i` instead of `ie`,
// a few more bytes could be saved, but I'm saying it anyways, because that's
// how I roll)
// Minified (111 chars):
with(document.createElement("b"))for(var ie=-1;innerHTML="<!--[if gt IE "+ ++ie+"]>1<![endif]-->",+innerHTML;);
// Version without `with` in case that's how you roll (112 chars):
for(var ie=-1,b=document.createElement("b");b.innerHTML="<!--[if gt IE "+ ++ie+"]>1<![endif]-->",+b.innerHTML;);
@cowboy
Copy link
Author

cowboy commented Aug 21, 2010

My previous version was still quite small at 142 chars, because it used a closure, but the closure is really unnecessary in this case. View the live test page to see it in action. Also notice that ie === 0 in non-IE browsers.

@marcelkorpel
Copy link

Why do you use the unary plus operator in var ie = id > 5 ? +id : 0? It does nothing and adds a character to your minified version.

And why did you change the minimal IE version to detect to 6? IE 5 also supports conditional comments.

@cowboy
Copy link
Author

cowboy commented Aug 23, 2010

Marcel, I use + to cast id, which is a string, to a number. I changed the comment to more accurately reflect that this code detects a minimum version of IE6 (I don't really care about IE5 support).

@marcelkorpel
Copy link

Ah, I didn't know about the side-effect of typecasting of +. Indeed, according to the ECMAScript specification, + converts ToNumber(GetValue(expr)).

The only thing is, id is never changed into a string; only the innerHTML is.

@cowboy
Copy link
Author

cowboy commented Aug 23, 2010

In Chrome console, if you enter var b=document.createElement("b"); b.id=1; b.id, you get "1" (string).

@marcelkorpel
Copy link

Of course, I didn't think of the impact of the with statement.

@cowboy
Copy link
Author

cowboy commented Aug 23, 2010

Yeah, that's how I can get away with not needing a closure or temp var!

@balupton
Copy link

Great stuff, what's the license? Or is it so small, that it would fall under public domain?...

... also, how come var ie is inside the with, and id is missing var?...

@kflorence
Copy link

I believe he is accessing the id as a property of the element (element.id), so it does not need a var declaration.

@davidmurdoch
Copy link

121 chars: with(document.createElement("b")){for(id=-1;innerHTML="<!--[if gt IE "+ ++id +"]>1<![endif]-->",innerHTML>0;);var ie=+id}

I haven't tested it very much, just Chrome, IE8, and IE8 in IE7 mode; though it shouldn't differ to much from Ben's.

It will also go through 5 or so extra loops in IE.

@cowboy
Copy link
Author

cowboy commented Apr 8, 2011

David, I managed to get it even smaller, down to 112 chars:

with(document.createElement("b"))for(var ie=-1;innerHTML="<!--[if gt IE "+ ++ie+"]>1<![endif]-->",innerHTML>0;);

@cowboy
Copy link
Author

cowboy commented Apr 8, 2011

But if you can't stand the with, it's still pretty small at 113 chars:

for(var ie=-1,b=document.createElement("b");b.innerHTML="<!--[if gt IE "+ ++ie+"]>1<![endif]-->",b.innerHTML>0;);

And changing the var name from ie to i would shave off another 2 chars!

@davidmurdoch
Copy link

\o/ for Code Golf! 108 chars now:

with(ie=-1,document.createElement("b"))while(innerHTML="<!--[if gt IE "+ ++ie+"]>1<![endif]-->",+innerHTML);

p.s., this last one doesn't care about local scope; it will take up residence in your window. It will clobber window.ie if it already existed.

@cowboy
Copy link
Author

cowboy commented Apr 8, 2011

I'm not really down with the global var solution, as it would make this unsuitable for inclusion in production code.. but your coercing +innerHTML was awesome, so I added it into my gist. Sweet!

@davidmurdoch
Copy link

Yah, I got a little carried away there.

Now we wait for @jdalton to find the one use-case where it will break. haha. :o)

@cowboy
Copy link
Author

cowboy commented Apr 8, 2011

+1

@davidmurdoch
Copy link

@marcelkorpel
Copy link

Even better, you don't need explicit typecasting at all, just innerHTML will do the trick, too. ;-)

@cowboy
Copy link
Author

cowboy commented Apr 8, 2011

Marcel, have you actually even tried that cross-browser?

@marcelkorpel
Copy link

Yes, at least in FF4, IE8, IE8-acting-as-IE7, Chromium 10.

@kflorence
Copy link

with(document.body)for(var ie=0;innerHTML="<!--[if gt IE "+ie+"]>1<![endif]-->",+innerHTML;ie++);

97 chars. Tested in IE 6-8, FF and Chrome, needs to be above body tag.

@kflorence
Copy link

Also, firefox 3.6 needs the +innerHTML, can't use just "innerHTML"

@kflorence
Copy link

@kflorence
Copy link

Ah, I think I found out why. If you put that code in a script block before your body tag it will be executed before the body has content it seems... example

@Perelandric
Copy link

One very small correction in your code comments.

// If non-IE (or a lower version IE), the innerHTML will be an empty string,
// which gets coerced to 0 (falsy) by the + operator.

While it is the case for IE that innerHTML will be an empty string, for non-IE browsers you'll get the full HTML code comment:

<!--[if gt IE 0]>1<![endif]-->

...which is coerced to NaN by the unary + operator.

Of course the outcome is the same, as both 0 and NaN are "falsey".

@Jaybuz
Copy link

Jaybuz commented Oct 10, 2011

(ie <= 7) is causing an error in IE8:

'Undefined' is null or not an object.

@albell
Copy link

albell commented Apr 4, 2013

Such a sweet, sweet, slender piece of code. So.... what's the absolute smallest way to add detection for IE10 without conditional comments (not supported) or UA-sniffing? I think

document.body.style.msFlex

is the shortest :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment