Normally for a string to object is converted as follows.
var obj:object=getChildByName("string");
And we can give properties to it like obj.x=100;But in the case of a series of stings
[objet Stage].[object MainTimeline].[object TextField]
it wil not works.Actually i need to give properties to a target path which is a string
what i do??
Here is the code to get path to a movieclip:
addEventListener(MouseEvent.CLICK, targetMC);
function targetMC(MouseEvent:Event):void
{
var curinstance = MouseEvent.target.valueOf();
var targ:Object = curinstance.parent;
var path = curinstance;
do
{
if (targ == "[object Stage]")
{
path = targ + "." + path;
}
else
{
path = targ + "." + path;
}
targ = targ.parent;
} while (targ);
trace(path);
}
i would like to give properties to path.
A number of things are awkward about your code:
Don't compare the string value of objects to find out about class type. Use the is keyword:
if (obj.parent is Stage) doSomething();
Don't use class names as parameter names: MouseEvent is a type!
function targetMC ( ev:MouseEvent ) // ...more code
It is useful to name handler methods according to the event upon which they are invoked, for example:
function onMouseClick (ev:MouseEvent)
or
function mouseClickHandler (ev:MouseEvent)
If you can avoid it, don't cast to Object to access members, but try to use subclass types - it allows the compiler to more effectively check your code for errors. Since all objects in the display list are instances of DisplayObject, you could use this:
var obj:DisplayObject = ev.target as DisplayObject;
If you want to output a path to your object, use instance names instead of types - you might have more than one TextField!
private function getObjectPath (obj:DisplayObject) : String {
var path:String = obj.name;
if (obj.parent != null && !(obj.parent is Stage)) {
path = getObjectPath (obj.parent) + "." + path;
}
return path;
}
Now for your answer: Use the KeyboardEvent.
textField.addEventListener (KeyboardEvent.KEY_UP, onKeyUp);
and
private function onKeyUp (ev:KeyboardEvent) : void {
var tf:TextField = ev.target as TextField;
var text:String = tf.text;
tf.text = text + String.fromCharCode(charCode);
}
Note that this will only work as long as the TextField has focus, that is the user has to click it first.
If you need to pass a key charCode to a TextField, the latter should listen to a KeyboardEvent and retrieve the info from the event's charCode property
http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/
Your perspective of AS3 is "different"... For instance getChildByName doesn't convert a String to an Object, it basically does what the method name states , it retrieves a parent's child using its name as a reference.
It looks like you're adapting whatever language you're coming from to AS3. I doubt this will work...
Related
I'm trying to modify an Object in another class. So I have something like this:
MainClass.as:
..
var myObject:Object = new Object();
Class2_Instance.get_JSON(myObject);
trace(myObject.id); // output: undefined. whereas it should be 42. see below.
..
Class2.as
public function get_JSON(url:String , the_object:Object)
{
var request:URLRequest = new URLRequest(url);
var variables:URLLoader = new URLLoader();
variables.dataFormat = URLLoaderDataFormat.TEXT;
variables.addEventListener(Event.COMPLETE, Complete_Handler_JSON(the_object));
try
{
variables.load(request);
}
catch (error:Error)
{
trace("Unable to load URL: " + error);
}
}
function Complete_Handler_JSON(the_object:Object):Function
{
return function(event:Event):void
{
var loader:URLLoader = URLLoader(event.target);
the_object = JSON.parse(loader.data);
trace(the_object.id); //returns 42.
};
}
So the JSON operation performs correctly within Class2, and it assigns the .parse() value to the_object, but I think there is something I don't understand with AS's pass-by-reference logic. Since I was expecting myObject in MainClass.as would change, too.
What should I do to modify the value of the function argument (myObject) directly ?
Thanks !
The issue is in this line in your event handler:
the_object = JSON.parse(loader.data);
The minute you do this, you're no longer dealing with the object which you passed in to the method. You're assigning a new value to the local variable named the_object. It's important to understand that objects are not passed by reference - object references are passed by value. So the_object in your method is a copy of the reference. When you assign a new value, that copy is overwritten with a different reference.
The solution is to pass the reference by reference - this is related to the concept of double pointers in languages such as C++, also known as double indirection. I'm not certain that this is even possible in ActionScript.
A better solution, just return the deserialized object as a return value.
Objects are passed by reference.
But as i see in your code you are overwriting the_object by another one on the line : the_object=JSON.parse(loader.data).
You can create a new variable and then copy the values in the_object:
var json:Object = JSON.parse(loader.data);
for (var k:String in json) {
the_object[k]=json[k];
}
I want to pass an object to a function by value so that I can make modifications to that object. I don't want the original object to be updated. However, all the function parameters are passed by reference.
I've tried to copy an object ( var new_object:Object = original_object; ) This just creates a pointer to original_object.
Is there a way I can pass parameter by value?
update One workaround I see is to make deep copy of an object by using ByteArray as described here. Not sure how efficient it is. Maybe there is a better solution out there.
You will have to make a copy of the object before passing it to the function :
public function copy(value:Object):Object
{
var buffer:ByteArray = new ByteArray();
buffer.writeObject(value);
buffer.position = 0;
var result:Object = buffer.readObject();
return result;
}
public function testFunction(obj:Object):void
{
//do something with obj
}
public function test():void
{
var obj:Object = {};
testFunction(copy(obj));
}
I know that AS3 does not have pointer or reference. Every object is pass by reference already. (I supposed?)
What should I do if I want to do with pointer?
e.g. all object point to one target, I only need to change target's value, then all other object will access different value.
You can effectively get the same behavior by using a helper object to simulate a pointer -- in other words using it to carry the target reference. For instance:
public class PseudoPointer
{
private var obj:Object;
private var prop:String;
public function PseudoPointer(obj:Object, prop:String)
{
// Point to property with name 'prop' on object 'obj'.
this.obj = obj;
this.prop = prop;
}
public function get value():* {
return obj[prop];
}
public function set value(value:*):void {
obj[prop] = value;
}
}
Then you could do this -- assume there's a magicNumber property on an object named target:
var numberPtr = new PseudoPointer(target, "magicNumber");
myDynamicObjectA.numberPtr = numberPtr;
myDynamicObjectB.numberPtr = numberPtr;
myDynamicObjectC.numberPtr = numberPtr;
Now any object that has a reference to the pseudo-pointer can read and write the target property:
numberPtr.value = 42;
You could create a function and in which you give it the value and then subsequently assign it to all of those other variables.
Something like below:
var objectA:Number;
var objectB:Number;
...
function myFunction(newValue:Number):void
{
objectA = newValue;
objectB = newValue;
...
}
You could try setting a variable reference to a function. Then if you update that reference, it would return a different function.
var myFunc:Function;
function funcOne():int {
return 1;
}
function funcTwo():int {
return 2;
}
function getFunc():Function {
return myFunc;
}
myFunc = funcOne;
var myObjOne:Object = new Object();
myObjOne.objFunc = getFunc;
var myObjTwo:Object = new Object();
myObjTwo.objFunc = getFunc;
trace(myObjOne.objFunc.call().call()); // 1
trace(myObjTwo.objFunc.call().call()); // 1
myFunc = funcTwo;
trace(myObjOne.objFunc.call().call()); // 2
trace(myObjTwo.objFunc.call().call()); // 2
This allows any object to point at a single function and have what that returns be updateable for all of them simultaneously. It's not the prettiest code and it's not as type-safe as if ActionScript had delegates to enforce the signatures of what's set for myFunc, but it is still a pretty flexible model if you get creative with it.
Have those pointers point to something that contains the object or has the object as a property on it.
So
var myArr:Array = [new YourObject()];
var client1:ArrayClient = new ArrayClient();
client1.array = myArr;
var client2:ArrayClient = new ArrayClient();
client2.array = myArr;
myArr[0] = new YourObject();
//client1.array[0]==client2.array[0]==the new object
However, this seems to be a great way to get yourself into a lot of trouble really quickly. What's the use case?
I have hit a road block on this and would highly appreciate if someone can help me on this, please. What I am trying to do is to use shared runtime library by loading a swf ('index.swf') which has numerous library objects which are named in sequence such as:
(orange1,orange2,orange3,orange4)
(red1,red2,red3,red4)
I am able to load the swf('index.swf') without any issues and even am able to load the right library asset, but I have to declare the full name as string such as getDefinition('orange1'). What I would like to do is to match first three letters of string and then run a for loop to load up all the classes that match the first three letters. I usually can do this by employing indexOf() method.
here is my code:
public function loadContent():void
{
ldr.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, onloadHandler);
ldr.load(req);
}
public function progressHandler(eProgress:ProgressEvent):void
{
var percent:Number = (eProgress.bytesLoaded / eProgress.bytesTotal);
trace(percent);
}
public function onloadHandler(e:Event):void
{
// THIS IS WHERE I AM TRYING TO MATCH THE STRING
var str:String = "red";
str = (str.indexOf(str));
var ref1:Class = e.currentTarget.applicationDomain.getDefinition(str) as Class
trace(ref1);
}
I would highly appreciate your help.
Thanks.
I think your problem lies in the following lines of code:
str = (str.indexOf(str));
var ref1:Class = e.currentTarget.applicationDomain.getDefinition(str) as Class
indexOf() returns the index of the first occurrence of the specified substring or -1 if the substring doesn't exist. So , you are passing a string representation of some int (either -1 or 0, 1, 2, etc) to getDefinition()... which probably isn't returning a class reference.
Assuming you have some clips named red1, red2, red3, red4 I would do something like the following:
for (var i:int=0; i < 4; i++) {
var classRef:Class = e.currentTarget.applicationDomain.getDefinition("red" + (i+1).toString()) as Class;
trace(classRef);
}
I have to assume I am missing something simple, or I am not understanding something, but I can't seem to figure this.
I have a list of strings that I add to an array, then attempt to set those values in a for-loop using data that I read in. The array gets updated, but the values the array contains do not. I also have an array of buttons that I update this same way that works great, but strings don't seem to work the same way. I have tried moving the string array to give it full scope, and still nothing... What am I missing?
public class test extends Sprite
{
// Declare a list of strings
protected var title0:String = undefined;
protected var title1:String = undefined;
protected var title2:String = undefined;
protected function onDataLoad(evt:Event):void{
var titleArray:Array = new Array(title0,title1,title2); // Array of strings
for(i=0; i<=evt.target.data.count; i++){
titleArray[i] = evt.target.data["title"+i]; // attempt to set the title values
}
}
protected function function0(e:Event):void {
trace("My title is: " + title0); // title0 is null
}
}
It has to do with how AS3 stores Array elements. You would need to explicitly set both the instance property (title1, title2, title3) and the associated array element (array[0], array[1], array[2]) to achieve what you want. Or, you could drop the instance properties (title0, title1, title2) completely and just use the array to store your values. Something like:
public class test extends Sprite
{
protected var _titleArray:Array = [];
protected function onDataLoad(evt:Event):void{
for(i=0; i<=evt.target.data.count; i++){
// set the title values
_titleArray[i] = evt.target.data["title"+i];
}
}
protected function function0(e:Event):void {
trace("My title is: " + _titleArray[0]);
}
}