Which is a better way to detect a client's user-agent? - javascript

I am interested if which would be the best place to detect the client's user-agent, client-side (javascript) or server-side? I brought up the question due to the fact that some IE8 users are getting a message saying they're using IE6.

The short and correct answer is : do not use anything that relies on UserAgent sniffing.
To reliable be able to adjust code paths you should test for the specific 'thing' that the codepath is adjusted for, primarily features. This is called Feature Detection.
So if feature X is supported we do this, if not we do that.
Deducing if a feature is supported based on which UserAgent is present will rapidly fail, especially when new browsers come to the marked.
Take the following example, which can actually be found in several major libraries (!)
if (isIE8) {
// use new feature provided by IE8
} else if (isIE7) {
// use not so new feature provided by IE7 (and IE8)
} else {
// use fallback for all others (which also works in IE7 and IE8)
}
What do you think happens when IE9 comes along?
The correct pattern in this case would be
if ("addEventListener" in foo) {
// use DOM level 2 addEventListener to attach events
foo.addEventListener(...
} else if ("attachEvent" in foo) {
// use IE's proprietary attachEvent method
foo.attachEvent(...
} else {
// fall back to DOM 0
foo["on" + eventName] = ....
}

The User-agent available on both sides should be the same, unless there's funny stuff going on, which normally isn't.
If you want to show a message to IE6 users, I suggest you use conditional comments. They're an IE-specific feature and work very well for detecting IE versions.

The information found through client or server-side detection is basically the same.
Keep in mind it is extremely easy to spoof what browser you're in. There is no fail-safe way to detect all browser types accurately.

i don't know how you're checking for the user agent, but i'd do this way:
<%=
case request.env['HTTP_USER_AGENT']
when /Safari/
"it's a Mac!"
when /iPhone/
"it's a iPhone"
else
"i don't know :("
end
%>
checking directly in the user request seems to be the most consistent way to verify the user browser. And the request.env is avaliable in your controller and views, so you could pass this to rjs if needed.

For those who need to get the actual user-agent using JavaScript, you can use navigator.userAgent

Related

Cross browser navigation of DOM elements in Javascript

A teammate of mine wrote some code about a short time ago which navigated about the DOM elements in out HTML page to pre-fill some fields in a modal based on the already existing data in an object (the modal allowed a user to edit that data). The items are generated generically from a database table.
function showModal(editImage) {
var modal = document.getElementById('myModal');
var span = document.getElementsByClassName("close")[0];
var nameAndTitle = editImage.srcElement.parentElement.innerHTML;
var parent = editImage.srcElement.parentElement.parentElement;
etc....
The problem is, they only tested that it worked in Chrome. The code never worked in firefox, it seems. When I try to open one of the modals in firefox, I get the console output "TypeError: editImage.srcElement is undefined"
My question is, is there a more "correct" way to access this data that will work for any browser, or do I need to check what browser I am in and access that information in a different way depending on the browser being used?
Your immediate answer is: change srcElement to target. The Mozilla Developer Network is a very good (one of many) resource to check for standards compliance. A visit to their site for srcElement indicates that it is non-standard and makes the suggestion on the correct way (target).
Unfortunately, even APIs that are standard don't always work in all browsers. Usually, parts of a standard are implemented piecemail. Checking with authoritative sources is vital to know what is supported where.
Other resources:
The World Wide Web Consortium (W3C) for HTML, CSS, XML and many others
The European Computer Manufacturer's Association (ECMA) for JavaScript
CanIUse.com Good for quick compatibility compliance checking
As for your explicit question:
"My question is, is there a more "correct" way to access this data that will work for any browser, or do I need to check what browser I am in and access that information in a different way depending on the browser being used?"
Use standards and check for support (via the resources I've provided above) to have the best chance at cross-browser code.
DO NOT write code that checks the browser type and version to see if your code will run (browser detection) because:
There are too many browsers and too many versions - this sucks!
Browsers can and will lie to you about what they are!
Use "feature detection" when in doubt. Feature detection is code that evaluates whether a feature exists and uses it if it does. If it doesn't a fallback is provided. Here's a very common one for IE8 (and lower) browsers that did not yet support the W3C standard for event handling:
// Here we are attempting to obtain the value of the
// addEventListener property of the window object.
// IE 8 doesn't implement this property so "undefined"
// will be returned. But, because we are attempting to
// use the value as the condition of an if/then construct
// "undefined" will be converted to a boolean. "undefined"
// is a "falsey" value, so it will convert to false.
// This means that if the else portion of our construct
// is reached, we have a browser that doesn't support
// addEventListener
if(window.addEventListener){
// W3C standards are supported - do things the standard way
obj.addEventListener("click", someFunction, capture);
} else {
// Must be IE 8 or less - do things the IE way
obj.attachEvent("onclick", someFunction);
}
This is but one way to use feature detection, but it typically hinges on converting a value to a boolean. See more on it here.
That function showModal is probably an event listener, so the argument editImage is actually an Event object.
As such, the actual property that reports the source of the event - and the only one supported by Firefox - is target, while srcElement is a legacy property that was created by Microsoft and Webkit/Blink based browsers kept supporting it for compatibility. But not Firefox.
In short: use target or, if you need to support older version of Internet Explorer, try with (editImage.target || editImage.srcElement).
srcElement is from IE. The standard property is target.
You should do this:
var target = editImage.srcElement || editImage.target;

JavaScript browser detection?

I need to add a certain kind of support for touch devices on a current project. As this is the first time I have to do something like this, I took a look at the code of some "well made" websites to see how they do that.
One page does something like this:
if(document.querySelectorAll && (navigator.platform == "iPad" || navigator.platform.substring(0, 6) == "iPhone" || navigator.platform == "iPod" || navigator.userAgent.indexOf('Android') > -1)) {...}
I tested it on all the devices I have at hand and it works, but please tell me, is it alright to do it this way? Is there a "correct" way to do it?
I am asking because here I've read that browser detection should be avoided, instead object detection should be used. Now I see that they are also testing for document.querySelectorAll which is object detection, so maybe everything that comes after it is just some sort of safety net?
Browser detection should be avoided, yes. Because a browser can change.
Today, maybe google Chrome don't support a feature. But tomorrow Chrome should be updated and support it.
So if you do something like if (!isGoogleChrome()), the day when Chrome is updated, you must update your code.
You should do object detection.
For example, if you want to make sure that a function/object is here, just test it :
if (document.querySelectorAll !== undefined) {
//...
}
You could also use http://modernizr.com/ , it can detect the current browser features for you.
The code you use is very very sensible : any simple character insertion at the start would make it fail.
You could replace it with something like
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|Mini/i.test(navigator.userAgent)) { ...
But you should be aware that detecting devices is dangerous as they might be more diverse that what one thinks : some have better CPU, network access or screen than some desktop browsers. So for most uses, it's better to detect the features you need.
This detection can legitimately, in my opinion, be used to detect touch screens if you plan to maintain your site depending on available devices but there are other solutions, for example libraries like Modernizr or specific tests.

Javascript detection not working anymore

After this weekend my Wicket application cannot correctly detect javascript anymore. It doesn't work on my webhoster, on my local machine and I tested it also on another computer.
My detection script:
WebClientInfo clientInfo = (WebClientInfo)WebSession.get().getClientInfo();
if(!clientInfo.getProperties().isJavaEnabled()){
System.out.println("not enabled!");
WebSession.get().setClientInfo(null);
}
plus this in the application class:
getRequestCycleSettings().setGatherExtendedBrowserInfo(true);
I also created a wicket app from scratch, same result, no javascript detection.
While writing this I checked it in the Internet Explorer. Works fine with IE 8 + 9. Doesn't work with FF 11.0. Wicket version is 1.5.5.
Anyone can confirm this behavior? (possible JIRA-worthy...)
UPDATE: I found the cause of this behavior. isJavaEnabled checks if Java (not Javascript) is enabled. Firefox (silently) blocked the Java plugin on April 2nd, therefore no javaEnabled property set: https://addons.mozilla.org/en-US/firefox/blocked/p80. Cumbersome.
Likely this never worked, and the fact that it seemed to was dumb luck.
Looking at the javadocs for ClientProperties.isJavaEnabled(), it returns the client's navigator.javaEnabled property, which reflects whether Java is enabled, not JavaScript.
Java != JavaScript.
An alternative is to use the 'user agent' string:
public boolean javascriptSupported() {
WebRequest webRequest = (WebRequest) getRequest();
String userAgent = webRequest.getHeader("User-Agent");
if (userAgent == null || userAgent.startsWith("Googlebot")) {
return false;
}
return true;
}
I have used this to fallback on AjaxLazyLoadPanel for search engines, although you would need to expand on the list of user-agents above.
There is also WebRequest.isAjax(), which might be useful too, as it is used to determine the RedirectPolicy used, and thus, the behaviour of Wicket when Javascript is not present.

browser identification

I want to identify if the broswer is IE then goto if block, other browser to else block in Java script.
I have one code here,
var browserName=navigator.appName;
if(browserName == "Microsoft Internet Explorer"){
IE code
}
else{
Other code
}
but i want to know is there any other way of implementing it?
Rather than do browser sniffing, you should do feature detection. Later versions of IE may support standards compliant stuff that in older versions you needed to work around or use MS-specific stuff.
Microsoft themselves have written up about the best way to do this and provide examples of both bad code (via sniffing) and good code (via detection). Make sure you go down the "good code" route.
I just started using this script to identify browser, version, and OS:
http://www.quirksmode.org/js/detect.html
If you are needing to use different code based on browser support for certain objects or methods, it's usually better to use object or method detection instead of browser detection. I use the browser detection for collecting statistics on my users, not for enabling or disabling features.
Quirksmode has a short article about why you don't use browser detection this way: http://www.quirksmode.org/js/support.html It's also linked from the browser detection script.
I found that This task is quite difficult as browsers all have similar names and different userAgent strings, so this is my Conditional statement to identify browsers.
I used this to identify the browser for different style sheets.
function styc()
{
var str = navigator.userAgent;
var res = navigator.userAgent.match(/Trident/);
var res2 = navigator.userAgent.match(/Firefox/);
if(res=="Trident"||res2=="Firefox")
{
//alert(navigator.userAgent);//for testing
document.getElementById('IE_fix').setAttribute("href", "IE_fix.css");
}
else
{
//alert("no");//for testing
document.getElementById('IE_fix').setAttribute("href", "mt_default.css");
}
}
Find a unique word in the userAgent string match it and check if the condition is true or not true depending on what you are doing.
The unique word I found for IE is Trident, and also identifies IE versions according to MicroSoft(not positive on this).

disable javascript on ie browsers

is there a way to disable a certain script for all ie browsers?
You can make use of conditional compilation to determine if the client is using MSIE.
var IE = /*#cc_on!#*/false;
which can be used as
if (IE) {
// IE.
} else {
// Others.
}
Only in IE, the ! will be compiled and taken in the expression, resulting in a new expression !false, which is logically true. This works better than $.browser.msie because it can be fooled by the useragent and also better than document.all because it would affect certain Opera versions as well.
That said, what is it you're trying to disable? You can on the other hand also make use of feature detection. Here's a discussion about this: Browser detection versus feature detection
I wouldn't recommend this, but:
if(!$.browser.msie) {
//non IE script
}
I would fix the script to work in IE, or exclude it based on some feature the browser doesn't support...not just because it's IE. With any browser a feature could be added via an update tomorrow, and your script would still exclude it. See $.support for more on feature detection.
Excluding something from running because "it isn't supported" is a perfectly valid scenario. However, excluding something because "IE doesn't support it...when I wrote this code" isn't a good approach. Instead, check if the feature that you need is present, and the user gets the richest experience possible in their current browser.
You could not include the javascript at all for IE browsers using Microsoft's recommended way of inserting a conditional comment:
<!--[if !IE]>
<script src="myscript.js" type="text/javascript"></script>
<![endif]-->
or simply wrap the code you want to exclude in the comment.
If you're speaking of IE 6, you can crash it by calling this function :
function crash_IE6() {for(x in document.open);}
Seriously, the most use way of deteting IE is checking the presence of document.all... but it still isn't a good thing.
You should nerver check what browser your script is running on... you should just check the presence of the needed methods.

Categories

Resources