function Treeview() 
{
}

Treeview.prototype.IsExpanded = function (element)
{
    return (this.HasClass(element, "collapse"));
}

Treeview.prototype.TogglePlusMinus = function (element, showPlus)
{
    if (this.HasAnyClass(element))
    {
        var showPlusLocal = this.IsExpanded(element);
        if ((typeof(showPlus) != "undefined") && (showPlus != null))
            showPlusLocal = showPlus;
        var oldClass = showPlusLocal ? "collapse" : "expand";
        var newClass = showPlusLocal ? "expand" : "collapse";
        this.SwapClass(element, oldClass, newClass);
    }
}

Treeview.prototype.ToggleChildrenDisplay = function (element, collapse)
{
    if ((element != null) && (element.parentNode != null) && (element.parentNode.getElementsByTagName != null))
    {    
        var childrenToHide = element.parentNode.getElementsByTagName("ul");
        var oldClass = collapse ? "show" : "hide";
        var newClass = collapse ? "hide" : "show";
    	for (var i=0; i<childrenToHide.length; i++)
    	{
    	    if ((childrenToHide[i].parentNode != null) && (childrenToHide[i].parentNode == element.parentNode))    	    
        	    this.SwapOrAddClass(childrenToHide[i], oldClass, newClass);
		}
	}
}

Treeview.prototype.ExpandCollapse = function (sourceElement)
{
    if (this.HasAnyClass(sourceElement))
    {
        var expanded = this.IsExpanded(sourceElement);
        this.TogglePlusMinus(sourceElement, expanded);
        this.ToggleChildrenDisplay(sourceElement, expanded);
    }
}

Treeview.prototype.CanHaveClass = function (element)
{
    return ((element != null) && (element.className != null));
}

Treeview.prototype.HasAnyClass = function (element)
{
    return (this.CanHaveClass(element) && (element.className.length > 0));
}

Treeview.prototype.HasClass = function (element, specificClass)
{
    return (this.HasAnyClass(element) && (element.className.indexOf(specificClass) > -1));
}

Treeview.prototype.AddClass = function (element, classToAdd)
{
    if (this.HasAnyClass(element))
    {
        if (!this.HasClass(element, classToAdd))        
            element.className = element.className + " " + classToAdd;
    }
    else if (this.CanHaveClass(element))    
        element.className = classToAdd;
}

Treeview.prototype.AddClassUpward = function (startElement, stopParentClass, classToAdd)
{
    var elementOrParent = startElement;
    while ((elementOrParent != null) && (!this.HasClass(elementOrParent, topmostClass)))
    {
        this.AddClass(elementOrParent, classToAdd);
        elementOrParent = elementOrParent.parentNode;
    }
}

Treeview.prototype.SwapClass = function (element, oldClass, newClass)
{
    if (this.HasAnyClass(element))
        element.className = element.className.replace(new RegExp(oldClass, "gi"), newClass);
}

Treeview.prototype.SwapOrAddClass = function (element, oldClass, newClass)
{
    if (this.HasClass(element, oldClass))    
        this.SwapClass(element, oldClass, newClass);
    else
        this.AddClass(element, newClass);
}

Treeview.prototype.RemoveClass = function (element, classToRemove)
{
    this.SwapClass(element, classToRemove, "");
}

Treeview.prototype.RemoveClassUpward = function (startElement, stopParentClass, classToRemove)
{
    var elementOrParent = startElement;
    while ((elementOrParent != null) && (!this.HasClass(elementOrParent, topmostClass)))
    {
        this.RemoveClass(elementOrParent, classToRemove);
        elementOrParent = elementOrParent.parentNode;
    }    
}

// Global instance
var treeview = new Treeview();

