Destroy all widgets/dijits in a DOM node

Following up on Tom’s post from 2011, and taking into account the comments posted, here is the latest “known good” technique.

Often we need to empty a DOM node of all widgets. Here’s the magic incantation.

require(["dijit/registry", "dojo/dom-construct", 
        "dojo/_base/array"], 
        function(registry, domConstruct, array) {

    // Your DOM node reference goes here
    var node = null; 

    // Destroy the widgets, including their
    // children and DOM fragments
    array.forEach(registry.findWidgets(node), 
        "item.destroyRecursive()");

    // OPTIONAL: Explicitly empty the node.
    // This will take care of DOM nodes that 
    // weren't managed by widgets
    domConstruct.empty(node);

});

Writing a simple, self contained tab container Dijit in Dojo

Over the last few weeks, I’ve been working with a new team and have been putting together some versatile dijits that are to be used throughout the UI. Today I spent some time working on an idea for a tab container which requires little or no customisation / interaction to get set up and running.

Additional Comment: The reason why I have done this over using the built in Dojo TabContainer is that I find it to be a bit ‘over the top’ for simple use as a plain tab container. I get faced with steep design guidelines by clients and even STEEPER browser requirements (such asIE6) and as a result, I find that it’s important to keep the memory / processor useage to a minimum and ensure that the fewest number of dom nodes are created. Thus, my ‘lite’ tabContainer was born!

I’ve spent the last hour or two re-writing a clean room version which I’d like to show to you all to demonstrate how easy it is to style and manipulate dom elements once you have them on the page.

Click to skip to the Demo Page

The idea was simple…
Get a tab container on a page, with tab switching, tab change events and a way to set which tab is shown externally.
The main requirement I gave myself what that it MUST be simple and self contained. In the past I’ve added tabs and panes to the page separately and then connected their events, but this proves fiddly and repetitive, so I’ve worked all of the variables into the dijit attributes, settable via it’s declarative marking! So…

What’s in the template…
…Not much

<div class="tabContainer">
	<ul dojoAttachPoint="_listNode"></ul>
	<div dojoAttachPoint="containerNode" class="content"></div>
</div>

An outer div with a class to restrict my CSS calls easily, a list to hold the tabs and a ‘content’ div with the magic attach point ‘containerNode’. As mentioned before, this is used throughout the dijit framework, and is where the innerHTML of your dijit declaration is copied to when the dijit is parsed. So this is the div into which our tab pane content will be put.

Now for the declaration…

<div dojoType="tom.dijit.TabContainer">
	<div tab="tab1" label="Tab One" selected="true">Content One</div>
	<div tab="tab2" label="Tab Two">Content Two</div>
	<div tab="tab3" label="Tab Three">Content Three</div>
</div>

As you can see, I’m putting using the ‘tab’ and ‘label’ attrs of the inner divs to define my parameters. The ‘tab’ param is the name that the tabContainer dijit will refer to the pane by, these need to be unique within each tabContainer level. The ‘label’ param is simply picked up and placed as the link text inside the tab and is the text that the user will see. And that’s all there is to it from a html point of view. This simple model allows n layer nesting of tab containers and makes it all very simple.

So how does that work…
Well, during the post create of the tabContainer dijit, I run a dojo query for all immediate children on my containerNode with the attribute ‘tab’. For each of these, I get hold of it’s tab and label attributes and create a list item and link for each result in the list node. I then add this info along with attach points to both the pane node and the tab node to a dijit level object and finally, I check to see if the pane has ‘selected==true’ and apply the selected class to it’s tab accordingly. If a pane is not ‘selected’, I hide it using a simple ‘display:none’ class named hidden.

postCreate : function() {
		this.inherited(arguments);
		
		//look for divs with a tab attr inside my container node!
		dojo.query("> div[tab]", this.containerNode).forEach(dojo.hitch(this, function(thisNode){
			//start building up our tab object
			var tabObj = {	"paneNode" : thisNode,
							"label" : dojo.attr(thisNode, "label") ? dojo.attr(thisNode, "label") : "Undefined" };
			//get the tab name, we'll need this!
			var tabName = dojo.attr(thisNode, "tab");
			
			//add a list item and an anchor tag to the list
			var tabItem = dojo.create("li", {"class":"tab"}, this._listNode);
			var tabLink = dojo.create("a", {"innerHTML": tabObj.label, "href":"javascript:;", "tab":tabName}, tabItem);
			tabObj.tabNode = tabItem;
			
			//connect the onclick event of our new link
			dojo.connect(tabLink, "onclick", this, "_onTabLinkClick");
			
			//now add our tabObj to the dijit level tabList so we can 
			//get to it later
			this._tabList[tabName] = tabObj;
			
			//get hold of the selected attr, to see if it should
			//be initially visible - last one found will win this battle
			var selected = dojo.attr(thisNode, "selected");
			
			if (!selected) {
				//not selected, so adding hidden class
				//(hidden class defined in global css as display:none)
				dojo.addClass(thisNode, "hidden");
			}
			else {
				//this ones selected, so put the name into our selectedTab var
				this._selectedTab = tabName;
				//add a 'selected' class to our tab list item
				dojo.addClass(tabItem, "selected");
			}
		}));		
	}

The result of all of this, is a very plain dom tree with all the elements we need to flesh out via CSS a lightweight, customisable tabContainer.

For the purposes of this demo, I have added a bounding border and a wrapper div to show the tabContainer’s containment.

So with a little bit of CSS effort, you can now transform this shell to any number of tabContainer layouts. For now, here’s a screenshot and a snippet of a small bit of CSS to give you a feel (bare in mind I spent 2 min on this CSS).
I hope to add another post in a few days to go over how to style the dijit and use the tabContainer’s events and functions to interact with a page controller (page level javascript).

Once again, I’ve used dashed borders to show where boundaries lie. The basic CSS is shown below

div.tabContainer > ul {
	list-style: none;
	padding: 0;
	margin: 0;
	height: 25px;
}

div.tabContainer > ul > li {
	float: left;
	height: 15px;
	padding: 5px;
	margin: 0px 5px;
	background: black;
}

div.tabContainer > ul > li > a {
	text-decoration: none;
	color: #EBEBED;
}

div.tabContainer > ul > li:hover,
div.tabContainer > ul > li:hover a {
	background: #EBEBED;
	color: #black;
}

div.tabContainer > ul > li.selected a {
	color: #729fcf;
	font-weight: bold;
}

Click the link to go take a look at a working demo (which I’ll upload shortly after completing this post!)
TabContainer Demo Page

TabContainer Full JS Source Code

Enjoy!

Styling dijit.form.Button, the easy way!… with baseClass

As a follow up to my previous post, I’d like to add to my final comment about using the baseClass attr on dijit.form.Button to make styling nice and easy!

In the past, when trying to use the class attr to skin a dojo button, I’ve always came across problems, because they class you add ends up about 4 layers deep into the Dijit, thus making it hard to get a handle to the outer elements of it.
To get around this, I’ve adopted a method of ‘wrapping’ a button in a span with an appropriate class as follows:

<span class="roundBlueButton">
	<div dojoType="dijit.form.Button">Text</div>
</span>

Allowing CSS as follows:

span.roundBlueButton .dijitButton {
	//now let's style it!!
}

BUT, obviously that’s not ideal now is it?!
So digging around inside some dijit button demos, (search for Test_Button.html in the dijit code base) I found an example where the class “acmeButton” is added to some buttons, not using ‘class’, but by using the mythical ‘baseClass’ attribute. It seems that this attribute overrides the class on the outermost element of a dijit.form.Button and allows you to now, finally, get a handle on that button and unleash your creative side!

<div dojoType="dijit.form.Button" baseClass="tomButton">Text</div>
.tomButton {
	//now let's style it!!
}

Even better still, this seems to remove the dijitButton class rather than adding to it, meaning that your dijit Button, is now a nice, plain black bordered, white backgrounded button…basically a blank canvas!!

This custom class you have added, now get’s used in the button’s CSS mix in functions. So in the case of my tomButton class, you’ll find that your dijit gets supplemented with tomButtonHover, tomButtonActive and tomButtonFocused under the right circumstances. Thus allowing you to style hover over effects etc.. for troublesome browsers such as IE6, IE7, IE8, probably IE9 and then IE10, 11, 12 etc.. going forward!

So there you have it! An easy way to style a dijit Button! This ‘baseClass‘ attribute should be applicable to many different types of button!
So good luck and enjoy!!

As a final comment: I’ve found that in some cases you need to add ‘!important‘ tags to your CSS classes in order to ensure that they get applied. This seems to be required when trying to apply background images etc…