
/*** CONFIRM EXIT FROM A FORM ***/

/* set to 1 if data has been submitted through submit button */
var form_submitted = 0;


/*
 * Accept changes in a form prior to submitting it.  This function is
 * necessary to bypass onbeforeunload handler which would confirm exit
 * from a page when user submits a form through the submit button.
 *
 * This very function must be attached to form.onsubmit handler to work.
 */
function form_accept () {
  form_submitted = 1;
  return true;
}


/*
 * Discard changes to a form and allow user to leave the current page 
 * without confirmation.
 */
function form_discard () {
  form_reset();
  return true;  
}


/*
 * Called prior to leaving the current page in Mozilla, Firefox, MSIE and 
 * Safari.  The purpose of this function is to check if the page has unsaved
 * changes and confirm the exit if there is a risk of losing some data.
 *
 * This function has unusual calling schemantics.  If the function does not
 * return anything, then no questions will be asked and the user is free to
 * navigate to another page.  However, if the function does return something,
 * even an empty string or null, then the return value is shown to user in
 * a question dialog and user is asked to make a choice.
 */
function form_confirm () {
  if (form_submitted == 0) {
    /* iterate form elements in all forms */
    var changed = false;
    for (var i = 0; i < document.forms.length; ++i) {
      for (var j = 0; j < document.forms[i].length; ++j) {
        var f = document.forms[i].elements[j];
        if (f.type == "checkbox") {
          if (f.checked != f.defaultChecked) {
            changed = true;
          }
        } else if (f.type == "text"  ||  f.type == "textarea") {
          if (f.defaultValue != f.value) {
            /* value changed */
            changed = true;
          }
        } else if (f.type == "select-one") {
          for (var k = 0; k < f.options.length; ++k) {
            if (f.options[k].selected != f.options[k].defaultSelected) {
              /* selection changed */
              changed = true;
            }
          }
        }
      }
    }

    /* confirm exit (see header for discussion on calling schemantics) */
    if (changed) {
      return "Changes will be lost if you navigate away from this page without submitting the form.";
    }
  }
  form_submitted = 0;
}


/* install the form_configm to be called prior to navigating away */
window.onbeforeunload = form_confirm;



/*** FORM VALIDATION ***/

/*
 * See if the string s is a valid email address.
RFC 2821:
"The local-part of a mailbox MUST BE treated as case sensitive. Therefore,
SMTP implementations MUST take care to preserve the case of mailbox
local-parts. Mailbox domains are not case sensitive. In particular,
for some hosts the user "smith" is different from the user "Smith".
However, exploiting the case sensitivity of mailbox local-parts impedes
interoperability and is discouraged."
 */
function form_isemail (s) {
  return s.match(/^ *[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@([0-9a-z][0-9a-z-]*[0-9a-z]\.)+[a-z]{2}[mtgvu]? *$/);
}



/*** FORM ACTIONS ***/

/*
 * Clear all input fields in a form.  This is useful if the default
 * values are retrieved from database, for example, in which case the
 * standard reset would undo editing and leave the fields filled.
 */
function form_reset () {
  /* iterate form elements in all forms */
  var changed = false;
  for (var i = 0; i < document.forms.length; ++i) {
    for (var j = 0; j < document.forms[i].length; ++j) {
      var f = document.forms[i].elements[j];
      if (f.type == "checkbox"  ||  f.type == "radio") {
        f.checked = false;
      } else if (f.type == "text"  ||  f.type == "textarea") {
        f.value = "";
      } else if (f.type == "select-one") {
        f.selectedIndex = 0;
      }
    }
  }

  return false;
}



