/**
 * FormField class
 *
 * For generating form fields.
 *
 * Details of properties used by most elements:
 * - name: The element name. Used to generate the element ID.
 * - display: Text describing the element. Used to generate an associated label element.
 * - value: The element's default value.
 * - validationrule: 
 * - rule: Alias for validationrule.
 *
 * Details of Form Field Types
 * - FORMFIELDTYPE_TEXTBOX
 *   Generates a text input.
 * - FORMFIELDTYPE_TEXTAREA
 *   Generates a text area.
 * - FORMFIELDTYPE_DROPDOWN
 *   Generates a dropdown list. Use the 'options' property to specify the list options in the form of a key=>value array.
 * - FORMFIELDTYPE_CHECKBOX
 *   Generates a checkbox. Use the 'checked' property to specify whether it is checked by default.
 * - FORMFIELDTYPE_MULTISELECT
 *   Not implemented.
 * - FORMFIELDTYPE_MULTISELECT_CHECKBOX_GROUP
 *   Generates a group of checkboxes. Use the 'options' property to specify the list options in the form of a key=>value array.
 *   Not implemented.
 * - FORMFIELDTYPE_RADIO
 *   Not implemented.
 * - FORMFIELDTYPE_HIDDEN
 *   Generates a hidden field.
 * - FORMFIELDTYPE_MULTILINGUAL_TEXTBOX
 *   Partially implemented.
 * - FORMFIELDTYPE_MULTILINGUAL_TEXTAREA
 *   Partially implemented.
 * - FORMFIELDTYPE_INLINE_CHECKBOX
 *   Generates an inline checkbox (ie, where the label will appear to the right of the checkbox rather than the left)
 * - FORMFIELDTYPE_DATE
 *   Generates a date selection field in the form of a group of dropdowns. The element name is appended with [day], [month], and [year].
 * - FORMFIELDTYPE_DATE_DAY_MONTH_YEAR
 *   Alias for FORMFIELDTYPE_DATE
 * - FORMFIELDTYPE_DATE_DAY_MONTHYEAR
 *   Generates a date selection field where the year and month are in the same dropdown. The data is submitted in the same format as a normal date dropdown.
 */

// Constants
var FORMFIELDTYPE_TEXTBOX = 'textbox';
var FORMFIELDTYPE_TEXTAREA = 'textarea';
var FORMFIELDTYPE_PASSWORD = 'password';
var FORMFIELDTYPE_DROPDOWN = 'dropdown';
var FORMFIELDTYPE_CHECKBOX = 'checkbox';
var FORMFIELDTYPE_RADIO = 'radio'; // NOT IMPLEMENTED
var FORMFIELDTYPE_MULTISELECT = 'multiselect'; // NOT IMPLEMENTED
var FORMFIELDTYPE_MULTISELECT_CHECKBOX_GROUP = 'multiselect_checkbox_group';
var FORMFIELDTYPE_MULTISELECT_CHECKBOX_LIST = 'multiselect_checkbox_list';
var FORMFIELDTYPE_MULTISELECT_CHECKBOX_GROUPS = 'multiselect_checkbox_groups';
var FORMFIELDTYPE_HIDDEN = 'hidden';
var FORMFIELDTYPE_MULTILINGUAL_TEXTBOX = 'multilingual_textbox'; // PARTIALLY IMPLEMENTED
var FORMFIELDTYPE_MULTILINGUAL_TEXTAREA = 'multilingual_textarea'; // PARTIALLY IMPLEMENTED
var FORMFIELDTYPE_INLINE_CHECKBOX = 'inline_checkbox';
var FORMFIELDTYPE_DATE = 'date_dropdowns';
var FORMFIELDTYPE_DATE_DAY_MONTH_YEAR = 'date_dropdowns';
var FORMFIELDTYPE_DATE_DAY_MONTHYEAR = 'date_dropdowns_day_monthyear';

var FormFieldArrayCounter = 0;

var FormField = Class.create({
	// Constructor
	initialize: function(properties) {
		// Initialize Members
		this.name = null;
		this.value = null;
		this.display = null;
		this.type = FORMFIELDTYPE_TEXTBOX;
		this.options = null;
		this.checked = false;
		this.classname = null;
		this.validationrule = null;
		
		if (properties !== undefined) {
			if (properties.name !== undefined) {
				this.setName(properties.name);
			}
			if (properties.value !== undefined) {
				this.setValue(properties.value);
			}
			if (properties.display !== undefined) {
				this.setDisplay(properties.display);
			}
			if (properties.type !== undefined) {
				this.setType(properties.type);
			}
			if (properties.options !== undefined) {
				this.setOptions(properties.options);
			}
			if (properties.checked !== undefined) {
				this.setChecked(properties.checked);
			}
			if (properties.classname !== undefined) {
				this.setClassName(properties.classname);
			}
			if (properties.validationrule !== undefined) {
				this.setValidationRule(properties.validationrule);
			}
			if (properties.rule !== undefined) {
				this.setValidationRule(properties.rule);
			}
			
			if (properties._name !== undefined) {
				this.setName(properties._name);
			}
			if (properties._value !== undefined) {
				this.setValue(properties._value);
			}
			if (properties._display !== undefined) {
				this.setDisplay(properties._display);
			}
			if (properties._type !== undefined) {
				this.setType(properties._type);
			}
			if (properties._options !== undefined) {
				this.setOptions(properties._options);
			}
			if (properties._checked !== undefined) {
				this.setChecked(properties._checked);
			}
			if (properties._classname !== undefined) {
				this.setClassName(properties._classname);
			}
			if (properties._validationrule !== undefined) {
				this.setValidationRule(properties._validationrule);
			}
			if (properties._rule !== undefined) {
				this.setValidationRule(properties._rule);
			}
		}
	},
	
	// Getters & Setters
	getName: function(options) {
		return FormFields.formatFieldName(this.name);
	},
	setName: function(value) {
		this.name = value;
	},
	getValue: function() {
		return this.value;
	},
	setValue: function(value) {
		this.value = value;
	},
	getDisplay: function() {
		return this.display;
	},
	setDisplay: function(value) {
		this.display = value;
	},
	getType: function() {
		return this.type;
	},
	setType: function(value) {
		this.type = value;
	},
	getOptions: function() {
		return this.options;
	},
	setOptions: function(value) {
		this.options = value;
	},
	getChecked: function() {
		return this.checked;
	},
	setChecked: function(value) {
		this.checked = value;
	},
	getClassName: function() {
		return this.classname;
	},
	setClassName: function(value) {
		this.classname = value;
	},
	getValidationRule: function() {
		return this.validationrule;
	},
	setValidationRule: function(value) {
		this.validationrule = value;
	},
	
	// Methods
	generateID: function(name) {
		if (name.indexOf('[]') != -1) {
			name = name.replace('[]', '[' + FormFieldArrayCounter + ']');
			FormFieldArrayCounter++;
		}
		return name.replace(/[\[\]]|__/g, '_').replace(/(__)/g, '_').replace(/\_$/, '');
	},
	validate: function(value) {
		var rule = this.getValidationRule();
		if (rule) {
			return rule.validate(value);
		}
		return true;
	},
	create: function(container, options) {
		container = $(container);
		
		if (options == undefined) {
			options = {};
		}
		if (options.showLabels == undefined) {
			options.showLabels = true;
		}
		if (options.addBR == undefined) {
			options.addBR = true;
		}
		
		var fieldname = this.getName(options);
		var was_conflict = false;
		do {
			var fieldid = this.generateID(fieldname);
			if ($(fieldid) || was_conflict) {
				fieldname = this.getName(options);
				was_conflict = true;
			}
		} while ($(fieldid));
		
		var label;
		if (options.showLabels) {
			if (this.getDisplay()) {
				label = createExtendedElement('label', {
					htmlFor: fieldid,
					innerHTML: this.getDisplay()
				});
			}
		}
		
		switch (this.getType()) {
			case FORMFIELDTYPE_HIDDEN:
				if (label) {
					label = null;
				}
				var field = createExtendedElement('input', {
					id: fieldid,
					type: 'hidden',
					name: fieldname,
					value: this.getValue(),
					parent: container
				});
				if (this.getValue()) {
					field.value = this.getValue();
				}
				break;
			case FORMFIELDTYPE_TEXTBOX:
			case FORMFIELDTYPE_PASSWORD:
				if (label) {
					container.appendChild(label);
				}
				var field_type = 'text';
				if (this.getType() == FORMFIELDTYPE_PASSWORD) {
					field_type = 'password';
				}
				var field = createExtendedElement('input', {
					id: fieldid,
					type: field_type,
					name: fieldname,
					parent: container
				});
				if (this.getValue()) {
					field.value = this.getValue();
				}
				if (options.addBR) {
					createExtendedElement('br', {
						parent: container
					});
				}
				break;
			case FORMFIELDTYPE_TEXTAREA:
				if (label) {
					container.appendChild(label);
				}
				var field = createExtendedElement('textarea', {
					id: fieldid,
					name: fieldname,
					parent: container
				});
				if (this.getValue()) {
					field.value = this.getValue();
				}
				if (options.addBR) {
					createExtendedElement('br', {
						parent: container
					});
				}
				break;
			case FORMFIELDTYPE_MULTILINGUAL_TEXTBOX:
			case FORMFIELDTYPE_MULTILINGUAL_TEXTAREA:
				if (label) {
					container.appendChild(label);
				}
				var fieldcontainer = createExtendedElement('div', {
					id: fieldid,
					parent: container
				});
				if (!this.getValue() || typeof(this.getValue()) == 'string') {
					this.createMultilingualField(fieldcontainer, fieldname, 'en', '', false, false, true, options);
				} else {
					iteration = 0;
					$H(this.getValue()).each((function(pair) {
						removelink = (iteration > 0) ? true : false;
						var validation = false;
						if (pair.key == 'en') {
							validation = true;
						}
						this.createMultilingualField(fieldcontainer, fieldname, pair.key, pair.value, removelink, false, validation, options);
						iteration++;
					}).bind(this));
				}
				var link_add = createExtendedElement('a', {
					href: '#',
					innerHTML: 'Want to add this in another language?',
					parent: container
				});
				Event.observe(link_add, 'click', (function(event) {
					Dialog.confirm('<div id="' + fieldid + '_addlanguage">Select a language<br /><br /></div>', {
						className: 'cityred',
						width: 300,
						height: 105,
						okLabel: 'Add',
						cancelLabel: 'Cancel',
						onBeforeShow: function(win) {
							var message = $(fieldid + '_addlanguage');
							var language_select = createExtendedElement('select', {
								id: fieldid + '_selectlanguage',
								parent: message
							});
							language_select.options[0] = new Option('English', 'en');
							language_select.options[1] = new Option('French', 'fr');
							language_select.options[2] = new Option('Spanish', 'es');
							language_select.options[3] = new Option('German', 'de');
						},
						onOk: (function(win) {
							var language_select = $(fieldid + '_selectlanguage');
							var language = language_select.options[language_select.selectedIndex].value;
							this.createMultilingualField(fieldcontainer, fieldname, language);
							return true;
						}).bind(this),
						onCancel: function(win) {
							return;
						}
					});
					Event.stop(event);
				}).bind(this));
				if (options.addBR) {
					createExtendedElement('br', {
						parent: container
					});
				}
				break;
			case FORMFIELDTYPE_MULTISELECT_CHECKBOX_LIST:
				var containerp = createExtendedElement('p', {
					className: 'checkboxList',
					parent: container
				});
				$H(this.getOptions()).each(function(pair) {
					var field = createExtendedElement('input', {
						id: fieldid + '_' + pair.key,
						type: 'checkbox',
						name: fieldname + '[' + pair.key + ']',
						value: 1,
						parent: containerp
					});
					if (typeof(this.getChecked()) == 'object') {
						var checkedOptions = this.getChecked();
						if (+checkedOptions[pair.key]) {
							field.checked = true;
						}
					}
					createExtendedElement('label', {
						htmlFor: fieldid + '_' + pair.key,
						innerHTML: pair.value,
						parent: containerp
					});
				}.bind(this));
				break;
			case FORMFIELDTYPE_MULTISELECT_CHECKBOX_GROUP:
				var containerdiv = createExtendedElement('div', {
					className: 'checkboxgroup',
					parent: container
				});
				if (this.getDisplay()) {
					var header = createExtendedElement('h4', {
						innerHTML: this.getDisplay(),
						parent: containerdiv
					});
				}
				var containerul = createExtendedElement('ul', {
					parent: containerdiv
				});
				$H(this.getOptions()).each(function(pair) {
					var containerli = createExtendedElement('li', {
						parent: containerul
					});
					createExtendedElement('label', {
						htmlFor: fieldid + '_' + pair.key,
						innerHTML: pair.value,
						parent: containerli
					});
					var field = createExtendedElement('input', {
						id: fieldid + '_' + pair.key,
						type: 'checkbox',
						name: fieldname + '[' + pair.key + ']',
						value: 1,
						parent: containerli
					});
					if (typeof(this.getChecked()) == 'object') {
						var checkedOptions = this.getChecked();
						if (+checkedOptions[pair.key]) {
							field.checked = true;
						}
					}
				}.bind(this));
				createExtendedElement('br', {
					className: 'clear',
					parent: container
				});
				break;
			case FORMFIELDTYPE_MULTISELECT_CHECKBOX_GROUPS:
				var containertable = createExtendedElement('table', {
					className: 'checkboxgroups',
					parent: container
				});
				var containertbody = createExtendedElement('tbody', {
					parent: containertable
				});
				var containertr = createExtendedElement('tr', {
					parent: containertbody
				});
				var containertd = createExtendedElement('td', {
					parent: containertr
				});
				$H(this.getOptions()).each(function(pair) {
					if (pair.value == 'seperator') {
						containertd = createExtendedElement('td', {
							parent: containertr
						});
						return;
					}
					formfield = new FormField({
						name: fieldname,
						value: this.getValue(),
						display: pair.key,
						type: FORMFIELDTYPE_MULTISELECT_CHECKBOX_GROUP,
						checked: this.getChecked(),
						options: pair.value
					});
					formfield.create(containertd, options);
				}.bind(this));
				break;
			case FORMFIELDTYPE_CHECKBOX:
				var containerp = createExtendedElement('p', {
					className: 'checkbox',
					parent: container
				});
				var field = createExtendedElement('input', {
					id: fieldid,
					className: 'checkbox',
					type: 'checkbox',
					name: fieldname,
					value: this.getValue(),
					checked: this.getChecked(),
					parent: containerp
				});
				if (label) {
					containerp.appendChild(label);
				}
				break;
			case FORMFIELDTYPE_INLINE_CHECKBOX:
				label = null;
				var containerp = createExtendedElement('p', {
					parent: container
				});
				var field = createExtendedElement('input', {
					id: fieldid,
					className: 'checkbox',
					type: 'checkbox',
					name: fieldname,
					value: this.getValue(),
					checked: this.getChecked(),
					parent: containerp
				});
				if (this.getDisplay()) {
					createExtendedElement('span', {
						innerHTML: this.getDisplay(),
						parent: containerp
					});
				}
				break;
			case FORMFIELDTYPE_RADIO:
				if (label) {
					container.appendChild(label);
				}
				$H(this.getOptions()).each(function(pair) {
					var field = createExtendedElement('input', {
						id: fieldid + '_' + pair.key,
						type: 'radio',
						name: fieldname,
						value: pair.key,
						parent: container
					});
					if (this.getValue() !== null) {
						if (pair.key == this.getValue()) {
							field.checked = true;
						}
					}
					createExtendedElement('span', {
						//htmlFor: fieldid + '_' + pair.key,
						innerHTML: pair.value,
						parent: container
					});
				}.bind(this));
				if (options.addBR) {
					createExtendedElement('br', {
						parent: container
					});
				}
				break;				
			case FORMFIELDTYPE_DROPDOWN:
				if (label) {
					container.appendChild(label);
				}
				var field = createExtendedElement('select', {
					id: fieldid,
					name: fieldname,
					parent: container
				});
				$H(this.getOptions()).each(function(pair) {
					field.options[field.options.length] = new Option(pair.value, pair.key);
					if (this.getValue() !== null) {
						if (pair.key == this.getValue()) {
							field.options[field.options.length - 1].selected = true;
						}
					}
				}.bind(this));
				if (options.addBR) {
					createExtendedElement('br', {
						parent: container
					});
				}
				break;
			case FORMFIELDTYPE_DATE:
				if (label) {
					container.appendChild(label);
				}
				var current_date = new Date();
				var selected_date;
				if (this.getValue() !== null) {
					selected_date = new Date(this.getValue() * 1000);
				}
				var field_day = createExtendedElement('select', {
					id: fieldid,
					parent: container
				});
				for (var day = 1; day <= 31; day++) {
					field_day.options[field_day.options.length] = new Option(day, day);
					if (selected_date) {
						if (day == selected_date.getDate()) {
							field_day.options[field_day.options.length - 1].selected = true;
						}
					} else if (day == current_date.getDate()) {
						field_day.options[field_day.options.length - 1].selected = true;
					}
				}
				var field_month = createExtendedElement('select', {
					parent: container
				});
				for (var month = 0; month <= 11; month++) {
					field_month.options[field_month.options.length] = new Option(readableMonths[month], month + 1);
					if (selected_date) {
						if (month == selected_date.getMonth()) {
							field_month.options[field_month.options.length - 1].selected = true;
						}
					} else if (month == current_date.getMonth()) {
						field_month.options[field_month.options.length - 1].selected = true;
					}
				}
				var field_year = createExtendedElement('select', {
					parent: container
				});
				for (var year = current_date.getFullYear() - 1; year <= current_date.getFullYear() + 1; year++) {
					field_year.options[field_year.options.length] = new Option(year, year);
					if (selected_date) {
						if (year == selected_date.getFullYear()) {
							field_year.options[field_year.options.length - 1].selected = true;
						}
					} else if (year == current_date.getFullYear()) {
						field_year.options[field_year.options.length - 1].selected = true;
					}
				}
				var field = createExtendedElement('input', {
					type: 'hidden',
					name: fieldname,
					parent: container
				});
				if (selected_date) {
					field.value = (selected_date.getTime() / 1000).floor();
				} else {
					field.value = (current_date.getTime() / 1000).floor();
				}
				Event.observe(field_day, 'change', function(event) {
					var selected_date = new Date();
					selected_date.setDate($F(field_day));
					selected_date.setMonth($F(field_month));
					selected_date.setFullYear($F(field_year));
					field.value = (selected_date.getTime() / 1000).floor();
				});
				Event.observe(field_month, 'change', function(event) {
					var selected_date = new Date();
					selected_date.setDate($F(field_day));
					selected_date.setMonth($F(field_month));
					selected_date.setFullYear($F(field_year));
					field.value = (selected_date.getTime() / 1000).floor();
				});
				Event.observe(field_year, 'change', function(event) {
					var selected_date = new Date();
					selected_date.setDate($F(field_day));
					selected_date.setMonth($F(field_month));
					selected_date.setFullYear($F(field_year));
					field.value = (selected_date.getTime() / 1000).floor();
				});
				if (options.addBR) {
					createExtendedElement('br', {
						parent: container
					});
				}
				break;
			case FORMFIELDTYPE_DATE_DAY_MONTHYEAR:
				if (label) {
					container.appendChild(label);
				}
				var field_options = Object.extend({
					from: 'last year',
					to: 'next year',
					empty: false
				}, this.getOptions());
				
				var current_date = new Date();
				var selected_date = false;
				if (this.getValue() !== null) {
					selected_date = new Date(this.getValue() * 1000);
				}
				var field_day = createExtendedElement('select', {
					id: fieldid,
					className: 'date_d_my_day',
					parent: container
				});
				if (field_options.empty) {
					field_day.options[field_day.options.length] = new Option('--', '');
				}
				for (var day = 1; day <= 31; day++) {
					field_day.options[field_day.options.length] = new Option(day, day);
					if (selected_date) {
						if (day == selected_date.getDate()) {
							field_day.options[field_day.options.length - 1].selected = true;
						}
					} else if (day == current_date.getDate()) {
						if (!field_options.empty) {
							field_day.options[field_day.options.length - 1].selected = true;
						}
					}
				}
				var field_monthyear = createExtendedElement('select', {
					id: fieldid + '_monthyear',
					className: 'date_d_my_monthyear',
					parent: container
				});
				
				var display_date = new Date();
				switch (field_options.from) {
					case 'today':
						break;
					case 'last year':
					default:
						display_date.setDate(1);
						display_date.setFullYear(display_date.getFullYear() - 1);
				}
				var display_end_date = new Date();
				switch (field_options.to) {
					case 'next year':
					default:
						display_end_date.setDate(1);
						display_end_date.setFullYear(display_end_date.getFullYear() + 1);
				}
				if (field_options.empty) {
					field_monthyear.options[field_monthyear.options.length] = new Option('--', '');
				}
				
				while (display_date <= display_end_date) { //for (var months_ahead = 0; months_ahead <= 24; months_ahead++) {
					field_monthyear.options[field_monthyear.options.length] = new Option(readableMonths[display_date.getMonth()] + ' ' + display_date.getFullYear(), display_date.getMonth() + 1 + ',' + display_date.getFullYear());
					if (selected_date) {
						if (display_date.getMonth() == selected_date.getMonth() && display_date.getFullYear() == selected_date.getFullYear()) {
							field_monthyear.options[field_monthyear.options.length - 1].selected = true;
						}
					} else if (display_date.getMonth() == current_date.getMonth() && display_date.getFullYear() == current_date.getFullYear()) {
						if (!field_options.empty) {
							field_monthyear.options[field_monthyear.options.length - 1].selected = true;
						}
					}
					display_date.setMonth(display_date.getMonth() + 1);
				}
				
				var field = createExtendedElement('input', {
					type: 'hidden',
					name: fieldname,
					parent: container
				});
				if (selected_date) {
					field.value = (selected_date.getTime() / 1000).floor();
				} else if (field_options.empty) {
					field.value = '';
				} else {
					field.value = (current_date.getTime() / 1000).floor();
				}
				Event.observe(field_day, 'change', function(event) {
					if ($F(field_day) != '' && $F(field_monthyear) == '') {
						$(field_monthyear).selectedIndex = 1;
					} else if ($F(field_day) == '' && $F(field_monthyear) != '') {
						$(field_monthyear).selectedIndex = 0;
					}
					if ($F(field_monthyear) != '' && $F(field_day) != '') {
						var selected_date = new Date();
						selected_date.setDate($F(field_day));
						var monthyear = $F(field_monthyear).split(',');
						selected_date.setMonth(monthyear[0] - 1);
						selected_date.setFullYear(monthyear[1]);
						field.value = (selected_date.getTime() / 1000).floor();
					} else {
						field.value = '';
					}
				});
				Event.observe(field_monthyear, 'change', function(event) {
					if ($F(field_day) != '' && $F(field_monthyear) == '') {
						$(field_day).selectedIndex = 0;
					} else if ($F(field_day) == '' && $F(field_monthyear) != '') {
						$(field_day).selectedIndex = 1;
					}
					if ($F(field_monthyear) != '' && $F(field_day) != '') {
						var selected_date = new Date();
						selected_date.setDate($F(field_day));
						var monthyear = $F(field_monthyear).split(',');
						selected_date.setMonth(monthyear[0] - 1);
						selected_date.setFullYear(monthyear[1]);
						field.value = (selected_date.getTime() / 1000).floor();
					} else {
						field.value = '';
					}
				});
				if (options.addBR) {
					createExtendedElement('br', {
						parent: container
					});
				}
				break;
			default:
				// Clean Up
				label = null;
		}
		
		if (field) {
			if (options.fieldOptions != undefined) {
				if (options.fieldOptions.events != undefined) {
					for (var i = 0; i < options.fieldOptions.events; i++) {
						if (options.fieldOptions.events[i].fieldname == this.name) {
							$(field).observe(options.fieldOptions.events[i].event, options.fieldOptions.events[i].callback.bindAsEventListener(field));
						}
					}
				}
			}
		}
		
		// Where possible, have fields reflect the ValidationRule
		this.addValidationToField(field);
		
		// Add class to field
		if (this.getClassName()) {
			if (field != undefined) {
				$(field).addClassName(this.getClassName());
			}
		}
	},
	addValidationToField: function(field) {
		if (field == undefined) {
			return;
		}
		
		if (this.getValidationRule()) {
			var rule = this.getValidationRule();
			if (rule.getEmpty() === false) {
				// Add 'Required' class to fields which cannot be empty
				field.className = field.className + ' required';
			}
			if (rule.getLessThan() != null && rule.getType() == 'string') {
				if (
					this.getType() == FORMFIELDTYPE_TEXTBOX ||
					this.getType() == FORMFIELDTYPE_MULTILINGUAL_TEXTBOX ||
					this.getType() == FORMFIELDTYPE_PASSWORD
					) {
					field.maxLength = rule.getLessThan() - 1;
				}
			}
			if (rule.getType() == 'number') {
				Event.observe(field, 'keypress', function(event) {
					var charCode = (event.which) ? event.which : event.keyCode;
					if (charCode == 46) {
						if (field.value.indexOf('.') != -1) {
							event.stop();
						}
					} else if (charCode > 31 && (charCode < 48 || charCode > 57)) {
						event.stop();
					}
				});
			}
			
			field.validate = function() {
				if (!rule.validate($F(field))) {
					$(field).addClassName('error');
					return false;
				} else {
					$(field).removeClassName('error');
					return true;
				}
			};
		}
	},
	createMultilingualField: function(container, fieldname, language, value, removelink, fadein, validation, options) {
		if (value == undefined) {
			value = '';
		}
		if (removelink == undefined) {
			removelink = true;
		}
		if (fadein == undefined) {
			fadein = true;
		}
		if (validation == undefined) {
			validation = false;
		}
		
		langfieldid = this.generateID(fieldname + '[' + language + ']');
		
		if ($(langfieldid + '_container')) {
			// If field already exists but has been hidden, place it at the bottom of the container and display it
			field_lang = $(langfieldid + '_container');
			if (!field_lang.visible()) {
				container.removeChild(field_lang);
				container.appendChild(field_lang);
				if (fadein) {
					field_lang.appear();
				} else {
					field_lang.show();
				}
			}
			return;
		}
		
		var field_lang = createExtendedElement('div', {
			id: langfieldid + '_container',
			className: 'multilingual_input_container',
			hidden: true,
			parent: container
		});
		if (this.getType() == FORMFIELDTYPE_MULTILINGUAL_TEXTAREA) {
			var field = createExtendedElement('textarea', {
				id: langfieldid,
				name: fieldname + '[' + language + ']',
				value: value,
				className: language,
				parent: field_lang
			});
		} else if (this.getType() == FORMFIELDTYPE_MULTILINGUAL_TEXTBOX) {
			var field = createExtendedElement('input', {
				id: langfieldid,
				type: 'text',
				name: fieldname + '[' + language + ']',
				value: value,
				className: language,
				parent: field_lang
			});
		}
		if (removelink) {
			var link_remove = createExtendedElement('a', {
				id: langfieldid + '_link',
				href: '#',
				title: 'Remove translation',
				hidden: true,
				className: 'multilingual_removelink',
				parent: field_lang
			});
			createExtendedElement('img', {
				src: 'images/remove.png',
				border: 0,
				alt: 'Remove translation',
				parent: link_remove
			});
			Event.observe(link_remove, 'click', function(event) {
				field.value = '';
				field_lang.fade();
				Event.stop(event);
			});
			Event.observe(field_lang, 'mouseover', function(event) {
				link_remove.show();
			});
			Event.observe(field_lang, 'mouseout', function(event) {
				link_remove.hide();
			});
		}
		
		if (field) {
			if (options.fieldOptions != undefined) {
				if (options.fieldOptions.events != undefined) {
					for (var i = 0; i < options.fieldOptions.events.length; i++) {
						if (options.fieldOptions.events[i].fieldname == this.name + '[' + language + ']') {
							$(field).observe(options.fieldOptions.events[i].event, options.fieldOptions.events[i].callback.bindAsEventListener(field));
						}
					}
				}
			}
		}
		
		if (validation) {
			// Where possible, have fields reflect the ValidationRule
			this.addValidationToField(field);
		}
		
		if (fadein) {
			field_lang.appear();
		} else {
			field_lang.show();
		}
	}
});

// Static Methods
FormField.generateID = function(name) {
	return name.replace(/[\[\]]|__/g, '_').replace(/(__)/g, '_').replace(/\_$/, '');
}