Chapter Ten. Using Basic ActionScript

Using Flash can be like visiting a restaurant in a foreign country. To request a standard meal, you can point to what you want on the menu. But to get something prepared a special way, you have to talk to the waiter—and to do that, you have to speak the waiter’s language.

The language Flash understands is ActionScript. If you can “speak” in ActionScript, you can get Flash to do almost anything you want.

Like any other language, ActionScript requires serious study and practice: Reading a task-based book like this isn’t enough. This chapter presents just a taste of how ActionScript works and what its capabilities are. To learn underlying principles and more techniques, read a more in-depth ActionScript book such as Flash CS3 Professional Advanced for Windows and Macintosh: Visual QuickPro Guide by Russell Chun.

In the meantime, you can learn a few phrases to use in a pinch—the Flash equivalent of being able to say “Diet Coke, no ice” in a way that the waiter will understand.

Choosing an Appropriate ActionScript Version

The original version of ActionScript—now known as ActionScript 1.0—was designed to be easy for beginners to use. At the time, no one envisioned that Flash would become a professional-level tool for building complex interfaces and Web applications. As more serious programmers began to use Flash, they became frustrated with ActionScript’s limitations. Macromedia responded with ActionScript 2.0, which gave ActionScript many of the capabilities available in object-oriented programming languages such as C++.

ActionScript 3.0, the first version to be released by Adobe, is a complete rewrite of ActionScript. Not only are the structure and syntax significantly different from those in ActionScript 1.0, but ActionScript 3.0’s technical underpinnings have changed so radically that it’s no longer compatible with its predecessors. Flash Player 9 is essentially two players combined: one to execute ActionScript 3.0 and one to execute earlier versions.

The continued existence of that virtual “second player” is good news. For the time being, Flash allows you to use whichever version of ActionScript you’re most comfortable with. For beginners, that’s usually ActionScript 1.0, perhaps with a few techniques from 2.0 thrown in. Because ActionScript 3.0 is aimed at experienced programmers, we won’t be working with it very much in this chapter. (You’ll get a better look at 3.0 in Chapter 11.)

When you create a new document, the first decision Flash requires you to make is whether you want it to use ActionScript 2.0 or 3.0; choosing 2.0 allows you to use 1.0 as well. The choice you make determines which versions of Flash Player you can target in Publish Settings (see #77) and which commands are available to you in the Actions panel (see #85). Once you’ve made that decision for a particular FLA file, it can’t be changed (Figure 84a).

Figure 84a. There’s no such thing as a generic FLA file anymore. When you select File > New, you must choose between ActionScript 2.0 and 3.0.

Image

The scripting techniques you’ll learn in this chapter are labeled with the version of ActionScript to which they apply. If you want to try them out, be sure to do so in a FLA file that’s been set for the appropriate version; they won’t work otherwise.

Using the Actions Panel

The Actions panel is where you write and edit ActionScript code. To open it, choose Window > Actions or press F9 (Windows) or Option-F9 (Mac). If you’ve selected an instance of a movie clip or button symbol on the Stage (in ActionScript 1.0/2.0) or a keyframe in the Timeline (all versions), you can open the Actions panel by clicking the ActionScript icon in the Property inspector (Figure 85a).

Figure 85a. This icon appears in the Property inspector when you’ve selected a keyframe or a symbol instance to which a script can be attached. Click the icon to open the Actions panel.

Image

By default, the Actions panel has three panes, although it can acquire a fourth if you turn on Script Assist (see #86). The top-left pane, called the Actions toolbox, contains a categorized list of the elements used in the version of ActionScript that you selected, including commands, functions, classes, methods, properties, and other elements (Figure 85b). The right pane, called the Script pane, is where you write and edit your scripts. Double-clicking an ActionScript element in the toolbox causes it to appear in the Script pane, accompanied by any necessary punctuation.

Figure 85b. In the Actions panel, categories are indicated by an open or closed book icon; ActionScript elements are indicated by a round ActionScript icon.

Image

Most beginners prefer to look up the ActionScript elements they need in the toolbox and double-click them to let Flash “write” a script in the Script pane, usually with the aid of Script Assist. If you’re not sure what an item means or how it’s used, you can select it and click the Help icon for an explanation.

If you prefer, you can choose ActionScript elements from menus and submenus by clicking the Add icon, but you can’t use Help in that case.


Tip

Another way to add an element to your script is to drag it directly from the toolbox into the Script pane.


Once you have enough experience with ActionScript, you can choose to type your code directly into the Script pane—which is much faster but can lead to mistakes.

If you have more than one script in your FLA file, the bottom-left pane—called the Script navigator—helps you find the one you’re looking for. Double-clicking a script in the Script navigator “pins” the script, keeping it visible in the Actions panel even if you select something else on the Stage or in the Timeline.

Using Script Assist

Most ActionScript commands require additional information in order for Flash to carry them out. For example, if you use the ActionScript 1.0 command getURL (which opens a Web link), Flash has to know which URL you want it to click and in which browser window you want the Web page to open. These extra pieces of information are called parameters.

If you’re not experienced with ActionScript, you probably don’t know what parameters a particular command requires and how they need to be coded. Clicking the Script Assist button (see Figure 85b) opens a new pane in the Actions panel that helps answer these questions.

Script Assist does two things: If you select an ActionScript element in the toolbox, the Script Assist pane displays a brief description of that element (Figure 86a). If you bring that element into the Script pane by double-clicking or dragging it, Script Assist adds a field or menu for each parameter that the command requires. As you fill in each parameter, Script Assist adds it to the script with the proper syntax.

Figure 86a. The Script Assist pane defines the selected ActionScript element and provides a convenient way to specify parameters.

Image

Writing Simple Frame Scripts (ActionScript 1.0)

ActionScript 1.0 supports two basic kinds of scripts: Object scripts, which will be covered in #88, are attached to objects such as buttons and movie clips. Frame scripts, which are covered here, are attached to keyframes in the Timeline.

Every script is associated with an event that acts as a trigger: Something happens—either initiated by the user or by Flash itself—that causes the commands in the script to be executed. In the case of a frame script, that event is the playhead’s arrival at the keyframe to which the script is attached.

For a very simple example, suppose you have a movie that’s 20 frames long. When the playhead leaves frame 20, its default behavior is to snap back to frame 1, causing the movie to loop. In this case, however, you want the movie to play once and stop.

You can accomplish this with a frame script:

1. Insert a keyframe in frame 20.

2. With that keyframe selected, go to the Actions panel and make sure that the script type at the upper-left corner is “Actions - Frame” (Figure 87a). If it’s anything other than that, the keyframe isn’t selected. Go back and reselect it.

Figure 87a. When you create your “stop” script, the Actions panel should look like this.

Image

3. In the Actions toolbox, choose Global Functions > Timeline Control > stop.

4. Double-click “stop” or drag it into the Script pane. It now appears like this:

stop();

For an explanation of the odd punctuation, see the sidebar “Syntax, Part 1.”


Note

When you write a script in the Actions panel, you don’t have to press Enter or click an OK button to make the script “stick.” A script becomes active the moment it’s entered in the Script pane.


5. Preview or test the movie. When the playhead reaches frame 20, it executes the script and the movie stops.

You can tell that a keyframe has a frame script attached to it by the letter a that appears in the Timeline (Figure 87b). Technically, you can attach a script to any keyframe. In practice, however, it’s highly recommended that you add a new layer and put all your frame scripts in that layer. (Most people call the layer “Actions” or “Scripts,” and they put it at the top of the Timeline so it can be seen easily.)

Figure 87b. Frame scripts (indicated by the letter a) should be placed in a layer of their own.

Image

Besides stop, the command used most frequently in simple frame scripts is “go to.” For example, imagine a 20-frame animation in which a match lights a candle and exits in frame 15, leaving the candle flame flickering. You’d want the candle-lighting portion of the animation to play once, but you’d want the candle to go on flickering indefinitely. In that case, you could attach a script to frame 20 that tells the playhead to jump to frame 16. The technique is illustrated in Figure 87c.

Figure 87c. Every time the playhead reaches frame 20, a frame script causes the playhead to go to frame 16.

Image

Writing Simple Button Scripts (ActionScript 1.0)

In #27, you created a button symbol that responded to mouse input but didn’t do anything else. To make an instance of the button functional, you have to attach a script to it. (For easier reading, we’ll refer to an instance of a button symbol simply as a “button.”)

Object scripts, such as those attached to a button, differ from frame scripts in one important respect: The user, not Flash, initiates the events that trigger them. As you remember from #87, the only event that can trigger a frame script is the playhead’s arrival at the frame to which the script is attached. In contrast, a script attached to a button can be triggered by any number of events. For example, when a user’s pointer is over a button on the Stage, the user might press the mouse button; release the mouse button; press the mouse button and roll away from the button symbol, then release the mouse button; and so on (you get the idea).

Unlike a frame script, an object script must not only contain a set of commands, but it must also specify the event that will cause those commands to be executed. An event is preceded by the keyword on, as in on (release).

Imagine that you’ve placed a button on the Stage that you want the viewer to use to pause the movie. You could do it this way:

1. Select the button on the Stage.

2. Go to the Actions panel and make sure that the script type at the upper-left corner is “Actions - Button” (Figure 88a). If it’s anything other than that, the button isn’t selected. Go back and reselect it.

Figure 88a. When you write a button script, the Actions panel looks like this.

Image

3. If the Actions panel doesn’t include the Script Assist pane, click the Script Assist button to make it appear.

4. In the Actions toolbox, choose Global Functions > Movie Clip Control > on.

5. Double-click “on” or drag it into the Script pane.

6. In the Script Assist pane, choose the event that will trigger the script. For button scripts, that event is usually “release.” (The user-interface convention is for a button click to take effect when the user releases the mouse button.)

The Script pane now shows:

Image

See the sidebar “Syntax, Part 2” for an explanation of the placement of the braces.

7. Choose Global Functions > Timeline Control > stop.

8. Double-click “stop” or drag it to line 1 in the Script pane. The script now looks like this:

Image

9. Preview or test the movie. When you click the pause button, the movie stops.

To allow the user to resume the movie, you can create a play button: Follow the same steps, but choose “play” rather than “stop” in step 7.


Note

Unlike frame scripts, object scripts don’t show up in the Timeline. If you create a button script and the letter a appears in a keyframe, you didn’t select the button properly. Go back to step 2.


Organizing the Timeline for Interactivity

When you play an audio CD, you can listen to it all the way through from beginning to end, or you can jump from one track to another. The Flash Timeline can work the same way. The techniques we’ve worked with so far involve playing the Timeline continuously from beginning to end, but it’s also possible to divide it into discrete segments and let the user decide which to play.

For example, imagine a Flash movie that shows a neutral face and two buttons, one labeled Happy and one labeled Sad. If the user clicks the Happy button, you want the corners of the mouth to turn upward; if the user clicks the Sad button, you want them to turn downward (Figure 89a).

Figure 89a. The static frame at the beginning of the movie is shown on the left. In the center, you see the result of clicking the Happy button; on the right, the result of clicking the Sad button.

Image

You can accomplish this task by dividing the Timeline into three segments. The first segment displays the neutral face; since it’s not animated, it only has to be one frame long. The second segment animates the transition from neutral to happy; the third segment animates the transition from neutral to sad (Figure 89b).

Figure 89b. The Timeline has been divided into three segments, each of which begins with a frame label and ends with a “stop” frame script.

Image

To make this arrangement work, you need button scripts and frame scripts. Assuming that the “happy” segment of the Timeline starts at frame 2 and the “sad” segment starts at frame 12, you’d attach the following script to the Happy button:

Image

You’d attach a similar script to the Sad button, but with 12 as the frame number. (To attach a script to a button, see #88; to use the “go to” command, see #87.)

All that’s left is to add some “stop” frame scripts: one in frame 1, to keep the playhead from moving until the user clicks a button; one in frame 11, to stop the playhead from moving into the “sad” segment when it comes to the end of the “happy” segment; and one in the final frame, to prevent the playhead from snapping back to frame 1.

There’s one problem with this arrangement: If you move any of the keyframes to lengthen or shorten the animation, you’ll have to change the frame numbers in the scripts. If you forget to do that, or if you change the numbers incorrectly, the movie won’t work.

The solution to this problem is to add frame labels to the beginning of each segment. To do this, insert a keyframe (if there’s not one there already), select the keyframe, and type a label into the Frame field in the Property inspector (Figure 89c). The label appears in the Timeline, marked by a red flag.

Figure 89c. Entering a frame label in the Property inspector (left) makes the label appear in the Timeline (right).

Image


Note

Since your frame labels are being used in scripts, it’s important that they follow standard ActionScript naming rules: Each label should begin with a lowercase letter and contain only letters and numbers, with no spaces or punctuation.


You can now change the frame numbers in the script parameters to frame labels, as in:

Image

The frame label has to be in quotation marks; also, ActionScript is case-sensitive, so you can’t use “Happy” as the parameter if the frame label is “happy.”

Like frame scripts, frame labels are best placed in a layer of their own at the top of the Timeline. If you need to move a keyframe of animation, you can select the frame label at the same time and move them in tandem.

Controlling Objects from a Frame Script (ActionScript 2.0)

Attaching scripts to objects on the Stage in ActionScript 1.0 is intuitive and convenient, but it presents a problem: If you want to review or edit all the scripts in a movie, you don’t always know where to find them.

Since the introduction of ActionScript 2.0, the recommended practice has been to move all of a movie’s object scripts into a single frame script. (In ActionScript 3.0, attaching scripts to objects is no longer allowed.)

Let’s work with the same example that we used in #89: a movie in which the Happy button causes a face to smile and the Sad button causes it to frown. In this case, however, we want to use a frame script to control the buttons.

Before ActionScript can send a command to an object, it has to know which object it’s talking to. Therefore, each button has to be given a unique instance name. You assign an instance name to an object the same way you assign a label to a keyframe: Select it and type a name in the Instance Name field in the Property inspector (Figure 90a). For this example, give the Happy button the instance name happy_btn and the Sad button the instance name sad_btn.

Figure 90a. Select an object and type its name in the Instance Name field of the Property inspector. Only instances of buttons and movie clips can be given instance names.

Image


Note

An instance name must begin with a lowercase letter and contain only letters and numbers, with no spaces or punctuation. The “_btn” suffix isn’t required, but it’s recommended for button instances, as is the “_mc” suffix for movie-clip instances.


Objects are typically controlled from a frame script in frame 1. In this case, frame 1 already contains a frame script with the stop command. To edit the script, select its keyframe in the Timeline. The script appears in the Script pane of the Actions panel.

Here’s how to add the necessary commands to the frame script:

1. If the Script Assist pane is visible, click the Script Assist button to eliminate it. (Script Assist works well for simple scripts, but not for the more advanced technique we’re using here.)

2. Click the first blank line in the Script pane. If there is no blank line, click at the end of the script and press Enter (Windows) or Return (Mac) to create one.

3. Click the Insert Target Path icon (Figure 90b). A dialog box appears, listing all of the objects with instance names.

Figure 90b. Clicking the Insert Target Path icon opens a dialog box that lists all of the objects with instance names.

Image

4. Select happy_btn and click OK. The Script pane displays this.happy_btn followed by a flashing cursor.

5. Press the Period key. (In ActionScript, a command and its targeted instance are separated by a period, usually referred to as a dot.) A list box appears, containing all the possible ActionScript elements that might follow the instance name.

6. Scroll down the list and double-click “onRelease.” The onRelease event appears after the dot in the Script pane.

7. Complete the script by typing the code shown in bold:

Image

Loosely speaking, a function is a piece of code that accepts an input and delivers an output. In this case, you’ve created a function that accepts a mouse-release event from happy_btn and outputs a “go to” command.

8. Select the Happy button on the Stage. Its attached object script appears in the Script pane of the Actions panel.

9. Select all the text in the script and press Delete to remove it.

10. Test the movie. It should work identically to the movie in #89.

You can now follow the same series of steps for the Sad button, substituting “sad” for “happy” as needed.

Converting Animation to ActionScript (ActionScript 3.0)

One of the trickier parts of using ActionScript is coding an object’s movement on the Stage. A series of motion tweens that takes a few minutes to create in the Timeline could take hours to re-create in ActionScript.

Why would you want to animate objects in ActionScript rather than in the Timeline? Usually, it’s because you want to vary the animation while the movie is playing—for example, by giving the user controls that allow the movement to be sped up, slowed down, or redirected. If the animation is coded as a function in ActionScript, you can change any aspect of the animation by feeding new parameters to the function.

Flash CS3 has the ability to convert Timeline animation to ActionScript code. It works with motion tweens only—not with shape tweens or frame-by-frame animation—and it converts to ActionScript 3.0 only. To use it:

1. Motion-tween an object on the Stage. The animation can be as elaborate as you want: It can contain any number of intermediate keyframes, and it can even use a motion guide (see #40).

2. Choose a movie-clip symbol to which you want to copy the animation and drag an instance to the Stage. (Graphic and button symbols won’t work.)

3. Give the new object an instance name (see #90).

4. In the Timeline, select all the frames of the original object’s motion tween (Figure 91a).

Figure 91a. The animation you copy can have as many keyframes as you want, as long as they are confined to one layer.

Image

5. Choose Edit > Timeline > Copy Motion as ActionScript 3.0. A dialog box appears, asking for the instance name of the object to which you want to apply the animation.

6. Type the instance name from step 3 and click OK.

7. If there’s not already an Actions layer in the Timeline, create one; then select the keyframe in frame 1.

8. Open the Actions panel (if it’s not already open) and click in the Script pane.

9. Choose Edit > Paste. The ActionScript code representing the animation appears in the pane.

10. Test the movie and compare the coded motion of the second object to the Timeline animation of the first object. They should look the same.

Try changing some parameters in the ActionScript code, then test the movie again. The coded animation will look different; the Timeline animation will stay the same.

If you wish, you can remove the original object from the Timeline.

Using External AS Files (ActionScript 2.0 and 3.0)

The scripts we’ve worked with so far have all been embedded in the FLA file. You have the option, however, of keeping your scripts in external files. External files are useful for editing scripts without having to open them in Flash, storing scripts that are too long to fit conveniently into the Actions panel, or sharing one script among several movies.

An external script file is a plain text file. You can create one in any text-editing program, as long as you save it with the filename extension .as. Another option is to use the Script window built into Flash. Like the Actions panel, it contains an Actions toolbox and other tools to help you write and edit your script (Figure 92a). When you save a script in the Script window, the resulting file is automatically given the .as extension.

Figure 92a. The Script window initially appears with the Actions toolbox hidden. To access the toolbox, click the Show/Hide Toolbox icon.

Image

The Script window is often overlooked because it’s not on the Window menu—or, for that matter, any other menu. To get to it, choose File > New to open the New File dialog box, then choose ActionScript File from the list of file types. To edit an existing AS file in the Script window, double-click the file outside of Flash or choose File > Open in Flash.

An AS file won’t be executed unless you associate it with a specific FLA file:

1. Put the AS file and the FLA file in the same folder.

2. Add a frame script or edit the existing frame script in frame 1 of the FLA file’s Timeline. Add the command include "filename.as" (keeping the quotation marks, but replacing filename with the actual name of the file).

3. Test or publish the movie. Flash incorporates the contents of the AS file into the SWF file.

Because the AS file is needed only when you create the SWF file—not when you play it—there’s no need to upload AS files to a Web server. However, if you make any changes to the AS file, they won’t take effect until you generate a new SWF file.


Note

Some types of ActionScript code, such as definitions of classes, must be in external files. To associate those with a FLA file, you use the import command rather than include.


Formatting and Validating a Script

As we noted in #88, Flash ignores tabs, line breaks, and extra spaces when it interprets ActionScript. An entire script could be written on one long line, and Flash wouldn’t know the difference: It pays attention only to punctuation such as parentheses, braces, and semicolons.

Nevertheless, it’s important to format a script neatly and consistently, so that people who edit your script can know at a glance what’s going on. Flash does some formatting on the fly when you type in the Actions panel or Script window, but it doesn’t do really thorough formatting until you click the “Auto format” icon (Figure 93a).

Figure 93a. These icons appear in the Actions panel only if Script Assist is turned off.

Image

In order to format your script, Flash has to understand the script: It has to know which words are commands, which are variables, which are properties, and so on. Assuming your spelling, syntax, and punctuation are correct, Flash has no trouble figuring out what’s what. If you’ve made even a single error, however, Flash loses its bearings. As a result, when you click “Auto format,” you may see an alert telling you that formatting was unsuccessful (Figure 93b).

Figure 93b. This alert appears if errors in your script prevent Flash from formatting it.

Image

Finding a mistake can be difficult when there’s only one incorrect character among thousands. Flash makes the task easier by giving you some guidance: A panel called Compiler Errors pops up and lists the errors that Flash found (Figure 93c).

Figure 93c. The Compiler Errors panel describes the problems Flash found in your script.

Image


Note

Clicking the “Check syntax” icon finds and identifies the same errors that clicking “Auto format” does, but without attempting to format your script.


Testing an Interactive Movie

The “Check syntax” and “Auto format” features find errors in the structure of your script, but they don’t find errors in the content. Suppose you have the following script in frame 1:

Image

When the user clicks the button called myButton_btn, this script is supposed to cause a movie-clip instance called myInstance_mc to become invisible. In the Actions panel, the script checks out with no errors; the vocabulary and syntax are fine.

But when you test the movie, it doesn’t work. No matter how many times you click the button, myInstance_mc remains visible on the Stage. What do you do now?

First you need to figure out where the problems lie. Is the button receiving your mouse clicks? Is the frame script communicating properly with the button? Perhaps there’s something wrong with myInstance_mc?

Next you need to test each of these possibilities. In a situation like this, the trace command is indispensable; its job is to send you status reports from inside a movie.

For example, you might modify your frame script like so:

Image

The trace command communicates through a panel called Output. In this case, when you test the movie and click the button, the Output panel pops open and displays the message “The button has been clicked.” This tells you that the button is receiving your mouse clicks and that the frame script is working.

The trace command can send two types of messages. The first is what’s called a string—a collection of characters that ActionScript doesn’t understand, but you do. A string is surrounded by quotation marks. When the trace command is executed, it simply repeats what’s between the quotation marks—in this case, “The button has been clicked.”

The other type of message trace can send is a value. For example, you might modify your script to look like this:

Image

This version of the script once again tries to make the movie clip instance invisible, but that attempt is followed by a report from the trace command on the value of myInstance_mc._visible—which should, if the script is working correctly, be false.

Let’s say you test the movie and click the button. On the Stage, myInstance_mc remains visible, but the Output panel displays “undefined” instead of “true.” An instance has to be either visible or invisible. How can it be undefined?

This message tells you that the instance called myInstance_mc doesn’t exist. How can this be? After all, you can see it on the Stage. Perhaps its instance name doesn’t actually match what’s in the script. For example, if you accidentally named the instance myIntance_mc, then there is no object called myInstance_mc.

To troubleshoot an interactive movie, you have to be part plumber, part Sherlock Holmes, and part gunslinger with the trace command in your holster.

Using the Debugger

The Debugger is a panel (or, in some cases, a collection of panels) that helps you find errors in ActionScript code. Using the Debugger for the simple scripts we’ve discussed here is like using a sledgehammer to swat flies. For tracking down errors in a beginner’s ActionScript file, the trace command (see #94) is usually all you need.

Most of the Debugger’s features become useful with scripts that contain variables, nested functions, and if/else statements, all of which are beyond the scope of this book. However, it does have a feature that can come in handy for scripts of any size: the ability to set breakpoints.

A breakpoint is a pause that you insert between lines of ActionScript code. When you play a movie in the Debugger, the script stops executing at each breakpoint and continues only when you ask it to. By seeing how your script executes step by step, you can often find out where the problems are. Although ActionScript 2.0 and 3.0 use different versions of the Debugger, the breakpoint feature is the same in both.

You can add breakpoints to a script in the Actions panel by clicking in the margin to the left of any line of code. Clicking once turns a breakpoint on (identified by a red dot); clicking again turns the breakpoint off (Figure 95a). Breakpoints are saved with the FLA file, but they don’t have any effect unless the movie is played in the Debugger.

Figure 95a. A breakpoint is indicated by a red dot in the left margin of a script. You can set breakpoints in the Actions panel or in the Code View pane of the Debugger.

Image

To see your breakpoints in action, select Debug > Debug Movie. Your movie previews in Flash Player as it normally does when you test a movie, and the Debugger opens at the same time. In the Code View pane, you can see your script as it appears in the Actions panel. A yellow arrow moves from line to line as the script executes (Figure 95b). When it gets to a breakpoint, the execution stops.

Figure 95b. This is the ActionScript 2.0 Debugger. The 3.0 Debugger is laid out differently but has many of the same features.

Image

From the breakpoint, you can step through each line of code by clicking the Step In icon, or you can click Continue to resume execution of the script. Other panes of the Debugger are constantly updated with the values of variables and objects’ properties.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.213.196