Writing and Understanding Loop Conditions

For the rest of this lesson, we'll focus on the while loop. The actions within this type of loop are performed continuouslyas long as the condition evaluates to true. For example:


var i:Number = 0;

while (i < 10) {

  // perform these actions

}


The condition in the loop is i < 10. This means that as long as the value of i is less than 10, the statement is true and the actions within the loop are repeated. However, the looping statement is missing a key ingredient; it doesn't have a means by which the condition eventually becomes false. Without this functionality, the loop could continue forever, and in the real world endless loops cause applications to freeze. Flash can't do anything else until the looping statement completes its job. To prevent an endless loop in the example, the value of i must be incremented so that its value eventually equals 10, at which point the condition proves false and the loop stops.

You can use the increment operator (++) to handle incrementing a loop. Here's an example:


var i:Number = 0;

while (i < 10) {

  //perform these actions

  ++i

}


Incrementing the value of i causes the loop to perform 10 iterations. The value of i is initially set to 0. However, with each loop that value increases by 1. On the tenth loop, i = 10, which means that i < 10 is no longer true and the loop halts. Here's a shortcut that accomplishes the same goal:


var i:Number = 0;

while (++i < 10) {

  // perform these actions

}


This loop performs 9 iterations. The value of i is initially set to 0. However, with each iteration (including the first), that value is incremented by 1 within the conditional statement of the loop itself. On the tenth loop, i = 10, which means that i < 10 is no longer true, and the loop halts.

graphics/09inf04.gif

You can also use the decrement operator with a loop, which might look something like this:


var i:Number = 10;

while (--i > 0) {

  // perform these actions}

}


Alternatively, you can write this script using a for loop as follows:


for (var i:Number = 10; i>0; --i) {

  // perform these actions

}


The condition in a loop doesn't have to depend on an incremented value; it can be any sort of condition. It can also be the result of a function call that returns a value of true or false, like this:


while (someFunction()) {

  // perform these actions

}


In the following exercise, you create a drop-down list using a while loop.

  1. Open pictureShow1.fla in the Lesson09/Assets folder.

    The main timeline includes three layers: Background, Dynamic Elements, and Actions. The Actions layer contains all the ActionScript for this project. Not surprisingly, the Background layer contains the project's background graphic. The Dynamic Elements layer includes four movie clip instances: three above the stage that contain pictures, and an instance on the stage named dropDownList_mc that contains a button named menu_btn and another movie clip instance named item_mc. The item_mc instance is made up of two elements: a dynamic text field with an instance name of itemName_txt, and a button that appears as a semitransparent white box and has an instance name of list_btn. The itemName_txt instance plays an important part in this exercise because it will be duplicated in a process to generate clickable menu choices dynamically.

    graphics/09inf05.gif

  2. With the Actions panel open, select the frame in the Actions layer and add these two lines:

    
    var buttonNames:Array = ["Paris", "New York", "London"];
    
    dropDownList_mc.item_mc._visible = false;
    
    

    The first action in this script creates an array named buttonNames, which contains names that will appear in the drop-down list. The second action makes the item_mc movie clip instance invisible. (Because you'll be using the item_mc movie clip instance only as a template for creating duplicates, the instance itself doesn't need to be visible.)

  3. Add this function after the script you just added in Step 2:

    
    function populateList() {
    
      var spacing:Number = dropDownList_mc.item_mc._height + 2;
    
      var numberOfButtons:Number = buttonNames.length;
    
    }
    
    

    When complete, this function duplicates the item_mc movie clip instance, aligns the duplicates under the Menu button, and changes the text displayed in the duplicated instances.

    Because this function dynamically generates the list of choices, we need to consider vertical spacing between the list-choice buttons in the script. In its first action, this function creates a variable named spacing. This variable's value is determined by retrieving the height of the item_mc movie clip instance and adding 2 to that value. The loop uses the resulting value to set the spacing between the top of one duplicated movie clip instance and the top of the next movie clip instance underneath.

    graphics/09inf06.gif

    The numberOfButtons variable gets its value from the length of the buttonNames array (that is, the number of elements that the array contains). The while loop (added in the next step) used to build the drop-down list will use value of numberOfButtons to determine the number of iterations to perform. Because the length of buttonNames is currently 3 (the array contains three city names), the loop we set up will loop three times, creating a list button with each loop. If we placed another city's name in the array, the value of the length property of buttonNames would be 4, which means that the loop would adjust accordingly and create four list buttons.

  4. Add this script to the populateList() function after the last line of code in the function:

    
    var i:Number = -1;
    
      while (++i < numberOfButtons) {
    
      var name:String = "item" + i;
    
      dropDownList_mc.item_mc.duplicateMovieClip(name, i);
    
      dropDownList_mc[name].itemName_txt.text = buttonNames[i];
    
      dropDownList_mc[name]._x = 0;
    
      dropDownList_mc[name]._y = i * spacing;
    
      dropDownList_mc[name].pictureID = i + 1;
    
      dropDownList_mc[name].list_btn.onRelease = function() {
    
        itemClicked(this._parent.pictureID);
    
      };
    
    }
    
    

    You've just scripted a while loop that duplicates the item_mc movie clip instance as needed for the drop-down list, positions the duplicates, and gives each duplicate a name to display.

    Before the loop is defined, the script creates a local variable named i and assigns it the value -1.

    NOTE

    The letter i is commonly used as the name of an incremental variable in loops.

    The next line of the script starts the while loop and defines the condition that makes the loop continue working. It states, "As long as the incremented value of i is less than the value of numberOfButtons, keep looping." When the loop begins, i has a value of 0; although i is initially assigned a value of -1, the increment operator (++) increments its value by 1 prior to each loop, including the first. Because numberOfButtons has a value of 3 (as discussed in Step 3), and i is incremented by 1 with each iteration, the condition that this loop analyzes will prove false after three iterations.

    The first action in the script creates a variable called name, which is assigned a dynamic value based on the current value of i. Because that value is incremented with each iteration of the loop, name is assigned a value of item0 in the first iteration of the loop; item1 in the second iteration, and so on. The next line uses the duplicateMovieClip() method to create a new instance of the item_mc movie clip. The two parameters in this method are separated by a comma: the first assigns an instance name to the duplicate that's created, and the other parameter assigns the duplicate a depth (think of this as the stacking order). As defined in the method's parenthetical syntax, we use the current value of the name variable (dynamically set with the previous action) as the instance name of the duplicate, and we use the current value of i to set the depth.

    For the next four actions in the loop, dropDownList_mc[name] references the name of the duplicate just created. As discussed in Lesson 6, "Creating and Manipulating Data," this special syntax provides a dynamic way of referencing a variable name in ActionScript. In the loop's first iteration, name is assigned a value of item0. With the first iteration of the loop, these lines of script could be rewritten this way:

    
    dropDownList_mc.item0.itemName_txt.text = buttonNames[i];
    
    dropDownList_mc.item0._x= 0;
    
    dropDownList_mc.item0._y = i * spacing;
    
    dropDownList_mc.item0.pictureID = i + 1;
    
    

    With each loop iteration, the value of name is updated and used to name the duplicate created. These actions reference the duplicated instance.

    Each duplicate contains the two elements included in the original item_mc movie clip instance: the white button named list_btn and the dynamic text field named itemName_txt. The third line in the looping statement,

    
    dropDownList_mc[name].itemName_txt.text = buttonNames[i];
    
    

    sets the value of itemName_txt.text (and the text that will be displayed over the button) in the duplicated instance. That value is set by using the current value of i to reference a string in the buttonNames array created in Step 2. In the loop's first iteration, the value of i is 0, which means that the value of itemName_txt.text would be buttonNames[0], or the first element in that array, the text string "Paris".

    The next two lines of script position the duplicated instance on the stage. As shown in the script, each of the duplicates will have the same x position, 0. The y position of the duplicate is dynamic, and is determined by multiplying the variable i by spacing. This action has the effect of spacing the duplicates an equal distance apart vertically.

    After executing the two lines of script that position the movie clip, the loop creates a variable named pictureID inside the duplicated instance. The value assigned to the variable is based on the current value of i + 1. This variable will not be used until the next exercise, where it will be employed to determine the set of pictures to display.

    graphics/09inf07.gif

    Finally, this loop adds an onRelease event handler to the list_btn button in each newly duplicated movie clip. When released, the button calls a function named itemClicked() on the main timeline and passes in the pictureID variable. You'll add the itemClicked() function in the next exercise.

    The call to the itemClicked() function within the onRelease event handler references the pictureID variable with the following script:

    
    this._parent.pictureID;
    
    

    To grasp this syntax concept, it's important to understand the path between the pictureID variable and the list_btn button. The pictureID variable exists within the duplicated movie clip instance that also contains list_btn. The pictureID data exists not within the button (button instances can't hold data), but within the button's parent, which is the duplicated movie clip instance. For the button to reference a variable that exists in its parent, the button must step back one level (_parent) to get to the pictureID variable: hence this._parent.pictureID.

  5. Add this script after the populateList() function:

    
    dropDownList_mc.menu_btn.onRelease = function() {
    
      populateList();
    
    };
    
    

    When the Menu button is released, the populateList() function is called and a set of list buttons appears. (The list buttons were created dynamically by the function.)

  6. Choose Control > Test Movie. Click the Menu button to test your script.

    When you click the Menu button, the populateList() function is called, and several duplicates of the item_mc movie clip instance are created, positioned, and populated with textall nearly instantaneously.

  7. Close the test movie and save your work as pictureShow2.fla.

    You created a drop-down list using a while loop. In the next exercise, you put this list to work by making something happen when you click a list item.