Organized Selector Chaos with dojo.behavior

By  on  

One of the most underrated parts of writing good JavaScript code is writing *maintainable* code:  readable, modular, and clean.  Just because you use a JavaScript framework doesn't mean your code is maintainable.  Quick the contrary could be true -- some frameworks make JavaScript uglier.

Because of all the DOM node traversal that's involved with modern day JavaScript techniques, class usage and element event modification can quickly become spaghetti code.  Luckily dojo.behavior exists.  This Dojo class allows you to handle event querying and functionality assignment in a very uniform, clean manner.

Element Usage without Behavior:  query and forEach

The typical element collection and functionality assignment is done with dojo.query and dojo.forEach:

/* style updates */
dojo.query('a.someClass').forEach(function(item) {
	item.addClass('someOtherClass');
})

/* events */
dojo.query('a.someClass').forEach(function(item) {
	dojo.connect(item,'onclick',function() {
		console.log('clicked!');
	});
});

This code is by no means ugly, but it can quickly become a mess.  The other drawback to using this method is that there's no clean way to "enable" and disable these behaviors.  Once they're set, you need another code block to remove the behaviors.  Enter dojo.behavior.

Organization:  dojo.behavior!

dojo.behavior provides a solid, functional, and readable structure of handling selector-to-functionality assignments.  A quick format overview:

/* require the class */	
dojo.require('dojo.behavior');
	
/* super basic usage */
dojo.behavior.add({
	'a.someClass': function(node) { //assumes "found"
		console.log('Found a node:  ',node);
	}
});
dojo.behavior.apply();

/* multiple selectors */
dojo.behavior.add({
	'#someNode': {
		onclick: function(e) {
			e.preventDefault(); // stop the default event handler
			console.log('clicked! ', e.target);
		}
	},
	'div': {
		found: function(node) {
			console.log('Found a node:  ',node);
		},
		onclick: function(e) {
			console.log('this DIV was clicked! ', e.target);
		}
	}
});
dojo.behavior.apply();

dojo.behavior.apply...applies...the behaviors we've set.  Simple, effective, clean.

Widget Creation with dojo.behavior

Widget creation is an even better opportunity to use dojo.behavior:

dojo.behavior.add({
	'select': function(node) {
		//create this type of widget for all select elements
		new dijit.form.FilteringSelect({/* options */,node});
	},
	'input[type=text]': {
		found: function(node) {
			new dijit.form.TextBox({},node);
		},
		onfocus: function(e) {
			console.log('got focus!');
		}
	}
});
dojo.behavior.apply();

Event Assignement with dojo.behavior

Event assignment also works with dojo.behavior:

dojo.behavior.add({
	'a.disableClick': {
		onchange: function(e) {
			e.preventDefault();
		}
	}
});
dojo.behavior.apply();

As does topic subscribing:

dojo.behavior.add({
    '#someUL > li': '/found/li'
});
dojo.subscribe('/found/li', function(msg){
    console.log('message: ', msg);
});
dojo.behavior.apply();

Behave!

Though dojo.behavior doesn't save much code, it definitely makes code more readable and thus, more portable.

Recent Features

  • By
    Animated 3D Flipping Menu with CSS

    CSS animations aren't just for basic fades or sliding elements anymore -- CSS animations are capable of much more.  I've showed you how you can create an exploding logo (applied with JavaScript, but all animation is CSS), an animated Photo Stack, a sweet...

  • By
    5 HTML5 APIs You Didn’t Know Existed

    When you say or read "HTML5", you half expect exotic dancers and unicorns to walk into the room to the tune of "I'm Sexy and I Know It."  Can you blame us though?  We watched the fundamental APIs stagnate for so long that a basic feature...

Incredible Demos

  • By
    Custom Scrollbars in WebKit

    Before each of the browser vendors we like was providing unique CSS controls, Internet Explorer was setting the tone.  One such example is IE's early implementation of CSS filters. Internet Explorer was also the first browser that allowed developers to, for better or worse, customize...

  • By
    New MooTools Plugin:  ElementFilter

    My new MooTools plugin, ElementFilter, provides a great way for you to allow users to search through the text of any mix of elements. Simply provide a text input box and ElementFilter does the rest of the work. The XHTML I've used a list for this example...

Discussion

  1. This blog post made me take a closer look at dojo.behavior – http://whatsthepointeh.blogspot.com/2010/09/dojoconnect-vs-dojobehavior.html

  2. Is this basically a way to prevent using dojo.query() in a way that is executed immediately whilst also providing a level of control over the commands?

  3. Paul Lysak

    Hi.
    I wonder if dojo.behavior can work well with declaratively created dijits. Say, for connecting handlers to menu items if this menu was created using “parseOnLoad: true” option.
    Thanks.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!