Over the past few weeks, I've been taking a look at Spry's widgets, specifically those related to form items. I've been surprised by what I've found. I really wish I would have looked at them earlier. Today I looked at another widget, the HTML Panel. This one isn't form related, but is darn cool.

The HTML Panel is not a "panel" like what you get in ColdFusion 8. You can think of the panel as simply an item on your web page that can be loaded with other content. For example, imagine this div:

<div id="content"> Stuff will load here. </div>

Now imagine I want to load content into this div. By creating an HTML Panel widget out of the div, I can easily change the content. Let's look at a real example.

First off - like the other widgets, you need to use a CSS and JavaScript file:

<html>

<head> <script src="/spryjs/SpryHTMLPanel.js" language="javascript" type="text/javascript"></script> <link href="/sprycssSpryHTMLPanel.css" rel="stylesheet" type="text/css"> </head>

Next I'm going to create a menu. This is what I'll use to load content:

<h2>Products</h2>

<p> <b> <a onClick="panel.loadContent('apple.html'); return false">Apples</a> / <a onClick="panel.loadContent('banana.html'); return false">Bananas</a> / <a onClick="panel.loadContent('cherry.html'); return false">Cherries</a> </b> </p>

Don't worry about the JavaScript just yet. Now I'll create the area where content will load:

<div id="product"> <p> Please select a product. </p> </div>

The last thing I'll do is enable the HTML panel with a line of JavaScript. This is like every other widget I've covered so far:

<script type="text/javascript"> var panel = new Spry.Widget.HTMLPanel("product"); </script> </body> </html>

I simply create a new instance of the HTMLPanel, and point it to the ID of the item that will be replaceable. Ok, so now if you go back to the JavaScript you can see what I use to load content:

<a onClick="panel.loadContent('apple.html'); return false">Apples</a>

I just use the loadContent function of the panel object. I point it to the HTML to load, and that's it! You can see a live example of this here. View source to see the complete example.

So far so good - and easy as well. But wait - it gets a lot sexier. One of the things Spry tries to help out with is a progressive enhancement. That is a fancy way of saying "support non-JavaScript" browsers. One of the options you can use when loading widgets is to supply an ID. Spry will load the remote content, but only display the stuff within the specified ID. Why is that sexy? Consider this new example (note, I trimmed a bit of the HTML):

<h2>Fragment Test</h2>

<p> <b> <a href="f1.html" onClick="panel.loadContent(this.href,{id:'content'}); return false">Test One</a> / <a href="f2.html" onClick="panel.loadContent(this.href,{id:'content'}); return false">Test Two</a> </b> </p>

<div id="panel"> <p> Please select something! </p> </div>

<script type="text/javascript"> var panel = new Spry.Widget.HTMLPanel("panel"); </script>

As with the previous example, I've got a menu on top with a section in the middle that will be dynamic, but let's focus on one of the links:

<a href="f1.html" onClick="panel.loadContent(this.href,{id:'content'}); return false">Test One</a>

Note that I have a normal href. Then notice my onclick. First off - the URL for the onclick refers to the same URL defined in the tag itself. A little fancy self-referring which is nice if you ever change the URL. The second argument passed to the loadContent function is an object with one key/value pair. The ID attribute simply means, "Load the remote URL, but just show the stuff inside the content id." Let's look at f1.html:

<html>

<head> <title>F1</title> </head>

<body>

<h2>F1</h2>

<div id="content"> <p> This is the content for fragement page 1. </p> </div>

</body> </html>

As you can see - only one div has the ID of content. Now think about it. With one link you have 2 possible things going on:

  1. If the user doesn't have JavaScript, it loads up f1.html, and they get the complete page.
  2. If the user does have JavaScript, the remote page is loaded, but only the content area is displayed.

So in one simple link you have support for both JS enabled browser and browsers that have JS turned off (or search engines). As I said - darn sexy! You can see this in action here, and I recommend testing it with JS on and off to see it working.

Now one thing you can may not like about this is that even with the JS-enabled clicks, you are loading all the HTML, but it should still be faster for the end user as the browser won't have to load layout UI and stuff like that - just the content it needs. You can get around this easily enough in ColdFusion of course. Have your non-JS link to foo.cfm, and your Spry link to foo.cfm?slim=1, where the existence of the URL parameter tells your layout code to suppress any output.

Lastly - be sure to check out the complete docs for the HTML panel:

HTML Region Overview