Simple organizational chart
This code will automatically generate invisible checkboxes in front of all labels in the chart, which will be used to show and hide child elements. If JavaScript is disabled, the chart will still be visible, but not interactive. This small sacrifices makes it easier to write the HTML for charts as you do not need to place inputs with custom ids, and because the for attribute on labels is set automatically. The JS is executed once and does not bind events, making it quite efficient.
I also used a small hack to be able to box items without giving them a class by wrapping low-level items with <i>, but that's not required.
HTML
<ul class="org-chart">
<li><label>good</label>
<ul>
<li><label>Fruits</label>
</li>
</ul>
</li>
<li><label>Food</label>
<ul>
<li><label>Fruits</label>
<ul>
<li><i>Apple</i></li>
<li><i>Orange</i></li>
</ul>
</li>
<li><label>Junk</label>
<ul>
<li><i>Chips</i></li>
<li><i>Candy</i></li>
<li><i>Cookies</i></li>
</ul>
</li>
</ul>
</li>
<li><label>Drinks</label>
<ul>
<li><label>Soft drinks</label>
<ul>
<li><i>Cola</i></li>
<li><i>Lime soda</i></li>
<li><i>Rootbeer</i></li>
</ul>
</li>
<li><label>Hot</label>
<ul>
<li><i>Coffee</i></li>
<li><i>Tea</i></li>
<li><i>Hot chocolate</i></li>
</ul>
</li>
</ul>
</li>
</ul>
CSS
/* functionality style */
.org-chart, .org-chart ul, .org-chart ol {
list-style: none;
}
.org-chart li>input:not(:checked)+label+ul {
display: none;
}
.org-chart li>input:not(:checked)+label:before {
content: '+ ';
font-family: monospace;
}
.org-chart li>input:checked+label:before {
content: '- ';
font-family: monospace;
}
/* sample custom style */
.org-chart i {
font-style: normal;
}
.org-chart li>label, li>i {
display: block;
border: solid 2px #fc0;
border-radius: 5px;
padding: 10px;
margin: 10px;
}
.org-chart li li>label, li li>i {
border-color: #5f5;
}
.org-chart li li li>label, li li li>i {
border-color: #00d;
}
JavaScript
//(function() { // closure
var generateID = (function() {
var idCounter = 0;
return function(prefix) {
return(prefix + idCounter++);
}
})();
var inputMold = document.createElement('input');
inputMold.type = 'checkbox';
inputMold.style.display = 'none';
// inputMold.checked = true;
var labels = document.querySelectorAll('.org-chart label');
for (var i=0; i<labels.length; ++i) {
var label = labels[i];
var input = inputMold.cloneNode(false);
label.htmlFor = input.id = generateID('org-chart-box-');
label.parentNode.insertBefore(input, label);
}
//})(); // closure