Walk the DOM

Expand/Collapse DOM items

by roge roge

HTML

<a href="javascript:void(0);" title="Déplier" onclick="showLevel(document.getElementById('Data'), 10)"> Open all </a> &nbsp; &nbsp;
<a href="javascript:void(0);" title="Plier" onclick="showLevel(document.getElementById('Data'), 0)"> Close all </a> &nbsp; &nbsp;
<a href="javascript:void(0);" title="Plier" onclick="computeMaxLevel(document.getElementById('Data'))"> Compute MaxLevel </a>
   
<pre id="Data">
<span class="OB" style="display: inline;">{</span>
<a class="ExpanderOpened" title="Plier/Déplier" onclick="toggleContainer(this)">course: <span class="NB">12345</span></a>
   <span class="Container" style="display: inline;">
   <a class="ExpanderOpened" title="Plier/Déplier" onclick="toggleContainer(this)">Modules</a>: 
      <span class="Container" style="display: inline;">
         <span class="LI" style="display: inline;">[</span>
            <span class="OB" style="display: inline;">{</span>
               <a class="ExpanderOpened" title="Plier/Déplier" onclick="toggleContainer(this)">Module: <span class="NB">1</span></a>
               <span class="Container" style="display: inline;">
                  <a class="ExpanderOpened" title="Plier/Déplier" onclick="toggleContainer(this)">Sequences</a>: 
                  <span class="Container" style="display: inline;">
                     <span class="LI" style="display: inline;">[</span>
                        <span class="OB" style="display: inline;">{</span>
                           <a class="ExpanderOpened" title="Plier/Déplier" onclick="toggleContainer(this)">Sequence<span class="NB">1</span></a>
                           <a class="ExpanderOpened" title="Plier/Déplier" onclick="toggleContainer(this)">Sequence<span class="NB">1</span></a>
                        <span class="OB" style="display: inline;">}</span> 
                     <span class="LI" style="display: inline;">]</span> 
                  </span>
               </span>
            <span class="OB" style="display: inline;">},</span> 
       ...

CSS

.OB { /* ObjectBrace */
	color:#00AA00;
	font-weight:bold;
}
.LI { /* ObjectBrace */
	color:#0033FF;
	font-weight:bold;
}
PRE.CodeContainer {
	margin-left:10px;
	line-height: 16pt;
}

A.ExpanderOpened {
	cursor: pointer;
	color: #060; 
	border-bottom: 1px solid #999;
}	
A.ExpanderClosed {
	cursor: pointer;
	color: #800; 
	font-weight: bold;
	border-bottom: 1px solid #666;
}	
A.ExpanderOpened:hover, A.ExpanderClosed:hover {
	border-radius: 4px;
	background: #ddd; 
}

JavaScript

/*
	Node.ELEMENT_NODE == 1 ( element node )
	Node.ATTRIBUTE_NODE == 2 ( node attribute )
	Node.TEXT_NODE == 3 ( text node )
	Node.CDATA_SECTION_NODE == 4 ( CDATA section node )
	Node.ENTITY_REFERENCE_NODE == 5 ( node reference to an entity )
	Node.ENTITY_NODE == 6 ( Feature node )
	Node.PROCESSING_INSTRUCTION_NODE == 7 ( processing instruction node )
	Node.COMMENT_NODE == 8 ( comment node )
	Node.DOCUMENT_NODE == 9 ( document node )
	Node.DOCUMENT_TYPE_NODE == 10 ( Document Type node )
	Node.DOCUMENT_FRAGMENT_NODE == 11 ( node document fragment )
	Node.NOTATION_NODE == 12 ( node notation )
*/

function computeMaxLevel(obj) {
	var maxLevel=0;
	function walkTheContainer(node, depth, func) {
		 depth = func(node, depth);
		 node = node.firstChild;
		 while (node) {
			//console.log(depth + "+ Node : " + node.nodeName + " ==> " + node.className);
			walkTheContainer(node, depth, func);
			node = node.nextSibling;
		 }    
	}
	walkTheContainer(obj, 0, function (node, depth) {
		if (node.className == "Container") {
			depth++;
			maxLevel = Math.max (maxLevel, depth);
			//console.log(" ++++   maxLevel  " + maxLevel + " - Container " );
		}
		return depth;
	});
	alert("maxLevel = " + maxLevel);
}

function showLevel(obj, lev) {
	function walkTheContainer(node, depth, maxDepth, func) {
		 if (depth > maxDepth + 1) return;
		 depth = func(node, depth, maxDepth);
		 node = node.firstChild;
		 while (node) {
			walkTheContainer(node, depth, maxDepth, func);
			node = node.nextSibling;
		 }    
	}
	walkTheContainer(obj, 1, lev, function (node, depth, maxDepth) {
		switch (node.className) {
			case "ExpanderOpened" :	
			case "ExpanderClosed" :	
				node.className = (depth > maxDepth) ? "ExpanderClosed" : "ExpanderOpened";
				console.log(depth + "+ Expander : " + node.innerHTML + " ==> " + node.className);
				break;
			case "Container" :	
				node.style.display = (depth > maxDepth) ? "none" : "inline";  
				console.log(depth + "  Container : " + node.style.display...