I l@ve RuBoard

Chapter 1. Flash Basics

In this chapter, we learn to build simple interface elements and interactive structures. Both the elementary structures we build and the techniques we learn are used and developed further throughout the book.

This chapter is intended for readers who are new to Flash. It brings them up to speed quickly on editing conventions and ActionScript fundamentals. It also presents an overview of the design of data and execution in the trivia game.
    I l@ve RuBoard


The Background of Flash

Flash is an interesting phenomenon. It began with technology intended for pen computing. This technology—which translated strokes into drawings—was commercialized as SmartSketch, a personal computer drawing package. SmartSketch made it easy for artists to create pictures that were defined as geometry, not as a screen of pixels. The inventors of the program, such as, Jonathan Gay, understood the advantages of this technology—vector drawing—over the more familiar technique of pixel painting. Geometric descriptions scale perfectly and they are extremely efficient. It is easy to move these pictures from one computer to another. High-level drawing descriptions also make it easy to organize the elements of a drawing—and to manipulate them mathematically.

Easy manipulation means powerful animation. SmartSketch evolved into CelAnimator—a professional cartooning tool. The cartooning world is fairly small—and was smaller still in the 1990s. This vector animation program might have disappeared like its predecessors except for the emergence of the Internet. Device independence and tiny bandwidth requirements were a great fit for the web—which was starved for animation.

Macromedia was introducing its venerable animation system, Director, to the Internet under the name Shockwave. But pixel-based technology such as Director is inflexible and slow to load. In 1996, Macromedia acquired the product, then called FutureSplash. They changed the name to Flash and merged it into the Shockwave line.

In succeeding years, more interactivity and much more scripting were added to Flash.

After a few awkward attempts to develop a proprietary coding syntax, Flash ActionScript was stabilized by adopting ECMA-262 as the basis of its language definition. ECMA-262 is the international standard for web scripting. (JavaScript is an ECMA-compliant language.)

This decision lowered the learning curve for developers and reduced a lot of confusion and ambiguity. It allowed Flash to develop from a simple animation system to a fairly robust environment for the development of interactive web applications.

A second wise decision also involved the adoption of web standards. Macromedia chose XML to be Flash's data-communication technology. Suddenly Flash developers were able to easily interact with an enormous number of web services. This changed the nature of Flash once more. Instead of a stand-alone web application, a Flash presentation can be integrated into a complex system of web-enabled software. Flash is no longer limited to entertainment. It is now ready to provide high-quality interfaces to all kinds of hard working web applications.


Practical Flash

In this chapter, we do not attempt to conscientiously teach Flash graphics creation. That is the subject of many other books. The chapter is not even an overview of the subject. In fact this chapter is more of an underview. We offer a mouse's-eye view of the construction of a few simple but sophisticated interface elements. We don't suggest that our methods are the best approach to each problem. Multifaceted software like Flash invites creative approaches. The approach we show here, based on much experience in team production of code and graphics, is one good approach. Consider it as you develop your own.

Project Design

The trivia quiz game that we will build throughout this book is complex and sophisticated. It starts, however, with some simple ideas that are recognizable in every later step of development.

Before we start any code, even demonstration code, we need to think a little about the design. In general, a detailed planning phase is always a good investment. But in this case, just a simple layout of hierarchy will suffice.

We organize a Game into a series of Quizzes (Figure 1.1). Each Quiz has several rounds. A Round is the presentation of a Question, the player's response, and the scoring. The Question is presented in Q&A format: a single Q and multiple-choice A's.

Figure 1.1. Object Hierarchy of the Trivia Game

In this chapter we create a single functional Round. We present a Question and a series of Answer options and determine whether the player has chosen the correct one. That's all for now.

Our approach is to develop three states: Start state, Win state, and Lose state (Figure 1.2). The latter two states comprise the Response to the user. The Start state encapsulates the Question presentation.

Figure 1.2. Logic at One Round
    I l@ve RuBoard


Event-Driven Graphics

A great strength of ActionScript is that execution is event driven. Things that happen in the outside world cause things to happen in Flash.

Frame Events

The most common event is that time passes. Of course, time passes rather continuously, but in Flash (as in video or film) time is broken into a stream of regular intervals called frames. In a typical Flash application there are 12 frames per second. Twelve times every second, Flash is interrupted by a frame event (more precisely, a frame start event), which starts a cascade of calculations. Anything that is in the process of moving must determine its new position and prepare to redisplay. This is how animation happens.

Each movie has a timeline. When a frame event occurs, it advances a pointer along the timeline to execute any new script or effect any changes scheduled for this frame.

Mouse Events

Frame events give Flash animation. Mouse events give it interactivity. When a user clicks a button, that is an event. It is in fact a series of events: First the cursor enters the button's hot spot (the Roll Over event). Then the user depresses the button (the Press event). Then the user stops pressing (Release) and moves the cursor away (Roll Out). All four events happen often within a half second, but each has a different meaning in the rapidly stabilizing language of user interface:

Roll Over: | What is this?
Press: | I think I want to perform this action
Release: | Yes, I do! I am committed.
Roll Out: | Oh. Well, now I am bored.

A good designer considers each event and supplies appropriate responses.

Button State

A button has three preprogrammed responses to mouse events. Each is a special named frame.

The Roll Out event causes gotoAndStop("Up").
Roll Over causes gotoAndStop("Over").
The Press event causes gotoAndStop("Down").

Button Event Handlers

There are many more mouse events besides these three. Flash allows us to attach activity to any combination of events.

An event handler connects an event to actions. Event handlers are expressed as code fragments, not as keyframes. They are explicitly packaged as the code called by (for example) the Drag Out event or the <Escape> Key Press event—or both.

There is a fundamental difference between button states and button events. Button state frames are formulated as part of the button object. This is, in effect, a prototype that we construct that lives in the library. Later, we place as many instances of this button in the application as we need.

An instance is not a copy. It is a new reference to the original unchanged prototype. This very powerful concept is at the heart of Flash architecture.

Since the button states are in the prototype, all instances we create (by dragging the button into the scene) share the same states. They behave identically, as long as their behavior is designed in the states.

But every button cannot do the same thing. Some buttons open and some buttons close. Some win and some lose.

To make this happen, Flash allows us to attach event handlers as Object Actions to the instance of the button. They can behave like the button states, and they can do more. They can identify seven mouse events, not just three, and they can attach any ActionScript to those events on that button. Button state frames (in the button's prototype) usually define the button's appearance and its dynamics—how it looks, how it moves, and how it sounds. Event handlers (attached to the instance) usually specify what the button does, how it affects the rest of the world.


Building a Button

An answer option must be sensitive to the mouse. Players click on one of the options and actions are performed. It would also be good to have visible and audible reaction to the various steps in the mouse click and to the mouse rollover as well. Flash gives us all these abilities and more in the Button primitive. To clearly understand how buttons operate, it is best to take a step or two back.

To create a button, invoke Flash's NEW SYMBOL function, tucked away in the Insert pulldown (Figure 1.3).

Figure 1.3. Starting a New Button Symbol

Button Graphics

The button we want is a wide panel of color. One such button will sit behind the text of each answer option and perform all mouse interactions.

We create a filled rectangle— nice and wide and not much taller than a single line of text. It can easily be resized and reshaped later, if necessary. Our example is 400 pixels wide and 30 high.

We also included a simple beveled effect by making an outline rectangle of the same size. For clarity, it is given its own Border layer. New layers are created by clicking the dog-eared icon with a + sign.

Right-clicking on the outline brings us to the Stroke palette, where we set the thickness to 3. We duplicate the Border layer and create Border-top and Border-bottom using cut and paste and rename. We differentiate them by deletion so that Border-top has only the top and left line segments and Border-bottom has the bottom and right segments. The Border-top layer is colored brighter than the panel, while the Border-bottom layer is darker.

Button States

As we've seen, a button has four predefined frames:

  • Up is the default button state.

  • Over starts with mouse roll-on and ends with roll-off or click.

  • Down is from mouse click until release or roll-off.

  • Hit is the invisible shape that defines the click-sensitive area (hot spot) of the button.

We leave Hit as our original rectangle. Its color is meaningless.

For each of the three visible states we create a keyframe (INSERT/KEYFRAME) on each layer. Colorizing these nine keys gives us a lively button. The panel (a solid shape) is colored with the Paint Bucket while the borders (strokes) require the Ink Bottle. Each tool has its own color menu.

Big jumps in color make buttons very interactive but often very unpleasant. Rather than choosing colors from all over the spectrum, we should seek a meaningful palette with subtle transitions.

Button Sounds

Before moving on, let's add a finishing touch to this button: a bit of audible response. Ideally, we would like to hear a sound begin when the button is pressed and conclude when it is released. Like cha-klunk—sounding cha on press, klunk on release. This is possible in Flash, but it is not directly supported. It is much easier to simply attach a sound to the Down frame. Users will hear the sound—the whole sound—as soon as they press the button. Unfortunately, this means that they hear the same confirming cue when they press down but roll off (i.e., change their minds) as when they solidly click and release the button (commit).

Create a Sound layer, which is simply an ordinary new layer that you name Sound (only for our own source clarity, not for Flash). Insert a single keyframe in the Down frame. Choose a sharp sound from the choices in WINDOW/COMMON LIBRARY/SOUNDS. A tiny Play button in the library window allows you to preview each sound. With the keyframe highlighted, merely drag the sound into the main window to integrate it into the button (Figure 1.4).

Figure 1.4. Adding Sound to a Button

By now, you must be ready to try this button out. CONTROL/TEST MOVIE lets you click your new button. Close the window to return to the editor.

Experiment with your own ideas to make the button lively and unique. Subtle tunings make big differences. Get happy with your button and move on.


Constructing a Round

We now build the interactive round. In this case, the round has three possible states:

Start: Present the question and wait for response.

Win: Response was correct.

Lose: Response was incorrect.

Note

We believe that strict discipline is sometimes liberating. Flash allows code to be embedded in any frame and any layer and to be attached to each instance of any object. This much freedom permits the programmer to be creative. Code can be tucked into many corners, and a clever programmer can devise a tricky game of hide and seek.

Hide and seek is fun in the back yard. But it is annoying at the computer and deadly when many people are working together and facing real deadlines.

The challenges of making good software together are numerous enough without inventing more. So we direct our creativity elsewhere and approach code placement with this strict discipline:

If you use ActionScript on any frame, put it in a reserved layer called Code.

Put labels on the top layer— in the Code layer if there is one, or even a Label layer.

Sounds should also be in their own layer(s).

Object actions, such as button actions, are exceptions. If the button is going to do anything, an event handler must be attached to the object instance, not to a keyframe in a timeline layer. Any object action should be extremely simple—it should invoke script visible on this timeline. (This means calling a local function or going to a particular frame.)

Like the button, the Round will establish each of the three states as a separate frame. While Flash frames often represent tiny slices of time in the progress of an animation, they frequently are used instead to represent static screens and as targets in finite-state logic. Often, they are both.

Make a Movie Clip symbol using INSERT/NEW SYMBOL.

Create a Code layer. Like the Sound layer earlier, this is an ordinary layer to which we give a special name. Other than as a reminder for ourselves (and a hint to fellow programmers) layer names have absolutely no meaning.


Making Keyframes

In the Code layer, label three keyframes Start, Win, and Lose. These frames do not have to be consecutive. It is easier to read the labels if they are not and if the LARGE option is chosen behind this tiny icon, found on the right, just above the timeline:

To label a frame easily, open the Frame panel (by right-clicking on a frame, then opening PANELS/FRAME). Type the label name into the obvious place, and voilà!

Construct the Start state

The Start state has a question and four answer options. Each answer option links to either the Lose or Win state. It also has a tiny bit of script.

Double-click on the Start keyframe. This will open an Actions panel.

Type in the single command stop(); and close the panel. This will freeze the movie on the first frame of the scene. It will not animate. It will sit patiently waiting for the user to create the events that bring it to life.

To create the events, the user needs buttons to press.

Button Instance

Make a layer for the first option. Let's call it A0. Highlight a keyframe at the Start frame of A0, and drag in the AnswerButton we already built. The AnswerButton is a symbol in the library. If the library is not already open, select WINDOW/LIBRARY.

The button we see on the Start frame is an instance of the AnswerButton symbol. Many instances can exist for any symbol. They share one copy of the graphics, sound, and embedded code. But each instance has its own set of variables. Each has independent properties. And each instance has unique actions attached to it. That is our next step.

Button Actions

Right-click on the button and open Object Actions (Figure 1.5). Since it is possible to place actions on the keyframe as well as on the button itself, you must take care to double-click on the button, not the frame. The operations look similar but function differently. The title of the ActionScript panel should be "Object Actions."

Figure 1.5. Adding Actions to an Object in Normal Mode

This ActionScript panel can appear in Normal or Expert Mode. In Normal mode you can click on Go To and insert this function. Choose the Type of the goto as Frame Label and select the Lose frame.

The support from the Normal mode training wheels is welcome at first; it helps remind us of options and syntax (was it "Roll Out" or "rollOut"?). But it quickly becomes claustrophobic.

This code will cause the movie to play the Lose frame whenever the mouse release (the final part of a click) occurs with the cursor over this button. This functionality is all we need for now.

Button Text

Now we need to put an actual answer on this option button.

Highlight the keyframe (and defocus the button; Figure 1.6). Using the Text tool, stretch a rectangle across the face of the button and type in the first answer option. Right-click on the text to open the panel Character to choose color, font, and size. Paragraph lets you choose (for example) to center text.

Figure 1.6. Adding Text to a Button

Now we have a single button that is useful for choosing "William the Conqueror" and achieving a Lose result.

Hey, it's a start.

More Buttons

Highlight the keyframe that has the button instance and the text (Figure 1.7). Copy the keyframe. Create three more layers, and paste the keyframe in each. Name them and align the buttons nicely.

Figure 1.7. Quadruplicated Buttons

It is best to align the buttons using numbers in the Info inspector. While Flash features alignment tools to help with layout problems like this, we'd better get used to solving them mathematically. We are ultimately going to abstract and automate these design steps, for example, when programming an unknown number of buttons to space themselves out automatically.

Now it is the work of a few minutes to change the text so that we have four distinct answers. While we are at it, we had better include a question in the Q layer (Figure 1.8).

Figure 1.8. Differentiating the Four Buttons
    I l@ve RuBoard


Constructing the Responses

Now that we have a Question and four possible Answers, we need to formulate a few Responses: Lose and Win.

Lose State

The Lose frame replaces the question on the Q layer with the message "Sorry, wrong" (Figure 1.9). The keyframe has a single line of ActionScript—just

Figure 1.9. The Lose Screen

ActionScript
stop();

This has the desired effect of keeping the player at this screen until he decides to move on. It is a trivial interaction; the player has no other choice and in fact is not penalized for making a bad choice—yet.

The Lose frame drops layers a1, a2, and a3 (three buttons) and changes the text on the remaining button. More important, it also changes the button's Object Actions script. The new Object Action script has a goTo aimed at the Start frame (Figure 1.10).

Figure 1.10. Programming the Try Again Button

Win State

Finally, the Win frame tells the player he won the round and presents a little explanatory text (Figure 1.11).

Figure 1.11. The Win Screen

We have all the parts of a very primitive quiz round. Try it (CONTROL/TEST MOVIE). It moves—but it feels dead. So far there is no scorekeeping, just the display of text. In fact, the player who gets here after three wrong guesses gets pretty much the same payoff as the player who knows the correct answer right away.


Finishing Features

Lets polish this little round with a scoring mechanism and a button that takes the player from the Win screen to the next round. We understand buttons now, so we should be able to create this button without help. Try it!

Keeping Score

Scoring requires a more sophisticated approach to ActionScript than we've seen so far. A score is measured in points. Our first pass is this: When a player answers incorrectly, he loses a point. When he answers correctly, he gains a point. Since he can make several wrong answers before the correct one, we will need a variable, called points.

Many languages require variables to be declared—their name and type (and scope) have to be unambiguously indicated before they can appear in code. Not so in scripting languages like ActionScript. A variable can be written to before it is declared. It can even be accessed before it is declared or written to. In that case, it is of type undefined. Depending on the context, it will provide a value of 0, "", null, false, or NaN (NotANumber).

Although it is somewhat questionable coding practice, we will take advantage of this feature. It keeps our example simple, and it is certainly stable enough for the demonstration.

Open the Actions on the Win keyframe and add these lines:

ActionScript
points++;
trace( points );
stop();

The first line should be familiar: It is the elegant increment operator, introduced by Kernighan and Ritchie and found in many languages. It has the same effect as but it looks infinitely cooler, even after 20 years.

ActionScript
points= points+1;

The second line is a temporary step that prints the value of points in a debugging window of the Flash development environment called Output. It will soon be removed. (In fact, Flash can remove trace() commands automatically when the .swf file is published.)

Open the Lose frame, enter the same code, but replace the increment operator with decrement.

ActionScript
points--;
trace( points );
stop();

Play with it. It works fine, and it is certainly satisfying to know that ignorant players will lose something for choosing the wrong William.

But unless we display the score onscreen, it is pointless.

Displaying the Score with DYNAMIC TEXT

A spot for text has been blocked out on the screen (Figure 1.12) in the upper right. The Character and Paragraph features of the text are similar to those we've applied in the past, but the Text Options are new. Rather than Static Text, Text Options is set to Dynamic Text and displays the points variable. At this point we can remove the trace() statements from the Win and Lose keyframes.

Figure 1.12. Setting Up Dynamic Text

Now play with our round!

With the addition of these features, the game is quite a bit more fun! It is great to keep score (especially when we know the answer). But the most exciting feature is the little button labeled "Next." The "Next" button promises a fresh question. It reminds us that often fun depends on fresh content. This would not be true if we were building an online checkers site, but it is absolutely the case in a trivia game.

Figure 1.13. Win Screen with Score Display
    I l@ve RuBoard


Conclusion—and Beyond

We have created an interesting little quiz round that is clear and responsive and tracks the player's score. But let's be honest—it isn't a very intelligent design. With good questions, this game will be fun to play, but it is never going to be fun to develop, and maintenance will be a tedious feat of endurance. To create the second (or the nth) question will require an effort comparable to the work we just did creating the first.

In the next chapter we make the same user experience a much better experience for those of us who develop the game. Any work that is done creating buttons will be done only once. Software and data-driven elements will leverage the investment we make in the first question and take us one step closer to a clever solution designed around a thin Flash component fed by a rich XML trivia server.


Chapter 2. Flash ActionScript: Objects and Events

This chapter promotes our understanding of Flash to include advanced ActionScripting. We will study data structures in memory and the dynamic creation and destruction of graphic elements. The basics of object-oriented programming are covered.

We start by covering the basics of object orientation. Then we use that knowledge in reforming our quiz. The quiz round we built in the previous chapter is functional but inflexible. We fix that by changing the way it is constructed, from the inside out. The goal is an entirely data-driven trivia game. Eventually the game will get its data from external servers—but not in this chapter. Here we convert our quiz into a data-driven quiz, but the data is hard coded internally in the Flash file itself.

This chapter is intended for those who are still learning Flash ActionScript. It teaches practical issues of execution control, data access, and a quick shower of syntax. It is not meant to be comprehensive coverage of ActionScript, but it will take an attentive novice from a dead stop to functional scripter in a dozen pages.


Object Orientation Concepts

The distinguishing characteristic of object-oriented programming languages is the design of objects.

Suppose we wished to keep track of all the information about the green floppy disk where we are saving this document. We would need many variables. We could give them names like greenDiskFreespace, and greenDiskWriteProtected. But we quickly see that the code grows unwieldy when we wish to also create representations of a translucent red disk (where we store a backup of this chapter), a nontranslucent red disk (which holds a copy of "Ozymandias"), and a yellow disk (which was just formatted).

By contrast, we can create an object. An object is a collection of variables and functions that represent some thing. It can be a physical dingus in the outside world—like a rocketship or floppy disk. It can be a well-understood abstraction—like a savings account or a 3D transformation matrix. Or it can be a new abstraction that we invent for our own convenience—like a trivia question or an internet socket. The fundamental requirement is that our thing has some standardized definition and makeup or that we can create one for it.

To then use the object, we instantiate it. Instantiation consists of creating an actual variable that represents a particular copy of the object we just created—for example, the green instance of the general object type FloppyDisk.

Classes

The code that defines an object needs to be written only once. That abstract definition of the generic object is usually called the class. A class merely explains how the object is constructed, exactly what the object is, and what it does. It is also called a template for the object (or an object's factory). Sometimes the word is prototype or even symbol.

In fact, since the abstract object is called the object, that word is also frequently used to refer to this formal declaration. This is especially true in languages like ActionScript, where the terms class, template and factory do not appear in the language. Class appears briefly in the documentation and symbol is used for the special case of MovieClip objects.

Instances

Once we have designed an object, we want to create a number of instances of the object. After we create a class template for a FloppyDisk object, we might spawn one, two, or even a thousand FloppyDisks. The thousand instances behave the same, but each has its own identity. Each one has a distinct name. The instances of the object FloppyDisk have all its properties and methods, but each has its own individual value. For example, values for its label and its contents would probably be unique. What one instance of FloppyDisk does (for instance, call the function eject()) affects neither the general class nor any other instances of FloppyDisk.

Objects have the following components:

PROPERTIES

An object that simulates a floppy disk has certain qualities, or properties. It may have a physical size, stored in length, width, and thickness, a string that contains its label, a boolean that indicates write protection, and some quantity of data content. By defining what variables every disk has, we can create several disks that have all the variables we just defined. We can either set up the properties to automatically have a default value or assign values to them later.

So far, objects offer little more than other data structures. Why would anyone want to orient their programming around them?

METHODS

Then we add the object functions called methods. Instead of having a loose function called format that can operate on floppy disks, we can have a function called format within the FloppyDisk object. So we can merely say myFloppyDisk.format() and the floppy disk object, which under stands its own inner workings, formats itself. An object function serves two important purposes. First, it allows us to transfer a self-contained object to anyone who may need it. The second purpose is encapsulation.

ENCAPSULATION

Encapsulation hides the inner workings of an object. Whether the FloppyDisk is a software abstraction or a real disk formatting itself with motors and magnets is nobody's business but its own. Without knowledge of the object's insides, other software and programmers are unable to fiddle with the object and break things. Instead, they can manipulate the object only through an interface that the object's creator designates.

Most object-oriented languages (like Java or C++) force programmers to respect these interfaces. ActionScript does not. It is quite easy to cheat and ignore the distinction between public and private parts of the object. But self-discipline will reap important advantages. These advantages all derive from knowing what the object does—but not how it does it.

It is easier to change an object, because we can change the internal functions and variables and leave the outside interface the same. Imagine if we had to go through various modules updating them all because we've figured out how to make the format command more efficient. Encapsulation also makes it easier to work with other people. A single person may need to know exactly how the object works, but a team does not. It doesn't matter to other programmers how it works; it just matters that it does (this is the way we might feel about an air conditioner).

INHERITANCE

Further, we can set up relationships between objects. A FloppyDisk is one specific type (also known as a child) of the general object Disk (other children might include HardDisk and CDROM). In this case, it is said that FloppyDisk inherits from Disk (also known as its parent). For instance, Disk may have a format() command. In that case FloppyDisk would also have a format() command, by default identical to the Disk.format() method. Further, FloppyDisk would have the same variables that Disk has. This is one of the main advantages of object orientation: its inheritance from Object, to Disk, to FloppyDisk (Table 2.1).

Table 2.1. Inheritance from Object, to Disk, to FloppyDisk
OBJECT ToString()
Disk

FloppyDisk
FloppyDisk instance

EXTENSION

Note the extension of the format command in Table 2.1. If a child object did nothing more than duplicate its parent, inheritance would not be a powerful idea. Inherited traits are modified to meet the needs of the child class. An object-oriented software model of a FloppyDisk might format itself exactly as a generic Disk does. (Set data to be nothing, set free space to be maximum.) But the CDROM object would have a different format routine. (Fail.) No problem. It can overwrite the format routine it inherited.

An object can simply extend its inherited methods. For example our FloppyDisk object might add an extra instruction to the Disk.format() it inherits. (Take a really long time.) Rather than copy code, we say, "Take a really long time" and then format yourself however a regular Disk would be formatted. Extension allows changes to be made at the parent level and trickle down. We can reliably make sweeping changes in small amounts of time.


Object-Oriented Theory vs. ActionScript Reality

The implementation of classic object orientation within Flash is far less rigorous than in many other languages, like Java or C++.

ActionScript does not provide the security of meaningful encapsulation. We have seen that an object's private functions and data are not protected from other ActionScript entities. In fact, outside code not only can examine and alter any variable in an object, it also can create new variables and install new functions. Any programmer can easily overwrite the native functions of another programmer's object—at run time. Not only can the functions of an individual instance be overwritten, but they can also be overwritten in the actual class definition. In fact, a programmer can change the class definition of someone else's objects, and those objects that are already in place and working will immediately exhibit the new behavior. This is rather dangerous.

Other features of object-oriented languages are available in Flash. It is possible to create objects. With a bit of work you can create objects that exhibit inheritance. The actual syntax for creating such hierarchical objects bears attention, as it is not documented and it is far from clear. ActionScript objects are never explicitly declared. Rather, they are implied with the following elements:

A constructor is a function that initializes new instances of an object. Every ActionScript function has the potential to be the constructor of objects with the same name. Simply calling the function with the keyword new identifies it as an object constructor. A function named Disk will construct Disk objects when used in the statement.

floppy = new Disk();

Within an object constructor function, the keyword this points to the new object being created. It is commonly used to initiate variables within the new object.

this.formatted = false;

It can also be used to include methods in the object:

this.format = function ( ) ( ...

However, this places an individual copy of the function in each new instance. There is a more efficient way to construct objects. These properties (functions and variables) can be added to the object's prototype. The prototype is a property that all functions have. It is used by objects to identify the functions and variables of which it is composed. The statement

Disk.prototype.format = function ( ) ( ...

establishes a format() function that all Disk objects will automatically have. It is interesting that the function can be installed into the prototype at any time, even after the constructor has been used to make new instances of the object. All existing instances of the object will suddenly have the new function.

If an object instance does not have a function that is being called, the ActionScript engine seeks it in the prototype. It locates the prototype of any object instance by looking at the object's _proto_ variable, which points to the class prototype.

We can use this trick to create a hierarchical object structure, so that we can gain object inheritance.

FloppyDisk.prototype._proto_ = Disk.prototype;

This sets up the Disk object as a parent of the FloppyDisk object. Here is how we would create the hierarchy of Figure 2.1 in ActionScript code.

Figure 2.1. Adding Dynamic Text to the Button

// Defining the Disk Object
function Disk ( ) {
      trace ( "new Disk" );
}
Disk.prototype.label = "unlabelled disk ";
Disk.prototype.directory = function ( ) {
      trace ( "Directory of Disk... .") ;
}
Disk.prototype.format = function () {
      trace ( "Disk formatted.");
}
// Defining the FloppyDisk Object
function FloppyDisk ( ) {
      trace ( "new FloppyDisk" ) ;
}
FloppyDisk.prototype._proto_ =. Disk.prototype;
FloppyDisk.prototype.directory = function ( ) {
      trace ( "Directory of Disk... .") ;
}
FloppyDisk.prototype.format = function () {
      trace ( "Special floppy format tweak");
      this._proto_._proto_.format ();
FloppyDisk.prototype.eject = function () {
      trace ( "Eject floppy disk");
}
// Here we use the function
fd = new FloppyDisk();  // constructor
fd.directory();         // inherited function
fd.format();            // extended function
fd.eject();             // function
trace ( "Label reads:" + fd.label); // class variable
stop();

The resulting output is

new FloppyDisk
Directory of Disk... .
Special floppy format tweak
Disk formatted.
Eject floppy disk
Label reads: unlabelled disk

We see that fd was able to find eject() in its own prototype. fd found the variable label and the function directory() in its parent's prototype. The format() function used code from the prototypes of both FloppyDisk and Disk.


Flash Objects

The trivia game that we will build by the end of this book is complex and sophisticated. It starts, however, with some simple ideas that will be recognizable in each stage of development. Each round of the game is presented in Q&A format: a single Q and multiple choice As. The quizzes are stored in memory as an array of objects.

Predefined Objects

ActionScript comes with several well-defined built-in objects. The XML object will absorb much of our attention. It has methods (like toString()) and properties (like loaded). It also has a constructor, new XML(). This is the method called when the object is created to set up a new instance of the object. A constructor may load default values into variables, position objects, and take arguments that help individualize and define a particular instance. XML, like all provided classes, is also extensible.

Other Flash objects include traditional data types (such as Number, String, Array, and the generic Object) and system constructs (like Date or XMLSocket). Flash also supplies multimedia objects (Color, Sound, Mouse). Finally it includes the object MovieClip, which describes the methods these animations can perform (like play() or gotoAndStop() ) and the properties they all have (like _visible or _xscale).

Code Objects

ActionScript programmers can extend the palette of objects they are given, as in any object- oriented language. The procedure for defining a new object is simple.

To define an object, first a function is written and given the name of the object. This function will be the object's constructor, the new operator that instantiates the object.

ActionScript
function Question( stuff ) {  . . . startup code for Question. . . . }

Then the _prototype property allows us to add methods and properties to our object. It is the object template. The templated definitions

ActionScript
Question._prototype.ask = function () {  . . . method code. . . .}

become specific and real when application code is encountered:

ActionScript
tuffy= new Question( tuffStuff );
tuffy.ask();

MovieClip Objects

Every time we design a MovieClip (the basic unit of Flash Animation), we are essentially making an object. Though they are not always identified as objects, MovieClips have the same qualities as code objects and ought to be considered at the same time. Like objects, they can be prototyped and instantiated, and they have a private name space.

MovieClips have predefined methods and properties. The predefined properties all begin with an underscore: position as _xpos and _ypos, size as _xscale, _yscale, and so on. The methods include play() and stop().

When we create new MovieClips, we frequently give them their own variables and their own functions. These are addressed and used exactly like the built-in properties and methods of MovieClips.

Symbols and Instances

The object definition of a MovieClip is created while it is open in the editing window. What might be called a class or a template elsewhere is here called a symbol. The symbol libraries have plenty of object definitions, both predefined and custom-built. When we place a MovieClip on the stage—inside another MovieClip (or in the Scene)—we have created an instance of the object.

Functions and variables are usually defined when the symbol is created, but they are usually accessed by individual instances: The basic definition of a MovieClip includes scale properties and play methods. But it is an individual instance that is sized or that plays.

We will see the same characteristics in the objects we build—both in our own specialized MovieClips and in our original ActionScript objects.

Note

Instantiation

Sometimes the concept of instantiation can be hard to keep clear. An analogy might be a television program. A master definition is created (at the studio). An infinite number of instances of this show can exist (in living rooms) without diminishing the original. Each instance can be different (larger, smaller, louder, brighter, bluer) than it appeared at the studio. These differences result from adjustments made to the instance (tweaking the volume, for example). Adjustments to the instance do not affect the original definition, nor do they alter other instances.

MovieClip objects behave the same way. You may draw a robot 300 pixels high, but in one scene he might only be 50 pixels high. In fact, he may appear several times in the same scene at different sizes. Each is an independent instance.

ActionScript objects behave the same way—the contsructor and prototype define generic behavior, but the values within their variables create individual identity for the instances.


Programmable Button

We will drive our game with data in objects like those we just studied. But first we must create interface elements that can respond to these objects.

Text on the Button

Our path to a data-driven screen starts at the bottom. Our first goal is to data-drive the text of each answer option button.

The most straightforward approach is to move the text into the actual button. Currently the four lines of answer option text are in the base movie, each superimposed over a button. We want the button to include dynamic text fields, so that the base movie has no text variables—just four buttons and the ability to direct each of them to display the appropriate text. So we add a new layer to the button; for our own convenience, we name it Text. We create a simple line of text in the desired font and location (Figure 2.1). Bearing in mind that this line of text is just a placeholder and that it stands in for hundreds of different lines of text, we carefully size it and position it to make each of the unknown lines look good.

Dynamic Text

Before we put too much effort into making the text pretty, we need to make it smart. This is easily accomplished with the Text Options panel (Figure 2.2).

Figure 2.2. Dynamic Text Based on the Variable text

We convert this text into Dynamic Text to reflect the contents of a variable, not a fixed string set by the designer. The variable name is specified by the programmer. In this case the variable is named (rather boringly) text.

Checking the HTML option enables italics, boldface, and other effects, and it also permits us to rotate the design—by setting a large font size, for example. We use the HTML option in later examples (though certainly nobody can stop you from trying it right now).

Border/Bg is quite useful for quickly creating simple forms, dialogues, and utilitarian interfaces, but is too crude for a design like ours. It creates a very visible and opaque text box for display, input, or both. It is blatantly two-dimensional, and it lacks even a clumsy mechanism for customization.

The Selectable option should be scrupulously disabled for any button face text. If not, mouse clicks on the button face are frequently trapped as text selection rather than as a button press.

Flash does not know the contents of the text that this line will be called on to display. Neither do we, at this point, but we are in a better position to guess. If we can determine that the text requires only a subset of the entire font, we can trim the size of the Flash file. Faster downloads, happier users.

Most designers call for a special font (one that is not installed on every computer). To display this text, the Flash file must include a copy of each font it uses. Flash is smart enough to create a subset of the font, if you are smart enough to know which characters must be in it: include the whole font, or a subset.

The Text Options panel contains punchbuttons for uppercase and lowercase alphabets, digits, punctuation, and a user-supplied list of characters. We indulge a lazy instinct and just click the Include Entire Font Outline icon.

Now let's clear out some of the clutter from the Static Text example.

Highlight all four answer option layers and click on the garbage can symbol:

Separate the question and responses and the (now solitary) answer onto appropriate layers and frames (see Figure 2.3).

Figure 2.3. Separating the Different States

Activating the Dynamic Text

When we run CONTROL/TEST MOVIE, we see nothing very interesting. Try it. The text is still the text we typed in (Figure 2.4). Boring. But remember that the Dynamic Text is pointing to a variable called text that we have yet to define.

Figure 2.4. No Dynamic Text Appears

Open the Actions panel for frame 1 of the main movie (Figure 2.5). Open the keyframe on the Code layer. Above the existing stop instruction, define the variable text by assigning to it a value—in this case an utterly meaningless string literal.

Figure 2.5. Setting the text Variable

text = "This is the good stuff!";
stop();

Now when we test the movie, the button reflects this assignment:

How dynamic is this dynamic text? Pretty dynamic. Try an assignment that is less fixed than the assigned string literal, like

text= new Date().toString();

The results will be different every time it is run. On this lucky afternoon, the button looks like this:

Fancy Text Effects

Smart design can enable pretty design. Clean structure and no duplication create a great environment for creating rich and interesting graphic details.

In the last chapter we made four different lines of text for the answer options. Each one was individually created as a graphic element. We can see that for every round in a quiz, four more text elements will be needed. Creating a small, 10-question quiz would mean editing 40 lines of text, each of which is a complex graphic operation in a drawing editor. Clearly, you would need to keep the graphic ambitions of the text as simple as possible (no special effects). Otherwise the work of maintaining the quiz site would be overwhelming and extremely error-prone.

By contrast, in the new system, using the elements we are now building, all 40 lines of text display the same text graphic. Any work we do is leveraged enormously—4,000 percent on the first quiz! It pays to invest effort into making this line of text as handsome and as responsive as we can.

Drop Shadow

We can create a drop shadow for this line of text, which will give it a dimensional look. We can also animate the color of both text and shadow on each of the three states, just as the color of the button graphic elements change.

Animating the position of text face and shadow will give the impression that the button is tangibly responding to the click of the mouse. Creative readers will certainly explore other interesting ideas. All this goes toward making our button—and the text on it—lively, rich, and real.

Duplicate the text layer. Name the lower one Text-shadow. Make sure Text is bright and Text-shadow is dark. Offset the two layers slightly. Fortunately, the original Static Text contents are still visible, which helps immensely when laying out and animating the drop shadow (Figure 2.6). Each of these two layers (Text and Text-shadow) will have unique keyframes for the Up, Over and Down states.

Figure 2.6. Shadowed Text

Each of the six keyframes can be tweaked and retweaked until the button feels like it lights up magically, pushes in resiliently, or stimulates whatever sensation the user is intended to feel.


Data Encapsulation

If we like the button, we will want to use it for all four answer options. Our instinct is to copy the button for each of four answers (Figure 2.7). This instinct is fine, but immediately we encounter an important problem. Each button is an instance of the same object, and that object is programmed to display the contents of the string variable text. That means that when this movie runs, all four buttons will always sport identical labels (Figure 2.8). The buttons may delight the eye and tickle the mouse finger, but if they offer no actual choice, the players will find this quiz game pretty dull.

Figure 2.7. The Copied Button

Figure 2.8. Four Buttons—One Variable

Consider various strategies for correcting this problem.

  • Return to static text. We probably don't want to do this. Remember that each of our fancy buttons now has six unique text keyframes. Creating a new simple quiz is no longer merely a tedious ordeal of setting 40 graphic text controls. It is now the impossible chore of programming 240 of them.

  • Create a unique variable for each button (text0, text1… textn). A way to escape from the purgatory of cut and paste might be to establish a special variable for each answer option. Creating a new question now requires only a single assignment of each answer option string:

    text0="Snickers";
text1="Mounds";
text2="Runts";
text3="Payday";

    This looks better at first. But implementation of this scheme will introduce nasty compromises into the button design. To link the button to this text, the button code must include the variable name. We are now talking about four different buttons, alike in every way but the name of a variable.

    This is messy. It destroys the sense that the button is an abstracted prototype that is applicable everywhere. And it limits the number of answers that a question can have.

    Perhaps worse is the practical fact that this scheme will freeze development of the button. It seems pretty and bouncy now, but in the future (maybe 10 minutes from now) we might want to tweak it. We would have to replicate each tweak for all four buttons. In real life, we would leave it untweaked.

  • Apply object-oriented data encapsulation. We can eliminate the problems of proliferating edit points by developing a somewhat more complex object structure. This kind of solution will be our choice again and again in this book. The solution is not free: In exchange for eliminating the chore of performing multiple edits (and remembering where they are), we are required to understand more complex structures built of layered abstractions. As designers, we must create these structures with enough architectural clarity that they can be understood by other restless programmers—such as our future selves.

    This task embodies the noble attributes of every programmer: intelligent appetite for abstraction, distaste for hard-coded hacks and lazy aversion to any repetitive task. Our problem is to differentiate the text data used by one button from the data that another button refers to by the same name.

    Buttons themselves cannot encapsulate data. Specifically, they share the namespace with the MovieClip in which they are instantiated. A MovieClip (the base movie or any other) that contains four button instances has only one text variable.

Note

NAMESPACE

Namespace is an important concept in programming. It is the same as scope. Namespace refers to the phenomenon of the same name having different meanings, depending on where it is used. For instance, the identifier "Dad" could refer to billions of people, but there is only one Dad (normally) in any given family. Namespace is similar. Different objects can have properties with the same names. But because each property is accessed within the context of a different object that it resides in, each is different.

The MovieClip itself has a unique namespace. Thus a MovieClip containing four MovieClip instances can have five unique text variables: its own and one for each of the submovies. It does not matter if the four instances are of the same MovieClip symbol (prototype) or not.

So by wrapping our button in a MovieClip, we can make it addressable.

ActionScript
answer0.text="Snickers";
answer1.text="Mounds";
answer2.text="Runts";
answer3.text="Payday";

Though this seems similar to the previous solution, it is very different. There is only one AnswerButton button object and, in fact, only one AnswerOption MovieClip object (see Figure 2.9). Labels like answer0 and answer1 refer to instances of the AnswerOption symbol. AnswerOption contains a single instance of the AnswerButton. The base movie has four instances of AnswerButton, but they are encapsulated in the answer0, answer1, answer2, and answer3 AnswerOptions.

Figure 2.9. Buttons and MovieClip Symbols

Flash does not allow us to name button instances because button instances do not have private namespaces. We can address only the internals of named MovieClip instances. In Flash, the term target is used to refer to a such a named instance.

For historic reasons, Flash has two ways to address targets and their member components. In Flash 4, we struggled to learn a notation that imitates Unix and URL conventions. Object levels are separated by slashes. Variables are separated by colons. Parents are indicated by double dots and the root by a leading slash. In contrast, Flash 5 introduced ECMA style notation (Table 2.2). Everything is separated by dots. Roots and parents have special names. Despite its wordiness and ambiguity (see _root.carrot and _root.carrot in the table), the ECMA notation is undoubtedly superior and is used throughout this book. The ambiguity demonstrated in the table is overcome by the restriction that a MovieClip object and a data variable cannot use the same name in the same namespace.

Table 2.2. Different Syntax for Reference
WHAT WE ARE REFERING TO | SLASH–COLON SYNTAX | DOT SYNTAX
My variable bar | bar | bar
my child foo's variable bar | foo:bar | foo.bar
root variable carrot | /:carrot | _root.carrot
root MovieClip carrot | /carrot | _root.carrot
carrot's submovie tip | /carrot/tip | _root.carrot.tip
my grandfather's dentures | ../../:dentures | _parent._parent.dentures

Now that we have an AnswerOption that is more capable than the AnswerButton, we need to retrofit our Question display. Returning to the Start frame, we can right-click on each of the buttons, one at a time, to automatically select the correct keyframe and bring up the Instance panel.

The leftmost icon is Swap Symbol. Use it to change each of the AnswerButton references to AnswerOptions.

Click the desired choice, and then set the behavior and name it.

Data-Driven Flash

At last we can act like programmers, not clerks. By addressing each instance of the AnswerOption object by name, we can inject data into it (see Figure 2.10).

Figure 2.10. Four Buttons—Four Variables

answer0.text="William the Conqueror";
answer1.text="William the Bastard";
answer2.text="William the Bald";
answer3.text="William the Duke of Normandy";
stop ();

The text, of course, will be visible only as the movie plays.

It is a little disturbing to write to a variable (text) that not only does not yet exist but is in an other object's namespace (answer0.text). Certainly it violates the principles of real object-oriented programming to directly write to a variable that resides in another object. Normally a method of the class would be especially designated to set the text (so that the fundamental design of the object could change, but no code that uses the object would have to). It is shocking simply to write to one that does not even exist. (The AnswerButton will read the text variable but does not declare, define, or assign it.) The primary reason is to prevent accidental overwrites and other miscommunication between programmers, or between us and us when we come back to the code in three weeks.

But this is valid ActionScript. It is a feature of scripting languages like ActionScript and JavaScript (and, as we will see later, PHP) that variables can be established simply by assignment—they need not be declared.

It is also true that ActionScript variables are visible globally. Some other object-oriented languages allow us to restrict access to our object's variables. Data hiding—the protection of an object's variables by the privacy of its namespace—offers a higher degree of security, something like the protection of an unlisted phone number. Although the access syntax and the usage of MovieClip variables are similar to those of the instance variables of an object, this is not pure object-oriented programming. This form of data encapsulation provides for instantiation and packaging of variables for each MovieClip but not data hiding.


Conclusion

We have learned the principles of event-driven design and object-oriented programming. It is clear that they can be used to make a flexible interface. We have begun the first steps to having a data driven quiz. But there is still a lot of work that needs to be done.


Chapter 3. More ActionScript: Data-Driven Interfaces

This chapter completes our brief survey of advanced ActionScripting. We fulfill the goals we developed in the last chapter, focusing on data-driven solutions—design and logic that respond to internal data. This approach includes the dynamic creation and destruction of graphic elements. We build up skills with internal data so that after we learn XML we will easily be able to create presentations driven by external data.

Throughout this book we concentrate on Flash as thin, flexible clients. A thin client presents data that comes from elsewhere; it focuses on the graphic and interactive function, where Flash shines. A flexible client can take a wide variety of inputs and adapt to what it gets; it does not require careful input. There are wins in system maintenance and upgrades, multiplatform support, version control, and download time. But our primary interest in a thin client is to more clearly expose the data inside—to study XML. Our aim is thin, pliant Flash that wraps itself around a fairly visible XML skeleton.

This chapter is less involved with the rules of ActionScript language than with the practical problems of building smart graphics. It demonstrates a useful approach to the problems and is designed to stimulate readers to invent other approaches.


Data-Driven Decisions

So far we have applied labels to buttons, which is nice. The buttons click nicely, too. But nothing happens. By adding functionality to the buttons, we can extend interest in our little game beyond the first few seconds. There are several strategies by which this can be done.

A bit of code might examine the AnswerOption to see if it is the correct one. If that code were in the base movie it might have a local variable where the clicked option leaves its name:

ActionScript
_parent.clicked = _name;        // code in the AnswerOption

Then it might examine the variable to decide whether it is a win or a loss:

ActionScript
if( clicked eq "answer2" ) {     // code in the base movie

This is an adequate but not optimal design. There is a bit of fragility in recording the correct answer as the name of the interface object to which it is attached. For one thing, a change to the order of the questions requires changing the name of the correct choice, which invites error. A second concern is the scattering of information between the child object and its parent.

Better design would involve smarter AnswerOptions. These objects should each know whether they are correct or not. This design also makes it easy to have multiple correct choices or none and even to have choices that are not exactly wrong or right but offer partial credit.

Whether such a feature would be fun is a game design issue, not a technical issue. But it is always good to create systems that do not preclude this kind of flexibility. The effort of realizing the feature is usually made only after interest in it has been demonstrated.

Let us then assume that each object contains not only the text of the answer but also a score variable. For the moment, we will assume that a positive value means a correct answer. But we will start building this with a simple view of the world: Everybody is always wrong.

Clicking the AnswerButton will ultimately cause the base movie to go to the Lose state we built in Chapter 1. Between the button and the base movie is the AnswerOption object, and this is where we want to build the logic.

First we give the object two states: a waiting state and a thinking state. Each is represented by a keyframe. Unlike our experience earlier, these simple states do not require labeled keyframes (though that might have documentation value).

The first frame is the waiting state. Waiting is easy. Just instruct Flash to stop (Figure 3.1). How do we know the waiting is over? A button is clicked. Open the Object (not Frame) Actions panel for the button, and simply have it play when it is clicked. This will get past the stop in struction on the first frame (waiting) and advance to the second frame (thinking; Figure 3.2). In fact, very little thought is required. Since everyone is always wrong (at this stage), the thinking frame merely directs its parent (the base movie) to advance to its Lose state (Figure 3.3).

Figure 3.1. The Waiting State

Figure 3.2. Waiting Ends

Figure 3.3. The Thinking State

ActionScript
_parent.gotoAndPlay("Lose");

Try it out. It is somewhat discouraging because everyone always loses. But otherwise it works. Making it work better is a simple matter of improving the thinking state. If the object looks into itself and examines its own score variable, it will know whether Win or Lose is appropriate:

ActionScript
if( score>0 ){
    _parent.gotoAndPlay ("Win");
      }
else{
    _parent.gotoAndPlay ("Lose");
    }

Of course, this code will not work unless we have set the score variable—at least for the one option that holds the correct answer. The others, being uninitialized variables, have a value of 0. Normally, we would want to assure that there was no score value already there, as would happen if answer 3 was the correct answer to a previous question. In this case, we know that between questions, these buttons will go out of scope. Whenever we are setting the score variable values, all the variables are fresh and valueless. We can do this at the same time that we are applying the labels, in the first frame of the base movie on the Code layer.

ActionScript
answer0.text="William the Conqueror";
answer1.text="William the Bastard";
answer2.text="William the Bald";
answer2.score=1;
answer3.text="William the Duke of Normandy";
stop ();

Now when the movie plays, it plays correctly.


Data-Driven Everything

There are still some missing details. Most important, the answers are dynamic but the questions are not. We correct this by making a question object q with a text variable. This is established in the code on the first frame of the base movie.

ActionScript
q= new Object();
q.text="Which of these names does<br><b>not</b> belong with the others?"
answer0.text="William the Conqueror";
answer1.text="William the Bastard";
answer2.text="William the Bald";
answer2.score=1;
answer3.text="William the Duke of Normandy";
stop ();

The nature of the object q (its text string variable member) is never declared. It is simply constructed when it is invoked. And this works.

Now the hardcoded question in the Start state is replaced with a Dynamic Text field (Figure 3.4). Note the connection to the q.text variable. Note also that HTML is enabled. This will support the HTML tags that we included in the q.text: a line break and the boldface tags around the word "not."

Figure 3.4. The Dynamic Text Field

But the HTML checkbox has an undesirable side effect (at least as of this writing). It causes Flash to ignore the Paragraph settings. The question is no longer centered when it is displayed but rather left justified. To correct this, we can embed HTML alignment tags like

HTML
<p align='center'>

Similarly, we might smarten up the text displayed in the Win state. Attach it to a variable called comment. The content of this variable could be established in the movie's initial frame by a simple straightforward assignment:

ActionScript
comment= "Bald Bill is fake. The other 3 are all the same guy";

But we want to add another degree of flexibility to our system. We want to associate the comments to the answers rather than the question.

So far, we have played with a system that provides only a conclusion, a comment seen by the player only after the round is over, in this case after the correct answer is (finally) chosen. We can easily enable this scenario simply by attaching the comment to the correct answer. And since our structure allows multiple correct answers, each can now have a unique comment.

Even more useful is the new ability to associate comments with wrong answers. Jokes, taunts, and real clues can all make a game more lively. So we add a line into the AnswerOption symbol in the second frame (thinking). We want to simply use the value of the chosen answer to rewrite the comment that will be displayed:

ActionScript
_parent.comment = comment;

This works fine. It updates the comment display with its own local comment. If it has no comment, it updates the variable to be null, and the display is blank. This is the desired behavior.

We can clean up our data by factoring out the HTML centering tags. This is a solid idea since the alignment is related to this particular display far more than to the inherent meaning of the comment. After all, the ideal toward which we are working is display-agnostic content feeding a content-agnostic display. In other words, one part of the program cares solely about the content, and one part cares solely about the display of the content. The content portion will eventually be given to us by XML; the display portion will stick around and eventually become our Flash thin client.

ActionScript
_parent.comment = " <p align='center'>" + comment + "</p>";
if( score>0 ){    _parent.gotoAndPlay ("Win");   }
else         {    _parent.gotoAndPlay ("Lose");  }

To be able to see the hints and jokes, we need to include the comment display in the Lose state as well as the Win. It is a separate keyframe, rather than an extension of the first (like Score), because it needs to be repositioned (see Figure 3.5). Since it represents loss, we give it a slightly different color and point size.

Figure 3.5. Rearranging Keyframes

The organization of layers and keyframes has been cleaned up and we have sneaked in a few sounds. It is still a bit too complex. There is no reason to have separate layers for the question and answers. Layers have no scripting value. They are meaningful only to the editing process: they help us think about, communicate, and especially manipulate the components of a scene. None of this will be made more difficult by collapsing the five layers into a single q & a layer, and the result will be easier to handle.

Now we update the data assignments in the first frame of the movie.

ActionScript
q.text="Which of these 4 names does<br><b>not</b> belong with the others?"
answer0.text="William the Conqueror";
answer1.text="William the Bastard";
answer2.text="William the Bald";
answer2.score=1;
answer2.comment="<b>William the Bastard</b> was the illegitimate son of
       <br>Robert I, Duke of Normandy and a tanner's daughter. Fatherless
       at seven, by fifteen he was acknowledged <b>William the Duke of
       Normandy</b>. At age thirty-eight, he persued his claim to the
       British throne, and at the Battle of Hastings became <b>William the
       Conqueror</b>.<br><br>History records no <b>William the Bald</b>";
answer3.text="William the Duke of Normandy";
answer3.comment="<i>Hint</i>:<br>In 1066, <b>William, the Duke of
       Normandy</b> became<br>William I, the King of England";
stop ();


Isolating the Data

We are well along toward our goal of separating content and presentation. But all the data is still coded directly into the presentation component.

Let's collect the presentation functionality into its own MovieClip symbol. Flash does not make this easy, but with much cutting and pasting of keyframes we can make a symbol called Round. The base movie now has a single instance (called round) of this symbol.

As a first rough step, we can quickly strip all the data out of round and stuff it into a special Round object in the base movie.

ActionScript
r = new Object();
   r.q  = "<p align='center'>Which of these names...
   r.a0 = new Object();
         r.a0.text="William the Conqueror";
   r.a1= new Object();
etc...

You get the idea. We are defining the data structure as we need it. It is an irregular tree that models exactly the data we have on hand. It packages all this data into a single variable r. Once r is filled we can copy into round.

ActionScript
ActionScript
round.r=r;
stop ();

Now the round must be smart enough to get its data from the single object. In this rough first step, we simply copy out of the object the nine pieces of data that we know it contains. We do this one by one (Figure 3.6). Within round the data is distributed into the proper components.

Figure 3.6. Copying Answers Out of a Round

So far we have broken nothing; it still works. And the data is removed from the round proper. But it is still a clumsy system. We can clean it up by creating a regular data structure. Returning to the initial frame of the base movie, we establish an object Question, which is composed of q (the text of the question) and an array of Answers. The Answer object is the text, the score earned, and a comment.

These structures are defined by their constructors:

ActionScript
function Question( questiontext, answerarray ){
    this.q= questiontext;
    this.a= answerarray;
}
function Answer( text, score, comment ){
    this.text=text;
    this.score=score;
    this.comment=comment;

These constructors are invoked (as in similar languages) when the object is first created.

A shortfall compared to similar languages is the lack of multiple signatures. The Answer constructor requires us to supply the text, score, and comment. Classically, we might create another Answer constructor that is distinguished by requiring only text. We would write this constructor to assume the obvious and create a wrong answer option with no comment. This would save coders and readers the tedium of lines filled with formulaic emptiness. But we do not have such a feature, as can be seen by this initialization (in which long lines of text have been truncated for legibility):

ActionScript
new Question ( "Which of these names does<br>
                not belong with the others?",
        new Array(
            new Answer ("William the Conqueror",  0, ""),
            new Answer ("William the Bald", 1, "<b>William the ..."),
            new Answer ("William the Bastard", 0, ""),
            new Answer ("William the Duke of Normandy", 0, "Hint...")
            )
        );
round.r=r;
stop ();

However, we are not forced to do things in such an ugly way. We can work around Flash's lack of multiple signatures. Any parameters we do not pass to our constructor will be of the undefined type, although it is important to note that the missing parameters will be assumed to be the last ones. For instance, if we typed in something like

ActionScript
new Answer ("William the Bastard", "Who would have the guts to call him
             that?");

the constructor would assume that the text was "William the Bastard" and the score was "Who would have the guts to call him that?" It would assume that comment was of the type undefined.

Now that we know that the parameters may be undefined, we can modify our constructor to take different signatures.

ActionScript
function Answer( text, score, comment ) {
   this.text = text;
   if (typeof(score)=="undefined")
      {
      this.score = 0;
      this.comment = "";
      }
   else
      {
      this.score = score;
      if( typeof(comment)=="undefined")
         this.comment = "";
      else
         this.comment = comment;
      }
   }

This code is longer but more robust. There are several ways we could improve it, they are left as exercises for readers to do as much or little of as they see fit. We could check to see whether score was a string or a number (such as 1) when there is no comment. Then, if it were a string, we could presume that comment was intended to be present and the score omitted, and write our code accordingly. We could use the conditional operator to tighten its appearance.

Note

CONDITIONAL OPERATOR

The conditional operator is an operator much like plus or times. Unlike those two, the conditional operator takes in three values. The first value is a boolean and usually is the result of some equality check or comparison such as variable>1. A question mark is placed after the first value. Then a second value is added. This value will be returned by the conditional operator if the first variable evaluates to true. A colon separates the second from the third value, which is returned if the first value equates to be false. This has the same effect as an if/else statement whose sole purpose is to assign one value or another to a variable.

For example,

ActionScript
 IsXOne = (X==1) ? "Yes" : "No";
 IsXTwo = (X==2) ? "Yes" : "No";
 this.score   = (typeof(score)   == "undefined")?  0 : score;
 this.comment = (typeof(comment) == "undefined")? "" : comment;

Regardless of how we end up writing the code, again we have packaged all our information into a single variable r, but now we have been far more rigorous. Though Flash will actually do little to enforce it, we have a well-defined data structure that is both predictable and flexible.

Note that this definition does not demand that our questions have four answer options. As we go further we will work to avoid and eradicate such assumptions. For example, we need to rewrite the step in round where the data object is deconstructed and the presentation screen is created. Round needs to be made aware of the new question structure. An intelligent for loop avoids explicit assumptions about how many answers exist. But the graphics still assume four answers: Round contains four MovieClip instances (answer0, answer1… answer3). These AnswerOption objects are addressed by constructing each name and using eval to treat the string as an object name.

ActionScript
q = r.q;
for( var i=0; i< r.a.length; i++){
  eval("answer"+i).text   = r.a[i].text;
  eval("answer"+i).score  = r.a[i].score;
  eval("answer"+i).comment= r.a[i].comment;
  }
stop ();


Dynamic Creation of Graphics

As data drives the content of this game, we want it also to start driving the game's graphic format. The most rigid feature, at the moment, is the predefined set of four AnswerOptions. The best way to make it more flexible is to spawn AnswerOption instances as they are needed.

Flash has a mechanism for saving prototypes of MovieClips and then instantiating them from within a running application. (The prototypes can even reside on a remote server and be accessed by URL!)

To make a symbol available for instantiation, right-click on its name in the Library panel. The Linkage panel appears. It seems foolish to change the name at this point, but Flash invites you to anyway (Figure 3.7). Resist.

Figure 3.7. Exporting a Symbol

With this symbol available, we can dynamically generate the display by instantiating as many AnswerOptions as the data requires—not always four. The attachMovie method allows us to spawn the new buttons (Figure 3.8).

Figure 3.8. Data-Driven Graphics

The code executes as each round begins. It supplements Flash's automatic creation of graphic elements with our custom code.

ActionScript
for( var i=0; i< r.a.length; i++){
    this.attachMovie("AnswerOption","answer"+i,++_root.maxdepth+5555);
    setProperty( "answer"+i, _y,  50*i);
    eval("answer"+i).text=   r.a[i].text;
    eval("answer"+i).score=  r.a[i].score;
    eval("answer"+i).comment=r.a[i].comment;
    }

  stop();

For each option in the array of answers, we punch out another copy of the AnswerOption object (button, text treatments, sounds, and a little code).

AttachMovie is a method of any MovieClip. Here we have round call its own method and attach the new instances as its own direct children. We supply three arguments:

  • The name of the prototype symbol. This is the name we published from the Library using the Linkage panel.

  • The names of the instances: answer0, answer1, answer2, and so on

  • The depth. We hold our nose and write in this global.

Note

SETTING THE DEPTH LEVEL

This is a weakness in ActionScript. The scripter is expected to know the layout of the object levels at runtime.

Depth is an internal parameter that determines display list priority, among other things. However, like array indices, depth values must be unique. And worse, unlike array indices they must be unique throughout the Flash session, not just within a limited namespace.

No matter how many Flash MovieClips are running, two objects cannot share the same depth. The second object to be assigned will silently annihilate the first.

Yet the programmer cannot read the depth of an object, as he can the other properties. Nor can the programmer inspect system internals through some sort of read-only access functions, perhaps nextAvailableDepth() or isDepthUsed(). Even a desperate programmer willing to experiment is out of luck: the depth of an object cannot be determined at authoring time. It can vary tremendously based on the context of the object's use and the history of any session.

Common practice (and ours) is to pick a large number arbitrarily and assign depths consecutively from that point. Our counter is a global in the root. Any code that uses this counter anywhere increments it, which prevents our depth assignments from colliding. We also add a large constant to avoid the danger that an uninitialized depth counter could cause the destruction of the root or other important objects, which presumably reside at low depths.

But other assignments, from other people's code and from Flash's own operation, can still collide with our levels.

Every error that can happen eventually will. And sooner than we think. The only thing predictable about the resulting bug is that it will be very hard to identify.

As we create the answer instances, we set the _y property (the relative vertical positioning) on each—as a function of i—so they stack up properly. We also plug the appropriate values into the text, score, and comment fields.

In a more sophisticated version, we would hope to find a more thoughtful consideration of r.a.length—the number of answer options for this question. For example, we might program _y as a more complex function of i that squeezes and stretches the spacing. But now we are happy that we can create answers at will and that they look pretty good with two, three, four, or five choices.

But creation is only half the job. We also need to be able to destroy the answers when we are through with them. We have done this casually so far—almost unconsciously. In the static versions of round, all four answer options and the question text are in the layer q&a. This layer has contents only on frame 1 of the movie. When we enter that frame, Flash creates all the graphic elements. When we move out of the frame to Win or Lose, Flash destroys the objects and cleans up (Figure 3.9).

Figure 3.9. Automatic Creation and Destruction

But now that we have created our own graphic structures, they are not located on the timeline. Who will destroy them? We will, of course. It would help if Flash offered an onExit frame event. It doesn't: All frame code implicitly handles the onEnter frame event. We have to split the Start state into two keyframes. The first is entering the state. It creates and displays all the structures and waits for user action. The second keyframe cleans up memory and the screen and decides what to do next. (If this sounds like the waiting and thinking steps of the AnswerOption earlier, it should. As that functionality is assumed by its parent, AnswerOption gets simpler.)

In fact, it becomes very simple (see Figure 3.10). It records its own name as the chosen answer in its parent, the round.

Figure 3.10. Simplified Answer Option

ActionScript
_parent.chosenanswer=_name;

It then tells the round to play, which takes it to the exit frame of its Start state.

ActionScript
_parent.play();

The code on this frame falls into two sections. The first removes the MovieClips from memory. To be easy on the memory manager, they are removed in LIFO order. (Last in, first out sometimes minimizes memory fragmentation.) RemoveMovieClip is a method of instances that have been created dynamically.

ActionScript
for( var i=r.a.length-1; i>=0; i--){
  eval("answer"+i).removeMovieClip();
  }

If we are on this frame, the player has clicked on one of the options, and the option has stored its instance name in our variable chosenAnswer. (This instance name is something like "answer2".) Skip past the six letters in "answer" and convert the rest to a number. This is the option chosen—it is an index into the array of answers.

ActionScript
chosen=Number( chosenanswer.substring( "answer".length));
Figure 3.11. Destroying Graphics

We use it to display the proper comment and to direct the transition to either the Win or the Lose state.

ActionScript
comment="<p align=center>"+r.a[chosen].comment+"</p>";
if( r.a[chosen].score>0 ){
    gotoAndPlay ("Win");
       }
else{
    r.a.splice( chosen, 1);
    gotoAndPlay ("Lose");
    }

Finally, as a nice detail in the case of a wrong answer, we use splice()—a method available to all array objects—to delete this used-up option from the array. When the first frame plays again and round generates its display, it will list one fewer option. The copy of this array in the base movie is unaffected; we are altering only the data in round's private copy.


Multiple Questions

This game is sweet. But market research indicates that a trivia game with only one question can expect a very short shelf life.

We'll fix this. We will build a database of questions and let the player step through them. Later this will be a powerful multitiered trivia server—but not yet. At this point our trivia database is simply an array in memory, generated by ActionScript code. Later, we will externalize it, but first lets get it to work.

All we need to do is create a loop along the timeline of the base movie (Figure 3.12).

Figure 3.12. Step 1: Initializing Data

Frame 1 has the entire database. It includes the definitions of the Question and Answer constructors

ActionScript
function Question( questiontext, answerarray ){

and

ActionScript
function Answer( text, score, comment ){

but now r is not a single Question object but an array of them.

ActionScript
r=  new Array (
        new Question ( "Which of these names do ...
        new Array(
            new Answer ("William the Conqueror",0...
            new Answer ("William the Bald",1,"Will...
            new Answer ("William the Bastard",0,""),
            new Answer ("William the Duke of Norma...
            )
        ),
        new Question ( "Put these in order:",
        new Array(
            new Answer ("micro nano pico gigo", 0,""),
            new Answer ("micro millo nano pico",0,""),
            new Answer ("micro nano pico fempto",1...
            new Answer ("micro pico nano fempto",0...
            new Answer ("milli micro nano giga",0,...
            )
      ),
      new Question ( "<i>Geek question:</i> <br>((i++++...
      new Array(
          new Answer ("True",  0, " <i>Hint</i>: <br>...
          new Answer ("False", 1, "i++ + ++i =<br>i...
          )
       )
    );
whichquestion=0;

It also initializes whichquestion, a variable that indexes into the array of questions to point to the one currently in use.

It is in the second frame that the data is selected from the array and loaded (in a single assignment) into the round (see Figure 3.13).

Figure 3.13. Step 2: Selecting a Question

ActionScript
  round.r=r[whichquestion];
  stop ();

The game waits here for the player (Figure 3.14).

Figure 3.14. The "Next" Button Moves the Round Along

When the player makes it through the round to its Win state, a "next" button appears. This button causes round's parent (the base movie) to play forward along its timeline (Figure 3.15). This third frame of the main timeline completes the game.

Figure 3.15. Step 3: Repeat if There Are More Questions

ActionScript
if( ++whichquestion  < r.length ){   prevFrame ();}

We advance our question pointer. If we have not yet hit the end of the list, we pop back to the second frame, which runs the round again with the fresh question. If we are at the end of the list (whichquestion==r.length), the movie proceeds forward. (In this case we are on the last frame and the Flash player will begin all over again at the first frame.)

Note that it is only on the second frame that the round (or any other graphics) exists. This means that in each round, when the second frame is entered, either from the first frame (first round) or coming backward from the third (all subsequent rounds), Flash instantiates the round object from scratch. After the round is finished and exits the frame, the instance is destroyed. This is a healthy design, where fresh objects are always in use.

We must be cautious not to put any persistent information in the round object. In particular, the points variable was originally in this object. Now that we have multiple questions, we need the points to be valid for multiple rounds. Though we will keep a local round.points for display, the actual score is tracked in the parent object (the base movie, now).

The code at round's Win frame is now

ActionScript
points=++_parent.points;
stop ();

What will the code be in the Lose frame? It differs by two tiny strokes. Instead of adding to the score, we subtract:

ActionScript
points=--_parent.points;
stop ();


Conclusion

We have constructed a solid framework on which to develop the client side of a database-driven Flash application. A trivia quiz gives us a chance to explore many issues of data organization and communication without becoming distracted by seductive animation scenarios. Graphic animation issues have a much greater learning curve and a more tenuous relevance to the multitiered issues we care about.

In these three chapters, we have learned most of the ActionScript concepts we need to create highly functional demonstrations of the material in the rest of the book. Already we have an application that runs briskly, but it cries out almost audibly for an external source of fresh data. That source will be XML.

So we turn our attention away from Flash and begin to unravel XML.


Chapter 4. XML Fundamentals

If you want to connect Flash to the outside world, you need to learn XML. This may strike you as yet another a tedious chore (it did us), but it is not. This is an opportunity to ride a wave that is transforming the Internet. The XML standard is relatively simple, but the XML perspective is profound. Simply learning the syntax gets you going today with Flash—but if you understand the purpose of the standard, you will be ready for the web of tomorrow.

This chapter presents the roots of XML, the philosophy of XML, and the power that the philosophy can provide—especially in a world where change is the only constant and where the role of automation increases every day. These pages can be skipped by any pragmatic programmer. They contain no code or rules of syntax. More thoughtful readers might want to spend fifteen minutes contemplating why XML—which manages to be both simple and clumsy—merits the attention it attracts.


XML Background

Let's begin with a historical perspective.

SGML

Today's World Wide Web is built, of course, on HTML. This method of formatting pages shares ancestry with XML: They both derive from the Standard Generalized Markup Language (SGML). SGML was established around 1969 to unify the Babel of languages then in place to format documents for publication. These "markup languages" evolved out of handwritten typesetting instructions used in the printing industry. And they initially served the same function: to convey formatting decisions from designer to compositor.

Dr. Charles Goldfarb, originator of SGML, foresaw a world in which computer systems as well as humans process documents. SGML can explain to a computer the structure of a very complex text. At first it was used to prepare documents for the printing press. Later it was used to format documents to be read by people on their computer screens. Then Goldfarb and his colleagues became interested in preparing texts that were never to reach human eyes: messages from computer to computer or even from human to computer. Data.

Any SGML object is both document and data. This dual nature increases its value: one aspect emphasizes publishing, the other emphasizes data exchange. As a publishing tool it produces documents of very sophisticated structure and integrity. To data exchange it brings the flexibility of text documents.

Publishing

The publishing model concentrates on documents presented to humans. The markup languages based on SGML have advantages over their predecessors (e.g., HTML over RTF): They allow publishers to create documents that can be viewed in many different systems. By differentiating a heading from the body of text (for example), the standard permits machines with different characteristics to display the same document. The pages don't look the same on all machines, but the basic structure of the document is clearly visible on a graphic workstation or a crude terminal.

The empowering philosophy is abstraction, an expression of the function of each element of text rather than its appearance. The presentation software (browser) is free to decide precisely how to best set off a <BLOCKQUOTE> segment or whether <STRONG> text is best seen in bold or all caps.

Document with Only Formatting:

RTF
{\rtf1\ansi \deff4\deflang1033
{\fonttbl
{\f4\froman\fcharset0\fprq2 Times New Roman;} }
\pard\plain \widctlpar \f4\fs20 \par \pard \qc\widctlpar
{\fs36 Who Needs Titles?\par }
\pard \widctlpar \par \pard \fi720\widctlpar While the body of a document
can be analyzed-by word counting or by sophisticated lexical heuristics-it
is still difficult to automatically extract the author\rquote s original
intent. It is more difficult still to generate a brief text fragment that
telegraphs this meaning. On the other hand, by composing a title, the
author has done exactly this.
\par \pard \fi720\widctlpar \par }

Similar Document with Structure:

HTML
<HTML>
<HEAD>
<TITLE> Who Needs Titles?</TITLE></HEAD>
<BODY>
<P>Software can attempt to analyze a text, but it is very difficult
to automatically extract the author's original intent. It is more difficult
still to generate a brief text fragment that conveys this meaning. On the
other hand, by composing a title, the author has done exactly this.</P>
</BODY>
</HTML>

SGML is very powerful. You can express almost any document in SGML. Unfortunately, nobody could view your document. SGML is so abstract and so complex that no software can reliably display it.

HTML

Enter HTML. In the early 1990s HTML was created as a simplification of the SGML standard. HTML was a slim SGML intended for use in publishing academic and scientific journals in the real world. Its page markup capabilities were extremely simplistic, and its current multimedia capabilities did not exist. HTML had two great strengths. Its simplicity was one. Because it demanded little of the device it was viewed on or of the software required to make the presentation, HTML browsers appeared quickly on many kinds of machines.

Its other great strength is the hyperlink. The Internet created a single global computer system. The hyperlink created a single global document—the World Wide Web. Hyperlinks and the Internet combined to make HTML an enormous success. Publishing became immediate: simple HTML documents could be displayed meaningfully on almost any device anywhere. In the brief childhood of the web, interoperability and intelligence were more important than graphic design.

The success of HTML has made the web into a mass medium. With its success, HTML has faced pressures that have separated it from its original ideals. There is a new perspective. For better or worse, attractive graphics, not platform independence, not metastructure, drives the web. We want attractive screens. Who cares about the document structure?

Actually the structure of information is more important than ever. The potential data content of the web is increasing enormously—perhaps even faster than the growth in visual sophistication. But while we have done a great job of making the pages prettier, we have not done so well at the hard work of making them smart.

The data content of the web is only potential, because most of its organization is lost in descriptions of presentation. We have HTML descriptions like the one below, which is a fragment of the options list for a new Saturn (from edmunds.com). The table may delight human eyes, but it ignores the real needs of a shopping robot or an affiliate marketer or a car buyer with a Palm. Consider, for example, that the "UP0" option package is simply the "UL0" package plus a CD player. A human can deduce this from the information scattered in the table. But it would take very complex and unreliable software to figure it out. Dr. Goldfarb's vision that a document is a data structure has been lost.

HTML
<TABLE BORDER="0" cellPadding="0" cellSpacing="5" WIDTH="100%">
   <TBODY>
     <TR>
       <TD vAlign="top"><FONT FACE="Arial"><I><B>Option<BR>Code</B></I>
         </FONT></TD>
       <TD vAlign="top"><FONT FACE="Arial"><I><B>Option Name</B></I>
         </FONT></TD>
       <TD ALIGN="right" vAlign="top" WIDTH="250"><FONT FACE="Arial"><I>
         <B>Invoice</B></I></FONT></TD>
       <TD ALIGN="right" vAlign="top" WIDTH="65"><FONT FACE="Arial"><I>
         <B>MSRP</B></I></FONT></TD>
     </TR>
     <TR>
       <TD vAlign="top"><FONT FACE="Arial" SIZE="2"><B>UL0</B></FONT>
       </TD>
       <TD vAlign="top"><FONT FACE="Arial" SIZE="2"><B>Radio: AM/FM Stereo
        Cassette and Automatic Tone Control (SC)</BBR>
        Includes theft protection and 4 coaxial speakers. NOT AVAILABLE with
        UP0.</FONT></TD>
       <TD ALIGN="right" vAlign="top" WIDTH="250"><FONT FACE="Arial"
         SIZE="2">$90</FONT></TD>
       <TD ALIGN="right" vAlign="top" WIDTH="65"><FONT FACE="Arial"
         SIZE="2">$100</FONT></TD>
     </TR>
     <TR>
       <TD vAlign="top"><FONT FACE="Arial" SIZE="2"><B>UP0</B></FONT>
       </TD>
       <TD vAlign="top"><FONT FACE="Arial" SIZE="2"><B>Radio: AM/FM Stereo
         CD and Cassette (SC)</BBR>
        Includes auto tone control, theft protection and 4 coaxial
         speakers. NOT AVAILABLE with UL0.</FONT></TD>
       <TD ALIGN="right" vAlign="top" WIDTH="250"><FONT FACE="Arial"
         SIZE="2">$198</FONT></TD>
       <TD ALIGN="right" vAlign="top" WIDTH="65"><FONT FACE="Arial"
         SIZE="2">$220</FONT></TD>
    </TR>
   </TBODY>
 </TABLE>

The result of this HTML is this chart.

OPTIONAL EQUIPMENT (Descriptions & Prices)
CODE | OPTION NAME | INVOICE | MSRP
C60 | Air Conditioning (SC1/SL) Includes CFC-free refrigerant. | $864 | $960
CF5 | Power Sunroof (SL2/SL1/SC) | $652 | $725
HL1 | SC1 Option Package (SC1) Includes air conditioning, cruise control, power exterior mirrors, power windows with driver express-down, power door locks, remote keyless entry and Saturn security system. | $1647 | $1830
JM4 | Anti-Lock Braking System (All Except SL) Includes traction control. | $446 | $495
UL0 | Radio: AM/FM Stereo Cassette and Automatic Tone Control (SC) Includes theft protection and 4 coaxial speakers. NOT AVAILABLE with UP0. | $90 | $100
UP0 | Radio: AM/FM Stereo CD and Cassette (SC) Includes auto tone control, theft protection and 4 coaxial speakers. NOT AVAILABLE with UL0. | $198 | $220

XML to the Rescue

XML can represent this data in a variety of ways. The most natural formulations make clear the items included in each option package and can easily express a superset relationship like that of the UL0 and UP0 packages.

XML
<OPTION
 code= "UP0"
 msrp="198"
 invoice="220"
 availability="SC">
      Radio: AM/FM Stereo CD and Cassette
      <ITEM>CD player</ITEM>
      <OPTION
             code= "UL0"
             msrp="90"
             invoice="100"
              availability="SC">
              Radio: AM/FM Stereo Cassette and Automatic Tone Control
              <ITEM>theft protection</ITEM>
              <ITEM>4 coaxial speakers</ITEM>
              <ITEM>AM/FM radio</ITEM>
              <ITEM>cassette player</ITEM>
       </OPTION>
</OPTION>

Data Exchange

Conversely, a data structure is also a document. Consider a few:

Library catalog entry

Telephone bill

Class schedule

Each of these is a data object with functional work to do. But people need to read them, as well. They exist in database format, and programmers can (and do) make them visible by writing middleware software to convert the content to HTML. But if these objects were in XML format, they could be read by browsers as easily (and sometimes more easily) as a web page and as attractively—if styling files exist.

This is the other approach to Dr. Goldfarb's ideal. The data is self-describing and open. The distinction between document and datagram disappears.


How XML Works

XML provides a very general method for expressing data structure and content. To maintain portability, it consists solely of a stream of text that avoids any assumptions about the systems exchanging information. It is so general and so adaptable that the first thing it declares is which alphabet it is using and how that alphabet is encoded.

XML itself can structure data, but it says nothing about the meaning of the data. XML merely provides a notation in which the meaning can be unambiguously expressed. XML cares solely about syntax; the semantics are up to us.

However, XML provides a technique by which protocols about data elements can be shared. An optional piece of information within an XML file is a reference to an external data definition. Industry associations, academic conferences, and less formal groups can shape XML vocabularies around their needs and store the shape in such an external file. Schoolteachers and astronomers and chemical salesmen and librarians are all forming agreements on ways to express the information they care about. Your own application might have special data requirements, but by using the referencing system that XML provides, you will be able to clearly expose this data to man and machine.

XML Structure

An XML document is a tree of elements. A single element is at the root and encapsulates the entire document. Within the element are attributes that describe it, its plain text content, and its child elements. Each of these is optional. It could contain nothing at all, just exist as a named presence. Within each of its child elements are exactly the same data options. And so on to the child elements of the child elements.

XML Language

The actual look of XML is familiar to anyone who has used its cousin, HTML. Each element of data is blocked out by tags. A start tag <TAG> introduces the element and an end tag </TAG> marks its end. Between them lies the arbitrary content of the element:

XML
<author>Sir Arthur Conan Doyle</author>

Simplicity is its strength. XML by itself can structure data, but it says nothing about the meaning of the data. For example, the XML line

XML
<title>The Hound of the Baskervilles</title>

looks like this line of HTML:

HTML
<title>The Hound of the Baskervilles</title>

This is because the two lines are identical. (Thanks to common SGML roots.) However, in HTML the words have a specific meaning: a title element has certain properties: it is unique to a page, it synopsizes the page, it is used by browsers and by search engines, and so on. In XML, a title is only another element. XML by itself knows no more about a title than it does about a tittle.

XML Vocabularies

Users create vocabularies in XML. Vocabularies can be formalized and published both for human eyes and for XML processors, or they can be implicit in the file. The explicit, public vocabularies will be encountered in Chapter 6 on DTD. Here, we assume that by some external form of agreement, the meaning of element tags is understood by the Flash application and by the source of the XML.

Obviously, without an external vocabulary, XML can provide no validation of the content of an element. When a vocabulary is formalized in a DTD, we can use that file to validate the integrity of our XML and its adherence to the published rules of the vocabulary. We should note that even with a formal DTD vocabulary, we cannot check type on element contents. All the character data between the start and end tags is only strings of text to the XML parser. It makes no attempt to interpret the text.

None of these are numbers:

XML
<pagecount>233</pagecount>
<copyright>1901</copyright>
<isbn>0-7897-2242-9</isbn>

They are simply lines of text. In fact, every XML element can contain only text—and other elements.

Note

WELL-FORMED VS. VALID XML

XML documents that obey the rules of XML syntax (details in the next chapter) are referred to as well-formed. A well-formed document that references an external DTD (or, coming soon, Schema) and conforms to the data design expressed within it can be called valid.

A parser that reads both the XML file and its DTD (or Schema) and tests the former against the latter is a validating parser. Flash does not have a validating parser. This is not uncommon for a presentation-level system. After all, if the file is not valid by the time it is seen in a Flash-enabled browser, it is too late to fix. Validation is more commonly a step in the creation and maintenance of XML systems than in their display.

Unfortunately, some conveniences—such as the expansion of symbols and the assignment of default values—cannot be performed without an external design, so a nonvalidating parser also omits these functions.


Designing the Data

We stand exactly at the intersection of these two historic forces: a pretty web and a smart web. Lucky us—it is a good place to be. Flash is designed to make attractive graphics. Server software was built to do data processing. We must link them.

As you design the data object, you decide the nature of the project, now and in the future. Your creative decisions will make the difference between a flexible, useful, lively site and a disposable web presence that is quickly outdated and must be recreated.

Consider the following issues as you design your data object.

Many Browsers

Your XML should describe the content in a way that is useful on many platforms. Your ActionScript software will interpret the content to create an animated Flash display. But most publishers want to have alternate access for those who won't or can't install the required plugin. So you or someone else may create a script (perhaps an XSL file) that transforms the XML data into HTML, WML, or some other format. Even if this is not yet planned, consider now what information the transformation will require. Clearly you will want to avoid presentation information that limits the platform, for instance, expressing some values in terms meaningful only in ActionScript.

Some platform-dependent data may be inevitable, despite your best efforts to abstract it. As in the following example, you should supply alternative data for other platforms.

Example

You have been asked to create a jukebox application for a music site. The songs exist as music videos in SWF format. XML is used to create a catalogue of music and artists and it locates each SWF music video. If your XML format includes a URL for an MP3 file as well as the SWF file, you will be creating the backbone for an alternate no-Flash jukebox. The people responsible for this site will have to maintain only a single set of XML files to support both the Flash jukebox and the HTML/MP3 version.

It isn't trivial: As of this writing, for example, some mobile devices can display simple HTML and can play MP3s. But there is no Flash plugin available. You may not care about this audience—they aren't Flash folk. But your client probably does.

Many Users

The objects you manipulate will exist in many states. The display the public sees is one view of your data. Since it is how your organization markets its product, it rightfully is considered extremely important. But by considering the other people who will touch this data, a designer can create a sturdy and useful object that documents its own life cycle.

Example

Your client wants to sell college-logo sportswear. Your job is to build the Flash-based storefront. When designing the XML object that represents each entry in the catalogue, you think in terms of the display you want to present to the customer: a photograph of the sweatshirt, ad copy, perhaps an animated mascot, and so on. Eventually you add elements to enable the shop ping process, SKU numbers, prices, sizes, maybe even stock counts. But when you think about it, you realize that more is demanded of this page. The marketing manager must approve a catalog item before it goes live. The licensing college must sign off on any page in which their mascot or logo is displayed. These initials should be right there in the XML, at least in some stage of its life cycle. Model releases, authoring information, expiration schedules, and marketing effectivity data all might be part of this item, depending on who is looking at it and when. You can design an XML object that describes as fully as possible the way this item is seen throughout your client's organization. The happy result of this would be improved work flow and a faster, more responsive organization. This is not to say that all these elements would be present in any XML presentation. No user would want to see all these things. But the data design should be able to encompass any of them.

By the way, it is quixotic to try to anticipate every use to which your XML object might be put. Don't worry. The X in XML stands for eXtensible. New elements can be added later to your design, both globally or as a special extension.

Industry Standards

Before starting the big job of designing a sturdy data object, consider this: Your client is a member of a community. In most communities, you will not be the first to try to apply XML solutions to the common problems. There may be a committee-driven or de facto standard already in place. By building on such a standard, you will put your client in the market, not attempt to build a private market.

Example

You have been hired by a large real estate broker to provide a slick web browser for their real estate database. Assuming that their data is not in XML form, you will need to create an XML vocabulary for their server to communicate with your Flash browser. You must think through the data requirements and carefully develop a data object that will support all the features you want, now and in the future.

Or you can do some research and discover that this job has already been done. RELML, the Real Estate Listing Markup Language, is gathering industry support. By adopting this as your data format, instead of developing your own, you collect all these advantages:

  • You have saved considerable work in designing and defining the data.

  • You may save more work if you license existing RELML middleware.

  • You have rich sets of test data.

  • Other software—browsers or bots—can easily shop at your client's site.

  • Your client can expose listings from other databases.

  • A great deal of your development work can be reused on other real estate projects.


Conclusion

A subtle intellectual breakthrough combined the flexible power of data structures and the benign legibility of text. The result empowered both the world of publishing and the world of data sharing.

The World Wide Web began with that abstraction and for a while managed to balance being pretty with being smart. But it became a mass medium, intoxicated with good looks. HTML became hostage to the demands of graphic designers and lost its sense of abstraction. The most popular presentation technologies, like Flash, ignored data concerns and focused entirely on, well, flash.

But the pendulum is swinging back. The need for XML was felt, and it appeared. XML picked up the serious job of abstraction and freed her tarty sister HTML to become a language about how screens look.

XML now emerges as a publication format for very pure content.


Chapter 5. XML Structure

In this chapter we closely examine the XML specification and learn how to create a well-formed XML document. The relevance of each topic to ActionScript is considered, often in the light of an evolving implementation.

Readers with moderate experience in XML might find this chapter useful. Each time the XML specification is restated in English, a new perspective is formed. XML workers might find a tiny highlight in this formulation that rounds out their mental image, if only by raising objections.

Even busy XML experts should read the sections entitled Flash Context. These sections point out the differences between the XML specification and the ActionScript implementation at the time of writing and as anticipated in the future.


Element

An XML document is simply a tree composed of a hierarchy of elements. In fact the document (exclusive of its optional prologue and extremely rare epilogue) is a single XML element. Since an element includes its child elements, a thousand-element tree, if properly formed, is also a single element—the one at the root.

Flash Context

An element appears in the Flash dataspace as a node. The root element appears as the only child element of the document. Each element has multiple pointers into the hierarchy: parent, siblings, and children. Each carries a list of the names and values of all its attributes. In sub-sequent chapters we become familiar with the precise arrangement of these data, and we become comfortable tracing and manipulating them.

Syntax

An element is bracketed by a pair of tags. The information between these tags is the content of the element. The content can be nothing (it often is) or it can be a hideously complex and bulky data structure with hundreds of other complicated elements (it often is). Attribute information, if present, must be embedded in the start tag.The form of the element ID:

<start tag>optional content</end tag>

In the case of an empty element (which contains no content, though it has a name and may have attributes), the start tag and end tag are immediately consecutive and can be fused into a special symbol:

<empty element tag/>

Rules

Each element must have

  • a start tag, introducing its Name

  • an end tag (in some cases these two tags are fused)

Additionally, every element can contain any, all, or none of the following:

  • More elements

  • Text

  • Attributes

  • Entity references

  • Processing instructions

  • Comments

It may not have

  • XML declaration

  • document declaration

  • unterminated elements, references, comments, processor instructions

  • duplicate assignment of attribute

Examples of Elements

<Address>125 Main St</Address> | Address element with street number as content
<Address>Fourscore... earth.</Address> | Another address; it is up to the XML author
<Address line="city">N.Y.C.</Address> | Element with content and attribute assignment
<Address>New York <b>City</b></Address> | Element whose content includes another element
<Address line="apartment"/> | Empty element with an attribute
<Address/> | Empty element containing only a name token

Bad examples

<Address line="optional" line="zip"/> | Multiple assignments of the same attribute
<Address>New York <br>City</Address> | Incomplete inner element
<Address>New York <b>City</Address></b> | Incomplete element: improper nesting


Name

A name describes an element. It is not unique: lots of elements can have the same name. Therefore, a name cannot be used to identify an individual element. Instead, it tells us the kind of element, similar to declaring the class of an object or the type of a variable. There are no predefined element types and (with a single exception explained later) there are no reserved element names. It is up to the user to create and maintain meaning.

Flash Context

Lexically, XML names are similar to ActionScript names. XML is slightly more permissive. There is a potential for trouble from two characters, the colon (:) and the period (.). These have special meaning in ActionScript but are permitted in XML names. Yet even in XML they imply a sense of namespace hierarchy. The colon is explicitly discouraged (though not forbidden) in the XML protocol. And use of the period seems only to invite disaster. We avoid the use of either one due to their use as namespace delimiters.

Of course there is no requirement that an application map XML names directly to ActionScript names. Most applications that tried to do so would come across an obstacle larger than a dot or two.

ActionScript names are unique within their scope (you cannot have two variables called "foo" on the same level). XML element names are very frequently identical to the names of their siblings. While ActionScript names serve to identify an individual datum, XML element names do not.

Syntax

The restrictions on names are simple. Names can use any letter in the alphabet. The alphabet does not have to be ASCII, Latin-1, or even 8 bit. XML supports Unicode and allows names in the current alphabet. Our examples, however, will all be within the Latin alphabet.

Case matters, but it is your choice. There is no standard practice for use of case in XML. Often element names are all lower case with dashes standing in for spaces:

first-name

Names can use any digits, but they may not start with a digit:

first-name2

XML defines no element names, but it does reserve all names beginning with the three letters "xml" (case insensitive), so xml-test is not a permitted name.

Rules

CHARACTER | INITIAL | INTERIOR | SAMPLE
letters | yes | yes | A B C a b c Å ß ç
digits |  | yes | 0 1 2 3
underscore | yes | yes | _
colon | yes, but[1] | yes, but[1] | :
dot and dash |  | yes | .—
xml prefix |  | yes | XML xml xML

[1] Colons should be avoided due to the namespace connotation.

Examples of Names

ADDRESS | Street, city, etc.
player | Contains personal data, such as an address
team | Probably contains several player elements
_team | Different kind of team element
team.mascot | Just a simple name. The dot has no meaning.
team_mascot | Alternative name
team-mascot | Traditional XML name formation
Formula1 | Digits can be included
test-xml | Noninitial XML triplet is fine

Bad examples

xmlTEST | Cannot begin with xml
9-iron | Cannot begin with digit
team:player | Legal, but very bad form unless team is a namespace


Start Tag

XML data is a serial stream. The start tag informs the receiving software that all the incoming data will belong to this element until the matching end tag is encountered. Very often, more start tags are encountered before the end tag. Each start tag must be matched with its own end tag before the previous start tag can be matched.

Syntax

A start tag is simply an element name framed by angle brackets:

XML
<TAG>

If the element has attributes assigned to it, they belong within the start tag. An element can have multiple attributes, but they must be unique:

XML
<TAG attribute="value">

Space is forbidden between the opening bracket and the name. It is required before each attribute assignment. It is optional before the end bracket.

Start tags should look familiar to anyone who has worked with HTML.

Rules

Each start tag must have

  • the < character

  • a name

  • the > character

Additionally, every start tag may contain:

  • Attribute assignments

  • Whitespace after the tag's name

Examples of Start Tags

<ADDRESS> Street, city, etc.
<player   >
Contains legal but probably useless whitespace
<team   mascot= "wildcat">
Contains valid attribute assignment
<team   mascot="wildcat" color="purple">
Multiple attribute assignment is permitted

Bad Examples

<  player  >
Illegal whitespace before name
<team   color="purple" color="white">
Duplicate attribute assignment is forbidden.


End Tag

The end tag functions exactly like a right parenthesis or a closing quotation mark or a right curly brace. It contains no data of its own; it simply ends the most recent (innermost) tag with the same name.

XML requires a matching end tag for each start tag. Not only must they have matching names, but they must also nest properly. The most recently encountered start tag must be paired with the next end tag. If they do not match, it is a fatal error.

Syntax

The end tag contains exactly the same name as the start tag it closes. Simple punctuation distinguishes it from the start tag:

XML
</TAG>

It cannot include attribute assignments or any other content.

Rules

Each end tag must have

  • the </ character pair

  • the name

  • the > character

Alternatively, in the special case of an empty element, the end tag may be fused with the start tag. This results in an empty tag containing

  • the < character

  • the name

  • optional attribute assignments

  • the /> character pair

Examples of End Tags

<Team> . . . </Team> | Street, city, etc.
<Team> . . . <Player> . . .
    </Player> . . . </Team>-
Proper nesting
<Play> </Play> | Empty Play element
<Play/> | Exactly equivalent to the preceding, using an empty tag
<Play  speed= "normal"/>
Empty Play element with speed attribute
<A><B> . . . <C/> <C/><B> . . .
<C></C></B></B></A>
Complex nesting: A contains only B, which contains data, two empty Cs, and another B. This inner B also has data and a single empty C. All three Cs are equivalent.

Bad Examples

<Team>…</team> | Not a match (case violation)
<Team/>. . . </Team> | End tag paired with self-ending empty start tag
<Team> . . . <Player> . . .
    </Team>  </Player>
Bad nesting


Attributes

Every element can have an unlimited number of attributes. Attributes are a special form of content. They are meant to represent unique properties that are bound very tightly to an individual element. Unlike the element's text content or subelement structure, the attributes tend to be very constrained.

An element can only have a single value for any attribute. A tag that contains two attributes with the same name produces a fatal error.

The XML document definition mechanisms allow us to define attributes unambiguously. We state which attributes each element may or must have. We establish the type of each attribute and we can limit its valid values. Default values can be specified by the data designer.

Validating XML parsers will insure that a document's attributes fit the constraints we've established. No other content can be validated this rigorously, so attributes have an important role in an XML document in transmitting critical data.

Flash Context

Attributes are organized in ActionScript as an associative array, which is a member of the element node object. The name of the attribute becomes the index into the array and the value becomes the string content of the associated array element. Parsing the value into numeric form (for example) is the responsibility of the programmer, although in practice it is often performed automatically by ActionScript's implicit casting operations.

Syntax

Attributes are presented as names and values joined with an equal sign (=).

XML
attrib = "value"

Attribute names must comply with the name constraints we studied earlier. Spaces are permitted but not required. Most important, the value must always be a quoted string.

Rules

Each attribute must have

  • the name

  • an equals sign

  • an open quote

  • a value

  • a close quote

It may include:

  • space.

Attribute values must not make references outside the document they appear in. (We will see later how these references are made in other parts of the XML document.)

Attribute values cannot contain a < character, except as &lt;.

Examples of Attribute

name= "Anna" | Simple value
name= "Anna Leah" | Value can contain whitespace.
name= "&daughter;" | Value can be an internal reference.
url= "http://bigfun.net/index.xlm" | Value can be a complex string.
Speed= "4.5" | Numeric values represented as strings

Bad Examples

url= http://bigfun.net/index.xlm | Forgot the quotes
tag = "<IMG>" | Forbidden character
name = "&//bigfun.net:daughter;" | Illegal external reference
Speed = 4.5 | Forgot the quotes again


Text (Character Data)

Text—or, more properly, character data—is all the document content other than markup. (Markup is the XML codes: tags, comments, declarations, and so on.) The intent of the XML standard is that the significant content of the document is contained in the character data while the structure of the document is encoded in the markup. This intent is generally followed.

All character data is found within an XML element and forms the content of that element:

XML
<ELEMENT>Some text.</ELEMENT>

Elements are often found within text blocks. In this case, the outer element contains both character data and a child element:

XML
<ELEMENT>Some text.<CHILD/>More text</ELEMENT>

The embedded element breaks the character data into two distinct objects that applications can treat separately. When we study the Document Object Model, we will find these two blocks of text in separate nodes. There would then be three children of this element—two text nodes and one child element.

Of course, the child element might also have its own character data, which is not directly part of the outer element:

XML
<ELEMENT>Some text.<CHILD>Child's private text</CHILD>More text
  </ELEMENT>

Flash Context

Within ActionScript, each block of character data appears as an individual node. In the object model, these text nodes are as significant as element nodes. They are differentiated by NodeType and they must always be leaf nodes. Text that is interrupted by an element (as in the previous line of code) appears in memory as two separate text nodes plus the interrupting element (e.g., <CHILD>). This is especially problematic when the content contains even simple HTML markup. For example, it might include the common <u>underline</u> tag.

Syntax

Character data is any sequence of characters in the document's alphabet. The only disallowed characters are the two that introduce XML markup: the left angle bracket (<), which initiates all XML tags, and the ampersand (&), which initiates an entity. These two characters are inserted into character data with escape sequences.

Rules

Character data is composed of:

  • any character (including whitespace) except the < or &.

It may also include

  • escape sequences

  • other entity references

  • CDATA blocks

Examples of Character Data

<Team>Duluth Wildcats</Team> | "Duluth Wildcats" is the content.
<EQ>2*2&lt;5</EQ> | Content is "2*2 <5".
<weather>El Ni&#0241;o</weather> | Content is "El Niño".

Bad Examples

<longdistance>AT&T</longdistance> | Forbidden character
<caption>The "<IMG>" tag</caption> | Forbidden even within quotes


Entity References

It is frequently convenient and often necessary to perform string substitution during the parsing of an XML file. The XML entity concept allows such substitution. We will encounter other entity types later, but the only references found in an XML file proper are general entity references. These are references that replace short symbols with legitimate XML character strings. They serve many purposes.

The simplest (and perhaps most common) case is the need to insert into a text stream characters that are meant literally as character data but that the parser would consider as markup. The two characters susceptible to such misinterpretation are the < character, which introduces a tag, and the & character, which introduces, in fact, an entity reference. These two characters can appear in an XML document only when they are serving their specific functions. XML defines entities that substitute for these two. In addition, it provides for a substitute for the > character to satisfy an obscure SGML requirement and for both single and double quote marks, for reasons of convenience that should be obvious.

Additionally a similar escape sequence can exist for any character. The character code (e.g., ASCII or Unicode value) can be expressed in decimal or hexadecimal form. This lets us embed characters that are difficult to produce on the keyboard or unreliable to display.

If the DTD (a preprocessor file we will encounter later) defines it, we can use our own notation, like &yen; to represent the ¥ symbol more clearly than &#165; does.

Of course we are not limited to single characters. The entity can be invoke a string of arbitrary length. An entity is a useful way to represent frequently used and lengthy text. It is even more valuable for representing volatile data. For example, an entity called &webmaster; might list the name and contact information for the person responsible for supporting an XML document. Data encoders enjoy the ability to represent this lengthy, frequently repeated data with a short clear symbol. And if the webmaster position has high turnover, everyone will appreciate the entity's ability to manage volatility.

Flash Context

Few of the abilities of the entity reference are actually realized in the version of Flash available at the time of this writing. The ActionScript parser is declared to be nonvalidating. A nonvalidating parser does not check the XML file against the declarations in the reference DTD file.

The complex capabilities of entity processing—the surface of which we have merely scratched—depend on use of DTD. So it is not surprising to find that user-defined entities such as &yen; or &webmaster; do not function as of the time of this writing.

The five predefined escape sequence entities work as expected, and so does the decimal encoding of single characters. The hexadecimal equivalent is not functional at the time of writing but might be fixed soon, as it seems to be the product of oversight, not architecture.

Syntax

The entity reference generally presumes a matching entity declaration in a referenced document: the DTD.

Alternatively there are five symbolic predefined entities and a mechanism for specifying them with decimal or hexadecimal numbers. All these invoke only a single character:

XML
&#ddd;        decimal character code ddd
&#xhh;        hex character code hh
&amp;         &
&lt;          <
&gt;          >
&quot;        "
&apo;         '

Rules

Each entity reference must have

  • an opening ampersand (&)

  • a valid entity reference

  • a closing semicolon (;)

It may have (in the entity reference position)

  • the # followed by a decimal number representing a character code

  • the pair #x followed by a hexadecimal character code

  • one of five standard character entities: lt, gt, apos, amp, quot

  • any token defined in the DTD

It may not have

  • any characters or sequence not valid in an XML name.

Examples of General Entity References

if (x&gt;min &amp;&amp; x&lt; <max)
    print(&quot;it&apos;s ok&quot;);
if( x >min && x <max) print("it's ok");
&#xA9;2000 Jacobson &amp; Jacobson ©2000 Jacobson & Jacobson
&copyrt;2000 Jacobson &amp; Jacobson Same as above if DTD defines copyrt as #xA9

Bad Examples

&copyrt;2000 Jacobson &amp; Jacobson | If no definition of copyrt exists, this resolves to &copyrt;2000 Jacobson & Jacobson
<ELEMENT attribute=&quot;value&quote;> | Entity references cannot be terminators.


Comments

A comment is text, inserted into the document tree, that is not part of the XML content itself. Comments are meaningful only to humans (when they are meaningful at all). They are typically used by the publisher of an XML document to help other developers extract the most meaning from the document.

Comments are most valuable during the software development phase. During normal XML data exchange they are disregarded.

While most editors preserve comments, not all software will. Browsers, such as IE5, usually preserve both the comment's text and its relationship to the hierarchy of the XML object, allowing comments to be carefully placed where the context is significant.

Flash Context

The Flash XML parser discards incoming comments. This is perfectly legitimate—comments are meant to be read not by applications but only by humans. They are not available to the ActionScript application except by using heroic measures (i.e., writing our own mini-parser).

In fact, older releases of Flash (5.0) cannot properly parse comments. When Flash reads in XML with comments, the entire object model is corrupted.

You are strongly urged to avoid comments in the XML that will feed into your Flash application until it has been tested thoroughly.

ActionScript cannot generate comments in the XML object it outputs. It would be possible to insert comments only "manually" by serializing the XML (generating an XML string from the XML object) and then using string operations to insert or concatenate the comment. This extreme effort should be warranted by some extreme requirement.

If it were necessary to preserve comments in and out of our ActionScript, we would be better off inventing a <COMMENT> element. This would be a normal XML element containing normal text data. It would pass through parsers and code generators in place and intact. It would be incumbent on us, of course, to code our applications to treat it appropriately, and indeed it could be treated quite intelligently.

Syntax

The comment is introduced by the string "<!--" and terminated by "-->". Between these can go any text except for two consecutive dashes (this restriction was introduced for compatibilty with legacy of SGML):

<!--This is commentary.-->

Rules

Each comment must have

  • the four-character string <!--

  • any text

  • the character triplet -->

It may have

  • the & and < characters, forbidden in character data.

It may not have

  • a pair of consecutive hyphens (--)

Examples of Comments

<!-- this is a message from me.--> | Normal usage
<phone>555-0308 <!--use dash--></phone> | Comments can be inside an element.
<town>Kolumbis<!--sic-->, Ohio</town> | Comments can be inside a text string. (Note: This will cause Flash to incorrectly break the text node into two nodes.)
<!DOCTYPE MyXML [<!--by Jesse-->]> | Comments can even be inside a document declaration.

Bad Examples

<town <!--or city--> >New York</town> | Comments cannot be inside a tag.
<!-- It's a--brief--message from me.--> | Double dashes are disallowed.
<!-- If grade is B+ or A---> | A triple dash terminator is disallowed.


Processor Instructions

XML anticipates the need to embed code within a data document. The PI is a mechanism to contain such code. Each PI node identifies the target, the application that will interpret and execute the code. It follows the target identification with the code itself. The XML standard establishes few protocols for engaging this process. It does, however, require parsers to maintain the PI nodes and make them available to the application.

Flash Context

Flash does not like processor instructions. The PI data is not preserved. Even if it were, it could not contain real ActionScript code and make it executable by the application. That would require the Flash player to include an ActionScript interpreter. For reasons of size, it does not. Anyone who has used the eval() operator in Flash and elsewhere will recognize that the Flash implementation is extremely limited. This limitation is to avoid burdening the player with a full interpreter.

But it is worse. At presstime, a bug in the Flash parser misinterprets the PI and recovers poorly. All subsequent data is incorrectly positioned in the hierarchy. Since this bug corrupts the entire XML object—sometimes trivially, often fatally—it would be unwise to include PI material in any XML meant to integrate with Flash. If it is unavoidable (i.e., it is someone else's data), you should check. The PI bug may be corrected by the time you read this. If not, you might need to use an XLS preprocessor to filter the XML (or use a server-based proxy) or you might sign up for some heavy sessions inside the Flash debugger, determining the specific behavior you need to code around.

Syntax

PI begins with <? and ends with ?>. Between these is any text. The syntax is defined by the foreign processing language, not by XML. The XML parser will not interpret this text, nor will it expand any embedded entity references.

Rules

Each PI must have

  • the opening character pair <?

  • the target application (or device) to which the PI is directed

  • whitespace

  • the actual processing instruction stream

  • the closing character pair ?>

It may have

  • any characters whatsoever up to the closing ?>.

It may not have

  • an embedded ?> pair

  • entity references that are meant to be expanded

Examples of PI

<?php counter++; ?> | Embedded line of PHP script
<?xml version='1.0'?> | Standard XML declaration is a PI to the XML processor.
<?xm-replace_text { Click here} ?> | Proprietary instruction of the XMeTal editor

Bad Examples

<?mathpro 3.1?>x**2=>n! ?> | Forbidden characters in string
<?actionscript this.nextFrame(); ?> | Not yet, not yet

Note

XML FOR THE HTML EXPERT

XML will feel familiar to the HTML coder. It has the same notions of start and end tags enclosing very loosely defined text data. They both interject well-specified attribute data within the body of the opening tag.

In practice, XML is far stricter than HTML. Coders used to the forgiving nature of web browsers and the lax definition of many HTML tags should prepare for a more stringent environment. Respect the following differences:

Case sensitivity. HTML is not sensitive to case; XML is.

<Price> is not the same as <PRICE>.

<name> will not be terminated by </Name>.

Explicit end tags. HTML tolerates unclosed elements. XML does not.

Stand-alone <P> and <br> will not work.

<P></P> and <br></br> will work.

Stand-alone <P/> and <br/> will work.

Value delimiters. HTML permits unquoted attribute values. XML does not.

<OBJECT width=100> does not work.

<OBJECT width="100"> works.

Proper nesting. HTML permits element overlap. XML is strict.

"I just <B><I>know</B></I> it!" will not process.

"I just <B><I>know</I></B> it!" will.

XHTML

Since XML is more demanding than HTML but similar in syntax, it is possible to write proper HTML that is legitimate XML as well. This more formal HTML is called XHTML. It is HTML 4.0 that follows the disciplines required to be well-formed and a few others required to be valid.


Conclusion

The structure of basic XML is relatively simple and not unfamiliar to those exposed to HTML. However, it is stricter than HTML.

Many XML features are not implemented in Flash. The features that are missing would be useful in a very complex architecture, but their omission does not prevent XML from being powerful and perfectly useful within Flash.


Chapter 6. XML Validation: DTD

We have seen that XML can describe nearly any data. It offers tremendous flexibility as nothing is predefined. The element names we use have no intrinsic meaning in the XML standard. We make them up as we go along to describe our data.

Similarly, there are no rules about how the single document element organizes its component elements or how those elements are themselves composed. They too are established to fit the data being modeled.

This practice is fragile. To be useful, the producer and the consumer of an XML document must agree on the structure of the document and each of its elements. In this chapter we will learn to create formal declarations of XML vocabularies.

Several formats have been proposed to formalize these designs. The original (and simplest) is Document Type Definition (DTD). We will learn the syntax of DTD, and we will use it to express a data design and validate compliance.

There are other important uses for DTD, and exposure to them is necessary for a solid understanding of XML. But none of these advantages will be exploited by Flash applications here or elsewhere. The Flash XML parser does not parse DTDs directly. Reliance on these techniques will create problems. So we learn to use the DTD only to create macro shortcuts and conditionally compile.


Purpose of DTD

The software that writes an XML document is often written by the same developer who writes the software which reads it. The structure of the XML elements seems obvious. The need for a formal specification might not be felt at all.

As software development proceeds, the data usually becomes more complex and the project often involves more developers. Client software and server software become mismatched as they reflect different stages in the evolution of the data design.

This problem is common when a project starts without planning the data communications. Thoughtful data design is a good investment. It requires a serious commitment of time, but it pays off in stable XML formats. This stability frees the developers of the client and server application from a hobbling dependence.

An XML server must provide the elements the client requires in the expected format. Otherwise, dysfunction is inevitable: the client fails to get necessary information or the server sends signals that the client ignores.

XML is famously resilient. Many miscommunications will still work—more or less. But this level of function can easily cause bugs. These bugs will be more subtle and more difficult to identify than a frank data load error.

The solution is to describe the data structure independently of the file. We create a link in the XML file to a reference file. The reference file describes the XML structure unambiguously. Programmers experienced in languages like C++ will be very familiar with this concept. In such languages, prototypes of the objects in the applications are placed in a shared header file. This ensures agreement between all the source files on their structure.

By placing these shared definitions in a common file, several wins are achieved. Maintenance is simplified and features are simple to publish. Collisions are averted. Best of all, the compiler—not sloppy humans—automatically enforces compliance with agreed-upon standards.

The solution is very similar in XML. Authors of XML data structures publish their design assumptions in an external file to which compliant data files refer. It is enforced by the XML parser.


Valid XML and Well-Formed XML

XML that names an external model and is compliant with that model is said to be valid. The term is very specific; it describes the highest of three states that an XML file can attain.

  • A valid XML entity is a well-formed XML entity that references a published data descriptor and complies with the rules it expresses.

  • A well-formed XML entity complies with all XML syntax rules.

  • A malformed XML entity does not have proper XML syntax. (It is not really XML.)

There are several competing formats for expressing XML data structure. The official format is the Document Type Definition (DTD). It is officially accepted but not unchallenged. Weaknesses in DTD expressivity have led to the rise of competing technologies. The most viable of these seems to be Microsoft's Schema. Schema is still a work in progress, growing in both technical maturity and political acceptance. But in spite of their strengths, other proprietary formats are not as broadly accepted as DTD, which will be our focus here.

It should be noted that not every parser is a validating parser. The Flash parser, for example, is not. It cannot distinguish well-formed from valid files. It will not open the DTD file and will not use the tools supplied.

We could ask why we need to stuff our aching heads with the DTD syntax if it will be ignored by Flash. The reason is sound. Every file we read had to be written at some point. As it is being written, particularly when it is written by a human, there is the potential for errors. The use of a DTD (or Schema, or other data definition) will test the XML—not for its compliance with the XML standard but for its adherence to the higher standard asserted by the application. A standardized DTD makes an excellent way to publish (to outside content providers, for example) the format in which you will accept data. Content publishers and their customers not only can express these formats but easily test them. Each can get confidence from a validation procedure that is as simple as opening the XML file in Internet Explorer.


DTD Declarations

Oddly, the DTD uses syntax that has a confusing similarity to XML syntax but is completely different. A DTD declaration has the form

Open delimiter (DTD mimics XML by using < to open the declaration.)

Declaration (Unlike XML, DTD has a finite set of predetermined declarations.)

Name (Name of this object in the XML file.)

Rule (Defines constraints on the content of this object.)

Close delimiter (>)

Example: <!ELEMENT Quiz ((Q,A,A+)*)> This is an !ELEMENT declaration that declares a type of XML element called a Quiz whose content is a series of Qs, each followed by two or more As.

<!ELEMENT>

This is the simplest declaration. It simply declares the existence of an element type and specifies the content it may have:

DTD
<!ELEMENT name (contents)>

name is a legitimate XML name (see Chapter 5).

contents is a rule composed of the following set of symbols.

<!ELEMENT> Content Rule Symbols

#ANY tells the validating processor that nothing is known about this element. For describing an element itself, this is a waste of bytes. However it serves a need when this element (about which nothing is yet known) needs to be introduced to the processor, so it can appear as content in the declaration of a larger element.

\#EMPTY defines the element as a leaf element with no content. (Leaf nodes are those without child nodes.) This does not mean that the element has no meaning. Such an element might carry a great informational cargo in its attributes. Even a bare element with neither content nor attributes can present great meaning. Elemental tokens by their presence and by their context can be very meaningful.

#PCDATA is parsed character data. This is text without markup except entity references. Of the following two lines, only the first is PCDATA:

XML
He&apos;s coming!
He <bold>is</bold> coming!

An element containing only PCDATA is a leaf node and is more specifically referred to as a node with character content.

elementname The appearance of a declared element name in the content rule marks this element as a parent element, that is an element with element content.

<!ELEMENT> Content Rule Operators

It is not unusual for an element to contain multiple elements or to contain both element content and character content (mixed content). Any combination can be expressed with a set of operators that express combination and occurrence.

Combination

, | The comma states that the two elements it joins must both appear and in this order.
| | The bar states that one and only one of the two elements it joins must appear.
() | Parentheses group rules into symbols to clarify the associativity of the operators.

(dot,star) is a dot followed by a star.

(dot|star) is either a dot or a star.

(dot|(dot,star)) is either a dot or a dot and a star.

(dot,(dot|star)) is either dot-dot or dot-star.

Occurrence

 | A symbol without an occurrence modifier must appear once in this position.
? | A symbol followed by a question mark must appear here once or not at all.
* | A symbol followed by the star appears any number of times or not at all.
+ | A symbol followed by the plus sign must appear any number of times.

 | May not repeat | May repeat
May not be omitted |  | +
May be omitted | ? | *

(Q,A)+ One or more Q/A pairs

(Q,A*) Q with an unspecified number of As

(Q,A,A+)* Any number (even zero) of Qs, each followed by two or more As

(Q, ((A,A)|(A,A,A,A,A)) ) Q followed by two or five As.

((A | B | C )*) Any series of any number of As, Bs and/or Cs in any order.

<!ATTLIST>

The DTD format is criticized for its inability to type content. It cannot specify whether content is text, numeric data, or any other type. For a technology called a document type definition, very little typing is defined. The major exception occurs in the attribute list.

The type of each attribute must be specified. A parameter in the declaration defines its type. However, if you expect to find familiar types like boolean or float or even number, you are out of luck. Take a deep breath and enter a complicated world.

<!ATTLIST> Types

CDATA This attribute contains string data. This might be a line of text or a URL or even a number (55) or a boolean (true). It is a very general specification that tells us very little.

ID This attribute contains a unique identifier. Although a number often makes an easy and reliable unique identifier, it is not accepted by the XML rules. The identifier must be a proper XML name and follow the rules for names considered earlier. Uniqueness is independent of context. An element called <player> Jocko is not unique from <game> Jocko. The ID must be unique only within this XML entity. An ID must obey the rules for XML names. It cannot be an optional attribute; its default must be #IMPLIED or #REQUIRED.

IDREF This attribute links to another element somewhere in this file. It does so by referring to the unique ID of that element. Although infrequently used, it permits the creation of data structures more complex than are afforded by XML's basic tree hierarchy. Complex directed graphs, circular references, multiply-linked lists, and relational database models can be represented with these internal references.

IDREFS indicates an attribute that is a sequence of IDREF symbols joined by white space. It gives us the power to make and manipulate simple lists.

ENTITY compels this attribute to be set to the name of a previously declared unparsed external entity. As we have seen, entities are references to files that are not necessarily XML files (e.g., a JPEG image or an MP3 sound). Naturally, references to such entities cannot be fully expanded by the XML parser, so they are maintained as references.

ENTITIES is just a list of entities joined by white space. These plural types are necessary because, unlike its child elements, all the attributes of an element must have unique names.

NMTOKEN restricts this attribute to a single well-formed name.

NMTOKENS allows a series of names separated by spaces.

Enumerated lists consist of a series of names separated by the | (or) symbol. This list defines the set of values from which the value of this attribute must be selected.

NOTATION can precede an enumerated list and restrict it to notations. These are typically used to describe the properties (e.g., media types) of the files referred to by external unparsed entities.

<!ATTLIST> Defaults

A very useful feature of DTD attribute typing is the ability to define the default value of an attribute. Even more useful is the syntax that allows you three special options. Typically the default value is a simple literal like "true" or "5." But it can also be one of the following symbols.

#REQUIRED in place of a default value informs the processor that a valid XML file must supply a proper value for this attribute whenever it appears. There is no default.

#IMPLIED in place of a default value informs a processor that the final application is better able to supply a default value than is the XML processor. In essence, the processor is instructed that there is no default, but unlike the #REQUIRED case, an omission of this attribute is not an error.

#FIXED preceding a default value informs the processor that this attribute must always have this value. If omitted from the XML, it will be supplied. If present, it must agree with the default or an error has occurred that invalidates the XML.


Entities

In addition to the preceding syntax, which specifies the fine structure of the XML document, the DTD makes heavy use of the entities feature. We saw entities in our survey of XML proper, since most (though not all) entity declarations are valid within an XML document itself. However, it is in the DTD that entities are most commonly defined and encountered.

An entity is a richly overloaded term that identifies a coherent block of content. The entity has two formal parts, a name and the block of content that the name represents. This can be almost any self-contained block of content anywhere. It can be huge or tiny.

The XML document is an entity. This document entity is often associated with the idea of a file. While an XML file contains exactly one document, many XML documents never exist as files. In fact, such entities are most interesting to us in this book: only two of our projects involve an XML file. The rest deal with dynamic, ephemeral data that is passed back and forth between live processes. Each of these communications is an XML document entity.

At the other end of the spectrum, an entity can be as atomic as a single byte. XML has five predefined entities, each of which represents a single character. These five characters are troublesome when they appear in character data (text), as they imply markup. The entity feature is used as an escape sequence to insert these characters where they would otherwise disturb the parser. For example, the entity &apos; represents the single-quote (apostrophe) character.

With the exception of these predefined entities and the implied document entity, entities are created by declaration. The declaration is a simple syntax, behind which lurks a bewildering tangle of variations.

DTD
<!ENTITY name value>

Entities fall into five classes.

Character entities are the simplest. They each resolve to a single character. They include the five predefined entities and the numeric entity, in which a reference to any character can be made with a numeric escape sequence. The form is &#number;. For example, Zo&#235; resolves to Zoë.

Internal general entities are only slightly more complex. These are basic text substitutions that are explicitly defined and referenced in the basic XML file itself (not in a DTD). For example:

DTD
<!ENTITY cpyrt copyright 2001 Jacobson and Jacobson>

That text would be inserted into the following line:

XML
Chapter 5. &cpyrt; All Rights Reserved

External general entities separate the value of the entity from the XML document. To resolve an external entity, the processor must read in a new document that is linked to this entity in the declaration. This action could be used to perform text substitution of large, volatile, or shared text content, where the files referenced contain blocks of straight character data, like

DTD
<!ENTITY address   SYSTEM "http://lincoln.com/gettysburgaddress.txt">
<!ENTITY headline  SYSTEM "headline.txt">
<!ENTITY motto     SYSTEM "../missionstatement">

In these examples, the keyword SYSTEM informs the processor that the resource identifier will be found in the same document system as the document it is currently processing. This means, almost always, the Internet. Specifically, the processor seeks the referenced file beginning at the same location as the current file. In the motto example, the missionstatement file will be found in the parent directory of the directory in which the file with that reference was found. For example, while processing an XML file, we might call in the DTD it references. The motto entity declaration might be found in that DTD. If so, the file is sought relative to the current DTD file, not the original XML.

In addition to the SYSTEM identifier, a PUBLIC identifier can also be established. These identifiers are meant to be used to invoke common standards. For example, the W3C Internet protocol committee has a document that specifies standards for HTML. Every well-behaved web page, especially an XML-compliant one, should invoke the standard with a line like this:

HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">

Without the PUBLIC identifier, every browser, when it opened any web page, would be obliged to refer to the DTD document stored on the w3.org server. The load would be insufferable. Instead, an abstract symbol identifies the standard. The naming convention has fields separated by double slashes (and peppered with white space). These identify, respectively,

- ISO-registered (+) or not (-) organization. (The W3C is unregistered?)

W3C (OwnerID) organization itself

DTD (Public Text Class) type of document

HTML 4.0 Transitional (Public Text Description) subject, version, and status

EN (Public Text Language) language of the document

Catalog systems (there are multiple standards for these) retain local copies of the meaning of these symbols.

This discussion implies another consideration. The external entity can hold far more than simple text. It is more common that the entity contains markup, in particular data definitions, entity declarations, and other production rules.

Sound familiar? It should. The DTD is itself such a document. It is an entity invoked by the XML file. It often invokes other entities.

The DTD is written not in XML syntax but in a sister syntax that is interdependent. All validating XML parsers are capable of reading the DTD. But other entities can be even more exotic.

Unparsed entities are external documents that the XML processor is not expected to understand. The documents can be text based or, for example, a gif image or an audio file. All unparsed entities must be external entities, of course. The parser must be able to tell which external entities are meant to be parsed. It does this with the help of a markup called notations.

Notations are an XML feature that allows the document to identify the content type of external files. Notations are separately declared. Most formally they attach a name to a file definition using a PUBLIC or SYSTEM identifier. In practice, this resolves to one of two forms. A notation can be a MIME content–type identifier that is familiar throughout the Internet. Examples are text/html or image/gif or application/xml. Alternatively, a notation can refer to the application required to process the data. The MIME identification is more solid, of course, since application names and locations vary greatly from machine to machine.

Unparsed entities are differentiated from general external entities by the presence of notation, introduced by the keyword NDATA:

DTD
<!ENTITY snapshot SYSTEM "../photos/annaleah.jpg" NDATA image/jpeg>

So far we have seen four types of entities. Each of them can be declared in an XML file or preferably in a separate DTD. All four entities can be referenced (invoked) in the XML document—but none of them can be referenced within a DTD.

Parameter entities are a special case of entities that can be referenced in a DTD. They resemble general internal entities except that they use a special character. As the ampersand (&) is the escape character that begins any entity reference, the percent symbol (%) introduces a parameter entity reference. The percent sign is also used in the declaration of a parameter entity, which is otherwise identical to the general entity declaration:

<!ENTITY % ENGLISH INCLUDE>
<!ENTITY % SPANISH  IGNORE>

This example demonstrates the utility of parameter entities in the DTD when used in conjunction with the keywords INCLUDE and IGNORE. The preceding definition would be followed later in the document by

DTD
<![ %ENGLISH;  [ ..stuff.. ]]
<![ %SPANISH;  [ ..stuff.. ]]

Conditional sections like these can be as long as you like. They identify different versions of the DTD contents and can easily be reversed by changing the parameter entity declarations.


Namespace

Clearly, as DTDs and their elements are being created all over the world, all the time, name collisions are bound to occur. Our document might call in two different DTD protocols, perhaps from two different vendors. For example, we might want to handle two different formats for news sources, the RSS/RDF format from Netscape and the CDF from Microsoft.

Both define, for example, an element called <title> and another called <item>, but these elements have different meanings and very different structures. If our XML is to use both of them, it must be able to easily distinguish between them. It does so by putting a prefix in front of each one, separated from the original name by a colon. Thus we might have <microsoft:title> and <netscape:title>. Or <cdf:title> and <rdf:title>.

It remains to link the initials cdf and rdf to globally unique names, not casual acronyms. The mechanism for selecting globally unique names is the URI (e.g., URL) system of domain ownership. The line

DTD
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"

appears to reference a document on the web. However, it is merely using this unique location to create a unique namespace. It links the abbreviation rdf to this unique identifier during the processing of this DTD. It is considered good form (though not a requirement) to have documentation of some sort at the named URI.

With this definition and a similar one for CDF, we can easily refer to each sort of item element as

DTD
<rdf:item/>

and

DTD
<cdf:item/>

In fact, we can even define the namespace of the null prefix. With the line

DTD
xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"

we assign to the null prefix the namespace that used to be assigned to rdf. The result is that unprefixed elements like <item> or <title> will have the meaning previously held by <rdf:item> and <rdf:tile>.


Conclusion

We have rounded out our view of DTD. We have discovered a powerful metaformat with which we can shape XML documents. But what good is it to Flash programmers? After all, the current Flash parser is not a validating parser—it will not read in external files such as DTD.

Clearly, there is no value in the runtime use of DTD. But DTD has a critical role in the production process. DTD informs co-developers in your organization and elsewhere how to make XML files that are compliant with your application. It will allow you to test them efficiently.

It is also invaluable in the process of data publishing to both the publisher and the subscriber. It will allow you to produce data for many clients—not all of them created by you, not all of them using Flash.

Also, it will allow you to create applications that comply with formats that have been developed outside your organization. This brings forward the goal of data sharing between organizations and a web not of graphic pages but of high-order information.

In a later chapter we will write to a popular DTD and peek into a worldwide web of data.


Appendix A. Microsoft Compatibility

    ASP Code with Flash

    IIS and PHP


ASP Code with Flash

ASP code permits a very simple web-based maintenance of our Quiz server. There is no database in this implementation. Instead a system of flat XML files is maintained.

ASP
<html>
<head>
<title>XML Upload Server</title>
</head>
<body>

Like PHP, an ASP file starts out in HTML mode, and an escape sequence such as <% marks the beginning of the interpretable script

ASP
  <%
    ' receives data (xml from flash)
   ' 1: back-up currently active quiz ( old/quiz.xml )
   ' 2: make newly editted quiz active ( quiz.xml )
   ' 3: archive today's latest version (eg: old/20011125.xml )
   ' 4: displays xml in a browser window
Option Explicit
Dim xmldom
Dim XMLstr

Option Explicit forces all variables to be declared before use. (It would be nice to have this option in ActionScript and in PHP. We have seen how frustrating it can be when every typo can silently generate a phantom variable and an elusive bug.)

ASP
' xmldom = Server.CreateObject("MSXML2.DOMDocument.3.0")
  xmldom = Server.CreateObject("MSXML.DOMDocument")

We first create a powerful XML object in the call to the MSXML dynamic library. This code runs better with Version 3 of MSXML. It also works better when we do not hardcode the version numbers into the object request. In particular this makes it easier to move the code between two very different installations in development and the publishing environments.

ASP
xmldom.load(Request)
XMLstr=xmldom.xml

We only need to ask the XML object to load itself from the data POSTed by the requesting client. Then we can create a string version of the object.

All this is much more sophisticated than PHP's simple event-driven parser. It is similar to the ActionScript implementation of the DOM-based functionality. (PHP ought to be there soon, however. At least two groups are now building new DOM-based XML modules for PHP.)

ASP
If IsEmpty( xmldom) Then
    Response.Write "XML load failure"
 '  Response.Flush
    If IsEmpty( Request.Form("xml")) Then
       Response.Status = 412
       Response.End

Send Precondition Failed error code to the client. It asked you to update the XML file but neglected to send the new data.

ActionScript
Else
      Dim fs
      Dim filename
      Dim backname
      Dim thisfile
      Response.ContentType="text/xml"
      Response.Write Request.Form("xml")

Request is the data object that arrived from the Client. Response is the data that the server is sending back in return. These lines tell the client to get ready for XML data and then echo back the XML we just received.

ActionScript
filename = server.mappath( "quiz.xml" )
backname = server.mappath( "old/quiz..xml")

We need the operating system's names for the files that the web server knows as "quiz.xml" and "old/quiz.xml". (These files do not have to actually exist. In particular the "old/" one might not yet have been created.) Rather than a relative address in a space limited to the Internet domain, the operating system uses a disk identifier and directory path on the server machine to reach the physical file.

ActionScript
Set fs = CreateObject("Scripting.FileSystemObject")

This fs object is not a file handle. It is a file system handle. It is the object that performs all the file-oriented operations we need.

Set thisfile= fs.GetFile( filename )
thisfile.Copy( backname )

We can address a file without opening it and instruct it to make a copy of itself as the backup file. If there is a backup file already, it is overwritten.

Set thisfile= fs.OpenTextFile(filename,2,True)
thisfile.write( Request.Form( "xml") )
thisfile.close

Now we open the file for writing and write into it the string representation of the XML object that was posted.

backname = server.mappath( "old/" & Year(Date()) &
        Month(Date()) & Day(Date()) & ".xml")
Set thisfile= fs.GetFile( filename )
thisfile.Copy( backname )

To create a permanent backup that will not be overwritten by the next update, we make an archive copy of today's new XML using today's date to name it.

Set thisfile = Nothing
Set fs = Nothing
End if

Then we recover the memory.

    Else
       Response.Write "Look I found it!"
       Response.Write XMLstr
End if
 %>
</body>
</html>


IIS and PHP

It is not necessary to learn ASP, even if you are compelled to work with a Microsoft server and operating system.

Internet Information Server will support PHP 4. Success has even been reported with the advanced socket manipulations required for XML sockets, using IIS server and Windows 2K, as long as the -enable-sockets directive has been compiled into PHP. (This is not the default.)


Appendix B. Scalable Vector Graphics (SVG)

Our work with XML uses the language to encode fairly abstract data like quiz questions or player identities. We use Flash to convert these into on-screen displays. Typography, layout and illustration—as well as animation and interaction—are employed to create a display that beautifies the data and hopefully clarifies its meaning.

There is a huge divide between the XML data and the graphics used to display it. The graph ics are transmitted as .swf files in Flash's proprietary encoding. The graphic data exist in a different address space not directly accessible to the functions that manipulate the XML data.

This divide may disappear. A very well-supported effort is underway to create an XML vocabulary for web graphics. The aim of this effort is universal browser support of a nonproprietary, highly sophisticated graphic language that meshes cleanly with the other technologies of the web.

Vector graphics, typography, and scripting are valued by this consortium. The standard that resulted from their efforts is called Scalable Vector Graphics (SVG). Its functionality overlaps the SWF functionality—it has a set of graphic primitives that are similar—but is somewhat more sophisticated.

The graphic primitives include the shapes of swf plus rectangles, circles, and more sophisticated bezier curves. The fill effects are like those of Flash, including outlines, gradients, masking, pattern fills, and transparency (all animatable), and also include plugin functionality similar to Photoshop filters, which can be applied to lines as well as fills.

SVG attaches font characteristics to true text: Rather than being buried in an swf file, pure text is exposed to search engines and indexing robots while retaining all the flexible styling ability that a Flash file would have.

All the tools of an interactive page can be integrated seamlessly into an SVG graphic: JavaScript, DHTML, XHTML, and CSS. The elements of a graphic can be distributed across many files or across many web sites, allowing great efficiencies of maintenance and flexibility of presentation to those who plan their site well.

Surprisingly, despite the fact that these graphics are presented in plain text XML, the early tests show files that are somewhat smaller than the matching SWF files (possibly because they were hand-encoded?). However, automatic zip compression will be introduced to the web at the same time as SVG. The text of SVG compresses easily, and the standard seems far more efficient than swf.

The future SVG-enabled browser (IE 6.0?) will be the equivalent of today's browsers with Flash player plugins. There are some important differences to look forward to. First, the SVG player will not be a proprietary system but will have support from multiple vendors. This is good and bad. Multiple vendors will compete for high-performance, highly compliant implementations, and that tends to result in better products brought rapidly to market.

On the other hand, veteran web developers will recognize the pain in store for them. In the past, we have had to straddle (for example) the slightly different renderings of HTML, Java, and scripting languages of Netscape, AOL, and Microsoft. The dream of a page rendering identically on different platforms will always be a dream. Maybe if we are lucky, it will display correctly on multiple platforms.

But the significance of SVG is greater than second-sourcing a player plugin. It is useful to have the graphics and script exposed in the transparent coding of XML. Transparent source code raises issues of site and transactional security. And it challenges (as most web protocols do) the competitive instinct to treat source code as a trade secret. Yet it opens up a new world of tremendously dynamic web entities that will make today's Flash sites seem stiff and unresponsive. And it invites the creation of a multiplicity of tools and libraries that push the envelope creatively, technically, and in fulfilling the needs of niche communities.

Even more significant than the transparency of the XML code is the integration of scripting, graphics, HTML, and XML into a single Document Object Model, at the core of the browser. An ActionScript programmer now cannot do something as simple as read an XML file containing (for example) sales data and create a simple area chart from it. While the XML data is accessible, the points in a polygon are not.

In an SVG environment, this code would be trivially simple. In fact, since the incoming sales information and the displayable SVG graph are both legitimate XML codings, the graphing function could exist in as simple a form as an XLS transformation file. Today a stock-charting site delivers dumb gif files. In the future it might combine XML-based data, a charting rubric (expressed in XLS and rendered in SVG) within a publisher's presentation coded in some kind of HTML. Each of these files is simple and independent. Each can be provided by a different supplier, allowing a web of flexible relationships and profound personalization.

When (and if) SVG will become ubiquitous is unknown, but momentum seems to be building. Macromedia has expressed support for the standard. IBM, Corel, and Adobe have been even more enthusiastic. Recent advances in Flash, starting with ECMA coding and XML readiness in version 5.0, can be seen as steps in the direction of this emergent standard. Hopefully the paths of Flash and SVG will continue to converge and the skills we are developing in ActionScript code and in XML will serve us well in the future.


Appendix C. Tools and Sources

A much better version of this appendix is online at flashandxml.com, along with code samples, bonus tracks, and bulletin boards. The online version features live links, free demos, and special programs for our readers.

Following are the tools we used during the writing of the book. This appendix is not meant to be an exhaustive view of the market or an analytical comparison of competitors. For example, we have low demands on development tools. Our work is not high-volume production but cautious experimentation. About 90 percent of the code was handwritten in very simple text editors (often web-based editors). The only tool that was truly indispensable (besides the Google search engine) was the Iris packet sniffer.


Network Tool

Iris

Iris is a packet sniffer: It monitors all the traffic going through a network connection. Iris can inspect every bit of traffic in a very lucid context. Without a tool like this, it is difficult to perfect a distributed network application. We are forced to guess what each application sends based on the response of the other applications. Very tough.

Directly examining packet dumps seems like tedious work, but it is precise and always illuminating. If you are building a system around connectivity, you ought to know what is really going on.

This tool is beautifully made and works flawlessly. Despite its considerable expense, it will certainly save time.

Thanks to Dave Rosenbaum who insists: "Don't assume. Test," and to Nigel Head who showed us how.


Servers

CULT XML Socket Server

The first commercial third party socket server. This product seems promising but was not ready for testing as we went to press.


XML Tools

XML Spy

This tool is engineered with enthusiasm and marketed with gusto. Fortunately, that marketing gusto has been toned down, and it no longer stamps its own name into every file you write! Like Real Networks, though, it still exhibits an unattractive desire to make itself the default app on dozens of file types.

Engineering enthusiasm makes for a finely built, highly featured product. But here too there is a sense of overkill. Maybe these guys need a harder job! Instead, they overinvented the user interface.

XML documents are straight tree structures. Trees are displayed with similar mechanisms in Mac and Windows Explorer and almost every app. Think of the directory structure you see in a file operation, with folders that open and contain other folders.

XML Spy visualizes trees as a clutter of nested boxes. This never made sense to us, although it might make sense to other people. We disregarded that very central aspect of the product, which promised a path to visual data design, and instead used XML Spy only as XML source editor, validator, and file manager. As such, it is excellent—well engineered and a pleasure to operate.

EditML

We spent less time with this XML editor. It is more modest than XML Spy, but, in our clumsy hands, it was also a bit less sturdy. It is designed as not only a tool but an introduction to the technology. Its help screens are excellent for teaching XML to the novice.

The product has an organization that is simple and easy to understand, although gratuitously cute icons give it an elementary school feel.

MS XML Notepad

This is a very simple and easy to use tool, but it is insufficient for designing valid XML. But the learning curve is a tiny bump, the price is zero, and the display of tree structure is free of the excessive creativity that makes the other two products annoying to use.

If you do not care about DTDs but you do care about money, this little gift from Bill Gates might be just fine.

Web Sources

www.w3.org/TR/REC-xml The definitive word on XML, literally.

editml.com/Samples.htm A nice set of simple starter sample XML files.

xmlpitstop.com A pleasant starting point with a fun attitude, a generous sysop, and hundreds of annotated links.

userland.com A highly active center for development of RSS, SOAP, and other interactive XML technologies. The focus is on pathways for independent servers to interoperate—such as automated content publishing and aggregation—and on functionality as content!


PHP Tools

PHP Coder

This is a very rich IDE (integrated development environment) for PHP. We used it a little bit, but we got our (beta) copy after we had become comfortable with simpler editors. Our projects were small, single-file experiments. If we were beginning a larger PHP project, this tool would probably be at the heart. In that case, the productivity payback for the considerable installation effort and the light learning curve would probably be pretty quick.

Sources

Zend.com The commercial arm of the PHP's hardworking mentors.

PHPBuilder.com An independent development oriented site with great community.


MySQL Tools

MySQLEditor

This is a mild pain reliever for assembling and interacting with a MySQL database. It makes communication a bit easier and helps visualization of the results. Version 0.3 (available to us) was still fairly rough.

Source

MySQL.com The source for everything including an excellent downloadable documentation.


I l@ve RuBoard Previous Section

Flash

Sources

macromedia.flash (newsgroup) An all-ages show, with some very patient flash masters…and much much noise.

flashkit.com A much more advanced group. Not for newbies. A rich web site with excellent discussions and heaps of resources. Also a conference in Sydney and Los Angeles, that addresses the accomplished Flash user.

figtree.com Top educators in advanced ActionScript (like Brendan Hall). The real thing.

moock.com Colin Moock approaches technology with creativity and generosity.

flashforward (conference) Held in both San Francisco and New York and drenched in information and attitude. Wear black, be pierced, and make sure it can all be expensed.
    I l@ve RuBoard Previous Section