/******************************************************************************
 qForm JSAPI: Custom functions Library
******************************************************************************/
/* Adds a formatter function.  A formatter function attaches itself to the onblur event. */
function _addFormatter(name, fn)
{
	var eventname = _param(arguments[2], "onblur", "string");

	if( arguments.length < 2 ) return alert("To create a new formatter object, you must specify \nboth a name and function to run: \n  _addFormatter(\"formatTime\", __FormatTime);");
	// strip "format" out of name if present
	if( name.substring(0, 6).toLowerCase() == "format" ) name = name.substring(6);

	var strFN = fn.toString();
	var strName = strFN.substring(strFN.indexOf(" "), strFN.indexOf("("));
	var strArguments = strFN.substring( strFN.indexOf("(")+1, strFN.indexOf(")") );
	// remove spaces from the arguments
	while( strArguments.indexOf(" ") > -1 ) strArguments = strArguments.substring( 0, strArguments.indexOf(" ") ) + strArguments.substring( strArguments.indexOf(" ")+1 );

	// get the body of the custom function
	var strBody = "this.value = this.obj.value";
	strBody += strFN.substring( strFN.indexOf("{")+1, strFN.lastIndexOf("}") );
	strBody += "this.obj.value = this.value";

	// Create the function that will apply the formatter function to the field's event.
	var strNewFN = "new Function(";
	var aryArguments = strArguments.split(",");
	for( var i=0; i < aryArguments.length; i++ ){
		if(aryArguments[i] != "") strNewFN += "\"" + aryArguments[i] + "\",";
	}

	// Add the actual formatter function to the Field prototype.
	eval("Field.prototype.doformat" + name + " = " + strNewFN + "strBody);");

	// Create the function that applies the format function to the specified event.
	var strRule = "var cmd = this.pointer + '.doformat" + name + "';\n";
	strRule += "cmd += '( ';\n";
	strRule += "for( i=0; i < arguments.length; i++ ){ \n";
	strRule += "if( typeof arguments[i] != 'undefined' ){ ;\n";
	strRule += "if( typeof arguments[i] == 'string' ) cmd += '\"' + arguments[i] + '\",';\n";
	strRule += "else cmd += arguments[i] + ',';\n";
	strRule += "}}\n";
	strRule += "cmd = cmd.substring(0, cmd.length-1);\n";
	strRule += "cmd += ')';\n";
	strRule += "this.addEvent('onblur', cmd, false);\n";
	strRule += "eval(cmd);\n";
	strRule += "return true;\n";
	strNewFN += "strRule);";
	eval("Field.prototype.format" + name + " = " + strNewFN);

	return true;
}

function _Field_isDecimal(commas)
{
	var commas = _param(arguments[0], true);   // default value for commas

	var sVal = this.value;
	var	fVal;

	if	(commas)
	{	// Strip commas, if we're supposed to.
		sVal = sVal.split(",").join("");
	}

	// Now parse it into a float.
	fVal = parseFloat(sVal);
	if	(isNaN(fVal))
	{
		this.error = "The value for " + this.description + " is not a decimal value. This field requires a decimal value.";
	}
}
_addValidator("isDecimal", _Field_isDecimal);

// Validate that a date is in the future
function _Field_validateFutureDate()
{
	var value = new Date(this.value);
	var now = new Date();

	now = new Date(now.getYear(), now.getMonth(), now.getDate());
	if	(value < now)
	{
		this.error = "The " + this.description + " must be in the future.";
	}
}
_addValidator("FutureDate", _Field_validateFutureDate);

// Validate that a date is today or in the past
function _Field_validatePresentPastDate()
{
	var value = new Date(this.value);
	var now = new Date();

	now = new Date(now.getYear(), now.getMonth(), now.getDate());
	if	(value > now)
	{
		this.error = "The " + this.description + " must be today or in the past.";
	}
}
_addValidator("PresentPastDate", _Field_validatePresentPastDate);

// GT zero checks - very common, I'll just create a validator.
function _Field_isGTZero()
{
	if	(parse_float(this.value) <= 0)
	{
		this.error = "The " + this.description + " must be greater than 0.";
	}
}
_addValidator("isGTZero", _Field_isGTZero);

// This formats a field into a number, with commas and decimal padding.
function _Field_FormatNumber(commas, decimals, allow_blank)
{
	var commas = _param(arguments[0], false, "boolean");
	var decimals = _param(arguments[1], 0, "number");
	var allow_blank = _param(arguments[2], true, "boolean");

	if	((this.value.length != 0)
		||	(allow_blank == false)
		)
	{
		this.value = format_number(this.value, commas, decimals);
	}
}
_addFormatter("Number", _Field_FormatNumber);

// This formats a field into a number, with commas and decimal padding.
function _Field_FormatPositiveInt(commas)
{
	var commas = _param(arguments[0], false, "boolean");

	this.value = _stripInvalidChars(this.value, "numeric");
	if (this.value.length != 0)
	{
		this.value = format_number(this.value, commas, 0);
	}
}
_addFormatter("PositiveInt", _Field_FormatPositiveInt);

// Basically a trim() formatter.
function _Field_FormatTrim()
{
	this.value = _trim(this.value);
}
_addFormatter("Trim", _Field_FormatTrim);

// Format a field with m/d/y information.
function _Field_FormatDate()
{
	var year_set = this.value.split("/");
	var pdate = new Date(this.value);
	if (isNaN(pdate))
	{	// Invalid date - clear it out.
		this.value = "";
	}
	else
	{	// Valid date
		if	((year_no = parseInt(year_set[2], 10)).toString().length != 4)
		{	// The year is a little kooky.
			if	(	(year_no < 30)
				||	(year_no > 99)	)
			{	// Year is under 30, we're in 2000
				pdate.setFullYear(year_no + 2000);
			}
			else
			{
				pdate.setFullYear(year_no + 1900);
			}
		}
		this.value = pdate.format();
	}
}
_addFormatter("Date", _Field_FormatDate);

// Makes sure there's an http, https, ftp at the front of a text box.
function _Field_FormatURL()
{
	val = this.value.toLowerCase();

	if	(	(val.substring(0, 7) == "http://")
		||	(val.substring(0, 8) == "https://")
		||	(val.substring(0, 6) == "ftp://")
		)
	{	// Everthing is hunkey-dorey.
		return;
	}
	else
	{	// oop - stick something on there, quick!
		this.value = "http://" + this.value;
	}
}
_addFormatter("URL", _Field_FormatURL);

// Formats a field into title case.
function _tcase(match)
{
	return match.slice(0, -1) + match.charAt(match.length - 1).toUpperCase();
}

function _Field_FormatTitleCase(cur_val)
{
	// Start by trimming and lowercasing everything.
	var	rv = this.value.trim().toLowerCase();
	// Then uppercase all the first letters
	rv = rv.replace(/\b[a-z]/g, _tcase);
/* Disabled for now.
	// Handle the special case of Mc
	rv = rv.replace(/\bMc[a-z]/g, _tcase);
	// Handle the special case of Mac
	rv = rv.replace(/\bMac[a-z]/g, _tcase);
	// Handle the special case of De
	rv = rv.replace(/\bDe[a-z]/g, _tcase);
*/

	this.value = rv;
}
_addFormatter("TitleCase", _Field_FormatTitleCase);

// Formats a field into upper case.
function _Field_FormatUpperCase()
{
	this.value = _trim(this.value);
	var cur_val = this.value;
	var strReturn_Value = "";
	var iTemp = cur_val.length;

	if	(iTemp == 0)
	{
		return "";
	}

	strReturn_Value = cur_val.toUpperCase();
	this.value = strReturn_Value;
}
_addFormatter("UpperCase", _Field_FormatUpperCase);

function _Field_DateGTEField(fieldname)
{
	var ofield = this.qForm[fieldname];
	// Snag this date..
	var tdate = new Date(this.value);
	var odate = new Date(ofield.getValue());
	if	((isNaN(tdate))
		||	(isNaN(tdate))	)
	{	// One of the dates is invalid..
		this.error = this.description + " must be on or after " + ofield.description;
	}
	else
	{	// Both of our dates are valid.
		// Round the time off our dates.
		tdate.setHours(0);
		tdate.setMinutes(0);
		tdate.setSeconds(0);
		tdate.setMilliseconds(0);
		odate.setHours(0);
		odate.setMinutes(0);
		odate.setSeconds(0);
		odate.setMilliseconds(0);
		if	(tdate < odate)
		{	// Our date is less than the other date.
			this.error = this.description + " must be on or after " + ofield.description;
		}
	}
}
_addValidator("DateGTEField", _Field_DateGTEField);

/* Strips all characters that match the regular expression out of the string
 * To strip all but the specified characters, use a non-matching set, for example
 * /[^0-9]/g to strip everything but digits.
 */
function _Field_FormatStripCharacters(rexp)
{
	this.value = this.value.replace(rexp, "");
/*
	var character_set = _param(arguments[0], "", "string");
	
	var result = "";
	for ( var i = 0 ; i < this.value.length ; i++ )
	{ // Look at each character in our string.
		if (character_set.indexOf(this.value.charAt(i)) != -1)
		{
			result += this.value.charAt(i);
		}
	}
	this.value = result;
*/
}
_addFormatter("StripCharacters", _Field_FormatStripCharacters);



/*
	Custom Functions added to the standard qForms API distribution
	Coder Vince Terpe
	Last Mod 11/2/2010
*/

// Format special function fields
function _Field_FormatSpecialField(mask)
{
	strMaskLC = mask.toLowerCase();
	var mask_format = "";
	
	// define the formats
	if(strMaskLC == "ssn") {mask_format = "xxx-xx-xxxx";}
	else if(strMaskLC == "phone") {mask_format = "(xxx) xxx-xxxx";}
	else if(strMaskLC == "zip5") {mask_format = "xxxxx";}
	else if(strMaskLC == "zip9" ) {mask_format = "xxxxx-xxxx";}
	else if(strMaskLC == "taxid" ) {mask_format = "xx-xxxxxxx";	}
	else if(strMaskLC == "acc") {mask_format = "xxxx-xxxx-xxxx-xxxx";}
	else {this.error = "An invalid format mask has been specified; contact the programmer.";}

	var mask_char = "x";
	var aVal = _stripInvalidChars(this.value, "numeric").split("");	// Reduce the string to an array of single digit numbers.
	var aMask = mask_format.split("");	// Split the mask into an array..faster? easier? something.
	var iMaskPos;
	var iMaskCount;
	var iValPos;
	var sResult;

	// Delete 1 prefix
	if	((strMaskLC == "phone") && (aVal[0] == "1"))
	{
		aVal = aVal.slice(1);
	}

	// Find out how many placeholders are in the mask.
	for	( iMaskPos = 0, iMaskCount = 0 ; iMaskPos < aMask.length ; iMaskPos++ )
	{
		if	(aMask[iMaskPos] == mask_char)
		{
			iMaskCount++;
		}
	}

	if	(aVal.length >= iMaskCount)
	{	// We match our mask.  Format the number.
		for	( iMaskPos = 0, iValPos = 0, sResult = "" ; iMaskPos < aMask.length ; iMaskPos++ )
		{	// Go through and replace stuff.
			if	(aMask[iMaskPos] == mask_char)
			{
				sResult += aVal[iValPos++];
			}
			else
			{
				sResult += aMask[iMaskPos];
			}
		}

		this.value = sResult;
	}
	else if (aVal.length == 0)
	{
		this.value = "";
	}
	else
	{	// Make it look all bad and stuff.
		this.obj.style.backgroundColor = qFormAPI.errorColor;
	}
}
_addFormatter("SpecialField", _Field_FormatSpecialField);

// Formatter to strip ~!@#$% etc from input fields.
function _Field_FormatBadChrs(cur_val)
{
	// Start by trimming and lowercasing everything.
	var rv = this.value.trim().toLowerCase();
	// Check if the first character in the field is a pound
	if (rv.charAt(0) == '#') {alert('Please use Unit or Apt or Suite instead of # (Please type the word in!)')}
	// Then get rid of the crap the user typed in
	rv =  _stripInvalidChars(rv, "&abcdefghijklmnopqrstuvwxyz1234567890./\s/ ")
	// Then uppercase all the first letters
	rv = rv.replace(/\b[a-z]/g, _tcase);
	// Then replace duplicate white space
	rv = rv.replace(/( ){2,}/g," ");

	this.value = rv;
}
_addFormatter("BadChrs", _Field_FormatBadChrs);

function _Field_FormatPhoneNumber(cur_val)
{
	newString = this.value.replace(/\D/g,'').replace(/^(\d{3})(\d{3})/,'($1) $2-');
	//this.setValue(newString, true, false);
	this.value = newString;
}
_addFormatter("PhoneNumber", _Field_FormatPhoneNumber);

function _Field_FormatStripAlpha()
{
	var rv = this.value.trim().toLowerCase();
	rv =  _stripInvalidChars(rv, "1234567890-")
	this.value = rv;
}
_addFormatter("StripAlpha", _Field_FormatStripAlpha);

function _Field_isCVV2(){
	if(this.obj.value.length != 3){
  	this.error = "The " + this.description + " field must be exactly 3 digits.";
	}
}
_addValidator("isCVV2", _Field_isCVV2);

function _Field_isCreditCardExpired(ccMonth, ccYear){
	fMonth = document.getElementById(ccMonth).value;
	fMonth = parseInt(fMonth)-1;
	fYear = document.getElementById(ccYear).value;
  var dToday = new Date();
	var dPassed = new Date(fYear, fMonth, 1);
	if(dPassed < dToday){
  	this.error = "The " + this.description + " date must be in the future.";
	}
}
_addValidator("isCreditCardExpired", _Field_isCreditCardExpired);

function __isNotEqualTo(NotValue){
	if(parseInt(this.value) == parseInt(NotValue)){
		this.error = "The " + this.description + " field must be selected.";
	}
}
_addValidator("isNotEqualTo", __isNotEqualTo);
