if (this['document']) {

  function getText(control) {
    if (document.all)
        return control.innerText;
    else
        return control.textContent;
  }

  function setText(control, value) {
    if (document.all)
        control.innerText = value;
    else
        control.textContent = value;
  }

  // freaking ie does not support changing button's type through dom
  var submitElem = document.getElementById('regform-submit');
  var newSubmitElem = document.createElement('button');
  newSubmitElem.setAttribute("type", "button");
  setText(newSubmitElem, getText(submitElem));
  submitElem.parentNode.replaceChild(newSubmitElem, submitElem);
  newSubmitElem.setAttribute('id', 'regform-submit');
  submitElem = newSubmitElem;

  function onTrySubmit(e) {
    if (validateInBrowser()) {
      submitElem.form.submit();
    }
   }
   if (submitElem.addEventListener)
     submitElem.addEventListener("click", onTrySubmit, false);
   else
     submitElem.attachEvent("onclick", onTrySubmit);
}

function validateInBrowser() {
  function getInputElem(prefix) { return document.getElementById(prefix);}
  function getLabelElem(prefix) {
    if (prefix == 'regform-contact-phone-area-code' ||
       prefix == 'regform-contact-phone-local-number')
      prefix = 'regform-contact-phone';
    return document.getElementById(prefix + '-label');
  }
  var vlogElem = document.getElementById('regform-validate-log');
  function mark(prefix, isProblem, msg) {
    getLabelElem(prefix).style.color = isProblem ? 'red' : '';
    if (isProblem) {
      var entry = document.createElement('li');
      vlogElem.appendChild(entry);
      entry.appendChild(document.createTextNode(msg));
    }
  }
  // xxx prefices should be collected from the dom.
  var prefices = ['regform-tour-id',
		  'regform-org-type', 'regform-org-name', 'regform-first-name',
		  'regform-last-name', 'regform-contact-phone-area-code',
		  'regform-contact-phone-local-number', 'regform-contact-email',
		  'regform-contact-verify-email', 'regform-group-size',
		  'regform-captcha'];
  var formData = {};
  var index;
  for (index = 0; index < prefices.length; ++index) {
    var inputElem = getInputElem(prefices[index]);
    formData[inputElem.name] = inputElem.value;
  }

  while(vlogElem.firstChild) vlogElem.removeChild(vlogElem.firstChild);
  var validationErrors = validateFormData(formData);
  for (index = 0; index < prefices.length; ++index) {
    var prefix = prefices[index];
    var thisResult = (validationErrors || {})[getInputElem(prefix).name];
    mark(prefix, thisResult !== undefined, thisResult);
  }

  if (validationErrors)
    return false;

  // captcha is special.
  var request = window.XMLHttpRequest ?
    new XMLHttpRequest() : new ActiveXObject("MSXML2.XMLHTTP.3.0");
  request.open("POST", "tourSupport/validate-captcha.php", false);
  request.setRequestHeader("Content-Type",
			   "application/x-www-form-urlencoded");
  request.send('captcha=' + encodeURIComponent(formData.captcha));
  var captchaPass = ('Yes' == request.responseText);
  mark('regform-captcha', !captchaPass,
       "Please enter the symbols in the graphic at the bottom of the registration form as displayed.");
  return captchaPass;
}

function validateFormData(formData)
{
  // validate the raw form data. If everything's fine return null, otherwise
  // return a dictionary which maps the name of the problematic parameter to
  // the string which is supposed to instruct the user what to do.
  var rv = null;
  if (!/^\d+$/.test(formData.tourId))
    (rv = rv || {})['tourId'] = "Please select the tour you would like to "
				+ "attend.";
  var knownOrgTypes = { 'Individual': 1, 'Family': 1, 'K-12': 1, 'Club': 1,
			'Other': 1 };
  var emptyRegex = /^\s*$/;
  if (!knownOrgTypes[formData.orgType])
    (rv = rv || {})['orgType'] = ("Please select the type of the organization "
	                          + "you want to make tour reservations for.");
  if (formData.orgType != 'Individual' && formData.orgType != 'Family' &&
      emptyRegex.test(formData.orgName))
    (rv = rv || {})['orgName'] = ("Please enter the name of your organization "
				  + "unless individual or family.");
  if (emptyRegex.test(formData.firstName))
    (rv = rv || {})['firstName'] = ("Please enter the contact person's first "
				    + "name.");
  if (emptyRegex.test(formData.lastName))
    (rv = rv || {})['lastName'] = ("Please enter the contact person's last "
				   + "name.");
  var acRegex = /^\d{3}$/;
  if (!acRegex.test(formData.contactPhoneAC))
    (rv = rv || {})['contactPhoneAC'] = ("Please enter the three-digit area "
					 + "code.");
  formData.contactPhoneLN = formData.contactPhoneLN.replace(/[^0-9]/g, '');
  if (formData.contactPhoneLN.length != 7)
    (rv = rv || {})['contactPhoneLN'] = ("Please enter the 7-digit local phone "
					 + "number.");

  function isValidEmail(str) {
    // code from wikipedia
    if (!str)
      return false;
    var atSym = str.lastIndexOf("@");
    if (atSym < 1)
      return false;
    if (atSym == str.length - 1)
      return false;
    if (atSym > 64)
      return false;
    if (str.length - atSym > 255)
      return false;

    var lastDot = str.lastIndexOf(".");
    if (lastDot > atSym + 1 && lastDot < str.length - 1)
      return true;

    if (str.charAt(atSym + 1) == '[' &&  str.charAt(str.length - 1) == ']')
      return true;
    return false;
  }
  if (!isValidEmail(formData.contactEmail))
    (rv = rv || {})['contactEmail'] = "Please enter a valid email address.";
  if (formData.contactEmail != formData.contactVerifyEmail)
    (rv = rv || {})['contactVerifyEmail'] = ("Please make sure that the "
	                                     + "contact email is correct.");
  if (!/^\d\d?\d?$/.test(formData.groupSize) ||
      parseInt(formData.groupSize) < 1 || parseInt(formData.groupSize) > 200)
    (rv = rv || {})['groupSize'] = ("The group size should be between 1 and "
				    + "200.");

  return rv;
}
