FlashVars broken in IE8

Unsurprisingly, Internet Explorer 8 broke yet another feature of the web. This time, the folks at Redmond broke how Internet Explorer passes the flashvars parameter into Flash. Typically, when placing a Flash object on an HTML page, you use the following syntax:

<object id="flv" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="692" height="516" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" align="middle">
 <param name="allowScriptAccess" value="sameDomain" />
 <param name="allowFullScreen" value="true" />
 <param name="quality" value="high" />
 <param name="bgcolor" value="#424242" />
 <param name="FlashVars" value="name=value" />
 <param name="wmode" value="transparent" />
 <embed type="application/x-shockwave-flash" width="692" height="516" src="http://www.example.com/mysample.swf" name="flv" allowfullscreen="true" allowscriptaccess="sameDomain" wmode="transparent" bgcolor="#424242" quality="high" flashvars="name=value" pluginspage="http://www.macromedia.com/go/getflashplayer" align="middle"></embed>
 <param name="movie" value="http://www.example.com/mysample.swf" />
</object>

The OBJECT tag is used by Internet Explorer and the EMBED tag is used by everyone else (Firefox, Safari, etc.). Although the flashvars paramter is not formally described in the HTML 4.0.1 spec1, this code worked fine with IE 6 and IE 7. Unfortunately, IE 8 does not pass flashvars into the Flash Player. The only work around is to pass the flashvars parameter as part of the movie name parameter, as shown below:

<object id="flv" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="692" height="516" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" align="middle">
 <param name="allowScriptAccess" value="sameDomain" />
 <param name="allowFullScreen" value="true" />
 <param name="quality" value="high" />
 <param name="bgcolor" value="#424242" />
 <param name="FlashVars" value="name=value" />
 <param name="wmode" value="transparent" />
 <embed type="application/x-shockwave-flash" width="692" height="516" src="http://www.example.com/mysample.swf" name="flv" allowfullscreen="true" allowscriptaccess="sameDomain" wmode="transparent" bgcolor="#424242" quality="high" flashvars="name=value" pluginspage="http://www.macromedia.com/go/getflashplayer" align="middle"></embed>
 <param name="movie" value="http://www.example.com/mysample.swf?name=value" />
</object>

 

Notes:

1 http://www.w3.org/TR/html4/struct/objects.html#h-13.3.2

Embedding HTML Document in an IFRAME with GWT

While working on a recent project in GWT, I needed to embed a full HTML document inside an IFRAME. And I didn't want to specify a remote URL for the IFRAME - I actually wanted to shove the HTML content directly into the IFRAME.

Initially I thought it was trivial: create an IFrameElement and call setInnerHTML.

IFrameElement iframe = Document.get().createIFrameElement();
iframe.setInnerHTML(htmlContent);

Unfortunately, that doesn't work. It doesn't cause any errors, but it doesn't actually fill in the iframe. Instead, you have to use native javascript to write into the document object for the iframe:

private final native void fillIframe(IFrameElement iframe, String content) /*-{
  var doc = iframe.document;
 
  if(iframe.contentDocument)
    doc = iframe.contentDocument; // For NS6
  else if(iframe.contentWindow)
    doc = iframe.contentWindow.document; // For IE5.5 and IE6
 
   // Put the content in the iframe
  doc.open();
  doc.writeln(content);
  doc.close();
}-*/;

Voila! However, one of the side effects is that the iframe doesn't include any CSS unless your embedded HTML references a stylesheet. If you want to manually add a reference to a specific stylesheet, you can do that through native javascript as well:

private final native void addHeadElement(IFrameElement iframe, String cssUrl) /*-{
  setTimeout(function() {
 
    var body;
    if ( iframe.contentDocument ) { 
      // FF
      iframe.contentDocument.designMode= "On";
      iframe.contentDocument.execCommand('styleWithCSS',false,'false');
      body= iframe.contentDocument.body;
    }
    else if ( iframe.contentWindow ) {
      // IE
      body = iframe.contentWindow.document.body;  
    }
 
    if (body == null) {
      return;
    }
 
    body.className = "custom-body-classname";
    var head = body.previousSibling;
    if(head == null) {
      head = iframe.contentWindow.document.createElement("head");
 
      iframe.contentWindow.document.childNodes[0].insertBefore(head, body);
    }
    var fileref = iframe.contentWindow.document.createElement("link");
    fileref.setAttribute("rel", "stylesheet");
    fileref.setAttribute("type", "text/css");
    fileref.setAttribute("href", cssUrl); 
    head.appendChild(fileref);
  }, 50);
}-*/;}

There's still one more problem. You can't use either of native methods until the IFRAME element has been attached to the DOM. The easiest way around this is to add the IFRAME element to a panel and over the onLoad() method for the panel:

final IFrameElement iframe = Document.get().createIFrameElement();
FlowPanel innerBox = new FlowPanel() {
    @Override
    protected void onLoad() {
        super.onLoad();
 
        // Fill the IFrame with the content html
        fillIframe(iframe, contentHtml);
 
        // Add a HEAD element to the IFrame with the appropriate CSS
        addHeadElement(iframe, cssUrl);
    }
};
innerBox.getElement().appendChild(iframe);

I got the idea and the important code from an article titled Inject HTML into an IFrame from Software As She's Developed.

Subversion: File or directory is out of date; try updating

I recently started encountering a strange problem with Subversion on one of my machines. In larger commits, I would suddenly get an error:

$ svn ci -m "My commit message."
Sending        src/Foo.java
svn: Commit failed (details follow):
svn: File or directory 'src/Foo.java' is out of date; try updating
svn: resource out of date; try updating

Although I was positive the file(s) were up to date, I ran an svn up just to be safe:

$ svn up
At revision 10803.

Nothing changed. If I tried to commit again, I would get the same out of date error. Eventually I figured out that if I delete the folder containing the problematic file, ran svn up to restore the working copy and re-edited (or restored from a backup) the modified file, the problem went away. This suggested an issue with the Subversion metadata, but this blog post from Pageworthy describes a much easier work around:

Delete the all-wcprops file from the .svn metadata folder for the offending file.

In other words, if Subversion complains about src/com/mycompany/Foo.java, then delete src/com/mycompany/.svn/all-wcprops.

OS: Mac 10.6
IDE: Eclipse 20090920-1017
Subversive Team Provider: 0.7.8
Subversive Connectors: 2.2.1
SVNKit 1.3.0: 2.2.1
Subversion: 1.6.6

 

Checking Linux RAID array status

This website runs on a pair of drives in a RAID-1 configuration, as do several pairs of drives in my home that I use for storing media (music, movies, television, etc.). On all servers, I run software raid in Linux using mdadm. For some reason, I can never remember the simple syntax for checking the status of an array:

$ sudo /sbin/mdadm -QD /dev/md0
/dev/md0:
        Version : 00.90.03
  Creation Time : Fri Jun 19 06:16:37 2009
     Raid Level : raid1
     Array Size : 104320 (101.89 MiB 106.82 MB)
  Used Dev Size : 104320 (101.89 MiB 106.82 MB)
   Raid Devices : 2
  Total Devices : 2
Preferred Minor : 0
    Persistence : Superblock is persistent
 
    Update Time : Wed Sep 16 00:22:58 2009
          State : clean
 Active Devices : 2
Working Devices : 2
 Failed Devices : 0
  Spare Devices : 0
 
           UUID : b185a678:1789acb9:327678ee:0f02177d
         Events : 0.14
 
    Number   Major   Minor   RaidDevice State
       0       3        1        0      active sync   /dev/hda1
       1       3       65        1      active sync   /dev/hdb1

The State line and Working Devices are the most important for me. In this case, they indicate the array is just fine and both drives are working.

Kubuntu 9.10 Dual Monitors

A few months back I got a new 12.1" System76 Darter laptop and I finally decided to setup dual monitors on Kubuntu 9.10 (Karmic Koala).What I wanted was to have my laptop LCD on the left at 1280x800 and my ViewSonic LCD panel on the right running at 1680x1050. Apparently I'm old-skool, because I'm used to hacking away at my xorg.conf just to get dual monitor support to work under Linux. Somehow I never knew about xrandr, KRandR, etc.

ThinkWiki has a great article using XRandR (http://www.thinkwiki.org/wiki/Xorg_RandR_1.2) that really helped me out. When I first launched Kubuntu the two screens were mirrored. So, I tried to use KRandR to set the screens side by side. Unfortunately, it seemed to be confused - it saw there were two outputs, but it thought they were the same screen. This is where the ThinkWiki article came in handy.

With the later versions of Xorg, Ubuntu doesn't even include an xorg.conf. Instead of even monkeying around with Xorg, I just used xrandr. There were three key steps:

Identify Outputs

$ xrandr -q
Screen 0: minimum 320 x 200, current 2960 x 1050, maximum 8192 x 8192
VGA1 connected 1680x1050+1280+0 (normal left inverted right x axis y axis) 474mm x 296mm
   1680x1050      60.0*+
   1280x1024      75.0
   1152x864       75.0
   1024x768       75.1     70.1     60.0
   832x624        74.6
   800x600        72.2     75.0     60.3     56.2
   640x480        72.8     75.0     66.7     60.0
   720x400        70.1
LVDS1 connected 1280x800+0+0 (normal left inverted right x axis y axis) 261mm x 163mm
   1280x800       60.0*+
   1024x768       60.0
   800x600        60.3
   640x480        59.9
DP1 disconnected (normal left inverted right x axis y axis)

 

This shows I have two main outputs connected right now: VGA1 and LVDS1. Under Ubuntu 9.04 (Jaunty), my outputs were labeled VGA and LVDS.

Disable secondary output

Once we know the name of the outputs, we can disable the secondary output. This is the key step to getting a large virtual desktop working without something like Xinerama. If you don't disable the secondary output, Xorg never seems to be able to successfully distinguish between the two outputs.

$ xrandr --output VGA1 --off

Re-enable both outputs

When we re-enable the outputs we can specify the location of the secondary display, relative to the primary. We can also let xrandr figure out the best resolution for each:

$ xrandr --output LVDS --auto --output VGA --auto --right-of LVDS

Voila. Finally, if you want to automate this, the ThinkWiki article has a great little script you can use. However, I did have to modify it slightly ... I had to force the VGA1 output off before setting them both to auto. Without that, the secondary screen remained blank.

# If an external monitor is connected, place it with xrandr
 
# External output may be "VGA" or "VGA-0" or "DVI-0" or "TMDS-1"
EXTERNAL_OUTPUT="VGA1"
INTERNAL_OUTPUT="LVDS1"
# EXTERNAL_LOCATION may be one of: left, right, above, or below
EXTERNAL_LOCATION="right"
 
case "$EXTERNAL_LOCATION" in
       left|LEFT)
               EXTERNAL_LOCATION="--left-of $INTERNAL_OUTPUT"
               ;;
       right|RIGHT)
               EXTERNAL_LOCATION="--right-of $INTERNAL_OUTPUT"
               ;;
       top|TOP|above|ABOVE)
               EXTERNAL_LOCATION="--above $INTERNAL_OUTPUT"
               ;;
       bottom|BOTTOM|below|BELOW)
               EXTERNAL_LOCATION="--below $INTERNAL_OUTPUT"
               ;;
       *)
               EXTERNAL_LOCATION="--left-of $INTERNAL_OUTPUT"
               ;;
esac
 
xrandr |grep $EXTERNAL_OUTPUT | grep " connected "
if [ $? -eq 0 ]; then
    xrandr --output $EXTERNAL_OUTPUT --off
    xrandr --output $INTERNAL_OUTPUT --auto --output $EXTERNAL_OUTPUT --auto $EXTERNAL_LOCATION
    # Alternative command in case of trouble:
    # (sleep 2; xrandr --output $INTERNAL_OUTPUT --auto --output $EXTERNAL_OUTPUT --auto $EXTERNAL_LOCATION) &amp;
else
    xrandr --output $INTERNAL_OUTPUT --auto --output $EXTERNAL_OUTPUT --off
fi

Place this /etc/X11/Xsession.d as 45custom_xrandr-settings and it will automatically run.

Syndicate content