<!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.11.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 language="JavaScript" 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"; // XML document object var xDoc;
/********************************** 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) { var ol = xDoc.getElementsByTagName("body")[0]; var outlineLen = ol.getElementsByTagName("outline").length; // get OPML expansionState data var expandElem = xDoc.getElementsByTagName("expansionState")[0]; var expandedData = (expandElem.childNodes.length) ? expandElem.firstChild.nodeValue.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; ol = (ol) ? ol : xDoc.getElementsByTagName("body")[0]; prefix = (prefix) ? prefix : ""; if (ol.childNodes[ol.childNodes.length - 1].nodeType == 3) { ol.removeChild(ol.childNodes[ol.childNodes.length - 1]); } for (var i = 0; i < ol.childNodes.length ; i++) { if (ol.childNodes[i].nodeType == 3) { continue; } if (ol.childNodes[i].childNodes.length > 0 && ol.childNodes[i].childNodes[ol.childNodes[i].childNodes.length - 1].nodeType == 3) { ol.childNodes[i].removeChild(ol.childNodes[i].childNodes[ol.childNodes[i].childNodes.length - 1]); } nestCount = ol.childNodes[i].childNodes.length; 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) ? 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].getAttribute("uri")) ? ol.childNodes[i].getAttribute("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].getAttribute("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].getAttribute("uri")) ? ol.childNodes[i].getAttribute("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].getAttribute("text") + "</span></a>"; output += "</div>n"; } } return output; }
/********************************* OUTLINE INITIALIZATIONS **********************************/ // expand items set in expansionState OPML tag, 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"; } } }
function finishInit() { // get outline body elements for iteration and conversion to HTML var ol = xDoc.getElementsByTagName("body")[0]; // wrap whole outline HTML in a span var olHTML = "<span id='renderedOL'>" + drawOutline(ol) + "</span>"; // throw HTML into 'content' div for display document.getElementById("content").innerHTML = olHTML; initExpand(); }
function continueLoad(xFile) { xDoc.load(escape(xFile)); // IE needs this delay to let loading complete before reading its content setTimeout("finishInit()", 300); }
// verify that browser supports XML features and load external .xml file function loadXMLDoc(xFile) { if (document.implementation && document.implementation.createDocument) { // this is the W3C DOM way, supported so far only in NN6 xDoc = document.implementation.createDocument("", "theXdoc", null); } else if (typeof ActiveXObject != "undefined") { // make sure real object is supported (sorry, IE5/Mac) if (document.getElementById("msxml").async) { xDoc = new ActiveXObject("Msxml.DOMDocument"); } } if (xDoc && typeof xDoc.load != "undefined") { // Netscape 6+ needs this delay for loading; start two-stage sequence setTimeout("continueLoad('" + xFile + "')", 50); } else { var reply = confirm("This example requires a browser with XML support, such as IE5+/Windows or Netscape 6+.n nGo back to previous page?"); if (reply) { history.back(); } } }
// initialize first time -- invoked onload function initXMLOutline(xFile) { loadXMLDoc(xFile); }
</script> </head> <body onload="initXMLOutline('SpecOutline.xml')"> <h1 style="font-size:1.2em; font-weight:bold">Expandable Navigation Menu (OPML)</h1> <hr /> <div id="content"></div> <!-- Try to load Msxml.DOMDocument ActiveX to assist support verification --> <object id="msxml" WIDTH="1" HEIGHT="1" classid="CLSID:2933BF90-7B36-11d2-B20E-00C04F983E60" ></object> </body> </html>
|