﻿// Javascript File
// version 1.1
//	uses Byrom namespace

var x; if (x != x) { Byrom = {}; } //HACK:	for intellisense


//HACK:	This script does not require MS javascript to run - BUT - Ajax WCF services create the namespace of any complex object(s) in their interface.
//				Those creates will fail if this module creates it's own (none MS) namespace (Byrom) first 
//				solution if required is to include this within the form definition rather than the header (MS ajax (hence Type.registerNamespace) will be loaded by then)
Byrom_registerNamespace = function(name)
{
	var Type;
	if (Type && Type.registerNamespace)	//	try ms 1st
	{
		Type.registerNamespace(name);
	}
	else
	{
		var ns = window;
		var names = name.split('.');
		for (var index = 0; index < names.length; index++)
		{
			var nsPart = names[index]
			if (nsPart)
			{
				if (!ns[nsPart])
					ns[nsPart] = {};
				ns = ns[nsPart];
			}
		}
	}
};

Byrom_registerNamespace('Byrom');

Byrom.registerNamespace = function(name)
{
	Byrom_registerNamespace(name);
};

Byrom.startDate = new Date();
Byrom.versionNumber = '1.1';
Byrom.versionInfo = {};
Byrom.versionInfo.Byrom = Byrom.versionNumber;

Byrom.toggleStateExpanded = 'expanded';
Byrom.toggleStateCollapsed = 'collapsed';

Byrom.setVersionInfo = function(key, value)
{
	Byrom.versionInfo[key] = value;
};
Byrom.getVersionInfo = function(key, delim)
{
	if (!delim)
		delim = '\n';
	if (key)
		return Byrom.versionInfo[key];
	else
	{
		var result = '';
		for (var index in Byrom.versionInfo)
		{
			result += ((result == '') ? '' : delim) + index.toString() + ' : ' + Byrom.versionInfo[index];
		}
		var runtimeMs = (new Date()) - Byrom.startDate;
		var numDays = Math.floor(runtimeMs / 86400000);
		var days = (numDays > 0) ? numDays.toString() + ' day' + ((numDays == 1) ? ' ' : 's ') + ' ' : '';
		result += ((result == '') ? '' : delim) + 'Runtime' + ' : ' + days + (new Date(0, 0, 0, 0, 0, 0, runtimeMs)).toLocaleTimeString();
		return result;
	}
};
Byrom.chooseOption = function(id, value)
{
	return Byrom.chooseOptionBy(id, value, false);
};
Byrom.chooseOptionByText = function(id, value)
{
	return Byrom.chooseOptionBy(id, value, true);
};

Byrom.chooseOptionBy = function(id, value, byText)	//	default by value
{
	var listBox = document.getElementById(id);
	if (listBox && listBox.options)
	{
		var testValue = null;
		if (listBox.selectedIndex > 0)	//	may be set already
		{
			testValue = byText ? listBox.options[listBox.selectedIndex].text : listBox.options[listBox.selectedIndex].value;
			if (testValue == value)
				return true;
		}
		for (var index = 0; index < listBox.options.length; index++)
		{
			testValue = byText ? listBox.options[index].text : listBox.options[index].value;
			if (testValue == value)
			{
				listBox.selectedIndex = index;
				return true;
			}
		}
	}
	return false;
};


Byrom._disabledElements = {}; //	cache
Byrom.disableAll = function(id, setOpacity, reCheck)
{
	if (!reCheck && Byrom._disabledElements[id])
	{
		Byrom.enableAll(id, setOpacity, true);
	}
	else
	{
		var el = null;
		if (typeof id == 'object')
			el = id;
		else
			var el = document.getElementById(id)
		var altered = new Array();
		if (el)
		{
			//var els = el.all;
			var els = el.getElementsByTagName("*");
			for (var index = 0; index < els.length; index++)
			{
				var elem = els[index];
				if (elem.tagName && elem.id)
				{
					var tagName = elem.tagName.toLowerCase();
					if ((tagName == 'input' || tagName == 'select') && !elem.readOnly && !elem.disabled)
					{
						altered.push(elem.id);
						elem.setAttribute('disabled', true);
					}
				}
			}
		}
		Byrom._disabledElements[id] = altered;
	}
};

Byrom.enableAll = function(id, setOpacity, disabled)
{
	if (id && Byrom._disabledElements[id] && Byrom._disabledElements[id].length)
	{
		var altered = Byrom._disabledElements[id];
		for (var index = 0; index < altered.length; index++)
		{
			var el = document.getElementById(altered[index]);
			if (el)
			{
				if (disabled)
					el.setAttribute('disabled', true);
				else
					el.removeAttribute('disabled');
			}
		}
	}
};

Byrom.setCheckBoxesToggle = function(id, toggleByFirst, ignoreDisabled)
{
	if (arguments.length < 2)
		toggleByFirst = false;
	if (arguments.length < 3)
		ignoreDisabled = true;

	var elem = document.getElementById(id);
	if (elem)
		Byrom.setCheckBoxesToggleByElem(elem, toggleByFirst, ignoreDisabled);
};

Byrom.setCheckBoxesToggleByElem = function(elem, toggleByFirst, ignoreDisabled)
{
	if (arguments.length < 2)
		toggleByFirst = false;
	if (arguments.length < 3)
		ignoreDisabled = true;
	var c = new Array();
	c = elem.getElementsByTagName('input');
	if (toggleByFirst)
	{
		var checked = null;
		for (var i = 0; i < c.length; i++)
		{
			if (c[i].type == 'checkbox')
			{
				if (!ignoreDisabled || (c[i].disabled != true && c[i].disabled != 'disabled'))
				{
					if (checked == null)
						checked = !c[i].checked;
					Byrom.setCheckBoxByElem(c[i], checked);
				}
			}
		}
	}
	else
	{
		for (var i = 0; i < c.length; i++)
		{
			if (c[i].type == 'checkbox' && (!ignoreDisabled || (c[i].disabled != true && c[i].disabled != 'disabled')))
			{
				Byrom.setCheckBoxToggleByElem(c[i]);
			}
		}
	}
};

Byrom.setCheckBoxToggle = function(id)
{
	var elem = document.getElementById(id);
	if (elem)
		Byrom.setCheckBoxByElem(elem, toggleByFirst);
};

Byrom.setCheckBoxToggleByElem = function(elem)
{
	if (elem.type == 'checkbox')
	{
		if (elem.checked)
			elem.checked = false;
		else
			elem.checked = true;
	}
};


Byrom.setCheckBoxToggle = function(id, checked)
{
	if (arguments.length < 2)
		checked = true;
	var elem = document.getElementById(id);
	if (elem)
		Byrom.setCheckBoxByElem(elem, checked);
};


Byrom.setCheckBoxes = function(id, checked)
{
	if (arguments.length < 2)
		checked = true;
	var elem = document.getElementById(id);
	if (elem)
		Byrom.setCheckBoxesByElem(elem, checked);
};

Byrom.setCheckBoxesByElem = function(elem, checked)
{
	if (arguments.length < 2)
		checked = true;
	var c = new Array();
	c = elem.getElementsByTagName('input');
	for (var i = 0; i < c.length; i++)
	{
		Byrom.setCheckBoxByElem(c[i], checked);
	}
};

Byrom.setCheckBox = function(id, checked)
{
	if (arguments.length < 2)
		checked = true;
	var elem = document.getElementById(id);
	if (elem)
		Byrom.setCheckBoxByElem(elem, checked);
};

Byrom.setCheckBoxByElem = function(elem, checked)
{
	if (arguments.length < 2)
		checked = true;
	if (elem.type == 'checkbox')
	{
		elem.checked = checked;
	}
};

Byrom.setDisabled = function(id, disable)
{
	var disabled = 'disabled';
	if (arguments.length == 2 && !disable)
		disabled = '';

	var elem = id;
	if (typeof id != 'object')
		elem = document.getElementById(id);

	if (elem)
	{
		elem.disabled = disabled;
		if (elem.style)
		{
			if (disable)
			{
				elem.style.color = '#ACA899';
				elem.style.backgroundColor = '#EBEBE4';
			}
			else
			{
				//elem.style.color='Black'
				elem.style.color = ''
				elem.style.backgroundColor = ''; ;
			}
		}
	}
};

Byrom.unSetDisabled = function(id)
{
	var elem = document.getElementById(id);
	if (elem)
	{
		elem.disabled = '';
	}
};

Byrom.disable = function(id, disable)
{
	if (arguments.length < 2)
		disable = true;
	Byrom.setDisabled(id, disable)
};

Byrom.createDictionary = function(arrayName, keyName)
{
	var returnValue = new Object();
	var ex = 'for (var i = 0; i< ' + arrayName + '.length; i++)\r\n';
	ex += '{\r\n	returnValue[' + arrayName + '[i]' + ((keyName) ? '.' + keyName : '') + '] = ' + arrayName + '[i];\r\n}\r\n';
	eval(ex);
	return returnValue;
};
Byrom.getWcfDate = function(dt)
{
	//	when server deserializes, gmt offset is unhelpfully applied so offset the offset
	dt.setMinutes(dt.getMinutes() - dt.getTimezoneOffset());
	dt = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate(), dt.getHours(), dt.getMinutes(), dt.getSeconds());
	return dt;
};

Byrom.language = '';

Byrom.setLanguage = function(language)
{
	Byrom.language = language;
	Byrom.checkLocalize();
};

Byrom.languageLocal = function()
{
	return (navigator.language) ? navigator.language : navigator.userLanguage;
};

// Dates	
// Field		| Full Form			| Short Form
// -------------+-------------------+-----------------------
// Year			| yyyy (4 digits)	| yy (2 digits), y (2 or 4 digits)
// Month		| MMM (name or abbr)| MM (2 digits), M (1 or 2 digits)
//				| NNN (abbr)		|
// Day of Month | dd (2 digits)		| d (1 or 2 digits)
// Day of Week  | EE (name)			| E (abbr)
// Hour (1-12)  | hh (2 digits)		| h (1 or 2 digits)
// Hour (0-23)  | HH (2 digits)		| H (1 or 2 digits)
// Hour (0-11)  | KK (2 digits)		| K (1 or 2 digits)
// Hour (1-24)  | kk (2 digits)		| k (1 or 2 digits)
// Minute		| mm (2 digits)		| m (1 or 2 digits)
// Second		| ss (2 digits)		| s (1 or 2 digits)
// AM/PM		| a					|
//
// Examples:
//  "MMM d, y" matches: January 01, 2000
//					  Dec 1, 1900
//					  Nov 20, 00
//  "M/d/yy"   matches: 01/20/00
//						9/2/00
//  "MMM dd, yyyy hh:mm:ssa" matches: "January 01, 2000 12:30:45AM"
// ------------------------------------------------------------------

//TODO:	add localization

Byrom.localize = function()
{
	if (!Byrom.language)
		Byrom.language = ((navigator.language) ? navigator.language : navigator.userLanguage).substring(0, 2);

	Byrom.MONTH_NAMES_EN = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
	Byrom.MONTH_NAMES = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
	Byrom.DAY_NAMES_EN = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
	Byrom.DAY_NAMES = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
	Byrom.DATE_FORMAT = 'dd MMM yyyy';
	Byrom.TIME_FORMAT = 'hh:kk:ss';
	Byrom.TIME_HM_FORMAT = 'hh:kk';
	Byrom.LOCALIZE_LANGUAGE = Byrom.language;
	switch (Byrom.language)
	{
		case 'de':
			Byrom.MONTH_NAMES = new Array('Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember', 'Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez');
			Byrom.DAY_NAMES = new Array('Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Son', 'Mon', 'Die', 'Mit', 'Don', 'Fre', 'Sam');
			Byrom.DATE_FORMAT = 'dd.MMM.yyyy';
			break;
		case 'es':
			Byrom.MONTH_NAMES = new Array('enero', 'febrero', 'marcha', 'abril', 'puede', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre', 'ene', 'feb', 'mar', 'abr', 'pue', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic');
			Byrom.DAY_NAMES = new Array('Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado', 'Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb');
			Byrom.DATE_FORMAT = 'dd.MMM.yyyy';
			break;
		case 'fr':
			Byrom.MONTH_NAMES = new Array('janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'decembre', 'jan', 'fév', 'mar', 'avr', 'mai', 'jun', 'jul', 'aoû', 'sep', 'oct', 'nov', 'dec');
			Byrom.DAY_NAMES = new Array('dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dim', 'lun', 'mar', 'mer', 'jeu', 'ven', 'sam');
			Byrom.DATE_FORMAT = 'dd/MMM/yyyy';
			break;
		case 'it':
			Byrom.DAY_NAMES = new Array('domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì', 'venerdì', 'sabato', 'dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab');
			Byrom.MONTH_NAMES = new Array('gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno', 'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre', 'gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug', 'ago', 'set', 'ott', 'nov', 'dic');
			Byrom.DATE_FORMAT = 'dd/MMM/yyyy';
			Byrom.TIME_FORMAT = 'hh.kk.ss';
			break;
	}
	Byrom.DATETIME_FORMAT = Byrom.DATE_FORMAT + ' ' + Byrom.TIME_FORMAT;
	Byrom.DATETIME_HM_FORMAT = Byrom.DATE_FORMAT + ' ' + Byrom.TIME_HM_FORMAT;

	Byrom.MONTH_NAMES_SHORT = ',';
	Byrom.MONTH_NAMES_SHORT_EN = ',';
	for (var monthIndex = 0; monthIndex <= 11; monthIndex++)
	{
		Byrom.MONTH_NAMES_SHORT += Byrom.MONTH_NAMES[12 + monthIndex] + ',';
		Byrom.MONTH_NAMES_SHORT_EN += Byrom.MONTH_NAMES_EN[12 + monthIndex] + ',';
	}
};

//startIndex blank (default = 0), a number (), 1) or 'JAN'
Byrom.getMonthsOptionsHtml = function(startIndex, useShortNames)
{
	if (arguments.length < 1)
		startIndex = 0;
	if (arguments.length < 2)
		useShortNames = false;
	var keyType = startIndex;
	if (startIndex.toString() == 'jan')
		keyType = 'jan'
	else if (startIndex.toString() == 'Jan')
		keyType = 'Jan'
	else if (startIndex.toString().toLowerCase() == 'jan')
		keyType = 'JAN'
	else if (!Byrom.isInteger)
		startIndex = 0;
	var html = '';
	for (var monthIndex = 0; monthIndex <= 11; monthIndex++)
	{
		var name = (useShortNames ? Byrom.MONTH_NAMES[12 + monthIndex] : Byrom.MONTH_NAMES[monthIndex])
		var key = '';
		if (keyType == 'jan')
			key = Byrom.MONTH_NAMES_EN[12 + monthIndex].toLowerCase();
		else if (keyType == 'Jan')
			key = Byrom.MONTH_NAMES_EN[12 + monthIndex].toUpperCase().substr(0, 1) + Byrom.MONTH_NAMES_EN[12 + monthIndex].toLowerCase().substr(1);
		else if (keyType == 'JAN')
			key = Byrom.MONTH_NAMES_EN[12 + monthIndex].toUpperCase();
		else
		{
			key = startIndex.toString();
			startIndex++;
		}
		html += '<option value=' + key + '>' + name + '</option>';
	}
	return html;
}

Byrom.getShortFromMonthIndex = function(monthIndex)
{
	if (monthIndex >= 0 && monthIndex <= 11)
	{
		return Byrom.MONTH_NAMES_SHORT_EN.substr(monthIndex * 4 + 1, 3);
	}
}
Byrom.getMonthIndexFromShort = function(monthShortName)
{
	//	try for string (MMM format)
	var indexOfMonth = Byrom.MONTH_NAMES_SHORT_EN.toLowerCase().indexOf(',' + monthShortName.toLowerCase() + ',', 0);
	if (indexOfMonth < 0)
		return -1;
	return parseInt(indexOfMonth / 4);
}
Byrom.checkLocalize = function()
{
	if (Byrom.LOCALIZE_LANGUAGE != Byrom.language)
		Byrom.localize();
};

// Some common format strings (JSON)
Byrom.formatDateMasks = {
	defaultFormat: "MMM dd yyyy HH:mm:ss",
	dateTimeNoYS: "d MMM HH:mm",
	shortDate: "m/d/yy",
	mediumDate: "MMM d, yyyy",
	longDate: "MMM d, yyyy",
	fullDate: "dddd, MMM d, yyyy",
	shortTime: "h:mm TT",
	mediumTime: "h:mm:ss TT",
	longTime: "h:mm:ss TT Z",
	isoDate: "yyyy-MM-dd",
	isoTime: "HH:mm:ss",
	isoDateTime: "yyyy-MM-dd'T'HH:mm:ss",
	isoFullDateTime: "yyyy-MM-dd'T'HH:mm:ss.lo"
};

Byrom.LZ = function(x) { return (x < 0 || x > 9 ? "" : "0") + x };

// ------------------------------------------------------------------
// Returns true if date string matches format of format string and
// is a valid date. Else returns false.
Byrom.isDate = function(val, format)
{
	var date = Byrom.getDateFromFormat(val, format);
	if (date == 0) { return false; }
	return true;
};

// -------------------------------------------------------------------
//	Compare two date strings to see which is greater.
//	Returns:	if 1>2 : 1,  2>=1 : 0, nad : -1
Byrom.compareDates = function(date1, dateformat1, date2, dateformat2)
{
	var d1 = Byrom.getDateFromFormat(date1, dateformat1);
	var d2 = Byrom.getDateFromFormat(date2, dateformat2);
	if (d1 == 0 || d2 == 0)
	{
		return -1;
	}
	else if (d1 > d2)
	{
		return 1;
	}
	return 0;
};

// ------------------------------------------------------------------
// formatDate (date_object, format)
Byrom.formatDate = function(date, format)
{
	if (!date)
		return '';
	Byrom.checkLocalize();
	if (!format)
		format = Byrom.formatDateMasks.defaultFormat;
	format = format + "";
	var result = "";
	var i_format = 0;
	var c = "";
	var token = "";
	var y = date.getYear() + "";
	var M = date.getMonth() + 1;
	var d = date.getDate();
	var E = date.getDay();
	var H = date.getHours();
	var m = date.getMinutes();
	var s = date.getSeconds();
	var yyyy, yy, MMM, MM, dd, hh, h, mm, ss, ampm, HH, H, KK, K, kk, k;
	// Convert real date parts into formatted versions
	var value = new Object();
	if (y.length < 4) { y = "" + (y - 0 + 1900); }
	value["y"] = "" + y;
	value["yyyy"] = y;
	value["yy"] = y.substring(2, 4);
	value["M"] = M;
	value["MM"] = Byrom.LZ(M);
	value["MMM"] = Byrom.MONTH_NAMES[M - 1];
	value["NNN"] = Byrom.MONTH_NAMES[M + 11];
	value["d"] = d;
	value["dd"] = Byrom.LZ(d);
	value["E"] = Byrom.DAY_NAMES[E + 7];
	value["EE"] = Byrom.DAY_NAMES[E];
	value["H"] = H;
	value["HH"] = Byrom.LZ(H);
	if (H == 0) { value["h"] = 12; }
	else if (H > 12) { value["h"] = H - 12; }
	else { value["h"] = H; }
	value["hh"] = Byrom.LZ(value["h"]);
	if (H > 11) { value["K"] = H - 12; } else { value["K"] = H; }
	value["k"] = H + 1;
	value["KK"] = Byrom.LZ(value["K"]);
	value["kk"] = Byrom.LZ(value["k"]);
	if (H > 11) { value["a"] = "PM"; }
	else { value["a"] = "AM"; }
	value["m"] = m;
	value["mm"] = Byrom.LZ(m);
	value["s"] = s;
	value["ss"] = Byrom.LZ(s);
	while (i_format < format.length)
	{
		c = format.charAt(i_format);
		token = "";
		while ((format.charAt(i_format) == c) && (i_format < format.length))
		{
			token += format.charAt(i_format++);
		}
		if (value[token] != null) { result = result + value[token]; }
		else { result = result + token; }
	}
	return result;
};

// ------------------------------------------------------------------
Byrom._isInteger = function(val)
{
	return Byrom.isInteger(val);
};
Byrom.isInteger = function(val)
{
	var digits = "1234567890";
	for (var i = 0; i < val.length; i++)
	{
		if (digits.indexOf(val.charAt(i)) == -1) { return false; }
	}
	return true;
};
Byrom._getInt = function(str, i, minlength, maxlength)
{
	for (var x = maxlength; x >= minlength; x--)
	{
		var token = str.substring(i, i + x);
		if (token.length < minlength) { return null; }
		if (Byrom._isInteger(token)) { return token; }
	}
	return null;
};

// ------------------------------------------------------------------
// It matches If the date string matches the format string, it returns the 
// getTime() of the date. If it does not match, it returns 0.
Byrom.getDateFromFormat = function(val, format)
{
	val = val + "";
	format = format + "";
	var i_val = 0;
	var i_format = 0;
	var c = "";
	var token = "";
	var token2 = "";
	var x, y;
	var now = new Date();
	var year = now.getYear();
	var month = now.getMonth() + 1;
	var date = 1;
	var hh = now.getHours();
	var mm = now.getMinutes();
	var ss = now.getSeconds();
	var ampm = "";

	while (i_format < format.length)
	{
		// Get next token from format string
		c = format.charAt(i_format);
		token = "";
		while ((format.charAt(i_format) == c) && (i_format < format.length))
		{
			token += format.charAt(i_format++);
		}
		// Extract contents of value based on format token
		if (token == "yyyy" || token == "yy" || token == "y")
		{
			if (token == "yyyy") { x = 4; y = 4; }
			if (token == "yy") { x = 2; y = 2; }
			if (token == "y") { x = 2; y = 4; }
			year = Byrom._getInt(val, i_val, x, y);
			if (year == null) { return 0; }
			i_val += year.length;
			if (year.length == 2)
			{
				if (year > 70) { year = 1900 + (year - 0); }
				else { year = 2000 + (year - 0); }
			}
		}
		else if (token == "MMM" || token == "NNN")
		{
			month = 0;
			for (var i = 0; i < Byrom.MONTH_NAMES.length; i++)
			{
				var month_name = Byrom.Byrom.MONTH_NAMES[i];
				if (val.substring(i_val, i_val + month_name.length).toLowerCase() == month_name.toLowerCase())
				{
					if (token == "MMM" || (token == "NNN" && i > 11))
					{
						month = i + 1;
						if (month > 12) { month -= 12; }
						i_val += month_name.length;
						break;
					}
				}
			}
			if ((month < 1) || (month > 12)) { return 0; }
		}
		else if (token == "EE" || token == "E")
		{
			for (var i = 0; i < Byrom.DAY_NAMES.length; i++)
			{
				var day_name = Byrom.DAY_NAMES[i];
				if (val.substring(i_val, i_val + day_name.length).toLowerCase() == day_name.toLowerCase())
				{
					i_val += day_name.length;
					break;
				}
			}
		}
		else if (token == "MM" || token == "M")
		{
			month = Byrom._getInt(val, i_val, token.length, 2);
			if (month == null || (month < 1) || (month > 12)) { return 0; }
			i_val += month.length;
		}
		else if (token == "dd" || token == "d")
		{
			date = Byrom._getInt(val, i_val, token.length, 2);
			if (date == null || (date < 1) || (date > 31)) { return 0; }
			i_val += date.length;
		}
		else if (token == "hh" || token == "h")
		{
			hh = Byrom._getInt(val, i_val, token.length, 2);
			if (hh == null || (hh < 1) || (hh > 12)) { return 0; }
			i_val += hh.length;
		}
		else if (token == "HH" || token == "H")
		{
			hh = Byrom._getInt(val, i_val, token.length, 2);
			if (hh == null || (hh < 0) || (hh > 23)) { return 0; }
			i_val += hh.length;
		}
		else if (token == "KK" || token == "K")
		{
			hh = Byrom._getInt(val, i_val, token.length, 2);
			if (hh == null || (hh < 0) || (hh > 11)) { return 0; }
			i_val += hh.length;
		}
		else if (token == "kk" || token == "k")
		{
			hh = Byrom._getInt(val, i_val, token.length, 2);
			if (hh == null || (hh < 1) || (hh > 24)) { return 0; }
			i_val += hh.length; hh--;
		}
		else if (token == "mm" || token == "m")
		{
			mm = Byrom._getInt(val, i_val, token.length, 2);
			if (mm == null || (mm < 0) || (mm > 59)) { return 0; }
			i_val += mm.length;
		}
		else if (token == "ss" || token == "s")
		{
			ss = Byrom._getInt(val, i_val, token.length, 2);
			if (ss == null || (ss < 0) || (ss > 59)) { return 0; }
			i_val += ss.length;
		}
		else if (token == "a")
		{
			if (val.substring(i_val, i_val + 2).toLowerCase() == "am") { ampm = "AM"; }
			else if (val.substring(i_val, i_val + 2).toLowerCase() == "pm") { ampm = "PM"; }
			else { return 0; }
			i_val += 2;
		}
		else
		{
			if (val.substring(i_val, i_val + token.length) != token) { return 0; }
			else { i_val += token.length; }
		}
	}
	// If there are any trailing characters left in the value, it doesn't match
	if (i_val != val.length) { return 0; }
	// Is date valid for month?
	if (month == 2)
	{
		// Check for leap year
		if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
		{ // leap year
			if (date > 29) { return 0; }
		}
		else { if (date > 28) { return 0; } }
	}
	if ((month == 4) || (month == 6) || (month == 9) || (month == 11))
	{
		if (date > 30) { return 0; }
	}
	// Correct hours value
	if (hh < 12 && ampm == "PM") { hh = hh - 0 + 12; }
	else if (hh > 11 && ampm == "AM") { hh -= 12; }
	var newdate = new Date(year, month - 1, date, hh, mm, ss);
	return newdate.getTime();
};

// ------------------------------------------------------------------
// A second argument (prefer_euro_format) may be passed to instruct the method to search
// for formats like d/M/y before M/d/y (American).
Byrom.parseDate = function(val)
{
	var preferEuro = (arguments.length == 2) ? arguments[1] : false;
	generalFormats = new Array('y-M-d', 'MMM d, y', 'MMM d,y', 'y-MMM-d', 'd-MMM-y', 'MMM d');
	monthFirst = new Array('M/d/y', 'M-d-y', 'M.d.y', 'MMM-d', 'M/d', 'M-d');
	dateFirst = new Array('d/M/y', 'd-M-y', 'd.M.y', 'd-MMM', 'd/M', 'd-M');
	var checkList = new Array('generalFormats', preferEuro ? 'dateFirst' : 'monthFirst', preferEuro ? 'monthFirst' : 'dateFirst');
	var d = null;
	for (var i = 0; i < checkList.length; i++)
	{
		var l = window[checkList[i]];
		for (var j = 0; j < l.length; j++)
		{
			d = Byrom.getDateFromFormat(val, l[j]);
			if (d != 0) { return new Date(d); }
		}
	}
	return null;
};


Byrom.setDdItem = function(targetId, value)
{
	var target = document.getElementById(targetId);

	if (target.options[target.selectedIndex].value != value)
	{
		for (var index = 0; index < target.options.length; index++)
		{
			if (target.options[index].value == value)
			{
				target.selectedIndex = index;
				return;
			}
		}
	}
};

Byrom.setLabel = function(id, value)
{
	Byrom.setContents(id, value);
};

Byrom.setContents = function(id, value)
{
	var elem = document.getElementById(id);
	if (elem)
		elem.innerHTML = value;
};

Byrom.formatHtml = function(id)
{
	var elem = document.getElementById(id);
	if (elem && elem.innerHTML)
	{
		for (var i = 1, j = arguments.length; i < j; i++)
		{
			elem.innerHTML = elem.innerHTML.replace('{' + (i - 1).toString() + '}', arguments[i]);
		}
	}
};

Byrom.stringFormat = function(value)
{
	return Byrom.formatStringArr(value, arguments);
};

Byrom.formatString = function(value)
{
	return Byrom.formatStringArr(value, arguments);
};

Byrom.formatStringArr = function(value, args)
{
	if (!value)
		return value;
	var returnValue = value;
	for (var i = 1, j = args.length; i < j; i++)
	{
		returnValue = returnValue.replace('{' + (i - 1).toString() + '}', args[i]);
	}
	return returnValue;
};

Byrom.queryString = function(key, defaultValue)
{
	try
	{
		key = key.toLowerCase();
		keyValuePairs = window.location.search.substring(1).split("&");
		for (i = 0; i < keyValuePairs.length; i++)
		{
			keyValuePair = keyValuePairs[i].split("=");
			if (keyValuePair.length == 2 && keyValuePair[0].toLowerCase() == key)
			{
				return keyValuePair[1];
			}
		}
	}
	catch (ex) { ; }

	return defaultValue;
};

Byrom.enableMenus = function()
{
	Byrom.setStyleDisplay('menuLanguagesPanel', '');
};
Byrom.getButtonValue = function(id, defaultValue)
{
	var elem = document.getElementById(id);
	if (elem)
	{
		if (elem.checked != undefined)
			return elem.checked;
		else
			return elem.value;
	}
	else
		return defaultValue;
};
Byrom.toggleController = function(id, value, expandImgUrl, collapseImgUrl)
{
	var toggleValue = value;
	var controller = id;
	if (typeof controller != 'object')
		controller = document.getElementById(id);

	if (controller)
	{
		var expand = expandImgUrl ? expandImgUrl : 'images/Fifa/expand.gif';
		var collapse = collapseImgUrl ? collapseImgUrl : 'images/Fifa/collapse.gif';
		var imgs = controller.getElementsByTagName('img');
		var img = null;
		if (imgs && imgs.length > 0)
			img = imgs[0];
		if (img == null && controller.src)
			img = controller;
		//if (img && img.src && (img.src.toLowerCase().endsWith(expand.toLowerCase()) || img.src.toLowerCase().endsWith(collapse.toLowerCase()) ))
		if (img && img.src)
		{
			if (!(img.src.toLowerCase().endsWith(expand.toLowerCase()) || img.src.toLowerCase().endsWith(collapse.toLowerCase())))
			{
				var expandWord = null;
				var collapseWord = null;
				var isExpand = false;
				var found = false;
				for (var index = 0; index < 2; index++)
				{
					var expandWord = ['expanded', 'expand'][index];
					var collapseWord = ['collapsed', 'collapse'][index];
					if (img.src.toLowerCase().indexOf(expandWord) >= 0 || img.src.toLowerCase().indexOf(collapseWord) >= 0)
					{
						found = true;
						break;
					}
				}
				if (found)
				{
					expand = img.src.toLowerCase().replace(collapseWord, expandWord);
					collapse = expand.replace(expandWord, collapseWord);
				}
			}

			if ((img.src.toLowerCase().endsWith(expand.toLowerCase()) || img.src.toLowerCase().endsWith(collapse.toLowerCase())))
			{
				//	it's an image, image input, or an image inside a hyperlink
				if (toggleValue)	//	value just being set
					img.src = (toggleValue == Byrom.toggleStateCollapsed ? expand : collapse);
				else				//	toggle value
				{
					if (img.src.toLowerCase().endsWith(expand.toLowerCase()))
					{
						toggleValue = Byrom.toggleStateExpanded;
						img.src = collapse;
					}
					else
					{
						toggleValue = Byrom.toggleStateCollapsed;
						img.src = expand;
					}
				}
			}
		}
	}
	return toggleValue;
};


Byrom.getToggleControllerState = function(id)
{
	var toggleValue = null;
	var controller = id;
	if (typeof controller != 'object')
		controller = document.getElementById(id);
	if (controller)
	{
		var expand = 'images/Fifa/expand.gif';
		var collapse = 'images/Fifa/collapse.gif';
		var imgs = controller.getElementsByTagName('img');
		var img = null;
		if (imgs && imgs.length > 0)
			img = imgs[0];
		if (img && (img.src.toLowerCase().endsWith(expand.toLowerCase()) || img.src.toLowerCase().endsWith(collapse.toLowerCase())))
		{
			//	it's an image inside a hyperlink
			if (img.src.toLowerCase().endsWith(expand.toLowerCase()))
			{
				toggleValue = Byrom.toggleStateCollapsed;
			}
			else
			{
				toggleValue = Byrom.toggleStateExpanded;
			}
		}
	}
	return toggleValue;
};
Byrom.toggleVisible = function(id)
{
	return Byrom.setStyleDisplayToggle(id);
};

Byrom.setStyleDisplayToggle = function(id)
{
	var elem = document.getElementById(id);
	if (elem)
	{
		if (elem.style.display != 'none')
			elem.style.display = 'none';
		else
			elem.style.display = 'block';
		return elem.style.display == 'block' ? Byrom.toggleStateExpanded : Byrom.toggleStateCollapsed;
	}

};
Byrom.showToggle = function(id, controller, expandImgUrl, collapseImgUrl)
{
	if (controller)
	{
		Byrom.show(id, Byrom.toggleController(controller, null, expandImgUrl, collapseImgUrl) == Byrom.toggleStateExpanded);
	}
	else
		return Byrom.setStyleDisplayToggle(id);
};
Byrom.showInline = function(id)
{
	Byrom.setStyleDisplay(id, 'inline');
};
Byrom.show = function(id, show, controller)
{
	if (arguments.length < 2)
		show = true;
	if (show)
	{
		Byrom.setStyleDisplay(id, 'block');
		Byrom.toggleController(controller, Byrom.toggleStateExpanded);
	}
	else
	{
		Byrom.setStyleDisplay(id, 'none');
		Byrom.toggleController(controller, Byrom.toggleStateCollapsed);
	}
};
Byrom.hide = function(id, hide)
{
	if (arguments.length < 2)
		hide = true;
	if (hide)
		Byrom.setStyleDisplay(id, 'none');
	else
		Byrom.setStyleDisplay(id, 'block');
};

Byrom.setStyleDisplayShow = function(id)
{
	Byrom.setStyleDisplay(id, 'block');
};
Byrom.setStyleDisplayHide = function(id)
{
	Byrom.setStyleDisplay(id, 'none');
};
Byrom.setStyleDisplay = function(id, value)
{
	var elem = document.getElementById(id);
	if (elem)
		elem.style.display = value;
};

Byrom.findPos = function(obj)
{
	var curleft = curtop = 0;
	if (obj.offsetParent)
	{
		curleft = obj.offsetLeft;
		curtop = obj.offsetTop;
		while (obj = obj.offsetParent)
		{
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
		}
	}
	return [curleft, curtop];
};
// Move an element directly on top of another element (and optionally
// make it the same size) - used in ajax controls
Byrom.Cover = function(bottom, top, ignoreSize)
{
	var location = Sys.UI.DomElement.getLocation(bottom);
	top.style.position = 'absolute';
	top.style.top = location.y + 'px';
	top.style.left = location.x + 'px';
	if (!ignoreSize)
	{
		top.style.height = bottom.offsetHeight + 'px';
		top.style.width = bottom.offsetWidth + 'px';
	}
};

Byrom.CoverInSameDiv = function(bottom, top, ignoreSize)
{
	//	this is very limited, assumes bottom element is in same div as top and no funny re-positioning applied
	//	point is to keep it simple & avoid wrong screen positioning co-ordinates 
	//	(need to take 'top' out of doc & re-insert at root level to make sure works ok - does not at the moment)
	top.style.position = 'absolute';
	if (bottom.style.top)
		top.style.top = bottom.style.top;
	else
		top.style.top = '0px';

	if (top.style.left)
		top.style.left = bottom.style.left;
	else
		top.style.left = '0px';

	if (top.style.marginLeft)
		top.style.marginLeft = bottom.style.marginLeft;
	else
		top.style.marginLeft = '0px';

	if (!ignoreSize)
	{
		top.style.height = bottom.offsetHeight + 'px';
		top.style.width = bottom.offsetWidth + 'px';
	}
	top.style.height = bottom.style.height;
	top.style.width = bottom.style.width;
	//				alert('bottom.style.top=' + bottom.style.top + ' bottom.style.left=' + bottom.style.left + ' top.style.left=' + top.style.left + ' top.style.left=' + top.style.left);
};

// terrible function to avoid dropdown's 'always on top' feature when moving divs around (only a problem in ie 6)
// get around poblem by swapping drop down for text box & Swap back again
Byrom.SwapDropDownForIe6 = function(ddId, textId)
{
	//	debugger;
	if (Byrom.IsBrowserIeEarlierThan7())
	{
		var dd = $get(ddId);
		if (dd)
		{
			var tx = $get(textId);
			if (tx)
			{
				// tx.style.height = dd.offsetHeight ;
				tx.style.top = dd.offsetTop;
				tx.style.width = dd.offsetWidth - 6;
				tx.style.left = dd.offsetLeft;
				try
				{
					var myindex = dd.selectedIndex;
					tx.value = dd.options[myindex].text
				}
				catch (err)
				{
					try
					{
						tx.value = dd.options[0].text
					}
					catch (err2)
					{
					}
				}
				dd.style.display = "none";
				tx.style.display = "";
			}
		}
	}
};
Byrom.SwapDropDownForIe6Back = function(ddId, textId)
{
	//	debugger;
	if (Byrom.IsBrowserIeEarlierThan7())
	{
		var dd = $get(ddId);
		if (dd)
		{
			var tx = $get(textId);
			if (tx)
			{
				dd.style.display = "";
				tx.style.display = "none";
			}
		}
	}
};
Byrom.IsBrowserIeEarlierThan7 = function()
{
	//	debugger;
	var browser = navigator.appName;
	var b_version = navigator.appVersion;
	var version = parseFloat(b_version);
	if (browser == "Microsoft Internet Explorer" && (b_version.startsWith("4.0 (compatible; MSIE 6.0;") || b_version.startsWith("4.0 (compatible; MSIE 5.0;")))
		return true;
	else
		return false;
	return true;
};

Byrom.GetCookie = function(name)
{
	return Byrom.GetMsCookie(name);
};

Byrom.GetMsCookie = function(name)
{
	// first we'll split this cookie up into name/value pairs
	// note: document.cookie only returns name=value, not the other components
	var a_all_cookies = document.cookie.split(';');
	var cookie_name = '';
	var cookie_value = '';
	var i = 0;

	for (i = 0; i < a_all_cookies.length; i++)
	{
		// now we'll split apart each name=value pair
		// a_temp_cookie = a_all_cookies[i].split( '=' );
		var cookie = a_all_cookies[i];
		a_temp_cookie = null;
		var pos = cookie.indexOf('=');
		if (pos > 0)
			cookie_name = cookie.substring(0, pos);
		else if (pos < 0)
			cookie_name = cookie;

		// and trim left/right whitespace while we're at it
		cookie_name = cookie_name.replace(/^\s+|\s+$/g, '');

		// if the extracted name matches passed name
		if (cookie_name == name)
		{
			// we need to handle case where cookie has no value but exists (no = sign, that is):
			if (pos >= 0)
			{
				cookie_value = unescape(cookie.substring(pos + 1).replace(/^\s+|\s+$/g, ''));
			}
			// note that in cases where cookie is initialized but no value, null is returned
			return cookie_value;
		}
	}
	return null;
};

Byrom.GetCookieValue = function(name, queryName, defaultValue)
{
	return Byrom.GetMsCookieValue(name, queryName, defaultValue);
};

Byrom.GetMsCookieValue = function(name, queryName, defaultValue)
{
	if (arguments.length < 3)
		defaultValue = null;
		
	// first we'll split this cookie up into name/value pairs
	// note: document.cookie only returns name=value, not the other components
	var a_all_cookies = document.cookie.split(';');
	var cookie_query_name = '';
	var cookie_name = '';
	var cookie_query = '';
	var cookie_value = '';
	var queryPos = -1;
	var i = 0;

	for (i = 0; i < a_all_cookies.length; i++)
	{
		// now we'll split apart each name=value pair
		// a_temp_cookie = a_all_cookies[i].split( '=' );
		var cookie = a_all_cookies[i];
		a_temp_cookie = null;
		var pos = cookie.indexOf('=');
		if (pos > 0)
			cookie_name = cookie.substring(0, pos);
		else if (pos < 0)
			cookie_name = cookie;

		// and trim left/right whitespace while we're at it
		cookie_name = cookie_name.replace(/^\s+|\s+$/g, '');

		// if the extracted name matches passed name
		if (cookie_name == name)
		{
			// we need to handle case where cookie has no value but exists (no = sign, that is):
			if (pos >= 0)
			{
				cookie_query = unescape('&' + cookie.substring(pos + 1).replace(/^\s+|\s+$/g, '') + '&');
				queryPos = cookie_query.indexOf('&' + queryName + '=');
				if (queryPos >= 0)
				{	//	found
					var queryValuePos = cookie_query.indexOf('&', queryPos + queryName.length + 2);
					if (queryValuePos >= 0)
						return cookie_query.substring(queryPos + queryName.length + 2, queryValuePos);
					else
						return defaultValue;
				}
			}
			// note that in cases where cookie is initialized but no value, null is returned
			return defaultValue;
		}
	}
	return defaultValue;
};
Byrom.SetCookieValue = function(name, queryName, value, expires, path, domain, secure)
{
	Byrom.SetMsCookieValue(name, queryName, value, expires, path, domain, secure)
};
Byrom.SetMsCookieValue = function(name, queryName, value, expires, path, domain, secure)
{
	// first we'll split this cookie up into name/value pairs
	// note: document.cookie only returns name=value, not the other components
	var a_all_cookies = document.cookie.split(';');
	var cookie_query_name = '';
	var cookie_name = '';
	var cookie_query = '';
	var cookie_value = '';
	var queryPos = -1;
	var i = 0;


	// set time, it's in milliseconds
	var today = new Date();
	today.setTime(today.getTime());
	/*
	if the expires variable is set, make the correct
	expires time, the current script below will set
	it for x number of days, to make it for hours,
	delete * 24, for minutes, delete * 60 * 24
	*/
	if (expires)
		expires = expires * 1000 * 60 * 60 * 24;
	else
		expires = 0;
	var expiresDate = new Date(today.getTime() + (expires));

	//Note:	this routine does not take account of any escaped values

	//expected structure : "Byrom.PreCheckIn=PreCheckIn.GridPageSize=5&alwaysSetTourStyleCheckBox=True&showPopupsCheckBox=False&MapContour=r&MapDimensions=2d; accessFIFA=standard; UserLanguage=en; CP=null*; chkcookie=1210769769031"
	var myCookie = ';' + document.cookie + ';'
	var hasSpace = 0;
	var pos = myCookie.indexOf(';' + name + '=');
	if (pos < 0)
	{
		pos = myCookie.indexOf('; ' + name + '=');
		hasSpace = 1;
	}
	if (pos >= 0)
	{
		var posEnd = myCookie.indexOf(';', pos + name.length + 2);
		if (posEnd > pos)
		{	//	found basic cookie
			cookie_query = '&' + myCookie.substring(pos + name.length + 2 + hasSpace, posEnd) + '&';
			var queryPos = cookie_query.indexOf('&' + queryName + '=');
			if (queryPos >= 0)
			{	//	found
				var queryValuePos = cookie_query.indexOf('&', queryPos + queryName.length + 2);

				if (queryValuePos >= 0)	//	set value
					cookie_query = cookie_query.substring(0, queryPos + queryName.length + 2) + value	//	(value NOT escaped)
						+ cookie_query.substring(queryValuePos);
			}
			else
			{	//	add new key value pair
				cookie_query += queryName + '=' + value + '&'
			}
			cookie_query = name + '=' + cookie_query.substring(1, cookie_query.length - 1) +  //	remove surrounding '&'s
				((expires) ? ";expires=" + expiresDate.toGMTString() : "") +
				((path) ? ";path=" + path : "") +
				((domain) ? ";domain=" + domain : "") +
				((secure) ? ";secure" : "")
				+ ';';
			//	recreate cookie
			document.cookie = cookie_query;
		}
	}
	else if (name && queryName)
	{	//	not found - it's a new cookie
		cookie_query = name + '=' + queryName + '=' + escape(value) +
				((expires) ? ";expires=" + expiresDate.toGMTString() : "") +
				((path) ? ";path=" + path : "") +
				((domain) ? ";domain=" + domain : "") +
				((secure) ? ";secure" : "")
				+ ';';
		document.cookie = cookie_query;
	}
};

Byrom.DeleteCookie = function(name, path, domain, secure)
{
	var expires = -1;
	var expiresDate = new Date();
	expiresDate.setMonth(-1);

	var myCookie = ';' + document.cookie + ';'
	var pos = myCookie.indexOf(';' + name + '=');
	if (pos < 0)
		pos = myCookie.indexOf('; ' + name + '=');
	if (pos >= 0)
	{
		var posEnd = myCookie.indexOf(';', pos + name.length + 2);
		if (posEnd > pos)
		{	//	recreate cookie
			var cookie_query = name + '=nothing' +
				((expires) ? ";expires=" + expiresDate.toGMTString() : "") +
				((path) ? ";path=" + path : "") +
				((domain) ? ";domain=" + domain : "") +
				((secure) ? ";secure" : "")
				+ ';';

			document.cookie = cookie_query;
		}
	}
};




/******************************************
Validation
*******************/

Byrom.trim = function(value)
{
	if (!value)
		return value;
	return value.toString().replace(/^\s+|\s+$/g, "");
};

Byrom.addClass = function(id, className)
{
	var elem = document.getElementById(id);
	if (elem)
	{
		var existingClassName = elem.className;
		if (!existingClassName)
			elem.className = className;
		else if ((' ' + existingClassName + ' ').indexOf(' ' + className + ' ', 0) < 0)
			elem.className += ' ' + className;
	}
};

Byrom.removeClass = function(id, className)
{
	var elem = document.getElementById(id);
	if (elem)
	{
		elem.className = Byrom.trim((' ' + elem.className + ' ').replace(' ' + className + ' ', ''));
	}
};



Byrom.ValidateRemove = function(validateItems, showId, resultsId, action, actionValue)
{
	if (!showId)
		showId = resultsId;
	var elem = null;

	if (validateItems.length > 0 && Byrom.isArray(validateItems[0]))
	{	//	its an array of groups, validate each group in turn
		for (index = 0; index < validateItems.length; index++)
		{
			group = validateItems[index];
			Byrom.ValidateRemoveGroup(group, action, actionValue)
		}
	}
	else
	{	//	its a group already validate just this
		Byrom.ValidateRemoveGroup(validateItems, action, actionValue)
	}

	//	display errors on target element
	if (resultsId)
	{
		elem = document.getElementById(resultsId);
		if (elem)
		{
			elem.innerHTML = '';
		}
	}

	//	make target element visible ?
	Byrom.hide(showId);
};

Byrom.ValidateRemoveGroup = function(validateItems, action, actionValue)
{
	for (var index = 0; index < validateItems.length; index++)
	{
		var item = validateItems[index];
		item.actionOnValid(action, actionValue);
	}
};


Byrom.isArray = function(obj)
{
	//returns true is it is an array
	return (obj.constructor.toString().indexOf("Array") != -1)
};

Byrom.emailIsValid = function(email)
{
	var emailPat = /^([\w-]+(?:\.[\w-']+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
	return email.match(emailPat) != null;
};

Byrom.CreditCardTypes = [
	{ name: "VIS", length: "13,16", prefixes: "4", checkdigit: true }
	, { name: "VISA", length: "13,16", prefixes: "4", checkdigit: true }
	, { name: "MAST", length: "16", prefixes: "51,52,53,54,55", checkdigit: true }
	, { name: "MST", length: "16", prefixes: "51,52,53,54,55", checkdigit: true }
	, { name: "DIN", length: "14,", prefixes: "300,301,302,303,304,305,36,38", checkdigit: true }
	, { name: "DINE", length: "14,", prefixes: "300,301,302,303,304,305,36,38", checkdigit: true }
	, { name: "DINERS", length: "14,", prefixes: "300,301,302,303,304,305,36,38", checkdigit: true }
	, { name: "CARTEBLANCHE", length: "14", prefixes: "300,301,302,303,304,305,36,38", checkdigit: true }
	, { name: "AMEX", length: "15", prefixes: "34,37", checkdigit: true }
	, { name: "Discover", length: "16", prefixes: "6011", checkdigit: true }
	, { name: "JCB", length: "16", prefixes: "3,1800,2131", checkdigit: true }
	, { name: "Enroute", length: "15", prefixes: "2014,2149", checkdigit: true }
	, { name: "SWI", length: "12,13,14,15,16,17,18,19", prefixes: "4,5,6", checkdigit: true }
	, { name: "VSE", length: "13,16", prefixes: "4", checkdigit: true }
	, { name: "VSD", length: "13,16", prefixes: "4", checkdigit: true}];


//	align credit card codes - name is code not long description
Byrom.CreditCardTypeSet = function(name, nameNew)
{
	for (var i = 0; i < Byrom.CreditCardTypes.length; i++)
	{
		if (name.toLowerCase() == Byrom.CreditCardTypes[i].name.toLowerCase())
		{
			Byrom.CreditCardTypes[i].name = nameNew.toString();
			break;
		}
	}
}

Byrom.CreditCardIsValid = function(cardnumber, cardname)
{
	var cards = Byrom.CreditCardTypes;

	var ccErrorNo = 0;
	var ccErrors = new Array()

	var strUnknowCardType = "Unknown card type";
	var strCardNumberNoProvided = "No card number provided";
	var strCardInvalidFormatNumber = "Credit card number is in invalid format";
	var strCardInvalidNumber = "Credit card number is invalid";
	var strCardInapropiateDigitsNumber = "Credit card number has an inappropriate number of digits";

	ccErrors[0] = strUnknowCardType;
	ccErrors[1] = strCardNumberNoProvided;
	ccErrors[2] = strCardInvalidFormatNumber;
	ccErrors[3] = strCardInvalidNumber;
	ccErrors[4] = strCardInapropiateDigitsNumber;

	// Establish card type
	var cardType = -1;
	for (var i = 0; i < cards.length; i++)
	{
		// See if it is this card (ignoring the case of the string)
		if (cardname.toLowerCase() == cards[i].name.toLowerCase())
		{
			cardType = i;
			break;
		}
	}

	// If card type not found, report an error
	if (cardType == -1)
	{
		ccErrorNo = 0;
		return false;
	}

	// Ensure that the user has provided a credit card number
	if (cardnumber.length == 0)
	{
		ccErrorNo = 1;
		return false;
	}

	// Check that the number is numeric, although we do permit a space to occur	
	// every four digits. 
	var cardNo = cardnumber
	var cardexp = /^([0-9]{4})\s?([0-9]{4})\s?([0-9]{4})\s?([0-9]{0,7})$/;
	if (!cardexp.exec(cardNo))
	{
		ccErrorNo = 2;
		return false;
	}

	// Now remove any spaces from the credit card number
	cardexp.exec(cardNo);
	var cardNoNew = RegExp.$1 + RegExp.$2 + RegExp.$3 + RegExp.$4;
	cardNo = cardNoNew;

	// Now check the modulus 10 check digit - if required
	if (cards[cardType].checkdigit)
	{
		var checksum = 0; 																// running checksum total
		var mychar = ""; 																 // next char to process
		var j = 1; 																			 // takes value of 1 or 2

		// Process each digit one by one starting at the right
		var calc;
		for (i = cardNo.length - 1; i >= 0; i--)
		{

			// Extract the next digit and multiply by 1 or 2 on alternative digits.
			calc = Number(cardNo.charAt(i)) * j;

			// If the result is in two digits add 1 to the checksum total
			if (calc > 9)
			{
				checksum = checksum + 1;
				calc = calc - 10;
			}

			// Add the units element to the checksum total
			checksum = checksum + calc;

			// Switch the value of j
			if (j == 1) { j = 2 } else { j = 1 };
		}

		// All done - if checksum is divisible by 10, it is a valid modulus 10.
		// If not, report an error.
		if (checksum % 10 != 0)
		{
			ccErrorNo = 3;
			return false;
		}
	}

	// The following are the card-specific checks we undertake.
	var LengthValid = false;
	var PrefixValid = false;
	var undefined;

	// We use these for holding the valid lengths and prefixes of a card type
	var prefix = new Array();
	var lengths = new Array();

	// Load an array with the valid prefixes for this card
	prefix = cards[cardType].prefixes.split(",");

	// Now see if any of them match what we have in the card number
	for (i = 0; i < prefix.length; i++)
	{
		var exp = new RegExp("^" + prefix[i]);
		if (exp.test(cardNo)) PrefixValid = true;
	}

	// If it isn't a valid prefix there's no point at looking at the length
	if (!PrefixValid)
	{
		ccErrorNo = 3;
		return false;
	}

	// See if the length is valid for this card
	lengths = cards[cardType].length.split(",");
	for (j = 0; j < lengths.length; j++)
	{
		if (cardNo.length == lengths[j]) LengthValid = true;
	}

	// See if all is OK by seeing if the length was valid. We only check the 
	// length if all else was hunky dory.
	if (!LengthValid)
	{
		ccErrorNo = 4;
		return false;
	};

	// The credit card is in the required format.
	return true;
}

Byrom.Validate = function(validateItems, showId, resultsId, errors, action, actionValue, maxErrorsDesc, maxErrors)
{//_text.maxErrors
	if (!showId)
		showId = resultsId;
	if (maxErrors == undefined || maxErrors == null)
		maxErrors = 9999999999;
	if (maxErrors == 9999999999 && maxErrorsDesc)
		maxErrors = 20;

	var elem = null;

	var isValid = false;
	var index = 0;
	var anyIndex = 0;
	var item = null;
	var group = null;
	errors = new Array();
	var anyErrors = new Array();

	if (validateItems.length > 0 && Byrom.isArray(validateItems[0]))
	{	//	its an array of groups, validate each group in turn
		for (index = 0; index < validateItems.length; index++)
		{
			anyErrors = new Array();
			group = validateItems[index];
			isValid = Byrom._validateGroup(group, errors, anyErrors, action, actionValue);
			for (anyIndex = 0; anyIndex < anyErrors.length; anyIndex++)
			{
				item = anyErrors[anyIndex];
				if (!isValid)
					item.actionOnInvalid(action, actionValue);
				else
					item.actionOnValid(action, actionValue);
			}
		}
	}
	else
	{	//	its a group already validate just this
		isValid = Byrom._validateGroup(validateItems, errors, anyErrors, action, actionValue);
		for (anyIndex = 0; anyIndex < anyErrors.length; anyIndex++)
		{
			item = anyErrors[anyIndex];
			if (!isValid)
				item.actionOnInvalid(action, actionValue);
			else
				item.actionOnValid(action, actionValue);
		}
	}


	//	display errors on target element
	if (resultsId)
	{
		elem = document.getElementById(resultsId);
		if (elem)
		{
			var html = '';
			for (var errorIndex = 0; errorIndex < errors.length && errorIndex < maxErrors; errorIndex++)
			{
				var errorItem = errors[errorIndex];
				if (errorItem.message && errorItem.message != '')
				{
					if (html != '')
						html += '<br/>';
					html += (errorIndex + 1).toString() + '. ' + errorItem.message;
				}
			}
			if (errors.length > maxErrors && maxErrorsDesc)
			{
				//	(maxErrors + 1).toString() + '. ' + 
				html += '<br/><br/>' + Byrom.formatString(maxErrorsDesc, errors.length, maxErrors) + '<br/>';
			}
			elem.innerHTML = html;
		}
	}
	//	make target element visible ?
	if (errors.length > 0)
		Byrom.show(showId);
	else
		Byrom.hide(showId);

	//	move focus to 1st error
	if (errors.length > 0)
	{
		elem = document.getElementById(errors[0].id);
		if (elem)
		{
			try
			{
				elem.focus();
				elem.select();
			}
			catch (ex) { ; }
		}
	}
	return errors.length == 0;
};

Byrom._validateGroup = function(validateItems, errors, anyErrors, action, actionValue)
{
	var index = 0;
	var item = null;
	if (!errors)
		errors = new Array();
	if (!anyErrors)
		anyErrors = new Array();
	var errorsLength = errors.length;
	//var anyErrors = new Array();

	for (index = 0; index < validateItems.length; index++)
	{
		item = validateItems[index];
		if (item.type == 'any')
			anyErrors.push(item);
		else if (!item.validate(action, actionValue))
			errors.push(item.clone());
	}
	return errorsLength == errors.length;
};



Byrom.ValidateItem = function(id, labelId, message, type, compareId, messageCompare, min, max, monthId, yearId, action, actionValue, validateFunc)
{
	this.id = id;
	this.labelId = labelId;
	this.message = message;
	this.type = type;
	this.compareId = compareId;
	this.messageCompare = messageCompare;
	this.min = min;
	this.max = max;
	this.monthId = monthId;
	this.yearId = yearId;
	this.action = action;
	this.actionValue = actionValue;
	this.validateFunc = validateFunc;
	this.initialize();
};

Byrom.ValidateItem.prototype =
{
	initialize: function()
	{
		if (!this.action)
			this.action = 'class';
		if (!this.actionValue)
			this.actionValue = 'validateError';
	},
	validate: function(action, actionValue)
	{
		var valid = this.isValid();
		if (valid)
			this.actionOnValid(action, actionValue);
		else
			this.actionOnInvalid(action, actionValue);
		return valid;
	},
	isValid: function()
	{
		if (this.validateFunc &&
				((typeof this.validateFunc == 'function' && !this.validateFunc())
						|| (typeof this.validateFunc == 'object' && this.validateFunc.validate && !this.validateFunc.validate())))
			return false;

		var value = null;
		var elem = document.getElementById(this.id)
		var index = 0;
		if (elem || (this.type == 'date' && !this.id && (!!this.monthId && !!this.yearId)))	//	may be MY date with no day
		{
			var type = this.type;
			if (!type)
			{
				var tagName = elem.tagName.toLowerCase();
				switch (tagName)
				{
					case 'input':
						type = 'text';
						break;
					case 'select':
						type = 'select';
						break;
					default:
				}
			}

			switch (type)
			{
				case 'text':
					value = elem.value;
					value = value.replace(/[\s\t.]/g, '');
					if (value == "" && (isNaN(this.min) || this.min > 0))
						return false;
					if (!isNaN(this.min) && value.length < this.min)
						return false;
					if (!isNaN(this.max) && value.length > this.max)
						return false;
					break;
				case 'select':
					if ((!elem.selectedIndex || elem.selectedIndex < 0) && (isNaN(this.min) || elem.value < this.min))
					//if (!elem.value && (isNaN(this.min) || elem.value < this.min))
						return false;
					break;
				case 'email':
					if (elem.value == "" && (isNaN(this.min) || this.min > 0))
						return false;
					if (!isNaN(this.min) && elem.value.length < this.min)
						return false;
					if (!isNaN(this.max) && elem.value.length > this.max)
						return false;
					if (!Byrom.emailIsValid(elem.value))
						return false;
					break;
				case 'url':
					if (elem.value == "" && (isNaN(this.min) || this.min > 0))
						return false;
					if (!isNaN(this.min) && elem.value.length < this.min)
						return false;
					if (!isNaN(this.max) && elem.value.length > this.max)
						return false;
					var urlPat = "^[A-Za-z]+://[A-Za-z0-9-_]+\\.[A-Za-z0-9-_%&\?\/.=]+$";
					var matchURL = elem.value.match(urlPat);
					if (matchURL == null)
						return false;
					break;
				case 'cc':
					var cc = null;
					cc = elem.value;
					if (!cc)
					{
						return false;
					}
					//	do we have a cc type too ?
					if (this.compareId && document.getElementById(this.compareId) && document.getElementById(this.compareId).value)
					{
						return Byrom.CreditCardIsValid(cc, document.getElementById(this.compareId).value)
					}
					else
					{
						// remove non-numerics
						var v = "0123456789";
						var w = "";
						for (var i = 0; i < cc.length; i++)
						{
							var x = cc.charAt(i);
							if (v.indexOf(x, 0) != -1)
								w += x;
						}
						// validate number
						var j = w.length / 2;
						if (j < 6.5 || j > 8 || j == 7)
							return false;
						var k = Math.floor(j);
						var m = Math.ceil(j) - k;
						var c = 0;
						for (var i = 0; i < k; i++)
						{
							var a = w.charAt(i * 2 + m) * 2;
							c += a > 9 ? Math.floor(a / 10 + a % 10) : a;
						}
						for (var i = 0; i < k + m; i++) c += w.charAt(i * 2 + 1 - m) * 1;
						return (c % 10 == 0);
					}
					break;
				case 'date':
					var dt = null;
					//				if (elem.value == "" && (isNaN(this.min) || this.min > 0))
					//					return false;
					//				var dt = elem.value;
					//TODO:	this (internationalisation for months too)
					if (!!this.monthId && !!this.yearId)
					{	//	day/month/year sperate elements (does not cope with time as yet) - MAY be no day (just month/year like credit cards)
						var day = null;
						if (this.id)
						{
							day = elem.value;
							if (day != null)
								day = day.replace(/^[0]+/g, "");
							if (!day || isNaN(day) || day.toString().indexOf('.', 0) >= 0 || parseInt(day) < 1 || parseInt(day) > 31)
								return false;
						}
						else
							day = 1;
						var monthElem = document.getElementById(this.monthId);
						var yearElem = document.getElementById(this.yearId);
						if (!monthElem || !yearElem)
							return false;
						//	month as month index (0-11) or MMM	(need to do internationalisation)
						var month = null;
						if (monthElem.options)
						{	//	select
							month = monthElem.selectedIndex;
							if (monthElem.options.length == 13)
								month--;
						}
						else
						{	//	input element
							month = monthElem.value;
							if (!isNaN(month))
							{
								//	try for string (MMM format)
								month = Byrom.getMonthIndexFromShort(elem.value);
								if (month < 0)
									return false;
							}
							else
							{	//	month 1-12
								month = parseInt(month) - 1;
							}
						}
						if (month.toString().indexOf('.', 0) >= 0 || parseInt(month) < 0 || parseInt(month) > 11)
							return false;
						var year = yearElem.value;
						if (year != null)
							year = year.replace(/^[0]+/g, "");
						if (!year || isNaN(year) || year.toString().indexOf('.', 0) >= 0 || parseInt(year) < 1)	//	leave other year test for individual element validations
							return false;

						dt = new Date(year, month, day);
						if (dt == null)
							return false;
					}
					else
					{	//	single date element
						dt = Byrom.parseDate(elem.value);
					}

					if (dt == null || (this.min && dt < this.min) || (this.max && dt > this.max))
						return false;
					break;
				case 'number':
					if (elem.value == "")
						return false;
					if (isNaN(elem.value))
						return false;
					if (!isNaN(this.min) && parseFloat(elem.value) < this.min)
						return false;
					if (!isNaN(this.max) && parseFloat(elem.value) > this.max)
						return false;
					break;
				case 'integer':
					if (elem.value == "")
						return false;
					var value = elem.value;
					if (value != null)
						value = parseInt(value.replace(/^[0]+/g, ""));
					if (isNaN(value) || value.toString().indexOf('.', 0) >= 0)
						return false;
					if (!isNaN(this.min) && value < this.min)
						return false;
					if (!isNaN(this.max) && value > this.max)
						return false;
					break;
				case 'phonePrefix':
					value = elem.value;
					value = value.replace(/[\s\t()+-.]/g, '');
					if (value == "" || value.length < 1)
						return false;
					if (isNaN(value) || value.toString().indexOf('.', 0) >= 0)
						return false;
					if (!isNaN(this.min) && value < this.min)
						return false;
					if (!isNaN(this.max) && value > this.max)
						return false;
					if (!Byrom.isInteger(value))
						return false;
					break;
				case 'phone':
					value = elem.value;
					value = value.replace(/[\s\t()+-.]/g, '');
					if (value == "" || value.length < 7)
						return false;
					if (isNaN(value) || value.toString().indexOf('.', 0) >= 0)
						return false;
					if (!isNaN(this.min) && value < this.min)
						return false;
					if (!isNaN(this.max) && value > this.max)
						return false;
					if (!Byrom.isInteger(value))
						return false;
					break;
				case 'checkboxes': //	checkboxes - a stated number must be checked
					var els = elem.getElementsByTagName("*");
					value = 0;
					for (var index = 0; index < els.length; index++)
					{
						var el = els[index];
						if (el.tagName)
						{
							var tagName = el.tagName.toLowerCase();
							if ((tagName == 'input' && el.type.toLowerCase() == 'checkbox'))	//	 && !el.readOnly  && !el.disabled)
							{
								if (el.checked)
									value++;
							}
						}
					}
					if (!isNaN(this.min) && value < this.min)
						return false;
					if (!isNaN(this.max) && value > this.max)
						return false;
					break;
				default:
			}
		}
		return true;
	},
	actionOnInvalid: function(action, actionValue)
	{	//	need to check "action" and "this.action" - something like 'class' or 'asterix'
		//	if (action == 'class')
		//		Byrom.addClass(this.id, actionValue);
		if (!actionValue)
			actionValue = this.actionValue;
		this.actionOnInvalidIds(this.id, actionValue); // Byrom.addClass(this.id, actionValue);
		this.actionOnInvalidIds(this.labelId, actionValue); //	Byrom.addClass(this.labelId, actionValue);
		if (this.type == 'date')
		{
			if (this.monthId)
				this.actionOnInvalidIds(this.monthId, actionValue); //	Byrom.addClass(this.monthId, actionValue);
			if (this.yearId)
				this.actionOnInvalidIds(this.yearId, actionValue); //	Byrom.addClass(this.monthId, actionValue);
		}

		//		//	ie problem - does not support border in css
		//		var el = document.getElementById(this.id)
		//		if (el.tagName.toLowerCase() == 'select')
		//		{
		//			var parentId = '_validate_' + el.id;
		//			if (el.parentNode.id != parentId)
		//				//el.outerHTML = '<div id="' + parentId + '" class="validateErrorContainer" >' + el.outerHTML + '</div>';				
		//				el.outerHTML = '<div id="' + parentId + '" style="border:1px solid red;background-color:Red;display:inline;pa">' + el.outerHTML + '<div>';				
		//				
		//				
		//		}
	},
	actionOnValid: function(action, actionValue)
	{
		if (!actionValue)
			actionValue = this.actionValue;
		this.actionOnValidIds(this.id, actionValue);
		this.actionOnValidIds(this.labelId, actionValue);
		if (this.type == 'date')
		{
			if (this.monthId)
				this.actionOnValidIds(this.monthId, actionValue);
			if (this.yearId)
				this.actionOnValidIds(this.yearId, actionValue);
		}

		//		//	ie problem - does not support border in css
		//		var el = document.getElementById(this.id)
		//		if (el.tagName.toLowerCase() == 'select')
		//		{
		//			var parentId = '_validate_' + el.id;
		//			if (el.parentNode.id == parentId)
		//			{
		//				var parentEl = document.getElementById(parentId)
		//				parentEl.outerHTML = el.outerHTML;
		//			}
		//		}
	},
	actionOnInvalidIds: function(id, value)
	{//	need to check "action" and "this.action" - something like 'class' or 'asterix'
		//	if (action == 'class')
		//		Byrom.addClass(this.id, actionValue);
		var ids = this.getArrayOfIds(id);
		for (var index = 0; index < ids.length; index++)
		{
			Byrom.addClass(id, value);
		}
	},
	actionOnValidIds: function(id, value)
	{
		var ids = this.getArrayOfIds(id);
		for (var index = 0; index < ids.length; index++)
		{
			Byrom.removeClass(id, value);
		}
	},
	getArrayOfIds: function(id)
	{
		var ids = new Array();
		if (typeof id == 'object' && id.length)
			return id;
		else
			ids.push(id);
		return ids;
	},
	clone: function()
	{
		return new Byrom.ValidateItem(this.id, this.labelId, this.message, this.type, this.compareId, this.messageCompare, this.min, this.max, this.monthId, this.yearId, this.action, this.actionValue);
	}
};

Byrom.CountDownTimer = function(id, endDate, intervalMs, timerVariableName, onCompleteEval, displayStyle, adjustTimeZone)
{
	this.Id = id;
	if (adjustTimeZone)
		endDate.setMinutes(endDate.getMinutes() - endDate.getTimezoneOffset());
	this.EndDate = endDate;
	this.IntervalMs = intervalMs;
	this.TimerVariableName = timerVariableName;
	this.DisplayStyle = 'Images'; //	'Text'
	if (displayStyle)
		this.DisplayStyle = displayStyle;
	this.DigitTemplate = "<div class='countDown{0}'></div>";
	this.SepTemplate = "<div class='countDownSep'></div>";
	this.Enabled = false;
	this.StartOffsetMs = 0;
	this.DisplayCurrent = function()
	{
		if (!this.Enabled)
			return;
		var now = new Date();
		var el = document.getElementById(this.Id);
		if (el)
		{
			var timeToGo = 0;
			if (now < this.EndDate)
				timeToGo = this.EndDate - now;
			timeToGo = new Date(0, 0, 0, 0, 0, 0, timeToGo);
			var hours = timeToGo.getHours();
			var minutes = timeToGo.getMinutes();
			var seconds = timeToGo.getSeconds();
			if (hours < 10)
				hours = "0" + hours;
			if (minutes < 10)
				minutes = "0" + minutes;
			if (seconds < 10)
				seconds = "0" + seconds;
			var html = '';
			if (this.DisplayStyle.toLowerCase() == 'images')
			{
				html += Byrom.formatString(this.DigitTemplate, hours.toString().substr(0, 1)) + Byrom.formatString(this.DigitTemplate, hours.toString().substr(1, 1)) + this.SepTemplate;
				html += Byrom.formatString(this.DigitTemplate, minutes.toString().substr(0, 1)) + Byrom.formatString(this.DigitTemplate, minutes.toString().substr(1, 1)) + this.SepTemplate;
				html += Byrom.formatString(this.DigitTemplate, seconds.toString().substr(0, 1)) + Byrom.formatString(this.DigitTemplate, seconds.toString().substr(1, 1));
			}
			else
			{
				html += hours + ":" + minutes + ":" + seconds;
			}
			el.innerHTML = html;
		}
		if (now < this.EndDate)
			setTimeout(this.TimerVariableName + ".DisplayCurrent()", this.IntervalMs + this.StartOffsetMs);
		else
		{
			this.Enabled = false;
			if (onCompleteEval)
				eval(onCompleteEval);
		}
		this.StartOffsetMs = 0;
	};
	this.Start = function()
	{
		this.Enabled = true;
		var now = new Date();
		if (now.getMilliseconds() < 900)
			this.StartOffsetMs = now.getMilliseconds() - 900;
		this.DisplayCurrent();
	};
	this.Stop = function()
	{
		this.Enabled = false;
	};
};


Byrom.localize();