Multi arguments to CALLBACK in addEventListener in the FOR statement is difficult - actionscript-3

For loop generates Button
I wanted to generate dynamic amount button.
And wanted to recognize which one was clicked.
This is real code...
for(var col:int = 1; col <= MaxColumn; col++){
for(var row:int = 1; row <= MaxRow; row++){
makeGrid(col, row);
Button["btn_" + col + "_" + row] = new Button();
Button["btn_" + col + "_" + row].label = col + "行" + row + "列" ;
Button["btn_" + col + "_" + row].setStyle("fontSize", 10);
Button["btn_" + col + "_" + row].setStyle("cornerRadius", 0);
Button["btn_" + col + "_" + row].x = 1150 - 500/MaxRow * (row - 1);
Button["btn_" + col + "_" + row].y = 150 + 500/MaxColumn * (col - 1);
Button["btn_" + col + "_" + row].width = 500/MaxRow;
Button["btn_" + col + "_" + row].height = 500/MaxColumn;
Button["btn_" + col + "_" + row].setStyle("color", 0x191970);
Button["btn_" + col + "_" + row].setStyle("fontSize", 7);
Button["btn_" + col + "_" + row].addEventListener(MouseEvent.CLICK, onGridClick(col, row));
rootPanel.addElement(Button["btn_" + col + "_" + row]);
}
}
private function onGridClick(col, row):void{
makeGridId(col, row);
return function(event:Event):void{
var createGridDialog:CreateGridDialog = PopUpManager.createPopUp(this, CreateGridDialog, true) asCreateGridDialog;
PopUpManager.centerPopUp(createGridDialog);
createGridDialog.setGridId(globalGridId);
createGridDialog.setMaxRow(MaxRow);
createGridDialog.addEventListener(CreateGridEvent.GRID_SUBMIT, tmpSave);
}
}
public function makeGridId(col:int, row:int):void{
globalGridId = (col - 1) * MaxRow + row;
}
addEventListener's callback function is difficult
Because, in
private function onGridClick(col, row):void{
,
makeGridId(col, row);
repeated in each for blocks, so globalGridId is overwritten in the end after compile.(row = MaxRow,col = MaxColumn)
If the callback function could accept col&row directly, this issue would close.
But addEventListener's callback is difficult...
addEventListener(MouseEvent.CLICK, **onGridClick**)
The callback basically accept only one argument:MouseEvent directly, and only return void type.
I want to make globalGridId when I click, and I want to send it to where I click.
How should I do?
I Notice
please see this...
<s:Button id="Grid1" x="220" y="0" width="80" height="80" click="onSubClick(event, 0)"/>
private function onSubClick(event:MouseEvent, division:int):void {
var subSymbolDialog:SubSymbolDialog = PopUpManager.createPopUp(this, SubSymbolDialog, true) as SubSymbolDialog;
PopUpManager.centerPopUp(subSymbolDialog);
subSymbolDialog.setDivision(division);
subSymbolDialog.addEventListener(SubSymbolEvent.SUB_CLOSE, onSubClose);
}
this is weird.
click="onSubClick(event, 0)"
Why this is working?

you cannot pass arguments to listeners callback functions.
Try extends the buttonClass as follow:
package
{
public class MyButton extends Button
{
public var row:int;
public var col:int;
public function MyButton()
{
super();
}
}
}
After that you just have to fill the row and col property for the buttons.
for(var col:int = 1; col <= MaxColumn; col++){
for(var row:int = 1; row <= MaxRow; row++){
makeGrid(col, row);
Button["btn_" + col + "_" + row] = new MyButton();
Button["btn_" + col + "_" + row].col = col;
Button["btn_" + col + "_" + row].row = row;
//...
on the callback function you can retrieve it as follow:
private function onGridClick(e:Event):void
{
var b:MyButton = event.target as MyButton;
makeGridId(b.col, b.row);
var createGridDialog:CreateGridDialog = PopUpManager.createPopUp(this, CreateGridDialog, true) asCreateGridDialog;
PopUpManager.centerPopUp(createGridDialog);
createGridDialog.setGridId(globalGridId);
createGridDialog.setMaxRow(MaxRow);
createGridDialog.addEventListener(CreateGridEvent.GRID_SUBMIT, tmpSave);
}
PS: I warn you about the use of your array named Button exactly the same a s the class Button.
If you can use upercase first letters only for class name and keep lowercase first letter for variable, it's better (ex: MyClassName, myVariableName) ;)

Related

Convert a decimal number to a fraction AS3

I'm trying to get to convert the decimals to a fraction so for example, I had written something such as var _pow:int = Math.pow(base,i) and if i turned out to be a negative number it would give out a decimal (example: 3 ^ -2) and I'm currently stuck trying to find a way to turn _pow into a franction (so _pow out of a 100) so I tried to do var _pow:int = Math.pow(base,i) * 100 which should stop it from being a decimal but it's not showing in the dynamic text, and this only happens if i is negative
package{
import flash.display.*;
import flash.events.MouseEvent;
public class name_ extends MovieClip{
public function _name_(){
btn.addEventListener(MouseEvent.CLICK, input)
base.restrict = "0-9\\.\\-";
pow.restrict = "0-9\\.\\-";
answer.multiline = true;
}
private function input(event:MouseEvent):void{
var pow = pow.text;
var base = base.text;
var answerText:String = "";
if(pow > 0){
for(var i = 1; i <= pow; i++){
_pow = Math.pow(base,i);
answerText += ("\n" + base + " exposant(power) " + i + " = "+ _pow );
answer.text = answerText;
}
}else{
for(i = 1; i <= pow; i++){
var _pow:int = Math.pow(base,i) * 100
answerText += ("\n" + base + " exposant(power) " + i + " = "+ _pow );
answer.text = answerText; //Dynamic text
}
}
}
}
}
Have you tried using an "if" statement? Something like if(i <= 0){code}.
You can also try using the Math.floor(number to be rounded down); or Math.ceiling(number to be rounded up)

How do I compare a string in Flash to the name of a variable?

I'm not entirely sure if this is possible at all, but I'm trying to take a string in Flash and check to see if it is the same as the name of an already existing variable. Here is a piece of my code:
var randomNumber:int;
var randomNumberS:String;
var Mem1:String;
var Mem2:String;
randomNumber = Math.floor(Math.random()*3);
randomnumberS = ("Mem" + String(randomNumber));
TGiven.text = [the randomnumberS string, except as either the variable name Mem1 or Mem2]
Is this a possible task, and if not, is there a better way to perform this task? It would be very useful as I plan on making many more variables that start with Mem with higher and higher numbers.
It would be optimal if the variables were a member of a class or Object, to which you could evaluate whether they exist using hasOwnProperty().
For example:
var obj:Object = {
Mem1: "value1",
Mem2: "value2"
};
You could test whether obj has a property by name:
obj.hasOwnProperty("Mem1");
Applying your example using random numbers:
for (var i = 0; i < 100; i++) {
var randomNumber:int = Math.floor(Math.random() * 3);
if (obj.hasOwnProperty("Mem" + randomNumber))
trace("Mem" + randomNumber + " exists.");
else
trace("Mem" + randomNumber + " does not exist.");
}
You can also use the in keyword, such as:
"Mem1" in obj;
Using the same example:
for (var i = 0; i < 100; i++) {
var randomNumber:int = Math.floor(Math.random() * 3);
if (("Mem" + randomNumber) in obj)
trace("Mem" + randomNumber + " exists.");
else
trace("Mem" + randomNumber + " does not exist.");
}

ActionScript 3 Public MovieClip

I've dynamically created a menu using MovieClips as menu items inside a public function, but I also need to access these MovieClips on the timeline, however using similar code as below works for initially creating them, but not accessing them on the timeline.
I'm attempting to access functions and child MovieClips inside each menu items.
public function createMenuFunction():void {
var buttonMC:menuButtonMC;
for (var i:uint = 1; i <= totalTopicsI; i++) {
buttonMC = new menuButtonMC();
menuMC.contentMC.addChild(buttonMC);
buttonMC.name = 'button' + i + 'MC';
menuMC.contentMC.getChildByName('button' + i + 'MC').UI();
menuMC.contentMC.getChildByName('button' + i + 'MC').y = (i - 1) * 70;
menuMC.contentMC.getChildByName('button' + i + 'MC').updateTextFunction(textO['Topic ' + i]);
menuMC.contentMC.getChildByName('button' + i + 'MC').addEventListener(MouseEvent.CLICK, updateCurrentTopicFunction);
trace('Menu ' + i + ': ' + textO['Topic ' + i]);
}
}
}
For example, the following line of code works inside this function, but not on the timeline:
menuMC.contentMC.getChildByName('button' + i + 'MC').UI();
Any suggestions are welcome.
Try this:
public var menuData:Array = new Array();
for (var i:uint = 1; i <= totalTopicsI; i++) {
menuData[i] = new menuButtonMC();
menuMC.contentMC.addChild(menuData[i]);
menuData[i].name00 = 'button' + i + 'MC';
menuMC.contentMC.getChildByName('button' + i + 'MC').UI();
menuMC.contentMC.getChildByName('button' + i + 'MC').y = (i - 1) * 70;
menuMC.contentMC.getChildByName('button' + i + 'MC').updateTextFunction(textO['Topic ' + i]);
menuMC.contentMC.getChildByName('button' + i + 'MC').addEventListener(MouseEvent.CLICK, updateCurrentTopicFunction);
trace('Menu ' + i + ': ' + textO['Topic ' + i]);
}
This way you will save all your buttons and properties. (use name00 not name)

Removing just a set of instances of an object from the scene

I have a problem in ActionScript 3 with a project where I am to output a bunch of data in a diagram and as pure text. This is not the problem, though. The problem is that when the user changes the type of data he wants shown. I would then remove the currently shown columns in the diagram, and add new ones. But my code removes ALL columns, so that there is no diagram at all!
I've done it all in Flash CS5, and the columns are instances of an object I made (a rectangle) which I just add to the stage. All the instances are added to the container "container." When I want to remove them, and add new ones I use:
var container = new Sprite(); // The container for my diagram
function emptyContainer() {
if (container.numChildren > 0) {
container.removeChildAt(0);
}
}
Which works.
I have switch statement that adds the different columns based on user-input. The name of the object (the rectangle) is "soyle." The name of the instances is "stolpe"
(I am norwegian by the way, so that's the deal with those weird words)
function fChange(event:Event) {
textToBeReturned = "";
switch (treCbox.selectedItem.label) {
case "Furu":
for (var a = 1; a < table.length; a++ ){
textToBeReturned += "I år: " + table[a][0] + " - " + table[a][1] + " millioner trær." + "\n";
// Diagram
var stolpe = new soyle;
stolpe.width = table[a][1];
stolpe.x = 20;
stolpe.y = 100 + (a * 30);
container.addChild(stolpe);
// Description for the columns
var textbox = new TextField;
textbox.text = "År " + table[a][0];
textbox.x = stolpe.width + 30;
textbox.y = stolpe.y;
container.addChild(textbox);
}
break;
case "Gran":
for (var b = 1; b < table.length; b++ ){
textToBeReturned += "I år: " + table[b][0] + " - " + table[b][2] + " millioner trær." + "\n" ;
var stolpe = new soyle;
stolpe.width = table[b][1];
stolpe.x = 20;
stolpe.y = 100 + (b * 30);
container.addChild(stolpe);
// Description for the columns
var textbox = new TextField;
textbox.text = "År " + table[b][0];
textbox.x = stolpe.width + 30;
textbox.y = stolpe.y;
container.addChild(textbox);
}
break;
case "Lauvtre":
for (var c = 1; c < table.length; c++ ){
textToBeReturned += "I år: " + table[c][0] + " - " + table[c][3] + " millioner trær." + "\n" ;
var stolpe = new soyle;
stolpe.width = table[c][1];
stolpe.x = 20;
stolpe.y = 100 + (c * 30);
container.addChild(stolpe);
// Description for the columns
var textbox = new TextField;
textbox.text = "År " + table[c][0];
textbox.x = stolpe.width + 30;
textbox.y = stolpe.y;
container.addChild(textbox);
}
break;
}
txtReturn.text = textToBeReturned;
};
I wonder where to place my function for removing all children, to remove just those children that were added earlier. To matter where I place the function (at the start of fChange, at the beginning of each case) there is NO diagram shown, either new or old.
There is of course an array with the data, but I do not post it as it is irrelevant.
Thank you for your time, and in advance for your help! :)
Couple of problems here. I assume you want to remove all children from your container MC before adding new children inside your switch. (Tip for next time, try to post only the code your working with. The switch statement here is large and overwhelming. It's also not really relevant)
Your function emptyContainer does not actually remove all children, it only removes one at index 0. This needs to be inside of a loop.
function emptyContainer() {
while (container.numChildren > 0) { //changed the if to a while. This will run until there are no children left in container
container.removeChildAt(0);
}
}
You're going to want to call this first thing inside of your fChanged function
function fChange(event:Event) {
emptyContainer()
/* rest of function */
}
try this out and let me know how it works.

Convert seconds to minutes and seconds in Actionscript 3

I'm working with the youtube API and I'm getting the current time on the video as seconds.
What I want to do is to convert them into this: MM:SS
I've tried to google and try different things by myself but nothing seemed to work and be efficient.
I'll be glad to see how it can be done in a good and efficient way thanks in advance!
Something like:
var formattedTime =
(Math.floor(seconds/60)) + ":" + // minutes
(seconds % 60 >= 10 ? "": "0") + // padding for seconds if needed
(seconds % 60)); // seconds
here is a little class I use all the time just for what you need. I've also added a timecodes to seconds method. Simply use it like Timecodes.secondsToTimecode(634); which will output 00:10:34
package com.ronnieswietek.utils
{
public class Timecodes
{
public function Timecodes()
{
}
public static function timecodeToSeconds(tcStr:String):Number
{
var t:Array = tcStr.split(":");
return (t[0] * 3600 + t[1] * 60 + t[2] * 1);
}
public static function secondsToTimecode(seconds:Number):String
{
var minutes:Number = Math.floor(seconds/60);
var remainingSec:Number = seconds % 60;
var remainingMinutes:Number = minutes % 60;
var hours:Number = Math.floor(minutes/60);
var floatSeconds:Number = Math.floor((remainingSec - Math.floor(remainingSec))*100);
remainingSec = Math.floor(remainingSec);
return getTwoDigits(hours) + ":" + getTwoDigits(remainingMinutes) + ":" + getTwoDigits(remainingSec);
}
private static function getTwoDigits(number:Number):String
{
if (number < 10)
{
return "0" + number;
}
else
{
return number + "";
}
}
}
}
var timeStr:String;
//Video's length >= 1 hour
if( seconds >= 60*60 ){
//Format-> H:MM:SS
timeStr = (""+Math.floor(seconds/(60*60))) + //Hours
":"+
("0"+Math.floor((seconds%(60*60))/60)).substr(-2)+ //Minutes
":"+
("0"+(seconds%60)).substr(-2); //Seconds
}else{
//Format-> MM:SS
timeStr = ("0"+Math.floor(seconds/60)).substr(-2)+ //Minutes
":"+
("0"+(seconds%60)).substr(-2); //Seconds
}
Something a little easier to read to get your head around it:
var seconds:int = 200;
var minutes:int = 0;
while(seconds >= 60)
{
seconds -= 60;
minutes ++;
}
trace(minutes, seconds);
The leading zeros part can be done like so:
var secStr:String = String(seconds);
var minStr:String = String(minutes);
secStr = (secStr.length == 1) ? "0" + secStr : secStr;
minStr = (minStr.length == 1) ? "0" + minStr : minStr;
trace(minStr + ":" + secStr);