Search code examples
javascriptdojo

Dojo Parameters for Tabs


I'm having trouble with the Dojo documentation (as usual).
On their TabContainer API, they list the second argument as an object called "params", but they never say what you can actually put in this params object. Can I specify the width? The height? Do I specify the id's of the divs I want to be the tabs inside the container?

There's also no specification of what attributes I would put in HTML if I wanted to specify the tab containers to be parsed by the Dojo parser. I found the following example that lets you put the title, selected and closable options. Is there anything else?

<div id="tabA1" dojoType="dijit.layout.ContentPane" title="First Tab"  selected="true" closable="true">
        First Tab
    </div>
    <div id="tabA2" dojoType="dijit.layout.ContentPane" title="Second Tab" closable="true">
        Second Tab
    </div>
    <div id="tabA3" dojoType="dijit.layout.ContentPane" title="Third Tab" closable="true">
        Third Tab
    </div>
</div>

Solution

  • I am not an expert in Dojo widgets, but this is what I know:

    1. All Dojo widget constructors have signature:

      var widget = new Widget(params, node);

    2. The best way to discover params is to look at the source code — don't get scared, they would be documented variables at the beginning of a relevant class.

    3. The relevant file is usually simple to find using the name of the widget because they are named by their path.

    4. The best way to look up this stuff is to use a Dojo checkout with your favorite text editor. But the nightly checkout works too (if you follow the trunk). Or the Trac source browser.

    5. Don't underestimate the power of looking at tests and demos.

    Example: dijit.layout.TabContainer ⇒ dijit/layout/TabContainer.js. If the file is missing look into directories of the hierarchy for _base.js, or some similarly sounding files — the latter can bundle related classes together. But in most cases (like with TabContainer) you'll find it immediately. Let's go and look.

    There are two public documented parameters in the top of the class:

    • tabPosition — String. Defines where tabs go relative to tab content. "top", "bottom", "left-h", "right-h". Default: "top".
    • tabStrip — bool. Defines whether the tablist gets an extra class for layouting. Default: false.
    • _controllerWidget — just ignore it, no public parameters start with the underscore — it is a common JavaScript convention to designate protected members.

    But it is not all. TabContainer is based on dijit.layout.StackContainer (just look at the dojo.declare() header). We can use StackContainer's public parameters as well:

    • doLayout — Boolean. If true, change the size of my currently displayed child to match my size. Default: true.
    • persist — Boolean. Remembers the selected child across sessions. Default: false.

    As you can see the code and parametrs are nicely documented, yet not always reflected in the API tool. Now we can create the tab container with confidence.

    But let's see it in action first. All Dijit tests are always in dijit/tests. Any dijit.layout.* widget will be tested in dijit/tests/layout. The relevant test file would be named something like test_TabContainer.html, and in fact I see 5 files for that:

    For example, let's recreate the first TabContainer of test_TabContainer.html:

    var tc = new dijit.layout.TabContainer(
      {persist: true, tabStrip: true}, "mainTabContainer");
    

    Or we can do it like in the test inline:

    <div id="mainTabContainer" dojoType="dijit.layout.TabContainer"
        persist="true" tabStrip="true" style="width: 100%; height: 20em;">
      ...
    </div>
    

    Coming back to your original question: now you can see that width and height are specified simply as styles, no special attributes, nothing fancy, just some intuitive CSS. So if you want to do it programmatically, just set them on a node before creating a new instance of TabContainer.

    Yeah, I wish the API doc got all these small details too, but the whole setup is intuitive, and relevant parts are documented right in the file. We did go to the source code, but we didn't try to decipher the source code, just read human-readable comments on the top of the class.