// return a reference to a DOM element by ID
function e(id) {
	return document.getElementById(id);
}

// return a reference to a form element by name (within the first form)
function f(name) {
	// modifying to allow for multiple forms (function fails to work as expected in magic)
	var forms = document.forms;
	for (var i = 0; i < forms.length; i++) if (typeof(forms[i].elements[name]) != 'undefined') return forms[i].elements[name];
	return {checked:0, disabled:1, selectedIndex:0, options:{0:{value:'', text:''}}};
}

// return or set the display property of a DOM element (accepts element or element ID)
function d(element, display) {
	if (typeof(element) == 'string') element = e(element);
	if (element == null) return false;
	if (arguments.length == 1) return (element.style.display == 'none' ? false : true);
	else element.style.display = display ? '' : 'none';
	render();
}

// toggle display of a DOM element (accepts element or element ID)
function toggle(element) {
	if (typeof(element) == 'string') element = e(element);
	if (element == null) return false;
	element.style.display = element.style.display == 'none' ? '' : 'none';
	render();
}

// safely set or get an array of classes from an element
function c(element, classes) {
	if (typeof(element) == 'string') element = e(element);
	if (element == null) return false;
	if (arguments.length == 2) element.className = classes.join(' ');
	if (element.className.length) return element.className.split(' ');
	else return new Array();
}

// return whether or not an element has a named class set
function hasClass(element, className) {
	var classes = c(element);
	for (var i = 0; i < classes.length; i++) if (classes[i] == className) break;
	return i < classes.length;
}

// add a class to an element
function addClass(element, className) {
	var classes = c(element);
	for (var i = 0; i < classes.length; i++) if (classes[i] == className) break;
	classes[i] = className;
	c(element, classes);
}

// remove a class from an element
function removeClass(element, className) {
	var classes = c(element);
	for (var i = 0; i < classes.length; i++) if (classes[i] == className) break;
	delete classes[i];
	c(element, classes);
}

// toggle a class on an element
function toggleClass(element, className) {
	var classes = c(element);
	for (var i = 0; i < classes.length; i++) if (classes[i] == className) break;
	if (i < classes.length) delete classes[i];
	else classes[i] = className;
	c(element, classes);
}

// swap two classes on an element
function swapClasses(element, classNameOne, classNameTwo) {
	var classes = c(element);
	for (var i = 0; i < classes.length; i++) {
		if (classes[i] == classNameOne) classes[i] = classNameTwo;
		else if (classes[i] == classNameTwo) classes[i] = classNameOne;
	}
	c(element, classes);
}

// toggle minimise and maximise on a collapsible element
function toggleCollapsible(element) {
	// swap the minimised and maximised classes
	swapClasses(element.parentNode, 'minimised', 'maximised');
	// detect persistence and session the value
	if (hasClass(element.parentNode, 'persistent')) {
		var form = document.forms[document.forms.length - 1];
		form.elements[0].name = element.parentNode.id + 'Open';
		form.elements[0].value = hasClass(element.parentNode, 'maximised') ? 1 : 0;
		form.submit();
	}
	return false;
	render();
}

// trim a string of whitespace
var whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';
function trim(s) {
	for (var i = 0; i < s.length; i++) if (whitespace.indexOf(s.charAt(i)) == -1) break;
	if (i > 0) s = s.substring(i);
	for (i = s.length - 1; i > -1; i--) if (whitespace.indexOf(s.charAt(i)) == -1) break;
	return s.substring(0, i + 1);
}

// re-render the document (added to allow rendering functions and magic.js to function as expected during document changes)
function render() {
	// call popupReposition function (from magic.js) if it exists and if popupWrapper is visible
	if (popupReposition && d('popupWrapper')) popupReposition();
	// call render functions (from style.js) if they exist
	if (renderTables) renderTables(document);
	if (renderULs) renderULs(document);
	if (renderFieldsets) renderFieldsets(document);
}

// add "last" class to the last TR and to the last TD in each row of all tables
function renderTables(element) {
	// find all the tables
	var tables = element.getElementsByTagName('table');
	for (var i = 0; tables[i]; i++) {
		// determine the last row
		var j = tables[i].rows.length - 1;
		// add class 'last' to the last row in the table
		addClass(tables[i].rows[j], 'last');
		// add class 'last' to the last cell in the first row of the table
		addClass(tables[i].rows[0].cells[tables[i].rows[0].cells.length - 1], 'last');
		// add class 'last' to the last cell in the last row of the table
		addClass(tables[i].rows[j].cells[tables[i].rows[j].cells.length - 1], 'last');
	}
}
// add "last" class to the last item in all lists (ULs, OLs, DLs)
function renderULs(element) {
	// collect and iterate through all the lists
	var lists = [];
	lists = lists.concat(element.getElementsByTagName('ul'), element.getElementsByTagName('ol'), element.getElementsByTagName('dl'));
	for (var i = 0; i < lists.length; i++) for (var j = 0; lists[i][j]; j++) {
		// find the last child in the list that is a element node
		for (var lastItem = lists[i][j].lastChild; lastItem && lastItem.nodeType != 1; lastItem = lastItem.previousSibling) continue;
		// add class 'last' to the last LI in the UL
		addClass(lastItem, 'last');
	}
}
// add "last" class to the last block element in a fieldset
function renderFieldsets(element) {
	// iterate through all the FIELDSETs
	var fieldsets = element.getElementsByTagName('fieldset');
	for (var i = 0; fieldsets[i]; i++) {
		// find the last element in the FIELDSET (that is a element node)
		for (var lastElement = fieldsets[i].lastChild; lastElement && lastElement.nodeType != 1; lastElement = lastElement.previousSibling) continue;
		// ignore FORMs
		if (lastElement.nodeName == 'FORM') for (var lastElement = lastElement.lastChild; lastElement && lastElement.nodeType != 1; lastElement = lastElement.previousSibling) continue;
		// add class 'last' to the last element in the FIELDSET
		addClass(lastElement, 'last');
	}
}

// add "onclick" to any LI elements with only one A element, within a UL class links
function renderClickableLIs(ul) {
	// disabled cause it's not working correctly
	return;
	// get the LIs within the UL
	var items = ul.getElementsByTagName('li');
	for (var i = 0; items[i]; i++) {
		// walk the children of the LI (skipping non-element nodes) searching for an anchor
		for (var itemChild = items[i].firstChild; itemChild && itemChild.nodeType != 1; itemChild = itemChild.nextSibling) if (itemChild.nodeName == 'A') break;
		// if last iterated child is not null it was an anchor so add onclick to the LI to follow the child anchor
		if (itemChild.nodeName == 'A') items[i].onclick = activateChildAnchor;
	}
}
/* activate the child anchor of (this) LI */
function activateChildAnchor() {
	if (this.getElementsByTagName('a')[0].getAttribute('onclick')) eval(this.getElementsByTagName('a')[0].getAttribute('onclick').substring(7));
	else window.location.assign(this.getElementsByTagName('a')[0].getAttribute('href'));
}
