|
On a recent project, I found an oddity with the loader component. I found some images loaded with it were having their complete event fired before the image was actually done loading. This caused all sorts of problems, as I was dynamically resizing a frame around the loaded content in the complete event. With the event firing prematurely, the height and width of the content were showing as 0,0 so the frame was not being properly sized. It seems the issue lies with the mx.core.ExternalContent class which is used by mx.core.View (the superclass of Loader).
ExternalContent has a method checkLoadProgress which reads like this:
function checkLoadProgress():Void
{
var i:String;
for (i in loadList)
{
var x:Object = loadList[i];
//trace("loading..." + i);
x.loaded = x.obj.getBytesLoaded();
x.total = x.obj.getBytesTotal();
//trace( x.loaded +"/"+ x.total );
if (x.total > 0)
{
x.obj._visible = false;
dispatchEvent({type: "progress", target: x.obj, current: x.loaded, total: x.total});
if (x.loaded == x.total) {
if (loadedList == undefined)
loadedList = new Object();
loadedList[i] = x;
delete loadList[i];
doLater(this, "contentLoaded");
}
}
else if (x.total == -1)
{
// sometimes you get a -1 before it starts loading
if (x.failedOnce != undefined)
{
x.failedOnce++;
if (x.failedOnce > 3)
{
dispatchEvent({type: "complete", target: x.obj, current: x.loaded, total: x.total});
//trace("total == -1 loaded = " + x.loaded);
delete loadList[i];
delete x;
}
}
else
x.failedOnce = 0;
}
else
{
}
doLater(this, "checkLoadProgress");
}
}
The problem is the line "if (x.failedOnce > 3)" whats happening here, is that if after 3 tries the content still hasn't started loaded (therefore the getBytesLoaded() call returns -1), this component fires its complete event, even though it hasnt actually started. I dont know why this is being done, but clearly, its causing problems.
There are several possible solutions, including one mentioned on bgxcomponents.com, which uses the prototype method to override the component.
Another less desirable solution would be to change the code in the ExternalContnet class. this is clearly a bad solution, as this code was probably written for a reason, and just because we dont understand why, doesnt mean its not valid for some cases.
The OO friendly solution would be to subclass Loader, and override the method for our new subclass. I've done this, the code can be seen below.
class IELoader extends mx.controls.Loader{
static var symbolName:String = "IELoader";
static var symbolOwner:Object = IELoader;
var className:String = "IELoader";
var loadList:Object;
var loadedList:Object;
function checkLoadProgress(){
for (var i in this.loadList){
var x:Object = this.loadList[i];
x.loaded = x.obj.getBytesLoaded();
x.total = x.obj.getBytesTotal();
if (x.total > 0){
x.obj._visible = false;
this.dispatchEvent({type: "progress", target: x.obj, current: x.loaded, total: x.total});
if (x.loaded == x.total) {
if (this.loadedList == undefined){
this.loadedList = new Object();
}
this.loadedList[i] = x;
delete loadList[i];
this.doLater(this, "contentLoaded");
} else {
this.doLater(this, "checkLoadProgress");
}
} else {
if (x.total == -1){
if (x.failedOnce != undefined){
x.failedOnce++;
} else {
x.failedOnce = 0;
}
}
this.doLater(this, "checkLoadProgress");
}
}
}
}
Remember, this is a class file for a new Component. To effectively use it, it needs to be linked with a movie clip, which will act as your component. For ease of use, I've uploaded an installer which contains this class packaged as a Flash component. You can download it from here.
You've outdone yourself on this one! The component works perfectly.
Macromedia needs to thank you for fixing they're software...
Jon Lawpaugh
I have been struggeling around with this problem all day...without any
success until i found your component...its works perfectly fine!!
For the past three days all that I have done is to search for a solution to
this problem!!! Thanks for providing such a dynamite solution. I've run
into this problem many time in my application development, and you're the
first person who's provided a real, workable solution. Thanks a million!!!
Thank You very mutch for this solution. Like all others I went crazy!
Thanks again! Phil from Switzerland
Now what kind of component fires "complete" when it's not complete? Go
figure...
it might be an overstatement to say that you saved my life, but only
slightly. you did save my sanity. i have spent the last day and a half a)
trying to figure out why ie was blowing apart my project, which worked
great on every other browser, and b) honing the search terms to describe
the problem until i finally arrived here.
wow! good work! that's why Firefox was the only browser running my loaders
properly. MX 2004 help says about Loaders:
"If you load certain version 2 components into a SWF file or into the
Loader component, the components may not work correctly. These components
include the following: Alert, ComboBox, DateField, Menu, MenuBar, and
Window."
Well.. they work now!
I cant tell you how many hours I have wasted over the past year or so
trying to fix IE and the loader component. I had even given up on using it,
because of this bug - although I thought it was IE's fault, and not
Macromedia's.
I second that! I've just spent 3 days trying to get to the bottom of a
Loader problem - this has fixed it completely - a thousand thanks! :-)
Wow, this is perfect. I am amazed MM did not fix this in their "Flash 8"
release.
Vahe
Indeed, MM should have fixed it in F8.
I have the same problem but with the ScrollPane Component.
I guess the the ScrollPane uses the Loader component to load the content,
and i must change this with IELoader. But how?
Actually, both Loader and ScrollPane extend View, and its View that has the
mixins from the ExternalContent class. The real bug is in ExternalContent,
so this can potentially be seen by any subclass of View. You can use the
same fix I list above, but you will want to subclass ScrollPane instead of
Loader. Something like this.
class MyScrollView extends mx.core.ScrollView{
static var symbolName:String = "MyScrollView";
static var symbolOwner:Object = MyScrollView;
var className:String = "MyScrollView";
var loadList:Object;
var loadedList:Object;
function checkLoadProgress(){
for (var i in this.loadList){
var x:Object = this.loadList[i];
x.loaded = x.obj.getBytesLoaded();
x.total = x.obj.getBytesTotal();
if (x.total > 0){
x.obj._visible = false;
this.dispatchEvent({type: "progress", target: x.obj, current:
x.loaded, total: x.total});
if (x.loaded == x.total) {
if (this.loadedList == undefined){
this.loadedList = new Object();
}
this.loadedList[i] = x;
delete loadList[i];
this.doLater(this, "contentLoaded");
} else {
this.doLater(this, "checkLoadProgress");
}
} else {
if (x.total == -1){
if (x.failedOnce != undefined){
x.failedOnce++;
} else {
x.failedOnce = 0;
}
}
this.doLater(this, "checkLoadProgress");
}
}
}
}
one more thanx to you
you're good you, you're good... :-)
Solved a big headache! And I thought I was doing something wrong. @_@;
Thanks a million!
Thanks, but I got a problem in FireFox. I'm using Image component in a
CellRenderer of a TileList (Flex 1.5). What is does is reusing the tiles
while scrolling. therefor the content of the Image is changed everytime on
scrolling. The Effect in FireFox is that every request is shown!!! So the
image is flickering untill the last image is reached. No problem in IE it
works fine. If you need more info contact me..
function setValue(suggested:String,item:Object,selected:String):Void {
if(item.someid==undefined){
this.imageID=undefined;
}
if (item!=undefined && (this.imageID!=item.someid)){
this.image.load(item.imageURL);
this.imageID=item.someid;
}
}
Jeff,
Thanks a million. This loader component allowed me to leave some hair on my
head!
Regards
Hi Jeff, I can see that IELoader works perfectly, but how can you override
a method from a class (ExternalContent) that isn't a supertype of IELoader?
Thank you very very much, I was struggling for more than 2 months around
this issue.
I've been struggling with the scrollpane properly loading its content with
IE. On firefox it loads the content perfectly, but in IE instead of masking
the content page, it is placed in front if everything else.
http://www.yourbackupvault.com/ybv2
Hey! Thanks for the heads up! I've spent many hours trying to figure out
what the problem was.
I certainly understand that, I spent more hours than I even want to think
of trying to figure it out. Here is a link from the Flash site which
contains a possible solution let me know if it helps:
The URL wouldn't load (probably because of the session ID). I'm curious to
know what knowledgebase article you found.
Adobe TechNote Details
ID: 17226748
Product(s): Flash Player, Flash
Versions: MX 2004
OS: NA
Browser: Internet Explorer
Server: NA
Database: NA
THANK YOU! Thank you so much for writing this. I thought it was just me!
I've had that little bug haunting me for months; now I can finally make my
app BUG-FREE! Rad!
Hey Hey! Wonderful work! I was also having troubles doing cross-browser
testing - you have made my life 10 x easier already!!
Hey Hey! Wonderful work! I was also having troubles doing cross-browser
testing - you have made my life 10 x easier already!!
I have been fussing with this issue for almost a month now. Thank you a
thousand times over for finding this bug.
Thank you very much!!!!!!. Wonderful work!!!!
you have saved my life with this. ive been trying to figure this out all
day
Please, I newbie in Flash and I could not solve the problem with the
scrollPane component, even try to use the Class suggested by Jeff Tapper.
Dear Jeff,
hey will this fix the problem i have on my site??
Just have to say Big Thanks. Been losing sleep over this problem for ages.
This is fantastic!!
Thanks
Thanks a lot. Fortunately, I only speed about an hour before finding this
code.
I've spent about three hours trying to fix this since I assumed it was
something wrong with how I was handeling events. Finally I checked google
and found you.
Thank you
you are a golden god of awesomeness!
Thanks Jeff for your excellent help!
GREAT CONTRIBUTION! I was loosing my sleep with the wrong IE positiioning
and resiziing problem of the mx.controls.Loader up till I found your post.
Wooohoo! Finally it works in IE just like it does in Firefox. I couldn't
believe it can be beacuse of a bug but luckily a friend of mine showed me
your post. THANK YOU And for the installer: THANK YOU
You are my hero. I just wish I had found your page 24 hours ago.
All I can say is Wow!
thank you, thank you, thank you, thank you, thank you, thank you, thank
you, thank you
Years has this one been getting me; finally glad to find out it wasn't
shabby coding on my part!
Any idea how to fix this for Actionscript 3.0 applications as they seem to
have a simular problem with both Loader and the UILoader objects in
Internet Explorer?
I guess the same thing could be done in AS3, but I wasn't able to. However
I got another solution working. I've posted it on my site if anyone is
interested: http://labs.kaliko.com
thank you very much!
it's working perfectly :)
This is great, it saved a bunch of braincells. Can I uh... send you flowers
or something?
No need for flowers. I wrote this a few years ago when i first ran across
the problem, and am glad to share the solution with anyone who needs it.
Awesome, THANKS! You kept me from pulling the rest of my hair out.