Embedding Objects with dojox/embed

In this tutorial, you'll learn about the dojox/embed project, and how to use it to include plugin-based objects such as Flash and Quicktime movies—as well as learning about the special proxy method available for Flash objects.

  • Difficulty: Beginner
  • Dojo Version: 1.8

Getting Started

The Dojo Toolkit provides many tools for your application development, including user-interface elements (i.e. Dijit), DOM manipulation and a lot more. But what if your application needs functionality that native HTML-based things can't provide? What if you're looking to show Flash movies (like YouTube or Vimeo) or include Quicktime-based movies in your Dojo-based application?

The solution to this that the Dojo Toolkit provides is dojox/embed, a small codebase designed to allow you to programmatically embed plugin-based objects into your application.

A Short History

The ability to embed plugin-based objects has been around for a very long time—but differences in browser implementations have made it difficult to always get it right. In addition, programmatically inserting plugin-based objects has always been difficult and inconsistent; what one plugin might want, another might not. It can quickly become a nightmare for maintenance, and lead to hours of frustration.

The dojox/embed project was designed to smooth out these cross-browser inconsistencies, and to provide a simple, stable API that could be applied to almost any kind of plugin. It was also designed to "pass through" as much as possible, so that you can always get at any kind of JavaScript API provided by the plugin creators. And in some cases, the dojox/embed API has been extended to handle additional functionality, as we'll see later on when we talk about the special proxy helper method available with dojox/embed/Flash.

Embedding Quicktime Movies

The simplest of the tools available for embedding objects with dojox/embed is the Quicktime embedder, which (like the rest of the tools available in the embed project) is a constructor. The dojox/embed/Quicktime resource currently leans on two require statements; one to dojo/on to listen for window load, and then another to get dojox/embed/Quicktime:

// Get dojo/on for event handling
require(["dojo/on", "dojo/aspect", "dojo/dom/", "dojo/ready"], function(on, aspect, dom, ready) {
	// Make sure document has loaded fully
	// OK, now it's safe to load dojox/embed/Quicktime
	require(["dojox/embed/Quicktime"], function(Quicktime) {
		// Use it!
	});
});

With dojox/embed/Quicktime available, to insert a Quicktime movie in your document, you'd call it directly—passing it a keyword arguments object and an HTML node in which to insert your movie:

require(["dojox/embed/Quicktime"], function(Quicktime) {

	function placeMovie(){
		var node = dom.byId("movieNode");
		var movie = new Quicktime({
			path: "url/to/my/movie.mov",
			width: 400,
			height: 300
		}, node);
		return movie;
	}

	if(Quicktime.initialized){
		movie = placeMovie();
	} else {
		var h = aspect.after(Quicktime, "onInitialize", function(){
			h.remove();
			movie = placeMovie();
		});
	}

});
View Demo

There are a number of things that need to be taken into account when programmatically inserting any plugin-based object into your document, and the example above illustrates them. In particular, timing is important—not only do you have to wait for your document to be ready, but you also have to wait for dojox/embed/Quicktime to be initialized before you can insert a movie into your document. This is because dojox/embed/Quicktime gets other information about the state of the Quicktime plugin in a browser—such as if it is available, what version is available, what minimum version of Quicktime is supported (version 6 at the time of writing), and more.

Because browsers handle Quicktime differently, this base information may not be immediately available when you try to embed your movie—so you should always check to make sure that dojox/embed/Quicktime is initialized before inserting your movie.

This is true for any of the objects available in dojox/embed, as you'll see later on with dojox/embed/Flash.

The return from dojox/embed/Quicktime is a reference to the actual HTML Object that is created and inserted into the document. From there, you can manipulate your movie using the standard Quicktime JavaScript API.

Getting information about the Quicktime plugin

As alluded to above, dojox/embed/Quicktime has a number of properties you can use to get information about the Quicktime plugin in a browser. The properties are as follows:

//	all of the following are attached directly to dojox/embed/Quicktime
minSupported: 6,    // minimum supported version
available: bool,    // if the plugin is available
supported: bool,    // if the plugin is supported
version: {
	major: num,
	minor: num,
	rev:   num
},				    // the full version of the plugin
initialized: bool,  // if dojox/embed/Quicktime is initialized
onInitialize: fn    // an event stub you can connect to
					// to know when dojox/embed/Quicktime
					// gets initialized

Of all of these properties, you'll probably just be using initialized and the onInitialize event stub in your own code; dojox/embed/Quicktime should handle the case where Quicktime is not available by placing a warning message and a link to get the Quicktime plugin. You can customize this by passing a redirect property with your keyword arguments object when embedding a movie; this should be a URL that the user will be redirected to.

Now that we've learned how to embed Quicktime movies, let's take a look at the other most popular plugin: Flash.

Embedding Flash Movies

Like dojox/embed/Quicktime, dojox/embed/Flash was designed to be a basic constructor that you can use to quickly add Flash movies to your document. However, the Flash embedder has a few other useful methods you can use to find out when the movie itself is ready, and when it has finished loading:

	require(["dojox/embed/Flash", "dojo/aspect", "dojo/dom", "dojo/domReady!"],
		function(Flash, aspect, dom) {

			function placeMovie(){
				var node = dom.byId("movieNode"),
					movie = new Flash({
						path: "../resources/love_dojo.swf",
						width: 960,
						height: 540
					}, node);
				return movie;
			}

			function showVersion(){
				var v = Flash.version;
				dom.byId("flashStats").innerHTML = "Flash version: "
					+ "<strong>" + v.major + "." + v.minor + "." + v.rev;
			}

			if(!Flash.available){
				dom.byId("movieNode").innerHTML = "<strong><em>Flash is not installed on your system.</em></strong>";
				showVersion();
			} else {
				if(Flash.initialized){
					movie = placeMovie();
					showVersion();
				} else {
					var h = aspect.after(Flash, "onInitialize", function(){
						h.remove();
						placeMovie();
						showVersion();
					});
				}
			}

	});
View Demo

One thing to note is that dojox/embed/Flash does not try to bypass any kind of Flash blocker extensions.

As you can see, the basic mechanism is the same as dojox/embed/Quicktime; you'll need to wait for the document to be ready, and then you'll need to ensure that dojox/embed/Flash has been initialized (for the same reasons as the Quicktime embedder) before trying to place your movie in a document.

Unlike dojox/embed/Quicktime, the return from dojox/embed/Flash is not a reference to the actual movie, but the wrapper object for that movie. If you need a reference to the actual movie object, you can use the id of the movie (available from the wrapper object itself) and use the wrapper's byId method to get a reference.

Getting information about the Flash plugin

In addition to the basic mechanisms to embed a Flash movie, dojox/embed/Flash also provides a number of properties to get information about the Flash plugin installed in a browser. These properties are exactly the same as the properties listed above, under "Getting information about the Quicktime plugin", and all should be available (like the Quicktime embedder) once the Flash embedder has been initialized.

If just embedding a Flash movie was all that is possible with Flash, we would stop there. However, since version 9, Flash has an ExternalInterface class that you can use in ActionScript; this class enables communication between the browser + JavaScript and the Flash movie itself. dojox/embed/Flash has a wrapper method that you can use to create "faux" methods on your returned dojox/embed/Flash-placed movie, called proxy.

The proxy helper method

dojox/embed/Flash/proxy is a helper/wrapper method that will allow you to pass a list of methods (as an array) and have them set up on your returned Movie object, so that you can call these methods directly—as if those methods were pure JavaScript ones. All of the mechanisms for marshalling and serializing argument objects across the browser/Flash boundaries are taken care of for you; in the end, you can simply use the returned movie as if it were a native JavaScript object.

Setting up your "proxy" is simple: embed your movie using dojox/embed/Flash, and in the onLoad event on your movie, set up the proxy like so:

// Flash is from dojox/embed/Flash
// aspect is from dojo/aspect

var movie = new Flash({
	path: "url/to/your/movie.swf",
	width: 400,
	height: 300
});

var h = aspect.after(movie, "onLoad", function(){
	h.remove();

	Flash.proxy(movie, [
		"getMessage",
		"setMessage"
	]);
});

That's all there is to it. Then, later on or somewhere else in your application, you can call these methods directly from the movie object, like so:

//	somewhere later on in the application
movie.setMessage("This is some message!");

//	...and even later on in the application
var msg = movie.getMessage();
View Demo

Note that the above example assumes that your movie has had getMessage and setMessage set up using the ExternalInterface class in ActionScript. Also, dojox/embed/Flash/proxy makes no assumptions about the number of arguments a method was designed to take; it is the responsibility of the developer to know what's available and what isn't.

As you can see, you can use dojox/embed/Flash/proxy to quickly set up JavaScript-like pass-through methods so that your application can interact with a Flash movie in a simple and intuitive way!

Embed widget-ified: dojox/embed/Object

Finally, the dojox/embed project includes a simple "catch-all" object—fittingly called dojox/embed/Object—that allows you to embed a movie using Dijit-like markup syntax. This constructor will attempt to auto-detect what kind of object you are trying to embed (using the src attribute), and make sure that the right constructor in dojox/embed is called. For example:

<div dojoType="dojox.embed.Object"
	src="path/to/my/movie.mov"
	width="400"
	height="300">
</div>
View Demo

You'll note that this markup uses the "old" method of adding properties using attributes; dojox/embed/Object has not been tested with the newer HTML5-style data attributes at the time of writing, although it is a legitmate Dijit-based widget.

You've probably also noticed that while the Quicktime and Flash embedders use a path property to point at the resource, dojox/embed/Object uses a src attribute. The two map to each other internally, but src was chosen because it is a legitimate HTML attribute.


That's it to using dojox/embed in a declarative manner. At the time of writing, only Quicktime movies (or audio) and Flash movies are supported (since they are the only two embedders present)—but the dojox/embed project was deliberately designed to allow for other plug-in types to be added, so in the future look for others.

Conclusion

In this tutorial, we've learned about the facilities available in dojox/embed to help you place your own non-native HTML objects, such as Flash and Quicktime movies, into a document in both a programmatic and declarative way. We've also learned how to use dojox/embed/Flash/proxy to set up more intuitive functionality for JavaScript developers working with Flash movies that have used the ExternalInterface in their ActionScript. We hope that these facilities provide a simple way for you to include things other than HTML in your Dojo-based applications!

Error in the tutorial? Can’t find what you are looking for? Let us know!