/*
   New Perspectives on JavaScript
   Tutorial 10
   Tutorial Case

   Author: Krystin Scott
   Date:   11/5/09

   Filename: toc.js

   Global Variables:
   sections
      An array contain the HTML elements used as section headings in the historic document

   Functions List:
   levelNum(node)
      Returns the level number of the object node. If the object node does not
      represent a section heading, the function returns the value -1.

   eventSource(e)
      Returns the source of an event under either the W3C or Internet Explorer
      event models

   makeTOC()
      Generate a table of contents as a nested list for the contents of the "doc" 
      element within the current Web page. Store the nested list in the "toc"
      element.

   createList()
      Goes through the child nodes of the "doc" element searching for section headings.
      When it finds a section heading, a new entry is added to the table of contents

   expandCollapse()
      Expands and collapse the content of the table of contents and the historic
      document

   expandCollapseDoc()
      Goes through the child nodes of the "doc" element determining which elements to
      hide and which elements to display


*/

var sections = new Array("h1","h2","h3","h4","h5","h6");

function levelNum(node) {
   for (var i=0; i<sections.length; i++) {
      if (node.nodeName==sections[i].toUpperCase()) return i;
   }
   return -1;
}

function eventSource(e) {
   var IE = document.all ? true:false;
   var DOM = document.addEventListener ? true: false;
   if (IE) return event.srcElement;
   else if (DOM) return e.currentTarget;
}

function makeTOC() {
TOC = document.getElementById("toc");
TOC.innerHTML="<h1>Table of Contents</h1>";
TOCList = document.createElement("ol");
TOC.appendChild(TOCList);

historyDoc = document.getElementById("doc");
createList(TOCList);
}

function createList(list) {
var prevLevel = 0;
var headNum = 0;
for (var n=historyDoc.firstChild; n!=null; n=n.nextSibling) {
nodeLevel = levelNum(n);
if (nodeLevel != -1) {

// insert ids for the section headings
headNum++;
if (n.id == "") {
sectionId = "head"+headNum;
n.id = sectionId;
}
else sectionId = n.id;

listItem = document.createElement("li");
listItem.id="TOC"+sectionId;
linkItem = document.createElement("a");
linkItem.innerHTML = n.innerHTML;
linkItem.href="#" +sectionId;
listItem.appendChild(linkItem);

if (nodeLevel == prevLevel) {
// append listitem to the list
list.appendChild(listItem);
}
else if (nodeLevel > prevLevel){
//append listitem to a new list
//change the prevLevel value
newList = document.createElement("ol");
newList.appendChild(listItem);
list.appendChild(newList);
list = newList;
prevLevel = nodeLevel;

//create and place the plus-minus box
plusMinusBox = document.createElement("span");
plusMinusBox.innerHTML="--";
plusMinusBox.onclick = expandCollapse;
prevListItem = list.previousSibling;
prevListItem.insertBefore(plusMinusBox, prevListItem.firstChild);
}
else if (nodeLevel < prevLevel) {
//append listitem to the list of that level
//change the prevLevel value
levelUp = prevLevel - nodeLevel;
for (j=1; j<=levelUp; j++) list=list.parentNode;
list.appendChild(listItem);
prevLevel = nodeLevel;
}
}
}
}
function expandCollapse(e) {
var plusMinusBox=eventSource(e);
if (plusMinusBox.innerHTML=="--") plusMinusBox.innerHTML="+";
else plusMinusBox.innerHTML="==";

var nestedList = plusMinusBox.parentNode.nextSibling;
if (nestedList.style.display=="") nestedList.style.display="none";
else nestedList.style.display="";

expandCollapseDoc();
}

function expandCollapseDoc() {
historyDoc = document.getElementById("doc");
for (n=historyDoc.firstChild; n!=null; n=n.nextSibling) {
nodeLevel = levelNum(n);
if (nodeLevel != -1) {
//set the display status for the heading
displayStatus = "";
TOCitem = document.getElementById("TOC"+n.id);
for(l=nodeLevel; l >= 0; l--) {
TOCitem = TOCitem.parentNode;
if (TOCitem.style.display == "none") {displayStatus = "none";
break;}
}
}
if (n.nodeType==1) {
// apply the display status to the element
n.style.display = displayStatus;
}
}
}