Accessing JSON array after it has been streamed, Flash as3 - json

I have the following code:
import flash.utils.describeType;
import flash.utils.getQualifiedClassName;
import flash.text.TextField;
stop();
var chartsURL : URLRequest = new URLRequest();
chartsURL.url="http://zagony.net/charts.php"
chartsURL.method=URLRequestMethod.GET;
var streamer:URLLoader=new URLLoader();
streamer.addEventListener(Event.COMPLETE, receive);
streamer.addEventListener(IOErrorEvent.IO_ERROR, missing);
streamer.load(chartsURL);
function receive (event : Event) : void
{
var buttonsCount:int = 0;
var json : String = event.target.data;
var myResults:Object = JSON.parse(json);
//trace(json);
for each(var data:Object in myResults)
{
var listItem:ListItem = new ListItem();
addChild(listItem);
listItem.y = 200 + (buttonsCount * 400);
buttonsCount++;
}
}
function missing (event : Event) : void
{
//trace("broken");
}
It successfully gets the JSON from the URL, but when it goes to add a symbol for each entry in the array, it simply does nothing.
This problem is only worsened by the fact that I'm using Flash 11 export in CS5, and therefore I can't use the built in Test Movie or trace to the console.
If anybody could point out what I'm doing wrong, it would be greatly appreciated. Thanks in advance.

Related

Smooth image on load in as3

I am new here and a complete noob when it comes to as3. Somehow I have managed to put this together with some help from different places. And now I turn to you guys :)
I need to put smoothing on my images and thumbs that Im loading from an XML file. I have tried a lot of things but can't get any of it to work and I get this error:
Scene 1, Layer 'as3', Frame 1, Line 27 1120: Access of undefined property e. -> So I know var bitmapContent:Bitmap = Bitmap( e.target.content ); is the problem. but I have no idea what to use instead of e. I
this i what I have so far:
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.events.MouseEvent;
import fl.transitions.Tween;
import fl.transitions.easing.None;
import flash.display.Bitmap;
// Loads the first image//
var i =new Loader();
i.load(new URLRequest("images/1.jpg"));
mainLoader.addChild(i)
//Loads the XML file//
var picsXML:XML;
var xmlLoader:URLLoader = new URLLoader();
xmlLoader.addEventListener(Event.COMPLETE , xmlLoaded);
xmlLoader.load(new URLRequest("imagelist.xml"));
//Loads images into thumbs//
function xmlLoaded(event:Event):void{
picsXML = new XML(xmlLoader.data);
//trace(picsXML);
var bitmapContent:Bitmap = Bitmap( e.target.content );
bitmapContent.smoothing = true;
var thumbLoader:UILoader;
for (var i:uint=0; i<picsXML.image.length(); i++)
{
thumbLoader=UILoader(getChildByName("thumb"+i));
thumbLoader.load(new URLRequest("thumbs/"+picsXML.image[i].#file));
thumbLoader.buttonMode = true;
thumbLoader.addEventListener(MouseEvent.CLICK, thumbClicked);
thumbLoader.addEventListener(MouseEvent.CLICK, tester);
}
}
//Loads large image when thumb is clicked//
function thumbClicked(event:MouseEvent){
//var bitmapImage:Bitmap = event.target.content;
//bitmapImage.smoothing = true;
var thumbName:String = event.currentTarget.name;
var thumbIndex:uint = uint(thumbName.substr(5));
var fullPath:String = "images/"+picsXML.image[thumbIndex].#file;
mainLoader.load(new URLRequest(fullPath));
var myTween:Tween = new Tween(mainLoader,"alpha", None.easeNone, .3,1,18,false);
}
//Removes the first image when thumbs is clicked//
function tester(event:MouseEvent){
if (mainLoader.contains(i)) {
trace("hej")
mainLoader.removeChild(i);
}
}
If i get your code true problem is here: u import an external xml file which is probably contain your url's and name of pic's. U can't turn ur xml file into a bitmap.
If u want smoothing on your pictures u need to it after load ur pics or thumb's.
Probably ur problem will fix like this :) Hope this will help
Functions with arguments work like this: function Name ( input arg Name : input arg Type )
Firstly, your function xmlLoaded(event:Event) cannot have an input called event
but then you try to do a Bitmap( e.target.content ); so for that bitmap line to work you'd have to change your input name to e like so... xmlLoaded( e : Event );
Secondly, var bitmapContent:Bitmap = Bitmap( e.target.content ); is incorrect.
This is more correct var bitmapContent:Bitmap = img_Bytes_Loader.content as Bitmap; set a Loader's content as Bitmap not XML content (text) as Bitmap (pixels).
Anyways assuming your XML file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Items>
<mp3>
<url> track1.mp3 </url>
<image> image1.jpg </image>
</mp3>
<mp3>
<url> track2.mp3 </url>
<image> image2.jpg </image>
</mp3>
</Items>
Then your code should look something like this below :
var imgLoader_XML : URLRequest;
var picLoader : Loader = new Loader();
function xmlLoaded(event:Event):void
{
picsXML = new XML(xmlLoader.data);
//trace(picsXML);
imgLoader_XML = new URLRequest( picsXML.mp3[ index ].image ); //[index] could be replaced with [i] if FOR loop
picLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, picloadComplete);
picLoader.load (imgLoader_2);
}
public function picloadComplete(evt:Event)
{
yourContainer.addChild(picLoader);
yourContainer.width = 100;
yourContainer.height = 100;
yourContainer.alpha = 1;
}
Thanks for the inputs guys. It is greatly appreciated.
I figured it out. You were right, of course I can't put smoothing on the UILoader, so I had to target the content of the UILoader and run thumbLoader.addEventListener(Event.COMPLETE, smoothing); each time an image is importet.
Here is the entire working code (maybe it can help someone else :) :
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.events.MouseEvent;
import fl.transitions.Tween;
import fl.transitions.easing.None;
import flash.display.Bitmap;
import flash.display.Loader;
// Loads the first image//
var i =new Loader();
i.load(new URLRequest("images/1.jpg"));
mainLoader.addChild(i)
//Loads the XML file//
var picsXML:XML;
var xmlLoader:URLLoader = new URLLoader();
xmlLoader.addEventListener(Event.COMPLETE , xmlLoaded);
xmlLoader.load(new URLRequest("imagelist.xml"));
//Loads images into thumbs//
function xmlLoaded(event:Event):void{
picsXML = new XML(xmlLoader.data);
var thumbLoader :UILoader = new UILoader();
for (var i:uint=0; i<picsXML.image.length(); i++)
{
thumbLoader=UILoader(getChildByName("thumb"+i));
thumbLoader.load(new URLRequest("thumbs/"+picsXML.image[i].#file));
thumbLoader.buttonMode = true;
thumbLoader.addEventListener(MouseEvent.CLICK, thumbClicked);
thumbLoader.addEventListener(MouseEvent.CLICK, tester);
thumbLoader.addEventListener(Event.COMPLETE, smoothing);
}
}
function smoothing(e:Event):void{
if(e.currentTarget.content is Bitmap)
{
Bitmap(e.currentTarget.content).smoothing = true;
}
}
//Loads large image when thumb is clicked//
function thumbClicked(event:MouseEvent){
var thumbName:String = event.currentTarget.name;
var thumbIndex:uint = uint(thumbName.substr(5));
var fullPath:String = "images/"+picsXML.image[thumbIndex].#file;
mainLoader.load(new URLRequest(fullPath));
mainLoader.addEventListener(Event.COMPLETE, smoothing);
var myTween:Tween = new Tween(mainLoader,"alpha", None.easeNone, .3,1,18,false);
}
//Removes the first image when thumbs is clicked//
function tester(event:MouseEvent){
if (mainLoader.contains(i)) {
trace("hej")
mainLoader.removeChild(i);
}
}

Action Script 3 return value from Class

I have AS3 class which parses xml and creates buttons foreach item in XML. However I want to access total number of items later.How can i do that ?
I am using it like this.
var menu:MenuClass = new MenuClass();
trace( menu.aItems() );
Right now it is retuning NAN however If i trace it after line Items = xml.item.length(); it outputs correct number.
package com.lib.menu
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class MenuClass extends MovieClip {
private var urlLoader:URLLoader;
private var urlRequest:URLRequest;
private const XML_PATH:String = "resources/menu.xml";
private var xml:XML;
protected var Items:Number;
public function MenuClass() {
urlLoader = new URLLoader();
urlLoader.load(new URLRequest(XML_PATH));
urlLoader.addEventListener(Event.COMPLETE, xmlLoaded);
}
private function xmlLoaded(e:Event):void
{
xml = new XML(e.target.data);
Items = xml.item.length();
for (var i:int = 0; i < Items; i++) {
var btn:Button = new Button(xml.item[i].#title,xml.item[i].#image);
btn.y = Math.floor(i * (btn.height+2)) ;
addChild(btn);
}
}
public function aItems():Number {
return Items;
}
}
}
URLLoader loads data asynchronously which means the constructor MenuClass does not wait for the loading to complete. When loading of the XML is complete xmlLoaded will be called and a valid value will be set to Items. But you are trying to access Items just after creating the object, i.e. before xmlLoaded is called. So you are getting NaN at that point.
Ok. I solved this by adding this.dispatchEvent(new Event("MenuComplete")); to end of private function xmlLoaded(e:Event):void and then
var menu:MenuClass = new MenuClass();
menu.addEventListener('MenuComplete', onNext);
function onNext(e:Event):void{
trace(menu.aItems());
}

TypeError: Error #1009 in AS3 flash cs6

I have got this error while working on my flash:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Options()
This is my Options class:
package {
import flash.display.MovieClip;
import fl.managers.StyleManager;
import flash.text.TextFormat;
import fl.events.ComponentEvent;
import fl.events.*;
import flash.events.MouseEvent;
import fl.controls.*;
import flash.net.SharedObject;
import flash.events.Event;
public class Options extends MovieClip
{
//DECLARE CLASS VARIABLES//
//DECLARE COMPONENT VARIABLES
private var cComponentFmt:TextFormat;
//DECLARE SAVE DATA VARIABLES
private var cPlayerData:Object;
private var cSavedGameData:SharedObject;
//DECLARE SOUND VARIABLES
public function Options()
{
//created the SharedObject using the getLocal() function
cSavedGameData = SharedObject.getLocal("savedPlayerData");
//set component formats
setComponents();
//initialize player's data
setPlayerData();
//set default message display upon entering the setup page
msgDisplay.text = "Introduce yourself to the fellow minions!";
//add event listeners
nameBox.addEventListener(MouseEvent.CLICK, clearName);
nameBox.addEventListener(ComponentEvent.ENTER, setName);
}
private function setComponents():void
{
//set the TextFormat for the components
cComponentFmt = new TextFormat();
cComponentFmt.color = 0x000000; //black colour
cComponentFmt.font = "Comic Sans MS"; //set default "Comic Sans MS"
cComponentFmt.size = 16;
//apply the new TextFormat to ALL the components
StyleManager.setStyle("textFormat", cComponentFmt);
}
private function setName(evt:ComponentEvent):void
{
trace("Processing text input box..");
// player pressed the ENTER key
cPlayerData.pName = nameBox.text;
msgDisplay.text = "Welcome, " + cPlayerData.pName + "! \nEnjoy many hours of fun with us!";
saveData();
}
private function clearName(evt:MouseEvent):void
{
// player CLICKED in the nameBox
nameBox.text = "";
}
private function setPlayerData():void
{
//all variables that relate to the player
cPlayerData = new Object();
//options related variables
cPlayerData.pName = "Papoi";
cPlayerData.sndTrack = "none";
//game related variables
cPlayerData.pScore = 0;
//save the player's data
saveData();
}
private function saveData():void
{
//savedPlayerData = cPlayerData is the name=value pair
cSavedGameData.data.savedPlayerData = cPlayerData;
//force Flash to update the data
cSavedGameData.flush();
//reload the newly saved data
loadData();
}
private function loadData():void
{
//gets the data stored in the SharedObject
//this particular line not found in the options.as
cSavedGameData = SharedObject.getLocal("savedPlayerData","/",false);
//now stores the save data in the player object
cPlayerData = cSavedGameData.data.savedPlayerData;
}
}
}
Does anyone know why this particular error exists?
And also, I want to make the cPlayerData.pName to be "Papoi" if a name is not entered in the nameBox. How am I to make that happen? Cuz right now, I tried by setting the cPlayerData.pName to "Papoi" by default, but it doesn't work. Hmm..
Your problem is in the constructor function so maybe the component “msgDisplay” and/or the component “nameBox” are/is not initialized completely yet while you are trying to access one of its properties...
A good practice is to access your objects only when they are fully initialized, that can be done using the event “AddedToSatge” which will not be fired before all children’s are initialized..
Note: even if it is not the source of your problem, it is a good thing to do always because it will save you from other problems and bugs related to the same issue.
UPDATE:
The problem was in your loadData() function, because you have changed the localPath of your SharedObject inside that function body (it is not the same as used in saveData() function), then your loaded data will always be null, and that was what you see in the error message. you just need to delete that line from loadData function. see my updated code below.
package
{
import flash.display.MovieClip;
import fl.managers.StyleManager;
import flash.text.TextFormat;
import fl.events.ComponentEvent;
import fl.events.*;
import flash.events.MouseEvent;
import fl.controls.*;
import flash.net.SharedObject;
import flash.events.Event;
public class Options extends MovieClip
{
//DECLARE CLASS VARIABLES//
//DECLARE COMPONENT VARIABLES
private var cComponentFmt:TextFormat;
//DECLARE SAVE DATA VARIABLES
private var cPlayerData:Object;
private var cSavedGameData:SharedObject;
//DECLARE SOUND VARIABLES
public function Options()
{
if (stage)
{
init();
}
else
{
addEventListener(Event.ADDED_TO_STAGE, init);
}
}
public function init(e:Event = null):void
{
// it is important to remove it coz you don't need it anymore:
removeEventListener(Event.ADDED_TO_STAGE, init);
//created the SharedObject using the getLocal() function
cSavedGameData = SharedObject.getLocal("savedPlayerData");
//set component formats
setComponents();
//initialize player's data
setPlayerData();
//set default message display upon entering the setup page
msgDisplay.text = "Introduce yourself to the fellow minions!";
//add event listeners
nameBox.addEventListener(MouseEvent.CLICK, clearName);
nameBox.addEventListener(ComponentEvent.ENTER, setName);
}
private function setComponents():void
{
//set the TextFormat for the components
cComponentFmt = new TextFormat();
cComponentFmt.color = 0x000000;//black colour
cComponentFmt.font = "Comic Sans MS";//set default "Comic Sans MS"
cComponentFmt.size = 16;
//apply the new TextFormat to ALL the components
StyleManager.setStyle("textFormat", cComponentFmt);
}
private function setName(evt:ComponentEvent):void
{
trace("Processing text input box..");
// player pressed the ENTER key
// remove the whitespace from the beginning and end of the name:
var playerNameWithoutSpaces:String = trimWhitespace(nameBox.text);
// check if the user did not enter his name then default name is "Papoi":
if (playerNameWithoutSpaces == "")
{
cPlayerData.pName = "Papoi";
}
else
{
cPlayerData.pName = nameBox.text;
}
//// This will replace the default message :
//// msgDisplay.text = "Welcome, " + cPlayerData.pName + "! \nEnjoy many hours of fun with us!";
// This will add the welcome message to the default message :
msgDisplay.text += "\nWelcome, " + cPlayerData.pName + "! \nEnjoy many hours of fun with us!";
saveData();
}
private function clearName(evt:MouseEvent):void
{
// player CLICKED in the nameBox
nameBox.text = "";
}
private function setPlayerData():void
{
//all variables that relate to the player
cPlayerData = new Object();
//options related variables
cPlayerData.pName = "Papoi";
cPlayerData.sndTrack = "none";
//game related variables
cPlayerData.pScore = 0;
//save the player's data
saveData();
}
private function saveData():void
{
//savedPlayerData = cPlayerData is the name=value pair
cSavedGameData.data.savedPlayerData = cPlayerData;
//force Flash to update the data
cSavedGameData.flush();
//reload the newly saved data;
loadData();
}
private function loadData():void
{
//gets the data stored in the SharedObject
//this particular line not found in the options.as
//// delete the next line, no need to set it every time :
//// cSavedGameData = SharedObject.getLocal("savedPlayerData","/",false);
//now stores the save data in the player object
cPlayerData = cSavedGameData.data.savedPlayerData;
}
//────────────────────────────────────────────
private function trimWhitespace($string:String):String
{
if ($string == null)
{
return "";
}
return $string.replace(/^\s+|\s+$/g, "");
}
//────────────────────────────────────────────
}
}

flash as3 trying to play audio from external swf and getting message "Call to a possibly undefined method"

I'm able to load graphics from an external library with no problems, but for some reason all of the audio will not load/play.
Here's the loader class I'm using...
package
{
import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.events.Event;
import flash.net.URLRequest;
import flash.text.Font;
public class LoadLibrary extends MovieClip
{
private var gear:MovieClip = new mcGear();
private var txtLoading:BlankClip;
private var _gameLib:String = "";
private var _Impact:Font = new Impact();
public function LoadLibrary(gameLibrary:String)
{
_gameLib = gameLibrary;
addChild(gear);
gear.x = 512;
gear.y = 384;
gear.alpha = .2;
gear.scaleX = .33;
gear.scaleY = .33;
txtLoading = new BlankClip(_Impact, "LOADING...", -400, -60, 800, 120, 26, "center", 5);
addChild(txtLoading);
txtLoading.x = 512;
txtLoading.y = 525;
txtLoading.alpha = .2;
var request:URLRequest = new URLRequest(_gameLib);
LoadVars.LIBLOADER.contentLoaderInfo.addEventListener(Event.COMPLETE, gameLibraryLoaded);
LoadVars.LIBLOADER.load(request);
}
private function gameLibraryLoaded(e:Event):void
{
removeChild(gear);
removeChild(txtLoading);
LoadVars.LIBLOADER.contentLoaderInfo.removeEventListener(Event.COMPLETE, gameLibraryLoaded);
var loaderInfo:LoaderInfo = LoaderInfo(e.currentTarget);
LoadVars.APPDOMAIN = loaderInfo.applicationDomain;
dispatchEvent(new GameEvents(GameEvents.LIBRARY_LOADED));
}
}
}
and the functions in my main class...
private function loadLib():void
{
_loadGraphics = new LoadLibrary("Elemental_Library.swf");
addChild(_loadGraphics);
_loadGraphics.addEventListener(GameEvents.LIBRARY_LOADED, test);
}
private function test(e:GameEvents):void
{
trace("LOADED");
var music:Sound = new GameMusic();
music.play();
}
Everything works fine until I try music.play and I get "1180: Call to a possibly undefined method GameMusic." I've tried several other audio clips and I get the same message. I tried creating a new library and imported just one audio file, same message. I verified I'm using the correct linkage names and the crazy part is that all of the movie clips load just fine from the same library.
Changed test to...
private function test(e:GameEvents):void
{
trace("LOADED");
var musicClass:Class = Class(LoadVars.APPDOMAIN.getDefinition("GameMusic"));
var music:Sound = Sound(new musicClass()); music.play();
}
I knew it was something stupid :P

Loading and Returning Text Data with ActionScript 3 (URLLoader)

I'm trying to do something exceedingly simple: write a function that reads text from a text file and returns the text in a string using AS3.
The Function
public function readData(path:String):String
{
var dataSet:String;
var urlRequest:URLRequest = new URLRequest(path);
var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
urlLoader.addEventListener(Event.COMPLETE, urlLoader_complete);
urlLoader.load(urlRequest);
function urlLoader_complete(evt:Event):void {
dataSet = urlLoader.data;
trace(dataSet)
}
trace(dataSet);
return dataSet;
}
Calling the Function
var dataString:String = aq.readData("http://example.com/data.txt");
trace(dataString);
This code returns a null string when I run it. Why?
EDIT:
Ok, I now see that this doesn't work because urlLoader is acting asynchronously. I'm writing a program that reads in a data file and acts on it. Does this mean that I need to write the rest of my program inside function urlLoader_complete? Or should I pause the program until urlLoader is finished?
In Flash and Flex, all network I/O is asynchronous. It has to be this way in order to avoid blocking your browser.
As a result, it is not possible to write a readData() function that directly returns the result of a network read operation. You will have to pass a callback function to the readData() function. When readData() has finished reading the data, it can call the callback function.
For example:
/**
* Asynchronous function to read data as a string. When the data has been read,
* the callback function is called with the result.
*
* #param path the URL to read
* #param callback the function that is called with the result; should take
* one string argument.
*/
public function readData(path:String, callback:Function):void
{
var dataSet:String;
var urlRequest:URLRequest = new URLRequest(path);
var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
urlLoader.addEventListener(Event.COMPLETE, urlLoader_complete);
urlLoader.load(urlRequest);
function urlLoader_complete(evt:Event):void {
dataSet = urlLoader.data;
trace(dataSet);
callback(dataSet);
}
}
Here is how you might call that function from Flex:
<mx:Label id="mylabel" />
<mx:Button click="readData('http://www.google.com/',
function(s:String):void {mylabel.text = s})" />
Its been 3 years ago since this question arose with you, but since I stumbled on this problem a few hours ago, and managed to get it to work and thought why not share it. There might be better alternatives already, but hey I just started coding Actionscript so no blames :)
First build a Preloader class with a filecounter. There will be a numFiles parameter in the constructor which holds the total number of files to be loaded. Every time when the complete method is called, 1 to the filecounter will be added and a statement will be checking if all files are loaded. when the numFiles is equal to the counter call the start() method of the calling class.
*Preloader.as *
package
{
import flash.display.Loader;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class Preloader
{
public var urlLoader:URLLoader;
public var response:Array = new Array();
public var callingClass:Object;
public var numFiles:uint;
private var counter:uint;
public function Preloader(callingClass:Object, numfiles:uint)
{
this.callingClass = callingClass;
this.numFiles = numFiles;
}
public function load(name:String):void
{
var request:URLRequest = new URLRequest(name);
urlLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, onLoad);
urlLoader.load(request);
}
public function onLoad(event:Event):void
{
response[counter] = event.currentTarget.data;
if(numFiles == counter) {
callingClass.start();
} else {
counter++;
}
}
}
}
The constructor method in the calling class will have to call all the preload files and the start method will be the replacement of your constructor stuff. note that when the preloader loads it need the reference to its calling class and the total number of "to be loaded" files:
package
{
import flash.display.MovieClip;
import misc.Preloader;
public class Path extends MovieClip
{
public var preloader:Preloader = new Preloader(this, 3); //pass this class and the total number of files
public function Controller()
{
preloader.loadJSON('file1.js');
preloader.loadJSON('file2.js');
preloader.loadJSON('file3.js');
}
public function start():void
{
trace(preloader.response[0]); //Get first file contents
}
}
}