The layout tutorials for dojo that I’ve seen all seem to fall into two categories:
- Markup-based: adding dojoType properties to HTML elements in the markup
- Programmatic: creating HTML elements in JavaScript
When using a toolkit such as dojo for layout rather than standard CSS, my preference would be to keep the dojo layout stuff entirely in JavaScript, separate from the markup, whilst still using HTML to describe my content. This allows an easy transition to/from dojo and CSS layout techniques, doesn’t clutter the markup with dojo specific stuff that would only be needed when JavaScript is enabled, and just provides a cleaner separation. I was sure this must be possible in dojo and it is; it just doesn’t seem to be well documented anywhere.
After playing for a while (and with quite a bit of help from James), I turned this…
<script type="text/javascript">
dojo.require("dijit.layout.BorderContainer");
dojo.require("dijit.layout.TabContainer");
dojo.require("dijit.layout.AccordionContainer");
dojo.require("dijit.layout.ContentPane");
</script>
<div dojoType="dijit.layout.BorderContainer"
style="width: 100%; height: 100%;">
<div dojoType="dijit.layout.ContentPane" region="top">
Top pane
</div>
<div dojoType="dijit.layout.AccordionContainer" region="leading">
<div dojoType="dijit.layout.AccordionPane" title="pane #1">
accordion pane #1
</div>
<div dojoType="dijit.layout.AccordionPane" title="pane #2">
accordion pane #2
</div>
<div dojoType="dijit.layout.AccordionPane" title="pane #3">
accordion pane #3
</div>
</div>
<div dojoType="dijit.layout.TabContainer" region="center">
<div dojoType="dijit.layout.ContentPane" title="tab #1">
tab pane #1
</div>
<div dojoType="dijit.layout.ContentPane" title="tab #2">
tab pane #2
</div>
<div dojoType="dijit.layout.ContentPane" title="tab #3">
tab pane #3
</div>
</div>
<div dojoType="dijit.layout.ContentPane" region="trailing">
Trailing pane
</div>
<div dojoType="dijit.layout.ContentPane" region="bottom">
Bottom pane
</div>
</div>
<style type="text/css">
html, body {
width: 100%;
height: 100%;
margin: 0;
}
</style>
…into this…
<script type="text/javascript">
dojo.require("dijit.layout.BorderContainer");
dojo.require("dijit.layout.TabContainer");
dojo.require("dijit.layout.AccordionContainer");
dojo.require("dijit.layout.ContentPane");
dojo.ready(function () {
var mainContainer = new dijit.layout.BorderContainer(
{}, 'mainContainer');
var topPane = new dijit.layout.ContentPane(
{'region': 'top'}, 'topPane');
mainContainer.addChild(topPane);
var leftPane = new dijit.layout.AccordionContainer(
{'region': 'leading'}, 'leftPane');
var accordionPane1 = new dijit.layout.AccordionPane(
{'title': 'pane #1'}, 'accordionPane1');
var accordionPane2 = new dijit.layout.AccordionPane(
{'title': 'pane #2'}, 'accordionPane2');
var accordionPane3 = new dijit.layout.AccordionPane(
{'title': 'pane #3'}, 'accordionPane3');
leftPane.addChild(accordionPane1);
leftPane.addChild(accordionPane2);
leftPane.addChild(accordionPane3);
mainContainer.addChild(leftPane);
var centerPane = new dijit.layout.TabContainer(
{'region': 'center'}, 'centerPane');
var tabPane1 = new dijit.layout.AccordionPane(
{'title': 'tab #1'}, 'tabPane1');
var tabPane2 = new dijit.layout.AccordionPane(
{'title': 'tab #2'}, 'tabPane2');
var tabPane3 = new dijit.layout.AccordionPane(
{'title': 'tab #3'}, 'tabPane3');
centerPane.addChild(tabPane1);
centerPane.addChild(tabPane2);
centerPane.addChild(tabPane3);
mainContainer.addChild(centerPane);
var rightPane = new dijit.layout.ContentPane(
{'region': 'trailing'}, 'rightPane');
mainContainer.addChild(rightPane);
var bottomPane = new dijit.layout.ContentPane(
{'region': 'bottom'}, 'bottomPane');
mainContainer.addChild(bottomPane);
mainContainer.startup();
});
</script>
<div id="mainContainer">
<div id="topPane">Top pane</div>
<div id="leftPane">
<div id="accordionPane1">accordion pane #1</div>
<div id="accordionPane2">accordion pane #2</div>
<div id="accordionPane3">accordion pane #3</div>
</div>
<div id="centerPane">
<div id="tabPane1">tab pane #1</div>
<div id="tabPane2">tab pane #2</div>
<div id="tabPane3">tab pane #3</div>
</div>
<div id="rightPane">Trailing pane</div>
<div id="bottomPane">Bottom pane</div>
</div>
<style type="text/css">
html, body, #mainContainer {
width: 100%;
height: 100%;
margin: 0;
}
</style>
There’s lots of code but I prefer the separation. In reality I’d move the JavaScript etc into a separate files but it’s easier to demonstrate like this.
A couple of gotchas:
- Adding extra HTML elements dynamically
Sometimes dojo will require extradivs for layout purposes (for different digit classes, e.g. dijit.layout.BorderContainer). Clearly it would be wrong to modify markup to include extradivs just for this so you’ll probably want to create them programmatically. This is fine, but instead of usingaddChildto append a child, you’ll need to place the new element in the DOM yourself usingdojo.place(myDynamicElement.domNode, myExistingElement.domNode);. - Specifying the top level widget
If you use dojo’s markup method (withdjConfig="parseOnLoad:true"set or runningdojo.parser.parse()), the top level widgets are determined automatically. With this method, we need to manually start it by callingstartup()on the top level widget (in our case, themainContainerelement). Otherwise, no layout occurs at all.
Thank very, very much!!! that helped me a lot!
This is very much what I want to do as well — my problem is that I’m trying to do everything as self-contained custom widgets based on http://dojotoolkit.org/documentation/tutorials/1.6/templated/
And so the widget code defined needs to hang off of the document defined in templateString, and not the DOM above. I think I’m supposed to use data-dojo-attach-point to connect them, but I’m not quite sure how that works.
Hi Will. Sorry, not something that I know enough about. Have you tried asking on the Dojo forums (http://dojotoolkit.org/community/)?
I found the easiest way to do it was based off the programmatic BorderContainer test that’s in the source code: http://download.dojotoolkit.org/release-1.6.1/dojo-release-1.6.1/dijit/tests/layout/test_BorderContainer.html