Netscape DevEdge

Skip to: [content] [navigation]

Netscape DevEdge

Skip to: [content] [navigation]

Scripting The Flash Player Plugin

This article is about the interaction between JavaScript in a webpage and multimedia plugins such as Flash. For a more introductory article on plugins and Netscape Gecko browsers, read the plugin overview.

Often, websites use JavaScript to communicate with multimedia plugins such as Macromedia's Flash player. Using JavaScript to communicate with plugins allows developers to take advantage of both DHTML and multimedia to create compelling new user experiences. JavaScript can be used to toggle the plugin's features, allowing the creation of custom controls in DHTML to manipulate a media player. Similarly, the plugin can also make invocations into a web page's JavaScript methods, allowing the web page to be completely aware of events taking place within the multimedia plugin. This allows for tight integration between the classic elements of a web page -- JavaScript and HTML -- and the multimedia world of the plugin -- animations, video, and audio. In Netscape Gecko browsers, recent versions of the Flash Plugin allow this kind of JavaScript-to-plugin communication, as well as the plugin-to-JavaScript communication. This article uses Flash as a case study to show developers the kinds of things they can do using scriptability, and mentions the other plugins you can script in Netscape Gecko browsers. Links to the developer documentation of these other plugins can be found in the section on other plugins.

Contents

Putting a Plugin On a Page -- the HTML

The Embed Element

The embed element has been used to invoke plugins since the early days of Netscape browsers. Typically, the embed element is nested within an object element, such that the outer object tag invokes an ActiveX control for IE, whereas the inner embed tag invokes a Netscape Plugin. Here is an example of this usage:

 
<p>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0"
width=366 height=142 id="myFlash">
  <param name=movie value="javascript_to_flash.swf">
  <param name=quality value=high>
  <param name="swliveconnect" value="true">
    <embed src="javascript_to_flash.swf" quality="high" width="366" height="142"
    type="application/x-shockwave-flash"
    pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"
    name="myFlash" swliveconnect="true">
    </embed> 
</object>
</p>
Links to the rules governing the use of the embed element can be found in the references section. The embed tag is currently the most widely used tag to invoke plugins in Netscape browsers. It is important to note, however, that the embed element is not part of the HTML 4.01 Specification, and is therefore not a W3C standard. Some caveats governing the use of the embed element are:
  • Do not include a name attribute with the object element, especially if it is the same name value as that of the embed element. Netscape Gecko will not allow you to access the named embed element via JavaScript DOM 0 methods if the object element has the same name. It is okay, however, to use the id attribute with the object element, and the id attribute of the object element can be the same value as the name attribute of the embed element. The id attribute is the correct specification-approved attribute for affixing a name to the object element.
  • You'll notice that the embed tag allows configuration parameters passed to the plugin via custom attributes, such as swliveconnect="true". Flash requires this to allow JavaScript to make calls to the element. Different plugin vendors may require different configuration paramaters to be passed via the embed element, and learning these is advisable. The reference section points to additional vendor resources of other plugins.

The Object Element: W3C Standards and Cross-Browser Issues

The object element is part of the HTML 4.01 specification, unlike the embed element. Traditionally, however, the object element and the embed element have always been used in conjunction, with the object element on the outside and the embed element nested inside the object element, as in the previous example. This continues to be the most popular cross-platform way to invoke plugins. Implicit in this nesting is an architecture assumption:

  • That the outer object element will contain a classid attribute with a Unique Identifier (UUID) that will invoke an ActiveX control. Browsers like Netscape 7 will ignore this object element, since they don't support ActiveX. IE will display the ActiveX control associated with the outer object element.
  • The inner embed element will contain a MIME type and will invoke a Netscape plugin. IE will ignore this element.

But with embed being a non-standard element, authors who are keen on writing validating markup will want to use the object element correctly so that all major browser implementations that adhere to the HTML 4.01 specification can display media content. Although traditionally IE expects object elements with classid attributes (and UUIDs), IE also understands the use of the object tag with the type attribute only (and no classid). IE maps MIME types to their respective ActiveX handlers. Because of this, it is possible to use one single object element that will work in implementations that support the object element:

<object id="myFlash" data="javascript_to_flash.swf" type="application/x-shockwave-flash" 
width="366" height="142">
	<param name="movie" value="javascript_to_flash.swf">
    	<param name="quality" value=high>
    	<param name="swliveconnect" value="true">    	
</object>
In the above code, the MIME type for Flash is used as the primary invocation mechanism for the Flash control in IE, and the Flash plugin in Netscape Gecko-based browsers.

The problem with the above code is that it makes no allowance for architecture-specific obtention mechanisms. The markup above will display a Flash animation (javascript_to_flash.swf) perfectly in both browsers, but assumes that the Flash component is installed already. What if the Flash Plugin or Flash ActiveX control is not present on the machine that the browser in question (e.g. IE 6 or Netscape 7) is running? The markup contains no clue as to how to get the missing component, or where to look. Typically, IE is used with both a classid attribute (indicating ActiveX and not Netscape plugin architecture) and a codebase attribute to show where to get the missing ActiveX control. With only one single object element, it is not possible to specify a cross-browser obtention mechanism in Netscape 7 (and Mozilla-based browsers) or IE. In IE browsers, typically the codebase attribute points to a location on the web from which to download a digitally signed CAB file which will then initiate an ActiveX installation procedure. Netscape 7 and other Mozilla-based browsers do not currently support ActiveX. Furthermore, IE 6 dropped support for Netscape-style plugins, making both browsers architecturally incompatible as far as plugins and components go. Both browsers respect the MIME type-based invocation of Flash, but both browsers do not share the same implementation of Flash. Further caveats about the use of the object element follow:

  • The HTML 4.01 Specification for the object element offers a way out of the world of architectural dissonance: it says that you can nest object tags within each other, and that the user-agent must display the outermost object element, and if it cannot, it must work through the nested object elements till it can find something to display, finally culminating with some alternate content nested inside the other object elements. Netscape 7 and Mozilla browsers behave in this way, so it stands to reason that you can nest a Netscape Plugin-specific object element within an IE specific object element (which will invoke an ActiveX control). IE should pick up the ActiveX-specific object element, and ignore the Netscape Plugin-specific object element. Unfortunately, this is not the case. IE displays object elements with the type attribute and object elements with the classid attribute, and treats nested object elements as if they were in series. For instance, in IE 6, the code below will display two Flash animations:

    <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
    codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0"
    width=366 height=142 id="myFlash">
    	<param name="movie" value="javascript_to_flash.swf">
    	<param name="quality" value="high">
    	<param name="swliveconnect" value="true">
    	
    	<object type="application/x-shockwave-flash" width="366" height="142"
    	id="myFlash" data="javascript_to_flash.swf" 
    	codebase="http://www.macromedia.com/">
    		<param name="movie" value="javascript_to_flash.swf">
    		<param name="quality" value="high">
    		<param name="swliveconnect" value="true">
    	<object/>		
    
    <object/>
    
    This behavior is contrary to the specification -- for instance, if you were to specify an outer object element with a Flash animation and an inner nested object element with a WMA (Windows Media Audio file), IE 6 would display both. Netscape 7 and the latest Mozilla browsers would only display the Flash animation. IE's behavior is likely to stifle the adoption of nested object elements.

  • In Flash Player 6 r.47, a bug exists with the interpretation of the <param name="movie" value="someAnimation.swf"> which is a param element -- a child of the object element -- that starts the animation playing. Param elements are typically used to configure the component or plugin, and this particular param with name="movie" is used to start the Flash plugin playing an animation (SWF file). Instead of using the param element, developers will have to use the data attribute of the object element. The data attribute points to a file for the plugin to start playing; in the case of Flash, this can be used to point to a SWF file. The param element can't be used as a means to load a SWF file to the Flash Player till Flash addresses this issue in a subsequent release. Note that the explicit use of data to point to a SWF file creates a violation of the HTML 4.01 specification if the codebase attribute is used to point to where the missing plugin can be obtained from. According to the specification, the codebase attribute is an indicator of the base path used to qualify relative URI values used by the data attribute. But much like IE uses codebase to point to a signed CAB file in case the ActiveX control is not installed on the machine, Netscape 7 and Mozilla browsers use codebase to obtain plugins that are missing. In the above example, you can observe that the codebase points to http://www.macromedia.com/ whereas the data attribute points to a local SWF file. In Netscape 7, if under Edit | Preferences | Navigator | Helper Applications you check Always Use Netscape's Plugin Finder Service to get plug-ins, the browser will download an XPI file and dynamically install Flash no matter what the author specifies in the codebase attribute.

  • With the embed element, webpage authors could specify a pluginurl or pluginspage attribute to obtain missing plugins. If neither attribute was provided, the browser would automatically consult Netscape's Plugin Finder Service for the missing plugin. With the object element, no such automatic mechanism exists if the codebase attribute is not provided. At a minimum, the codebase attribute must be specified in order to initiate a search for missing plugins. The fact that not specifying a codebase attribute doesn't automatically trigger a search is the subject of a bug. Do you want the Netscape Plugin Finder Service to be invoked if the codebase attribute is not specified with the object element? Let us know in the bug or send us feedback.

Owing to the challenges that stem from the inability to nest object elements in a cross-browser manner, the best bet is to create object elements dynamically based on browser. You can, using the JavaScript document.write create object elements dynamically based on the browser that your script is evaluated on. Here is an example:

if (window.ActiveXObject)
{
// This is a browser that understands ActiveX
// Create object elements accordingly
document.write('<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"');
document.write(' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0"');
document.write(' width="366" height="142" id="myFlash">');
document.write(' <param name="movie" value="javascript_to_flash.swf">');
document.write(' <param name=quality value=high>');
document.write(' <param name="swliveconnect" value="true">');
document.write('</object>');

}

else
{
// This is a browser in which the classid/UUID based implementation is not useful
// Create object elements based on MIME type

document.write('<object id="myFlash" data="javascript_to_flash.swf" type="application/x-shockwave-flash"');
document.write(' width="366" height="142"');
document.write('<param name="movie" value="javascript_to_flash.swf">');
document.write('<param name="quality" value="high">');
document.write('<param name="swliveconnect" value="true">');    	
document.write('</object>'); 

}

In order to avoid the tedium of using document.write to generate "quoted" markup on the fly, it is feasible to use DOM methods to create the object elements, but this may require more lines of code than using document.write

Using JavaScript to Talk to Flash

The following simple sample below from Macromedia's technical support pages will work in Mozilla-based browsers such as Netscape 7 provided that the latest version of the Flash plugin is installed -- currently, this is Flash 6 r.47.

In the sample below, there are two form fields. One is an HTML one, and the other is a Flash form field (in SWF format). The Flash form field is represented by a variable, "myVar" (set when the Flash form was created using DreamWeaver MX) and the sample uses browser JavaScript to call a Flash method -- SetVariable -- to toggle the value of myVar so that the HTML form passes values to the Flash form.

Here's the example, and here's a source code listing of the example in plain text. You will see that object elements have been conditionally written out using document.write as in the example above.

The actual invocation to the Flash method SetVariable occurs using DOM methods to access the object element that represents the plugin:

function doPassVar(args){
	var sendText = args;
	// get the object element labeled myFlash and invoke a method on it
	document.getElementById("myFlash").SetVariable("myVar", sendText);
	return false;
}
Note that we invoke Flash methods directly on the object element that spawns the plugin, using the DOM as a way to access the element, and using it as a handle to the plugin.

Allowing Your Page's JavaScript to Be Called By Flash

Just as you can use Flash methods to call the Flash plugin from your web page's JavaScript, Flash can also make calls into the JavaScript of the Flash player's environment. This means that your Flash animation can access JavaScript methods on your web page, provided it knows what these methods are called.

Flash's fscommand feature allows you to communicate between your Flash animation and a JavaScript handler. Flash provides its own ECMA-262 compliant scripting language called ActionScript, which helps animate Flash movies, and fscommand is an ActionScript feature to send arguments to the host application.

In a web browser, fscommand calls the function moviename_Dofscommand, where moviename is the name given to the embed element or the id given to the object element. In JavaScript, fscommand functions which "listen" for invocations from Flash look like this:

function myFlash_DoFSCommand(command, args)
{
  // use DOM 0 ways to access embed element
  // myFlash is the name of the embed element
		
  var myFlashObj = InternetExplorer ? myFlash : document.myFlash;
  
  // Now do something with the args parameter passed from Flash
  alert(args);
 
}

In the sample below, you can see both JavaScript to Flash communication at work, as well as fscommand (Flash to JavaScript) communication at work. Note that this sample has been left as a DOM 0 sample using the embed element, since this is currently the most common invocation mechanism. Converting it to object element usage is a trivial exercise given the caveats of the previous section.

Here is the example and here is a code listing for the example in plain text. The JavaScript to Flash communication occurs using DOM 0 methods of the sort document.embedElementName.methodName and the fscommand feature shows Flash passing a color as an argument to the browser, which then does a document.bgcolor = arg to change the background color of the entire web page.

Other Plugins To Script

RealPlayer

Both RealPlayer 8 and RealOne player are scriptable in Netscape 7 and Mozilla browsers, and RealNetworks have released developer documentation showing you how you can invoke methods on the RealPlayer. As of this time, RealNetworks haven't implemented the callback layer in their plugins for Netscape 7 and Mozilla-based browsers, so the plugin to JavaScript communication does not work. JavaScript to plugin communication, however, works well. Netscape 7 ships with RealPlayer 8.

ViewPoint Player

The ViewPoint plugin ships with Netscape 7 and is a fully scriptable and interactive multimedia plugin. It supports callbacks (plugin to JavaScript communication). ViewPoint's developer documentation presents what you can do with the software in web browsers.

Cult3D Player

Cult3D is a 3D plugin that is fully scriptable in Netscape 7 and Mozilla-based browsers. Documentation is available for Cult3D on the Web, including a PDF document on JavaScript and Cult3D.

Apple QuickTime Player

As of Apple Quicktime 6, the QuickTime plugin has been fully scriptable in Netscape 7 and Mozilla-based browsers, including callbacks (plugin to JavaScript communication). QuickTime's developer documentation shows how to invoke methods on the QuickTime plugin via JavaScript and more.

References

A+R