WebReference.com - When You Can't Trust the Browser: the Lies Opera Tells (2/2)
[previous] |
When You Can't Trust the Browser
Opera's Little Lie
The user can change Opera's identifying user agent string in the preferences dialog. And starting with version 6 there is a 'Quick Preferences' dialog that makes it even easier:
Opera 6's quick preferences menu lets you instantly pretend you are running a different
browser.
And both Opera 5 and Opera 6 allow for the direct setting of the browser identification
in the preferences menu.
These are the userAgent
strings returned from Opera 6 in each disguise:
(the Windows XP bit would be replaced by whatever platform is used)
Identify as MSIE 5.0:
Mozilla/4.0 (compatible; MSIE 5.0; Windows XP) Opera 6.01 [en]
Identify as Mozilla 3.0:
Mozilla/3.0 (Windows XP; U) Opera 6.01 [en]
Identify as Mozilla 4.0:
Mozilla/4.78 (Windows XP; U) Opera 6.01 [en]
Identify as Mozilla 5.0:
Mozilla/5.0 (Windows XP; U) Opera 6.01 [en]
Identify as Opera:
Opera/6.01 (Windows XP; U) [en]
Another interesting thing about all this is when you install Opera for Windows on a Windows machine, it starts out life with the IE identification, and not the 'Opera.'
The point is, if you have some code that is just for IE, you can't rely on
testing for the MSIE
in the uA string. The other ids just twiddle the
version number, and don't cause the same potential for sleepless nights and
unpleasant e-mail, but when an IE is not IE you can have problems.
You can definitely spot Opera by explicitly testing the string for the 'Opera,' which is always tacked on the uA string, in a kind of "I was only fooling" tail.
if(iz('IE') && navigator.userAgent.indexOf('Opera')== -1)
But that is just bad code. It's three times as long to write and makes the engine do two separate tests to find one thing.
Opera doesn't say much about the reasons for all this, although I believe there
was a time when some large, well known sites didn't load all their pages if
the userAgent
failed the MSIE
test.
Opera just says, in their documentation:
When a Web browser connects to a Web site, it tells the Web site which browser it is. In an ideal world, all browsers would work with all sites, but that is sadly not the case. Browsers work a bit differently, and some Web sites may intentionally or unintentionally shut out some browsers as a result.
If you experience problems with a Web site, try changing the browser identification and reload the page.
Are there end users who actually play with these settings?
It feels like a programmer's toy to me. Of course, I like toys. On the Opera site they have recently added some pretty good documentation, and it appears that a major reason for giving Opera the IE switch was to run a subset of Microsoft's J-script on top of the JavaScript that is standards supported. Now, J-Script is a whole 'nuther article...
To get back to the point, sometimes Opera can handle the code written for IE. Some of the form elements, links & anchors, and images behave fairly well with basic scripts. But you can't count on it.
That's the little lie. It helped me switch my strategy for browser
testing away from the userAgent
and toward actual browser capability.
It is better to test the browser for what it can do, not what its name is.
Or might be. For example:
Finding Ids
Say you want to find an element by its id.
function Mr(hoo){
if(document.getElementById)
return document.getElementById(hoo);
// document.all must come second, or Opera (with IE setting)
// and IE will use this method
else if (document.all)
return document.all[hoo];
else if (document.layers)
return document.layers[hoo];
else return false;
}
If you are using Opera or IE5+ or Mozilla/N6 the first if, getElementById
,
will snag your man. IE4 will discover him with the all
array, and Navigator
might find the id, if the element is positioned and in the first level. If you
write your code to run depending on the result of testing an if(Mr(hoo))
statement, you'll keep out the rif raff.
A test for (create.documentFragment)
returns true for N6, Mozilla and
IE6 but not IE5 or Navigator. This works for various methods in the document
object model. Except...
The Big Lie
My favorite, separate the men from the boys, the wheat from the chaff,
never fail, do or die browser test has been (document.createElement)
.
If a browser client can create new elements in an open document, the page is wide
open for scripting with document objects.
If the browser doesn't pass the document.createElement
test, I either give
it a document write to make new content, or a link to another page, or leave
'em the plain HTML--just like mother used to make.
I have a set of tests I use enough to keep in a single function, called
iz
. Remember iz
? There is a set of strings you can send,
to test for a few important abilities. My favorite is to test for
(document.createElement)
.
I start countless scripts with a test like:
if(iz('DOM')) do a lotta DOM code;
else do some other code.
It has always worked--until the latest Opera version. Guess what Opera tells us?
Yep. Opera claims to understand document.createElement
. So it
gets in the approved section and in a microsecond it is asked to create an element
and that's all, folks... it never sees the code written for the browsers that
can't use createElement
.
It goes to show, we cannot let up. No matter how carefully we test and retest, something will come along and break our code. We have to keep testing, keep checking, and never assume we know what is coming next.
So far Opera doesn't claim to support document.createTextNode
,
so with a quick edit, I recovered. My test in iz
for the DOM now
reads:
case 'dom':return !!(document.createTextNode);
But I'm not really comfortable with iz
anymore...
About the Author
Kenneth Tibbetts is the creator of the Yankee Web Shop at https://www.yankeeweb.com/webshop.html and can be reached at: [email protected].
[previous] |
Created: April 1, 2002
Revised: April 1, 2002
URL: https://webreference.com/programming/javascript/operalies/2.html