Add Class for different browsers - javascript

I know this is an old question. I want to add browser specific classes for different browsers mainly for IE versions.
I used below mentioned code:
<!--[if IE 7 ]> <html dir="ltr" lang="en-US" class="ie ie7 lte8 lte9"> <![endif]-->
<!--[if IE 8 ]> <html dir="ltr" lang="en-US" class="ie ie8 lte8 lte9"> <![endif]-->
<!--[if IE 9 ]> <html dir="ltr" lang="en-US" class="ie ie9 lte9"> <![endif]-->
<!--[if (gte IE 9)|!(IE)]><!--><html dir="ltr" lang="en-US" class="not-ie"><!--<![endif]-->
Here problem is now conditional comments are gone form ie10+ and I want specific class for all ie versions. Even it would great if I also get class for webkit and moz browsers.
Purpose of this to remove all css hacks from my existing stylesheet.
I want something should work like this and JScript solution is also acceptable.
<!--[if IE 7 ]> <html dir="ltr" lang="en-US" class="ie ie7 lte8 lte9"> <![endif]-->
<!--[if IE 8 ]> <html dir="ltr" lang="en-US" class="ie ie8 lte8 lte9"> <![endif]-->
<!--[if IE 9 ]> <html dir="ltr" lang="en-US" class="ie ie9 lte9"> <![endif]-->
<!--[if IE 10 ]> <html dir="ltr" lang="en-US" class="ie ie10"> <![endif]--> <!--no more work for 1e10+ -->
<!--[if IE 11 ]> <html dir="ltr" lang="en-US" class="ie ie11"> <![endif]--> <!--no more work for 1e10+ -->
<!--[if !IE]><!--><html dir="ltr" lang="en-US" class="not-ie"><!--<![endif]-->

In javascript you can use the navigator.userAgent variable and check if it match the IE user agent (MSIE ** or Trident/**)
Warning : Trident is the new way to check for IE:
var newIEReg = new RegExp("Trident\/([0-9]+)\.0")
var oldIEReg = new RegExp("MSIE ([0-9]+)\.[0-5]+")
var ieVersion = -1;
if(navigator.userAgent.match(newIEReg))
{
ieVersion = parseInt(newIEReg.$1) + 4;
}
else if(navigator.userAgent.match(oldIEReg))
{
ieVersion = parseInt(oldIEReg.$1);
}

Use following JavaScript code, it will add IE version class in HTML tag:
Source:
(function () {
var v = 3,
div = document.createElement('div'),
all = div.getElementsByTagName('i'),
browser,
isIE;
while ( div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->', all[0]);
v = v > 4 ? v : document.documentMode;
if (v) {
browser = " ie"
for(var i = 5; i<12; i++){
if(v < i) {
browser += ' lte-ie' + i;
}else if (v > i) {
browser += ' gte-ie' + i;
}else if (v == i) {
browser += ' ie' + i;
}
}
isIE = {
"version" : v
}
} else {
browser = ' not-ie';
isIE = false;
}
document.documentElement.className += browser;
window.ie = isIE;
}());
Minified:
(function(){for(var a=3,b=document.createElement("div"),c=b.getElementsByTagName("i");b.innerHTML="\x3c!--[if gt IE "+ ++a+"]><i></i><![endif]--\x3e",c[0];);if(a=4<a?a:document.documentMode){b=" ie";for(c=5;12>c;c++)a<c?b+=" lte-ie"+c:a>c?b+=" gte-ie"+c:a==c&&(b+=" ie"+c);a={version:a}}else b=" not-ie",a=!1;document.documentElement.className+=b;window.ie=a})();
Comment:
Since the script is supporting IE5 and above, I'm keeping all version detection. It may not be useful for you but someone else can find it helpful. And there is no harm of having extra CSS classes.

Each browser has a user agent, so you can use something like following:
var user_agent = navigator.userAgent;
if(user_agent=="BROWSER_USER_AGENT"){
// your code
}
The user agents list is available online.

Main Solution:
I forgot where I got this function so I can't properly give credit to it but it works really well:
function getInternetExplorerVersion() {
var rv = -1; // Return value assumes failure.
if (navigator.appName == 'Microsoft Internet Explorer') {
var ua = navigator.userAgent;
var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
if (re.exec(ua) != null)
rv = parseFloat(RegExp.$1);
}
if (rv > -1) {
return rv;
}
else {
return 0;
}
}
So what you can do with this is:
if(getInternetExplorerVersion() == 6) {
$('head').append('<link id="styles" rel="stylesheet" type="text/css" href="/ie6Styles.css" />');
}
Or something along those lines.
Other Solutions:
For other browsers you can also do the following:
var is_chrome = navigator.userAgent.indexOf('Chrome') > -1;
var is_explorer = navigator.userAgent.indexOf('MSIE') > -1;
var is_firefox = navigator.userAgent.indexOf('Firefox') > -1;
var is_safari = navigator.userAgent.indexOf("Safari") > -1;
var is_Opera = navigator.userAgent.indexOf("Presto") > -1;
var is_Silk = navigator.userAgent.indexOf("Silk") > -1;
var is_Kindle = navigator.userAgent.indexOf("Kindle") > -1;
and I prefer these for iPads/iPods/iPhones:
if (navigator.userAgent.match(/iPad/)) { iPad = true; }
if (navigator.userAgent.match(/iPhone/) || navigator.userAgent.match(/iPod/)) { iPhone = true; }
Modernizr works great, but it only lets you know if a browser can handle certain features. Sometimes you actually have to target a specific browser for other fixes, like styles. This is where any of the above solutions can come in really handy. Good luck and let me know if you have any questions.

You can opt for some sort of JavaScript detection, but that would be beating around the bush and not dealing with the problem directly. It is what's usually called a band aid fix.
You shouldn't have to use hacks for IE11, IE10 and even IE9. They are fairly competent and standards compliant browsers.
I would look into solving the issues at their core - clean up and simplify your markup, make sure it validates, all tags are closed, declare dimensions, use a CSS reset, clear your floats etc.
That's if your issues are layout related.
If they aren't and you are using some bleeding edge functionality that's not supported everywhere, use feature detection - not browser detection.
This is the exact reason why Microsoft stopped supporting conditional comments. This is also why they changed the User Agent in IE11 to completely omit the fact that the browser is in fact IE.
They did it to encourage proper feature detection i.e Modernizr and not UA sniffing, as it's a bad idea.

See this JSFiddle for an example.
This supports IE 7 - 11, WebKit (Chrome, Safari etc.) and Gecko (Firefox etc.).
Detect the user agent with JavaScript and apply a class to the body depending on which browser:
<script>
var ua = navigator.userAgent;
if (!ua.contains("MSIE")) { // If it doesn't contain MSIE
document.body.classList.add("not-ie");
if (ua.contains("(Windows NT 6.3; Trident/7.0; rv:11.0)")) {
// IE11 pretends to not be IE and doesn't contain MSIE in the
// default user agent, but it contains the string above
document.body.classList.remove("not-ie");
document.body.classList.add("ie", "ie11");
} else if(ua.contains("Gecko")) {
document.body.classList.add("gecko");
} else if(ua.contains("WebKit")) {
document.body.classList.add("webkit");
}
} else {
document.body.classList.add("ie");
if (ua.contains("11.0")) {
// Just in case we're using an alternative user agent
document.body.classList.add("ie11");
} else if (ua.contains("10.6") || ua.contains("10.0")) {
document.body.classList.add("ie10");
} else if (ua.contains("9.0")) {
document.body.classList.add("ie9");
} else if (ua.contains("8.0")) {
document.body.classList.add("ie8");
} else if (ua.contains("7.0")) {
document.body.classList.add("ie7");
};
};
</script>

Some references to get you going:
http://blog.tcg.com/tcg/2012/08/mobile-browser-detection-and-redirects.html
Here are a few other sites to check:
http://blogs.msdn.com/b/ie/archive/2011/04/15/the-ie10-user-agent-string.aspx
How to write specific CSS for mozilla, chrome and IE
http://bastianallgeier.com/css_browser_selector/

Related

Instead of using prefixes I want to ask site visitors to upgrade their browser

I'm re-building a site using CSS flexbox.
In checking browser compatibility, I see that flexbox is supported by all modern browsers, except that Safari 8 and IE 10 require vendor prefixes.
In checking Google Analytics, I see that 96% of site visitors in the last 6 months use browsers that fully support flexbox. The remaining 4% use browsers that require prefixes or provide no support.
Since we're talking about 4% of users, and the number will keep getting smaller, (and I like to keep my code as clean and simple as possible), I'm considering not using prefixes, and instead asking users to upgrade their browsers.
How can I target older browsers in order to display a message to users asking them to update their browser?
Here's what I have so far:
<!--[if IE]>
<div class="browserupgrade">
<p>You are using an outdated browser. Please <a href="http://browsehappy.com/">
upgrade your browser</a> to improve your experience.</p>
</div>
<![endif]-->
This IE conditional comment covers me for IE versions 6, 7, 8 and 9.
These visitors will get an alert with a link to download a current browser. However, Microsoft discontinued support for conditional comments starting with IE10.
Now I need something similar for:
IE 10
Safari 7-8
Opera Mini < 8
UC Browser for Android
Android Browser < 4.4
Is there a simple JS/jQuery script to handle this job? Or another lightweight method?
Solution
Thanks for all the answers. Clearly there are many ways to tackle this problem (Modernizr, PHP, jQuery functions, plain Javascript, CSS, browser-update.org, etc.) Many of these methods will do the job completely and effectively.
I went with the simplest one: CSS (credit #LGSon).
This CSS covers essentially all targeted browsers, except for IE <= 7.
.browserupgrade { display: block; }
_:-ms-fullscreen, :root .browserupgrade { display: none; }
:-o-prefocus, .browserupgrade { display: none; }
#supports (display: flex) { .browserupgrade { display: none; }}
See the answer for details.
And for those relatively few visitors using IE <= 7, a conditional comment in the HTML:
<!--[if lte IE 7]>
<div style=" ... inline styles here ...">
browser upgrade message here
</div>
<![endif]-->
Revised answer after question edit
Here is a CSS only way to achieve that.
As the CSS #supports won't work on your targeted (unwanted) browsers: Safari 7-8, IE <= 10, Android Browser < 4.4, UC Browser for Android and Opera Mini < 8, your "browserupgrade" message will be visible on those using this rule.
#supports (display: flex) { .browserupgrade { display: none; }}
There is a few browsers that still does support the non-prefixed flex but doesn't support #supports, IE 11(1) and Opera Mini 8, but luckily we can address them with a couple of CSS specific rules.
/* IE 11 */
_:-ms-fullscreen, :root .browserupgrade { display: none; }
/* Opera Mini 8 */
:-o-prefocus, .browserupgrade { display: none; }
Here is the complete code to show an upgrade message for your targeted browsers.
CSS
.browserupgrade { display: block; }
/* IE 11 */
_:-ms-fullscreen, :root .browserupgrade { display: none; }
/* Opera Mini 8 */
:-o-prefocus, .browserupgrade { display: none; }
/* all modern browsers */
#supports (display: flex) { .browserupgrade { display: none; }}
HTML
<div class="browserupgrade">
<p>You are using an outdated browser. Please <a href="http://browsehappy.com/">
upgrade your browser</a> to improve your experience.</p>
</div>
(1): The IE 11 CSS rule should work on IE Mobile 11 too, though haven't one to test it on.
The CSS #supports is also available as an API, CSS.supports(). Here is a very well written article by David Walsh.
Additionally, if one would like to automatically redirect those browser, here is a small script that does that, after a delay of 10 sec.
var el = document.querySelector('.browserupgrade');
if (window.getComputedStyle(el,null).getPropertyValue("display") != 'none') {
setTimeout(function(){
window.location = 'http://browsehappy.com/';
}, 10000);
}
PREMISE
The JavaScript style property returns a complete collection of CSS properties that the browser supports for the specified element, which can be tested using the following Snippet:
for(var x in document.body.style)
console.log(x);
This is true whether or not a particular property is explicitly set for the specified element. This can be tested by running the following Snippet in Chrome, for example; the first line will return false as Chrome does not yet support the unprefixed appearance property while the second line will return true.
console.log("appearance" in document.body.style);
console.log("-webkit-appearance" in document.body.style);
body{
appearance:none;
}
However, it should be noted that if an unsupported property is set on an element using JavaScript, via the style property then checking for the presence of that property will return true:
document.body.style.appearance="none";
console.log("appearance" in document.body.style);
Therefore we will be using document.createElement() to create a temporary element so we can be sure none of the properties we are checking for have been set in this manner. (Thanks to Gothdo for this suggestion, which removed the need for any assumptions to be made.)
REQUIREMENTS
Looking at the list of browsers to be targeted:
Internet Explorer 10 supported flexbox with the -ms- prefix.
Safari 7 & 8 supported flexbox with the -webkit- prefix.
Opera Mini, according to caniuse.com, has supported flexbox without prefixing since version 5, however I cannot attest to the accuracy of that and am looking for someone to confirm it.
UC Browser currently (v9.9) supports flexbox with the -webkit- prefix.
Prior to v4.4, Android Browser supported flexbox with the -webkit- prefix.
SOLUTION
We can see from that list that all the browsers to be targeted require prefixing of the flexbox properties so we can target them simply by checking for the presence of any of the unprefixed properties in the temporary element's style collection. The following Snippet will return true when run in any of the above browsers:
console.log(!("flex" in document.createElement("p").style));
Armed with this knowledge we can now create a working solution to display the browser upgrade message to the necessary browsers.
if(!("flex" in document.createElement("p").style))
document.getElementById("browserupgrade").style.display="block";
#browserupgrade{
display:none;
font-family:sans-serif;
}
<div id="browserupgrade">
<p>You are using an outdated browser. Please upgrade your browser to improve your experience.</p>
</div>
NOTES
Old Syntax
There was a version of the current flexbox spec that used a slightly different syntax with one of the differences being that the order property was named flex-order. To the best of my knowledge, the only browser that ever supported that syntax was IE10 which required prefixing so should, therefore, be targeted by the solution above. For the sake of completeness, though, in case there were ever any browsers that supported that syntax without prefixing, you can include an additional check for the presence of the flex-order property while also checking that the order property isn't present in case there are any browsers that support both versions of the syntax.
var checkstyle=document.createElement("p").style;
if(!("flex" in checkstyle)||("flex-order" in checkstyle&&!("order" in checkstyle)))
document.getElementById("browserupgrade").style.display="block";
#browserupgrade{
display:none;
font-family:sans-serif;
}
<div id="browserupgrade">
<p>You are using an outdated browser. Please upgrade your browser to improve your experience.</p>
</div>
Firefox
Firefox added support for unprefixed flexbox properties in version 22 but did not support either the flex-flow or flex-wrap properties until version 28 so to add v22-27 to our targeting, we should instead check for the presence of one of those properties.
var checkstyle=document.createElement("p").style;
if(!("flex-flow" in checkstyle)||("flex-order" in checkstyle&&!("order" in checkstyle)))
document.getElementById("browserupgrade").style.display="block";
#browserupgrade{
display:none;
font-family:sans-serif;
}
<div id="browserupgrade">
<p>You are using an outdated browser. Please upgrade your browser to improve your experience.</p>
</div>
Internet Explorer 11
Despite not requiring prefixing, IE11's support for flexbox is still extremely buggy so you might want to consider targeting it as well. There is no way of doing so using any of the flexbox properties, however IE 7-11 (sort of) supported the image-rendering property via the non-standard -ms-interpolation-mode property, with support later dropped in Edge/v12+ so we can instead check for that. There is no guarantee, though, that this property won't be added back in to a future version of Edge so that should be monitored.
var checkstyle=document.createElement("p").style;
if(!("flex-flow" in checkstyle)||("flex-order" in checkstyle&&!("order" in checkstyle))||"-ms-interpolation-mode" in checkstyle)
document.getElementById("browserupgrade").style.display="block";
#browserupgrade{
display:none;
font-family:sans-serif;
}
<div id="browserupgrade">
<p>You are using an outdated browser. Please upgrade your browser to improve your experience.</p>
</div>
Opera Mini
Although caniuse.com claims full support for flexbox has existed in Opera Mini since version 5 and is widely considered to be an authoritative source for such information, if you still wish to target it, you can do so by checking for the presence of one of the myriad of properties it doesn't support. To keep things concise, though, I'd suggest replacing the -ms-interpolation-mode check with a check for transform-style which is not supported by Opera Mini nor by pre-Edge versions of IE. As with the previous check, this one should be monitored as future versions of Opera Mini which you might not want to target may continue not to support the transform-style property.
var checkstyle=document.createElement("p").style;
if(!("flex-flow" in checkstyle)||("flex-order" in checkstyle&&!("order" in checkstyle))||!("transform-style" in checkstyle))
document.getElementById("browserupgrade").style.display="block";
#browserupgrade{
display:none;
font-family:sans-serif;
}
<div id="browserupgrade">
<p>You are using an outdated browser. Please upgrade your browser to improve your experience.</p>
</div>
UPDATES
13/05/16: Added additional checks to target more browsers after question was updated.
16/05/16: Added more detailed explanations of the proposed solution based on feedback provided in the comments and to make it worthy of the bounty on offer. Removed checks for old flexbox spec as they were redundant.
17/05/16: Added a temporary element to run the checks on, rather than using document.body, following Gothdo's suggestion, which led to the removal of suggesting the use of getElementsByTagName() for wider browser support.
23/05/16: Added notes with suggested checks for Internet Explorer 11 & Opera Mini.
You can use modernizr.js for feature detection.
And then write some JavaScript to re-direct the users to the URL above if the feature isn't found.
Yes we have a solution for this...
first of all download a custom build Modernizr from (click here --) https://modernizr.com/
(for flexbox property) then include latest Jquery to your page, add some stylesheet and you are done!
(Note: It is not necessary to download a custom build Modernizr, you can use whole complete build directly from Modernizr CDN but as you need to check Flexbox property only; thats why I told you to download a custom build)
Check this fiddle flexbox support fiddle
Your entire html page (with css, jquery ) will be like this...
<!doctype html>
<html class="no-js" lang="en">
<head>
<meta charset="utf-8">
<title>BroswerCheck</title>
<style type="text/css">
#browserupgrade{
display:none;
text-align:center;
background:#F1070B;
color:#FFFFFF;
font-family:Segoe, "Segoe UI", Verdana, sans-serif;
font-size:15px;
padding:10px;}
#browserupgrade a{
color:#FFFFFF;
background:#000000;
text-decoration:none;
padding:5px 15px;
border-radius:25px;}
</style>
<script src="modernizr.js"></script>
</head>
<body>
<div id="browserupgrade">
<p>You are using an outdated browser. Please upgrade your browser to improve your experience.</p>
</div>
<script src="jquery-2.1.1.js"></script>
<script type="text/javascript">
$(document).ready(function () {
if (!Modernizr.flexbox) { $("#browserupgrade").show(); }
});
</script>
</body>
</html>
Your steps will be,
1. Download custom Modernizr to detect flexbox property
2. create a html page with class="no-js" added in html tag
3. create a div for displaying a message and hide it
4. add jquery and Modernizr to your page
5. show a div, when a browser doesn't support flexbox-property
(for that purpose use 'Modernizr.flexbox' property as shown in above script)
or if you dont want to use Jquery then use following script (thanks to #Shaggy) as,
$(document).ready(function () {
if(!Modernizr.flexbox)document.getElementByID("browserupgrade").style.display="‌​block";
});
Okay, also I suggest to use modernizr (download from https://modernizr.com/), but a little bit differently. I take it as a fact that your actual concern is only to detect if the browser supports flexbox or not, and not if it's a particular browser or browser version.
After you install it and load your page, modernizr will put classes into the <body> tag. Concerning flexbox it will put either the class .flexbox OR the class .no-flexbox into the body tag, like <body class="no-flexbox bgsizecover csscalc"> (and in fact many more classes, unless you download a modernizr custom build only for flexbox). So you can use a simple combined selector for a CSS rule that selects a DIV block into which you write your warning concerning an outdated browser. Example:
Into the HTML, write something like:
<div class="browserwarning">Your browser is outdated and cannot display this page properly! Please install an up-to-date browser, which you can get from here.</div>
In the CSS stylesheet, add this:
.browserwarning {
display: none;
}
.no-flexbox .browserwarning {
display: block;
font-size: 24px;
color: red;
background-color: yellow;
}
This will hide this message first (by the first rule), and then (second rule) only display it in browsers which cannot handle flexbox and therefore have the .no-flexbox class put into the body tag by modernizr when the page is loaded: The combined selector .no-flexbox .browserwarning works regardless of where in the body that browser warning is placed - it doesn't have to be a direct child of body, but can be anywhere in there.
This works for sure - I've used this in pages I did successfully...
EDIT:
There are two viable approaches: Modernizr or Feature Queries. Modernizr is the current stable solution, but feature queries #support, when fully supported by all browsers, will be the best pure CSS solution for css feature detection.
Currently you need to add some prefixes to target those browsers that do not support feature queries, ie. see LGSon's answer.
Modernizr approach:
You can create a flexbox custom Modernizr build pretty easy, as previously recommended: Modernizr Custom Flexbox Build. Reference your custom modernizr javascript file in your website and then add some Html markup and Css classes , something like this:
NOTE: Open the snippet in different browsers to check support.
TESTS:
No flexbox support: Internet Explorer 10
Flexbox support: Chrome 50
/*! modernizr 3.3.1 (Custom Build) | MIT *
* https://modernizr.com/download/?-flexbox-setclasses !*/
! function(e, n, t) {
function r(e, n) {
return typeof e === n
}
function o() {
var e, n, t, o, s, i, a;
for (var l in C)
if (C.hasOwnProperty(l)) {
if (e = [], n = C[l], n.name && (e.push(n.name.toLowerCase()), n.options && n.options.aliases && n.options.aliases.length))
for (t = 0; t < n.options.aliases.length; t++) e.push(n.options.aliases[t].toLowerCase());
for (o = r(n.fn, "function") ? n.fn() : n.fn, s = 0; s < e.length; s++) i = e[s], a = i.split("."), 1 === a.length ? Modernizr[a[0]] = o : (!Modernizr[a[0]] || Modernizr[a[0]] instanceof Boolean || (Modernizr[a[0]] = new Boolean(Modernizr[a[0]])), Modernizr[a[0]][a[1]] = o), g.push((o ? "" : "no-") + a.join("-"))
}
}
function s(e) {
var n = x.className,
t = Modernizr._config.classPrefix || "";
if (_ && (n = n.baseVal), Modernizr._config.enableJSClass) {
var r = new RegExp("(^|\\s)" + t + "no-js(\\s|$)");
n = n.replace(r, "$1" + t + "js$2")
}
Modernizr._config.enableClasses && (n += " " + t + e.join(" " + t), _ ? x.className.baseVal = n : x.className = n)
}
function i(e, n) {
return !!~("" + e).indexOf(n)
}
function a() {
return "function" != typeof n.createElement ? n.createElement(arguments[0]) : _ ? n.createElementNS.call(n, "http://www.w3.org/2000/svg", arguments[0]) : n.createElement.apply(n, arguments)
}
function l(e) {
return e.replace(/([a-z])-([a-z])/g, function(e, n, t) {
return n + t.toUpperCase()
}).replace(/^-/, "")
}
function f(e, n) {
return function() {
return e.apply(n, arguments)
}
}
function u(e, n, t) {
var o;
for (var s in e)
if (e[s] in n) return t === !1 ? e[s] : (o = n[e[s]], r(o, "function") ? f(o, t || n) : o);
return !1
}
function d(e) {
return e.replace(/([A-Z])/g, function(e, n) {
return "-" + n.toLowerCase()
}).replace(/^ms-/, "-ms-")
}
function p() {
var e = n.body;
return e || (e = a(_ ? "svg" : "body"), e.fake = !0), e
}
function c(e, t, r, o) {
var s, i, l, f, u = "modernizr",
d = a("div"),
c = p();
if (parseInt(r, 10))
for (; r--;) l = a("div"), l.id = o ? o[r] : u + (r + 1), d.appendChild(l);
return s = a("style"), s.type = "text/css", s.id = "s" + u, (c.fake ? c : d).appendChild(s), c.appendChild(d), s.styleSheet ? s.styleSheet.cssText = e : s.appendChild(n.createTextNode(e)), d.id = u, c.fake && (c.style.background = "", c.style.overflow = "hidden", f = x.style.overflow, x.style.overflow = "hidden", x.appendChild(c)), i = t(d, e), c.fake ? (c.parentNode.removeChild(c), x.style.overflow = f, x.offsetHeight) : d.parentNode.removeChild(d), !!i
}
function m(n, r) {
var o = n.length;
if ("CSS" in e && "supports" in e.CSS) {
for (; o--;)
if (e.CSS.supports(d(n[o]), r)) return !0;
return !1
}
if ("CSSSupportsRule" in e) {
for (var s = []; o--;) s.push("(" + d(n[o]) + ":" + r + ")");
return s = s.join(" or "), c("#supports (" + s + ") { #modernizr { position: absolute; } }", function(e) {
return "absolute" == getComputedStyle(e, null).position
})
}
return t
}
function h(e, n, o, s) {
function f() {
d && (delete z.style, delete z.modElem)
}
if (s = r(s, "undefined") ? !1 : s, !r(o, "undefined")) {
var u = m(e, o);
if (!r(u, "undefined")) return u
}
for (var d, p, c, h, v, y = ["modernizr", "tspan", "samp"]; !z.style && y.length;) d = !0, z.modElem = a(y.shift()), z.style = z.modElem.style;
for (c = e.length, p = 0; c > p; p++)
if (h = e[p], v = z.style[h], i(h, "-") && (h = l(h)), z.style[h] !== t) {
if (s || r(o, "undefined")) return f(), "pfx" == n ? h : !0;
try {
z.style[h] = o
} catch (g) {}
if (z.style[h] != v) return f(), "pfx" == n ? h : !0
}
return f(), !1
}
function v(e, n, t, o, s) {
var i = e.charAt(0).toUpperCase() + e.slice(1),
a = (e + " " + b.join(i + " ") + i).split(" ");
return r(n, "string") || r(n, "undefined") ? h(a, n, o, s) : (a = (e + " " + E.join(i + " ") + i).split(" "), u(a, n, t))
}
function y(e, n, r) {
return v(e, t, t, n, r)
}
var g = [],
C = [],
w = {
_version: "3.3.1",
_config: {
classPrefix: "",
enableClasses: !0,
enableJSClass: !0,
usePrefixes: !0
},
_q: [],
on: function(e, n) {
var t = this;
setTimeout(function() {
n(t[e])
}, 0)
},
addTest: function(e, n, t) {
C.push({
name: e,
fn: n,
options: t
})
},
addAsyncTest: function(e) {
C.push({
name: null,
fn: e
})
}
},
Modernizr = function() {};
Modernizr.prototype = w, Modernizr = new Modernizr;
var x = n.documentElement,
_ = "svg" === x.nodeName.toLowerCase(),
S = "Moz O ms Webkit",
b = w._config.usePrefixes ? S.split(" ") : [];
w._cssomPrefixes = b;
var E = w._config.usePrefixes ? S.toLowerCase().split(" ") : [];
w._domPrefixes = E;
var P = {
elem: a("modernizr")
};
Modernizr._q.push(function() {
delete P.elem
});
var z = {
style: P.elem.style
};
Modernizr._q.unshift(function() {
delete z.style
}), w.testAllProps = v, w.testAllProps = y, Modernizr.addTest("flexbox", y("flexBasis", "1px", !0)), o(), s(g), delete w.addTest, delete w.addAsyncTest;
for (var N = 0; N < Modernizr._q.length; N++) Modernizr._q[N]();
e.Modernizr = Modernizr
}(window, document);
.support-container {
display: none;
}
.no-flexbox .support-container {
display: block;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: #CE3426;
padding: 100px;
}
.support-container__update-browser {
color: #ffffff;
font-size: 2em;
}
.support-container__can-i-use {
font-size: 1.2em;
font-style: italic;
color: #dddddd;
}
.support-container__update-browser a,
.support-container__can-i-use a {
background-color: #ffffff;
text-decoration: underline;
padding: 0 3px;
border-radius: 4px;
border-bottom: 2px solid rgba(0, 0, 0, 0.3);
}
<div class="support-container">
<div id="browserupgrade" class="support-container__update-browser">
<p>Dear user, you are using an outdated browser. Please
upgrade your browser to improve your experience.</p>
</div>
<div class="support-container__can-i-use">
<p>
For more browser support info click
here
.
</p>
</div>
</div>
FURTHER EXPLANATION:
Modernizr checks if the browser supports your custom feature in this case flexbox. If the browser does not support it, Modernizr adds a class to your <html> tag. Like this: <html class="no-flexbox>. Which you can use at your convenience in your stylesheet.
Additionally, you can add a function to detect the user's browser and add it to your update browser message for a better UX. Credit: kennebec
navigator.sayswho= (function(){
var ua= navigator.userAgent, tem,
M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if(/trident/i.test(M[1])){
tem= /\brv[ :]+(\d+)/g.exec(ua) || [];
return 'IE '+(tem[1] || '');
}
if(M[1]=== 'Chrome'){
tem= ua.match(/\b(OPR|Edge)\/(\d+)/);
if(tem!= null) return tem.slice(1).join(' ').replace('OPR', 'Opera');
}
M= M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];
if((tem= ua.match(/version\/(\d+)/i))!= null) M.splice(1, 1, tem[1]);
return M.join(' ');
})();
On the front end you could use modernizr library and detect if browser support the modern features you are using.
Another thing to do is to do redirect directly from the back end to a special page. If you are using PHP for the back end you can use get_browser function to detect user agent and then load a normal page or if the browser is one of unsupported browser open a page suggesting users to upgrade.
http://php.net/manual/en/function.get-browser.php
Or another lightweight method?
If you're serving your page through nginx, there is very useful directive ancient_browser.
You need to set a list of browsers you wish to not support:
ancient_browser msie 9.0;
and then redirect those to special browser-upgrade page:
if ($ancient_browser) {
rewrite ^ /install-chrome.html;
}
This way you're not polluting your already existing pages and do not need to load extra css for users who do not need it.
You can also insert prefixes into stylesheet. Check if the browsers style property actually supports the style properties either already present, or dynamically inserted later. Composed it primarily for animations, though could be modified to test for any css, style property in the browser. If props already present in stylesheet, vendor prefixes are inserted into stylesheet. If props are later dynamically inserted, vendor prefixes are also inserted, or attached onto those props.
For example, adding prefixes for animation, backface-visibility, border-radius, box-shadow, transform, transform-style, transition; also setting prefix at #keyframes
(function prefix() {
// var el = $(selector).get(0), i.e.g, $("body").get(0), $("#animated").get(0)
var prefixes = {"MozAnimation": "-moz-","webkitAnimation": "-webkit-"
,"msAnimation": "-ms-","oAnimation": "-o-"};
var props = ["animation", "backface-visibility", "border-radius"
, "box-shadow", "transform", "transform-style", "transition"];
$.each(prefixes, function(key, val) {
$("style")
.attr({"data-prefix": val,"class": String(val).replace(/-/g, "")});
return !(key in el.style);
});
$.each(props, function(index, value) {
var cssPrefix = $("style").attr("data-prefix");
if (value in el.style === false) {
$.fn.pfx = function(prop, pfxprop, q) {
return $("style").html($("style").text()
.replace(new RegExp(prop, "g"), q
+ $("style").attr("data-prefix") + pfxprop))
};
$("style").pfx("#keyframes", "keyframes", "#")
.pfx(value, value, "");
};
});
}());
github https://github.com/guest271314/prefix/blob/master/prefix.1.1.min.js
A more thorough approach.
You can get the user-agent strings for each browser you are interested and create an array of all the ones you want to exclude.
List of User Agent Strings
Use navigator.userAgent to get the visitor's user-agent and check if it is in your not-supported-browsers array using jQuery inArray()
A simple javascript alert could be thrown for visitors using a browser that is a match.
Here is an example of getting browser related information (example source:w3schools.com)
var txt = "";
txt += "<p>User-agent header: " + navigator.userAgent + "</p>";
txt += "<p>Browser CodeName: " + navigator.appCodeName + "</p>";
txt += "<p>Browser Name: " + navigator.appName + "</p>";
txt += "<p>Browser Version: " + navigator.appVersion + "</p>";
txt += "<p>Cookies Enabled: " + navigator.cookieEnabled + "</p>";
txt += "<p>Browser Language: " + navigator.language + "</p>";
txt += "<p>Browser Online: " + navigator.onLine + "</p>";
txt += "<p>Platform: " + navigator.platform + "</p>";
document.getElementById("demo").innerHTML = txt;
<div id="demo"></div>
UPDATE
This is a very simple approach, no 3rd party API involved. Simply use UAparser.js to filter results. All you need to check from your part is browser name and version. Check the example below
var parser = new UAParser();
var thisBrowser = parser.getBrowser();
var thisOS = parser.getOS();
switch(true) {
case (thisBrowser.name=="IE" && thisBrowser.version<=10) :
alert("IE versions older than v11 are not supported");
break;
case (thisBrowser.name=="Safari" && (thisBrowser.version>=7 || thisBrowser.version<9)):
alert("Safari versions 7 and 8 are not supported");
break;
case (thisBrowser.name=="Android Webkit Browser" && thisBrowser.version<4.4):
alert("Default browser of Android OS versions older than v4.4 are not supported.");
break;
case (thisBrowser.name=="UC Browser" && thisOS.name=="Android"):
alert("UC browser versions for Android are not supported.");
break;
case (thisBrowser.name=="Opera Mini" && thisBrowser.version<8):
alert("Default browser of Android OS versions older than v4.4 are not supported.");
break;
default:
alert("Great this is a supported browser");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/UAParser.js/0.7.10/ua-parser.min.js"></script>
You can use UAParser.js. It can give you the browser name, version, os, etc. Here's an example.
There is even a jQuery plugin for it.
var parser = new UAParser();
var browser = parser.getBrowser();
// leave only the major version and minor in order to compare
// eg 12.2.4 > 12.2
var secondDot = browser.version.indexOf(".", browser.version.indexOf(".") + 1);
browser.version = parseFloat(browser.version.substr(0, secondDot));
// debugging
$("#browserName").html(browser.name);
$("#browserVersion").html(browser.version);
if (["IE", "Safari", "Opera Mobi", "UCBrowser", "Android Browser"].indexOf(browser.name) != -1) {
if (browser.name == "IE" && browser.version <= 10) {
$("#browserupgrade").show();
}
if (browser.name == "Safari" && browser.version <= 10) {
$("#browserupgrade").show();
}
if (browser.name == "UCBrowser") {
$("#browserupgrade").show();
}
if (browser.name == "Android Browser" && browser.version <= 4.4) {
$("#browserupgrade").show();
}
}
See : https://browser-update.org/
<script>
var $buoop = {c:2};
function $buo_f(){
var e = document.createElement("script");
e.src = "//browser-update.org/update.min.js";
document.body.appendChild(e);
};
try {document.addEventListener("DOMContentLoaded", $buo_f,false)}
catch(e){window.attachEvent("onload", $buo_f)}
</script>
You can use the following functions to get the browser name and version :
function get_browser() {
var ua = navigator.userAgent, tem, M = ua
.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i)
|| [];
if (/trident/i.test(M[1])) {
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
return 'IE ' + (tem[1] || '');
}
if (M[1] === 'Chrome') {
tem = ua.match(/\bOPR\/(\d+)/)
if (tem != null) {
return 'Opera ' + tem[1];
}
}
M = M[2] ? [ M[1], M[2] ] : [ navigator.appName, navigator.appVersion,
'-?' ];
if ((tem = ua.match(/version\/(\d+)/i)) != null) {
M.splice(1, 1, tem[1]);
}
return M[0];
}
function get_browser_version() {
var ua = navigator.userAgent, tem, M = ua
.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i)
|| [];
if (/trident/i.test(M[1])) {
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
return 'IE ' + (tem[1] || '');
}
if (M[1] === 'Chrome') {
tem = ua.match(/\bOPR\/(\d+)/)
if (tem != null) {
return 'Opera ' + tem[1];
}
}
M = M[2] ? [ M[1], M[2] ] : [ navigator.appName, navigator.appVersion,
'-?' ];
if ((tem = ua.match(/version\/(\d+)/i)) != null) {
M.splice(1, 1, tem[1]);
}
return M[1];
}
and you can use the following code to alert the user to update the browser.
jQuery(document).ready(function() {
var browser = get_browser();
var browser_version = get_browser_version();
if (browser == "Chrome" && browser_version <= 30) {
alert("Your browser is below the minimum required version. Please update your browser for this site to function properly");
}
if (browser == "Firefox" && browser_version <= 25) {
alert("Your browser is below the minimum required version. Please update your browser for this site to function properly");
}
if (browser == "MSIE" && browser_version <= 8) {
alert("Your browser is below the minimum required version. Please update your browser for this site to function properly");
}
});
This one line will check for ie10 and return true if ie10 or false otherwise .
var ie10 = /MSIE 10/i.test(navigator.userAgent) && /MSIE 10/i.test(navigator.vendor);
Did my studies here : https://blogs.msdn.microsoft.com/ie/2011/04/15/the-ie10-user-agent-string/
use case
Option 1
if(ie10){
//Do something
}
UPDATE :
Microsoft browsers use #cc_on which will allow you to initiate conditional comments through script .
Option 2 :
<script>
/*#cc_on
#if (#_jscript_version == 10){
document.write("You are using IE10");
}
#*/
</script>
FYI . Only EI 10 and below do not support flexbox css . Proof here : http://caniuse.com/#feat=flexbox
Hope this helps
Try this:
navigator.browser = (function() {
var ua = navigator.userAgent, tem,
M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if (/trident/i.test(M[1])) {
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
return 'IE '+(tem[1] || '');
}
if (M[1]=== 'Chrome') {
tem = ua.match(/\b(OPR|Edge)\/(\d+)/);
if (tem != null) return tem.slice(1).join(' ').replace('OPR', 'Opera');
}
M = M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];
if ((tem = ua.match(/version\/(\d+)/i))!= null)
M.splice(1, 1, tem[1]);
return M.join(' ');
})();
But you are trying to reinvent the wheel, with Modernizr you can do:
if (Modernizr.flexbox) {
// Modern Flexbox supported
}
else {
// Flexbox syntax not supported
}

Print external page without open it

I want print a page without open it on all major browsers. (Safari, IE, firefox, Chrome and Opera)
I tried that but doesn't work on firefox (Error : Permission denied to access property 'print') :
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
<link rel="alternate" media="print" href="print.php">
<script type="text/javascript">
function impression() {
window.frames[0].focus();
window.frames[0].print();
}
</script>
</head>
<body>
<iframe height="0px" src="print.php" id="fileToPrint" style="visibility: hidden"></iframe>
Imprimer
</body>
</html>
This code works on Chrome.
I want one thing like that for all browsers to mention but I don't know how.
Is there another way to do that?
Create an iframe, hide it, and then call the proper print functions. The execCommand should work for all versions of IE.
Mind you: $.browser won't work for newer versions of jQuery and should be avoided. Use your preferred way of detecting features.
var ifr = createIframe();
ifr.hide();
if ($.browser.msie) {
ifr.contentWindow.document.execCommand('print', false, null);
} else {
ifr.contentWindow.focus();
ifr.contentWindow.print();
}
This was developed for IE, FF and Chrome. I have no idea how well this will work for Safari and Opera, but it might give you some ideas.
Edit: as adeneo correctly pointed out, $.browser is deprecated and should be avoided. I updated my statement. I'll leave my code untouched, as it still expresses the correct intent.
You can try this code, but it's Javascript ;
<script language="JavaScript">
var gAutoPrint = true; // Tells whether to automatically call the print function
function printSpecial()
{
if (document.getElementById != null)
{
var html = '<HTML>\n<HEAD>\n';
if (document.getElementsByTagName != null)
{
var headTags = document.getElementsByTagName("head");
if (headTags.length > 0)
html += headTags[0].innerHTML;
}
html += '\n</HE>\n<BODY>\n';
var printReadyElem = document.getElementById("printReady");
if (printReadyElem != null)
{
html += printReadyElem.innerHTML;
}
else
{
alert("Could not find the printReady function");
return;
}
html += '\n</BO>\n</HT>';
var printWin = window.open("","printSpecial");
printWin.document.open();
printWin.document.write(html);
printWin.document.close();
if (gAutoPrint)
printWin.print();
}
else
{
alert("The print ready feature is only available if you are using an browser. Please update your browswer.");
}
}
</script>

Get IE Version + Add Class to body

I am trying to find which version of IE people are using and adding a class to the body tag depending on which browser.
the code i have is
if (navigator.appName == "Microsoft Internet Explorer") {
//Set IE as true
ie = true;
//Create a user agent var
var ua = navigator.userAgent;
//Write a new regEx to find the version number
var re = new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})");
//If the regEx through the userAgent is not null
if (re.exec(ua) != null) {
//Set the IE version
ieVersion = parseInt(RegExp.$1);
}
}
else {
ie = false;
}
function ieTag() {
if (ie == true) {
if (ieVersion == 7) {
$('body').addClass('IE7');
}
}
if (ie == true) {
if (ieVersion == 8) {
$('body').addClass('IE8');
}
}
if (ie == true) {
if (ieVersion == 9) {
$('body').addClass('IE9');
}
}
}
and i am using this to call the function
<script type="text/javascript">
$(document).ready(function () {
//IE Version Control
ieTag();
});
</script>
but i am only picking up IE 9 for some reason, i have had this script working before so i really dont understand whats gone wrong!!!
i have even tried using this script
function ieTag() {
if (ie == true) {
$('body').addClass('IE' + ieVersion);
}
}
but still only picking up IE9
I ma using IE( and the developer tools to change version (which both of these scripts has worked on before)
This is probably not the answer you are looking for, but it does seem like the simplest solution:
<!--[if lt IE 7]> <body class="ie6"> <![endif]-->
<!--[if IE 7]> <body class="ie7"> <![endif]-->
<!--[if IE 8]> <body class="ie8"> <![endif]-->
<!--[if IE 9]> <body class="ie9"> <![endif]-->
<!--[if gt IE 9]> <body class="ie10+"> <![endif]-->
<!--[if !IE]><!--> <body> <!--<![endif]-->
of course added in the HTML where your body tag is supposed to start.
You could use conditional comments so that it doesn't affect other browsers.
<!--[if IE 6]>
<script>
$(document).ready(function(){
$("body").addClass("ie-6");
});
</script>
<![endif]-->
<!--[if IE 7]>
<script>
$(document).ready(function(){
$("body").addClass("ie-7");
});
</script>
<![endif]-->
<!--[if IE 8]>
<script>
$(document).ready(function(){
$("body").addClass("ie-8");
});
</script>
<![endif]-->
<!--[if IE 9]>
<script>
$(document).ready(function(){
$("body").addClass("ie-9");
});
</script>
<![endif]-->
You don't need JavaScript for this.
<!--[if IE 9]>
<body class='ie9'>
<![endif]-->
<!--[if IE 8]>
<body class='ie8'>
<![endif]-->
etc. For normal browsers you do:
<!--[if IE]><!-->
<body class='normal'>
<!--<![endif]-->
The Reason why the js in the question failed in IE 7 and IE 8 was the fact i had included the script using application/javascript rather than text/javascript,
the reason is doesn't work with application/javascript is because this is a new way of including the script that only modern browsers support and older browsers does not support this method, hence IE 7 & 8 failing.
If you have jQuery you can add ie class to body like this
$(function(){
if ($.browser.msie && $.browser.version == 8) {
$('body').addClass('ie8');
}
});

browser detection in javascript

I need to show a different webpage when i open my website in IE6 and below version.
Need to show fbrowser.html file when my website opens in IE6 and below versions.
Please suggest!!
In head:
<!--[if lte IE 6]>
<meta http-equiv="refresh" content="0; url=fbrowser.html">
<![endif]-->
Sorry, no javascript needed.
You could consider using http://api.jquery.com/jQuery.browser/
According to this answer, you can try somethiing like the following:
<script type="text/javascript">
// <![CDATA[
var BrowserCheck = Class.create({
initialize: function () {
var userAgent = navigator.userAgent.toLowerCase();
this.version = (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1];
this.safari = /webkit/.test(userAgent) && !/chrome/.test(userAgent);
this.opera = /opera/.test(userAgent);
this.msie = /msie/.test(userAgent) && !/opera/.test(userAgent);
this.mozilla = /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent);
this.chrome = /chrome/.test(userAgent);
}
});
// ]]>
</script>

Does not work window.onload in IE8

I have a pretty simple image switcher, which I use for manual images switcher and for carousel. In IE 8 it works strange. In carousel scenario image switches just once, thereafter it's dies. But (!) when I implemented Firebug Lite and try to trace - it's works well, only with firebug on... I tried some tricks, I found, but it's all to no purpose. I have no idea what caused this kind of behavior. How to fix it?
js
function toSlide(wrapper, options){
var active = $('#' + wrapper + ' div.active');
var slide;
var direction;
if (active.length === 0){
active = $('#' + wrapper + ' div:last');
}
if (options === null) {
options = {};
options.reverse = false;
options.animate = false;
} else {
options.reverse = options.reverse === null ? false : options.reverse;
options.animate = options.animate === null ? false : options.animate;
}
direction = options.reverse === true ? active.prev() : active.next();
slide = direction.length ? direction : $('#' + wrapper + ' div:first');
if (options.animate === true){
active.addClass('last-active');
slide.addClass('active')
.css({opacity:0.0})
.animate({opacity:1.0}, 1000, function() {
active.removeClass('active last-active');
});
} else {
slide.addClass('active');
active.removeClass('active');
}
}
function startSlideShow() {
setInterval(function(){ toSlide('slideshow', {'animate': true}); }, 5000);
};
window.onload = function() {
if (document.location.pathname == '/'){startSlideShow();};
};
html in head
<!--[if IE 8 ]>
<link rel="stylesheet" href="{{ MEDIA_URL }}css/ie8.css" type="text/css" media="screen, projection" /> <html lang="en" class="no-js ie8">
<script defer src="ie_onload.js"></script>
<script>!window.jQuery && document.write(unescape('%3Cscript src="{{ MEDIA_URL }}js/jquery-1.6.2.js"%3E%3C/script%3E'))</script>
<script type="text/javascript" src="http://fbug.googlecode.com/svn/lite/branches/firebug1.3/content/firebug-lite-dev.js"></script>
<![endif]-->
in bottom of html
<!-- Grab Google CDN's jQuery. fall back to local if necessary -->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<!-- <script>!window.jQuery && document.write(unescape('%3Cscript src="{{ MEDIA_URL }}js/jquery-1.4.2.js"%3E%3C/script%3E'))</script> -->
<!-- scripts concatenated and minified via ant build script-->
<script src="{{ MEDIA_URL }}js/plugins.js"></script>
<script src="{{ MEDIA_URL }}js/script.js"></script>
<!-- end concatenated and minified scripts-->
Accessing console in FF without Firebug open or in IE will result in an error that will block the rest of your JS from executing. If you want to leave calls to console in, you should implement them like one of the following:
try { console.log('blah'); } catch(e) {}
// or
if (typeof console != 'undefined') console.log('blah');
Or use a custom built logging function that implements something like the above.
The cause was non-functional window.onload in IE8. I did right trick but made stupid mistake. So, I fixed it:
was
<!--[if IE 8 ]>
<script defer src="ie_onload.js"></script>
<![endif]-->
is now
<!--[if IE 8 ]>
<script defer src="{{ MEDIA_URL }}js/ie_onload.js"></script>
<![endif]-->
in ie_onload.js
document.body.onload = function() {
imageViewer();
// and other functions
};

Categories

Resources