This one is probably the most common cause of problems with JavaScript (it would probably compete with the abuse of document.all by people who do not realise that document.getElementById is the right way to do things). It's a simple enough idea. You can use this collection to ask a browser what plugin types it supports. Say you are going to put a Flash animation on the page, so you want to check if the browser supports Flash. If not, you can offer them a link to download it, or for better accessibility, you can give them alternative content. It was added to the JavaScript specification way back when IE 3 was released.
This is how it works:
var isSupported = navigator.plugins['Shockwave Flash'];
and we can even check for the version:
var v = parseInt( isSupported.description.replace( /^[^\d]*/, '' ) );
If the user has disabled it, the entry does not exist. Simple.
If the browser does not support navigator.plugins (old browsers such as Opera 5- do not support the plugins collection),
we also have the alternative navigator.mimeTypes
var isSupported = navigator.mimeTypes['application/x-shockwave-flash'];
isSupported = isSupported && isSupported.enabledPlugin; //in case they disabled it
Again not hard.
A simple if statement checks which one we should use (preference is given to the first since it also gives version numbers). Sounds simple enough. Except it isn't. Because of IE. Due to one of the most short sighted decisions, they decided not only would they not support either technique, but they would support the collections. They would just leave them empty. Their documentation gives a completely inaccurate description of the collections, making it impossible to understand what approach to take.
With IE, there is an alternative. Attempt to create a Flash ActiveX object. If that produces an error, assume it is not supported. Well wow. That sounds really sensible. So now we have to make sure we avoid the error, by placing it in an error catching structure. Netscape 4 and IE 4 did not understand try...catch, so using it would be impossible. ActiveX is also crippled in Explorer Mac, so to allow it to use the navigator.plugins array (which it supports correctly, by the way), people resort to using VBscript so that Windows IE can also be supported. One more case where IE needs a completely different system to everything else. Instead of just writing the VBscript on the page normally (which is perfectly valid), people detect IE, and use JavaScript to write the VBscript to detect Flash in IE, and get other browsers to run the correct detection script.
And here is where everything goes disastrously wrong. Most browser detects used for this have been copied for years, since the days when only IE and Netscape existed as current browsers, and are done using one of the following stupid bits of code:
if( document.layers ) {
//use navigator.plugins
} else {
//write the VBscript
}
if( document.all ) {
//write the VBscript
} else {
//use navigator.plugins
}
if( navigator.userAgent.indexOf('MSIE') != -1 ) {
//write the VBscript
} else {
//use navigator.plugins
}
This causes no end of problems:
If that is not bad enough, all of these can also fail in IE, since they all rely on VBscript. But all versions of Windows IE support VBscript don't they? Surprise; no. VBscript was the cause of a number of security holes in IE, and many users and corporations choose to install IE without VBscript support. And if IE did things properly, that would be ok.
It is a complete mess. All caused by not just a missing object, but by a completely incorrect implementation of an otherwise very useful set of collections. So one simple if statement and three lines of code becomes a few kilobytes of code, requiring knowledge of two separate programming languages. It produces errors in other current browsers, fails to work even in Explorer Mac, and doesn't even work in all Windows IE installs. Thanks again IE. Thankyou so much.
Demo:
Workaround: Use a properly written support detect script.