function frm_validate( frm ) {
	var msg         = '';
	var all_valid       = true;

	/*
	if( !frm.terms_agree.checked ) {
		all_valid = false;
		msg += '- You must agree to the Terms & Conditions.';
		frm.terms_agree.parentNode.style.color = '#c00';
	}
	*/

	ipt = frm.getElementsByTagName('input');
	iterations = 0;
	for( i=0; i < ipt.length; i++ ) {
		iterations++;
		if( ipt.item(i).type.match('text') ) {
			this_valid = true;
			var v = frm[ ipt.item(i).name ].value;
			switch( ipt.item(i).name ) {
				case 'data[Customer][first_name]':
					this_valid = ( v.length > 1 );
					break;
				case 'data[Customer][last_name]':
					this_valid = ( v.length > 2 );
					break;
				case 'data[Address][street]':
					this_valid = ( v.length > 4 );
					break;
				case 'data[Address][city]':
					this_valid = ( v.length > 2 );
					break;
				case 'data[Address][state]':
					this_valid = ( v.length > 1 );
					break;
				case 'data[Address][postal_code]':
					this_valid = ( v.length > 4 && !v.match(/\D/) );
					break;
				case 'data[Customer][email]':
					this_valid = isEmail( v );
					break;
				case 'data[Customer][phone]':
					this_valid = ( v.length > 9 );
					break;
				case 'data[Payment][card_name]':
					this_valid = ( v.length > 4 );
					break;
				case 'data[Payment][card_number]':
					this_valid = isCreditCard( v );
					break;
				case 'data[Payment][card_expiration]':
					// 20070516 check value from mm & yyyy dropdowns
					if( 0 == v.length
						&& null != document.getElementById('PaymentCardExpiration')) {
						v = frm['ExpMonth'].value + '/' + frm['ExpYear'].value;
					}
					this_valid = isExpirationValid( v );
					break;
				case 'data[Payment][card_cid]':
					this_valid = ( v.length > 2 );
					break;
				default:
					// non-required fields fall through here
					break;
			}
			if( !this_valid ) {
				ipt.item(i).style.backgroundColor = '#fee';
				all_valid  = false;
				msg += (0 < v.length) ? '\n- invalid ' + ipt.item(i).name : '';
			} else {
				// restore background color if on 2nd run it is valid
				ipt.item(i).style.backgroundColor = '';
			}
		} else if( ipt.item(i).type.match('checkbox') && 'agree_terms' == ipt.item(i).name && !ipt.item(i).checked ) {
			all_valid  = false;
			msg += '\nYou did not agree to Terms!\n';
		} else if( 'hidden' == ipt.item(i).type && '' == ipt.item(i).value ) {
			// handle hidden toggle fields
			/*
			all_valid  = false;
			if( '' == msg ) {
				msg += '\nSelect all your XXXX options!\n';
			}
			*/
		}
	}
	if( frm.ExpYear && frm.ExpYear[frm.ExpYear.selectedIndex].value == (new Date()).getFullYear()) {
		// validate Credit Card expiration date
		var mo = (new Date()).getMonth() + 1;
		if( mo > frm.ExpMonth[frm.ExpMonth.selectedIndex].value ) {
			all_valid = false;
			alert('Card expired!\nEnter valid expiration date.');
		}
	}
	if( !all_valid ) {
		alert( 'Provide all required fields: Verify input, then try again\n' + msg );
	}
	return all_valid;
}

function isCreditCard( st ) {
	// discard any dashes
	st = st.replace(/-/g,'');
	// Encoding only works on cards with less than 19 digits
	if( st.length > 19 || 13 > st.length ) { return false; }
	var sum = 0;
	var mul = 1;
	var l = st.length;
	for( var i = 0; i < l; i++ ) {
		var digit = st.substring( l-i-1, l-i );
		var tproduct = parseInt( digit, 10 ) * mul;
		if( tproduct >= 10 ) {
			sum += (tproduct % 10) + 1;
		} else {
			sum += tproduct;
		}
		if( mul == 1 ) {
			mul++;
		} else {
			mul--;
		}
	}
	return ( (sum % 10) == 0 );
}

function isExpirationValid( st ) {
	today  = new Date();
	var dt = st.split( /\D/ );
	tmp = ( 2 == dt.length ) ? 1 : 2;
	yr = dt[tmp]*1 + (( 100 > dt[tmp] ) ? 2000 : 0);
	mo = dt[0];
	return ( new Date( yr, mo, 0 ) >= today );
}

function isEmail( el ) {
	return (
		   4 < el.length
		&& 1 < el.indexOf(     '@' )
		&& 3 < el.lastIndexOf( '.' )
		&&     el.lastIndexOf( '.' ) < (el.length - 1)
		)
		? true
  		: false
		;
}
