Object.extend(Form.Element, {
	hasChanged: function(element){
		element = $(element);
		return element.__changed;
	},
	markChanged: function(element) {
		element = $(element);
		element.__changed = true;
	},
	resetChanged: function(element){
		element = $(element);
		element.__changed = false;
		Event.observe(element, 'change', function(){
			element.__changed = true;
		});
	}
});

Object.extend(Form, {
	hasChanged: function(form){
		form = $(form);
		for (var i = 0; i < form.elements.length; i++)
			if (Form.Element.hasChanged(form.elements[i]))
				form.__changed = true;
		return form.__changed;
	},
	markChanged: function(form) {
		form = $(form);
		form.__changed = true;
	},
	resetChanged: function(form){
		form = $(form);
		form.__changed = false;
		for (var i = 0; i < form.elements.length; i++)
			Form.Element.resetChanged(form.elements[i]);
	}
});

var Superform = {

	setup: function() {

		$A(document.forms).each( function(form) {

			if (!form._superform) {
	
				Form.resetChanged(form);
	
				// Cancel
		
				form.cancel = function () {
		
					if (!Form.hasChanged(this))
						return true;
		
					else
						return confirm('You have made changes to this form, if you proceed you will lose these changes.\nDo you wish to proceed?');
		
				}
		
				// Clear
				
				form.clear = function () {
		
					Form.markChanged(this);
		
					for (var i = 0; i < this.elements.length; i++) {
						switch (this.elements[i].type) {
							case 'checkbox':	this.elements[i].checked = false; break;
							case 'radio':		this.elements[i].checked = false; break;
							case 'select-one':	this.elements[i].options[0].selected = true; break;
							case 'submit':		break;
							case 'reset':		break;
							case 'button':		break;
							case 'hidden':		break;
							default:			this.elements[i].value = ''; break;
						}
					}
		
					if (typeof this.onClear != 'undefined')
						this.onClear();
				}
		
				// Proceed
				
				form.proceed = function () {
		
					if (this.onsubmit())
						this.submit();
		
				}
		
				// Revert
				
				form.revert = function () {
		
					this.reset();
		
					Form.resetChanged(this);
		
					if (typeof this.onRevert != 'undefined')
						this.onRevert();
		
				}
				
				// SELECT functions
			
				$A(form.getElementsByTagName('select')).each( function(el) { 
		
					// Populate
				
					el.populate = function (elements) {

						var parameters = ( arguments.length > 1 ? arguments[1] : {} );

						// parameters.sort (true | false);
						// parameters.descending (true | false);
		
						// Clear out the combo
		
						var combo = this;
		
						if (combo.options.length > 0) {
		
							var first = (combo.options[0].value == '') ? 1 : 0;
		
							while (combo.options.length > first)
								combo.options[first] = null;
								
						}
						
						// Now populate the combo
						
						var options = [];
						var elements = elements || {};
						
						var records = elements.recordcount || elements.rowcount || 0;
						var columns = (elements.columnlist || elements.columns || '').split(',');

						for (var i = 0; i < records; i++) {
		
							var otemp = {};
		
							for (var j = 0; j < columns.length; j++)
								otemp[columns[j]] = elements.data[columns[j]][i];
		
							options[options.length] = otemp;
		
						}
		
						$A(options).each(function (el) {
							combo.options[combo.options.length] = new Option(
								el.text || '', 
								el.value || '',
								el.defaultselected || false,
								el.selected || false
							);
						});
		
						// Now sort (if specified)
		
						if (parameters.sort || false)
							combo.sort((parameters.descending || false));
					}
					
					// Sort
					
					el.sort = function(descending) {
					
						var combo = this;
		
						if (combo.options.length > 0) {
						
							var atemp = new Array();
							var first = (combo.options[0].value == '') ? 1 : 0;
		
							if (combo.options.length > 1) {
							
								for (var i = first; i < combo.options.length; i++)
									atemp[atemp.length] = new Option(
										combo.options[i].text,
										combo.options[i].value,
										combo.options[i].defaultSelected,
										combo.options[i].selected
									);
		
								atemp = atemp.sort( 
									function (a, b) { 
										if ((a.text + '') < (b.text + '')) { return (descending || false) ? 1 : -1; }
										if ((a.text + '') > (b.text + '')) { return (descending || false) ? -1 : 1; }
										return 0;
									}
								);
		
								for (var i = 0; i < atemp.length; i++)
									combo.options[i + first] = new Option(
										atemp[i].text, 
										atemp[i].value, 
										atemp[i].defaultSelected, 
										atemp[i].selected
									);
		
							}
					
						}
						
					}
		
				});
				
				// Load additional form defaults (if specified)
		
				if (typeof form.onRevert != 'undefined') {

					form.onRevert();

					$A(form.elements).each( function(element) {
						if (!element._superform) {
							Form.Element.resetChanged(element);
							element._superform = true;
						}
					});

				}
	
				form._superform = true;
			}

			$A(form.elements).each( function(element) {
				if (!element._superform) {
					Form.Element.resetChanged(element);
					element._superform = true;
				}
			});

		});

	}
};
  
Event.observe(window, 'load', Superform.setup);   
