function focusFormComponent(e) {
	var element = getTarget(getEvent(e));
	if (element.type && element.type == 'checkbox') {
		element.className = 'checkbox_active';
	}
	else {
		element.className = 'input_active';
	}
}

function blurFormComponent(e) {
	var element = getTarget(getEvent(e));
	if (element.type && element.type == 'checkbox') {
		element.className = 'checkbox_inactive';
	}
	else {
		element.className = 'input_inactive';
	}
	checkFormComponent(e);
}

function checkFormComponent(e) {
	var element = getTarget(getEvent(e));
	checkField(element, false);
	checkSubmitButton(element.form);
}

var _fieldValidators = [];
var _fieldIsValid = [];
var _fieldMessages = [];
var _invalidFields = [];
function setValidator(form, field, regexp, message) {
	if (!_fieldValidators[form]) {
		_fieldValidators[form] = [];
		_fieldMessages[form] = [];
	}
	_fieldValidators[form][field] = regexp;
	_fieldMessages[form][field] = message;
}

function isValid(form, field, value, cardinality) {
	if (!cardinality) {
		cardinality = 1;
	}
	var valid;
	if (_fieldValidators[form] && _fieldValidators[form][field]) {
		valid = eval('value.search(' + _fieldValidators[form][field] + ')') > -1;
	}
	else {
		valid = true;
	}
	if (_fieldIsValid[form]) {
		if (!_fieldIsValid[form][field] && valid) {
			_fieldIsValid[form][field] = valid;
			_invalidFields[form] -= cardinality;
		}
		else if (_fieldIsValid[form][field] && !valid) {
			_fieldIsValid[form][field] = valid;
			_invalidFields[form] += cardinality;
		}
	}
	return valid;
}

function checkField(element, showErrors) {
	if (element.tagName == 'OPTION') {
		element = element.parentNode;
	}
	var value;
	var cardinality = 1;
	if (element.type && (element.type == 'checkbox' || element.type == 'radio')) {
		var peers = element.form[element.name];
		value = '';
		cardinality = peers.length;
		for (i = 0; i < peers.length; i++) {
			if (peers[i].checked) {
				if (value != '') {
					value += ',';
				}
				value += peers[i].value;
			}
		}
		if (!value) {
			value = "" + element.checked;
		}
	}
	else {
		value = element.value;
	}
	
	if (isValid(element.form.id, element.name, value, cardinality)) {
		if (_fieldMarkers[element.form.id][element.name]) {
			_fieldMarkers[element.form.id][element.name].src = _fieldOk.src;
			_fieldMarkers[element.form.id][element.name].style.cursor = 'auto';
			_fieldMarkers[element.form.id][element.name].onclick = null;
		}
		return true;
	}
	else {
		if (_fieldMarkers[element.form.id][element.name]) {
			_fieldMarkers[element.form.id][element.name].src = _fieldNotOk.src;
			_fieldMarkers[element.form.id][element.name].style.cursor = 'help';
			_fieldMarkers[element.form.id][element.name].onclick = function(e) {
				checkField(element, true);
			};
		}
		if (showErrors) {
			element.focus();
			alert(_fieldMessages[element.form.id][element.name]);
		}
		return false;
	}
}

var _fieldMarkers = [];
var _fieldOk = new Image();
_fieldOk.src = 'images/check.gif';
var _fieldNotOk = new Image();
_fieldNotOk.src = 'images/x.gif';

function checkForm(form, showErrors) {
	var children = form.elements;
	_fieldIsValid[form.id] = [];
	_invalidFields[form.id] = children.length;
	var ok = true;
	var element;
	for (var i = 0; i < children.length; i++) {
		element = children[i];
		ok = checkField(element, showErrors && ok) && ok;
	}
	checkSubmitButton(form);
	return ok;
}

function checkSubmitButton(form) {
	var ok = _invalidFields[form.id] == 0;
	_formSubmits[form.id].className = ok ? 'button' : 'button_disabled';
}

function setNextField(element, nextElement) {
	element.onkeypress = function(e) {
		var event = getEvent(e);
		if (event.keyCode == 13) {
			nextElement.focus();
			return false;
		}
		else {
			return true;
		}
	}
}

function isSetup(element) {
	return element.onchange == checkFormComponent;
}

function setupField(lastField, element) {
	if (element.type && element.type == 'checkbox') {
		element.className = 'checkbox_inactive';
	}
	else {
		element.className = 'input_inactive';
	}
//	element.onfocus = focusFormComponent;
//	element.onblur = blurFormComponent;
	if (element.addEventListener) {
		element.addEventListener('focus', focusFormComponent, false);
		element.addEventListener('blur', blurFormComponent, false);
	}
	else if (element.attachEvent) {
		element.attachEvent('onfocus', focusFormComponent);
		element.attachEvent('onblur', blurFormComponent);
	}
	if (!lastField) {
		element.blur();
		element.focus();
	}
	else if (lastField.tagName != 'TEXTAREA') {
		setNextField(lastField, element);
	}
	element.onkeyup = element.onchange = element.onclick = checkFormComponent;
	return element;
}

function setupButton(lastField, element) {
	if (!element.className) {
		element.className = 'button';
	}
	if (element.type == 'submit' && lastField && lastField.tagName != 'TEXTAREA') {
		lastField.onkeypress = function(e) {
			var event = getEvent(e);
			if (event.keyCode == 13) {
				if (element.form.onsubmit()) {
					element.form.submit();
				}
				return false;
			}
			else {
				return true;
			}
		}
	}
	return lastField;
}

function setupMarker(element, positionElement) {
	if (!positionElement) {
		positionElement = element;
	}

	var temp = document.createElement('img');
	temp.src = _fieldNotOk.src;
	temp.style.position = 'absolute';
	_formScratch[element.form.id].appendChild(temp);
	temp.style.top = (absTop(positionElement) + 2) + 'px';
	temp.style.left = (absLeft(positionElement) + positionElement.offsetWidth + 4) + 'px';
	_fieldMarkers[element.form.id][element.name] = temp;
}

function deactivateForm(form) {
	var element;

	var children = form.elements;
	for (var i = 0; i < children.length; i++) {
		element = children[i];
		element.onkeyup = element.onchance = element.onclick = null;
		if (element.removeEventListener) {
			element.removeEventListener('focus', focusFormComponent, false);
			element.removeEventListener('blur', blurFormComponent, false);
		}
		else if (element.detachEvent) {
			element.detachEvent('onfocus', focusFormComponent);
			element.detachEvent('onblur', blurFormComponent);
		}
	}

	children = _formScratch[form.id].childNodes;
	for (i = 0; i < children.length; i++) {
		element = children[i];
		_formScratch[form.id].removeChild(element);
	}
	document.body.removeChild(_formScratch[form.id]);
	_fieldMarkers[form.id] = [];
	
	if (_oldsubmits[form.id]) {
		form.onsubmit = _oldsubmits[form.id];
	}
}

var _formSubmits = [];
var _formScratch = [];
var _oldsubmits = [];
var _oldfocus = [];
function activateForm(form) {
	if (form.onsubmit) {
		_oldsubmits[form.id] = form.onsubmit;
		form.onsubmit = function(e) {
			if (checkForm(form, true)) {
				return _oldsubmits[form.id]();
			}
			else {
				return false;
			}
		};
	}
	else {
		form.onsubmit = function(e) {
			return checkForm(form, true);
		}
	}
	
	_formScratch[form.id] = document.createElement('div');
	document.body.appendChild(_formScratch[form.id]);

	_fieldMarkers[form.id] = [];

	var children = form.elements;
	var element;

	for (var i = 0; i < children.length; i++) {
		element = children[i];
		if (element.type && element.type == 'submit') {
			_formSubmits[form.id] = element;
		}
	}
	
	var lastField = null;
	var markerText = '_marker';
	for (var i = 0; i < children.length; i++) {
		element = children[i];

		if (element.tagName == 'INPUT') {
			if ((element.type == 'text' || element.type == 'password' || element.type == 'file' || element.type == 'checkbox') && !isSetup(element)) {
				if (element.name.indexOf(markerText) == Math.max(0, element.name.length - markerText.length)) {
					var markerFor = form[element.name.substring(0, element.name.length - markerText.length)];
					if (!markerFor.form) { // it is a nodelist, just pick one
						setupMarker(markerFor[0], element);
						for (var i2 = 0; i2 < markerFor.length; i2++) {
							lastField = setupField(lastField, markerFor[i2]);
						}
					}
					else {
						setupMarker(markerFor, element);
						lastField = setupField(lastField, markerFor);
					}
				}
				else if (element.type == "checkbox") {
					setupMarker(element, element.parentNode);
				}
				else {
					setupMarker(element);
				}
				if (element.style.visibility != 'hidden') {
					lastField = setupField(lastField, element);
				}
			}
			else if (element.type == 'button' || element.type == 'submit') {
				lastField = setupButton(lastField, element);
			}
		}
		else if (element.tagName == 'SELECT') {
			setupMarker(element);
			lastField = setupField(lastField, element);
		}
		else if (element.tagName == 'TEXTAREA') {
			setupMarker(element);
			lastField = setupField(lastField, element);
		}
	}
	
	checkForm(form, false);
}

