Skip to main content
Known Participant
August 7, 2009
Answered

Pulling data from Class Array onto a MovieClip

  • August 7, 2009
  • 2 replies
  • 1176 views

I am trying to create this slide show application that will show product information (Tennis Rackets) based on diffrent categories. A great programmer advised me that OOP would be a way to go, however i am having a difficulty with it.

I created:

A document class called CustomClass --> this class downloads all XML data from the server and pushing the content of it into Arrays based on a category.These arrays are public, there is also a funciton iterateArray which places the children information somewhere.

I would like to have 3 diffrent movie clips

1st Screen -> Welcome Message

2nd Screen -> First Array Displayed

3rd Screen -> Second Array Dispalyed

package {
     
     import flash.display.*;
     import fl.transitions.*;
     import fl.transitions.easing.*;
     import flash.net.*;
     import flash.events.*;
     import flash.text.*;
     import flash.text.AntiAliasType;
     import flash.utils.*;
     import bucket_right;
     import bucket_left;
     import firstScreen;
     import secondScreen;
     
     
     public class CustomClass extends MovieClip {
          
          
          [Embed(source="C:/WINDOWS/Fonts/Eurosti.ttf", fontFamily="Euro")]
          public  var EuroEmbedded:Class;
          
          
          //XML responsible variables
          private var xmlLoader:URLLoader;
          private var xmlContainer:XML;
          private var xmlList:XMLList;
          
          //Array specific variables
          public var rackUSA:Array;
          public var rackOther:Array;
          public var imagesArray:Array;
          
          //Position Variables
          public var position:Number;
          
          //Movie Clip Related Data
          public var bucket:MovieClip;
          public var firstScreenShow:MovieClip;
          public var secondScreenShow:MovieClip;
          
          //Text Field Formatting
          private var brandnameTxt:TextFormat;
          private var detailsTxt:TextFormat;
          private var priceTxt:TextFormat;
          public  var euroEmbeddedFont:Font;
          private var fontNeeded:String;
          
          
          //Set up Timer Vars
          private var applicationStart:Timer;
          private var delay:Number;
          private var repeat:Number;
          
          //Positioning Variable
          private var positionBuckets:Boolean = true;
          
          //This is the constructor of the application
          public function CustomClass() {
               euroEmbeddedFont = new EuroEmbedded();
               fontNeeded            = euroEmbeddedFont.fontName;
               position         = 5;
               rackUSA            = new Array();
               rackOther            = new Array();
               imagesArray       = new Array();
               
               delay                 = 2000;
               repeat                = 1;
               applicationStart = new Timer(delay, repeat);
               LoadXML();
          }
          
          private function LoadXML() {
               xmlLoader = new URLLoader();
               xmlLoader.load(new URLRequest("http://localhost/xml/index.php"));
               xmlLoader.addEventListener(Event.COMPLETE, populateInfo);
          }
          
          public function populateImages(imgname:String, imgurl:String):* {
               var imageLoader:Loader = new Loader();
               //imgname = imgname.split(".gif").join("");
               //imageLoader.name = imgname;
               //imagesArray.push(imageLoader);
              imageLoader.load(new URLRequest(imgurl));
               return imageLoader;
          }
          
          public function getArray(arrayName:Array) {
               return arrayName;
          }
          /*public function startApplication() {
               applicationStart.start();
               applicationStart.addEventListener(TimerEvent.TIMER_COMPLETE, firstScreen);
          }
          
          public function firstScreen(e:TimerEvent) {
               removeChild(secondScreenShow);
               applicationStart.reset();
               applicationStart.removeEventListener(TimerEvent.TIMER_COMPLETE, firstScreen);
               firstScreenShow = new firstScreen();
               addChild(firstScreenShow);
               //firstScreenShow.iterateArray(rackUSA);
               applicationStart.start();
               applicationStart.addEventListener(TimerEvent.TIMER_COMPLETE, secondScreen);
          }
          
          public function secondScreen(e:TimerEvent) {
               applicationStart.reset();
               applicationStart.removeEventListener(TimerEvent.TIMER_COMPLETE, secondScreen);
               removeChild(firstScreenShow);
               secondScreenShow = new secondScreen();
               addChild(secondScreenShow);
               //secondScreenShow.iterateArray(rackOther);
               applicationStart.start();
               applicationStart.addEventListener(TimerEvent.TIMER_COMPLETE, firstScreen);
          }*/
          
          public function setFontFormat() {
               //Text Formatting for Brand Name Field
               brandnameTxt = new TextFormat();
               brandnameTxt.font = fontNeeded;
               brandnameTxt.color = 0x006699;
               brandnameTxt.size = 20;
               brandnameTxt.bold = true;
               //
               
               //Text Formatting for Country/Material
               detailsTxt = new TextFormat();
               detailsTxt.font = fontNeeded;
               detailsTxt.color = 0x006699;
               detailsTxt.size = 10;
               detailsTxt.bold = false;
               
               //Text Formatting for Country/Material
               priceTxt = new TextFormat();
               priceTxt.font = fontNeeded;
               priceTxt.color = 0x9DE36E;
               priceTxt.size = 20;
               priceTxt.bold = true;
          }
          
          public function tweenBucket(bucket:MovieClip) {
                    var bucketImgTrans = new TransitionManager(bucket);
                    bucketImgTrans.startTransition({type:Zoom, direction:Transition.IN, duration:3, easing:Strong.easeOut});
          }
          
          private function iterateArray(contentInfo:Array) {
               this.setFontFormat();
               
               for (var c:uint = 0; c < contentInfo.length; c++) {
                         var brand:TextField   = new TextField();
                         var country:TextField = new TextField();
                         var made:TextField    = new TextField();
                         var cost:TextField    = new TextField();
                         var img:Loader;     
                         brand.embedFonts        = true;
                         
                         img            = contentInfo.picture;
                         brand.text   = contentInfo.brand;
                         country.text = contentInfo.country;
                         made.text    = contentInfo.made;
                         cost.text    = contentInfo.cost;
                         
                         if (positionBuckets) {
                         bucket       = new bucket_left();     
                         //Align Data
                         bucket.y = position;
                         bucket.x = 70;
                         brand.x = -50;
                         brand.y = -35;
                         country.x  = -45;
                         country.y  = -10;
                         made.x = -45;
                         made.y = 5;
                         cost.x = 45;
                         cost.y = -10;
                         img.x = -105;
                         img.y = -35;
                         brandnameTxt.align = TextFormatAlign.LEFT;
                       priceTxt.align         = TextFormatAlign.LEFT;
                         positionBuckets    = false;
                         } else {
                         bucket       = new bucket_right();     
                         //Align Data
                         bucket.y = position;
                         bucket.x = 240;
                         brand.x = -50;
                         brand.y = -35;
                         country.x  = -45;
                         country.y  = -10;
                         made.x = -45;
                         made.y = 5;
                         cost.x = -110;
                         cost.y = -10;
                         img.x = 70;
                         img.y = -35;
                         brandnameTxt.align = TextFormatAlign.RIGHT;
                         positionBuckets    = true;      
                         }
                         brand.setTextFormat(brandnameTxt);
                         country.setTextFormat(detailsTxt);
                         made.setTextFormat(detailsTxt);
                         cost.setTextFormat(priceTxt);
                         //this.tweenBucket(bucket);
                         addChildAt(bucket, 0);
                         bucket.addChild(DisplayObject(img));
                         bucket.addChild(brand);
                         bucket.addChild(country);
                         bucket.addChild(made);
                         bucket.addChild(cost);
                         position += 70;
               }
          }

          
          private function populateInfo(event:Event) {
               
               //Incoming XML Data
               xmlContainer = new XML(event.target.data);
               xmlList = xmlContainer.product;
               //
               
               //Variables to hold the string
               var brandTxt:String;
               var country:String;
               var material:String;
               var price:String;
               var image:String;
               
               for (var i:uint = 0; i < xmlList.length(); i++) {     
               if (xmlList.country.text() == "USA") {
               brandTxt = xmlList.brand.text();
               country = "product of " + xmlList.country.text();
               material = "made of " + xmlList.material.text();
               price = "$" + xmlList.price.text();
               image = xmlList.image.text();
               rackUSA.name = brandTxt.toLowerCase();
               var imgVar:* = this.populateImages(image, "http://localhost/rackets/" + image);
               rackUSA.push({brand: brandTxt, country: country, made: material, cost: price, pic: image, picture: imgVar});
               //addChild(DisplayObject(rackUSA[0].picture));
               } else if (xmlList.country.text() == "Other") {
               brandTxt = xmlList.brand.text();
               country = "product of " + xmlList.country.text();
               material = "made of " + xmlList.material.text();
               price = "$" + xmlList.price.text();
               image = xmlList.image.text();
               var imgVarOther:* = this.populateImages(image, "http://localhost/rackets/" + image);
               rackOther.push({brand: brandTxt, country: country, made: material, cost: price, pic: image, picture: imgVarOther});
               }
               }
               //this.startApplication();
          }
          
          
          
          
          
     }
}

If i have movie clip named firstScreen how do i populate with data from the array rackUSA, using the iterateArray funtions

I tried in a movieClip

CustomClass.iterateArray(rackUSA); //but this does not work

Any suggestions

This topic has been closed for replies.
Correct answer Andrei1-bKoviI

I would like to clarify use cases.

1. load data into document class

2. display a welcome message

3. allow users browse through the products.

Q1: Do you mean by "welcome message" a user interface that allows for starting browsing?

Q2: Will products be displayed the same way. I mean, do you envision that product display will have a uniform layout?

If the answer to Q2 is yes, I would:

1. Create a class that displays products. Let's name it ProductDisplay

2. Pass data (subset of XML related to a particular product - in your case it may be an object in the array position) into an instance of ProductDisplay

I would like you to consider the following.

It is a good OOP practice to make each class do as little as possible. This means a class should have a very focused functionality. For instance, you ProductClass should perform tasks related to laying out product display. With this in mind it is better to delegate, say, image loading to a separate class. Believe me, when you do that - your life will be much easier if you make functionality as granular as possible even though sometimes it feels like an overkill.

So, here are sketches of your classes. I just wrote it to illustrate the idea. I did not check the code at runtime so it is definitely buggy.

Read my comments at the bottom too.

This is a product image class that loads image:

 
package  
{
     import flash.display.Loader;
     import flash.display.Sprite;
     import flash.events.Event;
     import flash.events.ProgressEvent;
     import flash.net.URLRequest;
     
     public class ProductImage extends Sprite 
     {
          // image url
          private var _url:String;
          // loader
          private var _loader:Loader;
          public function ProductImage() 
          {
               if (stage) init();
               else addEventListener(Event.ADDED_TO_STAGE, init);
          }
          
          private function init(e:Event = null):void 
          {
               removeEventListener(Event.ADDED_TO_STAGE, init);
               _loader = new Loader();
               _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoad);
               _loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
               _loader.load(new URLRequest(url));
          }
          
          private function onProgress(e:ProgressEvent):void 
          {
               // display progress if needed
          }
          
          private function onLoad(e:Event):void 
          {
               _loader.contentLoaderInfo.removeEventListener(Event.COMPLETE);
               _loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress);
               addChild(_loader);
               
          }
          
          public function get url():String { return _url; }
          
          public function set url(value:String):void 
          {
               _url = value;
          }
          
     }
     
}

ProdustDisplay class. Note how Product Class is instantiated

 

package  
{
     import flash.display.Sprite;
     import flash.events.Event;

     public class ProductDisplay extends Sprite
     {
          // hold the metadata
          private var _metaData:Object;
          // an object that holds the image
          private var _imageDisplay:ProductImage;
          public function ProductDisplay() 
          {
               if (stage) init();
               else addEventListener(Event.ADDED_TO_STAGE, init);
          }
          
          private function init(e:Event = null):void 
          {
               removeEventListener(Event.ADDED_TO_STAGE, init);
               // only if metadat is set - build interface
               if (metaData) {
                    build();
               }
               
          }
          // build interface
          private function build():void {
               // place prduct image
               _imageDisplay = new ProductImage();
               _imageDisplay.url = metaData.image;
               addChild(_imageDisplay);
               // do the rest - like description, etc.
          }
          // function that accepts product metadata
          public function set metaData(metaObject:Object):void {
               _metaData = metaObject;
          }
          // returns metadata
          public function get metaData():Object {
               return _metaData;
               
          }
          
     }
     
}

Now in your document class you can created unlimited number of instances of ProductDisplay (like slides) and manipulate them. Again, this is just a sketch. Actual functionality and code placement will be somehow different:

var productDisplay:ProductDisplay = new ProductDisplay();
productDisplay.metaData = rackUSA[2];

Note: Your code has many inconsistencies - we will need to go through them some other time. For now just digest these ideas. I understand that it will involve some refactoring on your part but once you are done with it - things will fall into place quick.

2 replies

Andrei1-bKoviICorrect answer
Inspiring
August 7, 2009

I would like to clarify use cases.

1. load data into document class

2. display a welcome message

3. allow users browse through the products.

Q1: Do you mean by "welcome message" a user interface that allows for starting browsing?

Q2: Will products be displayed the same way. I mean, do you envision that product display will have a uniform layout?

If the answer to Q2 is yes, I would:

1. Create a class that displays products. Let's name it ProductDisplay

2. Pass data (subset of XML related to a particular product - in your case it may be an object in the array position) into an instance of ProductDisplay

I would like you to consider the following.

It is a good OOP practice to make each class do as little as possible. This means a class should have a very focused functionality. For instance, you ProductClass should perform tasks related to laying out product display. With this in mind it is better to delegate, say, image loading to a separate class. Believe me, when you do that - your life will be much easier if you make functionality as granular as possible even though sometimes it feels like an overkill.

So, here are sketches of your classes. I just wrote it to illustrate the idea. I did not check the code at runtime so it is definitely buggy.

Read my comments at the bottom too.

This is a product image class that loads image:

 
package  
{
     import flash.display.Loader;
     import flash.display.Sprite;
     import flash.events.Event;
     import flash.events.ProgressEvent;
     import flash.net.URLRequest;
     
     public class ProductImage extends Sprite 
     {
          // image url
          private var _url:String;
          // loader
          private var _loader:Loader;
          public function ProductImage() 
          {
               if (stage) init();
               else addEventListener(Event.ADDED_TO_STAGE, init);
          }
          
          private function init(e:Event = null):void 
          {
               removeEventListener(Event.ADDED_TO_STAGE, init);
               _loader = new Loader();
               _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoad);
               _loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
               _loader.load(new URLRequest(url));
          }
          
          private function onProgress(e:ProgressEvent):void 
          {
               // display progress if needed
          }
          
          private function onLoad(e:Event):void 
          {
               _loader.contentLoaderInfo.removeEventListener(Event.COMPLETE);
               _loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress);
               addChild(_loader);
               
          }
          
          public function get url():String { return _url; }
          
          public function set url(value:String):void 
          {
               _url = value;
          }
          
     }
     
}

ProdustDisplay class. Note how Product Class is instantiated

 

package  
{
     import flash.display.Sprite;
     import flash.events.Event;

     public class ProductDisplay extends Sprite
     {
          // hold the metadata
          private var _metaData:Object;
          // an object that holds the image
          private var _imageDisplay:ProductImage;
          public function ProductDisplay() 
          {
               if (stage) init();
               else addEventListener(Event.ADDED_TO_STAGE, init);
          }
          
          private function init(e:Event = null):void 
          {
               removeEventListener(Event.ADDED_TO_STAGE, init);
               // only if metadat is set - build interface
               if (metaData) {
                    build();
               }
               
          }
          // build interface
          private function build():void {
               // place prduct image
               _imageDisplay = new ProductImage();
               _imageDisplay.url = metaData.image;
               addChild(_imageDisplay);
               // do the rest - like description, etc.
          }
          // function that accepts product metadata
          public function set metaData(metaObject:Object):void {
               _metaData = metaObject;
          }
          // returns metadata
          public function get metaData():Object {
               return _metaData;
               
          }
          
     }
     
}

Now in your document class you can created unlimited number of instances of ProductDisplay (like slides) and manipulate them. Again, this is just a sketch. Actual functionality and code placement will be somehow different:

var productDisplay:ProductDisplay = new ProductDisplay();
productDisplay.metaData = rackUSA[2];

Note: Your code has many inconsistencies - we will need to go through them some other time. For now just digest these ideas. I understand that it will involve some refactoring on your part but once you are done with it - things will fall into place quick.

georgeebAuthor
Known Participant
August 7, 2009

That seems to be making sense

Now, couple more things

1) We will only be using Sprite from now on, so if i want to cuztomize each display object with a specific background and other information that i wish for it to display, Where would i put the slide specific information, like specific heading, background etc.

2) If i am running this slide show from a document class on  Timers, do i just set the diffrent timer properties in the Document class, and then run the data as instances in the document Class, letting it populate that way. (From what i am getting, i do not touch the timeline at all).

3) How do i pass the value of the Arrays that have been populated by my function, so that the document class can use, lending these resources to the product display. How can i make use of the Arrays that have been populated, and pass them to other classes.

What i meant by diffrent screen displays was that i would like to show those slides using a timer, for the most part, it will be the product information, however at the begining i would like to welcome the user to the slide show --> so Welcome screen would be approporiate.

That will require me to create a class for it and then make an instance of it in the Document Class

Thank you so much for clarifying this stuff for me, i really appreciate. I am trying to Read the Design Patterns AS3, but it seems as a lot of it is not familiar

Thanks again

Inspiring
August 7, 2009

Too many questions for one post :-)

1) We will only be using Sprite from now on, so if i want to cuztomize each display object with a specific background and other information that i wish for it to display, Where would i put the slide specific information, like specific heading, background etc.

Yes, Sprites are more compact than MovieClips. One can look at MovieClips as Sprites on steroids - MovieClips has timeline in addition to everything Sprite has/does. If you look into documentation (http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/MovieClip.html) you will notice that MovieClip extends sprite (in other words, it inherits everything from Sprite an adds methods/properties pertaining to timeline/frames).

To answer the question about how to customize ProductDisplay, first you need to list all the visuals that it must have. You already mentioned background and headers. What else do you want to be there?

Also, what kind of background will it be? Just something that changes color? Different shape? Is it having just fill or line too?

When you answer these questions it will be clear how you want to deal with visuals.

Are they going to be drawn at runtime or they are so complicated that it makes sense to store symbols in library?

I think  you need to come up with an image made in Photoshop that shows your vision. It would be great if you presented a mockup of entire slide - it will make code writing much easier strangely enough.

2) If i am running this slide show from a document class on  Timers, do i just set the diffrent timer properties in the Document class, and then run the data as instances in the document Class, letting it populate that way.

I see it as one instance of Timer in Document class that runs entire show. On each timer cycle, you will call a function that moves the next slide in queue to the view and moves previous slide out.

Perhaps, for a smoother presentation, you will need to instantiate the next slide every time a new slide is displayed. Let me explain.

When you load your application for the first time, you would need to create the first instance of a slide that sits in index 0 of the metadata array. This way when user initiates automated slide show - chances are great that image in the first slide is loaded.

As the show progresses, every time new slide shown - you will instantiate the next one:

Say, the current slide is slide_0. At this point you make a new slide but keep it in memory and don't show it yet. When time comes - you show slide_1 by calling addChild() (and, perhaps, applying some transition (move in-out, fade, whatever suits you). At the same time you make an instance of slide_2, etc., etc., etc.

Perhaps another thing you need to consider is removing used slides from memory. Say, it could be a slide that was instantiated before previous one. Yes, it will force you to make additional calls to the server for images that are already loaded but the benefit would be to have a lean fast memory.

From what i am getting, i do not touch the timeline at all

Not physically. There is nothing on the timeline. BUT, your document class is the one that places objects on the timeline at runtime.

3) How do i pass the value of the Arrays that have been populated by my function, so that the document class can use, lending these resources to the product display. How can i make use of the Arrays that have been populated, and pass them to other classes.

In my previous post I described this. I guess I was not clear.

I don't remember your naming conventions but, say, in your Document class after XML was loaded you populated an array with metadata. Say your array is:

var slidesData:Array = [];

I suggest you have only data from XML in this array - not image loaders - and delegate image loading to a special class ProductImage.

So, you array will have metadata like that:

slidesData.push({imageUrl:"image address from XML", header:"header from XML", description:"description from XML", etc...});

As shown, ProductDisplay class has an accessor method metaData. So, you will pass the data pertaining to the slide like this:

var slide_0:ProductDisplay = new ProductDisplay();
slide_0.metaData = slidesData[0];

var slide_1:ProductDisplay = new ProductDisplay();
slide_1.metaData = slidesData[1];

Of course it should be done on request - not all of them at the same time.

Perhaps, what I am going to say will be too overwhelming but, in essence, you don't need to create this array of metadata at all. AS3 deals with XML very efficiently . If XML is small (I see yours will be small) - you just can reuse it as is by extracting corresponding to slides nodes and pass them into ProductDisplay instance.

But it may be too much...

What i meant by diffrent screen displays was that i would like to show those slides using a timer, for the most part, it will be the product information, however at the begining i would like to welcome the user to the slide show --> so Welcome screen would be approporiate.

Yes, I would definitely create a separate class that represents welcome screen.

August 7, 2009
private function iterateArray(contentInfo:Array) {

If you want to access this outside this class it should be defined as public instead of private.