Timing issues with IE6 and SWFObject
May 23, 2008
Flash
iPresent is new software for Windows that creates synchronized powerpoint and video presentations. It outputs to a variety of formats, but I purchased it for its Flash output capabilities. However, when I output a file using the latest version, I found that IE6 was giving an error whenever a Table of contents button or slide thumbnail was clicked on:


Ads by Google

Posted by ellen at May 23, 2008 11:09 AM "flowPlayer1" is null or not an object.
A little research showed that this is a common issue with swfobject, and is really just a timing issue, not an issue that is specific to iPresent. The problem happens when you call functions on the player before it is really there. Firefox and IE7 did not seem to care, but IE6 does.
So, here is what doesn't work:





Untitled Document



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <!-- saved from url=(0014)about:internet --> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>FlowPlayer</title> <style> body { margin: 0px 0px 0px 0px; padding: 0px 0px 0px 0px; background-color: #E5E5E5; color: #000000; font-size: 12px; font-family: verdana, "Lucida Grande", arial, helvetica, sans-serif; } #pres_link { font-size: 10px; } </style> <script type="text/javascript" src="swfobject.js"></script> <script type="text/javascript"> /* * Init and setup FlowPlayer. This example file shows 'advanced' features like * playlists and configuring with JavaScript. FlowPlayer.html is a simpler example. */

var flowPlayer1; function init() { if (document.getElementById) { flowPlayer1 = document.getElementById("FlowPlayer"); } }

// wait for the page to fully load before initializing window.onload = init;

/* * JavaScript event hanlders: */ var pStatus='PLAYING';

function seek(ms) { secs = Math.round(ms/1000); if (pStatus=='PAUSED' || pStatus=='STOPPED') {flowPlayer1.DoPlay();} flowPlayer1.Seek(secs); parent.frames['slidearea'].document.slide.src = parent.oPres.SLIDES[parent.GetSlideIdxByTimepoint(ms)].SlideFile; }

function getDuration() { var value = flowPlayer1.getDuration(); }

function getPercentLoaded() { var value = flowPlayer1.getPercentLoaded(); //var field = document.getElementById("loaded"); //field.value = value; }

/* * Flash callback handlers. The player calls these on specific events: */

function onClipDone(clip) {

}

function onLoadBegin(clip) {

}

function onStartBuffering(clip) {

}

function onPlay(clip) { pStatus='PLAYING'; }

function onStop(clip) { pStatus='STOPPED'; }

function onPause(clip) { pStatus='PAUSED'; }

function onResume(clip) {

}

function onCuePoint(cuePoint) { parent.frames['slidearea'].document.slide.src = cuePoint.thumb; seq=cuePoint.thumb.split('_'); parent.SetCurrentSlide(seq[1]); }

</script> </head> <body>

<div style="padding:5px 5px 2px 5px;"><strong>The Toyota Way</strong></div> <div id="pres_link" style="padding:0px 5px 7px 5px;"> <a href="#" onclick="parent.NewWindow('details.htm','mywin2','640','320','yes','center');return false">[Presentation Details]</a> </div>

<div id="flowplayerholder"> This will be replaced by the player. </div> <script type="text/javascript"> var fo = new SWFObject("FlowPlayerWhite.swf", "FlowPlayer", "300", "240", "8", "#ffffff", true); fo.addParam("AllowScriptAccess", "always"); fo.addParam("allowFullScreen", "true"); fo.addVariable("config", "{ playList: [ { url: '1.flv' } ], autoPlay: true, showPlayListButtons: true, initialScale: 'scale',showPlayList: false, bufferLength: 1, loop: false, hideControls: false, progressBarColor1: 0xFF0000, progressBarColor2: 0xFF0000, bufferBarColor1: 0x00FF00, bufferBarColor2: 0x00FF00, progressBarBorderColor1: 0xAAAAAA, progressBarBorderColor2: 0xAAAAAA, useNativeFullScreen: true, autoBuffering: true, showFullScreenButton: false, menuItems: [true,true,true,true,false,false] }"); fo.write("flowplayerholder"); </script>

</body> </html>


Note that the "init" function is called with a window.onload statement and that the swfobject player "write" statement comes just after the div which will contain the player. What did I change? I moved the "fo.write" statement into a new function called doLoad, and called both doLoad()and init() using the "body onload" event.
This works:




Untitled Document



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <!-- saved from url=(0014)about:internet --> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>FlowPlayer</title> <style> body { margin: 0px 0px 0px 0px; padding: 0px 0px 0px 0px; background-color: #E5E5E5; color: #000000; font-size: 12px; font-family: verdana, "Lucida Grande", arial, helvetica, sans-serif; } #pres_link { font-size: 10px; } </style> <script type="text/javascript" src="swfobject.js"></script> <script type="text/javascript"> /* * Init and setup FlowPlayer. This example file shows 'advanced' features like * playlists and configuring with JavaScript. FlowPlayer.html is a simpler example. */

var flowPlayer1; function init() { if (document.getElementById) { flowPlayer1 = document.getElementById("FlowPlayer"); } } function doLoad(){ var fo = new SWFObject("FlowPlayerWhite.swf", "FlowPlayer", "300", "240", "8", "#ffffff", true); fo.addParam("AllowScriptAccess", "always"); fo.addParam("allowFullScreen", "true"); fo.addVariable("config", "{ playList: [ { url: '1.flv' } ], autoPlay: true, showPlayListButtons: true, initialScale: 'scale',showPlayList: false, bufferLength: 1, loop: false, hideControls: false, progressBarColor1: 0xFF0000, progressBarColor2: 0xFF0000, bufferBarColor1: 0x00FF00, bufferBarColor2: 0x00FF00, progressBarBorderColor1: 0xAAAAAA, progressBarBorderColor2: 0xAAAAAA, useNativeFullScreen: true, autoBuffering: true, showFullScreenButton: false, menuItems: [true,true,true,true,false,false] }"); fo.write("flowplayerholder");

}

/* * JavaScript event hanlders: */ var pStatus='PLAYING';

function seek(ms) { secs = Math.round(ms/1000); if (pStatus=='PAUSED' || pStatus=='STOPPED') {flowPlayer1.DoPlay();} flowPlayer1.Seek(secs); parent.frames['slidearea'].document.slide.src = parent.oPres.SLIDES[parent.GetSlideIdxByTimepoint(ms)].SlideFile; }

function getDuration() { var value = flowPlayer1.getDuration(); }

function getPercentLoaded() { var value = flowPlayer1.getPercentLoaded(); //var field = document.getElementById("loaded"); //field.value = value; }

/* * Flash callback handlers. The player calls these on specific events: */

function onClipDone(clip) {

}

function onLoadBegin(clip) {

}

function onStartBuffering(clip) {

}

function onPlay(clip) { pStatus='PLAYING'; }

function onStop(clip) { pStatus='STOPPED'; }

function onPause(clip) { pStatus='PAUSED'; }

function onResume(clip) {

}

function onCuePoint(cuePoint) { parent.frames['slidearea'].document.slide.src = cuePoint.thumb; seq=cuePoint.thumb.split('_'); parent.SetCurrentSlide(seq[1]); }

</script> </head> <body onLoad="doLoad();init();">

<div style="padding:5px 5px 2px 5px;"><strong>The Toyota Way</strong></div> <div id="pres_link" style="padding:0px 5px 7px 5px;"> <a href="#" onclick="parent.NewWindow('details.htm','mywin2','640','320','yes','center');return false">[Presentation Details]</a> </div>

<div id="flowplayerholder"> This will be replaced by the player. </div> <script type="text/javascript"> /* var fo = new SWFObject("FlowPlayerWhite.swf", "FlowPlayer", "300", "240", "8", "#ffffff", true); fo.addParam("AllowScriptAccess", "always"); fo.addParam("allowFullScreen", "true"); fo.addVariable("config", "{ playList: [ { url: '1.flv' } ], autoPlay: true, showPlayListButtons: true, initialScale: 'scale',showPlayList: false, bufferLength: 1, loop: false, hideControls: false, progressBarColor1: 0xFF0000, progressBarColor2: 0xFF0000, bufferBarColor1: 0x00FF00, bufferBarColor2: 0x00FF00, progressBarBorderColor1: 0xAAAAAA, progressBarBorderColor2: 0xAAAAAA, useNativeFullScreen: true, autoBuffering: true, showFullScreenButton: false, menuItems: [true,true,true,true,false,false] }"); fo.write("flowplayerholder");*/ </script>

</body> </html>


Ads by Google

5 Comments

Hi Ellen

Just an FYI this example uses SWFObject 1.4, which is deprecated; if you upgrade to SWFObject 2.0 (and stick with the 'dynamic publishing' option), SWFObject will automatically handle the onload for you through a 'domready' event. It also makes the domready event available for any of your other scripting needs.

var flashvars = {
config: "{ playList: [ { url: '1.flv' } ], autoPlay: true, showPlayListButtons: true, initialScale: 'scale',showPlayList: false, bufferLength: 1, loop: false, hideControls: false, progressBarColor1: 0xFF0000, progressBarColor2: 0xFF0000, bufferBarColor1: 0x00FF00, bufferBarColor2: 0x00FF00, progressBarBorderColor1: 0xAAAAAA, progressBarBorderColor2: 0xAAAAAA, useNativeFullScreen: true, autoBuffering: true, showFullScreenButton: false, menuItems: [true,true,true,true,false,false] }"
};

var params = {
allowScriptAccess: "always",
allowFullScreen: "true"
};

var attributes = {
id: "FlowPlayer",
name: "FlowPlayer"
};

var flowPlayer1;

function init() {
if (document.getElementById) {
flowPlayer1 = document.getElementById("FlowPlayer");
if(!flowPlayer1){
alert("the flowplayer can't be located");
}
}
}

swfobject.embedSWF("FlowPlayerWhite.swf", "flowplayerholder", "300", "240", "8", null, flashvars, params, attributes);
swfobject.addDomLoadEvent(init);

If you decide to stick with the earlier version of SWFObject, you should make sure you have version 1.5.1... it fixes some video-handling bugs.

You'd also need to correct the syntax; the current code:

var fo = new SWFObject("FlowPlayerWhite.swf", "FlowPlayer", "300", "240", "8", "#ffffff", true);

has the boolean 'true' at the end; this was for ExpressInstall in SWFObject 1.4 (and older). SWFObject 1.5 uses the following syntax:

var fo = new SWFObject("FlowPlayerWhite.swf", "FlowPlayer", "300", "240", "8", "#ffffff");
fo.useExpressInstall('expressinstall.swf');

("expressinstall.swf" is the location of your expressinstall SWF, which comes with the SWFObject ZIP.)

Hope this helps! :)
- philip

Thank you VERY MUCH! I will pass this along to the iPresent folks who may want to touch up their template. Very good to know, in general.

Ellen


Hi Ellen,

Thanks for bringing this issue to our attention. I also enjoyed our discussion today - thanks for the great feedback.

We will certainly be incorporating a fix for IE6 to our Flash presentation templates for our next release.

One other quick solution I wanted to mention is that you can add a defer="defer" attribute to the script tag that contains the SWFObject.

Just change this:
script type="text/javascript"

to this:
script type="text/javascript" defer="defer"

This ensures the SWFObject object is fully loaded and there are no DOM execution timing issues, as you mentioned.

Thanks again.

Carmen-

I just wanted to add a quick response to Philip's comment on the FlowPlayer version.

FlowPlayer is a great Flash video player. We found the older version of the FlowPlayer to provide the most compatibility across browsers for our presentation templates, which include video and synchronization of slides and images.

We are always looking to improve Presio. As such, we are actively testing out the latest version of the FlowPlayer as well as other options to see if we can incorporate it into Presio.

Thanks.

Carmen-

jQuery solution for object null/not exists yet. The "live()" binds action to existing and future elements.
$(document).ready(function(){
gPageTitle = $("title").html();
$("object").live("mouseenter mouseleave mousedown mouseup",function(){
document.title = gPageTitle;
});
});


Ads by Google

 RSS   |   Contact Me


Ads by Google