//****************************************************************
//  CourseCenter Tree Script 1.0
//  (c) 2002-2005 Jonatan Söderberg, Framehouse AB
//  Changelog:
//  Modified:  2004-04-21 (Fixed id for NodeImg, Added FirstLevelFlat)
//  Added:    2004-05-26 (SiteMakerNode)
//  MODIFIED: 2011-05-18 (JJ) Rework to speed up the rendering process
//    Some user-agents (IE) prompts the user to abort the script due to slow
//    execution.
//****************************************************************

// DEBUG: Remove when in PRODUCTION!!!
//function CoreCommand() { console.log(arguments); }

function TextWriter() {
  var _text = ''; //, _mode = 0;
  //this.getMode = function() { return _mode; };
  //this.setMode = function(mode) { _mode = mode; };
  this.write = function(s) { _text += s; };
  this.toString = function() { return _text; };
}

var ccTrees = [], ua = window.navigator.userAgent.toLowerCase();

function ccTree(nodeObject){
  var textWriter = new TextWriter;
  this.textWriter = textWriter;
  this.Root = null;
  this.ID = -1;
  this.Name = "xxx";
  this.Nodes = [];
  this.RenderOptions = new ccTreeRenderOptions();
  this.yPos = 0;
  this.Init = function() {
    this.Root && this.Root.Init(null, '', 0);
  };
  this.Register = function(nodeObject) {
    var RootNode = new ccNode(nodeObject);
    RootNode.TreeObject = this;
    this.Root = RootNode;
    this.Name = "Tree" + ccTrees.length;
    this.ID = ccTrees.length;
    ccTrees[ccTrees.length] = this;
  };
  this.Render = function() {
    this.RenderBegin && this.RenderBegin();
    this.Root && this.Root.Render();
    this.RenderEnd && this.RenderEnd();
    //if (textWriter.getMode() == 0)
    document.write(textWriter.toString());
    this.Connect();
  };
  this.Connect = function() {
    //if(textWriter.getMode() != 0) return;
    if(this.Root)
      this.Root.Connect();

    this.Contract();
  };
  this.RenderBegin = null;
  this.RenderEnd = null;
  this.SelectedNodeIndex = -1;
  this.NodeRenderBegin = ccNodeRenderBegin;
  this.NodeRenderEnd = ccNodeRenderEnd;
  this.Expand = function() {
    var str = ""
    for(var i=0;i<this.Nodes.length;i++)
      if(this.Nodes[i].ChildNodes.length > 0)
        this.Nodes[i].Expand();
  };
  this.Contract = function() {
    for(var i=0;i<this.Nodes.length;i++)
      if(this.Nodes[i].ChildNodes.length > 0){
        for(var j=0;j<this.Nodes[i].ChildNodes.length;j++){
          this.Nodes[i].ChildNodes[j].Contract()
          if(this.Nodes[i] != this.Root) this.Nodes[i].Hide();
        }
      }else
        if(this.Nodes[i] != this.Root) this.Nodes[i].Hide();
    if(this.Root.NodeObject == null)
      this.Root.Expand();
  };

  //Initialize...
  this.Register(nodeObject);
}

function ccNode(nodeObject){
  this.NodeObject = nodeObject;
  this.TreeObject = null;
  this.Object = null;
  this.ID = -1;
  this.ClientID = -1;
  this.State = 1;
  this.Parent = null;
  this.ChildNodes = new Array;
  this.Tree = "";
  this.LastNode = true;
  this.innerHtml = "";
  this.ImgIcon = null;
  this.ImgNode = null;
  this.IconFolderOpen = "";
  this.IconFolderClose = "";
  this.IconDocument = "";
  this.Icon = "";
  this.CustomChildren = false;

  //Methods...
  this.Init = function(parentNode, strTree, isLast) {
    if(this.ID == -1) this.Register();
    this.LastNode = isLast;
    this.Tree = strTree;
    this.Parent = parentNode;
    var RenderOptions = this.TreeObject.RenderOptions;
    if(this.NodeObject != null){
      if(this.NodeObject.Init) this.NodeObject.Init();

      if(this.IconFolderOpen == "") this.IconFolderOpen = ((this.Icon != "")?(this.Icon):(((this.NodeObject.IconFolderOpen != null)?(this.NodeObject.IconFolderOpen):(this.TreeObject.RenderOptions.IconFolderOpen))));
      if(this.IconFolderClose == "") this.IconFolderClose = ((this.Icon != "")?(this.Icon):(((this.NodeObject.IconFolderClose != null)?(this.NodeObject.IconFolderClose):(this.TreeObject.RenderOptions.IconFolderClose))));
      if(this.IconDocument == "") this.IconDocument = ((this.Icon != "")?(this.Icon):(((this.NodeObject.IconDocument != null)?(this.NodeObject.IconDocument):(this.TreeObject.RenderOptions.IconDocument))));

      var strSpace = ((RenderOptions.HSpace > 0 || RenderOptions.VSpace > 0)?("<td><img src='" + RenderOptions.IconSpacer + "' height=" + (RenderOptions.IconDocumentHeight + RenderOptions.VSpace) + " width=" + RenderOptions.HSpace + "></td>"):(""));
      var strOnClick = [
        (RenderOptions.ShowNode
          ? ("<a href='#' onclick='ccNodeClick(" + nodeObject.ID + ", " + this.ID + ")'>")
          : ("")
        ),
        ((RenderOptions.ShowIcon && RenderOptions.ShowNode) ? "</a>": "")
      ];
      var RenderTree = true;
      if(this == this.TreeObject.Root)
        RenderTree = false
      else
        if(!RenderOptions.ShowThread && !RenderOptions.ShowNode)
          for(var i=0;i<this.TreeObject.Root.ChildNodes.length;i++)
            if(this == this.TreeObject.Root.ChildNodes[i])
              RenderTree = false;
      if(RenderTree)
        if(isLast){
          strNode = "<td>" + strOnClick[0] + "<img name='node_" + this.TreeObject.ID + "_" + this.ClientID + "' src='" + ((RenderOptions.ShowNode)?((this.HasChildren())?(RenderOptions.IconNodeCloseEnd):((RenderOptions.ShowThread)?(RenderOptions.IconThreadEnd):(RenderOptions.IconSpacer))):((RenderOptions.ShowThread)?(RenderOptions.IconThreadEnd):(RenderOptions.IconSpacer))) + "' width=" + RenderOptions.IconTreeWidth + " height=" + RenderOptions.IconTreeHeight + " border=0>" + strOnClick[1] + "</td>";
          this.innerHtml = strSpace + strTree + strNode + ((RenderOptions.VSpace > 0)?(strSpace):(""));
          strTree += "<td><img src='" + RenderOptions.IconSpacer + "' width=" + RenderOptions.IconTreeWidth + " height=" + RenderOptions.IconTreeHeight + "></td>" + ((RenderOptions.VSpace > 0)?(strSpace):(""));
        }else{
          strNode = "<td>" + strOnClick[0] + "<img name='node_" + this.TreeObject.ID + "_" + this.ClientID + "' src='" + ((RenderOptions.ShowNode)?((this.HasChildren())?(RenderOptions.IconNodeCloseContinue):((RenderOptions.ShowThread)?(RenderOptions.IconThreadContinue):(RenderOptions.IconSpacer))):((RenderOptions.ShowThread)?(RenderOptions.IconThreadContinue):(RenderOptions.IconSpacer))) + "' width=" + RenderOptions.IconTreeWidth + " height=" + RenderOptions.IconTreeHeight + " border=0>" + strOnClick[1] + "</td>";
          this.innerHtml = strSpace + strTree + strNode + ((RenderOptions.VSpace > 0)?(strSpace):(""));
          strTree += "<td><img src='" + ((RenderOptions.ShowThread)?(RenderOptions.IconThread):(RenderOptions.IconSpacer)) + "' width=" + RenderOptions.IconTreeWidth + " height=" + RenderOptions.IconTreeHeight + "></td>" + ((RenderOptions.VSpace > 0)?(strSpace):(""));
        }
      else this.innerHtml = strSpace; //this.Render(strSpace);
    }
    if(this.HasChildren())
      for(var i=0;i<this.ChildNodes.length;i++)
        this.ChildNodes[i].Init(this, (!RenderOptions.FirstLevelFlat || (this.Parent && this.Parent.NodeObject) ? strTree : ""), ((i == this.ChildNodes.length - 1)?(true):(false)));
  };
  this.Register = function() {
    this.ID = this.TreeObject.Nodes.length;
    this.ClientID = this.TreeObject.Name + this.TreeObject.Nodes.length;
    this.TreeObject.Nodes[this.TreeObject.Nodes.length] = this;
  };
  this.Render = function() {
    var strTree = this.innerHtml;
    if(this.NodeObject != null){
      if(this.TreeObject != null){
        this.RenderBegin = this.TreeObject.NodeRenderBegin;
        this.RenderEnd = this.TreeObject.NodeRenderEnd;
        var RenderOptions = this.TreeObject.RenderOptions;
        var strOnClick = [
          ((RenderOptions.ShowIcon)?("<a href='#' onclick='ccNodeClick(" + this.TreeObject.ID + ", " + this.ID + ")'>"):""),
          ((RenderOptions.ShowIcon)?("</a>"):"")];
        var strPadding = ((RenderOptions.TitlePadding > 0)?("<td><img src='" + RenderOptions.IconSpacer + "' height=1 width=" + RenderOptions.TitlePadding + "></td>"):(""));
        var strIcon = "<td>" + strOnClick[0] + "<img id='icon_" + this.TreeObject.ID + "_" + this.ClientID + "' src='" + ((this.HasChildren())?(this.IconFolderClose):(this.IconDocument)) + "' border=0>" + strOnClick[1] + "</td>";

        this.RenderBegin();
              var html = strTree + strIcon + strPadding;
              html += "<td width='100%'" + ((RenderOptions.NoWrap) ? (" NoWrap") : ("")) + ((RenderOptions.TitlePaddingTop > 0) ? (" style='padding-top:" + RenderOptions.TitlePaddingTop + "'") : ("")) + ">";
              this.TreeObject.textWriter.write(html);
        if(this.NodeObject.Render) this.NodeObject.Render()
        else this.RenderNodeObject();
        this.TreeObject.textWriter.write("</td>")
        this.RenderEnd();
      }
    }
    if(this.HasChildren())
      for(var i=0;i<this.ChildNodes.length;i++)
        this.ChildNodes[i].Render();
  };
  this.RenderBegin = null;
  this.RenderEnd = null;
  this.RenderNodeObject = function() {
    var RenderOptions = this.TreeObject.RenderOptions;
    var strOnClick = new Array("<a href='#' onclick='ccNodeObjectClick(" + this.TreeObject.ID + ", " + this.ID + ")' ", "</a>");
    this.TreeObject.textWriter.write(strOnClick[0] + " class='NodeObject' id='" + this.ClientID + "_Caption'");
    if(this.NodeObject.Title != null)
      this.TreeObject.textWriter.write(">" + this.NodeObject.Title)
    else
      this.TreeObject.textWriter.write(">...");
    this.TreeObject.textWriter.write(strOnClick[1]);
  };
  this.Connect = function() {
    this.Object = document.getElementById(this.ClientID);
    if(this.TreeObject.RenderOptions.ShowNode && this.HasChildren())
      this.ImgNode = document.getElementById("node_" + this.TreeObject.ID + "_" + this.ClientID);
    if(this.TreeObject.RenderOptions.ShowIcon)
      this.ImgIcon = document.getElementById("icon_" + this.TreeObject.ID + "_" + this.ClientID);

    if (this.NodeObject != null)
      this.NodeObject.Caption = document.getElementById(this.ClientID + '_Caption');
    
    if (this.NodeObject != null && this.NodeObject.Connect != null)
      this.NodeObject.Connect();

    if(this.HasChildren())
      for(var i=0;i<this.ChildNodes.length;i++)
        this.ChildNodes[i].Connect();
    if(this.State == 2)
      this.Expand()
    else if(this.State == 1 || this.Parent.State != 2)
      this.Contract();
  };
  this.AddChild = function(Node) {
    var newNode = new ccNode(Node);
    newNode.TreeObject = this.TreeObject;
    newNode.Parent = this;
    if(Node != null) Node.BaseNode = newNode;
    this.ChildNodes[this.ChildNodes.length] = newNode;
    return newNode;
  };
  this.Delete = function(unreg) {
    this.TreeObject.SelectedNodeIndex = -1;

    if(unreg){
      var newNodes = new Array();
      for(var i=0;i<this.TreeObject.Nodes.length;i++){
        if(this.TreeObject.Nodes[i] != this)
          newNodes[newNodes.length] = this.TreeObject.Nodes[i]
      }
      this.TreeObject.Nodes = newNodes;
      for(var i=0;i<this.ChildNodes.length;i++)
        this.ChildNodes.Delete(true);
    }

    if(this.Parent != null){
      var newNodes = new Array();
      for(var i=0;i<this.Parent.ChildNodes.length;i++){
        if(this.Parent.ChildNodes[i] != this)
          newNodes[newNodes.length] = this.Parent.ChildNodes[i]
      }
      this.Parent.ChildNodes = newNodes;
      if(newNodes.length == 0) this.Parent.State = 1;
    }

    this.Parent = null;
  };
  this.AppendChild = function(node) {
    this.ChildNodes[this.ChildNodes.length] = node;
    node.Parent = this;
  };
  this.Show = function() {
    if(this.Object == null) return false;
    if(this.State == 2)
      this.Expand()
    else
      this.State = 1;
    this.Object.style.display = "block"
  };
  this.Hide = function() {
    if(this.Object == null) return false;

    if(this.State == 2){
      for(var i=0;i<this.ChildNodes.length;i++)
        this.ChildNodes[i].Hide()
    }else
      this.State = 0;
    if(this.Object.style.display != "none")
      this.Object.style.display = "none";
  };
  this.Expand = function() {
    this.State = 2;
    for(var i=0;i<this.ChildNodes.length;i++)
      this.ChildNodes[i].Show();
    var RenderOptions = this.TreeObject.RenderOptions;
    if(this.ImgNode != null) this.ImgNode.src = ((this.LastNode)?(RenderOptions.IconNodeOpenEnd):(RenderOptions.IconNodeOpenContinue));
    if(this.ImgIcon != null) this.ImgIcon.src = this.IconFolderOpen;
    if (this.Object != null && this.HasChildren())
      this.Object.className = "NodeOpen";
  };
  this.Contract = function() {
    if(!this.HasChildren()) return;
    this.State = 1;
    for(var i=0;i<this.ChildNodes.length;i++)
      this.ChildNodes[i].Hide();
    var RenderOptions = this.TreeObject.RenderOptions;
    if(this.ImgNode != null)
      this.ImgNode.src = ((this.LastNode)?(RenderOptions.IconNodeCloseEnd):(RenderOptions.IconNodeCloseContinue));
    if(this.ImgIcon != null)
      this.ImgIcon.src = this.IconFolderClose;
    if (this.Object != null && this.HasChildren())
      this.Object.className = "NodeClose";
  };
  this.Select = function() {
    if(this.NodeObject.Caption != null)
      this.NodeObject.Caption.className = "NodeObjectSelected";
  };
  this.Unselect = function() {
    if(this.NodeObject.Caption != null) this.NodeObject.Caption.className = "NodeObject";
  };
  this.IsChild = function(node) {
    var IsChild = false;
    for(var iNode=0;iNode<this.ChildNodes.length;iNode++){
      if(this.ChildNodes[iNode] == node) return true;
      IsChild = IsChild || this.ChildNodes[iNode].IsChild(node);
    }
    return IsChild;
  };
  this.HasChildren = function() {
    return (this.CustomChildren || this.ChildNodes.length > 0);
  };
}


function ccNodeRenderBegin() {
  this.TreeObject.textWriter.write("<table class='Node' border=0 cellspacing=0 cellpadding=0 width=100% ");
  this.TreeObject.textWriter.write("id='" + this.ClientID + "' style='display:block;position:block;'><tr>")
}

function ccNodeRenderEnd() {
  var html = "</tr></table>";
  this.TreeObject.textWriter.write(html);
}

function ccNodeClick(iTree, iNode){
  myNode = ccTrees[iTree].Nodes[iNode];
  if(myNode.HasChildren()){
    if(myNode.State == 2) myNode.Contract();
    else myNode.Expand();
  }else ccNodeObjectClick(iTree, iNode);
}

function ccNodeObjectClick(iTree, iNode){
  myTree = ccTrees[iTree];
  myNode = myTree.Nodes[iNode];
  if(myNode.HasChildren()) myNode.Expand(true);
  if(myTree.SelectedNodeIndex > -1)
    myTree.Nodes[myTree.SelectedNodeIndex].Unselect();
  myTree.SelectedNodeIndex = iNode;
  myNode.Select();
  if(myNode.NodeObject.Click != null) myNode.NodeObject.Click();
}


// Node Link...
function NodeLink(title, href, target){
  return new ccNodeLinkClass(title, href, target);
}

function ccNodeLinkClass(title, href, target){
  this.BaseNode = null;
  this.Caption = null;

  this.Title = title;
  this.Href = href;
  this.Target = target;

  this.Click = ccNodeLinkClick
}


function ccNodeLinkClick(){
  window.open(this.Href, this.Target)
}

// Node SiteMaker...
function NodeSiteMaker(documentid, title, script, width){
  return new ccNodeSiteMakerClass(documentid, title, script, width);
}

function ccNodeSiteMakerClass(documentid, title, script, width){
  this.BaseNode = null;
  this.Caption = null;

  this.DocumentID = documentid;
  this.Title = title;
  this.Script = script;
  this.Width = width;

  this.Click = ccNodeSiteMakerClick
}

function ccNodeSiteMakerClick(){
  if(ua.indexOf("mac"))
    window.setTimeout(this.Script, 10);
  else
    eval(this.Script);
}

// Defined Tree Render Options...

function ccTreeRenderOptions(){
  this.NoWrap = false;
  this.ShowThread = true;
  this.ShowNode = true;
  this.ShowIcon = true;
  this.HSpace = 0;
  this.VSpace = 0;
  this.TitlePadding = 3;
  this.TitlePaddingTop = 0;

  this.FirstLevelFlat = false;

  this.IconTreeWidth = 16;
  this.IconTreeHeight = 16;
  this.FolderWith = 16;
  this.FolderHeight = 16;
  this.DocumentWidth = 16;
  this.DocumentHeight = 16;

  this.IconSpacer = "Graphics/spacer.gif";
  this.IconThread = "Graphics/win9x_t.gif";
  this.IconThreadEnd = "Graphics/win9x_te.gif";
  this.IconThreadContinue = "Graphics/win9x_tc.gif";
  this.IconNodeOpenEnd = "Graphics/win9x_nb_1e.gif";
  this.IconNodeOpenContinue = "Graphics/win9x_nb_1c.gif";
  this.IconNodeCloseEnd = "Graphics/win9x_nb_0e.gif";
  this.IconNodeCloseContinue = "Graphics/win9x_nb_0c.gif";
  this.IconFolderOpen = "Graphics/win9x_f_1.gif";
  this.IconFolderClose = "Graphics/win9x_f_0.gif";
  this.IconDocument = "Graphics/win9x_d.gif";
}


function ccTreeRenderOptionsWin9x(){
  myTRO              = new ccTreeRenderOptions();
  myTRO.NoWrap          = true;
  myTRO.ShowThread        = true;
  myTRO.ShowNode          = true;
  myTRO.ShowIcon          = true;
  myTRO.HSpace          = 0;
  myTRO.VSpace          = 0;
  myTRO.TitlePadding        = 3;
  myTRO.IconSpacer        = "Graphics/spacer.gif";
  myTRO.IconThread        = "Graphics/win9x_t.gif";
  myTRO.IconThreadEnd        = "Graphics/win9x_te.gif";
  myTRO.IconThreadContinue    = "Graphics/win9x_tc.gif";
  myTRO.IconNodeOpenEnd      = "Graphics/win9x_nb_1e.gif";
  myTRO.IconNodeOpenContinue    = "Graphics/win9x_nb_1c.gif";
  myTRO.IconNodeCloseEnd      = "Graphics/win9x_nb_0e.gif";
  myTRO.IconNodeCloseContinue    = "Graphics/win9x_nb_0c.gif";
  myTRO.IconFolderOpen      = "Graphics/win9x_f_1.gif";
  myTRO.IconFolderClose      = "Graphics/win9x_f_0.gif";
  myTRO.IconDocument        = "Graphics/win9x_d.gif";
  return myTRO;
}

function ccTreeRenderOptionsWinXP(){
  myTRO              = new ccTreeRenderOptions();
  myTRO.NoWrap          = true;
  myTRO.ShowThread        = false;
  myTRO.ShowNode          = true;
  myTRO.ShowIcon          = true;
  myTRO.HSpace          = 3;
  myTRO.VSpace          = 1;
  myTRO.TitlePadding        = 5;

  myTRO.IconDocumentHeight    = 16;

  myTRO.IconSpacer        = "Graphics/spacer.gif";
  myTRO.IconNodeOpenEnd      = "Graphics/winXP_nb_1.gif";
  myTRO.IconNodeOpenContinue    = myTRO.IconNodeOpenEnd;
  myTRO.IconNodeCloseEnd      = "Graphics/winXP_nb_0.gif";
  myTRO.IconNodeCloseContinue    = myTRO.IconNodeCloseEnd;
  myTRO.IconFolderOpen      = "Graphics/winXP_f_1.gif";
  myTRO.IconFolderClose      = "Graphics/winXP_f_0.gif";
  myTRO.IconDocument        = "Graphics/winXP_d.gif";
  return myTRO;
}

function ccTreeRenderOptionsNodes(){
  myTRO              = new ccTreeRenderOptions();
  myTRO.NoWrap          = true;
  myTRO.ShowThread        = false;
  myTRO.ShowNode          = false;
  myTRO.ShowIcon          = true;
  myTRO.HSpace          = 0;
  myTRO.VSpace          = 8;
  myTRO.TitlePadding        = 6;

  myTRO.IconTreeWidth       = 15;
  myTRO.IconTreeHeight      = 15;
  myTRO.IconFolderWith      = 11;
  myTRO.IconFolderHeight      = 11;
  myTRO.IconDocumentWidth      = 11;
  myTRO.IconDocumentHeight    = 11;

  myTRO.IconSpacer        = "Graphics/spacer.gif";
  myTRO.IconFolderOpen      = "Graphics/nodes_nb_1.gif";
  myTRO.IconFolderClose      = "Graphics/nodes_nb_0.gif";
  myTRO.IconDocument        = "Graphics/nodes_d.gif";
  return myTRO;
}


function ccTreeRenderOptionsCourse(){
  myTRO              = new ccTreeRenderOptions();
  myTRO.NoWrap          = true;
  myTRO.ShowThread        = false;
  myTRO.ShowNode          = false;
  myTRO.ShowIcon          = true;
  myTRO.HSpace          = 3;
  myTRO.VSpace          = 1;
  myTRO.TitlePadding        = 3;

  myTRO.IconTreeWidth       = 10;
  myTRO.IconDocumentHeight    = 16;

  myTRO.IconSpacer        = "Graphics/spacer.gif";
  myTRO.IconFolderOpen      = "Graphics/course_f_1.gif";
  myTRO.IconFolderClose      = "Graphics/course_f_0.gif";
  myTRO.IconDocument        = "Graphics/course_d.gif";
  return myTRO;
}

function ccTreeRenderOptionsCourseXP(){
  myTRO              = new ccTreeRenderOptions();
  myTRO.NoWrap          = false;
  myTRO.ShowThread        = false;
  myTRO.ShowNode          = false;
  myTRO.ShowIcon          = true;
  myTRO.HSpace          = 3;
  myTRO.VSpace          = 1;
  myTRO.TitlePadding        = 3;

  myTRO.IconTreeWidth       = 2;
  myTRO.IconFolderWith      = 22;
  myTRO.IconFolderHeight      = 17;

  myTRO.IconSpacer        = "Graphics/spacer.gif";
  myTRO.IconFolderOpen      = "Graphics/coursexp_f_1.gif";
  myTRO.IconFolderClose      = "Graphics/coursexp_f_0.gif";
  myTRO.IconDocument        = "Graphics/coursexp_d.gif";
  return myTRO;
}

