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 () {
		
					var i,
						ignore = (arguments.length ? arguments[0].split(',') : []);
		
					Form.markChanged(this);
					
					for (i = 0; i < this.elements.length; i++)
						if (ignore.indexOf(this.elements[i].id) == -1)
							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) {

						elements = elements || {};

						var i, j,
							parameters = ( arguments.length > 1 ? arguments[1] : {} ),
							combo = this,
							options = [],
							records = elements.recordcount || elements.rowcount || 0,
							columns = (elements.columnlist || elements.columns || '').split(','),
							otemp = {},
							first = ((combo.options.length > - 1) && (combo.options[0].value == '')) ? 1 : 0;

						// parameters.sort (true | false);
						// parameters.descending (true | false);
		
						// Clear out the combo
		
						if (combo.options.length > 0)
							while (combo.options.length > first)
								combo.options[first] = null;

						// Now populate the combo

						for (i = 0; i < records; i++) {

							otemp = {};
							for (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 i,
							combo = this,
							atemp = [],
							first = ((combo.options.length > - 1) && (combo.options[0].value == '')) ? 1 : 0;
		
						if (combo.options.length > 0) {
						
							if (combo.options.length > 1) {
							
								for (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 (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);   
