
	if (!IntersonForm) {
		var IntersonForm = function (sId, aErrors) {
			this.sId = sId;
			this.rows = [];
			this.input = [];
			this.errors = aErrors;
			this.state = {};
			
			j(document).ready(createMethodReference(this, this.initialize));
		};
		
		IntersonForm.prototype.initialize = function () {
			this.oForm = $(this.sId);

			if (!this.oForm)
				return;
			
			var row = getElementsByClass('form_row', this.oForm, 'div');
			for (var k = 0; k < row.length; k ++) {
				var r = {
					"input": {}
				};
				
				var input = getElementsByClass('form_input', row[k]);
				var is_error = false;
				
				for (var jk = 0; jk < input.length; jk ++) {
					var st = is_subclass_of(input[jk], 'checkform-groupstatus') ? getElementsByClass('form_status', input[jk].parentNode.parentNode) : getElementsByClass('form_status', input[jk]);

					var i = {
						"status": st.length ? st[0] : null,
						"row": row[k],
						"input": input[jk],
						"form": this,
						"controlChecking": false,
						"controlCheckingTimeout": null
					};
					
					var control = i['control'] = this.getControl(input[jk]);

					if (!control) {
						if (this.errors[name])
							alert(this.errors[name]);

						continue;
					}
						
					var name = i['name'] = control.getAttribute('name').replace('[]', '');

					var ctrl = IntersonForm.getControls(input[jk]);
					for (var l = 0; l < ctrl.length; l ++) {
						attachEvent(ctrl[l], 'blur', createMethodReference(i, this.controlChange));
						attachEvent(ctrl[l], 'change', createMethodReference(i, this.controlChangeDelay));
						attachEvent(ctrl[l], 'keyup', createMethodReference(i, this.controlChangeDelay));
					}
					
					r.input[name] = i;
					this.input[name] = i;

					this.state[name] = 1;
					
					if (this.errors[name] != undefined) {
						is_error = true;
						if (i.status && this.errors[name]) {
							i.status.innerHTML = '<img src="' + JS_HOST + 'view/images/icon_error.png" class="mid" /> <span class="mid">' + this.errors[name] + '</span>';
							i.status.className += ' form_error_status';
						} else if (this.errors[name] && $('error-space-' + this.sId)) {
							var d = n('div');
							d.className = 'error';
							d.innerHTML = this.errors[name];
							$('error-space-' + this.sId).appendChild(d);
						} else {
							this.state[name] = this.errors[name] ? 0 : 1;
						}

						input[jk].parentNode.className += ' form_error';
					} else if (i.status) {
						i.status.style.display = 'none';
					}
				}
				
				if (is_error) {
					j(row[k]).addClass('form_error');
				}
			}

			for (k in this.errors) {
				if (!this.state[k]) {
					alert(this.errors[k]);
				}
			}
		};

		IntersonForm.prototype.getControl = function (node) {
			var input = j(node).find('input');
			if (input.length > 0 && !is_subclass_of(input[0], 'skip-autoform'))
				return input[0];

			input = j(node).find('textarea');
			if (input.length > 0 && !is_subclass_of(input[0], 'skip-autoform'))
				return input[0];

			input = j(node).find('select');
			if (input.length > 0 && !is_subclass_of(input[0], 'skip-autoform'))
				return input[0];

			return null;
		};
		
		IntersonForm.getControls = function (node, named) {
			var res = named ? {"item": {}, "length": 0} : [];
			
			var input = j(node).find('input');
			for (var i = 0; i < input.length; i ++) {
				if (named) {
					res.item[input[i].name] = input[i];
					res.length ++;
				} else
					res.push(input[i]);
			}
				
			input = j(node).find('textarea');
			for (i = 0; i < input.length; i ++) {
				if (named) {
					res.item[input[i].name] = input[i];
					res.length ++;
				} else
					res.push(input[i]);
			}
				
			input = j(node).find('select');
			for (i = 0; i < input.length; i ++) {
				if (named) {
					res.item[input[i].name] = input[i];
					res.length ++;
				} else
					res.push(input[i]);
			}

			return res;
		};
		
		IntersonForm.prototype.controlChangeDelay = function () {
			clearInterval(this.controlCheckingTimeout);
			this.controlCheckingTimeout = setTimeout(createMethodReference(this, this.form.controlChange), 1000);
		};
		
		IntersonForm.prototype.controlChange = function () {
			if (!this.controlChecking) {
				clearInterval(this.controlCheckingTimeout);
				
				this.controlChecking = true;
				
				try {
					var sUrl = this.form.oForm.getAttribute('action');
					sUrl = sUrl.replace(/\/[^\/]+\/(\?(.*))?$/, '/checkfield/?$2');
					sUrl += '&field=' + this.name;
					
					var conn = new TConnection;
					conn.sUrl = sUrl;
					conn.sMethod = 'POST';
					
					conn.onData = createMethodReference(this, function (c) {
						try {
							try {
								eval('var data = ' + c.responseText + ';');
								
								if (data) {
									if (data.is_null) {
										this.input.parentNode.className += ' form_error';

										if (data.errstr != "") {
											this.status.innerHTML = '<img src="' + JS_HOST + 'view/images/icon_error.png" class="mid" /> ' +  data.errstr;
											this.status.style.display = '';
										}
										
										this.status.className += ' form_error_status';
									} else {
										this.input.parentNode.className = this.input.parentNode.className.replace(/ form_error/g, '');
//										this.status.className = this.input.parentNode.className.replace(/ form_error_status/g, '');
										
										//this.status.innerHTML = '<img src="' + JS_HOST + 'view/images/icon_ok.png" class="mid" /> ' + (this.status.nodeName.toLowerCase() == 'div' ? 'OK' : '');
										this.status.style.display = 'none';
									}
								}
							} catch (e) {
								debug(e);
							}
						} finally {
							this.controlChecking = false;
						}
					});
					
					setFormDataToConnection(this.form.oForm, conn);
					
					conn.open();
				} catch (e) {
					debug(e);
					this.controlChecking = false;
				}
			}
		};
	}
