
function jsInclude(src)
{
	document.write('<scr' + 'ipt src="' + src + '">' + '</scr' + 'ipt>\n');
}

if (!document.evaluate) jsInclude("/js/xpath.js");

function url(u, org, program)
{
// RewriteRule ^@([^/:]+)(:([0-9]+))?/(.*)$ /$4?_org=$1&_progId=$3 [L,NS,NC,QSA]
	var matches = /@([^\/:]+)(:([0-9]+))?/.exec(document.location.href);
	var o,p;
	if (matches != null)
	{
		o = matches[1];
		p = matches[3];
	}
	if (typeof org != "undefined" && org != null)
	{
		o = org == "none" ? null : org;
	}
	if (typeof program != "undefined")
	{
		p = program == "none" ? null : program;
	}

	if (o)
		u = "/@" + (p ? o + ":" + p + u : o + u);

	var spanHitId = document.getElementById('hit-id');
	if (spanHitId)
	{
		if (u.lastIndexOf('?') == -1)
			u += "?";
		else
			u += "&";
		u += "h=" + spanHitId.innerHTML;
	}

	return u;
}

/*
	Delegate: a static class to help keep events tied to an object.
*/
var Delegate = {
	objects: new Array(),
	
	/*
		(object) ptr: the object the event should be tied to
		(string) func: the name of the function that should be called; it must reside in the ptr object.
	*/
	create: function(ptr, func)
	{
		if (!ptr._delegates)
		{
			ptr._delegates = new Array();
			Delegate.objects[Delegate.objects.length] = ptr;
		}
		
		return !ptr._delegates[func] ? (ptr._delegates[func] = function(event) { return ptr[func](event); }) : ptr._delegates[func];
	},
	
	/*
		Returns a delegate already created. Note that subsequent calls to 'create' are the
		same as calling get, so this method really doesn't ever _need_ to be used.
	*/
	get: function(ptr, func)
	{
		return (!ptr._delegates || !ptr._delegates[func]) ? false : ptr._delegates[func];
	},
	
	/*
		Destroys the delegate (but not the actual function). It can be useful in removing
		small memory leaks in some browsers, but doesn't have to be called.
	*/
	destroy: function(ptr, func)
	{
		if (!ptr._delegates || !ptr._delegates[func]) return false;
		
		ptr._delegates[func] = null;
	},
	
	/*
		Destroys all the delegates. (See the destroy method.)
	*/
	destroyAll: function()
	{
		for (var i in Delegate.objects)
		{
			for (var j in Delegate.objects[i]._delegates)
			{
				Delegate.objects[i]._delegates[j] = null;
			}
		}
	}
};

/*
	RPC: a static class used to make realtime class to the server via XMLHttpRequest.
	Can be used with post or get, and utilizes extendable callback methods.
*/
var RPC2 = {
	// responseType enumerations
	HTML: 1, // the response will be sent to the loader function as-is
	JSON: 2, // the response will be evaluated as a JavaScript object.
	XML:  3, // the response will be passed as an XML node
	
	/*
		 Creates and returns a new transport. This is the first method that
		 should be called when you want to set up a new RPC.
	*/
	create: function()
	{
		return new RPC2.transport();
	},
	
	/*
		Creates the necessary transport object, depending on the browser's capabilities.
		(Should be considered a private method.)
	*/
	transport: function()
	{
		this.responseType = RPC2.HTML;
		this.fields = Object();
		
		this.obj = new XMLHttpRequest();
		
		if (this.obj)
		{
			this.obj.onreadystatechange = Delegate.create(this, 'onReadyStateChange');
		}
	}
};

/* create wrapper functions for XMLHttpRequest */
if (window.ActiveXObject) window.XMLHttpRequest = function() 
{
	/* IE */
	if (window.ActiveXObject)
	{
		try {
			return new ActiveXObject("Msxml2.XMLHTTP");					
		} catch (e) {
			try {
				return new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {					
				// IE 7 might have ActiveX disabled.
				if ((typeof window.XMLHttpRequest) != "undefined") return new XMLHttpRequest();
			}
		}
	}
		
	return false;
};
else if (!window.XMLHttpRequest) window.XMLHttpRequest = function()
{
	return false;
};

/*
	Private method that handles status change. Only the final state (4)
	is very reliable, so that's all that is recognized.
*/
RPC2.transport.prototype.onReadyStateChange = function()
{
	if (this.obj.readyState == 4)
	{
		if (this.obj.status != 200)
			return this.onError(this.obj.status);
			
		if (this.responseType == RPC2.XML)
		{
			if (!this.obj.responseXML || (this.obj.responseXML.parseError && this.obj.responseXML.parseError != 0))
				this.onError(this.obj.status);
			else
				this.onLoad(this.obj.responseXML.documentElement);
		}
		else if (this.responseType == RPC2.JSON)
		{
			eval("var json = " + this.obj.responseText);
			this.onLoad(json);
		}
		else
			this.onLoad(this.obj.responseText);
	}
};

/* onLoad and onError can be overloaded if needed */
RPC2.transport.prototype.onLoad = function(response) {};
RPC2.transport.prototype.onError =  function(errorCode) {};

/* add a field to a POST request (does nothing for GET) */
RPC2.transport.prototype.addField = function(key, val)
{
	this.fields[key] = val;
};

/* perform a GET request to the url specified */
RPC2.transport.prototype.go = function(url)
{
	this.obj.open("GET", url, true);
	this.obj.send(true);
	return true;
};

/* perform a POST request to the url specified */
RPC2.transport.prototype.post = function(url, ct)
{
	if (!ct) ct = 'application/x-www-form-urlencoded';
	this.obj.open("POST", url, true);
	try {
		this.obj.setRequestHeader('Content-Type', ct);
	}
	catch (e) {
		return false;
	}	
	var data = "";
	var first = true;
	for (var i in this.fields)
	{
		if (first) first = false; else data += "&";
		data += i + "=" + encodeURIComponent(this.fields[i]);
	}	
	this.obj.send(data);
	return true;
};


/* RPC */
function RPC(debug)
{
	this.debug = debug;
	this.fields = new Array();
	this.responseType = 'html';

	if ((typeof window.XMLHttpRequest) != "undefined")
	{
		this.req = new XMLHttpRequest();
	}
	else
	{	
		try {
			this.req = new ActiveXObject("Msxml2.XMLHTTP");					
		} catch (e) {
			try {
				this.req= new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {					
				this.req = false;
			}
		}
	}
}

RPC.prototype.setResponseType = function (type)
{
	this.responseType = (type == 'xml') ? 'xml' : 'html';
}

RPC.prototype.load = function(url)
{
	if (!this.req)
	{
		if (this.debug) alert("DEBUG: Browser is not supported");
		return false;
	}
	
	var me = this;			
	this.url = url;
	
	this.req.onreadystatechange = function()
	{
		if (me.req.readyState == 4)
		{
			if (me.debug && me.req.status != 200) alert("DEBUG: Error (" + me.req.status + ")");
			if (me.onLoad)
			{
				if (me.responseType == 'xml')
				{
					if (!me.req.responseXML || (me.req.responseXML.parseError && me.req.responseXML.parseError != 0))
						me.onLoad(me.req.status, false)
					else
						me.onLoad(me.req.status, me.req.responseXML.documentElement);
				}
				else
					me.onLoad(me.req.status, me.req.responseText);
			}
			else if (me.debug) alert("DEBUG: No onLoad() function defined.");					
		}
	}
	this.req.open("GET", url, true);
	this.req.send(true);
	
	return true;
}

RPC.prototype.addField = function(key, val)
{
	this.fields[key] = val;
}

RPC.prototype.numFields = function()
{
	j = 0;
	for (var i in this.fields) j++;

	return j;
}

RPC.prototype.post = function(url)
{
	if (!this.req)
	{
		if (this.debug) alert("DEBUG: Browser is not supported");
		return false;
	}
	var me = this;			
	this.req.onreadystatechange = function()
	{
		if (me.req.readyState == 4)
		{
			if (me.debug && me.req.status != 200) alert("DEBUG: Error (" + me.req.status + ")");
			if (me.onLoad)
			{
				if (me.responseType == 'xml')
				{
					if (!me.req.responseXML || (me.req.responseXML.parseError && me.req.responseXML.parseError != 0))
						me.onLoad(me.req.status, false)
					else
						me.onLoad(me.req.status, me.req.responseXML.documentElement);
				}
				else
					me.onLoad(me.req.status, me.req.responseText);
			}
			else if (me.debug) alert("DEBUG: No onLoad() function defined.");					
					
		}
	}
	
	this.req.open("POST", url, true);

	//try {
		//if (this.req.setRequestHeader)
			this.req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		//else
		//	alert("Unsupported");
	//}
	//catch (e)
	//{
	//	alert("Error: " + e.message);
	//}
	
	var data = "";
	var first = true;
	for (var i in this.fields)
	{
		if (first) first = false; else data += "&";
		data += i + "=" + encodeURIComponent(this.fields[i]);
	}	
	this.req.send(data);

	return true;
}

/*** Event Stuff ***/

/* Cross Browser Event Handler */
function xEvent(e)
{		
	this.e = !e ? window.event : e;	
}

xEvent.prototype.getObject = function()
{
	if (this.e.srcElement)
		return this.e.srcElement;
	else if (this.e.target)
		return this.e.target;
		
	return false;
}

xEvent.prototype.getX = function()
{
	if (this.e.pageX)	
		return this.e.pageX;	
	else if (this.e.clientX)	
		return this.e.clientX + document.body.scrollLeft;	
	return -1;
}

xEvent.prototype.getY = function()
{
	if (this.e.pageY)	
		return this.e.pageY;	
	else if (this.e.clientY)
		return this.e.clientY + document.body.scrollTop;		
	return -1;
}

xEvent.prototype.keyASCII = function()
{
	if (this.e.which && this.e.which >= 32)
	{
		return String.fromCharCode(this.e.which);
	}
	else
		return '';
}

xEvent.prototype.getKeyCode = function()
{
	if (this.e.which)
		return this.e.which;
	else if (this.e.keyCode)
		return this.e.keyCode;
}

xEvent.prototype.keyEnter = function() { return this.e.keyCode == 13; }
xEvent.prototype.keyLeft = function() { return this.e.keyCode == 37 && !this.e.which; }
xEvent.prototype.keyUp = function() { return this.e.keyCode == 38 && !this.e.which; }
xEvent.prototype.keyRight = function() { return this.e.keyCode == 39 && !this.e.which; }
xEvent.prototype.keyDown = function() { return this.e.keyCode == 40 && !this.e.which; }

if (!window.Event) var Event = new Object();

Event.add = function(element, event, callback, capture)
{
	if (element.addEventListener)
		return element.addEventListener(event, callback, capture);
	else if (element.attachEvent)
		return element.attachEvent("on" + event, callback);		
	else
		return false;
};

Event.remove = function(element, event, callback, capture)
{
	if (element.removeEventListener)
		return element.addEventListener(event, callback, capture);
	else if (element.detachEvent)
		return element.detachEvent("on" + event, callback);		
	else
		return false;
};

/* functions to handle className manipulation */
function HTMLElement_firstParentOf(o, nodeName)
{
	while (o && o.nodeName != nodeName) o = o.parentNode;
	return o;
}

function HTMLElement_inClass(o, className)
{
	var re = new RegExp("(^| )" + className + "($| )");
	return re.test(o.className);
}

function HTMLElement_removeClass(o, className)
{
	var old = o.className.split(" ");
	var newClass = new Array();
	for (var i=0; i<old.length; i++)
	{
		if (old[i] != "" && old[i] != className)
			newClass[newClass.length] = old[i];
	}
		
	o.className = newClass.join(" ");
}

function HTMLElement_addClass(o, className)
{
	o.className += " " + className;
}

function HTMLElement_myIndex(o)
{
	var p = o.parentNode;
	if (!p) return 0;
	var l = p.childNodes.length;
	var index = 0;
	for (var i=0; i < l; i++)
	{
		var n = p.childNodes[i];
		if (n == o) return index;
		else if(n.nodeType == 1) ++index;
	}
	
	return -1;
}

/* hack to load multiple onloads (http://www.sitepoint.com/blog-post-view.php?id=171578) */
function addLoadEvent(func)
{
	addBubbleEvent(window, 'load', func);
}

function addBubbleEvent(o, e, f)
{
	if (!o) return;	
	e = "on" + e;
	
	var oldFunction = o[e];
	if (typeof oldFunction != 'function')
		o[e] = f;
	else
	{
		o[e] = function() {
			oldFunction();
			f();
		}
	}
}

/* find the real x,y coords (http://www.quirksmode.org/js/findpos.html)*/
function getAbsX(obj)
{
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

function getAbsY(obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

/* tool tip functions */
var g_toTooltip = 0;
var g_divTooltip = 0;
var g_tooltipCache = new Array();

function clearTooltip()
{
	try {
		if (g_toTooltip)
		{
			clearTimeout(g_toTooltip);
			g_toTooltip = 0;
		}
		if (g_divTooltip)
		{
			g_divTooltip.parentNode.removeChild(g_divTooltip);
			g_divTooltip = 0;
		}
	}
	catch (e) { /* FF throws an error sometimes??? */ }
}

function setToolTipHTML(ev, html)
{
	var e = new xEvent(ev);
	var x = e.getX();
	var y = e.getY();
	
	g_toTooltip = setTimeout(
		function() { 
			var rpc = new RPC();
			rpc._x = x + 12;
			rpc._y = y + 12;
			rpc.onLoad = showTooltip;
			if ((typeof html) == "function")
				rpc.onLoad(200, html(e));
			else
				rpc.onLoad(200, html);
		},
	1000);
}


function setToolTip(ev, func)
{
	var e = new xEvent(ev);
	var x = e.getX();
	var y = e.getY();
	
	g_toTooltip = setTimeout(
		function() { 
			var url = func(e);
			var rpc = new RPC();
			rpc._x = x + 12;
			rpc._y = y + 12;
			rpc.onLoad = showTooltip;
			if (!g_tooltipCache[url])
				rpc.load(url);
			else
				rpc.onLoad(200, g_tooltipCache[url]);
		},  
	1000);
}

function showTooltip(status, html)
{
	if (status == 200)
	{
		clearTooltip();
		if (this.url) g_tooltipCache[this.url] = html;
		
		if (!html) return;
		
		g_divTooltip = document.createElement("DIV");
		g_divTooltip.style.position = "absolute";
		g_divTooltip.style.top = "0px";
		g_divTooltip.style.left = "0px";
		g_divTooltip.style.visibility = "hidden";
		
		g_divTooltip.className = "drop-shadow";
		
		var divInner = document.createElement("DIV");
		divInner.className = "wrap";
		var divDB = document.createElement("DIV");
		divDB.className = "tool-tip";
		divDB.innerHTML = html;
		divInner.appendChild(divDB);	
		
		g_divTooltip.appendChild(divInner);

		document.getElementsByTagName("BODY").item(0).appendChild(g_divTooltip);
		
		var sw = document.getElementsByTagName("BODY").item(0).offsetWidth;
		if (sw < g_divTooltip.offsetWidth + this._x)
		{
			g_divTooltip.style.top = this._y + "px";
			g_divTooltip.style.left = (sw - g_divTooltip.offsetWidth) + "px";
		}
		else
		{
			g_divTooltip.style.top = this._y + "px";
			g_divTooltip.style.left = this._x + "px";
		}
		
		// eliminates the flash that may show otherwise
		setTimeout('if (g_divTooltip) g_divTooltip.style.visibility = "visible"',  1);
	}
}


/* Onload */
var DOMLoaded = false;
var DOM_onLoad_functions = new Array();
function dom_onLoad()
{
	if (DOMLoaded) return;
	DOMLoaded = true;
	
	for (var i=0; i<DOM_onLoad_functions.length; i++)
		DOM_onLoad_functions[i]();
}

function add_DOM_onLoad(func)
{
	DOM_onLoad_functions[DOM_onLoad_functions.length] = func;
}

if (document.addEventListener) document.addEventListener("DOMContentLoaded", dom_onLoad, false);
addBubbleEvent(window, 'load', dom_onLoad);


/* ========================== WIKI EDITOR ========================== */
add_DOM_onLoad(
	function()
	{
		if (!document.evaluate) return false;
		
		var divs = document.evaluate("//div[@class='wiki-toolbar']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
		var length = divs.snapshotLength;
		for (var i=0; i<length; i++)
		{
			var img = divs.snapshotItem(i).getElementsByTagName("INPUT")[0];
			img.onclick = wikiBtnImage_onClick;
		}
		
		divs = document.evaluate("//div[@class='wiki-tabbar']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
		length = divs.snapshotLength;
		for (var i=0; i<length; i++)
		{
			var span = divs.snapshotItem(i).getElementsByTagName("SPAN");
			span.item(0).onclick = wikiEdit_onClick;
			span.item(1).onclick = wikiPreview_onClick;
		}
		
		divs = document.evaluate("//div[@class='tabbed-form']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
		length = divs.snapshotLength;
			
		for (var i=0; i<length; i++)
		{
			var divTabContainer = divs.snapshotItem(i);
			
			var divTabBar = document.createElement("DIV");
			divTabBar.className = "tab-bar";
			
			var tblSections = document.evaluate("//table[@class='form-section']", divTabContainer, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
			var tblSectionCount = tblSections.snapshotLength;
			
			var w = 0;
			
			for (var j=0; j<tblSectionCount; j++)
			{
				var spanTab = document.createElement("SPAN");
				if (!j) spanTab.className = "selected";
				spanTab.innerHTML = tblSections.snapshotItem(j).summary;
				spanTab.pos = j;
				spanTab.onclick = formTab_onClick;
				divTabBar.appendChild(spanTab);
				
				if (w < tblSections.snapshotItem(j).offsetWidth)
					w = tblSections.snapshotItem(j).offsetWidth;
				
				if (j) tblSections.snapshotItem(j).style.display = "none";
			}
			
			for (var j=0; j<tblSectionCount; j++)
			{
				tblSections.snapshotItem(j).width = w;
			}
			
			divTabContainer.insertBefore(divTabBar, divTabContainer.firstChild);
		}	
	}
);

function formTab_onClick(e)
{
	var e = new xEvent(e);
	var o = e.getObject();
	var divTabContainer = o.parentNode.parentNode;
	var divTabBar = o.parentNode;
	var tblSections = document.evaluate("//table[@class='form-section']", divTabContainer, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	var tblSectionCount = tblSections.snapshotLength;
	for (var i=0; i<tblSectionCount; i++)
	{
		if (i == o.pos)
		{
			tblSections.snapshotItem(i).style.display = "";
			HTMLElement_addClass(divTabBar.childNodes[i], "selected");
		}
		else
		{
			tblSections.snapshotItem(i).style.display = "none";
			HTMLElement_removeClass(divTabBar.childNodes[i], "selected");
		}
	}
}

function wikiEdit_onClick(e) 
{
	var e = new xEvent(e);
	var o = e.getObject();
	var divWiki = o.parentNode.parentNode;
	
	HTMLElement_addClass(o, "selected");
	HTMLElement_removeClass(o.parentNode.getElementsByTagName("SPAN").item(1), "selected");
	
	var divPreview = document.evaluate("//div[@class='preview']", divWiki, null, 0, null).iterateNext();
	if (divPreview)
	{
		divPreview.style.display = "none";
	}
}

function wikiPreview_onClick(e)
{
	var e = new xEvent(e);
	var o = e.getObject();
	var divWiki = o.parentNode.parentNode;
	
	var ta = divWiki.getElementsByTagName("TEXTAREA").item(0);
	var h = ta.offsetHeight, w = ta.offsetWidth;
	
	var divPreview;
	
	if (!document.evaluate("count(//div[@class='preview'])", divWiki, null, XPathResult.NUMBER_TYPE, null).numberValue)
	{
		divPreview = document.createElement("DIV");
		divPreview.className = "preview";
		divPreview.style.fontFamily = "Verdana, Arial";
		divPreview.style.fontSize = "12px";
		divPreview.style.lineHeight = "1.4";
		divPreview.style.position = "absolute";
		divPreview.style.backgroundColor = "white";
		divPreview.style.border = "inset black 1px";
		divPreview.style.padding = "8px";
		divPreview.style.zIndex = 100;
		divPreview.style.overflow = "auto";
		divPreview.style.left = getAbsX(ta) + "px";
		divPreview.style.top = getAbsY(ta) + "px";
		divPreview.style.height = (h-18) + "px";
		divPreview.style.width = (w-18) + "px";
	}
	else
	{
		divPreview = document.evaluate("//div[@class='preview']", divWiki, null, 0, null).iterateNext();
		divPreview.style.display = "block";
	}
	
	divPreview.innerHTML = "Loading...";
	divWiki.insertBefore(divPreview, ta);
	
	var rpc = new RPC();
	rpc.addField("wikitext", ta.value);
	rpc.onLoad = function(status, html)
	{
		divPreview.innerHTML = html;
	}
	rpc.post("/rpc/preview-wiki.rpc.php");
	
	
	HTMLElement_addClass(o, "selected");
	HTMLElement_removeClass(o.parentNode.getElementsByTagName("SPAN").item(0), "selected");
}

function wikiBtnImage_onClick(e)
{
	var e = new xEvent(e);
	var o = e.getObject();
	var imageGallery = document.getElementById("tr-" + o.getAttribute("gallery"));

	if (imageGallery)
	{
		var textarea = o.parentNode.parentNode.getElementsByTagName("TEXTAREA")[0];
		window.open("/select-image-from-list/" + textarea.id + "/" + o.getAttribute("gallery"), "select_image", "dependent=yes,width=400,height=400,left=" + (screen.width/2-200) + ",top=" + (screen.height/2-200));
	}
}

function wikiBtnImage_onLoad(ta_id, gallery_id)
{
	var trGallery = document.getElementById("tr-" + gallery_id);
	var li = trGallery.getElementsByTagName("LI");
	var liCount = li.length;
	var imgList = new Array();
	for (var i=0; i<liCount; i++)
	{
		var img = li[i].getElementsByTagName("IMG")[0];
		var span = li[i].getElementsByTagName("SPAN")[0];
		var id = /-([0-9]+)$/.exec(img.id)[1];
		imgList[id] = {"caption": span.innerHTML, "src": img.src};
	}
	
	return imgList;
}

function wikiBtnImage_onSelect(ta_id, code)
{
	var textarea = document.getElementById(ta_id);

	if (textarea.selectionStart || textarea.selectionStart == '0') 
	{
		var startPos = textarea.selectionStart;
		var endPos = textarea.selectionEnd;
		textarea.value = textarea.value.substring(0, startPos) + code + textarea.value.substring(endPos, textarea.value.length);
		textarea.focus();
		textarea.selectionStart = (startPos + code.length);
		textarea.selectionEnd = (startPos + code.length);
	}
	else if (document.selection)
	{
		textarea.focus();
		sel = document.selection.createrange();
		sel.text = code;
	}
	else
		textarea.value += code;	
	
}

/* ========================== IMAGE LIST ========================== */
function imageListUpload_onClick(e)
{
	var e = new xEvent(e);
	var o = e.getObject();
	var fieldset = o;
	while (fieldset && fieldset.nodeName != "FIELDSET") fieldset = fieldset.parentNode;
	
	var matches = /([^-]+)-([0-9]+)/.exec(fieldset.id);
	var linkType = matches[1];
	var linkId = matches[2];

	window.open("/image-upload/" + linkType + "/" + linkId, "image_upload", "dependent=yes,width=400,height=400,left=" + (screen.width/2-200) + ",top=" + (screen.height/2-200));
}

function imageList_onSelect(field_id, image_id, caption, filename)
{
	var fieldset = document.getElementById(field_id);
	var ul = fieldset.getElementsByTagName("UL")[0];
	var li = document.createElement("LI");
	var img = document.createElement("IMG");
	var span = document.createElement("SPAN");
	
	img.id = "img-" + image_id;
	img.src = "/images/gallery/" + filename;
	img.onclick = imageListImage_onClick;
	span.innerHTML = caption;
	
	li.appendChild(img);
	li.appendChild(document.createElement("BR"));
	li.appendChild(span);
	ul.appendChild(li);
	
	if (fieldset.dependents)
	{
		var len = fieldset.dependents.length;
		for (var i=0; i<len; i++)
		{
			var o = fieldset.dependents[i];
			o.options[o.options.length] = new Option(caption, image_id);
		}
	}
}

function imageListImage_onClick(e)
{
	var e = new xEvent(e);
	var o = e.getObject();
	var fieldset = o;
	while (fieldset && fieldset.nodeName != "FIELDSET") fieldset = fieldset.parentNode;
	
	var imgList = document.evaluate("ul/li/img", fieldset, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	var imgListCount = imgList.snapshotLength;
			
	for (var i=0; i<imgListCount; i++)
	{
		imgList.snapshotItem(i).className = "";
	}	
	
	o.className = "selected";
	
	fieldset.getElementsByTagName("INPUT")[2].disabled = false;
}

function imageListDelete_onClick(e)
{
	var e = new xEvent(e);
	var o = e.getObject();
	var fieldset = o;
	while (fieldset && fieldset.nodeName != "FIELDSET") fieldset = fieldset.parentNode;
	
	var imgList = document.evaluate("ul/li/img", fieldset, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	var imgListCount = imgList.snapshotLength;
	
	var imageId = 0;
			
	for (var i=0; i<imgListCount; i++)
	{
		var img = imgList.snapshotItem(i);
		if (img.className == "selected")
		{
			imageId = /img-([0-9]+)/.exec(img.id)[1];
			var li = img.parentNode;			
			li.parentNode.removeChild(li);
			break;
		}
	}
	
	var matches = /([^-]+)-([0-9]+)/.exec(fieldset.id);
	var linkType = matches[1];
	var linkId = matches[2];
	
	var rpc = new RPC();
	rpc.load("/rpc/delete-image.rpc/" + linkType + "/" + linkId + "/" +imageId);
	
	fieldset.getElementsByTagName("INPUT")[2].blur();
	fieldset.getElementsByTagName("INPUT")[2].disabled = true;
	fieldset.style.display = "none";
	fieldset.style.display = "";
	
	if (fieldset.dependents)
	{
		var len = fieldset.dependents.length;
		for (var i=0; i<len; i++)
		{
			var o = fieldset.dependents[i];
			var oLen = o.options.length;
			for (var j=0; j<oLen; j++)
			{
				if (o.options[j].value == imageId)
				{
					o.options[j] = null;
					break;
				}
			}
		}
	}
}

add_DOM_onLoad(
	function()
	{
		var imgGallery = document.evaluate("//fieldset[@class='image-gallery']/ul/li/img", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
		var imgGalleryCount = imgGallery.snapshotLength;
				
		for (var i=0; i<imgGalleryCount; i++)
		{
			imgGallery.snapshotItem(i).onclick = imageListImage_onClick;
		}
		
		
		var imgList = document.evaluate("//select[@class='image-list']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
		var imgListCount = imgList.snapshotLength;
				
		for (var i=0; i<imgListCount; i++)
		{
			var fieldset = document.getElementById("tr-" + imgList.snapshotItem(i).getAttribute("gallery")).getElementsByTagName("FIELDSET")[0];
			if(!fieldset.dependents)
				fieldset.dependents = new Array();
				
			fieldset.dependents[fieldset.dependents.length] = imgList.snapshotItem(i);
		}
	}
);

/* ========================== SURVEYS ========================== */

function calculate_percentages(inputs, changed_object)
{
	total = 0;

	for(var i = 0; i < inputs.length; i++)
	{
		var val = inputs[i].value;
		for(var j = 0; j < val.length; j++)
		{
			character = val.charAt(j);
			if(character < "0" || character > "9")
			{
				val = val.replace(character, "");
			}
			if(j == 0 && character == "0")
			{
				val = val.replace(character, "");
			}
		}
		inputs[i].blur();
		inputs[i].value = val;

		var subtot = parseInt(inputs[i].value);
		if(!isNaN(subtot)) total += subtot;
	}

	if(total > 100)
	{
		total -= changed_object.value;
		changed_object.value = 100 - total;
		total = 100;
	}

	changed_object.focus();
	
	var question_id = changed_object.id.split("-");

	document.getElementById("percentage_total_" + question_id[0]).innerHTML = total;
}

function dTable(tbl)
{
	this.domTable = tbl;
	/*
	this.maxHeight = 0;
	this.selectedRow = 0;
	this.column = new Array();
	*/
}

function drag_row(td)
{
	var tr = HTMLElement_firstParentOf(td, "TR");
	if (tr.parentNode.nodeName == "TBODY")
	{
		var self = this;
		this.domTable.style.cursor = "move !important";
		this.dragRow = tr;
		this.dragRowI = HTMLElement_myIndex(tr);
		this.setCSSDragTO = setTimeout(function() { if (self.dragRow == tr) HTMLElement_addClass(self.dragRow,"dragging"); }, 500);
		return false;
	}
}

function formElementPercentages_onKeyUp(event)
{
	var e = new xEvent(event);
	var o = e.getObject();

	var inputs = HTMLElement_firstParentOf(o, "TBODY").getElementsByTagName("INPUT");
	calculate_percentages(inputs, o);
}

add_DOM_onLoad(
	function()
	{
		var inputs = document.getElementByClassName("INPUT", "percentages");

		for(var i = 0; i < inputs.length; i++)
		{
			inputs[i].onkeyup = formElementPercentages_onKeyUp;
		}
	}
);

function formElementRanked_onMouseDown(event)
{
	var e = new xEvent(event);
	var td = e.getObject();

	var tbl = HTMLElement_firstParentOf(td, "TABLE");

	drag_row(td);
}

function object_alert(o) {
	var txt;
	for (objprop in o)
	{
		txt += objprop + ' => ' + o[objprop] + '\n';
	}
	alert(txt);
}

add_DOM_onLoad(
	function()
	{
		var tables = document.getElementByClassName("TABLE", "reorder-question");
		for(var i = 0; i < tables.length; i++)
		{
			tables[i].onmousedown = formElementRanked_onMouseDown;
		}
	}
);

document.getElementByClassName = function(tagName, className)
{
	var elements = document.getElementsByTagName(tagName);
	var matches = new Array();

	for(var i = 0; i < elements.length; i++)
	{
		if (elements[i].className == className)
		{
			matches[matches.length] = elements[i];
		}
	}

	return matches;
}

document.getElementsByClassName = function(tagName, className)
{
	return document.getElementByClassName(tagName, className);
}

/* ========================== SPLIT TABLES ========================== */
function splitTable(table)
{
	var tableHead = table.cloneNode(true);
	tableHead.id = table.id + "-head";
	var div = document.createElement("DIV");

	div.style.maxHeight = "200px";
	div.style.overflow = "auto";
	
	table.parentNode.insertBefore(div, table);
	table.style.borderTop = "0px solid white";
	
	div.appendChild(table.parentNode.removeChild(table));
	
	try {
		tableHead.removeChild(tableHead.getElementsByTagName("TBODY")[0]);
		table.removeChild(table.getElementsByTagName("THEAD")[0]);
	} catch (e) {
		alert("Trying to split a table that doesn't have a TBODY and THEAD");
		return false;
	}
	
	div.parentNode.insertBefore(tableHead, div);

	resizeTable(table);
}

function resizeTable(table)
{
	var tableHead = document.getElementById(table.id + "-head");	
	tableHead.style.width = table.offsetWidth + "px";
	
	var trHead = tableHead.getElementsByTagName("TR")[0];	if (!trHead) return;	
	var tr = table.getElementsByTagName("TR")[0];           if (!tr) return;
	var tdHead = trHead.getElementsByTagName("TD");
	var td = tr.getElementsByTagName("TD");
	
	try {	
		for (var i=0; i<td.length; i++)	
		{
			var hw = Number(tdHead[i].offsetWidth);
			td[i].style.width = hw + "px";
			var w = Number(td[i].offsetWidth);
			td[i].style.width = (tdHead[i].offsetWidth + (hw - w)) + "px";
		}	
	}
	catch (e) {
		alert("Note: resizing table failed.");
	}

}

/* ========================== EXTERNAL LINKING ========================== */

function externalLink(h, t, new_window)
{
	rpc = new RPC();

	rpc.onLoad = function()
	{
		if(new_window == "1")
		{
			window.open(h, "mywin");
		}
		else
		{
			window.location.href = h;
		}
	}

	rpc.addField('href', h);
	rpc.addField('title', t);
	rpc.post("/rpc/external-link.rpc");
	
}

// prevent session timeout, ping every 5 minutes
var g_pingCount = 0;
var g_pingInterval = window.setInterval(
	function() {
		var rpc = new RPC();
		rpc.load('/rpc/ping.rpc');
		
		if (++g_pingCount > 100)
			window.clearInterval(g_pingInterval);
	}
, 300000);
