Building Continuous-Feedback Buttons

It's sometimes useful to have actions executed continually while a button is being clicked. A button set up to enable continuous execution is known as a continuous-feedback buttonand a scroll button (the focus of this exercise) is a perfect example.

If you wanted to scroll through a list of information in a window, you would quickly become frustrated if you had to click a button every time you wanted to make the information scroll up or down. Far less frustrating is a button that needs to be clicked just once to scroll continuously until the button is released. In Flash, you can create this type of functionality by using the onEnterFrame clip event with a button, as we'll soon demonstrate.

In this exercise, you'll add scrolling buttons to the list you built in the previous exercises.

  1. Open scrollingList2.fla.

    In this exercise, you'll add ActionScript to Frame 1 of the Actions layer in the main timeline, to the scroll buttons themselves, and to the clips that contain the scroll buttons. You'll build the function that performs the actual scrolling; then you'll add the commands to the required areas so that the function is called.

    Remember that there's a movie clip instance called list_mc inside the display_mc clip. All the attached infoBar movie clip instances that we create will exist inside the list_mc instance. We'll set up our scrolling function to move the list_mc movie clip instance up and down to achieve the effect of scrolling through the list of items.

    NOTE

    When we use the term scrolling in this exercise, we're talking about increasing or decreasing the _y property value of the list_mc movie clip instance to move it up or down onscreen.

  2. With the Actions panel open, select Frame 1 of the Actions layer and then add the following line of script just below the line that creates the list array:

    
    var startingY:Number = display_mc.list_mc._y;
    
    

    With scrolling, you must establish maximum and minimum vertical locations (y) to which the list can scroll: these represent the boundaries for scrolling (or continued vertical movement). In any application where scrolling is allowed, you're prevented from scrolling beyond the top or bottom borders of the document. The preceding line of script is used to establish the edge of one of these vertical boundaries: the movie clip instance list_mc, which will contain the list of attached instances, should not continue scrolling if its y position exceeds the starting y position. In a moment, we'll use the value of the startingY variable to control scrolling.

    graphics/15inf11.gif

  3. To set part of the other scrolling boundary, add the following line to Frame 1, just below the line of script you added in Step 2:

    
    var bottom:Number = 120;
    
    

    As mentioned in Step 2, the highest possible y value that the list_mc movie clip instance can scroll to is its starting position. The bottom variable defined in this step will be used as an offset to the upward extreme of scrolling so that the bottom of the list doesn't go all the way to the top of the window. The reasons for using this variable will become more obvious in coming steps.

  4. Define the following variable just after the line of script added in Step 3:

    
    var direction:String;
    
    

    graphics/15inf12.gif

    The function that handles scrolling, which you'll start setting up in the next step, will scroll the list either up or down based on the value of the direction variable. This variable will be set from one of two separate button events that will be created later in this exercise.

  5. Start defining the function that will be used to scroll the movie clip instance. To do this, add the following ActionScript to Frame 1, just below the buildList() function definition:

    
    function scroll () {
    
      var speed:Number = 10;
    
    }
    
    

    Soon, we'll set up our project to call this function via an onEnterFrame clip event on the main timeline if one of two scrolling buttons is being clicked. One of the scroll buttons will be used to scroll up; the other will be used to scroll down.

    The variable speed is just thatthe scrolling speed. When the scroll button is held down, the list_mc instance will scroll up or down by the value of speed in every frame.

    NOTE

    There's nothing magic about the number 10; you can adjust it to anything that looks good.

  6. Add the following if/else if statement inside the function definition, just below var speed:Number = 10;:

    
    if (direction == "up") {
    
    }else if (direction == "down") {
    
    }
    
    

    The direction variable is used to store a string value of "up" or "down". The conditional statement in this step determines how the scroll() function works, based on that value. Over the next few steps, you'll be adding actions to this conditional statement so that if the intended scrolling direction is up, a certain list of actions will be performed; if the scrolling direction is down, another set of actions will be performed.

  7. Nest the following if/else statement in the "up" leg of the if/else if statement you just entered in Step 6:

    
    if (display_mc.list_mc._y - speed + display_mc.list_mc._height > (startingY + bottom)) {
    
      display_mc.list_mc._y -= speed;
    
    } else {
    
      display_mc.list_mc._y = (startingY + bottom) - display_mc.list_mc._height;
    
    }
    
    

    Because this statement is nested within the "up" leg of the previous statement, it's evaluated if the value of direction is up.

    The first part of the expression in the statement is used to determine what the bottom position of the list_mc instance would be if it were to move 10 pixels upward. The expression does this by looking at the list_mc instance's current y position and then subtracting the value of speed and adding the height of the instance. That bottom position of the instance is then compared against one of the scrolling boundaries, as established by adding the value of bottom to the value of startingY. If moving the list_mc instance up doesn't cause the bottom of the instance to exceed the boundary, the first action in the statement is executed and the list is moved up. If moving the instance up would make it exceed the boundary, however, the else part of the statement would be executed, simply snapping its vertical position to the maximum allowable.

    graphics/15inf13.gif

    If you're confused, don't worry: Let's look at an example to see how this technique works. For this demonstration, we'll assume the following values:

    
    var speed:Number = 10
    
    var startingY:Number = 100
    
    var bottom:Number = 120
    
    display_mc.list_mc._height = 400 //vertical height of the list instance
    
    display_mc.list_mc._y = -165 //current vertical position of the list instance
    
    

    Using these values, the expression in the if statement is evaluated as follows:

    
    if (-165 - 10 + 400 > (100 + 120))
    
    

    which further evaluates to:

    
    if (225 > 220)
    
    

    In this case, 225 is greater than 220, so the following action is executed:

    
    display_mc.list_mc._y -= speed;
    
    

    This moves the list_mc instance up 10 pixels, and its y position now equals 175. If the statement were evaluated again, it would look like this:

    
    if (-175 - 10 + 400 > (100 + 120))
    
    

    which further evaluates to:

    
    if (215 > 220)
    
    

    In this case, 215 is less than 220, so the following action (the else part of the statement) is executed:

    
    display_mc.list_mc._y = (startingY + bottom) - display_mc.list_mc._height;
    
    

    Here, the list_mc instance's y position is set based on the value of the expression to the right of the equals sign. Using the values established for this example, this expression would be evaluated as follows:

    
    (startingY + bottom) - display_mc.list_mc._height
    
    

    which further evaluates to:

    
    (100 + 120) - 400
    
    

    which further evaluates to:

    
    220 - 400
    
    

    which further evaluates to:

    
    -180
    
    

    This means that the list_mc instance would be snapped into a vertical position of 180, placing the bottom of the instance at the edge of the upper scrolling boundary. This statement is set up so that the bottom of the list_mc instance never scrolls beyond this point.

    NOTE

    This can be a tricky concept: You may want to review this information several times.

    Next, let's set up the function to handle downward scrolling.

  8. Nest this if/else statement in the "down" portion of the outer if/else if statement:

    
    if (display_mc.list_mc._y + speed < startingY) {
    
      display_mc.list_mc._y += speed;
    
    } else {
    
      display_mc.list_mc._y = startingY;
    
    }
    
    

    graphics/15inf14.gif

    This part of the statement serves to scroll the movie clip instance downward. Similar to the statement in Step 7, this statement looks to see whether moving the list_mc instance down by the value of speed:

    
    display_mc.list_mc._y + speed
    
    

    will keep the instance within the lower scrolling boundary (startingY). If so, the first action in the statement is executed, moving the instance down; otherwise (else), if moving the instance by the value of speed causes it to exceed the lower boundary, the action within the else part of the statement is executed, snapping the instance into vertical alignment with the lower boundary.

    Now that you've defined this function, it's time to begin working with the scroll buttons.

  9. At the end of the current script on Frame 1, add the following line of script to initialize the scrollButtonPressed variable:

    
    var scrollButtonPressed:Boolean = false;
    
    

    The variable scrollButtonPressed can have a value of either true or false. In future steps you'll add button events that will serve to toggle the value of scrollButtonPressed between true and false. When true, the scroll function will be called repeatedly by an onEnterFrame event.

  10. Add the following script at the bottom of the frame:

    
    display_mc.down_btn.onPress = function() {
    
      scrollButtonPressed = true;
    
      direction = "down";
    
    };
    
    display_mc.down_btn.onRelease = function() {
    
      scrollButtonPressed = false;
    
    };
    
    

    The display_mc movie clip contains two buttons that you will use to control the scrolling. Their instance names are down_btn and up_btn. In this step you are adding onPress and onRelease button events to the down_btn button instance.

    When the down_btn button is pressed, the variable scrollButtonPressed is set to true and the variable direction is given a value of "down". The onEnterFrame event (not yet added) will call the scroll() function when it sees that scrollButtonPressed has a value of true. The scroll() function will in turn use the value of the direction variable to determine whether to scroll the list_mc movie clip up or down, as described in Steps 7 and 8.

  11. Add the following button events for the up_btn button instance:

    
    display_mc.up_btn.onPress = function() {
    
      scrollButtonPressed = true;
    
      direction = "up";
    
    };
    
    display_mc.up_btn.onRelease = function() {
    
      scrollButtonPressed = false;
    
    };
    
    

    This script acts similar to the script added in Step 10. When the up_btn button instance is clicked, the scrollButtonPressed variable is set to true so that the onEnterFrame event can continually call the scroll() function. In addition, the value of direction is set to "up". As mentioned in Step 10, an onEnterFrame event we will add in the next step will call the scroll() function whenever scrollButtonPressed is true. This, accompanied by the fact that the value of direction is set to "up", will cause our list of items to scroll upward continuously when this button is clicked.

    When the button is released, the scrollButtonPressed variable is set back to false to stop the scrolling.

  12. Add the following onEnterFrame event:

    
    this.onEnterFrame = function() {
    
      if (scrollButtonPressed) {
    
        scroll();
    
      }
    
    };
    
    

    This script defines an onEnterFrame event for the _root timeline. It's executed once every frame (24 times a second). When it's executing, if the value of scrollButtonPressed is true, the scroll function is called. The scroll function will then scroll the list_mc movie clip based on the current value of direction.

  13. Choose Control > Test Movie to test this movie.

    Give your buttons a try to test your ActionScript. You can click and hold a button down to make scrolling occur. When the list_mc movie clip instance reaches its upper or lower maximum, it will stop scrolling.

  14. Close the test movie and save your work as scrollingList3.fla.

    You've now created the ActionScript required to scroll a list of dynamic items between upper and lower boundaries using continuous-feedback buttons.