Sunday, July 4, 2010

Easy Web Application Layout with Dojo

Whenever you are writing software, you want to spend most of your time working on the business logic of your application. That is to say, you need to put the work into what makes your application special. I've found that when making web applications, too much wasted time can easily be spent trying to get the layout correct. That's why I love The Dojo Toolkit.

Using Dojo's BorderContainer to do your layout is extremely simple and saves countless hours that you could waste doing it yourself. Let's look at the steps involved.

First, set things up. BorderContainer is actually part of the Dijit Widgets subset of the Dojo Toolkit. The first step in using any of these things is to download and set up Dojo on your web server. See the Dojo website for information on how to do that.

Once you have the Dojo scripts available to use in your pages, consider this simple example.

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<link rel="stylesheet" type="text/css" href="/dijit/themes/tundra/tundra.css" />
<script type="text/javascript" src="/dojo/dojo.js" djConfig="parseOnLoad: true"></script>
<script type="text/javascript">

dojo.require("dijit.layout.BorderContainer");
dojo.require("dijit.layout.ContentPane");

</script>
</head>

<body class="tundra">

<div dojoType="dijit.layout.BorderContainer" design="sidebar" style="width: 100%; height: 100%;">

<div style="background-color: #FF66FF;" dojoType="dijit.layout.ContentPane" region="top">This is the top pane.</div>

<div style="background-color: #66FFCC;" dojoType="dijit.layout.ContentPane" region="center">This is the center pane.</div>

</div>

</body>

</html>
So what exactly is going on here? Well first, you can see the CSS include. This is just one of the styles that comes with Dojo. You can change this if you want.

Second, you'll notice the script reference for dojo.js. This is the main Dojo library. Every page that uses a Dojo function or widget needs this. The interesting part of the script tag is the djConfig attribute. Since we use inline specification for the widgets (the dojoType attributes on the divs) we want that set to parse on load.

Third, there's the dojo.require stuff. Dojo has a great dynamic feature-set loading capability. Instead of having to explicitly add a script tag for every feature you want to use, you just "require" the stuff you'll be working with on this page. We want to use the BorderContainer and ContentPane, so we have the require lines for them here.

Now we're into the real layout of the page. The outermost div has a dojoType attribute of "dijit.layout.BorderContainer", which basically means that this div is going to be the border container object. When Dojo loads completely, it will parse the HTML of the page and transform this simple div into a complex and awesome layout container for you. Notice also the design attribute. When set to "sidebar" the left and right panes will stretch from the top of the window to the bottom. The other option is "headline", which is the default if no design attribute is specified. In headline mode, the top and bottom panes stretch the entire width of the window and the left and right panes are the same height as the center pane. The style attribute sets the width and height of the container to basically take up the whole window.

Inside the main div, we put the divs that will hold our content. They have the dojoType "dijit.layout.ContentPane" and have a region attribute that specifies where they fit in the container. Content Panes are quite simply just panes for your content. They can contain any HTML or text that you would normally put in a div.

The top pane has the region attribute set to "top". This div can also have a style tag if you want to specify a height for the pane. The center pane has the region attribute set to "center" and should not ever have a width or height specified. It's size will be automatically calculated to fit all the space remaining after every other pane is given its size.

You can see the page in action here.

Hey hold on a minute! In the text above I just had "This is the center pane." as the text for the main pane, but in the example it had a bunch of cool gibberish text. What's going on? Well, the gibberish text is Lorem Ipsum. You've probably seen it in lots of places. We use it so show how something will look with text in it when we don't want the reader to be distracted by what the text says. You can generate your own at this website! I didn't include it in the example code above to save space and to not distract from the code.

The longer text also allows demonstration of how the center pane will have scroll bars automatically appear if the content is too large for the pane.

Now let's make our layout a little more complex by adding side panes.

Place this code inside the border container div, before the top pane:

<div style="background-color: #99FF66;" dojoType="dijit.layout.ContentPane" region="left">This is the left pane.</div>

That will be the left pane. Place this code as the last thing inside the border container div:

<div style="background-color: #FF9966;" dojoType="dijit.layout.ContentPane" region="right">This is the right pane.</div>

Look here to see what we have now.

Pretty easy, huh? Now remember I said earlier that you can specify sizes for any pane except the center. You just use standard CSS styles to do that, and you can use either percentages or pixels. Let's give it a try, and add a bottom pane as well.

Add this code before the div for the right pane. This will be the bottom pane. Notice that it specifies a height of 300 pixels. The middle panes (top, center, and bottom) will have their widths automatically sized so only heights make sense for top and bottom.

<div style="height: 300px; background-color: #66CCFF;" dojoType="dijit.layout.ContentPane" region="bottom">This is the bottom pane.</div>

Change the style attribute on the left and right panes to include "width: 25%". This means that the side panes will take up a combined 50% of the window width, leaving 50% for the top, center, and bottom panes. Resize the window to see the sizes of all the panes change. The left pane should now read like this:

<div style="width: 25%; background-color: #99FF66;" dojoType="dijit.layout.ContentPane" region="left">This is the left pane.</div>

and the right pane should look like this:

<div style="width: 25%; background-color: #FF9966;" dojoType="dijit.layout.ContentPane" region="right">This is the right pane.</div>

Check out the changes here.

But wait, it gets even better! You don't have to make your border container the size of the whole window. You can specify any width and height you want, but more importantly you can nest border containers inside other border containers!

Let's try it by replacing the text in the bottom pane with another border container, itself with left, right, top, and center panes. Replace the text "This is the bottom pane" with the following code:

<div dojoType="dijit.layout.BorderContainer" design="sidebar" style="width: 100%; height: 100%;">

<div style="width: 25%; background-color: #99FF66;" dojoType="dijit.layout.ContentPane" region="left">This is the left pane.</div>

<div style="background-color: #FF66FF;" dojoType="dijit.layout.ContentPane" region="top">This is the top pane.</div>

<div style="background-color: #66FFCC;" dojoType="dijit.layout.ContentPane" region="center">This is the center pane.</div>

<div style="width: 25%; background-color: #FF9966;" dojoType="dijit.layout.ContentPane" region="right">This is the right pane.</div>

</div>

Now have a look at the finished product.

As you can see, doing web application layout can be insanely easy with the help of Dojo. If you want more information on Border Container or any of the other Dojo tools, check out the online documentation here.