Section 23.4. Scripting Flash


23.4. Scripting Flash

Having explained how JavaScript can script Java and vice versa, let's now turn to the Flash Player and the scripting of Flash movies. The subsections that follow explain several different levels of Flash scripting. First, you can use JavaScript to control the Flash Player itself: starting and stopping the movies, jumping to specified frames, and so forth. A more interesting kind of scripting actually invokes ActionScript functions defined within a Flash movie. This section shows the tricks required (prior to Flash 8) to accomplish this.

Next, the roles are reversed, and you'll see how ActionScript code can communicate with JavaScript. Then Section 23.4.5. provides an example in two parts (the JavaScript code and the ActionScript code) that demonstrates bidirectional communication between JavaScript and ActionScript. Section 23.5. shows the same basic example again, rewritten and simplified using the facilities of Flash 8.

There is more to Flash than ActionScript, and most Flash content developers use a commercial Flash development environment from Adobe. All Flash examples in this chapter contain only ActionScript code that can be converted to SWF files (i.e., Flash movies) using a tool such as the open source ActionScript compiler mtasc (see http://www.mtasc.org). The sample movies don't include embedded media, but they can be compiled for use without an expensive development environment.

This chapter does not attempt to teach the ActionScript programming language or the API of the libraries available to the Flash Player. Many resources online can help you learn ActionScript and the Flash API. One you may find particularly useful is the ActionScript Dictionary.[*]

[*] At the time of this writing, the Dictionary is located at http://www.macromedia.com/support/flash/action_scripts/actionscript_dictionary/. Since Macromedia was acquired by Adobe, however, this URL may change by the time you read this book.

23.4.1. Embedding and Accessing Flash Movies

Before a Flash movie can be scripted, it must first be embedded in an HTML page so that your JavaScript code can refer to it. This is tricky only because of browser incompatibilities: IE requires an <object> tag with certain attributes, and other browsers want an <object> tag with different attributes or an <embed> tag. <object> is the standard HTML tag, but the Flash-to-JavaScript scripting technique described here seems to expect the use of <embed>.

The solution in this case relies on IE-specific HTML conditional comments to hide the <object> tag from all browsers except IE and to hide the <embed> tag from IE. Here's how to embed the Flash movie mymovie.swf and give it the name "movie":

 <!--[if IE]> <object  type="application/x-shockwave-flash"         width="300" height="300">   <param name="movie" value="mymovie.swf"> </object> <![endif]--><!--[if !IE]> <--> <embed name="movie" type="application/x-shockwave-flash"        src="/books/2/427/1/html/2/mymovie.swf" width="300" height="300"> </embed> <!--> <![endif]--> 

The <object> tag has an id attribute, and the <embed> tag has a name attribute. This is a common practice and means that you can refer to the embedding element with the following cross-browser snippet of code:

 // Get the Flash movie from Window in IE and Document in others var flash = window.movie || document.movie; // Get Flash object 

The <embed> tag must have a name attribute if Flash-to-JavaScript scripting is to work correctly. You can also give it an id, if you wish, and if you do this, you can portably use getElementById() to locate the <object> or the <embed> tag.

23.4.2. Controlling the Flash Player

Once you have embedded the Flash movie in your HTML page and used JavaScript to obtain a reference to the HTML element that embeds the movie, you can script the Flash Player simply by calling methods of that element. Here are some of the things you might do with these methods:

 var flash = window.movie || document.movie;  // Get the movie object if (flash.IsPlaying( )) {                     // If it is playing,     flash.StopPlay( );                        // stop it     flash.Rewind( );                          // and rewind it } if (flash.PercentLoaded( ) == 100)            // If it is fully loaded,     flash.Play( );                            // start it. flash.Zoom(50);                              // Zoom in 50% flash.Pan(25, 25, 1);                        // Pan 25% right and down flash.Pan(100, 0, 0);                        // Pan 100 pixels right 

These Flash Player methods are documented in Part IV under FlashPlayer, and some are demonstrated in Example 23-5.

23.4.3. Scripting Flash Movies

More interesting than controlling the Flash Player is invoking ActionScript methods defined in the movie itself. With Java applets, this is easy to do: simply call the desired methods as if they were methods of the HTML <applet> tag. It is also this easy in Flash 8. But if you want to target users who may not yet have upgraded to that version of the player, you'll have to jump through some more hoops.

One of the basic methods for controlling the Flash Player is called SetVariable(). Another is GetVariable(). You can use these to set and retrieve the values of ActionScript variables. There is no InvokeFunction() method, but you can take advantage of an ActionScript extension to JavaScript to use SetVariable() to trigger a function invocation. In ActionScript, every object has a watch() method that can set a debugger-style watch point: whenever the value of a specified property of the object changes, a specified function is invoked. Consider the following ActionScript code:

 /* ActionScript */ // Define some variables to hold function arguments and the return value // _root refers to the root timeline of the movie. SetVariable( ) and // GetVariable( ) can set and get properties of this object. _root.arg1 = 0; _root.arg2 = 0; _root.result = 0; // This variable is defined to trigger a function invocation _root.multiply = 0; // Now use Object.watch( ) to invoke a function when the value of // the "multiply" property changes.  Note that we handle type conversion // of the arguments explicitly _root.watch("multiply", function( ) {                 _root.result = Number(_root.arg1) * Number(_root.arg2);                 // This return value becomes the new value of the property.                 return 0;             }); 

For the sake of example, let's assume that the Flash Player plug-in is much better at multiplication than the JavaScript interpreter. Here's how to invoke this ActionScript multiplication code from JavaScript:

 /* JavaScript */ // Ask the Flash movie to multiply two numbers for us function multiply(x, y) {     var flash = window.movie || document.movie; // Get the Flash object     flash.SetVariable("arg1", x);               // Set first argument     flash.SetVariable("arg2", y);               // Set second argument     flash.SetVariable("multiply", 1);           // Trigger multiplication code     var result = flash.GetVariable("result");   // Retrieve the result     return Number(result);                      // Convert and return it. } 

23.4.4. Calling JavaScript from Flash

ActionScript can communicate with JavaScript using a function named fscommand(), to which it passes two strings:

 fscommand("eval", "alert('hi from flash')"); 

The arguments to fscommand() are called command and args, but they don't have to represent a command and a set of arguments: they can be any two strings.

When ActionScript code calls fscommand(), the two strings are passed to a specific JavaScript function, which can take any action it desires in response to the command. Note that the JavaScript return value is not passed back to ActionScript. The name of the JavaScript function that fscommand() invokes depends on the id or the name used with the <object> or <embed> tag when the movie was embedded. If your movie is named "movie", you must define a JavaScript function named movie_DoFSCommand. Here is an example that can handle the fscommand() invocation:

 function movie_DoFSCommand(command, args) {         if (command == "eval") eval(args); } 

This is straightforward enough, but it does not work in Internet Explorer. For some reason, when Flash is embedded in the IE browser, it cannot communicate directly with JavaScript; however, it can communicate with Microsoft's proprietary scripting language, VBScript. And VBScript can communicate with JavaScript. So to make fscommand() work with IE, you must also include the following snippet of code (which also assumes that the movie is named "movie") in your HTML file:

 <script language="VBScript"> sub movie_FSCommand(byval command, byval args)   call movie_DoFSCommand(command, args) ' Just call the JavaScript version end sub </script> 

You aren't expected to understand this code; just put it your HTML file. Browsers that don't understand VBScript will simply ignore this <script> tag and its contents.

23.4.5. Example: Flash to JavaScript, and Back to Flash

Now let's put all these pieces together into a two-part example that consists of a file of ActionScript code (Example 23-4) and a file of HTML and JavaScript code (Example 23-5). When the Flash movie loads, it uses fscommand() to notify JavaScript, which enables a form button in response. When you click this form button, JavaScript uses the SetVariable() technique to get the Flash movie to draw a rectangle. In addition, when the user clicks the mouse within the Flash movie, it uses an fscommand() to report the mouse position to JavaScript. Both examples are well commented and should be easy to understand.

Example 23-4. ActionScript code that works with JavaScript

 /**  * Box.as: ActionScript code to demonstrate JavaScript <-> Flash communication  *  * This file is written in ActionScript 2.0, a language that is based on  * JavaScript, but extended for stronger object-oriented programming.  * All we're doing here is defining a single static function named main( )  * in a class named Box.  *  * You can compile this code with the open source ActionScript compiler mtasc  * using a command like this:  *  *   mtasc -header 300:300:1 -main -swf Box1.swf Box1.as  *  * mtasc produces a SWF file that invokes the main( ) method from the first  * frame of the movie. If you use the Flash IDE, you must insert your own  * call to Box.main( ) in the first frame.  */ class Box {     static function main( ) {         // This is an ActionScript function we want to use from JavaScript.         // It draws a box and returns the area of the box.         var drawBox = function(x,y,w,h) {             _root.beginFill(0xaaaaaa, 100);             _root.lineStyle(5, 0x000000, 100);             _root.moveTo(x,y);             _root.lineTo(x+w, y);             _root.lineTo(x+w, y+h);             _root.lineTo(x, y+h);             _root.lineTo(x,y);             _root.endFill( );             return w*h;         }         // Here's how we can allow the function to be invoked from JavaScript         // prior to Flash 8. First, we define properties in our root timeline         // to hold the function arguments and return value.         _root.arg1 = 0;         _root.arg2 = 0;         _root.arg3 = 0;         _root.arg4 = 0;         _root.result = 0;         // Then we define another property with the same name as the function.         _root.drawBox = 0;         // Now we use the Object.watch( ) method to "watch" this property.         // Whenever it is set, the function we specify will be called.         // This means that JavaScript code can use SetVariable to trigger         // a function invocation.         _root.watch("drawBox",    // The name of the property to watch                     function( ) {  // The function to invoke when it changes                         // Call the drawBox( ) function, converting the                         // arguments from strings to numbers and storing                         // the return value.                         _root.result = drawBox(Number(_root.arg1),                                                Number(_root.arg2),                                                Number(_root.arg3),                                                Number(_root.arg4));                         // Return 0 so that the value of the property we                         // are watching does not change.                         return 0;                     });         // This is an ActionScript event handler.         // It calls the global fscommand( ) function to pass the         // coordinates of a mouse click to JavaScript.         _root.onMouseDown = function( ) {             fscommand("mousedown", _root._xmouse + "," + _root._ymouse);         }         // Here we use fscommand( ) again to tell JavaScript that the         // Flash movie has loaded and is ready to go.         fscommand("loaded", "");     } } 

Example 23-5. Scripting a Flash movie

 <!--   This is a Flash movie, embedded in our web page.   Following standard practice, we use <object id=""> for IE and   <embed name=""> for other browsers.   Note the IE-specific conditional comments. --> <!--[if IE]> <object  type="application/x-shockwave-flash"         width="300" height="300">   <param name="movie" value="Box1.swf"> </object> <![endif]--><!--[if !IE]> <--> <embed name="movie" type="application/x-shockwave-flash"        src="/books/2/427/1/html/2/Box1.swf" width="300" height="300"> </embed> <!--> <![endif]--> <!--   This HTML form has buttons that script the movie or the player.   Note that the Draw button starts off disabled. The Flash movie   sends a command to JavaScript when it is loaded, and JavaScript   then enables the button. --> <form name="f" onsubmit="return false;">xs <button name="button" onclick="draw( )" disabled>Draw</button> <button onclick="zoom( )">Zoom</button> <button onclick="pan( )">Pan</button> </form> <script> // This function demonstrates how to call Flash the hard way. function draw( ) {     // First we get the Flash object. Since we used "movie" as the id     // and name of the <object> and <embed> tags, the object is     // in a property named "movie". In IE, it is a window property,     // and in other browsers, it is a document property.     var flash = window.movie || document.movie; // Get Flash object.     // Make sure the movie is fully loaded before we try to script it.     // This is for demonstration only: it is redundant since we disable     // the button that invokes this method until Flash tells us it is loaded     if (flash.PercentLoaded( ) != 100) return;     // Next we "pass" the function arguments by setting them, one at a time.     flash.SetVariable("arg1", 10);     flash.SetVariable("arg2", 10);     flash.SetVariable("arg3", 50);     flash.SetVariable("arg4", 50);     // Now we trigger the function by setting one more property.     flash.SetVariable("drawBox", 1);     // Finally, we ask for the function's return value.     return flash.GetVariable("result"); } function zoom( ) {     var flash = window.movie || document.movie; // Get Flash object.     flash.Zoom(50); } function pan( ) {     var flash = window.movie || document.movie; // Get Flash object.     flash.Pan(-50, -50, 1); } // This is the function that is called when Flash calls fscommand( ). // The two arguments are strings supplied by Flash. // This function must have this exact name, or it will not be invoked. // The function name begins with "movie" because that is the id/name of // the <object> and <embed> tags used earlier. function movie_DoFSCommand(command, args) {     if (command=="loaded") {         // When Flash tells us it is loaded, we can enable the form button.         document.f.button.disabled = false;     }     else if (command == "mousedown") {         // Flash tells us when the user clicks the mouse.         // Flash can only send us strings. We've got to parse them         // as necessary to get the data that Flash is sending us.         var coords = args.split(",");         alert("Mousedown: (" + coords[0] + ", " + coords[1] + ")");     }     // These are some other useful commands.     else if (command == "debug") alert("Flash debug: " + args);     else if (command == "eval") eval(args); } </script> <script language="VBScript"> ' This script is not written in JavaScript, but Microsoft's ' Visual Basic Scripting Edition.  This script is required for Internet ' Explorer to receive fscommand( ) notifications from Flash. It will be ' ignored by all other browsers since they do not support VBScript. ' The name of this VBScript subroutine must be exactly as shown. sub movie_FSCommand(byval command, byval args)   call movie_DoFSCommand(command, args) ' Just call the JavaScript version end sub </script> 




JavaScript. The Definitive Guide
JavaScript: The Definitive Guide
ISBN: 0596101996
EAN: 2147483647
Year: 2004
Pages: 767

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net