/*************************************************************************
 * FILE:   formValidation.css                                            *
 * AUTHOR: Justin Spargur                                                *
 * DATE:   04/11/07                                                      *
 *                                                                       *
 * DESCRIPTION:                                                          *
 * This file contains the Javascript used to provide form validation     *
 * for the WYSIWYG email form used in the UA Spending Reduction          *
 * application.                                                          *
 *                                                                       *
 * FUNCTIONS INCLUDED:                                                   *
 *    - validateForm   - Validate all elements in a given form that      *
 *                       have a class value containing the word          *
 *                       'required'.                                     *
 *    - trimAll        - Removes whitespace from around a set of words.  *
 *    - noReturn       - Prevents a form from submitting when the        *
 *                       'Enter' key is pressed while in an input field. *
 *    - validateEmail  - Validates whether a given string is a valid     *
 *                       email address.                                  *
 *                                                                       *
 * GLOBAL VARIABLES:                                                     *
 *    - SHOW_ERRORS => Used in debugging.                                *
 *                                                                       *
 * KNOWN BUGS:                                                           *
 *    - None                                                             *
 *                                                                       *
 * ADDITIONAL NOTES:                                                     *
 *    - None                                                             *
 *                                                                       *
 * CHANGES MADE:                                                         *
 *    - None                                                             *
 *                                                                       *
 *************************************************************************/

// Global variables.
var SHOW_ERRORS = false;

function initFileFields()
{
   alert("here");
   document.getElementById("MAX_FILE_SIZE").value = "100";
   alert(document.getElementById("MAX_FILE_SIZE").value);
}

/****************************************************
 * METHOD NAME: validateForm                        *
 *                                                  *
 * DESCRIPTION: Validate all elements in a given    *
 *              form which have a class value       *
 *              containing the word required.       *
 *                                                  *
 *              For select boxes, it will require   *
 *              the user to select something other  *
 *              than the first (default) option.    *
 *                                                  *
 *              Change: If there is a parent node   *
 *              surrounding the select, then it     *
 *              will be highlighted  --Gene         *
 *                                                  *
 *              For radio buttons, it will require  *
 *              that one of the options has been    *
 *              selected. If there is a parent node *
 *              surrounding the set of radio        *
 *              buttons (that is not the form       *
 *              itself), then it will be            *
 *              highlighted.                        *
 *                                                  *
 *              For text boxes, it will do an       *
 *              additional check to see if the      *
 *              element name contains the word      *
 *              "email". If it does, it will try to *
 *              validate the email address using    *
 *              another function called             *
 *              validateEmail().                    *
 *                                                  *
 *              This does not cover "file-select"   *
 *              fields.                             *
 *                                                  *
 * PARAMETERS:  theForm - the form being validated. *
 *                                                  *
 * RETURNS:     Boolean - If the form is valid, it  *
 *              returns true. Otherwise, it alerts  *
 *              the user to the error and returns   *
 *              false.                              *
 ****************************************************/
function validateForm(theForm)
{
   // Give the user the benefit of the doubt.
   var isValid = true;

   // Initialize our default error message.
   var errorMessage = "Please fill out all required fields.\nMissing or unselected items are marked in red.\nThank you.";

   // Loop through every element in the form
   for(a = 0; a < theForm.elements.length; a++)
   {
      // Get the element.
      var thisField = theForm.elements[a];
      
      // Get the class name.
      var thisClass = thisField.className;

     /***************************************
      * If the current element is required, *
      * then we check to see if it's valid. *
      * Otherwise, we ignore it.            *
      ***************************************/
      if(thisClass.indexOf("required") != -1)
      {
        /************************************
         * If the element is a select box,  *
         * then we make sure that the user  *
         * has selected something other     *
         * than the first element in the    *
         * drop-down menu. If they haven't, *
         * then we highlight the parent     *
         * node and set isValid to false.   *
         ************************************/
         if(thisField.type == "select-one")
         {
            if(thisField.selectedIndex == 0)
            {
               thisField.parentNode.style.border = "1px solid red";
               if(document.getElementById(thisField.id+"Label"))
                  document.getElementById(thisField.id+"Label").style.color = "red";
               isValid = false;
            }
         }
        /***********************************
         * If the element is a text input, *
         * then we make sure that it's not *
         * blank. If it is, then we        *
         * highlight the parent node and   *
         * set isValid to false.           *
         ***********************************/
         else if(thisField.type == "text" || thisField.type == "password" || thisField.type == "file")
         {
            // Trim off any leading or trailing white space.
            if(trimAll(thisField.value) == "")
            {
               thisField.style.border = "1px solid red";
               if(document.getElementById(thisField.id+"Label"))
                  document.getElementById(thisField.id+"Label").style.color = "red";
               isValid = false;
            }
           /***********************************
            * If the text input isn't blank,  *
            * then we check to see if it's an *
            * email field. If it is, then we  *
            * try to validate the input as a  *
            * valid email address.            *
            ***********************************/
            else 
            {
               var fieldName = thisField.name;
               var mailpat =/email/i;
               if (fieldName.match(mailpat) != null )
               {
                  var emailStr = thisField.value;
                  // Check the email and alert the user to any errors.
                  if(!validateEmail(emailStr, SHOW_ERRORS))
                  {
                     if(document.getElementById(thisField.id+"Label"))
                        document.getElementById(thisField.id+"Label").style.color = "red";
                     isValid = false;
                     errorMessage = "Please enter a valid email address.";
                  }
               }
            }
         }
        /***********************************
         * If the element is a textarea,   *
         * then we make sure that it's not *
         * blank. If it is, then we        *
         * highlight the parent node and   *
         * set isValid to false.           *
         ***********************************/
         else if(thisField.type == "textarea")
         {
            if(thisField.value == "")
            {
               thisField.style.border = "1px solid red";
               if(document.getElementById(thisField.id+"Label"))
                  document.getElementById(thisField.id+"Label").style.color = "red";
               isValid = false;
            }
         }
        /*************************************
         * If the element is a radio button, *
         * then we make sure that something  *
         * has been chosen from the options. *
         * If nothing has been selected, we  *
         * highlight the parent node and set *
         * isValid to false.                 *
         *************************************/
         else if(thisField.type == "radio")
         {
            // Get the whole set of radio button options.
            var radiogroup = theForm.elements[thisField.name];
            var isChecked = false;

            for (i=0; i<radiogroup.length; i++)
            {
               if (radiogroup[i].checked)
               {
                  isChecked = true;
                  break;
               }
            }
            
            if(!isChecked)
            {
               isValid = false;
               if(thisField.parentNode.tagName != "FORM")
               {
                  thisField.parentNode.style.border = "1px solid red";
                  if(document.getElementById(thisField.name+"Label"))
                     document.getElementById(thisField.name+"Label").style.color = "red";

               }
            }
         }
      }
   }
   
   // If the form isn't valid, alert the user.
   if(!isValid)
      alert(errorMessage);

   return isValid;
}

/****************************************************
 * METHOD NAME: trimAll                             *
 *                                                  *
 * DESCRIPTION: This is a rewrite of the common     *
 *              trim function native to many        *
 *              programming languages, but not to   *
 *              Javascript! The function simply     *
 *              removes any leading or trailing     *
 *              whitespace and returns the string.  *
 *                                                  *
 *              It is worth noting that this only   *
 *              removes spaces and not new lines or *
 *              tabs.                               *
 *                                                  *
 * PARAMETERS:  sString - the form being validated. *
 *                                                  *
 * RETURNS:     String - String without leading or  *
 *              trailing white space.               *
 ****************************************************/
function trimAll(sString)
{
   // Strip of leading white-space
   while (sString.substring(0,1) == ' ')
   { sString = sString.substring(1, sString.length); }

   // Strip of trailing white-space
   while (sString.substring(sString.length-1, sString.length) == ' ')
   { sString = sString.substring(0,sString.length-1); }

   // Return trimmed string.
   return sString;
}

/****************************************************
 * METHOD NAME: noReturn                            *
 *                                                  *
 * DESCRIPTION: This function is called when an     *
 *              input element's onkeypress event    *
 *              is called. The function simply      *
 *              catches any keystrokes and returns  *
 *              true, unless the keystroke is the   *
 *              'Enter' button, in which case false *
 *              is returned, keeping the form from  *
 *              submitting.                         *
 *                                                  *
 * PARAMETERS:  key - Key pressed by the user.      *
 *                                                  *
 * RETURNS:     Boolean - False if the key pressed  *
 *              is the 'Enter' key, true otherwise. *
 ****************************************************/
function noReturn(key)
{
   if (window.event)
   {
      if (window.event.keyCode == 13)
         return false;
   }
   else if (key)
   {
      if (key.which == 13)
         return false;
   }
   return true;
}


/****************************************************
 * METHOD NAME: validateEmail                       *
 *                                                  *
 * DESCRIPTION: This is a massive email validation  *
 *              script! It uses lots of regular     *
 *              expressions and covers a lot of     *
 *              bases. Read inline comments for     *
 *              more details about what is covered. *
 *                                                  *
 * PARAMETERS:  emailStr   - the string to be       *
 *                           checked                *
 *              showErrors - boolean indicating     *
 *                           whether alerts should  *
 *                           be used when an error  *
 *                           is found.              *
 *                                                  *
 * RETURNS:     Boolean - True if the string is a   *
 *              valid email address format. False   *
 *              otherwise.
 ****************************************************/
function validateEmail(emailStr, showErrors)
{
   var checkTLD=1;
   
   var knownDomainsPattern=/^(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$/;

   // Specify user@domain format
   var emailPattern=/^(.+)@(.+)$/;

   // Things we don't want ...
   var specialChars="\\(\\)><@,;:\\\\\\\"\\.\\[\\]";

   // (Allow everything but the above)
   var validChars="\[^\\s" + specialChars + "\]";

   // Allow for quoted user names
   var quotedUser="(\"[^\"]*\")";

   // Allow for domains in IP format
   var ipDomainPattern=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;


  /***********************************
   * The following string represents *
   * an atom (basically a series of  *
   * non-special characters.)        *
   ***********************************/
   var atom=validChars + '+';

  /*************************************
   * The following string represents   *
   * one word in the typical username. *
   * For example, in                   *
   * john.doe@somewhere.com, john and  *
   * doe are words. Basically, a word  *
   * is either an atom or quoted       *
   * string.                           *
   *************************************/
   var word="(" + atom + "|" + quotedUser + ")";

  /***********************************
   * The following pattern describes *
   * the structure of the user.      *
   ***********************************/
   var userNamePattern = new RegExp("^" + word + "(\\." + word + ")*$");

  /***********************************
   * The following pattern describes *
   * the structure of a normal       *
   * symbolic domain, as opposed to  *
   * ipDomainPattern, shown above.   *
   ***********************************/
   var domainNamePattern = new RegExp("^" + atom + "(\\." + atom +")*$");

  /**********************************
   * Finally, let's start trying to *
   * figure out if the supplied     *
   * address is valid.              *
   * Begin with the coarse pattern  *
   * to simply break up user@domain *
   * into different pieces that are *
   * easy to analyze.               *
   **********************************/
   var matchArray=emailStr.match(emailPattern);

   if (matchArray==null)
   {
      /***********************************
       * Too many/few @'s or something;  *
       * basically, this address doesn't *
       * even fit the general mould of a *
       * valid e-mail address.           *
       ***********************************/
      if(showErrors)
         alert("Email address seems incorrect (check @ and .'s)");
      return false;
   }

   var user=matchArray[1];
   var domain=matchArray[2];

  /*********************************
   * Start by checking that only   *
   * basic ASCII characters are in *
   * the strings (0-127).          *
   *********************************/
   for (i=0; i<user.length; i++)
   {
      if (user.charCodeAt(i)>127)
      {
         if(showErrors)
            alert("Ths username contains invalid characters.");
         return false;
      }
   }

   for (i=0; i<domain.length; i++)
   {
      if (domain.charCodeAt(i)>127)
      {
         if(showErrors)
            alert("Ths domain name contains invalid characters.");
         return false;
      }
   }

   // See if "user" is valid 
   if (user.match(userNamePattern)==null) 
   {
      // User is not valid
      if(showErrors)
         alert("The username doesn't seem to be valid.");
      return false;
   }

  /**********************************
   * If the e-mail address is at an *
   * IP address (as opposed to a    *
   * symbolic host name) make sure  *
   * the IP address is valid.       *
   **********************************/
   var IPArray=domain.match(ipDomainPattern);
   if (IPArray!=null) 
   {

      // This is an IP address
      for (var i=1; i<=4; i++) 
      {
         if (IPArray[i]>255)
         {
            if(showErrors)
               alert("Destination IP address is invalid!");
            return false;
         }
      }
      return true;
   }

   // Domain is symbolic name.  Check if it's valid.
   var atomPat=new RegExp("^" + atom + "$");
   var domArr=domain.split(".");
   var len=domArr.length;

   for (i=0;i<len;i++) 
   {
      if (domArr[i].search(atomPat)==-1) 
      {
         if(showErrors)
            alert("The domain name does not seem to be valid.");
         return false;
      }
   }

  /************************************
   * Domain name seems valid, but now *
   * make sure that it ends in a      *
   * known top-level domain (like     *
   * com, edu, gov) or a two-letter   *
   * word, representing country (uk,  *
   * nl), and that there's a hostname *
   * preceding the domain or country. *
   ************************************/
   if (checkTLD && domArr[domArr.length-1].length!=2 && domArr[domArr.length-1].search(knownDomainsPattern)==-1) 
   {
      if(showErrors)
         alert("The address must end in a well-known domain or two letter country.");
      return false;
   }

  /*********************************
   * Make sure there's a host name *
   * preceding the domain.         *
   *********************************/
   // 
   if (len<2) 
   {
      if(showErrors)
         alert("This address is missing a hostname!");
      return false;
   }

  /*****************************
   * If we've gotten this far, *
   * everything's valid!       *
   *****************************/
   return true;

}