Book HomeActionScript: The Definitive GuideSearch this book

10.11. The User-Input Movie Clip Events

The remainder of the movie clip events relate to user interaction. When any of the user-input clip events occurs, all clips on stage (no matter how deeply nested in other clips) receive the event. Hence, multiple clips may react to a single mouseclick, mouse movement, or keystroke.

To execute code based on the proximity of the mouse to a particular clip, an event handler should check the location of the mouse pointer relative to the clip. The built-in hitTest( ) function provides an easy way to check whether a mouseclick occurred within a certain region, as shown later in Example 10-9.

10.11.1. mouseDown

Like the press button event, the mouseDown clip event detects the downstroke of a mouseclick. The mouseDown event occurs each time the primary mouse button is depressed while the mouse pointer is over any part of the Stage.

Unlike the button press event, mouseDown is not tied to the hit area of a button. In combination with the mouseUp and mouseMove events and the Mouse.hide( ) method, the mouseDown event can be used to implement a custom mouse pointer, as we'll see later in Example 10-8.

10.11.2. mouseUp

The mouseUp event is the counterpart to mouseDown. It occurs each time the primary mouse button is released while the mouse pointer is over any part of the Stage. As with mouseDown, a clip with a mouseUp handler must be present on stage at the time the mouse button is released in order for the event to have any consequence. The mouseUp, mouseDown, and mouseMove events can be used to create rich levels of mouse interactivity without affecting the appearance of the mouse pointer (as a button does).

10.11.3. mouseMove

The mouseMove event lets us detect changes in the mouse pointer's position. Whenever the mouse is in motion, mouseMove events are issued repeatedly, as fast as the processor can generate new events. A clip with a mouseMove handler must be present on stage at the time the mouse is moving in order for the mouseMove event to have any effect.

The mouseMove event is useful for code that wakes up idle applications, displays mouse trails, and creates custom pointers, as we'll see later in Example 10-8.

10.11.4. keyDown

The keyDown and keyUp events are the keyboard analogs of mouseDown and mouseUp. Together, they provide fundamental tools for coding keyboard-based interactivity. The keyDown event occurs whenever a key on the keyboard is depressed. When a key is held down, keyDown may occur repeatedly, depending on the operating system and keyboard setup. Unlike the keyPress button event, keyDown clip events occur when any key -- not just the specific key -- is pressed.

To trap (i.e., detect or catch) a keyDown event, we must ensure that a movie clip with a keyDown event handler is present on stage at the time that a key is pressed. The following code does the trick:

onClipEvent (keyDown) {
  trace("Some key was pressed");
}

You'll notice that our keyDown handler does not tell us which key was pressed. If we're waiting for the user to press any key to continue, we might not care which key it was. But usually, we want to tie some action to a specific key. For example, we might want different keys to turn a spaceship in different directions.

To find out which keys triggered the keyDown event, we consult the built-in Key object, which describes the keyboard's state. The type of information we require depends on the interactivity we're trying to produce. Games, for example, require instant, continuous feedback from potentially simultaneous keypresses. Navigational interfaces, in contrast, may require only the detection of a single keypress (e.g., the spacebar in a slide show presentation).

The Key object can tell us which key was last pressed and whether a particular key is currently being pressed. To determine the state of the keyboard, we use one of the four Key object methods:

Key.getCode( )           // Base-10 keycode value of last key pressed
Key.getAscii( )          // Base-10 ASCII value of last key pressed
Key.isDown(keycode)     // Returns true if specified key is currently pressed
Key.isToggled(keycode)  // Determines whether Caps Lock or Num Lock is toggled on

Example 10-5 shows a keyDown handler that tells us the ASCII value of the last key pressed.

Example 10-5. Checking the Last Key Pressed

onClipEvent (keyDown) {
  // Retrieve the ASCII value of the last key pressed and convert it to a character
  lastKeyPressed = String.fromCharCode(Key.getAscii( ));
  trace("You pressed the '" + lastKeyPressed + "' key.");
}

Example 10-6 shows a sample keyDown handler that checks whether the up arrow was the last key pressed.

Example 10-6. Detecting an Up Arrow Keypress

onClipEvent (keyDown) {
  // Check to see if the up arrow was the last key pressed.
  // The up arrow is represented by the Key.UP property.
  if (Key.getCode( ) == Key.UP) {
    trace("The up arrow was the last key depressed");
  }
}

There are several ways to query the state of the keyboard, and you must choose the one that best suits your application. For example, the Key.getAscii( ) method returns the ASCII value of the character associated with the last-pressed key, which may differ across keyboards in different languages (though, in English, the placement of the letters and numbers on a keyboard is standardized). On the other hand, the Key.getCode( ) method returns a value tied to a physical key on the keyboard, not a specific letter. Key.getCode( ) may be more useful for an international or cross-platform audience if you want to, say, use four adjacent keys for navigation regardless of the characters they represent. There's more information on this topic under Reference 20.85 in Part III, "Language Reference".

You can download sample keyDown and keyUp .fla files from the online Code Depot.

TIP

Event handlers that react to keystrokes are executed only if the Flash Player has mouse focus. Users must click the Stage of a movie before the movie's keystroke handlers will become active. Consider forcing users to click a button before entering any keyboard-controlled section of a movie.

10.11.4.1. Handling special keys

To disable the Flash standalone Player menu commands (Open, Close, Fullscreen, etc.), add the following line of code to the beginning of your movie:

fscommand("trapallkeys", "true");

That command also prevents the Escape key from exiting fullscreen mode in a Projector. To capture Escape in a Projector, use:

onClipEvent (keyDown) {
  if (Key.getCode( ) == Key.ESCAPE) {
    // Respond to Escape keypress
  }
}

Note that the Escape key cannot be trapped in all browsers. Furthermore, there is no way to disable the Alt key or the Windows Alt-Tab or Ctrl-Alt-Delete key sequences.

To capture Tab keypresses, create a button with the following handler:

on (keyPress "<Tab>") {
  // Respond to Tab key
}

In the standalone Player, the Tab key may also be captured with a clip event handler such as:

onClipEvent (keyDown) {
  if (Key.getCode( ) == Key.TAB) {
    // Respond to Tab keypress
  }
}

In some browsers, the Tab key can be detected only with a button keyPress event, and it may even be necessary to combine a keyPress button event with a keyUp clip event. The following code first traps the Tab key with keyPress, and then reacts to it in a keyUp handler. Note that we don't use keyDown because Key.getCode( ) for the Tab key is set only on the key upstroke in Internet Explorer:


// CODE ON BUTTON ON MAIN TIMELINE
on (keyPress "<Tab>") {
  // Set a dummy variable here
  foo = 0;
}

// CODE ON MOVIE CLIP ON MAIN TIMELINE
onClipEvent (keyUp) {
  if (Key.getCode( ) == Key.TAB) {
    // Now place the cursor in myTextField on _level0
    Selection.setFocus("_level0.myTextField");
  }
}

We typically trap the Tab key in order to move the insertion point to a particular text field in a form. See the example under Reference 20.205 in Part III, "Language Reference" for details.

To capture a shortcut-key-style combination such as Ctrl-F, use an enterFrame handler and the Key.isDown( ) method:

onClipEvent (enterFrame) {
  if (Key.isDown(Key.CONTROL) && Key.isDown(70)) {
	// Respond to Ctrl-F
  }
}

To capture the Enter (or Return) key, use either a button handler, such as:

on (keyPress "<Enter>") {
  // Respond to Enter key press (e.g., submit a form)
}

or a keyDown handler, such as:

onClipEvent (keyDown) {
  if (Key.getCode( ) == Key.ENTER) {
    // Respond to Enter key press (e.g., submit a form)
  }
}

See Reference 20.85 and Reference 20.87 in Part III, "Language Reference" for more information on capturing other special keys such as the function keys (F1, F2, etc.) or keys on the numeric keypad.

10.11.5. keyUp

The keyUp event is triggered when a depressed key is released. The keyUp event is an essential component of game programming because it lets us turn off something that was turned on by an earlier keyDown event -- the classic example being a spaceship's thrust. As a further example, in the Flash authoring tool, holding down the spacebar temporarily switches to the Hand tool, and releasing the spacebar restores the previous tool. This approach can be used to show and hide things in your application, such as temporary menus.

As with keyDown, in order to obtain useful information from a keyUp event, we normally use it with the Key object:

onClipEvent (keyUp) {
  if (!Key.isDown(Key.LEFT)) {
    trace("The left arrow is not depressed");
  }
}

Because the Key.isDown( ) method lets us check the status of any key anytime, we may use an enterFrame event loop to check whether a certain key is depressed. However, polling the keyboard (i.e., checking the status of a key repeatedly) is less efficient than waiting until we know that a key has been pressed as indicated by a keyDown event triggering our event handler.

The approach we end up taking ultimately depends on the type of system we're building. In a system that's constantly in motion, such as a game, polling may be appropriate because we're cycling through a main game loop with every frame anyway. So, we can just check the Key object while we're doing the rest of our loop. For example:


// CODE ON EMPTY CLIP
// This keeps the game process running
onClipEvent (enterFrame) {
  _root.mainLoop( );
}

// CORE GAME CODE ON MAIN TIMELINE
// This is executed once per frame
function mainLoop ( ) {
  if (Key.isDown(Key.LEFT)) {
    trace("The left arrow is depressed");
    // Rotate the spaceship to the left
  }

  // Check the other keys, then carry on with our game cycle
}

In static-interface environments, there's no need to use an enterFrame loop to check for keypresses unless you are trying to detect specific keyboard combinations (i.e., multiple keys being pressed simultaneously). You should ordinarily use keyDown and keyUp event handlers, which are triggered precisely once for each keypress and key release. When using keyUp and keyDown event handlers, you need not concern yourself with whether the key is still being pressed at any given instant. This allows you to detect keypresses accurately even if the user releases the key between frames, and it also prevents you from checking the same key twice if it was pressed only once. In any case, you will ordinarily use the Key.getCode( ) and Key.getASCII( ) methods to check for the last key pressed within a keyDown or keyUp event handler.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.