23.4. Scripting FlashHaving 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.[*]
23.4.1. Embedding and Accessing Flash MoviesBefore 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 PlayerOnce 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 MoviesMore 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 FlashActionScript 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 FlashNow 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
Example 23-5. Scripting a Flash movie
|