The browser plug-ins for QuickTime 7.2.1 and later include the ability to emit Document Object Model (DOM) events. DOM events can be emitted when the plug-in is instantiated and ready to interact with JavaScript, at various points during a movie’s loading process, when playback has begun, paused, or ended, or in the event of an error. JavaScript functions can be set to "listen" for particular DOM events. Whenever the DOM event occurs, the listener function is called.
This allows you to create web pages that detect events such as movie loading, playing, pausing, or ending, without having to create JavaScript timing loops or constantly poll the plug-in for status. It also allows you to execute JavaScript functions in response to various movie events without sending javascript:// URLs from a movie.
The plug-in posts standard DOM events, so in browsers that support the W3C's DOM Level 2 Event Specification (http://www.w3.org/TR/DOM-Level-2-Events/) you use the addEventListener() method to monitor for the events.
Safari 3.0 and FireFox 2.0 are examples of browsers that support the W3C standards sufficiently to work with the methods described in this document.
Internet Explorer version 5 and later supports a slightly different method that is essentially equivalent: attachEvent().
For a page to work correctly whether visitors are using browsers that support the W3C standards or using Internet Explorer, you must include JavaScript code for both the addEventListener() function and the attachEvent() function.
All the examples in this document use both methods and should work with all W3C-compliant browsers, and well as with Internet Explorer.
Summary of DOM Events
Enabling DOM Events
Listening For DOM Events
Using DOM Events to Monitor Movie Loading
Monitoring and Controlling Multiple Movies
QuickTime can emit DOM events when the plug-in is instantiated and ready to interact with JavaScript, at various points during a movie’s loading process, when playback has begun, paused, or ended, or in the event of an error. The following list shows the DOM events that can be listened for. Note that all QuickTime DOM events begin with the prefix “qt_” to prevent name space collisions.
qt_begin — The plug in has been instantiated and can interact with JavaScript.
qt_loadedmetadata — The movie header information has been loaded or created. The duration, dimensions, looping state, and so on are now known.
qt_loadedfirstframe — The first frame of the movie has been loaded and can be displayed. (The frame is displayed automatically at this point.)
qt_canplay — Enough media data has been loaded to begin playback (but not necessarily enough to play the entire file without pausing).
qt_canplaythrough — Enough media data has been loaded to play through to the end of the file without having to pause to buffer, assuming data continues to come in at the current rate or faster. (If the movie is set to autoplay, it will begin playing now.)
qt_durationchange — The media file’s duration is available or has changed. (A streaming movie, a SMIL movie, or a movie with a QTNEXT attribute may load multiple media segments or additional movies, causing a duration change.)
qt_load — All media data has been loaded.
qt_ended — Playback has stopped because end of the file was reached. (If the movie is set to loop, this event will not occur.)
qt_error — An error occurred while loading the file. No more data will be loaded.
qt_pause — Playback has paused. (This happens when the user presses the pause button before the movie ends.)
qt_play — Playback has begun.
qt_progress — More media data has been loaded. This event is fired no more than three times per second.
This event occurs repeatedly until the qt_load event or qt_error event. The last progress event may or may not coincide with the loading of the last media data. Use the progress function to monitor progress, but do not rely on it to determine whether the movie is completely loaded. Use the qt_load function in conjunction with the qt_progress function to monitor load progress and determine when loading is complete.
qt_waiting — Playback has stopped because no more media data is available, but more data is expected. (This usually occurs if the user presses the play button prior to the qt_canplaythrough event. It can also occur if the data throughput slows during movie playback, and the buffer runs dry.)
qt_stalled — No media has been received for approximately three seconds.
qt_timechanged — The current time has been changed (current time is indicated by the position of the playhead).
qt_volumechange — The audio volume or mute attribute has changed.
The QuickTime plug-in will emit DOM events only if this feature is explicitly enabled by setting postdomevents true in the <OBJECT> or <EMBED> tag.
In Internet Explorer you must also ensure that the <HEAD> element contains an <OBJECT> element for the “binary behavior” object (clsid CB927D12-4FF7-4a9e-A169-56E4B8A75598) that emits DOM events. The <OBJECT> tag that invokes the plug-in must include a style attribute that references the “binary behavior” object's ID, using the following syntax: style="behavior:url(#BinaryBehaviorID)".
For example, if the binary behavior object has the ID “qt_event_source”, the object tag that embeds the movie must include the attribute style='behavior:url(#qt_event_source)'. The necessary tags to perform these actions are automatically inserted by the AC_QuickTime.js script when the postdomevents parameter is set true.
Note: The ID for the <EMBED> and <OBJECT> tags must have unique values, but the <EMBED> NAME parameter can have the same value as the <OBJECT> ID to simplify movie addressing from JavaScript.
Listing 1-6 Enabling DOM Events Using AC_QuickTime.js
<script language="javascript" type="text/javascript"> |
QT_WriteOBJECT('MyMovie.mov' , '320', '256', '', 'EnableJavaScript', 'True', 'postdomevents', 'True', 'emb#NAME' , 'movie1' , 'obj#id' , 'movie1', 'emb#id', 'movie_embed1') ; |
</script> |
If you prefer not to use the AC_QuickTime.js script to create the <OBJECT> and <EMBED> tags, the following listing shows the syntax for creating the necessary tags manually.
Listing 1-7 Enabling DOM Events Manually
<object id="qt_event_source" classid="clsid:CB927D12-4FF7-4a9e-A169-56E4B8A75598" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=7,2,1,0" ></object> |
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=7,2,1,0"
width="320" height="256" type="video/quicktime" id="movie1"
style="behavior:url(#qt_event_source);">
|
<param name="src" value="MyMovie.mov" /> <param name="postdomevents" value="true" /> |
<embed |
src="MyMovie.mov" |
width="320" height="256" |
id="movie_embed1" |
name="movie1" |
postdomevents="true"> |
</embed> |
</object> |
In order to respond to DOM events, you need to create and register a “listener” function for each DOM event you are interested in.
For browsers that work with the W3C DOM Level 2 Event Specification, use the addEventListener() function; for Internet Explorer, use the attachEvent() function and add the prefix “on” to the event. The following listing gives an example.
Listing 1-8 Cross-platform event listener registration
<script language="javascript" type="text/javascript"> |
function myAddListener(obj, evt, handler, captures) |
{ |
if ( document.addEventListener ) |
obj.addEventListener(evt, handler, captures); |
else |
// IE |
obj.attachEvent('on' + evt, handler); |
} |
</script> |
Here’s an example of a web page that listens for the DOM event emitted periodically when a movie is loading, and displays the percent of the movie loaded so far. It also monitors for the movie loaded event, and overwrites the progress message with a “movie loaded” message when the movie is fully loaded.
Listing 1-9 Monitoring movie loading using DOM events
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html140/DTD/loose.dtd"> |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> |
<head> |
<script src="AC_QuickTime.js" language="JavaScript" type="text/javascript"> |
</script> |
<script language ="JavaScript" type="text/javascript"> |
<!-- |
/* define function that shows percentage of movie loaded */ |
function showProgress() |
{ |
var percentLoaded = 0 ; |
percentLoaded = parseInt((document.movie1.GetMaxTimeLoaded() / document.movie1.GetDuration()) * 100); |
document.getElementById("loadStatus").innerHTML = 'Movie loading: ' + percentLoaded + '% complete...'; |
} |
/* define function that executes when movie loading is complete */ |
function movieLoaded() |
{ |
document.getElementById("loadStatus").innerHTML = "Movie Loaded" ; |
} |
/* define function that adds another function as a DOM event listener */ |
function myAddListener(obj, evt, handler, captures) |
{ |
if ( document.addEventListener ) |
obj.addEventListener(evt, handler, captures); |
else |
// IE |
obj.attachEvent('on' + evt, handler); |
} |
/* define functions that register each listener */ |
function RegisterListener(eventName, objID, embedID, listenerFcn) |
{ |
var obj = document.getElementById(objID); |
if ( !obj ) |
obj = document.getElementById(embedID); |
if ( obj ) |
myAddListener(obj, eventName, listenerFcn, false); |
} |
/* define a single function that registers all listeners to call onload */ |
function RegisterListeners() |
{ |
RegisterListener('qt_progress', 'movie1', 'qtmovie_embed', showProgress); |
RegisterListener('qt_load', 'movie1', 'qtmovie_embed', movieLoaded); |
} |
//--> |
</script> |
<title>JavaScript Movie Monitor</title> |
</head> |
<body onload="RegisterListeners()"> |
<div align=center> |
<h2>Movie with JavaScript Progress/Load Monitors</h2> |
<script language="javascript" type="text/javascript"> |
QT_WriteOBJECT('MyMovie.mov' , '320', '256', '', 'EnableJavaScript', 'True', |
'postdomevents', 'True', 'emb#NAME' , 'movie1' , 'obj#id' , 'movie1', 'emb#id', |
'qtmovie_embed') ; |
</script> |
<p ID="loadStatus"> |
MOVIE LOADING... |
</p> |
<p> <a href="javascript:document.movie1.Play();">Play</a> </p> |
<p> <a href="javascript:document.movie1.Stop();">Stop</a> </p> |
</div> |
</body> |
</html> |
You can control and monitor multiple movies on a single web page using JavaScript controls and DOM events. You need to give each movie a unique name in the <EMBED> tag, a matching ID in the <object> tag, as well as a unique ID in the <EMBED> tag.
Create and register DOM event listeners for each movie, using the <EMBED> and <OBJECT> IDs.
Create JavaScript controls for each movie, using the <EMBED> NAME, which is the same as the <OBJECT> ID.
For example, you might have two movies, the first with an <OBJECT> ID and <EMBED> NAME of movie1, and an <EMBED> ID of movie_embed1, and a second movie with an <OBJECT> ID and <EMBED> NAME of movie2, and an <EMBED> ID of movie_embed2. Register DOM event listeners for movie1/movie_embed1 and movie2/movie_embed2, and create JavaScript controls for movie1 and movie2.
The following listing is an example of a web page that monitors the load progress and load completion of two movies, and provides play and stop controls for each movie in JavaScript.
Listing 1-10 Web page that monitors and controls two movies using JavaScript and DOM events
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html140/DTD/loose.dtd"> |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> |
<head> |
<script src="AC_QuickTime.js" language="JavaScript" type="text/javascript"> |
</script> |
<script language ="JavaScript" type="text/javascript"> |
<!-- |
/* define function that shows percentage of movie 1 loaded */ |
function showProgress() |
{ |
var percentLoaded = 0 ; |
percentLoaded = parseInt((document.movie1.GetMaxTimeLoaded() / document.movie1.GetDuration()) * 100); |
document.getElementById("loadStatus1").innerHTML = 'Movie loading: ' + percentLoaded + '% complete...'; |
} |
/* define function that executes when movie1 loading is complete */ |
function movieLoaded() |
{ |
document.getElementById("loadStatus1").innerHTML = "Movie Loaded" ; |
} |
/* define function that shows percentage of movie 2 loaded */ |
function showProgress2() |
{ |
var percentLoaded = 0 ; |
percentLoaded = parseInt((document.movie2.GetMaxTimeLoaded() / document.movie2.GetDuration()) * 100); |
document.getElementById("loadStatus2").innerHTML = 'Movie loading: ' + percentLoaded + '% complete...'; |
} |
/* define function that executes when movie2 loading is complete */ |
function movieLoaded2() |
{ |
document.getElementById("loadStatus2").innerHTML = "Movie Loaded" ; |
} |
/* define function that adds another function as a listener for a DOM event */ |
function myAddListener(obj, evt, handler, captures) |
{ |
if ( document.addEventListener ) |
obj.addEventListener(evt, handler, captures); |
else |
// IE |
obj.attachEvent('on' + evt, handler); |
} |
/* define functions that register each listener */ |
function RegisterListener(eventName, objID, embedID, listenerFcn) |
{ |
var obj = document.getElementById(objID); |
if ( !obj ) |
obj = document.getElementById(embedID); |
if ( obj ) |
myAddListener(obj, eventName, listenerFcn, false); |
} |
/* define a single function that registers all listeners to call onload */ |
function RegisterListeners() |
{ |
RegisterListener('qt_progress', 'movie1', 'qtmovie_embed', showProgress); |
RegisterListener('qt_load', 'movie1', 'qtmovie_embed', movieLoaded); |
RegisterListener('qt_progress', 'movie2', 'qtmovie_embed2', showProgress2); |
RegisterListener('qt_load', 'movie2', 'qtmovie_embed2', movieLoaded2); |
} |
//--> |
</script> |
<title>JavaScript Movie Controls and Monitors</title> |
</head> |
<body onload="RegisterListeners()"> |
<div align=center> |
<h2>Two Movies with JavaScript Play/Stop Controls<br>and Progress/Load Monitors</h2> |
<script language="javascript" type="text/javascript"> |
QT_WriteOBJECT('MyMovie.mov', '360','256', '', 'obj#id', 'movie1', 'emb#id', 'qtmovie_embed', 'emb#name', 'movie1', 'postdomevents', 'true', 'enablejavascript', 'true'); |
</script> |
|
<script language="javascript" type="text/javascript"> |
QT_WriteOBJECT('MyOtherMovie.mov', '360','256', '', 'obj#id', 'movie2', 'emb#id', 'qtmovie_embed2', 'emb#name', 'movie2', 'postdomevents', 'true', 'enablejavascript', 'true'); |
</script> |
<table width="100%"> |
<tr> |
<td align=center> |
<P ID="loadStatus1"> |
MOVIE LOADING... |
</p> |
</td> |
<td align=center> |
<P ID="loadStatus2"> |
MOVIE LOADING... |
</p> |
</td> |
</tr> |
<tr> |
<td align=center> |
<P> <a href="javascript:document.movie1.Play();">Play 1</a> </P> |
</td> |
<td align=center> |
<P> <a href="javascript:document.movie2.Play();">Play 2</a> </P> |
</td> |
</tr> |
<tr> |
<td align=center> |
<P> <a href="javascript:document.movie1.Stop();">Stop 1</a> </P> |
</td> |
<td align=center> |
<P> <a href="javascript:document.movie2.Stop();">Stop 2 </a> </P> |
</td> |
</tr> |
</table> |
</div> |
</body> |
</html> |
Last updated: 2008-02-08