Home » Code

Using LightWindow with Inline Javascript for Flash or Video

LightWindow is one of the better modal windows available for the Prototype/Scriptaculous environment. It looks great, has excellent browser compatibility, and works with many kinds of content. However, I ran into a situation that required a few tweaks to get LightWindow to work on all current browsers.

Recently, I needed a modal window for two different kinds of dynamic content: preview a FLV movie using Flowplayer, and preview a custom flash widget using SWFObject. In both cases I started out configuring LightWindow to use inline content:

<div id="videoplayer" name="videoplayer" style="display:none;">
    <script>
        //... inline javascript for video/flv player...
    </script>
</div>
 
<a href="javascript: myLightWindow.activateWindow({href: '#videoplayer', type: 'inline' });">
    [preview video]
</a>

This worked fine on Firefox, Safari, Opera, and Chrome, but didn’t work on Internet Explorer. It appears that IE7 and IE8 (I didn’t test IE6) will not execute inline javascript when contents of the #videoplayer node are added to the DOM by LightWindow. This broke both the Flowplayer and SWFObject functionality in Internet Explorer, while both worked fine in all other browsers tested.

The next step was to try loading the node via Ajax instead of inline. This way, the #videoplayer node isn’t already in the DOM, and perhaps it will be handled differently. It’s not clearly documented on the LightWindow web site, but local pages (residing on the same domain) are actually fetched by LightWindow using Prototype’s Ajax.Request. So passing type: ‘page’ does the trick:

<a href="javascript: myLightWindow.activateWindow({href: '/get_videoplayer_node', type: 'page' });">
    [preview video]
</a>

Now, the server simply returns the HTML and javascript for the videoplayer and it is dynamically inserted into the DOM. Does this now work on all browsers? No. Actually, it now fails on every browser for all dynamic content. The javascript simply doesn’t get executed. Looking into lightwindow.js you will notice that the handler for inline content adds the node to the DOM like this:

lightwindow.js, line 1354:

new Insertion.Top($('lightwindow_contents'), response.responseText);

…while the handler for Ajax requests adds the content like this:

lightwindow.js, line 1336:

$('lightwindow_contents').innerHTML += response.responseText;

In the latter case, no browser will execute javascript in the Ajax response. Changing the handler to use the same code as the inline case fixes this:

case 'page' :
  var newAJAX = new Ajax.Request(
    this.contentToFetch, {
      method: 'get',
      parameters: '',
      onComplete: function(response) {
        // replace with same technique as case 'inline' so inline javascript gets executed.
        //$('lightwindow_contents').innerHTML += response.responseText;
        new Insertion.Top($('lightwindow_contents'), response.responseText);
 
        this.resizeTo.height =
            $('lightwindow_contents').scrollHeight+(this.options.contentOffset.height);
        this.resizeTo.width =
            $('lightwindow_contents').scrollWidth+(this.options.contentOffset.width);
        this._processWindow();
      }.bind(this)
    }
  );
break;

Now all browsers are happy, and the two real world cases I tested (Flowplayer and SWFObject) are working fine…. Until you close the LightWindow. Again, every other browser handles this just fine except IE, ( 7 and 8 ) which doesn’t destroy the embedded objects, so the audio continues to play until the entire page is refreshed.

Flowplayer and SWFObject both provide methods to close (or at least stop) the player. What if these could be called when the modal window closes? Since there are several ways to close the modal window (including keypress and mouse actions), the only reliable technique is to call a handler from LightWindow’s deactivate method. This requires several steps.

Add the handler to the activateWindow options:

lightwindow.js, line 316:

  this.element = Object.extend({
    href : null,
    title : null,
    author : null,
    caption : null,
    rel : null,
    top : null,
    left : null,
    type : null,
    showImages : null,
    height : null,
    width : null,
    loadingAnimation : null,
    iframeEmbed : null,
    // add close handler for IE compatibility
    closeHandler : false,
    form : null
  }, options || {});

Call the handler from within deactivate():

lightwindow.js, line 276:
deactivate : function(){
 
  // call close handler for IE compatibility
  if (this.element.closeHandler) {
    this.element.closeHandler();
  }

And finally, the handler must be passed on the call to activateWindow.

Flowplayer example:

<a href="javascript: myLightWindow.activateWindow(
        {   href: '/get_videoplayer_node',
            type: 'page',
            closeHandler: function(){ 
                        $f('flowplayer').stop(); 
                        } });">
[preview video]
</a>

SWFObject example:

<a href="javascript: myLightWindow.activateWindow(
        {   href: '/get_videoplayer_node',
            type: 'page',
            closeHandler: function(){ 
                        swfobject.removeSWF('flash-object'); 
                        } });">
[preview video]
</a>

LightWindow has great support built in for simply displaying SWFs and other media types, but if your application requires Javascript as well, the above techniques helped me achieve 100% compatibility on current browsers.

  • Jeremy

    Hi. I ran into the same problem and would like to thank you for posting a solution. My player now works but I (and probably many others trying to play flv files judging by the lightwindow feedback comments) would be quite interested to see how you coded the player via get_videoplayer_node.

  • Jeremy, here are the important parts returned by get_videoplayer_node:

    < a href="/content.flv" id="flowplayer_id">
    < / a >
    <script language="JavaScript">
    flowplayer("flowplayer_id", "/js/flowplayer/flowplayer-3.1.1.swf");
    </script>

  • Walt -

    Not a programmer, so forgive me for asking - or asking a stupid question:

    I'm also using LightWindow, with a dock menu that is requiring a javascript call (couldn't figure out another way to get it to work).

    I get type:'page' and 'image' to work fine, but if I try to load a .swf FlashPaper using 'media' it loads, but is blank?

    If I spend the time trying to work through your example, do you think it will work for me when loading FlashPaper like when your loading a video?

    {link:"javascript:myLightWindow.activateWindow({href: 'Brochure.swf', type:'media', title: 'title', caption: 'caption'});"});

  • Walt: Correction (type:'page', not 'media')!

    {link:"javascript:myLightWindow.activateWindow({href: 'Brochure.swf', type:'page', title: 'title', caption: 'caption'});"});

  • Tim,

    I'm not sure if that will work. The best way to find out is to try it! :)

    Walt

blog comments powered by Disqus