Macromedia MX 2004 User Guide

DIRECTOR®MX
2004
Director Scripting Reference
Trademarks
ActiveEdit, ActiveTest, Add Life to the Web, Afterburner, Aftershock, Andromedia, Allaire, Animation PowerPack, Aria, Attain, Authorware, Authorware Star, Backstage, Blue Sky Software, Blue Sky, Breeze, Bright Tiger, Clustercats, ColdFusion, Contents Tab Composer, Contribute, Design In Motion, Director, Dream Templates, Dreamweaver, Drumbeat 2000, EDJE, EJIPT, Extreme 3D, Fireworks, Flash, FlashHelp, Flash Lite, FlashPaper, Flex, Flex Builder, Fontographer, FreeHand, Generator, Help To Source, HomeSite, Hotspot Studio, HTML Help Studio, JFusion, JRun, Kawa, Know Your Site, Knowledge Objects, Knowledge Stream, Knowledge Track, LikeMinds, Lingo, Live Effects, MacRecorder Logo and Design, Macromedia, Macromedia Action!, Macromedia Central, Macromedia Flash, Macromedia M Logo and Design, Macromedia Spectra, Macromedia xRes Logo and Design, MacroModel, Made with Macromedia, Made with Macromedia Logo and Design, MAGIC Logo and Design, Mediamaker, Movie Critic, Open Sesame!, RoboDemo, RoboEngine JFusion, RoboHelp, RoboHelp Office, RoboInfo, RoboInsight, RoboPDF, 1-Step RoboPDF, RoboFlash, RoboLinker, RoboScreenCapture, ReSize, Roundtrip, Roundtrip HTML, Shockwave, Sitespring, Smart Publishing Wizard, Software Video Camera, SoundEdit, Titlemaker, UltraDev, Web Design 101, what the web can be, WinHelp, WinHelp 2000, WinHelp BugHunter, WinHelp Find+, WinHelp Graphics Locator, WinHelp Hyperviewer, WinHelp Inspector, and Xtra are either registered trademarks or trademarks of Macromedia, Inc. and may be registered in the United States or in other jurisdictions including internationally. Other product names, logos, designs, titles, words, or phrases mentioned within this publication may be trademarks, service marks, or trade names of Macromedia, Inc. or other entities and may be registered in certain jurisdictions including internationally.
Third-Party Information
This guide contains links to third-party websites that are not under the control of Macromedia, and Macromedia is not responsible for the content on any linked site. If you access a third-party website mentioned in this guide, then you do so at your own risk. Macromedia provides these links only as a convenience, and the inclusion of the link does not imply that Macromedia endorses or accepts any responsibility for the content on those third-party sites.
Apple Disclaimer
APPLE COMPUTER, INC. MAKES NO WARRANTIES, EITHER EXPRESS OR IMPLIED, REGARDING THE ENCLOSED COMPUTER SOFTWARE PACKAGE, ITS MERCHANTABILITY OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. THE EXCLUSION OF IMPLIED WARRANTIES IS NOT PERMITTED BY SOME STATES. THE ABOVE EXCLUSION MAY NOT APPLY TO YOU. THIS WARRANTY PROVIDES YOU WITH SPECIFIC LEGAL RIGHTS. THERE MAY BE OTHER RIGHTS THAT YOU MAY HAVE WHICH VARY FROM STATE TO STATE.
Copyright © 2004 Macromedia, Inc. All rights reserved. This manual may not be copied, photocopied, reproduced, translated, or converted to any electronic or machine-readable form in whole or in part without prior written approval of Macromedia, Inc.
Second Edition: September 2004 Macromedia, Inc.
600 Townsend St. San Francisco, CA 94103

CONTENTS

CHAPTER 1: Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Intended audience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
What’s new with Director scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
What’s new in this documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Finding information about scripting in Director . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
CHAPTER 2: Director Scripting Essentials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Types of scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Scripting terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Scripting syntax. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Literal values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Conditional constructs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Events, messages, and handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Linear lists and property lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
JavaScript syntax arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
CHAPTER 3: Writing Scripts in Director . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Choosing between Lingo and JavaScript syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Scripting in dot syntax format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Introducing the Director objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Object model diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Top level functions and properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Introduction to object-oriented programming in Director . . . . . . . . . . . . . . . . . . 54
Object-oriented programming with Lingo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Object-oriented programming with JavaScript syntax . . . . . . . . . . . . . . . . . . . . . . 65
Writing scripts in the Script window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
3
CHAPTER 4: Debugging Scripts in Director . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Good scripting habits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Basic debugging. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Debugging in the Script window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Debugging in the Message window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Debugging in the Object inspector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
Debugging in the Debugger window. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Debugging projectors and Shockwave movies . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Advanced debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
CHAPTER 5: Director Core Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
CHAPTER 6: Media Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
CHAPTER 7: Scripting Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
CHAPTER 8: 3D Objects. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
CHAPTER 9: Constants. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
CHAPTER 10: Events and Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
CHAPTER 11: Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
CHAPTER 12: Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
CHAPTER 13: Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 595
CHAPTER 14: Properties. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617
INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1103
4 Contents
CHAPTER 1

Introduction

This reference provides conceptual and how-to information about scripting in Macromedia Director MX 2004, and also provides reference descriptions and examples for the scripting application programming interfaces (APIs) that you use to write scripts.
The scripting APIs are the means by which you access the functionality of Director through script to add interactivity to a movie. By using these APIs, you can create interactive functionality that is identical to that provided by the prewritten behaviors that are shipped with Director, in addition to functionality that is more powerful and more varied than that provided by the prewritten behaviors.
The prewritten behaviors enable you to add basic interactive functionality to a movie, such as moving the playhead to a frame number or marker, or zooming in when a user clicks a sprite. They also enable non-interactive functionality such as sprite animation, media loading, and frame navigation. The scripting APIs enable you to extend and customize these types of functionality.

Intended audience

This reference is intended for you if you want to do any of the following:
Extend the existing functionality of prewritten behaviors by using script.
Add functionality to a movie by using script instead of prewritten behaviors.
Add more powerful, varied, and custom functionality to a movie than that provided by
prewritten behaviors.
This reference is intended to provide all the information, from basic to advanced, you need to add interactivity to your movies by using script. Therefore, you do not need to have any prior scripting experience to write effective scripts in Director.
Regardless of your experience level with Director, Lingo, or JavaScript syntax, take a few moments to browse Chapter 2, “Director Scripting Essentials,” on page 9 and Chapter 3, “Writing Scripts
in Director,” on page 49 before you begin writing scripts. Like any product, Director has its own
unique set of scripting conventions, types of data, and so on. You will need to be comfortable with these unique characteristics of Director before you can write effective scripts.
5

What’s new with Director scripting

If you have written scripts in previous versions of Director, you should note some new and important changes about scripting in this latest release.

Dot syntax scripting format

In previous releases of Director, you could write Lingo scripts by using two types of syntax: verbose syntax or dot syntax. Verbose syntax was very similar to English, and was relatively easy for new programmers to learn. However, verbose syntax scripts quickly became long and complex, and were difficult to debug.
Now that the scripting model of Director is compatible with both Lingo and JavaScript syntax, scripts should be written only in dot syntax. Dot syntax will be familiar to many programmers, since it is the syntax used in most object-oriented languages such as Java or C++, and in many web-based scripting languages such as Microsoft JScript or JavaScript.
To support backwards compatibility, scripts written by using verbose syntax in previous versions of Director will still run. However, starting with Director MX 2004, dot syntax is the recommended syntax to use, and is the only syntax that will be supported and documented in the future.
For more information on using dot syntax to write scripts, see “Scripting in dot syntax format”
on page 50.

JavaScript syntax compatibility

Director is now compatible with JavaScript syntax. This means that in addition to being able to author and debug scripts by using Lingo, which is the long-time scripting language of Director, you can choose to author and debug scripts by using JavaScript syntax. The implementation of JavaScript in Director is referred to as JavaScript syntax throughout this reference.
The support of JavaScript syntax in Director helps create a scripting environment that is familiar not only to JavaScript developers but also to developers experienced with Macromedia Flash ActionScript, Macromedia Flash Communication Server, Macromedia Dreamweaver, Macromedia Authorware, and a number of other environments.
The implementation of JavaScript syntax in Director is JavaScript 1.5, which means that it is fully compliant with the ECMAScript Language Specification ECMA-262, 3rd Edition. Almost all of the features and functionality in JavaScript 1.5 are now available in Director.
For more information on choosing Lingo or JavaScript syntax, see “Choosing between Lingo and
JavaScript syntax” on page 49.
Note: This reference is intended to only discuss the features and functionality of the JavaScript 1.5 implementation that are essential to writing JavaScript syntax scripts in Director. It is not intended to provide a complete reference for JavaScript 1.5. For more detailed information on JavaScript 1.5 than is provided in this reference, see one of the many third-party resources on the subject.

New ways to access the scripting APIs

In this release of Director, the scripting APIs have been grouped into objects, and are accessed through these objects. These objects contain the functionality required to add interactivity to your movies and are accessible to both Lingo and JavaScript syntax within Director, projectors, and Macromedia Shockwave Player.
6 Chapter 1: Introduction
Although the way you access the scripting APIs in this release may vary from previous releases, you still have access to the same APIs that you did before, in addition to some brand new ones. The only difference is that you access them by using the new objects.
For more information on the objects and their corresponding scripting APIs, see “Introducing the
Director objects” on page 51.

What’s new in this documentation

If you learned how to script in previous versions of Director, you should know about some changes in the scripting documentation for this release. The Director Scripting Reference takes the place of the Lingo Dictionary that was shipped with previous versions of Director. This reference is organized differently than the Lingo Dictionary.
In the Lingo Dictionary, information about the scripting model was organized by feature. For example, if you wanted to learn how to work with sprites in script, you looked up that information in one of the sections under the Sprites heading, such as Dragging Sprites, Sprite Dimensions, and so on. In addition, all of the scripting APIs were listed in a single alphabetical list, which meant that all functions, properties, events, and so on were mixed together alphabetically.
In the Director Scripting Reference, information about the scripting model is organized by object. This organization closely reflects the organization of the actual scripting objects that you use in your scripts. For example, if you want to find out how to work with sprites in script, you should look for the Sprite section in the chapter, Director Core Objects.
The scripting APIs are still listed in alphabetical order, but they are categorized by API type. For example, all methods are listed alphabetically under the Methods heading, all properties are listed alphabetically under the Properties heading, and so on.

Finding information about scripting in Director

With its new organization, the Director Scripting Reference contains the following topics:
Director Scripting Essentials Provides information about the basic scripting concepts and
components you will use when scripting in Director.
Writing Scripts in Director Provides information about the Director scripting environment in
addition to advanced scripting concepts and techniques.
Debugging Scripts in Director Provides information about how to find problems in your
scripts when they are not performing as expected.
Director Core Objects Provides a list of the objects and APIs that you use to access the core
functionality and features in Director, such as the Director player engine, movie windows, sprites, sounds, and so on.
Media Types Provides a list of the media types and APIs that you use to access the functionality
of the various media types in Director, such as RealMedia, DVD, Animated GIF, and so on, that are added to movies as cast members.
Scripting Objects Provides a list of the scripting objects, also known as Xtra extensions, and
APIs that you use to extend core Director functionality. Xtra extensions provide capabilities such as importing filters and connecting to the Internet.
3D Objects Provides a list of the objects you use to add 3D functionality to a movie.
Finding information about scripting in Director 7
Constants Provides a list of the constants that are available in Director.
Events and Messages Provides a list of the events that are available in Director.
Keywords Provides a list of the keywords that are available in Director.
Methods Provides a list of the methods that are available in Director.
Operators Provides a list of the operators that are available in Director.
Properties Provides a list of the properties that are available in Director.
8 Chapter 1: Introduction
CHAPTER 2

Director Scripting Essentials

If you are new to scripting in Macromedia Director MX 2004, you may want to take some time to learn the basic scripting concepts that are essential to understanding how to script in Director before you begin. Some of these essentials include definitions of important terms, syntax rules, available data types, and information about the basic elements of scripting in Director—for example, variables, arrays, operators, and so on.

Types of scripts

A Director movie can contain four types of scripts: behaviors, movie scripts, parent scripts, and scripts attached to cast members. Behaviors, movie scripts, and parent scripts all appear as independent cast members in the Cast window. A script attached to a cast member is associated with that cast member in the Cast window and does not appear independently.
Behaviors are scripts that are attached to sprites or frames in the Score, and are referred to as
sprite behaviors or frame behaviors. The Cast window thumbnail for each behavior contains a behavior icon in the lower right corner.
When used in the Director Scripting Reference, the term behavior refers to any script that you attach to a sprite or a frame. This differs from the behaviors that come in the Director Library Palette. For more information on these behaviors, which are built into Director, see the Using Director topics in the Director Help Panel.
All behaviors that have been added to a cast library appear in the Behavior inspector’s Behavior pop-up menu. Other types of scripts do not appear there.
You can attach the same behavior to more than one location in the Score. When you edit a behavior, the edited version is applied everywhere the behavior is attached in the Score.
Movie scripts contain handlers that are available globally, or on a movie level. Event handlers in
a movie script can be called from other scripts in the movie as the movie plays. A movie script icon appears in the lower right corner of the movie script’s Cast window
thumbnail. Movie scripts are available to the entire movie, regardless of which frame the movie is in or
which sprites the user is interacting with. When a movie plays in a window or as a linked movie, a movie script is available only to its own movie.
9
Parent scripts are special scripts that contain Lingo that is used to create child objects. You can
use parent scripts to generate script objects that behave and respond similarly yet can still operate independently of each other. A parent script icon appears in the lower right corner of the Cast window thumbnail.
For information on using parent scripts and child objects, see “Object-oriented programming
with Lingo” on page 55.
JavaScript syntax does not use parent scripts or child objects; it uses regular JavaScript syntax­style object-oriented programming techniques. For information on object-oriented programming in JavaScript syntax, see “Object-oriented programming with JavaScript syntax”
on page 65
Scripts attached to cast members are attached directly to a cast member, independent of the
Score. Whenever the cast member is assigned to a sprite, the cast member’s script is available. Unlike behaviors, movie scripts, and parent scripts, cast member scripts do not appear in the
Cast window. However, if Show Cast Member Script Icons is selected in the Cast Window Preferences dialog box, cast members that have a script attached display a small script icon in the lower left corner of their thumbnails in the Cast window.

Scripting terminology

Both Lingo and JavaScript syntax use some terms that are specific to each language, in addition to some terms that are shared between each language.
Important scripting terms are listed here in alphabetical order. These terms are used throughout the Director Scripting Reference, so it will help to understand these terms before moving forward.
Constants are elements whose values do not change. For example, in Lingo, constants such as
TAB, EMPTY, and RETURN always have the same values, and cannot be modified. In JavaScript
syntax, constants such as cannot be modified. You can also create your own custom constants in JavaScript syntax by using the keyword
For more information on constants, see “Constants” on page 20.
Math.PI and Number.MAX_VALUE always have the same values, and
const.
Events are actions that occur while a movie is playing. Events occur when a movie stops, a
sprite starts, the playhead enters a frame, the user types at the keyboard, and so on. All events in Director are predefined, and always have the same meaning.
For more information on events, see “Events” on page 33.
Expressions are any part of a statement that produces a value. For example, 2 + 2 is
an expression.
Functions refer to either top-level functions or specific types of JavaScript syntax code.
A top-level function instructs a movie to do something while the movie is playing or returns a value, but it is not called from any specific object. For example, you would call the top-level
list() function by using the syntax list(). Like a function, a method also instructs a movie
to do something while the movie is playing or returns a value, but it is always called from an object.
A function is used in JavaScript syntax to represent an event handler, a custom object, a custom method, and so on. The use of JavaScript functions in these cases is described in the applicable topics later in this reference.
10 Chapter 2: Director Scripting Essentials
Handlers, or event handlers, are sets of statements within a script that run in response to a
specific event and subsequent message. When an event occurs, Director generates and sends a corresponding message to scripts, and a corresponding handler runs in response to the message. The names of handlers are always the same as the events and messages they respond to.
Note: Although in JavaScript syntax an event is actually handled by a function, the term handler is used generically throughout this reference to refer to both Lingo handlers and JavaScript syntax functions that handle events.
For more information on handlers, see “Handlers” on page 35.
Keywords are reserved words that have a special meaning. For example, in Lingo, the keyword
end indicates the end of a handler. In JavaScript syntax, the keyword var indicates that the
term following it is a variable.
Lists (Lingo) or Arrays (JavaScript syntax) are ordered sets of values used to track and update
an array of data, such as a series of names or the values assigned to a set of variables. A simple example is a list of numbers such as
[1, 4, 2].
For more information on using lists in both Lingo and JavaScript syntax, see “Linear lists and
property lists” on page 38.
For more information on using JavaScript syntax arrays, see “JavaScript syntax arrays”
on page 45.
Messages are notices that Director sends to scripts when specific events occur in a movie. For
example, when the playhead enters a specific frame, the Directors sends an
enterFrame message. If a script contains an enterFrame handler, the
statements within that handler will run, because the handler received the If no scripts contain a handler for a message, the message is ignored in script.
For more information on messages, see “Messages” on page 34
enterFrame event occurs and
enterFrame message.
Methods are terms that either instruct a movie to do something while the movie is playing or
return a value, and are called from an object. For example, you would call the method from the Movie object, using the syntax
_movie.insertFrame(). Although similar in
functionality to top-level functions, methods are always called from an object, and top-level functions are not.
insertFrame()
Operators are terms that calculate a new value from one or more values. For example, the
addition ( For more information on operators, see “Operators” on page 25.
+) operator adds two or more values together to produce a new value.
Parameters are placeholders that let you pass values to scripts. Parameters only apply to
methods and event handlers, and not to properties. They are required by some methods and optional for others.
For example, the Movie object’s optionally specifies the name of the movie that frame is in. To perform this task, the method requires at least one parameter, and allows for a second parameter. The first required parameter specifies what frame to send the playhead to, and the second optional parameter specifies what movie the frame is in. Because the first parameter is required, a script error will result if it is not present when the optional, the method will perform its task even if the parameter is not present.
go() method sends the playhead to specific frame, and
go()
go() method is called. Because the second parameter is
Scripting terminology 11
Properties are attributes that define an object. For example, a sprite in a movie has specific
attributes, such as how wide it is, how tall it is, its background color, and so on. To access the values of these three specific attributes, you would use the Sprite object’s
backColor properties.
width, height, and
For more information on assigning properties to variables, see “Storing and updating values in
variables” on page 21.
Statements are valid instructions that Director can execute. All scripts are made up of sets of
statements. The following Lingo is a single complete statement.
_movie.go("Author")
For more information on writing script statements, see “Scripting in dot syntax format”
on page 50
Variables are elements used to store and update values. Variables must start with a letter, an
underscore ( digits (0-9). To assign values to variables or change the values of many properties, you use the equals (
For more information on using variables, see “Variables” on page 21.
_), or the dollar sign ($). Subsequent characters in a variable name can also be
=) operator.

Scripting syntax

The following are general syntax rules that apply to Lingo and JavaScript syntax.
Comment markers vary between Lingo and JavaScript syntax.
All Lingo comments are preceded by double hyphens ( multiple lines must be preceded by double hyphens.
-- This is a single-line Lingo comment
--). Each line of a comment that covers
-- This is a
-- multiple-line Lingo comment
JavaScript syntax comments on a single line are preceded by a double-slash (//). Comments that cover multiple lines are preceded with a
// This is a single-line JavaScript syntax comment
/* This is a multiple-line JavaScript syntax comment */
You can place a comment on its own line or after any statement. Any text following the comment markers on the same line are ignored.
Comments can consist of anything you want, such as notes about a particular script or handler or notes about a statement whose purpose might not be obvious. Comments make it easier for you or someone else to understand a procedure after you’ve been away from it for a while.
Adding large numbers of comments does not increase the size of your movie file when it is saved as a compressed DCR or DXR file. Comments are removed from the file during the compression process.
Comment markers can also be used to ignore sections of code you want to deactivate for testing or debugging purposes. By adding comment markers rather than removing the code, you can temporarily turn it into comments. Select the code you want to turn on or off, and then use the Comment or Uncomment buttons in the Script window to quickly add or remove comment markers.
12 Chapter 2: Director Scripting Essentials
/* and followed by a */.
Parentheses are required after all method and function names. For example, when calling the
Sound object’s Otherwise, a script error will occur.
// JavaScript syntax _sound.beep(); // this statement will work properly _sound.beep; // this statement will result in a script error
When you call a method, function, or handler from within another method, function, or handler, you must include parentheses in the calling statement. In the following example, the
modifySprite() method contains a call to a spriteClicked handler. The call to the spriteClicked handler must include parentheses; otherwise, a script error occurs.
// JavaScript syntax function modifySprite() {
spriteClicked(); // this call to the handler will work properly
spriteClicked; // this call to the handler results in a script error } function spriteClicked() {
// handler code here }
You can also use parentheses to override the order of precedence in math operations, or to make your statements easier to read. For example, the first math expression below yields a result of 13, while the second expression yields a result of 5:
5 * 3 - 2 -- yields 13 5 * (3 - 2) -- yields 5
beep() method, you must include the parentheses after the word beep.
Event handler syntax varies between Lingo and JavaScript syntax. In Lingo, handlers use the
syntax
on handlerName. In JavaScript syntax, handlers are implemented as functions, and use
the syntax
function handlerName(). For example, the following statements comprise a
handler that plays a beep when the mouse button is clicked:
-- Lingo syntax on mouseDown
_sound.beep() end // JavaScript syntax function mouseDown() {
_sound.beep(); }
Event handler parameter syntax can vary between Lingo and JavaScript syntax. Both Lingo and
JavaScript syntax support enclosing parameters passed to a handler within parentheses. If more than one parameter is passed, each parameter is separated by a comma. In Lingo, you can also pass parameters that are not enclosed by parentheses. For example, the following handler receives the two parameters
-- Lingo syntax on addThem a, b -- without parentheses
c = a + b end
a and b.
addThem
on addThem(a, b) -- with parentheses
c = a + b end
// JavaScript syntax function addThem(a, b) {
c = a + b; }
Scripting syntax 13
The const keyword can be used in JavaScript syntax to specify a constant whose value does not
change. Lingo has its own predefined set of constants ( keyword
const does not apply to Lingo.
For example, the following statement specifies a constant named to 12. This value will always be 12, and cannot be changed through script.
// JavaScript syntax const intAuthors = 12;
TAB, EMPTY, and so on); therefore, the
intAuthors and sets its value
The var keyword in JavaScript syntax can be placed in front of a term to specify that the term
is a variable. The following statement creates a variable named
// JavaScript syntax var startValue = 0;
Note: Although using var in JavaScript syntax is optional, it is recommended that you always declare local JavaScript syntax variables, or those inside a function, using var. For more information on using variables, see “Variables” on page 21.
startValue.
The line continuation symbol (\) in Lingo indicates that a long line of sample code has been
broken into two or more lines. Lines of Lingo that are broken in this way are not separate lines of code. For example, the following code would still run.
-- Lingo syntax tTexture = member("3D").model("box") \
.shader.texture
JavaScript syntax does not include a line continuation symbol. To break multiple lines of JavaScript syntax code, add a carriage return at the end of a line, and then continue the code on the following line.
Semicolons can be used to specify the end of a statement of JavaScript syntax code. Semicolons
do not apply to Lingo. Using a semicolon is optional. If used, it is placed at the end of a complete statement. For
example, both of the following statements create a variable named
// JavaScript syntax var startValue = 0 var startValue = 0;
startValue.
A semicolon does not necessarily specify the end of a line of JavaScript syntax code, and multiple statements can be placed on one line. However, placing separate statements on separate lines is recommended in order to improve readability. For example, the following three statements occupy only one line of code and function properly, but it is difficult to read the code.
// JavaScript syntax _movie.go("Author"); var startValue = 0; _sound.beep();
Character spaces within expressions and statements are ignored in both Lingo and JavaScript
syntax. In strings of characters surrounded by quotation marks, spaces are treated as characters. If you want spaces in a string, you must insert them explicitly. For example, the first statement below ignores the spaces between the list items, and the second statement includes the spaces.
-- Lingo syntax myList1 = ["1", "2", "3"] -- yields ["1", "2", "3"] myList2 = [" 1 ", " 2 ", " 3 "] -- yields [" 1 ", " 2 ", " 3 "]
14 Chapter 2: Director Scripting Essentials
Case-sensitivity can vary between Lingo and JavaScript syntax.
Lingo is not case-sensitive in any circumstance—you can use uppercase and lowercase letters however you want. For example, the following four statements are equivalent:
-- Lingo syntax member("Cat").hilite = true member("cat").hiLite = True MEMBER("CAT").HILITE = TRUE Member("Cat").Hilite = true
Although Lingo is not case-sensitive, it’s a good habit to choose a case convention and use it consistently throughout your scripts. This makes it is easier to identify names of handlers, variables, cast members, and so on.
JavaScript syntax is case-sensitive when referring to objects, the top level properties or methods that refer to objects, or when referring to user-defined variables. For example, the top level
sprite() method returns a reference to a specific Sprite object, and is implemented in
Director with all lowercase letters. The first statement below refers to the name of the first sprite in a movie, while the second and third statements result in a script error.
// JavaScript syntax sprite(1).name // This statement functions normally Sprite(1).name // This statement results in a script error SPRITE(1).name // This statement results in a script error
Literal strings are always case-sensitive in both Lingo and JavaScript syntax. For more information on using strings, see “Strings” on page 18.

Data types

A data type is a set of data with values that have similar, predefined characteristics. Every variable and property value in Director is of a specific data type, and values returned by methods are of a specific data type.
For example, consider the following two statements. In the first statement, variable assigned a whole number value of 14, which is an integer. So, the data type of variable integer. In the second statement, variable which is a string. So, the data type of variable
-- Lingo syntax intX = 14 stringX = "News Headlines"
stringX is assigned a sequence of character values,
stringX is string.
intX is
intX is
// JavaScript syntax var intX = 14; var stringX = "News Headlines";
The values that are returned by methods or functions are also of an inherent data type. For example, the Player object’s
windowPresent() method returns a value that specifies whether a
window is present. The returned value is TRUE (1) or FALSE (0).
Data types 15
Some data types are shared between Lingo and JavaScript syntax, and some data types are specific to one language or another. The set of data types that Director supports is fixed and cannot be modified, meaning that new data types cannot be added and existing data types cannot be removed. Director supports the following data types.
Data type Description
# (symbol) A self-contained unit that can be used to represent a condition or flag. For example,
Array (JavaScript syntax only) Although not literally a data type, an Array object can be
Boolean A value that is
Color Represents an object’s color.
Constant A piece of data whose value does not change.
Date Although not literally a data type, in JavaScript syntax a Date object can be used to
Float (Lingo only) A floating-point number. For example, 2.345 or 45.43.
Function (JavaScript syntax only) Although not literally a data type, a Function object can be
Integer (Lingo only) A whole number. For example, 5 or 298.
List A linear or property list made up of values or property names and values,
Math (JavaScript syntax only) Although not literally a data type, a Math object can be
null (JavaScript syntax only) Denotes a variable whose value behaves as 0 in numeric
Number (JavaScript syntax only) Although not literally a data type, a Number object can be
Object Although not literally a data type, an Object object can be used to create a custom
Point A point on the Stage that has both a horizontal and vertical coordinate.
Rect A rectangle on the Stage.
RegExp (JavaScript only) A regular expression pattern that is used to match character
String A contiguous sequence of keyboard symbols or character values. For example,
#list or #word.
used to work with linear lists of values. The functionality of an Array object is similar to that of the List data type in Lingo.
TRUE (1) or FALSE (0). In Lingo, all TRUE or FALSE values are simple
integer constants, 1 for values are by default the actual Boolean simple integer constants automatically when required in Director.
In Lingo, syntax,
work with dates. In Lingo, use the date() method to create a Date object and work with dates.
used to specify a string of code to run.
respectively.
used to perform mathematical functions.
contexts and as
used to represent numerical constants, such as a maximum value, not-a-number (NaN), and infinity.
named container that contains data and methods that act on that data.
combinations in strings.
"Director" or "$5.00".
TRUE and FALSE can be either lowercase or uppercase. In JavaScript
true and false must always be lowercase.
TRUE, 0 for FALSE. In JavaScript syntax, all true or false
true or false values, but are converted to
FALSE in Boolean contexts.
16 Chapter 2: Director Scripting Essentials
Data type Description
undefined (JavaScript syntax only) Denotes a variable that does not have a value.
Vector A point in 3D space.
VOID (Lingo only) Denotes an empty value.
Note: Many of the data types and objects that are specific to JavaScript syntax contain their own set of methods and properties that can be used to further manipulate those types. While the Director Scripting Reference may refer to some of these methods and properties, it does not include complete reference information about them. For more detailed information on these data types and objects, and their methods and properties, see one of the many third-party resources on the subject.
The built-in properties in Director, such as the Cast object’s name property, can only be assigned values that are the same data type as that of the property’s inherent data type. For example, the Cast object’s
News Headlines. If you try to assign a value of a different data type to this property, such as the
name property’s inherent data type is a string, so the value must be a string such as
integer 20, a script error occurs.
If you create your own custom properties, their values can be of any data type, regardless of the data type of the initial value.
Both Lingo and JavaScript syntax are dynamically typed. This means that you do not have to specify the data type of a variable when you declare it, and data types are automatically converted as needed while a script runs.
For example, the following JavaScript syntax initially sets the variable later in the script it is set to a string. When the script runs, the date type of
myMovie to an integer, and
myMovie is converted
automatically.
-- Lingo syntax myMovie = 15 -- myMovie is initially set to an integer ... myMovie = "Animations" -- myMovie is later set to a string
// JavaScript syntax var myMovie = 15; // myMovie is initially set to an integer ... myMovie = "Animations"; // myMovie is later set to a string
Data types 17

Literal values

A literal value is any part of a statement or expression that is to be used exactly as it is, rather than as a variable or a script element. Literal values that you encounter in script are character strings, integers, decimal numbers, cast member names and numbers, frame and movie names and numbers, symbols, and constants.
Each type of literal value has its own rules.

Strings

Strings are words or groups of characters that script treats as regular words instead of as variables. Strings must be enclosed in double quotation marks. For example, you might use strings to give messages to the user of your movie or to name cast members. In the following statement, and Greeting are both strings. Hello is the literal text being put into the text cast member;
Greeting is the name of the cast member.
-- Lingo syntax member("Greeting").text = "Hello"
Similarly, if you test a string, double quotation marks must surround each string, as in the following example:
-- Lingo syntax if "Hello Mr. Jones" contains "Hello" then soundHandler
Both Lingo and JavaScript syntax treat spaces at the beginning or end of a string as a literal part of the string. The following expression includes a space after the word to:
// JavaScript syntax trace("My thoughts amount to ");
Although Lingo does not distinguish between uppercase and lowercase when referring to cast members, variables, and so on, literal strings are case-sensitive. For example, the following two statements place different text into the specified cast member, because literal strings.
-- Lingo syntax member("Greeting").text = "Hello" member("Greeting").text = "HELLO"
In Lingo, the string() function can convert a numerical value into a string. In JavaScript syntax, the
toString() method can convert a numerical value into a string.
Note: Attempting to use the toString() method in JavaScript syntax on a null or undefined value results in a script error. This is in contrast with Lingo, in which the values, including those that are
VOID.
Hello and HELLO are
string() function works on all
Hello

Numbers

In Lingo, there are two types of numbers: integers and decimals.
An integer is a whole number, without any fractions or decimal places, in the range of
-2,147,483,648 and +2,147,483,647. Enter integers without using commas. Use a minus ( for negative numbers.
18 Chapter 2: Director Scripting Essentials
-) sign
A decimal number, also called a floating-point number, or float, is any number that includes a decimal point. In Lingo, the
floatPrecision property controls the number of decimal places
used to display these numbers. Director always uses the complete number, up to 15 significant digits, in calculations; Director rounds any number with more than 15 significant digits in calculations.
JavaScript syntax does not distinguish between integers and floating-point numbers, and merely uses numbers. For example, the following statements illustrate that the number 1 is an integer in Lingo and a number in JavaScript syntax, and that the decimal number 1.05 is a float in Lingo and a number in JavaScript syntax:
-- Lingo syntax put(ilk(1)) -- #integer put(ilk(1.05)) -- #float
// JavaScript syntax trace(typeof(1)) // number trace(typeof(1.05)) // number
In Lingo, you can convert a decimal to an integer by using the integer() function. You can also convert an integer to a decimal by performing a mathematical operation on the integer, for example, by multiplying an integer by a decimal. In JavaScript syntax, you can convert a string or a decimal number to a whole number by using the
integer() function, parseInt() rounds down. For example, the following statement rounds
parseInt() function. As opposed to Lingo’s
off the decimal number 3.9 and converts it to the integer 4 (Lingo) and the number 3 (JavaScript syntax).
-- Lingo syntax theNumber = integer(3.9) -- results in a value of 4
// JavaScript syntax var theNumber = parseInt(3.9); // results in a value of 3
In Lingo, the value() function can convert a string into a numerical value.
You can also use exponential notation with decimal numbers: for example, -
123.4e+9.
In Lingo, you can convert an integer or string to a decimal number by using the
1.1234e-100 or
float()
function. In JavaScript syntax, you can convert a string to a decimal number by using the
parseFloat() function. For example, the following statement stores the value 3.0000 (Lingo)
and 3 (JavaScript syntax) in the variable
-- Lingo syntax theNumber = float(3) -- results in a value of 3.0000
theNumber.
// JavaScript syntax var theNumber = parseFloat(3) // results in a value of 3
Literal values 19

Constants

A constant is a named value whose content never changes.
In Lingo, the predefined terms are always the same. The predefined terms
TRUE, FALSE, VOID, and EMPTY are constants because their values
BACKSPACE, ENTER, QUOTE, RETURN, SPACE, and TAB
are constants that refer to keyboard characters. For example, to test whether the last key pressed was the Space bar, use the following statement:
-- Lingo syntax if _key.keyPressed() = SPACE then beep()
In JavaScript syntax, you can access predefined constants using some of the data types that are unique to JavaScript syntax. For example, the Number object contains constants such as
Number.MAX_VALUE and Number.NaN, the Math object contains constants such as Math.PI and Math.E, and so on.
Note: This reference does not provide in-depth information about the predefined constants in JavaScript syntax. For more information on these constants, see one of the many third-party resources on the subject.
In JavaScript syntax, you can also define your own custom constants by using the const keyword. For example, the following statement creates a constant named
items, and assigns it a value of 20.
This value cannot be changed after it has been created.
// JavaScript syntax const items = 20;
For more information on constants, see Chapter 9, “Constants,” on page 151.

Symbols

A symbol is a string or other value in Lingo that begins with the pound (
#) sign.
Symbols are user-defined constants. Comparisons using symbols can usually be performed very quickly, providing more efficient code.
For example, the first statement below runs more quickly than the second statement:
-- Lingo syntax userLevel = #novice userLevel = "novice"
Symbols cannot contain spaces or punctuation.
In both Lingo and JavaScript syntax, convert a string to a symbol by using the
-- Lingo syntax x = symbol("novice") -- results in #novice
symbol() method.
// JavaScript syntax var x = symbol("novice"); // results in #novice
Convert a symbol back to a string by using the string() function (Lingo) or the toString() method (JavaScript syntax).
-- Lingo syntax x = string(#novice) -- results in "novice"
// JavaScript syntax var x = symbol("novice").toString(); // results in "novice"
20 Chapter 2: Director Scripting Essentials
In JavaScript syntax, you cannot compare symbols of the same name to determine whether they refer to the same symbol. To compare symbols of the same name, you must first convert them to strings by using the
toString() method, and then perform the comparison.

Variables

Director uses variables to store and update values. As the name implies, a variable contains a value that can be changed or updated as a movie plays. By changing the value of a variable as the movie plays, you can do things such as store a URL, track the number of times a user takes part in an online chat session, record whether a network operation is complete, and many more options.
It is a good idea always to assign a variable a known value the first time you declare the variable. This is known as initializing a variable. Initializing variables makes it easier to track and compare the variable’s value as the movie plays.
Variables can be global or local. A local variable exists only as long as the handler in which it is defined is running. A global variable can exist and retain its value as long as Director is running, including when a movie branches to another movie. A variable can be global within an individual handler, a specific script, or an entire movie; the scope depends on how the global variable is initialized.
If you want a variable to be available throughout a movie, it is good practice to declare it in an
prepareMovie
ensures that the variable is available from the very start of the movie.
For more information on using both global and local variables, see “Using global variables”
on page 22 and “Using local variables” on page 24.

Storing and updating values in variables

Variables can hold data for any of the data types found in Director, such as integers, strings, or
FALSE values, symbols, lists, or the result of a calculation. Use the equals (=) operator to store
the values of properties and variables.
As mentioned in the Data types section of this reference, variables in both Lingo and JavaScript syntax are dynamically typed, which means that they can contain different types of data at different times. (The ability to change a variable’s type distinguishes Lingo from other languages such as Java and C++, in which a variable’s type cannot be changed.)
For example, the statement assigned the variable an integer. If you subsequently use the statement becomes a string variable, because the variable now contains a string.
You can convert a string to a number by using the method (JavaScript syntax), or a number to a string by using the string() function (Lingo) or the
toString() method (JavaScript syntax).
The values of some properties can be both set (the value is assigned) and returned (the value is retrieved), and some property values can only be returned. Properties whose values can be both set and returned are called read/write, and those that can only be returned are called read-only.
Often these are properties that describe some condition that exists outside the control of Director. For example, you cannot set the of channels within a movie that contains Macromedia Shockwave content. However, you can return the number of channels by referring to the
(Lingo) or a function prepareMovie() (JavaScript syntax) handler. This
x = 1 creates the variable x, which is an integer variable because you
x = "one", the variable x
value() function (Lingo) or the parseInt()
numChannels cast member property, which indicates the number
numChannels property of a cast member.
on
TRUE
Variables 21
To assign a value to a variable:
Use the equals (=) operator.
For example, the following statement assigns a URL to the variable
// JavaScript syntax var placesToGo = "http://www.macromedia.com";
Variables can also hold the results of mathematical operations. For example, the following statement adds the result of an addition operation to the variable
-- Lingo syntax mySum = 5 + 5 -- this sets mySum equal to 10
As another example, the following statement returns the cast member assigned to sprite 2 by retrieving the value of the sprite’s
-- Lingo syntax textMember = sprite(2).member
member property and places it into the variable textMember.
It is good practice to use variable names that indicate what the variable is used for. This makes your scripts easier to read. For example, the variable
mySum indicates that the variable contains a
sum of numbers.
To test the values of properties or variables:
placesToGo:
mySum:
Use the put() or the trace() functions in the Message window or check the values in the
Watch er wi ndow ; ( both Lingo and JavaScript syntax).
For example, the following statement displays the value assigned to the variable Message window.
-- Lingo syntax myNumber = 20 * 7 put(myNumber) -- displays 140 in the Message window
put() and trace() provide identical functionality and are available to
myNumber in the
// JavaScript syntax var myNumber = 20 * 7; trace(myNumber) // displays 140 in the Message window

Using global variables

Global variables can be shared among handlers, scripts, or movies. A global variable exists and retains its value as long as Director is running or until you call the
clearGlobals() method.
In Macromedia Shockwave Player, global variables persist among movies displayed by the
goToNetMovie() method, but not among those displayed by the goToNetPage() method.
Every handler that declares a variable as global can use the variable’s current value. If the handler changes the variable’s value, the new value is available to every other handler that treats the variable as global.
It is good practice to start the names of all global variables with a lowercase g. This helps identify which variables are global when you examine your code.
Director provides a way to display all current global variables and their current values and to clear the values of all global variables.
22 Chapter 2: Director Scripting Essentials
To display all current global variables and their current values:
Use the Global object’s showGlobals() method in the Message window.
For more information on the Message window, see “Debugging in the Message window”
on page 87.
To clear all current global variables:
Use the Global object’s clearGlobals() method in the Message window to set the value of all
global variables to
To monitor the values of global variables during movie playback, use the Object inspector. For more information on the Object inspector, see “Debugging in the Object inspector” on page 91.
Global variables in Lingo
In Lingo, variables are considered local by default, and you do not need to precede the variable name with any keyword. To declare a global variable, you must precede the variable with the keyword
global.
If you declare a global variable at the top of a script and before any handlers, the variable is available to all handlers in that specific script. If you declare a global variable within a handler, the variable is available only to that handler; however, if you declare a global variable with the same name within two separate handlers, an update to the variable’s value in one handler will also be reflected in the variable in the other handler.
The following example illustrates working with two global variables: to all handlers in the script, and other handlers that declare it on the first line of the handler.
-- Lingo syntax global gScript -- gScript is available to all handlers
VOID (Lingo) or undefined (JavaScript syntax).
gScript, which is available
gHandler, which is available within its defining handler and any
on mouseDown
global gHandler gScript = 25 gHandler = 30
end
on mouseUp
global gHandler trace(gHandler) -- displays 30
end
In Lingo, when you use the term global to define global variables, the variables automatically have
VOID as their initial value.
Global variables in JavaScript syntax
In JavaScript syntax, variables are considered global by default. The scope of a global variable can be determined by how and where it is declared.
If you declare a variable within a JavaScript syntax function without preceding the variable
name with the keyword script.
var, the variable is available to all functions within its containing
If you declare a variable outside a JavaScript syntax function, with or without the keyword var,
the variable is available to all functions within its containing script.
Variables 23
If you declare a variable inside or outside a JavaScript syntax function by using the syntax
_global.varName, the variable is available to all scripts within a movie.
The following example uses the syntax
gMovie as global. This variable is available to all scripts within the movie.
// JavaScript syntax _global.gMovie = 1; // Declare gMovie in one script
// Create a function in a separate script that operates on gMovie function mouseDown() {
_global.gMovie++; return(_global.gMovie);
}
The following example declares the global variable gScript in one script. This variable is available only to functions within that script.
// JavaScript syntax var gScript = 1; // Declare gScript in a script
// gScript is available only to functions in the script that defines it function mouseDown() {
gScript++; return(gScript);
}
In JavaScript syntax, when you define variables before any handlers, the variables automatically have
undefined as their initial value.

Using local variables

A local variable exists only as long as the handler in which it is defined is running. However, after a local variable is created, you can use the variable in other expressions or change its value while a script is still within the handler that defined the variable.
Treating variables as local is a good idea when you want to use a variable only temporarily in one handler. This helps you avoid unintentionally changing the value in another handler that uses the same variable name.
_global.gMovie in one script to declare the variable
To create a local variable:
In Lingo, assign the variable a value using the equals (=) operator.
In JavaScript syntax, inside a function precede the variable name with the keyword var, and
then assign the variable a value using the equals operator.
Note: Because JavaScript syntax variables are global by default, if you attempt to declare a local variable inside a function without using the keyword behavior. Therefore, although using local JavaScript syntax variables using
To display all current local variables in the handler:
var is optional, it is strongly recommended that you declare all
var to avoid any unexpected behavior.
var, your script could produce unexpected
In Lingo only, use the showLocals() function.
In Lingo, you can use this method in the Message window or in handlers to help with debugging. The result appears in the Message window. The JavaScript syntax.
To monitor the values of local variables during movie playback, use the Object inspector. For more information on the Object inspector, see “Debugging in the Object inspector” on page 91.
24 Chapter 2: Director Scripting Essentials
showLocals() method does not apply to

Operators

Operators are elements that tell Lingo and JavaScript syntax scripts how to combine, compare, or modify the values of an expression. Many of the operators in Director are shared between Lingo and JavaScript syntax, and some are unique to each language.
Some types of operators include the following:
Arithmetic operators (such as +, -, /, and *)
Comparison operators (such as <, >, and >=), which compare two arguments
Logical operators (not, and, or), which combine simple conditions into compound ones
String operators (such as &, &&, and +), which join, or concatenate, strings of characters
Note: There are many more types of operators in JavaScript syntax than there are in Lingo, and not all of them are covered in this reference. For more information on additional operators in JavaScript 1.5, see one of the many third-party resources on the subject.
The items that operators act upon are called operands. In Lingo, there are only binary operators. In JavaScript syntax, there are both binary and unary operators. A binary operator requires two operands, one before the operator and one after the operator. A unary operator requires a single operand, either before or after the operator.
In the following example, the first statement illustrates a binary operator, where the variables and
y are operands and the plus (+) sign is the operator. The second statement illustrates a unary
operator, where the variable
// JavaScript syntax x + y; // binary operator i++; // unary operator
For reference information on operators, see Chapter 13, “Operators,” on page 595.
i is the operand and ++ is the operator.
x

Understanding operator precedence

When two or more operators are used in the same statement, some operators take precedence over others in a precise hierarchy to determine which operators to execute first. This is called the operators’ precedence order. For example, multiplication is always performed before addition. However, items in parentheses take precedence over multiplication. In the following example, without parentheses the multiplication in this statement occurs first:
-- Lingo syntax total = 2 + 4 * 3 -- results in a value of 14
When parentheses surround the addition operation, addition occurs first:
-- Lingo syntax total = (2 + 4) * 3 -- results in a value of 18
Descriptions of the types of operators and their precedence order follow. Operators with higher precedence are performed first. For example, an operator whose precedence order is 5 is performed before an operator whose precedence order is 4. Operations that have the same order of precedence are performed left to right.
Operators 25

Arithmetic operators

Arithmetic operators add, subtract, multiply, divide, and perform other arithmetic operations. Parentheses and the minus sign are also arithmetic operators.
Operator Effect Precedence
( )
-
*
mod
/
%
++
--
+
-
Note: In Lingo, when only integers are used in an operation, the result is an integer. Using integers and floating-point numbers in the same calculation results in a floating-point number. In JavaScript syntax, all calculations essentially result in floating-point numbers.
Groups operations to control precedence order. 5
When placed before a number, reverses the sign of a number. 5
Performs multiplication. 4
(Lingo only) Performs modulo operation. 4
Performs division. 4
(JavaScript syntax only) Returns the integer remainder of dividing two operands.
(JavaScript syntax only) Adds one to its operand. If used as a prefix operator ( as a postfix operator ( adding one.
(JavaScript syntax only) Subtracts one from its operand. The return value is analogous to that of the increment operator.
When placed between two numbers, performs addition. 3
When placed between two numbers, performs subtraction. 3
++x), returns the value of its operand after adding one. If used
x++), returns the value of its operand before
4
4
4
When dividing one integer by another does not result in a whole number, Lingo rounds the result down to the nearest integer. For example, the result of
4/3 is 1. In JavaScript syntax, the actual
floating-point value, 1.333, is returned.
To force Lingo to calculate a value without rounding the result, use values in an expression. For example, the result of
4/float(3) is 1.333.
float() on one or more

Comparison operators

Comparison operators compare two values and determine whether the comparison is true or false.
Operator Meaning Precedence
==
===
!=
26 Chapter 2: Director Scripting Essentials
(JavaScript syntax only) Two operands are equal. If the operands are not of the same data type, JavaScript syntax attempts to convert the operands to an appropriate data type for the comparison.
(JavaScript syntax only) Two operands are equal and of the same data type
(JavaScript syntax only) Two operands are not equal. If the operands are not of the same data type, JavaScript syntax attempts to convert the operands to an appropriate data type for the comparison.
1
1
1
Operator Meaning Precedence
!==
<>
<
<=
>
>=
=
(JavaScript syntax only) Two operands are not equal and/or not of the same type
(Lingo only) Two operands are not equal 1
The left operand is less than the right operand 1
The left operand is less than or equal to the right operand 1
The left operand is greater than the right operand 1
The left operand is great than or equal to the right operand 1
(Lingo only) Two operands are equal 1

Assignment operators

Assignment operators assign a value to its left operand based on the value of its right operand. With the exception of the basic assignment operator, equal (
=), all of the following shortcut
assignment operators apply only to JavaScript syntax.
Operator Meaning Precedence
= Equal 1
x += y (JavaScript syntax only) x = x + y 1
x -= y (JavaScript syntax only) x = x - y 1
x *= y (JavaScript syntax only) x = x * y 1
x /= y (JavaScript syntax only) x = x / y 1
x %= y (JavaScript syntax only) x = x % y 1
1

Logical operators

Logical operators test whether two logical expressions are true or false.
Use care when using logical operators and string operators in Lingo and JavaScript syntax. For example, in JavaScript syntax true, but in Lingo,
&& is a string operator that concatenates two strings and inserts a space
&& is a logical operator that determines whether two expressions are
between the two expressions.
Operator Effect Precedence
and
&&
or
||
not
!
(Lingo only) Determines whether both expressions are true 4
(JavaScript syntax only) Determines whether both expressions are true 4
(Lingo only) Determines whether either or both expressions are true 4
(JavaScript syntax only) Determines whether either or both expressions are true
(Lingo only) Negates an expression 5
(JavaScript syntax only) Negates an expression 5
Operators 27
4
The not (Lingo) or ! (JavaScript syntax) operator is useful for toggling a TRUE or FALSE value to its opposite. For example, the following statement turns on the sound if it’s currently off and turns off the sound if it’s currently on:
-- Lingo syntax _sound.soundEnabled = not (_sound.soundEnabled)
// JavaScript syntax _sound.soundEnabled = !(_sound.soundEnabled);

String operators

String operators combine and define strings.
Use care when using logical operators and string operators in Lingo and JavaScript syntax. For example, in JavaScript syntax true, but in Lingo,
&& is a string operator that concatenates two strings and inserts a space
&& is a logical operator that determines whether two expressions are
between the two expressions.
Operator Effect Precedence
& (Lingo only) Concatenates two strings 2
+ (JavaScript syntax only) Concatenates two string values and returns a
third string that is the union of the two operands
+= (JavaScript syntax only) Concatenates one string variable and one
string value, and assigns the returned value to the string variable
&& (Lingo only) Concatenates two strings and inserts a space between
the two
" Marks the beginning or end of a string. 1
2
2
2

Conditional constructs

By default, Director always executes script statements starting with the first statement and continuing in order until it reaches the final statement or a statement that instructs a script to go somewhere else.
The order in which statements are executed affects the order in which you should place statements. For example, if you write a statement that requires some calculated value, you need to put the statement that calculates the value first.
The first statement in the following example adds two numbers, and the second statement assigns a string representation of the sum to a field cast member named Stage. The second statement could not be placed before the first statement because the variable has not yet been defined.
-- Lingo syntax x = 2 + 2 member("Answer").text = string(x)
// JavaScript syntax var x = 2 + 2; member("Answer").text = x.toString();
28 Chapter 2: Director Scripting Essentials
Answer, which appears on the
x
Both Lingo and JavaScript syntax provide conventions for altering the default execution order or script statements, and for performing actions depending on specific conditions. For example, you may want to do the following in your scripts:
Execute a set of statements if a logical condition is true, or execute alternate statements if the
logical condition is false.
Evaluate an expression and attempt to match the expression’s value to a specific condition.
Execute a set of statements repeatedly until a specific condition is met.

Testing for logical conditions

To execute a statement or set of statements if a specified condition is true or false, you use the
if...then...else (Lingo) or if...else (JavaScript syntax) structures. For example, you can
create an
if...then...else or if...then structure that tests whether text has finished
downloading from the Internet and, if it has, then attempts to format the text. These structures use the following pattern to test for logical conditions:
In both Lingo and JavaScript syntax, statements that check whether a condition is true or false
begin with the term
if.
In Lingo, if the condition exists, the statements following the term then are executed. In
JavaScript syntax, curly brackets ( surround each individual
if, else, or else if statement.
{ }) take the place of the Lingo term then, and must
In both Lingo and JavaScript syntax, if the condition does not exist, scripts skip to the next
statement in the handler using the term
else or else if.
In Lingo, the term end if specifies the end of the if test. In JavaScript syntax, the if test ends
automatically, so there is no term that explicitly ends the test.
To optimize your script’s performance, test for the most likely conditions first.
The following statements test several conditions. The term perform if previous conditions are false:
-- Lingo syntax if _mouse.mouseMember = member(1) then
_movie.go("Cairo")
else if _mouse.mouseMember = member(2) then
_movie.go("Nairobi")
else
_player.alert("You’re lost.")
end if
else if specifies alternative tests to
// JavaScript syntax if (_mouse.mouseMember = member(1)) {
_movie.go("Cairo");
} else if (_mouse.mouseMember = member(2)) {
_movie.go("Nairobi");
} else {
_player.alert("You’re lost.");
}
Conditional constructs 29
When writing if...then structures in Lingo, you can place the statement or statements following carriage return after
then in the same line as then, or you can place them on their own line by inserting a
then. If you insert a carriage return, you must also include an end if
statement at the end of the if...then structure.
When writing following carriage return after
if structures in JavaScript syntax, you can place the statement or statements
if in the same line as if, or you can place them on their own line by inserting a
if.
For example, the following statements are equivalent:
-- Lingo syntax if _mouse.mouseMember = member(1) then _movie.go("Cairo")
if _mouse.mouseMember = member(1) then
_movie.go("Cairo")
end if
// JavaScript syntax if (_mouse.mouseMember = member(1)) { _movie.go("Cairo"); }
if (_mouse.mouseMember = member(1)) {
_movie.go("Cairo");
}
For reference information on using the if...then...else and if...else structures, see “if”
on page 209.

Evaluating and matching expressions

case (Lingo) or switch...case (JavaScript syntax) structures are shorthand alternatives to
The using
if...then...else or if...then structures when setting up multiple branching
structures. The than many
In Lingo, the condition to test for follows the term
case and switch...case structures are often more efficient and easier to read
if...then...else or if...then structures.
case in the first line of the case structure.
The comparison goes through each line in order until Lingo encounters an expression that matches the test condition. When a matching expression is found, Director executes the Lingo that follows the matching expression.
In JavaScript syntax, the condition to test for follows the term structure. Each comparison in the test follows the term Each
case comparison can be ended by using the optional term break. Including the term break
breaks the program out of the
switch structure and executes any statements following the
switch in the first line of the
case for each line that contains a test.
structure. If break is omitted, the following case comparison is executed.
A
case or switch...case structure can use comparisons as the test condition.
For example, the following case and switch...case structures test which key the user pressed most recently and responds accordingly.
If the user pressed A, the movie goes to the frame labeled Apple.
If the user pressed B or C, the movie performs the specified transition and then goes to the
frame labeled Oranges.
30 Chapter 2: Director Scripting Essentials
If the user pressed any other letter key, the computer beeps.
-- Lingo syntax case (_key.key) of
"a" : _movie.go("Apple")
"b", "c":
_movie.puppetTransition(99) _movie.go("Oranges")
otherwise: _sound.beep() end case
// JavaScript syntax switch (_key.key) {
case "a" :
_movie.go("Apple"); break;
case "b":
_movie.puppetTransition(99); _movie.go("Oranges"); break;
case "c":
_movie.puppetTransition(99); _movie.go("Oranges"); break;
default: _sound.beep() }
Note: In JavaScript syntax, only one comparison can be made per case statement.
For reference information on using case structures, see “case” on page 203.

Repeating actions

In both Lingo and JavaScript syntax, you can repeat an action a specified number of times or while a specific condition exists.
In Lingo, to repeat an action a specified number of times you use a Specify the number of times to repeat as a range following
repeat with.
In JavaScript syntax, to repeat an action a specified number of times you use the The
for structure takes three parameters: the first parameter typically initializes a counter
repeat with structure.
for structure.
variable, the second parameter specifies a condition to evaluate each time through the loop, and the third parameter is typically used to update or increment the counter variable.
The
repeat with and for structures are useful for performing the same operation on a series of
objects. For example, the following loop makes Background Transparent the ink for sprites 2 through 10:
-- Lingo syntax repeat with n = 2 to 10
sprite(n).ink = 36
end repeat
// JavaScript syntax for (var n=2; n<=10; n++) {
sprite(n).ink = 36;
}
Conditional constructs 31
The following example performs a similar action, but with decreasing numbers:
-- Lingo syntax repeat with n = 10 down to 2
sprite(n).ink = 36
end repeat
// JavaScript syntax for (var n=10; n>=2; n--) {
sprite(n).ink = 36;
}
In Lingo, to repeat a set of instructions as long as a specific condition exists, use the repeat
while
structure.
In JavaScript syntax, to repeat a set of instructions as long as a specific condition exists, use the
while structure.
For example, the following statements instruct a movie to beep continuously whenever the mouse button is being pressed:
-- Lingo syntax repeat while _mouse.mouseDown
_sound.beep()
end repeat
// JavaScript syntax while (_mouse.mouseDown) {
_sound.beep();
}
Both Lingo and JavaScript syntax scripts continue to loop through the statements inside the loop until the condition is no longer true, or until one of the statements sends the script outside the loop. In the previous example, the script exits the loop when the mouse button is released because the
mouseDown condition is no longer true.
In Lingo, to exit a loop, use the
In JavaScript syntax, to exit a loop you can use the term
exit repeat statement.
break. A loop also automatically exits
when a condition is no longer true.
For example, the following statements make a movie beep while the mouse button is pressed, unless the mouse pointer is over sprite 1. If the pointer is over sprite 1, the script exits the loop and stops beeping. The
rollover() method indicates whether the pointer is over the
specified sprite.
-- Lingo syntax repeat while _mouse.stillDown
_sound.beep() if _movie.rollOver(1) then exit repeat
end repeat
// JavaScript syntax while (_mouse.stillDown) {
_sound.beep(); if (_movie.rollOver(1)) {
break; }
}
For reference information on the repeat while and while structures, see “repeat while”
on page 220.
32 Chapter 2: Director Scripting Essentials

Events, messages, and handlers

A key component to creating powerful, useful scripts is an understanding of the concepts and functionality of events, messages, and handlers. Understanding the order in which events and messages are sent and received will help you determine exactly when specific scripts or parts of scripts should run. It will also help you debug scripts when specific actions are not occurring when you expect them to occur.
When a movie plays, the following occurs:
1 Events occur in response to either a system or user-defined action 2 Messages that correspond to these events are sent to the scripts in a movie 3 Handlers within scripts contain the instructions that run when a specific message is received
The name of an event corresponds to the name of the message it generates, and the handler that handles the event corresponds to both the event and the message. For example, when the event named
mouseDown occurs, Director generates and sends to scripts a message named mouseDown,
which would in turn be handled by a handler named
mouseDown.

Events

There are two categories of events that occur when a movie plays:
System events occur without a user interacting with the movie, and are predefined and
named in Director. For example, when the playhead enters a frame, when a sprite is clicked, and so on.
User-defined events occur in response to actions that you define. For example, you could
create an event that occurs when the background color of a sprite changes from red to blue, when a sound has played five times, and so on.
Many system events, such as in a predefined order while a movie is playing. Other system events, particularly mouse events such as
mouseDown, mouseUp, and so on, do not necessarily occur automatically while a movie is
playing, but rather when a user triggers them.
For example, when a movie first starts, the
prepareFrame event always occurs second, and so on. However, the mouseDown and mouseUp
events may never occur in a movie unless a user triggers them by clicking the movie.
The following lists illustrate the system events that always occur during a movie, and the order in which they occur.
prepareFrame, beginSprite, and so on, occur automatically and
prepareMovie event always occurs first, the
When the movie first starts, events occur in the following order:
1 prepareMovie 2 prepareFrame Immediately after the prepareFrame event, Director plays sounds, draws
sprites, and performs any transitions or palette effects. This event occurs before the event. A
prepareFrame handler is a good location for script that you want to run before the
enterFrame
frame draws.
3 beginSprite This event occurs when the playhead enters a sprite span. 4 startMovie This event occurs in the first frame that plays.
Events, messages, and handlers 33
When the movie encounters a frame, events occur in the following order:
1 beginSprite This event occurs only if new sprites begin in the frame. 2 stepFrame
3 prepareFrame 4 enterFrame After enterFrame and before exitFrame, Director handles any time delays
required by the tempo setting, idle events, and keyboard and mouse events.
5 exitFrame 6 endSprite This event occurs only if the playhead exits a sprite in the frame.
When a movie stops, events occur in the following order:
1 endSprite This event occurs only if sprites currently exist in the movie. 2 stopMovie
For reference information on the predefined system events in Director, see Chapter 10, “Events
and Messages,” on page 159.

Messages

To run the appropriate set of script statements at the right time, Director must determine what is occurring in the movie and which statements to run in response to certain events.
Director sends messages to indicate when specific events occur in a movie, such as when sprites are clicked, keyboard keys are pressed, a movie starts, the playhead enters or exits a frame, or a script returns a certain result.
The general order in which messages are sent to objects is as follows:
1 Messages are sent first to behaviors attached to a sprite involved in the event. If a sprite has more
than one behavior attached to it, behaviors respond to the message in the order in which they are attached to the sprite.
2 Messages are sent next to a script attached to the cast member assigned to the sprite. 3 Messages are then sent to behaviors attached to the current frame. 4 Messages are sent last to movie scripts.
Although you can define your own message names, most common events that occur in a movie have built-in message names.
For reference information on the built-in messages in Director, see Chapter 10, “Events and
Messages,” on page 159.

Defining custom messages

In addition to using built-in message names, you can define your own messages and corresponding handler names. A custom message can call another script, another handler, or the statement’s own handler. When the called handler stops executing, the handler that called it resumes.
A custom message and handler name must meet the following criteria:
It must start with a letter.
It must include alphanumeric characters only (no special characters or punctuation).
34 Chapter 2: Director Scripting Essentials
It must consist of one word or of several words connected by an underscore—no spaces
are allowed.
It must be different from the name of any predefined Lingo or JavaScript syntax element.
Using predefined Lingo or JavaScript keywords for message and handler names can create confusion. Although it is possible to explicitly replace or extend the functionality of a Lingo or JavaScript element by using it as a message or handler name, this should be done only in certain advanced situations.
When you have multiple handlers with similar functions, it is useful to give them names that have similar beginnings so they appear together in an alphabetical listing, such as the listing that can be displayed by the Edit > Find > Handler command.

Handlers

A handler is a set of statements within a script that runs in response to a specific event and subsequent message. Although Director contains built-in events and messages, you must create your own custom handlers for each event/message pair that you want to handle.
Deciding where to place handlers
You can place handlers in any type of script, and a script can contain multiple handlers. It’s a good idea to group related handlers in a single place, though, for easier maintenance.
The following are some useful guidelines for many common situations:
To associate a handler with a specific sprite, or to have a handler run in response to an action
on a specific sprite, put the handler in a behavior attached to the sprite.
To set up a handler that should be available any time the movie is in a specific frame, put the
handler in a behavior attached to the frame. For example, to have a handler respond to a mouse click while the playhead is in a frame,
regardless of where the click occurs, place a behavior rather than in a sprite behavior.
mouseDown or mouseUp handler in the frame
To set up a handler that runs in response to messages about events anywhere in the movie, put
the handler in a movie script.
To set up a handler that runs in response to an event that affects a cast member, regardless of
which sprites use the cast member, put the handler in a cast member script.
Determining when handlers receive a message
After sending a message to scripts, Director checks for handlers in a definite order.
1 Director first checks whether a handler exists in the object from which the message was sent. If
a handler is found, the message is intercepted, and the script in the handler runs.
2 If no handler is found, Director then checks cast member, in ascending o rder, for any associated
movie scripts that might contain a handler for the message. If a handler is found, the message is intercepted, and the script in the handler runs.
3 If no handler is found, Director then checks whether a frame script contains a handler for the
message. If a handler is found, the message is intercepted, and the script in the handler runs.
4 If no handler is found, Director then checks sprites, in ascending order, for any scripts
associated with the sprites that might contain a handler for the message. If a handler is found, the message is intercepted, and the script in the handler runs.
Events, messages, and handlers 35
After a handler intercepts a message, the message does not automatically pass on to the remaining locations. However, in Lingo you can use the
pass() method to override this default rule and
pass the message to other objects.
If no matching handler is found after the message passes to all possible locations, Director ignores the message.
The exact order of objects to which Director sends a message depends on the message. For information on the sequence of objects to which Director sends specific messages, see the entry for each message in Chapter 10, “Events and Messages,” on page 159.
Using parameters to pass values to a handler
By using parameters for values, you can give the handler exactly the values that it needs to use at a specific time, regardless of where or when you call the handler in the movie. Parameters can be optional or required, depending on the situation.
To create parameters for a handler:
In Lingo, put the parameters after the handler name. In JavaScript syntax, put the parameters
within parentheses, and then put them after the handler name. Use commas to separate multiple parameters.
When you call a handler, you must provide specific values for the parameters that the handler uses. You can use any type of value, such as a number, a variable that has a value assigned, or a string of characters. Values in the calling statement must be in the order that they follow in the handler’s parameters, and they must be surrounded by parentheses.
In the following example, the variable assignment passed the two values 2 and 4. The
addThem handler replaces the parameter placeholders a and b
with the two values passed to it, stores the result in the local variable
return to send the result back to the original method, which is then assigned to mySum.
Because 2 is first in the list of parameters, it is substituted for is second in the list of parameters, it is substituted for
-- Lingo syntax mySum = addThem(2, 4) -- calling statement
mySum calls the method addThem, which is
c, and then uses the keyword
a in the handler. Likewise, because 4
b in the handler.
on addThem a, b -- handler
c = a + b return c -- returns the result to the calling statement
end
// JavaScript syntax var mySum = addThem(2, 4); // calling statement
function addThem(a, b) { // handler
c = a + b; return c; // returns the result to the calling statement
}
In Lingo, when you call a custom method from an object, a reference to the script object in memory is always passed as an implied first parameter to the handler for that method. This means that you must account for the script object reference in your handler.
36 Chapter 2: Director Scripting Essentials
For example, consider that you wrote a custom sprite method named jump() that takes a single integer as a parameter, and you placed the method in a behavior. When you call
jump() from a
sprite object reference, the handler must also include a parameter that represents the script object reference, and not just the single integer. In this case, the implied parameter is represented by the keyword
-- Lingo syntax myHeight = sprite(2).jump(5)
on jump(me,a)
end
on jump(a)
end
me, but any term will work.
return a + 15 -- this handler works correctly, and returns 20
return a + 15 -- this handler does not work correctly, and returns 0
You can also use expressions as values. For example, the following statement substitutes 3+6 for a and
8>2 (or 1, representing TRUE) for b, and would return 10:
-- Lingo syntax mySum = addThem(3+6, 8>2)
In Lingo, each handler begins with the word on followed by the message that the handler should respond to. The last line of the handler is the word
end, but this is optional.
In JavaScript syntax, each handler begins with the word
end. You can repeat the handler’s name after
function followed by the message that
the handler should respond to. The statements that comprise the handler are surrounded by opening and closing brackets, as are all JavaScript syntax functions.
Returning results from handlers
Often, you want a handler to report some condition or the result of some action.
To return results from a handler:
Use the keyword return to have a handler report a condition or the result of an action. For
example, the following
-- Lingo syntax on findColor
return sprite(1).foreColor end
// JavaScript syntax function findColor() {
return(sprite(1).foreColor); }
You can also use the keyword return by itself to exit from the current handler and return no value. For example, the following jump handler returns nothing if the aVal parameter equals 5; otherwise, it returns a value.
-- Lingo syntax on jump(aVal)
if aVal = 5 then return
aVal = aVal + 10 return aVal
end
findColor handler returns the current color of sprite 1:
Events, messages, and handlers 37
// JavaScript syntax function jump(aVal) {
if(aVal == 5) {
return; } else {
aVal = aVal + 10;
return(aVal); }
}
When you define a handler that returns a result, you must use parentheses after the handler when you call it from another handler. For example, the statement
findColor
handler and then displays the result in the Message window.
put(findColor()) calls the on

Linear lists and property lists

In your scripts, you may want to track and update lists of data, such as a series of names or the values assigned to a set of variables. Both Lingo and JavaScript syntax have access to linear lists and property lists. In a linear list, each element in the list is a single value. In a property list, each element in the list contains two values; the first value is a property name, and the second value is the value associated with that property.
Because both Lingo and JavaScript syntax have access to linear and property lists, it is recommended that you use linear lists and property lists if values in your code are shared between Lingo and JavaScript syntax scripts.
If values in your code are used only in JavaScript syntax scripts, it is recommended that you use JavaScript Array objects to work with lists of data. For more information on using arrays, see
“JavaScript syntax arrays” on page 45.

Creating linear lists

You create a linear list in one of the following ways:
In Lingo, use either the top level list() function or the list operator ([ ]), using commas to
separate items in the list.
In JavaScript syntax, use the top level list() function, using commas to separate items in
the list.
The index into a linear list always starts with 1.
When you use the top level function. This function is useful when you use a keyboard that does not provide square brackets.
All of the following statements create a linear list of three names and assign it to a variable.
-- Lingo syntax workerList = ["Bruno", "Heather", "Carlos"] -- using the Lingo list operator workerList = list("Bruno", "Heather", "Carlos") -- using list()
// JavaScript syntax var workerList = list("Bruno", "Heather", "Carlos"); // using list()
38 Chapter 2: Director Scripting Essentials
list() function, you specify the list’s elements as parameters of the
You can also create empty linear lists. The following statements create empty linear lists.
-- Lingo syntax workerList = [] -- using the Lingo list operator workerList = list() -- using list() with no parameters
// JavaScript syntax var workerList = list(); // using list() with no parameters

Creating property lists

You create a property list in one of the following ways:
In Lingo, use either the top level propList() function or the list operator ([:]). When using
the list operator to create a property list, you can use a either a colon to designate name/value elements and commas to separate elements in the list, or commas to both designate name/value elements and to separate elements in the list.
In JavaScript syntax, use the top level propList() function and insert commas to both
designate name/value elements and to separate elements in the list.
When you use the top level parameters of the function. This function is useful when you use a keyboard that does not provide square brackets.
Properties can appear more than once in a given property list.
All of the following statements create a property list with four property names—
right, and bottom—and their corresponding values.
-- Lingo syntax sprite1Loc = [#left:100, #top:150, #right:300, #bottom:350] sprite1Loc = ["left",400, "top",550, "right",500, "bottom",750] sprite1Loc = propList("left",400, "top",550, "right",500, "bottom",750)
propList() function, you specify the property list’s elements as
left, top,
// JavaScript syntax var sprite1Loc = propList("left",400, "top",550, "right",500, "bottom",750);
You can also create empty property lists. The following statements create empty property lists.
-- Lingo syntax sprite1Loc = [:] -- using the Lingo property list operator sprite1Loc = propList() -- using propList() with no parameters
// JavaScript syntax var sprite1Loc = propList(); // using propList() with no parameters

Setting and retrieving items in lists

You can set and retrieve individual items in a list. The syntax differs for linear and property lists.
To set a value in a linear list, do one of the following:
Use the equals (=) operator.
Use the setAt() method.
Linear lists and property lists 39
The following statements illustrate defining the linear list workerList that contains one value,
Heather, and then adds Carlos as the second value in the list.
-- Lingo syntax workerList = ["Heather"] -- define a linear list workerList[2] = "Carlos" -- set the second value using the equal operator workerList.setAt(2, "Carlos") -- set the second value using setAt()
// JavaScript syntax var workerList = list("Heather"); // define a linear list workerList[2] = "Carlos"; // set the second value using the equal operator workerList.setAt(2, "Carlos"); // set the second value using setAt()
To retrieve a value in a linear list:
Use the list variable followed by the number that indicates the value’s position in the list. Place
square brackets around the number.
Use the getAt() method.
The following statements create the linear list the list to the variable
-- Lingo syntax workerList = ["Bruno", "Heather", "Carlos"] -- define a linear list name2 = workerList[2] -- use bracketed access to retrieve "Heather" name2 = workerList.getAt(2) -- use getAt() to retrieve "Heather"
// JavaScript syntax var workerList = list("Bruno", "Heather", "Carlos"); var name2 = workerList[2] // use bracketed access to retrieve "Heather" var name2 = workerList.getAt(2) // use getAt() to retrieve "Heather"
To set a value in a property list, do one of the following:
name2.
workerList, and then assign the second value in
Use the equals (=) operator.
In Lingo only, use the setaProp() method.
Use dot syntax.
The following Lingo statement uses the equals operator to make with the property
-- Lingo syntax foodList = [:] -- define an empty property list foodList[#Bruno] = "sushi" -- associate sushi with Bruno
Bruno.
The following Lingo statement uses setaprop() to make sushi the new value associated with the property Bruno.
-- Lingo syntax foodList = [:] -- define an empty property list foodList.setaProp(#Bruno, "sushi") -- use setaProp()
sushi the new value associated
// JavaScript syntax foodList = propList() -- define an empty property list foodList.setaProp("Bruno", "sushi") -- use setaProp()
The following statements use dot syntax to set the value associated with Bruno from sushi to
teriyaki.
40 Chapter 2: Director Scripting Essentials
-- Lingo syntax foodList = [#Bruno:"sushi"] -- define a property list trace(foodList) -- displays [#Bruno: "sushi"] foodList.Bruno = "teriyaki" -- use dot syntax to set the value of Bruno trace(foodList) -- displays [#Bruno: "teriyaki"]
// JavaScript syntax var foodList = propList("Bruno", "sushi"); // define a property list trace(foodList); // displays ["Bruno": "sushi"] foodList.Bruno = "teriyaki" // use dot syntax to set the value of Bruno trace(foodList) -- displays [#Bruno: "teriyaki"]
To retrieve a value in a property list, do one of the following:
Use the list variable followed by the name of the property associated with the value. Place
square brackets around the property.
Use the getaProp() or getPropAt() methods.
Use dot syntax.
The following statements use bracketed access to retrieve the values associated with the properties
breakfast and lunch.
-- Lingo syntax
-- define a property list foodList = [#breakfast:"Waffles", #lunch:"Tofu Burger"] trace(foodList[#breakfast]) -- displays "Waffles" trace(foodList[#lunch]) -- displays "Tofu Burger"
// JavaScript syntax // define a property list var foodList = propList("breakfast", "Waffles", "lunch", "Tofu Burger"); trace(foodList["breakfast"]); // displays Waffles trace(foodList["lunch"]); // displays Tofu Burger
The following statements use getaProp() to retrieve the value associated with the property
breakfast, and getPropAt() to retrieve the property at the second index position in the list.
-- Lingo syntax
-- define a property list foodList = [#breakfast:"Waffles", #lunch:"Tofu Burger"] trace(foodList.getaProp(#breakfast)) -- displays "Waffles" trace(foodList.getPropAt(2)) -- displays #lunch
// JavaScript syntax // define a property list var foodList = propList("breakfast", "Waffles", "lunch", "Tofu Burger"); trace(foodList.getaProp("breakfast")) // displays Waffles trace(foodList.getPropAt(2)) // displays lunch
The following statements use dot syntax to access the values associated with properties in a property list.
-- Lingo syntax
-- define a property list foodList = [#breakfast:"Waffles", #lunch:"Tofu Burger"] trace(foodList.breakfast) -- displays "Waffles"
// JavaScript syntax // define a property list var foodList = propList("breakfast", "Waffles", "lunch", "Tofu Burger"); trace(foodList.lunch); // displays Tofu Burger
Linear lists and property lists 41

Checking items in lists

You can determine the characteristics of a list and the number of items the list contains by using the following methods.
To display the contents of a list, use the put() or trace() functions, passing the variable that
contains the list as a parameter.
To determine the number of items in a list, use the count() method (Lingo only) or the
count property.
To determine a list’s type, use the ilk() method.
To determine the maximum value in a list, use the max() method.
To determine the minimum value in a list, use the min() function.
To determine the position of a specific property, use the findPos, findPosNear, or
getOne command.
The following statements use
-- Lingo syntax workerList = ["Bruno", "Heather", "Carlos"] -- define a linear list trace(workerList.count()) -- displays 3 trace(workerList.count) -- displays 3
// JavaScript syntax var workerList = list("Bruno", "Heather", "Carlos"); // define a linear list trace(workerList.count); // displays 3
The following statements use ilk() to determine a list’s type.
-- Lingo syntax x = ["1", "2", "3"] trace(x.ilk()) // returns #list
count() and count to display the number of items in a list.
// JavaScript syntax var x = list("1", "2", "3"); trace(x.ilk()) // returns #list
The following statements use max() and min() to determine the maximum and minimum values in a list.
-- Lingo syntax workerList = ["Bruno", "Heather", "Carlos"] -- define a linear list trace(workerList.max()) -- displays "Heather" trace(workerList.min()) -- displays "Bruno"
// JavaScript syntax var workerList = list("Bruno", "Heather", "Carlos"); // define a linear list trace(workerList.max()); // displays Heather trace(workerList.min()); // displays Bruno
The following statements use findPos to get the index position of a specified property in a property list.
-- Lingo syntax
-- define a property list foodList = [#breakfast:"Waffles", #lunch:"Tofu Burger"] trace(foodList.findPos(#lunch)) -- displays 2
// JavaScript syntax // define a property list var foodList = propList("breakfast", "Waffles", "lunch", "Tofu Burger"); trace(foodList.findPos("breakfast")); // displays 1
42 Chapter 2: Director Scripting Essentials

Adding and deleting items in lists

You can add or delete items in a list by using the following methods.
To add an item at the end of a list, use the append() method.
To add an item at its proper position in a sorted list, use the add() or addProp() methods.
To add an item at a specific place in a linear list, use the addAt() method.
To add an item at a specific position in a property list, use the addProp() method.
To delete an item from a list, use the deleteAt(), deleteOne(), or deleteProp() methods.
To replace an item in a list, use the setAt() or setaProp() methods.
The following statements use
-- Lingo syntax workerList = ["Bruno", "Heather", "Carlos"] -- define a linear list workerList.append("David") trace(workerList) -- displays ["Bruno", "Heather", "Carlos", "David"]
// JavaScript syntax var workerList = list("Bruno", "Heather", "Carlos"); // define a linear list workerList.append("David"); trace(workerList); // displays ["Bruno", "Heather", "Carlos", "David"]
The following statements use addProp() to add a property and an associated value to a property list.
-- Lingo syntax
-- define a property list foodList = [#breakfast:"Waffles", #lunch:"Tofu Burger"] foodList.addProp(#dinner, "Spaghetti") -- adds [#dinner: "Spaghetti"]
append() to add an item to the end of a list.
// JavaScript syntax // define a property list var foodList = propList("breakfast", "Waffles", "lunch", "Tofu Burger"); foodList.addProp("dinner", "Spaghetti"); // adds ["dinner": "Spaghetti"]
You do not have to explicitly remove lists. Lists are automatically removed when they are no longer referred to by any variable. Other types of objects must be removed explicitly, by setting variables that refer to them to
VOID (Lingo) or null (JavaScript syntax).

Copying lists

Assigning a list to a variable and then assigning that variable to a second variable does not make a separate copy of the list. For example, the first statement below creates a list that contains the names of two continents, and assigns the list to the variable assigns the same list to a new variable to
landList also automatically adds Australia to the list continentList. This happens
continentList. In the third statement, adding Australia
landList. The second statement
because both variable names point to the same list object in memory. The same behavior occurs by using an array in JavaScript syntax.
-- Lingo syntax landList = ["Asia", "Africa"] continentList = landList landList.add("Australia") -- this also adds "Australia" to continentList
Linear lists and property lists 43
To create a copy of a list that is independent of another list:
Use the duplicate() method.
For example, the following statements create a list and then make an independent copy of the list.
-- Lingo syntax oldList = ["a", "b", "c"] newList = oldList.duplicate() -- makes an independent copy of oldList
// JavaScript syntax var oldList = list("a", "b", "c"); var newList = oldList.duplicate(); // makes an independent copy of oldList
After newList is created, editing either oldList or newList has no effect on the other.

Sorting lists

Lists are sorted in alphanumeric order, with numbers being sorted before strings. Strings are sorted according to their initial letters, regardless of how many characters they contain. Sorted lists perform slightly faster than unsorted lists.
A linear list is sorted according to the values in the list. A property list is sorted according to the property names in the list or array.
After the values in a linear or property list are sorted, they will remain sorted, even as values are added to or removed from the lists.
To sort a list:
Use the sort() method.
For example, the following statements sort a nonsorted alphabetical list.
-- Lingo syntax oldList = ["d", "a", "c", "b"] oldList.sort() -- results in ["a", "b", "c", "d"]
// JavaScript syntax var oldList = list("d", "a", "c", "b"); oldList.sort(); // results in ["a", "b", "c", "d"]

Creating multidimensional lists

You can also create multidimensional lists that enable you to work with the values of more than one list at a time.
In the following example, the first two statements create the separate linear lists
list1 and list2.
The third statement creates a multidimensional list and assigns it to mdList. To access the values in a multidimensional list, the fourth and fifth statements use brackets to access the values in the list; the first bracket provides access to a specified list, and the second bracket provides access to the value at a specified index position in the list.
-- Lingo syntax list1 = list(5,10) list2 = list(15,20) mdList = list(list1, list2) trace(mdList[1][2]) -- displays 10 trace(mdList[2][1]) -- displays 15
44 Chapter 2: Director Scripting Essentials
// JavaScript syntax var list1 = list(5,10); var list2 = list(15,20); var mdList = list(list1, list2); trace(mdList[1][2]); // displays 10 trace(mdList[2][1]); // displays 15

JavaScript syntax arrays

JavaScript syntax arrays are similar to Lingo-style linear lists in that each element in an array is a single value. One of the main differences between JavaScript syntax arrays and Lingo-style linear lists is that the index into an array always starts with 0.
You create a JavaScript syntax array by using the Array object. You can use either square brackets (
[ ]) or the Array constructor to create an array. The following two statements create an array
with two values.
// JavaScript syntax var myArray = [10, 15]; // using square brackets var myArray = new Array(10, 15); // using the Array constructor
You can also create empty arrays. The following two statements create an empty array.
// JavaScript syntax var myArray = []; var myArray = new Array();
Note: The Director Scripting Reference does not include a complete reference for JavaScript syntax Array objects. For more complete information on using Array objects, see one of the many third-party resources on the subject.

Checking items in arrays

You can determine the characteristics of an array and the number of items the array contains by using the following methods.
To display the contents of a list, use the put() or trace() function, passing the variable that
contains the list as a parameter.
To determine the number of items in an array, use the Array object’s length property.
To determine an array’s type, use the constructor property.
The following example illustrates determining the number of items in an array using the
length property, and then returning the type of object using the constructor property. // JavaScript syntax
var x = ["1", "2", "3"]; trace(x.length) // displays 3 trace(x.contructor == Array) // displays true

Adding and deleting items in arrays

You can add or delete items in an array by using the following methods:
To add an item at the end of an array, use the Array object’s push() method.
To add an item at its proper position in a sorted array, use the Array object’s splice() method.
To add an item at a specific position in an array, use the Array object’s splice() method.
JavaScript syntax arrays 45
To delete an item from an array, use the Array object’s splice() method.
To replace an item in an array, use the Array object’s splice() method.
The following example illustrates using the Array object’s delete items from, and replace items in an array.
// JavaScript syntax var myArray = new Array("1", "2"); trace(myArray); displays 1,2
myArray.push("5"); // adds the value "5" to the end of myArray trace(myArray); // displays 1,2,5
myArray.splice(3, 0, "4"); // adds the value "4" after the value "5" trace(myArray); // displays 1,2,5,4
myArray.sort(); // sort myArray trace(myArray); // displays 1,2,4,5
myArray.splice(2, 0, "3"); trace(myArray); // displays 1,2,3,4,5
myArray.splice(3, 2); // delete two values at index positions 3 and 4 trace(myArray); // displays 1,2,3
myArray.splice(2, 1, "7"); // replaces one value at index position 2 with "7" trace(myArray); displays 1,2,7

Copying arrays

Assigning an array to a variable and then assigning that variable to a second variable does not make a separate copy of the array.
For example, the first statement below creates an array that contains the names of two continents, and assigns the array to the variable new variable automatically adds
continentList. In the third statement, adding Australia to landList also
Australia to the array continentList. This happens because both variable
landList. The second statement assigns the same list to a
names point to the same Array object in memory.
// JavaScript syntax var landArray = new Array("Asia", "Africa"); var continentArray = landArray; landArray.push("Australia"); // this also adds "Australia" to continentList
splice() method to add items to,
To create a copy of an array that is independent of another array:
Use the Array object’s slice() method.
For example, the following statements create an array and then use independent copy of the array.
// JavaScript syntax var oldArray = ["a", "b", "c"]; var newArray = oldArray.slice(); // makes an independent copy of oldArray
After newArray is created, editing either oldArray or newArray has no effect on the other.
46 Chapter 2: Director Scripting Essentials
slice() to make an

Sorting arrays

Arrays are sorted in alphanumeric order, with numbers being sorted before strings. Strings are sorted according to their initial letters, regardless of how many characters they contain.
To sort an array:
Use the Array object’s sort() method.
The following statements sort a non-sorted alphabetical array.
// JavaScript syntax var oldArray = ["d", "a", "c", "b"]; oldArray.sort(); // results in a, b, c, d
The following statements sort a non-sorted alphanumeric array.
// JavaScript syntax var oldArray = [6, "f", 3, "b"]; oldArray.sort(); // results in 3, 6, b, f
Sorting an array results in a new sorted array.

Creating multidimensional arrays

You can also create multidimensional arrays that enable you to work with the values of more than one array at a time.
In the following example, the first two statements create the separate arrays The third statement creates a multidimensional array and assigns it to values in a multidimensional array, the fourth and fifth statements use brackets to access the values in the array; the first bracket provides access to a specified array, and the second bracket provides access to value at a specified index position in the array.
// JavaScript syntax var array1 = new Array(5,10); var array2 = [15,20]; var mdArray = new Array(array1, array2); trace(mdArray[0][1]); // displays 10 trace(mdArray[1][0]); // displays 15
array1 and array2.
mdArray. To access the
JavaScript syntax arrays 47
48 Chapter 2: Director Scripting Essentials
CHAPTER 3

Writing Scripts in Director

Scripts in Macromedia Director MX 2004 support all kinds of functionality in movies that would not be possible otherwise. As you write scripts, you may find the need for increasingly advanced scripts to support complex interactivity in your Director movies. Intermediate and advanced scripting concepts and techniques are presented here, including information about object­oriented scripting in Director.
If you are new to scripting in Director, make sure to read Chapter 2, “Director Scripting
Essentials,” on page 9 in addition to the topics here.

Choosing between Lingo and JavaScript syntax

Both Lingo and JavaScript syntax provide access to the same objects, events, and scripting APIs. Therefore, it does not necessarily matter which language you choose to write your scripts. Your choice might be as simple as deciding which language you have the most knowledge of and are most comfortable with.
To understand how scripting languages typically work with a given object and event model in Director, consider the following:
In general, a given scripting language, such as Lingo or JavaScripts syntax, is wrapped around a
given object and event model in order to provide access to those objects and events.
JavaScript is an implementation of the ECMAScript standard that is wrapped around a web
browser’s object and event model to provide access to the browser’s objects and events.
ActionScript is an implementation of the ECMAScript standard that is wrapped around the
Macromedia Flash object and event model to provide access to Flash objects and events.
The Director implementation of JavaScript syntax is an implementation of ECMAScript that
is wrapped around the Director object and event model to provide access to Director objects and events.
Lingo is a custom syntax that is wrapped around the Director object and event model to
provide access to Director objects and events.
Lingo and JavaScript syntax are the two languages you can use to access the same Director object and event model. Scripts written in one language have the same capabilities as scripts written in the other language.
49
Therefore, after you know how to access the scripting APIs in one language, you essentially know how to access them in the other language. For example, JavaScript syntax code can access Lingo data types such as symbols, linear lists, property lists, and so on, create and invoke Lingo parent scripts and behaviors, create and invoke Xtra extensions, and use Lingo string chunk expressions. Also, both JavaScript syntax and Lingo scripts can be used within a single movie; however, a single script cast member can contain only one syntax or the other.
There are two main differences between Lingo and JavaScript syntax:
Each language contains some terminology and syntax conventions that are unique to each
language. For example, the syntax for an event handler is different in Lingo than it is in JavaScript syntax:
-- Lingo syntax on mouseDown
... end
// JavaScript syntax function mouseDown() {
... }
For more information on the terminology and syntax conventions used for each language, see
“Scripting terminology” on page 10 and “Scripting syntax” on page 12.
Some of the scripting APIs are accessed slightly differently in each language. For example,
you would use different constructs to access the second word in the first paragraph of a text cast member:
-- Lingo syntax member("News Items").paragraph[1].word[2]
// JavaScript syntax member("News Items").getPropRef("paragraph", 1).getProp("word", 2);

Scripting in dot syntax format

Whether you write scripts in Lingo or JavaScript syntax, you write them by using the dot syntax format. You use dot syntax to access the properties or methods related to an object. A dot syntax statement begins with a reference to an object, followed by a period (dot), and then the name of the property, method, or text chunk that you want to specify. Each dot in a statement essentially represents a move from a higher, more general level in the object hierarchy to a lower, more specific level in the object hierarchy.
For example, the following statement first creates a reference to the cast library named "News Stories", and then uses dot syntax to access the number of cast members in that cast library.
-- Lingo syntax castLib("News Stories").member.count
// JavaScript syntax castLib("News Stories").member.count;
50 Chapter 3: Writing Scripts in Director
To identify chunks of text, include terms after the dot to refer to more specific items within text. For example, the first statement below refers to the first paragraph of the text cast member named "News Items". The second statement below refers to the second word in the first paragraph.
-- Lingo syntax member("News Items").paragraph[1] member("News Items").paragraph[1].word[2]
// JavaScript syntax member("News Items").getPropRef("paragraph", 1); member("News Items").getPropRef("paragraph", 1).getProp("word", 2);
For certain objects that handle cascading property access to either data or a specific cast member type, as illustrated in the previous two statements, access to the properties is not supported by using normal JavaScript syntax. Therefore, you must use the
getPropRef() and getProp()
methods to access cascading properties in JavaScript syntax.
There are a few things to note about this JavaScript syntax exception:
This technique must be applied to 3D objects, text cast members, field cast members, and
XML Parser Xtra extensions accessed by using JavaScript syntax.
You must use the getPropRef() method to store a reference to one of the previously
mentioned objects or its properties by using JavaScript syntax.
You must use the getProp() method to retrieve a property value of one of the previously
mentioned objects or its properties by using JavaScript syntax.
3D objects and properties must be accessed by using their fully qualified names in JavaScript
syntax. For example, in Lingo, the property
shaderList[1]. However, in JavaScript syntax, the property shaderList[1] must be used at
all times.
shader can be used as a shortcut for the property

Introducing the Director objects

In basic terms, objects are logical groupings of named data that also can contain methods that act on that data. In this release of Director, the scripting APIs have been grouped into objects and are accessed through these objects. Each object provides access to a specific set of named data and type of functionality. For example, the Sprite object provides access to the data and functionality of a sprite, the Movie object provides access to the data and functionality of a movie, and so on.
The objects used in Director fall into the following four categories. Depending on the type of functionality you want to add and the part of a movie you are adding functionality to, you will use the objects from one or more of these categories:
Core objects
Media types
Scripting objects
3D objects
Introducing the Director objects 51

Core objects

This category of objects provides access to the core functionality and features available in Director, such as the Director player engine, movie windows, sprites, sounds, and so on. They represent the base layer through which all APIs and other object categories are accessed.
There are also a group of top-level methods and properties that enable you to access all of the core objects directly, instead of having to traverse the object hierarchy to access a specific core object.
For a reference of the available core objects and their APIs, see Chapter 5, “Director Core
Objects,” on page 101.

Media types

This category of objects provides access to the functionality of the various media types, such as RealMedia, DVD, Animated GIF, and so on, which are added to movies as cast members.
Literally, media types are not actually objects, but rather cast members that are of a specific type of media. When a media type is added to a movie as a cast member, it not only inherits the functionality of the core Member object, it also extends the Member object by providing additional functionality that is available only to the specified media type. For example, a RealMedia cast member has access to the Member object’s methods and properties, but it also has additional methods and properties that are specific to RealMedia. All other media types also exhibit this behavior.
For a reference of the available media types and their APIs, see Chapter 6, “Media Types,”
on page 119.

Scripting objects

This category of objects, also known as Xtra extensions, provides access to the functionality of the software components, such as XML Parser, Fileio, SpeechXtra, and so on, that are installed with Director and extend core Director functionary. The preexisting Xtra extensions provide capabilities such as importing filters and connecting to the Internet. If you know the C programming language, you can create your own custom Xtra extensions.
For a reference of the available scripting objects and their APIs, see Chapter 7, “Scripting
Objects,” on page 137.

3D objects

This category of objects provides access to the functionality of the cast members and text that are used to create 3D movies.
For more information about 3D movies, see the Using Director topics in the Director Help Panel.
For a reference of the available 3D objects and their APIs, see Chapter 8, “3D Objects,”
on page 141.
52 Chapter 3: Writing Scripts in Director

Object model diagrams

The following diagrams illustrate the basic high-level relationships between the object groups and their hierarchies within Director. For information on object creation, properties and methods, and other APIs, see the relevant API reference topics.
Object model diagrams 53

Top level functions and properties

There are a number of top level functions and properties that provide direct access to the core objects and functionality in Director. You will likely make extensive use of many of these functions and properties as you create references to core objects, new images, lists, and so on. For example, the top level
list() function creates a linear list.
The following tables list the top level functions and properties.
Top level functions
castLib() randomVector()
channel() (Top level) rect()
color() script()
date() (formats), date() (System) showLocals()
image() sound()
isBusy() sprite()
list() symbol()
member() timeout()
point() trace()
propList() vector()
put() window()
random() xtra()
_movie property refers directly to the core Movie object, and the top level
Top level properties
_global _player
_key _sound
_mouse _system
_movie

Introduction to object-oriented programming in Director

By using either Lingo or JavaScript syntax, you can apply object-oriented programming principles to your scripts. Applying object-oriented principles typically makes programming easier by letting you write less code and letting you use simpler logic to accomplish tasks, in addition to increasing the reusability and modularity of your code.
Depending on the scripting language you are using, you apply these principles using two different paradigms:
In Lingo, you use parent scripts, ancestor scripts, and child objects to simulate object-oriented
programming.
In JavaScript syntax, you use standard JavaScript-style object-oriented programming
techniques to create classes and subclasses.
54 Chapter 3: Writing Scripts in Director
Each paradigm enables you to apply the advantages of object-oriented programming to your scripts, so it does not really matter which scripting language you are using. You merely apply the principles in different ways.
Because each scripting language uses a different paradigm to apply object-oriented principles, the techniques described for one language won’t work in the other language. Therefore, you only need to read the content that applies to the scripting language you are using:
For more information on simulating object-oriented programming in Lingo, see “Object-
oriented programming with Lingo” on this page.
For more information on object-oriented programming in JavaScript syntax, see “Object-
oriented programming with JavaScript syntax” on page 65.

Object-oriented programming with Lingo

In Lingo, parent scripts provide the advantages of object-oriented programming. You can use parent scripts to generate script objects that behave and respond similarly yet can still operate independently of each other.
You can create multiple copies (or instances) of a parent script by using Lingo. Each instance of a parent script is called a child object. You can create child objects on demand as the movie plays. Director does not limit the number of child objects that can be created from the same parent script. You can create as many child objects as the computer’s memory can support.
Director can create multiple child objects from the same parent script, just as Director can create multiple instances of a behavior for different sprites. You can think of a parent script as a template and of child objects as implementations of the parent template.
The discussion about Lingo parent scripts and child objects describes the basics of how to write parent scripts and create and use child objects, and also provides script examples. It does not teach fundamental object-oriented programming concepts; however, to use parent scripts and child objects successfully, you must understand object-oriented programming principles. For an introduction to the basics of object-oriented programming, see one of the many third-party resources on that subject.

Similarity to other object-oriented languages

If you are familiar with an object-oriented programming language such as Java or C++, you may already understand the concepts that underlie parent scripting but know them by different names.
Terms that Director uses to describe parent scripts and child objects correspond to the following common object-oriented programming terms:
Parent scripts in Director correspond to classes in object-oriented programming.
Child objects in Director correspond to instances in object-oriented programming.
Property variables in Director correspond to instance variables or member variables in object-
oriented programming.
Handlers in Director correspond to methods in object-oriented programming.
Ancestor scripts in Director correspond to the Super class or base class in object-oriented
programming.
Object-oriented programming with Lingo 55

Parent script and child object basics

In Lingo, a parent script is a set of handlers and properties that define a child object; it is not a child object itself. A child object is a self-contained, independent instance of a parent script. Children of the same parent have identical handlers and properties, so child objects in the same group can have similar responses to events and messages.
Typically, parent scripts are used to build child objects that make it easier to organize movie logic. These child objects are especially useful when a movie requires the same logic to be run several times concurrently with different parameters. You can also add a child object to a Sprite object’s
scriptInstanceList or the Movie object’s actorList as a way to control animation.
Because all the child objects of the same parent script have identical handlers, those child objects respond to events in similar ways. However, because each child object maintains independent values for the properties defined in the parent script, each child object can behave differently than its sibling objects—even though they are instances of the same parent script.
For example, you can create a parent script that defines child objects that are editable text fields, each with its own property settings, text, and color, regardless of the other text fields’ settings. By changing the values of properties in specific child objects, you can change any of these characteristics as the movie plays without affecting the other child objects based on the same parent script.
Similarly, a child object can have a property set to either
TRUE or FALSE regardless of that
property’s setting in sibling child objects.
A parent script refers to the name of a script cast member that contains the property variables and handlers. A child object created from a parent script is essentially a new instance of the script cast member.

Differences between child objects and behaviors

While child objects and behaviors are similar in that they both can have multiple instances, they have some important differences as well. The main difference between child objects and behaviors is that behaviors are associated with locations in the Score because they are attached to sprites. Behavior objects are automatically created from initializers stored in the Score as the playhead moves from frame to frame and encounters sprites with attached behaviors. In contrast, child objects from parent scripts must be created explicitly by a handler.
Behaviors and child objects differ in how they become associated with sprites. Director automatically associates a behavior with the sprite that the behavior is attached to, but you must explicitly associate a child object with a sprite. Child objects do not require sprite references and exist only in memory.

Ancestor basics

Parent scripts can declare ancestors, which are additional scripts whose handlers and properties a child object can call on and use.
Ancestor scripting lets you create a set of handlers and properties that you can use and reuse for multiple parent scripts.
56 Chapter 3: Writing Scripts in Director
A parent script makes another parent script its ancestor by assigning the script to its ancestor property. For example, the following statement makes the script What_Everyone_Does an ancestor to the parent script in which the statement occurs:
-- Lingo syntax ancestor = new(script "What_Everyone_Does")
When handlers and properties are not defined in a child object, Director searches for the handler or property in the child’s ancestors, starting with the child’s parent script. If a handler is called or a property is tested and the parent script contains no definition for it, Director searches for a definition in the ancestor script. If a definition exists in the ancestor script, that definition is used.
A child object can have only one ancestor at a time, but that ancestor script can have its own ancestor, which can also have an ancestor, and so on. This lets you create a series of parent scripts whose handlers are available to a child object.

Writing a parent script

A parent script contains the code needed to create child objects and define their possible actions and properties. First, you must decide how you want the child objects to behave. Then, you can write a parent script that does the following:
Optionally declares any appropriate property variables; these variables represent properties for
which each child object can contain a value independent of other child objects.
Sets up the initial values of the child objects’ properties and variables in the on new handler.
Contains additional handlers that control the child objects’ actions.
Declaring property variables
Each child object created from the same parent script initially contains the same values for its property variables. A property variable’s value belongs only to the child object it’s associated with. Each property variable and its value persists as long as the child object exists. The initial value for the property variable is typically set in the
on new handler; if it’s not set, the initial value is VOID.
To declare a property variable:
Use the property keyword at the beginning of the parent script.
To set and test property variables from outside the child object:
Set and test property variables in the same way you would any other property in your scripts,
by using the syntax
For example, the following statement sets the
car1.speed = 55
Creating the new handler
Each parent script typically uses an when another script issues a specified parent script to create a child object from itself. The can also set the child object’s initial property values, if you want.
The
on new handler always starts with the phrase on new, followed by the me variable and any
parameters being passed to the new child object.
objectRef.propertyName.
speed property of an object car1:
on new handler. This handler creates the new child object
new(script parentScriptName) command, which tells the
on new handler in the parent script
Object-oriented programming with Lingo 57
The following on new handler creates a new child object from the parent script and initializes the child’s
spriteNum property with the value passed to it in the aSpriteNum parameter. The return
statement returns the child object to the handler that originally called the on new handler.
me
-- Lingo syntax property spriteNum
on new me, aSpriteNum
spriteNum = aSpriteNum return me
end
For more information on calling the on new handlers, see “Creating a child object” on page 59.
Adding other handlers
You determine a child object’s behavior by including in the parent script the handlers that produce the desired behavior. For example, you could add a handler to make a sprite change color.
The following parent script defines a value for the property handler that changes the
-- Lingo syntax property spriteNum
on new me, aSpriteNum
spriteNum = aSpriteNum return me
end
on changeColor me
spriteNum.foreColor = random(255)
end
foreColor property of the sprite.
spriteNum, and contains a second
Referring to the current object
Typically, one parent script creates many child objects, and each child object contains more than one handler. The special parameter variable
me tell the handlers in a child object that they are to
operate on the properties of that object and not on the properties of any other child object. This way, when a handler within a child object refers to properties, the handler uses its own child object’s values for those properties.
The term parent script. It is always important to define
me must always be the first parameter variable stated in every handler definition in a
me as the first parameter for parent scripts and to
pass the same parameter if you need to call other handlers in the same parent script, since these will be the handlers in each of the script’s child objects.
When referring to properties defined in ancestor scripts, you must use the
me parameter as the
source of the reference. This is because the property, while defined in the ancestor script, is nevertheless a property of the child object. For example, the following statement uses to an object and access properties defined in an ancestor of the object:
-- Lingo syntax x = me.y -- access ancestor property y
Because the variable me is present in each handler of a child object, it indicates that all the handlers control that same child object.
58 Chapter 3: Writing Scripts in Director
me to refer

Creating a child object

Child objects exist entirely in memory; they are not saved with a movie. Only parent and ancestor scripts exist on disk.
To create a new child object, you use the
new() method and assign the child object a variable
name or position in a list so you can identify and work with it later.
To create a child object and assign it to a variable, use the following syntax.
-- Lingo syntax variableName = new(script "scriptName", parameter1, parameter2, ...)
The scriptName parameter is the name of the parent script, and parameter1, parameter2, ... are any parameters you are passing to the child object’s creates a child object whose ancestor is
scriptName. It then calls the on new handler in the child
on new handler. The new() method
object with the specified parameters.
You can issue a initial settings by changing the values of the parameters passed with the
new() statement from anywhere in a movie. You can customize the child object’s
new() statement.
Each child object requires only enough memory to record the current values of its properties and variables and a reference to the parent script. Because of this, in most cases, you can create and maintain as many child objects as you require.
You can produce additional child objects from the same parent script by issuing additional
new() statements.
You can create child objects without immediately initializing their property variables by using the
rawNew() method. The rawNew() method does this by creating the child object without calling
the parent script’s
rawNew() allows you to create the objects ahead of time and defer the assignment of property
on new handler. In situations where large numbers of child objects are needed,
values until each object is needed.
The following statement creates a child object from the parent script Car without initializing its property variables and assigns it to the variable
-- Lingo syntax car1 = script("Car").rawNew()
car1:
To initialize the properties of one of these child objects, call its on new handler:
car1.new

Checking child object properties

You can check the values of specific property variables in individual child objects by using a simple
objectName.propertyName syntax. For example, the following statement assigns the
variable
-- Lingo syntax x = car1.carSpeed
x the value of the carSpeed property of the child object in the variable car1:
Querying object properties from outside the objects themselves can be useful for getting information about groups of objects, such as the average speed of all the car objects in a racing game. You might also use the properties of one object to help determine the behavior of other objects that are dependent on it.
Object-oriented programming with Lingo 59
In addition to checking the properties that you assign, you can check whether a child object contains a specific handler or find out which parent script an object came from. This is useful when you have objects that come from parent scripts that are similar but that have subtle differences.
For example, you may want to create a scenario in which one of several parent scripts might be used to create a child object. You can then determine which parent script a particular child object came from by using the
The following statements check whether the object named
Car:
-- Lingo syntax if car1.script = script("Car") then
_sound.beep()
end if
script() function, which returns the name of an object’s parent script.
car1 was created from the parent script
You can also get a list of the handlers in a child object by using the handlers() method, or check whether a particular handler exists in a child object by using the
The following statement places a list of the handlers in the child object
myHandlerList:
-- Lingo syntax myHandlerList = car1.handlers()
handler() method.
car1 into the variable
The resulting list would look something like this:
[#start, #accelerate, #stop]
The following statements use the handler() method to check whether the handler on
accelerate
-- Lingo syntax if car1.handler(#accelerate) then
put("The child object car1 contains the handler named on accelerate.")
end if
exists in the child object car1:

Removing a child object

You can remove a child object from a movie by setting all variables that contain a reference to the child object to another value. If the child object has been assigned to a list, such as
actorList,
you must also remove the child object from the list.
To remove a child object and the variables that refer to it:
Set each variable to VOID.
Director deletes the child object when there are no more references to it. In the following example,
ball1 contains the only reference to a specific child object, and it is set to VOID to delete
the object from memory.
-- Lingo syntax ball1 = VOID
To remove an object from actorList:
Use the delete() method to delete the item from the list.
60 Chapter 3: Writing Scripts in Director

Using scriptInstanceList

You can use the Normally,
scriptInstanceList property to dynamically add new behaviors to a sprite.
scriptInstanceList is the list of behavior instances created from the behavior
initializers defined in the Score. If you add child objects created from parent scripts to this list, the child objects receive the messages sent to other behaviors.
For example, the following statement adds a child object to the
scriptInstanceList property
of sprite 10:
-- Lingo syntax add(sprite(10).scriptInstanceList, new(script "rotation", 10))
The following is a possible parent script that the previous statement refers to:
-- Lingo syntax parent script "rotation" property spriteNum
on new me, aSpriteNum
spriteNum = aSpriteNum return me
end
on prepareFrame me
sprite(spriteNum).rotation = sprite(spriteNum).rotation + 1
end
When a child object is added to scriptInstanceList, you must initialize the child object’s
spriteNum property. Typically, you do this from a parameter passed in to the on new handler.
Note: The beginSprite message is not sent to dynamically added child objects.
For reference information on scriptInstanceList, see “scriptInstanceList” on page 975.

Using actorList

You can set up a special list of child objects (or any other objects) that receives its own message each time the playhead enters a frame or the
The special list is
actorList, which contains only objects that have been explicitly added to
updateStage() method updates the Stage.
the list.
The message is the
updateStage() command is used.
Objects in
actorList receive a stepFrame message instead of an enterFrame message at each
stepFrame message that is sent only when the playhead enters a frame or the
frame. If the objects have an on stepFrame handler available, the script in the handler runs each time the playhead enters a new frame or the
Some possible uses of
actorList and stepFrame are to animate child objects that are used as
updateStage() method updates the Stage.
sprites or to update a counter that tracks the number of times the playhead enters a frame.
An
on enterFrame handler could achieve the same results, but the actorList property and
stepFrame handler are optimized for performance in Director. Objects in actorList respond
more efficiently to
stepFrame messages than to enterFrame messages or custom messages sent
after an updateStage() method.
Object-oriented programming with Lingo 61
To add an object to the actorList:
Use the actorList property as follows, where childObject is a reference to the child object
to add:
-- Lingo syntax _movie.actorList.add(childObject)
The object’s stepFrame handler in its parent or ancestor script then runs automatically each time the playhead advances. The object is passed as the first parameter,
stepFrame
Director does not clear the contents of
handler.
actorList when branching to another movie, which can
me, to the on
cause unpredictable behavior in the new movie. If you do not want child objects in the current movie to be carried over into the new movie, insert a statement that clears
prepareMovie
To clear child objects from actorList:
handler of the new movie.
actorList in the on
Set actorList to [ ], which is an empty list.
For reference information on

Creating timeout objects

A timeout object is a script object that acts like a timer and sends a message when the timer expires. This is useful for scenarios that require specific things to happen at regular time intervals or after a particular amount of time has elapsed.
Timeout objects can send messages that call handlers inside child objects or in movie scripts. You create a timeout object by using the handler to be called, and the frequency with which you want the handler to be called. After a timeout object is created, Director keeps a list of currently active timeout objects, called
timeOutList.
The syntax described below is necessary for all new movies authored in Director MX 2004, or for older movies playing in Director MX 2004 whose to a value of 10. Movies authored in Director MX and earlier have a property set to a value of 9 which allows you to use the syntax found in Director MX and earlier.
actorList, see “actorList” on page 625.
new() keyword. You must specify a name for the object, a
scriptExecutionStyle property has been set
scriptExecutionStyle
To create timeout objects:
-- Lingo syntax when scriptExecutionStyle is set to 9 variableName = timeout(name).new(timeoutPeriod, timeoutHandler,
targetObject)
-- Lingo syntax when scriptExecutionStyle is set to 10 variableName = timeout().new(timeoutName, timeoutPeriod, timeoutHandler,
targetObject) variableName = new timeout(timeoutName, timeoutPeriod, timeoutHandler,
targetObject)
// JavaScript syntax variableName = new timeout(timeoutName, timeoutPeriod, timeoutFunction,
targetObject)
62 Chapter 3: Writing Scripts in Director
This statement uses the following elements:
variableName is the variable you are placing the timeout object into.
timeout indicates which type of Lingo object you are creating.
timeoutName is the name you give to the timeout object. This name appears in the
timeOutList. It is the #name property of the object.
new creates a new object.
intMilliseconds indicates the frequency with which the timeout object should call the
handler you specify. This is the calls the specified handler every 2 seconds.
#period property of the object. For example, a value of 2000
#handlerName is the name of the handler you want the object to call. This is the
#timeOutHandler property of the object. You represent it as a symbol by preceding the name
with the
#accelerate.
# sign. For example, a handler called on accelerate would be specified as
targetObject indicates which child object’s handler should be called. This is the #target
property of the object. It allows specificity when many child objects contain the same handlers. If you omit this parameter, Director looks for the specified handler in the movie script.
The following statement creates a timeout object named handler in the child object
-- Lingo syntax myTimer = timeOut("timer1").new(2000, #accelerate, car1)
car1 every 2 seconds:
To determine when the next timeout message will be sent from a particular timeout object, check its
#time property. The value returned is the point in time, in milliseconds, when the next
timeout message will be sent. For example, the following statement determines the time when the next timeout message will be sent from the timeout object Message window:
-- Lingo syntax put(timeout("timer1").time)
timer1 that calls an on accelerate
timer1 and displays it in the
Using timeOutList
When you begin creating timeout objects, you can use
timeOutList to check the number of
timeout objects that are active at a particular moment.
The following statement sets the variable
count property.
-- Lingo syntax x = _movie.timeoutList.count
x to the number of objects in timeOutList by using the
You can also refer to an individual timeout object by its number in the list.
The following statement deletes the second timeout object in
forget() method.
-- Lingo syntax timeout(2).forget()
Object-oriented programming with Lingo 63
timeOutList by using the
Relaying system events with timeout objects
When you create timeout objects that target specific child objects, you enable those child objects to receive system events. Timeout objects relay these events to their target child objects. The system events that can be received by child objects include
stopMovie, prepareFrame, and exitFrame. By including handlers for these events in child
prepareMovie, startMovie,
objects, you can make the child objects respond to them for whatever purposes you see fit. System events received by child objects are also received by movie scripts, frame scripts, and other scripts designed to respond to them.
The following parent script contains a handler for the system event handler
-- Lingo syntax property velocity
on new me
end
on exitFrame
end
on slowDown mph
end
slowDown.
velocity = random(55)
velocity = velocity + 5
velocity = velocity - mph
exitFrame and a custom
Associating custom properties with timeout objects
If you want to associate custom properties with a timeout object, you may want to create a timeout object that uses as a target anything other than a reference to a script instance object. When you use this technique, the target data becomes data that is associated with the timeout object, and can be used in your timeout handler.
The following example illustrates using this technique.
-- Lingo syntax
-- initialize a timeout object and pass it a data property list (tData)
-- instead of a reference to a script instance object tData = [#beta: 0] tTO = timeout("betaData").new(50,#targetHandler,tData)
-- within a movie script, create the targetHandler handler on targetHandler (aData)
-- increment and display the beta property tData.beta = tData.beta + 1 put(tData.beta)
end targetHandler
In the previous example, the beta property keeps incrementing. This means that you can initialize several timeout objects that all call the same movie script handler, and each timeout object can have its own data list associated with it.
64 Chapter 3: Writing Scripts in Director
In general, keep the following in mind:
When using a reference to a script instance as a target, the target handler in that particular
script instance is called. This technique does now allow the use of custom properties.
When using a reference to anything other than a script instance (such as a property list) as a
target, the target handler in a movie script is called. This technique allows the use of custom properties.

Object-oriented programming with JavaScript syntax

Object-oriented programming in JavaScript syntax is somewhat different than it is in other object-oriented languages such as Java and C++—while some object-oriented languages are class­based, JavaScript syntax is prototype-based.
The following two bullet points compare and contrast, at a high level, class-based languages with prototype-based languages such as JavaScript syntax.
In class-based languages, you create class definitions that define the initial properties and
methods that characterize all instances created from those classes. A class definition contains special methods, called constructor methods, that are used to create the instances of that class. When an instance is created by using the constructor method, that instance inherits all the properties of its parent class. That instance can also perform other processing specific to that instance depending on the constructor that was called.
In a class definition, you perform inheritance by creating a subclass that inherits all the properties of its parent class, in addition to defining new properties and optionally modifying inherited ones. The parent class from which a subclass is created is also known as a super-class.
new operator in association with a particular
In prototype-based languages, such as JavaScript syntax, there is no distinction between classes,
instances, subclasses, and so on—they are all known as objects. Instead of using class definitions, in JavaScript syntax you use "prototype objects" as the template from which new objects are created. Similar to class-based languages, in JavaScript syntax, you create a new object by using the
Instead of using super-classes and subclasses, in JavaScript syntax, you associate prototype objects with constructor functions to perform inheritance. This process is very similar to using super-classes and subclasses, only with different terminology.
Also, as opposed to class-based languages, in JavaScript syntax you can add and remove properties from an object or set of objects at runtime. For example, if you add a property to a prototype object at runtime, any instance objects for which it is a prototype also get that property.
new operator in association with a constructor function.

Object-oriented terminology

Because all types in JavaScript syntax are known as objects, class-based terms such as super-class, subclass, class, instance, and so on do not have literal technical meanings in JavaScript syntax.
However, all of these terms essentially map to objects in JavaScript syntax, and are convenient to use generically when referring to the different types of JavaScript syntax objects. Therefore, these class-based terms are used interchangeably with object throughout the discussion about object­oriented programming in JavaScript syntax to mean the following:
superclass Any class from which subclasses (objects) are created; a parent class.
subclass Any class that has been created from a superclass (object); a child class.
Object-oriented programming with JavaScript syntax 65
class A generic term for a superclass or subclass; a parent or child class.
instance or object instance A single object that has been created from a superclass.

Custom classes

One of the major advantages of object-oriented programming is the ability to create your own custom classes that enable you to add custom functionality to your scripts. The predefined classes provided by JavaScript syntax, such as Object, String, Math, and so on are useful in some cases, but they may not provide the functionality you require to accomplish your task. For example, suppose you want some objects in your movie to represent types of transportation, such as cars, boats, planes, and so on, and that you want each category to exhibit unique characteristics and functionality. Neither the predefined JavaScript syntax classes nor the predefined Director objects may directly provide the functionality that you need. Therefore, you may want to create a new class for each type of transportation so you can define unique characteristics for each type.
Keep in mind that when you create custom JavaScript syntax classes, you still have access to all the features and functionality of the predefined Director objects. This means that although the predefined Director objects may not directly provide the functionality that you need, you can still use them in your custom classes to access their values and predefined functionality.

Constructor functions

In JavaScript syntax, a constructor function represents the class that contains the template from which new object instances are created. Constructor functions create and initialize (set the default state of) properties in the new objects.
Constructor functions are essentially identical in format to regular JavaScript syntax method functions. The difference between a constructor function and a method function is that a constructor function uses the special is being initialized. A method function typically only performs some action on a given set of an object’s data.
The following example illustrates one way to create a Rectangle constructor function that could be used to initialize the height and width of new Rectangle objects.
function Rectangle(w, h) {
this.width = w; this.height = h;
}
You can also create a constructor function by using "function literal" syntax. Function literal syntax provides the same functionality as the syntax used previously, and is merely an alternative way to write the constructor. The following example illustrates using function literal syntax to create a Rectangle constructor function similar to the one illustrated previously.
Rectangle = function(w, h) {
this.width = w; this.height = h;
}
Note: When defining constructor functions that apply to a movie, be sure to place them in a movie script so they are available globally.
this keyword to represent a reference to the new object that
It is considered good scripting practice to give constructor functions names that map to their functionality, and to use initial capitalization in their names, such as
66 Chapter 3: Writing Scripts in Director
Rectangle or Circle.
Constructor functions are typically used only to initialize new objects, but can also return the object if desired. If you do return the initialized object, the returned object becomes the value of the
new expression.

Object instances

The most common way to create a new object instance is to use the
new operator followed by the
name of a constructor function. The following examples create new object instances.
var objRandom = new Object(); // assigns a reference to an Object object var objString = new String(); // assigns a reference to a String object
A constructor function can optionally define parameters that a new object instance passes to it to initialize the state of the object instance. If a constructor function does define parameters used during initialization of new object instances, the property values are initialized as follows:
If you pass values to the constructor function during initialization, the properties that received
values are set to those values.
If you do not pass values to the constructor function during initialization, the properties that
did not receive values are set to
When you create new object instances, the keyword constructor function to refer to the new object instance. Therefore, a new object instance is initialized with all of the properties defined by using the
In the following example, a names of three properties that will be associated with new object instances. The statement following the constructor initializes a new object instance by passing values to the constructor. These values are used as the initial values of the properties specified by the keyword
// Circle constructor function function Circle(x, y, r) {
this.xCoord = x; this.yCoord = y; this.radius = r;
}
undefined.
this is used in the body of the associated
this.propertyName syntax.
Circle constructor function uses the keyword this to specify the
this.
// xCoord = 10, yCoord = 15, radius = 5 var objCircle = new Circle(10, 15, 5);
Now that objCircle has been initialized, you can access its properties. Using the objCircle instance created previously, you could set some variables equal to the values of its properties.
var theXCoord = objCircle.xCoord; // assigns the value 10 to theXCoord var theYCoord = objCircle.yCoord; // assigns the value 15 to theYCoord var theRadius = objCircle.radius; // assigns the value 5 to theRadius
Note: For more information on using dot syntax to access properties and methods of an object, see
“Scripting in dot syntax format” on page 50.
It is considered good scripting practice to give new objects names that map to their functionality, and to name them by using lowercase letters, such as
objRectangle or objCircle.
You can also create an object instance by using "object literal" syntax, which eliminates the need for the
new operator and a constructor function. You typically only use this technique when you
need only one instance of an object that has not been defined in a constructor function. The following example creates an object instance with
var objSmallCircle = { x:1, y:2, radius:2 };
Object-oriented programming with JavaScript syntax 67
x = 1, y = 2, and radius = 2.

Object inheritance

In addition to being able to create your own custom classes, another major advantage of object­oriented programming is the ability of subclasses to inherit the properties and methods of the superclasses from which they were created. Inheritance enables you to easily create objects that already have built-in properties and functionality.
In JavaScript syntax, there is one superclass that acts as the base class from which all other subclasses are created—the Object superclass. The Object superclass contains a few basic properties and methods. The subclasses that are created by using Object as a template always inherit these basic properties and methods, and likely define their own properties and methods. Subclasses of these classes inherit from Object, from their superclasses, and so on. All additional objects that you create would continue this chain of inheritance.
For example, Object contains the create a new class named the
constructor property and the toString() method of Object. If you then create another
class named
constructor property and the toString() method of Object, in addition to any custom
SubObj2 using SubObj1 as a superclass, SubObj2 would also inherit the
SubObj1, it is a subclass of Object, and therefore automatically inherits
properties and methods you defined in
constructor property and the toString() method. If you
SubObj1.
Two of the important properties that your custom constructor functions inherit from the Object superclass are
prototype and constructor. The prototype property represents the prototype
object of a class, which enables you to add variables (properties) and methods to object instances,
and is the means by which inheritance is typically implemented in JavaScript syntax. The
constructor property represents the constructor function itself. The use of these properties is
explained in the following sections.

Prototype objects

As previously stated, when you create a subclass, it automatically inherits the properties and methods of the superclass on which it is based. In JavaScript syntax, inheritance is typically implemented by using prototype objects. A subclass actually inherits its properties and methods from the prototype object of its superclass, and not from the superclass itself. This important point offers a distinct advantage: all properties and methods do not literally have to be copied from a class to an object instance of that class, which can dramatically decrease the amount of memory required by new object instances.
Every class in JavaScript syntax, including the predefined Object class, contains only one prototype object. Every object instance created from a class has access to the properties and methods in the prototype object of that class. Therefore, the prototype object of a class is typically the only object that actually stores the properties and methods for that class; an object instance only contains the properties required to initialize that instance.
In your code, it appears that each object instance actually contains those properties and methods because you can access them directly from each object instance, but the instance is actually using the prototype object to access them. The prototype object of a class is created automatically when you create the class. You access the prototype object by using the
prototype property of the class.
Because a prototype object of a class stores properties that are shared by all object instances, they are ideally suited to define properties and methods whose values will be shared across all object instances. By sharing properties and methods across object instances, you can easily create instances that exhibit a defined default behavior, and can also customize any instances that deviate from the default behavior.
68 Chapter 3: Writing Scripts in Director
Prototype objects typically are not suited to define properties and methods whose values may vary across object instances. In cases where values may vary across object instances, you typically define those properties and methods within the class itself.
To specify the scope of a custom property or method, you define it as one of the following four types:
Instance variables
Instance methods
Class variables
Class methods
Instance variables
Instance variables are any variables (properties) that are defined in a constructor function and that are copied into each object instance of that constructor. All object instances have their own copies of instance variables. This means that if there are five object instances of a five copies of each instance variable defined in the class. Because each object instance has its own copy of an instance variable, each object instance can assign a unique value to an instance variable without modifying the values of other copies of the instance variable. You access instance variables directly from their containing object instances.
The following example defines four instance variables—
make, model, color, and speed—in a
constructor function. These four instance variables are available directly from all object instances of the
Car constructor.
function Car(make, model, color) { // define a Car class
this.make = make; this.model = model; this.color = color; this.speed = 0;
}
The following object instance objCar contains all four instance variables. Although a value for the instance variable whose initial value is 0 because the
// objCar.make="Subaru", objCar.model="Forester", // objCar.color="silver", objCar.speed = 0 var objCar = new Car("Subaru", "Forester", "silver");
speed is not passed to the Car constructor, objCar still has a speed property
speed variable is defined in the Car constructor.
Circle class, there are
Instance methods
Instance methods are any methods that are accessible through an object instance. Object instances do not have their own copies of instance methods. Instead, instance methods are first defined as functions, and then properties of the constructor function’s prototype object are set to the function values. Instance methods use the keyword
this in the body of the defining constructor
function to refer to the object instance they are operating on. Although a given object instance does not have a copy of an instance method, you still access instance methods directly from their associated object instances.
Object-oriented programming with JavaScript syntax 69
The following example defines a function named Car_increaseSpeed(). The function name is then assigned to the
// increase the speed of a Car function Car_increaseSpeed(x) {
this.speed += x; return this.speed;
} Car.prototype.increaseSpeed = Car_increaseSpeed;
increaseSpeed property of the Car class’s prototype object.
An object instance of Car could then access the increaseSpeed() method and assign its value to a variable by using the following syntax.
var objCar = new Car("Subaru", "Forester", "silver"); var newSpeed = objCar.increaseSpeed(30);
You can also create an instance method by using function literal syntax. Using function literal syntax eliminates the need to define a function, and the need to assign a property name to the function name.
The following example uses function literal syntax to define an contains the same functionality as the
// increase the speed of a Car Car.prototype.increaseSpeed = function(x) {
this.speed += x; return this.speed;
}
increaseSpeed() function defined previously.
increaseSpeed() method that
Class variables
Also known as static variables, these are any variables (properties) that are associated with a class, and not an object instance. There is always only one copy of a class variable, regardless of the number of object instances that are created from that class. Class variables do not use the prototype object to implement inheritance. You access a class variable directly through the class, and not through an object instance; you must define a class in a constructor function before you can define class variables.
The following example defines two class variables—
function Car() { // define a Car class
...
}
MAX_SPEED and MIN_SPEED.
Car.MAX_SPEED = 165; Car.MIN_SPEED = 45;
You would access the MAX_SPEED and MIN_SPEED class variables directly from the Car class.
var carMaxSpeed = Car.MAX_SPEED; // carMaxSpeed = 165 var carMinSpeed = Car.MIN_SPEED; // carMinSpeed = 45
Class methods
Also known as static methods, these are any methods that are associated with a class, and not an object instance. There is always only one copy of a class method, regardless of the number of object instances that are created from that class. Class methods do not use the prototype object to implement inheritance. You access a class method directly through the class, and not through an object instance; you must define a class in a constructor function before you can define class methods.
70 Chapter 3: Writing Scripts in Director
The following example defines a function named setInitialSpeed() that can change the default speed of new car instances. The function name is assigned to the property of the
function Car(make, model, color) { // define a Car class
this.make = make; this.model = model; this.color = color; this.speed = Car.defaultSpeed;
} Car.defaultSpeed = 10; // initial speed for new Car instances // increase the speed of a Car function Car_setInitialSpeed(x) {
Car.defaultSpeed = x;
} Car.setInitialSpeed = Car_setInitialSpeed;
Car class.
setInitialSpeed
You access the setInitialSpeed() class method directly from the Car class.
var newSpeed = Car.setInitialSpeed(30);
You can also create a class method by using function literal syntax. The following example uses function literal syntax to define a functionality as the
// increase the speed of a Car Car.setInitialSpeed = function(x) {
Car.defaultSpeed = x;
}
setInitialSpeed() function defined previously.
setInitialSpeed() method that contains the same

Recommended steps for defining a class

The following list describes the recommended steps to follow when defining a class:
1 Define a constructor function that is used as the template from which all object instances are
initialized. You may additionally define any instance variables in the constructor function by using the keyword
2 Define any instance methods, and possibly additional instance variables, that are stored in the
this to refer to an object instance.
prototype object of a class. These instance methods and variables are available to all object instances, and are accessible through the prototype object of the class.
3 Define any class methods, class variables, and constants that are stored in the class itself. These
class methods and variables are accessible only through the class itself.
In your code, when you access a property of an object instance, JavaScript syntax searches the object instance itself for that property. If the instance does not contain the property, JavaScript syntax then searches the prototype object of the super-class from which the instance was created. Because an object instance is searched before the prototype object of the class from which it was created, object instance properties essentially hide properties from the prototype object of their super-classes. This means that both an object instance and its super-class could realistically define a property with the same name but different values.
Object-oriented programming with JavaScript syntax 71

Deleting variables

You can delete a class variable or an instance variable by using the
delete operator. The following
example illustrates this process.
function Car() { // define a Car constructor function
...
} Car.color = "blue"; // define a color property for the Car class Car.prototype.engine = "V8"; // define an engine property for the prototype
var objCar = new Car();
trace(Car.color); // displays "blue" trace(objCar.engine); // displays "V8"
delete Car.color; delete Car.prototype.engine;
trace(Car.color); // displays undefined trace(objCar.engine); // displays undefined

Accessing the constructor property of a prototype object

When you define a class by creating a constructor function, JavaScript syntax creates a prototype object for that class. When the prototype object is created, it initially includes a property that refers to the constructor function itself. You can use the
constructor property of a
constructor
prototype object to determine the type of any given object.
In the following example, the function used to the create the object instance. The value of the
constructor property contains a reference to the constructor
constructor property is actually
a reference to the constructor itself and not a string that contains the constructor’s name.
function Car() { // define a Car class
// initialization code here
} var myCar = new Car(); // myCar.constructor == function Car() {}

Creating properties dynamically

Another advantage of using prototype objects to implement inheritance is that properties and methods that are added to a prototype object are automatically available to object instances. This is true even if an object instance was created before the properties or methods were added.
In the following example, the
color property is added to the prototype object of a Car class after
an object instance of Car has already been created.
function Car(make, model) { // define a Car class
this.make = make; this.model = model;
} var myCar = new Car("Subaru", "Forester"); // create an object instance
trace(myCar.color); // returns undefined
// add the color property to the Car class after myCar was initialized Car.prototype.color = "blue";
trace(myCar.color); // returns "blue"
72 Chapter 3: Writing Scripts in Director
You can also add properties to object instances after the instances have been created. When you add a property to a specific object instance, that property is available only to that specific object instance. Using the
color property to myCar after it has already been created.
trace(myCar.color); // returns undefined
myCar.color = "blue"; // add the color property to the myCar instance
trace(myCar.color); // returns "blue"
var secondCar = new Car("Honda", "Accord"); // create a second object instance
trace(secondCar.color); // returns undefined
myCar object instance created previously, the following statements add the

Writing scripts in the Script window

When you write scripts for a movie, the quantity and variety of scripts can be very large. Deciding which methods or properties to use, how to structure scripts effectively, and where scripts should be placed requires careful planning and testing, especially as the complexity of your movie grows.
Before you begin writing scripts, formulate your goal and understand what you want to achieve. This is as important—and typically as time-consuming—as developing storyboards for your work.
When you have an overall plan for the movie, you are ready to start writing and testing scripts. Expect this to take time. Getting scripts to work the way you want often takes more than one cycle of writing, testing, and debugging.
The best approach is to start simple and test your work frequently. When you get one part of a script working, start writing the next part. This approach helps you identify bugs efficiently and ensures that your scripts are solid as they become more complex.
When you write your scripts, you write them in the Script window in the Director user interface. The Script window provides a number of features that help you create and modify your scripts.
To open the Script window, do one of the following:
Select Window > Script.
Double-click a script cast member in the Cast window.
For information on alternative ways to create and open scripts, see “Performing common tasks”
on page 79.
Writing scripts in the Script window 73

Setting Script window preferences

You can change the font of text in the Script window and define different colors for various code components. To change the default font of text in the Script window and the color of various code elements, you use Script window preferences. Director automatically colors different types of code elements unless you turn off Auto Coloring.
To set Script window preferences:
1 Select Edit > Preferences > Script. 2 To choose the default font, click the Font button and select settings from the Font dialog box. 3 To choose the default color of text in the Script window, select a color from the Color menu. 4 To choose the background color for the Script window, select a color from the Background
color menu.
5 To make new Script windows automatically color certain code elements, select Auto Coloring.
This option is on by default. With Auto Coloring off, all text appears in the default color.
6 To make new Script windows automatically format your scripts with proper indenting, select
Auto Format. This option is on by default.
Note: The auto coloring and auto formatting features do not apply to JavaScript syntax code. Therefore, if you are authoring scripts using JavaScript syntax, the Auto Coloring and Auto Format buttons in the Script window are disabled, and terms such as the default text color.
function, var, and this will appear in
7 To make new Script windows display line numbers for your scripts, select Line Numbering.
This option is on by default.
8 If Auto Coloring is on, select colors for the following code elements from the corresponding
color menus:
Keywords
Comments
Literals
Custom (terms you define in your own code)
9 To change the line number column background color, click the Line Numbers color menu and
choose a new color.
10 To change the location of the Call Stack, Variable, and Watcher panes in the Debugger
window, select left, top, right, or bottom from the Debugger Panes menu.
74 Chapter 3: Writing Scripts in Director

Inserting common scripting terms

The Script window provides pop-up menus of common scripting terms that you can use to insert statements in a script. The same menus also appear in the Message window.
In both the Script window and the Message window, you can select which scripting syntax you want to use for a particular script.
To select the scripting syntax:
From the Script Syntax pop-up menu, select either Lingo or JavaScript.
After you select a scripting syntax, you enter code in the syntax you have chosen. If you try to compile a script in a syntax other than the one you chose, a script error occurs.
When entering scripts in the Script window, you can comment out or uncomment either single or multiple lines of code by using the Comment or Uncomment buttons. Depending on which scripting syntax you have chosen, the Comment and Uncomment buttons display the correct comment markers for that syntax; Lingo uses double-hyphens ( double-slashes (
//).
--), and JavaScript syntax uses
To comment code:
Highlight the line or lines of code you want to comment out, and click Comment.
Note: When using the Comment button to comment out multiple lines of JavaScript syntax code, Director inserts double-slashes before each line. You can also comment out multiple lines of code by inserting /* before the first line of commented code and inserting */ after the last line of commented code, but you must do this manually.
To uncomment code:
Highlight the line or lines of code that you want to remove comments from, and
click Uncomment.
Both the Script window and the Message window contain the following menus:
The Alphabetical Lingo menu lists every element in alphabetical order, except 3D Lingo.
The Categorized Lingo menu lists categories of elements according to the features they are
often used for. It does not include 3D Lingo.
The Alphabetical 3D Lingo menu lists all 3D Lingo elements in alphabetical order.
Writing scripts in the Script window 75
The Categorized 3D Lingo menu lists categories of all 3D Lingo elements according to the
features they are used for.
The Scripting Xtras pop-up menu includes the methods and properties of all scripting Xtra
extensions found, regardless of whether they are Macromedia or third-party Xtra extensions.
Note: The scripting Xtra extensions listed in the Scripting Xtras pop-up menu are only those that support the some cast member media types such as 3D and DVD also support the not appear in the Scripting Xtras pop-up menu because they are not implemented in Director as scripting Xtra extensions.
interface() method and whose names actually appear in the pop-up menu. Although
interface() method, they do
When you select an element from the pop-up menus, Director inserts the element at the insertion point in the Script window.
When an element requires additional parameters, placeholder names are included that indicate the additional required information. When more than one argument or parameter is required, the first one is highlighted for you, so all you must do is type to replace it. You must select and change the other parameters yourself.
Some cast member types and scripting Xtra extensions provide scripting terms that do not appear in the pop-up menus. These member types and Xtra extensions often have their own documentation, and you can find some information from within Director.
To display a list of available Xtra extensions:
Issue either put(_player.xtraList) or trace(_player.xtraList) in the Message window.
To display a list of available scripting Xtra extensions:
Issue either put(_player.scriptingXtraList) or trace(_player.scriptingXtraList)
in the Message window.
To display a list of methods and properties for an Xtra extension:
From the Scripting Xtras pop-up menu, point to an Xtra extension, and on the submenu,
click put interface. The methods and properties for that Xtra extension appear in the Message window.

Entering and editing text

Entering and editing text in a Script window is similar to entering and editing text in any other field.
The following are common editing tasks that you perform in the Script window:
To select a word, double-click the word.
To select an entire script, select Select All from the Edit menu.
To start a new line, enter a carriage return.
In Lingo, to wrap a long line of code with a continuation symbol, press Alt+Enter (Windows)
or Option+Return (Macintosh) where you want to insert a soft line break. The continuation symbol (\) that appears indicates that the statement continues on the next line.
In JavaScript syntax, to wrap a long line of code, insert a regular line break by pressing Enter (Windows) or Return (Macintosh). The Lingo continuation symbol causes a script error in JavaScript syntax scripts.
76 Chapter 3: Writing Scripts in Director
To locate a handler in the current script, select the handler’s name from the Go to Handler
pop-up menu in the Script window.
To compile any modified scripts, click the Script window’s Recompile All Modified Scripts
button or close the Script window. When you modify a Script, an asterisk appears in the Script window title bar, indicating that the script needs to be recompiled.
To compile all scripts in a movie, select Recompile All Scripts from the Control menu.
To reformat a script with proper indentation, press Tab in the Script window.
Director automatically indents statements when the syntax is correct. If a line does not indent properly, there is a problem in the syntax on that line.
To open a second Script window, Alt-click (Windows) or Option-click (Macintosh) the New
Cast Member button in the Script window. This can be helpful for editing two different sections of a long script simultaneously.
To toggle line numbering, click the Line Numbering button.
To toggle Auto Coloring, click the Auto Coloring button. Auto coloring displays each type of
Lingo element (properties, commands, and so on) in a different color.
To toggle Auto Formatting, click the Auto Format button. Auto Formatting adds the correct
indenting to your scripts each time you add a carriage return or press Tab.
Note: The auto coloring and auto formatting features do not apply to JavaScript syntax code. Therefore, if you are authoring scripts using JavaScript syntax, the Auto Coloring and Auto Format buttons in the Script window are disabled, and terms such as the default text color.

Finding handlers and text in scripts

The Find command in the Edit menu is useful for finding handlers and for finding and editing text and handlers.
function, var, and this will appear in
To find handlers in scripts:
1 Select Edit > Find > Handler.
The Find Handler dialog box appears. The left-most column in the Find Handler dialog box displays the name of each handler in
the movie. The middle column displays the number of the cast member associated with the handler’s script, along with the name of that cast member. The rightmost column lists the cast library that contains the cast member.
2 Select the handler that you want to find. 3 Click Find.
The handler appears in the Script window. The title bar at the top of the Script window indicates the script’s type.
Writing scripts in the Script window 77
To find text in scripts:
1 Make the Script window active. 2 Select Edit > Find > Text.
The Find Text dialog box appears.
3 Enter text that you want to find in the Find field, and then click Find.
By default, find is not case-sensitive:
ThisHandler, thisHandler, and THISHANDLER are all the
same for search purposes. Click the Case Sensitive check box to make the find case-sensitive.
To specify which cast members to search:
Select the appropriate option under Search: Scripts.
To start the search over from the beginning after the search reaches the end:
Select the Wrap-Around option.
To search only for whole words and not fragments of other words that match the word:
Select the Whole Words Only option.
To find the next occurrence of the text specified in the Find field:
Select Edit > Find Again.
To find occurrences of selected text:
1 Select the text. 2 Select Edit > Find > Selection.
78 Chapter 3: Writing Scripts in Director

Performing common tasks

The following are ways to perform common tasks for creating, attaching, and opening scripts.
To create a frame behavior (script attached to a frame):
Double-click the behavior channel in the frame to which you want to attach the behavior.
Behavior channels
When you create a new behavior, the behavior receives the cast library number of the first available location in the current Cast window.
When you create a new frame behavior, the Script window opens and already contains the Lingo
on exitFrame handler The first line contains on exitFrame, followed by a line with a blinking
insertion point, and then a line with the word common Lingo behavior to the frame. To make this handler work with JavaScript syntax, replace
on exitFrame with function exitFrame() {, and replace end with }.
end. This makes it easy for you to quickly attach a
One of the most common frame behaviors is one that keeps the playhead looping in a single frame. This can be useful when you want your movie to keep playing in a single frame while waiting for the user to click a button or for a digital video or sound to finish playing.
To keep the playhead in a single frame:
In a frame behavior, type the following statement on the line after the on exitFrame (Lingo)
or
function exitFrame() (JavaScript syntax) statement:
-- Lingo syntax _movie.go(_movie.frame)
// JavaScript syntax _movie.go(_movie.frame);
The Movie object’s frame property refers to the frame currently occupied by the playhead. This statement essentially tells the playhead to "go back to the frame you are currently in."
Writing scripts in the Script window 79
To create a sprite behavior (script attached to a sprite):
In the Score or on the Stage, select the sprite that you’re attaching the behavior to. Then select
Window > Behavior Inspector and select New Behavior from the Behavior pop-up menu.
When you create a new sprite behavior, the Script window opens and already contains the Lingo
on mouseUp handler. The first line contains the line on mouseUp, followed by a line with a
blinking insertion point, and then a line with the word
end. This makes it easy for you to quickly
attach a common behavior to the sprite. To make this handler work with JavaScript syntax, replace
on mouseUp with function mouseUp() {, and replace end with }.
To open a behavior for editing:
1 Double-click the behavior in the Cast window.
The Behavior inspector opens.
2 Click the Script Window icon in the Behavior inspector.
The Script window displays the behavior.
Alternatively, you can open the Script window and cycle through the scripts until you reach the behavior.
To remove a behavior from a Score location:
Select the location and then delete the script from the list displayed in the Property inspector
(Behavior tab).
To attach existing behaviors to sprites or frames, do one of the following:
Drag a behavior from a cast to a sprite or frame in the Score or (for sprites) to a sprite on
the Stage.
In the score, select the sprites or frames that you’re attaching the behavior to. Then
select Window > Behavior Inspector and select the existing behavior from the Behavior pop-up menu.
To create a movie script (script attached to a movie), do one of the following:
If the current script in the Script window is a movie script, click the New Script button in the
Script window. (Clicking the New Script button always creates a script of the same type as the current script.)
If the current script in the Script window is not a movie script, click the New Script button
and then change the new script’s type with the Script Type pop-up menu in the Script tab of the Property inspector.
If no sprites or scripts are selected in the cast, Score, or Stage, then open a new Script window;
this creates a new movie script by default.
To open a movie script or parent script for editing:
Double-click the script in the Cast window.
To change a script’s type:
1 Select the script in the Cast window or open it in the Script window. 2 Click the Script tab of the Property inspector and select a script type from the Script Type
pop-up menu.
80 Chapter 3: Writing Scripts in Director
To cycle through the scripts in the Script window:
Use the Previous Cast Member and Next Cast Member arrows at the top of the Script window
to advance or back up to a script.
To duplicate a script:
Select the script in the Cast window and select Duplicate from the Edit menu.
To create a script that is attached automatically to every sprite made from a specific cast member, attach the script to the cast member itself.
To create a script attached to a cast member or open an existing one, do one of the following:
Right-click (Windows) or Control-click (Macintosh) on a cast member in the Cast window
and select Cast Member Script from the context menu.
Select a cast member in the Cast window and then click the Cast Member Script button in the
Cast window.

Using linked scripts

In addition to scripts stored as internal cast members, you can choose to keep scripts in external text files and link them to your Director movie. These linked scripts are similar to linked image or digital video files that you can import into Director movies.
Advantages of using linked scripts include the following:
One person can work on the Director file while another works on the script.
You can easily exchange scripts with others.
You can control the scripts separately from the Director file in a source code control
application such as Microsoft Visual SourceSafe or Perforce by Perforce Software. Applications such as this prevent multiple programmers working on the same Director project from overwriting each other’s work.
Linked scripts are used by Director only during authoring. At runtime, Director projectors and Macromedia Shockwave Player use a special internal copy of the script data stored in the movie. This way, your linked scripts need not be distributed with your movies and cannot be copied by end users.
To import a script as a linked text file:
1 Select File > Import. 2 Select Script as the type of file to import. 3 Select the script file(s) you want to import.
You can import files with the file extensions .txt, .ls, or .js. The .ls extension is the Director linked script extension.
To create a list of files you want to import, you can use the Add and Add All buttons. This is especially useful if you want to import scripts from multiple locations.
4 Select Link to External File from the Media pop-up menu. 5 Click Import.
Writing scripts in the Script window 81
You can edit linked scripts normally in the Director Script window. Changes you make are written to the external files each time you save your Director movie. (If you imported the linked script from a UNIX server, UNIX line endings are preserved.) If you import a script whose text file is locked, you won’t be able to edit the script in Director.
You cannot apply custom text colors to linked scripts in the Script window. Script auto coloring, however, is enabled for linked scripts.
To turn an internal script cast member into an external, linked script cast member:
1 Select the internal cast member and click the Script tab of the Property inspector. 2 Click Link Script As. 3 Enter a name for the script file in the Save As dialog box. 4 Click Save.
To reload a linked script after it is edited:
Use the Member object’s unload() method.
If a linked script is edited outside of Director, you can reload it by using the the Message window. The following statement causes the script member unloaded and then reloaded:
-- Lingo syntax member("myScript").unload()
// JavaScript syntax member("myScript").unload();
unload() method in
myScript to be
82 Chapter 3: Writing Scripts in Director
CHAPTER 4

Debugging Scripts in Director

Scripts do not always do what you want the first time. The script often has an error in its syntax: possibly a word is misspelled or a small part of the script is missing. Other times, the script might work but does not produce the expected result. Mistakes or bugs almost always occur when writing your scripts, so you should allow enough time for debugging when you develop multimedia titles.
As your skill with scripting increases, you’ll probably encounter different types of problems as you master one area but start learning others. However, the basic troubleshooting techniques described here are useful for novice and advanced users alike.
The best way to correct a bug in your scripts varies from situation to situation. There are not one or two standard procedures that resolve the problem. You must use a variety of tools and techniques, such as the following:
An overview and understanding of how scripts in the movie interact with each other
Familiarity and practice with common debugging methods
The following tools help you identify problems in scripts:
The Message window, when tracing is on, displays a record of the frames that play and the
handlers that run in the movie.
The Debugger window displays the values of global variables, properties of the script that is
currently running, the sequence of handlers that ran to get to the current point, and the value of variables and expressions that you select.
The Script window lets you enter comments, insert stopping points in the script, and select
variables whose value is displayed in the Object inspector.
The Object inspector lets you view and set the values of objects and properties you select.
83

Good scripting habits

Good scripting habits can help you avoid many scripting problems in the first place.
Try to write your scripts in small sets of statements and test each one as you write it. This
isolates potential problems where they are easier to identify.
Insert comments that explain what the script statements are intended to do and what the
values in the script are for. This makes it easier to understand the script if you return to it later or if someone else works on it. For example, the comment in the following statements make the purpose of the
-- Lingo syntax
-- Loop until the "s" key is pressed repeat while not(_key.keyPressed("s"))
_sound.beep() end repeat
// JavaScript syntax // Loop until the "s" key is pressed while(!_key.keyPressed("s")) {
_sound.beep(); }
if...then structure and repeat loop clear:
Make sure that the script’s syntax is correct. Use the Script window’s pop-up menus to insert
pre-formatted versions of scripting elements. Rely on the API topics of this reference to check that statements are set up correctly.
Use variable names that indicate the variables’ purpose. For example, a variable that contains a
number should be called something like
newNumber instead of ABC.

Basic debugging

Debugging involves strategy and analysis, not a standard step-by-step procedure. This section describes the basic debugging approaches that programmers successfully use to debug any code, not just Lingo or JavaScript syntax.
Before you modify a movie significantly, always make a backup copy. It may help to name the copies incrementally, for example, fileName_01.dir, fileName_02.dir, fileName_03.dir, and so on to keep track of the various stages of a movie.

Identifying the problem

It might seem obvious, but the first thing to do when debugging is to identify the problem. Is a button doing the wrong thing? Is the movie going to the wrong frame? Is a field not editable when it should be?
You may also want to determine what you expect a particular script to do, and then compare your expectation with what the script actually does. This process helps you clearly define your goal and see what parts of the goal are not being met.
If you copied a script or a portion of a script from another movie or from a written example, check whether the script was designed for some specific conditions. Perhaps it requires that a sprite channel is already scripted. Maybe cast member names must follow a specific style convention.
84 Chapter 4: Debugging Scripts in Director

Locating the problem

Do the following to start locating a problem:
Think backwards through the chain to identify where the unexpected started to happen.
Use the Message window to trace which frames the movie goes through and the handlers
that your scripts run.
Determine what the scripts should be doing and consider what in these statements relates to
the problem. For example, if a text cast member is not editable when you expect it to be, where in the movie does (or does not) your script set the cast member’s
editable property?
If a sprite does not change as intended on the Stage, is the updateStage() method needed
somewhere?
Does the problem occur only on certain computers and not others? Does it happen only when
the display is set to millions of colors? Maybe something in the computer is interfering with the application.
You can focus on specific lines of script by inserting a breakpoint—a point where the script pauses its execution and invokes the Debugger window—in a line. This gives you a chance to analyze conditions at that point before the script proceeds. For information on how to insert breakpoints in a script, see “Debugging in the Debugger window” on page 94.

Solving simple problems

When finding a bug, it’s a good idea to check for simple problems first.
The first debugging test occurs when you compile your script. You can compile your script by doing one of the following:
In the Script window, click Recompile All Modified Scripts.
From the Control menu, click Recompile All Scripts.
Press Shift+F8.
Close the Script window.
It is typically more convenient to compile scripts by using one of the first three options. The fourth option requires that you close the Script window each time you want to compile a script.
When you compile your script, Macromedia Director MX 2004 gives you an error message if the script contains incorrect syntax. The message usually includes the line in which the problem was first detected. A question mark appears at the spot in the line where Director first found the problem.
For example, the first line in the previous error message tells you that the script error in question is a syntax error, and also tells you what the syntax error is. The second line in the error message displays the actual line of code that contains the syntax error.
Basic debugging 85
Looking for syntax errors
Syntax errors are probably the most common bug encountered while scripting. When a script fails, it is a good idea to first make sure that:
Terms are spelled correctly, spaces are in the correct places, and necessary punctuation is used.
Director cannot interpret incorrect syntax.
Quotation marks surround the names of cast members, labels, and strings within a statement.
All necessary parameters are present. The specific parameters depend on the individual
element. See the API topic entries in this reference to determine any additional parameters that an element requires.
Looking for other simple bugs
If your script compiles without an error message, it might contain a bug. If your script is not doing what you want, check the following:
Values for parameters are correct. For example, using an incorrect value for the number of
beeps that you want the
beep() method to generate gives you the wrong number of beeps.
Values that change—such as variables and the content of text cast members—have the values
you want. You can display their values in the Object inspector by selecting the name of the object and clicking Inspect Object in the Script window, or in the Message window by using the
put() or trace() functions.
The scripting elements do what you think they do. You can check their behavior by referring to
the API topic entries in this reference.
If the script is written in JavaScript syntax, the script may contain a capitalization error.
JavaScript syntax is case-sensitive, which means that all methods, functions, properties, and variables must be referred to by using the correct capitalization.
If you attempt to call a method or function by using incorrect capitalization, you will receive a script error.
If you attempt to access a variable or property by using incorrect capitalization, you may not receive a script error, but your script may not behave as expected. For example, the following
mouseUp handler contains a statement that attempts to access the itemLabel property by using
incorrect capitalization. This script does not produce a script error, but instead dynamically creates a new variable with the incorrect capitalization. The value of the newly created variable is
undefined.
// JavaScript syntax function beginSprite() {
this.itemLabel = "Blue prints"; }
function mouseUp() {
trace(this.itemlabel) // creates the itemlabel property }
86 Chapter 4: Debugging Scripts in Director

Debugging in the Script window

The Script window contains several features that can help you debug scripts.
To open the Script window:
Select Window > Script.
To make the current line of code a comment:
Click Comment.
To remove commenting from the current line of code:
Click Uncomment.
To turn breakpoints in the current line of code on and off:
Click Toggle Breakpoint.
To turn off all breakpoints.
Click Ignore Breakpoints.
To add the selected expression or variable to the Object inspector:
Click Inspect Object.

Debugging in the Message window

The Message window provides a way for you to test scripting commands and to monitor what is happening in your scripts while a movie plays.
To open the Message window:
Select Window > Message.
Debugging in the Message window 87

Managing the Message window

The Message window has an Input pane and an Output pane. The Input pane is editable. The Output pane is read-only. The only way to display text in the Output pane is by calling the or
trace() functions.
You can adjust the sizes of the Input and Output panes by dragging the horizontal divider that separates them.
To resize the Output pane:
Drag the horizontal divider to a new position.
To hide the Output pane completely:
Click the Collapse/Expand button in the center of the horizontal divider.
When the Output pane is hidden, output from scripts that execute is displayed in the Input pane.
To display the Output pane if it is hidden:
Click the Collapse/Expand button again.
To clear the contents of the Message window:
Click the Clear button.
If the Output pane is visible, its contents are deleted. If the Output pane is not visible, the contents of the Input pane are deleted.
To delete a portion of the contents of the Output pane:
1 Select the text to be deleted. 2 Press the Backspace or Delete key.
put()
To copy text in the Input or Output pane:
1 Select the text. 2 Select Edit > Copy.

Testing scripts in the Message window

You can test Lingo and JavaScript syntax statements to see how they work by entering them in the Message window and observing the results. When you enter a command in the Message window, Director executes the command immediately, regardless of whether a movie is playing.
Before entering the statements you want to test, you must first select which scripting syntax, Lingo or JavaScript syntax, you are going to test.
To select the scripting syntax
1 From the Script Syntax pop-up menu, select either Lingo or JavaScript.
To test a one-line statement:
1 Type the statement directly in the Message window. 2 Press Enter (Windows) or Return (Macintosh). Director executes the statement.
If the statement is valid, the Message window displays the result of the statement in the Output pane at the bottom of the window. If the script is invalid, an alert appears.
88 Chapter 4: Debugging Scripts in Director
For example, if you type the following statement into the Message window:
-- Lingo syntax put(50+50)
// JavaScript syntax trace(50+50);
and press Enter (Windows) or Return (Macintosh), the result appears in the Output pane:
-- Lingo syntax
-- 100
// JavaScript syntax // 100
If you type the following statement into the Message window:
-- Lingo syntax _movie.stage.bgColor = 255
// JavaScript syntax _movie.stage.bgColor = 255;
and press Enter (Windows) or Return (Macintosh), the Stage becomes black.
You can test multiple lines of code all at once by copying and pasting statements into the Message window or by pressing Shift+Return after each line of code.
To execute multiple lines of code by copying and pasting:
1 Copy the lines of code to the clipboard. 2 Enter a blank line in the Message window. 3 Paste the code into the input pane of the Message window. 4 Place the insertion point at the end of the last line of code. 5 Press Control+Enter (Windows) or Control+Return (Macintosh). Director finds the first blank
line above the insertion point and executes each line of code after the blank line in succession.
To enter multiple lines of code manually:
1 Enter a blank line in the Message window. 2 Enter the first line of code. 3 Press Shift+Return at the end of the line. 4 Repeat steps 2 and 3 until you have entered the last line of code. 5 Press Control+Enter (Windows) or Control+Return (Macintosh). Director finds the first blank
line above the insertion point and executes each line of code after the blank line in succession.
You can test a handler without running the movie by writing the handler in a Movie Script or Behavior Script window, and then by calling it from the Message window.
To test a handler:
1 Copy and paste or manually enter a multiline handler into the Message window as described in
the previous two procedures.
2 Place the insertion point at the end of the last line of code. 3 Press Enter (Windows) or Return (Macintosh). The handler executes.
Any output from
put() or trace() statements in the handler appears in the Message window.
Debugging in the Message window 89
Like the Script window, the Message window contains pop-up menus of scripting commands. When you select a command from one of the pop-up menus, the command appears in the Message window with the first argument that you must provide selected. Several menus are provided to give you easy access to the whole catalog of scripting terms.
The pop-up menus include the following:
Alphabetical Lingo includes all commands except 3D Lingo, presented in an alphabetical list.
Categorized Lingo includes all commands except 3D Lingo, presented in a categorized list.
Alphabetical 3D Lingo includes all 3D Lingo, presented in an alphabetical list.
Categorized 3D Lingo includes all 3D Lingo, presented in a categorized list.
Scripting Xtra extensions includes the methods and properties of all scripting Xtra extensions
found, regardless of whether they are Macromedia or third-party Xtra extensions.
Note: The scripting Xtra extensions listed in the Scripting Xtras pop-up menu are only those that support the some cast member media types such as 3D and DVD also support the not appear in the Scripting Xtras pop-up menu because they are not implemented in Director as scripting Xtra extensions.
interface() method and whose names actually appear in the pop-up menu. Although
interface() method, they do

Monitoring scripts in the Message window

You can set the Output pane of the Message window to display a record of the statements that a movie executes as it plays. This is useful for tracking the flow of your code and seeing the result of specific statements. You can do this in one of two ways.
To display statements in the Output pane, do one of the following:
On the Message window, click Trace.
Set the Movie object’s traceScript property to TRUE.
Entries after a double equal sign (==) indicate what has occurred in the movie—such as which frame the movie has just entered, which script is running, or the result of a method or setting a value.
For example, the following line indicates several things:
== Frame: 39 Script: 1 Handler: mouseUp
The movie entered frame 39.
The movie ran script 1, the first script attached to the frame.
The movie ran the mouseUp handler in script 1 after the movie entered the frame.
90 Chapter 4: Debugging Scripts in Director
Entries after an arrow made up of a double hyphen and right angle bracket (-->) indicate lines of your code that have run. For example, the following Lingo lines:
--> _sound.fadeOut(1, 5*60)
--> if leftSide < 10 then
--> if leftSide < 200 then
--> _movie.go("Game Start")
indicate that these Lingo statements have run. Suppose you were trying to determine why the playhead did not go to the frame labeled "Game Start." If the line
_movie.go("Game Start")
never appeared in the Message window, maybe the condition in the
-->
previous statement was not what you expected.
The Message window Output pane can fill with large amounts of text when the Trace button is on. To delete the contents of the Output pane, click the Clear button. If the Output pane is not visible, the contents of the Input pane are deleted.
You can keep track of the value of variables and other objects by selecting the name of the object in the Message window and clicking the Inspect Object button. The object is added to the Object inspector, where its value is displayed and updated as the movie plays. For more information on the Object inspector, see “Debugging in the Object inspector” on page 91.
When you are in debugging mode, you can follow how a variable changes by selecting it in the Message window and then clicking the Watch Expression button. Director then adds the variable to the Watcher pane in the Debugger window, where its value is displayed and updated as you work in the Debugger window. For more information on the Watcher pane, see “Debugging in
the Debugger window” on page 94.

Debugging in the Object inspector

With the Object inspector, you can view and set properties of many kinds of objects that are not displayed in the Property inspector. These include scripting objects such as global variables, lists, child objects from parent scripts, all 3D cast member properties, sprite properties, script expressions, and so on. In addition, the Object inspector displays changes to object properties that occur while a movie plays, such as changes due to scripts or changes to sprite Score properties. These kinds of runtime changes are not displayed in the Property inspector during movie playback.
To open the Object inspector:
Select Window > Object Inspector.
Debugging in the Object inspector 91

Understanding object structure

The Object inspector can be very useful for understanding the structure of complex objects. For example, 3D cast members have many layers of properties. Because the Object inspector shows you a visual representation of the nested structure of those properties, it makes it much easier to become familiar with them and their relationships to each other. Understanding the property structure of objects in Director is important when writing scripts.
The ability to watch the values of properties change while a movie plays is helpful for understanding what is happening in the movie. It is especially helpful when testing and debugging scripts because you can watch as the values change based on scripts you’ve written.
The Director Debugger window displays this information also, but is only available when you are in debugging mode. For more information on debugging, see “Advanced debugging”
on page 99.

Viewable objects

The following are some of the objects you can enter into the Object inspector:
Sprites, such as sprite(3)
Cast members, such as member("3d")
Global variables, such as gMyList
Child objects, such as gMyChild
Macromedia Flash objects, such as gMyFlashObject; for more information about using Flash
objects in Director, see the Using Director topics in the Director Help Panel.
Script expressions, such as sprite(7).blend
Viewing objects
There are three ways to view an object in the Object inspector. You can drag items directly into the Object inspector, enter the name of an item into the Object inspector manually, or use the Inspect Object button in the Message and Script windows.
To drag an item to the Object inspector, do one of the following:
Select a sprite in the Score window and drag it to the Object inspector.
Select a cast member in the Cast window and drag it to the Object inspector.
Select a the name of an object in the Script, Message, or Text window and drag it to the
Object inspector.
To enter an object manually in the Object inspector:
1 Double-click in the first empty cell in the Object column of the Object inspector. 2 Type the name of the object into the cell. Use the same name you would use to refer to the
object in your scripts.
3 Press Enter (Windows) or Return (Macintosh). If the object has subproperties, a plus sign (+)
appears to the left of it.
4 Click the plus sign. The properties of the object appear below it. Properties with subproperties
appear with a plus sign to their left. Click each plus sign to display the subproperties.
92 Chapter 4: Debugging Scripts in Director
To view an object using the Inspect Object button:
1 In the Script window, highlight the part of a statement that refers to an object. 2 In the Script window, click Inspect Object. If the object has subproperties, a plus sign (+)
appears to the left of it.
3 Click the plus sign. The properties of the object appear below it. Properties with subproperties
appear with a plus sign to their left. Click each plus sign to display the subproperties.
Note: Inspecting large numbers of objects or large individual objects in the Object inspector can cause noticeable performance issues during authoring, particularly when Auto Poll is enabled. For example, inspecting a list that contains 10,000 entries can make Director appear to hang while the display is updating.
Navigating objects
You can also navigate the contents of the Object inspector with the arrow keys on your keyboard.
To move up or down in the list of items:
Use the Up and Down arrow keys.
To view an item’s subproperties:
Select the item and press the Right arrow key.
To hide an item’s subproperties:
Select the item and press the Left arrow key.

Using Autopoll

System properties, such as
milliseconds and colorDepth are only updated in the Object
inspector when the Autopoll option is turned on. Using Autopoll increases the processor workload, which can slow your movie’s performance when you add more than a few system properties to the Object inspector.
To turn on Autopoll:
1 Right-click (Windows) or Control-click (Macintosh) in the Object inspector. The Object
inspector context menu appears.
2 Select Autopoll from the context menu. When Autopoll is on, a check mark appears next to the
Autopoll item in the context menu.
To turn off Autopoll:
Select Autopoll from the context menu again.

Modifying object or property values

You can set the value of an object or property in the Object inspector by entering a new value in the box to the right of the object or property name.
To set an object or property value:
1 Double-click the value to the right of the item name. 2 Enter the new value for the item. 3 Press Enter (Windows) or Return (Macintosh). The new value is set and reflected in your
movie immediately.
You can enter a script expression as the value for an item. For example, you might set the value of
sprite(3).locH to the expression sprite(8).locH + 20.
Debugging in the Object inspector 93

Removing objects

You can also remove items from the Object inspector.
To remove a single item from the Object inspector:
Select the item and press the Backspace (Windows) or Delete (Macintosh) key.
To clear the entire contents of the Object inspector:
Right-click (Windows) or Control-click (Macintosh) inside the Object inspector and select
Clear All from the context menu.
When you open a separate movie from the one you are working on, the objects you entered in the Object inspector remain. This makes it easy to compare different versions of the same movie. When you exit Director, the items in the Object inspector are lost.

Debugging in the Debugger window

The Debugger window is a special mode of the Script window. It provides several tools for finding the causes of problems in your scripts. By using the Debugger, you can quickly locate the parts of your code that are causing problems. The Debugger window allows you to run scripts one line at a time, skip over nested handlers, edit the text of scripts, and view the values of variables and other objects as they change. Learning to use the tools in the Debugger window can help you become a more efficient programmer.
The Debugger window can help you locate and correct errors in your scripts. It includes several tools that let you do the following:
See the part of the script that includes the current line of code.
Track the sequence of handlers that were called before getting to the current handler.
Run selected parts of the current handler.
Run selected parts of nested handlers called from the current handler.
Display the value of any local variable, global variable, or property related to the code that
you’re investigating.

Entering debugging mode

In order to access the Debugger window, a break must occur in a script. A break occurs when Director encounters a script error or a breakpoint in a script.
When a script error occurs, the Script Error dialog box appears. The dialog box displays information about the type of error that occurred, and asks you whether you want to debug the script, edit the script in the Script window, or cancel.
To enter debugging mode, do one of the following:
Click Debug in the Script Error dialog box.
Place a breakpoint in a script.
When Director runs and encounters a breakpoint, the script stops executing and the Script window changes to debugging mode. The movie is still playing, but the execution of your scripts is stopped until you use the Debugger to tell Director how to proceed. If you have multiple Script windows open, Director searches for one containing the script where the breakpoint occurred and changes that window to debugging mode.
94 Chapter 4: Debugging Scripts in Director
To add a breakpoint that will open the Debugger window:
1 In the Script window, open the script that should contain the breakpoint. 2 Click in the left margin of the Script window next to the line of code where you want the
breakpoint to appear, or place the insertion point on the line of code and click Toggle Breakpoint. Your code will stop executing at the beginning of this line, and the Script window will enter debugging mode.
If the Script window is open when Director encounters a script error or a breakpoint, the Debugger window replaces the Script window.
To stop debugging, do one of the following:
Click the Run Script button in the Debugger window. This resumes normal script execution.
Click the Stop Debugging button in the Debugger window. This stops both the debugging
session and the movie. The Script window reappears in place of the Debugger window.
When the Debugger window opens, it shows the current line of code and offers several choices for what to run next.
To see which is the current line of code:
Look for the green arrow next to a line of code in the Script pane.
The green arrow points to the current line. You cannot select a different line of code by clicking it in the Script pane.

Viewing the call stack in the Debugger window

The Call Stack pane displays the sequence of nested handlers that ran before the current line of code. This sequence is called the call stack. Use the call stack to keep track of the structure of your code while you are debugging. You can view the variables associated with a specific handler by clicking the handler name in the Call Stack pane. The variables are displayed in the Variable pane.
Debugging in the Debugger window 95

Viewing variables in the Debugger window

The Variable pane of the Debugger window displays the variables associated with the current handler. The current handler is the handler displayed in the Script pane and the last handler displayed in the Call Stack pane. You can also display the variables associated with previous handlers in the call stack. As you step through a script, changes to the values of any of the variables are displayed in red. For more information on stepping through scripts, see “Stepping
through scripts in the Debugger window” on page 97.
To display the variables associated with a handler in the call stack:
Click the name of the handler in the Call Stack pane. The variables appear in the
Variable pane.
The Variable pane includes four tabs for viewing variables:
The All tab displays both global and local variables associated with the current handler.
The Local tab displays only the local variables associated with the selected handler.
The Property tab displays the properties declared by the current script.
The Global tab displays only the global variables associated with the selected handler.
You can sort the variables in the Variable pane:
To sort the variables by name, click the word Name that appears above the variable names.
To sort the variables in reverse-alphabetical order, click the word Name a second time.
You can change the values of local variables of the current handler and global variables in the Variable pane. You cannot change the value of local variables that are not in the current handler.
To change the value of a variable in the Variable pane:
1 Double-click the value of the variable in the Value column. 2 Enter the new value for the variable. 3 Press Enter (Windows) or Return (Macintosh).

Viewing objects in the Debugger window

With the Watcher pane in the Debugger window, you can view variables and other data objects associated with the current handler, as well as objects associated with other handlers. By adding objects to the Watcher pane, you can keep track of their values as they change because of scripts. When the value of an object changes due to the execution of a line of code, Director changes the color of the object’s name in the Watcher pane to red.
The Watcher pane displays only the objects you add to it. You can use up to four separate tabs in the Watcher pane to organize objects into groups.
To add an object to the Watcher pane whose name appears in the Script pane:
1 Select the name of the object in the Script pane. 2 Click the Watch Expression button.
96 Chapter 4: Debugging Scripts in Director
To add an object to the Watcher pane whose name does not appear in the Script pane:
1 Double-click the first empty cell in the object column of the Watcher pane. 2 Type the name of the object in the cell and press Enter (Windows) or Return (Macintosh).
If the object has properties, a plus sign (+) appears next to the object’s name.
To display an object’s properties:
Click the plus sign next to the object name.
The Watcher pane lets you organize objects in a few ways.
To organize objects in the Watcher pane, do one of the following:
To sort the objects in the Watcher pane, click the Name column head at the top of the left
column. The object names in the column are listed in alphabetical order.
To sort the objects in reverse-alphabetical order, click the Name column head a second time.
To organize objects into groups, use the tabs in the Watcher pane. To add an object to a
specific tab, click the tab you want to use before adding the object.
To clear the contents of a tab in the Watcher pane, select the tab and then right-click
(Windows) or Control-click (Macintosh) in the Watcher pane and select Clear All.

Stepping through scripts in the Debugger window

The Debugger window provides you with a set of tools for running scripts slowly, so you can watch the effect that each line of code has on your movie. You can execute one line of code at a time and choose whether to execute nested handlers one line at a time or all at once.
To execute only the current line of code indicated by the green arrow:
Click the Step Script button.
Many handlers include calling statements to other handlers. You can focus your attention on such nested handlers, or ignore them and focus on the code in the current handler.
When you are confident that nested handlers are performing as expected and want to concentrate on the code in the current handler, the Debugger window can step over nested handlers and go directly to the next line of code in the current handler. When the Debugger steps over a nested handler, it executes the handler, but does not display the handler’s code or pause within the nested handler.
To step over nested handlers:
Click the Step Script button in the Debugger window.
The Step Script button runs the current line of code, runs any nested handlers that the line calls, and then stops at the next line in the handler.
If you suspect that nested handlers are not performing as expected and want to study their behavior, the Debugger window can run nested handlers line by line as well.
To run nested handlers one line at a time:
Click the Step Into Script button in the Debugger window.
Clicking the Step Into button runs the current line of code and follows the normal flow through any nested handlers called by that line. When finished with a nested handler, the Debugger window stops at the next line of code within the upper-level handler.
Debugging in the Debugger window 97
When you are finished debugging, you can exit the Debugger at any time:
To resume normal execution of code an exit the Debugger window:
Click the Run Script button.
To exit the Debugger and stop playback of the movie:
Click the Stop Debugging button.

Editing scripts in debugging mode

When you are in debugging mode, you may edit your scripts directly in the Debugger window. This enables you to fix bugs as soon as you find them and then continue debugging.
To edit a script in the Debugger window:
1 Click in the Script pane and place the insertion point where you want to begin typing. 2 Enter the changes to the script.
You can jump to a specific handler by selecting the name of the handler and clicking the Go To Handler button.
3 When you are finished debugging and editing scripts, click the Stop Debugging button. The
Script window returns to Script mode.
4 Click the Recompile All Modified Scripts button.

Debugging projectors and Shockwave movies

This section discusses debugging during runtime in Director projectors and movies that contain Macromedia Shockwave content. You can use either the Message window or enable full script error dialog boxes to debug projectors and movies that contain Shockwave content.
To debug using the Message window:
Set the Player object’s debugPlaybackEnabled property to TRUE.
When this property is content opens a Message window (Windows) or a Message text file (Macintosh), and the results of any
put() or trace() function calls are output to these formats.
If at any time during the movie the Message window or text file is closed and cannot be opened again during that playback session, even if
debugPlaybackEnabled is set back to TRUE later in that session.
To debug by enabling full script error dialogs:
TRUE, playing back a projector or a movie that contains Shockwave
debugPlaybackEnabled property is set to FALSE, the
In an .ini file for a projector or a movie that contains Shockwave content, set the
DisplayFullLingoErrorText property to 1.
This generates more descriptive error text in the script error dialog box than the generic error text. For example, a generic error message might look like:
Script error: Continue?
Setting the DisplayFullLingoErrorText property to 1 could generate the following error message:
Script error: list expected
For information on creating and modifying an appropriate .ini file for a projector or a movie that contains Shockwave content, see the Director.ini template file in the root Director installation folder.
98 Chapter 4: Debugging Scripts in Director

Advanced debugging

If the problem is not easy to identify, try the following approaches:
Determine which section has the problem. For example, if clicking a button produces the
wrong result, investigate the script assigned to the button. If a sprite does the wrong thing, try checking the sprite’s property values. Are they set to the
values you want when you want?
Figure out where the script flows. When a section of the movie does not do what you want,
first try to trace the movie’s sequence of events in your head. Look at other scripts in the message hierarchy to make sure Director is running the correct handler.
Follow the tracing in the Message window; this shows which frames the movie goes through
and any handlers that the movie calls as the movie plays.
Try using the Step Script and Step Into features in the Debugger window and see whether the
results differ from what you expect.
Check variables and expressions. Analyze how their values change as the movie plays. See if
they change at the wrong time or do not change at all. If the same variable is used in more than one handler, make sure that each handler that uses the variable states that the variable is global.
You can track the values of variables and expressions by displaying their values in the Watcher pane of the Debugger window or the Object inspector.
Make changes one at a time. Don’t be afraid to change things in a handler to see if the change
eliminates the problem or gives some result that helps point to the problem. However, do not trade one problem for another. Change things one at a time and change them
back if the problem is not fixed. If you introduce too many changes before solving a problem, you might not determine what the original problem was and you might even introduce new problems.
Re-create the section. If you have not found the problem, try re-creating the section from
scratch. For example, if rolling the pointer over a sprite does not make the sprite behave the way you want, create a simple movie that contains just the sprite and handler with the
rollOver() method.
Do not just copy and paste scripts; that might just copy the problem. Re-creating the section lets you reconstruct the logic at its most basic level and verify that Director is working as you expect. If the section that you re-create still does not work properly, chances are that there is something wrong in the logic for the section.
If the section that you re-create works properly, compare that section to the original movie to see where the two differ. You can also copy the section into the original piece and see whether this corrects the problem.
Advanced debugging 99
100 Chapter 4: Debugging Scripts in Director
Loading...