/* this is a subset from formValidation.js */
var formValidation = {
	init: function (form, labelClassOnError, errorMessages, onSuccess) {
		var errorHandler = this.errorHandler;
		var idToLabel = new Object();
		var els, vals, i, j;
		if (!form || typeof labelClassOnError != 'string' || !errorMessages) {
			return;
		}
		els = form.getElementsByTagName('label');
		for (i = els.length - 1; i >= 0; i--) {
			if (els[i].htmlFor) {
				idToLabel[els[i].htmlFor] = els[i];
			}
		}
		els = form.elements;
		for (i = els.length - 1; i >= 0; i--) {
			vals = els[i].validators;
			if (vals) {
				for (j = vals.length - 1; j >= 0; j--) {
					vals[j].errorHandler = errorHandler;
				}
			}
		}
		form.idToLabel = idToLabel;
		form.labelClassOnError = labelClassOnError;
		form.errorMessages = errorMessages;
		form.onSuccess = onSuccess;
		form.onsubmit = this.performValidation;
	},

	uninit: function (form) {
		var els, vals, i, j;
		if (!form) {
			return;
		}
		this.resetLabels(form);
		els = form.elements;
		for (i = els.length - 1; i >= 0; i--) {
			vals = els[i].validators;
			if (vals) {
				for (j = vals.length - 1; j >= 0; j--) {
					vals[j].errorHandler = null;
				}
			}
		}
		form.idToLabel = form.labelClassOnError = form.errorMessages = form.onSuccess = form.onsubmit = null;
	},

	getHighlightLabels: function (el, obj) {
		var labels = new Array();
		var l = 0;
		var idToLabel = el.form.idToLabel;
		var thing = (obj.highlightId) ? obj.highlightId : el.id;
		var ids = new Array();
		var highlightEl, i;
		if (typeof thing == 'function') {
			ids = thing();
		}
		else if (typeof thing == 'string') {
			ids = [thing];
		}
		else if (thing && thing.length > 0) {
			ids = thing;
		}
		for (i = 0; i < ids.length; i++) {
			highlightEl = idToLabel[ids[i]];
			if (highlightEl) {
				labels[l++] = highlightEl;
			}
		}
		return labels;
	},

	errorHandler: function (el) {
		var form = el.form;
		var labels = formValidation.getHighlightLabels(el, this);
		var cn = form.labelClassOnError;
		var i;
		for (i = labels.length - 1; i >= 0; i--) {
			className.add(labels[i], cn);
		}
		if (!form.errEl && !form.errObj) {
			form.errEl = el;
			form.errObj = this;
		}
	},

	resetLabels: function (form) {
		var idToLabel = form.idToLabel;
		var cn = form.labelClassOnError;
		var id;
		for (id in idToLabel) {
			className.remove(idToLabel[id], cn);
		}
		form.errEl = form.errObj = null;
	},

	showErrorAlert: function (form) {
		var errEl = form.errEl;
		var errObj = form.errObj;
		var focusThis;
		if (errEl && errObj) {
			if (errObj.errorKey) {
				alert(form.errorMessages[errObj.errorKey]);
			}
			focusThis = (errObj.focusThis) ? errObj.focusThis : errEl;
			if (focusThis.focus) {
				focusThis.focus();
			}
		}
	},

	performValidation: function () {
		var els = this.elements;
		var result = true;
		var el, vals, i, j;
		formValidation.resetLabels(this);
		for (i = els.length - 1; i >= 0; i--) {
			el = els[i];
			vals = el.validators;
			if (vals) {
				for (j = vals.length - 1; j >= 0; j--) {
					if (vals[j].reset) {
						vals[j].reset(el);
					}
				}
			}
			el.performValidation = true;
		}
		for (i = 0; i < els.length; i++) {
			el = els[i];
			vals = el.validators;
			if (vals) {
				for (j = 0; j < vals.length; j++) {
					if (el.performValidation && !vals[j].validator(el)) {
						if (vals[j].errorHandler) {
							vals[j].errorHandler(el);
						}
						result = false;
					}
				}
			}
		}
		formValidation.showErrorAlert(this);
		if (result && this.onSuccess) {
			this.onSuccess();
		}
		return result;
	},

	getFieldValue: function (el) {
		var result = '';
		if (el.nodeName) {
			switch (el.nodeName) {
			case 'INPUT':
			case 'TEXTAREA':
				if (el.type == 'checkbox' || el.type == 'radio') {
					if (el.checked) {
						result = 'checked';
					}
				}
				else {
					result = el.value;
				}
				break;
			case 'SELECT':
				if ((el.ignoreFirstOption && el.selectedIndex > 0) || (!el.ignoreFirstOption && el.selectedIndex >= 0)) {
					result = el.options[el.selectedIndex].value;
				}
				break;
			}
		}
		else if (typeof el == 'string') { 
			result = el;
		}
		return result.replace(/(^\s+|\s+$)/g, '');
	},

	notBlankValidator: function (el) {
		return (formValidation.getFieldValue(el).length > 0);
	},
	
	festivalNumberValidator: function (el) {
		return (formValidation.getFieldValue(el).search(/^[0-9]{0,5}$/)!=-1);
	},

	dateRangeValidator: function (el){
		var yyyy, mm;
		if (el.id.indexOf('year')){
			mm = parseInt(formValidation.getFieldValue(document.getElementById(el.id.substring(0, el.id.indexOf('year')) + 'month')));
			yyyy = parseInt(formValidation.getFieldValue(el));
		}else{
			mm = parseInt(formValidation.getFieldValue(el));
			yyyy = parseInt(formValidation.getFieldValue(document.getElementById(el.id.substring(0, el.id.indexOf('month')) + 'year')));
		}
		var ranges = this.ranges;
		if ((mm<ranges[0][0] && yyyy==ranges[0][1]) || (mm>ranges[1][0] && yyyy==ranges[1][1])){
			return false;
		}
		return true;
	},

	characterRangeValidator: function (el) {
		var value = formValidation.getFieldValue(el);
		var ranges = this.ranges;
		var min = new Array();
		var max = new Array();
		var isValid, i, j, c;

		for (i = ranges.length - 1; i >= 0; i--) {
			j = ranges[i];
			/* can't use instanceof because it doesn't exist in ie/mac */
			if (j && j.length >= 2) {
				min[i] = j[0];
				max[i] = j[1];
			}
		}

		for (i = value.length - 1; i >= 0; i--) {
			c = value.charCodeAt(i);
			isValid = false;
			for (j = min.length - 1; j >= 0; j--) {
				if (c >= min[j] && c <= max[j]) {
					isValid = true;
					break;
				}
			}
			if (!isValid) {
				return false;
			}
		}
		return true;
	},

	lengthValidator: function (el) {
		var len = formValidation.getFieldValue(el).length;
		var ranges = this.ranges;
		var min, max, i;

		for (i = ranges.length - 1; i >= 0; i--) {
			min = ranges[i][0];
			max = ranges[i][1];
			if (len >= min && len <= max) {
				return true;
			}
		}
		return false;
	},

	emailLocalValidator: function (el) {
		return (formValidation.getFieldValue(el).search(/[^\w+.-]/) == -1);
	},

	domainValidator: function (el) {
		var labels = formValidation.getFieldValue(el).replace(/\.$/, '').split('.');
		var i;
		if (labels.length < 2) {
			return false;
		}
		for (i = labels.length - 1; i >= 0; i--) {
			if (labels[i].search(/^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?$/) == -1) {
				return false;
			}
		}
		return true;
	},

	emailValidator: function (el) {
		var email = formValidation.getFieldValue(el);
		var atpos = email.indexOf('@');
		var local, domain;
		if (atpos > -1) {
			local = email.substring(0, atpos);
			domain = email.substring(atpos + 1);
			return (formValidation.emailLocalValidator(local) && formValidation.domainValidator(domain));
		}
    return false;
	},

//updated by jeffrey begin

	creditcard_no_invalid: function (el) {
		var card_no = formValidation.getFieldValue(el);
		var reg = /\D/; 
		if(card_no.length != 4) return;
		return card_no.match(reg)==null; 
	},

	name_invalid: function (el) {
		var strName = formValidation.getFieldValue(el);
		var badChar = "0123456789";
		badChar += "";
		var c;
		for(var i=0; i<strName.length; i++)
		{
			c = strName.charAt(i);
			if(badChar.indexOf(c) > -1) return false;
		}
		return true;
	},
//updated by jeffrey end
	card_number_validator: function (el) {
		var type = this.type;
		if(type.selectedIndex<0){return;};
		var num = formValidation.getFieldValue(el).replace(/\s+/g, '');
		if (type.options[type.selectedIndex].value==('HKAF Master')) {
			return (num.indexOf('54027488') == 0 || num.indexOf('54029088') == 0);
		}else{
			return formValidation.checkCreditCard(num, type.options[type.selectedIndex].value);
		}
		return true;
	},
	// http://www.braemoor.co.uk/software/creditcard.shtml
	checkCreditCard: function (cardnumber, cardname) {
		var cards = new Array();
		cards = [
			{name: "Visa", 
			   length: "13,16", 
			   prefixes: "4",
			   checkdigit: true},
			{name: "MasterCard", 
			   length: "16", 
			   prefixes: "51,52,53,54,55",
			   checkdigit: true},
			{name: "Diners", 
			   length: "14,16", 
			   prefixes: "300,301,302,303,304,305,36,38,55",
			   checkdigit: true},
			{name: "American", 
			   length: "15", 
			   prefixes: "34,37",
			   checkdigit: true},
			{name: "AE", 
			   length: "15", 
			   prefixes: "34,37",
			   checkdigit: true}
		];
		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; 
		}

		// Now remove any spaces from the credit card number
		cardnumber = cardnumber.replace (/\s/g, "");

		// Check that the number is numeric
		var cardNo = cardnumber
		var cardexp = /^[0-9]{13,19}$/;
		if (!cardexp.exec(cardNo))  {
			ccErrorNo = 2;
			return false; 
		}
		   
		// 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;
	},

	firstNotBlankGroupActivator: function (el) {
		var getFieldValue = formValidation.getFieldValue;
		var groups = this.groups;
		var activated = -1;
		var group, i, j;
		for (i = 0; i < groups.length; i++) {
			group = groups[i];
			for (j = group.length - 1; j >= 0; j--) {
				if (getFieldValue(group[j]).length > 0) {
					activated = i;
					break;
				}
			}
			if (activated != -1) {
				break;
			}
		}
		for (i = groups.length - 1; i >= 0; i--) {
			group = groups[i];
			for (j = group.length - 1; j >= 0; j--) {
				group[j].performValidation = (i == activated);
			}
		}
		return (activated != -1);
	},

	allOrNoneActivator: function (el) {
		var getFieldValue = formValidation.getFieldValue;
		var fields = this.fields;
		var activated = false;
		var i;
		for (i = fields.length - 1; i >= 0; i--) {
			if (getFieldValue(fields[i]).length > 0) {
				activated = true;
				break;
			}
		}
		for (i = fields.length - 1; i >= 0; i--) {
			fields[i].performValidation = activated;
		}
		return true;
	}
};

var dom = {
	is_descendent: function (desc, asc) {
		while (desc && desc != asc && desc.nodeName != 'BODY' && desc.parentNode) {
			desc = desc.parentNode;
		}
		return (desc == asc);
	},

	move_children: function (from, to) {
		var a = new Array();
		var i;
		for (i = from.childNodes.length - 1; i >= 0; i--) {
			a[i] = from.childNodes[i];
		}
		for (i = 0; i < a.length; i++) {
			to.appendChild(a[i]);
		}
	},

	find_position: function (el) {
		var left = 0;
		var top = 0;
		if (el.offsetParent) {
			left = el.offsetLeft;
			top = el.offsetTop;
			while (el.offsetParent) {
				el = el.offsetParent;
				left += el.offsetLeft;
				top += el.offsetTop;
			}
		}
		return [left, top];
	}
}

var className = {
	has: function (el, cn) {
		if (!el || typeof cn != 'string') {
			return false;
		}
		return (el.className && el.className.search && el.className.search(new RegExp('\\b' + cn + '\\b')) != -1);
	},

	add: function (el, cn) {
		if (!el || typeof cn != 'string') {
			return false;
		}
		if (!className.has(el, cn)) {
			el.className += ' ' + cn;
		}
		return true;
	},

	remove: function (el, cn) {
		var c;
		if (!el || typeof cn != 'string') {
			return false;
		}
		if (className.has(el, cn)) {
			c = el.className.replace(new RegExp('\\b' + cn + '\\b'), '');
			c = c.replace(/^ +| +$/g, ''); /* is all this */
			c = c.replace(/ {2,}/g, ' ');  /* necessary?  */
			el.className = c;
		}
		return true;
	},

	toggle: function (el, cn) {
		if (!el || typeof cn != 'string') {
			return false;
		}
		if (hasClass(el, cn)) {
			removeClass(el, cn);
		}
		else {
			addClass(el, cn);
		}
		return true;
	},

	getElementsByClassName: function (root, tag, cn) {
		var list = new Array();
		var l = 0;
		var els, i;
		if (!root || !tag || typeof cn != 'string') {
			return null;
		}
		els = root.getElementsByTagName(tag);
		for (i = els.length - 1; i >= 0; i--) {
			if (className.has(els[i], cn)) {
				list[l++] = els[i];
			}
		}
		return list.reverse();
	}
};

var tabs = {
	init: function (tab_list, pane_list, func) {
		var data = { current: null, onswitch: func };
		var tab, i;
		if (!tab_list || !pane_list || tab_list.length != pane_list.length) {
			return;
		}
		for (i = tab_list.length - 1; i >= 0; i--) {
			tab = tab_list[i];
			tab.tab_data = data;
			tab.tab_pane = pane_list[i];
			tab.onclick = tabs.switch_to;
		}
	},

	uninit: function (tab_list) {
		var tab, i;
		if (!tab_list) {
			return;
		}
		for (i = tab_list.length - 1; i >= 0; i--) {
			tab = tab_list[i];
			tab.tab_data = tab.tab_pane = tab.onclick = null;
		}
	},

	switch_to: function () {
		var data = this.tab_data;
		if (data.onswitch) {
			data.onswitch(data.current, this);
		}
		if (data.current) {
			className.remove(data.current.tab_pane, 'shown');
		}
		className.add(this.tab_pane, 'shown');
		data.current = this;
		if (this.blur) {
			this.blur();
		}
		return false;
	}
};

var dummy_field_text = {
	init: function (field, dummy, replace_even_if_dummy) {
		if (!field || typeof dummy != 'string') {
			return;
		}
		if (field.value != '') {
			if (replace_even_if_dummy) {
				if (field.value != dummy) {
					return;
				}
			}
			else {
				return;
			}
		}
		field.value = dummy;
		field.is_dummy_text = true;
		field.onfocus = dummy_field_text.clear;
	},

	uninit: function (field) {
		if (!field) {
			return;
		}
		if (field.is_dummy_text) {
			field.value = ''; /* this is suppose to stop explorer from remembering the dummy text, but... */
		}
		field.is_dummy_text = field.onfocus = null;
	},

	clear: function () {
		if (this.is_dummy_text) {
			this.value = '';
			this.is_dummy_text = false;
		}
	}
};

var clickable_labels = {
	init: function (label_list, field_list) {
		var label, field, i;
		if (!label_list) {
			return;
		}
		for (i = label_list.length - 1; i >= 0; i--) {
			label = label_list[i];
			if (label.htmlFor) {
				field = (field_list) ? field_list[i] : document.getElementById(label.htmlFor);
				if (field) {
					label.style.cursor = 'default';
					label.for_field = field;
					label.onclick = clickable_labels.label_click;
				}
			}
		}
	},

	uninit: function (label_list) {
		var label, i;
		if (!label_list) {
			return;
		}
		for (i = label_list.length - 1; i >= 0; i--) {
			label = label_list[i];
			label.style.cursor = '';
			label.for_field = label.onclick = null;
		}
	},

	label_click: function () {
		var field = this.for_field;
		var result;
		switch (field.nodeName) {
		case 'INPUT':
			switch (field.type) {
			case 'text':
			case 'password':
				if (field.focus) {
					field.focus();
					result = false;
				}
				break;
			case 'checkbox':
			case 'radio':
				if (field.click) {
					field.click();
					result = false;
				}
				break;
			}
			break;
		case 'SELECT':
		case 'TEXTAREA':
			if (field.focus) {
				field.focus();
				result = false;
			}
			break;
		}
		return result;
	}
}

/* this assumes that:
	the first segment of location.pathname is the current language
		e.g. location.pathname == '/en/...'
	the last segment of the href of each switch_lang link is the target language
		e.g. href = '.../tc/'
*/
var switch_lang = {
	init: function (el) {
		var current_lang, target_lang, els, a, i;
		if (!el) {
			return;
		}
		current_lang = '/' + switch_lang.find_lang(location.pathname, true) + '/';
		els = el.getElementsByTagName('a');
		for (i = els.length - 1; i >= 0; i--) {
			a = els[i];
			if (a.rel.indexOf('switch_lang') > -1) {
				target_lang = '/' + switch_lang.find_lang(a.href, false) + '/';
				a.href = location.href.replace(current_lang, target_lang);
			}
		}
	},

	find_lang: function (str, first) {
		var matches;
		if (typeof str != 'string') {
			return '';
		}
		matches = str.replace(/^\//, '').replace(/\/$/, '').split('/');
		return (first) ? matches[0] : matches[matches.length - 1];
	}
}

var print_button = {
	init: function (button_list, a_className) {
		var button, a, i;
		if (!button_list) {
			return;
		}
		for (i = button_list.length - 1; i >= 0; i--) {
			button = button_list[i];
			a = document.createElement('a');
			a.href = '#';
			a.className = a_className;
			a.onclick = print_button.print;
			dom.move_children(button, a);
			button.appendChild(a);
		}
	},

	uninit: function (button_list) {
		var button, a, i;
		if (!button_list) {
			return;
		}
		for (i = button_list.length - 1; i >= 0; i--) {
			button = button_list[i];
			a = button.firstChild;
			a.onclick = null;
			button.removeChild(a);
			dom.move_children(a, button);
		}
	},

	print: function () {
		window.print();
		return false;
	}
}

var image_form_buttons = {
	init: function (button_list, a_className) {
		var button, a, img, i;
		if (!button_list) {
			return;
		}
		for (i = button_list.length - 1; i >= 0; i--) {
			button = button_list[i];
			a = document.createElement('a');
			a.href = '#';
			a.className = (button.className) ? button.className : button.value;
			if (a_className) {
				a.className = a_className + ' ' + a.className;
			}
			a.type = button.type;
			a.value = button.value;
			a.form = button.form;
			a.onclick = this.button_click;
			img = document.createElement('img');
			img.src = button.src;
			img.alt = (button.alt) ? button.alt : button.value;
			button.parentNode.insertBefore(a, button.nextSibling);
			button.style.position = 'absolute';
			button.style.left = '-5000px';
			button.style.top = '-5000px';
			a.appendChild(img);
			button.new_button = a;
			a.old_button = button;
		}
	},

	uninit: function (button_list) {
		var button, a, i;
		if (!button_list) {
			return;
		}
		for (i = button_list.length - 1; i >= 0; i--) {
			button = button_list[i];
			a = button.new_button;
			a.onclick = a.form = a.oldbutton = null;
			a.parentNode.removeChild(a);
			button.style.position = button.style.left = button.style.top = '';
			button.new_button = null;
		}
	},

	button_click: function () {
		var do_blur = true;
		var result;
		switch (this.type) {
		case 'reset':
			this.form.reset();
			break;
		case 'submit':
			/*
			if (this.form.onsubmit) {
				result = this.form.onsubmit();
			}
			if (result != false) {
				this.form.submit();
			}
			else {
				do_blur = false;
			}
			*/
			/* in learned circles, this is known as an ugly hack */
			if (this.old_button.value.toLowerCase().indexOf('skip') > -1) {
				this.form.onsubmit = null;
			}
			this.old_button.click();
			do_blur = false;
			break;
		}
		if (do_blur && this.blur) {
			this.blur();
		}
		return false;
	}
};

var popup = {
	init: function (button_list, a_className) {
		var button, a, i;
		if (!button_list) {
			return;
		}
		for (i = button_list.length - 1; i >= 0; i--) {
			button = button_list[i];
			switch (button.popup_type) {
			case 'open':
				button.onclick = this.open;
				break;
			case 'close':
				a = document.createElement('a');
				a.href = '#';
				a.className = (a_className) ? a_className : '';
				a.onclick = this.close;
				dom.move_children(button, a);
				button.appendChild(a);
				break;
			}
		}
	},

	uninit: function (button_list) {
		var button, i;
		if (!button_list) {
			return;
		}
		for (i = button_list.length - 1; i >= 0; i--) {
			button = button_list[i];
			switch (button.popup_type) {
			case 'open':
				button.onclick = null;
				break;
			case 'close':
				a = button.firstChild;
				a.onclick = null;
				button.removeChild(a);
				dom.move_children(a, button);
				break;
			}
		}
	},

	/* do we need to test for self.screen? */
	open_window: function (url, n, w, h, f) {
		/*
		var width = (w) ? w : Math.floor(self.screen.availWidth / 2);
		var height = (h) ? h : Math.floor(self.screen.availHeight / 2);
		*/
		var width = (w) ? w : 700;
		var height = (h) ? h : 487;
		var left = Math.floor((screen.availWidth - width) / 2);
		var top = Math.floor((screen.availHeight - height) / 2);
		var name = (n) ? n : '';
		var features = 'left=' + left + ',top=' + top + ',width=' + width + ',height=' + height;
		if (f) {
			features += ',' + f;
		}
		var popup = window.open(url, name, features);
		var result = false;
		if (popup) {
			if (popup.focus) {
				popup.focus();
			}
			result = true;
		}
		return result;
	},

	open: function () {
		var success = popup.open_window(this.href, this.popup_name, this.popup_width, this.popup_height, this.popup_features);
		if (this.blur) {
			this.blur();
		}
		return !success;
	},

	close: function () {
		window.close();
		return false;
	}
};

var randomize = {
	init: function (item_list) {
		var i;
		if (!item_list) {
			return;
		}
		if (item_list.length > 1) {
			for (i = item_list.length - 1; i >= 0; i--) {
				className.add(item_list[i], 'hide');
			}
			item_list.current = null;
			if (!item_list.delay) {
				item_list.delay = 5000;
			}
			this.show_next(item_list);
		}
	},

	uninit: function (item_list) {
		var i;
		if (!item_list) {
			return;
		}
		if (item_list.length > 1) {
			if (item_list.timeout) {
				clearTimeout(item_list.timeout);
				item_list.timeout = null;
			}
			item_list.current = null;
			for (i = item_list.length - 1; i >= 0; i--) {
				className.remove(item_list[i], 'hide');
			}
		}
	},

	show_next: function (item_list) {
		var num = item_list.length;
		var prev = item_list.current;
		var rand, next;
		if (prev == null) {
			next = Math.floor(Math.random() * num); /* 0 .. num-1 */
		}
		else {
			rand = Math.floor(Math.random() * (num - 1)) + 1; /* 1 .. num-1 */
			next = (prev + rand) % num;
			className.add(item_list[prev], 'hide');
		}
		className.remove(item_list[next], 'hide');
		item_list.current = next;
		item_list.timeout = setTimeout(function () { randomize.show_next(item_list); }, item_list.delay);
	}
};

function flip_on_off(old_a, new_a) {
	var img;
	if (old_a) {
		img = old_a.getElementsByTagName('img')[0];
		img.src = img.src.replace('_on.', '_off.');
	}
	if (new_a) {
		img = new_a.getElementsByTagName('img')[0];
		img.src = img.src.replace('_off.', '_on.');
	}
}

function freeze_book_now(id) {
	if (details_book_now_img && id == 'book_now') {
		details_book_now_img.style.visibility = 'hidden';
	}
}

function unfreeze_book_now(id) {
	if (details_book_now_img && id == 'book_now') {
		details_book_now_img.style.visibility = '';
	}
}

function check_cookies() {
	var pair = 'testCookie=' + Math.random();
	var pairs, i;
	document.cookie = pair + '; path=/';
	pairs = document.cookie.split(';');
	for (i = pairs.length - 1; i >= 0; i--) {
		if (pairs[i].replace(/^\s+/, '') == pair) {
			return true;
		}
	}
	return false;
}

function book_now_cookie_check() {
	if (!cookies_enabled) {
		if (this.blur) {
			this.blur();
		}
		alert(global_messages.cookies_required);
		return false;
	}
	return true;
}

var body, header, main, related, newsletter_email, sections, section_nav;
var section_nav_links, related_print_buttons, labels, image_inputs, open_popup_links, close_popup_links, popup_lite_links, popup_lite_venue_links, details_book_now_img, special_offers;
var contact_form, donation_form, send_form, reminder_form, resender_form, ticketing_obj, programme_table;
var cookies_enabled;

function uninit() {
	tabs.uninit(section_nav_links);
	print_button.uninit(related_print_buttons);
	randomize.uninit(special_offers);
	dummy_field_text.uninit(newsletter_email);
	programme_list.init(programme_table);
	if (ticketing_obj) {
		ticketing_obj.uninit();
	}
	clickable_labels.uninit(labels);
	image_form_buttons.uninit(image_inputs);
	if (newsletter_email) {
		formValidation.uninit(newsletter_email.form);
	}
	formValidation.uninit(contact_form);
	formValidation.uninit(donation_form);
	formValidation.uninit(send_form);
	formValidation.uninit(reminder_form);
	formValidation.uninit(resender_form);
	popup.uninit(open_popup_links);
	popup.uninit(close_popup_links);
	popup_lite.uninit(popup_lite_links);
	popup_lite.uninit(popup_lite_venue_links);
}

window.onunload = uninit;



/* window.onload solution from http://dean.edwards.name/weblog/2006/06/again/ */
// Dean Edwards/Matthias Miller/John Resig

function init() {
	// quit if this function has already been called
	if (arguments.callee.done) return;

	// flag this function so we don't do the same thing twice
	arguments.callee.done = true;

	// kill the timer
	if (_timer) {
		clearInterval(_timer);
		_timer = null;
	}

	// do stuff

	body = document.body;
	header = document.getElementById('header');
	main = document.getElementById('main');
	related = document.getElementById('related');
	newsletter_email = document.getElementById('newsletter_email');
	var flash_container, use_flash, so, els, el, i;

	cookies_enabled = check_cookies();

	if (header) {
		switch_lang.init(header);
	}

	flash_container = document.getElementById('flash_content');
	if (flash_container) {
		use_flash = false;
		if (typeof flash_content == 'string') {
			so = new SWFObject(flash_content, 'body_swf', '950', '400', '8', '#000000');
			so.addParam('allowScriptAccess', 'sameDomain');
			so.addParam('scale', 'noscale');
			if (typeof flash_xml == 'string') {
				so.addVariable('xmlPath', flash_xml);
			}
			use_flash = so.write(flash_container);
		}
		if (!use_flash) {
			className.add(flash_container, 'no_flash');
		}
	}

	flash_container = document.getElementById('flash_heading');
	if (flash_container) {
		use_flash = false;
		if (typeof flash_heading == 'string') {
                        //comment by michael for interim site
			//so = new SWFObject(flash_heading, 'swfgallery', '738', '315', '8', '#ffffff');
                        //added by michael for interim site
			so = new SWFObject(flash_heading, 'swfgallery', '950', '320', '8', '#000000');
			so.addParam('allowScriptAccess', 'sameDomain');
			so.addParam('wmode', 'transparent');
			if (typeof flash_xml == 'string') {
				so.addVariable('xmlPath', flash_xml);
			}
			if (typeof flash_lang == 'string') {
				so.addVariable('lang', flash_lang);
			}
			use_flash = so.write(flash_container);
		}
		if (!use_flash) {
			className.add(flash_container, 'no_flash');
		}
	}

	flash_container = document.getElementById('flash_slideshow');
	if (flash_container) {
		use_flash = false;
		if (typeof flash_slideshow == 'string') {
			so = new SWFObject(flash_slideshow, 'photogallery', '323', '250', '8', '#ffffff');
			so.addParam('allowScriptAccess', 'sameDomain');
			if (typeof flash_xml == 'string') {
				so.addVariable('xmlPath', flash_xml);
			}
			use_flash = so.write(flash_container);
		}
		if (!use_flash) {
			className.add(flash_container, 'no_flash');
		}
	}

	flash_container = document.getElementById('flash_planner');
	if (flash_container) {
		if (!cookies_enabled) {
			i = function () { alert(global_messages.cookies_required); };
			if (window.addEventListener) {
				window.addEventListener('load', i, false);
			}
			else if (window.attachEvent) {
				window.attachEvent('onload', i);
			}
			else {
				i();
			}
		}
		use_flash = false;
		if (typeof flash_planner == 'string') {
			so = new SWFObject(flash_planner, 'planner', '950', '580', '8', '#ffffff');
			so.addParam('allowScriptAccess', 'sameDomain');
			if (typeof flash_xml == 'string') {
				so.addVariable('xmlPath', flash_xml);
			}
			use_flash = so.write(flash_container);
		}
		if (!use_flash) {
			className.add(flash_container, 'no_flash');
		}
	}

	if (main) {
		els = className.getElementsByClassName(main, 'div', 'sections');
		if (els && els.length > 0) {
			sections = els[0];
		}
		els = className.getElementsByClassName(main, 'ul', 'section_nav');
		if (els && els.length > 0) {
			section_nav = els[0];
		}
		if (sections && section_nav) {
			section_nav_links = section_nav.getElementsByTagName('a');
			tabs.init(section_nav_links, className.getElementsByClassName(sections, 'div', 'section'), flip_on_off);
			section_nav_links[0].onclick();
		}
	}

	if (related) {
		els = className.getElementsByClassName(related, 'a', 'add_to_planner');
		if (els && els.length > 0) {
			/* i'm the king of the world */
			i = location.pathname.substring(0, 3); /* hack */
			el = document.createElement('img');
			el.src = '/images' + i + '/programme/sending_details.gif';
			el.alt = programme_list_messages.sending;
			el.className = 'add_to_planner_image';
			programme_list.sending = el;
			el = document.createElement('img');
			el.src = '/images' + i + '/programme/add_in.gif';
			el.alt = programme_list_messages.added_to_planner;
			el.className = 'add_to_planner_image';
			programme_list.added = el;
			els[0].onclick = programme_list.add_to_planner;
		}
		els = className.getElementsByClassName(related, 'a', 'book_now');
		if (els && els.length > 0) {
			details_book_now_img = els[0].getElementsByTagName('img')[0];
			/* hack */
			popup_lite.onopen = freeze_book_now;
			popup_lite.onclose = unfreeze_book_now;
		}
		related_print_buttons = className.getElementsByClassName(related, 'li', 'print');
		print_button.init(related_print_buttons, 'rollover print');

		els = className.getElementsByClassName(related, 'ul', 'sponsors');
		if (els && els.length > 0) {
			special_offers = className.getElementsByClassName(els[0], 'li', 'offer');
			randomize.init(special_offers);
		}
	}

	dummy_field_text.init(newsletter_email, newsletter_email_dummy_text, true);

	labels = document.getElementsByTagName('label');
	clickable_labels.init(labels);

	image_inputs = new Array();
	els = document.getElementsByTagName('input');
	for (i = els.length - 1; i >= 0; i--) {
		el = els[i];
		if ((el.type == 'reset' || el.type == 'submit') && el.src) {
			image_inputs[image_inputs.length] = el;
		}
	}
	image_form_buttons.init(image_inputs, 'rollover');

	programme_table = document.getElementById('programme_list');
	programme_list.init(programme_table);

	if (document.getElementById('reserve_form')) {
		ticketing_obj = ticketing;
	}
	else if (document.getElementById('cart_form')) {
		ticketing_obj = cart;
	}
	else if (document.getElementById('billing_form')) {
		ticketing_obj = billing;
	}
	else {
		if (className.has(body, 'ticketing') && className.has(document.getElementById('container_container'), 'confirmation')) {
			ticketing_obj = confirmation;
		}
	}

	if (ticketing_obj) {
		ticketing_obj.init();
	}

	if (newsletter_email) {
		newsletter_email.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'email_blank'
			},
			{
				validator: function (el) { return !el.is_dummy_text; },
				errorKey: 'email_blank'
			},
			{
				validator: formValidation.emailValidator,
				errorKey: 'email_invalid'
			}
		];
		formValidation.init(newsletter_email.form, 'alert_user', newsletter_messages, subscribe_lite);
	}

	contact_form = document.getElementById('contact_form');
	if (contact_form) {
		contact_form.name.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'name_blank'
			}
		];
		contact_form.email.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'email_blank'
			},
			{
				validator: formValidation.emailValidator,
				errorKey: 'email_invalid'
			}
		];
		contact_form.phone_home.validators = [
			{
				validator: formValidation.firstNotBlankGroupActivator,
				errorKey: 'phone_blank',
				highlightId: 'contact_phone',
				groups: [
					[contact_form.phone_home],
					[contact_form.phone_office],
					[contact_form.phone_mobile]
				]
			}
		];
		contact_form.address_home.validators = [
			{
				validator: formValidation.allOrNoneActivator,
				fields: [contact_form.address_home, contact_form.address_office, contact_form.news_mail],
				errorKey: 'always_succeeds'
			},
			{
				validator: formValidation.firstNotBlankGroupActivator,
				errorKey: 'address_blank',
				highlightId: 'contact_address',
				groups: [
					[contact_form.address_home],
					[contact_form.address_office]
				]
			}
		];
		contact_form.subject.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'subject_blank'
			}
		];
		contact_form.subject.ignoreFirstOption = true;
		contact_form.message.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'message_blank'
			}
		];
		formValidation.init(contact_form, 'alert_user', contact_messages);
		contact_form.idToLabel['contact_phone'] = document.getElementById('contact_phone');
		contact_form.idToLabel['contact_address'] = document.getElementById('contact_address');
	}

	donation_form = document.getElementById('donation_form');
	if (donation_form) {
		donation_form.req_donation.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'amount_blank'
			}
			,{
				validator: formValidation.characterRangeValidator,
				errorKey: 'donation_amount_invalid',
				ranges: [[48, 57]] /* 0-9 */
			}
		];
		donation_form.req_cardno.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'card_number_blank'
			},
			{
				validator: formValidation.characterRangeValidator,
				errorKey: 'card_number_invalid',
				ranges: [[48, 57]] /* 0-9 */
			},
			{
				validator: formValidation.lengthValidator,
				errorKey: 'card_number_invalid',
				ranges: [[14, 16]]
			},
			{
				validator: formValidation.card_number_validator,
				errorKey: 'card_number_invalid',
				type: donation_form.donation_card_type
			}
		];
		donation_form.req_cardholder.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'card_holder_blank'
			}
		];
		donation_form.req_bank.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'card_bank_blank'
			}
		];
		donation_form.req_cardmonth.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'card_month_blank'
			}
		];
		donation_form.req_cardmonth.ignoreFirstOption = true;
		donation_form.req_cardyear.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'card_year_blank',
				highlightId: 'donation_card_month'
			},
			{
				validator: formValidation.dateRangeValidator,
				errorKey: 'card_expiry_date_invalid',
				highlightId: 'donation_card_month',
				ranges: [[10,2007], [12,2015]]
			}
		];
		donation_form.req_cardyear.ignoreFirstOption = true;
		donation_form.req_surname.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'contact_surname_blank'
			}
		];
		donation_form.req_givenname.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'contact_givenname_blank'
			}
		];
		donation_form.req_address1.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'contact_street1_blank'
			}
		];
		donation_form.req_daytel.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'contact_daytel_blank'
			}
		];
		donation_form.req_nighttel.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'contact_nighttel_blank'
			}
		];
		donation_form.contact_captcha.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'contact_captcha_blank'
			}
		];
		donation_form.req_email.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'contact_email_blank'
			},
			{
				validator: formValidation.emailValidator,
				errorKey: 'contact_email_invalid'
			}
		];
		formValidation.init(donation_form, 'alert_user', donation_messages);
	}

	send_form = document.getElementById('send_form');
	if (send_form) {
		send_form.FromUser.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'your_name_blank'
			}
		];
		send_form.FromUserEmail.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'your_email_blank'
			},
			{
				validator: formValidation.emailValidator,
				errorKey: 'your_email_invalid'
			}
		];
		send_form.YourFriendsName1.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'friend_name_blank'
			}
		];
		send_form.YourFriendsEmail1.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'friend_email_blank'
			},
			{
				validator: formValidation.emailValidator,
				errorKey: 'friend_email_invalid'
			}
		];
		send_form.YourFriendsName2.validators = [
			{
				validator: formValidation.allOrNoneActivator,
				fields: [send_form.YourFriendsName2, send_form.YourFriendsEmail2],
				errorKey: 'always_succeeds'
			},
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'friend_name_blank',
				highlightId: 'send_friend1_name'
			}
		];
		send_form.YourFriendsEmail2.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'friend_email_blank',
				highlightId: 'send_friend1_email'
			},
			{
				validator: formValidation.emailValidator,
				errorKey: 'friend_email_invalid',
				highlightId: 'send_friend1_email'
			}
		];
		send_form.YourFriendsName3.validators = [
			{
				validator: formValidation.allOrNoneActivator,
				fields: [send_form.YourFriendsName3, send_form.YourFriendsEmail3],
				errorKey: 'always_succeeds'
			},
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'friend_name_blank',
				highlightId: 'send_friend1_name'
			}
		];
		send_form.YourFriendsEmail3.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'friend_email_blank',
				highlightId: 'send_friend1_email'
			},
			{
				validator: formValidation.emailValidator,
				errorKey: 'friend_email_invalid',
				highlightId: 'send_friend1_email'
			}
		];
		formValidation.init(send_form, 'alert_user', send_messages);
	}

	reminder_form = document.getElementById('reminder_form');
	if (reminder_form) {
		reminder_form.reminder_email.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'email_blank'
			},
			{
				validator: formValidation.emailValidator,
				errorKey: 'email_invalid'
			}
		];
		reminder_form.reminder_time_1week.validators = [
			{
				validator: formValidation.firstNotBlankGroupActivator,
				errorKey: 'time_blank',
				highlightId: 'reminder_time',
				groups: [
					[reminder_form.reminder_time_1week],
					[reminder_form.reminder_time_2weeks]
				]
			}
		];
		formValidation.init(reminder_form, 'alert_user', reminder_messages);
		reminder_form.idToLabel['reminder_time'] = document.getElementById('reminder_time');
	}

//updated by jeffrey begin//
	
	resender_form = document.getElementById('resender_form');

	if (resender_form)
	{
		resender_form.resender_surname.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'surname_blank',
				highlightId: 'resender_surname'
			},
			{
				validator: formValidation.name_invalid,
				errorKey: 'surname_invalid',
				highlightId: 'resender_surname'
			}
			];

			resender_form.resender_givenname.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'givenname_blank',
				highlightId: 'resender_givenname'
			},
			{
				validator: formValidation.name_invalid,
				errorKey: 'givenname_invalid',
				highlightId: 'resender_givenname'
			}
			];

			resender_form.resender_email.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'email_blank',
				highlightId: 'resender_email'
			},
			{
				validator: formValidation.emailValidator,
				errorKey: 'email_invalid',
				highlightId: 'resender_email'
			}
	    	];
		
			resender_form.resender_creditcard_no.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'creditcard_no_blank',
				highlightId: 'resender_creditcard_no'
			},
			{
				validator: formValidation.creditcard_no_invalid,
				errorKey: 'creditcard_no_invalid',
				highlightId: 'resender_creditcard_no'
			}
			];
			resender_form.resender_captcha.validators = [
			{
				validator: formValidation.notBlankValidator,
				errorKey: 'captcha_blank',
				highlightId: 'resender_captcha'
			}
			];

			formValidation.init(resender_form, 'alert_user', resender_messages);
			
//		resender_form.idToLabel['resender_time'] = document.getElementById('resender_time');
	}

//updated by jeffrey end//



	open_popup_links = new Array();
	popup_lite_links = new Array();
	popup_lite_venue_links = new Array();
	els = document.getElementsByTagName('a');
	for (i = els.length - 1; i >= 0; i--) {
		el = els[i];
		if (el.rel.indexOf('popup_lite') > -1) {
			if (!className.has(el, 'venue_info')) {
				popup_lite_links[popup_lite_links.length] = el;
			}
			else {
				popup_lite_venue_links[popup_lite_venue_links.length] = el;
			}
		}
		else if (el.rel.indexOf('popup') > -1) {
			el.popup_type = 'open';
			if (className.has(el, 'donation')) {
				el.popup_width = 720;
				el.popup_height = 460;
				el.popup_name = 'donation';
				el.popup_features = 'scrollbars=yes';
			}
			else if (className.has(el, 'send_to_a_friend')) {
				el.popup_width = 700;
				el.popup_height = 487;
				el.popup_name = 'send_to_a_friend';
			}
			else if (className.has(el, 'newsletter')) {
				el.popup_width = 700;
				el.popup_height = 487;
				el.popup_name = 'newsletter';
			}
			else if (className.has(el, 'email_reminder')) {
				el.popup_width = 700;
				el.popup_height = 487;
				el.popup_name = 'email_reminder';
			}
			
			else if (className.has(el, 'email_resender')) {
				el.popup_width = 700;
				el.popup_height = 487;
				el.popup_name = 'email_resender';
			}
			else if (className.has(el, 'venue')) {
				el.popup_width = 720;
				el.popup_height = 487;
				el.popup_name = 'venue';
				el.popup_features = 'scrollbars=yes';
			}
			else if (className.has(el, 'terms')) {
				el.popup_width = 720;
				el.popup_height = 487;
				el.popup_name = 'terms';
				el.popup_features = 'scrollbars=yes';
			}
			open_popup_links[open_popup_links.length] = el;
		}
	}
	popup.init(open_popup_links);

	close_popup_links = className.getElementsByClassName(body, 'div', 'close_popup');
	for (i = close_popup_links.length - 1; i >= 0; i--) {
		close_popup_links[i].popup_type = 'close';
	}
	popup.init(close_popup_links, 'rollover');

	popup_lite.init(popup_lite_links, false);
	popup_lite.init(popup_lite_venue_links, true);

	els = className.getElementsByClassName(document, 'a', 'book_now');
	for (i = els.length - 1; i >= 0; i--) {
		el = els[i];
		if (el.rel.indexOf('popup_lite') == -1) {
			el.onclick = book_now_cookie_check;
		}
	}
};

/* for Mozilla/Opera9 */
if (document.addEventListener) {
	document.addEventListener("DOMContentLoaded", init, false);
}

/* for Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
  var proto = "src='javascript:void(0)'";
  if (location.protocol == "https:") proto = "src=//0";
	document.write("<script id=__ie_onload defer " + proto + "><\/script>");
	var script = document.getElementById("__ie_onload");
	script.onreadystatechange = function() {
		if (this.readyState == "complete") {
			init(); // call the onload handler
		}
	};
/*@end @*/

/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
	var _timer = setInterval(function() {
		if (/loaded|complete/.test(document.readyState)) {
			init(); // call the onload handler
		}
	}, 10);
}

/* for other browsers */
window.onload = init;

function subscribe_lite() { }
