loadermax to get qualified class name of the swf - actionscript-3

The typical as3 code would be like this
private function load():void {
var loaderContext:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
if(Security.sandboxType == Security.REMOTE) {
loaderContext.securityDomain = SecurityDomain.currentDomain;
}
loader.contentLoaderInfo.addEventListener(Event.INIT, handleInit);
loader.load(new URLRequest("capture.swf"), loaderContext);
}
private function handleInit(event:Event){
var className:String = getQualifiedClassName(loader.content);
var classRef:Class = loader.contentLoaderInfo.applicationDomain.getDefinition(className) as Class;
var captureModule = new classRef();
addChild(captureModule as DisplayObject);
}
now while using greensock's loadermax, how can I access the qualified class name, it's reference, create an object myself and add to display.
loaderMax.append(new SWFLoader("capture.swf", {name:"capture"}));
loaderMax.append(new SWFLoader("filter.swf", {name:"filter"}));
loaderMax.load();
the loadComplete function
function completeHandler(event:LoaderEvent): void {
trace(event.target + " is complete");
var capture = loaderMax.getContent("capture");
trace(getQualifiedClassName(capture)); //want to reach the custom class of the loaded sf
}

turns out that the loaded swf has a property loaderInfo.loader that you can access to use the loader.
var loader = loaderMax.getContent("capture").rawContent.loaderInfo.loader;
this.data["capture"] = loader.contentLoaderInfo.applicationDomain.getDefinition(getQualifiedClassName(loaderMax.getContent("capture").rawContent)) as Class;

Related

Can not retrieve data from completely Loaded static variable AS3

Basically I was trying to read an image in binary with help of URLLoader() and convert it to a image again in flash.
I wrote 2 static methods that one of them read image and set data properties to binary and other one is the COMPLETE handler.
In COMPLETE handler I convert the binary data to ByteArray and assign it to a static variable. then tried to access to it from Main Timeline but it won't work.
The problem is my temporary variable not fully loading the static variable and when I'm checking BytesAvailable it's something like only 2.
What I'm doing wrong?
The COMPLETE handler:
public static function compHand(e:Event):void
{
var myByteArray:ByteArray = URLLoader(e.target).data as ByteArray;
LoaderToObject.ImageBytes = myByteArray;
trace(myByteArray.bytesAvailable);
if (LoaderToObject.ImageBytes.length != myByteArray.length)
{
trace(myByteArray.length);
trace(LoaderToObject.ImageBytes.length);
}
else
{
trace("successFully loaded!");
}
}
public static function loadBin(FileUrl:String)
{
var imageBytes:ByteArray=new ByteArray();
var binUrl:URLRequest = new URLRequest(FileUrl);
var binLoader:URLLoader = new URLLoader(binUrl);
binLoader.dataFormat = URLLoaderDataFormat.BINARY;
binLoader.addEventListener(Event.COMPLETE,compHand);
//trace(LoaderToObject.ImageBytes);
trace(FileUrl);
}
The function I used in main timeLine:
function loadfile(e:MouseEvent):void
{
LoaderToObject.loadBin("chick.bmp");//send file to URLLoader
imageBytes= LoaderToObject.ImageBytes;
MakeImage2(imageBytes);
}
Please help me
Because URLLoader is asynchronous, so When you try to access imageBytes, the imageBytes hasn't been load complete yet.
Your need to pass callback function to loadBin for been called when load complete
Here is an example
The load class
Class MyLoader {
private var callback:function;
private var binLoader:URLLoader;
public function load(FileUrl:String, $callback:Function):void
{
callback = $callback;
//your code
var imageBytes:ByteArray=new ByteArray();
var binUrl:URLRequest = new URLRequest(FileUrl);
binLoader = new URLLoader(binUrl);
binLoader.dataFormat = URLLoaderDataFormat.BINARY;
binLoader.addEventListener(Event.COMPLETE,compHand);
//trace(LoaderToObject.ImageBytes);
trace(FileUrl);
}
private function compHand(e:Event):void
{
var myByteArray:ByteArray = URLLoader(e.target).data as ByteArray;
if (callback != null)
{
callback(myByteArray, this);
}
}
}
LoaderToObject's load function
//make MyLoader class live, it's important
private var loadValidDic:Dictionary = new Dictionary();
public static function loadBin(FileUrl:String, callback:Function)
{
var loader:MyLoader = new MyLoader();
loadValidDic[loader] = callback;
loader.load(FileUrl, internalComplete);
}
private static function internalComplete(ba:ByteArray, loader:MyLoader):void
{
var callback:function = loadValidDic[loader];
if (callback)
{
callback(ba);
loadValidDic[loader] = null;
delete loadValidDic[loader];
}
}
Used in timeline
function loadfile(e:MouseEvent):void
{
LoaderToObject.loadBin("chick.bmp", onComplete);//send file to URLLoader
}
private function onComplete(imageBytes:ByteArray):void
{
MakeImage2(imageBytes);
}

Passing variables from actionscript 3 to actionscript 2

I have a swf written in AS3 which loads an AS2 swf.
AS3 code:
var url:String = "as2.swf?myvar=hello";
var spURL:Array = url.split("?");
var urlVars:URLVariables = new URLVariables();
urlVars.decode(spURL[1]);
var req:URLRequest = new URLRequest( spURL[0] );
req.data = urlVars;
req.method = URLRequestMethod.GET;
AS2 code:
trace(_root.myvar);
but nothing traced!
I found solution to my question.
Full source code bellow
AS3: with a movieclip named "as2btn" and a text field named "as3_log". The publish class name is "main_as3"
package {
import flash.display.*;
import flash.events.*;
import flash.net.*;
public class main_as3 extends MovieClip {
public var ld:Loader;
public function main_as3() {
// constructor code
this.as2btn.addEventListener(MouseEvent.MOUSE_DOWN, as2Load);
this.logMessage("Initialized!");
}
public function logMessage(msg:String)
{
this.as3_log.appendText("AS3: " + msg + "\n");
}
public function as2Load(evt:MouseEvent)
{
if (this.ld) {
this.ld.unloadAndStop();
this.ld = null;
}
var url:String = "as2.swf?myvar=1rewr&myvar2=1234";
var spURL:Array = url.split("?");
var urlVars:URLVariables = new URLVariables();
urlVars.decode(spURL[1]);
var req:URLRequest = new URLRequest(spURL[0]);
req.data = urlVars;
req.method = URLRequestMethod.GET;
this.ld = new Loader();
this.ld.load(req);
addChild(this.ld);
}
}
}
AS2: with a movieclip linkage identifier "main" and class name "main_as2" includes a text field named "as2_log"
class main_as2 extends MovieClip
{
var _parent;
function main_as2()
{
super();
this.gotoAndStop(1);
this.logMessage("Initialized!");
this.logMessage("_parent.myvar: " + _parent.myvar);
}
function logMessage(msg:String)
{
this["as2_log"].text = this["as2_log"].text + "AS2: " + msg + "\n";
}
}

Putting Urlloader in a Class

I have searched on google en different pages i found the problem but not the solution.
I have a class i made and that class is called WebServiceController:
public class WebServiceController
{
private var url:String;
private var post:Object=new Object();
private var loader:URLLoader = new URLLoader();
private var postVariable:String="";
private var getVariable:String="";
private var Geladen:Boolean=false;
public function WebServiceController()
{
}
public function postUrlData(u:String,p:Object):String
{
url=u;
post=p;
var urlReq:URLRequest = new URLRequest (url);
var i:int=0;
for(var key:String in post)
{
//trace(key +" = " + post[key]);
if(i==0)
{
// urlVars.key = post[key];
postVariable=postVariable+""+key+"="+post[key];
}
else
{
//urlVars.key = post[key];
postVariable=postVariable+"&"+key+"="+post[key];
}
i++;
}
//trace(postVariable);
var urlVars:URLVariables = new URLVariables(postVariable);
//trace(urlVars);
// Add the variables to the URLRequest
urlReq.data = urlVars;
urlReq.method = URLRequestMethod.POST;
// Add the URLRequest data to a new Loader
//loader.load(urlReq);
// Set a listener function to run when completed
loader.addEventListener(Event.COMPLETE, onLoaderComplete);
// Set the loader format to variables and post to the PHP
loader.dataFormat = URLLoaderDataFormat.VARIABLES;
loader.load(urlReq);
function onLoaderComplete(event:Event):void
{
return loader.data;
}
}
Now from my movieclip i call the next function but it says undefined:
var wb:WebServiceController = new WebServiceController();
trace(wb.postUrlData(url,post));
I dont know how to solve this. I tried different things but it keeps saying undefined.
The URLLoader.load call is executed asynchronously so the data has not been returned when you attempt to trace it out in the class that instantiates your WebServiceController class.
To access the data in the parent class, your best bet is probably to dispatch an event from the WebServiceController class when the data has loaded and catch it in the parent class.
WebServiceController:
public function postUrlData(u:String, p:Object):void
{
url=u;
post=p;
var urlReq:URLRequest = new URLRequest (url);
var i:int=0;
for(var key:String in post)
{
//trace(key +" = " + post[key]);
if(i==0)
{
// urlVars.key = post[key];
postVariable=postVariable+""+key+"="+post[key];
}
else
{
//urlVars.key = post[key];
postVariable=postVariable+"&"+key+"="+post[key];
}
i++;
}
//trace(postVariable);
var urlVars:URLVariables = new URLVariables(postVariable);
//trace(urlVars);
// Add the variables to the URLRequest
urlReq.data = urlVars;
urlReq.method = URLRequestMethod.POST;
// Add the URLRequest data to a new Loader
//loader.load(urlReq);
// Set a listener function to run when completed
loader.addEventListener(Event.COMPLETE, onLoaderComplete);
// Set the loader format to variables and post to the PHP
loader.dataFormat = URLLoaderDataFormat.VARIABLES;
loader.load(urlReq);
}
private function onLoaderComplete(event:Event):void
{
// We can pass the event on like this
dispatchEvent(event);
}
Parent class:
public function initWebServiceController():void
{
var wb:WebServiceController = new WebServiceController();
wb.addEventListener(Event.COMPLETE, onWebServiceControllerDataLoaded);
wb.postUrlData(url, post);
}
private function onWebServiceControllerDataLoaded(event:Event):void
{
// The event target is the URLLoader instance. We can
// access the loaded data via its data property
trace(URLLoader(event.target).data);
}

Add complete contact object from Facebook to SqLite

I can't add name and image from Facebook contacts to SqLite, becouse adding is inside in loop and loader start when Event is Complete. Fllowing code adds data to the database, but in the name of the object is the last person out of the loop. Any thoughts? Thanks!
private var person:PersonVO;
protected function handleFriendsLoad(response:Object, fail:Object):void
{
if (fail) { return }
var friends:Array = response as Array;
var l:uint=friends.length;
for (var i:uint=0;i<l;i++) {
var friend:Object = friends[i];
FacebookDesktop.api('/'+friend.id, loadData);
}
}
private function loadData(object:Object, fail:Object):void
{
if (fail) { return; }
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageToByteArray);
loader.load(new URLRequest(FacebookDesktop.getImageUrl(object.id, 'large')));
person = new PersonVO()
person.name = object.first_name;
}
private function imageToByteArray(event:Event):void
{
var wczytaj:Loader = (event.target as LoaderInfo).loader;
var image:Bitmap = Bitmap(wczytaj.content);
var encoderJpeg:JPEGEncoder = new JPEGEncoder();
var byteArray:ByteArray = encoderJpeg.encode(image.bitmapData);
person.image= byteArray;
insert(person);
}
private function insert(person:PersonVO):void
{
dbStatement.text = "INSERT INTO person (name,image) values(:name,:jpeg)";
dbStatement.parameters[":name"] = person.name;
dbStatement.parameters[":jpeg"] = person.image;
dbStatement.execute();
}
Extend Loader class functionality:
dynamic class DynamicLoader extends Loader{}
Then store whatever you want in instances of DynamicLoader:
private function loadData(object:Object, fail:Object):void
{
if (fail) { return; }
var person:PersonVO = new PersonVO();
person.name = object.first_name;
var loader:DynamicLoader = new DynamicLoader();
loader.person = person;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageToByteArray);
loader.load(new URLRequest(FacebookDesktop.getImageUrl(object.id, 'large')));
}
private function imageToByteArray(event:Event):void
{
var wczytaj:DynamicLoader = (event.target as LoaderInfo).loader as DynamicLoader;
var image:Bitmap = Bitmap(wczytaj.content);
var encoderJpeg:JPEGEncoder = new JPEGEncoder();
var byteArray:ByteArray = encoderJpeg.encode(image.bitmapData);
var person:PersonVO = wczytaj.person;
person.image= byteArray;
insert(person);
}
I have not used private var person:PersonVO;. So if you are not using it in the other methods of your class, you could remove it completely.

URLLoader loads multi files and the result order is the same as call load()

Since URLLoader is async, how to make sure the order of data from server side is the same as the loader.load() call? In other words, the data order in totalResults is the same order of url-related content?
Following is code snippet:
1.for each(var url in urls) {
loadData(url);
}
2.private function loadData(url:String):void {
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, completeHandler);
var request:URLRequest = new URLRequest(url);
urlLoader.load(request);
}
3.private function completeHandler(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
var result:Object = loader.data;
totalResults.push(result);// suppose totalResults is Array and a property in the class.
}
You can extend URLLoader class functionality.
dynamic class DynamicURLLoader extends URLLoader { }
Then store data ( in your case probably index ) in loader object, before requesting:
var urlLoader:DynamicURLLoader = new DynamicURLLoader();
urlLoader.index = ...
After response, retrieve that data ( in your case index ):
var loader:DynamicURLLoader = DynamicURLLoader(event.target);
totalResults[ loader.index ] = loader.data;
you could either use BulkLoader - it got this build-in. or you have to build your own queue, where one file is loaded after the other.
code snippet:
0.var queue:Array, totalResults:Array = [];
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, completeHandler);
1.for each(var url in urls) {
loadData(url);
}
2.private function loadData(url:String):void {
var request:URLRequest = new URLRequest(url);
queue.push(request);
}
3.private function doQueue() {
if (queue.length > 0) {
var arr:Array = queue.splice(0,1);
var req:URLRequest = arr[0] as URLRequest;
urlLoader.load(req);
}
else {
// queue done !
trace(totalResults);
}
}
4.private function completeHandler(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
var result:Object = loader.data;
totalResults.push(result);// suppose totalResults is Array and a property in the class.
doQueue();
}
You can load each url sequentially one after the other in order like in the following example:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class Main extends Sprite
{
private var _urls:Vector.<String>;
private var _counter:int;
private var _data:Array;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
_urls = Vector.<String>(["text1.txt", "text2.txt", "text3.txt" ]);
_counter = 0;
_data = [];
loadNext();
}// end function
private function loadNext():void
{
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, onComplete);
urlLoader.load(new URLRequest(_urls[_counter]));
}// end function
private function onComplete(event:Event):void
{
_data.push((event.target as URLLoader).data);
if (_counter++ == (_urls.length - 1)) trace("complete");
else loadNext();
}// end function
}// end class
}// end package
The methods loadNext() and onComplete() act as a loop. When loadNext() is called, an URLLoader object is instantiated and loads an url in the Vector.<String> object _urls. It uses the _counter object as a counter that is increment upon each UrlLoader object's "complete" event.
When the onComplete() event handler is called, it pushes the data loaded by the URLLoader object into an array called _data. Finally an if statement checks to see if all the urls have been loaded, if not, it increments the counter, if so, it executes the rest of the code in the application, in this case trace("complete");.
Why not just use HTTPService, which allows you to use AsyncToken to determine which initial call resulted in which initial result? That way, you don't have to wait between calls (with the performance degradation that implies.) Here is some documentation about how it works with Remoting, which is similar http://flexdiary.blogspot.com/2008/11/more-thoughts-on-remoting.html . With HttpService, you get back the token as a result of the send() method.