Layout

HTML and Layouts

Typically HTML has bottom-up sizing, where a container is as big as it's contents, so that given

/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<div id="outer">
    <div id="inner1">
        Part 1
    </div>
    <div id="inner2">
        Part 2
    </div>
</div>

inner1 is big enough to hold the text "Part 1", inner2 is big enough to hold the text "Part 2", and outer is big enough to hold the divs. And if outer is bigger than the browser's viewport, the browser window displays a scrollbar. The web page you're reading now uses that layout, and unless your monitor is 3 feet tall (in which case, we envy you!) you see the scrollbar on the right.

But for some web pages, you want them to work with the opposite pattern, where you start with a given size, typically the browser viewport, and then partition it into smaller sections. This is the way desktop application look, for example a mail program that has a tree on the left, a list of messages in the upper right, and the message preview on the lower right.

Note that in this scenario, there's no scrollbar on the browser window itself, but if any pane is too small to display all the text it contains then it gets a scrollbar.

[inline:maildemo.png]

Layout like the picture above can be done using tables or fancy CSS (see recent A List Apart article about CSS sizing), but that technique has it's limits... it doesn't allow things like tabs or accordions or split containers where the user can adjust the size of each pane.

Dijit Layout

Dijit has a number of layout widgets which can be combined in a hierarchy to achieve that. Every layout widget contains a list of other layout widgets, except for the "leaf" nodes in the hierarchy, which are typically ContentPanes.

How does this work in practice? You need to think about the application above in a top-down (or outside-in) way:

  1. the screen is split into two parts. The top is a toolbar and
  2. the bottom is split into a left section and right section
  3. the left section has three panes one of which is shown at a time
  4. the right section is split into two parts, a list of messages and a preview pane.

Conceptually it's a set of containers like this:

[inline:layoutblock.png]

There are three types of elements in that picture:

  1. containers that display all their children side by side
  2. containers that display one child at a time
  3. leaf nodes containing content

#1 is either LayoutContainer or SplitContainer. A LayoutContainer is used when all but one of the elements is a constant size. (In this case, the toolbar is a constant size and the the bottom section takes the rest of the screen, so we will use a LayoutContainer for that, and SplitContainers for the other parts.

#2 is AccordionContainer, TabContainer, or StackContainer. They all do basically the same thing, but look different.

#3 is typically ContentPane but could be any widget. An important consideration is whether or not the widget's size is adjustable (like a ContentPane) or not (like a Toolbar). See #1 above.

So keeping those rules in mind and picking which widgets to use it will look like:

  • LayoutContainer
    • Toolbar
    • Horizontal Split Container
      • Accordion Container
        • ContentPane #1
        • ContentPane #2
        • ContentPane #3
      • Vertical Split Container
        • Content Pane #4
        • Content Pane #5

And then from there it's easy to convert to HTML. Starting from the outside:

/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<div dojoType="dijit.layout.LayoutContainer" id="mainDiv">
    <div dojoType="dijit.Toolbar" layoutAlign="top">...</div>
    <div dojoType="dijit.layout.SplitContainer" orientation="horizontal" layoutAlign="client">
    see below
    </div>
</div>

Note that the layoutAlign arguments on the child nodes are actually processed by the parent, but the other arguments are processed by the child. A bit confusing but that's the way it works.

The split container will look like:

/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<div dojoType="dijit.layout.SplitContainer" orientation="horizontal">
    (left part)
    <div dojoType="dijit.layout.AccordionContainer">
        <div dojoType="dijit.layout.AccordionPane" title="Mail">...</div>
        <div dojoType="dijit.layout.AccordionPane" title="News">...</div>
        <div dojoType="dijit.layout.AccordionPane" title="Alerts">...</div>
    </div>
    (right part, see below)
</div>

And on the right... since you want to split the screen vertically the SplitContainer would actually contain another SplitContainer:

/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<div dojoType="dijit.layout.SplitContainer" orientation="horizontal">
    <div dojoType="dijit.layout.AccordionContainer">
        <div dojoType="dijit.layout.AccordionPane" title="Mail">...</div>
        <div dojoType="dijit.layout.AccordionPane" title="News">...</div>
        <div dojoType="dijit.layout.AccordionPane" title="Alerts">...</div>
    </div>
    <div dojoType="dijit.layout.SplitContainer" orientation="vertical">
            <div dojoType="dijit.layout.ContentPane" title="Table">...</div>
        <div dojoType="dijit.layout.ContentPane" title="Preview">...</div>
    </div>

Tips

Sizing to browser viewport: To make the outermost layout widget size to the browser's viewport, in your page CSS you should have: /* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}

html, body, #mainDiv {
    width: 100%; height: 100%;
    border: 0; padding: 0; margin: 0;
 }

where mainDiv is the id of the outermost div.

Note that height=width=100% means different things depending on the browser when you have padding or border, so when using those tags it's best not to have either of those. Put your padding, border, and margin on elements inside the outer layout container.

Restrictions about visibility: none of the layout widgets work if they are inside a hidden element. This is very important and a mistake many people make.

Startup call: when building widgets programmatically, you create the parent first, then add the children, and grandchildren... and finally call startup(). Startup() is called once on the top element in the hierarchy, after the whole hierarchy has been setup and the element inserted.

Accordion Container
In this container, panes are pulled up or down like window blinds by clicking the pane title. Only one shows in full at a time.
[inline:accordion_pane.png]
Border Container (new in 1.1)
Partitions container into top/left/bottom/right/center sections with optional splitter controls so the user can adjust the dimensions. Useful (for example) to reserve the top 100px of the screen for title and navigation, and then the rest of the viewport for the contents. Note how in this case there would be just one scrollbar on the contents, rather than on the browser window itself.
[inline:border_container.png]
Content Pane
the leaves in the hierarchy. Contains arbitrary HTML.
[inline:content_pane.png]
Layout Container (deprecated in 1.1)
Arranges children into top/left/bottom/right/client sections. Useful (for example) to reserve the top 100px of the screen for title and navigation, and then the rest of the viewport for the contents. Note how in this case there would be just one scrollbar on the contents, rather than on the browser window itself.
[inline:layout_container.png]
Split Container (deprecated in 1.1)
Splits the children into sections where user can adjust the size of each section (making one section bigger makes others smaller)
[inline:split_container.png]
Stack Container
base class for TabContainer and AccordionContainer but allowing for user defined display to control which pane is shown
[inline:stack_container.png]
Tab Container
Like tabbed folders in a desk drawer, you click on a title tab to bring the corresponding pane to the front.
[inline:tab_container.png]

AccordionContainer

Like StackContainer and TabContainer, an AccordionContainer holds a set of panes whose titles are all visible, but only one pane's content is visible at a time. Clicking on a pane title slides the currently-displayed one away, similar to a garage door.

Examples

For this example, we'll show the lazy-loading feature of panes. Lazy loading defers the loading process until the pane is actually displayed. Since Dojo does this with XHR, you can only load panes that reside on the server from which the original content came. We'll use a test pane provided with Dijit. You can download this file from the nightly build at http://svn.dojotoolkit.org/dojo/dijit/trunk/tests/layout/tab1.html. For the example to work verbatim, just place it in the same directory as this file on your web server.

Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin ...

More content

  • One
  • Two
  • Three
/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Accordion Demo</title>
    <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
</script>
    <script type="text/javascript">
       dojo.require("dojo.parser");
       dojo.require("dijit.layout.AccordionContainer");
     </script>
</head>
<body class="tundra">
        <div dojoType="dijit.layout.AccordionContainer" duration="200"
                style="margin-right: 30px; width: 400px; height: 300px; overflow: hidden">

                <!-- content inline -->
                <div dojoType="dijit.layout.AccordionPane" selected="true" title="Pane 1">
                        <p >Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin ...</p >
                </div>
       
                <!-- loading by indirect reference -->
                <div dojoType="dijit.layout.AccordionPane" title="Pane 2 (lazy load)"
                     href="/dojoroot/dijit/tests/layout/tab1.html" >

                </div>
       
                <div dojoType="dijit.layout.AccordionPane" title="Pane 3">
                    More content
                    <ul>
                        <li>One</li>
                        <li>Two</li>
                        <li>Three</li>
                    </ul>
                </div>
        </div>
</body>
</html>
dijit.layout.AccordionContainer
Holds a set of AccordionPane widgets and displays the title of every pane, but only one pane is visible at a time. Switching between panes is visualized by sliding the other panes up/down.
Attributes
duration Integer
250
Amount of time (in ms) it takes for panes to slide
Methods
addChild(/*Widget*/ child, /*Integer?*/ insertIndex) Process the given child widget, inserting its dom node as a child of our dom node
back() New for 1.0Select previous page.
closeChild(/*Widget*/ page) Close the given widget, like clicking the X button
forward() New for 1.0Select next page.
Widget[] getChildren() returns array of children widgets
Widget getNextSibling() returns the widget "to the right"
Widget getParent() returns the parent widget of this widget, assuming the parent implements dijit._Container
Widget getPreviousSibling() returns the widget "to the left"
Boolean hasChildren() true if this widget has child widgets
removeChild(/*Widget*/ page) removes the passed widget instance from this widget but does not destroy it
resize(/* Object */ args) Explicitly set this widget size (in pixels), and then call layout() to resize contents (and maybe adjust child widgets). Args is of form {w: int, h: int, l: int, t: int}.
selectChild(/*Widget*/ page) Show the given widget (which must be one of my children)

dijit.layout.AccordionPane
AccordionPane is a ContentPane with a title. Indirect loading with the href property is supported. Nested Dijit layout widgets inside AccordionPane, such as SplitContainer, are not supported at this time.

Accessibility

Keyboard

ActionKey
Navigate to next titleRight or down arrow
Navigate to previous titleLeft or up arrow
Navigate into pageTab
Navigate to next pageCtrl + page down, ctrl + tab (except IE7)
Navigate to previous pageCtrl + page up

BorderContainer (1.1)

New in 1.1

This widget is a container partitioned into up to five regions: left (or leading), right (or trailing), top, and bottom with a mandatory center to fill in any remaining space. Each edge region may have an optional splitter user interface for manual resizing. Note that there can be at most one child marked for each region.

Sizes are specified for the edge regions in pixels or percentage using CSS -- height to top and bottom, width for the sides. You might specify a top region of height:100px and a left region of width:50%. The center typically does not have any dimensions specified in CSS and resizes automatically to fill the remaining space.

BorderContainer operates in a choice of two layout modes: the design attribute may be set to "headline" (by default) or "sidebar". With the "headline" layout, the top and bottom sections extend the entire width of the box and the remaining regions are placed in the middle. With the "sidebar" layout, the side panels take priority, extending the full height of the box.

A simple layout with design="headline": (demo not functional yet)

The Dojo Book
Table of Contents



/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Layout Container Demo 2</title>
    <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.1/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.1/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.1/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
</script>
    <style> 
        /* NOTE: for a full screen layout, must set body size equal to the viewport. */
        html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
    </style>
    <script type="text/javascript">
        dojo.require("dojo.parser");
        dojo.require("dijit.layout.ContentPane");
        dojo.require("dijit.layout.BorderContainer");
     </script>
</head>
<body class="tundra">
<div dojoType="dijit.layout.BorderContainer" design="headline">
   <div dojoType="dijit.layout.ContentPane" region="top" style="background-color:red">
        The Dojo Book
   </div>
   <div dojoType="dijit.layout.ContentPane" region="left"
        style="background-color:lightblue;width: 120px;">

        Table of Contents
    </div>
    <div dojoType="dijit.layout.ContentPane" region="center"
        style="background-color:yellow">

            <blockquote><a href="../node/717">Introduction</a>
                <ol>
                    <li><a href="../node/718">Dojo: What is It?</a></li>
                    <li><a href="../node/719">History</a></li>
                    <li><a href="../node/733">What Dojo Gives You</a></li>
                </ol>
                </blockquote>
    </div>
</div>       
</body></html>

[TODO: sidebar demo]

Splitters can be enabled on any of the regions, except the center, by setting the "splitter" attribute on the child widget to true. "minSize" and "maxSize" attributes on the regions can specify constraints for the splitter in pixels. The "liveSplitters" attribute on the BorderContainer enables behavior where the splitter actively resizes the regions as the user moves the mouse. If set to false, the resize will only occur on mouse up.

[TODO: splitter demo]

The "persist" attribute makes it possible for the widget to remember the splitter positions from one session to the next using cookies.

BiDi considerations

Because this widget is BiDi aware, "leading" or "trailing" terminology may be used to indicate that the layout should be flipped horizontally for right-to-left rendering. "left" and "right" are absolute positions and will be unaffected by text direction.

Accessibility (a11y)

The children of BorderContainer must be listed in their natural tab order.

1.0 Migration Tips

This widget replaces the functionality of LayoutContainer and SplitContainer. The most important things to note when migrating your code from these widgets are:

  • LayoutContainer.layoutAlign attribute corresponds to BorderContainer.region
  • What LayoutContainer called the "client" region, BorderContainer calls "center"
  • There must be at least one child marked as region="center"
  • sizeShare is no longer supported. Specify the pane sizes using CSS instead as pixels or percentages.

Unlike LayoutContainer, BorderContainer does not allow for multiple widgets to be placed in a given position (e.g. inner left and outer left, patterned after Delphi) In order to achieve this, nested BorderContainers must be used.

Also, while you can specify sizes in percentages, these are only initial sizes, so setting left and right to 33% will split the children across into thirds, but resizing will allow the center to grow or shrink while the sizes remain fixed. There currently is no widget to provide equal layout, although HTML Tables may serve this purpose.

Resizing and Layouts

Involved Mixins

Your widget will have to have dijit._Contained mixed in, and dijit._Container if you plan to put other widgets inside of it. Being a container means that the getChildren function will be available to you for use when passing down the resize events.

How Layout Widgets Communicate

A container will call the resize function on its contained widgets (that should also be its direct children to avoid ambiguous layout). They might pass a size object, and the conditions in which they will are outlined below.

2 Modes of Positioning

In many browsers, an easy method of making a block node fill up the entire area of its parent container (parent container referring to any node positioned using the relative or absolution value) is to position it absolutely, and set its top, right, bottom, and left positions to 0. This isn't true for all browsers or all nodes. Because of this, it can be confusing knowing how your resize function should work.

The resize Function

If you receive a size object (which has t, l, w, and h properties representing top, left, width, and height) then it probably means that your layout has encountered a situation in which CSS is no longer capable of handling positioning. What this means is that you'll have to alter this object according to the unique properties (most likely padding and offsets) before passing the value to contained widgets. You'll also use this object to size the widget's node using either dojo.marginBox as a setter, or setting the style properties directly.

If you don't receive a size object, it probably means that you can make adjustments using only CSS. For example, if you change the style attribute top in this situation, the height automatically changes, while in non-CSS mode, you would probably end up pushing your node down, without its height changing.

ContentPane

A Content Pane is the most basic layout tile. Conceptually, it's like the content boxes in portals like MyYahoo. A content pane resembles an iframe, but contains extra design features, fits in with the current theme, and renders widgets properly.

You can use content panes by themselves, but usually you will place content panes inside of a layout container. For example, in a tabbed layout, content pane tags surround each tab of information.

Examples

Simple content panes have their content inside the tags Most of the time, these simple panes are used inside layout containers, so the examples in LayoutContainer, StackContainer and TabContainer illustrate their use.

Linked content panes, those with their content in a separate URL, are useful even without containers. To illustrate, we'll use the example data store countries.txt, which you can download below (after this page text, and right above the navigation bars). For the example to work verbatim, just place it in the same directory as these files on your web server. If the following is linked_content_pane.html:

/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<!-- Note, you don't have to include Dojo scripts, CSS, or other things here ... -->
<div dojoType="dojo.data.ItemFileReadStore" jsId="continentStore"
        url="countries.txt">
</div>
<div dojoType="dijit.Tree" id="mytree" store="continentStore" query="{type:'continent'}"
        labelAttr="name" typeAttr="type">
</div>

You can include it within a page like this. Because the tree may take a long time to load, we display a loading message for the user.

This text be replaced with the tree
/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Linked Content Pane Demo</title>
    <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
</script>
        <script type="text/javascript">
        dojo.require("dojo.parser");
                dojo.require("dijit.layout.ContentPane");
                dojo.require("dijit.Tree");
                dojo.require("dojo.data.ItemFileReadStore");
     </script>
</head>
<body class="tundra">
        <div preload="true" dojoType="dijit.layout.ContentPane" href="linked_content_pane.html">
                This text be replaced with the tree
        </div>
</body></html>

Note here that the dojo.require for the tree is placed in the calling html. SCRIPT tags of type "text/Javascript" in the included html file are ignored. However SCRIPT tags with type dojo/method and dojo/connect work fine. See Understanding the Parser for details.

Like all Dijit components, you can create a ContentPane dynamically. The following example adds a new ContentPane to an existing Tab Container.

/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Content Pane Programmatic Demo</title>
    <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
</script>
        <script type="text/javascript">
                dojo.require("dijit.layout.ContentPane");
                dojo.require("dijit.layout.TabContainer");
                dojo.require("dijit.Tree");
                dojo.require("dojo.data.ItemFileReadStore");
               
                dojo.addOnLoad(function() {
                        // create a ContentPane
                        var newChild =
                                new dijit.layout.ContentPane({
                                                href:'linked_content_pane.html',
                                                title:'newChild',
                                                refreshOnShow:true
                                        },
                                        dojo.doc.createElement('div')
                                );
                       
                        // find my tabContainer and add our new ContentPane
                        dijit.byId('myTabContainer').addChild(newChild);
                       
                        // find parent Container and subscribe to selectChild event
                        // without it refreshOnShow and href load wont work.
                        newChild.startup();          
                });
     </script>
</head>
<body class="tundra">
        <div id="myTabContainer" dojoType="dijit.layout.TabContainer"
                 style="width:500px;height:300px">
</div>
</body></html>

NOTE! You must include a sourcenode when creating a ContentPane. You must call .startup() after you have addChild() it to your parent

dijit.layout.ContentPane
A widget that acts as an all-purpose sizable pane without navigation, and includes a ajax interface
Attributes
errorMessage String
Locale dep.
Message that shows if an error occurs
extractContent Boolean
false
Extract visible content from inside of <body> .... </body>
href String The href of the content that displays now. Set this at construction if you want to load data externally when the pane is shown. (Set preload=true to load it immediately.) Changing href after creation does not have any effect; see setHref();
isLoaded Boolean
false
Tells loading status see onLoad|onUnload for event hooks
loadingMessage String
Locale dep.
Message that shows while downloading
parseOnLoad Boolean
true
parse content and create the widgets, if any
preload Boolean
false
Force load of data even if pane is hidden.
preventCache Boolean
false
Cache content retreived externally
refreshOnShow Boolean
false
Refresh (re-download) content when pane goes from hidden to shown
Methods
cancel() Cancels a inflight download of content
refresh() Force a refresh (re-download) of content, be sure to turn off cache we return result of _prepareLoad here to avoid code dup. in dojox.layout.ContentPane
resize(/* String */size Explicitly set this widget size (in pixels), and then call layout() to resize contents (and maybe adjust child widgets)
setContent(/*String|DomNode|Nodelist*/data) Replaces old content with data content, include style classes from old content
setHref(/*String|Uri*/ href) Reset the (external defined) content of this pane and replace with new url Note: It delays the download until widget is shown if preload is false
Extension Points
onContentError(/*Error*/ error) called on DOM faults, require fault etc in content default is to display errormessage inside pane
onDownloadEnd() called when download is finished
onDownloadError(/*Error*/ error) Called when download error occurs, default is to display errormessage inside pane. Overide function to change that. The string returned by this function will be the html that tells the user a error happend
onDownloadStart() called before download starts the string returned by this function will be the html that tells the user we are loading something override with your own function if you want to change text
onLoad(/* Event */e) Event hook, is called after everything is loaded and widgetified
onUnload(/* Event */e) Event hook, is called before old content is cleared

Accessibility - updated for 1.0

General Issues

The developer is responsible for determining if the ContentPane should be in the tab order of the page or not. If the ContentPane is not likely to have a focusable item within the contents, the developer may want to add tabindex=""0" onto the ContentPane element. This will put the ContentPane into the tab order so if someone is using the tab key to navigate through the elements on the page, the ContentPane itself will get focus. Having focus go to the ContentPane itself can be helpful for users of assistive technology to be able to navigate to an area that may not have any focusable elements within it such as a preview pane for mail messages or a page footer containing important information.

LayoutContainer

Similar to a layout pane in Java AWT and Delphi, a LayoutContainer is a box with a specified size (like style="width: 500px; height: 500px;"), that contains children widgets marked with "layoutAlign" of "left", "right", "bottom", "top", and "client". It takes it's children marked as left/top/bottom/right, and lays them out along the edges of the box, and then it takes the child marked "client" and puts it into the remaining space in the middle.

Left/right positioning is similar to CSS's "float: left" and "float: right", and top/bottom positioning would be similar to "float: top" and "float: bottom", if there were such CSS.

Note that there can only be one client element, but there can be multiple left, right, top, or bottom elements.

Examples

A Layout Container easily formats a table of contents:

The Dojo Book
Table of Contents



/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Layout Container Demo 2</title>
    <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
</script>
    <style> 
        /* NOTE: for a full screen layout, must set body size equal to the viewport. */
        html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
    </style>
    <script type="text/javascript">
        dojo.require("dojo.parser");
        dojo.require("dijit.layout.ContentPane");
        dojo.require("dijit.layout.LayoutContainer");
     </script>
</head>
<body class="tundra">
<div dojoType="dijit.layout.LayoutContainer" style="width: 100%; height: 100%; padding: 0; margin: 0; border: 0;">
   <div dojoType="dijit.layout.ContentPane" layoutAlign="top" style="background-color:red">
        The Dojo Book
   </div>
   <div dojoType="dijit.layout.ContentPane" layoutAlign="left"
        style="background-color:lightblue;width: 120px;">

        Table of Contents
    </div>
    <div dojoType="dijit.layout.ContentPane" layoutAlign="client"
        style="background-color:yellow">

            <blockquote><a href="../node/717">Introduction</a>
                <ol>
                    <li><a href="../node/718">Dojo: What is It?</a></li>
                    <li><a href="../node/719">History</a></li>
                    <li><a href="../node/733">What Dojo Gives You</a></li>
                </ol>
                </blockquote>
    </div>
</div>       
</body></html>

To change the drawing order:

The LayoutContainer goes through the children as specified, and each child is laid out into the "remaining space", where "remaining space" is initially the content area of this widget, but is reduced to a smaller rectangle each time a child is added. So, changing the order of the children will change how they are laid out.

Table of Contents
The Dojo Book
/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Layout Container Demo 2</title>
    <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
</script>
     <style> 
        /* NOTE: for a full screen layout, must set body size equal to the viewport. */
        html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
    </style>
    <script type="text/javascript">
       dojo.require("dojo.parser");
       dojo.require("dijit.layout.ContentPane");
       dojo.require("dijit.layout.LayoutContainer");
     </script>
</head>
<body class="tundra">
<div dojoType="dijit.layout.LayoutContainer" style="width: 100%; height: 100%; padding: 0; margin: 0; border: 0;">
   <div dojoType="dijit.layout.ContentPane" layoutAlign="left"
        style="background-color:lightblue;width: 120px;">

        Table of Contents
    </div>
   <div dojoType="dijit.layout.ContentPane" layoutAlign="top" style="background-color:red">
        The Dojo Book
   </div>
    <div dojoType="dijit.layout.ContentPane" layoutAlign="client"
        style="background-color:yellow">

            <blockquote><a href="../node/717">Introduction</a>
                <ol>
                    <li><a href="../node/718">Dojo: What is It?</a></li>
                    <li><a href="../node/719">History</a></li>
                    <li><a href="../node/733">What Dojo Gives You</a></li>
                </ol>
                </blockquote>
    </div>
</div>       
</body></html>
dijit.layout.LayoutContainer
Provides Delphi-style panel layout semantics.
Methods
addChild(/*Widget*/ child, /*Integer?*/ insertIndex) Process the given child widget, inserting its dom node as a child of our dom node
Widget[] getChildren() returns array of children widgets
Widget getParent() returns the parent widget of this widget, assuming the parent implements dijit._Container
removeChild(/*Widget*/ page) removes the passed widget instance from this widget but does not destroy it
resize(/* Object */ args) Explicitly set this widget size (in pixels), and then call layout() to resize contents (and maybe adjust child widgets). Args is of form {w: int, h: int, l: int, t: int}.

SplitContainer

Contains multiple children widgets, all of which are displayed side by side (either horizontally or vertically); there's a bar between each of the children, and you can adjust the relative size of each child by dragging the bars. You must specify a size (width and height) for the SplitContainer.

Example

/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>SplitContainer Demo</title>
    <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
</script>
    <script type="text/javascript">
       dojo.require("dojo.parser");
       dojo.require("dijit.layout.SplitContainer");
       dojo.require("dijit.layout.ContentPane");
     </script>
</head>
<body class="tundra">
        <div dojoType="dijit.layout.SplitContainer"
                orientation="horizontal"
                sizerWidth="7"
                activeSizing="true"
                style="border: 1px solid #bfbfbf; width: 400px; height: 300px;">

                <div dojoType="dijit.layout.ContentPane" sizeMin="20" sizeShare="20">
                    <b>The Dojo Toolkit</b>
                    
                        Dojo is an Open Source DHTML toolkit written in JavaScript. It
                        builds on several contributed code bases (nWidgets, Burstlib, f(m)),
                        which is
                        why we refer to it sometimes as a "unified" toolkit. Dojo aims to
                        solve some long-standing historical problems with DHTML which
                        prevented mass adoption of dynamic web application development.
                       
                </div>
                <div dojoType="dijit.layout.ContentPane" sizeMin="50" sizeShare="50">
                    <b>Swedish Chef Translation</b>
                    
                        Duju is un Oopee Suoorce-a DHTML tuulkeet vreettee in JefeScreept.
                        Um de hur de hur de hur. It booeelds oon seferel cuntreebooted
                        cude-a beses (nVeedgets, Boorstleeb, f(m)),
                        vheech is vhy ve-a reffer tu it sumeteemes es
                        a "uneeffied" tuulkeet. Um de hur de hur de hur.
                        Duju eeems tu sulfe-a sume-a lung-stundeeng heesturicel
                        prublems veet DHTML vheech prefented mess edupshun
                        ooff dynemeec veb eppleeceshun defelupment. Um de hur de
                        hur de hur.
                       
                </div>
        </div>
</body></html>
dijit.layout.SplitContainer
Container with resizable dividers.
Attributes
activeSizing Boolean
false
If true, the children's size changes as you drag the bar; otherwise, the sizes don't change until you drop the bar (by mouse-up)
orientation String
horizontal
either 'horizontal' or vertical; indicates whether the children are arranged side-by-side or up/down.
persist Boolean
true
Save splitter positions in a cookie
sizerWidth Integer
7
Size in pixels of the bar between each child
Methods
addChild(/*Widget*/ child, /*Integer?*/ insertIndex) Process the given child widget, inserting its dom node as a child of our dom node
Widget[] getChildren() returns array of children widgets
Widget getParent() returns the parent widget of this widget, assuming the parent implements dijit._Container
removeChild(/*Widget*/ page) removes the passed widget instance from this widget but does not destroy it
resize(/* Object */ args) Explicitly set this widget size (in pixels), and then call layout() to resize contents (and maybe adjust child widgets). Args is of form {w: int, h: int, l: int, t: int}.

Sizing

sizeShare

Setting the sizeShare attribute on any child widgets of a SplitContainer sets the initial relative size of that widget, either its height or width depending on the layout of the SplitContainer. The value of sizeShare is not a percentage or a pixel measure. Its value is relative to other child widgets of the same SplitContainer. So, for example, given four child widgets and each having a sizeShare attribute of 25, would evenly divide the SplitContainer into four parts. However, giving each a sizeShare attribute of 10 or 1 would achieve the same result, as the values are computed relative to each other - they do not have to add up to 100.

sizeMin

Setting the sizeMin attribute on any child widget of a SplitContainer defines the smallest size, in pixels, that the child widget will be changed to. The value is specified as an integer, without "px" appended to it.

Accessibility (added for 1.0)

Keyboard

In Dojo 1.0 there is no keyboard mechanism to resize the split container. In Firefox the content panes within a split container will be in the tab order (this is default FF behavior) so if the data is not visible, the user can use the arrow keys to scroll the data into view. This allows keyboard access to all of the data and thus accessibility requirements are met by default in Firefox. IE does not include the content pane in the tab order. If there is a chance that all of the data will not being visible within a pane of a split container, a tabindex=0 should be included in the markup of the inner content pane to ensure keyboard accessibility in both Firefox and IE.

StackContainer

A container that has multiple children, but shows only one child at a time (like looking at the pages in a book one by one). This container is good for wizards, slide shows, and long lists or text blocks.

Examples

Here's a freely pageable document.

This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below.

As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below.

You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.

/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Stack Container Demo</title>
    <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
</script>
    <script type="text/javascript">
        dojo.require("dojo.parser");
        dojo.require("dijit.layout.ContentPane");
        dojo.require("dijit.layout.StackContainer");
        dojo.require("dijit.form.Button");
     </script>
</head>
<body class="tundra">
        <button id="previous" onClick="dijit.byId('mainTabContainer').back()"><</button>
        <button id="next" onClick="dijit.byId('mainTabContainer').forward()">></button>
        <div id="mainTabContainer" dojoType="dijit.layout.StackContainer"
             style="width: 90%; border:1px solid #9b9b9b; height: 20em;
                         margin: 0.5em 0 0.5em 0; padding: 0.5em;"
>

        <p id="Page1" dojoType="dijit.layout.ContentPane" label="Intro">
                This version of the GNU Lesser General Public License incorporates
                the terms and conditions of version 3 of the GNU General Public
                License, supplemented by the additional permissions listed below.
       
        <p id="Page2" dojoType="dijit.layout.ContentPane">
                As used herein, "this License" refers to version 3 of the GNU Lesser
                General Public License, and the "GNU GPL" refers to version 3 of the GNU
                General Public License. "The Library" refers to a covered work governed by
                this License, other than an Application or a Combined Work as defined below.
       
        <p id="Page3" dojoType="dijit.layout.ContentPane" >
                You may convey a covered work under sections 3 and 4 of this License
                without being bound by section 3 of the GNU GPL.
       
   </div>
</body></html>

Indication of the current child

As standard, there are no styles on the buttons associated with the StackContainer to indicate which child is currently being shown. However, Dijit adds a "dijitToggleButtonChecked" class to the button for the child being shown and we can use this class to provide styling ourselves. For example, we could use the following rules to highlight the button with a white background and, in Windows high contrast mode, a dashed border:
.dijitStackController .dijitToggleButtonChecked button {
    background-color: white;
    background-image: none;
}
.dijit_a11y .dijitStackController .dijitToggleButtonChecked button {
    border-style: dashed !important;
}
dijit.layout.StackContainer
A container of panes, one of which is always on top. Developer must provide navigation controls.
Attributes
doLayout Boolean
true
if true, change the size of my currently displayed child to match my size
Methods
addChild(/*Widget*/ child, /*Integer?*/ insertIndex) Process the given child widget, inserting its dom node as a child of our dom node
back() New for 1.0Select previous page.
forward() New for 1.0Select next page.
Widget[] getChildren() returns array of children widgets
Widget getNextSibling() returns the widget "to the right"
Widget getParent() returns the parent widget of this widget, assuming the parent implements dijit._Container
Widget getPreviousSibling() returns the widget "to the left"
removeChild(/*Widget*/ page) removes the passed widget instance from this widget but does not destroy it
resize(/* Object */ args) Explicitly set this widget size (in pixels), and then call layout() to resize contents (and maybe adjust child widgets). Args is of form {w: int, h: int, l: int, t: int}.
selectChild(/*Widget*/ page) Show the given widget (which must be one of my children)

Accessibility

Keyboard

ActionKey
Navigate to next tab buttonRight arrow
Navigate to previous tab buttonLeft arrow
Navigate into pageTab
Navigate to next pageCtrl + page down, ctrl + tab (except IE7)
Navigate to previous pageCtrl + page up
Delete a tabDelete, ctrl + w (updated for 1.0 - delete is not supported in stack container)

TabContainer

A TabContainer is a container that has multiple panes, but shows only one pane at a time. There are a set of tabs corresponding to each pane, where each tab has the title (aka label) of the pane, and optionally a close button.

Examples

Here's a Grimm set of tabs, indeed.

Once upon a time there was a dear little girl who was loved by every one who looked at her, but most of all by her grandmother, and there was nothing that she would not have given to the child.
Hard by a great forest dwelt a poor wood-cutter with his wife and his two children. The boy was called Hansel and the girl Gretel. He had little to bite and to break, and once when great dearth fell on the land, he could no longer procure even daily bread.
There was once upon a time a hermit who lived in a forest at the foot of a mountain, and passed his time in prayer and good works, and every evening he carried, to the glory of God, two pails of water up the mountain.
/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */ .geshifilter {font-family: monospace;} .geshifilter .imp {font-weight: bold; color: red;} .geshifilter .kw1 {color: #b1b100;} .geshifilter .kw2 {color: #000000; font-weight: bold;} .geshifilter .kw3 {color: #000066;} .geshifilter .coMULTI {color: #808080; font-style: italic;} .geshifilter .es0 {color: #000099; font-weight: bold;} .geshifilter .br0 {color: #66cc66;} .geshifilter .st0 {color: #ff0000;} .geshifilter .nu0 {color: #cc66cc;} .geshifilter .sc0 {color: #00bbdd;} .geshifilter .sc1 {color: #ddbb00;} .geshifilter .sc2 {color: #009900;}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>TabContainer Demo</title>
    <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
    </style>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
        djConfig="parseOnLoad: true">
</script>
    <script type="text/javascript">
       dojo.require("dojo.parser");
           dojo.require("dijit.layout.ContentPane");
           dojo.require("dijit.layout.TabContainer");
           dojo.require("dijit.form.Button");
     </script>
</head>
<body class="tundra">
   <div id="mainTabContainer" dojoType="dijit.layout.TabContainer"
        style="width:500px;height:100px">