Wednesday, 26 September 2007

Windows Media Player Javascript Detect and Embed

Geoff Stearns over at deconcept.com wrote a great script to detect and embed Flash objects, called SWFObject embed. What I love about it is that it is really simple to use and bypasses the problems of the Eolas v Microsoft debarcle (Click to activate this control). He also produced a Quicktime detect and embed alongside the Flash SWFObject that is also very useful. I needed a similar script for Windows Media Players, so without being able to find a great example, I knocked this up, based on his code.

First we create the WMPObject:


  1. WMPObject = function(mov, id, w, h) {

  2. this.mov = mov;

  3. this.id = id;

  4. this.width = w;

  5. this.height = h;

  6. this.redirect = "";

  7. this.sq = document.location.search.split("?")[1] || "";

  8. this.altTxt = "This content requires the Microsoft Windows Media Plugin. <a href='http://www.microsoft.com/windows/windowsmedia/download/'>Download Windows Media Player</a>.";

  9. this.bypassTxt = "<p>Already have Windows Media Player? <a href='?detectwmp=false&"+ this.sq +"'>Click here.</a></p>";

  10. this.params = new Object();

  11. this.doDetect = getQueryParamValue('detectwmp');

  12. }



Then deal with any parameters that are passed:


  1. WMPObject.prototype.addParam = function(name, value) {

  2. this.params[name] = value;

  3. }


  4. WMPObject.prototype.getParams = function() {

  5. return this.params;

  6. }


  7. WMPObject.prototype.getParam = function(name) {

  8. return this.params[name];

  9. }


  10. WMPObject.prototype.getParamTags = function() {

  11. var paramTags = "";

  12. for (var param in this.getParams()) {

  13. paramTags += '<param name="' + param + '" value="' + this.getParam(param) + '" />';

  14. }

  15. if (paramTags == "") {

  16. paramTags = null;

  17. }

  18. return paramTags;

  19. }



We then have a function to generate the core HTML and return a string of HTML code:


  1. WMPObject.prototype.getHTML = function() {

  2. var wmpHTML = "";

  3. if (navigator.plugins && navigator.plugins.length) { // not ie

  4. wmpHTML += '<embed type="application/x-mplayer2" pluginspage="http://www.microsoft.com/Windows/MediaPlayer/" src="'

  5. + this.mov + '" width="' + this.width + '" height="' + this.height + '" id="' + this.id + '"';

  6. for (var param in this.getParams()) {

  7. wmpHTML += ' ' + param + '="' + this.getParam(param) + '"';

  8. }

  9. wmpHTML += '></embed>';

  10. }

  11. else { // pc ie

  12. wmpHTML += '<object classid="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95" width="' + this.width + '" height="' + this.height + '" id="' + this.id + '">';

  13. this.addParam("src", this.mov);

  14. if (this.getParamTags() != null) {

  15. wmpHTML += this.getParamTags();

  16. }

  17. wmpHTML += '</object>';

  18. }

  19. return wmpHTML;

  20. }



And deal with attributes:


  1. WMPObject.prototype.getVariablePairs = function() {

  2. var variablePairs = new Array();

  3. for (var name in this.getVariables()) {

  4. variablePairs.push(name + "=" + escape(this.getVariable(name)));

  5. }

  6. if (variablePairs.length > 0) {

  7. return variablePairs.join("&");

  8. }

  9. else {

  10. return null;

  11. }

  12. }



Write the generated HTML out to the page:


  1. WMPObject.prototype.write = function(elementId) {

  2. if(isWMPInstalled() || this.doDetect=='false') {

  3. if (elementId) {

  4. document.getElementById(elementId).innerHTML = this.getHTML();

  5. } else {

  6. document.write(this.getHTML());

  7. }

  8. } else {

  9. if (this.redirect != "") {

  10. document.location.replace(this.redirect);

  11. } else {

  12. if (elementId) {

  13. document.getElementById(elementId).innerHTML = this.altTxt +""+ this.bypassTxt;

  14. } else {

  15. document.write(this.altTxt +""+ this.bypassTxt);

  16. }

  17. }

  18. }

  19. }



And deal with plugin detection:


  1. function isWMPInstalled() {

  2. var wmpInstalled = false;

  3. wmpObj = false;

  4. if (navigator.plugins && navigator.plugins.length) {

  5. for (var i=0; i < navigator.plugins.length; i++ ) {

  6. var plugin = navigator.plugins[i];

  7. if (plugin.name.indexOf("Windows Media Player") > -1) {

  8. wmpInstalled = true;

  9. }

  10. }

  11. } else {

  12. execScript('on error resume next: wmpObj = IsObject(CreateObject("MediaPlayer.MediaPlayer.1"))','VBScript');

  13. wmpInstalled = wmpObj;

  14. }

  15. return wmpInstalled;

  16. }


  17. /* get value of querystring param */

  18. function getQueryParamValue(param) {

  19. var q = document.location.search;

  20. var detectIndex = q.indexOf(param);

  21. var endIndex = (q.indexOf("&", detectIndex) != -1) ? q.indexOf("&", detectIndex) : q.length;

  22. if(q.length > 1 && detectIndex != -1) {

  23. return q.substring(q.indexOf("=", detectIndex)+1, endIndex);

  24. } else {

  25. return "";

  26. }

  27. }



Then to use the WMPObject, you can use the following:


  1. <div id="MyContainer">

  2. Loading product demonstration video...

  3. </div>


  4. <script type="text/javascript">

  5. var vo = new WMPObject("wmpMovie.wmv", "myMovie", "380", "285");

  6. vo.addParam("AutoPlay", "False");

  7. vo.addParam("ShowStatusBar", "True");

  8. vo.write("MyContainer");

  9. </script>



I'll put together a ZIP file at some point if anyone is interested.

4 comments:

Ing. Argenis León. MSc. said...

Great,
Could you please post the zip file?

Ben said...

I have created a zip file with the Javascript include file only. There is no demo, but at some point I'll warp it all together.

If you follow the instructions for the Quicktime example that Geoff Stearns has created and switch the references in your HTML code for the wmpObject instead, you shouldn't go far wrong.

The file can be found here: http://www.box.net/shared/3ddpad6hw0

Geoff's information on the Quicktime Object detect and embed is here: http://blog.deconcept.com/2005/01/26/web-standards-compliant-javascript-quicktime-detect-and-embed/

nopeahopea said...

Excellent work.

Unfortunately, a huge problem remains: when scaling embedded video, firefox (and other non-IE pc browsers) tend to not scale the video height when user has WMP 11 installed. This doesn't have anything to do with the script though. The problem relies on the general plugin implementation.

For example, let's say you wanted to scale up a 320x240 video to 640x480 - the video width is expanded to 640px but the height remains at 240px.

Have you guys come around this problem?

Ben said...

You could try adding the following parameter:

< PARAM name='windowlessVideo' value='true' >

A Google search turned this up, but I haven't tried it out.