You generally need JavaScript to handle dynamic behaviour, so I would expect a solution to a problem like this requires JavaScript. As far as I can tell, the only action HTML supports, is following links, and the only action CSS supports, is things like underlining or highlighting links on mouseover. There might be a few more CSS effects, but I'm not aware of them.
I poked around a few links I had stored on my work computer. I was trying to find stuff on keeping JavaScript and HTML separate, like I mentioned before. I haven't re-read them to check, but I think these were some good ones:
http://www.digital-web.com/articles/separa...nd_structure_2/http://www.quirksmode.org/js/introevents.htmlThere's also a Wiki article I found along the same lines:
http://en.wikipedia.org/wiki/Unobtrusive_JavaScriptAlso, to make better use of those schemes, it helps to know a little more about DOM (Document Object Model). Here's a reference (which I had to use to write my example):
http://www.w3.org/TR/REC-DOM-Level-1/level...l#ID-1451460987Now on to my code sample. Keep in mind that I don't do a whole lot of web programming, so you'll probably find better or shorter ways. I attempted to keep the HTML plain and simple, and usable even if JavaScript is disabled. I also attempted to keep the JavaScript somewhat general (although, that probably added to it's length and complexity). Note the absence of JavaScript code in the HTML file (other than the link in the header).
ShowHide.html:
<html>
<head>
<title>Show/Hide Test</title>
<script src="ShowHide.js"></script>
</head>
<body>
Some random page text to help add context.
<div id="container">
<h1>Section 1</h1>
<div>
This is some text in the first container.
</div>
<h1>Section 2</h1>
<div>
This is some text in the second container.
</div>
<h1>Section 3</h1>
<div>
This is some text in the third container.
</div>
</div>
More random text just to see how things fit.
</body>
</html>
ShowHide.js:
window.onload = function() {
// Initialize container with show/hide behavior
initShowHide(document.getElementById('container'));
}
function initShowHide(container) {
// Analyse structure of container
var nodeDivPairList = findNodeDivPair(container);
// Setup hide/show handlers for each pair, and hide div tags initially
for (var i = 0; i < nodeDivPairList.length; i++) {
// Install click handler to header tag (whatever tag comes before a div section)
nodeDivPairList[i][0].onclick = function() {
// Hide all paired div tags except one for current header tag
for (var i = 0; i < nodeDivPairList.length; i++) {
if (nodeDivPairList[i][0] != this) {
nodeDivPairList[i][1].style.display = 'none'; // Hide other div
} else {
nodeDivPairList[i][1].style.display = 'block'; // Show current div
}
}
}
// Hide div tag
nodeDivPairList[i][1].style.display = 'none';
}
}
// Finds an array of (tag, divTag) pairs within a given container
function findNodeDivPair(container) {
array = [];
var headerNode;
// Iterate over all child nodes
for (var node = container.firstChild; node != null; node = node.nextSibling) {
// Check if the child node is an element node (HTML tag)
if (node.nodeType == 1) {
// Check for end of pair
if (headerNode != null && node.nodeName == 'DIV') {
array.push([headerNode, node]);
headerNode = null; // Reset headerNode so it doesn't interfere with next pair match
} else {
headerNode = node;
}
}
}
return array;
}
Explanation of the JavaScript:
When you reference the file from the HTML header, it defines a few functions, and sets a window.onload handler. No code runs other than the simple assignment of an anonymous function to the onload event property.
When the page completely loads, including all resources, it triggers the onload event, which looks for the tag with the "container" id, and modifies it to have the show/hide behavior using the initShowHide function.
The findNodeDivPair function is used to scan a container for tag pairs, where the first tag can be of any type (including a div), and the second tag is a div. It skips over non tag nodes, such as text (including spaces and tabs from tag indentation). It was written to skip over pairs of tags that can't be properly matched (such as two successive span tags, or a header tag followed by a span tag). Basically, a missing div tag, or badly formed HTML section shouldn't mess things up much. The scan results are returned as an array of pairs.
The initShowHide function uses the findNodeDivPair function to understand the structure of the container it runs on. The initShowHide function will setup onclick handler functions for the first tag of each pair (the header element), which is responsible for hiding all section divs (the second tag of each pair), and then showing it's own associated div tag.
I had to scratch my head a bit about the closure part. I figured I'd either need to scan the DOM structure for every click, or I'd have to use a global variable or a closure to store cached references to the divs. The nesting of the handler function in the initShowHide function creates a closure, which gives the handler access to the array of tag pairs. The handler function can use "this" to refer to the node being clicked on, which is compared against the first element (the header) of each pair to know if it's associated div should be shown or hidden.
Also, if JavaScript is disabled, you'll just get a regular document with all sections visible. There is one downside to the example I've given though. If the page has lots of external resources to load, it may be some time before the JavaScript runs (since onload doesn't fire until everything is loaded), and so all sections may be initially visible until that happens. In practice, for small pages, you can probably ignore this, as you'll never notice this effect. If you're concerned about it though, it can be solved.
To deal with the initial visibility, should you need to, you can set a CSS rule to hide the div tags in the container element. The rule would be something along the lines of "#container div { display: none; }". I would suggest setting this from JavaScript though, right when you setup the onload event handler. If you set this rule in a simple CSS file, and JavaScript is disabled, all the div tags will be permanently hidden. If you do it from JavaScript, then they're only hidden when JavaScript is running and can reveal them as the headers are clicked. Basically, you have a nice fallback in that case.