/*
		File:		TabHelper class
		Version:	1.0
		Desc:		This class helps to build tabs on a page using lightweight markup and two HTML classes.
					Tested in IE6+, Firefox 1.0+ and Opera 9+. Needs to be tested in Safari 1.3+
		Requires:	/pages/v4/script/dhtml_lib.js
		Use:		To use the functions found in this file, start with simple markup:
		
					<div class="tabs">
						<[h3 or another tag] class="tab" id="[id name]">[Heading]</h3>
						<p>Content here in whatever tags you want. Feel free to nest infinitely.</p>
						<[h3 or another tag] class="tab" id="[another id]">[Another Heading]</h3>
						<ul>
							<li>More content</li>
							<li>In any format</li>
						</ul>
					</div>

					Instantiate:
						new TabHelper([param]) allows you to specify which tab index you want open by default.
						The default if not specified is the first tab, or 0. If the index doesn't exist, all of them will be hidden
						
						If you want an easy default implementation, just add a window load event to call TabHelper_AutoInit()
					
					Then write CSS to style the tabs. Don't forget to specify display property for the class ".tab-hidden".
							
		Author:		Eric Shepherd
		Date:		December 2006
		Methods:	The following methods are in this class.
		
					init(container element)
						Builds an unordered list from the headings in the container element
						Builds an array of content sections from the content under each heading
						Inserts the list into the parent element
						Inserts the sections into the parent element
						Sets the default active tab per the parameter (if any) passed into the constructor
						
					findTabHeadings(container element)
						Returns a node list of any elements with a class of "tab" inside the container
					
					buildList(container element)
						Parses through container looking for tags with class "tab"
						Loops through these tags, pulling out text and pushing into new <li> elements
						Returns an unordered list of these tab headings with the id of the heading
						Adds event listener to the newly created links on each tab (calls showHide)
					
					buildTabContainers(container element)
						Creates a new sections array
						Parses through element, beginning at heading and pushing nextSiblings into the array
						Loop stops when another heading or the end of the container section is reached
					
					showHide(link, container element, event)
						Gets the anchor link which was clicked, adds hidden class to all tab sections
						Returns the <a> tag from storage to the previously selected tab
						Removes hidden class from selected tab, activates the tab to remove the <a> tag
						Cancels default link action
						
					setDefaultActiveTab(container element)
						Sets the first tab to be active by retrieving the tab and calling DomHelper.ActivateElement
						
					deactivateElements(container element)
						Calls DomHelper.DeactivateElement for all list items which are activated in the tab set
							
									
			Version History:
				
				0.9		EBS		Created
				1.0		EBS		Launch version, tested and implemented
*/


// Constructor
// Pass in the tab number which should be active
function TabHelper(openDefault) 													
{
	this._openTab = (openDefault != null) ? openDefault : 0;
	this._tabKeyword = 'tab';
	this._tabHiddenClass = 'tab-hidden';
	this._tabListClass = 'tab-list';
	this._activeClass = 'active';
}

// Public Accessors
TabHelper.prototype.SetOpenTab = function(value) {
	this._openTab = value;
}

TabHelper.prototype.SetTabKeyword = function(value) {
	this._tabKeyword = value;
}

TabHelper.prototype.SetTabHiddenClass = function(value) {
	this._tabHiddenClass = value;	
}

TabHelper.prototype.SetTabListClass = function(value) {
	this._tabListClass = value;	
}

TabHelper.prototype.SetActiveClass = function(value) {
	this._activeClass = value;	
}

// Storage variable for activated tab link to chill until needed again
TabHelper.prototype.tabStorage = null;



// Function: init
// Builds the unordered list of tab options and inserts into the document
// Parameters:
//   parent - the HTML element that contains the tab content
// Returns:
//   void
TabHelper.prototype.init = function(parent) 
{
	if (!SupportTest.hasDom) return;
	
	thisList = this.buildList(parent);	
	sections = this.buildTabContainers(parent);
	parent.appendChild(thisList);
	for (var i=0; i<sections.length; i++) {
		parent.appendChild(sections[i]);
	}
	this.setDefaultActiveTab(parent);
}



// Function: findTabHeadings
// Finds the headings in the HTML and returns an array of elements
// Parameters:
//   parent - the HTML element that contains the tab content
// Returns:
//   void
TabHelper.prototype.findTabHeadings = function(parent) 
{
	return DomHelper.GetElementsByClassName(this._tabKeyword, null, parent);	
}



// Function: buildList
// Accepts an element, calls findTabHeadings, and returns an unordered list with nav items
// Parameters:
//   parent - the HTML element that contains the tab content
// Returns:
//   an unordered list element containing the navigation items
TabHelper.prototype.buildList = function(parent) 
{
			// get each item with class "tab" in the current section
	var headings = this.findTabHeadings(parent);
			// create list and items array
	var list = document.createElement('ul');
	list.className = this._tabListClass;
			// loop through headings, push text into list
	for (var i=0; i<headings.length; i++) {
		var text = headings[i].firstChild.nodeValue;
		var itemId = headings[i].id.length > 0 ? headings[i].id : '';
		var newLi = document.createElement('li');
				// create the link and text node
		var newLink = document.createElement('a');
		var newText = document.createTextNode(text);
		newLink.setAttribute('href', '#' + headings[i].id);
				// append text to link, set attributes and append the whole thing into the new list item
		newLink.appendChild(newText);
		var thisId = this._tabKeyword + '-' + headings[i].id;
		newLi.setAttribute('id', thisId)
		newLi.appendChild(newLink);
				// add the event
		var thisReference = this;
		EventHelper.AddEvent(newLink, 'click', ptr = function(e) { thisReference.showHide(this, parent, e); }, false);		
				// push the new list item into the ul
		list.appendChild(newLi);
	}
	return list;
}



// Function: buildTabContainers
// Finds the tab headings, parses through them and creates divs with meaningful ids while removing the headlines
// Parameters:
//   parent - the HTML element containing the tab content
// Returns:
//   an array of div elements with the tab content
TabHelper.prototype.buildTabContainers = function(parent) {
			// get each item with class "tab" in the current section
	var headings = this.findTabHeadings(parent);
			// array to hold all sections
	sections = new Array();
			// loop through headings
	for (var i=0; i<headings.length; i++) {
				// create new div and assign to array slot
		var newDiv = document.createElement('div');
		sections[i] = newDiv;
				// grab the node name of the heading
		var theNodeName = (headings[i].nodeName);
				// cycle through, grab nextSibling and push into div in array slot
		while (headings[i].nextSibling && headings[i].nextSibling.nodeName != theNodeName) {
			sections[i].appendChild(headings[i].nextSibling);	
		}
				// get rid of heading after assigning id to the new div, add class of 'tab' to new sections
		var thisId = headings[i].id;
		headings[i].parentNode.removeChild(headings[i]);
		sections[i].id = thisId;
		DomHelper.AddClassName(sections[i], this._tabKeyword);
				// hide all sections
		if (this._openTab != i) {
			DomHelper.AddClassName(sections[i], this._tabHiddenClass);
		}
	}
	return sections;
}



// Function: showHide
// Shows and hides the tab divs based on link click events
// This method would have to be extended/overwritten to include an effect rather than a hidden class
// Parameters:
//   theLink - the anchor element on each tab which receives the click event
//   parent - the HTML element containing the tab content
//   e - the click event on the tab
// Returns:
//   void
TabHelper.prototype.showHide = function(theLink, parent, e) 
{
	var theIds = theLink.toString().split('#');
	var section = theIds[1];
	var activatedElement = document.getElementById(section);
			// add hidden class name to all elements
	var headings = this.findTabHeadings(parent);
	for (i=0; i<headings.length; i++) {
		DomHelper.AddClassName(headings[i], this._tabHiddenClass);	
	}
			// remove hidden class on active element and cancel following link
	DomHelper.RemoveClassName(activatedElement, this._tabHiddenClass);
			// deactivate all and then activate the element
	this.deactivateElements(parent);
	var tabId = this._tabKeyword + '-' + activatedElement.id;
	var newTab = document.getElementById(tabId);
	this.tabStorage = DomHelper.ActivateElement(newTab, this.tabStorage);
	EventHelper.CancelDefault(e);
}



// Function: setDefaultActiveTab
// Sets the default active tab per index specified in constructor
// Parameters:
//   parent - the HTML element containing the tab content
// Returns:
//   void
TabHelper.prototype.setDefaultActiveTab = function(parent) 
{
	var list = parent.getElementsByTagName('ul')[0];
	var items = list.getElementsByTagName('li');
	for (var i = 0; i<items.length; i++) {
		if (i == this._openTab) {
			this.tabStorage = DomHelper.ActivateElement(items[i], this.tabStorage);	
		}
	}
}



// Function: deactivateElements
// Deactivates the active tab, placing the link into the static storage property
// Parameters:
//   parent - the HTML element containing the tab content
// Returns:
//   void
TabHelper.prototype.deactivateElements = function(parent)
{
	var list = parent.getElementsByTagName('ul')[0];
	var items = list.getElementsByTagName('li');
	for (var i=0; i<items.length; i++) {
		if (items[i].className.match(this._activeClass)) {
			DomHelper.DeactivateElement(items[i], this.tabStorage);	
		}
	}
}



// Function: AutoInit
// Static auto-initializer. Either call this function on window load, 
// or instantiate the TabHelper manually if you need more control.
// Auto-initializes any number of tab sets on a page
// Parameters:
//   none
// Returns:
//   void
TabHelper.AutoInit = function() 
{
			// get all elements with class of "tabs"
	var elements = DomHelper.GetElementsByClassName('tabs');
			// create new array to hold instances
	instances = new Array();
			// loop through all elements with "tabs" class
	for (var i=0; i<elements.length; i++) {
				// create new TabHelper instance at iterator location
		instances[i] = new TabHelper();
				// run init function for that particular instance, passing it the element at the iterator location
		instances[i].init(elements[i]);
	}
}