var xmlHttp

// Standard routines
function GetXmlHttpObject() {
	var xmlHttp = null;

	try {
		// Firefox, Opera 8.0+, Safari
		xmlHttp = new XMLHttpRequest();
	}
	catch(e) {
		//Internet Explorer
		try {
			xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch(e) {
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
	}
	return xmlHttp;

}

/* Clear down input fields eg login, search ***********/

function clearInput(input) {
	if (input.defaultValue == input.value) {
		input.value = '';
	}
}

/* Suckerfish menuing fix *****************************/

/*startList = function() {
	var i = 0;
	if (document.all && document.getElementById) {
		navRoot = document.getElementById("dmenu");
		for (i = 0; i < navRoot.childNodes.length; i++) {
			node = navRoot.childNodes[i];
			if (node.nodeName == "LI") {
				node.onmouseover = function() {
					this.className += " over";
				}
				node.onmouseout = function() {
					this.className = this.className.replace(" over", "");
				}
			}
		}
	}
}*/

/* homepage style for swapping text in a definition list ***************/

/*
function lastFive(resourcecategoryid) {
	new Ajax.Request("page_ajax.php", {
		method: 'get',
		parameters: 'q=last5&xhr=1&resourcecategoryid=' + resourcecategoryid,
		onSuccess: function(xhrResponse) {
			$('last5').update(xhrResponse.responseText);

		},
		onFailure: function(xhrResponse) {
			$('last5').update(getTemplate('500.html'));
		}
	});
	return (false);
}
*/




/****  COPY to clipboard function seemless in IE
	   needs manual intervention in MOZ            ************/

/*
function getPageEventCoords(evt) {

	var posx = 0;
	var posy = 0;

	var evt = (evt) ? evt: event;

	if (evt.pageX || evt.pageY) {
		posx = evt.pageX;
		posy = evt.pageY;
	} else if (evt.clientX || evt.clientY) {
		posx = evt.clientX + document.body.scrollLeft
		+ document.documentElement.scrollLeft;
		posy = evt.clientY + document.body.scrollTop
		+ document.documentElement.scrollTop;
	}

	return {
		left: posx,
		top: posy
	};
}

function copy_to_clipboard(e, id, text) {

	if (window.clipboardData) {
		window.clipboardData.setData('text', text);
	} else {

		// clear out any currently openned windows
		if ((popped = document.getElementById("copyLink")) != null) {
			popped.parentNode.removeChild(popped);
		}

		var popup = document.createElement("div");
		var inner = document.createElement("div");

		// name them so that we can apply styles
		popup.setAttribute("id", "copyLink");
		inner.setAttribute("id", "inner");

		inner.innerHTML = getTemplate("discussion_link_snippet.html");

		popup.appendChild(inner);

		var mousePosition = getPageEventCoords(e);

		popup.style.position = "Absolute";
		popup.style.top = (mousePosition.top + 10) + 'px';
		popup.style.left = (mousePosition.left - 420) + 'px';

		var bodyRef = document.getElementsByTagName("body").item(0);
		bodyRef.appendChild(popup);


		$('linkto').value = text;

		// and focus on the first field
		document.forms['linksnippet'].elements['linkto'].focus();
		document.forms['linksnippet'].elements['linkto'].select();
	}
} */

/* fix the background of png files for IE6
 * Takes a css class name or anything else that
 * can be returned by prototype's $$ operator
 */

/*function pingFix(cname) {
	if (navigator.userAgent.indexOf("MSIE") != -1) {
		var version = parseFloat(navigator.appVersion.split('MSIE')[1]);

		if ((version >= 5.5) && (version < 7)) {
			$$(cname).each(function(poElement) {

				// if IE5.5+ on win32, then display PNGs with AlphaImageLoader
				var cBGImg = poElement.currentStyle.backgroundImage;
				var cImage = cBGImg.substring(cBGImg.indexOf('"') + 1, cBGImg.lastIndexOf('"'));

				poElement.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + cImage + "', sizingMethod='scale')";
				poElement.style.backgroundImage = "none";
			});
		}
	}
}*/


// User
function userSuggestions(str) {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "base_ajax.php";
	url = url + "?q=userSuggestions;lastname=" + str;
	url = url + ";sid=" + Math.random();

	xmlHttp.open("GET", url, true);
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				document.getElementById("whatever goes here").innerHTML = xmlHttp.responseText;
			}
		}
	}


	xmlHttp.send(null);
}


/************************************
 * Organisation
 *
 ************************************/

function organisationSuggestions(str) {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "base_ajax.php";
	url = url + "?q=organisationSuggestions;organisationname=" + str;
	url = url + ";sid=" + Math.random();

	xmlHttp.open("GET", url, true);
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				document.getElementById("whatever goes here").innerHTML = xmlHttp.responseText;
			}
		}
	}


	xmlHttp.send(null);
}

function clearOrganisation() {
	/* function is ussed to get an empty organisation object to iterate through
   * its fields to clear down a form - that's all folks!
   */

	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "base_ajax.php";
	url = url + "?q=getOrganisation";
	url = url + ";sid=" + Math.random();
	xmlHttp.open("GET", url, true);

	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				var json = xmlHttp.responseText;

				if (json.length) {
					var options = eval("(" + json + ")");

					// populate with json data
					for (var fieldname in options) {
						if ($(fieldname) != null) {
							$(fieldname).value = options[fieldname];
						}
					}
				}
			}
		}
	}

	xmlHttp.send(null);
}


function getSelectedOrganisation(text, li) {

	var organisationid = (li === undefined) ? 0: li.id;

	/* get the organisation object and then populate the remaining fields */
	/* include the name field because this will be populated with a partial address */

	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "base_ajax.php";
	url = url + "?q=getOrganisation;organisationid=" + organisationid;
	url = url + ";sid=" + Math.random();
	xmlHttp.open("GET", url, true);

	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				var json = xmlHttp.responseText;

				if (json.length) {
					var options = eval("(" + json + ")");

					// populate with json data
					for (var fieldname in options) {
						if ($(fieldname) != null) {
							$(fieldname).value = options[fieldname];
						}
					}
				}
			}
		}
	}


	xmlHttp.send(null);

}



/************************************
 * Folder and File
 *
 ************************************/

function filetypeAoH(str) {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "folder_ajax.php";
	url = url + "?q=filetypeAoH;filename=" + str;
	url = url + ";sid=" + Math.random();

	xmlHttp.open("GET", url, true);
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				setOptions('DOMfiletypeid', xmlHttp.responseText);
			}
		}
	}


	xmlHttp.send(null);
}


function foldercontentsAoH(rid, order, sort) {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "folder_ajax.php";
	url = url + '?q=foldercontentsAoH;resourceid=' + rid + ';order=' + order + ';sort=' + sort;
	url = url + ";sid=" + Math.random();

	xmlHttp.open("GET", url, true);
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				document.getElementById("r" + rid).innerHTML = xmlHttp.responseText;
				//	document.getElementById("foldercontents"+rid).innerHTML = xmlHttp.responseText;
			}
		}
	}

	xmlHttp.send(null);
}




/************************************
 * Pageinfo
 *
 ************************************/

function showPageinfoTeamAoH(accountid, resourceid) {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "page_ajax.php";
	url = url + '?q=showPageinfoTeamAoH;resourceid=' + resourceid + ';accountid=' + accountid;
	url = url + ";sid=" + Math.random();

	xmlHttp.open("GET", url, true);
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				document.getElementById("pi" + accountid).innerHTML = xmlHttp.responseText;
			}
		}
	}

	xmlHttp.send(null);
}
function showPageinfoTeamELanguagesAoH(accountid, resourceid) {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "page_ajax.php";
	url = url + '?q=showPageinfoTeamELanguagesAoH;resourceid=' + resourceid + ';accountid=' + accountid;
	url = url + ";sid=" + Math.random();

	xmlHttp.open("GET", url, true);
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				document.getElementById("pi" + accountid).innerHTML = xmlHttp.responseText;
			}
		}
	}

	xmlHttp.send(null);
}

function hidePageinfoTeamAoH(accountid, resourceid) {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "page_ajax.php";
	url = url + '?q=hidePageinfoTeamAoH;resourceid=' + resourceid + ';accountid=' + accountid;
	url = url + ";sid=" + Math.random();

	xmlHttp.open("GET", url, true);
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				document.getElementById("pi" + accountid).innerHTML = xmlHttp.responseText;
			}
		}
	}

	xmlHttp.send(null);
}

function hidePageinfoTeamELanguagesAoH(accountid, resourceid) {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "page_ajax.php";
	url = url + '?q=hidePageinfoTeamAoH;resourceid=' + resourceid + ';accountid=' + accountid;
	url = url + ";sid=" + Math.random();

	xmlHttp.open("GET", url, true);
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				document.getElementById("pi" + accountid).innerHTML = xmlHttp.responseText;
			}
		}
	}

	xmlHttp.send(null);
}


/************************************
 * Poll functions
 *
 ************************************/

function pollResponse(form) {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var answers = form.answerid;
	var resourceid = form.resourceid.value;

	/* check that one answer has been selected and
   * return it's value OR false
   */
	var isValidRadio = function(options) {
		for (var i = 0; i < options.length; i++) {
			if (options[i].checked) {
				return options[i].value;
			}
		}
		return false;
	};

	var answerid = isValidRadio(answers);

	if (answerid != false) {
		var url = "poll_ajax.php";
		url = url + '?q=pollResponse;resourceid=' + resourceid + ';answerid=' + answerid;
		url = url + ";sid=" + Math.random();

		xmlHttp.open("GET", url, true);
		xmlHttp.send(null);
		xmlHttp.onreadystatechange = function() {
			if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
				if (xmlHttp.status == 200) {
					// We want to replace the entire div not just it's content
					var poll = $("r" + resourceid);
					var parent = poll.parentNode;
					var newdiv = document.createElement('div');

					newdiv.innerHTML = xmlHttp.responseText;
					parent.replaceChild(newdiv, poll);
				}
			}
		}
	}
}



/************************************
 * Gallery functions
 *
 ************************************/

function refreshGallery(resourceid, index, mode) {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "gallery_ajax.php";
	url = url + '?q=refreshGallery;resourceid=' + resourceid + ';index=' + index + ';mode' + mode;
	url = url + ";sid=" + Math.random();

	xmlHttp.open("GET", url, true);
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				// We want to replace the entire div not just it's content
				//var gallery = document.getElementById("r" + resourceid);
				var gallery = $("r" + resourceid);
				var parent = gallery.parentNode;
				var newdiv = document.createElement('div');

				newdiv.innerHTML = xmlHttp.responseText;

				parent.replaceChild(newdiv, gallery);
			}
		}
	}

	xmlHttp.send(null);
}


function getSlides(resourceid) {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "gallery_ajax.php";
	url = url + '?q=getSlides;resourceid=' + resourceid;
	url = url + ";sid=" + Math.random();

	xmlHttp.open("GET", url, false);
	xmlHttp.send(null);
	// this blocks as request is synchronous
	if (xmlHttp.status == 200) {
		return xmlHttp.responseText;
	}

	xmlHttp.send(null);
}

/***************************************************
 * slideShow Class
 * Hacked about implementation of an example at
 * http://www.icommunicate.co.uk/ (itself based on
 * one from http://www.tomdoyletalk.com/)
 * Changed to source data differently, add pause and rewind
 * Don't bother with the fade transition
 * We also deal with broken implementations of IE
 * and added a thumbnail mode.
 */

var slideShow = Class.create({
	initialize: function(argv) {
		this.resourceid = argv.resourceid ? argv.resourceid: '';
		this.wait		= argv.wait ? argv.wait: 4000;
		this.duration	= argv.duration ? argv.duration: 1;
		this.start		= argv.start ? argv.start: 0;
		this.i			= argv.i ? argv.i: 0;
		this.slides		= eval(getSlides(this.resourceid));
		this.image		= 'r' + this.resourceid + '_image';
		this.caption	= 'r' + this.resourceid + '_caption';
		this.counter	= 'r' + this.resourceid + '_counter';
		this.startBtn	= 'r' + this.resourceid + '_startBtn';
		this.pauseBtn	= 'r' + this.resourceid + '_pauseBtn';
		this.thumbBtn	= 'r' + this.resourceid + '_thumbBtn';
		this.slideBtn	= 'r' + this.resourceid + '_slideBtn';
		this.nextBtn	= 'r' + this.resourceid + '_nextBtn';
		this.prevBtn	= 'r' + this.resourceid + '_prevBtn';
		this.rewindBtn	= 'r' + this.resourceid + '_rewindBtn';

		this.interval = 0;

		// We hide both buttons with CCS style then display the one that isn't the default in this case the thumbnail button.
		$(this.thumbBtn).show();
	},

	thumbnail: function() {
		clearInterval(this.interval);
		$(this.thumbBtn).hide();
		$(this.slideBtn).show();
		$(this.startBtn).show();
		$(this.pauseBtn).hide();

		if ($(this.image) != null && $(this.image).hasChildNodes()) {
			while ($(this.image).firstChild) {
				$(this.image).removeChild($(this.image).firstChild);
			}
		}

		for (var i = 0; i < this.slides.length; i++) {
			var thumbnail = document.createElement('div');
			thumbnail.setAttribute('className', 'thumbnail');
			thumbnail.setAttribute('class', 'thumbnail');

			var link = document.createElement('a');
			link.setAttribute('href', '/images/' + this.slides[i].resourceid + '/' + this.slides[i].size);

			if (navigator.userAgent.indexOf("MSIE") != -1) {
				/* .... and because you can't use setAttribute with events in IE
				 * .... and because you can't set a variable in a paramter! */
				link.setAttribute('title', i);
				var func = 'gallery_r' + this.resourceid + '.display (this.title);';

				link.onclick = function() {
					eval(func);
					return false;
				};
			} else {
				link.setAttribute('onclick', 'gallery_r' + this.resourceid + '.display (' + i + ');return false;');
			}

			var img = document.createElement('img');
			img.setAttribute('src', '/images/' + this.slides[i].resourceid + '/0');
			img.setAttribute('alt', this.slides[i].resourcedesc);
			img.setAttribute('className', 'thumbimg');
			img.setAttribute('class', 'thumbimg');

			link.appendChild(img);
			thumbnail.appendChild(link);
			$(this.image).appendChild(thumbnail);

			// tidy up the gallery and make sure that the caption height doesn't change
			// so that the gallery height doesn't change
			$(this.caption).innerHTML = '&nbsp;';
			$(this.counter).innerHTML = this.slides.length + ' of ' + this.slides.length;

		}
	},

	play: function() {
		$(this.startBtn).hide();
		$(this.pauseBtn).show();

		if (++this.i == this.slides.length) {
			this.i = 0;
		}

		this.display();
	},

	pause: function() {
		clearInterval(this.interval);
		$(this.startBtn).show();
		$(this.pauseBtn).hide();
	},

	rewind: function() {
		clearInterval(this.interval);
		$(this.startBtn).show();
		$(this.pauseBtn).hide();

		this.i = 0;
		this.display();
	},

	next: function() {
		clearInterval(this.interval);
		$(this.startBtn).show();
		$(this.pauseBtn).hide();

		if (++this.i >= this.slides.length) {
			this.i = 0;
		}

		this.display();
	},

	previous: function() {
		clearInterval(this.interval);
		$(this.startBtn).show();
		$(this.pauseBtn).hide();

		if (--this.i < 0) {
			this.i = this.slides.length - 1;
		}

		this.display();
	},

	display: function(slide) {
		this.i = slide === undefined ? this.i: parseInt(slide);
		$(this.thumbBtn).show();
		$(this.slideBtn).hide();

		var num = this.i + 1;
		var imageStr = '';

		if (this.slides[this.i].url != null) {
			imageStr = '<a href="' + this.slides[this.i].url + '" target="_blank"><img class="photo" src="/images/' + this.slides[this.i].resourceid + '/' + this.slides[this.i].size + '" alt="' + this.slides[this.i].resourcedesc + '" /></a>';
		} else {
			imageStr = '<a href="/images/' + this.slides[this.i].resourceid + '/4" target="_blank">' + '<img class="photo" src="/images/' + this.slides[this.i].resourceid + '/' + this.slides[this.i].size + '" alt="' + this.slides[this.i].resourcedesc + '" /></a>';
		}

		$(this.caption).innerHTML = this.slides[this.i].resourcedesc;
		$(this.image).innerHTML = imageStr;
		$(this.counter).innerHTML = num + ' of ' + this.slides.length;
		$(this.image).hide();

		if (navigator.userAgent.indexOf("MSIE") != -1) {
			// who'd have thunk IE couldn't handle this!
			$(this.image).show();
		} else {
			$(this.image).appear({
				duration: this.duration
			});
		}
	},

	startShow: function() {
		this.interval = setInterval(this.play.bind(this), this.wait);
		$(this.startBtn).hide();
		$(this.pauseBtn).show();
	}

});

// TODO flash in - fade out element above image showing current zoom%
function growImage(resourceid, direction, factor) {
	resourceid = resourceid === undefined ? null: resourceid;
	direction = direction === undefined ? 'grow': direction;
	factor = factor === undefined ? 1.2: factor;

	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "gallery_ajax.php";
	url = url + "?q=growImage;resourceid=" + resourceid + ";direction=" + direction + ";factor=" + factor;
	url = url + ";sid=" + Math.random();

	xmlHttp.open("GET", url, true);
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				var dim = eval("(" + xmlHttp.responseText + ")");
				var image = "r" + resourceid + "_image";
				var caption = "r" + resourceid + "_caption";

				if ($(image) !== null && dim.height !== undefined
				&& dim.width !== undefined) {
					$(image).setAttribute('height', dim.height);
					$(image).setAttribute('width', dim.width);
					$(caption) !== null && $(caption).setAttribute('width', dim.width);
				}
			}
		}
	}
	xmlHttp.send(null);
}

/************************************
 * Discussion system
 *
 ***********************************/


function addDiscussion() {
	new Ajax.Request("discussion_ajax.php", {
		method: 'post',
		parameters: 'q=addDiscussion&xhr=1&' + get_params('discussion'),
		onSuccess: function(xhrResponse) {
			var parent;

			if ($F('parentid') != 1) {
				parent = $($F('parentid'));

			} else {

				parent = $('structure');
			}

			popup = $('addDiscussion');
			popup.parentNode.removeChild(popup);

			var newChild = document.createElement('DIV');
			newChild.innerHTML = xhrResponse.responseText;

			// NB this is not alphabetical
			//insertAlphabetical (newChild,parent);
			//newChild.focus ();
			insertAfter(newChild, parent);
		},
		on406: function(xhrResponse) {

			$('addDiscussion').innerHTML = xhrResponse.responseText;

			if ($F('typeid') == 'r' || $F('typeid') == 's') {
				showmoderate = $('showmoderate');
				showstatus = $('showstatus');
				showmoderate.parentNode.removeChild(showmoderate);
				showstatus.parentNode.removeChild(showstatus);
			}

		},
		onFailure: function(xhrResponse) {
			$('addDiscussion').innerHTML = getTemplate('500.html');
		}
	});
	return (false);

}


function displayDiscussionInput(typeid, level, root, parentid) {
	typeid = typeid === undefined ? 'r': typeid;
	level = level === undefined ? 0: level;
	root = root === undefined ? 1: root;
	parentid = parentid === undefined ? root: parentid;


	// clear out any currently openned windows
	if ((popped = document.getElementById("addDiscussion")) != null) {
		popped.parentNode.removeChild(popped);
	}

	var currentPosition = getElementPosition(typeid + parentid);

	// create the divs for the popup
	var popup = document.createElement("div");
	var inner = document.createElement("div");

	// name them so that we can apply styles
	popup.setAttribute("id", "addDiscussion");
	inner.setAttribute("id", "inner");

	inner.innerHTML = getTemplate("discussion_snippet.html");

	popup.appendChild(inner);
	popup.style.position = "Absolute";
	popup.style.top = (currentPosition.top - 32) + 'px';
	popup.style.left = (currentPosition.left + 32) + 'px';

	var bodyRef = document.getElementsByTagName("body").item(0);
	bodyRef.appendChild(popup);

	// set the values we know XXXXXXX do I want to pass this out to another
	// function via an associative array
	$('typeid').value = typeid;
	$('root').value = root;
	$('parentid').value = parentid;
	$('level').value = level;


	// we display different versions
	if ($('status_o') != null) {
		$('status_o').checked = true;
	}

	if ($('no') != null) {
		$('no').checked = true;
	}


	// which bits don't we want to see
	if (typeid == 'r' || typeid == 's') {
		var showmoderate = $("showmoderate");
		var showstatus = $("showstatus");
		showmoderate.parentNode.removeChild(showmoderate);
		showstatus.parentNode.removeChild(showstatus);
	}

	// and focus on the first field
	document.forms['discussion'].elements['resourcename'].focus();

}

/* monitor changes in a textarea and change size dynamically */

function textareaHeight(text_area) {
	text_area.style.height =
	text_area.scrollHeight - ((isIE()) ? 0: 2) + "px";
}


function discussionGetEditSnippet(id) {

	var messagediv = 'p' + id + '_content';
	var txtarea = 'p' + id + '_message';
	var height = $(messagediv).offsetHeight;
	var width = $(messagediv).offsetWidth;

	new Ajax.Request("discussion_ajax.php", {
		method: 'post',
		parameters: 'q=discussionGetEditSnippet&xhr=1&dpostingid=' + id + '&' + get_params('editMessage'),
		onSuccess: function(xhrResponse) {
			$(messagediv).innerHTML = xhrResponse.responseText;
			$(txtarea).style.height = height + 'px';
			$(txtarea).style.width = width + 'px';
			$(txtarea).style.overflow = 'auto';
		},
		on406: function(xhrResponse) {
			$(messagediv).innerHTML = xhrResponse.responseText;
			$(txtarea).style.height = height + 'px';
			$(txtarea).style.width = width + 'px';
			$(txtarea).style.overflow = 'auto';
		},
		onFailure: function(xhrResponse) {
			return getTemplate('500.html');
		}
	});

	return (false);
}


function discussionMakeEditable(id) {

	if ($(id) == null) {
		return;
	}
	var message = $(id);

	// get the dimensions of the original for the overlay size.
	var height = message.offsetHeight;
	var width = message.offsetWidth;

	// get the original text
	var txt = message.innerHTML;
	var wrapper = document.createElement('div');
	var snippet = getTemplate('discussionEditSnippet.html');


	snippet = snippet.replace(/\:\:\{\$dpostingid\}\:\:/g, id);
	snippet = snippet.replace(/\:\:\{\$message\}\:\:/g, txt);

	wrapper.innerHTML = snippet;

	// parent is the posting
	var parent = message.parentNode;

	try {
		parent.replaceChild(wrapper, message);
	} catch(err) {
		alert(err.message);
	}
}

function getTemplate(filename) {
	filename = filename === undefined ? '404.html': filename;

	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "page_ajax.php";
	url = url + '?q=getTemplate;filename=' + filename;
	url = url + ";sid=" + Math.random();

	// use false to wait on the return
	xmlHttp.open("GET", url, false);
	xmlHttp.send(null);
	// this blocks as request is synchronous
	if (xmlHttp.status == 200) {
		return xmlHttp.responseText;
	}

	xmlHttp.send(null);

}

function closePopup(popupID) {
	try {
		var popup = document.getElementById(popupID);
		//.style.display = "none";
		popup.parentNode.removeChild(popup);
	} catch(e) {
		alert("No popup object open");
	}
}


function toggleLock(obj, resourceid) {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "discussion_ajax.php";
	url = url + '?q=toggleLock;resourceid=' + resourceid;
	url = url + ";sid=" + Math.random();

	xmlHttp.open("GET", url, true);
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				if (obj.className == 'discussionlocklink') {
					obj.className = 'discussionunlocklink'
				} else {
					obj.className = 'discussionlocklink'
				}
			}
		}
	}

	xmlHttp.send(null);
}

function togglePin(obj, resourceid) {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "discussion_ajax.php";
	url = url + '?q=togglePin;resourceid=' + resourceid;
	url = url + ";sid=" + Math.random();

	xmlHttp.open("GET", url, true);
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				if (obj.className == 'discussionpinlink') {
					obj.className = 'discussionunpinlink'
				} else {
					obj.className = 'discussionpinlink'
				}
			}
		}
	}

	xmlHttp.send(null);
}

function setSelRange(inputEl, selStart, selEnd) {
	if (inputEl.setSelectionRange) {
		inputEl.focus();
		inputEl.setSelectionRange(selStart, selEnd);
	} else if (inputEl.createTextRange) {
		var range = inputEl.createTextRange();
		range.collapse(true);
		range.moveEnd('character', selEnd);
		range.moveStart('character', selStart);
		range.select();
	}
}



/** resource editing functions
 *
 */


function getEditable(resourceid) {

	/* 1. Get the insertion_point snippet and cache it for regex replacement
   *    we don't want to do the round trip more times than needed but we do
   *    want to get the correct language version
   * 2. Get the anchor divs
   * 3. Write the anchors out separately
   * 4. Toggle the edit/live button
   */

	// 1
	var insertionPoint = getTemplate('insertion_point_snippet.html');

	// 2
	var anchors = getElementsByRegExpId(/^anchor\d+$/, undefined, 'div');


	// 3
	for (var i = 0; i < anchors.length; i++) {
		{
			var anchorDIV = anchors[i];
			matches = anchorDIV.getAttribute('id').match(/anchor(\d+)/);
			anchor = matches[1];

			var divs = getElementsByRegExpId(/^r\d+$/, anchorDIV, 'div');

			var item = 1;
			for (var j = 0; j < divs.length; j++) {

				var child = divs[j];
				var iptemplate = insertionPoint;

				// parent is the anchor
				var parent = child.parentNode;

				// fill out the insertion template.
				var iPoint = document.createElement("div");
				iptemplate = iptemplate.replace(/id="pai"/g, 'id="p' + resourceid + 'a' + anchor + 'i' + item + '"');
				iptemplate = iptemplate.replace(/parentid=/g, 'parentid=' + resourceid);
				iptemplate = iptemplate.replace(/anchor=/g, 'anchor=' + anchor);
				iptemplate = iptemplate.replace(/item=/g, 'item=' + item);
				iptemplate = iptemplate.replace(/displayAddable\(\,\,\)/g, 'displayAddable(' + resourceid + ',' + anchor + ',' + item + ')');
				iptemplate = iptemplate.replace(/displayClipboard\(\,\,\)/g, 'displayClipboard(' + resourceid + ',' + anchor + ',' + item + ')');

				iPoint.innerHTML = iptemplate;

				parent.insertBefore(iPoint, child);

				var newchild = makeEditable(child.cloneNode(true), resourceid);

				try {
					parent.replaceChild(newchild, child);
				} catch(err) {
					alert(err.message);
				}

				item++;
			}

			// add the trailing insertion point
			var lastip = document.createElement('div');
			var iptemplate = insertionPoint;

			iptemplate = iptemplate.replace(/id="pai"/g, 'id="p' + resourceid + 'a' + anchor + 'i' + item + '"');
			iptemplate = iptemplate.replace(/parentid=/g, 'parentid=' + resourceid);
			iptemplate = iptemplate.replace(/anchor=/g, 'anchor=' + anchor);
			iptemplate = iptemplate.replace(/item=/g, 'item=' + item);
			iptemplate = iptemplate.replace(/displayAddable\(\,\,\)/g, 'displayAddable(' + resourceid + ',' + anchor + ',' + item + ')');
			iptemplate = iptemplate.replace(/displayClipboard\(\,\,\)/g, 'displayClipboard(' + resourceid + ',' + anchor + ',' + item + ')');

			lastip.innerHTML = iptemplate;

			anchorDIV.appendChild(lastip);
		}
	}

	// 4
	var editlink = document.getElementById('editmode');

	try {
		editlink.innerHTML = '<a href="change_display_mode.php?resourceid=' + resourceid + ';mode=live" accesskey="T" onclick="unwrap(' + resourceid + ');return false;"><img src="/icons/live.gif" alt="switch to normal view accesskey ALT+T" height="16" width="16" />Normal view</a>';
	} catch(err) {
		}

	// 5 Display the resource widget
	$$('div.editblock').each(function(div) {
		new Draggable(div, {
			revert: true,
			ghosting: true
		});
	});

	$$('div.additem').each(function(div) {
		Droppables.add(div, {
			accept: 'draggable',
			hoverclass: 'hover',
			onDrop: function() {
				div.highlight();
			}
		});
	});

	displayAddable();


}


function makeEditable(resource, resourceid) {

	// construct the wrapper
	var wrapper = document.createElement("div");
	wrapper.setAttribute("id", "editblock" + resourceid);
	wrapper.setAttribute("class", "editblock");

	var handle = document.createElement("div");
	handle.setAttribute("id", "editimage");

	var link = document.createElement("a");
	link.setAttribute("class", "editlink");
	link.href = "#";
	link.setAttribute('onclick', 'editResource(' + resourceid + ');return false;');

	var image = document.createElement("img");
	image.setAttribute("class", "editlinkimage");
	image.src = '/icons/edit.gif';
	image.alt = 'Edit properties';

	link.appendChild(image);
	handle.appendChild(link);

	wrapper.appendChild(resource);
	wrapper.appendChild(handle);


	return wrapper;
}


// get the insertion point template to cache
function getInsertionSnippet() {
	xmlHttp = GetXmlHttpObject();

	if (xmlHttp == null) {
		return;
	}

	var url = "page_ajax.php";
	url = url + '?q=getInsertionPointSnippet';
	url = url + ";sid=" + Math.random();

	// use false to wait on the return
	xmlHttp.open("GET", url, false);
	xmlHttp.onreadystatechange = function() {
		if (xmlHttp.readyState == 4 || xmlHttp.readyState == "complete") {
			if (xmlHttp.status == 200) {
				return xmlHttp.responseText;
			}
		}
	}

	xmlHttp.send(null);

}

function unwrap(resourceid) {

	if ($('addResource') != null) {
		$('addResource').remove();
	}

	var divs = getElementsByRegExpId(/^editblock\d+$/, undefined, 'div');

	for (var i = 0; i < divs.length; i++) {
		var child = divs[i];

		var parent = child.parentNode;
		var inner = child.firstChild;
		parent.replaceChild(inner, child)
	}

	// clean up the tail ends
	var tails = getElementsByRegExpId(/^p\d+a\d+i\d+$/, undefined, 'div');

	for (var i = 0; i < tails.length; i++) {
		var child = tails[i];
		var parent = child.parentNode;
		parent.removeChild(child);
	}

	// toggle the live/edit mode link
	var livelink = document.getElementById('editmode');

	try {
		livelink.innerHTML = '<a href="change_display_mode.php?resourceid=' + resourceid + ';mode=edit" accesskey="T" onclick="getEditable(' + resourceid + ');return false;"><img src="/icons/edit.gif" alt="switch to edit mode accesskey ALT+T" height="16" width="16" />Edit mode</a>';
	} catch(err) {
		}
}



function displayAddable(parentid, anchor, item) {
	parentid = parentid === undefined ? 1: parentid;
	anchor = anchor === undefined ? 1: anchor;
	item = item === undefined ? 1: item;

	// clear out any currently openned windows
	if ($('addResource') != null) {
		$('addResource').remove();
	}

	//  var currentPosition = getElementPosition ('p' + parentid + 'a' + anchor + 'i' + item);
	var currentPosition = {
		left: 120,
		top: 120
	};


	// XXXXXXXX BUST var pos = $('p' + parentid + 'a' + anchor + 'i' + item);
	// XXXXXXXX BUST var currentPosition = pos.positionedOffset();
	// create the divs for the popup
	//  var popup = document.createElement("div");
	//  var inner = document.createElement("div");
	var popup = new Element('div', {
		'id': 'addResource'
	});
	var inner = new Element('div', {
		'id': 'inner'
	});


	iptemplate = getTemplate("addResource_snippet.html");

	iptemplate = iptemplate.replace(/parentid=/g, 'parentid=' + parentid);
	iptemplate = iptemplate.replace(/anchor=/g, 'anchor=' + anchor);
	iptemplate = iptemplate.replace(/item=/g, 'item=' + item);

	inner.update(iptemplate);

	popup.appendChild(inner);
	popup.style.position = "Absolute";
	popup.style.top = (currentPosition.top - 32) + 'px';
	popup.style.left = (currentPosition.left + 32) + 'px';


	var bodyRef = document.getElementsByTagName("body").item(0);
	bodyRef.appendChild(popup);

	$('snippet').select('a').each(function(a) {
		new Draggable(a, {
			revert: true,
			ghosting: true
		});
	});

	// and focus on the first field
	//$('snippet').focus ();
}


/* utility functions */

function reveal(link, divID) {
	if (divID != null) {
		var pos = getElementPosition(link);

		$(divID).style.position = "Absolute";
		$(divID).style.top = (pos.top - 11) + 'px';
		$(divID).style.left = (pos.left - 145) + 'px';
		$(divID).show();
	}
}

function conceal(divID) {
	if (divID != null) {
		$(divID).hide();
	}
}


/**
 * Curtesy of Ajax the Definitive Guide ...
 * Uses Prototype library
 * This function, get_params, takes the id of a form in a page and
 * parses out all form elements, creating a parameter string to be
 * used in an Ajax call.
 *
 * @param {String} p_formId The id of the form to parse elements from.
 * @return Returns the parameter string containing all of the form
 * elements and their values.
 * @type String
 */

function get_params(p_formId) {

	if ($(p_formId) == null)
	{
		return false;
	}


	var params = '';
	var selects = $(p_formId).getElementsByTagName('select');

	/*
   * Loop through any <select> elements in the form and get their
   * values
   */

	for (var i = 0, il = selects.length; i < il; i++)
	params += ((params.length > 0) ? '&': '') + selects[i].id + '=' + selects[i].value;

	var inputs = $(p_formId).getElementsByTagName('input');

	/*
   * Loop through any <input> elements in the form and get their
   * values
   */

	for (var i = 0, il = inputs.length; i < il; i++) {
		var type = inputs[i].getAttribute('type');

		/*
	 * Is this <input> element of type text, password, hidden,
	 * or checkbox?
	 */

		if (type == 'text' || type == 'password' || type == 'hidden' || (type == 'checkbox' && inputs[i].checked))
		params += ((params.length > 0) ? '&': '') + inputs[i].id + '=' + inputs[i].value;

		/* Is this <input> element of type radio? */
		if ((type == 'radio' && inputs[i].checked))
		params += ((params.length > 0) ? '&': '') + inputs[i].name + '=' + inputs[i].value;
	}

	var textareas = $(p_formId).getElementsByTagName('textarea');

	/*
   * Loop through any <textarea> elements in the form and get their
   * values
   */

	for (var i = 0, il = textareas.length; i < il; i++) {
		params += ((params.length > 0) ? '&': '') + textareas[i].name + '=' + textareas[i].value;
	}
	return (params);
}

/**
 * XXXXXXXXXXXXXX Prototype example JUST HERE for demo purposes

 * This function, myForm_onclick, makes an Ajax request to the server
 * and changes the /pageContentContainer/ <div> element to the
 * /responseText/ sent by the server.
 *
 * @return Returns false so that the form will not submit in the
 *  normal XHTML fashion.
 * @type Boolean
 * @see Ajax#Request
 */

function myForm_onclick() {
	new Ajax.Request('example_14-7.php', {
		method: 'post',
		parameters: 'xhr=1&' + get_params('myForm'),
		onSuccess: function(xhrResponse) {
			$('pageContentContainer').innerHTML = xhrResponse.responseText;
		},
		onFailure: function(xhrResponse) {
			$('pageContentContainer').innerHTML = xhrResponse.responseText;
		}
	});
	return (false);
}





function getElementsByRegExpId(p_regexp, p_element, p_tagName) {
	p_element = p_element === undefined ? document: p_element;
	p_tagName = p_tagName === undefined ? '*': p_tagName;

	var v_return = [];
	var v_inc = 0;

	for (var v_i = 0, v_il = p_element.getElementsByTagName(p_tagName).length; v_i < v_il; v_i++) {
		if (p_element.getElementsByTagName(p_tagName).item(v_i).id &&
		p_element.getElementsByTagName(p_tagName).item(v_i).id.match(p_regexp)) {
			v_return[v_inc] = p_element.getElementsByTagName(p_tagName).item(v_i);
			v_inc++;
		}
	}
	return v_return;
}


function printDOM(node) {
	domstr = domstr + node.nodeType + " " + node.nodeName + " " + node.nodeValue + "\n";
	if (node.hasChildNodes()) {
		for (var i = 0; i < node.childNodes.length; i++) {
			printDOM(node.childNodes.item(i));
		}
	}
}

function getElementPosition(element) {
	var trail = document.getElementById(element);
	var offsetLeft = 0;
	var offsetTop = 0;

	while (trail) {
		offsetLeft += trail.offsetLeft;
		offsetTop += trail.offsetTop;
		trail = trail.offsetParent;
	}

	if (navigator.userAgent.indexOf("Mac") != -1 &&
	typeof document.body.leftMargin != "undefined") {
		offsetLeft += document.body.leftMargin;
		offsetTop += document.body.topMargin;
	}

	return {
		left: offsetLeft,
		top: offsetTop
	};

}


function insertAfter(elem, before) {
	// Takes two objects
	// If the parent's lastchild is the before element append to parent
	// else before element has siblings so put it before the next sibling
	var parent = before.parentNode;

	if (parent.lastchild == before) {
		parent.appendChild(elem);
	} else {
		parent.insertBefore(elem, before.nextSibling);
	}
}

/*********************************************************
 *
 * setOptions (str ElementId, str JSON)
 *
 * generalised method for populating a list with an array
 * of JSON hashes
 * Can support any attributes but MUST include at least
 * a name and value
 *
 * NB
 * It would be nice to use a boolean for selected BUT
 * we use the same library function for generating the data
 * and it needs to produce the selected attribute as is for
 * fallback pruposes on the non-javascript rendering of
 * this data.
 *
 *********************************************************/

function setOptions(id, json) {
	if (json == undefined || id == undefined) {
		return;
	}

	var options = eval(json);

	select = document.getElementById(id);

	if (select !== undefined && json.length) {

		// clear existing children
		if (select.hasChildNodes()) {
			while (select.firstChild) {
				select.removeChild(select.firstChild);
			}
		}

		// populate with new nodes
		for (var i = 0; i < options.length; i++) {
			var opt = document.createElement('option');

			for (var prop in options[i]) {
				if (prop === 'name') {
					opt.appendChild(document.createTextNode(options[i].name));
				} else if (prop === 'selected') {
					if (options[i].selected !== '')
					opt.setAttribute('selected', options[i].selected);
				} else {
					// and any other attributes
					opt.setAttribute(prop, options[i][prop]);
				}
			}

			select.appendChild(opt);
		}
	}
}

/*
function setListItems (id,json) {
if (json == undefined || id == undefined){
	return;
}

var lis = eval (json);
var ul  = $(id);

if (ul !== null && json.length) {
	// clear existing children
	if(ul.hasChildNodes()) {
	  while(ul.firstChild) {
	ul.removeChild($(id).firstChild);
	  }
	}


	// populate with new nodes
	for (var i = 0; i < lis.length; i++) {
	  var li = document.createElement ('li');
	  ul.appendChild (document.createTextNode (lis[i]));

	}
}
}

*/

/*********************************************************
 *
 * setTableRows (str ElementId, str JSON)
 *
 * takes a JSON array of hashes and transforms it into a
 * series of table rows.
 * Supports the following properties:
 * tr: class
 * td: class, headers, title
 * a:  class, href, target
 *
 *********************************************************/

function setTableRows(id, json) {

	if (json == undefined || id == undefined) {
		return;
	}

	var rows = eval(json);

	var tbody = document.getElementById(id);

	if (tbody != undefined && json.length) {

		// clear existing children
		if (tbody.hasChildNodes()) {
			while (tbody.firstChild) {
				tbody.removeChild(tbody.firstChild);
			}
		}

		// populate with new nodes
		for (var i = 0; i < rows.length; i++) {
			var row = document.createElement('tr');
			// set class for the row, if any
			// and because IE is completely braindead
			rows[i].classname != undefined && row.setAttribute('className', rows[i].classname);
			rows[i].classname != undefined && row.setAttribute('class', rows[i].classname);

			var cells = rows[i].cells;

			for (var j = 0; j < cells.length; j++) {
				var cell = document.createElement('td');

				// ditto above. I spent 5 hours sorting this out.  Thanks Bill your browser stinks!
				cells[j].classname != undefined && cell.setAttribute('class', cells[j].classname);
				cells[j].classname != undefined && cell.setAttribute('className', cells[j].classname);
				cells[j].headers != undefined && cell.setAttribute('headers', cells[j].headers);
				cells[j].title != undefined && cell.setAttribute('title', cells[j].title);

				var data = document.createTextNode(cells[j].data);

				if (cells[j].href != null) {
					var link = document.createElement('a');
					cells[j].title != undefined && link.setAttribute('title', cells[j].title);
					cells[j].href != undefined && link.setAttribute('href', cells[j].href);
					cells[j].target != undefined && link.setAttribute('target', cells[j].target);
					link.appendChild(data);
					cell.appendChild(link);
				} else {
					cell.appendChild(data);
				}

				row.appendChild(cell);
			}

			tbody.appendChild(row);
		}
	}
}

