Loading flex Modules from an XML file - actionscript-3

I am trying to parse an xml file and load Flex modules dynamically in my application. But it loads only the last module everytime. I have a singleton class which does the parsing and loading of modules. Here is the class
package
{
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
import mx.controls.Alert;
import mx.events.ModuleEvent;
import mx.modules.IModuleInfo;
import mx.modules.ModuleLoader;
import mx.modules.ModuleManager;
public class VappModuleManager
{
private static var _instance:VappModuleManager;
private static const MODULE_PATH:String="./com/emc/vapp/";
private static const MANIFEST_PATH:String="module-manifest.xml";
private var _module:IModuleInfo;
private var _handler:Function;
private var loader:URLLoader;
public function VappModuleManager(object:SingletonEnforcer)
{
}
public function set handler(handler:Function):void
{
_handler=handler;
}
public static function get instance():VappModuleManager
{
if(_instance==null)
{
_instance=new VappModuleManager(new SingletonEnforcer());
}
return _instance;
}
public function load():void
{
loader = new URLLoader();
loader.addEventListener(Event.COMPLETE, xmlLoaded);
loader.load(new URLRequest(MANIFEST_PATH));
}
private function xmlLoaded(event:Event):void
{
Alert.show("Event Completed");
var manifest:XML=new XML(event.target.data);
Alert.show(manifest.module.length());
for (var index:int=0;index<manifest.module.length();index++)
{
Alert.show(MODULE_PATH+manifest.module[index].#name);
_module=ModuleManager.getModule(MODULE_PATH+manifest.module[index].#name);
_module.addEventListener(ModuleEvent.READY,_handler);
_module.load();
}
}
}
}
internal class SingletonEnforcer {}
I use the above class as follows.
moduleManager=VappModuleManager.instance;
moduleManager.handler=myhandler;
moduleManager.load();
I understand the problem is with eventlistener for variable "_module" but dont know how to solve it. Any help appreciated.

The call to IModuleInfo.load is asynchronous so your for loop has run completely before any of the modules have loaded. Also, your class level _module property is overwritten by a new Module instance each time the loop iterates.
I'd suggest loading each module sequentially by waiting for the READY event and initiating the load of the next module only when it has fired. I'd also fire an event when all the modules are loaded instead of executing a callback function as this will give you more flexibility (multiple objects can listen for an event for example).
The following isn't tested, but should give you the idea:
package
{
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
import mx.controls.Alert;
import mx.events.ModuleEvent;
import mx.modules.IModuleInfo;
import mx.modules.ModuleLoader;
import mx.modules.ModuleManager;
public class VappModuleManager
{
private static var _instance:VappModuleManager;
private static const MODULE_PATH:String="./com/emc/vapp/";
private static const MANIFEST_PATH:String="module-manifest.xml";
private var loader:URLLoader;
private var manifest:XML;
private var loadCount:int = 0; // track loaded modules
public function VappModuleManager(object:SingletonEnforcer)
{
}
public static function get instance():VappModuleManager
{
if(_instance==null)
{
_instance=new VappModuleManager(new SingletonEnforcer());
}
return _instance;
}
public function load():void
{
loader = new URLLoader();
loader.addEventListener(Event.COMPLETE, xmlLoaded);
loader.load(new URLRequest(MANIFEST_PATH));
}
private function xmlLoaded(event:Event):void
{
manifest =new XML(event.target.data);
// load the first module
loadModule();
}
private function loadModule() {
// Use a locally scoped variable to avoid writing over the previous instance each time.
// You could push these onto an array if you need to be able to access them later
var module:IModuleInfo = ModuleManager.getModule(MODULE_PATH+manifest.module[loadCount].#name);
module.addEventListener(ModuleEvent.READY, moduleReadyHandler);
module.load();
}
private function moduleReadyHandler(event:ModuleEvent) {
// Remove the event listener on the loaded module
IModuleInfo(event.target).removeEventListener(ModuleEvent.READY, moduleReadyHandler);
loadCount ++;
// Are there still modules in the manifest to load?
if (loadCount < manifest.module.length()) {
// Yes... load the next module
loadModule();
} else {
// No... we're all finished so dispatch an event to let subscribers know
dispatchEvent(new Event("complete"));
}
}
}
}

Related

AS3: 1180 Call to a possibly undefined property: Add Child

Pretty big noob at AS3. I'm trying to Load a SWF into another file. (Main .fla loading external SWFS on mouse click)
I keep getting the error: 1180 Call to a possibly undefined property: Add Child, however.
My LoadSWF code is:
package {
import flash.display.*;
import flash.events.*;
import flash.net.*;
public class LoadSWF {
private var loaderFile: Loader;
private var swfFile: Object;
private var sourceFile: String;
private var fileLabel: String;
private var canDrag: Boolean;
private var popX: int;
private var popY: int;
public function LoadSWF(myFile: String, myLabel: String, myX: int = 0, myY: int = 0, myDrag: Boolean = false) {
// constructor code
trace("Loading SWF file:", myFile);
sourceFile = myFile;
fileLabel = myLabel;
canDrag = myDrag;
popX = myX;
popY = myY;
openSWF();
}
private function openSWF(): void {
// initialise variables
loaderFile = new Loader();
swfFile = addChild(loaderFile);
// set initial position of the SWF popup
loaderFile.x = popX;
loaderFile.y = popY;
try {
loaderFile.load(new URLRequest(sourceFile));
// runs after the SWF popup has finished loading
loaderFile.contentLoaderInfo.addEventListener(Event.COMPLETE, SWFloaded);
} catch (err: Error) {
// provide some error messages to help with debugging
trace("Error loading requested document:", sourceFile);
trace("Error:", err);
sourceFile = null;
}
} //end openSWF
private function SWFloaded(evt: Event): void {
// and add the required event listeners
loaderFile.addEventListener(MouseEvent.MOUSE_DOWN, dragSWF);
loaderFile.addEventListener(MouseEvent.MOUSE_UP, dropSWF);
// use the POPUP reference to access MovieClip content
swfFile.content.gotoAndStop(fileLabel);
// assigns a close function to the button inside the popup
swfFile.content.closeBtn.addEventListener(MouseEvent.CLICK, closeSWF);
// remove the COMPLETE event listener as it’s no longer needed
loaderFile.contentLoaderInfo.removeEventListener(Event.COMPLETE, SWFloaded);
} //end SWFLOaded
private function dragSWF(evt: MouseEvent): void {
swfFile.content.startDrag();
}
private function dropSWF(evt: MouseEvent): void {
swfFile.content.stopDrag();
}
private function closeSWF(evt: MouseEvent): void {
// remove the required event listeners first
loaderFile.removeEventListener(MouseEvent.MOUSE_DOWN, dragSWF);
loaderFile.removeEventListener(MouseEvent.MOUSE_UP, dropSWF);
swfFile.content.closeBtn.removeEventListener(MouseEvent.CLICK, closeSWF);
// remove the pop-up
loaderFile.unloadAndStop();
}
} //end class
} //end package
I'm calling it into my main class file, which code is (I left out the rest, guessing its unnecessary):
package {
import flash.display.MovieClip;
import flash.text.TextField;
import flash.display.SimpleButton;
import flash.utils.Dictionary;
import flash.text.TextFormat;
import flash.net.*;
import flash.events.*;
import fl.controls.*;
import flash.media.*;
import fl.events.ComponentEvent;
import fl.managers.StyleManager;
import fl.data.DataProvider;
import fl.data.SimpleCollectionItem;
import fl.managers.StyleManager;
import fl.events.ComponentEvent;
import flash.events.Event;
import flash.net.SharedObject;
import LoadSWF;
public class Main extends MovieClip {
//Declare variables
private var componentFmt: TextFormat;
private var radioBtnFmt: TextFormat;
private var playerData: Object;
private var savedGameData: SharedObject;
// Pop-up Variables
private var popupFile: LoadSWF;
private var swfPath: String;
public function Main() {
// constructor code
this.savedGameData = SharedObject.getLocal("savedPlayerData");
this.setComponents();
this.setPlayerData();
//this.swfPath = "";
//this.isHelpOpen = false;
//this.sndPath = "musicSFX/music2.mp3";
//this.isMuted = false;
//this.sndTrack = new LoadSND(this.sndPath, this.canRepeat);;
//this.muteBtn.addEventListener(MouseEvent.CLICK, this.setMute);
swfPath = "";
helpBtn.addEventListener(MouseEvent.CLICK, openSWF);
//hauntedForestBtn.addEventListener(MouseEvent.CLICK, openSWF);
}
public function openSWF(evt: MouseEvent): void {
// determine which button was pressed
var myFile: String = evt.currentTarget.name.replace("Btn", ".swf");
myFile = (swfPath == "") ? myFile : swfPath + myFile;
if (myFile == "help.swf") {
// load the help SWF file - is draggable
swfFile = new LoadSWF(myFile, currentFrameLabel, 80, 60, true);
} else {
// load the selected SWF file - is not draggable
swfFile = new LoadSWF(myFile, currentFrameLabel);
}
addChild(swfFile);
}
If anyone could help me find a solution, i'd greatly appreciate it.
Thanks :)
addChild is defined by DisplayObjectContainer.
So to access this function, you'll have to alter LoadSWF so that it extends DisplayObjectContainer.

Where must be custom logic in pureMVC (as3)?

I tried to write small as3 program based on framework pureMVC.
I understood basic principles of it, but I can't understand, where I must place custom logic.
For example, I must load 10 images. I created command, that init Proxy.
package app.controller
{
import app.model.GalleryProxy;
import dicts.Constants;
import org.puremvc.interfaces.INotification;
public class LoadFilesCommand extends BaseCommand
{
public function LoadFilesCommand() { }
override public function execute(note:INotification):void
{
facade.registerProxy(new GalleryProxy(Constants.FILES_LIST));
}
}
}
And Proxy is:
package app.model
{
import dicts.Constants;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.ErrorEvent;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
import org.puremvc.interfaces.IProxy;
import org.puremvc.patterns.proxy.Proxy;
public class GalleryProxy extends Proxy implements IProxy
{
public function GalleryProxy(list:Vector.<String>)
{
super(Constants.PROXY_GALLERY);
_fileList = list;
_total = _fileList.length;
load();
}
public function get currentImage():Bitmap
{
return _images[_index];
}
//--------------------------------------------------------------------------
// PRIVATE SECTION
//--------------------------------------------------------------------------
private var _fileList:Vector.<String>;
private var _total:uint;
private var _loaded:uint = 0;
private var _images:Array = [];
private var _index:int;
private function load():void
{
var loader:Loader;
for (var i:int = 0; i < _total; i++)
{
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoadHandler);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
loader.load(new URLRequest(_fileList[i]));
}
}
private function imageLoadHandler(event:Event):void
{
var info:LoaderInfo = LoaderInfo(event.currentTarget);
_images[Constants.FILES_LIST.indexOf(info.url)] = info.content;
info.removeEventListener(Event.COMPLETE, imageLoadHandler);
info.removeEventListener(IOErrorEvent.IO_ERROR, errorHandler);
_loaded++;
if (_loaded >= _total)
sendNotification(Constants.COMMAND_SHOW_MAIN);
}
private function errorHandler(event:ErrorEvent):void
{
throw new Error("bad link or internet disconnect");
}
}
}
Now my Proxy is loading images independently (functions load() and imageLoadHandler)
Is it correct?
Or I must move this logic to Command class?
Or I must create some LoadService.as, which will contains this logic?
What is the correct variant for pureMVC?
Do you want to load your 10 images on application startup? If not, make load() public and call it from a Mediator, responding to a UI event.
If so, what you have will work fine. One alternative would be writing GalleryProxy so it doesn't call load() in the constructor - instead, you could have the Command register the proxy, load the image list, and call proxy.load(images[i]) in a loop.

as3 calling a function in Main.as Document Class from another class

I am sure this is a popular question but I can't find the exact answer I need. I simply need to access a function or functions created in the Main.as document class. I have tried several methods and they do not seem to work. Here is one example I tried.
anotherClass.as // This needs to access functions Main.as
package com
{
import Main;
public class anotherClass
{
private var stageMain:Main;
public function anotherClass()
{
// tries to call a function in Main.as called languageLoaded. NO WORK!
stageMain.languageLoaded("English");
// in the Main.as languageLoaded is a public function
}
}
}
The cleaner way is to simply pass a reference to Main to the constructor of the class you want to be able to access it.
For example, your AnotherClass could look like this:
class AnotherClass
{
private var _main:Main;
public function AnotherClass(main:Main)
{
_main = main;
_main.test(); // Success!
}
}
And your main class:
class Main
{
public function Main()
{
var another:AnotherClass = new AnotherClass(this);
}
public function test():void
{
trace("Success!");
}
}
public class MainDoc extends MovieClip // as long as it extends eventDispatcher you re fine
{
private var otherClass:OtherClass;
public function MainDoc()
{
otherClass = new OtherClass();
otherClass.addEventListener("otherClassCustomEvent", onOtherClassReady);
otherClass.startLogic();
}
public function onOtherClassReady(event:Event = null)
{
trace("from other class:", otherClass.infoToShare) // traces "from other class: YOLO!"
}
}
public class OtherClass extends EventDispatcher // must extend the event dispatcher at least
{
public var infoToShare:String;
public function OtherClass()
{
}
public function startLogic()
{
// do what you got to do
// when you have your data ready
infoToShare = "YOLO!";
dispatchEvent("otherClassCustomEvent");
}
}
Once you're confortable with that, you can start looking into building custom events that could carry the variable to send back
Ok I got the following code to work. It's really a messy solution but I didn't know of a better way. It works. I just hope it's stable and does not use a lot of resources.
If you have a much better Idea I am open.
Here is the MainDoc.as
package {
import flash.display.MovieClip;
import flash.events.*;
import com.*;
import com.views.*;
import flash.display.*;
import flash.filesystem.*;
import com.greensock.*;
import com.greensock.easing.*;
import flash.system.System;
public class mainDoc extends MovieClip
{
/// (Get Main Doc flow) this creates an instace of the main timeline
/// and then I send it
private static var _instance:mainDoc;
public static function get instance():mainDoc { return _instance; }
/// Calls the defaultVars.as in to "vars".
var vars:defaultVars = new defaultVars();
public function mainDoc()
{
/// Makes this class ready to be passed to defautVars.as
_instance = this;
// Sends the _instance to defaulVars.as to be accessed later.
vars.getMainDoc(_instance);
// Calls a function in defaultVars.as and loads a var
vars.loadButtonVars("English");
}
}
}
Here is the defaultVars.as
package com {
import flash.display.Stage;
import flash.events.*
import flash.net.*;
import flash.display.*;
import flash.filesystem.*;
public class defaultVars
{
/// Makes the MainDoc.as a MovieClip
// Not sure if this is good but it works.
public var MainDoc:MovieClip;
public function defaultVars()
{
}
public function getMainDoc(_instance:MovieClip)
{
trace("CALLED" + _instance);
/// receives the _instance var and its converted to a MovieClip
// This can now be used in any function because I declared it a public var.
MainDoc = _instance;
}
public function loadButtonVars(Language:String)
{
myLoader.load(new URLRequest("Languages/" + Language + "/vars.xml"));
myLoader.addEventListener(Event.COMPLETE, processXML);
function processXML(e:Event):void
{
myXML = new XML(e.target.data);
/// Home Screen Buttons
homeT = myXML.Button.(#Title=="homeT");
homeB1 = myXML.Button.(#Title=="homeB1");
homeB2 = myXML.Button.(#Title=="homeB2");
homeB3 = myXML.Button.(#Title=="homeB3");
homeB4 = myXML.Button.(#Title=="homeB4");
homeB5 = myXML.Button.(#Title=="homeB5");
/// HERE IS WHERE I CALL FUNCTION from MainDoc after xml is loaded.
/////////////////
trace("xml loaded!!!! " + homeB1);
MainDoc.languageLoaded(Language);
}
}
}
}

Flex 4.5 Not listening to custom event dispatched in custom AS class

I have the following situation:
I have an event handler, that displays small messages in my application's statusbar.
These messages get passes through by dispatching events from custom components.
A simple message could be like "HTTP Error" or so.
Now, the main event listener, in the main application file, listens to the event dispatched by any custom component, but seems to refuse listening to events dispatched by custom AS classes.
Here is my code for the custom event:
package main.events
{
import flash.events.Event;
public class ShowNoticeEvent extends Event
{
public var message:String;
public static const SHOW_NOTICE:String = "showNotice";
public function ShowNoticeEvent(type:String, msg:String, bubbles:Boolean = false, cancelable:Boolean = false)
{
super(type, bubbles, cancelable);
this.message = msg;
}
override public function clone():Event
{
return new ShowNoticeEvent(type, message);
}
}
}
This is the event listener in the main application file:
addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);
And this is the custom AS class that dispatches the custom event. I pasted all the code, so you could see the whole part of it.
package components.dashboard
{
import components.dashboard.models.*;
/* Event imports */
import flash.events.*;
import main.events.*;
import mx.controls.Alert;
import mx.core.UIComponent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
[Event(name="showNotice", type="main.events.ShowNoticeEvent")]
public class Controller extends UIComponent
{
private var baseUrl:String;
public function Controller(baseUrl:String)
{
this.baseUrl = baseUrl;
}
public function getRunningQuotations():void
{
var runningQuotationsList:RunningQuotationsList = RunningQuotationsList.getInstance();
execService("index.php?a=1", runningQuotationsList.updateList, "pnlRunningQuotations");
}
public function getRecentProjects():void
{
var recentProjectsList:RecentProjectsList = RecentProjectsList.getInstance();
execService("index.php?a=2", recentProjectsList.updateList, "pnlRecentProjects");
}
public function getLatestCustomers():void
{
var latestCustomersList:LatestCustomersList = LatestCustomersList.getInstance();
execService("index.php?a=3", latestCustomersList.updateList, "pnlLatestCustomers");
}
private function execService(url:String, listener:Function, component:String):void
{
var basicService:HTTPService = new HTTPService(baseUrl);
basicService.showBusyCursor = true;
basicService.addEventListener(FaultEvent.FAULT, function(e:FaultEvent):void{httpFault(e, component)});
basicService.method = "POST";
basicService.resultFormat = "text";
basicService.url = url;
basicService.addEventListener(ResultEvent.RESULT, listener);
basicService.send();
}
private function httpFault(event:FaultEvent, component:String = null):void {
var faultstring:String = event.fault.faultString;
var eventObj:ShowNoticeEvent = new ShowNoticeEvent(ShowNoticeEvent.SHOW_NOTICE, faultstring, true);
dispatchEvent(eventObj);
trace(faultstring);
}
}
}
So to sum it all up:
- The event listener listens to the custom event dispatched by any custom component.
- The event listener does not listen to the custom event duspatched by an AS class.
Those who wonder, the event really gets dispatched, that's why I added a trace call.
The instance of Controller Class would have to be added to stage for that to work.
by doing
addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);
in the main file you are adding the listener to the stage.
So basically you are doing.
stage.addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);
If controler instance is not on stage you won't see the event.
You might want to look into a Singleton type pattern for your data management as that would fit this setup pretty good.
Main:
Controller.getLastInstance().addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true)
.
package components.dashboard
{
import components.dashboard.models.*;
/* Event imports */
import flash.events.*;
import main.events.*;
import mx.controls.Alert;
import mx.core.UIComponent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
[Event(name="showNotice", type="main.events.ShowNoticeEvent")]
public class Controller extends UIComponent
{
static public function getLastInstance():Controller { return _instance; }
static private var _instance:Controller;
private var baseUrl:String;
public function Controller(baseUrl:String)
{
_instance = this;
this.baseUrl = baseUrl;
}
public function getRunningQuotations():void
{
var runningQuotationsList:RunningQuotationsList = RunningQuotationsList.getInstance();
execService("index.php?a=1", runningQuotationsList.updateList, "pnlRunningQuotations");
}
public function getRecentProjects():void
{
var recentProjectsList:RecentProjectsList = RecentProjectsList.getInstance();
execService("index.php?a=2", recentProjectsList.updateList, "pnlRecentProjects");
}
public function getLatestCustomers():void
{
var latestCustomersList:LatestCustomersList = LatestCustomersList.getInstance();
execService("index.php?a=3", latestCustomersList.updateList, "pnlLatestCustomers");
}
private function execService(url:String, listener:Function, component:String):void
{
var basicService:HTTPService = new HTTPService(baseUrl);
basicService.showBusyCursor = true;
basicService.addEventListener(FaultEvent.FAULT, function(e:FaultEvent):void{httpFault(e, component)});
basicService.method = "POST";
basicService.resultFormat = "text";
basicService.url = url;
basicService.addEventListener(ResultEvent.RESULT, listener);
basicService.send();
}
private function httpFault(event:FaultEvent, component:String = null):void {
var faultstring:String = event.fault.faultString;
var eventObj:ShowNoticeEvent = new ShowNoticeEvent(ShowNoticeEvent.SHOW_NOTICE, faultstring, true);
dispatchEvent(eventObj);
trace(faultstring);
}
}
}
Not Ideal since you could only ever have 1 of them.
But I think better than having to turn a simple EventDispatcher into DisplayObject and add it to stage just to Simply bubble.

Getting data from custom classes (an OOP question)

How can I get some var / data from a custom classes?
The XML class
package classes
{
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.MovieClip;
public class videoData extends MovieClip
{
private var myXML:XML;
private var myXMList:XMLList;
public function videoData()
{
var myXMLLoader:URLLoader = new URLLoader();
myXMLLoader.load(new URLRequest("playlist.xml"));
myXMLLoader.addEventListener(Event.COMPLETE, processXML);
}
private function processXML(e:Event):void
{
myXML = new XML(e.target.data);
myXMList = new XMLList(myXML.children());
}
public function getXML()
{
return myXML;
}
}
}
The class that is calling the XML
package classes
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import classes.videoData;
public class playList extends MovieClip
{
private var vData:videoData = new videoData();
public function playList()
{
trace(vData.getXML())
}
}
}
I would setup an event listener in 'playList' and dispatch an Event from 'videoData' once the XML has finished loading. That way you know when it's finished loading without using ENTER_FRAME (which will use alot more CPU as its checking every frame).
package classes
{
import flash.events.*;
import flash.display.MovieClip;
import classes.VideoData;
public class PlayList extends MovieClip
{
private var vData:VideoData;
public function PlayList()
{
vData = new VideoData();
vData.addEventListener(Event.COMPLETE, onXMLCompleteHandler);
}
private function onXMLCompleteHandler(e:Event):void
{
vData.removeEventListener(Event.COMPLETE, onXMLCompleteHandler);
trace(vData.getXML());
}
}
}
package classes
{
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.MovieClip;
public class VideoData extends MovieClip
{
private var myXML:XML;
private var myXMList:XMLList;
private var myXMLLoader:URLLoader;
public function VideoData()
{
myXMLLoader = new URLLoader();
myXMLLoader.load(new URLRequest("playlist.xml"));
myXMLLoader.addEventListener(Event.COMPLETE, processXML);
}
private function processXML(e:Event):void
{
myXMLLoader.removeEventListener(Event.COMPLETE, processXML);
myXML = new XML(e.target.data);
myXMList = new XMLList(myXML.children());
dispatchEvent(e);
}
public function getXML():XML
{
return myXML;
}
}
}
You should also ALWAYS capitalise your class names 'VideoData' not 'videoData'
You will need for the XML data to have been received before getting a value.
Add a private Boolean _xmlLoaded in your videoData class , set it to true in the processXML method.
Create a getter
public function get xmlLoaded():Boolean
{
return _xmlLoaded;
}
Now you can do this:
private var data:videoData = new videoData();
private var xmlData:XML;
private function init():void
{
addEventListener(Event.ENTER_FRAME , xmlLoaded );
}
private function xmlLoaded(event:Event):void
{
if( videoData.xmlLoaded )
{
xmlData = videoData.getXML();
removeEventListener(Event.ENTER_FRAME , xmlLoaded );
}
}
You are already getting your private myXML variable out through the .getXML() method. This is the best way to expose encapsulated data to outside classes.
An alternative would be to make your myXML field public instead of private, but using the get/set accessor methods you are hiding your actual implementation from outside world.
[Edit]
If your getXML() method is returning null, it means that your event handler (the processXML method) has not yet been called.
The problem appears to be in your VideoData constructor:
public function videoData()
{
var myXMLLoader:URLLoader = new URLLoader();
myXMLLoader.load(new URLRequest("playlist.xml"));
myXMLLoader.addEventListener(Event.COMPLETE, processXML);
}
The XML file is probably loaded before you attach the event handler, and that is why the event fires right before you start to listen to it. Try to reverse it and see if it works:
public function videoData()
{
var myXMLLoader:URLLoader = new URLLoader();
myXMLLoader.addEventListener(Event.COMPLETE, processXML); // moved up
myXMLLoader.load(new URLRequest("playlist.xml"));
}