Tree with checkboxes and JavaScript

The Problem

We have a tree wich is built using nested unordered lists (ul tags). Some items in list have checkboxes. We want to add the following behavior to the checkboxes:

  • When a checkbox is checked/unchecked (by user or code) all children checkboxes are changed accordingly (checked/unchecked).
  • When a checkbox is unchecked (by user or code), the parent checkbox is also unchecked.

Here is a sample HTML code that can build such a tree:

<ul id="userTree">
	<li><input type="checkbox"> My Company
		<ul>
			<li>Clerks
				<ul>
					<li><input type="checkbox" value="users[101]"> Joe Clerk</li>
					<li><input type="checkbox" value="users[102]"> Klear Smith</li>
				</ul>
			</li>
			<li>Cashiers
				<ul>
					<li><input type="checkbox" value="users[201]"> Jean Doe</li>
				</ul>
			</li>
		</ul>
	</li>
</ul>

The Solution (MooTools)

Here is the code that solves the problem, using the MooTools JavaScript framework.

var Page = (function() {
		BindCheckboxTree: function(tree, elParentCheckbox) {
			var elChild, sType;
			var elCheckbox = elParentCheckbox;
 
			tree.getChildren().each( function(elChild) {
				elChild = $(elChild);
				switch (elChild.tagName.toLowerCase()) {
					case 'li':
					case 'ul':
						Page.BindCheckboxTree(elChild, elCheckbox);
						break;
					case 'input':
						if (elChild.type) sType = elChild.type;
						else sType = elChild.getAttribute('type');
						if (sType && sType.toLowerCase() == 'checkbox') {
							elCheckbox = elChild;
							elChild.addEvent("click", Page.evhCheckboxTreeClicked);
							elChild.pspCheckboxParent = Page.GetElementRef(elParentCheckbox);
							elChild.pspChildCheckboxes = [];
							if (elParentCheckbox) elParentCheckbox.pspChildCheckboxes.push(Page.GetElementRef(elChild));
						}
						break;
				}
			});
		},
 
		elementRefCache: [],
		GetElementRef: function(element) {
			if ( ! element) return null;
			if ( ! element.pspElementCacheRef ) {
				element.pspElementCacheRef = Page.elementRefCache.length;
				Page.elementRefCache.push(element);
			}
			return element.pspElementCacheRef;
		},
 
 
		GetElementByRef: function (elRef) {
			if (elRef == null) return null;
			return Page.elementRefCache[elRef];
		},
 
 
		CheckboxTreeUpdateChildren: function(elCheckbox) {
			var elChild;
			elCheckbox.pspChildCheckboxes.each(function(refChild) {
				elChild = Page.GetElementByRef(refChild);
				elChild.checked = elCheckbox.checked;
				Page.CheckboxTreeUpdateChildren(elChild);
			});
		},
 
		CheckboxTreeUpdateParent: function(elCheckbox) {
			var elParent = Page.GetElementByRef(elCheckbox.pspCheckboxParent);
			if ( elParent && ! elCheckbox.checked ) {
				elParent.checked = false;
				Page.CheckboxTreeUpdateParent(elParent);
			}
		},
 
		evhCheckboxTreeClicked: function() {
			var elCheckbox = this;
			Page.CheckboxTreeUpdateChildren(elCheckbox);
			Page.CheckboxTreeUpdateParent(elCheckbox);
		},
	}
})();

The foolowing code installs the checkbox behaviors. It needs to be placed somewhere after the Page object is created (see above).

window.addEvent("domready", function() {
	Page.BindCheckboxTree($('usertree'));
});

Back to JavaScript, Home

 
javascript/checkboxtree.txt · Last modified: 2009/10/31 23:36 (external edit)
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki