Browser Version or Bug Detection - javascript

I've recently seen some information about avoiding coding to specific browsers an instead using feature/bug detection. It seems that John Resig, the creator of jQuery is a big fan of feature/bug detection (he has an excellent talk that includes a discussion of this on YUI Theater). I'm curious if people are finding that this approach makes sense in practice? What if the bug no longer exists in the current version of the browser (It's an IE6 problem but not 7 or 8)?

Object detection's greatest strength is that you only use the objects and features that are available to you by the client's browser. In other words given the following code:
if (document.getFoo) {
// always put getFoo in here
} else {
// browsers who don't support getFoo go here
}
allows you to cleanly separate out the browsers without naming names. The reason this is cool is because as long as a browser supports getFoo you don't have to worry which one it is. This means that you may actually support browsers you have never heard of. If you target user agent strings find the browser then you only can support the browsers you know.
Also if a browser that previously did not support getFoo gets with the program and releases a new version that does, you don't have to change your code at all to allow the new browser to take advantage of the better code.

What if the bug no longer exists in the current version of the browser (It's an IE6 problem but not 7 or 8)?
That's the whole point of feature/bug detection. If the browser updates its features or fixes a bug, then the feature/bug detecting code is already up to date. If you're doing browser sniffing on the other hand, you have to change your code every time the capabilities of a browser changes.

Version and User Agent parsing remind me of stereotyping or racial profiling. Object detection is the way to go in my opinion. The book jQuery in Action does a good job of pointing out the fine details of why.

Well, if it is a problem in IE 6, but not IE 7 or IE 8 then the feature/bug detection mechanism will mark it as not a problem and use the appropriate functions.
It makes sense in practice, browser sniffing causes many issues, what if you don't update your signatures in time for some new browser that is released? You are now locking out potential customers, and visitors because you believe that their browser is unable to support something that indeed it can.
So yes, it makes sense, and your second question is moot because of the fact that it does the detection in the first place, if it is no longer a bug everything will work as expected without the work around that is in place if the bug was there!

Related

Deprecated Javascript OS detection techniques

I was wondering why javascript os detection techniques like navigator.userAgent, navigator.appName, navigator.appVersion and navigator.platform are in process of being dropped from web standards.
https://developer.mozilla.org/en-US/docs/Web/API/Navigator
If you visit every of those navigator props, you can see
Deprecated
This feature has been removed from the Web standards. Though some browsers may still support it, it is in the process of being dropped. Do not use it in old or new projects. Pages or Web apps using it may break at any time.
So I would like to know
Why they're removing this
Will they introduce a new way for OS detection
Can I use these techniques even if they're deprecated.
Probably there is a lot of cases where we need to know OS version.
It was incorrectly or accidentally marked as deprecated on MDN. They quickly corrected the page once they saw the problem, but since it had been a definitive source, references to it being deprecated still exist here and there.
Here's the conversation where it was fixed:
https://groups.google.com/forum/#!topic/mozilla.dev.mdc/tIx2iiH2u3o
You can use:
navigator.userAgentData.platform
I think the general thinking is that it's becoming unnecessary. Theoretically at least, there shouldn't be any functionality that works differently in any browser vs any other browser--at least not for JavaScript.
What you usually browser sniff for are features, and there are plenty of ways to find most of that stuff out without having to infer anything from the nightmare that is userAgent.
So it may be deprecated, or it may not. But it's a good idea to not have to sniff the browser. That stuff can get real complicated real fast. Even if it does become deprecated though, it'll probably stick around for a few decades so that half the web that still relies on it doesn't crash and burn.

How can I reliably detect the browser without using window.navigator?

I know there are a thousand questions on Stack Overflow about detecting the browser with JavaScript. My question is how can you detect the browser without window.navigator (which includes navigator.userAgent)?
First, to clarify, I don't need to know the rendering engine, this isn't for adaptive layout, and don't panic: I'm already doing feature detection. If why I'm asking about detecting the browser is important, please comment and I'll be happy to splice in the explanation, but it will probably make the question egregiously long.
Next, let me describe why my question is not a duplicate of:
Browser detection in Javascript? because of 19 answers, 12 of them use navigator.userAgent specifically (including jQuery.browser which used userAgent, and is now gone anyway), 4 use navigator.appName (which gives "Netscape" in Chrome...), 1 side-steps the question by recommending feature detection, which is different from browser detection (I am already using feature detection, but to know the extent to which I can use them, I need browser detection), and 2 aren't really answers or are IE-specific. (Although this non-answer is actually very explanatory about why my question here is relevant: I'm trying to avoid hitting pain points on certain browsers that would crash the tab!) Since my question is asking for an answer (even a hack?) without using window.navigator, it is not a duplicate of that question.
Check if the user is using IE because of 11 answers, 10 use navigator.userAgent and 1 of them uses an IE trick to detect IE only, which is not sufficient to answer my question (though it may be potentially be a small part of a helpful solution posted here)?
In Javascript, how do I determine if my current browser is Firefox on a computer vs everything else? because of 11 answers, 8 use navigator.userAgent, 2 recommend feature detection (again, not my question), and 1 isn't even an answer, really.
How to detect chrome and safari browser (webkit) because of 8 answers, 6 of them use navigator.userAgent, and 2 are webkit-specific. Unfortunately, WebKit is not necessarily tied to just Safari, and I need to know the browser, not the rendering engine.
Hopefully that is crystal clear.
I know there are other ways to do this, but I don't know the ins-and-outs of each browser well enough. Are there objects or variables that are consistently or reliably exposed to JavaScript in certain browsers, maybe? I know that some experimental APIs are vendor-prefixed, but that doesn't seem like a good idea for use in a commercial product, although I'm willing to stoop that low if needed. Any other possibilities?
A thought:
IE uses ActiveX (still does up to IE11, legacy), You can fairly easy deduce the fact that the user is using IE from looking at activeX availability, however if the security settings are on, you need to fall back on, guess what, other feature detection.
Chrome and Firefox both support the use of extensions, maybe detecting these extensions will help
Chrome has the window['chrome']['webstore'] object available in the global scope.
You can sort through the window object with Object.keys and look for vendor specific names like 'moz' or 'ms' or 'o'.
If you combine moz, ms and chrome-object you can sniff out the three largest browsers.
On a side note, feature detection is still the best option, not for the OP, but for the "I'm-just-getting-into-programming-and-I-like-to-know-how-I-sniff-out-a-browser-programmers" out there.
First off, just to be clear no inbound HTTP request is guaranteed to be accurate in saying who they are. In fact this is how some hackers operate by faking out the User-Agent field of the HTTP header. Most browser providers; however, do a good job of identifying who they are by saying so in the User-agent field of the inbound HTTP request header. The only problem working at the Javascript layer is that it is one layer too high for seeing the headers. However there are tricks and here's one of them :
var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
alert(headers);
I found this after thinking about the problem a bit and knowing the Network side pretty well... You can read more about this here: Accessing the web page's HTTP Headers in JavaScript, in fact this question could be considered a duplicate of that answer, however, not everyone knows the HTTP layer. The code above is pretending to be a legitimate inbound request, and opens the document.location using a "Get", but it sends nothing. Without knowing the browser internals I am guessing that it is the DOM itself that is returning the already known header information. Just parse the User-Agent portion of he response and you are all set.

Best way to display warning message to "untested" browsers?

I have an app that I have fully tested in Safari 5, IE 9, FF6, and Chrome 14. I'm not looking to block or exclude any browsers from the experience. But I want to warn/inform users that there may be a better experience in another browser, and if they choose to continue, there may be features not working or broken.
I have looked at jQuery browser detection, but it seems to be a bit quirky. I know the best solution would be to warn based on feature detection, but we are currently in beta and I am not completely sure what features make or break. Such as web workers, its known that web workers not working breaks our app, but it works in IE lower versions. But then there is an issue with Opera that web workers is available, but not functioning correctly.
Ultimately I am looking for an easy way to say Browser X Version y and up don't show warning, and those and under show warning.
What is the best way to approach this?
Browser detection is indeed "a bit quirky", in pretty much any scenario. The jQuery route is probably as good as you're going to get, but as you say it's not great.
A better solution is generally to do feature detection, especially in cases like the one you describe where your site relies on specific features.
The best feature detection library is Modernizr. This will give you an bunch of Javascript flags which are set to true or false according to whether the browser supports a given feature. It detects support for a whole bunch of stuff, including Web Workers.
Check out this: http://www.w3schools.com/js/js_browser.asp
-Easy way of detecting the user's browser with javascript. From there I'd just use a switch statement or something to display the messages for browsers that aren't tested yet. If you want the exact browser version you'll have to parse it from the "navigator.userAgent" field.
If the goal is full validation, you need to be even more specific about versions. Keep in mind that some browser upgrades are not 100% backwards compatible with previous versions. (Look at how IE8 mode in IE9 is not the same as native IE8 rendering, for instance.) You're going to have to retest with every new browser version, and sooner or later there's going to be a "Fully tested with browser version X, not tested with version X+1 that was released yesterday" problem. Feature detection, graceful degradation, and a warning non-intrusively displayed to the user if their experience is being significantly downgraded is a better way to go.
To directly answer your question, if you must implement what you are asking for just parse the user agent. This could be useful specifically watching out for a browser you know doesn't work right and warning, or as a bandaid for a badly written intranet app that is very picky about the exact browser version it will run on. For a newly developed app where you have control over the requirements, I would not recommend warning on browser version since there are better ways to do it.

sniffing browsers in a post sniff world, can I still use jquery.browser?

Post Sniffing Rules
Although browser sniffing used to be quite popular, it's now gone out of fashion (for good reasons) and has been deprecated (if not dropped) by popular libraries such as jquery.
The better way is to do feature detection.
Exception To The New Rule
However, there are times when you might be targeting (for whatever reason) a specific browser. iOS safari is a good example, as are other mobile browsers, as the mobile platform has different ui concerns.
My Particular Purpose
For my purposes, I want to target IE specifically in order to alert the user to use another browser.
You may not agree with what I want to do, but please disregard that in your answer.
With this in mind, what the best, most reliable way to detect browser versions, more specifically any IE version, and iOS Safari too.
Is it safe to still use jquery.browser?
Use Conditional Comments. The are a perfect fit for what you're after.
Also, it's all very well and good to tell people to use feature detection but in the real world, when you have 3 days to update the browser detection on your company's website you can't go and re-write all the Javascript just to take advantage of this, so I say, heck yes, use browser sniffing, because sometimes you don't have a choice.

Browser detection versus feature detection

I am going to play a devil's advocate for a moment. I have been always wondering why browser detection (as opposed to feature detection) is considered to be a flat out as a bad practise. If I test a certain version of certain browser and confirm that, that certain functionality behaves is in some predictable way then it seems OK to decide to do special case it. The reasoning is that it will be in future foolproof, because this partial browser version is not going to change. On the other hand, if I detect that a DOM element has a function X, it does not necessarily mean that:
This function works the same way in all browsers, and
More crucially, it will work the same way even in all future browsers.
I just peeked into the jQuery source and they do feature detection by inserting a carefully constructed snippet of HTML into DOM and then they check it for certain features. It’s a sensible and solid way, but i would say that it would be a bit too heavy if i just did something like this in my little piece of personal JavaScript (without jQuery). They also have the advantage of practically infinite QA resources. On the other hand, what you often see people doing is that they check for the existence of function X, and then based on this, they assume the function will behave certain way in all browsers which have this function.
I’m not saying anything in the sense that feature detection is not a good thing (if used correctly), but I wonder why browser detection is usually immediately dismissed even if it sounds logical. I wonder whether it is another trendy thing to say.
It seems to me browser detection has been widely frowned upon since this post by Resig a couple of years ago. Resig's comments however were specific to libraries/framework code, i.e. code that will be consumed by other [domain-specific] applications/sites.
I think feature detection is without question a good fit for libraries/frameworks. For domain-specific applications however I'm not so sure browser detection is that bad. It's suitable for working around known browser characteristics that are difficult to feature-detect, or for browsers that have bugs in their implementation of the feature itself. Times that browser detection is appropriate:
sites/applications that are not cross-browser and need to show a warning/dialog/DifferentPage tailoring to that client's browser. This is common in legacy applications.
Banks or private sites with strict policies on what browsers and versions are supported (to avoid known security exploits that may compromise user's data)
micro-optimizations: occasionally one browser is ridiculously faster than the others when performing some operation a certain way. It can be advantageous depending on your user base to branch on that particular browser/version.
Lack of png transparency in IE6
many display/rendering issues (read: IE css support) that are only witnessed in specific browser versions and you don't actually know what feature to test for.
That said, there are some major pitfalls (probably committed by most of us) to avoid when doing browser detection.
Here's a good article explaining how feature detection is superior in so many ways to browser sniffing.
The truth is that sniffing is extremely fragile. It's fragile in theory, as it relies on an arbitrary userAgent string and then practically maps that string to a certain behavior. It's also fragile in practice, as time has shown. Testing every major and minor version of dozens of browsers and trying to parse build numbers of some of those versions is not practical at all; Testing certain behavior for quirks, on the other hand, is much more robust. Feature tests, for example, often catch bugs and inconsistencies that browser vendors incidentally copy from each other.
From my own experience, fixing Prototype.js in IE8, I know that 90% of the problems could have been avoided if we didn't sniff in the first place.
While fixing Prototype.js I discovered that some of the features that need to be tested are actually very common among JS libraries, so I made a little collection of common feature tests for anyone willing to get rid of sniffing.
The ideal solution would be to have a combination of both feature and browser detection. The former falls down because of the points you mentioned and the latter because sometimes browsers publish false information to "make things work" just so.
Mozilla has a great Browser Detection Primer that might be helpful to you as well.
From wikipedia
"At various points in its history, use of the Web has been dominated by one browser to the extent that many websites are designed to work only with that particular browser, rather than according to standards from bodies such as the W3C and IETF. Such sites often include "browser sniffing" code, which alters the information sent out depending on the User-Agent string received. This can mean that less popular browsers are not sent complex content, even though they might be able to deal with it correctly, or in extreme cases refused all content. Thus various browsers "cloak" or "spoof" this string, in order to identify themselves as something else to such detection code; often, the browser's real identity is then included later in the string."

Categories