// from http://www.onlinetools.org/articles/unobtrusivejavascript/chapter5.html
// by Christian Heilmann 
// Modified by Bill Woodland for Caporal Assistance Network

//We start our form script by testing if DOM is available and that there is a field with the ID required. If neither is the case, we return to the document and the PHP fallback script formsend.php will take care of the rest.



function checkform(of)
{
	var focusField='';
	var alertMsg='';
  if(!document.getElementById || !document.createTextNode){return;}
  if(!document.getElementById('required')){return;}

//We continue by defining all the variables used in the error display and by splitting the required field IDs into an array.

  var errorID='errormsg';
  var errorClass='requiredfielderror'
  var errorMsg='Please enter or change the fields marked with this image: ';
  var errorImg='images/alert.gif';
  var errorAlt=' is required';
  var errorTitle='This field has an error!';
  var reqfields=document.getElementById('required').value.split(',');
	
//As we will add an element with the ID defined in errorID and add images to each field with an error, we need to remove all of those should the script be executed a second time. Otherwise, we'd end up with several messages and images.

// Cleanup old mess
  // if there is an old errormessage field, delete it
  if(document.getElementById(errorID))
  {
    var em=document.getElementById(errorID);
    em.parentNode.removeChild(em);
  }
  // remove old images and classes from the required fields
  for(var i=0;i<reqfields.length;i++)
  {
    var f=document.getElementById(reqfields[i]);
    if(!f){continue;}
    if(f.previousSibling && /img/i.test(f.previousSibling.nodeName))
    {
      f.parentNode.removeChild(f.previousSibling);
    }
    f.className='';
  }

//Now we can do what we have undone. We loop over the required fields and test first if the field exists. If not, we skip one round of the loop. This is purely to avoid error messages, the real form markup should have all required fields.

// loop over required fields
  for(var i=0;i<reqfields.length;i++)
  {
// check if required field is there
    var f=document.getElementById(reqfields[i]);
    if(!f){continue;}

//We then check each field according to its type. For textareas and text fields we need to check the value, for checkboxes we need to check for the checked attribute and for select boxes if there is a selectedIndex defined and that it is bigger than 0.

//If any of the fields have an error, we send it as an object to the method cf_adderr(). A special case is the email field, as this one also needs to be checked for valid email format. This check is performed by another method called cf_isEmailAddr(), using regular expressions.

// test if the required field has an error, 
// according to its type
    switch(f.type.toLowerCase())
    {
      case 'text':
        if(f.value=='' && f.id!='email'){cf_adderr(f)}              
// email is a special field and needs checking
        if(f.id=='email' && 
        !cf_isEmailAddr(f.value)){cf_adderr(f)}              
        if((document.getElementById(errorID)) && (focusField=='')) {focusField=f.id}
      break;
      case 'textarea':
        if(f.value==''){cf_adderr(f)}              
        if((document.getElementById(errorID)) && (focusField=='')) {focusField=f.id}
      break;
      case 'checkbox':
        if(!f.checked){cf_adderr(f)}              
        if((document.getElementById(errorID)) && (focusField=='')) {focusField=f.id}
      break;
      case 'select':
      	alert(f.selectedIndex);
        if(!f.selectedIndex && f.selectedIndex==0){cf_adderr(f)}              
        if((document.getElementById(errorID)) && (focusField=='')) {focusField=f.id}
      break;
    }
  }

//If any of the tests above trigger an error report, the cf_adderr() generates the error message (a DIV with the errorid as ID). Therefore we return to the sending process of the form only when this element is not existant.

	if(document.getElementById(errorID)) {
		alert(alertMsg);
		document.getElementById(focusField).focus();
  return !document.getElementById(errorID);
}

//That is the main function, now we need to concentrate on the methods used, the first one being the one adding the error images and the error message.

/* Tool methods */
function cf_adderr(o)
{

//We create the image, set its alternative text and title and insert it before the element. We apply the CSS-class stored in errorClass to the element to colour it.

	// create image, add to and colourise the error fields
	var errorIndicator=document.createElement('img');
	if(o.id=='email') {
		errorIndicator.alt=o.name + errorAlt + ' and must be in the correct format.';
		alertMsg+=o.name + errorAlt + ' and must be in the correct format.\n';
	} else {
		errorIndicator.alt=o.name + errorAlt;
		alertMsg+=o.name + errorAlt+'.\n';
	}
	errorIndicator.src=errorImg;
	//errorIndicator.title=errorTitle;
	o.className=errorClass;
	o.parentNode.insertBefore(errorIndicator,o);

//Then we check if there is already an error message and create it if necessary. Once we have created this element, this condition will not be executed again.

  // Check if there is no error message
	if(!document.getElementById(errorID))
	{
	// create errormessage and insert before submit button
		var em=document.createElement('div');
		em.id=errorID;
		var newp=document.createElement('p');
		newp.appendChild(document.createTextNode(errorMsg))
		// clone and insert the error image
		newp.appendChild(errorIndicator.cloneNode(true));
		newp.lastChild.alt='';
		em.appendChild(newp);

//We find the submit button (by checking the type of each input element) and insert the new message before its parent element (the paragraph the submit button resides in).

		// find the submit button 
		for(var i=0;i<of.getElementsByTagName('input').length;i++)
		{
			if(/submit/i.test(of.getElementsByTagName('input')[i].type))
			{
				var sb=of.getElementsByTagName('input')[i];
				break;
			}
		}
		if(sb)
		{
			sb.parentNode.insertBefore(em,sb);
		}  
	} 
}

//Finally, we need the method to test if the submitted email is in a valid format:

  function cf_isEmailAddr(str) 
  {
      return str.match(/^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/);
  }
}
