function isEmail(str) {
  // are regular expressions supported?
  var supported = 0;
  if (window.RegExp) {
    var tempStr = "a";
    var tempReg = new RegExp(tempStr);
    if (tempReg.test(tempStr)) supported = 1;
  }
  if (!supported) 
    return (str.indexOf(".") > 2) && (str.indexOf("@") > 0);
  var r1 = new RegExp("(@.*@)|(\.\.)|(@\.)|(^\.)");
  var r2 = new RegExp("^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$");
  return (!r1.test(str) && r2.test(str));
}

  function checkdate(seldate, min, max) {
  	// Date validator
  	// (c) 2006 Brad Murray / Fellowship Church
  	/*
  	returns:
		Date Object => Good
		0 => Not a date
  		-1 => Out of range, too high
  		-2 => Out of range, too low
  		-3 => Bad range specifier
  	*/
	//alert(seldate + '|' + min + '|' + max);
	seldate = parsedate(seldate);
	if(!seldate) return 0;
	//alert(seldate);
	if(min) {
		min = parsedate(min);
		if(!min) return -3;
		if(seldate < min) return -2;
	}
	if(max) {
		max = parsedate(max);
		if(!max) return -3;
		if(seldate > max) return -1;
	}
	// pad month and day
	var month = seldate.getMonth()+1;
	if(String(month).length == 1) month = '0'+String(month);
	var day = seldate.getDate();
	if(String(day).length == 1) day = '0'+String(day);
	var foo =(month + '/' + day + '/' + seldate.getFullYear());
	//alert(foo)
	return foo;
	
  }
  
  function parsedate(seldate) {
	// US-centric date parser
  	// (c) 2006 Brad Murray / Fellowship Church
	var now = new Date();
	if(seldate.length < 3) return false;	
	
	// parse date
	var regex = /^(\d{1,2})[\/-](\d{1,2})([\/-](\d{2}|\d{4}))*$/;
	var foo = regex.exec(seldate);
	if(foo) {
		var month = parseInt(foo[1],10);
		var day = parseInt(foo[2]);
		if(foo[4]) { 
			var year = parseInt(foo[4]); 
			if(year < 1000) {
				if(year < 10) year += 2000;
				else year += 1900;
			}
		}
		else {	var year = now.getFullYear(); }
		return new Date(year,month-1,day);
	}
	else return false;
  }


function mod_forms_validate() {
	var ele;
	var msg = '';
	// var emailRegxp = /^([\w]+)(.[\w]+)*@([\w\-]+)(.[\w]{2,3}){1,2}$/;
	var emailRegxp = /^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
	var zipRegxp = /^([0-9]{5})$/;
	var numbersonly = /^([0-9\-\.]*)$/;
	for(i in val) {
		if(isNaN(Number(i)) == true) continue;
		
		ele = document.getElementById('ff_' + i);
		switch(val[i]['type']) {
			case 'text':
			case 'textarea':
				if(val[i]['min'] && ele.value.length < val[i]['min']) {
					msg += val[i]['name'] + ' must have at least ' + val[i]['min'] + ' characters<br>';
				}
				if(val[i]['max'] && ele.value.length > val[i]['max']) {
					msg += val[i]['name'] + ' cannot be longer than ' + val[i]['max'] + ' characters<br>';
				}
				break;
			case 'integer': 
			case 'float':
			case 'money':
				// make sure we only allow numbers
				if(ele.value.length > 0) {
					// strip commas
					ele.value = ele.value.replace(/\,/g,'');
					var foo = numbersonly.exec(ele.value);
					if(!foo) {
						msg += val[i]['name'] + ' must be a number <br>';
					}
				}

				// exception for integer
				if(val[i]['type'] == 'integer' && Math.floor(Number(ele.value)) != Number(ele.value)) {
					msg += val[i]['name'] + ' must be a whole number <br>';
				}
				// common to integer, float, money
				if(val[i]['min'] && Number(ele.value) < Number(val[i]['min'])) {
					msg += val[i]['name'] + ' must be at least ' + val[i]['min'] + '<br>';
				}
				if(val[i]['max'] && Number(ele.value) > Number(val[i]['max'])) {
					msg += val[i]['name'] + ' must be less than ' + val[i]['max'] + '<br>';
				}
				break;
			case 'email':
				if(ele.value.length > 0 && emailRegxp.test(ele.value) != true) msg += val[i]['name'] + ' must be an email address <br>';
				if(val[i]['min'] && ele.value.length < 8) msg += val[i]['name'] + ' is required <br>';
				break;
			case 'zip':
				if(ele.value.length > 0 && zipRegxp.test(ele.value) != true) msg += val[i]['name'] + ' must be a zip code <br>';
				if(val[i]['min'] && ele.value.length != 5) msg += val[i]['name'] + ' is required <br>';
				break;
			case 'select':
				if(val[i]['min'] && ele[ele.selectedIndex].value == '') msg += val[i]['name'] + ' is required<br>';
				break;
			case 'date':
				// allow an empty date field if minimum is not set
				if(ele.value.length == 0 && !val[i]['min']) break;
				// otherwise require and check date
				var foo = checkdate(ele.value, val[i]['min'], val[i]['max']);
				//alert('returned:'+foo)
				switch(foo) {
					case 0:
						msg += val[i]['name'] + ' must be a date in the form (mm/dd/yyyy)<br>';
						break;
					case -1:
						msg += val[i]['name'] + ' must be less than ' + val[i]['max'] + '<br>';
						break;
					case -2:
						msg += val[i]['name'] + ' must be greater than ' + val[i]['min'] + '<br>';
						break;
					default:
						//ele.value = foo;
						break;
				}
				//alert(msg);
				break;
		}
		//alert(i);

	}

	if(msg == '') return true;
	else {
		document.getElementById('errormsg').innerHTML = msg;
		window.location.hash = "#errormsg";
		return false;
	}
}
