// treeView.js

// Name:     DHTML TreeView Script
// Purpose:  Provide tree view control for site navigation
//           In this implementation the top Browser window contains two frames
//           leftFrame: tree view doc containing pairs of folder fields and hyperlink fields
//           rightFrame: Site Content doc containing hyperlink fields with onClick=Sync() terms
//           Based on Marcelino Alves Martins 1997 "Folder-Tree" script 
// Rev:      05NOV01 DMH Original
//           08NOV01 DMH Use setTimeout to avoid crash in IE5
//           14NOV01 DMH Use Tree object with AddNode method to build tree
//           30NOV05 DMH Include target window option in Node definitions
//                       If Node target window = new window then sync Treeview to Node parent
//                       Ensure only one subfolder tree open at a time
//           02DEC05 DMH Use mouseovers to highlight current treeview node

var TreeFrame="fraLeftFrame"       // name of browser window frame to hold tree doc
var TargetFrame = "fraRightFrame"  // name of browser window frame for navigation target 
var WaitTime=500                   // delay time (ms) before redrawing left frame
var OneSubTreeOpen="Y"

var gTree			// Tree Object 
var gDoc			// left frame Document Object

// Build Tree of linked Node objects
function BuildTree()
{
 gTree = new Tree()
 with (gTree) {
 AddNode(0, "Home", "000_home.htm", "R")

 AddNode(1, "ACTAA Info", "500_state.htm", "R")
  AddNode(2, "Contacts", "510_names.htm", "R")
  AddNode(2, "Meetings", "540_mtgs.htm", "R")
  AddNode(2, "Wings", "572_wings.pdf", "N")
  AddNode(2, "Services", "530_svc.htm", "R")
  AddNode(2, "Constitution", "actaadocs/ACTAA Constitution & By Laws.pdf", "N")

 AddNode(1, "Events", "200_events.htm", "R")
  AddNode(2, "Meetings", "201_mtgs.htm", "R")
  AddNode(2, "Events", "210_event_2006.htm", "R")
  AddNode(2, "Champs", "520_champ.htm", "R")
  AddNode(2, "Comp Results", "220_res.htm", "R")

 AddNode(1, "Club Info", "400_club.htm", "R")
  AddNode(2, "Contacts", "410_clubs.htm", "R")
  AddNode(2, "Location Maps", "420_maps.htm", "R")
   AddNode(3, "BMAC<BR>Mitchell", "421_bmap.htm", "R")
   AddNode(3, "CMAC<BR>Symonston", "422_cmap.htm", "R")
   AddNode(3, "GMSF<BR>Goulburn", "423_gmap.htm", "R")
   AddNode(3, "NSFC<BR>Tharwa", "424_nmap.htm", "R")
   AddNode(3, "PMAC<BR>Cooma", "427_pmap.htm", "R")
   AddNode(3, "QMAC<BR>Mills X", "425_qmap.htm", "R")
   AddNode(3, "YMAC<BR>Yass", "426_ymap.htm", "R")
  AddNode(2, "Ground-level Views", "430_clubs.htm", "R")
   AddNode(3, "BMAC", "431_bmac.htm", "R")
   AddNode(3, "CMAC", "433_cmac.htm", "R")
   AddNode(3, "GMSF", "432_gmsf.htm", "R")
   AddNode(3, "NSFC", "434_nsfc.htm", "R")
   AddNode(3, "QMAC", "435_qmac.htm", "R")
   AddNode(3, "YMAC", "436_ymac.htm", "R")
  AddNode(2, "Aerial Views", "440_satimage.htm", "R")
   AddNode(3, "BMAC", "441_bmac.htm", "R")
   AddNode(3, "CMAC", "442_cmac.htm", "R")
   AddNode(3, "GMSF", "443_gmsf.htm", "R")
   AddNode(3, "LGSL", "448_lgsl.htm", "R")
   AddNode(3, "NSFC", "444_nsfc.htm", "R")
   AddNode(3, "QMAC", "445_qmac.htm", "R")
   AddNode(3, "YMAC", "446_ymac.htm", "R")
   AddNode(3, "PMAC", "447_pmac.htm", "R")

 AddNode(1, "Pix", "300_pix.htm", "R")
  AddNode(2, "People and Planes", "310_peopl.htm", "R")
  AddNode(2, "Club Fields - Ground", "430_clubs.htm", "R")
  AddNode(2, "Club Fields - Air", "440_satimage.htm", "R")
 
 AddNode(1, "MAAA Info", "600_national.htm", "R")
  AddNode(2, "General Model Rules", "mop014.pdf", "N")
  AddNode(2, "No Internal Navigation Systems", "mop044.pdf", "N")
  AddNode(2, "Display of Model Aircraft Procedure", "mop019.pdf", "N")
  AddNode(2, "Incident Report", "form010.pdf", "N")
  AddNode(2, "Visitor Insurance", "mop042.pdf", "N")
  AddNode(2, "Insurance Conditions", "mop057.pdf", "N")
  AddNode(2, "Frequency's", "mop013.pdf", "N")
  AddNode(2, "Indoor Flying", "mop059.pdf", "N")
  
 AddNode(1, "Gov Regs", "800_regs.htm", "R")
  AddNode(2, "Air Safety", "810_airsafety.htm", "R")
  AddNode(2, "Noise Pollution", "820_noise.htm", "R")
  AddNode(2, "Radio Spectrum", "830_radio.htm", "R")

 AddNode(1, "Web Stuff", "700_web.htm", "R")
  AddNode(2, "Web Links", "710_links.htm", "R")
  AddNode(2, "Feedback", "740_fb.htm", "R")
 }
}

// Node object constructor
function Node(id,desc,url,targ) 
{
   this.ID=id			// 1,2,...
   this.Type="D"		// "F" (Folder) or "D" (Document)
   this.Status="C"		// "O" (Open) or "C" (Closed)
   this.Desc=desc		// Subject Desc
   this.URL=url			// Subject URL
   this.Window=targ             // Target window for linked doc "R" (right frame)  or "N" (new)
   this.Parent=0                // ptr to parent node
   this.ChildCount=0		// child node count 0,1,2...
   this.Children=new Array      // ptrs to child nodes 
 
   this.AdoptChild=AdoptChild	// method
} 

// Node object method - link Child node to parent node
function AdoptChild(ChildNode)    
{
   this.Children[this.ChildCount]=ChildNode
   this.ChildCount++
   this.Type="F"                // convert D-node to F-node
}

// Tree object constructor
function Tree()
{
   this.Root =0				// Pointer to root Node
   this.HilitedID = 0                 	// node id of hilighted node in tree
   this.IDCounter = 0			// next node id
   this.RightmostNode = new Array	// Pointers to right-most node at each level of tree

   this.AddNode=AddNode			// methods
   this.FindNode=FindNode		
   this.FindNodeURL=FindNodeURL			
   this.CloseNodes=CloseNodes			
   this.OpenNodes=OpenNodes			
}

// Tree object method - add node to tree as right-most node at level lev
function AddNode(lev,desc,url,targ)
{
   var newNode
   var parentNode

   this.IDCounter++				// get unique ID for new node
   newNode = new Node(this.IDCounter,desc,url,targ)	// construct new node
   if (lev == 0)
      this.Root=newNode                 	// link new node as root node
   else
   {
      parentNode = this.RightmostNode[lev-1]	// fetch ptr to right-most node at lev-1
      parentNode.AdoptChild(newNode)      	// link new node as right-most child of this parent
      newNode.Parent = parentNode               // ptr to parent
   }
   this.RightmostNode[lev]=newNode      	// update ptr to right-most node at this lev
}

// Tree object method - recursive tree search for node with ID=targetID
function FindNode(thisNode,targetID)
{
   var i
   var r

   if (thisNode.ID == targetID)
      return thisNode
   else
      {
        for (i = 0; i < thisNode.ChildCount; i++)
        {
          r = FindNode(thisNode.Children[i],targetID)
          if (r != 0) return(r)   
        }
      return(0)
      }   
}

// Tree object method - recursive tree search for node with URL=targetURL
function FindNodeURL(thisNode,targetURL)
{
   var i
   var r

   if (thisNode.URL == targetURL)
      return thisNode
   else
   {
      for (i = 0; i < thisNode.ChildCount; i++ )
        {
          r = FindNodeURL(thisNode.Children[i],targetURL)
          if (r != 0) return(r)
        }
      return(0)
   }   
}

// Tree object method - close all Nodes in subtree starting at thisNode
function CloseNodes(thisNode)
{
   var i

   thisNode.Status = "C"
   for (i = 0;  i < thisNode.ChildCount; i++)
      {CloseNodes(thisNode.Children[i])} 
}

// Tree object method - Open all Nodes in path to node with ID=targetID
function OpenNodes(thisNode,targetID)
{
   var i
   var r

   if (thisNode.ID == targetID)
      {
         thisNode.Status = "O"		// open leaf folder
         return(1)			// stop recursion
      }
   else
      {
         for (i = 0; i < thisNode.ChildCount; i++)
         {
            r =OpenNodes(thisNode.Children[i],targetID)
            if (r == 1)			// open branch folder
               { thisNode.Status = "O"; return(1) }          
         }
         return(0)
      }   
}
   
// draw a new tree in the left frame of the Browser
function RedrawTree()
{
   with (gDoc) {
   //clear()
   write("<head>\n")
   write("<style type=text/css>\n")
   write("TD {color:Black; font-family:Verdana; font-size:8pt}\n" );
   write("</style>\n")
   write("</head>\n")
   write("<body bgColor='#E0F0FF' leftmargin=4  topmargin=16>\n")
   write("<p>\n")
   RedrawNode(gTree.Root,0)
   write("<p style='font-family: Verdana; font-size: 7pt;'>Click folder icon<br>to see topics then <BR>\n")
   write("click document icon <br>to read topic...<br>or click	 shortcut icon\n")
   write("<p><table cellspacing=0 cellpadding=0>\n")
   write("<tr onMouseOver=this.style.cursor='hand' onClick=top.GoTo('710_links.htm')>\n")
   write("<td><img src=img/new.gif>&nbsp;</td><td ID=Enew onMouseOver=top.NF(-1,'T') onMouseOut=top.NF(-1,'F')>Quick Links</td></tr>\n")
   write("<tr onMouseOver=this.style.cursor='hand' onClick=top.GoTo('130_weather.htm')>\n")
   write("<td><img src=img/weather.gif>&nbsp;</td><td ID=Eweather onMouseOver=top.NF(-2,'T') onMouseOut=top.NF(-2,'F')>Weather</td></tr>\n")
   write("<tr onMouseOver=this.style.cursor='hand' onClick=top.GoTo('050_search.htm')>\n")
   write("<td><img src=img/search.gif></td><td ID=Esearch  onMouseOver=top.NF(-3,'T') onMouseOut=top.NF(-3,'F')>Search</td></tr>\n")
   write("</table>\n")
   write("</body>\n")
   close()
   }
}

// generate HTML table statement to represent a node of tree
//   <table cellspacing=0 cellpadding=0 onClick=top.NodeClick({P2}) 
//              onMouseOver=top.NF({P2},"T") onMouseOut=top.NF({P2},"F")>
//    <tr>
//     <td width={8*lev}>&nbsp</td> <td><img src={P1}></td> <td ID=E{P2}>{P3}</td>
//    <tr>
//   </table
function RedrawNode(thisNode, lev)
{
   var i
   var P1  // folder/doc image
   var P2  // ID of node in tree
   var P3  // link text

   // icon img value
   if (thisNode.Type == "F") 
         if (thisNode.Status == "O")  
            P1="img/tvopen.gif "  
         else 
            P1="img/tvclosed.gif "
   else
      P1="img/tvdoc.gif "

   // icon onclick value
   P2=thisNode.ID   

   // link text value
   if (thisNode.ID == gTree.HilitedID)
      P3="<b>"+thisNode.Desc +"</b>"	// set hilite
   else
      P3=thisNode.Desc

   // start
   gDoc.write("<table cellspacing=0 cellpadding=0 >\n" +
    "<tr onMouseOver=this.style.cursor='hand' onClick=top.NodeClick(" + P2 + ")>\n")

   // indenting field
   if (lev > 0)
     gDoc.write("<td width=" + (8*lev) + ">&nbsp</td>\n")

   // icon field
   gDoc.write("<td valign=top><img src=" + P1 + "></td>\n")

   // text field 
   gDoc.write("<td ID=E" + P2 + " onMouseOver=top.NF(" + P2 + ",'T') onMouseOut=top.NF(" + P2 + ",'F')>" + P3 + "</td>\n")

   // end
   gDoc.write("</tr></table>\n\n")

   // create sub nodes
   if (thisNode.Type == "F" && thisNode.Status == "O") 
      {  
        lev++
         for (i = 0; i < thisNode.ChildCount; i++) 
            RedrawNode(thisNode.Children[i], lev)
      }
}

// user clicked on Icon field in tree view
// perform right frame navigation
// revise tree view
function NodeClick(clickedNodeID)
{
   var clickedNode
   var parentNode
   var openArg

   clickedNode=FindNode(gTree.Root,clickedNodeID)
   if (clickedNode != 0)
   {
      if (clickedNode.URL != "")	// perform navigation
        if (clickedNode.Window == "R")  // open target doc in right frame
          top.fraRightFrame.window.location.href=clickedNode.URL
        else {	
	  // open parent doc in main window
          parentNode=clickedNode.Parent
          clickedNodeID=parentNode.ID 					// left frame
          top.fraRightFrame.window.location.href=parentNode.URL  	// right frame
	  // open target doc in new window
	  openArg="toolbar=yes,status=yes,width=800,height=600"
	  window.open(clickedNode.URL,"",openArg)
        }

      gTree.HilitedID=clickedNodeID	// move hilite

      if (clickedNode.Type == "F" )
      {
         if (clickedNode.Status == "O")	// click on Open Folder Node 
         { 
            CloseNodes(clickedNode)	// close subtree
            if (clickedNode.ID == 1 )	// special case for home folder
               clickedNode.Status = "O"
         }else {			// click on Closed Folder Node
            if (OneSubTreeOpen=="Y"){
             CloseNodes(gTree.Root)			// collapse entire tree
             OpenNodes(gTree.Root,gTree.HilitedID)	// open path to clicked folder
            }else{
             clickedNode.Status = "O"			// open clicked folder
            }
         }
      }

      window.setTimeout("RedrawTree()",WaitTime) // show new tree	
   }
}

// user clicked on hyperlink (A-tag) in either left or right frame document
// browser is currently performing right frame navigation to href=targetURL
// revise tree view
function Sync(targetURL)
{
   var targetNode

   targetNode=FindNodeURL(gTree.Root,targetURL)	// find new doc's node
   if (targetNode != 0)
   {
      gTree.HilitedID = targetNode.ID		// move hilite
      CloseNodes(gTree)				// collapse entire tree
      OpenNodes(gTree.Root,gTree.HilitedID)	// open path to current node
      window.setTimeout("RedrawTree()",WaitTime) // show new tree	
   }
}

//Initialise the left frame
function InitTree()
{
   var browserName 	
   var browserVersion
	
   browserName = navigator.appName;
   browserVersion = parseFloat(navigator.appVersion); 
   if ((browserName == "Microsoft Internet Explorer" || browserName == "Netscape") 
   && browserVersion >3)
   {
      BuildTree()
      gDoc = top.fraLeftFrame.window.document    
      NodeClick(1)   // open home folder and draw the initial tree view
   }
   else
   {
      window.alert("To view this site upgrade your Browser to Microsoft IE 4/Netscape 4 or later")
   }
}

function GoTo(URL)
// called by left frame shortcuts
{
   var targetNode
   top.fraRightFrame.window.location.href=URL
   targetNode = FindNodeURL(gTree.Root,URL)
   CloseNodes(gTree.Root)
   OpenNodes(gTree.Root,targetNode.ID)
   gTree.HilitedID = targetNode.ID
   window.setTimeout("RedrawTree()",WaitTime)	
}

function NF(n,tf){
//highlight focussed treeview node in left frame
  var e
  if(n==-1)
    e=top.fraLeftFrame.window.document.getElementById("Enew")
  else if (n==-2)
    e=top.fraLeftFrame.window.document.getElementById("Eweather")
  else if (n==-3)
    e=top.fraLeftFrame.window.document.getElementById("Esearch")
  else
   e=top.fraLeftFrame.window.document.getElementById("E"+n);
  e.style.backgroundColor=(tf=="T")?"#E0E0E0":"#E0F0FF"
 }

//END