/*   10/16/2007 - ALIWEB's JavaScript for Forms/Field Entries           */

//      Global Variables

//      Form Functions
// setupForEdits() - Load the behavior we want for our fields
// setupFieldErrors() - Preload any field errors
// focusToFirst() - Set the focus to the first field
// getFormsFieldsArray() - Return the fields array for a form
// validateForm() - Validate all fields in the form

//      Field Functions
// setupFormFields() - Setup all fields for a form
// addErrorSpan() - Add a span element containing an error message
// hasWarning() - Return true if the passed field has a warning
// getFormsFieldObject() - Return the field object for a form

//      Field Validations
// validateField(oFld) - Validate a field
// stdValidations() - Handle all standard validations for a part
// getEntry() - Return the entry for a field
// getButtonGroup() - Return the button group for radio button name
// getRadioGrpValue(fld) - Return the value of a radio button group
// updtFieldStatus() - Update the error status of a field
// chkReqd() - Check that something was entered into the field
// chkNumber() - Check that only valid numbers were entered
// chkUSPhone() - Check that a valid US phone number was entered
// chkAllPhone() - Check that a valid US or foreign phone number was entered
// chkEmail() - Check that a valid email address was entered
// chkNSN() - Check that a valid NSN or NIIN was entered

//      Label Functions
// loadLabelFocus() - If a label is clicked, set the focus to its field

//      Style Functions
// fldLite() - Hilight the activated field
// fldUnlite() - Unhilight the activated field

//      Field Entry Aids
// saveCalendar() - Save the Calendar search results
// setupCalendar() - Setup and do the Calendar

//      Load Listeners

/************************************************************************/

//      Global Variables
var validErrCount = 0;       // Number of errors during page validation

// Array of all forms formatted as:
//      .Fld1 - Form ID
//      .Fld2 - Form Object
//      .Fld3 - Entry Fields Array (containing only field objects)
var raPageForms = new Array();

// Incoming field errors array; loaded as:
//      .Fld1 = field's ID
//      .Fld2 = error message
// Assigments must be done within the web page
var incomingErrors = new Array();

//      Form Functions

// setupForEdits() - Load the behavior we want for our fields
function setupForEdits()   {

    // Handle each form; one at a time
    var numForms = document.forms.length;
    for (var nRow=0; nRow < numForms; nRow++)    {
        var form = document.forms[nRow];

        // Handle all of this form's fields
        var raFlds = setupFormFields(form);

        // Add the form's submit handler
        form.onsubmit = function()    {
            return (validateForm(this.getAttribute("id")));
        }

        // Add the form and fields array to our global array
        var formID = form.getAttribute("id");
        raPageForms[nRow] = new LoadChoice(formID, form, raFlds);
    }

    // Now, load any initial error messages into their fields
    setupFieldErrors();
}

// setupFieldErrors() - Preload any field errors
function setupFieldErrors() {

    // Here we need to see if we have any errors recorded in our incoming
    //  array; if so, we're to pre-load the error message into the field.
    var errCount = incomingErrors.length;
    for (var i = 0; i < errCount; i++)    {
        if (incomingErrors[i].Fld1)    {
            var fieldID = incomingErrors[i].Fld1;
            var message = incomingErrors[i].Fld2;
            var fldObj = document.getElementById(fieldID);
            updtFieldStatus(fldObj, message);
            fldUnlite(fldObj);
        }
    }
}

// focusToFirst() - Set the focus to the first field
function focusToFirst()   {
    var form = document.forms[0];
    if (!hasClass(form, "hidden")) {
        for (var nRow=0; nRow < form.elements.length; nRow++)    {
            var elem = form.elements[nRow];
            if ((elem.tagName == "INPUT" || elem.tagName == "SELECT" ||
              elem.tagName == "TEXTAREA") && !(elem.type == "hidden" ||
              elem.type == "button" || elem.type == "submit"))    {
                elem.focus();
                break;
            }
        }
    }
}

// getFormsFieldsArray() - Return the fields array for a form
function getFormsFieldsArray(formsNameOrID) {
    var fieldsRA = false;
    var numForms = raPageForms.length;
    for (var i = 0; i < numForms; i++)   {
        if (raPageForms[i].Fld1 == formsNameOrID) {
            fieldsRA = raPageForms[i].Fld3;
            break;
        }
    }
    return fieldsRA;
}

// validateForm() - Validate all fields
function validateForm(formID) {
    validErrCount = 0;                      // Reset

    // Get our form's field array
    var raFields = getFormsFieldsArray(formID)

    // Now, validate each of the form's fields
    if (raFields)   {
        var numFlds = raFields.length;
        for (i = 0; i < numFlds; i++)   {
            var theFld = raFields[i];

            // Make it look like it's been changed, then validate it
            if (!hasClass(theFld, 'itChanged')) {
                addClass(theFld, 'itChanged');
            }
            validateField(theFld);
        }
        var retStatus = (validErrCount == 0)
        if (!retStatus) {
            focusToFirst()
        }
    }

    // If there's a finalValids() function, call that
    if (this.finalValids)    {
        this.finalValids(formID);
    }

    // If we're OK, show the hourglass
    if (validErrCount == 0) {
        oBody = document.body;
        addClass(oBody, "waiting");
        return true;
    }
    return false;
}


//      Field Functions

// setupFormFields() - Setup all fields for a form
function setupFormFields(theForm)   {

    // We'll need to return an array of fields for the form
    var raFields = new Array()

    // Now, handle all fields for the form
    var fields = theForm.elements;
    for (var i=0; i < fields.length; i++)  {
        var thisFld = fields[i];

        // Handle only user entry fields. Radio buttons can't be in error, nor
        //  can they be invalid so ignore them.  (If we have to do something
        //  with them it will require a custom function and custom load
        //  listener.
        if (!(thisFld.tagName == "INPUT" || thisFld.tagName == "SELECT" ||
          thisFld.tagName == "TEXTAREA")) {
            continue;
        }

        // We'll ignore all buttons here
        if (thisFld.tagName != "TEXTAREA") {
            var fldType = thisFld.getAttribute("type")
            if (fldType)    {
                fldType = fldType.toLowerCase();
            }
            if (fldType == 'button' || fldType == 'reset' ||
              fldType == 'submit' || fldType == 'hidden')
                continue;
        }

        // Add this field to our array and create its error span object
        fldCount = raFields.length;
        raFields[fldCount] = thisFld;
        addErrorSpan(thisFld);

        // Setup this field's display and focus/blur handlers. Also, radio
        //  buttons can't be in error, nor can they be invalid so ignore them.
        //  (If we have to do something with them it will require a custom
        //  function and custom load listener.
        if (fldType != 'radio')   {
            fldUnlite(thisFld);

            // Set onfocus unless ie7 and SELECT
            if (!(Browser == "ie7" && thisFld.tagName == "SELECT")) {
                thisFld.onfocus = function()    {
                    fldLite(this);
                }
            }
            thisFld.onblur = function() {
                validateField(this);
                fldUnlite(this);
            }
            if (thisFld.tagName == "SELECT") {
                var cAttr = thisFld.getAttribute("onchange");
                if (!cAttr) {
                    thisFld.onchange = function() {
                        validateField(this);
                        fldUnlite(this);
                    }
                }
            }
        }
    }
    return raFields;
}

// addErrorSpan() - Add a span element containing an error message
function addErrorSpan(errFld)   {

    // Create a <span> element with blank text; set its class and id
    var objSpan = document.createElement("span");
    var objText = document.createTextNode("");
    objSpan.appendChild(objText);
    objSpan.className = "red bold";
    objSpan.id = "err" + errFld.getAttribute("name");

    // Add the span element after the field
    insertAfter(objSpan, errFld);
}

// hasWarning() - Return true if the passed field has a warning
function hasWarning(fld) {

    // Two conditions are require for the field to show a warning:
    //  1. It must have a chkReqd class
    //  2. Its value must be empty
    if (hasClass(fld, 'chkReqd'))   {
        value = fld.value;
        if (Empty(value))   {
            return true;
        }
    }
    return false;
}

// getFormsFieldObject() - Return the field object for a form
function getFormsFieldObject(fldName, formName) {

    // If no formName is passed, it's the first form on the page
    if (!formName) {
        var formObj = document.forms[0];
    } else {
        formObj = null;
        for (i = 0; i < document.forms.length; i++) {
            if (document.forms[i].name == formName) {
                formObj = document.forms[i];
                break;
            }
        }
    }
    return formObj[fldName];
}


//      Field Validations

// validateField(oFld) - Validate a field
function validateField(oFld)    {
    var entry = getEntry(oFld);

    // If this has some classes, go handle the standard validations
    var errMessage = "";
    if (oFld.className) {
        errMessage = stdValidations(oFld, entry);
    }

    // If there's a check_<fldname> method, go run it
    if (errMessage.length == 0) {
        checkFunc = "check_" + oFld.getAttribute("name")
        if (this[checkFunc])    {
            errMessage = this[checkFunc](entry);
        }
    }

    // Update the field's status
    updtFieldStatus(oFld, errMessage);
    return true;        // We'll always let them out of a field
}

// stdValidations() - Handle all standard validations for a part
function stdValidations(oFld, entry)    {
    var warnMsg = "";
    if (hasClass(oFld, "chkReqd")) {
        warnMsg = chkReqd(oFld, entry);
    }
    if (warnMsg.length == 0 && hasClass(oFld, "chkNumber")) {
        warnMsg = chkNumber(oFld, entry);
    }
    if (warnMsg.length == 0 && hasClass(oFld, "chkUSPhone"))  {
        warnMsg = chkUSPhone(oFld, entry);
    }
    if (warnMsg.length == 0 && hasClass(oFld, "chkAllPhone"))  {
        warnMsg = chkAllPhone(oFld, entry);
    }
    if (warnMsg.length == 0 && hasClass(oFld, "chkEmail"))  {
        warnMsg = chkEmail(oFld, entry);
    }
    if (warnMsg.length == 0 && hasClass(oFld, "chkNSN"))  {
        warnMsg = chkNSN(oFld, entry);
    }
    return warnMsg;
}

// getEntry() - Return the entry for a field
function getEntry(fld) {
    var fldType = fld.tagName.toLowerCase();
    if (fldType == "input") {
        fldType = fld.getAttribute("type")
    }
    switch (fldType)    {
    case "text":
        trimVal = fld.value.AllTrim();
        fld.value = trimVal;
        return trimVal
    case "password":
        trimVal = fld.value.AllTrim();
        fld.value = trimVal;
        return trimVal
    case "checkbox":
        return fld.checked;           // true or false
    case "radio":
        return getRadioGrpValue(fld);    // value of selected button
    case "select":
        return fld.value;
    case "textarea":
        trimVal = fld.value.AllTrim();
        fld.value = trimVal;
        return trimVal
    }
    return "";
}

// getButtonGroup() - Return the button group for radio button name
function getButtonGroup(buttonName) {
    var btnGroup = false;
    for (var i = 0; i < raPageForms.length; i++)   {
        var thisForm = raPageForms[i].Fld2;
        if (thisForm[buttonName])   {
            var btnGroup = thisForm[buttonName];
            break;
        }
    }
    return btnGroup;
}

// getRadioGrpValue() - Return the value of a radio button group
function getRadioGrpValue(btnOrGroup) {
    if (btnOrGroup.length > 0) {
        var btnGroup = getButtonGroup(btnOrGroup);
    } else {
        btnGroup = btnOrGroup;
    }
    for (var i=0; i < btnGroup.length; i++) {
        if (btnGroup[i].checked == true)    {
            return btnGroup[i].value;
        }
    }
    return "";
}

// updtFieldStatus() - Update the error status of a field
function updtFieldStatus(theFld, errMsg)    {
    var spanName = "err" + theFld.getAttribute("name");
    var objSpan = document.getElementById(spanName);
    if (objSpan)    {
        spanText = objSpan.firstChild;
        if (errMsg.length == 0) {
            if (hasClass(theFld, "fldOops")) {
                removeClass(theFld, "fldOops");
            }
            spanText.nodeValue = errMsg;
        } else  {
            validErrCount += 1;
            if (!hasClass(theFld, "fldOops")) {
                addClass(theFld, "fldOops");
            }
            spanText.nodeValue = " " + errMsg;
        }
    }
    fldUnlite(theFld);
}

// chkReqd() - Check that something was entered into the field
function chkReqd(fld, fldEntry)    {
    var msg = ""

    // We'll only show the error message if the field was changed
    if (Empty(fldEntry)) {
        if (hasClass(fld, 'itChanged')) {
            msg = "An entry is needed."
        }
    } else {

        // Here we have an entry
        if (!hasClass(fld, 'itChanged')) {
            addClass(fld, 'itChanged');
        }
    }
    return msg;
}

// chkNumber() - Check that only valid numbers were entered
function chkNumber(fld, fldEntry)    {
    var msg = "";
    if (fldEntry.length > 0)    {

        // Strip out commas
        var stripped = fldEntry.replace(/,/g, '');
        var pattern = /^-?\d+(\.\d+)?$/;
        if (!pattern.test(stripped))  {
            msg = "The entry can only be a number."
        } else {
            fldEntry = stripped;
            fld.value = stripped;
        }
    }
    if (Empty(msg))  {
        var numValue = parseFloat(fldEntry);
        if (hasClass(fld, 'chkReqd') && numValue == 0.00)   {
            msg = "An entry is needed."
        }
    }
    return msg;
}

// chkUSPhone() - Check that a valid phone number was entered
function chkUSPhone(fld, fldEntry)    {
    var msg = "";
    if (fldEntry.length > 0)    {

        // Use a reg expr to strip out spaces, dashes, periods and parentheses
        var stripped = fldEntry.replace(/[\(\)\.\-\ ]/g, '');

        // Make sure what's left is numeric
        var pattern = /^\d+$/;
        if (!pattern.test(stripped))  {
            msg = "Phone has invalid characters.";
        } else if ((stripped.length != 10)) {
            msg = "Phone number is wrong length.";
        }
    }
    return msg;
}

// chkAllPhone() - Check that a valid US or foreign phone number was entered
function chkAllPhone(fld, fldEntry)    {
    var msg = "";
    if (fldEntry.length > 0)    {

        // Use a reg expr to strip out spaces, dashes, periods and parentheses
        //  and plus sign
        var stripped = fldEntry.replace(/[\(\)\.\-\ \+]/g, '');

        // Make sure what's left is numeric
        var pattern = /^\d+$/;
        if (!pattern.test(stripped))  {
            msg = "Phone has invalid characters.";
        }
    }
    return msg;
}

// chkEmail() - Check that a valid email address was entered
function chkEmail(fld, fldEntry)    {
    var msg = "";
    if (fldEntry.length > 0)    {
        var pattern = /^[\w\.\-]+@([\w\-]+\.)+[a-zA-Z]+$/;
        if (!pattern.test(fldEntry))  {
            msg = "The Email entry is invalid."
        }
    }
    return msg;
}

// chkNSN() - Check that a valid NSN or NIIN was entered
function chkNSN(fld, fldEntry)    {
    var msg = "";

    // Toss any dashes
    var testEntry = fldEntry.StrTran("-", "").AllTrim();

    // NSNs must now be 13 chars long, NIINs are 9 chars
    if (!(testEntry.length == 9 || testEntry.length == 13))    {
        msg = "That NSN/NIIN entry is invalid."
    }
    return msg;
}

//      Label Functions

// loadLabelFocus() - If a label is clicked, set the focus to its field
function loadLabelFocus()   {
    if (!document.getElementsByTagName) return false;
    var oLabels = document.getElementsByTagName("label");
    for (var i=0; i < oLabels.length; i++)  {
        var thisLabel = oLabels[i];
        var forAttr = thisLabel.getAttribute("for");
        if (forAttr) {
            thisLabel.onclick = function () {
                var id = this.getAttribute("for");
                if (!document.getElementById(id))
                    return false;
                var element = document.getElementById(id);
                element.focus();
            }
        }
    }
}

//      Style Functions

// fldLite() - Hilight the activated field
function fldLite(obj)    {

    // Needed to overcome styling deficiencies in IE
    obj.style.background = '#E4F7FA';
    obj.style.border = '2px solid #001C70';
}

// fldUnlite() - Unhilight the activated field
function fldUnlite(obj)    {

    // Needed to overcome styling deficiencies in IE
    if (hasClass(obj, 'fldOops'))   {
        obj.style.background = '#FF3E3E';
    } else if (hasWarning(obj))    {
        obj.style.background = '#FFDDDD';
    } else {
        obj.style.background = '#FFF';
    }
    obj.style.border = '2px solid #999';
}


//      Field Entry Aids

// Calendar public variables
var days = new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
var months = new Array('January','February','March','April','May','June','July','August','September','October','November','December');
oDate = '';

// setupCalendar() - Setup and do the Calendar
function setupCalendar(formVar)    {

    // Set the public variable
    oDate = formVar;
    if ( !Empty(oDate.value))  {
        if ( !isDate(oDate) ) {
            return false;
        }
    }

    // Open our dialog window
    var dialogWin = new Object();
    dialogWin.width = 225;
    dialogWin.height = 225;

    // The best we can do is center in screen.
    dialogWin.left = (screen.width - dialogWin.width) / 2
    dialogWin.top = (screen.height - dialogWin.height) / 2
    var attr = "left=" + dialogWin.left + ",top=" +
      dialogWin.top + ",resizable=yes,width=" + dialogWin.width +
      ",height=" + dialogWin.height

    // Open the window and set the focus
    dialogWin.win = window.open('/calendar.htm','wincalendar',attr);
    dialogWin.win.focus()

    // done
    return true;
}

// saveCalendar() - Save the Calendar search results
function saveCalendar( cDate ) {

    // update the field
    oDate.value = cDate;
    isDate(oDate);

    // done
}


//      Load Listeners (these run after the page loads)
addLoadListener(loadLabelFocus);
addLoadListener(setupForEdits);
addLoadListener(focusToFirst);