// ---------------------------------------------------------- | |
// 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;); |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
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 |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
marcelkorpel
Aug 22, 2010
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.
marcelkorpel
commented
Aug 22, 2010
Why do you use the unary plus operator in And why did you change the minimal IE version to detect to 6? IE 5 also supports conditional comments. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
cowboy
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).
Marcel, I use |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
marcelkorpel
Aug 23, 2010
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.
marcelkorpel
commented
Aug 23, 2010
Ah, I didn't know about the side-effect of typecasting of The only thing is, |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
cowboy
Aug 23, 2010
In Chrome console, if you enter var b=document.createElement("b"); b.id=1; b.id
, you get "1"
(string).
In Chrome console, if you enter |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
marcelkorpel
commented
Aug 23, 2010
Of course, I didn't think of the impact of the |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
Yeah, that's how I can get away with not needing a closure or temp var! |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
balupton
Jan 23, 2011
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
?...
balupton
commented
Jan 23, 2011
Great stuff, what's the license? Or is it so small, that it would fall under public domain?... ... also, how come |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
kflorence
Feb 8, 2011
I believe he is accessing the id as a property of the element (element.id), so it does not need a var declaration.
kflorence
commented
Feb 8, 2011
I believe he is accessing the id as a property of the element (element.id), so it does not need a var declaration. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
davidmurdoch
Apr 8, 2011
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.
davidmurdoch
commented
Apr 8, 2011
121 chars: 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. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
cowboy
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;);
David, I managed to get it even smaller, down to 112 chars:
|
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
cowboy
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!
But if you can't stand the
And changing the var name from |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
davidmurdoch
Apr 8, 2011
\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.
davidmurdoch
commented
Apr 8, 2011
\o/ for Code Golf! 108 chars now:
p.s., this last one doesn't care about local scope; it will take up residence in your |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
cowboy
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!
I'm not really down with the global var solution, as it would make this unsuitable for inclusion in production code.. but your coercing |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
davidmurdoch
Apr 8, 2011
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)
davidmurdoch
commented
Apr 8, 2011
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) |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
+1 |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
davidmurdoch
commented
Apr 8, 2011
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
marcelkorpel
Apr 8, 2011
Even better, you don't need explicit typecasting at all, just innerHTML
will do the trick, too. ;-)
marcelkorpel
commented
Apr 8, 2011
Even better, you don't need explicit typecasting at all, just |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
Marcel, have you actually even tried that cross-browser? |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
marcelkorpel
commented
Apr 8, 2011
Yes, at least in FF4, IE8, IE8-acting-as-IE7, Chromium 10. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
kflorence
Apr 8, 2011
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
commented
Apr 8, 2011
97 chars. Tested in IE 6-8, FF and Chrome, needs to be above body tag. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
kflorence
commented
Apr 8, 2011
Also, firefox 3.6 needs the +innerHTML, can't use just "innerHTML" |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
kflorence
commented
Apr 8, 2011
http://jsfiddle.net/kflorence/cu9Pw/ -- 97 chars |
kflorence
commented
Apr 8, 2011
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 |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
Perelandric
Oct 9, 2011
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".
Perelandric
commented
Oct 9, 2011
One very small correction in your code comments.
While it is the case for IE that
...which is coerced to Of course the outcome is the same, as both |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
Jaybuz
commented
Oct 10, 2011
(ie <= 7) is causing an error in IE8: 'Undefined' is null or not an object. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
albell
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 :)
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 :) |
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.