built on AIR - - - - so it runs on Win, Mac and Linux:

Retrieve images from RSS – all of them

Pages: part 1 part 2 part 3

3. Two ways to load images in AIR

The “iImgUrl” could contain a string like <img alt="" src="http://some.com/html/img1.gif" or just the url of a jpg image http://some.com/html/img2.jpg – or it could be empty. Of course, when I’d do some more string manipulation, I could retrieve the url from the src element: strip out the url there, use that with the standard Loader class. But I thought it would be more fun to use the alternative HTMLLoader class, which is AIR-only, and is used to define “a type of display object that is a container for HTML content”. Like that <img>-tag.
The two classes return a different kind of object, so I’ll show how the result is parsed as well.

I’ll just follow along with the flow of the script from the Telexer app: on click of a news item, a balloon is shown which could contain an image, and if there is one, I’m going to load it. In this DisplayBalloon class I have this snippet that picks the class with which the image will be loaded:

//load external img, then wait for it to display & adjust mask/size
trace('getting _imgUrl: '+_imgUrl);
if(_imgUrl.indexOf("<img")!=-1){
   extHtmlImg = new ExternalHtmlImage(_imgUrl);
   extHtmlImg.addEventListener(ExternalHtmlImage.LOADED, onExtHtmlImg);
}else{
   extUrlImg = new ExternalUrlImage(_imgUrl);
   _mc.addChild(extUrlImg);
   extUrlImg.addEventListener(ExternalUrlImage.LOADED, onExtUrlImg);
}
showImgStatusIcon("loading");

The ExternalUrlImage class is the “normal” way of getting images, using the Loader:

package com.utils {
   import flash.display.*;
   import flash.net.URLRequest;
   import flash.events.*;
   import com.ui.DisplayBalloon;

   public class ExternalUrlImage extends Sprite {
      public static const LOADED = "urlimgloaded";
      public static const LOADERROR = "urlloaderror";
      public var imgLoader:Loader;

      public function ExternalUrlImage( $url ) {
         //create the loader and add it to the display list
         imgLoader = new Loader();
         this.addChild(imgLoader);

         //add event handlers to check for progress
         imgLoader.contentLoaderInfo.addEventListener( Event.INIT, onExtUrlImg);
         imgLoader.contentLoaderInfo.addEventListener( IOErrorEvent.IO_ERROR, onImgLoadError);
         //load in the external image
         imgLoader.load(new URLRequest($url));
      }

      private function onImgLoadError(err:IOErrorEvent):void {
         trace('there\'s a loading error  - '+err);
         dispatchEvent(new Event(ExternalUrlImage.LOADERROR));
      }
      private function onExtUrlImg(ev:Event):void{
         dispatchEvent(new Event(ExternalUrlImage.LOADED));
      }
   }
}

The ExternalHtmlImage class, using the HTMLLoader, looks like this:

package com.utils {
   import flash.display.*;
   import flash.html.*; //HTMLLoader - air only
   import flash.net.URLRequest;
   import flash.events.*;

   public class ExternalHtmlImage extends Sprite {
      public static const LOADED = "htmlimgloaded";
      public static const LOADERROR = "urlloaderror";
      public var htmlObj:HTMLLoader;

      public function ExternalHtmlImage( $url ) {
         //load snippet in AIR
         var checkStr = $url;
         htmlObj = new HTMLLoader();

         htmlObj.width = 50; htmlObj.height = 50;
         htmlObj.x = 10; htmlObj.y = 10;
         htmlObj.addEventListener(Event.COMPLETE, onExtHtmlImg);
         htmlObj.addEventListener(IOErrorEvent.IO_ERROR, onImgLoadError);

         //if false, content won't show in local sandbox -
         //htmlstr can execute code, so be sure it can be trusted
         htmlObj.placeLoadStringContentInApplicationSandbox = true;
         htmlObj.loadString(checkStr);
         this.addChild(htmlObj);
         //trace('string url looks like: '+checkStr.toString());
      }

      private function onImgLoadError(err:IOErrorEvent):void {
         trace('there\'s a loading error  - '+err);
         dispatchEvent(new Event(ExternalHtmlImage.LOADERROR));
      }
      private function onExtHtmlImg(ev:Event):void{
         dispatchEvent(new Event(ExternalHtmlImage.LOADED));
      }
   }
}

In both cases, the function dispatches an event when the image has been loaded and is ready to be displayed. Back to the DisplayBalloon class, where the two callback functions are waiting to further process the image. The objects that are returned are different in nature, so you can’t use one function to catch both.
The Loader’s event target gives access to the public var imgLoader, which has a “content” property that is the loaded Bitmap. The HTMLLoader on the other hand returns the public var htmlObj, which is a DisplayObject in which the content from the src-string is placed.

//----loaded jpg img from url----
public function onExtUrlImg(e:Event):void {
   var _t = e.target; //Loader
   var _bitmap = _t.imgLoader.content;
   showImage(_bitmap);
   showImgStatusIcon("loaded");
   _bitmap.removeEventListener( Event.INIT, onExtUrlImg );
   _bitmap.removeEventListener( IOErrorEvent.IO_ERROR, onImgLoadError );
}
//----loaded jpg, gif or png img from htmlString----
public function onExtHtmlImg(e:Event):void {
   var _htmlObj = e.target.htmlObj; //htmlLoader
   showImage(_htmlObj);
   showImgStatusIcon("loaded");
   _htmlObj.removeEventListener( Event.COMPLETE, onExtHtmlImg );
   _htmlObj.removeEventListener( IOErrorEvent.IO_ERROR, onImgLoadError );
}

Both functions call the “showImage()” function, which will scale and mask the image (untyped, as it can be a Bitmap or a DisplayObject) and add the image to the balloon clip. In showImage, you can access the width and height properties of the image, whatever the type.

So there it is.
One last thing. I looked at an Actionscript library for RSS loading (AS3 syndication lib), and while I love using libraries, this AS one is the reason for me to write this three-part article. For one, as it’s made with Flex in mind it uses a few Flex-only classes, while I’m using Flash to build stuff. So if you’re in Flash you need to customise the library. See this post for an example and some to-the-point comments.
Then, when you delve into what it actually does, it seems it only retrieves images from description and enclosure, not from media-nodes. At least I don’t see the function that ought to do that. As I’ve shown in part 1, those media nodes for images are commonly used by some big sites… It will probably be added later. But for now, it seems to me you’re better off doing your RSS load code by hand, so you know exactly what you’ll be getting. Hence my title: retrieve ALL images from RSS!

Pages: part 1 part 2 part 3

  • Digg
  • Reddit
  • del.icio.us
  • StumbleUpon
  • Mixx
  • Tumblr
  • Technorati
  • NewsVine
share and connect
Posted in category Code snippetsTagged , Bookmark the permalink
Post a comment or leave a trackback.

One Comment

  1. varriastudios
    on February 3, 2010 at 16:06 | Permalink

    Great article, thank you for putting all of this information together.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Please leave these two fields as-is: