IE ActiveX Change
"Click to activate and use this control"

Thursday, April 20, 2006

External JavaScript solutions

The problems with all the official solutions (see links in the right hand column), is that they all require you to change your existing HTML pages. Wouldn't it be great if you could make one simple change to your site and all your pages would work again?

Well, in theory at least, you can. Any tag that is written to the page through an external script is not affected by the IE update, and so we can use an external JavaScript file to loop through and replace all the instances of <object> tags, and replace them with themselves. The basic code for this is:

theObjects = document.getElementsByTagName("object");
for (var i = 0; i < theObjects.length; i++) {
theObjects[i].outerHTML = theObjects[i].outerHTML;
}

Unfortunately there are a few problems with this solution. For a start some browsers (such as IE on a Mac) have trouble with the code, and outerHTML is an IE only property. This can easily be fixed with a check for the platform/browser.

Another issue is that if you use the data attribute in the <object> tag (such as in the Flash Satay method) then for some reason IE doesn't see any of the parameters, but again this can be overcome with a bit of JavaScript to remove the attribute, as IE doesn't use it anyway, it is only there for other browsers.

More troublesome though is the fact that IE tends to remember the original <object>, and this can cause issues such as increased memory/cpu usage, especially as IE doesn't always seem to remove the original <object> when leaving the page.

In the Macromedia Forums, fpproductions came up with a simple solution of including an window.onunload event, that kills the <object> by setting the outerHTML to an empty string.

Combining these additions together we have:

function ieupdate(){
var strBrowser = navigator.userAgent.toLowerCase();
if(strBrowser.indexOf("msie") > -1 && strBrowser.indexOf("mac") < 0){
var theObjects = document.getElementsByTagName('object');
var theObjectsLen = theObjects.length;
for (var i = 0; i < theObjectsLen; i++) {
if(theObjects[i].outerHTML){
if(theObjects[i].data){
theObjects[i].removeAttribute('data');
}
var theParams = theObjects[i].getElementsByTagName("param");
var theParamsLength = theParams.length;
for (var j = 0; j < theParamsLength; j++) {
if(theParams[j].name.toLowerCase() == 'flashvars'){
var theFlashVars = theParams[j].value;
}
}
var theOuterHTML = theObjects[i].outerHTML;
var re = /<param name="FlashVars" value="">/ig;
theOuterHTML = theOuterHTML.replace(re,
"<param name='FlashVars' value='" + theFlashVars + "'>");
theObjects[i].outerHTML = theOuterHTML;
}
}
}
}

window.onunload = function() {
if (document.getElementsByTagName) {
var objs = document.getElementsByTagName("object");
for (i=0; i<objs.length; i++) {
objs[i].outerHTML = "";
}
}
}


Note: The character in in the above code means that the code should run on one continuous line.

All that remains to do is place a call to the ieupdate somwhere on the page, now the easiest way would to include it in the window.onload event, however this is triggered when the page has finished loading, which may cause the Flash movies to play for a few seconds and then be replaced. Therefore placing a call to the ieupdate function just before the </body> is probably the best bet.
<script type="text/javascript">ieupdate();</script>


Outstanding Issues
If you use FlashVars parameter then for some reason IE doesn't see it as part of the outerHTML, and therefore isn't carried over to the rewritten object. You can get around it by passing through the information as a querystring on the swf, but we are trying to avoid altering the HTML at all!


I've updated the code to maintain any FlashVars set in the <param> tags.


In other articles we'll be looking at alternative solutions, that while requiring changes to the HTML code are very minor, especially when compared to the official solutions.

0 Comments:

Post a Comment

<< Home