//
//  validlib.jav.
//  Copyright (c) 1998-2003 //digital things, LLC - www.digithings.com - 800-775-3968.
//  License for use, replication and distribution granted to application owner under conditions specified 
//  by applicable agreements & contracts.
//
//  Client-side validation routines.
//
//  Change history:
//  07/07/98 - //digital things, LLC - Initial Release.
//  Standard JavaScript library of data validation functions.
//
var _dirty = false

var _string = 1
var _hlink = 5
var _date = 2
var _smallDate = 8
var _int = 3
var _float = 4
var _ccDate = 7
var _email = 9
var _ssn = 10
var _fein = 10
var _phone = 11
var _zip = 12
var _cc = 13
var _textarea = 14
var _time = 15
var _image = 100
var _inv = 101
var _text = 1

//
//  AppDocDirty()
//  Sets/gets value of '_dirty' global variable.
//  Parameter value: 'true' = set, 'false' = get.
//
function AppDocDirty(action)
{
	_dirty = action == true ? true : _dirty
	return _dirty
}

//
//  AppRound()
//  Accurately rounds decimals.
function AppRound(value, decimals)
{
    return(
    		parseFloat(value) != "NaN" && parseInt(decimals) != "NaN"  
    		? (Math.round(value * Math.pow(10, decimals))) / Math.pow(10, decimals) 
    		: "NaN"
    	  )
}

//
//  AppValidateValue()
//  Returns true if the value passed on 'val' is not in the exception list passed in 'notIn'.
//
function AppValidValue(val, notIn)
{
	if (notIn.length)
	{
		if (notIn.indexOf(val) != -1)
			return false
	}

	for (var i=0; i < val.length; i++)
	{
		if (val.charAt(i) != " ")
			return true
	}
		
	return false
}

//
//  AppValueIn()
//  Returns false if the value passed on 'val' is not in 'valIn'.
//
function AppValueIn(val, valIn)
{
	if (valIn.length)
	{
		for (var i=0; i < valIn.length; i++)
		{
			if (valIn.indexOf(val.charAt(i)) == -1)
				return false
		}
	}

	return true
}

//
//  AppIsFloat()
//  Returns true if 'str' is a valid float value, false otherwise.
//
function AppIsFloat(str)
{
	var off
	var rc = false

	if (str.length == 0 || (str.length == 1 && str == "-"))
		return rc

	off = str.indexOf("-")

	if (off > 0)
		return rc
	else if (str.indexOf("-", off+1) > -1)
		return rc

	off = str.indexOf(".")

	if (str.indexOf(".", off+1) > -1)
		return rc

	for (var i=0; !rc && i < str.length; i++)
	{
		if ( !rc && (str.charAt(i) == '-' || str.charAt(i) == '.'))
			rc = false
		else
			rc = !rc && isNaN(parseFloat(str.charAt(i)))
	}

	return (!rc && i)
}

//
//  AppIsInt()
//  Returns true if 'str' is a valid integer value, false otherwise.
//
function AppIsInt(str)
{
	return (AppIsFloat(str) && str.indexOf(".") == -1)
}

//
//  AppValidateField()
//  Validates 'field' for specified data type.
//  Low and high ranges can be specified for numbers and dates, a default value can be set to
//  if validation fails.
//  Returns true if valid, false otherwise, null values are always valid.
//  Data types are:
//  _string = 1
//  _hlink = 5
//  _date = 2
//  _smallDate = 8
//  _int = 3
//  _float = 4
//  _ccDate = 7
//  _email = 9
//  _ssn = 10
//  _fein = 10
//  _phone = 11
//  _zip = 12
//  _cc = 13
//  _textarea = 14
//  _time = 15
//  _image = 100
//  _inv = 101
//  _text = 1
//
function AppValidateField(field, type, lowRange, hiRange, dflt)
{
	var v
	var leapError = false
	var rc = true
	var off
	var tmp = ""
	var i
	var focus = false

	//  (null) is always valid.
	if (field.value.length == 0)
		return true

	//  Determine browser and set indicator.
	//  Navigator processes the onBlur event (where this function is ususally called) in a different way 
	//  than Explorer. Setting focus causes Navigator to enter an infinite event loop.
	if (navigator.appName.indexOf("etscape") == -1)
		focus = true

	//  String/Link/Text, etc...
	if (type == _string || type == _hlink|| type == 6 || type == _image || type == _textarea)
	{
		off = field.value.indexOf("\"")

		if (off != -1)
		{
			rc = false

			for (i = 0; i < field.value.length; i++)
			{
				if (field.value.charAt(i) != "\"")
					tmp = tmp + field.value.charAt(i)
			}

			field.value = tmp
			alert("Double quotes (\") are illegal in HTML text and were removed.\nPlease use single quotes (') instead.")
		}

		if (type == _textarea && (field.value.length > hiRange && hiRange > 0))
		{
			rc = false
			field.value = field.value.substring(0, hiRange)
			alert("This field should not exceed " + hiRange + " characters.\nText has been truncated.")
		}
	}
	// Date
	else if (type == _date)
	{
		v = field.value.split("/")

		if (v.length < 3)
			rc = false

		if (rc)
		{
			if (!AppIsInt(v[0]) || !AppIsInt(v[1]) || !AppIsInt(v[2]))
				rc = false

			if (rc)
			{
				vMth = v[0]
				vDay = v[1]
				vMth = vMth.length == 1 ? vMth.length == 2 && vMth.substring(1,1) == "0" ? vMth.substring(2,1) : vMth : vMth
				vDay = vDay.length == 1 ? vDay.length == 2 && vDay.substring(1,1) == "0" ? vDay.substring(2,1) : vDay : vDay
				vYr = parseInt(v[2])

				if (
				   //===vYr < 1 ||
				   (vMth < 1 || vMth > 12) ||
				   ((vDay < 1 || vDay > 31) && vMth != 2) ||
				   ((vDay < 1 || vDay > 29) && vMth == 2) ||
				   (vMth == 2 && vDay == 29 &&
				      ((vYr % 4 != 0) || (vYr % 4 == 0 && vYr % 100 == 0 && vYr % 400 != 0)))
				   )
				{
					rc = false

					if (vMth == 2 && vDay == 29)
						leapError = true
				}
			}
		}

		if (!rc)
		{
			if (leapError)
			{
				alert("Invalid date. '" + vYr + "' is not a leap year.")
				field.value = "2/28/" + vYr
			}
			else
			{
				alert("Invalid date. Date format: 'dd/mm/[yy]yy'.")

				if (dflt == 0)
					field.value = "01/01/1900"
				else
					field.value = dflt
			}
		}
	}
	// Time
	else if (type == _time)
	{
		v = field.value.split(":")

		if (v.length < 2)
			rc = false

		if (rc && (!AppIsInt(v[0]) || !AppIsInt(v[1])))
			rc = false
		else
		{
			if (v[0].length > 1 && v[0].substring(1,1) == "0")
			{
				v[0] = v[0].substring(2,1)
				field.value = v[0] + ":" + v[1]
			}

			vHr = parseInt(v[0])
			vMn = parseInt(v[1])

			if ((vHr < 1 || vHr > 12) || (vMn < 0 || vMn > 59))
				rc = false
		}

		if (!rc)
		{
			alert("Invalid time. Time format: 'hh:mm'\nHours: 1 to 12\nMinutes: 0 to 59.")

			if (dflt == 0)
				field.value = "12:00"
			else
				field.value = dflt
		}
	}
	// Credit card date
	else if (type == _ccDate)
	{
		v = field.value.split("/")

		if (v.length != 2)
			rc = false

		if (rc && (!AppIsInt(v[0]) || !AppIsInt(v[1])))
			rc = false
		else
		{
			vMth = parseInt(v[0])
			vYr = parseInt(v[1])

			if ( vYr < 0 || (vMth < 1 || vMth > 12) )
				rc = false
		}

		if (!rc)
		{
			alert("Invalid expiration date. Format: 'mm/yy'.")

			if (dflt == 0)
				field.value = "01/00"
			else
				field.value = dflt
		}
	}
	// Current Date
	else if (type == 8)
	{
		v = field.value.split("/")

		if (v.length < 2)
			rc = false

		if (rc && (!AppIsInt(v[0]) || !AppIsInt(v[1])))
			rc = false
		else
		{
			vMth = parseInt(v[0])
			vDay = parseInt(v[1])

			if (
			   (vMth < 1 || vMth > 12) ||
			   ((vDay < 1 || vDay > 31) && vMth != 2) ||
			   ((vDay < 1 || vDay > 29) && vMth == 2)
			   )
				rc = false
		}

		if (!rc)
		{
				alert("Invalid start date. Format: 'mm/dd'.")

				if (dflt == 0)
					field.value = "01/01"
				else
					field.value = dflt
		}
	}
	// Inventory control
	else if (type == _inv)
	{
		if ( !AppIsInt(field.value) )
		{
			alert("Please enter numeric values only.")
			field.value = dflt
			rc = false
		}
		else if ((hiRange || lowRange) && (parseInt(field.value) > hiRange || parseInt(field.value) < lowRange))
		{
			alert("Inventory control:\nPlease enter a value between '" + lowRange + "' and '" + hiRange + "'.")
			field.value = 1
			rc = false
		}
	}
	// Number
	else if (type == _int)
	{
		if ( !AppIsInt(field.value) )
		{
			alert("Please enter numeric values only.")
			field.value = dflt
			rc = false
		}
		else if ((hiRange || lowRange) && (parseInt(field.value) > hiRange || parseInt(field.value) < lowRange))
		{
			alert("Please enter a value between '" + lowRange + "' and '" + hiRange + "'.")
			field.value = dflt
			rc = false
		}
	}
	// Float
	else if (type == _float)
	{
		if ( !AppIsFloat(field.value) )
		{
			alert("Valid decimal value required.")
			field.value = dflt

			if (focus)
				field.focus()

			rc = false
		}
		else if ((hiRange || lowRange) && (parseInt(field.value) > hiRange || parseInt(field.value) < lowRange))
		{
			alert("Please enter a value between '" + lowRange + "' and '" + hiRange + "'.")
			field.value = dflt
			rc = false
		}
	}
	// E-Mail
	else if (type == _email)
	{
		var notThese = " <,>?\"'|\\}]{[=)(&^%#~`"
		var maxAt = 0
		rc = true

		for (var i=0; i < field.value.length; i++)
		{
			if (field.value.charAt(i) == '@')
				maxAt++

			if (notThese.indexOf(field.value.charAt(i)) != -1)
			{
				rc = false
				break
			}
		}
		
		if (!rc)
		{
			alert("Spaces or special characters\nare not allowed in E-Mail adresses.")
			//field.value = ""
		}
		else if (field.value.indexOf("@") == -1 || field.value.indexOf(".") == -1 || maxAt > 1)
		{
			rc = false
			alert("Invalid E-Mail address format.\nPlease use valid format: (eg: User@Domain.com).")
			//field.value = ""
		}
		
	}
	//  SSN/FEIN
	else if (type == _fein)
	{
		var ssn = field.value

		if (ssn.length == 9 && AppValueIn(ssn, "0123456789"))
			rc = true
		else if(ssn.length == 11 && AppValueIn(ssn, "0123456789-") && ssn.charAt(3) == "-" && ssn.charAt(6) == "-")
			rc = true
		else if(ssn.length == 10 && AppValueIn(ssn, "0123456789-") && ssn.charAt(2) == "-")
			rc = true
		else
		{
			rc = false
			alert("Invalid Tax ID. Valid formats:\nSSN: '999-99-9999' or '999999999'.\nFEIN: '99-9999999' or '999999999'")
		}
	}
	//  US Phone Number
	else if (type == _phone)
	{
		if (field.value.length > 14 || !AppValueIn(field.value, "0123456789-() "))
		{
			rc = false
			alert("Invalid Phone Number format. Formats allowed:\n1: '(999) 999-9999'.\n2: '999-999-9999'.\n3: '999 999 9999'.")
		}
	}
	//  ZIP code
	else if (type == _zip)
	{
		var zip = field.value
		rc = false

		if (zip.length == 5 && AppValueIn(zip, "0123456789"))
			rc = true

		if (zip.length > 5)
		{
			xZip = zip.split("-")

			if (zip.length > 9 && (xZip.length == 2 && AppValueIn(xZip[1], "0123456789")))
				rc = true
			else if (zip.length == 6 && zip.indexOf(" ") == -1)
				rc = true
		}

		if (!rc)
			alert("Invalid ZIP code. Valid formats:\nUSA: '99999'.\nUSA: '99999-9999\[9\]'.\nWorld: '99999'.\nCN: 'A9A9A9'.\nGB: 'A99AAA'.")
	}
	//  Credit Card Number
	else if (type == _cc)
	{
		if (field.value.length < 15 || !AppIsInt(field.value))
		{
			rc = false
			alert("Invalid Credit Card Number.\nPlease enter digits only (no less than 15).")
		}
	}

	if (!rc)
	{
		if (focus)
			field.focus()

		field.select()
	}

	return rc
}

//
//  AppFieldIsEmpty()
//  Return true if the passed field is empty (null or spaces), false otherwise.
//
function AppFieldIsEmpty(field)
{
	var i = 0
	var n = 0

	if (field.value.length == 0)
		return true

	for (i = 0; i < field.value.length; i++)
	{
		if (field.value.charAt(i) == " ")
			n++
	}

	if (n && i == n)
		return true

	return false
}

//
//  AppLTrim()
//  Remove leading white space.
//
function AppLTrim(s)
{ 
	while (s.charCodeAt(0) == 160 || s.charCodeAt(0) == 32)
		s = s.substring(1, s.length)

	return s
}

//
//  AppRTrim()
//  Remove trailing white space.
//
function AppRTrim(s)
{
	while (s.charCodeAt(s.length-1) == 160 || s.charCodeAt(s.length-1) == 32) 
		s = s.substring(0, s.length-1)

	return s
}

//
//  AppRTrim()
//  Remove leading & trailing white space.
//
function AppTrim(s)
{
	return AppLTrim(AppRTrim(s))
} 

//
//  AppDetectKey()
//  Detects a particular key being pressed.
//
function AppDetectKey(key)
{
	if (event.keyCode == key)
		return true
	else
		return false
}
