
String.prototype.trim = function() {
	return this.replace(/^\s+|\s+$/g,"");
}

var Validator = {
	isEmail : function(s) {
		//var reg = '^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$';
		// above is original regexp. from some reason it doesn't require the . of the domain. the below regexp does require it, but
		// it also allows multiple dots to be entered. therefore we'll add a test for two consecutive dots.
		var reg = '^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+[\.][-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$';

		if (!this.test(s, reg)) {
			return false;
		}
		
		if (s.indexOf('..') != -1) {
			return false;
		}
		
		return true;
	},
	isEmptyString : function(s) {
		return (s.trim() == '');
	},
	verifyMinMax : function(s, min, max) {
		return (s.length >= min && s.length <= max);
	},
	verifyDigits : function(s) {
		var digits = '0123456789';
		//alert('s: ' + s);
		for (var i = 0; i < s.length; i++) {
			var ch = s.substring(i, i + 1);
			//alert('testing: ' + s[i]);
			if (digits.indexOf(ch) == -1) {
				//alert('false! indexOf: ' + digits.indexOf(s[i])); 
				return false;
			}
		}

		return true;
	},
	verifyRadioSelected : function(arrRadios) {
		// See if at least one radio is checked
		for (var i = 0; i < arrRadios.length; i++) {
			var obj = document.getElementById(arrRadios[i]);
			if (obj.checked) {
				return true;
			}
		}

		return false;
	},
	verifyRadioSelectedAuto : function(baseName, numRadios) {
		// See if at least one radio is checked
		for (var i = 0; i < numRadios; i++) {
			var name = baseName + ':' + i;
			var obj = document.getElementById(name);
			if (obj.checked) {
				return true;
			}
		}

		return false;
	},
	verifyValueRange : function(n, min, max) {
		if (!this.verifyFloat(n)) {
			// Not numeric
			return false;
		}
		
		if (n < min || n > max) {
			return false;
		}
		
		return true;
	},
	verifyValueMin : function(n, min) {
		if (!this.verifyFloat(n)) {
			// Not numeric
			return false;
		}

		if (n < min) {
			return false;
		}

		return true;
	},
	verifyComboSelected : function(obj, unselectedIndex) {
		// Make sure that a different index from "unselectedIndex" is selected
		if (obj.selectedIndex == unselectedIndex) {
			return false;
		}

		return true;
	},
	verifyComboSelectedByValue : function(obj, unselectedValue) {
		// Make sure that a different value from "unselectedValue" is selected
		if (obj.value == unselectedValue) {
			return false;
		}

		return true;
	},
	verifyMultiSelectMinMax : function(elementId, minSelected, maxSelected) {
//alert('1');
		var i;
		var numSelected = 0;
		var obj = document.getElementById(elementId);
		//alert('2');
		if (typeof(obj) == 'undefined' || obj == null) {
			//alert('3');
			return false;
		}
		//alert('4');
		var options = obj.options;
		
		//alert('5');
		for (i = 0; i < options.length; i++) {
			if (options[i].selected) {
				numSelected++;
			}
		}
			
		//alert('6');
		if (numSelected < minSelected || numSelected > maxSelected) {
			//alert('7');
			return false;
		}
		//alert('8');
		
		return true;
	},
	verifyCheckboxesMinMax : function(formName, checkboxesName, minChecked, maxChecked) {
		//var checkboxes = document.getElementsByName(name);
		//if (!checkboxes) {
		//	return false;
		//}
		//alert('formName: ' + formName);
		var numChecked = 0;
		var i = 0;
		for (i = 0; i < document.forms[formName].elements.length; i++) {
			var element = document.forms[formName].elements[i];
			if (element.name == checkboxesName) {
				if (element.checked) {
					numChecked++;
				}
			}
		}
		
//alert('c: ' + numChecked);
		if (numChecked < minChecked || numChecked > maxChecked) {
//alert('c.5');
			return false;
		}
		
//alert('d');

		return true;
	},
	verifyComboOrTextboxHasValue : function(obj, unselectedIndex) {
		if (obj.type == "select-one") {
			// It's a combo
			return this.verifyComboSelected(obj, unselectedIndex);
		}
		else {
			// It's probably a textbox (currently, textbox is the only supported alternative control for this function)
			return !this.isEmptyString(obj.value);
		}
	},
	verifyIsraeliId : function(id) {
		var idnum1 = id.substr(0, 1) * 1;
		var idnum2 = id.substr(1, 1) * 2;
		var idnum3 = id.substr(2, 1) * 1;
		var idnum4 = id.substr(3, 1) * 2;
		var idnum5 = id.substr(4, 1) * 1;
		var idnum6 = id.substr(5, 1) * 2;
		var idnum7 = id.substr(6, 1) * 1;
		var idnum8 = id.substr(7, 1) * 2;
		var idnum9 = id.substr(8, 1) * 1;
	 
		if (idnum1 > 9) idnum1 = (idnum1 % 10) + 1;
		if (idnum2 > 9) idnum2 = (idnum2 % 10) + 1;
		if (idnum3 > 9) idnum3 = (idnum3 % 10) + 1;
		if (idnum4 > 9) idnum4 = (idnum4 % 10) + 1;
		if (idnum5 > 9) idnum5 = (idnum5 % 10) + 1;
		if (idnum6 > 9) idnum6 = (idnum6 % 10) + 1;
		if (idnum7 > 9) idnum7 = (idnum7 % 10) + 1;
		if (idnum8 > 9) idnum8 = (idnum8 % 10) + 1;
		if (idnum9 > 9) idnum9 = (idnum9 % 10) + 1;
	 
	    var sumval = idnum1 + idnum2 + idnum3 + idnum4 + idnum5 + idnum6 + idnum7 + idnum8 + idnum9;
	 
	    sumval = sumval % 10;
	    if (sumval > 0) {
	        return false;
	    }

	    return true;
	},
	limitTextareaLength : function(obj, max) {
		if (this.verifyMinMax(obj.value, 0, max)) {
			return true;
		}
		
		obj.value = obj.value.substring(0, max - 1);
		return false;
	},
	verifyUrlPart : function(s) {
		var reg = "^[0-9a-zA-Z]+$";

		if (!this.test(s, reg)) {
			return false;
		}
		
		if (s.indexOf(" ") != -1) {
			return false;
		}
		
		return true;
	},
	verifyFloat : function(s) {
		var reg = "^[0-9]+\\.?[0-9]*$";
		
		if (!this.test(s, reg)) {
			return false;
		}
		
		return true;
		/*
		var digits = '0123456789';
		for (var i = 0; i < s.length; i++) {
			var ch = s.substring(i, i + 1);
			//alert('testing: ' + s[i]);
			if (digits.indexOf(ch) == -1) {
				//alert('false! indexOf: ' + digits.indexOf(s[i])); 
				return false;
			}
		}
		*/

		return true;
	},
	test : function(s, p) {
		return (new RegExp(p).test(s, "i"));
		//return (new RegExp(p).test(s));
	},
	setupValidators : function(validators) {
		//alert('in setupValidators');
		// Automatically set up validators for the fields whose HTML IDs are listed in <subjects>.
		// Note: doesn't support two-fields validators setup. If you want to validate two fields -
		// set up the onblur() event manually.
		// Parameters:
		//		validators	:	associative array: [field name] --> [validation function] (see comments
		//						for function "validate" below for more details).
		
		for (var id in validators) {
			//alert('1: ' + id);
			var obj = document.getElementById(id);
			if (typeof(obj) == 'undefined' || obj == null) {
				//alert('out 1: ' + id);
				continue;
			}
			
			//alert('2: ' + id);
			//var scr = document.getElementById('ValidatorHelper');
			
			//alert('3: ' + id);
			var oldOnBlur = obj.onblur;
			
			if (typeof(oldOnBlur) != 'undefined' && oldOnBlur != null) {
				//alert('out 2: ' + id);
				// Field already has an onblur handler, don't overwrite it...
				continue;
			}
			
			//alert('4: ' + id);
			obj.onblur = function() {
				Validator.validate(validators, this.id);
			}
			//alert('5: ' + id);
		}
	},
	validateAll : function(validators, arr) {
		// Runs a series of validations; returns false if one or more validations failed. Doesn't stop
		// validating when an invalid field is encountered (so as to surface all errors in one time).
		
		// arr format:
		// [0] 'control id'
		// [1] ...
		// [2] array(
		//		[0] 'control1 id'
		//		[1] 'control2 id'
		// [3] ...
		if (arr == null) {
			// Take from validators parameter
			arr = new Array();
			var i = 0;
			for (var id in validators) {
				arr[i++] = id;
			}
		}
		
		var allGood = true;
		
		for (i = 0; i < arr.length; i++) {
			var element = arr[i];
			if (typeof(element) == 'object') {
				allGood = this.validate(validators, element[0], element[1]) && allGood;
			}
			else {
				allGood = this.validate(validators, element) && allGood;
			}
		}
		
		return allGood;
	},
	validate : function(validators, obj1Id, obj2Id) {
		// Validates a specific field (or a set of two fields, to support password confirmation).
		// Parameters:
		// 		validators 	:	an array of functions - one function per field that can be passed in <obj1Id>
		//						(or in "<obj1Id>_<obj2Id>" in case of two fields validation). Each function will
		//						called when the relevant field is validated. Each function is expected to return
		//						a string value in case field is invalid (the return value will be the error message).
		//						If the field is valid, the function is expected to return nothing ("undefined").
		//		obj1Id 		:	the HTML ID of the field that is to be validated. An HTML tag with an innerHTML
		//						attribute by the name of "<obj1Id>Error" is expected to exist; it will be filled
		//						with the validator's error message (or cleared if validation is successful).
		//		obj2Id		:	if two HTML fields participate in the validation (i.e. password and password
		//						confirmation), both their IDs will be passed.
		
		//////////// Constants ////
		var titleErrorTextColor = '#E93C10';
		var textErrorColor = '#DF2D31';
		var fieldErrorBorderColor = '#EE9D87';
		var fieldErrorBackgroundColor = '#FFEBE8';
		///////////////////////////
		
		var errContainerName = obj1Id + 'Error';
		var fieldTitleName = obj1Id + 'Title';
		
		var haveTwoObjects = false;
		
		if (typeof(obj2Id) != 'undefined') {
			haveTwoObjects = true;
		}

		var obj1 = document.getElementById(obj1Id);
		var obj2 = null;

		if (haveTwoObjects) {
			errContainerName = obj2Id + 'Error';
			fieldTitleName = obj2Id + 'Title';
			obj2 = document.getElementById(obj2Id);
		}
		
		var errContainer = document.getElementById(errContainerName);
		var fieldTitle = document.getElementById(fieldTitleName);
		
		var errText = '';
		var toEval = '';
		if (haveTwoObjects) {
			toEval = 'errText = validators["' + obj1Id + '_' + obj2Id + '"](obj1, obj2);';
		}
		else {
			toEval = 'errText = validators["' + obj1Id + '"](obj1);';
		}
		
		eval(toEval);
		if (typeof(errText) == 'undefined') errText = '';
		
		var obj = (haveTwoObjects ? obj2 : obj1);
		
		if (errText == '') {
			// No error
			errContainer.style.display = 'none';
			//errContainer.innerHTML = '';

			if (obj != null) {
				if (typeof(obj.originalBorderColor) != 'undefined') {
					obj.style.borderColor = obj.originalBorderColor;
					obj.style.backgroundColor = obj.originalBackgroundColor;
				}
			}

			if (fieldTitle != null) {
				if (typeof(fieldTitle.originalColor) != 'undefined') {
					fieldTitle.style.color = fieldTitle.originalColor;
				}
			}

			return true;
		}
		else {
			// Errorneous input. Notify user.
			//errContainer.innerHTML = '<font color="' + textErrorColor + '">' + errText + '</font>';
			if (errText != 'use text from err container') {
				errContainer.innerHTML = errText;
			}
			errContainer.style.display = 'block';
			
			if (obj != null) {
				if (typeof(obj.originalBorderColor) == 'undefined') {
					obj.originalBorderColor = obj.style.borderColor;
					obj.originalBackgroundColor = obj.style.backgroundColor;
				}
				obj.style.borderColor = fieldErrorBorderColor;
				obj.style.backgroundColor = fieldErrorBackgroundColor;
			}

			if (fieldTitle != null) {
				if (typeof(fieldTitle.originalColor) == 'undefined') {
					fieldTitle.originalColor = fieldTitle.style.color;
				}
				fieldTitle.style.color = titleErrorTextColor;
			}
			
			return false;
		}
	}
};