// ---------------------------------------------------------- | |
// 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 5) then: | |
// ie === undefined | |
// If you're in IE (>=5) then you can determine which version: | |
// ie === 7; // IE7 | |
// Thus, to detect IE: | |
// if (ie) {} | |
// And to detect the version: | |
// ie === 6 // IE6 | |
// ie > 7 // IE8, IE9 ... | |
// ie < 9 // Anything less than IE9 | |
// ---------------------------------------------------------- | |
// UPDATE: Now using Live NodeList idea from @jdalton | |
var ie = (function(){ | |
var undef, | |
v = 3, | |
div = document.createElement('div'), | |
all = div.getElementsByTagName('i'); | |
while ( | |
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->', | |
all[0] | |
); | |
return v > 4 ? v : undef; | |
}()); |
This comment has been minimized.
This comment has been minimized.
hawt +1 |
This comment has been minimized.
This comment has been minimized.
This would be even awesomer with some in-line notes explaining the magic. :) Nice work! |
This comment has been minimized.
This comment has been minimized.
Pretty sweet, especially useful since I've seen some user agents where it has two different IE versions listed. http://www.zachleat.com/web/2008/10/19/jquery-bug-ie-reports-incorrect-browserversion/ |
This comment has been minimized.
This comment has been minimized.
A bit smaller and returns
|
This comment has been minimized.
This comment has been minimized.
neato |
This comment has been minimized.
This comment has been minimized.
@zach: Ben Alman, Resig and I revised the UA sniffing for jQuery 1.4 in January so the issue from your post has since been resolved. I'll take a crack at documenting James' original: var ie = (function(){
var undef, v = 3, div = document.createElement('div');
// the while loop is used without an associated block: {}
// so, only the condition within the () is executed.
// semicolons arent allowed within the condition,
// so a comma is used to stand in for one
// basically allowing the two separate statements
// to be evaluated sequentially.
while (
div.innerHTML = '<!--[if gt IE '+(++v)+']><i></i><![endif]-->',
div.getElementsByTagName('i')[0]
);
// each time it's evaluated, v gets incremented and
// tossed into the DOM as a conditional comment
// the i element is then a child of the div.
// the return value of the getEBTN call is used as
// the final condition expression
// if there is an i element (the IE conditional
// succeeded), then getEBTN's return is truthy
// and the loop continues until there is no
// more i elements.
// In other words: ** MAGIC**
return v > 4 ? v : undef;
}()); |
This comment has been minimized.
This comment has been minimized.
Yeah, the jQuery team was very quick to patch it up, just offering as evidence that UA strings can be corrupted. |
This comment has been minimized.
This comment has been minimized.
+1 on the hawtness |
This comment has been minimized.
This comment has been minimized.
Cool ! |
This comment has been minimized.
This comment has been minimized.
Nice comments Paul! |
This comment has been minimized.
This comment has been minimized.
this is hawt. My first inclination was to replace the d.isIE sniff for this, but have to consider CLA. bummer. |
This comment has been minimized.
This comment has been minimized.
To compliment Paul's explanation I will get a bit more specy. A while statement is made of the following parts In James' example spec-ifies to
and could be broken down to
and could be broken down even further. There is no semi-colon in the expression because that would create an |
This comment has been minimized.
This comment has been minimized.
Sorry about not adding comments to the original -- thanks Paul for adding some! Thanks @jdalton for the improvement! I forgot about the whole live NodeList thing... very cool! |
This comment has been minimized.
This comment has been minimized.
Awesome script! Your comment |
This comment has been minimized.
This comment has been minimized.
@james you should totally sign a CLA so this can get added to dojo. It's superduper easy! |
This comment has been minimized.
This comment has been minimized.
@marcel, thanks, corrected. @SlexAxton, Okay, where do I go to sign? |
This comment has been minimized.
This comment has been minimized.
@jdalton, just noticed -- with yours, since it returns I chose
|
This comment has been minimized.
This comment has been minimized.
@dperini, plus, using |
This comment has been minimized.
This comment has been minimized.
@james good point on |
This comment has been minimized.
This comment has been minimized.
@james http://www.dojofoundation.org/cla/ -- You can just scan it or take a picture of it or something. Then you can be a Dojo Committer! |
This comment has been minimized.
This comment has been minimized.
YUICompressor hates and ClosureCompiler strips (!) the /*@cc_on conditional compilation action.. Not the end of the world here, but fair warning. |
This comment has been minimized.
This comment has been minimized.
Why do you need that early exit anyway? What does it add, apart from a very slight optimization of a function that probably runs only once? |
This comment has been minimized.
This comment has been minimized.
@marcel I believe your suggestion is correct, comparing IE4 to a new browser is wrong anyway ;-)
should be just enough (and shorter). |
This comment has been minimized.
This comment has been minimized.
Just got rid of the early exit (with conditional compilation). @dperini, that'd return |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Really handy! Thanks |
This comment has been minimized.
This comment has been minimized.
slightly improve to get smaller: http://gist.github.com/548648 |
This comment has been minimized.
This comment has been minimized.
How about simply returning NaN instead of an undefined variable? |
This comment has been minimized.
This comment has been minimized.
Great stuff, what's the license? Or is it so small, that it would fall under public domain?... |
This comment has been minimized.
This comment has been minimized.
@balupton, no worries, public domain. |
This comment has been minimized.
This comment has been minimized.
Sweet thanks a lot! and thanks Paul for showcasing this in your latest video :-) |
This comment has been minimized.
This comment has been minimized.
This bit has actually been incorporated into https://github.com/slexaxton/yepnope.js in the optional !ie prefix. It's a fantastic bit of javascript. |
This comment has been minimized.
This comment has been minimized.
Came back to use this, since it's awesome. But I'm wondering why your counter starts at 3, when you return undefined for <=4. Shouldn't the counter start at 4? |
This comment has been minimized.
This comment has been minimized.
Because James uses a pre-increment to increment
so the first test actually runs with Would he have used a post-increment, then your assumption is correct, but it has the disadvantage that the version number should be decremented afterwards, otherwise the loop will end with |
This comment has been minimized.
This comment has been minimized.
Ah, sure. My bad. Since I've never encountered a false positive for $.browser.msie, I had used that to toggle the test, and only used this script as a more reliable way to find the version number. Thanks. |
This comment has been minimized.
This comment has been minimized.
Anyone know how to make this Lint? |
This comment has been minimized.
This comment has been minimized.
Why? This is valid JavaScript. JSLint is just very restrictive. |
This comment has been minimized.
This comment has been minimized.
@marcel: I didn't ask why... just wondered if anyone ported this to Lint-friendly code. |
This comment has been minimized.
This comment has been minimized.
No, you didn't, but I did. ;) Anyway, just work around the issues JSLint complains about; e.g., only use a comparison as the condition within parentheses and do the assignment inside a statement, like:
and make |
This comment has been minimized.
This comment has been minimized.
Unfortunately this won't work for IE10 as they've dropped support for conditional comments: |
This comment has been minimized.
This comment has been minimized.
That's hopefully a good thing since IE10 shouldn't need singling out compared to it's predecessors. |
This comment has been minimized.
This comment has been minimized.
Unfortunately IE10 still needs to be targeted. Here's on of my latest problem with all versions of IE (including R10 as of today): Works perfectly in Chrome/Safari and Firefox. |
This comment has been minimized.
This comment has been minimized.
"Not supporting transforms" is not an IE quirk. This is a case where feature testing would be much more appropriate than IE sniffing. |
This comment has been minimized.
This comment has been minimized.
That's not the problem. The rotation transform works in IE 7-10 with the supplied example. The problem is that using a transform with opacity and border-radius will mess up the look of the border. (The background won't be transparent.) border-radius works natively in IE9-10 but they both have the above problem. The easies solution is to skip the opacity, but the browser(s) needs to be targeted for this and thus it's a shame they've removed conditional comments... |
This comment has been minimized.
This comment has been minimized.
You generally won't have a ton of luck using old proprietary DX Transforms and mixing it with anything. It seems like comparing the DX and the CSS3 ones is a little flawed. It's also guaranteed to be phased out eventually. Something like: .no-css-transforms .flip {
background-image:url(flipped-badge.jpg);
} would be a safe way to not just back-fill IE 6-10, but also mobile browsers or any of the slew of browsers that have issues with transforms. |
This comment has been minimized.
This comment has been minimized.
Cool technique, does it matter if IE10 is not detected? |
This comment has been minimized.
This comment has been minimized.
Hmm, I wonder if this could be rolled into an IE CSS expression that adds classes to the document. That way HTML5 boilerplate could lose the comments in the HTML and instead shift it to the CSS. |
This comment has been minimized.
This comment has been minimized.
IE10 still supports JavaScript conditional comments, so you could add something like this right below this code snippet: // IE 10 no longer supports conditional comments in HTML, but does support JavaScript conditional comments
// This will have to be revisited once IE 11 comes out... :(
if (/*@cc_on!@*/false && !ie) {
ie = 10; You could potentially do user agent sniffing to ensure that it's indeed IE10. |
This comment has been minimized.
This comment has been minimized.
For all how what to detect IE10: (function() {
"use strict";
var tmp = (document["documentMode"] || document.attachEvent) && "ev"
, msie = tmp
&& (tmp = window[tmp + "al"])
&& tmp("/*@cc_on 1;@*/")
&& +((/msie (\d+)/i.exec(navigator.userAgent) || [])[1] || 0)
;
return msie || void 0;
})(); user-agent sniffing, yeah :(
And still like @Daniel15 said: |
This comment has been minimized.
This comment has been minimized.
Looks like I'm late to the party. Here's my party favor anyway. var ie = (function(){
// for-loop saves characters over while
for( var v = 3,
// b just as good as a div with 2 fewer characters
el = document.createElement('b'),
// el.all instead of el.getElementsByTagName('i')
// empty array as loop breaker (and exception-avoider) for non-IE and IE10+
all = el.all || [];
// i tag not well-formed since we know that IE5-IE9 won't mind
el.innerHTML = '<!--[if gt IE ' + (++v) + ']><i><![endif]-->',
all[0];
);
// instead of undefined, returns the documentMode for IE10+ compatibility
// non-IE will still get undefined as before
return v > 4 ? v : document.documentMode;
}() ); Compatible with "use strict" (tested in Firefox 22 and Chrome 27). Uses no user agent string sniffing. Also compatible with all known JS minifiers as it uses no IE-specific JavaScript comments. Minifies to 171 bytes. var ie=function(){for(var a=3,b=document.createElement("b"),c=b.all||[];b.innerHTML="<!--[if gt IE "+ ++a+"]><i><![endif]-->",c[0];);return 4<a?a:document.documentMode}(); Unfortunately, it's now so small that gzip -9 yields 175 bytes. |
This comment has been minimized.
This comment has been minimized.
I needed IE10 support, as I was using the imagesloaded plugin in combination with imgrefresh (https://code.google.com/p/image-refresh/) (so to refresh unloaded images in ie), as IE still has issues with cached images! So the check had to be extended to IE10. Here's the code. I'm not a JS guru, so I've probably brutalized it, but it does work now for IE10 -- based on Daniel15's Idea. If someone wants to make it all sparkly again, by all means. var ie = (function(){ var undef, v = 3, div = document.createElement('div'), all = div.getElementsByTagName('i'); while ( div.innerHTML = '', all[0] ) { ver = v; } //ie10 support if (/*@cc_on!@*/false && typeof ver === 'undefined') { ver = 10; } else { ver = 3; } return ver > 4 ? ver : undef; }()); |
This comment has been minimized.
This comment has been minimized.
Regarding IE 10 detection and following @Daniel15's idea, we can use @_jscript_version instead of the UA (see http://msdn.microsoft.com/en-us/library/ie/s59bkzce%28v=vs.94%29.aspx):
Note that we could only use that last if statement, but then that would return incorrect version numbers when changing the browser mode. As mentioned before, this may break in IE 11. |
This comment has been minimized.
This comment has been minimized.
Beware I wasted an awful of time on a IE issue related to requirejs trying to eval the last version of this gist submitted by @ecstaticpeon. So if you use this through requirejs and have a http://requirejs.org/docs/errors.html#fromtexteval error msg, it's definitely because of |
This comment has been minimized.
This comment has been minimized.
@nrako: thanks for the heads up. But adding a space like you did does break the code. Try it on http://jsfiddle.net/P5z4N/4/ |
This comment has been minimized.
This comment has been minimized.
@nrako: here is a different version that might work for you :) Try it on http://jsfiddle.net/e8G3S/1/
|
This comment has been minimized.
This comment has been minimized.
@adrien-be indeed it fail on IE10, the last code you sent is quite different it's solely useragent sniffing, and I still love the conditional comment better, I (and requirejs) just don't like the condition compilation stuff for IE10 detection. |
This comment has been minimized.
This comment has been minimized.
Smaller yet? https://gist.github.com/devxdev/6506658 I Can't test I'm on Ubuntu. maybe smaller if |
This comment has been minimized.
This comment has been minimized.
The expression in the while statement was done proper though for clarity I'd use a do-while. |
This comment has been minimized.
This comment has been minimized.
(+/-) from the grade listed. |
This comment has been minimized.
This comment has been minimized.
(+/-) from the grade listed. |
This comment has been minimized.
This comment has been minimized.
(+/-) from the grade listed. |
This comment has been minimized.
This comment has been minimized.
(+/-) from the grade listed. |
This comment has been minimized.
This comment has been minimized.
I wanted this script to include IE10+11 as well, and my tests works fine by just returning
|
This comment has been minimized.
This comment has been minimized.
So I tried the code above, also davidhellsing's version, and I tested this on ie8, and it always says it's version 7, when it's 8. So I don't think this works on ie8. |
This comment has been minimized.
This comment has been minimized.
Also, just tried it in ie10 and ie gets declared as undefined. |
This comment has been minimized.
This comment has been minimized.
@ttfkam Best Solution for IE10+ |
This comment has been minimized.
This comment has been minimized.
For any future spelunkers, the @davidhellsing version just above works fine on IE8 through IE11 |
This comment has been minimized.
This comment has been minimized.
If I'm testing IE11, but it's forced into ie8 via 'IE=EmulateIE8', this solution from @davidhellsing still show the IE version as 8, not as 11. Any thoughts? I want to determine if it's really IE10/11. |
This comment has been minimized.
This comment has been minimized.
You can use bowser. |
This comment has been minimized.
This comment has been minimized.
This is slick! |
This comment has been minimized.
This comment has been minimized.
Unfortunately IE>=10 don't have conditional comments |
This comment has been minimized.
This comment has been minimized.
The best option for IE / Edge these days is probably Layout Engine or something similar that uses JavaScript to detect browser features. User agents can be forged or altered so I wouldn't rely on UA sniffing. |
This comment has been minimized.
This comment has been minimized.
Maybe help: var ie = 'NotIE'; //IE5-11 |
This comment has been minimized.
This is hawt. I love the way you use the expression in the
while
statement though it could be done with ado-while
for clarity. Very cool :{D