
/*

	Class:  JavaScript
	File:  _class.javascript.js
	Version: 1.2.2
	Purpose: Contains all basic javascript functions
	Author:  Matthew Lindley
	
	Notes:
	
	
	# Version 1.2.2 (22/03/2006)
	
	- Added open_window method
	
	
	# Version 1.2.1 (28/02/2006)
	
	- Added "pnumber" (positive number) validation type
	
	
	# Version 1.2
	
	- Added methods
		> get_month_days()
		> get_months()
		> this_year()
		> year_is_leap_year()
	
	
	# Version 1.1.0
	
	- Added format_form_field method
	- Added validate_form_field method
	
	
	# Version 1.0.0
	
	- First Version

*/

function JavaScript() {
	
	this.months = new Array();
		this.months[this.months.length] = new Array(1, "January", 31);
		this.months[this.months.length] = new Array(2, "February", 28);
		this.months[this.months.length] = new Array(3, "March", 31);
		this.months[this.months.length] = new Array(4, "April", 30);
		this.months[this.months.length] = new Array(5, "May", 31);
		this.months[this.months.length] = new Array(6, "June", 30);
		this.months[this.months.length] = new Array(7, "July", 31);
		this.months[this.months.length] = new Array(8, "August", 31);
		this.months[this.months.length] = new Array(9, "September", 30);
		this.months[this.months.length] = new Array(10, "October", 31);
		this.months[this.months.length] = new Array(11, "November", 30);
		this.months[this.months.length] = new Array(12, "December", 31);
		
}



JavaScript.prototype.add_select_option = function (field, option_value, option_text) {
	field.options[field.options.length] = new Option(option_text, option_value);
}



JavaScript.prototype.currency = function (number) {
	
	number = number.toString();
	
	switch (number.indexOf(".")) {
		
		case -1:
			number += ".00";
		break;
		
		case number.length-2:
			number += "0";
		break;
	
	}
	
	return number;
	
}




JavaScript.prototype.empty_select = function (field) {

	while(field.length > 0) {
		field.options[0] = null;
	}

}



JavaScript.prototype.fill_select = function (field, data, selected_value) {
	/*
		Example data: (value, text)
			data[0] = new Array(1, "Apple");
			data[1] = new Array(2, "Banana");
	*/
	
	var do_selected = (selected_value == null) ? false : true;
	var index = 0;
	
	for (var i = 0; i < data.length; i++) {
		
		this.add_select_option(field, data[i][0], data[i][1]);
		
		if ((do_selected) && (data[i][0] == selected_value)) {
			index = (field.options.length-1);
		}
		
	}
	
	if (do_selected) {
		field.selectedIndex = index;
	}
	
}




JavaScript.prototype.find_field = function (form, field_name) {
	
	for (var i = 0; i < form.length; i++) {
		
		if (form[i].name != field_name) {
			continue;
		} else {
			return form[i];
		}
		
	}
	
}



JavaScript.prototype.format_form_field = function (e, format_type) {
	
	var regexp;

	switch (format_type.toLowerCase()) {
		
		case "currency":
			regexp = /[^0-9\-\.]/g;
			e.value = e.value.replace(regexp, "");
		break;
		
		case "email":
		case "e-mail":
			e.value = e.value.toLowerCase();
			
			regexp = /[^a-z0-9\-_\.@]/g;
			e.value = e.value.replace(regexp, "");
		break;
		
		case "pnumber":
		case "number":
			regexp = /[^0-9]/g;
			e.value = e.value.replace(regexp, "");
		break;
		
		case "numeric":
			regexp = /[^0-9\.\-]/g;
			e.value = e.value.replace(regexp, "");
		break;
		
	
		case "telephone":
		case "telephonenomobile":
			regexp = /[^0-9]/gi;
		break;
		
		case "postcode":
			regexp = /[^a-z0-9]/gi;
			e.value = e.value.replace(regexp, "");
			e.value = e.value.substr(0, (e.value.length -3)).toUpperCase() + " " + e.value.substr((e.value.length -3), 3).toUpperCase();
		break;
		
	}
	
}


JavaScript.prototype.get_month_days = function (month, year) {
	
	var days = new Array();
	
	//  If month is null assume current month and get month
	if ((month == null) || (isNaN(month))) {
		var date = new Date();
		var month = (date.getMonth()+1);  //  Add one to make it easier to work out
	}
	
	//  If year is null assume current year and get year
	if ((year == null) || (isNaN(year)) || (year.toString().length != 4)) {
		year = this.this_year();
	}

	//  Number of days in the specified month
	var num_days = this.months[(month-1)][2];

	//  If it's a leap year, we need to do an extra day so increment it

	if (month == 2) {
		num_days = (this.year_is_leap_year(year)) ? 29 : 28;
	}

	for (var i = 1; i <= num_days; i++) {
		
		days[days.length] = new Array(i, i);
	
	}
	
	return days;
	
}


JavaScript.prototype.get_months = function (year) {
	
	var m;
	var months = this.months;
			
	//  If year is null assume current year and get year
	if ((year == null) || (isNaN(year)) || ((year.toString()).length != 4)) {
		this.this_year();
	}
	
	if (this.year_is_leap_year(year)) {
		months[1][2] = 29;
	} else {
		months[1][2] = 28;
	}
	
	return months;
	
}



JavaScript.prototype.in_array = function (needle, haystack) {
	
	var found = false;
	
	for (var i = 0; i < haystack.length; i++) {
		if (haystack[i] != needle) {
			continue;
		} else {
			found = true;
			break;
		}
	}
	
	return found;
	
}




JavaScript.prototype.open_window = function (url, width, height, popup_name) {
	
	var win;
	var default_height = 400;
	var default_width = 500;
	
	if (url == null) {
		alert("open_window() could not complete its task because no URL has been specified.");
		return false;
	}
	
	if (width == null) {
		width = default_width;
	}
	
	if (height == null) {
		height = default_height;
	}
	
	if (popup_name == null) {
		popup_name = "my_popup";
	}
	
	properties = "width=" + width + ",height=" + height + ",scrollbars=yes,location=no,history=no,status=no,top=0,left=0";
	
	win = window.open(url, popup_name, properties);
	
	win.focus();
	
}




JavaScript.prototype.select_options_number_range = function (num_start, num_end) {
	
	var array = new Array();
	
	if ((num_start == null) || (isNaN(num_start))) {
		return false;
	}
	
	if ((num_end == null) || (isNaN(num_end))) {
		return false;
	}
	
	if (num_end > num_start) {
		for (var i = num_start; i <= num_end; i++) {
			array[array.length] = new Array(i, i);
		}
	} else {
		for (var i = num_start; i >= num_end; i--) {
			array[array.length] = new Array(i, i);
		}
	}
	
	return array;
	
}




JavaScript.prototype.this_year = function () {
	
	var date = new Date();
	var year = date.getFullYear();
	
	return year;
	
}




JavaScript.prototype.validate_form = function (form) {
	
	var c, e, x;
	var target;
	
	var error_count = 0;
	var error_msg = "Please correct the following errors:";
	
	var radio_log = new Array();
	var radio_group;
	var radio_selected = false;
	
	
	function log_error (field_name, error) {
		error_count++;
		error_msg += "\n -> " + field_name + ": " + error;
	}
	
	for (var i = 0; i < form.length; i++) {
		
		e = form[i];
		
		if (e.id.length == 0) {
			
			continue;
			
		} else {

			c = e.id.split("|");
			
			if (c.length == 1) {
				continue;
			}
			
			/*
			[0] = Mandatory
			[1] = Field name
			[2] = Validation type
			[3] = Extra vars (depending on validation type)
			*/
			
			c[0] = parseInt(c[0]);
			//alert(e.type);
			switch (e.type) {
				
				case "password":
				
					if ((c[3]) && (c[3].length > 0)) {
						
						if (target = eval("form." + c[3])) {
							if (e.value != target.value) {
								log_error(c[1], "does not match");
								continue;
							}
						}
						
					}
				
				//  No "break;" to keep fall-through
				
				case "hidden":
				case "text":
				case "textarea":
					if (c[0] && e.value == "") {
						log_error(c[1], "not entered");
						
					} else if (c[2] && c[2].length > 0) {
						
						this.format_form_field(e, c[2]);
						
						if (!this.validate_form_field(e, c[2], c[3])) {
							
							log_error(c[1], "not valid");
							continue;

						}
						
						
					}
				break;
                
                // Added 9.09.2007 - Boris Rogachov
                case "file":
                    if (c[0] && e.value == "") {
                        log_error(c[1], "not entered");
                    }
                break;
				
				
				case "select":
				case "select-one":
					if (c[0] && e.options[e.selectedIndex].value == "") {
						log_error(c[1], "not selected");
						continue;
					}
				break;
				
				
				case "checkbox":
					if (c[0] && !e.checked) {
						log_error(c[1], "not ticked");
						continue;
					}
				break;
				
				
				case "radio":
					if (c[0] && !this.in_array(e.name, radio_log)) {

						radio_log[radio_log.length] = e.name;
						radio_group = eval("form." + e.name);
						radio_selected = false;
						
						radio_length = radio_group.length;
						
						//  Treat as checkbox if only one button
						if (radio_length == null) {
							
							radio_selected = e.checked;
							
						} else {
						
							for (x = 0; x < radio_length; x++) {
								if (radio_group[x].checked) {
									radio_selected = true;
									break;
								}
							}
						
						}

						if (!radio_selected) {
							log_error(c[1], "not selected");
							continue;
						}
						
					}
				break;
				
				
				default:
					continue;
				
			}
			
		}
		
	}
	
	
	if (error_count > 0) {
		
		alert(error_msg);
		return false;

	} else {
		
		//return false;  //  For testing purposes
		return true;
		
	}
	
}


JavaScript.prototype.validate_form_field = function (e, format_type, ex) {
	
	var regexp;
	var is_valid = true;
	
	if ((ex != null) && (ex.length > 0) && (ex.indexOf("#") > -1)) {
		
		ex = ex.split("#");
		
	}
	
	
	switch (format_type.toLowerCase()) {
		
		case "currency":
			regexp = /^(0|-?[1-9]+[0-9]*)\.[0-9]{2}/;
			return (regexp.test(e.value));
		break;
		
		case "decimal":
			regexp = /^(0|-?[1-9]+[0-9]*)\.[0-9]*$/;
			return (regexp.test(e.value));
		break;
		
		case "url":
			
			regexp = /^(http:\/\/)?([a-zA-Z0-9_\-\.]+\.)?[a-zA-Z0-9_\-\.]+\.[a-zA-Z]{1,4}(:(\d+))?(.+)$/i;
			return (regexp.test(e.value));
			break;
		
		case "email":
		case "e-mail":
			regexp = /^\w(\.?\w(-)?)*@\w(\.?[-\w])*\.([a-z]{3}(\.[a-z]{2})?|[a-z]{2}(\.[a-z]{2})?)$/i;

			if (!regexp.test(e.value)) {
				
				return false;
				
			} else {
				
				/*if (ex[0] && ex[0].length > 0) {
					
					
					
				}*/
				
			}
			
		break;
		
		case "number":
			regexp = /[^0-9]/gi;
			return (!regexp.test(e.value));
		break;
		
		case "numeric":
			regexp = /^\-?(0|[1-9]+[0-9]*)\.?(0|[1-9]+[0-9]*)?$/;
			return (regexp.test(e.value));
		break;
		
		case "password":
			return (e.value.length > 5);
		break;
		
		case "pnumber":		//  Positive number
			regexp = /^[1-9][0-9]*$/;
			return (regexp.test(e.value));
		break;
		
		case "postcode":
			regexp = /^[A-Z]{1,2}\d{1,2}[A-Z]? \d[A-Z]{2}$/i;
			return (regexp.test(e.value));
		break;
		
		case "telephone":
			//  regexp = /^0((1\d{8,9})|(207\d{7})|(208\d{7})|(7\d{9,10})|(23\d{8})|(24\d{8})|(28\d{8})|(29\d{8})|(8\d{8,9}))$/;  //  Strict regexp
			regexp = /^0([1278])([0-9 ]){9,14}$/;
			return (regexp.test(e.value));
		break;
		
		case "telephonenomobile":
			regexp = /^0((1\d{8,9})|(207\d{7})|(208\d{7})|(23\d{8})|(24\d{8})|(28\d{8})|(29\d{8})|(87\d{7,8}))$/;
			return (regexp.test(e.value));
		break;
		
	}
	
	return true;
	
}



JavaScript.prototype.year_is_leap_year = function (year) {

	//  If no year, or year not valid, assume full year.
	if ((year == null) || (isNaN(year)) || ((year.toString()).length != 4)) {
		var date = new Date();
		year = date.getFullYear();
	}

	//  Mod year by 4, no remainder means year is leap year.
	return ((parseInt(year) % 4) == 0) ? true : false;
	
}



var JS = new JavaScript();
