/* ===============================================================================
 * Name: CoolTab                                                                 *
 * Author: HoangKC                                                               *
 * Email: hoangdq@vegasoft.ws                                                    *
 * Release: 11:03 AM 10/27/2006                                                  *
 * Description: Hope you like it. Enjoy ^_^                                      *
 *                                                                               *
 * This file is part of the CoolTab Code Samples.                                *
 *                                                                               *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,  *
 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED         *
 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.        *
 *                                                                               *
 * THIS NOTICE MAY NOT BE REMOVED OR ALTERED FROM ANY SOURCE DISTRIBUTION.       * 
 *                                                                               *
 * IF YOU WISH TO REPORT A BUG OR EXPRESS YOUR OPINION, FEEL FREE TO E-MAIL ME.  *
 * REMOTE JOB OFFERS ARE WELCOME.                                                *
 *                                                                               *
 * ==============================================================================*/
/* ===============================================================================
 *                                                                               *
 * Version history:                                                              *
 * Last Update: 9:27 PM 10/28/2006                                               *
 *                                                                               *
 * 1 Adding event handler ClientSideOnClick                                      *
 * 2 Adding asynchronize mode, CoolTab is built asynchronously from a DataSource *
 * 3 Adding event handler ClientSideOnLoadCompleted                              *
 * 4 Adding enabled/disabled mode and method SetEnabled for TabItem of CoolTab   *
 * 5 Method preInit return a collection of CoolTab objects                       *
 *                                                                               *
 * ==============================================================================*/
/* ===============================================================================
 *                                                                               *
 * Class CoolTab                                                                 *
 *                                                                               *
 * ==============================================================================*/

function CoolTab(holder)
{    
    this.type = "__CoolTab__";
    this.UniqueID = this.type+CoolTab.GenUniqueId();        
    this.Container = null;              // html element will contain all items
    this.oRow = null;
    this.control = null;                // will be used in async mode ?    
    this.Holder = null;                 // parent control
    this.MultiPage = "$";
    this.DataSource = null;             // virtual path to the URL or XML document
    this.ImageBaseUrl = "";             // virtual path to the image folder
    this.TabItemClickEvent = null;      // fired when an item in CoolTab is clicked
    this.LoadCompleteEvent = null;      // fired when CoolTab has completed to load data    
    this.readyState = $UNINITIALIZED;   // this CoolTab's readyState is used in async mode
		this.async = false;                 // flag indicates whether the CoolTab is built asynchronously from a DataSource    
    this.Initialize(holder);   // Initialize properties
}

CoolTab.prototype.Initialize = function(holder)
{
    // Constant CSS
    var tabName = holder.attributes.Type.value;
    this.defaultCss = [tabName + "LeftTab",tabName + "BgrTab", tabName + "RightTab", tabName + "Body"];
    this.hoverCss = [tabName + "LeftTabHover", tabName + "BgrTabHover", tabName + "RightTabHover"];
    this.selectedCss = [tabName + "LeftTabSelected", tabName + "BgrTabSelected", tabName + "RightTabSelected"];
    this.disabledCss = [tabName + "LeftTabDisabled", tabName + "BgrTabDisabled", tabName + "RightTabDisabled"];
    this.items = [];        
    // status text
	this.loadingLabel = document.createElement("span");
	this.loadingLabel.innerText = "Loading...";
    this.Container = document.createElement("table");
    this.Container.cellPadding = 0;
	this.Container.cellSpacing = 0;
	this.Container.border = 0;
    this.oRow = this.Container.insertRow(-1);
    // will be used in async mode ?
    this.control = document.createElement("div");
    this.control.appendChild(this.Container);
    this.Holder = holder;
    this.Holder.appendChild(this.control);
    // events
    this.TabItemClickEvent = new _Event();
    this.LoadCompleteEvent = new _Event();
}

CoolTab.prototype.OnLoadCompleted = function()
{
    this.readyState = $COMPLETE;
    this.Completed();
    this.LoadCompleteEvent.args.sender = this;
		this.LoadCompleteEvent.args.readyState = this.readyState;
		this.LoadCompleteEvent.Fire();        
}

CoolTab.prototype.OnTabItemClick = function(args)
{
    this.TabItemClickEvent.args.sender = this;
		this.TabItemClickEvent.args.item = args.sender;
		this.TabItemClickEvent.Fire();    
}

CoolTab.GenUniqueId = function()
{
	return ( (new Date()).valueOf()+"_"+Math.random() ).replace(/\./, "_");
}

CoolTab.prototype.FindTabItemById = function(id)
{
	for (var i=0; i<this.items.length; i++)
	{
		var item = this.items[i];
		if (item && item.id == id)
		{
			return item;
		}
	}
	return null;
}

CoolTab.prototype.InvokeMethod = function(method)
{
	var args = [];
	for (var i=1; i<arguments.length; i++)
	{
		args[i-1] = arguments[i];
	}
	for (var i=0; i<this.items.length; i++)
	{
		var item = this.items[i];
		if (item)
		{
			method.apply(item, args);     
		}
	}
}

CoolTab.prototype.Completed = function()
{
	if (this.async && this.readyState != $COMPLETE)
	{
		return; // not ready to show yet!
	}
	var mapClickEvent = function()
	{
		this.TabClickEvent.AddHandler(_Delegate(this.parent, this.parent.OnTabItemClick));
	}
	this.InvokeMethod(mapClickEvent);    
	this.control.style.display = "block";
    for (var i=0; i<this.items.length; i++)
    {
        if (this.items[i].selected && this.items[i].enabled)
        {
            this.items[i].selected = false;
            this.items[i].Actived();
            break;
        }
    }    
}

CoolTab.prototype.DataBind = function()
{
	try 
	{ 
	    var oDoc = new XMLDocument();
		if (typeof(this.DataSource)!="string") 
		{
			alert("An error occurred during data binding.\r\nSource: CoolTab.DataBind\r\nDetails: DataSource must be an URL to the XML data file.");
			return;
		}
		
		this.readyState = $LOADING;        
		this.control.appendChild(this.loadingLabel);                        
		oDoc.OnLoad = _Delegate(this, this._DataBind);
		oDoc.Load(this.DataSource);		
	}
	catch(ex) 
	{
	    alert("An error occurred during data binding.\r\nSource: CoolTab.DataBind\r\nDetails: "+ex.message);
	}
}

CoolTab.prototype.AddItem = function(oTabItem)
{
    if (this.items.length==0)
	{
        //this.control.appendChild(this.childContainer);
	}		
	var tabIndex = this.items.length;		
	this.items[tabIndex] = oTabItem;
	var oCell = this.oRow.insertCell(-1);    
	oCell.align = "center";        
	oCell.appendChild(oTabItem.control);        	
	oTabItem.index = tabIndex;	
	oTabItem.parent = this;
	// return the tab index
	return tabIndex;
}

CoolTab.prototype._DataBind = function(oDoc)
{
	this.readyState = $LOADED;    
	this.control.removeChild(this.loadingLabel);    
	if (oDoc.documentElement!=null)
	{	
		this._BuildTab(oDoc.documentElement, this);		
		this.OnLoadCompleted();
	}	
}

CoolTab.prototype._BuildTab = function(xmlNode, coolTab)
{
	var nodes = xmlNode.selectNodes("TabItem");
	if (nodes)
	{
		for (var i=0; i<nodes.length; i++)
		{
			var tabItem = this._TabItemFromXMLNode(nodes[i]);
			coolTab.AddItem(tabItem);			
		}
	}
}

CoolTab.prototype._TabItemFromXMLNode = function(xmlNode)
{
	var Keys         = this._ItemAttributesToKeysObject(xmlNode);
    var id          = Keys["ID"] ? Keys["ID"] : "id";
	var caption     = Keys["Text"] ? Keys["Text"] : "";
	var selected    = Keys["Selected"] ? Keys["Selected"] == "true" ? true : false : false;
    var enabled     = Keys["Enabled"] ? Keys["Enabled"] == "true" ? true : false : true;
	var target      = Keys["Target"] ? Keys["Target"] : "_self";
    var url         = Keys["NavigatorUrl"] ? Keys["NavigatorUrl"] : "javascript:void(0)";
	var leftIcon    = Keys["LeftIcon"] ? Keys["LeftIcon"] : "nothing.gif";
	var tabItem = new TabItem();    
	tabItem.Keys = Keys; // <- this is not property for all object - just current instance	
	tabItem.Initialize(id, caption, selected, enabled, url, target, leftIcon, this);  
	  
	return tabItem;
}

CoolTab.prototype._ItemAttributesToKeysObject = function(node)
{
	var attributes = node.attributes;
	var obj = new Object();
	if (attributes)
	{
		for (var i=0; i<attributes.length; i++)
		{
			var name = attributes.item(i).nodeName;
			var value = attributes.item(i).nodeValue;
			obj[name] = value;
		}
	}
	return obj;
}

CoolTab.prototype.FirstRender = function()
{
	if (this.MultiPage != "$")
	{	
		var lst = document.getElementById(this.MultiPage).getElementsByTagName("div");
		var count = lst.length > this.items.length ? this.items.length : lst.length;		
		for (var i=0; i<count; i++)
		{			
			this.items[i].container = lst[i];
		}		
		for (var k=0;k<lst.length-count;k++)
		{
			lst[lst.length-count+k].style.display = "none";
		}
	}
	var first = false;
	for (var i=0; i<this.items.length; i++)
	{
		if (this.items[i].container != null)
		{
			if (!first&&this.items[i].selected)
			{
				this.items[i].container.style.display = "block";
				first = true;
			}
			else
			{
				this.items[i].container.style.display = "none";
			}
		}
	}	
}

/* ===============================================================================
 *                                                                               *
 * Class TabItem                                                                 *
 *                                                                               *
 * ==============================================================================*/
 
function TabItem()
{   
    this.type = "__TabItem__";
    this.uniqueId = this.type+CoolTab.GenUniqueId();    
    this.id = "";
    this.caption = "";
    this.selected = false;
    this.enabled = true;
    this.lnk = null;
    this.href = "javascript:void(0)";
    this.target = "_self";            
    this.parent = null;
    this.index = -1;    
	this.control = null;
	this.container = null;  
	this.TabClickEvent = null;
}

TabItem.prototype.Initialize = function(id, caption, selected, enabled, url, target, leftIcon, parent)
{   		
	this.id = id;
    this.caption = caption;
    this.selected = selected;
    this.enabled = enabled;        
    this.href = url;
    this.parent = parent;    
    this.index = -1;
    this.target = target;        
	this.control = document.createElement("div");
	this.control.id = this.id;
	this.control.title = this.caption;		
    if (this.enabled == false)
    {
        this.currentCss = this.parent.disabledCss;
    }
    else
    {
        if (this.selected == false)
        {
            this.currentCss = this.parent.defaultCss;
        }
        else
        {
            this.currentCss = this.parent.selectedCss;
        }
    }
    this.leftIcon = document.createElement("img");    
	this.leftIcon.src = this.parent.ImageBaseUrl+leftIcon;
	if(this.id == "home")
    {
        this.leftIcon.style.width = "40px";
        this.leftIcon.style.height = "13px";
    }
	this.label = document.createElement("div");
    this.label.className = this.parent.defaultCss[3];  
    if (this.target!="_self")
    {    	
        this.lnk = document.createElement("a");
        this.lnk.innerHTML = this.caption;        
        this.lnk.target = this.target;
        if (!this.enabled)
        {
            this.lnk.href = "javascript:void(0)";
            this.lnk.className = "DisabledLink";
        }
        else
        {
            this.lnk.href = this.href;
            this.lnk.className = "EnabledLink";
        }
        this.label.appendChild(this.lnk);
    }
    else
    {
    	this.label.innerHTML = this.caption;
    }
	oTable = document.createElement("table");
	oTable.cellPadding = 0;		
	oTable.cellSpacing = 0;
	oTable.border = 0;    
	var oRow = oTable.insertRow(-1);	
	var oCell = oRow.insertCell(-1);
	oCell.appendChild(this.leftIcon);    
    oCell = oRow.insertCell(-1);
	oCell.appendChild(this.label);
    var itemTable = document.createElement("table");    
    itemTable.cellPadding = 0;
    itemTable.cellSpacing = 0;
    itemTable.border = 0;    
    var itemRow = itemTable.insertRow(-1);    
    var itemCell = itemRow.insertCell(-1);    
    itemCell.className = this.currentCss[0];
    this.itemCellLeft = itemCell;    
    itemCell = itemRow.insertCell(-1);
    itemCell.className = this.currentCss[1];        
    itemCell.onmouseover = _Delegate(this, this.Over);
    itemCell.onmouseout = _Delegate(this, this.Out);
    itemCell.onclick = _Delegate(this, this.OnClick);    
    itemCell.appendChild(oTable);    
    this.itemCell = itemCell;    
    itemCell = itemRow.insertCell(-1);
    itemCell.className = this.currentCss[2];
    this.itemCellRight = itemCell;    
    this.control.table = itemTable;    
    this.control.appendChild(this.control.table);    
	this.TabClickEvent = new _Event();
}

TabItem.prototype.SetEnabled = function(enabled)
{
    if (this.enabled == enabled) return;    
    this.enabled = enabled;
    if (!this.enabled)
    {
        if (this.lnk)
        {
            this.lnk.href = "javascript:void(0)";
            this.lnk.className = "DisabledLink";
        }
        if (this.container != null)
        {
        	this.container.style.display = "none";
        }
        this.currentCss = this.parent.disabledCss;
        this.ResetCss();
    }
    else
    {
        if (this.lnk)
        {
            this.lnk.href = this.href;
            this.lnk.className = "EnabledLink";
        }
        if (!this.selected)
        {
            this.selected = true;
            this.DeActived();
        }
        else
        {
            this.selected = false;
            this.Actived();
        }
    }
}

TabItem.prototype.ResetCss = function()
{
    this.itemCellLeft.className = this.currentCss[0];
    this.itemCell.className = this.currentCss[1];
    this.itemCellRight.className = this.currentCss[2];
}

TabItem.prototype.Over = function()
{
    if (!this.enabled) return;    
    if (!this.selected)
    {
        this.itemCellLeft.className = this.parent.hoverCss[0];
        this.itemCell.className = this.parent.hoverCss[1];
        this.itemCellRight.className = this.parent.hoverCss[2];
    }
}

TabItem.prototype.Out = function()
{
    if (!this.enabled) return;    
    this.ResetCss();
}

TabItem.prototype.Actived = function()
{
    if (!this.enabled) return;    
	if (this.selected) return;    
    this.parent.InvokeMethod(this.DeActived);
	this.selected = true;	
	if (this.container != null)
	{
		this.container.style.display = "block";
	}	
    this.currentCss = this.parent.selectedCss;
    this.ResetCss();
}

TabItem.prototype.DeActived = function()
{    
    if (!this.enabled) return;	
	if (!this.selected) return;    
	this.selected = false;	
	if (this.container != null)
	{
		this.container.style.display = "none";
	}	
    this.currentCss = this.parent.defaultCss;    
    this.ResetCss();
}

TabItem.prototype.OnClick = function()
{
    if (!this.enabled) return;            
    this.Actived();        
    this.TabClickEvent.args.sender = this;
	this.TabClickEvent.Fire();
}

// Delegate function
function _Delegate(caller, fnc)
{
	var delegate = function()
	{
		fnc.apply(caller, arguments);
	}
	return delegate;
}

/* ===============================================================================
 *                                                                               *
 * Class _Event                                                                  *
 *                                                                               *
 * ==============================================================================*/
 
function _Event()
{
	this.handlers = [];	
	this.args = new Object();
}

_Event.prototype.AddHandler = function(handler)
{   
	var id = this.handlers.length;
	this.handlers[id] = handler;
	return id;
}

_Event.prototype.RemoveHandler = function(id)
{
	delete this.handlers[id];
}

_Event.prototype.Fire = function()
{
	for (var i=0; i<this.handlers.length; i++)
	{
		this.handlers[i](this.args);
	}
}

/* ===============================================================================
 *                                                                               *
 * pre Initialize CoolTab                                                        *
 *                                                                               *
 * ==============================================================================*/
 
function preInitCoolTab(argument)
{
    var arrCoolTab = [];
    for (var i = 0; i < arguments.length; i++)
    {
        var index = arrCoolTab.length;
        var o = document.getElementById(arguments[i]);
    		arrCoolTab[index] = InitCoolTab(o);
    }
    return arrCoolTab;
}

function InitCoolTab(oCoolTabArea)
{        
	var oCoolTab = new CoolTab(oCoolTabArea);
	var imageBase      = oCoolTabArea.attributes.ImageUrl ? oCoolTabArea.attributes.ImageUrl.value:"images/";
	var siteMap        = oCoolTabArea.attributes.SiteMap ? oCoolTabArea.attributes.SiteMap.value : "App_Data/mainMenu.xml";
	var fncClick       = oCoolTabArea.attributes.ClientSideOnClick ? eval(oCoolTabArea.attributes.ClientSideOnClick.value) : null;
    var fncCompleted   = oCoolTabArea.attributes.ClientSideOnLoadCompleted ? eval(oCoolTabArea.attributes.ClientSideOnLoadCompleted.value) : null;
    var multiPage      = oCoolTabArea.attributes.MultiPageID ? oCoolTabArea.attributes.MultiPageID.value : "$";    
	oCoolTab.ImageBaseUrl = imageBase;
	oCoolTab.DataSource = siteMap;	
    oCoolTab.DataBind();    
    if (fncCompleted != null)
    {
        oCoolTab.LoadCompleteEvent.AddHandler(fncCompleted);
    }    
	if (fncClick != null)
	{
		oCoolTab.TabItemClickEvent.AddHandler(fncClick);
	}	
	if (multiPage != "$")
	{	
		var fnc = function()
		{
			oCoolTab.MultiPage = multiPage;			
			oCoolTab.FirstRender();
		}		
		if (navigator.userAgent.indexOf("Firefox")!=-1)
		{
			// if FF
			oCoolTab.LoadCompleteEvent.AddHandler(fnc);		
		}
		else
		{
	        try
			{
				// if IE with file protocol
				fnc();
			}
			catch (ex)
			{
				// if IE with http protocol
				oCoolTab.LoadCompleteEvent.AddHandler(fnc);
			}
		}
	} 
    return oCoolTab;
}
