﻿// Reusable 'class' that wraps html controls
function HtmlControlWrapper(map, children)
{
    // Pointer to this instance
    var self = this;
        
    // Store a copy of the map
    this.Map = map;
    
    // Use an array to keep track of the child names
    this._childrenNames = new Array();
    
    // If there are any childeren add them
    if (arguments.length > 1)
    {
        for (var i=1; i<arguments.length; i++)
        {
            // Create the child fields/properties
            self[arguments[i].Name] = arguments[i].Child;
            
            // Popuplate an array with the child names
            if (typeof arguments[i].Child  != "function")
            {
                self._childrenNames[i-1] = arguments[i].Name;
            }
        }
    }
           
    // Event handler for control change events
    this.OnChanged = function(e)
    {
        var target = getTarget(e);
       
        // Call the default handler
        self[self.Map[target.id]] = getSelectedValue(target);
        
        // Call any additional handlers
        var handler = "On" + self.Map[target.id] + "Changed";
        if (self[handler] != undefined)
        {
            self[handler](e);
        }
    }
        
    // Sets the control values equal to the fields
    this.Populate = function ()
    {
        // Set the controls to the falues of the properties
        for(name in self.Map)
        {
            setValue(self[name], self[self.Map[name]]);
        }
        
        // Call populate an any children
        for(var i=0; i<self._childrenNames.length; i++)
        {
            self[self._childrenNames].Populate();
        }
    }

    // Initialize the object
    for(name in self.Map)
    {
        // Set the properties
        self[name] = $(name);
        
        // Create and set the properties on the object
        self[self.Map[name]] = getSelectedValue($(name));
        
        // Add the change handler
        addEvent(self[name], getChangeEvent(name), self.OnChanged);
    }    
}

// Shows a listing of the control names and thier values
HtmlControlWrapper.prototype.Show = function(map)
{
    if (!map)
    {
        map = this.Map;
    }
        
    var msg = "";
    for(name in map)
    {
        msg += name + "=" + this[map[name]] + "\n";
    }
    alert(msg);
}

// Gets the event name to wire the change event handler to
function getChangeEvent(name)
{
    var tagName = $(name).tagName;
    if (tagName.toUpperCase() == "INPUT")
    {
        var type = $(name).type;
        if (type.toLowerCase() == "text")
        {
            return "blur";
        }
        else 
        {
            return "click";
        }
    }
    else if (tagName.toUpperCase() == "SELECT")
    {   
        return "change";
    }
    else
    {
        return "click";
    }
}

// Wires the event handler to the control
function addEvent(obj, evt, handler)
{
    try
    {
        if (obj.addEventListener)
        {
            obj.addEventListener(evt, handler, false);
        }
        else if (obj.attachEvent)
        {
            obj.attachEvent("on" + evt, handler);
        }
        
    }
    catch(e)
    {
        alert(e);
    }
}

// Gets the selected value from an html control using the tagName to determine
// the property to use
function getSelectedValue(element)
{
    if (element.tagName.toUpperCase() == "INPUT")
    {
        if (element.type.toLowerCase() == "text")
        {
            return element.value;
        }
        else if (element.type.toLowerCase() == "radio")
        {
            if (element.checked == true)
            {
                return element.value;
            }
        }
        else if (element.type.toLowerCase() == "checkbox")
        {
            return element.checked;
        }
    }
    else if (element.tagName.toUpperCase() == "SELECT")
    {
        if (element.multiple)
        {
            // Handle multiples taking an array of items 
            var selectedValues = new Array();
            var index = 0;
            for (var i =0; i<element.length; i++)
            {
                if (element.options[i].selected == true)
                {
                    selectedValues[index] = element.options[i].value;
                    index++;
                }
            }
            
            if (selectedValues.length > 1)
            {
                return selectedValues;
            }
            else
            {
                return selectedValues[0];
            }
        }
        else (element.selectedIndex >= 0)
        {   
            return element.options[element.selectedIndex].value;
        }
    }
    else
    {
        alert(tagName + " needs to be handled in getSelectedValue");
    }
}

// Sets the selected value of an html control using the tagName to determine
// the property to set
function setValue(element, value)
{
    if (element.tagName.toUpperCase() == "INPUT")
    {
        if (element.type.toLowerCase() == "text")
        {
            return element.value = value;
        }
        else if (element.type.toLowerCase() == "radio")
        {
            if (element.value == value)
            {
                element.checked = true;
            }
            else
            {
                element.checked = false;
            }
        }
        else if (element.type.toLowerCase() == "checkbox")
        {
            return element.checked = value;
        }
    }
    else if (element.tagName.toUpperCase() == "SELECT")
    {
        if (value.indexOf(",") >= 0)
        {
            value = value.split(",");
        }
        
        if (element.multiple 
            && value instanceof Array)
        {
            // Handle multiples taking an array of items 
            // NOTE: could be more efficient
            for (var i =0; i<element.length; i++)
            {
                var index = value.indexOf(element.options[i].value);
                if (index >= 0)
                {
                    element.options[i].selected = true;
                }
            }
            return;
        }
        else (element.selectedIndex >= 0)
        {
            for (var i =0; i<element.length; i++)
            {
                if (element.options[i].value == value)
                {
                    element.selectedIndex = i;
                    element.options[i].selected = true;
                    return;
                }
            }
        }
    }
    else
    {
        alert(tagName + " needs to be handled in getSelectedValue");
    }
}

// Add an indexOf to the array
Array.prototype.indexOf = function(element)
{
    for (var i=0; i<this.length; i++)
    {
        if (this[i] == element)
        {
            return i;
        }
    }
}

// Shortcut method for getElementById
function $(id)
{
    return document.getElementById(id);
}

// Gets the target or source element for the event
function getTarget(e)
{       
    if (e.target)
    {
        return e.target;
    }
    else
    {
        return e.srcElement;
    }
}

// Hides the element for the given id
function hideElement(id)
{
    $(id).style.display = "none"; 
}

// Shows the element for the given id
function showElement(id)
{
    $(id).style.display = ""; 
}

// Toggles visibility for the given id
function toggleDisplay(id)
{
    if ($(id).style.display == "")
    {
        hideElement(id);
    }
    else
    {
        showElement(id);
    }
}

// Disables the element for the given id
function disableElement(id)
{
    $(id).disabled = true;
}

// Enables the element for the given id
function enableElement(id)
{
    $(id).disabled = false;
}
