// Copyright (c) 2005 Rowley Associates Limited.

var initialised = false;
var imgLeaf = new Image();
var imgBranchOpen = new Image();
var imgBranchClosed = new Image();
var currentNode;
var currentPreviousNode;
var currentNextNode;
var currentUpNode;
var selectedLink;

function
pathsMatch(p1, p2)
{
  var p1l = p1.length;
  var p2l = p2.length;
  while (p1l-- && p2l--)
    {
      if(p1[p1l] != "." && p2[p2l] != "." && p1[p1l] != p2[p2l])
        return false;
    }
  return true;
}

function
findFirstElement(node, tag)
{
  var elements = node.getElementsByTagName(tag);
  return elements[0];
}

function      
getChild(node, tagName)
{       
  node = node.firstChild;
  while (node && node.tagName != tagName)
    node = node.nextSibling;
  return node;
}

function
previousNode(node)
{
  do
    { 
      var node2 = node.previousSibling;
      while (node2 && node2.tagName != "LI")
        node2 = node2.previousSibling;
      if (node2)
        { 
          var elements = node2.getElementsByTagName("LI");
          if (elements.length > 0)
            node2 = elements[elements.length - 1];
        }
      
      if (!node2)
        { 
          node2 = node.parentNode;
          while (node2 && node2.tagName != "LI")
            node2 = node2.parentNode;
        }
      node = node2;
    }
  while (node && node.tagName == "LI" && !getChild(node, "A"));
  return node;
}

function
nextNode(node)
{
  do
    {
      var node2 = node.getElementsByTagName("LI").item(0);
      if (!node2)
        {
          node2 = node.nextSibling;
          while (node2 && node2.tagName != "LI")
        node2 = node2.nextSibling;
        }
      while (!node2 && node.parentNode)
        {
          node = node.parentNode;
          node2 = node.nextSibling;
          while (node2 && node2.tagName != "LI")
            node2 = node2.nextSibling;
        }
      node = node2;
    }
  while (node && node.tagName == "LI" && !getChild(node, "A"));
  return node;
}

function    
upNode(node)
{
  do
    {
      node = node.parentNode;
    }
  while (node && node.tagName != "LI");
  return node;
}

function
initialiseNode(node)
{
  if (node.tagName == "LI" && !node.isinitialised)
    {
      if (node.className == "branch")
        node.style.backgroundImage = "url(" + imgBranchClosed.src + ")"; 
      else if (node.className == "leaf")
        node.style.backgroundImage = "url(" + imgLeaf.src + ")"; 
      node.isinitialised = true;
    }
}

function
initialiseChildNodes(node)
{
  node = findFirstElement(node, "LI");
  while (node)
    {
      initialiseNode(node);
      node = node.nextSibling;
    }
}

function
toggleBranch(node)
{
  /* Toggle the open/closed status of a branch */
  if (node.isopen)
    {
      node.isopen = false;
      node.style.backgroundImage = "url(" + imgBranchClosed.src + ")";
      node = findFirstElement(node, "UL");
      if (node)
        node.style.display = "none";
    }
  else
    {
      node.isopen = true;
      node.isinitialised = true;
      node.style.backgroundImage = "url(" + imgBranchOpen.src + ")";
      node = findFirstElement(node, "UL");
      if (node)
        node.style.display = "block";
      initialiseChildNodes(node);
    }
}

function
getEventTarget(event)
{
  var target;
  /* Get the event */
  if (!event)
    event = window.event;

  /* Get the source of the event */
  if (event.target)
    target = event.target;
  else if (event.srcElement)
    target = event.srcElement;
  if (target.nodeType == 3) // defeat Safari bug
    target = target.parentNode;
  return target;
}

function
toggleBranchEvent(event)
{
  target = getEventTarget(event);
  if (this == target)
    toggleBranch(this);
  return true;
}

function
linkClickedEvent(event)
{
  target = getEventTarget(event);
  while (target && target.tagName != "A")
    target = target.parentNode;
  selectedLink = target;
}

function
previousNodeClickedEvent(event)
{
  if (currentPreviousNode)
    selectedLink = findFirstElement(currentPreviousNode, "A");
}

function
nextNodeClickedEvent(event)
{
  if (currentNextNode)
    selectedLink = findFirstElement(currentNextNode, "A");
}

function
upNodeClickedEvent(event)
{
  if (currentUpNode)
    selectedLink = findFirstElement(currentUpNode, "A");
}

function
openBranches(node)
{
  while (node)
    {
      if (node.tagName == "LI" && node.className == "branch" && !node.isopen)
        toggleBranch(node);
      node = node.parentNode;
    }
}

function
closeBranches(node)
{
  while (node)
    {
      if (node.tagName == "LI" && node.className == "branch" && node.isopen)
        toggleBranch(node);
      node = node.parentNode;
    }
}

function
compareAndMarkCurrentNode(element, path1, stripAnchors)
{
  href = element.getAttribute("href");
  if (stripAnchors)
    href = href.split('#')[0];
  if (href)
    {
      path2 = href.split('/');
      if (pathsMatch(path1, path2))
        {
          element = element.parentNode;
          /* Mark the current node */
          while (element)
            {
              if (element.tagName == "LI")
                {
                  element.id = "currentnode";
                  return element;
                }
              element = element.parentNode;
            }
        }
    }
  return null;
}

function
findAndMarkCurrentNode(tree, currentURL, stripAnchors)
{
  // Check to see if we can work out the current item.
  if (!currentURL)
    currentURL = location.href;
  path = currentURL.split('/');
  if (selectedLink)
    {
      var node = compareAndMarkCurrentNode(selectedLink, path, stripAnchors);
      selectedLink = null;
      if (node)
        return node;
    }
  var elements = tree.getElementsByTagName("A");
  for (var i = 0; i < elements.length; ++i)
    {
      var node = compareAndMarkCurrentNode(elements[i], path, stripAnchors);
      if (node)
        return node;
    }
  return null;
}

function
updateCurrentNode(currentURL)
{
  var elements = document.getElementsByTagName("div");
  for (var i = 0; i < elements.length; ++i)
    {
      var element = elements[i];
      if (element.id == "tree_js")
        {
          if (currentNode)
            {
              closeBranches(currentNode);
              currentNode.id = "";
            }
          currentNode = findAndMarkCurrentNode(element, currentURL, false);
          if (!currentNode)
            currentNode = findAndMarkCurrentNode(element, currentURL.split('#')[0], true);
          if (currentNode)
            {
              currentNextNode = nextNode(currentNode);
              currentPreviousNode = previousNode(currentNode);
              currentUpNode = currentNode;
              do
                {
                  currentUpNode = upNode(currentUpNode);
                }
              while (currentUpNode && !getChild(currentUpNode, "A"));
              openBranches(currentNode);
              if (currentNode.scrollIntoView)
                currentNode.scrollIntoView();
              else
                window.scrollTo(currentNode.offsetLeft, currentNode.offsetTop);
            }
        }
    }
}

function
initialiseRootNodes(tree)
{
  node = findFirstElement(tree, "UL");
  while (node)
    {
      node.style.display = "block";
      var elements = node.getElementsByTagName("UL");
      for (var i = 0; i < elements.length; ++i)
        elements[i].style.display = "none";
      node = node.nextSibling;
      while (node && node != "UL")
        node = node.nextSibling;
    }
  initialiseChildNodes(tree);
}

function
initialiseTree(tree, imagePadding)
{
  var elements = tree.getElementsByTagName("LI");
  for (var i = 0; i < elements.length; ++i)
    {
      var element = elements[i];
      // The user has two options, either they can mark the LI nodes with the
      // class "branch" or "leaf" to tell us the node type and save the script
      // some work or the script can work it out.
      var isBranch;
      if (element.className == "branch")
        {
          isBranch = true;
        }
      else if (element.className == "leaf")
        {
          isBranch = false;
        }
      else
        {
          // User has not specified whether node is a branch or a leaf, so
          // we'll work it out.
          isBranch = element.getElementsByTagName("LI").length > 0;
          if (element.getElementsByTagName("LI").length > 0)
            {
              isBranch = true;
              element.className = "branch";
            }
          else
            {
              isBranch = false;
              element.className = "leaf";
            }
        }
      if (isBranch)
        {
          element.onclick = toggleBranchEvent;
        }
      element.style.paddingLeft = imagePadding;
      element.style.backgroundRepeat = "no-repeat";
    }

  elements = tree.getElementsByTagName("A");
  for (var i = 0; i < elements.length; ++i)
    {
      var element = elements[i];
      element.onclick = linkClickedEvent;
    }

  initialiseRootNodes(tree);

  elements = tree.getElementsByTagName("LI");
  for (var i = 0; i < elements.length; ++i)
    {
      var element = elements[i];
      if (element.getAttribute("openOnStartup"))
        openBranches(element);
    }
}

function
initialiseTrees(leafImageURL, branchOpenImageURL, branchClosedImageURL, imagePadding)
{
  imgLeaf.src = leafImageURL;
  imgBranchOpen.src = branchOpenImageURL;
  imgBranchClosed.src = branchClosedImageURL;

  var elements = document.getElementsByTagName("div");
  for (var i = 0; i < elements.length; ++i)
    {
      var element = elements[i];
      if (element.id == "tree")
        {
          element.id = "tree_js";
          initialiseTree(element, imagePadding);
        }
    }
  initialised = true;
}

