/*------------------------------------------------------------------------------
 * General Functions
 *----------------------------------------------------------------------------*/

/**
 * Renders a wait cursor for the page.
 */
function wait() {
    document.body.style.cursor = 'wait';
}

/**
 * Clears the wait cursor from the page.
 */
function nowait() {
    document.body.style.cursor = 'auto';
}

//------------------------------------------------------------------------------
//  Class Manipulation Methods
//------------------------------------------------------------------------------

/**
 * Appends the indicated newClassName to the objects class if it is not already present.
 *
 * @param obj           The DOM object to manipulate.
 * @param newClassName  The new class name.
 */
function appendClassName(obj, newClassName) {
    if (!containsClassName(obj, newClassName)) {
	    if (!obj.className) {
            obj.className = newClassName;
        } else {
	        obj.className = obj.className + " " + newClassName;
        }
    }
}

/**
 * Removes a class name from an object.
 *
 * @param obj           The DOM object to manipulate.
 * @param classNameToRemove  The class to remove.
 */
function removeClassName(obj, classNameToRemove) {
    if (obj.className) {
        var newClassName = '';
        var classNames = obj.className.split(' ');
        for (var i = 0; i < classNames.length; i++) {
            var className = classNames[i];
            if (classNames[i] != classNameToRemove) {
                newClassName = newClassName + className + ' ';
            }
        }

        newClassName = newClassName.substring(0, newClassName.length - 1)
        obj.className = newClassName;
    }
}

/**
 * Determines if a class name is present on an object.
 *
 * @param obj           The DOM object to manipulate.
 * @param className
 */
function containsClassName(obj, className) {
    if (obj.className) {
        var classNames = obj.className.split(' ');
        for (var i = 0; i < classNames.length; i++) {
            if (classNames[i] == className) {
                return true;
            }
        }
    }

    return false;
}

//------------------------------------------------------------------------------
//  DOM Manipulation Methods
//------------------------------------------------------------------------------

/**
 * Removes all of the child elements of an object.
 */
function removeAllChildren(obj) {
    if ( obj.hasChildNodes() ) {
        while ( obj.childNodes.length >= 1 ) {
            obj.removeChild( obj.firstChild );
        }
    }
}

/**
 * Replaces the contents of a DOM element with the specified
 * text.  This should be used in place of innerHTML for simple text.
 *
 * @param obj
 * @param text The new text.
 */
function replaceNodeText(obj, text) {
    removeAllChildren(obj);
    obj.appendChild(document.createTextNode(text));
}

//------------------------------------------------------------------------------
//  Select List Utility Methods
//------------------------------------------------------------------------------

/**
 *	Selects all the items in the selectList element.
 */
function selectAllItems(selectList) {
    if (!selectList) return;
    for (var i=0; i<selectList.length; i++) {
        selectList.options[i].selected = true;
    }
}

/**
 * Deselects all the items in the selectList element
 */
function deselectAllItems(selectList) {
    if (!selectList) return;
    for (var i=0; i<selectList.length; i++) {
        selectList.options[i].selected = false;
    }
}	

/**
 * Selects the option with the specified value in the select control.
 */
function selectOption(selectControl, value) {
    var selectOptions = selectControl.options;
    for (var i = 0; i < selectOptions.length; i++) {
        if (selectOptions[i].value == value) {
            selectControl.selectedIndex = i;
            break;
        }
    }
}

/**
 * Selects the options with the specified values in a multiselect select control
 */
function selectOptions(selectControl, values) {
    var selectOptions = selectControl.options;
    for (var i = 0; i < selectOptions.length; i++) {
        var matchFound = false;
        var optionValue = selectOptions[i].value;
        for (var j = 0; j < values.length; j++) {
            if (optionValue == values[j]) {
                selectOptions[i].selected = true;
                matchFound = true;
                break;
            }
            
            if (!matchFound) {
                selectOptions[i].selected = false;
            }
        }
    }
}

/**
 * Retrieves the selected option from a select control
 */
function getSelectedOption(selectControl) {
    if (selectControl) {
        if (-1 != selectControl.selectedIndex) {
            return selectControl.options[selectControl.selectedIndex];        
        } else {
            return null;
        }
    }

    return null;
}

/**
 * Retrieves the selected values from a multiselect control
 */
function getSelectedOptionValues(selectControl) {
    var selectedValues = new Array();
    for (var i = 0; i < selectControl.options.length; i++) {
        var option = selectControl.options[i];    
        if (option.selected) {
            selectedValues[selectedValues.length] = option.value;
        }
    }
    return selectedValues;
}


//------------------------------------------------------------------------------
//  Checkbox Utility Methods
//------------------------------------------------------------------------------

/**
 * Selects the checkbox with the specified value in the radio button group.
 */
function selectCheckbox(checkboxGroup, value) {
    if (checkboxGroup) {
        if (checkboxGroup.length) {
            for (var i = 0; i < checkboxGroup.length; i++) {
                if (checkboxGroup[i].value == value) {
                    checkboxGroup[i].checked = true;
                    break;
                }
            }
        } else {
            if (checkboxGroup.value == value) {
                checkboxGroup.checked = true;
            }
        }
    }
}

/**
 * Retrieves an array of all of the checked values in the specified 
 * checkbox group
 */
function getSelectedCheckboxValues(checkboxGroup) {
    var values = new Array();
    if (checkboxGroup) {
        if (checkboxGroup.length) {
            for (var i = 0; i < checkboxGroup.length; i++) {
                if (checkboxGroup[i].checked) {
                    values[values.length] = checkboxGroup[i].value
                }
            }
        } else {
            if (checkboxGroup.checked) {
                values[values.length] = checkboxGroup.value
            }
        }
    }
    
    return values;
}

/**
 * Retrieves an array of all of the checked values in the specified
 * checkbox group
 */
function getUnselectedCheckboxValues(checkboxGroup) {
    var values = new Array();
    if (checkboxGroup) {
        if (checkboxGroup.length) {
            for (var i = 0; i < checkboxGroup.length; i++) {
                if (!checkboxGroup[i].checked) {
                    values[values.length] = checkboxGroup[i].value
                }
            }
        } else {
            if (!checkboxGroup.checked) {
                values[values.length] = checkboxGroup.value
            }
        }
    }

    return values;
}

/**
 * Toggles the checkboxes on all of the checkboxes in the specified group.
 * 
 * @param checkboxGroup The group of checkboxes
 * @param checked true if the boxes should be checked, false otherwise. 
 */
function toggleCheckboxSelection(checkboxGroup, checked) {
    if (checkboxGroup) {
        if (checkboxGroup.length) {
            for (var i = 0; i < checkboxGroup.length; i++) {
                checkboxGroup[i].checked = checked;
            }
        } else {
            checkboxGroup.checked = checked;
        }
    }
}

/**
 * Determines if any of the elements in the specified checkbox group
 * are checked.   
 */
function isElementChecked(checkboxGroup) {
    var values = new Array();
    if (checkboxGroup) {
        if (checkboxGroup.length) {
            for (var i = 0; i < checkboxGroup.length; i++) {
                if (checkboxGroup[i].checked) {
                    return true;
                }
            }
        } else {
            if (checkboxGroup.checked) {
                return true;
            }
        }
    }
    
    return false;
}

/**
 * Determines if any of the elements in the specified checkbox group
 * are checked.   
 */
function isElementUnchecked(checkboxGroup) {
    var values = new Array();
    if (checkboxGroup) {
        if (checkboxGroup.length) {
            for (var i = 0; i < checkboxGroup.length; i++) {
                if (!checkboxGroup[i].checked) {
                    return true;
                }
            }
        } else {
            if (!checkboxGroup.checked) {
                return true;
            }
        }
    }
    
    return false;
}

/**
 * Sets the disabled flag on all of the items in a checkbox group
 */
function setCheckboxGroupDisabled(checkboxGroup, disabled) {
    if (checkboxGroup) {
        if (checkboxGroup.length) {
            for (var i = 0; i < checkboxGroup.length; i++) {
                checkboxGroup[i].disabled = disabled;
            }
        } else {
            checkboxGroup.disabled = disabled;
        }
    }
}


//------------------------------------------------------------------------------
//  Radio Button Utility Methods
//------------------------------------------------------------------------------

/**
 * Selects the radio button with the specified value in the radio button group.
 */
function selectRadioButton(radioButtonGroup, value) {
    if (radioButtonGroup) {
        if (radioButtonGroup.length) {
            for (var i = 0; i < radioButtonGroup.length; i++) {
                if (radioButtonGroup[i].value == value) {
                    radioButtonGroup[i].checked = true;
                    break;
                }
            }
        } else {
            if (radioButtonGroup.value == value) {
                radioButtonGroup.checked = true;
            }
        }
    }
}

/**
 * Retrieves the checked radio button from the specified group.
 */
function getSelectedRadioButton(radioButtonGroup) {
    if (radioButtonGroup) {
        if (radioButtonGroup.length) {
            for (var i = 0; i < radioButtonGroup.length; i++) {
                if (radioButtonGroup[i].checked) {
                    return radioButtonGroup[i];
                }
            }
        } else {
            if (radioButtonGroup.checked) {
                return radioButtonGroup; 
            }
        }
    }

    return null;
}

/**
 * Retrieves the value of the checked radio button from the specified group or null
 * if none is selected.
 */
function getSelectedRadioButtonValue(radioButtonGroup) {
    if (radioButtonGroup) {
        if (radioButtonGroup.length) {
            for (var i = 0; i < radioButtonGroup.length; i++) {
                if (radioButtonGroup[i].checked) {
                    return radioButtonGroup[i].value;
                }
            }
        } else {
            if (radioButtonGroup.checked) {
                return radioButtonGroup.value; 
            }
        }
    }

    return null;
}

/**
 * Sets the disabled flag on all of the items in a radio button group
 */
function setRadioButtonDisabled(radioButtonGroup, disabled) {
    if (radioButtonGroup) {
        if (radioButtonGroup.length) {
            for (var i = 0; i < radioButtonGroup.length; i++) {
                radioButtonGroup[i].disabled = disabled;
            }
        } else {
            radioButtonGroup.disabled = disabled;
        }
    }
}
 
/*------------------------------------------------------------------------------
 * Form Functions
 *
 * These functions require the x_core.js, x_dom.js, and x_event.js files to 
 * function correctly.
 *----------------------------------------------------------------------------*/
var _inputSubmissionFunctions = new Array();

/**
 * Initializes a form by binding the enter key press to the specified submission function.
 *
 * @param The form to process.
 * @param submissionFunction The function to call when the enter key is pressed on an input field.
 * @param autoFocus true if the focus should default to the first enabled element
 * @param focusElement The element to default the focus to.  This is only processed if autoFocus is
 *      false.
 */
function initForm(form, submissionFunction, autoFocus, focusElement) {
    if (autoFocus) {
        //Set the focusElement to null so that the focus will be calculated correctly
        focusElement = null;
    }
    
    for (var i = 0; i < form.elements.length; i++) {
        var input = form.elements[i];
        var inputType = input.type;
        if ((inputType == 'text') || (inputType == 'password') || (inputType == 'radio') || (inputType == 'checkbox')) {
            xAddEventListener(input, 'keypress', onFormKeyPress, false);
            
            _inputSubmissionFunctions[_inputSubmissionFunctions.length] =
                new RegisteredInput(input, submissionFunction);
        }
        
        if ((autoFocus) && (null == focusElement)) {
            if ((inputType != 'hidden') && (!input.disabled) && (!input.readOnly)) {
                focusElement = input;
            }
        }
    }
    
    if (focusElement) {
        focusElement.focus();
    }
}

/**
 * Event handler for the form key press
 */
function onFormKeyPress(evt) {
    var e = new xEvent(evt);
    if (13 == e.keyCode) {
        //This is not the best way to map inputs to functions, but it seems to
        //work for now and is not a performance pig so I'll leave it.  
        // -MCW 8/10/2004
        for (var i = 0; i < _inputSubmissionFunctions.length; i++) {
            if (_inputSubmissionFunctions[i].input == e.target) {
                _inputSubmissionFunctions[i].submissionFunction();
            }
        }
    } else {
        return true;
    }
}

/**
 * Object Template to map input fields to their submission function
 */
function RegisteredInput(input, submissionFunction) {
    this.input = input; 
    this.submissionFunction = submissionFunction;
}

/*------------------------------------------------------------------------------
 * Button Manipulation
 *----------------------------------------------------------------------------*/
var _disabledLinks = new Array();
var _linkOnClicks = new Array();

/**
 * Enables or disables a link.
 *
 * @param id                    The id of the link to toggle.
 * @param enable                true to enable the link, false to disable it
 * @param disabledClassName     An optional class name to use when flagging a link as
 *      disbled.
 */
function enableLink(id, enable, disabledClassName) {
    if (!disabledClassName) {
        disabledClassName = 'disabledButton';
    }
    
    var link = xGetElementById(id);
    if (link) {
        if (enable) {
            if (_disabledLinks[id]) {
                //The link is curently disabled, so we need to reenable it
                _disabledLinks[id] = false;

                if (_linkOnClicks[id]) {
                    //Restore the enable onclick functionality
                    link.onclick = _linkOnClicks[id];
                } else {
                    //Clear the disabled onclick functionality
                    link.onclick = null;
                }

                //Update the class on the link
                removeClassName(link, disabledClassName);
            }
        } else {
            if (!_disabledLinks[id]) {
                //The link is curently enabled, so we need to disable it
                _disabledLinks[id] = true;
                if (link.onclick) {
                    //Cache the current link on click behavior
                    _linkOnClicks[id] = link.onclick;
                }

                //Populate the onclick event with a return false function
                link.onclick = function() { return false; }

                //Update the class on the button
                appendClassName(link, disabledClassName);
            }
        }
    }
}
