using concatenation in getUrl during loop? - actionscript

I would like to write Actionscript loop that involves "getURL". However, from what I can see getURL does not allow concatenation of variable names?
I have variables textholder0, textholder1, textholder2 that have movieclip names as values and link0, link1, link2 that have website addresses as values.
I can use this["textholder" + 0].onRelease but getURL("link"+ 0) gives "undefined"
textholder0.onRelease = function()
{
getURL(link0);
}
textholder1.onRelease = function()
{
getURL(link1);
}
textholder2.onRelease = function()
{
getURL(link2);
}
Any way to do this so I can create a loop for the above?
Here is a test. Unfortunately, it still gives me "undefined/" for the URL. To keep it simple I created three movie clips, with instances textholder0, textholder1, textholder2. Put a loop on the main timeline.
var links:Array = ["http://www.google.ca", "http://www.google.com", "http://www.google.ru"];
for(var i:Number=0; i<links.length; i++){
this["textholder" + i].linkURL = links[i];
this["textholder" + i].onRelease = function() {
getURL(linkURL);
}
}
Here is output from debugger window
Variable _level0.links = [object #1, class 'Array'] [
0:"http://www.google.ca",
1:"http://www.google.com",
2:"http://www.google.ru" ]
Variable _level0.i = 3
Movie Clip: Target="_level0.textholder0"
Variable _level0.textholder0.linkURL = "http://www.google.ca"
Variable _level0.textholder0.onRelease = [function 'onRelease']
Movie Clip: Target="_level0.textholder1"
Variable _level0.textholder1.linkURL = "http://www.google.com"
Variable _level0.textholder1.onRelease = [function 'onRelease']
Movie Clip: Target="_level0.textholder2"
Variable _level0.textholder2.linkURL = "http://www.google.ru"
Variable _level0.textholder2.onRelease = [function 'onRelease']
I am starting to think that you can not use onRelease within a loop at all.

getURL("link"+ 0) will try to go to a URL "link0", since "link"+ 0 will be concatenated to the string "link0", and not get the value of link0. But you can try doing this:
getURL(this["link" + 0]);
The difference, and the mechanism of the bracket notation, is that you can reference a property of an object in two ways - using dot notation, like this.link0, or the bracket notation, this["link0"]. But it has to be expressed as an object property, just saying "link" + 0 anywhere, like in getURL("link"+ 0) won't give a reference to link0.

ok, so I think the problem with the loop here is that it was incrementing "i" variable before any of the buttons were clicked.
http://www.senocular.com/flash/tutorials/faq/#loopfunctions
Senocular.com says "you need to define a new, unique variable to represent that value at the time of function creation and have the function reference that value"
So the loop goes as following
var links:Array = ["http://www.google.ca", "http://www.google.com", "http://www.google.ru"];
var curr_button;
for(var i=0; i<=links.length; i++){
curr_button = this["textholder"+i];
//note creation of an extra variable "num" below to store the temp number
curr_button.num = i;
curr_button.onRelease = function() {
getURL(links[this.num]);
}
}

Related

Loop over a function and store as list

I have the following function that clicks a checkbox with splash:
local get_dimensions = splash:jsfunc([[
function () {
for i=1, 5 do
var rect = document.querySelector(string.format('checkbox[number="%d"]'), i)
.getClientRects()[0];
return {[rect.left]: rect.top};
end
}
]])
However, I cannot store a list from the loop into a single variable like rect, so how do I store a list into a variable, and when I return it, it should return a list of values?
Something similar to python, ie.:
def stuff():
rect = []
for i in range(5):
rect.append([...])
return rect
Let's take at your code.
You call splash:jsfunc. This function converts JavaScript into a Lua callable. It takes a single argument. A string that defines a JavaScript function.
yourString = [[
function () {
for i=1, 5 do
var rect = document.querySelector(string.format('checkbox[number="%d"]'), i).getClientRects()[0];
return {[rect.left]: rect.top};
end
}
]]
This looks like some weird mix of Lua and JavaScript.
This is how a JavaScript for loop looks like
for (let i = 0; i < 10; i++) {
// some code
}
This is how a Lua numeric for loop looks like:
Also what's the point of using return in a loop without any condition? This will be executed after the first cycle with i = 1. That's probably not what you want.
So fix the loop so it is JavaScript. Create a Object or Array and return that after the loop is complete.

How to use string in path to object?

I need to use string in path to object.
var nameOfTrails:String = "trail"+this.getDepth();
_parent.createEmptyMovieClip(nameOfTrails,this.getDepth()+1);
_parent.nameOfTrails.beginFill(FillColor,FillAlpha);
How to do this in ActionScript 2.0?
In you case you could access instance you created like this:
_parent[nameOfTrails]
The point is that you can access an object using string with his name by searching proper object for property with that name.
In your example you creating variable with id of nameOfTrails value inside some object which relate to your current code scope as parent, and put reference to newly created MovieClip inside this variable. So now, object referenced by _parent have property named for example 'trail0' (by the way this.getDepth() is not so smart thing to do then you creating objects in other scope). All you need to do now is access that property using classical 'give me property of that object by his key' style - obj['propertyName'] and voila.
You can do that like this :
for(var i:Number = 0; i < 3; i++){
var movie_clip:MovieClip = this.createEmptyMovieClip('movie_clip_' + i, i);
movie_clip._y = i * 22;
var text_field:TextField = movie_clip.createTextField('text_field', 0, 0, 0, 120, 18);
text_field.text = 'movie clip : ' + i;
}
var j:Number = 2;
trace(this['movie_clip_' + j].text_field.text); // gives : movie clip : 2
trace(eval('movie_clip_' + 1).text_field.text); // gives : movie clip : 1
For more details, take a look on the eval function.
Hope that can help.

What grammar is this?

I have to parse a document containing groups of variable-value-pairs which is serialized to a string e.g. like this:
4^26^VAR1^6^VALUE1^VAR2^4^VAL2^^1^14^VAR1^6^VALUE1^^
Here are the different elements:
Group IDs:
4^26^VAR1^6^VALUE1^VAR2^4^VAL2^^1^14^VAR1^6^VALUE1^^
Length of string representation of each group:
4^26^VAR1^6^VALUE1^VAR2^4^VAL2^^1^14^VAR1^6^VALUE1^^
One of the groups:
4^26^VAR1^6^VALUE1^VAR2^4^VAL2^^1^14 ^VAR1^6^VALUE1^^
Variables:
4^26^VAR1^6^VALUE1^VAR2^4^VAL2^^1^14^VAR1^6^VALUE1^^
Length of string representation of the values:
4^26^VAR1^6^VALUE1^VAR2^4^VAL2^^1^14^VAR1^6^VALUE1^^
The values themselves:
4^26^VAR1^6^VALUE1^VAR2^4^VAL2^^1^14^VAR1^6^VALUE1^^
Variables consist only of alphanumeric characters.
No assumption is made about the values, i.e. they may contain any character, including ^.
Is there a name for this kind of grammar? Is there a parsing library that can handle this mess?
So far I am using my own parser, but due to the fact that I need to detect and handle corrupt serializations the code looks rather messy, thus my question for a parser library that could lift the burden.
The simplest way to approach it is to note that there are two nested levels that work the same way. The pattern is extremely simple:
id^length^content^
At the outer level, this produces a set of groups. Within each group, the content follows exactly the same pattern, only here the id is the variable name, and the content is the variable value.
So you only need to write that logic once and you can use it to parse both levels. Just write a function that breaks a string up into a list of id/content pairs. Call it once to get the groups, and then loop through them calling it again for each content to get the variables in that group.
Breaking it down into these steps, first we need a way to get "tokens" from the string. This function returns an object with three methods, to find out if we're at "end of file", and to grab the next delimited or counted substring:
var tokens = function(str) {
var pos = 0;
return {
eof: function() {
return pos == str.length;
},
delimited: function(d) {
var end = str.indexOf(d, pos);
if (end == -1) {
throw new Error('Expected delimiter');
}
var result = str.substr(pos, end - pos);
pos = end + d.length;
return result;
},
counted: function(c) {
var result = str.substr(pos, c);
pos += c;
return result;
}
};
};
Now we can conveniently write the reusable parse function:
var parse = function(str) {
var parts = {};
var t = tokens(str);
while (!t.eof()) {
var id = t.delimited('^');
var len = t.delimited('^');
var content = t.counted(parseInt(len, 10));
var end = t.counted(1);
if (end !== '^') {
throw new Error('Expected ^ after counted string, instead found: ' + end);
}
parts[id] = content;
}
return parts;
};
It builds an object where the keys are the IDs (or variable names). I'm asuming as they have names that the order isn't significant.
Then we can use that at both levels to create the function to do the whole job:
var parseGroups = function(str) {
var groups = parse(str);
Object.keys(groups).forEach(function(id) {
groups[id] = parse(groups[id]);
});
return groups;
}
For your example, it produces this object:
{
'1': {
VAR1: 'VALUE1'
},
'4': {
VAR1: 'VALUE1',
VAR2: 'VAL2'
}
}
I don't think it's a trivial task to create a grammar for this. But on the other hand, a simple straight forward approach is not that hard. You know the corresponding string length for every critical string. So you just chop your string according to those lengths apart..
where do you see problems?

How to dynamically generate variables in Action Script 2.0

I have a for loop in action script which I'm trying to use to dynamically create variable.
Example
for( i = 0 ; i &lt 3 ; i++)
{
var MyVar+i = i;
}
after this for loop runs, i would like to have 3 variables named MyVar1, MyVar2, MyVar3. I know the code above will give you a syntax error, but that is just to illustrate what I am trying to do. Any takers?
The primary reason i'm doing this is because I'm having scope problems noted here in this other unanswered Action Script question: How to pass variables into inline functions in Action Script 2
Thanks!
I could be wrong (I haven't done AS2 for a long while), but I think you can do this using array syntax:
for( i = 0 ; i < 3 ; i++)
{
this["myVar"+i] = i;
}
and then for variable access:
var foo = this["myVar0"] //etc
First answer is correct, but if you make the class dynamic (ie. new members can be created dynamically) ...
dynamic class ClassName { // etc. }
... then you can reference the variable in normal syntax:
var foo = this.myVar0;
You won't be able to access the variable at all without 'this' whether the class is dynamic or not.

Is there a better way to get hold of a reference to a movie clip in actionscript using a string without eval

I have created a bunch of movie clips which all have similar names and then after some other event I have built up a string like:
var clipName = "barLeft42"
which is held inside another movie clip called 'thing'.
I have been able to get hold of a reference using:
var movieClip = Eval( "_root.thing." + clipName )
But that feels bad - is there a better way?
Movie clips are collections in actionscript (like most and similar to javascript, everything is basically key-value pairs). You can index into the collection using square brackets and a string for the key name like:
_root.thing[ "barLeft42" ]
That should do the trick for you...
The better way, which avoids using the deprecated eval, is to index with square brackets:
var movieClip = _root.thing[ "barLeft42" ]
But the best way is to keep references to the clips you make, and access them by reference, rather than by name:
var movieClipArray = new Array();
for (var i=0; i<45; i++) {
var mc = _root.thing.createEmptyMovieClip( "barLeft"+i, i );
// ...
movieClipArray.push( mc );
}
// ...
var movieClip = movieClipArray[ 42 ];
You can use brackets and include variables within them... so if you wanted to loop through them all you can do this:
for (var i=0; i<99; i++) {
var clipName = _root.thing["barLeft"+i];
}

Resources