<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd">
<!--
Example File From "JavaScript and DHTML Cookbook"
Published by O'Reilly & Associates
Copyright 2003 Danny Goodman
-->
<html>
<head>
<title>Recipe 10.10.TOC</title>
<style type="text/css">
.OLRow {vertical-align:middle; font-size:12px; line-height:11px; font-family:Arial,sans-serif}
.OLBlock {display:none}
img.widgetArt {vertical-align:text-top}
</style>
<script type="text/javascript">
/**********************************
GLOBAL VARIABLES
***********************************/
// pre-cache art files and sizes for widget styles and spacers
// (all images must have same height/width)
var collapsedWidget = new Image(20, 16);
collapsedWidget.src = "oplus.gif";
var collapsedWidgetStart = new Image(20, 16);
collapsedWidgetStart.src = "oplusStart.gif";
var collapsedWidgetEnd = new Image(20, 16);
collapsedWidgetEnd.src = "oplusEnd.gif";
var expandedWidget = new Image(20, 16);
expandedWidget.src = "ominus.gif";
var expandedWidgetStart = new Image(20, 16);
expandedWidgetStart.src = "ominusStart.gif";
var expandedWidgetEnd = new Image(20, 16);
expandedWidgetEnd.src = "ominusEnd.gif";
var nodeWidget = new Image(20, 16);
nodeWidget.src = "onode.gif";
var nodeWidgetEnd = new Image(20, 16);
nodeWidgetEnd.src = "onodeEnd.gif";
var emptySpace = new Image(20, 16);
emptySpace.src = "oempty.gif";
var chainSpace = new Image(20, 16);
chainSpace.src = "ochain.gif";
// miscellaneous globals
var widgetWidth = "20";
var widgetHeight = "16";
var currState = "";
var displayTarget = "contentFrame";
/**********************************
DATA COLLECTIONS
***********************************/
var expansionState = "";
// constructor for outline item objects
function outlineItem(text, uri) {
this.text = text;
this.uri = uri;
}
var olData = {childNodes:
[{item:new outlineItem("Forms"),
childNodes:
[{item:new outlineItem("Introduction", "http://www.w3.org/TR/html401/interact/forms.html#h-17.1")},
{item:new outlineItem("Controls", "http://www.w3.org/TR/html401/interact/forms.html#h-17.2"),
childNodes:
[{item:new outlineItem("Control Types", "http://www.w3.org/TR/html401/interact/forms.html#h-17.2.1")}
]},
{item:new outlineItem("FORM Element", "http://www.w3.org/TR/html401/interact/forms.html#h-17.3")},
{item:new outlineItem("INPUT Element", "http://www.w3.org/TR/html401/interact/forms.html#h-17.4"),
childNodes:
[{item:new outlineItem("INPUT Control Types", "http://www.w3.org/TR/html401/interact/forms.html#h-17.4.1")},
{item:new outlineItem("Examples", "http://www.w3.org/TR/html401/interact/forms.html#h-17.4.2")}
]},
{item:new outlineItem("BUTTON Element", "http://www.w3.org/TR/html401/interact/forms.html#h-17.5")},
{item:new outlineItem("SELECT, OPTGROUP, OPTION Elements", "http://www.w3.org/TR/html401/interact/forms.html#h-17.6"),
childNodes:
[{item:new outlineItem("Pre-selected Options", "http://www.w3.org/TR/html401/interact/forms.html#h-17.6.1")}
]},
{item:new outlineItem("TEXTAREA Element", "http://www.w3.org/TR/html401/interact/forms.html#h-17.7")},
{item:new outlineItem("ISINDEX Element", "http://www.w3.org/TR/html401/interact/forms.html#h-17.8")},
{item:new outlineItem("Labels", "http://www.w3.org/TR/html401/interact/forms.html#h-17.9"),
childNodes:
[{item:new outlineItem("LABEL Element", "http://www.w3.org/TR/html401/interact/forms.html#h-17.9.1")}
]},
{item:new outlineItem("FIELDSET, LEGEND Elements", "http://www.w3.org/TR/html401/interact/forms.html#h-17.10")},
{item:new outlineItem("Element Focus", "http://www.w3.org/TR/html401/interact/forms.html#h-17.11"),
childNodes:
[{item:new outlineItem("Tabbing Navigation", "http://www.w3.org/TR/html401/interact/forms.html#h-17.11.1")},
{item:new outlineItem("Access Keys", "http://www.w3.org/TR/html401/interact/forms.html#h-17.11.2")}
]},
{item:new outlineItem("Disabled and Read-Only Controls", "http://www.w3.org/TR/html401/interact/forms.html#h-17.12"),
childNodes:
[{item:new outlineItem("Disabled Controls", "http://www.w3.org/TR/html401/interact/forms.html#h-17.12.1")},
{item:new outlineItem("Read-Only Controls", "http://www.w3.org/TR/html401/interact/forms.html#h-17.12.2")}
]},
{item:new outlineItem("Form Submissions", "http://www.w3.org/TR/html401/interact/forms.html#h-17.13"),
childNodes:
[{item:new outlineItem("Form Submission Method", "http://www.w3.org/TR/html401/interact/forms.html#h-17.13.1")},
{item:new outlineItem("Successful Controls", "http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2")},
{item:new outlineItem("Processing Form Data", "http://www.w3.org/TR/html401/interact/forms.html#h-17.13.3"),
childNodes:
[{item:new outlineItem("1. Identify Successful Controls", "http://www.w3.org/TR/html401/interact/forms.html#h-17.13.3.1")},
{item:new outlineItem("2. Build Form Data Set", "http://www.w3.org/TR/html401/interact/forms.html#h-17.13.3.2")},
{item:new outlineItem("3. Encode Form Data", "http://www.w3.org/TR/html401/interact/forms.html#h-17.13.3.3")},
{item:new outlineItem("4. Submit Encoded Data", "http://www.w3.org/TR/html401/interact/forms.html#h-17.13.3.4")}
]},
{item:new outlineItem("Form Content Types", "http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4"),
childNodes:
[{item:new outlineItem("application/x-www-form-urlencoded", "http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1")},
{item:new outlineItem("multipart/form-data", "http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2")}
]
}
]
}
]},
{item:new outlineItem("Scripts"),
childNodes:
[{item:new outlineItem("Introduction", "http://www.w3.org/TR/html401/interact/scripts.html#h-18.1")},
{item:new outlineItem("Designing Documents for Scripts", "http://www.w3.org/TR/html401/interact/scripts.html#h-18.2"),
childNodes:
[{item:new outlineItem("SCRIPT Element", "http://www.w3.org/TR/html401/interact/scripts.html#h-18.2.1")},
{item:new outlineItem("Specifying the Scripting Language", "http://www.w3.org/TR/html401/interact/scripts.html#h-18.2.2"),
childNodes:
[{item:new outlineItem("Default Language", "http://www.w3.org/TR/html401/interact/scripts.html#h-18.2.2.1")},
{item:new outlineItem("Local Language Declaration", "http://www.w3.org/TR/html401/interact/scripts.html#h-18.2.2.2")},
{item:new outlineItem("References to HTML Elements", "http://www.w3.org/TR/html401/interact/scripts.html#h-18.2.2.3")}
]},
{item:new outlineItem("Intrinsic Events", "http://www.w3.org/TR/html401/interact/scripts.html#h-18.2.3")},
{item:new outlineItem("Dynamic Document Modification", "http://www.w3.org/TR/html401/interact/scripts.html#h-18.2.4")}
]},
{item:new outlineItem("Designing for Unscriptable Clients", "http://www.w3.org/TR/html401/interact/scripts.html#h-18.3"),
childNodes:
[{item:new outlineItem("NOSCRIPT Element", "http://www.w3.org/TR/html401/interact/scripts.html#h-18.3.1")},
{item:new outlineItem("Hiding Scripts from Clients", "http://www.w3.org/TR/html401/interact/scripts.html#h-18.3.2")}
]}
]}
]
};
/**********************************
TOGGLE DISPLAY AND ICONS
***********************************/
// invert item state (expanded to/from collapsed)
function swapState(currState, currVal, n) {
var newState = currState.substring(0,n);
newState += currVal ^ 1 // Bitwise XOR item n;
newState += currState.substring(n+1,currState.length);
return newState;
}
// retrieve matching version of 'minus' images
function getExpandedWidgetState(imgURL) {
if (imgURL.indexOf("Start") != -1) {
return expandedWidgetStart.src;
}
if (imgURL.indexOf("End") != -1) {
return expandedWidgetEnd.src;
}
return expandedWidget.src;
}
// retrieve matching version of 'plus' images
function getCollapsedWidgetState(imgURL) {
if (imgURL.indexOf("Start") != -1) {
return collapsedWidgetStart.src;
}
if (imgURL.indexOf("End") != -1) {
return collapsedWidgetEnd.src;
}
return collapsedWidget.src;
}
// toggle an outline mother entry, storing new state value;
// invoked by onclick event handlers of widget image elements
function toggle(img, blockNum) {
var newString = "";
var expanded, n;
// modify state string based on parameters from IMG
expanded = currState.charAt(blockNum);
currState = swapState(currState, expanded, blockNum);
// dynamically change display style
if (expanded == "0") {
document.getElementById("OLBlock" + blockNum).style.display = "block";
img.src = getExpandedWidgetState(img.src);
} else {
document.getElementById("OLBlock" + blockNum).style.display = "none";
img.src = getCollapsedWidgetState(img.src);
}
}
function expandAll() {
var newState = "";
while (newState.length < currState.length) {
newState += "1";
}
currState = newState;
initExpand();
}
function collapseAll() {
var newState = "";
while (newState.length < currState.length) {
newState += "0";
}
currState = newState;
initExpand();
}
/*********************************
OUTLINE HTML GENERATION
**********************************/
// apply default expansion state from outline's header
// info to the expanded state for one element to help
// initialize currState variable
function calcBlockState(n) {
// get default expansionState data
var expandedData = (expansionState.length > 0) ? expansionState.split(",") : null;
if (expandedData) {
for (var j = 0; j < expandedData.length; j++) {
if (n == expandedData[j] - 1) {
return "1";
}
}
}
return "0";
}
// counters for reflexive calls to drawOutline()
var currID = 0;
var blockID = 0;
// generate HTML for outline
function drawOutline(ol, prefix) {
var output = "";
var nestCount, link, nestPrefix, lastInnerNode;
prefix = (prefix) ? prefix : "";
for (var i = 0; i < ol.childNodes.length ; i++) {
nestCount = (ol.childNodes[i].childNodes) ? ol.childNodes[i].childNodes.length : 0;
output += "<div class='OLRow' id='line" + currID++ + "'>\n";
if (nestCount > 0) {
output += prefix;
output += "<img id='widget" + (currID-1) + "' src='" + ((i == ol.childNodes.length-1 && blockID != 0) ? collapsedWidgetEnd.src : (blockID == 0) ? collapsedWidgetStart.src : collapsedWidget.src);
output += "' height=" + widgetHeight + " width=" + widgetWidth;
output += " title='Click to expand/collapse nested items.' onClick='toggle(this," + blockID + ")'> ";
link = (ol.childNodes[i].item.uri) ? ol.childNodes[i].item.uri : "";
if (link) {
output += "<a href='" + link + "' class='itemTitle' title='" +
link + "' target='" + displayTarget + "'>" ;
} else {
output += "<a class='itemTitle' title='" + link + "'>";
}
output += "<span style='position:relative; top:-3px; height:11px'>" + ol.childNodes[i].item.text + "</span></a>";
currState += calcBlockState(currID-1);
output += "<span class='OLBlock' blocknum='" + blockID + "' id='OLBlock" + blockID++ + "'>";
nestPrefix = prefix;
nestPrefix += (i == ol.childNodes.length - 1) ?
"<img src='" + emptySpace.src + "' height=" + widgetHeight + " width=" + widgetWidth + ">" :
"<img src='" + chainSpace.src + "' height=" + widgetHeight + " width=" + widgetWidth + ">"
output += drawOutline(ol.childNodes[i], nestPrefix);
output += "</span></div>\n";
} else {
output += prefix;
output += "<img id='widget" + (currID-1) + "' src='" + ((i == ol.childNodes.length - 1) ? nodeWidgetEnd.src : nodeWidget.src);
output += "' height=" + widgetHeight + " width=" + widgetWidth + ">";
link = (ol.childNodes[i].item.uri) ? ol.childNodes[i].item.uri : "";
if (link) {
output += " <a href='" + link + "' class='itemTitle' title='" +
link + "' target='" + displayTarget + "'>";
} else {
output += " <a class='itemTitle' title='" + link + "'>";
}
output += "<span style='position:relative; top:-3px; height:11px'>" + ol.childNodes[i].item.text + "</span></a>";
output += "</div>\n";
}
}
return output;
}
/*********************************
OUTLINE INITIALIZATIONS
**********************************/
// expand items set in expansionState var, if any
function initExpand() {
for (var i = 0; i < currState.length; i++) {
if (currState.charAt(i) == 1) {
document.getElementById("OLBlock" + i).style.display = "block";
} else {
document.getElementById("OLBlock" + i).style.display = "none";
}
}
}
// initialize first time -- invoked onload
function initExpMenu(xFile) {
// wrap whole outline HTML in a span
var olHTML = "<span id='renderedOL'>" + drawOutline(olData) + "</span>";
// throw HTML into 'content' div for display
document.getElementById("content").innerHTML = olHTML;
initExpand();
}
</script>
</head>
<body style="font-family:Arial, sans-serif" onload="initExpMenu()">
<h1 style="font-size:1.2em; font-weight:bold">Expandable Navigation Menu</h1>
<hr />
<div id="content"></div>
</body>
</html>
|