views:

2614

answers:

6

I'm using a Flash TextField control to display some HTML content inside a Flash presentation to be shown on a large touch-screen kiosk. Unfortunately, if any image tag in the displayed HTML content points to a non-existent image, a dialogue is shown with the error message

Error #2044: Unhandled IOErrorEvent:. text=Error #2035: URL Not Found.

I am trying to avoid having that dialogue pop up. The solution for loading content through a loader class is to catch IOErrorEvent.IO_ERROR, but I've tried listening for that on the TextField, on stage, Main and loaderInfo to no avail. I've tried wrapping the whole thing in a try-catch, and that also doesn't work.

Here's the simplified code I'm using to find solutions:

package {
    import flash.display.Sprite;
    import flash.errors.IOError;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.text.TextField;
    import flash.text.TextFieldType;

    public class Main extends Sprite {

        public function Main():void {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }

        private function init(e:Event = null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);

            var html:TextField = new TextField();
            html.type = TextFieldType.DYNAMIC;
            html.multiline = true;
            html.htmlText = "Bogus image: <img src=\"foo.jpg\" />";         

            addChild(html);
        }
    }
}

Edit: And here's the entire working code.

For dynamic content and so forth, of course, you would need a list of images and a function to generate handlers, etc.

package {
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.errors.IOError;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.text.TextField;
    import flash.text.TextFieldType;

    public class Main extends Sprite {

        public function Main():void {
                if (stage) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
        }

        private function init(e:Event = null):void {
                removeEventListener(Event.ADDED_TO_STAGE, init);

                var html:TextField = new TextField();
                html.type = TextFieldType.DYNAMIC;
                html.multiline = true;
                html.htmlText = "Bogus image: <img id=\"image\" src=\"foo.jpg\" />";                 

                var loader:Loader = html.getImageReference("image") as Loader;
                if(loader){         
                    loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, function(e:Event):void {
                            trace("Error loading foo.jpg!");
                        });
                }               

                addChild(html);
        }
    }
}
A: 

This is a problem I'm also dealing with: it's a real annoyance. I'd really like to be able to catch all the errors. I assumed you could say...

stage.addEventListener(IOError.IO_ERROR, myErrorHandler);

...but that doesn't seem to work, as you've pointed out.

Perhaps you can check to make sure the kiosk's flash player isn't the debug version. I don't think that the release version throws the dialogs (could be wrong).

aaaidan
+2  A: 

This is a cool problem.

I have two suggestions.

1) Don't use TextField. I'm guessing that you developed in Flash before Flex, like me. You may already know this, but it took me awhile to find out: The TextField object isn't meant to be used for regular use in Flex. Check this out from the Flex3 language ref:

The TextField class is used to create display objects for text display and input. All dynamic and input text fields in a SWF file are instances of the TextField class. You can use the TextField class to perform low-level text rendering. However, in Flex, you typically use the Label, Text, TextArea, and TextInput controls to process text.

Obviously, there's nothing wrong with using TextField, but I've found that when I'm trying to figure out tricky problems, it's really helpful to do as much 'by the book' as I can to remove unknowns (as much as possible, at least).

2) I think I'd try either extending the Text component, or else creating a new component based on Text. In this component I'd add logic to load and insert images into the TextField object. That way, you could easily build and validate the string to insert into the TextField object prior to inserting it into the TextField.

If you get this working, please post - I could use it myself. :)

Ross Henderson
+3  A: 

You can add ID's to images

html.htmlText = "Bogus image: <img src=\"foo.jpg\" id="image" />";

And then setup IOErrorEvent handler to each image in HTML

var loader:Loader = html.getImageReference("image") as Loader;
if(loader){
    loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, function(e:Event):void{});
}
Ooh... I don't have time to test this at the moment but I'll get around to it.
Jesse Millikan
9 months later... Yes, this works.
Jesse Millikan
A: 

Impossible! Same problem if you use the Loader to load images that doesnt exists! Flex is a framework and the Image class uses this flash Loader object but with plenty of lines of code (check out the source of SwfLoader...).

You can check your image URL before set the htmlText property or you can create your own component to display Text and Images..

I can't believe this simple & stupid bug is not still fixed by Adobe!

eBuildy
+1  A: 

If there's a way for you to use the new FTE/TLF components, do so. Adobe is basically turning its back on the old TextField API, and this same error is a reason that I had to abandon many projects and components in the past. This error is thrown and basically cannot be caught. One of the worst aspects of Flash work in my opinion.

TLF addresses these problems and is SO much easier to work with. What would take days of experimentation in the old API now takes only a few hours. I've built a few rich text editors on the new API and it is SO very nice to use. You'll be glad you did :)

TK Kocheran
+1  A: 

I was able to detect when an image has loaded, but I think I'll follow the TLF advice. anyways if you need to know, you have to implement an enter_frame event listener on the Loader and check for the contentInfo on the bytes property the Lenght, if the image hasn't load the length is 0xffffffff, if the image has loaded the length is the size of the file, and if there is an error the bytes properties es NULL.

BUabco