Fixing Firefox & Internet Explorer's Missing Stage Width & Height
If, like me you’ve been tripped up by all your movieclips not laying out correctly when using the stage.stageWidth and stage.stageHeight in Firefox or Internet Explorer. Your not alone. The problem has been documented in SWFObject’s FAQ but it isn’t exactly easy to find. So for those pulling your hair out about what could be doing this, its a bug in Firefox and Internet Explorer that for the first few frame cycles of your swf, the stage.stageHeight and stage.stageWidth will be zero.
It gets stranger, I’ve seen this take up to 6 frames to get a return that isn’t zero when loading a swf from cache ( on Firefox ) and on Internet Explorer it will definitely be zero when loading from cache. So its worth making sure that you have this in your startup function.
SWFObject’s solution is to add a single resize handler to the stage and check if the stage.stageHeight and stage.stageWidth return something that isn’t zero. Which works, most the time…..
When using the dynamic publishing method in Internet Explorer or Firefox on Mac stage.stageWidth and stage.stageHeight might initially return 0 (note that for Internet Explorer the stage size will be available on first load, however when reloading or revisiting a page it will initially be 0). The solution is to define a resize handler in your ActionScript code. The Flash Player team was obviously aware of this issue and therefore the Flash Player will keep on triggering the stage.resize event until it receives its actual width and height.
stage.addEventListener(Event.RESIZE, resizeHandler);
stage.dispatchEvent(new Event(Event.RESIZE)); // force stage resize event for normal cases
function resizeHandler(event:Event):void {
if (stage.stageHeight > 0 && stage.stageWidth > 0) {
stage.removeEventListener(Event.RESIZE, resizeHandler); // only execute once
// your initialization code here
}
}
The only problem with SWFObject’s solution is the variable amount of frames cycles that could go by ( 0 – 6 ) and in my experience of this problem, sometimes the render event happens before the stage.stageWidth and stage.stageHeight are actually set to the real stage height and width ( eg when there is multiple swfs on the same page). So in my workaround I’ve added a timer event that fires every couple seconds or so until the stage is not zero in my startup function. This way its absolutely bulletproof for both Firefox and Internet Explorer, loaded from cache or not.
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class Main extends MovieClip {
// Timer used to check the stage
private var _stageTimer : Timer;
public function Main() {
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage, false, 0, true);
}
private function onAddedToStage(e : Event) : void {
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
// We cannot rely on our stage being available now to do the layout.
// This is due to some vague bug on some browsers some times, what a pain.
_stageTimer = new Timer(500, 0);
_stageTimer.addEventListener(TimerEvent.TIMER, checkForStageAvailabilty, false, 0, true);
_stageTimer.start();
}
// Check to see if the stage is available before laying things out then initialize
private function checkForStageAvailabilty(e : TimerEvent) : void {
if( stage.stageWidth + stage.stageHeight > 0 ) {
_stageTimer.stop();
_stageTimer.removeEventListener(TimerEvent.TIMER, checkForStageAvailabilty);
_stageTimer = null;
// your initialization code here
} else {
stage.dispatchEvent(new Event(Event.RESIZE));
}
}
}
}