-
Arrays & Loops
Inside each dataInput is a button that sets the var "varSumNum" to 1 or 2, retain or dismiss respectively. If I set varSumNum to 2 the retain button will hide the corresponding circleMC, but the circles need to toggle visible/invisible individually. This works fine on circleMC1, but I can't get it to check the rest of the dataInputs and toggle their circles.
To clarify further, it needs to check each dataInput and if 2 & 4 are set to 1 circle 2 & 4 are removed.
Code:
var allCircles:Array = [circleMC1, circleMC2, circleMC3, circleMC4, circleMC5, circleMC6, circleMC7, circleMC8, circleMC9, circleMC10];
var allInputs:Array = [dataInput1, dataInput2, dataInput3, dataInput4, dataInput5, dataInput6, dataInput7, dataInput8, dataInput9, dataInput10];
retainBtn.addEventListener(MouseEvent.CLICK, onRetain);
function onRetain(evt:MouseEvent):void {
for(var num:Number=0; num!=allCircles.length; num++){
if (allInputs[num].varSumNum == 1){
removeChild(allCircles[num]);
}
}
}
-
Are you getting any error messages, or is simply nothing happening? Are you sure that the values for dataInput2 and dataInput4 are being set properly?
I can't find anything else wrong with your code. However, I do suggest you write your loop like this:
Code:
for(var num:Number=0; num<allCircles.length; num++)
It's better practice to continue looping while your iterator is LESS than the number of desired iterations. If the iterator "num" were to somehow be set to a number GREATER than the length of your array or whatever the desired number of iterations were, it would loop infinitely.
Aside from that, if you could post more code, it might help clarify the issue.
-
Wow, stupid error on my part. Because I was still testing my mechanism I hadn't added the necessary code to the other inputs, which is why they didn't do anything. Thanks for jostling my brain. My next question is that right now clicking on the button just hides the other circles leaving the desired ones visible. this means there will be gaps. How can I move the visible circles so they appear one after the other.
Currently after pressing retainBtn the visible circleMCs look like this:
I want
-
Are all the circles of the same width? What you can do is loop through the remaining Movie Clip symbols and position them based on their widths apart from one another.
Code:
var index = 0;
... // do some looping here
myMovieClip.x = index * myMovieClip.width + someDefaultOffset;
Does this make sense?
-
Code:
var numCircles:Number = 10;
var allCircles:Array = [circleMC1, circleMC2, circleMC3, circleMC4, circleMC5, circleMC6, circleMC7, circleMC8, circleMC9, circleMC10];
var allInputs:Array = [dataInput1, dataInput2, dataInput3, dataInput4, dataInput5, dataInput6, dataInput7, dataInput8, dataInput9, dataInput10];
retainBtn.addEventListener(MouseEvent.CLICK, onRetain);
function onRetain(evt:MouseEvent):void {
for(var num:Number=0; num<numCircles; num++){
if (allInputs[num].varSumNum == 0){
allCircles[num].visible = false;
} else if (allInputs[num].varSumNum == 1){
This bit that's throwing me. I want to to check all the circles that are visible and x-offset them by 91.
col starts at 0, so the first vis circle is x=64, the second on is x=155 (64 + (91*1)), etc.
for (var col:Number=0; col<num; col++){
allCircles[num].x = 64 + (col * 91);
allCircles[num].visible = true;
}
} else if (allInputs[num].varSumNum == 2){
allCircles[num].visible = false;
} else if (allInputs[num].varSumNum == 3){
allCircles[num].visible = false;
}
}
}
-
You shouldn't need a second loop because you are already looping through and finding the circles with a varSumNum of 1.
All you should need to do is set the x for those circles which are meant to be visible. Your little offsetting equation, using the index, looks good. Take out the second loop and use "num" instead of "col" for your index.
Try that and let me know if it works.
-
Code:
} else if (allInputs[num].varSumNum == 1){
allCircles[num].x = 64 + (num * 91);
allCircles[num].visible = true;
}...
The circles don't change their x position.
-
Sorry, I've made an error. You will need to create a new array to store all the circles that are visible, THEN loop through those separately (after the initial loop). Otherwise, the circles are retaining their positions because the indices don't change. With a new loop, the index would be re-initialized to 0, and the math to figure out the x position will be correct.
Code:
var visibleCircles:Array = new Array();
...
else if (allInputs[num].varSumNum == 1) {
visibleCircles.push(allCircles[num]);
}
...
for (var i=0; i<visibleCircles.length; i++) {
visibleCircles[i].x = 64 + (i * 91);
}
This should move the circles. =)
-
That got it, and this is what my code looked like.
retainBtn.addEventListener(MouseEvent.CLICK, onRetain);
function onRetain(evt:MouseEvent):void {
// I put this here or it would only move one circle.
var visibleCircles:Array = new Array();
for(var num:Number=0; num<numCircles; num++){
if (allInputs[num].varSumNum == 0){
allCircles[num].visible = false;
} else if (allInputs[num].varSumNum == 1) {
// This sets all circles to visible or when I went to the next button, even though it might move the proper circles, you would't be able to see them since the retain button set them to invisible.
allCircles[num].visible = true;
visibleCircles.push(allCircles[num]);
for (var i=0; i<visibleCircles.length; i++) {
visibleCircles[i].x = 64 + (i * 91);
}
} else if (allInputs[num].varSumNum == 2){
allCircles[num].visible = false;
} else if (allInputs[num].varSumNum == 3){
allCircles[num].visible = false;
}
}
}
Now I also have an All Button that sets all circles to visible and in the correct order.
This is what my code looks like (it works):
Code:
var visibleCircles:Array = new Array();
for(var num:Number=0; num<numCircles; num++){
allCircles[num].visible = true;
visibleCircles.push(allCircles[num]);
for (var i=0; i<visibleCircles.length; i++) {
visibleCircles[i].x = 64 + (i * 91);
}
}
-
One more thing:
If I want to send the number of visible circles to a dynamic text box named "retainTxt", I tried the method in green but it didn't work. [object.circleMC] is returned to retainTxt
else if (allInputs[num].varSumNum == 1) {
allCircles[num].visible = true;
visibleCircles.push(allCircles[num]);
retainTxt.text = allCircles[num];
for (var i=0; i<visibleCircles.length; i++) {
visibleCircles[i].x = 64 + (i * 91);
}
}
Trying retainTxt.text = visibleCircles.length; gave a string conflict
-
You really shouldn't be looping through the visibleCircles array WITHIN the other loop. What it's doing is looping for every circle in allCircles, so as you continue to loop through allCircles, you are then looping over the same elements of visibleCircles, setting their positions for no reason. The visibleCircles loop should be done after the initial loop, otherwise you're performing unnecessary loops.
Though it's not intensive now, this would pose a problem in something more graphics-intensive if it was running all the time. It's best to practice good standards now rather than let it cripple your movie at a later date.
If this new button simply sets ALL circles to visible, you don't need to secondary array or secondary loop at all, as you know that ALL circles will be re-organized in order, since none are left out or invisible:
Code:
for(var num:Number=0; num<numCircles; num++){
allCircles[num].visible = true;
allCircles[num].x = 64 + (i * 91);
}
In your example, with the loop nested in the main loop, the total iterations would be equal to the number of circles times the number of circles times the number of circles. So, with 10 circles in the allCircles array, the loop runs 1000 times, which is very much unnecessary. A single loop through the final array is all that is necessary and cuts down the total number of loops from 1000 to 10.
For your latest question, what exactly do you want the retainTxt to display? The number of circles currently visible?
The reason you're seeing "[object .circleMC]" is because that's exactly what you're setting the text box to. The circle objects are Movie Clip objects that contain no text values. The object itself has no string value.
Code:
retainTxt.text = visibleCircles.length.toString();
You need to explicitly tell the visibleCircles.length, which is of type uint, to "become" a String. You can do this by casting the uint into a String, or by using the toString() method, which belongs to ALL objects, as everything extends the main Object class. AS3 won't do that implicitly, which is what you were doing: "implying" that it should become a String. =)
-
I wanted to make that action happen when you inputted the data, instead of clicking on the retainBtn...
On the stage I put:
Code:
var retainNum:uint = 0;
retainTxt.text = retainNum.toString();
And on each dataInput I put:
Code:
On button
MovieClip(this.parent).retainNum = MovieClip(this.parent).retainNum + 1;
MovieClip(this.parent).retainTxt.text = MovieClip(this.parent).retainNum.toString();
Does this look right. I'm going to work on moving the above code to the stage as well.
-
Here is that code moved to the stage:
Code:
for(var retainNumTxt:Number=0; retainNumTxt<numCircles; retainNumTxt++){
allInputs[retainNumTxt].retainBtn.addEventListener(MouseEvent.CLICK, onRetainNumTxt);
function onRetainNumTxt(evt:MouseEvent):void {
retainNum = retainNum + 1;
retainTxt.text = retainNum.toString();
}
}
for(var unclearNumTxt:Number=0; unclearNumTxt<numCircles; unclearNumTxt++){
allInputs[unclearNumTxt].unclearSumBtn.addEventListener(MouseEvent.CLICK, onUnclearNumTxt);
function onUnclearNumTxt(evt:MouseEvent):void {
unclearNum = unclearNum + 1;
unclearTxt.text = unclearNum.toString();
}
}
for(var staticNumTxt:Number=0; staticNumTxt<numCircles; staticNumTxt++){
allInputs[staticNumTxt].strikeBtn.addEventListener(MouseEvent.CLICK, onStrikeNumTxt);
function onStrikeNumTxt(evt:MouseEvent):void {
strikeNum = strikeNum + 1;
strikeTxt.text = strikeNum.toString();
}
}
Thanks for all you help Nidht.
-
I'm running into a conflict now that I moved that button action to the stage. The problem is that if I keep clicking on dataInput.retainBtn the retainTxt number keeps increasing. So I figured I'd just deactivate it after the click.
This code inside dataInput1 works:
Code:
retainBtn.addEventListener(MouseEvent.CLICK, onRetain);
function onRetain(evt:MouseEvent):void {
MovieClip(this.parent).retainNum = MovieClip(this.parent).retainNum + 1;
MovieClip(this.parent).retainTxt.text = MovieClip(this.parent).retainNum.toString();
retainBtn.mouseEnabled = false;
}
However, if I comment out that code and try to control it from the stage I it doesn't and I get a 101 error.
Code:
for(var retainNumTxt:Number=0; retainNumTxt<numCircles; retainNumTxt++){
allInputs[retainNumTxt].retainBtn.addEventListener(MouseEvent.CLICK, onRetainNumTxt);
function onRetainNumTxt(evt:MouseEvent):void {
retainNum = retainNum + 1;
retainTxt.text = "(" + retainNum.toString() + ")";
allInputs[retainNumTxt].retainBtn.mouseEnabled = false; // Without this line the other stuff works.
}
}
-
Why not just have the text field set to the number of elements in visibleCircles after each loop? Then you don't have to bother with changing the button code or incrementing values, as it will rely on the array length.
Also, when you're declaring functions inside the for-loop, I don't think they "survive" by the next iteration unless they are used right away, as they are event listeners that are garbage collected. You shouldn't declare functions inside of any type of loop, really.
You don't need to declare the functions if you follow my suggestion above, but if you do ever declare them in this manner in the future, you can store them TO the listener.
Code:
myButton.addEventListener(MouseEvent.CLICK,
function(event:MouseEvent):void {
trace("Test");
}
);
I don't recommend this if it's not absolutely necessary, though.
Try my suggestion by setting the text field to the number of elements in visibleCircles after each loop and let me know how that works. =)
-
Where this number is being declared, visibleCircles isn't defined yet.
visibleCircles is used in the organizational area while this is happening in the data entry area.
Code:
declare vs array
onbutton{
push to vs array
}
can i push to the array outside of my function? or shall i just declare a different array for the purpose of this function?
Also bear in mind that there are three buttons and three text fields to reflect the number of circles in each category. That's why I went with number variables.
-
You can absolutely access the array if it's outside of your function, as long as it's declared properly. Can you show me some of the scope of your code?
-
I just PMed you a link to my project file.
-
darngooddesign, this is too much code to sift through. Also, I wasn't able to run the Flash movie properly. Some of the buttons didn't seem to work and I was stuck on the first "screen".
Would you be able to just show me the scope of code where you're performing the loop and where it's failing to update the text field?
If you're unable to access the visibleCircles array from the "data portion" of your code, you need to declare it globally so that other frames can see the array and access it. This should allow you to update the text field. =)
-
The idea is that if you select retain, unclear or strike in one of the dataInputs the respective text box would reflect that. The number increases just fine, but what I'm trying to do is have decrease the number of retains if I change one from retain to unclear, for example, in a dataInput. This code works, and the check if zero works, but I'm having problems making the number decrease only if the summary status, retain/unclear/strike, has been set once before, currently it automatically decreases; otherwise, if the status has not been set before only the number would increase.
Code:
var retainNum:Number = 0;
var unclearNum:Number = 0;
var strikeNum:Number = 0;
for(var retainNumTxt:Number=0; retainNumTxt<numCircles; retainNumTxt++){
allInputs[retainNumTxt].retainBtn.addEventListener(MouseEvent.CLICK, onRetainNumTxt);
function onRetainNumTxt(evt:MouseEvent):void {
retainNum = retainNum + 1;
retainTxt.text = "(" + retainNum.toString() + ")";
if (unclearNum > 0) {
unclearNum = unclearNum - 1;
unclearTxt.text = "(" + unclearNum.toString() + ")";
}
if (strikeNum > 0) {
strikeNum = strikeNum - 1;
strikeTxt.text = "(" + strikeNum.toString() + ")";
}
}
}
for(var unclearNumTxt:Number=0; unclearNumTxt<numCircles; unclearNumTxt++){
allInputs[unclearNumTxt].unclearSumBtn.addEventListener(MouseEvent.CLICK, onUnclearNumTxt);
function onUnclearNumTxt(evt:MouseEvent):void {
unclearNum = unclearNum + 1;
unclearTxt.text = "(" + unclearNum.toString() + ")";
if (retainNum > 0) {
retainNum = retainNum - 1;
retainTxt.text = "(" + retainNum.toString() + ")";
}
if (strikeNum > 0) {
strikeNum = strikeNum - 1;
strikeTxt.text = "(" + strikeNum.toString() + ")";
}
}
}
for(var staticNumTxt:Number=0; staticNumTxt<numCircles; staticNumTxt++){
allInputs[staticNumTxt].strikeBtn.addEventListener(MouseEvent.CLICK, onStrikeNumTxt);
function onStrikeNumTxt(evt:MouseEvent):void {
strikeNum = strikeNum + 1;
strikeTxt.text = "(" + strikeNum.toString() + ")";
if (retainNum > 0) {
retainNum = retainNum - 1;
retainTxt.text = "(" + retainNum.toString() + ")";
}
if (unclearNum > 0) {
unclearNum = unclearNum - 1;
unclearTxt.text = "(" + unclearNum.toString() + ")";
}
}
}
Inside each dataInput is this code:
Code:
var varSumNum:uint = 0;
So I tried surrounding the ifs with:
Code:
if (allInputs[retainNumTxt].varSumNum > 0) {
if (unclearNum > 0) {
unclearNum = unclearNum - 1;
unclearTxt.text = "(" + unclearNum.toString() + ")";
}
if (strikeNum > 0) {
strikeNum = strikeNum - 1;
strikeTxt.text = "(" + strikeNum.toString() + ")";
}
}
But I get this error:
Code:
TypeError: Error #1010: A term is undefined and has no properties.
at jury9_fla::MainTimeline/onRetainNumTxt()
-
Just to clarify: you want to only decrease the summary status ONLY if it's been set before? I don't understand why this needs to be done. Are you going into the negatives?
-
The idea is that lets say you set three circles to retain and none to strike it would read:
Retain - 3
Strike - 0
And then if you change one of the three retains to strike it would read
Retain - 2
Strike - 1
But if you were to set an additional one, that hasn't been set before, it would be
Retain - 3
Strike - 1
To make sure there aren't negative numbers I added this check:
if (strikeNum > 0) {
But that may not be necessary if its built a different way.
-
I see your predicament, now.
I think what you need to do is re-calculate all the numbers at the end of each loop. If 3 were retained, and none were stricken out, then you know how many were retained. If, at the end of the loop, 3 were retained, but then 1 was stricken out, you have a total of 2 retained and 1 stricken out.
Basically, instead of figuring out whether you've set it before, just calculate it each time, and record the number of retained and stricken circles.
Does this make sense?