
	var HandleEstateForm = new Class({
		Implements: [Options, Events],

		options: {
			requestUrl             : '',
			classExcludeElements   : '',
			useClientcideWaiter    : false,
			clientcideOverlayTarget: null,
			clientcideWaiterOptions: {},
			onRequestStart         : $empty(),
			onRequestComplete      : $empty(),
			onRequestEmpty         : $empty(),
			onRequestFailed        : $empty()
		},

		initialize: function(frm, container, options){
			this.setOptions(options);

			this.frm           = frm;
			this.frmAction     = (this.frm) ? this.frm.get('action') : '';
			this.frmIsDisabled = false;
			this.container     = container;
			this.frmElements   = [];


			// Check required elements and definitions.
			// ----------------------------------------

			if(!this.checkInit())
				return;


			// Clientcide Waiter?
			// ------------------

			this.containerSpinner = false;

			if(this.options.useClientcideWaiter) {
				var cc_target = ($chk(this.options.clientcideOverlayTarget)) ? this.options.clientcideOverlayTarget : this.container;
				//this.containerSpinner = new Waiter(cc_target, this.options.clientcideWaiterOptions);
			}


			// Setup formular.
			// ---------------

			this.setupForm();


			// Setup formular elements.
			// ------------------------

			this.parseElements();
		},

		setupForm: function() {
			var siht = this;

			// Grab the submit button and set events.
			// --------------------------------------


			// The form may not be sent when the user press
			// Enter/Return in a input(type="text") field.
			// --------------------------------------------

			this.frm.addEvent('submit', function(ev) {
				if(siht.frmIsDisabled)
					new Event(ev).stop();
			});


			// Set default 'send' request instance for formular.
			// -------------------------------------------------

			this.frm.set('send', {
				url: siht.options.requestUrl,
				onRequest: function() {
			    	siht.handleReqStart();
			    },
			    onFailure: function(xhr) {
			    	siht.handleReqFailed(xhr);
			    },
				onComplete: function(resText, resXML) {

					if(!resText)
						resText = '';

					if(!resXML)
						resXML = '';

					siht.handleReqComplete(resText, resXML);
				}
			});
		},

		checkInit: function() {
			var i   = 1;
			var msg = '';

			if(!$chk(this.frm)) {
				msg+= i + ". Required element 'Form' not found.\n";
				i++;
			}

			if(this.frmAction.clean() == '') {
				msg+= i + ". Please check required formular action.\n";
				i++;
			}

			if(!$chk(this.container)) {
				msg+= i + ". Required element 'Container' not found.\n";
				i++;
			}

			if((!$chk(this.options.requestUrl) || this.options.requestUrl.clean() == '')) {
				msg+= i + ". Please check required option 'requestUrl'.\n";
				i++;
			}

			if(msg != '') {
				alert(msg);
				return false;
			}

			return true;
		},

		parseElements: function() {
			this.frm.getElements('input, textarea, select').each(function(el) {
				var fc = function() {
					this.frm.send();
				}.bind(this);

				switch(el.type) {
					case 'text':
						if(this.options.classExcludeElements == '' || !el.hasClass(this.options.classExcludeElements)) {
							// Add some events (not used)
						}

						var siht = this;

						el.addEvents({
							'focus': function() {
								siht.frmIsDisabled = true;
							},
							'blur': function() {
								siht.frmIsDisabled = false;
							}
						});
						break;

					case 'textarea':
						break;

					case 'select':
					case 'select-one':
						if(this.options.classExcludeElements == '' || !el.hasClass(this.options.classExcludeElements))
							el.addEvent('change', fc);
							this.frmElements.push(el);
						break;

					case 'select-multiple':
						if(this.options.classExcludeElements == '' || !el.hasClass(this.options.classExcludeElements)) {
							el.addEvents({
								'blur': fc
							});

							this.frmElements.push(el);
						}
						break;

					case 'checkbox':
					case 'radio':
						if(this.options.classExcludeElements == '' || !el.hasClass(this.options.classExcludeElements)) {
							el.addEvents({
								'click'  : fc,
								'keydown': function(ev) {
									if(ev.key == 'space')
										fc();
								}
							});
							this.frmElements.push(el);
						}
						break;
				}
			}.bind(this));
		},

		handleReqStart: function() {
			// Hide content spinner.
			this.handleSpinner(true);

			// Call user defined function.
	    	this.fireEvent('onRequestStart');
		},

		handleReqComplete: function(resText, resXML) {
			if(resText) {

				// Remove all Events from latest saved elements.
				this.garbageCleanUp();

				// Update inner content from target container.
				this.container.innerHTML = resText;

				// Set new events to formular fields etc. in target container.
				this.parseElements();

				// Hide content spinner.
				this.handleSpinner(false);

				// Call user defined function.
				this.fireEvent('onRequestComplete', resText, resXML);

	    	} else {

	    		// Call user defined function.
	    		this.handleReqEmpty();

	    	}
		},

		handleReqFailed: function(xhr) {
			// Hide content spinner.
			this.handleSpinner(false);

			// Call user defined function.
			this.fireEvent('onRequestFailed', xhr);
	    },

		handleReqEmpty: function() {
			// Hide content spinner.
			this.handleSpinner(false);

			// Call user defined function.
			this.fireEvent('onRequestEmpty');
		},

		handleSpinner: function(status) {
			if(this.containerSpinner) {
				if(status)
    				this.containerSpinner.start();
    			else
    				this.containerSpinner.stop();
			}
		},

		garbageCleanUp: function() {
			this.frmElements.each(function(el) {
				el.removeEvents();
			});
		}
	});
