The Elegant, Unobtrusive Javascript Workaround for "Click to activate and use this control"
Recent versions of Microsoft's Internet Explorer (6+), trace an ugly gray border around all multi-media objects embedded in web pages (Flash, Java applets, Media player widgets, etc.) and require an extra "activation" click before they can be used. This annoying feature was brought on by a stupid patent lawsuit, which Microsoft lost. (First time in years that I side with Microsoft on something.)
Several workarounds exist floating around the Interweb, including one distributed by Adobe (ick!), but they're all really, really, really ugly:
- Big, fat, and inefficient Javascript code.
- Require Javascript running to see the multi-media object at all.
- Require a major overhaul in how you embed multi-media objects in your pages.
This got me interested in writing my own piece of code that would be a) small and fast, and b) get the job done in as elegantly, unobtrusively as possible.
Here's what I came up with at work...
Step 0:
Embed your multi-media objects in your HTML as normal (using <object>
, <embed>
or <applet>
). Leave them as they are. No changes required in your HTML.
Step 1:
<embed>
and <applet>
tags, and to run also in Opera 9, after an helpful comment by David Muńoz. The minified version of the script is still only 395 bytes!Copy and paste this Javascript code into a file and let's save it as "eolasfix.js".
// Documentation & updates available at:
// http://codecentre.eplica.is/js/eolasfix/test.htm
(function( Eolas_Fixed,
win, doc,
getElementsByTagName,
outerHTML,
parentNode,
tags,
elmsToRemoveOnload,
x,
is_ie,
y,z,elm,childNode,HTML,dummy,eolasfix)
{
// run only once!
if (win[Eolas_Fixed]) return;
win[Eolas_Fixed] = 1;
eolasfix = function ()
{
// for each tag name specified in Array t
while (tags[++x])
{
// find all elements of that type in the document
// loop through the elements
y = 0;
while (elm = doc[getElementsByTagName](tags[x])[y++])
{
if (is_ie)
{
HTML = '>';
z = 0;
// <param> elements don't show up in innerHTML IE
// so we need to collect their outerHTML.
while (childNode = elm.childNodes[z++])
HTML += childNode[outerHTML];
// create a 'dummy' element
dummy = doc.createElement('i');
// inject it next to `elm`,
elm[parentNode].insertBefore(dummy, elm);
// and turn it into an `elm` clone
dummy[outerHTML] = elm[outerHTML].replace(/>/, HTML);
// increment y to skip over it
y++;
// then hide the original elm
elm.style.display = 'none';
// and save it in 'The List of Elements to Remove Later'.
elmsToRemoveOnload[elmsToRemoveOnload.length] = elm;
}
else
{
elm[outerHTML] = elm[outerHTML];
}
}
}
};
// For IE run the fix straight away (because the defer="defer"
// attribute has delayed execution until the DOM has loaded).
// Then assign a window.onload event to purge the old elements.
is_ie && !eolasfix() && win.attachEvent('onload', function(){
x=0;
while(elm = elmsToRemoveOnload[x++])
elm[parentNode].removeChild(elm);
});
// For Opera set an `DOMContentLoaded` event to run the fix.
win.opera && doc.addEventListener('DOMContentLoaded', eolasfix, 0);
})( '__Eolas_Fixed',
window, document,
'getElementsByTagName',
'outerHTML',
'parentNode',
['object','embed','applet'],
[],
-1 /*@cc_on,1 @*/
);
The code is wrapped in a self-executing anonymous function to avoid polluting the global name space - with the notable exception of one global variable __Eolas_Fixed
which is used to make sure the script runs only once (in case it gets linked to more than once within a single web-page).
The rest is hopefully fairly self-explanatory, albeit a bit "kludgy" looking, in part because of IE's quirkiness when it comes to working with <param>
elements, and furthermore because I'm optimizing the code for "minification".
Step 2:
Paste the following code-block somewhere (anywhere!) in the HTML of your page:
<script defer="defer" src="[script-folder-path]/eolasfix.js" type="text/javascript"></script>
Note: The code is wrapped inside Microsoft's proprietary conditional comment block, so all other browsers will gladly skip over it. Also: The defer
attribute tells Internet Explorer to run the script as soon as the page's HTML has finished loading, to ensure we catch all embedded objects on the page. Opera, on the other hand, gets instuctions to delay execution until onDOMContentLoaded
.
Step 3:
There's no Step 3. That's all.
See the online demo if you don't believe me. :-)
Licence
My employer says: Feel free to use this code in any way you like as long as the version version you distrubute includes a comment with an URL pointer to the demo page.
Nýleg svör frá lesendum