Loading Inconsistency in IE7 (swfupload_loaded_handler doesn't fire)

I recently implemented v2.2.0 Beta 3 and have been running into random issues with IE7. Sometimes when I refresh the page, the swfupload_loaded_handler doesn't fire, and the SWFUpload functionality only works to a point. A refresh of the page fixes the issue ... until it happens again.

A quick look at the debug output reveals something interesting. When SWFUpload loads correctly and fires the event, the debug output looks like this:

---SWFUpload Instance Info---
Version: 2.2.0 Beta 3
Movie Name: SWFUpload_0
Settings:
...
Event Handlers:
...
SWF DEBUG: SWFUpload Init Complete
SWF DEBUG:
SWF DEBUG: ----- SWF DEBUG OUTPUT ----
SWF DEBUG: Build Number: SWFUPLOAD 2.2.0 Beta 3 2008-11-16
SWF DEBUG: movieName: SWFUpload_0
SWF DEBUG: Upload URL: ****
SWF DEBUG: File Types String: *.jpg
SWF DEBUG: Parsed File Types: jpg
SWF DEBUG: HTTP Success: 0
SWF DEBUG: File Types Description: JPG Images (*.jpg)
SWF DEBUG: File Size Limit: 8290304 bytes
SWF DEBUG: File Upload Limit: 100
SWF DEBUG: File Queue Limit: 100
SWF DEBUG: Post Params:
SWF DEBUG: ----- END SWF DEBUG OUTPUT ----
SWF DEBUG:
Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)

However, when it does NOT work correctly, the two sections of debug output are in a different order (Init Complete first, followed by Instance Info) AND the "Removing Flash functions hooks" line is not there. All the other debug information is the same:

SWF DEBUG: SWFUpload Init Complete
SWF DEBUG:
SWF DEBUG: ----- SWF DEBUG OUTPUT ----
SWF DEBUG: Build Number: SWFUPLOAD 2.2.0 Beta 3 2008-11-16
SWF DEBUG: movieName: SWFUpload_0
SWF DEBUG: Upload URL: ****
SWF DEBUG: File Types String: *.jpg
SWF DEBUG: Parsed File Types: jpg
SWF DEBUG: HTTP Success: 0
SWF DEBUG: File Types Description: JPG Images (*.jpg)
SWF DEBUG: File Size Limit: 8290304 bytes
SWF DEBUG: File Upload Limit: 100
SWF DEBUG: File Queue Limit: 100
SWF DEBUG: Post Params:
SWF DEBUG: ----- END SWF DEBUG OUTPUT ----
SWF DEBUG:
---SWFUpload Instance Info---
Version: 2.2.0 Beta 3
Movie Name: SWFUpload_0
Settings:
...
Event Handlers:
...

I tried searching through the forum to find a discussion on this topic, so I apologize if this has been addressed before. Has anyone seen this? Any ideas? Thank you!

P.S. I should note that everything works fine in Firefox, and I get the first version of the debug output (without the IE memory leak line, of course).

Sample Code

As a test, I made this simple demo that illustrates the failure:

<script src="/scripts/swfupload/swfupload.js" type="text/javascript"></script>

<script>
var initUploader = function() {
swfu = new SWFUpload({
swfupload_loaded_handler : uploaderLoaded,
button_placeholder_id: "spanButtonPlaceHolder",
debug : true,
flash_url : "/scripts/swfupload/swfupload.swf"
});
}

window.onload = initUploader;

var uploaderLoaded = function() {
alert('test');
}
</script>

<span id="spanButtonPlaceHolder"></span>

gyphie's picture

New code

The code you are having a problem with is new in Beta 3. We are trying to kill some IE memory leaks before they start.

Try replacing the flashReady function in swfupload.js (starting on line 779) with the replacement below.

I've added a couple additional error checks.

---------------

SWFUpload.prototype.flashReady = function () {
// Check that the movie element is loaded correctly with its ExternalInterface methods defined
var movieElement = this.getMovieElement();

if (!movieElement) {
this.debug("Flash called back ready but the flash movie can't be found.");
return;
}

// Pro-actively unhook all the Flash functions
try {
if (movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)");
for (var key in movieElement) {
try {
if (typeof(movieElement[key]) === "function") {
movieElement[key] = null;
}
} catch (ex) {
}
}
}
} catch (ex1) {

}

this.queueEvent("swfupload_loaded_handler");
};

WAMP

Thank you, gyphie. That seems to have reduced the frequency, but it still happens about 20% of the time.

I have noticed, however, that it happens mostly when I'm testing locally with WAMP. When I move the code to a remote server, the issue is very rare. A timing issue influenced by how quickly things are loading locally?

gyphie's picture

Debug in flashReady

Are you getting an error on a particular line? All that stuff it supposed to ensure that the movie is loaded and ready before JavaScript start to mess with it.

But if Flash is calling flashReady before it is really ready then we've got a problem.

JavaScript isn't throwing

JavaScript isn't throwing any unhandled errors that I can see. The only difference I see is the "SWF DEBUG: SWFUpload Init Complete" data outputting to the debug console before the "---SWFUpload Instance Info---
", which seems to indicate it thinks it's ready just a moment too soon.

Some more ... I put an alert in flashReady before the first line (var movieElement ...), and it always fires. I moved the alert right after the first line, and when it works it fires; when it doesn't, no alert fires, but no JavaScript error either.

jerry2801's picture

If you have only 1 SWFUpload

If you have only 1 SWFUpload instance, it work good (use additional error checks)

But, in two instance, it does'n work in some time!

Hope, the Solution quickly~~ thx

act, i just want to use setButtonDisabled(false) in flashReady

gyphie's picture

Working on it

We are still working on this issue. It is a caching problem and a bug in IE (this affects browsers like IE, Avant and Maxthon which are all based on the IE rendering engine).

@jerry: Generally you should not be modifying flashReady, any code should be in your swfupload_loaded_handler.

Our current line is to hope that even though IE isn't allowing the Flash to JS calls to be set up that the movie is still executed and that we can create some checks that will re-initialize them.

If that doesn't work the only other workaround we can think of is to write a server-side script that servers the SWF file and tries to send headers that prevents the browser from caching.

jerry2801's picture

Thanks a lot, i waitting for

Thanks a lot, i waitting for you

gyphie's picture

Try the trunk

A new beta will be released soon but if you don't want to wait you can get the latest changes from the SVN trunk:

http://swfupload.googlecode.com/svn/swfupload/trunk/samples/demos/swfupl...
http://swfupload.googlecode.com/svn/swfupload/trunk/samples/demos/swfupl...

We've added a routine that checks to see if the ExternalInterface (all the StartUpload and GetStats calls) are available, if not then Flash tries to set them up again.

This seems to work well and fixed all the problems with DOM manipulation and CSS. But it did not make any difference in Opera. Surprisingly IE is the best behaved in this issue. But I could not reproduce the IE caching issue and can't be sure if these changes will fix that problem.

A couple issue to watch out for: The ExternalInterface check runs once every second. If you reparent the movie (or one of its parents) you must wait at least one second before you can be sure the ExternalInterface is restored or you may call a function that is not there getting similar results. (did any of that make sense?).

Further more, hiding or reparenting causes the Movie to reload (only reparenting causes this in IE). This means the Stats and any files queued are gone AND the file ID number restarts. If you are using the File ID as a reference in the page you can not rely on it being unique. We may try to address this before the beta is released.