AS3: SequentialLoader

View Example 1
View Example 2
View Documentation
Download Class & Example Files

UPDATE 10/14/08: Added a new parameter that checks policy files for downloading assets from a different server.

The SequentialLoader loads a series of SWFs and/or images in an ordered sequence. This is a conversion of the AS2 SequentialLoader class originally written by Tom Stanley with some additional methods added for more control.

The first example shows the simplest usage of SequentialLoader. The second example shows how to use SequentialLoader with the optional pauseAfterEachLoad property which allows you to run a set of actions after each item has loaded before you resume loading the rest of the sequence. The example loads a small image and then its corresponding large image below it before it goes on to load the next thumb/large image combo.

The class dispatches a custom SequentialLoaderEvent depending on what happens. The events are as follows:

Here is the code:

Actionscript:
  1. /**
  2. * The SequentialLoader loads a series of SWFs and/or images in an ordered sequence.  This is a conversion of the AS2 SequentialLoader class
  3. * originally written by Tom Stanley [http://www.staticmethods.com] with some additional methods added for more control.
  4. *
  5. * <p>The class dispatches a custom SequentialLoaderEvent depending on what happens.  The events are as follows:</p>
  6. *
  7. * <ul>
  8. * <li>SequentialLoaderEvent.ON_ITEM_START: Dispatched when an item starts to load (params object contains index)</li>
  9. * <li>SequentialLoaderEvent.ON_ITEM_PROGRESS: Dispatched while an item is loading (params object contains index, percent loaded, bytesLoaded, bytesTotal)</li>
  10. * <li>SequentialLoaderEvent.ON_ITEM_INIT: Dispatched when an item is loaded (params object contains index, asset)</li>
  11. * <li>SequentialLoaderEvent.ON_ITEM_SKIPPED: Dispatched when an item fails to load (params object contains index)</li>
  12. * <li>SequentialLoaderEvent.ON_SEQUENCE_COMPLETE: Dispatched when every item in the sequence has finished loading</li>
  13. * </ul>
  14. *
  15. * @usage
  16. * <code>
  17. * <pre>
  18. import com.reintroducing.loaders.SequentialLoader;
  19. import com.reintroducing.events.SequentialLoaderEvent;
  20. var assets:Array = new Array("1.jpg", "2.jpg", "3.jpg", "4.jpg", "5.jpg");
  21. var sl:SequentialLoader = new SequentialLoader(assets, false);
  22. sl.addEventListener(SequentialLoaderEvent.ON_ITEM_START, handleItemStart);
  23. sl.addEventListener(SequentialLoaderEvent.ON_ITEM_PROGRESS, handleItemProgress);
  24. sl.addEventListener(SequentialLoaderEvent.ON_ITEM_INIT, handleItemInit);
  25. sl.addEventListener(SequentialLoaderEvent.ON_ITEM_SKIPPED, handleItemSkipped);
  26. sl.addEventListener(SequentialLoaderEvent.ON_SEQUENCE_COMPLETE, handleSequenceComplete);
  27. function handleItemStart($evt:SequentialLoaderEvent):void
  28. {
  29.     trace("Item " + $evt.params.index + " has started loading.");
  30. }
  31. function handleItemProgress($evt:SequentialLoaderEvent):void
  32. {
  33.     trace("Item " + $evt.params.index + " is " + $evt.params.percent + "% loaded");
  34. }
  35. function handleItemInit($evt:SequentialLoaderEvent):void
  36. {
  37.     var asset:Loader = $evt.params.asset;
  38.     asset.x = ($evt.params.index * 160);
  39.     addChild(asset);
  40. }
  41. function handleItemSkipped($evt:SequentialLoaderEvent):void
  42. {
  43.     trace("Item " + $evt.params.index + " skipped.");
  44. }
  45. function handleSequenceComplete($evt:SequentialLoaderEvent):void
  46. {
  47.     trace("Sequence completed.");
  48. }
  49. sl.start();
  50. * </pre>
  51. * </code>
  52. *
  53. * @author Matt Przybylski [http://www.reintroducing.com]
  54. * @version 1.0
  55. */
  56.  
  57. package com.reintroducing.loaders
  58. {
  59.     import flash.display.Loader;
  60.     import flash.events.Event;
  61.     import flash.events.EventDispatcher;
  62.     import flash.events.IOErrorEvent;
  63.     import flash.events.ProgressEvent;
  64.     import flash.net.URLRequest;
  65.    
  66.     import com.reintroducing.events.SequentialLoaderEvent
  67.  
  68.     public class SequentialLoader extends EventDispatcher
  69.     {
  70. //- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
  71.  
  72.         private var _assets:Array;
  73.         private var _pauseAfterEachLoad:Boolean;
  74.         private var _isPaused:Boolean;
  75.         private var _totalLoads:uint;
  76.         private var _loader:Loader;
  77.         private var _currentIndex:uint;
  78.         private var _currentAsset:String;
  79.        
  80. //- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
  81.        
  82.         public static const DEFAULT_NAME:String = "com.reintroducing.loaders.SequentialLoader";
  83.        
  84. //- CONSTRUCTOR -------------------------------------------------------------------------------------------
  85.    
  86.         /**
  87.          * Creates a new instance of the SequentialLoader class and passes in the assets to load.  You can set the optional pauseAfterEachLoad boolean which allows you to
  88.          * pause after each item is loaded to do another action and then resume the SequentialLoader using the resume() method.
  89.          *
  90.          * @usage <pre><code>var sl:SequentialLoader = new SequentialLoader($assets, $pauseAfterEachLoad);</code></pre>
  91.          *
  92.          * @param $assets An array that holds the paths to the SWFs/images to be loaded
  93.          * @param $pauseAfterEachLoad A boolean that allows you to pause the SequentialLoader after each item is loaded
  94.          */
  95.        
  96.         public function SequentialLoader($assets:Array, $pauseAfterEachLoad:Boolean = false):void
  97.         {
  98.             this._assets = new Array();
  99.            
  100.             this._assets = $assets;
  101.             this._pauseAfterEachLoad = $pauseAfterEachLoad;
  102.             this._totalLoads = this._assets.length;
  103.         }
  104.        
  105. //- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
  106.        
  107.         private function loadItem($index:uint):void
  108.         {
  109.             this._currentIndex = $index;
  110.             this._currentAsset = this._assets[this._currentIndex];
  111.            
  112.             var l:Loader = new Loader();
  113.             l.contentLoaderInfo.addEventListener(Event.INIT, doLoadInit);
  114.             l.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, doProgress);
  115.             l.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, doError);
  116.            
  117.             l.load(new URLRequest(this._currentAsset));
  118.            
  119.             this._loader = l;
  120.            
  121.             var evt:SequentialLoaderEvent = new SequentialLoaderEvent(SequentialLoaderEvent.ON_ITEM_START, {index: this._currentIndex});
  122.             this.dispatchEvent(evt);
  123.         }
  124.        
  125.         private function completeSequence():void
  126.         {
  127.             var evt:SequentialLoaderEvent = new SequentialLoaderEvent(SequentialLoaderEvent.ON_SEQUENCE_COMPLETE, {});
  128.             this.dispatchEvent(evt);
  129.         }
  130.        
  131.         private function killEvents():void
  132.         {
  133.             this._loader.contentLoaderInfo.removeEventListener(Event.INIT, doLoadInit);
  134.             this._loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, doProgress);
  135.             this._loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, doError);
  136.             this._loader = null;
  137.         }
  138.        
  139. //- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
  140.    
  141.         /**
  142.          * Starts the loading of the specified assets.
  143.          *
  144.          * @usage <pre><code>sl.start();</code></pre>
  145.          *
  146.          * @return Nothing
  147.          */
  148.        
  149.         public function start():void
  150.         {
  151.             this.loadItem(0);
  152.         }
  153.        
  154.         /**
  155.          * Pauses the SequentialLoader at its current loading position.
  156.          *
  157.          * @usage <pre><code>sl.pause();</code></pre>
  158.          *
  159.          * @return Nothing
  160.          */
  161.        
  162.         public function pause():void
  163.         {
  164.             this._isPaused = true;
  165.         }
  166.        
  167.         /**
  168.          * Resume the SequentialLoader and load the next asset in the loading sequence.
  169.          *
  170.          * @usage <pre><code>sl.resume();</code></pre>
  171.          *
  172.          * @return Nothing
  173.          */
  174.        
  175.         public function resume():void
  176.         {
  177.             this._isPaused = false;
  178.             this._currentIndex++;
  179.             this.loadItem(this._currentIndex);
  180.         }
  181.        
  182.         /**
  183.          * Cleans up the listeners used by the current Loader.
  184.          *
  185.          * @usage <pre><code>sl.destroy();</code></pre>
  186.          *
  187.          * @return Nothing
  188.          */
  189.        
  190.         public function destroy():void
  191.         {
  192.             this.killEvents();
  193.         }
  194.  
  195. //- EVENT HANDLERS ----------------------------------------------------------------------------------------
  196.    
  197.         private function doProgress($evt:ProgressEvent):void
  198.         {
  199.             var percent:Number = Math.ceil(($evt.bytesLoaded / $evt.bytesTotal) * 100);
  200.            
  201.             var params:Object = new Object();
  202.             params.index = this._currentIndex;
  203.             params.percent = percent;
  204.             params.bytesLoaded = $evt.bytesLoaded;
  205.             params.bytesTotal = $evt.bytesTotal;
  206.            
  207.             var evt:SequentialLoaderEvent = new SequentialLoaderEvent(SequentialLoaderEvent.ON_ITEM_PROGRESS, params);
  208.             this.dispatchEvent(evt);
  209.         }
  210.        
  211.         private function doLoadInit($evt:Event):void
  212.         {
  213.             var params:Object = new Object();
  214.             params.index = this._currentIndex;
  215.             params.asset = $evt.target.loader;
  216.            
  217.             var evt:SequentialLoaderEvent = new SequentialLoaderEvent(SequentialLoaderEvent.ON_ITEM_INIT, params);
  218.             this.dispatchEvent(evt);
  219.            
  220.             this.killEvents();
  221.            
  222.             if (this._currentIndex <(this._totalLoads - 1))
  223.             {
  224.                 if (this._isPaused)
  225.                 {
  226.                     return;
  227.                 }
  228.                 else if (this._pauseAfterEachLoad != true)
  229.                 {
  230.                     this._currentIndex++;
  231.                     this.loadItem(this._currentIndex);
  232.                 }
  233.             }
  234.             else
  235.             {
  236.                 this.completeSequence();
  237.             }
  238.         }
  239.        
  240.         private function doError($evt:IOErrorEvent):void
  241.         {
  242.             var params:Object = new Object();
  243.             params.index = this._currentIndex;
  244.            
  245.             var evt:SequentialLoaderEvent = new SequentialLoaderEvent(SequentialLoaderEvent.ON_ITEM_SKIPPED, params);
  246.             this.dispatchEvent(evt);
  247.            
  248.             this.killEvents();
  249.            
  250.             if (this._currentIndex <this._totalLoads - 1)
  251.             {
  252.                 if (this._isPaused)
  253.                 {
  254.                     return;
  255.                 }
  256.                 else if (this._pauseAfterEachLoad != true)
  257.                 {
  258.                     this._currentIndex++;
  259.                     this.loadItem(this._currentIndex);
  260.                 }
  261.             }
  262.             else
  263.             {
  264.                 this.completeSequence();
  265.             }
  266.         }
  267.    
  268. //- GETTERS & SETTERS -------------------------------------------------------------------------------------
  269.    
  270.         /**
  271.          * Returns the value of isPaused.
  272.          *
  273.          * @usage <pre><code>trace(sl.isPaused);</code></pre>
  274.          *
  275.          * @return Boolean
  276.          */
  277.        
  278.         public function get isPaused():Boolean
  279.         {
  280.             return this._isPaused;
  281.         }
  282.        
  283.         /**
  284.          * Sets the value of isPaused.
  285.          *
  286.          * @usage <pre><code>sl.isPaused = true;</code></pre>
  287.          *
  288.          * @return Nothing
  289.          */
  290.        
  291.         public function set isPaused($val:Boolean):void
  292.         {
  293.             this._isPaused = $val;
  294.         }
  295.        
  296.         /**
  297.          * Returns the value of pauseAfterEachLoad.
  298.          *
  299.          * @usage <pre><code>trace(sl.pauseAfterEachLoad);</code></pre>
  300.          *
  301.          * @return Boolean
  302.          */
  303.        
  304.         public function get pauseAfterEachLoad():Boolean
  305.         {
  306.             return this._pauseAfterEachLoad;
  307.         }
  308.  
  309.         /**
  310.          * Sets the value of pauseAfterEachLoad.
  311.          *
  312.          * @usage <pre><code>sl.pauseAfterEachLoad = true;</code></pre>
  313.          *
  314.          * @return Nothing
  315.          */
  316.        
  317.         public function set pauseAfterEachLoad($val:Boolean):void
  318.         {
  319.             this._pauseAfterEachLoad = $val;
  320.         }
  321.  
  322. //- HELPERS -----------------------------------------------------------------------------------------------
  323.    
  324.         public override function toString():String
  325.         {
  326.             return "com.reintroducing.loaders.SequentialLoader";
  327.         }
  328.    
  329. //- END CLASS ---------------------------------------------------------------------------------------------
  330.     }
  331. }

If you found this post useful, please consider leaving a comment, subscribing to the feed, or making a small donation.

19 Comments

Hello. Just had a brief look and its looking very cool. It's a great contribution to the community. Appreciated.

(PS What plugin is that - can you email it because the one at my blog died..) Thanks

Thanks Lawrence.

Which plugin are you talking about? The code hilighter? If that's the case, its iG:Syntax Hiliter.

[...] made a very small update to the SequentialLoader which allows you to pass in an optional parameter to check for policy files when loading content [...]

This is awesome. Haven't looked into the code yet, but is it possible to make this load images from an XML file?

Joe,
Sure! You just have to parse the paths of the images into an array so that you could pass that array in as the asset array before initializing the SequentialLoader.

Matt, that's awesome. Thanks!

Matt,

I got the SequentialLoader to pull images from an XML file.
It works great but I'm also adding movieclip buttons on the stage, one for each image. I want the buttons to correspond to an image. It's simple to associate a button with an image in a standard XML gallery, but not sure how to do that here.
Basically I just want to add one button for each image, then have that image move to the front and alpha tween to 100%.

Joe,
It's hard to say because I don't know how your files are set up, but if you take a look at the Image Slider on this blog you could see how I used the SequentialLoader and then had images corresponding to an xml file as well as being clickable. Hope that helps

Thanks- I'll check out the image slider.

Just using your class in project and gotta say - it's a really nice time saver! Big tkank YOU Matt! Best regards!

Hey, great work,i've used it, but, it can be used to download video alongside with swf or images?

cheers
have a nice day

@metaisaak: Unfortunately no, it only works for images/swfs.

Thanksanyway.. great job,!

What happens to the params object that is stored in the SequentialLoaderEvent. Does this stay in memory because i don't see anywhere its getting removed. Other than that I think this is a great class and well done in its setup.

@Eric: Unfortunately there is nothing to clear that object, though I'd presume it'd be pretty easy to write something to either clear it or just set it to null when done with it. Either way I don't think the footprint of it is very large at all unless you have hundreds of them. And thanks for the kind words, I've actually built a newer system of managing image loading since this but have yet to release it, probably because you will find out shortly that there is something even better thats going to become available 😛

What if you set your public params to private and used a getter and setter to retrieve it. Would you still need to use a destroy method to clean up the private params property.

"I've actually built a newer system of managing image loading since this but have yet to release it, probably because you will find out shortly that there is something even better thats going to become available"

Please let us know when you release the new version. Do you mean you are releasing something better or someone else is releasing something better?

Thanks,
Eric

@Eric: If you set them to private and use get/set you'll have to create a method to destroy them, yes.

And while I do have something better, someone else has something that is going to "revolutionize" loading of external assets 😛

Great keep us posted when it comes out.

I've added "params.MCasset = $evt.target.loader.content;" on your SequentialLoader.as file to enable casting into MovieClip.

Btw very good class!! two thumbs up!!

"
private function doLoadInit($evt:Event):void
{
var params:Object = new Object();
params.index = this._currentIndex;
params.asset = $evt.target.loader;
params.MCasset = $evt.target.loader.content;

"

Leave a comment

(required)

(required)