Timing issues with IE6 and SWFObject

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:




"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>