Layout

Introduction

There are two philosophies to laying out the screen. One way, the "web-way", says that everything should flow naturally from HTML, meaning basically that a bunch of stuff is in the document and if your window isn't big enough, then you use the browser's scrollbar. This is the way traditional web pages work, and is the best choice for many applications.

There other philosophy is to take the available size of the viewport (basically, the browser window), and then to partition it into smaller and smaller pieces. If you think about a mail application that splits the screen into top/left/right sections, then you are thinking about this kind of design.

The Layout Widgets

Dojo provides a number of widgets for implementing the second design listed above. They fall into two basic categories.

Widgets that split the screen space between a set of widgets

  • LayoutContainer- lets you position the children into top/left/bottom/right positions, with the specified center piece taking all the remaining space
  • SplitContainer- shows children either horizontally or vertically aligned, and you can adjust the relative size of each child by moving the divider bars between the widgets

Widgets that hold mulitple children but only display one at a time:

  • TabContainer - names of children are printed as tab labels
  • AccordionContainer - stacks children vertically, and you can show one at a time
  • WizardContainer - go through the children in an ordered fashion like a wizard

In addition, there's one widget that isn't a layout widget per se, but it is often used with the layout widgets:

  • ContentPane - like a div, but it's a widget, and it can load its contents from a specified href.

These widgets can be nested to arbitrary levels, so that you could have a LayoutContainer with a top/bottom/client section, where the client section is a SplitContainer, and that SplitContainer could contain a TabContainer, which would itself contain a LayoutContainer, and so on.

The leaf nodes of this hierarchy could be any non-layout node, but often are ContentPane nodes.

Example

Example (currently not displaying correctly. wiki needs upgrade?!):

<DIV> <DIV>hello world </DIV> <DIV> <DIV>left side of split </DIV> <DIV> <DIV>second tab </DIV> <DIV>i'm on the bottom </DIV> </DIV>
<DIV dojoType="LayoutContainer" >
	<DIV dojoType="ContentPane"> hello world </DIV>
	<DIV dojoType="SplitContainer">
		<DIV dojoType="ContentPane"> left side of split </DIV>
		<DIV dojoType="TabContainer">
			<div dojoType="LayoutContainer">
			 ..
			</DIV>
			<DIV dojoType="ContentPane"> second tab </DIV>
		 </DIV>
	  </DIV>
	 <DIV dojoType="ContentPane"> i'm on the bottom </DIV>
</div>

Note that all these objects are called containers because they just contain a set of other objects; they don't contain mixed content (text and nodes) like a normal <DIV>.

Also note that there is no "LayoutContainerChild" or "SplitPaneContainerChild" like node. That's to reduce the amount of markup and code required to setup a deep hierarchy of layout widgets.

Parameters

Note that the example above is missing some important parameters. For one thing, it doesn't specify whether the SplitContainer arranges its children vertically or horizontally. For that we need:

    <DIV dojoType="SplitContainer" orientation="horizontal">

We are also missing the labels for each of the tabs in the TabContainer, which we can add like this:
    <DIV dojoType="TabContainer">
      <DIV dojoType="LayoutContainer" label="Tab 1">
       ..
      </DIV>
      <DIV dojoType="ContentPane" label="Tab 2"> second tab </DIV>
    </DIV></DIV>

Note that the labels are specified as parameters to the ContentPane and LayoutContainer, the children of the TabContainer, rather than as arguments to the TabContainer itself. "label" is not technically a property on those two objects, but you can still specify it,and the TabContainer will pick it up.

Similarly, for a LayoutContainer, you need to say where each child should be located:

	<DIV dojoType="LayoutContainer">
	<DIV dojoType="ContentPane" layoutAlign="top"> hello world </DIV>
	<DIV dojoType="SplitContainer" layoutAlign="client">...</DIV>
	<DIV dojoType="ContentPane" layoutAlign="bottom"> i'm on the bottom </DIV>
	</DIV>

You may freely mix sides (top, bottom, left, right) in a layout container. Sides are used from the outside in. The special side name "client" will fill in any part of the container that is not otherwise occupied. Very often you will use fixed-size side panes and a client pane that grows and shrinks as the user resizes the window, for example:

<DIV style="OVERFLOW: hidden; WIDTH: 100%; HEIGHT: 100%" dojoType="LayoutContainer">

  <DIV dojoType="ContentPane" layoutAlign="top" height="2em">

    Page header goes here; it stretches across the whole width of the window.

  </DIV>

  <DIV dojoType="ContentPane" layoutAlign="bottom" height="1em">

    And a footer here, also stretching across the whole width.

  </DIV>

  <DIV style="WIDTH: 120px" dojoType="ContentPane" layoutAlign="left">

    Some left-side navigation HTML, bounded by the header and footer

    since they were already added to the layout.

  </DIV>

  <DIV style="WIDTH: 60px" dojoType="ContentPane" layoutAlign="right">

    Some right-side navigation HTML

  </DIV>

  <DIV dojoType="ContentPane" layoutAlign="client">

    Main page body here, bounded by all the fixed-size elements above.

  </DIV>

</DIV>

Sizing

For the top level layout container in a hierarchy, you need to specify a size. If you don't, the contents of the container may be displayed oddly or not at all.

<DIV style="WIDTH: 500px; HEIGHT: 500px" dojoType="LayoutContainer"></DIV>

Many web applications will want to fill the whole screen with their top level layout container. Think of a case like a mail application. For any size browser window, you want the top part to have some menu choices, and then have the bottom part be split between a tree on the left and message list/message on the right.

In this case, you need CSS like this:

html, body, #mainWindow {

 width: 100%;

 height: 100%;

 overflow: hidden;

}

And then inside your tag you will have something like:

<DIV id=mainWindow dojoType="LayoutContainer"></DIV>

Programmatic creation

Creating a hierarchy of layout widgets programatically works the same way as normal programatic creation, except that sizing info needs to be specified in a special way.

// make a dummy div just to specify size

var div = document.createElement("div");
with(div.style){ height="500px"; width="500px"; }

// create the layout container
var lc = dojo.widget.createWidget("LayoutContainer", null, div);

// add some children for top, bottom, and center.  Top and Bottom
// children also need to have a size specified, and possibly a scrollbar
var topDiv = document.createElement("div");
with(topDiv.style){ height="30px"; overflow="auto"; }
lc.addChild( dojo.widget.createWidget("ContentPane", { href: "foo/bar.html", layoutAlign: "top" }, topDiv) );
var bottomDiv = document.createElement("div");
with(bottomDiv.style){ height="30px"; overflow="auto"; }
lc.addChild( dojo.widget.createWidget("ContentPane", { href: "foo/bar.html", layoutAlign: "bottom" }, bottomDiv) );

One other thing to note in this example is that each ContentPane has two parameters. The href parameter applies to the ContentPane itself, but the layoutAlign parameter is really something that the LayoutContainer processes.

Doing your own positioning

You also have the option to lay stuff out on the screen like LayoutContainer does, but without using LayoutContainer. There's a function called dojo.html.layout() that will position a bunch of elements just like LayoutContainer does. (Actually LayoutContainer calls this function.)