If you don't want to reload pages, I see no other option than Javascript. I made a small example. Please tell us if that's what you need.
<html>
<head>
<title>Test</title>
<script type="text/javascript">
function showPage(number) {
for (var i = 0; i < 2; i++)
{
if (i == number) document.getElementsByName('page')[i].style.display="block";
else document.getElementsByName('page')[i].style.display="none";
}
}
</script>
</head>
<body>
<p><a href="javascript:showPage(0)">show page 0</a></p>
<p><a href="javascript:showPage(1)">show page 1</a></p>
<p name="page" style="display:block">this is page 0</p>
<p name="page" style="display:none">this is page 1</p>
</body>
</html>
Note: All pages have the same name "page". Selection of a page is done by its number. Numbering goes from 0 to <number of pages - 1>. Visibility is controlled with the "display" css property which will make the object completely invisible if set to "none".
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.digital-web.com/articles/separating_behavior_and_structure_2/)
http://www.quirksmode.org/js/introevents.html (http://www.quirksmode.org/js/introevents.html)
There's also a Wiki article I found along the same lines:
http://en.wikipedia.org/wiki/Unobtrusive_JavaScript (http://en.wikipedia.org/wiki/Unobtrusive_JavaScript)
Also, 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-1451460987 (http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-1451460987)
Now 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.
PHP can't detect JavaScript, since it's run on the server, and JavaScript is a client side thing. You could potentially modify PHP output if the server was told by the client it doesn't support JavaScript, but that can only work on the second and subsequent pages. If you had a login screen, you might use JavaScript to set a hidden form element to true, that normally defaults to false, and the server could use that to make assumptions about JavaScript. But, other than these custom coded solutions, PHP won't know in general if a client supports JavaScript.
You can have an anchor with a regular HTML href link, and an onclick event handler. If the event handler returns false, it will cancel navigation to the href link. Hence, you can use the href as a fallback, while "upgrading" your links with an onclick handler.
You can modify the code I posted to give it a try. Change the header tags (the h1 tags) to anchors, add a suitable href, and ensure the handler function returns false at the end.
Modification to JavaScript:
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
}
}
return false; // <-- Modification
}
Mind you, the example starts to look a bit ugly due to the default inline styling for links. When you click one to expand it's text, the other anchors suddenly move off the end of the line to appear below the new expanded text. I find the effect looks much nicer when the clickable elements are always on separate lines. You can try adding the following CSS style to keep the anchors on separate lines:
<style>
#container a { display: block; }
</style>
Of course keeping the CSS in a separate linked file is usually nicer. But for my one line example I just couldn't bring myself to bother.
(double-post, arrrg! lol. Only way to bring attention to the new question)
In preparation for the next section rebuild, I was playing around with what you gave me hooman, and there is just one thing I don't like about it: you have to click the headers to hide/show the sections.
Is there a way to make it formatted more like this:
<table width='100%'>
<tr>
<td width='10%'>
//intra-page navagation, triggers sectional show/hide
</td>
<td>
//sections that are shown/hidden
</td>
<tr>
</table>
I know with php, I accomplished this with a switch:
<?php
if(empty($_GET['pg']))
{
$p = '0';
}
else
{
$p = $_GET['pg'];
}
echo "<table width='100%'>\n <tr>\n <td width='10%'>\n";
require('nav.html');
echo "\n </td>\n <td>\n";
switch($p)
{
case 0:
//either use an echo or include, depending on content
break;
//repeat for all sections
}
echo "\n </td>\n <tr>\n</table>"
?>
I use "\n" of course in order to preserve the formatting (more for my own sanity than anything else)