Quick Fixes and Dojo Support

By on October 21, 2008 7:55 am

A lot of the stock Dijit components are single-serve, meaning they only solve one style of problem. But Dojo is very flexible, and can work most any way you imagine or intend — you just have to put on your coder hat, and bend away. That’s where I come in. One of the things I do most often in my role as lead support for SitePen’s Dojo Support offering is to find simple solutions and workarounds for problems encountered when the widget code doesn’t behave exactly as you want, or otherwise needs some level of professional bending.

Something that has come up time and time again is a balance between user interface paradigms provided by widgets found in Dijit. Take for instance an AccordionContainer: it displays a number of title headings within a confined space, and uses the remaining space for the content area of each pane. The size of the content area is calculated based on the available space, and adding many additional AccordionPanes to the container eventually leaves you with very little space. Adding panes indefinitely will leave you with zero space for content, which is a bad user interface no matter which way you look at it.

The pattern here is: a fixed area, a fixed content area (calculated), and only one available visible pane at a time. The TitlePane widget on the other hand does the opposite: it sizes its content area to the size of the content, wiping in and out. TitlePane is standalone, and doesn’t communicate with other TitlePanes. It has two states: open and closed (okay, three: in transition). The benefit here is not needing to know the size of your content before you add it, but you lose the paradigm of having only one open pane at a given time in an automated fashion. With a series of TitlePane’s stacked upon one another you can have an infinitely long list of children with variable heights and never worry about cramped space or bad UI, though all the panes could potentially be in a closed state, or all open. What if we wanted it to be more Accordion-y?

Like most things in life, somewhere between two extremes rests a balance. That’s my job — finding these solutions. During a screen-sharing exercise with a client, I quickly put together a solution to the aforementioned user interface complication, and have been reusing the technique enough to constitute explaining it out loud. It comes up occasionally as a question in the Dojo forums and on IRC, and when I spot it, I provide this little paste of code:

// define the TitleGroup widget:
dojo.declare("dijit.TitleGroup", dijit._Widget, {

	postCreate: function(){
		this.connect(this.domNode, "onclick", "closeAllBut");
		// slightly foo: works in this use case, but this will close 
		// all TitlePane's on a page, even the ones not in this group! 
		// FIXME: add code to scope down could make 
		// addChild/removeChild function to handle connections?
		this.connect(dijit.TitlePane.prototype, "_onTitleKey", "closeAllBut")
	closeAllBut: function(e){
		// this closes all found titlePanes within this domNode excluding
		// the one the click event originated from.
		var d = dijit.getEnclosingWidget(e.target);
			dojo.query(".dijitTitlePane", this.domNode)
					var tp = dijit.getEnclosingWidget(n);
					if(tp && tp.open && tp !== d){ tp.toggle(); }

You can see the overall result versus the Accordions, where we’ve created a custom wrapper widget that manages the TitlePanes contained within, producing the Accordion-like behavior of having only one open pane at any given time. After ShrinkSafe, it is 446 bytes of enhancement — custom tailored for a specific use case, albeit a common one. With roughly ten lines of code, we’ve bridged the gap between the Accordion and TitlePane UI patterns, and created a really simple widget to compartmentalize this “hack” we’ve put in place.

This, and any other level of extension or reuse, is available because of the modular and functional approach Dojo and Dijit take to problem-solving, and why I enjoy getting my proverbial hands dirty in finding these kinds of workable solutions. Developer overhead for inventing the TitleGroup: thirty minutes. We just needed to look at the TitlePane code, determine which function was the delegator (decider?) of the open/close state (_onTitleKey handles the enterkey when the title has focus, and delegates onclick handling withing the TitlePane, so it was the safest route: we’ve retained accessibility!), then reusing publicly exposed API for managing the children.

There is a note above in the postCreate method where we’d created connection to the TitlePane.prototype, meaning any instance of a TitlePane will fire this function. The solution to the caveat listed in the comments would be to implement addChild and removeChild functions, tracking the individual children when they come and code, and connecting to the instances passed rather than generically across all instances. Fortunately, that was not a requirement for this use-case, but it may be for you.


  • thtai

    Great, but hey, there is a problem.

    If you put another dojo component inside this TitlePane.
    Then the onclick event of this component work incorrectly.

    For example: Place a dojox.grid.DataGrid inside this TitlePane, then click on the row of the grid, TitlePane will close.

    I think the root cause is the connection of “onclick” event to this.domNode:

    this.connect(this.domNode, “onclick”, “closeAllBut”);

  • thtai

    any suggestion, please! :)

  • thtai

    Currently I fixed this problem by adding a condition to the if clause:

    var d = dijit.getEnclosingWidget(e.target);
    // Just do toggle when click on dijit.TitlePane
    if(d && d.declaredClass =="dijit.TitlePane"){
    dojo.query(".dijitTitlePane", this.domNode)
    var tp = dijit.getEnclosingWidget(n);
    if(tp && tp.open && tp !== d){ tp.toggle(); }

  • Alysaa

    Thank u for ur solution.It worked wonderfully for me but i have to put some links inside the title panes and when i click on any of the sublinks i want the corresponding div to stay open to reflect the currently selected div and sublink.
    I am not able to find any solution how to make only the particular tab opened.
    By default when the page reloads always the first tab remains selected.

    Any help will be appreciated..

    Thank u..

  • Apps

    Excellent article. I have a question. Is it possible to hide all the accordion panes initially? Only on click I need to show the corresponding pane. Any help will be appreciated.

  • FWIW, I’ve addressed all the issues mentioned above and combined them into a new module in DojoX. At this very moment it is just a patch on a ticket. When I add documentation for this module I will commit it to DojoX (most likely 1.6)



  • Sean

    This AccordionContainer resizing dynamically seems to work fine with Firefox. Maybe its the way I’m building the children dynamically. So frustrating that it works how I hoped in FF, then IE kills me. I’m going to redo it with your TitleGroup, but just out of curiosity, do you know why FF allows it to work dynamically but IE does not?

    var store = new dojo.data.ItemFileWriteStore({data:”your json here”});
    var populateComments = function(){
    var accord = new dijit.layout.AccordionContainer({
    style: “width: 800px;”,
    jsId: “accordComments”,
    id: “accordComments”
    query:{root: true} //this could * for all,
    onItem: function(item,request){

    var comments = dojo.create(“div”);
    var accordContent = null;

    //item has a list of children which are references to other nodes in the store
    //for each child, add the comment to the comments div
    var mrcom = dojo.create(“div”,{},comments,”last”);

    var commentDiv = dojo.create(“div”,

    accordContent = new dijit.layout.ContentPane({
    title: item.name.toString(),
    content: comments

    }); //end foreach

    }//end onitem
    } //end fetch params
    );//end fetch


  • In 1.6 Accordion fits to its container height if wrapped into ContentPane.
    Trick is to define 100% height for wrapper and remove default padding:


    Hi how are you?

    place some long content and see the scrollbar here

  • Vivek Patel

    Hi, I tried the same but it does not work for me.
    Here is sample code. Please tell me what I am doing wrong?

    I have also created the sample .js file and included the code you have shows in the file.


  • David Marrs

    Thanks for the write up. You should know that the example link is broken