// ClientTabs.js
//
// Some Javascript techniques from:
// Erik Arvidsson (http://webfx.eae.net/contact.html#erik)

// An utility method that attaches event handlers in a 
// browser-nonspecific way.
function jhfAddEventListener(el, eventName, method) {
   if(el.addEventListener) {
      el.addEventListener(eventName, method, false);
   } else if(el.attachEvent) {
      el.attachEvent("on" + eventName, method);
   }
}

function jhfAddWindowLoadListener(method) {
   jhfAddEventListener(window, "load", method);
}

// A method that returns false, useful for cancelling
// IE onselectstart events that cause highlighting of tab
// contents
function jhfCancelEvent() {
   return false;
}

// Debugging utility function, gives more indepth
// information about an object.
function jhfPrintObject(o) {
   var s = "";
   for(var i in o) {
      s += i + ": " + o[i] + ".  ";
   }
   alert(s);
}

// The jhfClientTabs object represents a list of tabs that can be
// clicked on to show or hide a sheet.
function jhfClientTabs(tabsUl) {
   this.element = tabsUl;
   this.element.clientTabs = this;
   this.tabs = new Array();
   this.attachedSheets = new Array();

   var tempNode;
   for(var i = 0; i < tabsUl.childNodes.length; i++) {
      tempNode = tabsUl.childNodes[i];
      if(tempNode.nodeType != 3) {
         this.tabs[this.tabs.length] = new jhfClientTab(tempNode, this.tabs.length, this);;
      }
   }

   this.isMouseDown = false;
   jhfAddEventListener(tabsUl, "mousedown", jhfClientTabsOnMouseDown);
   this.element.unselectable = "on";
   this.element.onselectstart = jhfCancelEvent;
}

jhfClientTabs.prototype.setSelectedTab = function(s) {
   if(!this.tabs[s].isSelected()) {
      for(var i = 0; i < this.tabs.length; i++) {
         if(i != s.index)
            this.tabs[i].unSelectTab();
      }
   }

   for(var i = 0; i < this.attachedSheets.length; i++) {
      this.attachedSheets[i].setSelected(s);
   }
}

// Expensive, use rarely
jhfClientTabs.prototype.getSelectedTab = function() {
   for(var i = 0; i < this.tabs.length; i++) {
      if(this.tabs[i].isSelected())
         return i;
   }
}

jhfClientTabs.prototype.onSelectedTabChanged = new Array();

jhfClientTabs.prototype.setIsMouseDown = function(m) {
   this.isMouseDown = m;
}

jhfClientTabs.prototype.getIsMouseDown = function() {
   return this.isMouseDown;
}

jhfClientTabs.prototype.addSheet = function(sheet) {
   this.attachedSheets[this.attachedSheets.length] = sheet;
}

// A utility method to get the ClientTabs given an event object
// apparently in mozilla versuses IE, this is set differently
// based on who actually generated the event.  This traverses up the
// DOM to find the actualy clientTabs object.
function jhfClientTabsGetTabs(e) {
   var el = e.target || e.srcElement;
   while(el != null && el.clientTabs == null)	{
	   el = el.parentNode;
   }
   if(el)
	   return el.clientTabs;
	else
      return null;
}

function jhfClientTabsOnMouseDown(e) {
   var ct = jhfClientTabsGetTabs(e);
   jhfClientTabsAddGlobalMouseUp(ct);
   ct.setIsMouseDown(true);
   return true;
}

function jhfClientTabsMouseUp() {
   jhfClientTabs._currentClientTabs.setIsMouseDown(false);
   jhfClientTabsRemoveGlobalMouseUp();
   return true;
}

// When a tab is clicked and the mouse is held down we need to make sure
// when the mouse is released somewhere else in the document that the proper
// mouse button state is set in the client tabs.
function jhfClientTabsAddGlobalMouseUp(clientTabs) {
   jhfClientTabs._currentClientTabs = clientTabs;

   if(document.addEventListener) {
	   document.addEventListener("mouseup", jhfClientTabsMouseUp, true);
   } else if(document.attachEvent) {
	   document.attachEvent("onmouseup", jhfClientTabsMouseUp);
   }
}

function jhfClientTabsRemoveGlobalMouseUp() {
   if(document.addEventListener) {
      document.removeEventListener("mouseup", jhfClientTabsMouseUp, true);
   } else if(document.attachEvent) {
      document.detachEvent("onmouseup", jhfClientTabsMouseUp);
   }

   jhfClientTabs._currentClientTabs = null;
}

// The client tab object represents a single tab on the tabs list
// It handles all of the click events and over events and calls
// the tab list to set itself as the selected tab.
function jhfClientTab(tabLi, newIndex, clientTabs) {
   this.element = tabLi;
   this.element.clientTab = this;
   this.container = clientTabs;
   this.index = newIndex;

   // Grab the tab contents to be shown / hidden
   var nonTextIndex = 0;
   for(var i = 0; i < tabLi.childNodes.length && nonTextIndex < 2; i++) {
      if(tabLi.childNodes[i].nodeType != 3) {
         if(nonTextIndex == 0) {
            this.nonSelectedContents = tabLi.childNodes[i];
         } else if(nonTextIndex == 1) {
            this.selectedContents = tabLi.childNodes[i];
         }
         nonTextIndex++;
      }
   }

   jhfAddEventListener(tabLi, "mouseup", jhfClientTabMouseUp);
   jhfAddEventListener(tabLi, "mousedown", jhfClientTabMouseDown);
   jhfAddEventListener(tabLi, "mouseover", jhfClientTabMouseOver);
   this.element.onselectstart = jhfCancelEvent;
   this.element.unselectable = "on";
}

jhfClientTab.prototype.selectTab = function() {
   this.container.setSelectedTab(this.index);
   if(this.nonSelectedContents.style.display != "none") {
      this.nonSelectedContents.style.display = "none";
      this.selectedContents.style.display = "block";
   }
}

jhfClientTab.prototype.unSelectTab = function() {
   if(this.nonSelectedContents.style.display != "block") {
      this.nonSelectedContents.style.display = "block";
      this.selectedContents.style.display = "none";
   }
}

jhfClientTab.prototype.isSelected = function() {
   return this.selectedContents.style.display == "block";
}

function jhfClientTabGetTab(e) {
   var el = e.target || e.srcElement;
   while(el != null && el.clientTab == null)	{
	   el = el.parentNode;
   }

   if(el)
	   return el.clientTab;
	else
      return null;
}

function jhfClientTabMouseUp(e) {
   jhfClientTabGetTab(e).selectTab();
   return true;
}

function jhfClientTabMouseDown(e) {
   jhfClientTabGetTab(e).selectTab();
   return true;
}

function jhfClientTabMouseOver(e) {
   var ct = jhfClientTabGetTab(e);
   if(ct.container.getIsMouseDown()) {
      ct.selectTab();
   }
   return true;
}

// The client sheets object represents a list of sheets that
// are to be displayed or hidden based on the selected tab
function jhfClientSheets(sheetsDiv) {
   this.element = sheetsDiv;
   this.element.clientSheets = this;
   this.sheets = new Array();

   var tempNode;
   for(var i = 0; i < sheetsDiv.childNodes.length; i++) {
      tempNode = sheetsDiv.childNodes[i];
      if(tempNode.nodeType != 3) {
         this.sheets[this.sheets.length] = new jhfClientSheet(tempNode);
      }
   }
}

jhfClientSheets.prototype.setSelected = function(index) {
   for(var i = 0; i < this.sheets.length; i++) {
      if(i == index) {
         this.sheets[i].showSheet();
      } else {
         this.sheets[i].hideSheet();
      }
   }
}

jhfClientSheets.prototype.hideSheets = function() {
   for(var i = 0; i< this.sheets.length; i++) {
      this.sheets[i].hideSheet();
   }
}

// A client sheet object is used for showing and hiding different divs.
// Object instantiated by the jhfClientSheets object
function jhfClientSheet(sheetDiv) {
   this.element = sheetDiv;
   this.element.clientSheet = this;
}

jhfClientSheet.prototype.showSheet = function() {
   if(this.element.style.display != "block") {
      this.element.style.display = "block";
   }
}

jhfClientSheet.prototype.hideSheet = function() {
   if(this.element.style.display != "none") {
      this.element.style.display = "none";
   }
}

// Utility functions for creating client tabs objects with an id
function jhfCreateClientTabs(tabsName) {
   var ct = new jhfClientTabs(document.getElementById(tabsName));
}

function jhfCreateClientSheets(sheetsName) {
   var cs = new jhfClientSheets(document.getElementById(sheetsName));
}

function jhfAttachTabsToSheets(tabsName, sheetsName) {
   document.getElementById(tabsName).clientTabs.addSheet(document.getElementById(sheetsName).clientSheets);
}

function jhfClientSheetsHideSheets(sheetsName) {
   document.getElementById(sheetsName).clientSheets.hideSheets();
}