Skip to main content

A Better Applet Experience, Part 2: Poster Frames

Posted by joshy on August 26, 2008 at 2:37 PM PDT

In part one of this series I showed you how to set up a loading image, including an animated spinner gif. In this part I'll show you how use a screenshot or poster frame to speed up page loading.

Quicktime movies have the concept of a poster frame. It's a single frame of the movie (often the first frame) which is loaded in place of the movie. The actual movie will only be loaded over the network when the user clicks on the poster frame. This greatly speeds up loading the webpage the movie is in. Using a bit of Javascript we can do the exact same thing for Java Applets.

Poster Frames for Applets

Before we get into this demo I must mention that I haven't personally tested this on IE yet. If you find a browser that this doesn't work on please send me the error so I can update my javascript.

The basic idea is pretty simple. We create a div containing a link and an image of the screenshot. When the user clicks on the link we use javascript to replace the a and img elements in the page with a new applet element. Once the browser sees the new applet element it will load the Java plugin and start the applet.

Here is an example. If you click on the image a real applet will load in it's place and say 'applet loaded'

The Javascript

Here is the script which does it:

<script>
function generateInlineAppletTag(appletID, screenshotID) {
    var attributes = {
        code:'animatedstartup.MainApplet',
        width:100,
        height:100,
        archive:'http://projects.joshy.org/demos/AnimatedStartup/AnimatedStartup.jar',
        id:'fooApplet'
    };
    var parameters = {
        image:'http://projects.joshy.org/demos/AnimatedStartup.gif',
        centerImage:'true'
    };
   
   
    var appletTag = document.createElement("applet");
   
    for (var attribute in attributes) {
        appletTag.setAttribute(attribute,attributes[attribute]);
    }
   
    if (parameters != 'undefined' && parameters != null) {
        for (var parameter in parameters) {
            var param = document.createElement("PARAM");
            param.setAttribute("name",parameter);
            param.setAttribute("value",parameters[parameter]);
            appletTag.appendChild(param);
        }
    }
   
   
    var bodyRef = document.getElementById(appletID);
    var screenshot = document.getElementById(screenshotID);
    bodyRef.removeChild(screenshot);
    bodyRef.appendChild(appletTag);
}
</script>

The first part of script initializes two hashmaps containing the applet element's attributes and the nested param tags. Then it creates the applet using the document.createElement() method, and then configures the attributes and PARAM elements. So far this is pretty straight forward. The real magic happens in the last four lines of the generateInlineAppletTag function. It grabs the div element that surrounds the link and image using the passed in appletID parameter. Then it finds and removes the link and replaces it with the new applet element.

The HTML

To use this javascript function you just put it in the top of your page and call it from the href of your screenshot link. In this example I used this:

<div id="appletDiv">
<a id="screenshot1" href="javascript:generateInlineAppletTag('appletDiv','screenshot1');">
<img src="http://projects.joshy.org/demos/AnimatedStartup/applet_screenshot.png" border="0"
/>
</a>
</div>

The div is named appletDiv and the link is named screenshot1. The link's href invokes the javascript function, passing in the name of the div and link. Finally the image just shows a screenshot of the running applet overlaid with a play button. That's it. You can see the full HTML and Javascript here.

Conclusion

This javascript is just the start. You could easily extend it to have a rollover on image with more information about the applet. You could also rewrite the javascript into a more reusable form that could be shared across your entire site.

Next time I'll show you how to use the new deployment toolkit to auto detect the currently installed version of Java and start an upgrade.

Again, if you find any errors in this on particular platforms or browsers, please let me know so I can update it.

Comments

Great ideia. It's really a improve over usability.

i'm not sure if you're part of this team even, but i was always curious why the deployment sdk doesn't provide methods to add applets after the page was loaded (to a div with a certain id for instance). Anyways, I like the "click to play" approach... No problems on latest Safari/Firefox under os 10.5

p.s. I'm actually using this approach now: http://www.superduper.org/processing/metasurface thanks for the idea!

I click the image, something loads, and then the image is replaced with nothing. Is this supposed to work in Firefox and Ubuntu, when JDK 1.6 u10rc is installed? Also, I wonder why you are generating applet tags. Those were deprecated 9 years ago: http://www.w3.org/TR/REC-html40/struct/objects.html /Casper

coffeejolts: Looks like i've got some more IE testing to do. :) It's not possible to get access to the default loading image because it's not actually an image, it's some small native C code. we are working on ways of letting you build your own preloaders, however. carcour: the startup time is the combination of several things: jvm startup, initializing the browser plugin, downloading your app, starting your app. Going from a smaller to a larger application will only affect the last two things. As applications get larger you will of course have more to download, but thanks to the new plugin in JavaSE 6 update 10 you can use pack200 compression in applets. This means a factor of 5 compression over .zip alone (which is what standard jars use). This means most applications will be quite small and download time will be a small portion of the startup. The bigger part will be image resources, which flash apps have to deal with as well. Fortunately, your app has control over loading images so those can be downloaded *after* the app has already started (just like in flash), contributing to a faster startup user experience.

That's only for 1 applet that does nothing. A real applet will probably take 1s more. Also imagine having different applets in each page. They might use the same VM but they might use different ones depending on that was specified in the applet tag. Anyways to me this is not viable as a Flash replacement (I develop in Swing not flash and I'm not a Flash advocate). Most news sites now include flash and if it's gonna take 2s more to load then thank you very much.

2 seconds for an applet to load is unacceptable for the web?!? Hmmm.... Google.com is the only page that loads in under 2 seconds for me. From any ISP that I've been connected to. I guess I've been putting up with pathetic web access for too long then. I'll start complaining to my network admins and ISPs from now on. ;-)

Nice job. The only problem is the plugin load speed. On my current machine 3Ghz Pentium 4 with 2GB of RAM under Windows XP Pro on Firefox and IE7 it takes around 1.8s for the plugin to load with Java 6 Update 10b27 add to this the time it takes for the class loading and it goes up to 2s which is unacceptable for the Web. basic: PERF: AppletExecutionRunnable - applet.init() BEGIN ; jvmLaunch dt 423041 us, pluginInit dt 1452070 us, TotalTime: 1875111 us

Nice work, Josh!

Josh, Here are my test results in Internet Exploder. The code works perfectly in IE7. IE6 works, but there is a dialog box that says press ok to continue loading the page. IE 5.5 and below do not work. Is it possible to gain access to the progress bar that the default applet loading screen has? That would allow us to make some cool preloaders.