Putting Urlloader in a Class - actionscript-3

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);
}

Related

loadermax to get qualified class name of the swf

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;

AS3 call function inside loader event function

I have a problem to call a function inside a conditional in another function. I've tried it and it works perfectly but it depends on where the call is made.
Process: I have the checkCode(); function that is called when a form is completed and sent.
private function checkCode():void {
var url = "checktrue.php";
var loader:URLLoader = new URLLoader;
var urlreq:URLRequest = new URLRequest(url);
var urlvars:URLVariables = new URLVariables;
loader.dataFormat = URLLoaderDataFormat.VARIABLES;
urlreq.method = URLRequestMethod.POST;
urlvars.codeVar = formattedCode;
urlreq.data = urlvars;
loader.addEventListener(Event.COMPLETE, completed); //Completed function
status.text = "calling loader";
loader.load(urlreq);
}
When php is complete, "completed" is called and:
private function completed(event:Event = null):void {
var loader2: URLLoader = URLLoader(event.target);
var checked:String = loader2.data.checked;
var codetrue:String = loader2.data.codetrue;
if(checked == "1" || codetrue == null || codetrue == "") {
trace("WRONG");
}
else{
download(); //download function
trace("ok");
}
}
Here I get the php vars and check if they are valid to call the download() function.
public function download():void {
req = new URLRequest(proxy + filename);
file = new FileReference();
file.addEventListener(Event.COMPLETE, completeHandler);
file.addEventListener(Event.CANCEL, cancelHandler);
file.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
file.addEventListener(ProgressEvent.PROGRESS, progressHandler);
file.download(req, "file.zip");
}
It is possible this function cannt be called from the "completed" loader function?
Thank you very much!
You need to put the download function in another button for the correct use. Or create your own event.

Dynamic Object Name in AS3

I have this code in my MXML project, I want to get dynamic Stream connection for different and dynamic usernames.
private var inStream:NetStream;
private function listenStream(user:String):void
{
this["inStream"+user] = new NetStream(connection);
this["inStream"+user].play(user);
}
private function closeStream(user:String):void
{
//clear stream listener
this["inStream"+user].close();
}
But this code is not worked, How can i build dynamic object names in ActionScript3?
Thanks alot
Try Dictionary
import flash.utils.Dictionary
private var streamDict:Dictionary = new Dictionary();
private function listenStream(user:String):void
{
var key:String = getKey(user);
var lastStream:NetStream = streamDict[key] as NetStream;
if (lastStream)
{
//close the last stream or do sth else
}
else
{
streamDict[key] = new NetStream(connection);
streamDict[key].play(user);
}
}
private function closeStream(user:String):void
{
var key:String = getKey(user);
//clear stream listener
var stream:NetStream = streamDict[key] as NetStream ;
if (stream)
{
stream.close();
}
//delete the stream
streamDict[key] = null;
delete streamDict[key];
}
private function getKey(user:String):String
{
return "inStream" + user;
}

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.