/** 
* Javascript Form Classes
*
* @import Web/UI/HtmlControl.js
*/

/** Form Control */
with(Web_UI_FormControl_Form = NewClass()) 
{
	inherits(Web_UI_HtmlControl);

	// Construct the form and add events
	prototype.__construct = function () {
		parent.__construct.call(this);
		this.validators = [];
		this.errorHandlers = [];
		this.errors = [];
		this.controlErrors = {};
		this.events.onSubmit = new Web_UI_Event('onsubmit');
		this.events.onReset = new Web_UI_Event('onreset');
	}

	// Bind the change event
	prototype.load = function (e) {
		if (parent.load) parent.load.call(this, e);
		this.events.onSubmit.add(this.defaultSubmit.bind(this));
	}
	
	// Bind the change event
	prototype.unload = function (e) {	
		if (parent.load) parent.load.call(this, e);
		delete this.validators;
		delete this.errorHandlers;
	}
		
	// Form is default submitted; before validation
	prototype.defaultSubmit = function(e) {
		if (this.defaultValidation && !this.validate()) return false;
		return true;
	}

	// Refreshes the page by submitting this form
	prototype.refresh = function() {
		if (this.tag && this.defaultSubmit()) {
			__doPostBack(this.tag, '@refresh', '', false);
		}
	}
	
	// Finds the specified form fields by client id.
	prototype.findField = function (clientId) { 
		if (!this.tag) return null;
		return this.tag.elements[clientId]; 
	}
	
	/** Performs validation of the specified form */
	prototype.validate = function () {
		// Reset all the values
		var isValid = true;
		this.errors = [];
		this.controlErrors = {};
		var firstFailed = null;
		// Iterate all validators on the form
		for (var i = 0; i < this.validators.length; i++) {
			var validator = this.validators[i];
			if (!validator.validate()) {
				if (!firstFailed) firstFailed = validator;
				isValid = false;
			}
		}
		// Iterate all the registered error handlers
		for (var i = 0; i < this.errorHandlers.length; i++) this.errorHandlers[i].process();
		// Set focus on first failed validator
		if (!isValid && firstFailed.focus) firstFailed.focus();
		return isValid;
	}
}

/** TextBox Control */
with(Web_UI_FormControl_TextBox = NewClass()) 
{
	inherits(Web_UI_HtmlFormControl);

	// Bind the change event
	prototype.load = function (e) {
		if (parent.load) parent.load.call(this, e);
		if (this.keyRegExp) this.events.onKeyUp.add(this.filterKeyUp.bind(this));
		if (this.keyRegExp) this.events.onKeyPress.add(this.filterKey.bind(this));
		if (this.keyRegExp) this.events.onKeyDown.add(this.filterKeyDown.bind(this));
	}

	// Handle key up and key down to filter out function keys
	prototype.filterKeyUp = function (e) { this.funcKey = false; return true; }
	prototype.filterKeyDown = function (e) { 
		if (!e.keyCode) this.funcKey = true;
		if (e.keyCode < 32 && e.keyCode != 16) this.funcKey = true;
		if (e.keyCode >= 34 && e.keyCode <= 40) this.funcKey = true;
		if (e.keyCode == 46) this.funcKey = true;
		return true;
	}
	
	// Main key filter method
	prototype.filterKey = function (e) {
		if (!e.keyCode || !this.keyRegExp || this.funcKey) return true;
		var value = this.tag.value + e.keyChar;
		return (new RegExp('^'+this.keyRegExp+'$')).test(value);
	}
	
	// Get the contents of the text box
	prototype.getValidationValue = function() { return (this.tag) ? this.tag.value : null; }
}

/** Hidden Control */
with(Web_UI_FormControl_Hidden = NewClass()) 
{
	inherits(Web_UI_HtmlFormControl);
	
	// Get the contents of the text box
	prototype.getValidationValue = function() { return (this.tag) ? this.tag.value : null; }
}

/** CheckBox Control */
with(Web_UI_FormControl_CheckBox = NewClass()) 
{
	inherits(Web_UI_HtmlFormControl);

	// Construct the form and add events
	prototype.__construct = function () {
		parent.__construct.call(this);
		this.events.onChange.bindToEvent(this.events.onClick);
	}

	// Sets the value of this form control
	prototype.setValue = function(value) {
		if (!this.tag) return;
		if (value == this.tag.checked) return;
		this.tag.checked = value;
		if (this.tag.onchange) this.tag.onchange();
	}

	// Returns the value of the checkbox
	prototype.getValidationValue = function() { 
		return (this.tag && this.tag.checked) ? (isDefined(this.value) ? this.value : this.tag.value) : false; 
	};
}

/** ListBox Control */
with(Web_UI_FormControl_ListBox = NewClass()) 
{
	inherits(Web_UI_HtmlFormControl);

	// Get the contents of the list box
	prototype.getValidationValue = function() {
		if (!this.tag) return null;
		if (this.tag.type == 'select-multiple') {
			var result = new Array();
			for (var i = 0; i < this.tag.options.length; i++) {
				if (this.tag.options[i].selected) result[result.length] = this.tag[i].value;
			}
			return result;
		}
		if (this.tag.selectedIndex >= 0) return this.tag.options[this.tag.selectedIndex].value;
		return null;
	};

	// Returns the selected ListItem object if it exists
	prototype.selectedItem = function () {
		if (this.tag.selectedIndex < 0) return null;
		return Page.findControl(this.tag.options[this.tag.selectedIndex].id);
	}
	
	// Submit the form from this control
	prototype.submitForm = function (e) {
		if (!this.confirm()) {
			this.tag.selectedIndex = -1;
			return false;
		}
		if (parent.submitForm) return parent.submitForm.call(this, e);
	}	
		
	// Confirms the submission of the form by the current list item.
	prototype.confirm = function () {
		var item = this.selectedItem();
		if (!item || !item.confirm) return true;
		return confirm(item.confirm);
	}
}

/** ListItem Control */
with(Web_UI_FormControl_ListItem = NewClass()) 
{
	inherits(Web_UI_HtmlControl);
}

/** FileUpload Control */
with(Web_UI_FormControl_FileUpload = NewClass()) 
{
	inherits(Web_UI_HtmlFormControl);

	// Get the contents of the file upload
	prototype.getValidationValue = function() { return (this.tag) ? this.tag.value : null; }
}

/** RadioGroup control */
with(Web_UI_FormControl_RadioButtonGroup = NewClass()) 
{
	inherits(Web_UI_Control);
	
	// Construct the form and add events
	prototype.__construct = function () {
		parent.__construct.call(this);
		this.controls = [];
		this.events.onChange = new Web_UI_Event();
	}	

	// Gets the selected radio button
	prototype.getValidationValue = function() {
		for (var i = 0; i < this.controls.length; i++) {
			var value = this.controls[i].getValidationValue();
			if (value) return value;
		}
		return null;
	};

	// Loads the tag for this control if it exists
	prototype.exists = function() { 
		for (var i = 0; i < this.controls.length; i++) if (this.controls[i].exists()) return true;
		return false;
	}

	// Load all the controls in this group
	prototype.load = function() {
		if (parent.load) parent.load.call(this);
		if (!this.formId || !this.clientId) return;
		var form = Page.findControl(this.formId);
		if (!form) return;
		var group = form.findField(this.clientId);
		if (!group) group = form.findField(this.clientId+'[]');
		if (!group) return;
		if (group.length) {
			for (var i = 0 ; i < group.length; i++) {
				var control = Page.findControl(group[i].id);
				if (control) {
					if (!this.tag) this.tag = control.tag;
					this.controls.add(control);
					this.events.onChange.bindToEvent(control.events.onChange);
				}
			}
		} else {
			var control = Page.findControl(group.id);
			if (!this.tag) this.tag = control.tag;
			this.controls.add(control);
			this.events.onChange.bindToEvent(control.events.onChange);
		}
	}
	
	// Load all the controls in this group
	prototype.unload = function() {
		if (parent.unload) parent.unload.call(this);	
		this.controls.clear();
	}
	
	// Changes the control so it has error CSS
	prototype.setError = function() { for (var i = 0; i < this.controls.length; i++) this.controls[i].setError(); }
	prototype.clearError = function() { for (var i = 0; i < this.controls.length; i++) this.controls[i].clearError(); }
}

/** CheckGroup control */
with(Web_UI_FormControl_CheckBoxGroup = NewClass())
{
	inherits(Web_UI_FormControl_RadioButtonGroup);

	// Gets an array of all the checked items
	prototype.getValidationValue = function() {
		var result = new Array();
		for (var i = 0; i < this.controls.length; i++) {
			var value = this.controls[i].getValidationValue();
			if (value) result.add(value);
		}
		return result;
	}

	// Loads the tag for this control if it exists
	prototype.exists = function() { 
		for (var i = 0; i < this.controls.length; i++) if (this.controls[i].exists()) return true;
		return false;
	}
	
	// Sets all the items as checked
	prototype.setAll = function() {
		for (var i = 0; i < this.controls.length; i++) {
			this.controls[i].tag.checked = true;
		}
	}
	
	// Clears all the checks
	prototype.clearAll = function() {
		for (var i = 0; i < this.controls.length; i++) {
			this.controls[i].tag.checked = false;
		}
	}
}

/** Button Control */
with(Web_UI_FormControl_Button = NewClass()) 
{
	inherits(Web_UI_HtmlControl);

	// Binds the click method to the onClick event
	prototype.load = function() {
		if (parent.load) parent.load.call(this);
		this.events.onClick.add(this.click.bind(this));
	}
	
	// Handle the click of the button by submitting the form
	prototype.click = function(e) {
		if (this.confirm) if (!window.confirm(this.confirm)) return false;
		if (this.disableOnSubmit) this.tag.disabled = true;
		__doPostBack(this.formId, this.clientId, this.param, this.causesValidation);
		return null;
	}
}

/** DateBox Control */
with(Web_UI_FormControl_DateBox = NewClass()) 
{
	inherits(Web_UI_FormControl_TextBox);
	
	// Get the contents of the text box
	prototype.getValidationValue = function() { return (this.tag) ? this.tag.value : null; }
}

/** The CheckBoxGroupLink object */
with (Web_UI_FormControl_CheckBoxGroupLink = NewClass()) 
{
	inherits(Web_UI_HtmlControl);

	// Binds the click method to the onClick event
	prototype.load = function() {
		if (parent.load) parent.load.call(this);
		this.events.onClick.add(this.click.bind(this));
	}
	
	// Handle the click of buttons
	prototype.click = function(e) {
		if (!this.groupId) return;
		var group = Page.findControl(this.groupId);
		if (!group) return;
		if (this.mode == 1) group.clearAll();
		else group.setAll();
	}
}

/** Button Control */
with(Web_UI_FormControl_CommandLink = NewClass()) 
{
	inherits(Web_UI_HtmlControl);

	// Binds the click method to the onClick event
	prototype.load = function() {
		if (parent.load) parent.load.call(this);
		this.events.onClick.add(this.click.bind(this));
	}
	
	// Handle the click of the button by submitting the form
	prototype.click = function(e) {
		if (this.confirm) if (!window.confirm(this.confirm)) return false;
		var target = __findTarget(this.target);
		if (target && target.__doPostBack) {
			target.__doPostBack(null, '@command:'+this.commandName, this.commandArgument, this.causesValidation);
		}
		return null;
	}
}

/** DateBox Control */
with(Web_UI_FormControl_DurationBox = NewClass()) 
{
	inherits(Web_UI_Control);
	
	// Binds the click method to the onClick event
	prototype.load = function() {
		if (parent.load) parent.load.call(this);
		if (this.hoursId) this.hours = Page.findControl(this.hoursId);
		if (this.minutesId) this.minutes = Page.findControl(this.minutesId);
	}

	// Loads the tag for this control if it exists
	prototype.exists = function() { return (this.hours.exists() && this.minutes.exists()); }
	
	// Get the contents of the text box
	prototype.getValidationValue = function() {
		if (!this.hours.exists() || !this.minutes.exists()) return null;
		var hours = parseInt(this.hours.getValidationValue());
		var minutes = parseInt(this.minutes.getValidationValue());
		return (hours * 60 + minutes) * 60;
	}
}

/** DateBox Control */
with(Web_UI_FormControl_TimeBox = NewClass()) 
{
	inherits(Web_UI_Control);
	
	// Binds the click method to the onClick event
	prototype.load = function() {
		if (parent.load) parent.load.call(this);
		if (this.hourId) this.hour = Page.findControl(this.hourId);
		if (this.minuteId) this.minute = Page.findControl(this.minuteId);
		if (this.amPmId) this.amPm = Page.findControl(this.amPmId);
	}

	// Loads the tag for this control if it exists
	prototype.exists = function() { return (this.hour.exists() && this.minute.exists() && this.amPm.exists()); }
	
	// Get the contents of the text box
	prototype.getValidationValue = function() { 
		if (!this.hour.exists() || !this.minute.exists() || !this.amPm.exists()) return null;
		var hour = parseInt(this.hour.getValidationValue());
		var minute = parseInt(this.minute.getValidationValue());
		var amPm = this.amPm.getValidationValue();
		
		if (hour == 12) hour = (amPm == 'am') ? 0 : 12;
		else if (amPm == 'pm') hour += 12;
		return (hour * 60 * 60) + (minute * 60);
	}
}

/** DateBox Control */
with(Web_UI_FormControl_ExpiryBox = NewClass()) 
{
	inherits(Web_UI_Control);
	
	// Binds the click method to the onClick event
	prototype.load = function() {
		if (parent.load) parent.load.call(this);
		if (this.monthId) this.month = Page.findControl(this.monthId);
		if (this.yearId) this.year = Page.findControl(this.yearId);
	}

	// Loads the tag for this control if it exists
	prototype.exists = function() { return (this.month.exists() && this.year.exists()); }
	
	// Get the contents of the text box
	prototype.getValidationValue = function() { 
		if (!this.month.exists() || !this.year.exists()) return null;
		var month = parseInt(this.month.getValidationValue());
		var year = parseInt(this.year.getValidationValue());

		var date = new Date();
		date.setFullYear(year,month,1);
		date.setDate(date.getMonthDays());
		return date;
	}
}

/** DateBox Control */
with(Web_UI_FormControl_MonthDayBox = NewClass()) 
{
	inherits(Web_UI_Control);
	
	// Binds the click method to the onClick event
	prototype.load = function() {
		if (parent.load) parent.load.call(this);
		if (this.monthId) this.month = Page.findControl(this.monthId);
		if (this.dayId) this.day = Page.findControl(this.dayId);
	}

	// Loads the tag for this control if it exists
	prototype.exists = function() { return (this.month.exists() && this.day.exists()); }
	
	// Get the contents of the text box
	prototype.getValidationValue = function() { 
		if (!this.month.exists() || !this.day.exists()) return null;
		var month = parseInt(this.month.getValidationValue());
		var day = parseInt(this.day.getValidationValue());

		var date = new Date();
		date.setMonth(month);
		date.setDate(day);
		return date;
	}
}

/** CheckListBox Control */
with(Web_UI_FormControl_CheckListBox = NewClass()) 
{
	inherits(Web_UI_HtmlControl);

	// Adds	key events to the form fields
	prototype.__construct = function() {
		parent.__construct.call(this);
		this.events.onChange = new Web_UI_Event('onchange').add(this.change.bind(this));
	}
	
	// Binds the click method to the onClick event
	prototype.load = function() {
		if (parent.load) parent.load.call(this);
		if (this.tag) this.checkboxes = this.tag.getElementsByTagName("input");
		else return;
		// Bind change events to all the checkboxes
		for (var i = 0; i < this.checkboxes.length; i++) {
			this.events.onChange.bind(this.checkboxes[i]);
		}
	}
	
	// Get the contents of the list box
	prototype.getValidationValue = function() {
		if (!this.checkboxes) return null;
		var result = new Array();
		for (var i = 0; i < this.checkboxes.length; i++) {
			if (this.checkboxes[i].checked) result[result.length] = this.checkboxes[i].value;
		}
		return result;
	};
	
	// Gets the value of this form control
	prototype.change = function() {
		if (parent.change) parent.change.call(this);
		this.changed = true;
	}		
}

/** Hidden Control */
with(Web_UI_FormControl_Prompt = NewClass()) 
{
	inherits(Web_UI_FormControl_Hidden);

	// Creates the calendar and binds to the button
	prototype.load = function () {
		if (parent.load) parent.load.call(this);
		// Get the button control
		this.button = Page.findControl(this.buttonId);
		if (this.button) this.button.events.onClick.push(this.buttonClick.bind(this));
	}

	// Called when the button is clicked; returns false.
	prototype.buttonClick = function() {
		if (!this.message) return true;
		if (!this.tag) return true;
		var result = '';
		do {
			result = prompt(this.message, this.tag.value);
			if (isNull(result)) return false;
		} while (!result && this.required);
		this.tag.value = result;
		return true;
	}	
}

/** CheckBox Control */
with(Web_UI_FormControl_ToggleImage = NewClass()) 
{
	inherits(Web_UI_HtmlFormControl);

	// Construct the form and add events
	prototype.__construct = function () {
		parent.__construct.call(this);
		this.image = null;
	}

	// Load all the controls in this group
	prototype.load = function() {
		if (parent.load) parent.load.call(this);
		if (!this.imageId) return;
		this.image = Page.findControl(this.imageId);
		this.image.events.onClick.add(this.imageClick.bind(this));
	}

	// Called when the button is clicked; returns false.
	prototype.imageClick = function() {
		this.setValue(!this.tag.value);
		return false;
	}	

	// Sets the value of this form control
	prototype.setValue = function(value) {
		if (!this.tag || !this.image) return;
		if (value == !!this.tag.value) return;
		if (value) {
			this.tag.value = this.key;
			this.image.tag.src = this.activeSrc;
			this.image.tag.title = this.activeTitle;
		} else {
			this.tag.value = '';
			this.image.tag.src = this.inactiveSrc;
			this.image.tag.title = this.inactiveTitle;
		}
		if (this.tag.onchange) this.tag.onchange();
	}

	// Returns the value of the checkbox
	prototype.getValidationValue = function() { 
		return (this.tag && this.tag.value) ? (isDefined(this.value) ? this.value : this.tag.value) : false; 
	};
}

