function checkforms(){
	var numF=document.forms.length;
	if(numF > 0){
		for(i=0;i<numF;i++){
			//alert(document.forms[i].elements.length);
			for(j=0;j<document.forms[i].elements.length;j++){
				var e=document.forms[i].elements[j];
				if(e.type=="text"){
					e.onfocus=function(){ 
						this.style.backgroundColor = '#9a9a9a';
					};
					e.onblur=function(){ 
						this.style.backgroundColor = '#c9c9c9';
						
					};
				}
			}
		}
	}
}

function focus(element){
	//alert(element);
	element.value="1px solid white";
}
function createLightbox(content, lightboxId, className)
{
	var lightbox = _getLightboxHTML.apply(this, arguments);

	document.body.appendChild(lightbox);

	addEvent(document.body, 'keyup', function(e)
	{
		if(e.keyCode == 27 && (e.srcElement || e.target) == document.body) // escape
		{
			toggleLightbox(lightboxId);
			removeEvent(document.body, 'keyup', arguments.callee)
		}
	});

	jscss('add', document.body, 'displaying-lightbox');

	if(lightbox.scrollIntoView)
		lightbox.scrollIntoView();

	return lightbox;
};

function _getLightboxHTML(content, lightboxId, className)
{
	return createDOMNode(
		'div',
		{
			'id' : lightboxId,
			'class' : 'lightbox' + (className ? ' ' + className : ''),
			'event' :
			[
				'click',
				function(e)
				{
					if(e._dontClose)
						return;

					if(jscss('check', e.target || e.srcElement, 'lightbox'))
					{
						jscss('remove', document.body, 'displaying-lightbox');
						jscss('add', this, 'display-none');
					}
				}
			]
		},
		[ content ]
	);
}

function determineLightboxIdentifier(lightboxId)
{
	if(typeof lightboxId != 'string')
	{
		var lightbox = this.parentNode;

		while(!jscss('check', lightbox, 'lightbox') && lightbox.tagName != 'html')
			lightbox = lightbox.parentNode;

		if(lightbox.tagName == 'html')
			return false;

		lightboxId = lightbox.id;
	}

	return lightboxId;
}

function toggleLightbox(lightboxId, destroy)
{
	lightboxId = determineLightboxIdentifier.call(this,lightboxId);

	var lightbox = new DOMQuery('div#' + lightboxId).get(0);

	if(lightbox)
	{
		if(destroy)
			lightbox.parentNode.removeChild(lightbox);

		jscss('toggle', document.body, 'displaying-lightbox');
		jscss('toggle', lightbox, 'display-none');

		if(!jscss('check', lightbox, 'display-none') && lightbox.scrollIntoView)
			lightbox.scrollIntoView();

		return true;
	}
};
function contentInLayer(targets)
{
	if(!jscss('check', DOMQuery.prototype.scope, 'lightbox-content'))
		addEventToTargets(targets, 'click', _contentInLayer, 'a[rel^="layer"], body.list_messages div.extra-actions ul.links li[class] a, body.list_message div.extra-actions ul.links li[class] a');
};

function _contentInLayer(e)
{
	var rel = this.getAttribute('rel') && this.getAttribute('rel').match(/layer\[([^\]]+)\]/i);
	var className = 'layer' + (rel && rel.length ? '-' + rel[1] : '');

	/* Determine an id to identify this layer */
	var id;
	if(this.id)
		id = 'layer-' + this.id;
	else if(this.className)
		id = 'layer-' + this.className.replace(/\s/, '-');
	else
		id = (this.pathname + this.search).replace(/[^a-z]+/g, '-').replace(/^-*|-*$/, '');

	var specificElement = 'div#core';
	var container, onSubmitCallback;
	if(typeof _contentInLayerCallback == 'function')
	{
		var result = _contentInLayerCallback(this, id, rel);
		if(result === false)
		/* if result is explicitally 'false', the _contentInLayerCallback refuses to handle this, and indicates a removal */
		{
			e.preventDefault();
			return;
		}
		else if(result)
		{
			specificElement = result['specificElement'];
			container = result['container'];
			onSubmitCallback = result['onSubmitCallback'];
			updateType = result['updateType'];
		}
	}

	if(!container)
	{
		if(!id.length)
			return false;

		/* Check if lightbox already exists */
		if(toggleLightbox(id))
		{
			e.preventDefault();
			return;
		}

		container = createDOMNode(
			'div', 	{ 'class' : 'lightbox-content loading' }, [
				createDOMNode('span', { 'class' : 'clickable close', 'id' : 'close', 'event' : ['click', toggleLightbox] }, [ 'Sluit venster' ])
			]
		);

		var lightbox = createLightbox(container, id, className);
		jscss('add', lightbox, 'request-running');
	}

	e.preventDefault();

	/*	Fix bug in both IE6 and Safari; when a.pathname is used and the a.href contains
	 *	special characters (for example <a href=".../%FCn%EDc%A7de%20dingen">):
	 *		* IE6 - decodes both a.href and a.pathname
	 *		* Safari - decodes a.pathname
	 */
	var pathname, href;
	if (isIE6 || isWebKit)
	{
		if (isIE6)
			href = this.getAttribute('href', 2);
		else
			href = this.href;

		pathname = href.replace(/^https?:\/\/[^/]+(\/.*)$/, '$1');

		if (isIE6)
			pathname = pathname.substring(1);
	} else
		pathname = this.pathname;

	var req = httpreq_string(this.search.substr(1), null, (isIE ? '/' : '') + pathname, true, 'GET');
	var invoker = this; /* we assign this to a custom name so scoping with 'this' wont be a problem later on */
	req.onreadystatechange = function()
	{
		if (req.readyState != 4)
			return;

		jscss('remove', invoker, 'request-running');

		if(lightbox)
			jscss('remove', lightbox, 'request-running');

		if(req.getResponseHeader('X-Errormessage'))
		{
			handleXErrorMessage( req.getResponseHeader('X-Errormessage'), container );
			return;
		}

		var element = getElementFromXHR(req, specificElement);
		// console.log('fetching ', specificElement, ' from ', req, ' found ', element);
		if(!element)
		{
			if(lightbox)
				toggleLightbox(id);

			document.location.href = invoker.href;
			return;
		}

		var form = new DOMQuery('form.primary-input', element).get(0);
		if(!form && element.tagName.toLowerCase() == 'form')
			form = element;

		if(form)
		{
			/*
				To prevent the onsubmit() function to submit the form using a XHR,
				we have to store wether any previous action has stopped the default action
				(submitting of the form).
				So, we attach a special event at the propagation-phase (before all events[]
				do their work) at the parentNode, and modify the event-object to store
				wether preventDefault() has been called.
				Then, the second event-listener is called during the bubble-phase - and it
				checks wether the event has determined preventDefault() has been called.

				However... IE must die!
				It doesn't support propagation for submit-events, so we use the addEvent's behaviour
				of calling the functions in sequence of assignment to emulate the behaviour.
			*/

			var eventTarget = form;
			if(form.addEventListener)
			{
				var eventTarget = element;
			}

			/* only attach the handler on the container once */
			if(eventTarget.tagName == 'form' || typeof eventTarget.__preventDefaultHandler == 'undefined')
			{
				addEvent.eventListenerUseCapture = true;
				addEvent(eventTarget, 'submit', function(e)
				{
					e.__preventDefault = e.preventDefault;
					e.preventDefault = function()
					{
						e.defaultPrevented = true;
						e.__preventDefault();
					};
				});
				addEvent.eventListenerUseCapture = false;
				eventTarget.__preventDefaultHandler = true;
			}

			var onsubmit = function(e)
			{
				if(e.defaultPrevented)
					return false;

				jscss('add', invoker, 'request-running');

				/* find out wether preview or submit has been hit */
				if(e && e.type == "submit" && typeof e.explicitOriginalTarget != 'undefined' && e.explicitOriginalTarget.name == "data[preview]")
					return true;

				var processResult = function(transport, error)
				{
					jscss('remove', invoker, 'request-running');

					if(error)
					{
						handleXErrorMessage( error, container );
						return;
					}

					var callbackResult = {
						removeForm: true,
						toggleLightbox: true
					};

					if(onSubmitCallback) {
						tmpCallbackResult = onSubmitCallback(transport, container, invoker);

						if (typeof tmpCallbackResult == "object")
							callbackResult = tmpCallbackResult;
					}

					if(callbackResult.removeForm)
						form.parentNode.removeChild(form);

					if(lightbox && callbackResult.toggleLightbox)
					{
						toggleLightbox(id, true);
					}

					jscss('add', invoker, 'request-completed');
					setTimeout(function() { jscss('remove', invoker, 'request-completed'); jscss('remove', invoker, 'request-active'); }, 5000);
				};

				var request = gatherHttpForm(this);

				if(request)
				{
					var updatereq = httpreq_string(request, null, null, false);

					/* Evaluate javascripts TODO */
					/*
					var scripts = new DOMQuery('script[type="text/javascript"]', updatereq);
					for(var i = 0, script; (script = scripts.get(i)); i++)
						if(script.getAttribute('src') == '')
							eval(script.innerHTML);
					*/

					processResult(updatereq, updatereq.getResponseHeader('X-Errormessage'));

					e.preventDefault();
				}
				else // submit to iframe
				{
					var iframeName = 'iframe-xhr-emulator-' + new Date().getTime();
					var iframeName = 'iframe-xhr-emulator';
					var oldIframe = new DOMQuery('iframe#' + iframeName).get(0);
					if(oldIframe)
						oldIframe.parentNode.removeChild(oldIframe);

					if(isIE)
					{
						var ieHelper = createDOMNode('div', {}, []);
						ieHelper.innerHTML = '<iframe name="'+iframeName+'" id="'+iframeName+'" src="about:blank"></iframe>';
						document.body.appendChild(ieHelper);
						ieHelper.firstChild.onreadystatechange = function(){ if(this.readyState=='complete') { processResult(this.contentWindow, parent.frames[iframeName].error_message);} };

					}
					else
					{
						document.body.appendChild(createDOMNode('iframe', {'class' : 'display-none', 'name' : iframeName, 'id' : iframeName, 'event' : ['load', function(){ processResult(this.contentDocument, window.frames[iframeName].error_message); }]}, []));
					}

					this.target = iframeName;
					this.setAttribute('target', iframeName);
					this.appendChild(createDOMNode('input', {'type' : 'hidden', 'name' : 'dont_meta_refresh', 'value' : '1'}, []));

					return;
				}
			};

			addEvent(form, 'submit', onsubmit);
		}

		// var div = createDOMNode('div', {'id' : 'core'}, [element]);

		if (typeof updateType == 'string' && updateType == 'replace') {
			var myparent = getSiblingNode(container, 'up');
			myparent.replaceChild(element, container);
			container = element;
		} else
			container.appendChild(element);

		if(!e.inline)
			jscss('add', document.body, 'displaying-lightbox');

		/* Evaluate javascripts */
		var scripts = new DOMQuery('script[type="text/javascript"]', container);
		for(var i = 0, script; (script = scripts.get(i)); i++)
			if(script.getAttribute('src') == null || script.getAttribute('src') == '')
				eval(script.innerHTML);

		/* Fire events applied to container */

		_init(events, container);

		jscss('remove', container, 'loading');
	};

	e.preventDefault();
};

function handleXErrorMessage(error, container)
{
	alert( error );
};

function _contentInLayerCallback(invoker, id, rel)
{
	if(rel && rel.length) /* it's a layer */
		return;

	/* if it's not a layer, it's a topic-action */
	var li = getSiblingNode(invoker, 'up', 'li');
	if(!li)
		return;

	var topicid = invoker.href.replace(/.+(insert_topicreport|insert_bookmark|add_keywords|delete_keywords|insert_notification|rate|set_topic_posthistory|rate)(\/\D+)?\/(\d+)(.+)?/, '$3');
	if(!topicid)
		return;

	var classNames = jscss('get', li), request, formName;
	for(var i = 0; i < classNames.length;i++)
	{
		switch(classNames[i])
		{
			case 'topic-add-keyword':
			case 'topic-delete-keyword':
				// request = 'action=add_keywords&data%5Btype%5D=topic&data%5Bid%5D='+topicid;
				formName = 'form-add-keywords';

				if(classNames[i] == 'topic-delete-keyword')
				{
					request = 'action=delete_keywords&data%5Btype%5D=topic&data%5Bid%5D='+topicid;
					formName = 'form-delete-keywords';
				}

				var onSubmitCallback = function ()
				{
					var keywords = new DOMQuery('dl.topic-keywords dd').get(0);

					if(!keywords)
						return;

					var newKeywords = new DOMQuery('form#'+formname+' input#keywords').get(0).value;
					var listTopicsUrl = new DOMQuery('a', keywords).get(0).href;

					newKeywords = newKeywords.split(' ');

					for(var j = 0; j < newKeywords.length; j++)
						keywords.appendChild(createDOMNode('a', { 'href' : listTopicsUrl.replace(/=.+/i, '=' + newKeywords[j]) }, [ ' ' + newKeywords[j] ]));
				};
			break;
			case 'topic-report':
				// request = 'action=insert_topicreport&data%5Btopicid%5D='+topicid;
				formName = 'form-insert-topicreport';
			break;
			case 'topic-bookmark':
				// request = 'action=insert_bookmark&data%5Btopicid%5D='+topicid;
				formName = 'form-insert-bookmark';
			break;
			case 'topic-notification':
				// request = 'action=insert_notification&data%5Btype%5D=topic&data%5Bid%5D='+topicid;
				formName = 'form-insert-notification';
			break;
			case 'topic-posthistory':
				// request = 'action=set_topic_posthistory&data%5Btopicid%5D='+topicid;
				formName = 'form-posthistory-set';
			break;
			case 'topic-rate':
				// request = 'action=rate&data%5Btype%5D=topic&data%5Bid%5D='+topicid;
				formName = 'form-rate';
			break;
		}

		if(formName)
			break;
	}

	if(!formName)
		return;

	function removeForm()
	{
		var oldForm = new DOMQuery('form#'+formName, container).get(0);
		if(oldForm)
		{
			oldForm.parentNode.removeChild(oldForm);
			jscss('remove', invoker, 'request-active');
			jscss('remove', document.body, 'displaying-lightbox');
			return true;
		}
	}

	if(removeForm())
	{
		return false;
	}

	addEvent(document.body, 'keyup', function(e)
	{
		if(e.keyCode == 27) // escape, unlike the lightbox-escape handler we don't just allow the event on the body, but everywhere
		{
			removeForm();
			removeEvent(document.body, 'keyup', arguments.callee)
		}
	});

	var container = new DOMQuery("div.extra-actions").get(0);
	return {specificElement : 'form#' + formName, container : container, onSubmitCallback : onSubmitCallback};
}

function updateMessagesThruXmlHttp(targets)
{
	var items = getTargets(targets, "ol.messages li.message ul.message-links li.message-edit a");
	for(var i = 0, item;(item=items.get(i));i++)
	{
		addEvent(item, 'click',
			function(e)
			{
				var messageid = this.href.replace(/.+update_message\/(\d+)(.+)?/, '$1');
				if(!messageid)
					return true;

				var container = new DOMQuery("ol.messages li#message-" + messageid +" div.message-content").get(0);

				var result = xmlHttpForm(
						this,
						'action=update_message&data%5Bmessageid%5D='+messageid,
						container,
						function()
						{
							var request = 'action=view_message&data%5Bmessageid%5D='+messageid;
							var resultreq = httpreq_string(request, null, null, false);

							var target = new DOMQuery('div.message-content-content', container).get(0);
							while(target.childNodes.length > 0)
							{
								target.removeChild(target.firstChild);
							}

							var source = new DOMQuery('div#core form.primary-input dl.property-list dt:first-child + dd', resultreq.responseXML).get(0);
							while(source.childNodes.length > 0)
							{
								target.appendChild( source.removeChild(source.firstChild) );
							}
						}
				);

				if(result)
					e.preventDefault();
			}
		);
	}
};

function gatherHttpForm(form)
{
	var items = form.elements;
	var str = [ ];

	for(var i = 0, item;(item=items[i]);i++)
	{
		if(item.disabled)
			continue;

		switch( item.tagName.toLowerCase() )
		{
			case 'input':
				switch(item.type)
				{
					case 'text':
					case 'hidden':
					case 'password':
						str.push(encodeURIComponent(item.name)+'='+ encodeURIComponent( item.value ) );
					break;
					case 'radio':
					case 'checkbox':
						if(item.checked)
							str.push(encodeURIComponent(item.name)+'='+ encodeURIComponent( item.value ) );
					break;
					case 'file':
						if(item.value)
							return;
					break;
				}
			break;
			case 'select':
				if(item.selectedIndex > -1)
					str.push(encodeURIComponent(item.name)+'='+ encodeURIComponent( item.options[item.selectedIndex].value ) );
			break;
			case 'textarea':
				str.push(encodeURIComponent(item.name)+'='+ encodeURIComponent( item.value ) );
			break;
		}
	}

	return str.join('&');
};

function httpreq_xml(request, callback, url, async)
{
	var xmlurl = url || board_script_url + '/../xml_input.php';
  	var xmlParser, xmlDocument, req;

	if(window.XMLHttpRequest)
	{
		/* safari 1.3/2.0 doesn't support DOMParser */
		if(typeof DOMParser == "undefined")
			return false;

		req = new XMLHttpRequest();
		xmlParser = new DOMParser();
		xmlDocument = xmlParser.parseFromString(request, 'text/xml');
	}
	else if(window.ActiveXObject)
	{
		req = new ActiveXObject("MSXML2.XMLHTTP.3.0");

		xmlDocument = new ActiveXObject('Msxml2.DOMDocument.3.0');
		xmlDocument.async = false;
		xmlDocument.loadXML(request);
	}

	xmlDocument.insertBefore(xmlDocument.createProcessingInstruction("xml", "version='1.0'"), xmlDocument.firstChild);

	if(callback)
		req.onreadystatechange = callback;

	req.open("POST", xmlurl, (typeof async == "boolean" ? async : true) );

	if(window.XMLHttpRequest)
	{
		req.setRequestHeader('Content-Type', 'text/xml; utf-8');
	}

	req.send(request);

	return req;
};

function httpreq_string(request, callback, url, async, method)
{
  	var req;
	var xmlurl = url || board_script_url;
	method = method || "POST";
  	async = (typeof async == "boolean" ? async : true);

	if(window.XMLHttpRequest)
	{
		req = new XMLHttpRequest();
	}
	else if(window.ActiveXObject)
	{
		req = new ActiveXObject("MSXML2.XMLHTTP.3.0");
	}

	if(callback)
		req.onreadystatechange = callback;

	if(req.overrideMimeType)
		req.overrideMimeType('text/xml');

	request += '&dont_meta_refresh=1' + (isIE ? '&' + new Date().getTime() : '');

	if(method == "GET")
	{
		req.open(method, xmlurl + '?' + request, async );
		req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=UTF-8');
		req.send(null);
	}
	else
	{
		req.open(method, xmlurl, async );
		req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=UTF-8');
		req.send(request);
	}

	return req;
};

/* the container specifies the desired endpoint for the node */
function getElementFromXHR(transport, selector, container)
{
	container = container || document.body;
	var root;
	if(isWebKit || !transportHasValidResponseXML(transport) || isIE)
	{
		root = document.createElement('div');
		root.innerHTML = transport.responseText;

		/* nasty workaround; prototype actually uses getElementbyId, and so any selector with an id
		implies that the transport-content needs to be attached to the current document. Blegh. */
		if(DOMQuery.prototype.resultType == 'getElementsBySelector' && selector.match(/#/) )
		{
			document.appendChild(root);
			var cleanup = true;
		}
	}
	else
	{
		root = transport.responseXML;
	}

	var element = new DOMQuery(selector, root).get(0);
	if(cleanup)
		document.removeChild(root);

	if(!element)
		return;

	if(isWebKit || !transportHasValidResponseXML(transport) || isIE)
		return element;

	var _element;
	try
	{
		_element = container.ownerDocument.adoptNode( element, true );
	}
	catch(e)
	{
		_element = container.ownerDocument.importNode( element, true );
	}

	return container.namespaceURI == _element.namespaceURI ? _element : importNodeCurrentNS( _element );
};

function transportHasValidResponseXML(transport)
{
	if ( typeof transport.responseXML != 'undefined' || transport.responseXML.firstChild.tagName == 'parsererror' || transport.responseXML.documentElement == null || transport.responseXML.documentElement == 'undefined')
		return false;

	return true;
};

function importNodeCurrentNS(node)
{
	var clone;

	switch(node.nodeType)
	{
		default:
		case 8: /* comment */
			return;
		case 3: /* text */
			return document.createTextNode( node.nodeValue );
		case 1: /* node */
			clone = document.createElement( node.tagName );
	}

	for(var i=0, attribute; (attribute=node.attributes[i]); i++)
	{
		clone.setAttribute(attribute.name, attribute.value);
	}

	for(var j=0, subNode, importedSubNode; (subNode=node.childNodes[j]); j++)
	{
		importedSubNode = arguments.callee( node.childNodes[j] );
		if(importedSubNode)
			clone.appendChild( importedSubNode );
	}

	return clone;
};

/*  Copyright Mihai Bazon, 2002-2005  |  www.bazon.net/mishoo
 * -----------------------------------------------------------
 *
 * The DHTML Calendar, version 1.0 "It is happening again"
 *
 * Details and latest version at:
 * www.dynarch.com/projects/calendar
 *
 * This script is developed by Dynarch.com.  Visit us at www.dynarch.com.
 *
 * This script is distributed under the GNU Lesser General Public License.
 * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
 */

// $Id: calendar.js,v 1.3 2005/08/17 13:44:25 michiel Exp $

/** The Calendar object constructor. */
Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) {
	// member variables
	this.activeDiv = null;
	this.currentDateEl = null;
	this.getDateStatus = null;
	this.getDateToolTip = null;
	this.getDateText = null;
	this.timeout = null;
	this.onSelected = onSelected || null;
	this.onClose = onClose || null;
	this.dragging = false;
	this.hidden = false;
	this.minYear = 1970;
	this.maxYear = 2050;
	this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"];
	this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"];
	this.isPopup = true;
	this.weekNumbers = true;
	this.firstDayOfWeek = typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc.
	this.showsOtherMonths = false;
	this.dateStr = dateStr;
	this.ar_days = null;
	this.showsTime = false;
	this.time24 = true;
	this.yearStep = 2;
	this.hiliteToday = true;
	this.multiple = null;
	// HTML elements
	this.table = null;
	this.element = null;
	this.tbody = null;
	this.firstdayname = null;
	// Combo boxes
	this.monthsCombo = null;
	this.yearsCombo = null;
	this.hilitedMonth = null;
	this.activeMonth = null;
	this.hilitedYear = null;
	this.activeYear = null;
	// Information
	this.dateClicked = false;

	// one-time initializations
	if (typeof Calendar._SDN == "undefined") {
		// table of short day names
		if (typeof Calendar._SDN_len == "undefined")
			Calendar._SDN_len = 3;
		var ar = new Array();
		for (var i = 8; i > 0;) {
			ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len);
		}
		Calendar._SDN = ar;
		// table of short month names
		if (typeof Calendar._SMN_len == "undefined")
			Calendar._SMN_len = 3;
		ar = new Array();
		for (var i = 12; i > 0;) {
			ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len);
		}
		Calendar._SMN = ar;
	}
};

// ** constants

/// "static", needed for event handlers.
Calendar._C = null;

/// detect a special case of "web browser"
Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&
		   !/opera/i.test(navigator.userAgent) );

Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) );

/// detect Opera browser
Calendar.is_opera = /opera/i.test(navigator.userAgent);

/// detect KHTML-based browsers
Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent);

// BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate
//        library, at some point.

Calendar.getAbsolutePos = function(el) {
	var SL = 0, ST = 0;
	var is_div = /^div$/i.test(el.tagName);
	if (is_div && el.scrollLeft)
		SL = el.scrollLeft;
	if (is_div && el.scrollTop)
		ST = el.scrollTop;
	var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
	if (el.offsetParent) {
		var tmp = this.getAbsolutePos(el.offsetParent);
		r.x += tmp.x;
		r.y += tmp.y;
	}
	return r;
};

Calendar.isRelated = function (el, evt) {
	var related = evt.relatedTarget;
	if (!related) {
		var type = evt.type;
		if (type == "mouseover") {
			related = evt.fromElement;
		} else if (type == "mouseout") {
			related = evt.toElement;
		}
	}
	while (related) {
		if (related == el) {
			return true;
		}
		related = related.parentNode;
	}
	return false;
};

Calendar.removeClass = function(el, className) {
	if (!(el && el.className)) {
		return;
	}
	var cls = el.className.split(" ");
	var ar = new Array();
	for (var i = cls.length; i > 0;) {
		if (cls[--i] != className) {
			ar[ar.length] = cls[i];
		}
	}
	el.className = ar.join(" ");
};

Calendar.addClass = function(el, className) {
	Calendar.removeClass(el, className);
	el.className += " " + className;
};

// FIXME: the following 2 functions totally suck, are useless and should be replaced immediately.
Calendar.getElement = function(ev) {
	var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget;
	while (f.nodeType != 1 || /^div$/i.test(f.tagName))
		f = f.parentNode;
	return f;
};

Calendar.getTargetElement = function(ev) {
	var f = Calendar.is_ie ? window.event.srcElement : ev.target;
	while (f.nodeType != 1)
		f = f.parentNode;
	return f;
};

Calendar.stopEvent = function(ev) {
	ev || (ev = window.event);
	if (Calendar.is_ie) {
		ev.cancelBubble = true;
		ev.returnValue = false;
	} else {
		ev.preventDefault();
		ev.stopPropagation();
	}
	return false;
};

Calendar.addEvent = function(el, evname, func) {
	if (el.attachEvent) { // IE
		el.attachEvent("on" + evname, func);
	} else if (el.addEventListener) { // Gecko / W3C
		el.addEventListener(evname, func, true);
	} else {
		el["on" + evname] = func;
	}
};

Calendar.removeEvent = function(el, evname, func) {
	if (el.detachEvent) { // IE
		el.detachEvent("on" + evname, func);
	} else if (el.removeEventListener) { // Gecko / W3C
		el.removeEventListener(evname, func, true);
	} else {
		el["on" + evname] = null;
	}
};

Calendar.createElement = function(type, parent) {
	var el = null;
	if (document.createElementNS) {
		// use the XHTML namespace; IE won't normally get here unless
		// _they_ "fix" the DOM2 implementation.
		el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
	} else {
		el = document.createElement(type);
	}
	if (typeof parent != "undefined") {
		parent.appendChild(el);
	}
	return el;
};

// END: UTILITY FUNCTIONS

// BEGIN: CALENDAR STATIC FUNCTIONS

/** Internal -- adds a set of events to make some element behave like a button. */
Calendar._add_evs = function(el) {
	with (Calendar) {
		addEvent(el, "mouseover", dayMouseOver);
		addEvent(el, "mousedown", dayMouseDown);
		addEvent(el, "mouseout", dayMouseOut);
		if (is_ie) {
			addEvent(el, "dblclick", dayMouseDblClick);
			el.setAttribute("unselectable", true);
		}
	}
};

Calendar.findMonth = function(el) {
	if (typeof el.month != "undefined") {
		return el;
	} else if (typeof el.parentNode.month != "undefined") {
		return el.parentNode;
	}
	return null;
};

Calendar.findYear = function(el) {
	if (typeof el.year != "undefined") {
		return el;
	} else if (typeof el.parentNode.year != "undefined") {
		return el.parentNode;
	}
	return null;
};

Calendar.showMonthsCombo = function () {
	var cal = Calendar._C;
	if (!cal) {
		return false;
	}
	var cal = cal;
	var cd = cal.activeDiv;
	var mc = cal.monthsCombo;
	if (cal.hilitedMonth) {
		Calendar.removeClass(cal.hilitedMonth, "hilite");
	}
	if (cal.activeMonth) {
		Calendar.removeClass(cal.activeMonth, "active");
	}
	var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];
	Calendar.addClass(mon, "active");
	cal.activeMonth = mon;
	var s = mc.style;
	s.display = "block";
	if (cd.navtype < 0)
		s.left = cd.offsetLeft + "px";
	else {
		var mcw = mc.offsetWidth;
		if (typeof mcw == "undefined")
			// Konqueror brain-dead techniques
			mcw = 50;
		s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px";
	}
	s.top = (cd.offsetTop + cd.offsetHeight) + "px";
};

Calendar.showYearsCombo = function (fwd) {
	var cal = Calendar._C;
	if (!cal) {
		return false;
	}
	var cal = cal;
	var cd = cal.activeDiv;
	var yc = cal.yearsCombo;
	if (cal.hilitedYear) {
		Calendar.removeClass(cal.hilitedYear, "hilite");
	}
	if (cal.activeYear) {
		Calendar.removeClass(cal.activeYear, "active");
	}
	cal.activeYear = null;
	var Y = cal.date.getFullYear() + (fwd ? 1 : -1);
	var yr = yc.firstChild;
	var show = false;
	for (var i = 12; i > 0; --i) {
		if (Y >= cal.minYear && Y <= cal.maxYear) {
			yr.innerHTML = Y;
			yr.year = Y;
			yr.style.display = "block";
			show = true;
		} else {
			yr.style.display = "none";
		}
		yr = yr.nextSibling;
		Y += fwd ? cal.yearStep : -cal.yearStep;
	}
	if (show) {
		var s = yc.style;
		s.display = "block";
		if (cd.navtype < 0)
			s.left = cd.offsetLeft + "px";
		else {
			var ycw = yc.offsetWidth;
			if (typeof ycw == "undefined")
				// Konqueror brain-dead techniques
				ycw = 50;
			s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px";
		}
		s.top = (cd.offsetTop + cd.offsetHeight) + "px";
	}
};

// event handlers

Calendar.tableMouseUp = function(ev) {
	var cal = Calendar._C;
	if (!cal) {
		return false;
	}
	if (cal.timeout) {
		clearTimeout(cal.timeout);
	}
	var el = cal.activeDiv;
	if (!el) {
		return false;
	}
	var target = Calendar.getTargetElement(ev);
	ev || (ev = window.event);
	Calendar.removeClass(el, "active");
	if (target == el || target.parentNode == el) {
		Calendar.cellClick(el, ev);
	}
	var mon = Calendar.findMonth(target);
	var date = null;
	if (mon) {
		date = new Date(cal.date);
		if (mon.month != date.getMonth()) {
			date.setMonth(mon.month);
			cal.setDate(date);
			cal.dateClicked = false;
			cal.callHandler();
		}
	} else {
		var year = Calendar.findYear(target);
		if (year) {
			date = new Date(cal.date);
			if (year.year != date.getFullYear()) {
				date.setFullYear(year.year);
				cal.setDate(date);
				cal.dateClicked = false;
				cal.callHandler();
			}
		}
	}
	with (Calendar) {
		removeEvent(document, "mouseup", tableMouseUp);
		removeEvent(document, "mouseover", tableMouseOver);
		removeEvent(document, "mousemove", tableMouseOver);
		cal._hideCombos();
		_C = null;
		return stopEvent(ev);
	}
};

Calendar.tableMouseOver = function (ev) {
	var cal = Calendar._C;
	if (!cal) {
		return;
	}
	var el = cal.activeDiv;
	var target = Calendar.getTargetElement(ev);
	if (target == el || target.parentNode == el) {
		Calendar.addClass(el, "hilite active");
		Calendar.addClass(el.parentNode, "rowhilite");
	} else {
		if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2)))
			Calendar.removeClass(el, "active");
		Calendar.removeClass(el, "hilite");
		Calendar.removeClass(el.parentNode, "rowhilite");
	}
	ev || (ev = window.event);
	if (el.navtype == 50 && target != el) {
		var pos = Calendar.getAbsolutePos(el);
		var w = el.offsetWidth;
		var x = ev.clientX;
		var dx;
		var decrease = true;
		if (x > pos.x + w) {
			dx = x - pos.x - w;
			decrease = false;
		} else
			dx = pos.x - x;

		if (dx < 0) dx = 0;
		var range = el._range;
		var current = el._current;
		var count = Math.floor(dx / 10) % range.length;
		for (var i = range.length; --i >= 0;)
			if (range[i] == current)
				break;
		while (count-- > 0)
			if (decrease) {
				if (--i < 0)
					i = range.length - 1;
			} else if ( ++i >= range.length )
				i = 0;
		var newval = range[i];
		el.innerHTML = newval;

		cal.onUpdateTime();
	}
	var mon = Calendar.findMonth(target);
	if (mon) {
		if (mon.month != cal.date.getMonth()) {
			if (cal.hilitedMonth) {
				Calendar.removeClass(cal.hilitedMonth, "hilite");
			}
			Calendar.addClass(mon, "hilite");
			cal.hilitedMonth = mon;
		} else if (cal.hilitedMonth) {
			Calendar.removeClass(cal.hilitedMonth, "hilite");
		}
	} else {
		if (cal.hilitedMonth) {
			Calendar.removeClass(cal.hilitedMonth, "hilite");
		}
		var year = Calendar.findYear(target);
		if (year) {
			if (year.year != cal.date.getFullYear()) {
				if (cal.hilitedYear) {
					Calendar.removeClass(cal.hilitedYear, "hilite");
				}
				Calendar.addClass(year, "hilite");
				cal.hilitedYear = year;
			} else if (cal.hilitedYear) {
				Calendar.removeClass(cal.hilitedYear, "hilite");
			}
		} else if (cal.hilitedYear) {
			Calendar.removeClass(cal.hilitedYear, "hilite");
		}
	}
	return Calendar.stopEvent(ev);
};

Calendar.tableMouseDown = function (ev) {
	if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) {
		return Calendar.stopEvent(ev);
	}
};

Calendar.calDragIt = function (ev) {
	var cal = Calendar._C;
	if (!(cal && cal.dragging)) {
		return false;
	}
	var posX;
	var posY;
	if (Calendar.is_ie) {
		posY = window.event.clientY + document.body.scrollTop;
		posX = window.event.clientX + document.body.scrollLeft;
	} else {
		posX = ev.pageX;
		posY = ev.pageY;
	}
	cal.hideShowCovered();
	var st = cal.element.style;
	st.left = (posX - cal.xOffs) + "px";
	st.top = (posY - cal.yOffs) + "px";
	return Calendar.stopEvent(ev);
};

Calendar.calDragEnd = function (ev) {
	var cal = Calendar._C;
	if (!cal) {
		return false;
	}
	cal.dragging = false;
	with (Calendar) {
		removeEvent(document, "mousemove", calDragIt);
		removeEvent(document, "mouseup", calDragEnd);
		tableMouseUp(ev);
	}
	cal.hideShowCovered();
};

Calendar.dayMouseDown = function(ev) {
	var el = Calendar.getElement(ev);
	if (el.disabled) {
		return false;
	}
	var cal = el.calendar;
	cal.activeDiv = el;
	Calendar._C = cal;
	if (el.navtype != 300) with (Calendar) {
		if (el.navtype == 50) {
			el._current = el.innerHTML;
			addEvent(document, "mousemove", tableMouseOver);
		} else
			addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver);
		addClass(el, "hilite active");
		addEvent(document, "mouseup", tableMouseUp);
	} else if (cal.isPopup) {
		cal._dragStart(ev);
	}
	if (el.navtype == -1 || el.navtype == 1) {
		if (cal.timeout) clearTimeout(cal.timeout);
		cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250);
	} else if (el.navtype == -2 || el.navtype == 2) {
		if (cal.timeout) clearTimeout(cal.timeout);
		cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250);
	} else {
		cal.timeout = null;
	}
	return Calendar.stopEvent(ev);
};

Calendar.dayMouseDblClick = function(ev) {
	Calendar.cellClick(Calendar.getElement(ev), ev || window.event);
	if (Calendar.is_ie) {
		document.selection.empty();
	}
};

Calendar.dayMouseOver = function(ev) {
	var el = Calendar.getElement(ev);
	if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) {
		return false;
	}
	if (el.ttip) {
		if (el.ttip.substr(0, 1) == "_") {
			el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1);
		}
		el.calendar.tooltips.innerHTML = el.ttip;
	}
	if (el.navtype != 300) {
		Calendar.addClass(el, "hilite");
		if (el.caldate) {
			Calendar.addClass(el.parentNode, "rowhilite");
		}
	}
	return Calendar.stopEvent(ev);
};

Calendar.dayMouseOut = function(ev) {
	with (Calendar) {
		var el = getElement(ev);
		if (isRelated(el, ev) || _C || el.disabled)
			return false;
		removeClass(el, "hilite");
		if (el.caldate)
			removeClass(el.parentNode, "rowhilite");
		if (el.calendar)
			el.calendar.tooltips.innerHTML = _TT["SEL_DATE"];
		return stopEvent(ev);
	}
};

/**
 *  A generic "click" handler :) handles all types of buttons defined in this
 *  calendar.
 */
Calendar.cellClick = function(el, ev) {
	var cal = el.calendar;
	var closing = false;
	var newdate = false;
	var date = null;
	if (typeof el.navtype == "undefined") {
		if (cal.currentDateEl) {
			Calendar.removeClass(cal.currentDateEl, "selected");
			Calendar.addClass(el, "selected");
			closing = (cal.currentDateEl == el);
			if (!closing) {
				cal.currentDateEl = el;
			}
		}
		cal.date.setDateOnly(el.caldate);
		date = cal.date;
		var other_month = !(cal.dateClicked = !el.otherMonth);
		if (!other_month && !cal.currentDateEl)
			cal._toggleMultipleDate(new Date(date));
		else
			newdate = !el.disabled;
		// a date was clicked
		if (other_month)
			cal._init(cal.firstDayOfWeek, date);
	} else {
		if (el.navtype == 200) {
			Calendar.removeClass(el, "hilite");
			cal.callCloseHandler();
			return;
		}
		date = new Date(cal.date);
		if (el.navtype == 0)
			date.setDateOnly(new Date()); // TODAY
		// unless "today" was clicked, we assume no date was clicked so
		// the selected handler will know not to close the calenar when
		// in single-click mode.
		// cal.dateClicked = (el.navtype == 0);
		cal.dateClicked = false;
		var year = date.getFullYear();
		var mon = date.getMonth();
		function setMonth(m) {
			var day = date.getDate();
			var max = date.getMonthDays(m);
			if (day > max) {
				date.setDate(max);
			}
			date.setMonth(m);
		};
		switch (el.navtype) {
		    case 400:
			Calendar.removeClass(el, "hilite");
			var text = Calendar._TT["ABOUT"];
			if (typeof text != "undefined") {
				text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : "";
			} else {
				// FIXME: this should be removed as soon as lang files get updated!
				text = "Help and about box text is not translated into this language.\n" +
					"If you know this language and you feel generous please update\n" +
					"the corresponding file in \"lang\" subdir to match calendar-en.js\n" +
					"and send it back to <mihai_bazon@yahoo.com> to get it into the distribution  ;-)\n\n" +
					"Thank you!\n" +
					"http://dynarch.com/mishoo/calendar.epl\n";
			}
			alert(text);
			return;
		    case -2:
			if (year > cal.minYear) {
				date.setFullYear(year - 1);
			}
			break;
		    case -1:
			if (mon > 0) {
				setMonth(mon - 1);
			} else if (year-- > cal.minYear) {
				date.setFullYear(year);
				setMonth(11);
			}
			break;
		    case 1:
			if (mon < 11) {
				setMonth(mon + 1);
			} else if (year < cal.maxYear) {
				date.setFullYear(year + 1);
				setMonth(0);
			}
			break;
		    case 2:
			if (year < cal.maxYear) {
				date.setFullYear(year + 1);
			}
			break;
		    case 100:
			cal.setFirstDayOfWeek(el.fdow);
			return;
		    case 50:
			var range = el._range;
			var current = el.innerHTML;
			for (var i = range.length; --i >= 0;)
				if (range[i] == current)
					break;
			if (ev && ev.shiftKey) {
				if (--i < 0)
					i = range.length - 1;
			} else if ( ++i >= range.length )
				i = 0;
			var newval = range[i];
			el.innerHTML = newval;
			cal.onUpdateTime();
			return;
		    case 0:
			// TODAY will bring us here
			if ((typeof cal.getDateStatus == "function") &&
			    cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) {
				return false;
			}
			break;
		}
		if (!date.equalsTo(cal.date)) {
			cal.setDate(date);
			newdate = true;
		} else if (el.navtype == 0)
			newdate = closing = true;
	}
	if (newdate) {
		ev && cal.callHandler();
	}
	if (closing) {
		Calendar.removeClass(el, "hilite");
		ev && cal.callCloseHandler();
	}
};

// END: CALENDAR STATIC FUNCTIONS

// BEGIN: CALENDAR OBJECT FUNCTIONS

/**
 *  This function creates the calendar inside the given parent.  If _par is
 *  null than it creates a popup calendar inside the BODY element.  If _par is
 *  an element, be it BODY, then it creates a non-popup calendar (still
 *  hidden).  Some properties need to be set before calling this function.
 */
Calendar.prototype.create = function (_par) {
	var parent = null;
	if (! _par) {
		// default parent is the document body, in which case we create
		// a popup calendar.
		parent = document.getElementsByTagName("body")[0];
		this.isPopup = true;
	} else {
		parent = _par;
		this.isPopup = false;
	}
	this.date = this.dateStr ? new Date(this.dateStr) : new Date();

	var table = Calendar.createElement("table");
	this.table = table;
	table.cellSpacing = 0;
	table.cellPadding = 0;
	table.calendar = this;
	Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);

	var div = Calendar.createElement("div");
	this.element = div;
	div.className = "calendar";
	if (this.isPopup) {
		div.style.position = "absolute";
		div.style.display = "none";
	}
	div.appendChild(table);

	var thead = Calendar.createElement("thead", table);
	var cell = null;
	var row = null;

	var cal = this;
	var hh = function (text, cs, navtype) {
		cell = Calendar.createElement("td", row);
		cell.colSpan = cs;
		cell.className = "button";
		if (navtype != 0 && Math.abs(navtype) <= 2)
			cell.className += " nav";
		Calendar._add_evs(cell);
		cell.calendar = cal;
		cell.navtype = navtype;
		cell.innerHTML = "<div unselectable='on'>" + text + "</div>";
		return cell;
	};

	row = Calendar.createElement("tr", thead);
	var title_length = 6;
	(this.isPopup) && --title_length;
	(this.weekNumbers) && ++title_length;

	hh("?", 1, 400).ttip = Calendar._TT["INFO"];
	this.title = hh("", title_length, 300);
	this.title.className = "title";
	if (this.isPopup) {
		this.title.ttip = Calendar._TT["DRAG_TO_MOVE"];
		this.title.style.cursor = "move";
		hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"];
	}

	row = Calendar.createElement("tr", thead);
	row.className = "headrow";

	this._nav_py = hh("&#x00ab;", 1, -2);
	this._nav_py.ttip = Calendar._TT["PREV_YEAR"];

	this._nav_pm = hh("&#x2039;", 1, -1);
	this._nav_pm.ttip = Calendar._TT["PREV_MONTH"];

	this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0);
	this._nav_now.ttip = Calendar._TT["GO_TODAY"];

	this._nav_nm = hh("&#x203a;", 1, 1);
	this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];

	this._nav_ny = hh("&#x00bb;", 1, 2);
	this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"];

	// day names
	row = Calendar.createElement("tr", thead);
	row.className = "daynames";
	if (this.weekNumbers) {
		cell = Calendar.createElement("td", row);
		cell.className = "name wn";
		cell.innerHTML = Calendar._TT["WK"];
	}
	for (var i = 7; i > 0; --i) {
		cell = Calendar.createElement("td", row);
		if (!i) {
			cell.navtype = 100;
			cell.calendar = this;
			Calendar._add_evs(cell);
		}
	}
	this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;
	this._displayWeekdays();

	var tbody = Calendar.createElement("tbody", table);
	this.tbody = tbody;

	for (i = 6; i > 0; --i) {
		row = Calendar.createElement("tr", tbody);
		if (this.weekNumbers) {
			cell = Calendar.createElement("td", row);
		}
		for (var j = 7; j > 0; --j) {
			cell = Calendar.createElement("td", row);
			cell.calendar = this;
			Calendar._add_evs(cell);
		}
	}

	if (this.showsTime) {
		row = Calendar.createElement("tr", tbody);
		row.className = "time";

		cell = Calendar.createElement("td", row);
		cell.className = "time";
		cell.colSpan = 2;
		cell.innerHTML = Calendar._TT["TIME"] || "&nbsp;";

		cell = Calendar.createElement("td", row);
		cell.className = "time";
		cell.colSpan = this.weekNumbers ? 4 : 3;

		(function(){
			function makeTimePart(className, init, range_start, range_end) {
				var part = Calendar.createElement("span", cell);
				part.className = className;
				part.innerHTML = init;
				part.calendar = cal;
				part.ttip = Calendar._TT["TIME_PART"];
				part.navtype = 50;
				part._range = [];
				if (typeof range_start != "number")
					part._range = range_start;
				else {
					for (var i = range_start; i <= range_end; ++i) {
						var txt;
						if (i < 10 && range_end >= 10) txt = '0' + i;
						else txt = '' + i;
						part._range[part._range.length] = txt;
					}
				}
				Calendar._add_evs(part);
				return part;
			};
			var hrs = cal.date.getHours();
			var mins = cal.date.getMinutes();
			var t12 = !cal.time24;
			var pm = (hrs > 12);
			if (t12 && pm) hrs -= 12;
			var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23);
			var span = Calendar.createElement("span", cell);
			span.innerHTML = ":";
			span.className = "colon";
			var M = makeTimePart("minute", mins, 0, 59);
			var AP = null;
			cell = Calendar.createElement("td", row);
			cell.className = "time";
			cell.colSpan = 2;
			if (t12)
				AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]);
			else
				cell.innerHTML = "&nbsp;";

			cal.onSetTime = function() {
				var pm, hrs = this.date.getHours(),
					mins = this.date.getMinutes();
				if (t12) {
					pm = (hrs >= 12);
					if (pm) hrs -= 12;
					if (hrs == 0) hrs = 12;
					AP.innerHTML = pm ? "pm" : "am";
				}
				H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs;
				M.innerHTML = (mins < 10) ? ("0" + mins) : mins;
			};

			cal.onUpdateTime = function() {
				var date = this.date;
				var h = parseInt(H.innerHTML, 10);
				if (t12) {
					if (/pm/i.test(AP.innerHTML) && h < 12)
						h += 12;
					else if (/am/i.test(AP.innerHTML) && h == 12)
						h = 0;
				}
				var d = date.getDate();
				var m = date.getMonth();
				var y = date.getFullYear();
				date.setHours(h);
				date.setMinutes(parseInt(M.innerHTML, 10));
				date.setFullYear(y);
				date.setMonth(m);
				date.setDate(d);
				this.dateClicked = false;
				this.callHandler();
			};
		})();
	} else {
		this.onSetTime = this.onUpdateTime = function() {};
	}

	var tfoot = Calendar.createElement("tfoot", table);

	row = Calendar.createElement("tr", tfoot);
	row.className = "footrow";

	cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300);
	cell.className = "ttip";
	if (this.isPopup) {
		cell.ttip = Calendar._TT["DRAG_TO_MOVE"];
		cell.style.cursor = "move";
	}
	this.tooltips = cell;

	div = Calendar.createElement("div", this.element);
	this.monthsCombo = div;
	div.className = "combo";
	for (i = 0; i < Calendar._MN.length; ++i) {
		var mn = Calendar.createElement("div");
		mn.className = Calendar.is_ie ? "label-IEfix" : "label";
		mn.month = i;
		mn.innerHTML = Calendar._SMN[i];
		div.appendChild(mn);
	}

	div = Calendar.createElement("div", this.element);
	this.yearsCombo = div;
	div.className = "combo";
	for (i = 12; i > 0; --i) {
		var yr = Calendar.createElement("div");
		yr.className = Calendar.is_ie ? "label-IEfix" : "label";
		div.appendChild(yr);
	}

	this._init(this.firstDayOfWeek, this.date);
	parent.appendChild(this.element);
};

/** keyboard navigation, only for popup calendars */
Calendar._keyEvent = function(ev) {
	var cal = window._dynarch_popupCalendar;
	if (!cal || cal.multiple)
		return false;
	(Calendar.is_ie) && (ev = window.event);
	var act = (Calendar.is_ie || ev.type == "keypress"),
		K = ev.keyCode;
	if (ev.ctrlKey) {
		switch (K) {
		    case 37: // KEY left
			act && Calendar.cellClick(cal._nav_pm);
			break;
		    case 38: // KEY up
			act && Calendar.cellClick(cal._nav_py);
			break;
		    case 39: // KEY right
			act && Calendar.cellClick(cal._nav_nm);
			break;
		    case 40: // KEY down
			act && Calendar.cellClick(cal._nav_ny);
			break;
		    default:
			return false;
		}
	} else switch (K) {
	    case 32: // KEY space (now)
		Calendar.cellClick(cal._nav_now);
		break;
	    case 27: // KEY esc
		act && cal.callCloseHandler();
		break;
	    case 37: // KEY left
	    case 38: // KEY up
	    case 39: // KEY right
	    case 40: // KEY down
		if (act) {
			var prev, x, y, ne, el, step;
			prev = K == 37 || K == 38;
			step = (K == 37 || K == 39) ? 1 : 7;
			function setVars() {
				el = cal.currentDateEl;
				var p = el.pos;
				x = p & 15;
				y = p >> 4;
				ne = cal.ar_days[y][x];
			};setVars();
			function prevMonth() {
				var date = new Date(cal.date);
				date.setDate(date.getDate() - step);
				cal.setDate(date);
			};
			function nextMonth() {
				var date = new Date(cal.date);
				date.setDate(date.getDate() + step);
				cal.setDate(date);
			};
			while (1) {
				switch (K) {
				    case 37: // KEY left
					if (--x >= 0)
						ne = cal.ar_days[y][x];
					else {
						x = 6;
						K = 38;
						continue;
					}
					break;
				    case 38: // KEY up
					if (--y >= 0)
						ne = cal.ar_days[y][x];
					else {
						prevMonth();
						setVars();
					}
					break;
				    case 39: // KEY right
					if (++x < 7)
						ne = cal.ar_days[y][x];
					else {
						x = 0;
						K = 40;
						continue;
					}
					break;
				    case 40: // KEY down
					if (++y < cal.ar_days.length)
						ne = cal.ar_days[y][x];
					else {
						nextMonth();
						setVars();
					}
					break;
				}
				break;
			}
			if (ne) {
				if (!ne.disabled)
					Calendar.cellClick(ne);
				else if (prev)
					prevMonth();
				else
					nextMonth();
			}
		}
		break;
	    case 13: // KEY enter
		if (act)
			Calendar.cellClick(cal.currentDateEl, ev);
		break;
	    default:
		return false;
	}
	return Calendar.stopEvent(ev);
};

/**
 *  (RE)Initializes the calendar to the given date and firstDayOfWeek
 */
Calendar.prototype._init = function (firstDayOfWeek, date) {
	var today = new Date(),
		TY = today.getFullYear(),
		TM = today.getMonth(),
		TD = today.getDate();
	this.table.style.visibility = "hidden";
	var year = date.getFullYear();
	if (year < this.minYear) {
		year = this.minYear;
		date.setFullYear(year);
	} else if (year > this.maxYear) {
		year = this.maxYear;
		date.setFullYear(year);
	}
	this.firstDayOfWeek = firstDayOfWeek;
	this.date = new Date(date);
	var month = date.getMonth();
	var mday = date.getDate();
	var no_days = date.getMonthDays();

	// calendar voodoo for computing the first day that would actually be
	// displayed in the calendar, even if it's from the previous month.
	// WARNING: this is magic. ;-)
	date.setDate(1);
	var day1 = (date.getDay() - this.firstDayOfWeek) % 7;
	if (day1 < 0)
		day1 += 7;
	date.setDate(-day1);
	date.setDate(date.getDate() + 1);

	var row = this.tbody.firstChild;
	var MN = Calendar._SMN[month];
	var ar_days = this.ar_days = new Array();
	var weekend = Calendar._TT["WEEKEND"];
	var dates = this.multiple ? (this.datesCells = {}) : null;
	for (var i = 0; i < 6; ++i, row = row.nextSibling) {
		var cell = row.firstChild;
		if (this.weekNumbers) {
			cell.className = "day wn";
			cell.innerHTML = date.getWeekNumber();
			cell = cell.nextSibling;
		}
		row.className = "daysrow";
		var hasdays = false, iday, dpos = ar_days[i] = [];
		for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) {
			iday = date.getDate();
			var wday = date.getDay();
			cell.className = "day";
			cell.pos = i << 4 | j;
			dpos[j] = cell;
			var current_month = (date.getMonth() == month);
			if (!current_month) {
				if (this.showsOtherMonths) {
					cell.className += " othermonth";
					cell.otherMonth = true;
				} else {
					cell.className = "emptycell";
					cell.innerHTML = "&nbsp;";
					cell.disabled = true;
					continue;
				}
			} else {
				cell.otherMonth = false;
				hasdays = true;
			}
			cell.disabled = false;
			cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday;
			if (dates)
				dates[date.print("%Y%m%d")] = cell;
			if (this.getDateStatus) {
				var status = this.getDateStatus(date, year, month, iday);
				if (this.getDateToolTip) {
					var toolTip = this.getDateToolTip(date, year, month, iday);
					if (toolTip)
						cell.title = toolTip;
				}
				if (status === true) {
					cell.className += " disabled";
					cell.disabled = true;
				} else {
					if (/disabled/i.test(status))
						cell.disabled = true;
					cell.className += " " + status;
				}
			}
			if (!cell.disabled) {
				cell.caldate = new Date(date);
				cell.ttip = "_";
				if (!this.multiple && current_month
				    && iday == mday && this.hiliteToday) {
					cell.className += " selected";
					this.currentDateEl = cell;
				}
				if (date.getFullYear() == TY &&
				    date.getMonth() == TM &&
				    iday == TD) {
					cell.className += " today";
					cell.ttip += Calendar._TT["PART_TODAY"];
				}
				if (weekend.indexOf(wday.toString()) != -1)
					cell.className += cell.otherMonth ? " oweekend" : " weekend";
			}
		}
		if (!(hasdays || this.showsOtherMonths))
			row.className = "emptyrow";
	}
	this.title.innerHTML = Calendar._MN[month] + ", " + year;
	this.onSetTime();
	this.table.style.visibility = "visible";
	this._initMultipleDates();
	// PROFILE
	// this.tooltips.innerHTML = "Generated in " + ((new Date()) - today) + " ms";
};

Calendar.prototype._initMultipleDates = function() {
	if (this.multiple) {
		for (var i in this.multiple) {
			var cell = this.datesCells[i];
			var d = this.multiple[i];
			if (!d)
				continue;
			if (cell)
				cell.className += " selected";
		}
	}
};

Calendar.prototype._toggleMultipleDate = function(date) {
	if (this.multiple) {
		var ds = date.print("%Y%m%d");
		var cell = this.datesCells[ds];
		if (cell) {
			var d = this.multiple[ds];
			if (!d) {
				Calendar.addClass(cell, "selected");
				this.multiple[ds] = date;
			} else {
				Calendar.removeClass(cell, "selected");
				delete this.multiple[ds];
			}
		}
	}
};

Calendar.prototype.setDateToolTipHandler = function (unaryFunction) {
	this.getDateToolTip = unaryFunction;
};

/**
 *  Calls _init function above for going to a certain date (but only if the
 *  date is different than the currently selected one).
 */
Calendar.prototype.setDate = function (date) {
	if (!date.equalsTo(this.date)) {
		this._init(this.firstDayOfWeek, date);
	}
};

/**
 *  Refreshes the calendar.  Useful if the "disabledHandler" function is
 *  dynamic, meaning that the list of disabled date can change at runtime.
 *  Just * call this function if you think that the list of disabled dates
 *  should * change.
 */
Calendar.prototype.refresh = function () {
	this._init(this.firstDayOfWeek, this.date);
};

/** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */
Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {
	this._init(firstDayOfWeek, this.date);
	this._displayWeekdays();
};

/**
 *  Allows customization of what dates are enabled.  The "unaryFunction"
 *  parameter must be a function object that receives the date (as a JS Date
 *  object) and returns a boolean value.  If the returned value is true then
 *  the passed date will be marked as disabled.
 */
Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) {
	this.getDateStatus = unaryFunction;
};

/** Customization of allowed year range for the calendar. */
Calendar.prototype.setRange = function (a, z) {
	this.minYear = a;
	this.maxYear = z;
};

/** Calls the first user handler (selectedHandler). */
Calendar.prototype.callHandler = function () {
	if (this.onSelected) {
		this.onSelected(this, this.date.print(this.dateFormat));
	}
};

/** Calls the second user handler (closeHandler). */
Calendar.prototype.callCloseHandler = function () {
	if (this.onClose) {
		this.onClose(this);
	}
	this.hideShowCovered();
};

/** Removes the calendar object from the DOM tree and destroys it. */
Calendar.prototype.destroy = function () {
	var el = this.element.parentNode;
	el.removeChild(this.element);
	Calendar._C = null;
	window._dynarch_popupCalendar = null;
};

/**
 *  Moves the calendar element to a different section in the DOM tree (changes
 *  its parent).
 */
Calendar.prototype.reparent = function (new_parent) {
	var el = this.element;
	el.parentNode.removeChild(el);
	new_parent.appendChild(el);
};

// This gets called when the user presses a mouse button anywhere in the
// document, if the calendar is shown.  If the click was outside the open
// calendar this function closes it.
Calendar._checkCalendar = function(ev) {
	var calendar = window._dynarch_popupCalendar;
	if (!calendar) {
		return false;
	}
	var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);
	for (; el != null && el != calendar.element; el = el.parentNode);
	if (el == null) {
		// calls closeHandler which should hide the calendar.
		window._dynarch_popupCalendar.callCloseHandler();
		return Calendar.stopEvent(ev);
	}
};

/** Shows the calendar. */
Calendar.prototype.show = function () {
	var rows = this.table.getElementsByTagName("tr");
	for (var i = rows.length; i > 0;) {
		var row = rows[--i];
		Calendar.removeClass(row, "rowhilite");
		var cells = row.getElementsByTagName("td");
		for (var j = cells.length; j > 0;) {
			var cell = cells[--j];
			Calendar.removeClass(cell, "hilite");
			Calendar.removeClass(cell, "active");
		}
	}
	this.element.style.display = "block";
	this.hidden = false;
	if (this.isPopup) {
		window._dynarch_popupCalendar = this;
		Calendar.addEvent(document, "keydown", Calendar._keyEvent);
		Calendar.addEvent(document, "keypress", Calendar._keyEvent);
		Calendar.addEvent(document, "mousedown", Calendar._checkCalendar);
	}
	this.hideShowCovered();
};

/**
 *  Hides the calendar.  Also removes any "hilite" from the class of any TD
 *  element.
 */
Calendar.prototype.hide = function () {
	if (this.isPopup) {
		Calendar.removeEvent(document, "keydown", Calendar._keyEvent);
		Calendar.removeEvent(document, "keypress", Calendar._keyEvent);
		Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar);
	}
	this.element.style.display = "none";
	this.hidden = true;
	this.hideShowCovered();
};

/**
 *  Shows the calendar at a given absolute position (beware that, depending on
 *  the calendar element style -- position property -- this might be relative
 *  to the parent's containing rectangle).
 */
Calendar.prototype.showAt = function (x, y) {
	var s = this.element.style;
	s.left = x + "px";
	s.top = y + "px";
	this.show();
};

/** Shows the calendar near a given element. */
Calendar.prototype.showAtElement = function (el, opts) {
	var self = this;
	var p = Calendar.getAbsolutePos(el);
	if (!opts || typeof opts != "string") {
		this.showAt(p.x, p.y + el.offsetHeight);
		return true;
	};
	function fixPosition(box) {
		if (box.x < 0)
			box.x = 0;
		if (box.y < 0)
			box.y = 0;
		var cp = document.createElement("div");
		var s = cp.style;
		s.position = "absolute";
		s.right = s.bottom = s.width = s.height = "0px";
		document.body.appendChild(cp);
		var br = Calendar.getAbsolutePos(cp);
		document.body.removeChild(cp);
		if (Calendar.is_ie) {
			br.y += document.body.scrollTop;
			br.x += document.body.scrollLeft;
		} else {
			br.y += window.scrollY;
			br.x += window.scrollX;
		}
		var tmp = box.x + box.width - br.x;
		if (tmp > 0) box.x -= tmp;
		tmp = box.y + box.height - br.y;
		if (tmp > 0) box.y -= tmp;
	};
	this.element.style.display = "block";
	Calendar.continuation_for_the_fucking_khtml_browser = function() {
		var w = self.element.offsetWidth;
		var h = self.element.offsetHeight;
		self.element.style.display = "none";
		var valign = opts.substr(0, 1);
		var halign = "l";
		if (opts.length > 1) {
			halign = opts.substr(1, 1);
		}
		// vertical alignment
		switch (valign) {
		    case "T": p.y -= h; break;
		    case "B": p.y += el.offsetHeight; break;
		    case "C": p.y += (el.offsetHeight - h) / 2; break;
		    case "t": p.y += el.offsetHeight - h; break;
		    case "b": break; // already there
		}
		// horizontal alignment
		switch (halign) {
		    case "L": p.x -= w; break;
		    case "R": p.x += el.offsetWidth; break;
		    case "C": p.x += (el.offsetWidth - w) / 2; break;
		    case "l": p.x += el.offsetWidth - w; break;
		    case "r": break; // already there
		}
		p.width = w;
		p.height = h + 40;
		self.monthsCombo.style.display = "none";
		fixPosition(p);
		self.showAt(p.x, p.y);
	};
	if (Calendar.is_khtml)
		setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10);
	else
		Calendar.continuation_for_the_fucking_khtml_browser();
};

/** Customizes the date format. */
Calendar.prototype.setDateFormat = function (str) {
	this.dateFormat = str;
};

/** Customizes the tooltip date format. */
Calendar.prototype.setTtDateFormat = function (str) {
	this.ttDateFormat = str;
};

/**
 *  Tries to identify the date represented in a string.  If successful it also
 *  calls this.setDate which moves the calendar to the given date.
 */
Calendar.prototype.parseDate = function(str, fmt) {
	if (!fmt)
		fmt = this.dateFormat;
	this.setDate(Date.parseDate(str, fmt));
};

Calendar.prototype.hideShowCovered = function () {
	if (!Calendar.is_ie && !Calendar.is_opera)
		return;
	function getVisib(obj){
		var value = obj.style.visibility;
		if (!value) {
			if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C
				if (!Calendar.is_khtml)
					value = document.defaultView.
						getComputedStyle(obj, "").getPropertyValue("visibility");
				else
					value = '';
			} else if (obj.currentStyle) { // IE
				value = obj.currentStyle.visibility;
			} else
				value = '';
		}
		return value;
	};

	var tags = new Array("applet", "iframe", "select");
	var el = this.element;

	var p = Calendar.getAbsolutePos(el);
	var EX1 = p.x;
	var EX2 = el.offsetWidth + EX1;
	var EY1 = p.y;
	var EY2 = el.offsetHeight + EY1;

	for (var k = tags.length; k > 0; ) {
		var ar = document.getElementsByTagName(tags[--k]);
		var cc = null;

		for (var i = ar.length; i > 0;) {
			cc = ar[--i];

			p = Calendar.getAbsolutePos(cc);
			var CX1 = p.x;
			var CX2 = cc.offsetWidth + CX1;
			var CY1 = p.y;
			var CY2 = cc.offsetHeight + CY1;

			if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
				if (!cc.__msh_save_visibility) {
					cc.__msh_save_visibility = getVisib(cc);
				}
				cc.style.visibility = cc.__msh_save_visibility;
			} else {
				if (!cc.__msh_save_visibility) {
					cc.__msh_save_visibility = getVisib(cc);
				}
				cc.style.visibility = "hidden";
			}
		}
	}
};

/** Internal function; it displays the bar with the names of the weekday. */
Calendar.prototype._displayWeekdays = function () {
	var fdow = this.firstDayOfWeek;
	var cell = this.firstdayname;
	var weekend = Calendar._TT["WEEKEND"];
	for (var i = 0; i < 7; ++i) {
		cell.className = "day name";
		var realday = (i + fdow) % 7;
		if (i) {
			cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]);
			cell.navtype = 100;
			cell.calendar = this;
			cell.fdow = realday;
			Calendar._add_evs(cell);
		}
		if (weekend.indexOf(realday.toString()) != -1) {
			Calendar.addClass(cell, "weekend");
		}
		cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
		cell = cell.nextSibling;
	}
};

/** Internal function.  Hides all combo boxes that might be displayed. */
Calendar.prototype._hideCombos = function () {
	this.monthsCombo.style.display = "none";
	this.yearsCombo.style.display = "none";
};

/** Internal function.  Starts dragging the element. */
Calendar.prototype._dragStart = function (ev) {
	if (this.dragging) {
		return;
	}
	this.dragging = true;
	var posX;
	var posY;
	if (Calendar.is_ie) {
		posY = window.event.clientY + document.body.scrollTop;
		posX = window.event.clientX + document.body.scrollLeft;
	} else {
		posY = ev.clientY + window.scrollY;
		posX = ev.clientX + window.scrollX;
	}
	var st = this.element.style;
	this.xOffs = posX - parseInt(st.left);
	this.yOffs = posY - parseInt(st.top);
	with (Calendar) {
		addEvent(document, "mousemove", calDragIt);
		addEvent(document, "mouseup", calDragEnd);
	}
};

// BEGIN: DATE OBJECT PATCHES

/** Adds the number of days array to the Date object. */
Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31);

/** Constants used for time computations */
Date.SECOND = 1000 /* milliseconds */;
Date.MINUTE = 60 * Date.SECOND;
Date.HOUR   = 60 * Date.MINUTE;
Date.DAY    = 24 * Date.HOUR;
Date.WEEK   =  7 * Date.DAY;

Date.parseDate = function(str, fmt) {
	var today = new Date();
	var y = 0;
	var m = -1;
	var d = 0;
	var a = str.split(/\W+/);
	var b = fmt.match(/%./g);
	var i = 0, j = 0;
	var hr = 0;
	var min = 0;
	for (i = 0; i < a.length; ++i) {
		if (!a[i])
			continue;
		switch (b[i]) {
		    case "%d":
		    case "%e":
			d = parseInt(a[i], 10);
			break;

		    case "%m":
			m = parseInt(a[i], 10) - 1;
			break;

		    case "%Y":
		    case "%y":
			y = parseInt(a[i], 10);
			(y < 100) && (y += (y > 29) ? 1900 : 2000);
			break;

		    case "%b":
		    case "%B":
			for (j = 0; j < 12; ++j) {
				if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
			}
			break;

		    case "%H":
		    case "%I":
		    case "%k":
		    case "%l":
			hr = parseInt(a[i], 10);
			break;

		    case "%P":
		    case "%p":
			if (/pm/i.test(a[i]) && hr < 12)
				hr += 12;
			else if (/am/i.test(a[i]) && hr >= 12)
				hr -= 12;
			break;

		    case "%M":
			min = parseInt(a[i], 10);
			break;
		}
	}
	if (isNaN(y)) y = today.getFullYear();
	if (isNaN(m)) m = today.getMonth();
	if (isNaN(d)) d = today.getDate();
	if (isNaN(hr)) hr = today.getHours();
	if (isNaN(min)) min = today.getMinutes();
	if (y != 0 && m != -1 && d != 0)
		return new Date(y, m, d, hr, min, 0);
	y = 0; m = -1; d = 0;
	for (i = 0; i < a.length; ++i) {
		if (a[i].search(/[a-zA-Z]+/) != -1) {
			var t = -1;
			for (j = 0; j < 12; ++j) {
				if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
			}
			if (t != -1) {
				if (m != -1) {
					d = m+1;
				}
				m = t;
			}
		} else if (parseInt(a[i], 10) <= 12 && m == -1) {
			m = a[i]-1;
		} else if (parseInt(a[i], 10) > 31 && y == 0) {
			y = parseInt(a[i], 10);
			(y < 100) && (y += (y > 29) ? 1900 : 2000);
		} else if (d == 0) {
			d = a[i];
		}
	}
	if (y == 0)
		y = today.getFullYear();
	if (m != -1 && d != 0)
		return new Date(y, m, d, hr, min, 0);
	return today;
};

/** Returns the number of days in the current month */
Date.prototype.getMonthDays = function(month) {
	var year = this.getFullYear();
	if (typeof month == "undefined") {
		month = this.getMonth();
	}
	if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
		return 29;
	} else {
		return Date._MD[month];
	}
};

/** Returns the number of day in the year. */
Date.prototype.getDayOfYear = function() {
	var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
	var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
	var time = now - then;
	return Math.floor(time / Date.DAY);
};

/** Returns the number of the week in year, as defined in ISO 8601. */
Date.prototype.getWeekNumber = function() {
	var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
	var DoW = d.getDay();
	d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
	var ms = d.valueOf(); // GMT
	d.setMonth(0);
	d.setDate(4); // Thu in Week 1
	return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
};

/** Checks date and time equality */
Date.prototype.equalsTo = function(date) {
	return ((this.getFullYear() == date.getFullYear()) &&
		(this.getMonth() == date.getMonth()) &&
		(this.getDate() == date.getDate()) &&
		(this.getHours() == date.getHours()) &&
		(this.getMinutes() == date.getMinutes()));
};

/** Set only the year, month, date parts (keep existing time) */
Date.prototype.setDateOnly = function(date) {
	var tmp = new Date(date);
	this.setDate(1);
	this.setFullYear(tmp.getFullYear());
	this.setMonth(tmp.getMonth());
	this.setDate(tmp.getDate());
};

/** Prints the date in a string according to the given format. */
Date.prototype.print = function (str) {
	var m = this.getMonth();
	var d = this.getDate();
	var y = this.getFullYear();
	var wn = this.getWeekNumber();
	var w = this.getDay();
	var s = {};
	var hr = this.getHours();
	var pm = (hr >= 12);
	var ir = (pm) ? (hr - 12) : hr;
	var dy = this.getDayOfYear();
	if (ir == 0)
		ir = 12;
	var min = this.getMinutes();
	var sec = this.getSeconds();
	s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
	s["%A"] = Calendar._DN[w]; // full weekday name
	s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
	s["%B"] = Calendar._MN[m]; // full month name
	// FIXME: %c : preferred date and time representation for the current locale
	s["%C"] = 1 + Math.floor(y / 100); // the century number
	s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
	s["%e"] = d; // the day of the month (range 1 to 31)
	// FIXME: %D : american date style: %m/%d/%y
	// FIXME: %E, %F, %G, %g, %h (man strftime)
	s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
	s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
	s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
	s["%k"] = hr;		// hour, range 0 to 23 (24h format)
	s["%l"] = ir;		// hour, range 1 to 12 (12h format)
	s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
	s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
	s["%n"] = "\n";		// a newline character
	s["%p"] = pm ? "PM" : "AM";
	s["%P"] = pm ? "pm" : "am";
	// FIXME: %r : the time in am/pm notation %I:%M:%S %p
	// FIXME: %R : the time in 24-hour notation %H:%M
	s["%s"] = Math.floor(this.getTime() / 1000);
	s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
	s["%t"] = "\t";		// a tab character
	// FIXME: %T : the time in 24-hour notation (%H:%M:%S)
	s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
	s["%u"] = w + 1;	// the day of the week (range 1 to 7, 1 = MON)
	s["%w"] = w;		// the day of the week (range 0 to 6, 0 = SUN)
	// FIXME: %x : preferred date representation for the current locale without the time
	// FIXME: %X : preferred time representation for the current locale without the date
	s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
	s["%Y"] = y;		// year with the century
	s["%%"] = "%";		// a literal '%' character

	var re = /%./g;
	if (!Calendar.is_ie5 && !Calendar.is_khtml)
		return str.replace(re, function (par) { return s[par] || par; });

	var a = str.match(re);
	for (var i = 0; i < a.length; i++) {
		var tmp = s[a[i]];
		if (tmp) {
			re = new RegExp(a[i], 'g');
			str = str.replace(re, tmp);
		}
	}

	return str;
};

Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear;
Date.prototype.setFullYear = function(y) {
	var d = new Date(this);
	d.__msh_oldSetFullYear(y);
	if (d.getMonth() != this.getMonth())
	{
		this.setDate(28);
	}
	this.__msh_oldSetFullYear(y);
};

// END: DATE OBJECT PATCHES


// global object that remembers the calendar
window._dynarch_popupCalendar = null;
// ** I18N
Calendar._DN = new Array
("Zondag",
 "Maandag",
 "Dinsdag",
 "Woensdag",
 "Donderdag",
 "Vrijdag",
 "Zaterdag",
 "Zondag");

Calendar._SDN_len = 2;

Calendar._MN = new Array
("Januari",
 "Februari",
 "Maart",
 "April",
 "Mei",
 "Juni",
 "Juli",
 "Augustus",
 "September",
 "Oktober",
 "November",
 "December");

// tooltips
Calendar._TT = {};
Calendar._TT["INFO"] = "Info";

Calendar._TT["ABOUT"] =
"DHTML Datum/Tijd Selector\n" +
"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" +
"Ga voor de meest recente versie naar: http://www.dynarch.com/projects/calendar/\n" +
"Verspreid onder de GNU LGPL. Zie http://gnu.org/licenses/lgpl.html voor details." +
"\n\n" +
"Datum selectie:\n" +
"- Gebruik de \xab \xbb knoppen om een jaar te selecteren\n" +
"- Gebruik de " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " knoppen om een maand te selecteren\n" +
"- Houd de muis ingedrukt op de genoemde knoppen voor een snellere selectie.";
Calendar._TT["ABOUT_TIME"] = "\n\n" +
"Tijd selectie:\n" +
"- Klik op een willekeurig onderdeel van het tijd gedeelte om het te verhogen\n" +
"- of Shift-klik om het te verlagen\n" +
"- of klik en sleep voor een snellere selectie.";

//Calendar._TT["TOGGLE"] = "Selecteer de eerste week-dag";
Calendar._TT["PREV_YEAR"] = "Vorig jaar (ingedrukt voor menu)";
Calendar._TT["PREV_MONTH"] = "Vorige maand (ingedrukt voor menu)";
Calendar._TT["GO_TODAY"] = "Ga naar Vandaag";
Calendar._TT["NEXT_MONTH"] = "Volgende maand (ingedrukt voor menu)";
Calendar._TT["NEXT_YEAR"] = "Volgend jaar (ingedrukt voor menu)";
Calendar._TT["SEL_DATE"] = "Selecteer datum";
Calendar._TT["DRAG_TO_MOVE"] = "Klik en sleep om te verplaatsen";
Calendar._TT["PART_TODAY"] = " (vandaag)";
//Calendar._TT["MON_FIRST"] = "Toon Maandag eerst";
//Calendar._TT["SUN_FIRST"] = "Toon Zondag eerst";

Calendar._TT["DAY_FIRST"] = "Toon %s eerst";

Calendar._TT["WEEKEND"] = "0,6";

Calendar._TT["CLOSE"] = "Sluiten";
Calendar._TT["TODAY"] = "(vandaag)";
Calendar._TT["TIME_PART"] = "(Shift-)Klik of sleep om de waarde te veranderen";

// date formats
Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y";
Calendar._TT["TT_DATE_FORMAT"] = "%a, %e %b %Y";

Calendar._TT["WK"] = "wk";
Calendar._TT["TIME"] = "Tijd:";
/*  Copyright Mihai Bazon, 2002, 2003  |  http://dynarch.com/mishoo/
 * ---------------------------------------------------------------------------
 *
 * The DHTML Calendar
 *
 * Details and latest version at:
 * http://dynarch.com/mishoo/calendar.epl
 *
 * This script is distributed under the GNU Lesser General Public License.
 * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
 *
 * This file defines helper functions for setting up the calendar.  They are
 * intended to help non-programmers get a working calendar on their site
 * quickly.  This script should not be seen as part of the calendar.  It just
 * shows you what one can do with the calendar, while in the same time
 * providing a quick and simple method for setting it up.  If you need
 * exhaustive customization of the calendar creation process feel free to
 * modify this code to suit your needs (this is recommended and much better
 * than modifying calendar.js itself).
 */

// $Id: calendar-setup.js,v 1.1 2005/08/04 09:06:55 arjen Exp $

/**
 *  This function "patches" an input field (or other element) to use a calendar
 *  widget for date selection.
 *
 *  The "params" is a single object that can have the following properties:
 *
 *    prop. name   | description
 *  -------------------------------------------------------------------------------------------------
 *   inputField    | the ID of an input field to store the date
 *   displayArea   | the ID of a DIV or other element to show the date
 *   button        | ID of a button or other element that will trigger the calendar
 *   eventName     | event that will trigger the calendar, without the "on" prefix (default: "click")
 *   ifFormat      | date format that will be stored in the input field
 *   daFormat      | the date format that will be used to display the date in displayArea
 *   singleClick   | (true/false) wether the calendar is in single click mode or not (default: true)
 *   firstDay      | numeric: 0 to 6.  "0" means display Sunday first, "1" means display Monday first, etc.
 *   align         | alignment (default: "Br"); if you don't know what's this see the calendar documentation
 *   range         | array with 2 elements.  Default: [1900, 2999] -- the range of years available
 *   weekNumbers   | (true/false) if it's true (default) the calendar will display week numbers
 *   flat          | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID
 *   flatCallback  | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar)
 *   disableFunc   | function that receives a JS Date object and should return true if that date has to be disabled in the calendar
 *   onSelect      | function that gets called when a date is selected.  You don't _have_ to supply this (the default is generally okay)
 *   onClose       | function that gets called when the calendar is closed.  [default]
 *   onUpdate      | function that gets called after the date is updated in the input field.  Receives a reference to the calendar.
 *   date          | the date that the calendar will be initially displayed to
 *   showsTime     | default: false; if true the calendar will include a time selector
 *   timeFormat    | the time format; can be "12" or "24", default is "12"
 *   electric      | if true (default) then given fields/date areas are updated for each move; otherwise they're updated only on close
 *   step          | configures the step of the years in drop-down boxes; default: 2
 *   position      | configures the calendar absolute position; default: null
 *   cache         | if "true" (but default: "false") it will reuse the same calendar object, where possible
 *   showOthers    | if "true" (but default: "false") it will show days from other months too
 *
 *  None of them is required, they all have default values.  However, if you
 *  pass none of "inputField", "displayArea" or "button" you'll get a warning
 *  saying "nothing to setup".
 */
Calendar.setup = function (params) {
	function param_default(pname, def) { if (typeof params[pname] == "undefined") { params[pname] = def; } };

	param_default("inputField",     null);
	param_default("displayArea",    null);
	param_default("button",         null);
	param_default("eventName",      "click");
	param_default("ifFormat",       "%Y/%m/%d");
	param_default("daFormat",       "%Y/%m/%d");
	param_default("singleClick",    true);
	param_default("disableFunc",    null);
	param_default("dateStatusFunc", params["disableFunc"]);	// takes precedence if both are defined
	param_default("dateText",       null);
	param_default("firstDay",       null);
	param_default("align",          "Br");
	param_default("range",          [1900, 2999]);
	param_default("weekNumbers",    true);
	param_default("flat",           null);
	param_default("flatCallback",   null);
	param_default("onSelect",       null);
	param_default("onClose",        null);
	param_default("onUpdate",       null);
	param_default("date",           null);
	param_default("showsTime",      false);
	param_default("timeFormat",     "24");
	param_default("electric",       true);
	param_default("step",           2);
	param_default("position",       null);
	param_default("cache",          false);
	param_default("showOthers",     false);
	param_default("multiple",       null);

	var tmp = ["inputField", "displayArea", "button"];
	for (var i in tmp) {
		if (typeof params[tmp[i]] == "string") {
			params[tmp[i]] = document.getElementById(params[tmp[i]]);
		}
	}
	if (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) {
		alert("Calendar.setup:\n  Nothing to setup (no fields found).  Please check your code");
		return false;
	};

	function onSelect(cal) {
		var p = cal.params;
		var update = (cal.dateClicked || p.electric);
		if (update && p.inputField) {
			p.inputField.value = cal.date.print(p.ifFormat);
			if (typeof p.inputField.onchange == "function")
				p.inputField.onchange();
		}
		if (update && p.displayArea)
			p.displayArea.innerHTML = cal.date.print(p.daFormat);
		if (update && typeof p.onUpdate == "function")
			p.onUpdate(cal);
		if (update && p.flat) {
			if (typeof p.flatCallback == "function")
				p.flatCallback(cal);
		}
		if (update && p.singleClick && cal.dateClicked)
			cal.callCloseHandler();
	};

	if (params.flat != null) {
		if (typeof params.flat == "string")
			params.flat = document.getElementById(params.flat);
		if (!params.flat) {
			alert("Calendar.setup:\n  Flat specified but can't find parent.");
			return false;
		}
		var cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect);
		cal.showsOtherMonths = params.showOthers;
		cal.showsTime = params.showsTime;
		cal.time24 = (params.timeFormat == "24");
		cal.params = params;
		cal.weekNumbers = params.weekNumbers;
		cal.setRange(params.range[0], params.range[1]);
		cal.setDateStatusHandler(params.dateStatusFunc);
		cal.getDateText = params.dateText;
		if (params.ifFormat) {
			cal.setDateFormat(params.ifFormat);
		}
		if (params.inputField && typeof params.inputField.value == "string") {
			cal.parseDate(params.inputField.value);
		}
		cal.create(params.flat);
		cal.show();
		return false;
	}

	var triggerEl = params.button || params.displayArea || params.inputField;
	triggerEl["on" + params.eventName] = function() {
		var dateEl = params.inputField || params.displayArea;
		var dateFmt = params.inputField ? params.ifFormat : params.daFormat;
		var mustCreate = false;
		var cal = window.calendar;
		if (dateEl)
			params.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt);
		if (!(cal && params.cache)) {
			window.calendar = cal = new Calendar(params.firstDay,
							     params.date,
							     params.onSelect || onSelect,
							     params.onClose || function(cal) { cal.hide(); });
			cal.showsTime = params.showsTime;
			cal.time24 = (params.timeFormat == "24");
			cal.weekNumbers = params.weekNumbers;
			mustCreate = true;
		} else {
			if (params.date)
				cal.setDate(params.date);
			cal.hide();
		}
		if (params.multiple) {
			cal.multiple = {};
			for (var i = params.multiple.length; --i >= 0;) {
				var d = params.multiple[i];
				var ds = d.print("%Y%m%d");
				cal.multiple[ds] = d;
			}
		}
		cal.showsOtherMonths = params.showOthers;
		cal.yearStep = params.step;
		cal.setRange(params.range[0], params.range[1]);
		cal.params = params;
		cal.setDateStatusHandler(params.dateStatusFunc);
		cal.getDateText = params.dateText;
		cal.setDateFormat(dateFmt);
		if (mustCreate)
			cal.create();
		cal.refresh();
		if (!params.position)
			cal.showAtElement(params.button || params.displayArea || params.inputField, params.align);
		else
			cal.showAt(params.position[0], params.position[1]);
		return false;
	};

	return cal;
};


/*
	Colorpicker from http://www.colourlovers.com/blog/2008/01/16/free-advanced-dhtml-color-picker/ .
	Modified for implementation in React.
*/

/* Global variables */
var _stop = 1, _dragHandle = "", _dragHandleStyle, tX, tY, HSV = {0: 360,1: 0,2: 100}, hSV = 149, wSV = 140, _CLCPOffset = {x: 0, y: 0}, _canDragPicker = false, _CLCPdisplay = "none", _CLCPisDraggable = true, _CLCPposition = "absolute";
var _hueTrackHeight = 147, _clickMouseLocale = "", _clickMouseLocaleCLCPIinnerShell = false, _refreshTimeout = 0, _CLCPinitHex = "", _CLCPabsPos = "";
var _CLCPbasicLimits = {"CLCPbasicHex": [0,16777215],"CLCPbasicR": [0,255],"CLCPbasicG": [0,255],"CLCPbasicB": [0,255],"CLCPbasicH": [0,359],"CLCPbasicS": [0,100],"CLCPbasicV": [0,100],"CLCPbasicC": [0,100],"CLCPbasicM": [0,100],"CLCPbasicY": [0,100],"CLCPbasicK": [0,100]};
var CLCPFieldID = '';
var _CLCPdisplay = 'none';
var _CLCPisDraggable = true;
var _CLCPposition = 'absolute';
var _CLCPinitHex = '0039B3';

Array.prototype.CLCPin_array = function(_needle) {
	var _i;
	for (_i=0;_i<=this.length;_i++ ) {
		if (this[_i] == _needle) {
			return true;
		}
	}
	return false;
};

String.prototype.CLCPpadHex = function() {
	var _str = ("000000".toString() + this.toString());
	return _str.substring((_str.length - 6),_str.length); // THANKS IE!!!!
};

CLCPHandler = function(_hex)
{
	if(!CLCPFieldID)
		return;

	var CLCPField = new DOMQuery('#' + CLCPFieldID).get(0);

	if(CLCPField)
	{
		CLCPField.value = _hex;
		CLCPField.style.background = ("#" + _hex);
	}
};

CLCPdec2hex = function(_dec) {
	var _hexChars = "0123456789ABCDEF", _hex = "";
	while (_dec > 15) {
		_hex = (_hexChars.charAt((_dec - (Math.floor(_dec / 16)) * 16)) + _hex);
		_dec = Math.floor(_dec / 16);
	}
	return (_hexChars.charAt(_dec) + _hex);
};

CLCPhex2dec = function(_hex) {
	return parseInt(_hex,16);
};

if (typeof $$ != "function") {
	$$ = function(_elementID) {
		return new DOMQuery('#' + _elementID).get(0);
	}
};

if (typeof $S != "function") {
	$S = function(_elementID) {
		var element = $$(_elementID);

		if(!element)
			return false;

		return element.style;
	}
};

CLCPisHex = function(_hex) {
	return /^[a-fA-F0-9]{6}$/.test(_hex);
};

CLCPdomEvent = function(_event) {
	_event = (_event) ? _event : window.event;
	if (_event.srcElement) {
		_event.target = _event.srcElement;
	}
	_event.code = (_event.keyCode) ? _event.keyCode : _event.charCode;
	return _event;
};

CLCPabsPos = function(_object) {
	var r = {
		x : _object.offsetLeft,
		y : _object.offsetTop
	};
	if (_object.offsetParent) {
		var v = CLCPabsPos(_object.offsetParent);
		r.x += v.x;
		r.y += v.y;
	}
	return r;
};

CLCPinitPicker = function()
{
	if(!$S('CLCP'))
		return false;

	document.onmousemove = CLCPMouseHandlerOnMouseMove;
	document.onmouseup = CLCPMouseHandlerOnMouseUp;
	document.onmousedown = CLCPMouseHandlerOnMouseDown;

	$S("CLCP").left = 0;
	$S("CLCP").top = 0;
	$S("CLCP").width = "215px";
	$S("CLCP").height = "200px";
	$$("CLCP").innerHTML = "<div id=\"CLCPDragDiv\"><div id=\"CLCPIinnerShell\"><div id=\"CLCPPicker\"><div id=\"CLCPSatVal\" onmousedown=\"CLCPslide('CLCPSatValSlide','CLCPPicker',event);\"><div id=\"CLCPSatValSlide\"></div></div><div id=\"CLCPHueContainer\" onmousedown=\"CLCPslide('CLCPHueSlide','CLCPPicker',event);\"><div id=\"CLCPHueSlide\" style=\"top: -4px; left: -7px;\"></div><div id=\"CLCPHue\"></div></div><div id=\"CLCPSatContainer\" onmousedown=\"CLCPslide('CLCPSatSlide','CLCPPicker',event);\"><div id=\"CLCPSatSlide\" style=\"top: -4px; left: -7px;\"></div><div id=\"CLCPSat\"></div></div><div id=\"CLCPValContainer\" onmousedown=\"CLCPslide('CLCPValSlide','CLCPPicker',event);\"><div id=\"CLCPValSlide\" style=\"top: -4px; left: -7px;\"></div><div id=\"CLCPVal\"></div></div></div><div id=\"CLCPbPE\"><div style=\"width: 48px; margin-right: 10px; background: url(" + board_template_url + "img/icons/toolbar/colorpicker/hex.png) center top no-repeat;\"></div><div style=\"background: url(" + board_template_url + "img/icons/toolbar/colorpicker/r.png) center top no-repeat;\"></div><div style=\"background: url(" + board_template_url + "img/icons/toolbar/colorpicker/g.png) center top no-repeat;\"></div><div style=\"margin-right: 11px; background: url(" + board_template_url + "img/icons/toolbar/colorpicker/b.png) center top no-repeat;\"></div><div style=\"background: url(" + board_template_url + "img/icons/toolbar/colorpicker/h.png) center top no-repeat;\"></div><div style=\"background: url(" + board_template_url + "img/icons/toolbar/colorpicker/s.png) center top no-repeat;\"></div><div style=\"margin-right: 0; background: url(" + board_template_url + "img/icons/toolbar/colorpicker/v.png) center top no-repeat;\"></div><div class=\"CLCPClear CLCPNoDim\"></div><input type=\"text\" id=\"CLCPbasicHex\" maxlength=\"6\" value=\"\" style=\"width: 48px; margin-right: 12px; background: url(" + board_template_url + "img/icons/toolbar/colorpicker/formFieldLargeBG.png) no-repeat;\" /><input type=\"text\" id=\"CLCPbasicR\" maxlength=\"3\" /><input type=\"text\" id=\"CLCPbasicG\" maxlength=\"3\" /><input type=\"text\" id=\"CLCPbasicB\" maxlength=\"3\" style=\"margin-right: 13px;\" /><input type=\"text\" id=\"CLCPbasicH\" maxlength=\"3\" /><input type=\"text\" id=\"CLCPbasicS\" maxlength=\"3\" /><input type=\"text\" id=\"CLCPbasicV\" maxlength=\"3\" style=\"margin-right: 0;\" /><div class=\"CLCPClear\" style=\"width: 242px; height: 15px; margin: 0; font-size: 0;\"></div><div style=\"background: url(" + board_template_url + "img/icons/toolbar/colorpicker/c.png) center top no-repeat;\"></div><div style=\"background: url(" + board_template_url + "img/icons/toolbar/colorpicker/m.png) center top no-repeat;\"></div><div style=\"background: url(" + board_template_url + "img/icons/toolbar/colorpicker/y.png) center top no-repeat;\"></div><div style=\"background: url(" + board_template_url + "img/icons/toolbar/colorpicker/k.png) center top no-repeat;\"></div><div class=\"CLCPClear CLCPNoDim\"></div><div><input type=\"text\" id=\"CLCPbasicC\" maxlength=\"3\" /></div><div><input type=\"text\" id=\"CLCPbasicM\" maxlength=\"3\" /></div><div><input type=\"text\" id=\"CLCPbasicY\" maxlength=\"3\" /></div><div><input type=\"text\" id=\"CLCPbasicK\" maxlength=\"3\" /></div><span onclick=\"CLCPhidePicker(callback);\">"+getText('colorpicker', 'select_color')+"</span></></div></div>";

	$$("CLCPIinnerShell").onmousedown = function(_event) {
		_clickMouseLocaleCLCPIinnerShell = true;
		_canDragPicker = false;
	}
	$$("CLCPDragDiv").onmousedown = function() {
		if (_clickMouseLocaleCLCPIinnerShell == false) {
			_canDragPicker = true;
			_CLCPOffset.x = (_mouseCoords[0] - parseInt($S("CLCP").left));
			_CLCPOffset.y = (_mouseCoords[1] - parseInt($S("CLCP").top));
		}
	}

	if ((_CLCPdisplay == "block") || (_CLCPdisplay == "none")) {
		$S("CLCP").display = _CLCPdisplay;
	}
	if (_CLCPposition != "absolute") {
		$S("CLCP").position = "relative";
	}
	_CLCPinitHex = (CLCPisHex(_CLCPinitHex)) ? _CLCPinitHex : "ffffff";
	_CLCPabsPos = CLCPabsPos($$("CLCP"));
	$$("CLCPbasicHex").value = _CLCPinitHex;

	CLCPupdateBasicFromForm(null,"CLCPbasicHex");

	var _btns = ["CLCPbasicHex","CLCPbasicR","CLCPbasicG","CLCPbasicB","CLCPbasicH","CLCPbasicS","CLCPbasicV","CLCPbasicC","CLCPbasicM","CLCPbasicY","CLCPbasicK"];

	for (_i=0;_i<_btns.length;_i++) {
		if (["CLCPbasicC","CLCPbasicM","CLCPbasicY","CLCPbasicK"].CLCPin_array(_btns[_i]) == false) {
			$$(_btns[_i]).onblur = $$(_btns[_i]).onkeyup = function(_event) {
				_event = (_event) ? CLCPdomEvent(_event) : CLCPdomEvent(window.event);
				CLCPupdateBasicFromForm(_event,_event.target.id,true);
			}
		}

		$$(_btns[_i]).onkeydown = function(_event) {
			_event = (_event) ? CLCPdomEvent(_event) : CLCPdomEvent(window.event);
			var _val = $$(_event.target.id).value;
			if ([40,38].CLCPin_array(_event.code)) {
				_val = (_event.target.id == "CLCPbasicHex") ? CLCPhex2dec(_val) : parseInt(_val);
				(_event.code == 40) ? ((CLCPwithin(--_val,_CLCPbasicLimits[_event.target.id][0],_CLCPbasicLimits[_event.target.id][1])) ? "" : _val++) : ((CLCPwithin(++_val,_CLCPbasicLimits[_event.target.id][0],_CLCPbasicLimits[_event.target.id][1])) ? "" : _val--);
				_val = (_event.target.id == "CLCPbasicHex") ? CLCPdec2hex(_val).toString().CLCPpadHex() : _val;
				$$(_event.target.id).value = _val;
			}
			if ([13,40,38].CLCPin_array(_event.code)) {
				CLCPupdateBasicFromForm(_event,_event.target.id);
			}
		}
	}
};

CLCPDragPicker = function(_event) {
	if (_CLCPisDraggable == true) {
		var _xOffset = (_mouseCoords[0] - _CLCPOffset.x);
		if ($S("CLCP").position == "absolute") {
			_xOffset = (_xOffset < 0) ? 0 : _xOffset;
		}
		var _yOffset = (_mouseCoords[1] - _CLCPOffset.y);
		if ($S("CLCP").position == "absolute") {
			_yOffset = (_yOffset < 0) ? 0 : _yOffset;
		}
		$S("CLCP").left = (_xOffset + "px");
		$S("CLCP").top = (_yOffset + "px");
	}
};

CLCPMouseHandlerOnMouseMove = function(_event) {
	var _scrollTop = (document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop;
	var _scrollLeft = (document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft;

	_event = (_event) ? _event : event;
	_mouseCoords = (document.all) ? [event.clientX + _scrollLeft,event.clientY + _scrollTop] : [_event.pageX,_event.pageY];

	if (_clickMouseLocale == "CLCPPicker") {
		CLCPdrag(_event);
	} else if (_canDragPicker) {
		CLCPDragPicker(_event);
	}
};

CLCPMouseHandlerOnMouseUp = function(_event) {
	document.onselectstart = function() {
		return true;
	}

	if (_clickMouseLocale == "CLCPPicker") {
		_stop = 1;
	}
	_clickMouseLocale = "";
	_canDragPicker = false;
	_clickMouseLocaleCLCPIinnerShell = false;
};

CLCPMouseHandlerOnMouseDown = function() {
	document.onselectstart = function() {
		return true;
	}
};

CLCPshowPicker = function(_obj) {
	var _x = (_obj && _obj._x) ? _obj._x : _mouseCoords[0];
	var _y = (_obj && _obj._y) ? _obj._y : _mouseCoords[1];

	callback = _obj.callback;

	if ($S("CLCP").position == "relative") {
		_x -= _CLCPabsPos.x;
		_y -= _CLCPabsPos.y;
	}

	if (_obj && CLCPisHex(_obj._hex)) {
		$$("CLCPbasicHex").value = _obj._hex;
		CLCPupdateBasicFromForm(null,"CLCPbasicHex");
	}

	$S("CLCP").left = (_x + "px");
	$S("CLCP").top = (_y + "px");
	$S("CLCP").display = "block";
};

CLCPhidePicker = function(callback) {
	$S("CLCP").display = "none";

	if(typeof callback == 'function')
		callback();
};

CLCPagent = function(_agent) {
	return Math.max(navigator.userAgent.toLowerCase().indexOf(_agent),0);
};

CLCPslide = function(_dH,_object,_event) {
	_clickMouseLocale = "CLCPPicker";
	if (_stop) {
		_stop = 0;

		_dragHandleStyle = $S(_dH);
		_dragHandle = _dH;
		_absolutePosition = CLCPabsPos($$(_object)), tX, tY;
		_absolutePosition.x += 7;
		_absolutePosition.y += 7;

		CLCPdrag(_event);
	}
};

CLCPXY = function(_event) {
	var _scrollTop = (document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop;
	var _scrollLeft = (document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft;

	if (!document.all)
	{
		var layerpos = CLCPabsPos(_event.target);
		return [layerpos.x + _event.layerX, layerpos.y + _event.layerY];
	}

	return CLCPagent("msie") ? [event.clientX + _scrollLeft,event.clientY + _scrollTop] : [_event.pageX,_event.pageY];
};

CLCPtXY = function(_event) {
	tY = CLCPXY(_event)[1] - _absolutePosition.y;
	tX = CLCPXY(_event)[0] - _absolutePosition.x;
};

CLCPckHSV = function(a,b,_dragHandle) {
	if (CLCPwithin(a,0,b)) {
		return a;
	} else if (a > b) {
		return b;
	} else if (a < 0) {
		if (_dragHandle == "CLCPbasicSatValSlide") {
			return -3;
		} else {
			return -4;
		}
	}
};

CLCPwithin = function(_val,_low,_high) {
	return ((_val >= _low) && (_val <= _high));
};

CLCPmkHSV = function(a,b,c) {
	return Math.min(a,Math.max(0,Math.ceil((parseInt(c) / b) * a)));
};

CLCPdrag = function(_event) {
	_event = (!_event) ? window.event : _event;
	if (!_stop) {
		CLCPtXY(_event);

		clearTimeout(_refreshTimeout);
		if (_dragHandle == "CLCPSatValSlide") {
			_dragHandleStyle.left = CLCPckHSV(tX,wSV,_dragHandle) + "px";
			_dragHandleStyle.top = CLCPckHSV(tY,wSV,_dragHandle) + "px";

			$S("CLCPSatSlide").top = Math.floor((CLCPckHSV(tX,wSV,"CLCPSatValSlide") / wSV) * _hueTrackHeight) + "px";
			$S("CLCPValSlide").top = Math.floor((CLCPckHSV(tY,wSV,"CLCPSatValSlide") / wSV) * _hueTrackHeight) + "px";
			HSV[1] = CLCPmkHSV(100,wSV,_dragHandleStyle.left);
			HSV[2] = 100 - CLCPmkHSV(100,wSV,_dragHandleStyle.top);
		} else if (_dragHandle == "CLCPHueSlide") {
			var ck = CLCPckHSV(tY,_hueTrackHeight,_dragHandle);
			_dragHandleStyle.top = (ck + "px");
			HSV[0] = CLCPmkHSV(360,_hueTrackHeight,ck);
		} else if (_dragHandle == "CLCPSatSlide") {
			var ck = CLCPckHSV(tY,_hueTrackHeight,_dragHandle);
			_dragHandleStyle.top = (ck + "px");
			$S("CLCPSatValSlide").left = Math.floor((CLCPckHSV(tY,_hueTrackHeight,"CLCPSatValSlide") / _hueTrackHeight) * wSV) + "px";
			HSV[1] = CLCPmkHSV(100,_hueTrackHeight,ck);
		} else if (_dragHandle == "CLCPValSlide") {
			var ck = CLCPckHSV(tY,_hueTrackHeight,_dragHandle);
			_dragHandleStyle.top = (ck + "px");
			$S("CLCPSatValSlide").top = Math.floor((CLCPckHSV(tY,_hueTrackHeight,"CLCPSatValSlide") / _hueTrackHeight) * wSV) + "px";
			HSV[2] = (100 - CLCPmkHSV(100,_hueTrackHeight,ck));
		}

		$S("CLCPSatVal").backgroundColor = $S("CLCPSat").backgroundColor = $S("CLCPVal").backgroundColor = ("#" + CLCPhsv2hex([HSV[0],100,100]));
		if (CLCPHandler) {
			CLCPHandler(CLCPhsv2hex(HSV));
		}
		CLCPupdateBasicFormElements();
	}
};

CLCPupdateBasicFormElements = function(_except) {
	if (_except != "CLCPbasicHex") {
		$$("CLCPbasicHex").value = CLCPhsv2hex(HSV);
	}

	var _rgb = CLCPhsv2rgb(HSV);
	if (_except != "CLCPbasicR") {
		$$("CLCPbasicR").value = parseInt(_rgb[0]);
	}
	if (_except != "CLCPbasicG") {
		$$("CLCPbasicG").value = parseInt(_rgb[1]);
	}
	if (_except != "CLCPbasicB") {
		$$("CLCPbasicB").value = parseInt(_rgb[2]);
	}

	if (_except != "CLCPbasicH") {
		$$("CLCPbasicH").value = parseInt(HSV[0]);
	}
	if (_except != "CLCPbasicS") {
		$$("CLCPbasicS").value = parseInt(HSV[1]);
	}
	if (_except != "CLCPbasicV") {
		$$("CLCPbasicV").value = parseInt(HSV[2]);
	}

	var _cmyk = CLCPrgb2cmyk(CLCPhsv2rgb(HSV));
	if (_except != "CLCPbasicC") {
		$$("CLCPbasicC").value = parseInt(_cmyk[0]);
	}
	if (_except != "CLCPbasicM") {
		$$("CLCPbasicM").value = parseInt(_cmyk[1]);
	}
	if (_except != "CLCPbasicY") {
		$$("CLCPbasicY").value = parseInt(_cmyk[2]);
	}
	if (_except != "CLCPbasicK") {
		$$("CLCPbasicK").value = parseInt(_cmyk[3]);
	}
};

CLCPupdateBasicFromForm = function(_event,_elementID) {
	if (_elementID == "") {
		_event = (_event) ? _event : window.event;
		if (_event.srcElement) {
			_event.target = _event.srcElement;
		}
		var _id = _event.target.id;
	} else {
		var _id = _elementID;
	}
	var _val = $$(_id).value, _canUpdate = false, _skipHSV = false;

	if (_id == "CLCPbasicHex") {
		if (CLCPisHex(_val)) {
			HSV = CLCPrgb2hsv(CLCPhex2rgb(_val));
			_canUpdate = true, _skipHSV = true;
		}
	} else if (_id == "CLCPbasicR") {
		_val = parseInt(_val);
		if (CLCPwithin(_val,0,255)) {
			var _rgb = CLCPhsv2rgb(HSV);
			HSV = CLCPrgb2hsv([_val,_rgb[1],_rgb[2]]);
			_canUpdate = true;
		}
	} else if (_id == "CLCPbasicG") {
		_val = parseInt(_val);
		if (CLCPwithin(_val,0,255)) {
			var _rgb = CLCPhsv2rgb(HSV);
			HSV = CLCPrgb2hsv([_rgb[0],_val,_rgb[2]]);
			_canUpdate = true;
		}
	} else if (_id == "CLCPbasicB") {
		_val = parseInt(_val);
		if (CLCPwithin(_val,0,255)) {
			var _rgb = CLCPhsv2rgb(HSV);
			HSV = CLCPrgb2hsv([_rgb[0],_rgb[1],_val]);
			_canUpdate = true;
		}
	} else if (_id == "CLCPbasicH") {
		_val = parseInt(_val);
		if (CLCPwithin(_val,0,360)) {
			HSV = [_val,HSV[1],HSV[2]]
			_canUpdate = true;
		}
	} else if (_id == "CLCPbasicS") {
		_val = parseInt(_val);
		if (CLCPwithin(_val,0,360)) {
			HSV = [HSV[0],_val,HSV[2]]
			_canUpdate = true;
		}
	} else if (_id == "CLCPbasicV") {
		_val = parseInt(_val);
		if (CLCPwithin(_val,0,360)) {
			HSV = [HSV[0],HSV[1],_val]
			_canUpdate = true;
		}
	} else if ((_id == "CLCPbasicC") || (_id == "CLCPbasicM") || (_id == "CLCPbasicY") || (_id == "CLCPbasicK")) {
		_c = parseInt($$("CLCPbasicC").value);
		_m = parseInt($$("CLCPbasicM").value);
		_y = parseInt($$("CLCPbasicY").value);
		_k = parseInt($$("CLCPbasicK").value);

		if (_id == "CLCPbasicC") {
			_c = (CLCPwithin(_c,0,100)) ? _c : 0;
		} else if (_id == "CLCPbasicM") {
			_m = (CLCPwithin(_m,0,100)) ? _m : 0;
		} else if (_id == "CLCPbasicY") {
			_y = (CLCPwithin(_y,0,100)) ? _y : 0;
		} else if (_id == "CLCPbasicK") {
			_k = (CLCPwithin(_k,0,100)) ? _k : 0;
		}
		HSV = CLCPrgb2hsv(CLCPcmyk2rgb([_c,_m,_y,_k]));
		_canUpdate = true;
	}

	if (_canUpdate) {
		var _hueSliderY = CLCPh2y(HSV[0]);
		var _satSliderY = CLCPs2y(HSV[1]);
		var _valSliderY = CLCPv2y(HSV[2]);

		$S("CLCPHueSlide").top = Math.floor(CLCPckHSV((_hueSliderY - 3),_hueTrackHeight + 3,"CLCPHueSlide")) + "px";
		$S("CLCPSatSlide").top = Math.floor(CLCPckHSV((_satSliderY - 3),_hueTrackHeight + 3,"CLCPSatSlide")) + "px";
		$S("CLCPValSlide").top = Math.floor(CLCPckHSV((_valSliderY - 3),_hueTrackHeight + 3,"CLCPValSlide")) + "px";

		$S("CLCPSatValSlide").left = Math.ceil(CLCPckHSV((_satSliderY - 7),wSV,"CLCPSatValSlide")) + "px";
		$S("CLCPSatValSlide").top = Math.ceil(CLCPckHSV((_valSliderY - 7),wSV,"CLCPSatValSlide")) + "px";
		$S("CLCPSatVal").backgroundColor = $S("CLCPSat").backgroundColor = $S("CLCPVal").backgroundColor = ("#" + CLCPhsv2hex([HSV[0],100,100]));
		var _tmp = (_skipHSV == false) ? CLCPhsv2hex(HSV) : _val;

		if (CLCPHandler) {
			CLCPHandler(_tmp);
		}
		CLCPupdateBasicFormElements(_id);
	}
};


/* CONVERSIONS */
CLCPh2y = function(_hue) {
	return ((_hue / 360) * _hueTrackHeight);
};
CLCPs2y = function(_satVal) {
	return ((_satVal / 100) * _hueTrackHeight);
};
CLCPv2y = function(_valVal) {
	return (Math.abs(((_valVal / 100) * (_hueTrackHeight + 3)) - _hueTrackHeight - 3));
};
CLCPhsv2hex = function(h) {
	return CLCPrgb2hex(CLCPhsv2rgb(h));
};
CLCPtoHex = function(v) {
	v=Math.round(Math.min(Math.max(0,v),255)); return("0123456789ABCDEF".charAt((v-v%16)/16)+"0123456789ABCDEF".charAt(v%16));
};
CLCPhex2rgb = function(r) {
	return({0:parseInt(r.substr(0,2),16),1:parseInt(r.substr(2,2),16),2:parseInt(r.substr(4,2),16)});
};
CLCPrgb2hex = function(r) {
	return(CLCPtoHex(r[0])+CLCPtoHex(r[1])+CLCPtoHex(r[2]));
};
CLCPrgb2hsv = function(r) {
	var max=Math.max(r[0],r[1],r[2]), delta=max-Math.min(r[0],r[1],r[2]), H, S, V;
	if(max!=0) {
		S=Math.round(delta/max*100);
		if(r[0]==max) H=(r[1]-r[2])/delta; else if(r[1]==max) H=2+(r[2]-r[0])/delta; else if(r[2]==max) H=4+(r[0]-r[1])/delta; var H=Math.min(Math.round(H*60),360); if(H<0) H+=360;
	}
	return({0:H?H:0,1:S?S:0,2:Math.round((max/255)*100)});
};
CLCPhsv2rgb = function(r) {
	var F, R, B, G, H=r[0]/360, S=r[1]/100, V=r[2]/100;
	if(S>0) {
		if(H>=1) H=0;
		H=6*H; F=H-Math.floor(H); A=Math.round(255*V*(1-S)); B=Math.round(255*V*(1-(S*F))); C=Math.round(255*V*(1-(S*(1-F)))); V=Math.round(255*V);
		switch(Math.floor(H)) {
			case 0: R=V; G=C; B=A; break;
			case 1: R=B; G=V; B=A; break;
			case 2: R=A; G=V; B=C; break;
			case 3: R=A; G=B; B=V; break;
			case 4: R=C; G=A; B=V; break;
			case 5: R=V; G=A; B=B; break;
		}
		return([R?R:0,G?G:0,B?B:0]);
	}
	else return([(V=Math.round(V*255)),V,V]);
};
CLCPrgb2cmyk = function(r) {
	var C=1-(r[0]/255), M=1-(r[1]/255), Y=1-(r[2]/255), K=Math.min(Y,Math.min(M,Math.min(C,1)));
	C=Math.round((C-K)/(1-K)*100);
	C = (isNaN(C)) ? 0 : C;
	M=Math.round((M-K)/(1-K)*100);
	M = (isNaN(M)) ? 0 : M;
	Y=Math.round((Y-K)/(1-K)*100);
	Y = (isNaN(Y)) ? 0 : Y;
	K=Math.round(K*100);
	return([C?C:0,M?M:0,Y?Y:0,K]);
};
CLCPcmyk2rgb = function(r) {
	r[3]=r[3]/100; var R=(1-(r[0]/100*(1-r[3])+r[3]))*255, G=(1-(r[1]/100*(1-r[3])+r[3]))*255, B=(1-(r[2]/100*(1-r[3])+r[3]))*255;
	return([R,G,B]);
};
/* ripped from http://www.onlinetools.org/articles/unobtrusivejavascript/cssjsseparation.html */
/* 31-10-2005 13:59 replaced with tino's code, see below */
/*
	a
		defines the action you want the function to perform.
	o
		the object in question.
	c1
		the name of the first class
	c2
		the name of the second class

	Possible actions are:

	swap
		replaces class c1 with class c2 in object o.
	add
		adds class c1 to the object o.
	remove
		removes class c1 from the object o.
	check
		test if class c1 is already applied to object o and returns true or false
	toggle
		test if class c1 is already applied to object o and remove if so, otherwise add class c1
*/
function jscss(a,o,c1,c2)
{
	switch (a)
	{
		case 'add':
			jscss.addClass(o, c1);
			break;
		case 'remove':
			jscss.removeClass(o, c1, c2);
			break;
		case 'check':
			return jscss.hasClass(o, c1);
			break;
		case 'checkParents':
			do
			{
				if (jscss.hasClass(o, c1))
					return true;

				if(o.tagName.toLowerCase() == 'body')
					return false;
			}
			while(o = o.parentNode);
			return false;
			break;
		case 'toggle':
			var operation = 'add';

			if(jscss('check', o, c1))
				operation = 'remove';

			jscss(operation, o, c1, c2);
			break;
		case 'swap':
			jscss.replaceClass(o, c2, c1);
			break;
		case 'get':
			return jscss.getClassList(o);
			break;
	}
	return null;
};

/* taken from http://therealcrisp.xs4all.nl/meuk/classdealer.js */
/* author: Tino Zijdel, 2005 */
jscss.addClass = function (element, classname)
{
	var classes = jscss.getClassList(element);
	if (classes.indexOf(classname) == -1)
	{
		classes[classes.length] = classname;
	}

	jscss.setClassList(element, classes);
};

jscss.removeClass = function (element, classname)
{
	var classes = jscss.getClassList(element), index;
	if ((index = classes.indexOf(classname)) > -1)
	{
		delete classes[index];
	}

	jscss.setClassList(element, classes);
};

jscss.replaceClass = function (element, oldclass, newclass)
{
	var classes = jscss.getClassList(element), index;
	if ((index = classes.indexOf(oldclass)) > -1 && classes.indexOf(newclass) == -1)
	{
		classes[index] = newclass;
	}

	jscss.setClassList(element, classes);
};

jscss.getClassList = function (element)
{
	if (element.className)
		return element.className.split(/\s+/);
	return [];
};

jscss.setClassList = function (element, classes)
{
	element.className = classes.join(' ');
};

jscss.hasClass = function (element, classname)
{
	var wantedClasses = new Array();
	if (classname.indexOf(' ') > -1)
	{
		wantedClasses = classname.split(/\s+/);
	} else {
		wantedClasses[0] = classname;
	}

	var classes = jscss.getClassList(element);

	for (var i = 0; i < wantedClasses.length; i++)
	{
		if (classes.indexOf(wantedClasses[i]) == -1)
		{
			return false;
		}
	}

	return true;
};

if (!Array.prototype.indexOf)
{
	Array.prototype.indexOf = function(searchElement, fromIndex)
	{
		var l = this.length, i = 0;
		if (fromIndex)
		{
			i = fromIndex;
			if (i < 0)
			{
				i += l;
				if (i < 0)
					i = 0;
			}
		}

		while (i < l)
		{
			if (this[i] === searchElement)
				return i;
			i++;
		}

		return -1;
	};
}

if (!Array.prototype.lastIndexOf)
{
	Array.prototype.lastIndexOf = function(searchElement, fromIndex)
	{
		var i = this.length;
		if (!fromIndex) fromIndex = 0;
		else if (fromIndex < 1)
		{
			fromIndex += i;
			if (fromIndex < 0) fromIndex = 0;
		}

		while (i-- > fromIndex)
		{
			if (this[i] === searchElement) return i;
		}

		return -1;
	};
};

if (!Array.getUnique)
{
	Array.prototype.getUnique = function()
	{
		var new_array = [];

		for (var i=0; i < this.length; i++)
			if (new_array.indexOf(this[i]) == -1)
				new_array.push(this[i]);

		return new_array;
	}
};

if (!String.trim)
{
	String.prototype.trim = function() {
		return this.replace(/^[\0\s\t\n\r\x0B\x0C\xA0\xAD]+|[\0\s\t\n\r\x0B\x0C\xA0\xAD]+$/g, '');
	}
};

/* we're assuming cssQuery will always be available */
var cssQuery = {};
var DOMQuery = function()
{
	var DOMQuery;

	if(document.querySelector) /* w3c: http://www.w3.org/TR/selectors-api/ */
	{
		DOMQuery = function(selector, contextNode, ns)
		{
			if(typeof contextNode == "undefined")
			{
				contextNode = DOMQuery.prototype.scope;
			}

			this.result = contextNode.querySelectorAll(selector);
			this.length = this.result.length;
		}

		DOMQuery.prototype.resultType = 'querySelector';
		DOMQuery.prototype.get = function(index) { return this.result[index]; };
	}
	else if(document.evaluate && document.implementation.hasFeature('xpath','3.0')) /* our own xpath implementation */
	{
		DOMQuery = function(selector, contextNode, ns)
		{
			if(typeof contextNode == "undefined")
				contextNode = DOMQuery.prototype.scope;

			try
			{
				var owner = '';
				if(typeof contextNode.contentType != 'undefined')
					owner = contextNode.contentType;
				else if (contextNode.ownerDocument != null && typeof contextNode.ownerDocument.contentType != 'undefined')
					owner = contextNode.ownerDocument.contentType;
				else
					owner = 'text/html';

				var namespace = ns ? ns : (['application/xml', 'application/xhtml+xml', 'text/xml'].indexOf(owner) > -1) ? 'html:' : '';

				var xpath = this.cssToXPath(selector, contextNode, namespace);

				this.result = document.evaluate(xpath, contextNode, this.NSResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
				this.length = this.result.snapshotLength;
			}
			catch(e)
			{
				if (showAlertOnXpathError)
					alert('XPath error:'+selector+'\n'+xpath+'\n'+e);
			}
		}

		DOMQuery.prototype.resultType = 'XPath';
		DOMQuery.prototype.get = function(index) { return this.result.snapshotItem(index); };

		DOMQuery.prototype.NSResolver = function (prefix)
		{
			if(prefix == 'html')
			{
				return 'http://www.w3.org/1999/xhtml';
			}
			else
			{
				 //this shouldn't ever happen
				return null;
			}
		};

		DOMQuery.cachedXPaths = [ {}, {} ];

		/* tnx to http://www.joehewitt.com/ */
		DOMQuery.prototype.cssToXPath = function (rule, contextNode, namespace)
		{
			var namespaceSpecified = false;
			if(namespace == 'undefined')
				namespace = '';
			if(namespace != "")
				namespaceSpecified = true;

			var xpath = DOMQuery.cachedXPaths[ namespaceSpecified ? 0 : 1 ][rule];

			if(typeof xpath == 'string')
			{
				return xpath;
			}

			var _rule = rule;

			var regElement = /^([#.]?)([a-z0-9\\*_-]*)((\|)([a-z0-9\\*_-]*))?/i;
			var regAttr1 = /^\[([^\]]*)\]/i;
			var regAttr2 = /^\[\s*([^\^\$~*=\s]+)\s*([\^\$~*]?=)\s*(["]?)([^"]+)\3\s*\]/i;
			var regPseudo = /^:([a-z-]+)(\((["]?)([^)]+)\3\))?/i;
			var regCombinator = /^(\s*[>+\s])?/i;
			var regComma = /^\s*,/i;

			var index = 1;
			var parts = [".//", "*"], subparts = [], collection = [];
			var lastRule = null;
			var limit = false;

			while (rule.length && rule != lastRule)
			{
				lastRule = rule;

				// Trim leading whitespace
				rule = rule.replace(/^\s*|\s*$/g,"");
				if (!rule.length)
					break;

				subparts = [];

				// Match the element identifier
				var m = regElement.exec(rule);
				if (m)
				{
					if (!m[1])
					{
						if (m[5])
							parts[index] = namespace + m[5];
						else
							parts[index] = namespace + m[2];
					}
					else if (m[1] == '#')
					{
						subparts.push("@id='" + m[2] + "'");
					}
					else if (m[1] == '.')
						subparts.push("contains(concat(' ', @class, ' '),' " + m[2] + " ')");

					rule = rule.substr(m[0].length);
				}

				// Match attribute selectors
				m = regAttr2.exec(rule);
				if (m)
				{
					switch(m[2])
					{
						case '*=': /* contains */
							subparts.push("contains(@" + m[1] + ", \"" + m[4] + "\")");
						break;
						case '~=': /* contains in space-separated value */
							subparts.push("contains(concat(' ', @" + m[1] + ", ' '), \" " + m[4] + " \")");
						break;
						case '|=': /* its value either being exactly "val" or beginning with "val" immediately followed by "-"  */
							subparts.push("@" + m[1] + " = \"" + m[4] + "\") or starts-with(concat(@" + m[1] + ", '-'), \"" + m[4] + "\"))");
						break;
						case '$=': /* ends with */
							/* not supported: http://developer.mozilla.org/en/docs/XPath:Functions*/
							/*subparts.push("ends-with(\""+m[4]+"\", @"+m[1]+")");*/
							subparts.push("substring(@" + m[1] + ", string-length(@" + m[1] + ") - " + (m[4].length - 1) + ") = \"" + m[4] + "\"");
						break;
						case '^=': /* starts with */
							subparts.push("starts-with(@"+m[1]+", \""+m[4]+"\")");
						break;
						default:
							subparts.push("@" + m[1] + "=\"" + m[4] + "\"");
						break;
					}

					rule = rule.substr(m[0].length);
				}
				else
				{
					m = regAttr1.exec(rule);
					if (m)
					{
						subparts.push("@" + m[1] + "");
						rule = rule.substr(m[0].length);
					}
				}

				m = regPseudo.exec(rule);
				while (m)
				{
					rule = rule.substr(m[0].length);
					/* position() == 5 of pos[5] ? */
					/* check msdn! */
					switch(m[1])
					{
						case 'not':
							/* process type name, id name and multiple class names of the negation pseudo class in the same style as rule above	*/
							/* warning: other pseudo classes and attributes are not supported */
							var notRule = m[4];
							var notSubparts = [];
							var notLastRule = null;

							while (notRule.length && notRule != notLastRule)
							{
								notLastRule = notRule;

								// Trim leading whitespace
								notRule = notRule.replace(/^\s*|\s*$/g,"");
								if (!notRule.length)
									break;

								// Match the element identifier
								var m = regElement.exec(notRule);
								if (m)
								{
									if (!m[1])
									{
										if (m[5])
											notSubparts.push('self::'+ namespace + m[5]);
										else
											notSubparts.push('self::'+ namespace + m[2]);
									}
									else if (m[1] == '#')
									{
										notSubparts.push("@id='" + m[2] + "'");
									}
									else if (m[1] == '.')
										notSubparts.push("contains(concat(' ', @class, ' '),' " + m[2] + " ')");

									notRule = notRule.substr(m[0].length);
								}
							}

							if(notSubparts.length > 0)
							{
								subparts.push("not(" + notSubparts.join(" and ") + ")");
							}
						break;
						case 'first-child':
							subparts.push("position() = 1");
						break;
						case 'last-child':
							subparts.push("last()");
						break;
						case 'only-child':
							subparts.push("position() = 1");
							subparts.push("last()");
						break;
						case 'enabled':
						case 'disabled':
						case 'checked':
							subparts.push("@" + m[1] + " != \"\"");
						break;
						case 'empty':
							subparts.push("count(.) = 0");
						break;
						case 'lang':
							subparts.push("@lang=\""+m[4]+"\"");
						break;
						case 'contains':
							subparts.push("contains(text(), \""+m[4]+"\")");
						break;
						/* http://www.w3.org/TR/css3-selectors/#nth-child-pseudo */
						case 'nth-child':

							/* let op: tagname kan ook iets zijn als 'html div bla:nth-child(2n+1)', dus 'parent' klopt niet!!!! */
							/*position is dan ook tov div, niet bla's parent */

							switch(m[4])
							{
								/* special / frequently used cases */
								case 'odd':
								case '2n+1':
									subparts.push("position() mod 2 > 0");
									break;
								case 'even':
								case '2n':
								case '2n+0':
									subparts.push("position() mod 2 = 0");
									break;
								/* If both a and b are equal to zero, the pseudo-class represents no element in the document tree. .*/
								case '0n+0':
									subparts.push("false()");
									break;
								default:
									var found;
									/* When a=0, no repeating is used, so for example :nth-child(0n+5) matches only the fifth child. */
									if(found = m[4].match(/^(0n\+)?([0-9]+)$/))
									{
										subparts.push("position() = " + found[2]);
									}
									/* When a=1, the number may be omitted from the rule. */
									else if(found = m[4].match(/^(^|1)n$/))
									{
										;
									}
									/* If b=0, then every ath element is picked. In such a case, the b part may be omitted. */
									else if(found = m[4].match(/^([0-9]+)n(\+0|$)$/))
									{
										subparts.push("position() mod " + found[1] + " = 0");
									}
									/* The value a can be negative  */
									else if(found = m[4].match(/^-n\+([0-9]+)$/))
									{
										subparts.push("position() <= " + found[1]);
									}
									/* this matches the bth child of an element after all the children have been split into groups of a elements each. */
									else if(found = m[4].match(/^([0-9]+)n([+-])([0-9]+)$/))
									{
										subparts.push("position() mod " + found[1] + " = (" + found[1] + " " + found[2] + " " + found[3] + ") mod " + found[1]);
									}
									else
									{
										/*throw new Error("unsupported nth-child selector: "+ m[4];)*/
									}
							}
						break;

						case 'target':
							/* should read current anchor and find matching element */
						case 'hover':
						case 'root':
							/* unsupported atm http://www.quirksmode.org/css/root.html */
						default:
							throw new Error("unsupported pseudo class: "+ m[1]);
						break;
					}

					m = regPseudo.exec(rule);
				}

				if(subparts.length > 0)
				{
					parts.push('[' + subparts.join(" and ") + ']');
				}

				// Match combinators
				m = regCombinator.exec(rule);
				if (m && m[0].length)
				{
		            if(limit)
		         {
		             parts.push(limit);
		             limit = false;
		            }

					if (m[0].indexOf(">") != -1)
					{
						parts.push("/");
					}
					else if (m[0].indexOf("+") != -1)
					{
						parts.push("/following-sibling::");
						// following-sibling selects all following siblings, we need only the first next sibling
						limit = '[1]';
					}
					else
					{
						parts.push("//");
					}

					index = parts.length;
					parts.push("*");
					rule = rule.substr(m[0].length);
				}

				m = regComma.exec(rule);
				if (m)
				{
					if(limit)
					{
						parts.push(limit);
						limit = false;
					}

					collection.push( parts.join("") );

					parts = [".//", "*"];

					index = parts.length-1;
					rule = rule.substr(m[0].length);
				}
			}

		    if(limit)
				parts.push(limit);

			collection.push( parts.join("") );

			xpath = collection.join(" | ");

			DOMQuery.cachedXPaths[ namespaceSpecified ? 0 : 1 ][_rule] = xpath;

			/*DOMQuery.storeCachedXPaths();*/
			return xpath;
		};

		DOMQuery.hasXPath = true;
	}
	else if(typeof cssQuery != 'undefined') /* dean edward's cssquery */
	{
		DOMQuery = function(selector, contextNode, ns)
		{
			if(typeof contextNode == "undefined")
				contextNode = DOMQuery.prototype.scope;

			this.result = cssQuery(selector, contextNode);
			this.length = this.result.length;
		}

		DOMQuery.prototype.resultType = 'cssQuery';
		DOMQuery.prototype.get = function(index) { return this.result[index]; };
	}
	else if(typeof Element != 'undefined' && Element && typeof Element.getElementsBySelector != 'undefined' && Element.getElementsBySelector) /* prototype */
	{
		DOMQuery = function(selector, contextNode, ns)
		{
			if(typeof contextNode == "undefined")
				contextNode = DOMQuery.prototype.scope;

			/* prototype's highest point where getElementsBySelector is to be found is... */
			if(contextNode == document)
				contextNode = document.documentElement;

			try
			{
				this.result = $(contextNode).getElementsBySelector.apply($(contextNode), selector.split(',') );
			}
			catch(e)
			{
				this.result = [];
				this.length = 0;
				throw e;
			}
			this.length = this.result.length;
		}

		DOMQuery.prototype.resultType = 'getElementsBySelector';
		DOMQuery.prototype.get = function(index) { return this.result[index]; };
	}
	else if(typeof jQuery != 'undefined') /* jquery */
	{
		DOMQuery = function(selector, contextNode, ns)
		{
			if(typeof contextNode == "undefined")
				contextNode = DOMQuery.prototype.scope;

			this.result = jQuery(selector, contextNode);
			this.length = this.result.size();
		}

		DOMQuery.prototype.resultType = 'jQuery';
		DOMQuery.prototype.get = function(index) { return this.result[index]; };
	}

	if(typeof DOMQuery == 'undefined')
		throw "No DOMQuery handler found.";

	DOMQuery.prototype.scope = document;

	return DOMQuery;
}();

function getTargets(targets, defaultDOMQuery)
{
	if(targets)
	{
		if(typeof targets == 'string')
			return new DOMQuery(targets);
		else
			return targets;
	}
	else
	{
		if(typeof defaultDOMQuery == 'string')
			return new DOMQuery(defaultDOMQuery);
		else
			return defaultDOMQuery;
	}

	return new DOMQuery('');
};

function addClassToTargets(query, classname)
{
	var items = new DOMQuery(query);

	for(var i=0, item; (item=items.get(i)); i++)
	{
		jscss('add', item, classname, '');
	}
};

function addEventToTargets(targets, type, handler, defaultDOMQuery)
{
	var elements = getTargets(targets, defaultDOMQuery), el;

	for(var i=0;(el=elements.get(i));i++)
	{
		addEvent(el, type, handler);
	}

	return elements;
};

// written by Dean Edwards, 2005
// with input from Tino Zijdel - crisp@xs4all.nl
// http://dean.edwards.name/weblog/2005/10/add-event/
function addEvent(element, type, handler)
{
	if (element.addEventListener)
	{
		element.addEventListener(type, handler, arguments.callee.eventListenerUseCapture);
	}
	else
	{
		if (!handler.$$guid) handler.$$guid = addEvent.guid++;
		if (!element.events) element.events = {};
		var handlers = element.events[type];
		if (!handlers)
		{
			handlers = element.events[type] = {};
			if (element['on' + type])
				handlers[0] = element['on' + type];
			element['on' + type] = handleEvent;
		}

		handlers[handler.$$guid] = handler;
	}
}
addEvent.guid = 1;
addEvent.eventListenerUseCapture = false;

function removeEvent(element, type, handler)
{
	if (element.removeEventListener)
		element.removeEventListener(type, handler, false);
	else if (element.events && element.events[type] && handler.$$guid)
		delete element.events[type][handler.$$guid];
};

function removeEventFromTargets(targets, type, handler, defaultDOMQuery)
{
	var elements = getTargets(targets, defaultDOMQuery), el;

	for(var i=0;(el=elements.get(i));i++)
		removeEvent(el, type, handler);
};

function handleEvent(event)
{
	event = event || fixEvent(window.event);
	var returnValue = true;
	var handlers = this.events[event.type];

	for (var i in handlers)
	{
		if (!Object.prototype[i])
		{
			this.$$handler = handlers[i];
			if (this.$$handler(event) === false) returnValue = false;
		}
	}

	if (this.$$handler) this.$$handler = null;

	return returnValue;
};

function fixEvent(event)
{
	event.preventDefault = fixEvent.preventDefault;
	event.stopPropagation = fixEvent.stopPropagation;
	return event;
}

fixEvent.preventDefault = function()
{
	this.returnValue = false;
};

fixEvent.stopPropagation = function()
{
	this.cancelBubble = true;
};

// This little snippet fixes the problem that the onload attribute on the body-element will overwrite
// previous attached events on the window object for the onload event
if (!window.addEventListener)
{
	document.onreadystatechange = function()
	{
		if (window.onload && window.onload != handleEvent)
		{
			addEvent(window, 'load', window.onload);
			window.onload = handleEvent;
		}
	};
};

function getObj(ev, ob)
{
	if(!ob)
	{
		var targ;
		if (!ev) ev = window.event;

		if (ev.target) targ = ev.target;
		else if (ev.srcElement) targ = ev.srcElement;

		if (targ && targ.nodeType == 3) // defeat Safari bug
			targ = targ.parentNode;

		return targ;
	}
	else
	{
		return ob;
	}
};

function loadScript(url, prependBoardUrl)
{
	if(prependBoardUrl)
		url = board_template_url + url;

	var e = createDOMNode('script', {"type" : 'text/javascript', "src" : url}, []);

	document.getElementsByTagName("head")[0].appendChild(e);
};

function currentStyle(element, property)
{
	return window.getComputedStyle ? window.getComputedStyle(element,'').getPropertyValue(property) : element.currentStyle.getAttribute(property);
};


function overloadFunction( name, func )
{
	func.previousFunctionDefinition = window[name];
	window[name] = func;
};

function empty()
{
	if(this && this.value == this.defaultValue )
	{
		this.value = '';
	}
};

function unhtmlspecialchars(str)
{
	str = str.replace(/&amp;/gi, '&');
	str = str.replace(/&lt;/gi, '<');
	str = str.replace(/&gt;/gi, '>');
	return str;
};

/* tnx crisp */
function htmlspecialchars(input)
{
	input = input.replace(/&/g,'&amp;');
	input = input.replace(/>/g,'&gt;');
	input = input.replace(/</g,'&lt;');
	input = input.replace(/"/g,'&quot;');

	/* " < fix syntax highlighting */

	return input;
};

function getCookie(sName)
{
	var aCookie = document.cookie.split('; '), i = aCookie.length, aCrumb;
	while (i--)
	{
		aCrumb = aCookie[i].split('=');
		if (sName == aCrumb[0])
			return typeof aCrumb[1] != 'undefined'? unescape(aCrumb[1]) : null;
	}

	return null;
}

/*
 * Find the next sibling node (skipping text nodes) or a sibling with a specific tag name
 */
function getSiblingNode(startpoint, direction, tagName)
{
	var o = startpoint, tagEmpty = (tagName == undefined || tagName.length == 0);

	if (tagName != undefined)
		tagName = tagName.toLowerCase();

	do
	{
		if (direction == 'previous')
		{
			o = o.previousSibling;
		}
		else if ( direction == 'next' )
		{
			o = o.nextSibling;
		}
		else if ( direction == 'up' )
		{
			o = o.parentNode;
		}

		if ( o && o.nodeType == 1)
		{
			if (tagEmpty || o.tagName.toLowerCase() == tagName )
				return o;
		}

	} while (o);

	return null;
}

/*
example syntax:

var test = createDOMNode( 'div', {"class" : 'waa', "event" : ['click', _func] },
			[
				createDOMNode( 'span', {"class" : 'woei'},
				[
					'snotbeuken'
				]),
				'waa',
				123
			]);
creates:
text = <div class="waa"><span class="woei">snotbeuken>waa123</div>

Or add multiple events:

"event" : [
	['click', _func],
	['change', _func2]
]
*/
function createDOMNode(tagname, options, children)
{
	var option, child, me;

	if(isIE && typeof options['type'] == 'string' && (options['type'] == 'radio' || options['type'] == 'submit'))
	{
		/* IE doesn't like dynamically generated [s]radiobuttons[/] anything, so we have to set 'name' manually */
		me = document.createElement(
				'<input' +
				' type="'+options['type'] + '"' +
				' name="' + options['name'] + '"' +
				 (typeof options['checked'] != 'undefined' ? ' checked' : '') +
				'>'
			);
	}
	else if(tagname != null)
	{
		me = document.createElement(tagname);
	}
	else
	{
		me = document.createDocumentFragment();
	}

	for(option in options)
	{
		if(!options.hasOwnProperty(option))
			continue;

		if(option == 'event')
		{
			addEvent(me, options[option][0], options[option][1]);
		}
		else if(option == 'events')
		{
			var evnt;

			for(evnt in options[option])
			{
				if(typeof options[option][evnt][0] == 'string' && typeof options[option][evnt][1] == 'function')
					addEvent(me, options[option][evnt][0], options[option][evnt][1]);
			}
		}
		else
		{
			if (option == 'class')
			{
				me.setAttribute('className', options[option]);
			}
			else if (option == 'style' && me.style.setAttribute)
			{
				me.style.setAttribute('cssText', options[option]);
				continue;
			}

			me.setAttribute(option, options[option]);
		}
	}

	for(var i = 0; (child=children[i]); i++)
	{
		if( ["string", "number"].indexOf(typeof child) > -1 )
		{
			child = document.createTextNode(child);
		}
		me.appendChild(child);
	}

	return me;
};

function setCookie(sName, sValue)
{
	document.cookie = sName + '=' + escape(sValue) + '; expires=Fri, 31 Dec 2099 23:59:59 GMT; path=/';
}

// transparantPNG - Based on http://www.schillmania.com/projects/png/ but very much completely rewritten
// Apply a filter in IE to make png's (both images and background-images) transparant
function transparantPNG(targets, scalingMethod)
{
	if (!isIE || !isWin || isIE7)
		return;

	if(!scalingMethod)
		var scalingMethod = 'image';

	// Here you can decide which elements to search for png's (you can use * but that will be very slow)
	var elements = getTargets(targets, '.transparantPNG');
	var imagesource;

	for (var i=0, object; (object=elements.get(i)); i++)
	{
		if (object.getAttribute('src'))
		{
			imagesource = object.getAttribute('src');
			object.src = board_template_url + 'img/layout/iefix/transparantPNG.gif';
		}
		else if (object.currentStyle.backgroundImage.toString() && object.currentStyle.backgroundImage.toString() != "none")
		{
			var cssBackground = object.currentStyle.backgroundImage.toString();
			var j = cssBackground.indexOf('url("')+5;
			imagesource = cssBackground.substr(j,cssBackground.length-j-2);
			object.style.backgroundImage = 'none';
		}
		else
			continue;

		object.style.writingMode = 'lr-tb';
		object.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+imagesource+"',sizingMethod='" + scalingMethod + "')";

		object.style.border = '0';
	}
}

var texts = new Array();
function getText(a, b, c)
{
	if(typeof texts[a] == 'undefined' || typeof texts[a][b] == 'undefined' || !texts[a][b] )
		return '[text not found: '+a+'::'+b+']';

	if ( c )
		return texts[a][b].replace('%s',c);
	else
		return texts[a][b];
}

function insertMultipleDocuments()
{
	if (board_action != 'insert_document')
		return false;

	var insertMultipleLink = new DOMQuery('div.action-header li.insert-multiple-documents').get(0);

	// Show 'insert multiple documents' button
	jscss('remove', insertMultipleLink, 'display-none');

	addEvent(insertMultipleLink, 'click', _insertMultipleDocuments);
}

var documentInputCount = 0;
function _insertMultipleDocuments(e)
{
	jscss('add', document.getElementById('form-insert-document'), 'multiple-documents');

	if (document.getElementById('toggle-advanced-options'))
		jscss('add', document.getElementById('toggle-advanced-options'), 'display-none');

	var input = document.getElementById('userfile');
	var copy = input.cloneNode(true);
	copy.id = '';
	copy.value = '';
	copy.name += '_' + documentInputCount++;

	input.parentNode.appendChild(copy);

	e.preventDefault();
}

// Dean Edwards/Matthias Miller/John Resig
/* http://dean.edwards.name/weblog/2006/06/again/ */
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);

	_init(events);
};

function rand ( n )
{
	return ( Math.floor ( Math.random ( ) * n + 1 ) );
}

var timings = [];
var eventTiming = false;

if (typeof showAlertOnXpathError == "undefined")
	var showAlertOnXpathError = false;

var isIE, isIE7, isIE8, isNotIE7, isGecko, isWebKit, isWin;

function _init(events, scope)
{
	if(!document.body || this.name == 'iframe-xhr-emulator')
		return;

	var time1, time2, funcname;
	var funcPattern = /function\s+([^(]*)\s*\(/, total = 0, duration = 0;

	if(!arguments.callee.initalInit)
	{
		isIE = navigator.userAgent.indexOf('MSIE') != -1 && navigator.userAgent.indexOf('Opera') == -1;
		isIE6 = isIE && navigator.userAgent.indexOf('MSIE 6.0') != -1;
		isIE7 = isIE && navigator.userAgent.indexOf('MSIE 7.0') != -1;
		isIE8 = isIE && navigator.userAgent.indexOf('MSIE 8.0') != -1;
		isNotIE7 = !isIE7;
		isGecko = navigator.userAgent.indexOf('Gecko') != -1;
		isWebKit = navigator.userAgent.indexOf('WebKit') != -1;
		isWin = navigator.userAgent.indexOf('Windows') != -1;
		jscss('add', document.body, 'javascript', '');

		arguments.callee.initalInit = true;
	}

	if(scope)
	{
		var previousScope = DOMQuery.prototype.scope;
		DOMQuery.prototype.scope = scope;
	}

	for(var i=0; i<events.length; i++)
	{
		try
		{
			if(eventTiming)
			{
				funcname = events[i].toString().match(funcPattern);
				if(funcname && funcname[1] != '')
					funcname = funcname[1];
				else if(funcname)
					funcname = 'anonymous';
				else
					funcname = 'unknown';

				timings[i] = funcname + ' ???';
				time1 = new Date().getTime();
			}

			if(typeof events[i] == 'function')
				events[i]();
			else if(typeof events[i] == 'object')
				events[i][0].apply(window, events[i][1]);

			if(eventTiming)
			{
				time2 = new Date().getTime();
				duration = (time2 - time1);
				total += duration;

				for(j=(funcname.length + duration.toString().length); j<50; j++)
					funcname += ' ';

				timings[i] = funcname + duration + ' ms\r\n';
			}
		}
		catch (e)
		{
			/* we don't need to pass the scope again */
			arguments.callee( events.slice(i + 1) );
			if(scope)
				DOMQuery.prototype.scope = previousScope;

			throw e;
		}
	}

	if(scope)
	{
		DOMQuery.prototype.scope = previousScope;
	}

	if(eventTiming)
		document.body.appendChild(createDOMNode('pre', {}, timings));
}

/* for Mozilla/Opera9 */
if (document.addEventListener)
{
	document.addEventListener("DOMContentLoaded", init, false);
}

/* for Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
	document.write("<script id=__ie_onload defer src=//:><\/script>");
	var script = document.getElementById("__ie_onload");
	script.onreadystatechange = function()
	{
		if (this.readyState != "complete")
			return;

		if(typeof initReadyStateDetectionCallback != 'function' || initReadyStateDetectionCallback())
		{
			init();
			return;
		}

		var _timer = setInterval(function()
		{
			if(initReadyStateDetectionCallback())
			{
				init(); // call the onload handler
			}
		}, 10);
	};
/*@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 linkTitleInStatusbar(targets)
{
	addEventToTargets(targets, 'mouseover', showTitleInStatusbar, 'a');
	addEventToTargets(targets, 'mouseout', clearStatusbar, 'a');
};

function showTitleInStatusbar()
{
	if(this.title.length == 0)
		return;

	if(this.accessKey.length == 1)
	{
		window.status = this.title + ' - sneltoets: Alt + '+this.accessKey;
	}
	else
	{
		window.status = this.title + ' - ' + this.href;
	}
};

function clearStatusbar()
{
	window.status = '';
	return true;
};

var maxImageWidth = 595;
var maxImageHeight = 2000;
var imagesToScale = [];
function scaleImages(targets)
{
	imagesToScale = getTargets(targets, 'ol div.message-content img:not(.smiley)');

	for(var i=0, image;(image=imagesToScale.get(i));i++)
	{
		image.setAttribute('maxwidth', maxImageWidth);
		image.setAttribute('maxheight', maxImageHeight);

		if(image.complete)
			scaleImage.call(image, null);
		else
			addEvent(image, 'load', scaleImage);
	}
	imagesToScale = [];
};

function scaleImage()
{
	/* at some really old boards, an onload=scaleImage(this) was used - it is deprecated so ignore those calls */
	if(!this)
		return;

	var maxWidth = this.getAttribute('maxwidth');
	var maxHeight = this.getAttribute('maxheight');

	if(this.width <= maxWidth && this.height <= maxHeight)
		return jscss('remove', this, 'display-none');

	var scaleRatio = maxWidth / maxHeight;

	if (this.width > maxWidth || this.height > maxHeight)
	{
		var ratio = this.width / this.height;
		this.originalWidth = this.width;
		this.originalHeight = this.height;

		if (ratio > scaleRatio)
		{
			this.width = maxWidth;
			this.height = maxWidth / ratio;
		}
		else
		{
			this.height = maxHeight;
			this.width = maxHeight * ratio;
		}

		if (this.parentNode.nodeName != 'A')
		{
			addEvent(this, 'click', popupImage);
			jscss('add', this, 'enlargeable');
			this.title += getText('extra', 'click_to_enlarge');
		}
	}

	jscss('remove', this, 'display-none');
};

function popupImage()
{
	window.open(this.src, 'img', 'width='+(this.originalWidth+16)+',height='+(this.originalHeight+16)+',left=0,top=0');
};

function makeSmileysClickable(targets)
{
	addEventToTargets(targets, 'click', _insertSmiley, 'div#smileys img');
};

function _insertSmiley()
{
	putStr(' ' +  this.alt + ' ');
	hideSmileys();
};

function localAnchors()
{
	/* strict checking for the moment, should be evaluated at a later point */
	if(!jscss('check', document.body, 'list_message') && !jscss('check', document.body, 'list_messages'))
		return;

	var container = new DOMQuery('ol#messages').get(0);
	if(!container)
		return;

	var items = new DOMQuery('address.posted-at a, blockquote.quote-blockquote a.messagelink', container);
	var pattern = /list_message\//;
	for(var i = 0, item; (item=items.get(i)); i++)
	{
		if(pattern.test(item.pathname))
		{
			addEvent(item, 'click', function(e) { if(!_localAnchors(this)) { e.preventDefault(); } } );
		}
	}
};

function _localAnchors(x)
{
	var id = x.hash.substring(1), anchors = document.anchors;

	for(var i=0, anchor; (anchor=anchors[i]); i++)
	{
		if(anchor.name == id)
		{
			window.location.hash = id;
			return false;
		}
	}
};

function slashdotLinks(targets)
{
	var items = getTargets(targets, 'ol.messages a.link'), a = createDOMNode('a', {"href" : board_script_url}, []), span, clone, shortname;
	for(var i=0, item; (item = items.get(i)); i++)
	{
		if(a.hostname != item.hostname)
		{
			if(item.href == item.text || item.hostname == item.text)
				continue;

			shortname = hostnameToShortname(item.hostname);
			span = createDOMNode('span', {}, [item.cloneNode(true), ' [' + shortname + ']']);
			item.parentNode.replaceChild(span, item);
		}
	}
};
/* these regexp's have been copied from slashcode which is GPL */
/* file: utils/domainTagifyComments */
function hostnameToShortname(hostname)
{
	if(/^(\d{1,3}\.){3}\d{1,3}$/.test(hostname))
		return hostname;

	var result;

	for(var i=1; i<=3; i++)
	{
		switch(i)
		{
			case 1:
				result = hostname.match(/([\w-]+\.[a-z]{3,4})$/i);
			break;
			case 2:
				result = hostname.match(/([\w-]+\.[a-z]{2,4}\.[a-z]{2})$/i);
			break;
			case 3:
				result = hostname.match(/([a-z]+\.[a-z]{2})$/i);
			break;
		}
		if(result)
			return result[1];
	}

	var items = hostname.split('.');
	if(items.length >= 3)
		return items.reverse().slice(0,3).reverse().join('.');

	return hostname;
};

function externalLinksInPopup(targets)
{
	var items = getTargets(targets, 'ol.messages a.link'), a = createDOMNode('a', {"href" : board_script_url}, []);

	for(var i=0, item; (item = items.get(i)); i++)
	{
		if(item.href && a.hostname != item.hostname && ['http:', 'https:'].indexOf(item.protocol) != -1 )
		{
			addEvent(item, 'click', function(e) { if(!_localAnchors(this)) { window.open(this.href, 'popupexternal'); e.preventDefault(); } } );
		}
	}
};

function indicateSecureLink(targets)
{
	var items = getTargets(targets, 'ol.messages a.link'), a = createDOMNode('a', {"href" : board_script_url}, []);

	for(var i=0, item; (item = items.get(i)); i++)
	{
		if(a.hostname != item.hostname && item.protocol == 'https:')
		{
			jscss('add', item, 'secure-link');
		}
	}

};

function searchPopup(targets)
{
	addEventToTargets(targets, 'click', function() { try {_searchPopup(this);} catch (e) {} return false;}, 'div#navigation li#search-link a');
	addEventToTargets(targets, 'dblclick', function() { document.location.href = items[0].href; } , 'div#navigation li#search-link a');
};

function _searchPopup(x)
{
	var hiddenElements = [ ['action', 'find'], ['data[searchtype]', 'search'] ], input, fieldsetNodes = [];
	for(var i =0, item; (item = hiddenElements[i]);i++)
	{
		fieldsetNodes[fieldsetNodes.length] = createDOMNode('input', {"type" : 'hidden', "name" : item[0], "value" : item[1]}, []);
	}

	var form = createDOMNode('form', {"action" : board_script_url},
				[
					createDOMNode('fieldset', {},
					[
						/*fieldsetNodes,*/
						createDOMNode('input', {"type" : 'text', "name" : 'data[q]',"size" : 40, "id" : 'search-link-input', "defaultValue" : getText('extra', 'searchPopup'), "event" : ['focus', empty]}, [])
					]),

				]);

	x.parentNode.appendChild(form);

	new DOMQuery('input#search-link-input').get(0).focus();

	return false;
};

function closeAndSubmit(targets)
{
	var items = getTargets(targets, 'div#topic-admin input#status');
	if(items.length == 0)
		return;

	if(items.get(0).nextSibling.options[items.get(0).nextSibling.selectedIndex].value != 'Closed')
	{
		var input = createDOMNode('input', {"type" :'submit', "accessKey" :'c', "value" :getText('extra','close_and_submit'), "event" :['click', function() { _closeAndSubmit(this.form); }] }, []);
		items.get(0).parentNode.appendChild(input);
	}
};

function _closeAndSubmit(form)
{
	var items = new DOMQuery('input#status + select', form);
	if(items.length == 0)
		return;

	var select = items.get(0), opts = select.options;
	for(var i=0, option; (option=opts[i]); i++)
	{
		if(	option.value == 'Closed')
		{
			select.selectedIndex = i;
			select.previousSibling.checked = true;
			break;
		}
	}
};

function indicateAccesskey(targets)
{
	var items = getTargets(targets, 'input[accesskey]');

	var replacement, indicatorCharPos, textOnButton;
	for(var i=0, item; (item=items.get(i)); i++)
	{
		switch(item.type)
		{
			case 'submit':
			case 'reset':
				textOnButton = item.value;
				indicatorCharPos = textOnButton.toLowerCase().indexOf(item.accessKey);

				if(indicatorCharPos >= 0 )
				{
					replacement =	createDOMNode('button', {"accessKey" : item.accessKey, "name" : item.name, "id" : item.id, "type" : item.type, "class" : item.className},
									[
										textOnButton.substring(0, indicatorCharPos),
										createDOMNode('span', {"class" : 'accesskey'}, [textOnButton.charAt(indicatorCharPos)]),
										textOnButton.substring(indicatorCharPos+1)
									]);
				}
				else
				{
					replacement =	createDOMNode('button', {"accessKey" : item.accessKey, "name" : item.name, "id" : item.id, "type" : item.type, "class" : item.className},
									[
										textOnButton,
										' ',
										createDOMNode('span', {"class" : 'accesskey'}, [getText('extra', 'accesskey_indicator', item.accessKey)])
									]);
				}

				/* ie moet echt dood ofzo */
				/* ie pakt de 'type' attribute niet mee */
				if(isIE)
				{
					if(item.type == 'submit')
						addEvent(replacement, 'click', function() { this.form.submit(); } );
					else if(item.type == 'reset')
						addEvent(replacement, 'click', function() { this.form.reset(); } );
				}

				item.parentNode.replaceChild(replacement, item);
				break;
		}
	}

	return true;
};

function allPagesNavigation(targets)
{
	addEventToTargets(targets, 'click', _allPagesNavigation, 'dl.topic-navigation span.cutoff');
};

function _allPagesNavigation()
{
	var dl = getSiblingNode(this, 'up', 'dl');

	var link = new DOMQuery('dd a', dl);

	if(link.length == 0)
		return;
	else
		link = link.get(0);

	/* number is stored in dl's pages-... */
	var maxPage = dl.className.match(/pages\-([0-9]+)/)[1];

	var pageNumber = prompt(getText('extra','enter_page_number', maxPage), '1');
	if(!pageNumber)
		return;

	pageNumber = parseInt(pageNumber);

	if(isNaN(pageNumber) || pageNumber < 1 || pageNumber > maxPage)
	{
		alert(getText('extra', 'page_number_incorrect'));
		return;
	}

	var matches = link.href.match(/^([^0-9]+\/[0-9]+)(\/[0-9]+)?(.*)$/);
	var _link = matches[1] + '/' + pageNumber + matches[3];

	document.location.href = _link;
};

function highlightReferrerQuery()
{
	var q = '', item = null, el = [];
	var ref = document.referrer;
	if(ref != '')
	{
		ref = createDOMNode('a', {'href' : ref}, []).search.substr(1).split('&');
		/* ref now contains a list of a=b, x=y, ... sets */
		for(var i=0; (item = ref[i]); i++)
		{
			el = item.split('=');
			if(['q', 'p', 'query'].indexOf(el[0]) > -1)
			{
				q = el[1];
				break;
			}
		}

		if(q == '')
			return;

		/* tnx to http://svn.fucoder.com/fucoder/se-hilite/se_hilite_src.js */
		q = decodeURIComponent(q);
		q = q.replace(/\'|"/g, '');
		q = q.split(/[\s,\+\.]+/);

		highlightStrings(document.body, q );
	}
};

function highlightStrings(el, strs)
{
	var regexp, metch, words, replacement;
	for(var i=0, item; (item = el.childNodes[i]); i++)
	{
		if(item.nodeType == 3)
		{
			regexp = new RegExp('\\b('+strs.join('|')+')\\b', 'ig');
			if(words = item.nodeValue.split( regexp ))
			{
				/* now highlight the individual words */
				replacement = [];
				for(var j=0, word; (word = words[j]); j++)
				{
					replacement.push( strs.indexOf(word) > -1 ? createDOMNode('span', {'class' : 'highlight1'}, [word]) : word );
				}

				item.parentNode.replaceChild(createDOMNode('span', {'class' : 'highlighting'}, replacement), item);
			}
		}
		else if(item.nodeType == 1)
		{
			highlightStrings(item, strs);
		}
	}
};

function resolveIP2Hostname()
{
	var items = new DOMQuery('li.message-ip a');

	for(var i=0, item; (item=items.get(i)); i++)
	{
		addEvent(item, 'mouseover', _resolveIP2Hostname);
		addEvent(item, 'mouseout', _resolveIP2Hostname);
	}
};

var _resolveIP2HostnameXHR;
function _resolveIP2Hostname(ev)
{
	var target = this;

	switch(ev.type)
	{
		case 'mouseover':
			_resolveIP2HostnameXHR = setTimeout( function()
				{
					var callback = function()
					{
						if (typeof req != 'undefined' && req != null && req.readyState == 4)
						{
							var result = req.responseText.match(/<dd class="lookup_user">(.+)<\/dd>/);
							alert(result[1]);
						}
					};
					var req = httpreq_string('', callback, target.href, false);
				}, 250);
		break;
		case 'mouseout':
			clearTimeout(_resolveIP2HostnameXHR);
		break;
	}
};

function autocomplete(targets)
{
	var items = getTargets(targets, 'input[suggestions]');

	for(var i=0, item; (item=items.get(i));i++)
	{
		if(item.getAttribute('readonly'))
			addEvent(item, 'focus', autocompleteSuggest);
		else
			addEvent(item, 'keyup', autocompleteSuggest);

		addEvent(item, 'keypress', dontSubmit);
		addEvent(getSiblingNode(item, 'up', 'form'), 'submit', dontSubmit);
		addEvent(item, 'blur', hideAutocompleteSuggest);
		item.setAttribute('autocomplete', 'off');
		item.setAttribute('originalvalue', item.value);
	}
};

function dontSubmit(e)
{
	/* store the previous keycode for the submit-handler which follows */
	if(e.keyCode == 13 || arguments.callee.previousKeyCode == 13)
	{
		e.preventDefault();
	}

	arguments.callee.previousKeyCode = e.keyCode;
};

function hideAutocompleteSuggest()
{
	var list = new DOMQuery('div.autocomplete', document.body).get(0);
	if (list)
	{
		list.noFocus = true;
		if (list.noMouse)
			list.parentNode.removeChild(list);
	}

	if(this.getAttribute('originalvalue') != this.value)
	{
		if(document.createEvent)
		{
			var evt = document.createEvent("HTMLEvents");
			evt.initEvent("change", true, true);
			this.dispatchEvent(evt);
		}
		else if(document.createEventObject)
		{
			var evt = document.createEventObject();
			this.fireEvent("onchange", evt);
		}
	}
};

function autocompleteSuggest(e)
{
	var li_item, list = new DOMQuery('div.autocomplete', document.body).get(0);

	switch(e.keyCode)
	{
		case 27: /* escape */
		case 8:  /* backspace */
		case 46: /* delete */
		case 16: /* shift */
		case 36: /* home */
		case 35: /* end */
			if (!list)
				return;

			list.parentNode.removeChild(list);
			this.suggesting = false;
			return;
		break;

		case 40: /* down */
		case 38: /* up */
			if (!list)
				return;

			var items = new DOMQuery('li', list);
			for (var i=0, item; (item=items.get(i));i++)
			{
				if(!jscss('check', item, 'selected'))
					continue;

				var j = i;
				if(e.keyCode == 38) /* previous */
					j--;
				else				/* next */
					j++;

				var newSelection = items.get(j);
				if(newSelection)
				{
					jscss('remove', item, 'selected', '');
					jscss('add', newSelection, 'selected');

 					var corr = newSelection.offsetTop + newSelection.offsetHeight - list.scrollTop - list.offsetHeight;
					if (corr>0)
						list.scrollTop += corr;
					corr = list.scrollTop - newSelection.offsetTop;
 					if (corr>0)
 						list.scrollTop -= corr;
				}
				break;
			}
			return;
		break;

		case 13: /* enter */
			if (!list)
				return;

			var currentSelection = new DOMQuery('li.selected', list).get(0);

			if(!currentSelection)
				return;

			if (document.createEvent)
			{
				var evt = document.createEvent('MouseEvents');
				evt.initEvent('click', true, true);
				currentSelection.dispatchEvent(evt);
			}
			else if(document.createEventObject)
			{
				var evt = document.createEventObject();
				currentSelection.fireEvent('onclick', evt);
			}

			return;
		break;
	}

	var choices = this.getAttribute('suggestions').replace(/^\s+|\s+$/g, '').toLowerCase().split(/\s+/);

	if (this.getAttribute('readonly') || !this.value.split(/\s+/).pop())
		suggestions = choices;
	else
	{
		var suggestions = [];
		var last_value = this.value.split(/\s+/).pop();

		for(var i=0; i<choices.length;i++)
			if (choices[i].toLowerCase().indexOf(last_value.toLowerCase()) == 0)
				suggestions.push(choices[i]);
	}

	autocompleteShowList(suggestions, this);
}

function autocompleteShowList(choices, input)
{
	var list = new DOMQuery('div.autocomplete', document.body).get(0), suggestions = [], completed_inline = false;
	var values = input.value.replace(/^\s+|\s+$/g, '').split(/\s+/);
	var last_value = input.value.split(/\s+/).pop(); /* when the user isn't typing; we don't want to complete the last keyword */

	// Put selected values on top
	if (input.getAttribute('readonly') || !last_value)
		choices = values.concat(choices).getUnique();

	for(var i=0; i<choices.length;i++)
	{
		if (!completed_inline && last_value && !input.getAttribute('readonly') && !isIE)
		{
			var input_value_length = input.value.length;
			input.value += choices[i].substring(last_value.length);
			input.setSelectionRange(input_value_length, input.value.length);
			completed_inline = true;
		}

		li_item =
			createDOMNode(
				'li',
				{
					'class' : (suggestions.length == 0 ? 'selected' : '') + (values.indexOf(choices[i]) >= 0 ? ' picked' : ''),
					'keyword'	: choices[i],
					'event' : ['click', function()
					{
						for(var i = 0; i < values.length; i++)
						{
							if(values[i].toLowerCase() == this.getAttribute('keyword').toLowerCase())
							{
								values.splice(i,1);
								var removed = true;
								break;
							}
						}

						if (completed_inline)
							values.pop();

						keyword = this.getAttribute('keyword').toLowerCase()
						if(!removed)
							values.push( keyword );

						if (!input.value.match(/keyword$/))
							input.value = values.join(' ').replace(/^\s+|\s+$/g, '') + ' ';
					}]
				},
				[choices[i]]
			);

		addEvent(
			li_item,
			'mouseover',
			function ()
			{
				jscss('remove', new DOMQuery('li.selected', this.parentNode).get(0), 'selected', '');
				jscss('add', this, 'selected');
			}
		);

		suggestions.push(li_item);
	}

	if(list)
		list.parentNode.removeChild(list);
	input.suggesting = false;

	if(suggestions.length > 0)
	{
		var autocompleteList = createDOMNode('div', {'class' : 'autocomplete'}, [createDOMNode('ul', {}, suggestions)] );
		document.body.appendChild(autocompleteList);
		var pos = findPos(input);
		if (isIE)
			autocompleteList.style.left = (pos.x - document.body.offsetLeft) +'px';
		else
			autocompleteList.style.left = (pos.x + 6) +'px';

		autocompleteList.style.top = (pos.y + input.offsetHeight + 4) +'px';

		addEvent(autocompleteList, 'mouseover', autocompleteListMouseOver);
		addEvent(autocompleteList, 'mouseout', autocompleteListMouseOut);

		autocompleteList.noMouse = true;

		input.suggesting = true;
	}
};

function autocompleteListMouseOver()
{
	this.noMouse = false;
};

function autocompleteListMouseOut()
{
	this.noMouse = true;
	if (this.noFocus)
		this.parentNode.removeChild(this);
};

function findPos(obj)
{
	var curleft = curtop = 0;
	if (obj.offsetParent)
	{
		curleft = obj.offsetLeft;
		curtop = obj.offsetTop;
		while (obj = obj.offsetParent)
		{
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
		}
	}
	return {x: curleft, y: curtop};
};

function stretchTextareas(targets)
{
	addEventToTargets(targets, 'keyup', stretchTextarea, 'textarea');
	addEventToTargets(targets, 'change', stretchTextarea, 'textarea');
};

function stretchTextarea()
{
	var lines = this.value.match(/([\r\n])/g);
	if(lines == null)
		return;

	this.style.height = Math.min(500, parseFloat(currentStyle(this, 'line-height')) * (lines.length + 4)) + 'px';
};

function imageGallery()
{
	if(['list_message', 'list_messages'].indexOf(board_action) == -1)
		return;

	var container = new DOMQuery('div.extra-actions ul.links').get(0);
	if(!container)
		return;

	var actionheader = new DOMQuery('div#action-header').get(0);
	if(!actionheader)
		return;

	var link = createDOMNode('li', {'class' : 'topic-gallery'},
				[
					createDOMNode('span', {'class' : 'clickable', 'title' : getText('extra', 'show_gallery'), 'event' : ['click', _imageGallery], 'request' : 'action=list_messages&data%5Btopicid%5D=' + actionheader.className.match(/topic\-topicid\-([0-9]+)/i)[1] + '&limit=999&data%5Bfilter_keywords%5D=img&data%5Bboolean%5D=AND'}, [ getText('extra', 'show_gallery') ])
				]);

	container.insertBefore(link, container.firstChild);
};

function _imageGallery()
{
	var galleryContainer = new DOMQuery('div.image-gallery').get(0);
	if(galleryContainer)
		return jscss('toggle', galleryContainer, 'display-none');

	var galleryRequest = httpreq_string(this.getAttribute('request'), null, null, false);
	var size = 180;

	if(galleryRequest.getResponseHeader('X-Errormessage'))
	{
		alert( galleryRequest.getResponseHeader('X-Errormessage') );
		return true;
	}

	var container = getElementFromXHR(galleryRequest, 'div#core');
	var items = new DOMQuery('div.message-content-content img.rml', container);

	if(items.length == 0)
		return;

	var collection = [];
	for(var i = 0, item;(item = items.get(i)); i++)
	{
		jscss('add', item, 'display-none');

		item.setAttribute('maxwidth', size);
		item.setAttribute('maxheight', size);

		addEvent(item, 'load', scaleImage);

		collection.push( createDOMNode('li', {}, [ item ]) );
	}

	var galleryContainer = createDOMNode('div', {'class' : 'image-gallery'},
	[
		createDOMNode('h3', {}, [ getText('extra', 'show_gallery_header') ]),
		createDOMNode('ol', {}, collection)
	]);

	var container = getSiblingNode(this, 'up', 'div');
	container.parentNode.appendChild(galleryContainer);
};
var documents_data = Array();

function scrollToAnchor()
{
	if (!location.hash)
		return;

	var link          = location.hash.substr(1);

	if (!link.match(/^[0-9a-z]+$/))
	{
		return;
	}

	var element       = new DOMQuery("a#" +link );
	var scrollElement = element.get(0);

	if (!scrollElement)
		return;

	addEvent(
		window,
		'load',
		function() { scrollElement.scrollIntoView(); }
	);
}

function loginForm()
{
	/* checks if field isn't filled by browser's autocomplete feature */
	var f = new DOMQuery('input#quick-login-form-user').get(0);

	if(f && f.value == '')
	{
		f.value = getText('forms', 'username');
		addEvent(f, 'focus', _clearFieldSetTypePassword);
	}

	f = new DOMQuery('input#quick-login-form-password').get(0);
	if(f && f.value == '')
	{
		try
		{
			var replacement = f.cloneNode(true);
			replacement.type = 'text';
			replacement.value = getText('forms', 'password');
			f.parentNode.replaceChild(replacement, f);

			addEvent( replacement, 'click', _clearFieldSetTypePassword);
			addEvent( replacement, 'focus', _clearFieldSetTypePassword);
		}
		catch(e) { ; }
	}
};

function _clearFieldSetTypePassword()
{
	var password_input = new DOMQuery('input#quick-login-form-password').get(0);
	var username_input = new DOMQuery('input#quick-login-form-user').get(0);

	if ( username_input.value != getText('forms', 'username') )
		return;

	/* IE has problems, we will simply replace the whole element */
	try
	{
		var replacement = password_input.cloneNode(true);
		replacement.type = 'password';
		replacement.value = '';
		password_input.parentNode.replaceChild(replacement, password_input);

		username_input.value = '';
	}
	catch(e) { ; }
};

function boardForumPulldown()
{
	if(this.tagName.toLowerCase() != 'select')
		return;

	if(Number(this.value) > 0)
	{
		document.location.href =  board_script_url +'/list_topics/' + this.value;
	}
	else if(this.value != '')
	{
		document.location.href = this.value;
	}
};

function createFooter()
{
	var footer = new DOMQuery('div#footer').get(0);

	if (!footer)
		return;

	/* Add RSS link */
	var item = new DOMQuery('head link[type="application/rss+xml"]');

	if(item.length > 0)
	{
		var rss = item.get(0);

		var a = createDOMNode('a', {"href" : rss.href, "type" : rss.type, "title" : rss.title, "class" : 'rss-link'}, ['RSS']);

		footer.insertBefore(a, footer.firstChild);
	}

	var form = new DOMQuery('div#navigation form');
	if(form.length > 0)
	{
		footer.insertBefore(form.get(0).cloneNode(true), footer.firstChild);
	}
};

function topicNavigationPulldown(targets)
{
	addEventToTargets(targets, 'submit', function(){ return _handleTopicNavigationPulldown(this);}, 'form.topic-navigation');
	addEventToTargets(targets, 'change', function(){ return _handleTopicNavigationPulldown(this.form);}, 'form.topic-navigation select');
};

function _handleTopicNavigationPulldown(form)
{
	document.location.href = form.attributes['action'].value + form.elements['action'].value +'/'+ form.elements['data[topicid]'].value +'/'+ form.elements['data[offset]'].value;
	return false;
};

function pulldownAutoSubmits(targets)
{
	addEventToTargets(targets, 'change', _handlePullDowns, 'select.faq-list, form.topic-navigation select, form#more-topic select, select#calendar-select-date, select.page-dropdown');
	addEventToTargets(null, 'change', boardForumPulldown, 'select.jump-to-action');
};

function _handlePullDowns()
{
	if(this.tagName.toLowerCase() == 'select')
		this.form.submit();
};

function toggleAuthorLinks(targets)
{
	var items = getTargets(targets, 'ol.messages div.author-nickname');

	if(items.length == 0)
		return;

	for(var i = 0, item; (item=items.get(i)); i++)
	{
		addEvent(item, 'click', _toggleAuthorLinks);
		jscss('add', item, 'author-links-toggle', '');
	}
};

function _toggleAuthorLinks(e)
{
	if(!jscss('check', (e.srcElement || e.target), 'author-nickname')) /* dont expand when clicking on a sub-element */
		return;

	var item = new DOMQuery('ul.author-links', getSiblingNode(this, 'up', 'li')).get(0);

	if (item)
		jscss('toggle', item, 'author-links-expanded');

	jscss('toggle', this, 'author-links-toggle-open');
};

function followTopicLinks()
{
	var subitems = new DOMQuery('a', this);
	if(subitems.length == 1)
	{
		window.location.href = subitems.get(0).href;
	}
}

var toggleVisibilityCookie;
function toggleVisibility(targets)
{
	var items = getTargets(
		targets,
		'h3[id] + fieldset, h3[id] + dl.property-list, tr[id].category-name td, div.extra-actions ul li#forum-tagcloud, div.discussion-folders ul.folders li[id]'
	);

	if(items.length == 0)
		return;

	getToggleVisibilityCookie();

	for(var i = 0, item;(item=items.get(i));i++)
	{
		switch(item.tagName.toLowerCase())
		{
			case 'li':
			case 'td':
				addEvent(item, 'click', _toggleVisibility);
				jscss('add',item,'toggle-icon','');

				if(toggleVisibilityCookie.indexOf(item.tagName.toLowerCase() == 'li' ? item.id : item.parentNode.id) > -1)
					_toggleVisibility(true, item);
			break;
			default:
				addEvent(item.previousSibling, 'click', _toggleVisibility);
				jscss('add',item.previousSibling,'toggle-icon','');

				if(toggleVisibilityCookie.indexOf(item.previousSibling.id) > -1)
					_toggleVisibility(true, item.previousSibling);
			break;
		}
	}
};

function _toggleVisibility(init, x)
{
	if(typeof x == 'undefined')
		x = this;

	/* don't toggle when the user clicks a link */
	if(typeof init == 'object')
	{
		var target = init.srcElement || init.target;
		if(target.tagName.toLowerCase() == 'a')
			return;
	}

	var tagname = x.tagName.toLowerCase();

	if(tagname == 'td')
	{
		if(init != true)
			storeToggleVisibility(x.parentNode.id, jscss('check', x, 'toggle-alternate-icon'));

		var node = x.parentNode;

		while( node.nextSibling && (node = node.nextSibling) && !jscss('check', node, 'category-name') )
		{
			jscss('toggle', node, 'display-none','');
		}
	}
	else
	{
		if(init != true)
		{
			storeToggleVisibility(x.id, jscss('check', x, 'toggle-alternate-icon'));
		}

		if(tagname == 'li')
		{
			jscss('toggle', x, 'display-no-childs');
		}
		else
		{
			jscss('toggle', x.nextSibling, 'display-none','');
		}
	}

	if(typeof init == 'object')
	{
		init.stopPropagation();
	}

	jscss('toggle', x, 'toggle-alternate-icon','');

	return;
};

function storeToggleVisibility(x, del)
{
	toggleVisibilityCookie = toggleVisibilityCookie.getUnique();

	if(toggleVisibilityCookie.indexOf(x) > -1 && del)
	{
		var newCookie = [];
		for(var i=0, item;(item=toggleVisibilityCookie[i]);i++)
		{
			if( item != x )
				newCookie.push(item);
		}

		toggleVisibilityCookie = newCookie;
	}
	else
	{
		if (toggleVisibilityCookie.indexOf(x) == -1)
			toggleVisibilityCookie.push(x);
	}

	setCookie('toggle', toggleVisibilityCookie.join(':'));
};

function getToggleVisibilityCookie()
{
	var c = getCookie('toggle');
	toggleVisibilityCookie = [];

	if(c)
		toggleVisibilityCookie = c.split(':');
};

function disabledOption()
{
	if(jscss('check', this.options[this.selectedIndex], 'disabled', ''))
	{
		this.selectedIndex = -1;
		alert(getText('normal', 'disabled_option'));
	}
};

function fixBrowserIssues()
{
	var i = 0, items, item;

	if(board_action == 'error_general')
	{
		var reference = new DOMQuery('ul.error-links li.home').get(0);
		if(reference)
		{
			reference.parentNode.appendChild(
				createDOMNode('li', {"class" : "back"}, [
					createDOMNode('span', {"class" : "clickable", "event" : ['click', function() { history.go(-1);}] }, [ getText('normal', 'back') ])
				])
			);
		}
	}

	if(isIE)
	{
		items = new DOMQuery('dt.required');
		var req = null;
		for(i = 0;(item=items.get(i));i++)
		{
			req = createDOMNode('span', {"class" : 'required'}, [' *']);
			item.appendChild(req);
		}

		items = new DOMQuery('button');
		for(i = 0 ; (item=items.get(i));i++)
		{
			addEvent(item, 'click', function()
			{
				this.value = this.attributes['value'].value;
				if(isIE6 && this.type == 'submit')
				/*
					http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2
					"If a form contains more than one submit button, only the activated submit button is successful."
					IE6 doesn't care and sends other submit buttons as well :|
				 */
				{
					var form = getSiblingNode(this, 'up', 'form');
					if(form)
					{
						var items = new DOMQuery('button[type=submit]', form);
						for(var i = 0, item ; (item=items.get(i));i++)
						{
							if(item != this)
								item.disabled = true;
						}
					}
				}
			});
		}

		/* IE has problems with unicode characters in forms with 'multipart' encoding
		   It 'ignores' the first input field, so we add a bogus one for IE to forget */
		items = new DOMQuery('form');
		for(i = 0 ; (item=items.get(i));i++)
		{
			if(typeof item == 'undefined')
				continue;

			if ( typeof item.enctype != 'undefined' && item.enctype == 'multipart/form-data' )
			{
				var input = createDOMNode('input', {"type" : 'hidden', "name" : 'ie-dummy'}, []);

				if ( item.elements[0] )
					item.insertBefore(input, item.elements[0]);
				else
					item.insertBefore(input);
			}
		}

		var disabled = new DOMQuery("option[disabled]"), j, parent, parents = [];
		for(i = 0;(item=disabled.get(i));i++)
		{
			jscss('add', item, 'disabled', '');
			parent = getSiblingNode(item, 'up', 'select');

			if(parents.indexOf(parent) < 0)
			{
				addEvent(parent, 'change', disabledOption);

				if(jscss('check', parent.options[parent.selectedIndex], 'disabled'))
					parent.selectedIndex = -1;

				parents.push(parent);
			}
		}
		parents = null;

		// IE 6 & IE 7 have problems with a topic-navigation DL without a topic-links to push them down
		// So we add a special class to be able to fix it in IE fix css
		addClassToTargets('p + dl.topic-navigation', 'topic-navigation-nolinks');
	}

	if(isIE6)
	{
		// MSIE can't handle first-child/last-child, so let's fix it ourselfs,
		// including some other selectors ander :after fixes
		addClassToTargets('div.action-header ol li:first-child, div#navigation li:first-child, div#welcome-text li:first-child, ul.calendar-navigation-up li:first-child', 'first-child');
		addClassToTargets('form .advanced-option + *, form dt.advanced-option + * + dd.dd-sequence, form dt.advanced-option + * + dd.dd-sequence + dd.dd-sequence', 'advanced-option-adjacent');
		addClassToTargets('div.rmltoolbar + textarea#rml_textarea', 'adjacent');

		items = new DOMQuery('input, button');
		for(i=0; (item=items.get(i));i++)
		{
			jscss('add', item, item.type);
		}

		addClassToTargets('dd.poll-result span > span', 'sub');
		addClassToTargets('dt:first-child + dd + dd.poll-result span', 'first');

		var _toggleAdvancedOptions = toggleAdvancedOptions;
		/* prevent repaint problems in IE6 */
		toggleAdvancedOptions = function()
		{
			document.body.style.display = 'none';
			 _toggleAdvancedOptions();
			document.body.style.display = 'block';
		}
	}
	else if(isWebKit)
	{
		// fancyfy the searchfields; make 'm pretty
		items = new DOMQuery('input.searchfield');
		var a = createDOMNode('a', {"href" : board_script_url}, []);
		for(i = 0; (item=items.get(i));i++)
		{
			item.setAttribute('type', 'search');

			// apple prefers a nl.react.www.search syntax
			item.setAttribute('autosave', a.host.split('.').reverse().join('.')+'.search');
			item.setAttribute('results', 5);
			item.setAttribute('placeholder', getText('normal', 'search_webkit') );
		}

		// Fix a flow-render problem
		items = new DOMQuery('div#content, div#footer');
		for(i = 0; (item=items.get(i));i++)
			item.style.overflow = 'visible';
	}
};

function attachRMLToolbar(targets)
{
	var rmltextareas = getTargets(targets, 'textarea#rml_textarea');

	if(rmltextareas.length == 0)
		return;

	for(var i = 0, item; (item=rmltextareas.get(i));i++)
	{
		item.parentNode.insertBefore(getToolbar(board_documentlibrary_allowed), item);
		if(isIE)
		{
			addEvent(item, 'click', storeCursor);
			addEvent(item, 'keyup', storeCursor);
			addEvent(item, 'select', storeCursor);
		}
	}

	/* dirty IE hack to force reflow */
	if(isIE)
	{
		addEvent(window, 'load', function() { jscss('add', document.body, 'display-none'); jscss('remove', document.body, 'display-none'); });
	}
};

function logoutSessions(targets)
{
	if(board_action != 'logout')
		return;

	var sessions = getTargets(targets, 'input[type="checkbox"]');

	for(var i=0, item; (item=sessions.get(i)); i++)
	{
		addEvent(item, 'change', _logoutSessions);
		addEvent(item, 'click', _logoutSessions);
	}
};

function _logoutSessions()
{
	var logoutOptions = new DOMQuery('form#form-logout input[type="radio"]'), logoutBySession = new DOMQuery('input#logout_by_session');

	for(var i=0, item; (item=logoutOptions.get(i));i++)
	{
		item.checked = false;
	}

	logoutBySession.get(0).checked = true;
};

function setupToggleFolders()
{
	var menu = new DOMQuery('div.discussion-folders li');

	if(menu.length == 1)
	{
		addEvent(menu.get(0), 'click', toggleFolders);
	}
};

function toggleFolders(e)
{
	e.stopPropagation();

	var childs = new DOMQuery('ul', this);

	if(childs.length > 0)
	{
		jscss('toggle', this, 'active');
	}
};

function toggleTagcloudOverflow(e)
{
	var tagcloud = new DOMQuery('li.forum-tagcloud div').get(0);
	if(!tagcloud)
		return;

	if (new DOMQuery('a', tagcloud).length < 10)
		return;

	var more = createDOMNode('span', {'event' : ['click', function(e) { jscss('toggle', tagcloud, 'show-all'); e.stopPropagation(); }] }, [ ' ' + getText('normal', 'more') ]);

	tagcloud.appendChild(more);
};

/* used for quoteing messages to textarea */
var raw_messages = [];
var formRequiredFieldsDOMQuery = 'dt.required + dd input, dt.required + dd textarea, dt.required + dd select, dt[class^="requires-id-"] + dd input, dt[class^="requires-id-"] + dd textarea, dt[class^="requires-id-"] + dd select';
var formValidateFieldsDOMQuery = formRequiredFieldsDOMQuery + ', input[class^="validate-"], input#pwd2, input#keywords, input#query_input';
var focusableElements;

function focusFirstFormField(targets)
{
	focusableElements = getTargets(targets, 'input.focusable, textarea.focusable');

	if(focusableElements.length > 0)
	{
		setTimeout("focusableElements.get(0).focus();", 100);
	}
};

function validateForms(targets)
{
	var items = getTargets(targets, 'form');

	if(items.length == 0)
		return;

	for(var i = 0, item; (item=items.get(i));i++)
	{
		addEvent(item, 'submit', function(e) { if(!validateForm(this)) { e.preventDefault(); } } );
	}

	items = new DOMQuery(formRequiredFieldsDOMQuery);
	if(items.length > 0)
	{
		var text = new DOMQuery('div#action-header p'), p;

		if(text.length > 0)
		{
			p = text.get(0);
			p.appendChild(
				createDOMNode(null, {},
				[
					createDOMNode('br', {}, [ ]),
					createDOMNode('span', {}, [ getText('forms', 'marked_fields') ]),
					createDOMNode('span', {"class" :'required'}, ['*']),
					createDOMNode('span', {}, [ getText('forms', 'required') ])
				])
			);
		}
		else
		{
			p = createDOMNode('p', {},
				[
					createDOMNode('span', {}, [ getText('forms', 'marked_fields') ]),
					createDOMNode('span', {"class" :'required'}, ['*']),
					createDOMNode('span', {}, [ getText('forms', 'required') ])
				]
			);

			var h2 = new DOMQuery('div#action-header h2').get(0);
			if(h2)
				h2.parentNode.insertBefore(p, h2);
		}
	}

	items = new DOMQuery(formValidateFieldsDOMQuery);
	for(var j = 0; (item=items.get(j));j++)
	{
		addEvent(item, 'change', function() { validateField(this); }  );
	}
};

function hideAdvancedOptions(targets)
{
	if(forms_show_advanced_options)
	{
		jscss('add', document.body, 'show-advanced-options', '');
		return;
	}

	var advancedOptions = getTargets(targets, 'dt.advanced-option');
	if(!advancedOptions.length)
		return;

	if((new DOMQuery('span#toggle-advanced-options', document)).length == 0)
	{
		var p = new DOMQuery('div#action-header p', document).get(0);
		if(!p)
		{
			p = createDOMNode('p', {}, []);
			var h2 = new DOMQuery('div#action-header h2', document).get(0);
			if(!h2)
				return;

			h2.parentNode.insertBefore(p, h2);
		}

		p.appendChild(
			createDOMNode(null, {},
			[
				createDOMNode('br', {}, [ ]),
				createDOMNode('span',
						{
							'event' : ['click', toggleAdvancedOptions],
							'id' 	: 'toggle-advanced-options',
							'class' : 'clickable',
							'name'	: 'showAdvancedOptions'
						},
						[ getText('forms', 'show_advanced_options') ]
				)
			])
		);
	}

	if(document.location.hash == '#showAdvancedOptions')
	{
		toggleAdvancedOptions();
	}
}

function toggleAdvancedOptions()
{
	var items = new DOMQuery('form');
	if(items.length == 0)
		return;

	var indicator = new DOMQuery('span#toggle-advanced-options').get(0);
	if (!indicator)
		return;

	for(var i=0, item; (item=items.get(i)); i++)
	{
		jscss('toggle', item, 'show-advanced-options');
		if(jscss('check', item, 'show-advanced-options'))
		{
			if(isIE)
			{
				item.attributes['action'].value = item.attributes['action'].value.replace(/#(.+)$/, '') + '#showAdvancedOptions';
			}
			else
			{
				item.setAttribute('action', item.getAttribute('action').replace(/#(.+)$/, '') + '#showAdvancedOptions');
			}

			if(i)
				continue;

			if(!isIE)
				window.location.hash = '#showAdvancedOptions';

			indicator.firstChild.nodeValue = getText('forms', 'hide_advanced_options');
		}
		else
		{
			if(isIE)
			{
				item.attributes['action'].value = item.attributes['action'].value.replace(/#showAdvancedOptions$/, '');
			}
			else
			{
				item.setAttribute('action', item.getAttribute('action').replace(/#showAdvancedOptions$/, '') );
			}

			if(i)
				continue;

			if(!isIE)
			{
				if (indicator.id == 'showAdvancedOptions')
					document.location.hash = indicator.id;
				else
					document.location.hash = 'hideAdvancedOptions'; //Does not exist, but setting to '' does funky things
			}
			indicator.firstChild.nodeValue = getText('forms', 'show_advanced_options');
		}
	}
};

function validateForm(form)
{
	var items = new DOMQuery(formValidateFieldsDOMQuery, form);
	var errors = false;

	for (var i = 0, item; (item=items.get(i));i++)
	{
		errors = validateField(item, true) || errors;
	}

	if (errors)
	{
		var fields = new DOMQuery('dt.field-alert + dd input');

		if (fields.length > 0)
		{
			if (!jscss('check', fields.get(0).form, 'show-advanced-options'))
			{
				var hiddenFields = new DOMQuery('h3.advanced-option dt.field-alert + dd input, dt.field-alert.advanced-option + dd input');

				if (hiddenFields.length > 0)
					toggleAdvancedOptions();
			}

			try
			{
				fields.get(0).focus();
			} catch (e){}
		}
	}

	return !errors;
};

/*
	return false is field is valid
	return true is field is not valid
*/
function validateField(ob, ret)
{
	var field = this.tagName ?  this : ob, empty = false;

	unAlertUser(field);

	if ( jscss('check', field, 'not-required') )
		return false;

	switch(field.type)
	{
		case 'select-one':
		case 'select-multiple':
			empty = (field.selectedIndex == -1) || (field.value == '') ;
			break;
		case 'checkbox':
			if(field.name.indexOf('data[do_') != -1)
				return false;

			empty = true;
			var checkboxes = field.form[field.name];

			if(!checkboxes.length)
			{
				if(checkboxes.checked)
					empty=false;
			}
			else
			{
				for (var checkbox, i = 0; (checkbox=checkboxes[i]); i++)
				{
					if (checkbox.checked)
						empty=false;
				}
			}

			break;
		case 'radio':
			var radios = field.form[field.name];
			empty = true;
			for(var radio, i = 0; (radio=radios[i]); i++)
			{
				if(radio.checked)
				{
					empty = false;
					break;
				}
			}
		break;
		default:
			empty = (field.value.trim() == '' ? true : false);
			break;
	}

	if(!empty)
	{
		switch(board_action)
		{
			case 'create_user':
			case 'edit_user':
				switch(field.id)
				{
					case 'pwd2':
						return validatePassword(field);
					break;
					case 'nickname':
						if(field.value.length < 3)
						{
							alertUser(field, getText('forms', 'name_too_short'));
						}
						else if(!ret)
						{
							validateNickname(field);
						}
					break;
					case 'email':
						if(!ret)
						{
							validateEmail(field);
							validateEmailDomain(field);
						}
					break;
				}
			default :
				var reg, res, value = field.value;

				if(jscss('check', field, 'validate-email', ''))
				{
					reg = /^[\w-]+([\.\+][\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/;
					res = reg.test(value);
					if(!res)
					{
						alertUser(field, getText('forms', 'email_incorrect'));
						return true;
					}
				}
				if(jscss('check', field, 'validate-url', ''))
				{
					if (jscss('check', field, 'no-http', ''))
						reg = /^(([0-9]{1,3}\.){3}[0-9]{1,3}|\[([a-f0-9:]+)\]|([0-9a-z_!~*'\(\)-]+\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.[a-z]{2,6})(\/?|(\/[0-9a-z_!~*'\(\)\.;?:@&=+$,%#-]+)+\/?)$/i;
					else
						reg = /^(https?:\/\/)(([0-9]{1,3}\.){3}[0-9]{1,3}|\[([a-f0-9:]+)\]|([0-9a-z_!~*'\(\)-]+\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.[a-z]{2,6})((\/?)|(\/[0-9a-z_!~*'\(\)\.;?:@&=+$,%#-]+)+\/?)$/i;

					res = reg.test(value);
					if(!res)
					{
						alertUser(field, getText('forms', 'url_incorrect'));
						return true;
					}
				}
				if(jscss('check', field, 'validate-integer', '') || jscss('check', field, 'validate-sofinummer', ''))
				{
					reg = /^[0-9]*$/;
					res = reg.test(value);
					if(!res)
					{
						alertUser(field, getText('forms', 'numeric_only'));
						return true;
					}
				}
				if(jscss('check', field, 'validate-sofinummer', ''))
				{
					if(value.length != 9)
					{
						alertUser(field, getText('forms', 'length_not_9'));
						return true;
					}
					/* source: http://cgi.dit.nl/sofi.cgi */
					var total = 0;
					for (i=1; i<=8; i++)
					{
						total += (10-i) * value[i-1];
					}
					total += (-1) * value[8];

					if ((total % 11) > 0)
					{
						alertUser(field, getText('forms', 'sofinummer_mismatch'));
						return true;
					}
				}
				if (jscss('check', field, 'validate-usericon', ''))
				{
					if (value.length > 0)
					{
						var filename = value.split(/[\/\\]/).pop();

						if (filename.length > 60)
						{
							alertUser(field, getText('forms', 'filename_too_long'));
							return true;
						}
						if (!filename.match(/^[ a-z0-9\_\-\.]+$/i))
						{
							alertUser(field, getText('forms', 'filename_invalid'));
							return true;
						}
						if (!filename.match(/\.(jpg|jpeg|gif|png)$/i))
						{
							alertUser(field, getText('forms', 'extension_invalid'));
							return true;
						}
					}
				}

				switch(field.id)
				{
					case 'keywords':
						/*reg = /[^\w0-9_\-.]/;*/
						var values = value.split(' ');
						for(i=0;(value=values[i]);i++)
						{
							if(value.length > 50)
							{
								alertUser(field, getText('forms', 'keyword_too_long', value));
								return true;
							}

							/*res = reg.test(value);
							if(res)
							{
								alertUser(field, getText('forms', 'keywords_illegal_character', value));
								return true;
							}*/
						}
					break;
					case 'recipients':
						var elements = [];
						var previousQuote = false;
						var is_quoted_element = false;
						var element = '';
						for( i = 0; i <= value.length; i++ )
						{
							if ( value.charAt(i) == '"')
							{
								if ( previousQuote && previousQuote == value.charAt(i) )
								{
									is_quoted_element = true;
									previousQuote = false;
									continue;
								}
								else if ( !previousQuote )
								{
									previousQuote = value.charAt(i);
									continue;
								}
							}

							if ( (value.charAt(i) == ',' && !previousQuote) || value.length == i )
							{
								if ( !is_quoted_element && element.match(/[0-9]+/) )
									element = parseInt(element.match(/[0-9]+/)[0]);
								elements.push(element);
								element = '';
								is_quoted_element = false;
								continue;
							}

							element += value.charAt(i);
						}

						if (field.getAttribute('maxentries'))
						{
							if (elements.length > field.getAttribute('maxentries'))
								alertUser(field, getText('forms', 'max_entries_reached', field.getAttribute('maxentries')));
						}

						if(elements.indexOf(board_user_id) + elements.indexOf(board_user_nickname) != -2 )
							alertUser(field, getText('forms', 'cant_send_to_yourself'));
					break;
				}

				// If you want custom-field validation, create functions and add functionnames to array 'extraValidateFields'
				if(typeof extraValidateFields == 'object')
				{
					for(i=0; i<extraValidateFields.length; i++)
					{
						extraValidateFields[i](field);
					}
				}
			break;
		}
	}

	var dtFieldName = getSiblingNode(getSiblingNode(field, 'up', 'dd'), 'previous', 'dt');
	if(dtFieldName)
	{
		var isRequired   = jscss('check', dtFieldName, 'required');

		/* Mark other fields as required when this field is not empty */
		var res = /requires\-id\-([a-z0-9_]+)/i.exec(dtFieldName.className);
		if(res && res[0])
		{
			var inputField = new DOMQuery('#' + res[1]).get(0);
			if(inputField)
			{
				if(!empty)
					jscss('add', getSiblingNode(inputField.parentNode, 'previous', 'dt'), 'required');
				else
					jscss('remove', getSiblingNode(inputField.parentNode, 'previous', 'dt'), 'required');

				return validateField(inputField, true);
			}
		}
	}

	if (empty && isRequired)
	{
		var text = getText('forms', 'required_field.'+ field.id);

		if (text == '[text not found: forms::required_field.'+ field.id +']')
			text =  getText('forms', 'required_field');

		alertUser(field, text);
	}
	else if (empty && !isRequired)
	{
		return false;
	}

	if (ret)
		return empty;
};

function alertUser(inputfield, str)
{
	var ddInputField = getSiblingNode(inputfield, 'up', 'dd');
	var ddErrorMsg   = getSiblingNode(getSiblingNode(inputfield, 'up', 'dd'), 'next', 'dd');
	var dtFieldName  = getSiblingNode(getSiblingNode(inputfield, 'up', 'dd'), 'previous', 'dt');

	if(!ddErrorMsg || !jscss('check',ddErrorMsg,'dd-sequence field-alert',''))
	{
		jscss( 'add', dtFieldName, 'field-alert', '');

		var x = createDOMNode('dd', {"class" :'dd-sequence field-alert'}, [str]);

		/* Add special class for IE6 if it is an advanced option */
		if(isIE6 && (jscss('check', dtFieldName, 'advanced-option') || jscss('checkParents', dtFieldName, 'advanced-option')))
			jscss( 'add', x, 'advanced-option-adjacent', '');

		ddInputField.parentNode.insertBefore(x, ddInputField.nextSibling);
	}
};

function unAlertUser(inputfield)
{
	var ddInputField = getSiblingNode(inputfield, 'up', 'dd');
	var ddErrorMsg   = getSiblingNode(getSiblingNode(inputfield, 'up', 'dd'), 'next', 'dd');
	var dtFieldName  = getSiblingNode(getSiblingNode(inputfield, 'up', 'dd'), 'previous', 'dt');

	if(ddErrorMsg && jscss('check',ddErrorMsg,'dd-sequence field-alert'))
	{
		ddInputField.parentNode.removeChild(ddErrorMsg);
		jscss('remove', dtFieldName, 'field-alert', '');
	}
};

function _validationResult(request)
{
	if (typeof request != 'undefined' && request != null && request.readyState == 4)
	{
		var response = getElementFromXHR(request, 'div#core');

		return response.firstChild.nodeValue;
	}

	return "0";
};

function _xmlrequestComplete(request)
{
	return typeof request != 'undefined' && request != null && request.readyState == 4;
};


function validatePassword(x)
{
	var pwd1 = new DOMQuery('input#pwd1').get(0);

	if(pwd1.value != x.value)
	{
		alertUser(x, getText('forms', 'password_no_match'));
		return true;
	}
};


function validateNickname(field)
{
	nicknamereq = null;
	var request = 'action=custom&data%5Btemplate%5D=validate_nickname&data%5Bnickname%5D='+encodeURI(field.value);
	nicknamereq = httpreq_string(request, _validateNickname, null, true, "GET");
};

function _validateNickname()
{
	if (_xmlrequestComplete(nicknamereq) && _validationResult(nicknamereq) == '1')
	{
		alertUser(new DOMQuery('#nickname').get(0), getText('forms', 'username_taken'));
	}
};


function validateEmailDomain(field)
{
	emaildomainreq = null;
	var request = 'action=custom&data%5Btemplate%5D=validate_emaildomain&data%5Bemail%5D='+encodeURI(field.value);
	emaildomainreq = httpreq_string(request, _validateEmailDomain, false, true, "GET");
};


function _validateEmailDomain()
{
	if (_validationResult(emaildomainreq) == '1')
	{
		alertUser(new DOMQuery('#email').get(0), getText('forms', 'invalid_domain'));
	}
};


function validateEmail(field)
{
	emailreq = null;
	var request = 'action=custom&data%5Btemplate%5D=validate_email&data%5Bemail%5D='+encodeURI(field.value);
	emailreq = httpreq_string(request, _validateEmail, false, true, "GET");
};


function _validateEmail()
{
	if (emailreq && _validationResult(emailreq) == '1')
	{
		alertUser(new DOMQuery('#email').get(0), getText('forms', 'email_taken'));
	}
};

function attachCalendarSelector(targets)
{
	var calendarSelectors = getTargets(targets, 'input.date, input.datetime'), item;

	for(var i = 0, item; (item=calendarSelectors.get(i));i++)
	{
		if(item.id == '')
			continue;

		Calendar.setup({
			inputField			:		item.id,
			ifFormat			:		jscss('check', item, 'datetime') ? arguments.callee.ifFormatDateTime : arguments.callee.ifFormatDate,
			showsTime			:		jscss('check', item, 'datetime'),
			align				:		"Tl",
			step				:		1,
			electric			:		false,
			firstDay			:		1,
			onClose				:		function(cal)
										{
											cal.hide();
											if(document.createEvent)
											{
												var evt = document.createEvent("HTMLEvents");
												evt.initEvent("change", true, true);
												cal.params['inputField'].dispatchEvent(evt);
											}
											else if(document.createEventObject)
											{
												var evt = document.createEventObject();
												cal.params['inputField'].fireEvent("onchange", evt);
											}
										}
		});
	}
};
attachCalendarSelector.ifFormatDate = "%d-%m-%Y";
attachCalendarSelector.ifFormatDateTime = "%d-%m-%Y %H:%M:%S";


function selectAllRows(targets)
{
	var tables = getTargets(targets, 'div#content form table');

	if(tables.length == 0)
		return;

	for(var i = 0; i < tables.length; i++)
	{
		var checkboxes =  new DOMQuery('input[TYPE="checkbox"]', tables.get(i));
		if(checkboxes.length == 0)
			continue;

		var tablefooter = new DOMQuery("tfoot", tables.get(i)).get(0);
		if(!tablefooter)
			continue;

		var tr = createDOMNode('tr', {"class" :'footer-form'},
		[
			createDOMNode('td', {"class" :'select'},
			[
				createDOMNode('input', {"type" :'checkbox', "id" :'selectAllRows-'+i, "name" :'selectAllRows-'+i, "event" : (isIE ? ['click', _selectAllRows] : ['change', _selectAllRows]) }, [])
			]),
			createDOMNode('td', {"colSpan" :5},
			[
				isIE ?
				createDOMNode('label', { 'htmlFor' : 'selectAllRows-'+i}, [getText('forms', 'select_all_rows')])
				:
				createDOMNode('label', { 'for' : 'selectAllRows-'+i}, [getText('forms', 'select_all_rows')])
			])
		]);

		tablefooter.appendChild(tr);
	}

	if(isGecko && !isWebKit)
	{
		jscss('add',document.body,'display-none','');
		jscss('remove',document.body,'display-none','');
	}
};

function _selectAllRows()
{
	var checked = this.checked;
	var items = new DOMQuery('tbody input[TYPE="checkbox"]', getSiblingNode(this, 'up', 'table'));
	for(var i = 0, item; (item=items.get(i));i++)
	{
		item.checked = checked;
	}
};

function rewriteQuoteLinks()
{
	if(raw_messages.length == 0)
		return;

	for(var i = 0, item; (item=raw_messages[i]); i++)
	{
		/* using a reference to message-? to slightly speed up lookup */
		var links = new DOMQuery("li.message-quote a", new DOMQuery("li#message-"+item[0]).get(0) );

		if(links.length > 0)
		{
			addEvent(links.get(0), 'click', function(e) { if(!copyQuoteToRML(this)) { e.preventDefault(); } } );
		}
	}
};

function copyQuoteToRML(x)
{
	var path = board_script_url + '/quote_message/';
	var temp = x.href.substring( path.length );
	var reg = /^([0-9]+)/;
	var res = temp.match(reg);
	var messageid = res[1];

	for(var i = 0, item; (item=raw_messages[i]);i++)
	{
		if(item[0] == messageid)
		{
			putStr(item[1]);
			return false;
		}
	}

	return true;
};

/* helper function for raw messages */
function q()
{
	return '"';
};

function privateMessagingCopyContact(targets)
{
	if(board_action == 'pm_new_message')
		addEventToTargets(targets, 'change', _privateMessagingCopyContact, 'input#recipients + select');
};

function _privateMessagingCopyContact()
{
	if(this.options[this.selectedIndex].value == '')
		return;

	var input = new DOMQuery("input#recipients").get(0);

	var username = this.options[this.selectedIndex].value;

	if ( username.match("'") )
		username = '"'+ username + '"';
	else if ( username.match(/^[0-9]+$/) || username.match('"') )
		username = "'"+ username + "'";

	input.value += (input.value != '' ? ', ' : '') + username;
};

function selectSelectedTopicAdmin(targets)
{
	var selects = getTargets(targets, 'div#topic-admin select[selected]')

	for (var i = 0, select; (select=selects.get(i));i++)
	{
		for (var j = 0; j<select.options.length; j++)
		{
			if (select.options[j].value == select.getAttribute("selected"))
				select.options[j].selected = true;
		}
	}
};

function toggleChangeCheckboxTopicAdmin()
{
	var topicAdmin = new DOMQuery("div#topic-admin").get(0);
	if(!topicAdmin)
		return;

	addEventToTargets(new DOMQuery('input[type="text"], textarea, select', topicAdmin), 'change', _toggleChangeCheckboxTopicAdmin);
	addEventToTargets("input#delmessages", 'change', selectMessagesForDeletion);
	addEventToTargets("input#splitmessages", 'change', selectMessagesForSplit);
};

function _toggleChangeCheckboxTopicAdmin()
{
	var search = jscss('check', this.parentNode, 'dd-sequence') ? this.parentNode.previousSibling : this.parentNode;
	var items = new DOMQuery('input[type="checkbox"]', search);

	if(items.length > 0)
	{
		items.get(0).checked=true;
	}
};

var callbackOnMessageToggledSelected = null;
function _selectMessages(unsetCurrentMessages)
{
	var items = new DOMQuery('li.message');

	for(var i=0, item; (item=items.get(i));i++)
	{
		addEvent(item, 'click', _selectMessage);
		if(unsetCurrentMessages)
		{
			jscss('remove', item, 'selected', '');
		}
	}
};

function _selectMessage()
{
	if(!callbackOnMessageToggledSelected)
		return;

	jscss('toggle', this, 'selected', '');
	callbackOnMessageToggledSelected(this, jscss('check', this, 'selected', ''));
};

function _messageToggledForDeletion(listitem, selected)
{
	var del_messageids = new DOMQuery("input#del_messageids").get(0);
	if(!del_messageids)
		return;

	var reg = /^message\-([0-9]+)$/;
	var res = listitem.id.match(reg);
	var messageid = res[1];

	var ids = del_messageids.value.split(',');

	if(selected)
	{
		ids[ids.length] = messageid;
	}
	else
	{
		for(var i = 0; i < ids.length; i++)
		{
			if(ids[i] == messageid)
			{
				delete ids[i];
			}
		}
	}

	del_messageids.value = ids.join(',');
};

function selectMessagesForDeletion()
{
	var del_messageids = new DOMQuery("input#del_messageids").get(0);
	if(!del_messageids)
		return;

	del_messageids.value = '';

	_selectMessages(!this.checked);

	if(!this.checked)
		callbackOnMessageToggledSelected = null;
	else
		callbackOnMessageToggledSelected = _messageToggledForDeletion;

	if(this.checked)
		alert(getText('forms', 'select_messages'));
};

function _messageToggledForSplit(listitem, selected)
{
	var split_messageids = new DOMQuery("input#split_messageids").get(0);
	if(!split_messageids)
		return;

	var reg = /^message\-([0-9]+)$/;
	var res = listitem.id.match(reg);
	var messageid = res[1];

	var ids = split_messageids.value.split(',');

	if(selected)
	{
		ids[ids.length] = messageid;
	}
	else
	{
		for(var i=0, item; (item=ids[i]);i++)
		{
			if(item == messageid)
				delete item;
		}
	}

	split_messageids.value = ids.join(',');
};

function selectMessagesForSplit()
{
	var split_messageids = new DOMQuery("input#split_messageids").get(0);
	if(!split_messageids)
		return;

	split_messageids.value = '';

	_selectMessages(!this.checked);
	if(!this.checked)
		callbackOnMessageToggledSelected = null;
	else
		callbackOnMessageToggledSelected = _messageToggledForSplit;

	if(this.checked)
		alert(getText('forms', 'select_messages'));
};

function findForm()
{
	var order = new DOMQuery('form#form-find select#order').get(0);
	if(!order)
		return;

	var queryField = new DOMQuery('form#form-find input#query_input').get(0);
	if(!queryField)
		return;

	if(order.options[order.selectedIndex].value == 'relevance')
	{
		jscss('add', getSiblingNode(getSiblingNode(queryField, 'up', 'dd'), 'previous', 'dt'), 'required');
	}
	else
	{
		jscss('remove', getSiblingNode(getSiblingNode(queryField, 'up', 'dd'), 'previous', 'dt'), 'required');
		unAlertUser( queryField );
	}

	if(!arguments.callee.firstRun)
	{
		arguments.callee.firstRun = true;
		addEvent(order, 'change', arguments.callee);
	}
};
var doclibsOpened = Array();
var currentTextarea;

var rml_buttons = [
	'bold', 'italic', 'underline', 'strike','hline',
	/*'sup', 'sub','hline',*/
	'align_left','align_center','align_right','align_justify','hline',
	'list_bullet', 'list_num','hline',
	/*'color_bg', */'color_fg','hline',
	'link', 'image','hline',
	'table', /*'hr',*/'hline',
	'maximize', 'documentlibrary', 'smileys'
];

function setCurrentTextarea(window)
{
	currentTextarea = doclibsOpened[window];
};

function getToolbar( showDocumentLibrary )
{
	var x = createDOMNode('div', {"class": "rmltoolbar"}, []);

	var img;
	for(var i = 0; i < rml_buttons.length;i++)
	{
		if(rml_buttons[i] == 'documentlibrary' && !showDocumentLibrary)
			continue;

		if(rml_buttons[i] == 'maximize' && events.indexOf(stretchTextareas) > -1)
			continue;

		if(rml_buttons[i] == 'smileys')
		{
			var smileys = (new DOMQuery('div#smileys')).get(0);

			if(!smileys)
				continue;

			var smileysClone = smileys.cloneNode(true);
			var smileysContainer = getSiblingNode(smileys, 'up', 'dd');
			var smileysContainerLabel = getSiblingNode(smileysContainer, 'previous', 'dt');

			smileysContainerLabel.parentNode.removeChild(smileysContainerLabel);
			smileysContainer.parentNode.removeChild(smileysContainer);

			x.appendChild(smileysClone);
		}

		if(rml_buttons[i] == 'color_fg' || rml_buttons[i] == 'color_bg')
		{
			var colorpicker = new DOMQuery('div#CLCP').get(0);
			if(!colorpicker)
			{
				colorpicker = createDOMNode('div', { 'id' : 'CLCP', 'class' : 'CLCP' }, []);
				document.body.appendChild(colorpicker);
				CLCPinitPicker();
			}
		}

		img = createDOMNode('img', {
			'src'	: board_template_url+'img/icons/toolbar/toolbar-sprite.gif',
			'class' : 'button',
			'title' : getText('toolbar', rml_buttons[i]),
			'alt' : getText('toolbar', rml_buttons[i])
		}, []);

		if(rml_buttons[i] != 'hline')
		{
			addEvent(img, 'click', handleRMLToolbarClick);
			img.id  = 'rmltoolbar_'+rml_buttons[i];
		}
		else
			jscss('add',img,'hline','');

		x.appendChild(img);
	}

	return x;
};

function handleRMLToolbarClick()
{
	if(this.parentNode && this.parentNode.nextSibling && this.parentNode.nextSibling.tagName.toLowerCase() == 'textarea')
	{
		currentTextarea = this.parentNode.nextSibling;
	}

	var listtype, my_link, my_title, sel, rows, type, out;

	switch(this.id)
	{
		case 'rmltoolbar_bold':
			wrapSelection('[b]','[/b]');
			return;
			break;
		case 'rmltoolbar_italic':
			wrapSelection('[i]','[/i]');
			return;
			break;
		case 'rmltoolbar_underline':
			wrapSelection('[u]','[/u]');
			return;
			break;
		case 'rmltoolbar_strike':
			wrapSelection('[s]','[/s]');
			return;
			break;
		case 'rmltoolbar_sup':
			wrapSelection('[sup]','[/sup]');
			return;
			break;
		case 'rmltoolbar_sub':
			wrapSelection('[sub]','[/sub]');
			return;
			break;
		case 'rmltoolbar_align_left':
			wrapSelection('[left]','[/left]');
			return;
			break;
		case 'rmltoolbar_align_center':
			wrapSelection('[center]','[/center]');
			return;
			break;
		case 'rmltoolbar_align_right':
			wrapSelection('[right]','[/right]');
			return;
			break;
		case 'rmltoolbar_align_justify':
			wrapSelection('[justify]','[/justify]');
			return;
			break;
		case 'rmltoolbar_list_bullet':
			listtype = '*';
		case 'rmltoolbar_list_num':
			if(typeof listtype == 'undefined')
				listtype = '1';
			var type = '*';
			var sel = getCurrentSelection();
			var rows = sel.split('\n');
			var out = '[list='+listtype+']';
			for(var i = 0, row;(row=rows[i]);i++)
			{
				if(row != '')
					out += '\n\t[li]'+row+'[/li]';
			}

			if(i==0)
			{
				out += '\n\t[li]'+row+'[/li]';
			}

			out += '\n[/list]';
			setSelection(out);
			return;
			break;
		case 'rmltoolbar_color_fg':
			CLCPshowPicker( { 'callback' : function() { wrapSelection("[fgcolor=#" + CLCPhsv2hex(HSV) + "]", "[/fgcolor]") } } );
			break;
		case 'rmltoolbar_color_bg':
			CLCPshowPicker( { 'callback' : function() { wrapSelection("[bgcolor=#" + CLCPhsv2hex(HSV) + "]", "[/bgcolor]") } } );
			break;
		case 'rmltoolbar_table':
			sel = getCurrentSelection();
			rows = sel.split('\n');
			out = '[table]';
			var j;
			for(var i = 0, row;(row=rows[i]);i++)
			{
				out += '\n[tr]';
				var cells = row.split('\t');
				for(var j=0, cell;(cell=cells[j]);j++)
				{
					out += '\n\t[td]'+cell+'[/td]';
				}
				out += '\n[/tr]';
			}
			out += '\n[/table]';

			setSelection(out);
			return;
			break;
		case 'rmltoolbar_image':
			if(getCurrentSelection() != '')
			{
				wrapSelection('[img]', '[/img]');
				return;
			}
			my_link = prompt(getText('toolbar', 'enter_img_url'),"http://");

			if (my_link != null && my_link !='http://')
			{
				lft="[img]" + my_link;
				rgt="[/img]";
				wrapSelection(lft, rgt);
			}
			return;
			break;
		case 'rmltoolbar_link':
			my_link = prompt(getText('toolbar', 'enter_url'),"http://");
			if (my_link == null)
				return;

			var selection = getCurrentSelection();
			my_title = prompt(getText('toolbar', 'enter_title'),"");

			if ( selection == '' )
			{
				if(my_title != '' )
					lft="[url=" + my_link + "]"+my_title;
				else
					lft="[url=" + my_link + "]"+my_link;
			}
			else
			{
				if(my_title != '' )
					lft="[url=" + my_link + ","+my_title+"]";
				else
					lft="[url=" + my_link + "]";
			}

			rgt="[/url]";
			wrapSelection(lft, rgt);
			return;
			break;
		case 'rmltoolbar_documentlibrary':
			var width = 785;
			var height = 650;
			if(typeof wideScreenCSS != 'undefined' && wideScreenCSS)
			{
				var width = 980;
				var height = 750;
			}
			var ref = window.open(board_script_url+'/list_documents?data[small]=1','DocumentLibrary','width='+width+',height='+height+',resizable=yes,scrollbars=yes');
			doclibsOpened[ref] = this.parentNode.nextSibling;
			break;
		case 'rmltoolbar_smileys':
			toggleSmileys();
			addEvent(get_rmltextarea(), 'focus', hideSmileys);
			addEvent(get_rmltextarea(), 'blur', hideSmileys);
			break;
		case 'rmltoolbar_maximize':
			var txtarea = get_rmltextarea();
			if(jscss('check',txtarea,'extra-large',''))
			{
				jscss('remove',txtarea,'extra-large','');
				jscss('remove',txtarea,'large','');
			}
			else if( jscss('check',txtarea,'large') )
			{
				jscss('add',txtarea,'extra-large','');
			}
			else
			{
				jscss('add',txtarea,'large','');
			}
			break;
		case 'rmltoolbar_hr':
			setSelection('[hr]');
			break;
		case 'rmltoolbar_youtube':
			if(getCurrentSelection() != '')
			{
				wrapSelection('[youtube]', '[/youtube]');
				return;
			}
			my_link = prompt(getText('toolbar', 'youtube_link'), 'http://');

			if (my_link != null && my_link != 'http://')
			{
				lft="[youtube]" + my_link;
				rgt="[/youtube]";
				wrapSelection(lft, rgt);
			}
			return;
	}
};

function toggleSmileys()
{
	jscss('toggle', new DOMQuery('div#smileys').get(0), 'show');
};
function hideSmileys()
{
	jscss('remove', new DOMQuery('div#smileys').get(0), 'show');
};

function get_rmltextarea()
{
	if(typeof currentTextarea == 'undefined')
		currentTextarea = new DOMQuery('textarea#rml_textarea').get(0);
	return currentTextarea;
};

function getContentFromOriginal()
{
	get_rmltextarea().value=window.opener.get_rmltextarea().value;
};

function setContentToOriginal()
{
	window.opener.get_rmltextarea().value=get_rmltextarea().value;window.close();
};

function rescaleTextarea(txtarea)
{
	if (typeof document.all != 'undefined')
	{
		txtarea.style.height=(document.body.clientHeight-80)+'px';
		txtarea.style.width=(document.body.clientWidth-15)+'px';
	}
	else
	{
		txtarea.style.height=(window.innerHeight-80)+'px';
		txtarea.style.width=(window.innerWidth-15)+'px';
	}
};

function wrapSelection(lft, rgt)
{
	var txtarea = get_rmltextarea();

	if (isIE)
	{
		IEWrap(txtarea, lft, rgt);
	}
	else
	{
		mozWrap(txtarea, lft, rgt);
	}
};

function mozWrap(txtarea, lft, rgt)
{
	var selLength = txtarea.textLength;
	var selStart = txtarea.selectionStart;
	var selEnd = txtarea.selectionEnd;
	if (selEnd==1 || selEnd==2)
	{
		selEnd = selLength;
	}
	var s1 = txtarea.value.substring(0,selStart);
	var s2 = txtarea.value.substring(selStart, selEnd);
	var s3 = txtarea.value.substring(selEnd, selLength);

	var scrollTop = txtarea.scrollTop;
	txtarea.value = s1 + lft + s2 + rgt + s3;
	txtarea.scrollTop = scrollTop;
};

function IEWrap(txtarea, lft, rgt)
{
	strSelection = document.selection.createRange().text;
	if (strSelection != "" && document.selection.createRange().parentElement() == txtarea)
	{
		document.selection.createRange().text = lft + strSelection + rgt;
	}
	else
	{
		txtarea.value += lft + rgt;
	}
};

function getCurrentSelection()
{
	if (typeof document.selection != 'undefined' && document.selection.createRange)
	{
		return IEGet();
	}
	else if (document.getElementById)
	{
		var txtarea = get_rmltextarea();
		return mozGet(txtarea);
	}
	return '';
};

function mozGet(txtarea)
{
	var selLength = txtarea.textLength;
	var selStart = txtarea.selectionStart;
	var selEnd = txtarea.selectionEnd;
	if (selEnd==1 || selEnd==2)
		selEnd=selLength;
	return (txtarea.value).substring(selStart, selEnd);
};

function IEGet()
{
	return document.selection.createRange().text;
};

function setSelection(str)
{
	var txtarea = get_rmltextarea();
	if (typeof document.all != 'undefined')
	{
		IESet(txtarea, str);
	}
	else if (document.getElementById)
	{
		mozSet(txtarea, str);
	}
};

function mozSet(txtarea, str)
{
	var selLength = txtarea.textLength;
	var selStart = txtarea.selectionStart;
	var selEnd = txtarea.selectionEnd;
	if (selEnd==1 || selEnd==2)
		selEnd=selLength;
	var s1 = txtarea.value.substring(0,selStart);
	var s2 = txtarea.value.substring(selStart, selEnd);
	var s3 = txtarea.value.substring(selEnd, selLength);
	txtarea.value = s1 + str + s3;
};

function IESet(txtarea, str)
{
	strSelection = document.selection.createRange().text;

	if (strSelection!="")
	{
		document.selection.createRange().text = str;
	}
	else
	{
		txtarea.value += str;
	}
};

function storeCursor()
{
	this.cursorPos = document.selection.createRange().duplicate();
};

function putStr( text )
{
	var target = get_rmltextarea();

	if ( target )
	{
		if (typeof document.all != 'undefined' && target.cursorPos)
		{
			var cursorPos = target.cursorPos;
			cursorPos.text = cursorPos.text.charAt(cursorPos.text.length - 1) == ' ' ? text + ' ' : text;
		}
		else
		{
			try
			{
				wrapSelection('', text);
			}
			catch(e)
			{
				target.value += text;
			}
		}

		target.focus();
	}
};
var element_m = false;
var delta_y = 0;
var delta_x = 0;

function findMoveableElement(e)
{
	if(!e)
	{
		e = window.event;
	}

	element_m = this;

	if(!element_m)
		return;

	delta_y = (y(e) - currentStyle(element_m, 'top'));
	delta_x = (x(e) - currentStyle(element_m, 'left'));
};

function moveElement(e)
{
	if(!e)
	{
		e = window.event;
	}

	if(element_m)
	{
		var maxLeft = parseInt(window.XMLHttpRequest ? document.body.offsetWidth:document.body.scrollWidth) - currentStyle(element_m, 'width');

		element_m.style.left = Math.min(maxLeft, Math.max(x(e) - delta_x, 0)) + 'px';
		element_m.style.top = Math.max(y(e) - delta_y, 0) + 'px';
	}
};

function moveEnd()
{
	if(element_m)
		element_m = false;
};

function x(e)
{
	return (e.clientX) ? e.clientX : e.pageX;
};

function y(e)
{
	return (e.clientY) ? e.clientY : e.pageY;
};

function createOverlay()
{
	var w = document.createElement('div');

	w.style.width = window.XMLHttpRequest ? document.body.offsetWidth : document.body.scrollWidth;
	w.style.height = document.body.scrollHeight + 50;
	w.id = 'overlay';

	document.body.appendChild(w);
};

function destroyOverlay()
{
	document.body.removeChild(document.getElementById('overlay'));
};
function getDocumentSelector(documentid)
{
	var data = raw_documents[documentid];
	var format_list = [ createDOMNode('option', {"value" : ''}, [getText('doclib', 'original')]) ];

	if(typeof formats != "undefined")
	{
		for(var i=0; i < formats.length;i++)
		{
			format_list[i+1] = createDOMNode('option', {"value" : formats[i][0]}, [formats[i][0]+ ' (' + formats[i][1][0] + 'x' + formats[i][1][1] + ')']);
		}
	}

	/**
		var float_select = new DOMQuery('select[name="float"]', this);
		var format_select = new DOMQuery('select[name="format"]', this);
		var link_input = new DOMQuery('input[name="link"]', this);
	*/

	function toggleInsertAs()
	{
		var disabled = !(this.value == 'image');
		new DOMQuery('input#link_'+documentid).get(0).disabled = disabled;
		new DOMQuery('select#format_'+documentid).get(0).disabled = disabled;
		new DOMQuery('select#float_'+documentid).get(0).disabled = disabled;
	}

	var insert_as = [
		createDOMNode('dt', {}, [getText('doclib', 'insert_as')]),
		createDOMNode('dd', {}, [
			createDOMNode('input', {"value" : 'image', "name" : 'as', "type" : 'radio', "id" : 'as_image_'+documentid+'_image', 'checked' : 'checked', 'class' : 'radio', 'event' : [(isIE ? 'click' : 'change'), toggleInsertAs] }, []),
			createDOMNode('label', {'for' : 'as_image_'+documentid+'_image'}, [getText('doclib', 'insert_as_image')]),
			createDOMNode('input', {"value" : 'text', "name" : 'as', "type" : 'radio', "id" : 'as_text_'+documentid+'_image', 'class' : 'radio', 'event' : ['change', toggleInsertAs] }, []),
			createDOMNode('label', {'for' : 'as_text_'+documentid+'_text'}, [getText('doclib', 'insert_as_text')])
		] )
	];

	var insert_as_link = [
		createDOMNode('dt', {}, [getText('doclib', 'insert_as_link')]),
		createDOMNode('dd', {},
			[
				createDOMNode('input', {"value" : 'link', "name" : 'link', "type" : 'checkbox', "id" : 'link_'+documentid, 'class' : 'checkbox'}, []),
				createDOMNode('label', {'for' : 'link_'+documentid}, [getText('doclib', 'insert_as_thumb')])
			]
		)
	];

	var format = [
		createDOMNode('dt', {}, [getText('doclib', 'format')]),
		createDOMNode('dd', {},
			[
				createDOMNode('select', {"name" : 'format', "id" : 'format_'+documentid}, format_list)
			])
	];

	var align = [
		createDOMNode('dt', {}, [getText('doclib', 'outline')]),
		createDOMNode('dd', {},
		[
			createDOMNode('select', {"name" : 'float', "id" : 'float_'+documentid},
			[
				createDOMNode('option', {"value" : ''}, [getText('doclib', 'none')]),
				createDOMNode('option', {"value" : 'left'}, [getText('doclib', 'left')]),
				createDOMNode('option', {"value" : 'right'}, [getText('doclib', 'right')])
			]),
		])
	];

	var insert = [
		createDOMNode('dt', {}, [getText('doclib', 'insert')]),
		createDOMNode('dd', {},
		[
			createDOMNode('input', {"value" : getText('doclib', 'insert_image'), "type" : 'submit'}, []),
		])
	];

	if (data[5] == '1')
	{
		/* If the document is remote and doesn't have an alternative icon. Don't show the image
	 	 * related form elements */
		if (data[6] != '1')
		{
			format = [];
			align = [];
		}
		else
		{
			insert_as_link[1].childNodes[0].disabled = true;
			insert_as_link[1].childNodes[0].checked = true;
			insert_as_link[1].childNodes[0].defaultChecked = true;
		}
	}

	var form_combined = insert_as.concat(insert_as_link, format, align, insert);

	form_combined = form_combined.concat(insert_as_link);
	form_combined = form_combined.concat(format);
	form_combined = form_combined.concat(align);
	form_combined = form_combined.concat(insert);

	var form =
		createDOMNode('div', {"id" : "document-selector"},
		[
			createDOMNode('h3', {"id" : 'insert_image'}, [getText('doclib', 'insert_image')]),
			createDOMNode('form', {"method" : 'POST', "action" : board_script_url, "event" : ['submit', copy2rml]},
			[
				createDOMNode('fieldset', {},
				[
					createDOMNode('input', {"value" : documentid, "name" : 'documentid', "type" : 'hidden'}, []),
					createDOMNode('input', {"value" : data[0], "name" : 'url', "type" : 'hidden'}, []),
					createDOMNode('input', {"value" : data[1], "name" : 'key', "type" : 'hidden'}, []),
					createDOMNode('input', {"value" : data[2], "name" : 'libraryid', "type" : 'hidden'}, []),
					createDOMNode('input', {"value" : '', "name" : 'alt', "type" : 'hidden'}, []),
					createDOMNode('input', {"value" : data[4], "name" : 'filename', "type" : 'hidden'}, []),

					createDOMNode('dl', {}, form_combined)
				])
			])
		]);

	return form;
};

function doclibInteraction()
{
	switch(board_action)
	{
		case 'edit_document':
			addEventToTargets(null, 'click', modifyThumbnail, 'img[longdesc]');
		break;

		case 'list_documents':
			if (jscss('check', document.body, 'small'))
			{
				var links = new DOMQuery('a[href*="list_documents"], a[href*="edit_document"], a[href*="insert_document"]');

				for(var i = 0, link; (link = links.get(i));i++)
				{
					if(isIE)
					{
						/*
							IE checks if the link's firstChild.nodeValue equals a "valid" url,
							if so it will swap it's value with the newly set href.

							IE considers http://, https://, ftp:// and ^www. as "valid"

							IE should really die.
						*/
						if( link.firstChild.nodeValue.match(/^(((ftp|https?):\/\/)|(www\.))/) )
						{
							link.appendChild(createDOMNode('span', {'class' : 'dummy'}, []));
						}
					}
					if(isIE || isWebKit)
					{
						/*
							IE appends search part after hash, so we strip the hash,
							append search part, and append hash again

							IE should really die. See comment above.

							WebKit however has link.search as r/o, how useful is that?
						*/
						parts = link.href.split('#');

						link.href = parts[0];
						link.href += (link.search.length ? '&' : '?') +'data[small]=1';

						if(parts[1])
							link.hash = parts[1];
					}
					else
					{
						link.search += (link.search.length ? '&' : '?') +'data[small]=1';
					}
				}

				addEventToTargets(null, 'click', doclibImageClick, 'body.list_documents div.document');
			}
			else
			{
				addEventToTargets(null, 'click', selectAllDocuments, 'input#select_all_documents');
				addEventToTargets(null, 'click', selectDocument, 'body.list_documents div.document img, body.list_documents div.document li.select input');
			}
		break;
	}

	/* yes, it's doubtfull wether this is the best place... */
	var items = new DOMQuery('ol.messages a.doclib');
	for(var i = 0, item; (item = items.get(i)); i++)
	{
		addEvent(item, 'click', function(e) { window.open(this.href, 'popupdoclib'); e.preventDefault(); } );
	}
};


/*
	this function can be called in 3 ways:
	- by the checkbox itself
	- by a click on the image
	- by selectAllDocuments()
*/
function selectDocument(obj)
{
	var callingElement = this.tagName ?  this : obj, checkbox;
	var container = getSiblingNode(callingElement, 'up', 'div');

	/* if it's not the checkbox itself who's calling us, toggle it */
	if ( callingElement.tagName.toLowerCase() != 'input' )
	{
		checkbox = new DOMQuery('input[type=checkbox]', container).get(0);
		checkbox.checked = !checkbox.checked;
	}
	else
	{
		checkbox = callingElement;
	}

	if ( checkbox.checked )
	{
		jscss('add', container, 'selected', '');

		if( (new DOMQuery('div.document input')).length == (new DOMQuery('div.document.selected input')).length)
			(new DOMQuery('input#select_all_documents').get(0)).checked = true;
	}
	else
	{
		jscss('remove', container, 'selected', '');

		(new DOMQuery('input#select_all_documents').get(0)).checked = false;
	}
};

function selectAllDocuments()
{
	/* uncheck selected images */
	if(board_action == 'list_documents')
	{
		var img = new DOMQuery('div.document.selected img');
		for(var i = 0; i < img.length;i++)
		{
			selectDocument(img.get(i));
		}
	}

	if(!this.checked)
		return;

	if(board_action == 'list_documents')
	{
		img = new DOMQuery('div.document img');

		for(i=0; i < img.length;i++)
		{
			selectDocument(img.get(i));
		}
	}
};

function deselectAllDocuments()
{
	var selectedDocuments = new DOMQuery('div.document.selected');
	for(var i = 0, selectedDocument; (selectedDocument=selectedDocuments.get(i)); i++)
	{
		jscss('remove', selectedDocument, 'selected', '');
	}
}

function doclibImageClick(e)
{
	var x = this;
	if(x.tagName.toLowerCase() != 'img')
		x = new DOMQuery('img', this ).get(0);

	if (typeof x == 'undefined')
		return;

	var container = getSiblingNode(x, 'up', 'div');
	var documentid = container.id.replace(/^document_/, '');

	/* store for later use */
	var currentlySelected = jscss('check', container, 'selected');
	deselectAllDocuments();

	/* destroy existing */
	var currentForm = new DOMQuery("div.discussion-content div#document-selector").get(0);
	if(currentForm)
		currentForm.parentNode.removeChild(currentForm);

	/* show just one form at a time */
	var searchForm = new DOMQuery('form#form-documents-find').get(0);
	if(currentlySelected)
	{
		jscss('remove', searchForm, 'display-none');
		jscss('remove', getSiblingNode(searchForm, 'previous', 'h3'), 'display-none');
		deselectAllDocuments();
		/* we're de-selecting, so no info to parent window */
		return;
	}
	else
	{
		jscss('add', container, 'selected', '');

		if(searchForm)
		{
			jscss('add', searchForm, 'display-none');
			jscss('add', getSiblingNode(searchForm, 'previous', 'h3'), 'display-none');
		}
	}

	// do we have to notify the document selector opener?
	if(window.opener != null && typeof window.opener.selectedDocument != 'undefined')
	{
		try
		{
			window.opener.selectedDocument(documentid, window);
		}
		catch(e)
		{
			;
		}
	}

	var form = getDocumentSelector( documentid );
	if(!form)
		return;

	var p = new DOMQuery("div.discussion-content").get(0);
	if(!p)
		return;

	p.insertBefore(form, p.childNodes[0]);
};

function copy2rml(e)
{
	e.preventDefault();

	if (typeof window.opener == 'undefined' || !window.opener.document)
		return false;

	// Are we called from a FCKEditor image-selector?
	if(typeof window.opener.SetUrl != 'undefined')
	{
		window.opener.SetUrl(board_script_url +
				'/../download.php/download_document/' +
				new DOMQuery('input[name="documentid"]', this).get(0).value +
				'/' + new DOMQuery('input[name="key"]', this).get(0).value +
				'/' +
				new DOMQuery('select[name="format"]', this).get(0).value
		);
		window.close();
		return false;
	}

	/* find out which radio button was selected */
	var items = new DOMQuery('input[name="as"]', this), data_as;
	for(var i = 0, item; (item = items.get(i)); i++)
	{
		if(item.type == 'hidden' || item.checked)
		{
			data_as = item;
			break;
		}
	}

	if(!data_as)
		return false;

	var rml = '';
	switch( data_as.value )
	{
		case 'image':
			var float_select = new DOMQuery('select[name="float"]', this);
			var format_select = new DOMQuery('select[name="format"]', this);
			var link_input = new DOMQuery('input[name="link"]', this);

			var link = '0';

			var float = '', format='';

			if (float_select.length > 0)
				float = float_select.get(0).options[ float_select.get(0).selectedIndex ].value;

			if (format_select.length > 0)
				format = format_select.get(0).options[ format_select.get(0).selectedIndex ].value;

			if ( link_input.length > 0)
			{
				link = link_input.get(0).checked ? '1' : '0';
			}

			rml = '[doclib=' +
					new DOMQuery('input[name="documentid"]', this).get(0).value +
					',' +
					new DOMQuery('input[name="key"]', this).get(0).value +
					',' +
					new DOMQuery('input[name="libraryid"]', this).get(0).value +
					',' +
					format +
					',' +
					link +
					(float != "" ? ("," + float) : "" ) +
					']\n';
		break;
		case 'text':
			rml = '[doclib=' +
					new DOMQuery('input[name="documentid"]', this).get(0).value +
					',' +
					new DOMQuery('input[name="key"]', this).get(0).value +
					',' +
					new DOMQuery('input[name="libraryid"]', this).get(0).value +
					',,0]' +
					new DOMQuery('input[name="filename"]', this).get(0).value +
					'[/]\n';
		break;
		default:
			return;
	}
	window.opener.setCurrentTextarea(window);
	window.opener.putStr(rml);
	window.opener.focus();
	window.close();

	return false;
};
function documentSelector()
{
	var documentSelectors = new DOMQuery('div.document-selector'), input, image;

	for (var i = 0, container; (container=documentSelectors.get(i)); i++)
	{
		input = new DOMQuery('input[type=hidden]', container).get(0);
		image = new DOMQuery('img', container).get(0);

		container.appendChild(createDOMNode('ul', {}, []));

		if (!image || image.src != board_script_url + '/')
			documentSelectorActions(container);
		else if(image)
			image.parentNode.removeChild(image);

		addEventToTargets(null, 'mouseup', _documentSelector, 'li.select-document a');
		addEventToTargets(null, 'click', _documentSelector, 'li.select-document a');
	}
};

function _documentSelector(e)
{
	var li = getSiblingNode(this, 'up', 'li');
	var container = getSiblingNode(li, 'up', 'div');
	var input = new DOMQuery('input[type=hidden]', container).get(0);
	var image = new DOMQuery('img', container).get(0);

	switch(li.className)
	{
		case 'add-document':
			documentWindow = window.open(
				board_script_url + '/insert_document?data[small]=1',
				'DocumentLibrary',
				'width=900, height=500, resizable=yes, scrollbars=yes'
			);
			window.lastUsedDocumentSelectorContainer = container;

			e.preventDefault();
		break;

		case 'select-document':
			documentWindow = window.open(
				board_script_url + '/list_documents?data[small]=1',
				'DocumentLibrary',
				'width=900, height=500, resizable=yes, scrollbars=yes'
			);
			window.lastUsedDocumentSelectorContainer = container;

			e.preventDefault();
		break;

		case 'delete-document':
			input.value = '';
			image.parentNode.removeChild(image);
			documentSelectorActions(container);

			/* Re-attach contentInLayer event after recreating selectorActions */
			contentInLayer(new DOMQuery('li.add-document a', container));

			e.preventDefault();
		break;
	}
};

function documentSelectorActions(container)
{
	var ul = new DOMQuery('ul', container).get(0);
	var input = new DOMQuery('input[type=hidden]', container).get(0);
	var image = new DOMQuery('img', container).get(0);

	if(!ul)
		return;

	while(ul.firstChild)
		ul.removeChild(ul.firstChild);

	if (image && image.getAttribute('src', 2) != '')
	{
		var editLink = createDOMNode(
			'li',
			{ 'class' : 'edit-document' },
			[
				createDOMNode(
					'a',
					{
						'href' : board_script_url + '/edit_document/' + input.value.split('/').shift(),
						'target' : '_blank',
						'event' : [ 'click', _documentSelector ]
					},
					[ getText('publish', 'edit_document') ]
				)
			]
		);

		var deleteLink = createDOMNode(
			'li',
			{ 'class' : 'delete-document' },
			[
				createDOMNode(
					'a',
					{
						'href' : 'javascript:void(0)',
						'class' : 'clickable',
						'event' : [ 'click', _documentSelector ]
					},
					[ getText('publish', 'remove_document') ]
				)
			]
		);

		ul.appendChild(editLink);
		ul.appendChild(deleteLink);
	}
	else
	{
		var addLink = createDOMNode(
			'li',
			{ 'class' : 'add-document' },
			[
				createDOMNode(
					'a',
					{
						'href' : board_script_url + '/insert_document',
						'rel' : 'layer[add-document]',
						'class' : input.name.replace(/[^a-z0-9]+/g, '_'),
						'event' : [ 'click', function() {
							var dsc = getSiblingNode(getSiblingNode(this, 'up', 'li'), 'up', 'div');
							window.lastUsedDocumentSelectorContainer = dsc;
						}]
					},
					[ getText('publish', 'upload_document') ]
				)
			]
		);
		var selectLink = createDOMNode(
			'li',
			{ 'class' : 'select-document' },
			[
				createDOMNode(
					'a',
					{
						'href' : board_script_url + '/list_documents',
						'target' : '_blank',
						'event' : [ 'click', _documentSelector ]
					},
					[ getText('publish', 'add_document') ]
				)
			]
		);

		ul.appendChild(addLink);
		ul.appendChild(selectLink);
	}
};

function selectedDocument(document_id, popup_win)
{
	var document_hash = popup_win.raw_documents[document_id][0].split('/');

	document_hash.pop();
	document_hash = document_hash.pop();

	var container = window.lastUsedDocumentSelectorContainer;
	var ul = new DOMQuery('ul', container).get(0);
	var input = new DOMQuery('input[type=hidden]', container).get(0);
	var image = new DOMQuery('img', container).get(0);

	if(!image)
	{
		image = createDOMNode(
			'img',
			{
				'src' : board_script_url + '/download_document/' + document_id +'/'+ document_hash +'/document'
			},
			[ ]
		);

		ul.parentNode.insertBefore(image, ul);
	}
	else
		image.src = board_script_url + '/download_document/' + document_id +'/'+ document_hash +'/document';

	input.value = document_id +'/'+ document_hash;
	popup_win.close();

	documentSelectorActions(container);
};

var _contentInLayerCallbackOriginal = _contentInLayerCallback;
_contentInLayerCallback = function(invoker, id, rel)
{
	if(rel && rel.length) /* jaey, it's a layer */
	{
		switch (rel[1]) {
			case 'add-document':
				return {
					specificElement : 'form.primary-input'
				};
		}
	}

	return _contentInLayerCallbackOriginal.apply(this, arguments);
};
/*
	cssQuery, version 2.0 (2005/05/23)
	Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
	License: http://creativecommons.org/licenses/LGPL/2.1/
*/
if( DOMQuery.prototype.resultType == 'cssQuery' )
{
	eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p;}('8 C=6(){8 1H="2.0 (2S)";8 $2B=/\\s*,\\s*/;8 C=6($d,$$b){2T{8 $m=[];8 $1S=c.2Q.2A&&!$$b;8 $1K=($$b)?($$b.2R==2E)?$$b:[$$b]:[X];8 $$E=1o($d).22($2B),i;x(i=0;i<$$E.y;i++){$d=1C($$E[i]);9(16&&$d.S(0,3).2w("")==" *#"){$d=$d.S(2);$$b=26([],$1K,$d[1])}1I $$b=$1K;8 j=0,$U,$F,$c,$1a="";I(j<$d.y){$U=$d[j++];$F=$d[j++];$1a+=$U+$F;$c="";9($d[j]=="("){I($d[j++]!=")")$c+=$d[j];$c=$c.S(0,-1);$1a+="("+$c+")"}$$b=($1S&&19[$1a])?19[$1a]:2u($$b,$U,$F,$c);9($1S)19[$1a]=$$b}$m=$m.2N($$b)}1Y C.1m;7 $m}2P($1m){C.1m=$1m;7[]}};C.2i=6(){7"6 C() {\\n  [1H "+1H+"]\\n}"};8 19={};C.2A=P;C.33=6($d){9($d){$d=1C($d).2w("");1Y 19[$d]}1I 19={}};8 1P={};8 1X=P;C.1s=6($1b,$1q){9(1X)1n("$1q="+1i($1q));1P[$1b]=12 $1q()};C.30=6($Y){7 $Y?1n($Y):z};8 E={};8 v={};8 Z=[];E[" "]=6($l,$b,$q,$p){8 $5,i,j;x(i=0;i<$b.y;i++){8 $1r=1f($b[i],$q,$p);x(j=0;($5=$1r[j]);j++){9(O($5)&&1p($5,$p))$l.D($5)}}};E["#"]=6($l,$b,$H){8 $5,j;x(j=0;($5=$b[j]);j++)9($5.H==$H)$l.D($5)};E["."]=6($l,$b,$17){$17=12 1R("(^|\\\\s)"+$17+"(\\\\s|$)");8 $5,i;x(i=0;($5=$b[i]);i++)9($17.h($5.17))$l.D($5)};E[":"]=6($l,$b,$2y,$c){8 $h=v[$2y],$5,i;9($h)x(i=0;($5=$b[i]);i++)9($h($5,$c))$l.D($5)};v["2X"]=6($5){8 $X=V($5);9($X.1G)x(8 i=0;i<$X.1G.y;i++){9($X.1G[i]==$5)7 R}};v["35"]=6($5){};8 O=6($5){7($5&&$5.1Z==1&&$5.q!="!")?$5:2q};8 1l=6($5){I($5&&($5=$5.32)&&!O($5))2G;7 $5};8 K=6($5){I($5&&($5=$5.2U)&&!O($5))2G;7 $5};8 1L=6($5){7 O($5.2b)||K($5.2b)};8 2L=6($5){7 O($5.29)||1l($5.29)};8 15=6($5){8 $15=[];$5=1L($5);I($5){$15.D($5);$5=K($5)}7 $15};8 16=R;8 2z=6($5){7 V($5).31=="2V 2Y"};8 V=6($5){7 $5.2Z||$5.X};8 1f=6($5,$q){7($q=="*"&&$5.1J)?$5.1J:$5.1f($q)};8 1t=6($5,$q,$p){9($q=="*")7 O($5);9(!1p($5,$p))7 P;7 $5.q.28()==$q.28()};8 1p=6($5,$p){7!$p||($p=="*")||($5.2W==$p)};8 1V=6($5){7 $5.2K};6 26($l,$b,H){8 $m,i,j;x(i=0;i<$b.y;i++){9($m=$b[i].1J.34(H)){9($m.y==2q)$l.D($m);1I x(j=0;j<$m.y;j++)$l.D($m[j])}}7 $l};8 $1F=/\\|/;6 2u($$b,$U,$F,$c){9($1F.h($F)){$F=$F.22($1F);$c=$F[0];$F=$F[1]}8 $l=[];9(E[$U]){E[$U]($l,$$b,$F,$c)}7 $l};8 $2m=/^[^\\s>+~]/;8 $$2h=/[\\s#.:>+~()@]|[^\\s#.:>+~()@]+/g;6 1C($d){9($2m.h($d))$d=" "+$d;7 $d.m($$2h)||[]};8 $2g=/\\s*([\\s>+~(),]|^|$)\\s*/g;8 $2f=/([\\s>+~,]|[^(]\\+|^)([#.:@])/g;8 1o=6($d){7 $d.G($2g,"$1").G($2f,"$1*$2")};8 1Q={2i:6(){7"\'"},m:/^(\'[^\']*\')|("[^"]*")$/,h:6($u){7 z.m.h($u)},25:6($u){7 z.h($u)?$u:z+$u+z},2k:6($u){7 z.h($u)?$u.S(1,-1):$u}};8 1O=6($14){7 1Q.2k($14)};8 $2j=/([\\/()[\\]?{}|*+-])/g;6 10($u){7 $u.G($2j,"\\\\$1")};C.1s("1x-2a",6(){E[">"]=6($l,$b,$q,$p){8 $5,i,j;x(i=0;i<$b.y;i++){8 $1r=15($b[i]);x(j=0;($5=$1r[j]);j++)9(1t($5,$q,$p))$l.D($5)}};E["+"]=6($l,$b,$q,$p){x(8 i=0;i<$b.y;i++){8 $5=K($b[i]);9($5&&1t($5,$q,$p))$l.D($5)}};E["@"]=6($l,$b,$2l){8 $h=Z[$2l].h;8 $5,i;x(i=0;($5=$b[i]);i++)9($h($5))$l.D($5)};v["3s-1e"]=6($5){7!1l($5)};v["1B"]=6($5,$Y){$Y=12 1R("^"+$Y,"i");I($5&&!$5.1j("1B"))$5=$5.24;7 $5&&$Y.h($5.1j("1B"))};8 k={};k.1E="@";k.N={};k.m=/\\[([\\w-]+)\\s*(\\W?=)?\\s*([^\\]]*)\\]/g;k.G=6($m,$t,$2s,$A){8 $1y=k.1E+$m;9(!Z[$1y]){$t=k.2t($t,$2s||"",$A||"");Z[$1y]=$t;Z.D($t)}7 Z[$1y].H};k.2e=6($d){7 $d.G(z.m,z.G)};k.2t=6($1D,$h,$A){8 $1g={};$1g.H=k.1E+Z.y;$1g.1b=$1D;$h=z.N[$h];$h=$h?$h(k.1j($1D),1O($A)):P;$1g.h=12 2r("e","7 "+$h);7 $1g};k.1j=6($1b){1w($1b.3y()){B"H":7"e.H";B"3v":7"e.17";B"x":7"e.3x";B"27":9(16){7"1i((e.3n.m(/27=\\"?([^\\\\s\\"]*)\\"?/)||[])[1]||\'\')"}}7"e.1j(\'"+$1b+"\')"};z.k=k;k.N[""]=6($t){7 $t};k.N["="]=6($t,$A){7 $t+"=="+1Q.25($A)};k.N["~="]=6($t,$A){7"/(^|\\\\s)"+10($A)+"(\\\\s|$)/.h("+$t+")"};k.N["|="]=6($t,$A){7"/^"+10($A)+"(-|$)/.h("+$t+")"};8 2d=1o;1o=6($d){7 2d(k.2e($d))}});C.1s("1x-37",6(){8 1A=1P["1x-2a"];9(!1A)7;E["~"]=6($l,$b,$q,$p){8 $5,i;x(i=0;($5=$b[i]);i++){I($5=K($5)){9(1t($5,$q,$p))$l.D($5)}}};v["38"]=6($5,$14){$14=12 1R(10(1O($14)));7 $14.h(1V($5))};v["3k"]=6($5){7 $5==V($5).2J};v["3j"]=6($5){8 $M,i;x(i=0;($M=$5.2H[i]);i++){9(O($M)||$M.1Z==3)7 P}7 R};v["2v-1e"]=6($5){7!K($5)};v["3m-1e"]=6($5){$5=$5.24;7 1L($5)==2L($5)};v["3l"]=6($5,$d){8 $1N=C($d,V($5));x(8 i=0;i<$1N.y;i++){9($1N[i]==$5)7 P}7 R};v["2x-1e"]=6($5,$c){7 1z($5,$c,1l)};v["2x-2v-1e"]=6($5,$c){7 1z($5,$c,K)};v["3i"]=6($5){7 $5.H==3c.3b.S(1)};v["2F"]=6($5){7 $5.2F};v["3A"]=6($5){7 $5.1M===P};v["1M"]=6($5){7 $5.1M};v["2D"]=6($5){7 $5.2D};8 k=1A.k;k.N["^="]=6($t,$A){7"/^"+10($A)+"/.h("+$t+")"};k.N["$="]=6($t,$A){7"/"+10($A)+"$/.h("+$t+")"};k.N["*="]=6($t,$A){7"/"+10($A)+"/.h("+$t+")"};6 1z($5,$c,$1u){1w($c){B"n":7 R;B"3r":$c="2n";Q;B"3p":$c="2n+1"}8 $$23=15($5.24);6 1T($13){8 $13=($1u==K)?$$23.y-$13:$13-1;7 $$23[$13]==$5};9(!1d($c))7 1T($c);$c=$c.22("n");8 $T=2C($c[0]);8 $L=2C($c[1]);9((1d($T)||$T==1)&&$L==0)7 R;9($T==0&&!1d($L))7 1T($L);9(1d($L))$L=0;8 $1h=1;I($5=$1u($5))$1h++;9(1d($T)||$T==1)7($1u==K)?($1h<=$L):($L>=$1h);7($1h%$T)==$L}});C.1s("1x-3t",6(){16=1n("P;/*@3o@9(@\\3q)16=R@39@*/");9(!16){1f=6($5,$q,$p){7 $p?$5.3h("*",$q):$5.1f($q)};1p=6($5,$p){7!$p||($p=="*")||($5.3f==$p)};2z=X.2I?6($5){7/3g/i.h(V($5).2I)}:6($5){7 V($5).2J.q!="3e"};1V=6($5){7 $5.1k||$5.2K||20($5)};6 20($5){8 $1k="",$M,i;x(i=0;($M=$5.2H[i]);i++){1w($M.1Z){B 11:B 1:$1k+=20($M);Q;B 3:$1k+=$M.36;Q}}7 $1k}}});12 6(){8 $$18=6($6,$2c,$c){$6.18($2c,$c)};9(\'\'.G(/^/,1i)){8 2o=1i.1U.G;8 2p=6($1v,$1c){8 $m,$1W="",$u=z;I($u&&($m=$1v.3d($u))){$1W+=$u.S(0,$m.13)+$$18($1c,z,$m);$u=$u.S($m.3a)}7 $1W+$u};1i.1U.G=6($1v,$1c){z.G=(3w $1c=="6")?2p:2o;7 z.G($1v,$1c)}}9(!2r.18){8 J="18-"+3z(12 3u);$$18=6(f,o,a){8 r;o[J]=f;1w(a.y){B 0:r=o[J]();Q;B 1:r=o[J](a[0]);Q;B 2:r=o[J](a[0],a[1]);Q;B 3:r=o[J](a[0],a[1],a[2]);Q;B 4:r=o[J](a[0],a[1],a[2],a[3]);Q;2M:8 21=[],i=a.y-1;2O 21[i]="a["+i+"]";I(i--);1n("r=o[J]("+21+")")}1Y o[J];7 r}}9(![].D)2E.1U.D=6(){x(8 i=0;i<c.y;i++){z[z.y]=c[i]}7 z.y}};1X=R;7 C}();',62,223,'|||||element|function|return|var|if||from|arguments|selector||||test|||AttributeSelector|results|match|||namespace|tagName|||attribute|string|pseudoClasses||for|length|this|value|case|cssQuery|push|selectors|filter|replace|id|while|APPLY|nextElementSibling|step|node|tests|thisElement|false|break|true|slice|multiplier|token|getDocument||document|code|attributeSelectors|regEscape||new|index|text|childElements|isMSIE|className|apply|cache|cacheSelector|name|replacement|isNaN|child|getElementsByTagName|attributeSelector|count|String|getAttribute|textContent|previousElementSibling|error|eval|parseSelector|compareNamespace|script|subset|addModule|compareTagName|traverse|expression|switch|css|key|nthChild|css2|lang|_toStream|propertyName|PREFIX|NAMESPACE|links|version|else|all|base|firstElementChild|disabled|negated|getText|modules|Quote|RegExp|useCache|_checkIndex|prototype|getTextContent|newString|loaded|delete|nodeType|_getTextContent|aa|split|children|parentNode|add|_msie_selectById|href|toUpperCase|lastChild|level2|firstChild|object|_parseSelector|parse|IMPLIED_ALL|WHITESPACE|STREAM|toString|ESCAPE|remove|attributeSelectorID|STANDARD_SELECT||_stringReplace|_functionReplace|null|Function|compare|create|select|last|join|nth|pseudoClass|isXML|caching|COMMA|parseInt|indeterminate|Array|checked|continue|childNodes|contentType|documentElement|innerText|lastElementChild|default|concat|do|catch|callee|constructor|beta|try|nextSibling|XML|scopeName|link|Document|ownerDocument|valueOf|mimeType|previousSibling|clearCache|item|visited|nodeValue|level3|contains|end|lastIndex|hash|location|exec|HTML|prefix|xml|getElementsByTagNameNS|target|empty|root|not|only|outerHTML|cc_on|odd|x5fwin32|even|first|standard|Date|class|typeof|htmlFor|toLowerCase|Number|enabled'.split('|'),0,{}));
}
var texts = [];

texts['doclib'] = [];
texts['doclib']['insert_as']			= 'Invoegen als';
texts['doclib']['insert_as_image']		= 'afbeelding';
texts['doclib']['insert_as_text']		= 'tekst';
texts['doclib']['insert_as_link']		= 'Link';
texts['doclib']['insert_as_thumb']		= 'Link thumbnail naar origineel';
texts['doclib']['format']				= 'Formaat';
texts['doclib']['original']				= 'Origineel';
texts['doclib']['outline']				= 'Uitlijning';
texts['doclib']['none']					= 'Geen';
texts['doclib']['left']					= 'Links';
texts['doclib']['right']				= 'Rechts';
texts['doclib']['insert']				= 'Invoegen';
texts['doclib']['insert_image']			= 'Afbeelding invoegen';
texts['doclib']['not_implemented']		= 'Nog niet mogelijk';

texts['forms'] = [];
texts['forms']['marked_fields']			= 'Velden gemarkeerd met een ';
texts['forms']['required']				= ' zijn verplicht';
texts['forms']['hide_advanced']			= 'Uitgebreide mogelijkheden verbergen';
texts['forms']['show_advanced']			= 'Uitgebreide mogelijkheden weergeven';
texts['forms']['max_chars']				= 'Je mag hier maximaal %s karakters gebruiken';
texts['forms']['name_too_short']		= 'Deze gebruikersnaam is te kort';
texts['forms']['email_incorrect']		= 'Dit emailadres is incorrect';
texts['forms']['url_incorrect']			= 'Deze URL is incorrect';
texts['forms']['numeric_only']			= 'Dit veld kan alleen getallen bevatten';
texts['forms']['required_field']		= 'Dit veld is verplicht';
texts['forms']['required_field.query_input']= 'Dit veld is verplicht bij sortering op relevantie';
texts['forms']['password_no_match']		= 'De ingevoerde wachtwoorden komen niet overeen.';
texts['forms']['username_taken']		= 'Deze gebruikersnaam is al in gebruik.';
texts['forms']['invalid_domain']		= 'Dit domein mag niet op dit forum gebruikt worden. Kies svp een ander email-adres.';
texts['forms']['email_taken']			= 'Dit email-adres is al in gebruik.';
texts['forms']['select_all_rows']		= 'Selecteer alle rijen';
texts['forms']['select_messages']		= 'Klik op één of meerdere berichten om deze te selecteren. Klik vervolgens op Verstuur om ze daadwerkelijk te verwijderen.';
texts['forms']['username']				= 'Gebruikersnaam';
texts['forms']['password']				= 'Wachtwoord';
texts['forms']['sofinummer_mismatch']	= 'Dit getal voldoet niet aan de 11-proef, sofinummer ongeldig.';
texts['forms']['length_not_9']			= 'Dit veld moet precies 9 karakters bevatten.';
texts['forms']['show_advanced_options']	= 'Toon uitgebreide opties.';
texts['forms']['hide_advanced_options']	= 'Verberg uitgebreide opties.';
texts['forms']['keyword_too_long']		= 'Sleutelwoord `%s` is te lang, gebruik maximaal 50 karakters';
texts['forms']['keywords_illegal_character']	= 'Sleutelwoord `%s` bevat ongeldige karakters; gebruik enkel a-z, 0-9 en - of _';
texts['forms']['max_entries_reached']	= 'Je mag maximaal %s stuks opgeven';
texts['forms']['cant_send_to_yourself']	= 'Je kan geen prive-bericht naar jezelf sturen';
texts['forms']['filename_too_long']		= 'De bestandsnaam overschrijdt de limiet van 60 karakters';
texts['forms']['filename_invalid']		= 'De bestandsnaam bevat ongeldige karakters';
texts['forms']['extension_invalid']		= 'De extensie is ongeldig';

texts['imagewizard'] = [];
texts['imagewizard']['sizes_error']		= 'error :: original sizes of sourcefile not found';

texts['normal'] = [];
texts['normal']['disabled_option']		= 'Deze optie is niet mogelijk.';
texts['normal']['more']					= 'Meer...';
texts['normal']['search_webkit']		= 'Zoek binnen dit forum...';
texts['normal']['back']					= 'Terug';

texts['xmlhttp'] = [];
texts['xmlhttp']['close']				= 'Sluit';
texts['xmlhttp']['form_already_exists']	= 'Er is al een formulier op het scherm voor.\nWilt u deze vervangen?';

texts['extra'] = [];
texts['extra']['searchPopup']			= 'Zoek...';
texts['extra']['close_and_submit']		= 'Sluit & verstuur';
texts['extra']['accesskey_indicator']	= '(%s)';
texts['extra']['click_to_enlarge']		= ' - klik om te vergroten';
texts['extra']['enter_page_number']		= 'Geef een paginanummer tussen 1 en %s';
texts['extra']['page_number_incorrect']	= 'U heeft geen geldig paginanummer opgegeven.';
texts['extra']['show_gallery']			= 'Toon alle afbeeldingen in dit onderwerp';
texts['extra']['show_gallery_header']	= 'Alle afbeeldingen in dit onderwerp';

texts['toolbar'] = [];
texts['toolbar']['enter_img_url']		= 'Geef de URL van de afbeelding op:';
texts['toolbar']['enter_url']			= 'Geef de URL op:';
texts['toolbar']['enter_title']			= 'Geef optioneel een titel:';

texts['toolbar']['hline'] = '';
texts['toolbar']['bold'] = 'Maak tekst vetgedrukt';
texts['toolbar']['italic'] = 'Maak tekst schuingedrukt';
texts['toolbar']['underline'] = 'Maak tekst onderstreept';
texts['toolbar']['strike'] = 'Streep tekst door';
texts['toolbar']['sup'] = 'Plaats tekst hoger';
texts['toolbar']['sub'] = 'Plaats tekst lager';
texts['toolbar']['align_left'] = 'Lijn tekst links uit';
texts['toolbar']['align_center'] = 'Lijn tekst in het midden uit';
texts['toolbar']['align_right'] = 'Lijn tekst rechts uit';
texts['toolbar']['align_justify'] = 'Vul tekst uit';
texts['toolbar']['list_bullet'] = 'Maak een lijst';
texts['toolbar']['list_num'] = 'Maak een genummerde lijst';
texts['toolbar']['color_bg'] = 'Wijzig de achtergrondkleur';
texts['toolbar']['color_fg'] = 'Wijzig de tekstkleur';
texts['toolbar']['link'] = 'Voeg een link toe';
texts['toolbar']['image'] = 'Voeg een afbeelding toe';
texts['toolbar']['table'] = 'Voeg een tabel toe';
texts['toolbar']['hr'] = 'Voeg een horizontale streep toe';
texts['toolbar']['maximize'] = 'Vergroot het invoerveld';
texts['toolbar']['documentlibrary'] = 'Open de documentenbibliotheek';
texts['toolbar']['smileys'] = 'Kies een smiley';
texts['toolbar']['youtube'] = 'Plaats YouTube filmpje';
texts['toolbar']['youtube_link'] = 'Link naar YouTube filmpje';

texts['calendar'] = [];
texts['calendar']['calendarevent'] = 'Afspraken';
texts['calendar']['calendareventallday'] = 'Dagafspraken';
texts['calendar']['topicstart'] = 'Onderwerpen';
texts['calendar']['topicevent'] = 'Topicstarts';
texts['calendar']['birthday'] = 'Verjaardagen';

texts['colorpicker'] = [];
texts['colorpicker']['select_color'] = 'Gebruik de geselecteerde kleur';
texts['publish'] = [];
texts['publish']['edit_document'] 			= 'Wijzig bestand';
texts['publish']['remove_document'] 		= 'Geen bestand';
texts['publish']['upload_document']			= 'Upload bestand';
texts['publish']['add_document']			= 'Kies bestand';
/*! SWFObject v2.1 <http://code.google.com/p/swfobject/>
	Copyright (c) 2007-2008 Geoff Stearns, Michael Williams, and Bobby van der Sluis
	This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/

var swfobject = function() {
	
	var UNDEF = "undefined",
		OBJECT = "object",
		SHOCKWAVE_FLASH = "Shockwave Flash",
		SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
		FLASH_MIME_TYPE = "application/x-shockwave-flash",
		EXPRESS_INSTALL_ID = "SWFObjectExprInst",
		
		win = window,
		doc = document,
		nav = navigator,
		
		domLoadFnArr = [],
		regObjArr = [],
		objIdArr = [],
		listenersArr = [],
		script,
		timer = null,
		storedAltContent = null,
		storedAltContentId = null,
		isDomLoaded = false,
		isExpressInstallActive = false;
	
	/* Centralized function for browser feature detection
		- Proprietary feature detection (conditional compiling) is used to detect Internet Explorer's features
		- User agent string detection is only used when no alternative is possible
		- Is executed directly for optimal performance
	*/	
	var ua = function() {
		var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
			playerVersion = [0,0,0],
			d = null;
		if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
			d = nav.plugins[SHOCKWAVE_FLASH].description;
			if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
				d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
				playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
				playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
				playerVersion[2] = /r/.test(d) ? parseInt(d.replace(/^.*r(.*)$/, "$1"), 10) : 0;
			}
		}
		else if (typeof win.ActiveXObject != UNDEF) {
			var a = null, fp6Crash = false;
			try {
				a = new ActiveXObject(SHOCKWAVE_FLASH_AX + ".7");
			}
			catch(e) {
				try { 
					a = new ActiveXObject(SHOCKWAVE_FLASH_AX + ".6");
					playerVersion = [6,0,21];
					a.AllowScriptAccess = "always";	 // Introduced in fp6.0.47
				}
				catch(e) {
					if (playerVersion[0] == 6) {
						fp6Crash = true;
					}
				}
				if (!fp6Crash) {
					try {
						a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
					}
					catch(e) {}
				}
			}
			if (!fp6Crash && a) { // a will return null when ActiveX is disabled
				try {
					d = a.GetVariable("$version");	// Will crash fp6.0.21/23/29
					if (d) {
						d = d.split(" ")[1].split(",");
						playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
					}
				}
				catch(e) {}
			}
		}
		var u = nav.userAgent.toLowerCase(),
			p = nav.platform.toLowerCase(),
			webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
			ie = false,
			windows = p ? /win/.test(p) : /win/.test(u),
			mac = p ? /mac/.test(p) : /mac/.test(u);
		/*@cc_on
			ie = true;
			@if (@_win32)
				windows = true;
			@elif (@_mac)
				mac = true;
			@end
		@*/
		return { w3cdom:w3cdom, pv:playerVersion, webkit:webkit, ie:ie, win:windows, mac:mac };
	}();

	/* Cross-browser onDomLoad
		- Based on Dean Edwards' solution: http://dean.edwards.name/weblog/2006/06/again/
		- Will fire an event as soon as the DOM of a page is loaded (supported by Gecko based browsers - like Firefox -, IE, Opera9+, Safari)
	*/ 
	var onDomLoad = function() {
		if (!ua.w3cdom) {
			return;
		}
		addDomLoadEvent(main);
		if (ua.ie && ua.win) {
			try {	 // Avoid a possible Operation Aborted error
				doc.write("<scr" + "ipt id=__ie_ondomload defer=true src=//:></scr" + "ipt>"); // String is split into pieces to avoid Norton AV to add code that can cause errors 
				script = getElementById("__ie_ondomload");
				if (script) {
					addListener(script, "onreadystatechange", checkReadyState);
				}
			}
			catch(e) {}
		}
		if (ua.webkit && typeof doc.readyState != UNDEF) {
			timer = setInterval(function() { if (/loaded|complete/.test(doc.readyState)) { callDomLoadFunctions(); }}, 10);
		}
		if (typeof doc.addEventListener != UNDEF) {
			doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, null);
		}
		addLoadEvent(callDomLoadFunctions);
	}();
	
	function checkReadyState() {
		if (script.readyState == "complete") {
			script.parentNode.removeChild(script);
			callDomLoadFunctions();
		}
	}
	
	function callDomLoadFunctions() {
		if (isDomLoaded) {
			return;
		}
		if (ua.ie && ua.win) { // Test if we can really add elements to the DOM; we don't want to fire it too early
			var s = createElement("span");
			try { // Avoid a possible Operation Aborted error
				var t = doc.getElementsByTagName("body")[0].appendChild(s);
				t.parentNode.removeChild(t);
			}
			catch (e) {
				return;
			}
		}
		isDomLoaded = true;
		if (timer) {
			clearInterval(timer);
			timer = null;
		}
		var dl = domLoadFnArr.length;
		for (var i = 0; i < dl; i++) {
			domLoadFnArr[i]();
		}
	}
	
	function addDomLoadEvent(fn) {
		if (isDomLoaded) {
			fn();
		}
		else { 
			domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+
		}
	}
	
	/* Cross-browser onload
		- Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/
		- Will fire an event as soon as a web page including all of its assets are loaded 
	 */
	function addLoadEvent(fn) {
		if (typeof win.addEventListener != UNDEF) {
			win.addEventListener("load", fn, false);
		}
		else if (typeof doc.addEventListener != UNDEF) {
			doc.addEventListener("load", fn, false);
		}
		else if (typeof win.attachEvent != UNDEF) {
			addListener(win, "onload", fn);
		}
		else if (typeof win.onload == "function") {
			var fnOld = win.onload;
			win.onload = function() {
				fnOld();
				fn();
			};
		}
		else {
			win.onload = fn;
		}
	}
	
	/* Main function
		- Will preferably execute onDomLoad, otherwise onload (as a fallback)
	*/
	function main() { // Static publishing only
		var rl = regObjArr.length;
		for (var i = 0; i < rl; i++) { // For each registered object element
			var id = regObjArr[i].id;
			if (ua.pv[0] > 0) {
				var obj = getElementById(id);
				if (obj) {
					regObjArr[i].width = obj.getAttribute("width") ? obj.getAttribute("width") : "0";
					regObjArr[i].height = obj.getAttribute("height") ? obj.getAttribute("height") : "0";
					if (hasPlayerVersion(regObjArr[i].swfVersion)) { // Flash plug-in version >= Flash content version: Houston, we have a match!
						if (ua.webkit && ua.webkit < 312) { // Older webkit engines ignore the object element's nested param elements
							fixParams(obj);
						}
						setVisibility(id, true);
					}
					else if (regObjArr[i].expressInstall && !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac)) { // Show the Adobe Express Install dialog if set by the web page author and if supported (fp6.0.65+ on Win/Mac OS only)
						showExpressInstall(regObjArr[i]);
					}
					else { // Flash plug-in and Flash content version mismatch: display alternative content instead of Flash content
						displayAltContent(obj);
					}
				}
			}
			else {	// If no fp is installed, we let the object element do its job (show alternative content)
				setVisibility(id, true);
			}
		}
	}
	
	/* Fix nested param elements, which are ignored by older webkit engines
		- This includes Safari up to and including version 1.2.2 on Mac OS 10.3
		- Fall back to the proprietary embed element
	*/
	function fixParams(obj) {
		var nestedObj = obj.getElementsByTagName(OBJECT)[0];
		if (nestedObj) {
			var e = createElement("embed"), a = nestedObj.attributes;
			if (a) {
				var al = a.length;
				for (var i = 0; i < al; i++) {
					if (a[i].nodeName == "DATA") {
						e.setAttribute("src", a[i].nodeValue);
					}
					else {
						e.setAttribute(a[i].nodeName, a[i].nodeValue);
					}
				}
			}
			var c = nestedObj.childNodes;
			if (c) {
				var cl = c.length;
				for (var j = 0; j < cl; j++) {
					if (c[j].nodeType == 1 && c[j].nodeName == "PARAM") {
						e.setAttribute(c[j].getAttribute("name"), c[j].getAttribute("value"));
					}
				}
			}
			obj.parentNode.replaceChild(e, obj);
		}
	}
	
	/* Show the Adobe Express Install dialog
		- Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75
	*/
	function showExpressInstall(regObj) {
		isExpressInstallActive = true;
		var obj = getElementById(regObj.id);
		if (obj) {
			if (regObj.altContentId) {
				var ac = getElementById(regObj.altContentId);
				if (ac) {
					storedAltContent = ac;
					storedAltContentId = regObj.altContentId;
				}
			}
			else {
				storedAltContent = abstractAltContent(obj);
			}
			if (!(/%$/.test(regObj.width)) && parseInt(regObj.width, 10) < 310) {
				regObj.width = "310";
			}
			if (!(/%$/.test(regObj.height)) && parseInt(regObj.height, 10) < 137) {
				regObj.height = "137";
			}
			doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
			var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
				dt = doc.title,
				fv = "MMredirectURL=" + win.location + "&MMplayerType=" + pt + "&MMdoctitle=" + dt,
				replaceId = regObj.id;
			// For IE when a SWF is loading (AND: not available in cache) wait for the onload event to fire to remove the original object element
			// In IE you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
			if (ua.ie && ua.win && obj.readyState != 4) {
				var newObj = createElement("div");
				replaceId += "SWFObjectNew";
				newObj.setAttribute("id", replaceId);
				obj.parentNode.insertBefore(newObj, obj); // Insert placeholder div that will be replaced by the object element that loads expressinstall.swf
				obj.style.display = "none";
				var fn = function() {
					obj.parentNode.removeChild(obj);
				};
				addListener(win, "onload", fn);
			}
			createSWF({ data:regObj.expressInstall, id:EXPRESS_INSTALL_ID, width:regObj.width, height:regObj.height }, { flashvars:fv }, replaceId);
		}
	}
	
	/* Functions to abstract and display alternative content
	*/
	function displayAltContent(obj) {
		if (ua.ie && ua.win && obj.readyState != 4) {
			// For IE when a SWF is loading (AND: not available in cache) wait for the onload event to fire to remove the original object element
			// In IE you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
			var el = createElement("div");
			obj.parentNode.insertBefore(el, obj); // Insert placeholder div that will be replaced by the alternative content
			el.parentNode.replaceChild(abstractAltContent(obj), el);
			obj.style.display = "none";
			var fn = function() {
				obj.parentNode.removeChild(obj);
			};
			addListener(win, "onload", fn);
		}
		else {
			obj.parentNode.replaceChild(abstractAltContent(obj), obj);
		}
	} 

	function abstractAltContent(obj) {
		var ac = createElement("div");
		if (ua.win && ua.ie) {
			ac.innerHTML = obj.innerHTML;
		}
		else {
			var nestedObj = obj.getElementsByTagName(OBJECT)[0];
			if (nestedObj) {
				var c = nestedObj.childNodes;
				if (c) {
					var cl = c.length;
					for (var i = 0; i < cl; i++) {
						if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
							ac.appendChild(c[i].cloneNode(true));
						}
					}
				}
			}
		}
		return ac;
	}
	
	/* Cross-browser dynamic SWF creation
	*/
	function createSWF(attObj, parObj, id) {
		var r, el = getElementById(id);
		if (el) {
			if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content
				attObj.id = id;
			}
			if (ua.ie && ua.win) { // IE, the object element and W3C DOM methods do not combine: fall back to outerHTML
				var att = "";
				for (var i in attObj) {
					if (attObj[i] != Object.prototype[i]) { // Filter out prototype additions from other potential libraries, like Object.prototype.toJSONString = function() {}
						if (i.toLowerCase() == "data") {
							parObj.movie = attObj[i];
						}
						else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
							att += ' class="' + attObj[i] + '"';
						}
						else if (i.toLowerCase() != "classid") {
							att += ' ' + i + '="' + attObj[i] + '"';
						}
					}
				}
				var par = "";
				for (var j in parObj) {
					if (parObj[j] != Object.prototype[j]) { // Filter out prototype additions from other potential libraries
						par += '<param name="' + j + '" value="' + parObj[j] + '" />';
					}
				}
				el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
				objIdArr[objIdArr.length] = attObj.id; // Stored to fix object 'leaks' on unload (dynamic publishing only)
				r = getElementById(attObj.id);	
			}
			else if (ua.webkit && ua.webkit < 312) { // Older webkit engines ignore the object element's nested param elements: fall back to the proprietary embed element
				var e = createElement("embed");
				e.setAttribute("type", FLASH_MIME_TYPE);
				for (var k in attObj) {
					if (attObj[k] != Object.prototype[k]) { // Filter out prototype additions from other potential libraries
						if (k.toLowerCase() == "data") {
							e.setAttribute("src", attObj[k]);
						}
						else if (k.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
							e.setAttribute("class", attObj[k]);
						}
						else if (k.toLowerCase() != "classid") { // Filter out IE specific attribute
							e.setAttribute(k, attObj[k]);
						}
					}
				}
				for (var l in parObj) {
					if (parObj[l] != Object.prototype[l]) { // Filter out prototype additions from other potential libraries
						if (l.toLowerCase() != "movie") { // Filter out IE specific param element
							e.setAttribute(l, parObj[l]);
						}
					}
				}
				el.parentNode.replaceChild(e, el);
				r = e;
			}
			else { // Well-behaving browsers
				var o = createElement(OBJECT);
				o.setAttribute("type", FLASH_MIME_TYPE);
				for (var m in attObj) {
					if (attObj[m] != Object.prototype[m]) { // Filter out prototype additions from other potential libraries
						if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
							o.setAttribute("class", attObj[m]);
						}
						else if (m.toLowerCase() != "classid") { // Filter out IE specific attribute
							o.setAttribute(m, attObj[m]);
						}
					}
				}
				for (var n in parObj) {
					if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // Filter out prototype additions from other potential libraries and IE specific param element
						createObjParam(o, n, parObj[n]);
					}
				}
				el.parentNode.replaceChild(o, el);
				r = o;
			}
		}
		return r;
	}
	
	function createObjParam(el, pName, pValue) {
		var p = createElement("param");
		p.setAttribute("name", pName);	
		p.setAttribute("value", pValue);
		el.appendChild(p);
	}
	
	/* Cross-browser SWF removal
		- Especially needed to safely and completely remove a SWF in Internet Explorer
	*/
	function removeSWF(id) {
		var obj = getElementById(id);
		if (obj && (obj.nodeName == "OBJECT" || obj.nodeName == "EMBED")) {
			if (ua.ie && ua.win) {
				if (obj.readyState == 4) {
					removeObjectInIE(id);
				}
				else {
					win.attachEvent("onload", function() {
						removeObjectInIE(id);
					});
				}
			}
			else {
				obj.parentNode.removeChild(obj);
			}
		}
	}
	
	function removeObjectInIE(id) {
		var obj = getElementById(id);
		if (obj) {
			for (var i in obj) {
				if (typeof obj[i] == "function") {
					obj[i] = null;
				}
			}
			obj.parentNode.removeChild(obj);
		}
	}
	
	/* Functions to optimize JavaScript compression
	*/
	function getElementById(id) {
		var el = null;
		try {
			el = doc.getElementById(id);
		}
		catch (e) {}
		return el;
	}
	
	function createElement(el) {
		return doc.createElement(el);
	}
	
	/* Updated attachEvent function for Internet Explorer
		- Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks
	*/	
	function addListener(target, eventType, fn) {
		target.attachEvent(eventType, fn);
		listenersArr[listenersArr.length] = [target, eventType, fn];
	}
	
	/* Flash Player and SWF content version matching
	*/
	function hasPlayerVersion(rv) {
		var pv = ua.pv, v = rv.split(".");
		v[0] = parseInt(v[0], 10);
		v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
		v[2] = parseInt(v[2], 10) || 0;
		return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
	}
	
	/* Cross-browser dynamic CSS creation
		- Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php
	*/	
	function createCSS(sel, decl) {
		if (ua.ie && ua.mac) {
			return;
		}
		var h = doc.getElementsByTagName("head")[0], s = createElement("style");
		s.setAttribute("type", "text/css");
		s.setAttribute("media", "screen");
		if (!(ua.ie && ua.win) && typeof doc.createTextNode != UNDEF) {
			s.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
		}
		h.appendChild(s);
		if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
			var ls = doc.styleSheets[doc.styleSheets.length - 1];
			if (typeof ls.addRule == OBJECT) {
				ls.addRule(sel, decl);
			}
		}
	}
	
	function setVisibility(id, isVisible) {
		var v = isVisible ? "visible" : "hidden";
		if (isDomLoaded && getElementById(id)) {
			getElementById(id).style.visibility = v;
		}
		else {
			createCSS("#" + id, "visibility:" + v);
		}
	}

	/* Filter to avoid XSS attacks 
	*/
	function urlEncodeIfNecessary(s) {
		var regex = /[\\\"<>\.;]/;
		var hasBadChars = regex.exec(s) != null;
		return hasBadChars ? encodeURIComponent(s) : s;
	}
	
	/* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)
	*/
	var cleanup = function() {
		if (ua.ie && ua.win) {
			window.attachEvent("onunload", function() {
				// remove listeners to avoid memory leaks
				var ll = listenersArr.length;
				for (var i = 0; i < ll; i++) {
					listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
				}
				// cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect
				var il = objIdArr.length;
				for (var j = 0; j < il; j++) {
					removeSWF(objIdArr[j]);
				}
				// cleanup library's main closures to avoid memory leaks
				for (var k in ua) {
					ua[k] = null;
				}
				ua = null;
				for (var l in swfobject) {
					swfobject[l] = null;
				}
				swfobject = null;
			});
		}
	}();
	
	
	return {
		/* Public API
			- Reference: http://code.google.com/p/swfobject/wiki/SWFObject_2_0_documentation
		*/ 
		registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr) {
			if (!ua.w3cdom || !objectIdStr || !swfVersionStr) {
				return;
			}
			var regObj = {};
			regObj.id = objectIdStr;
			regObj.swfVersion = swfVersionStr;
			regObj.expressInstall = xiSwfUrlStr ? xiSwfUrlStr : false;
			regObjArr[regObjArr.length] = regObj;
			setVisibility(objectIdStr, false);
		},
		
		getObjectById: function(objectIdStr) {
			var r = null;
			if (ua.w3cdom) {
				var o = getElementById(objectIdStr);
				if (o) {
					var n = o.getElementsByTagName(OBJECT)[0];
					if (!n || (n && typeof o.SetVariable != UNDEF)) {
							r = o;
					}
					else if (typeof n.SetVariable != UNDEF) {
						r = n;
					}
				}
			}
			return r;
		},
		
		embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj) {
			if (!ua.w3cdom || !swfUrlStr || !replaceElemIdStr || !widthStr || !heightStr || !swfVersionStr) {
				return;
			}
			widthStr += ""; // Auto-convert to string
			heightStr += "";
			if (hasPlayerVersion(swfVersionStr)) {
				setVisibility(replaceElemIdStr, false);
				var att = {};
				if (attObj && typeof attObj === OBJECT) {
					for (var i in attObj) {
						if (attObj[i] != Object.prototype[i]) { // Filter out prototype additions from other potential libraries
							att[i] = attObj[i];
						}
					}
				}
				att.data = swfUrlStr;
				att.width = widthStr;
				att.height = heightStr;
				var par = {}; 
				if (parObj && typeof parObj === OBJECT) {
					for (var j in parObj) {
						if (parObj[j] != Object.prototype[j]) { // Filter out prototype additions from other potential libraries
							par[j] = parObj[j];
						}
					}
				}
				if (flashvarsObj && typeof flashvarsObj === OBJECT) {
					for (var k in flashvarsObj) {
						if (flashvarsObj[k] != Object.prototype[k]) { // Filter out prototype additions from other potential libraries
							if (typeof par.flashvars != UNDEF) {
								par.flashvars += "&" + k + "=" + flashvarsObj[k];
							}
							else {
								par.flashvars = k + "=" + flashvarsObj[k];
							}
						}
					}
				}
				addDomLoadEvent(function() {
					createSWF(att, par, replaceElemIdStr);
					if (att.id == replaceElemIdStr) {
						setVisibility(replaceElemIdStr, true);
					}
				});
			}
			else if (xiSwfUrlStr && !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac)) {
				isExpressInstallActive = true; // deferred execution
				setVisibility(replaceElemIdStr, false);
				addDomLoadEvent(function() {
					var regObj = {};
					regObj.id = regObj.altContentId = replaceElemIdStr;
					regObj.width = widthStr;
					regObj.height = heightStr;
					regObj.expressInstall = xiSwfUrlStr;
					showExpressInstall(regObj);
				});
			}
		},
		
		getFlashPlayerVersion: function() {
			return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
		},
		
		hasFlashPlayerVersion: hasPlayerVersion,
		
		createSWF: function(attObj, parObj, replaceElemIdStr) {
			if (ua.w3cdom) {
				return createSWF(attObj, parObj, replaceElemIdStr);
			}
			else {
				return undefined;
			}
		},
		
		removeSWF: function(objElemIdStr) {
			if (ua.w3cdom) {
				removeSWF(objElemIdStr);
			}
		},
		
		createCSS: function(sel, decl) {
			if (ua.w3cdom) {
				createCSS(sel, decl);
			}
		},
		
		addDomLoadEvent: addDomLoadEvent,
		
		addLoadEvent: addLoadEvent,
		
		getQueryParamValue: function(param) {
			var q = doc.location.search || doc.location.hash;
			if (param == null) {
				return urlEncodeIfNecessary(q);
			}
			if (q) {
				var pairs = q.substring(1).split("&");
				for (var i = 0; i < pairs.length; i++) {
					if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
						return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
					}
				}
			}
			return "";
		},
		
		// For internal usage only
		expressInstallCallback: function() {
			if (isExpressInstallActive && storedAltContent) {
				var obj = getElementById(EXPRESS_INSTALL_ID);
				if (obj) {
					obj.parentNode.replaceChild(storedAltContent, obj);
					if (storedAltContentId) {
						setVisibility(storedAltContentId, true);
						if (ua.ie && ua.win) {
							storedAltContent.style.display = "block";
						}
					}
					storedAltContent = null;
					storedAltContentId = null;
					isExpressInstallActive = false;
				}
			} 
		}
	};
}();

/*	Unobtrusive Flash Objects (UFO) v3.20 <http://www.bobbyvandersluis.com/ufo/>
	Copyright 2005, 2006 Bobby van der Sluis
	This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/>
*/

var UFO = {
	req: ["movie", "width", "height", "majorversion", "build"],
	opt: ["play", "loop", "menu", "quality", "scale", "salign", "wmode", "bgcolor", "base", "flashvars", "devicefont", "allowscriptaccess", "seamlesstabbing", "allowfullscreen"],
	optAtt: ["id", "name", "align"],
	optExc: ["swliveconnect"],
	ximovie: "ufo.swf",
	xiwidth: "215",
	xiheight: "138",
	ua: navigator.userAgent.toLowerCase(),
	pluginType: "",
	fv: [0,0],
	foList: [],

	create: function(FO, id) {
		if (!UFO.uaHas("w3cdom") || UFO.uaHas("ieMac")) return;
		UFO.getFlashVersion();
		UFO.foList[id] = UFO.updateFO(FO);
		UFO.createCSS("#" + id, "visibility:hidden;");
		UFO.domLoad(id);
	},

	updateFO: function(FO) {
		if (typeof FO.xi != "undefined" && FO.xi == "true") {
			if (typeof FO.ximovie == "undefined") FO.ximovie = UFO.ximovie;
			if (typeof FO.xiwidth == "undefined") FO.xiwidth = UFO.xiwidth;
			if (typeof FO.xiheight == "undefined") FO.xiheight = UFO.xiheight;
		}
		FO.mainCalled = false;
		return FO;
	},

	domLoad: function(id) {
		var _t = setInterval(function() {
			if ((document.getElementsByTagName("body")[0] != null || document.body != null) && document.getElementById(id) != null) {
				UFO.main(id);
				clearInterval(_t);
			}
		}, 250);
		if (typeof document.addEventListener != "undefined") {
			document.addEventListener("DOMContentLoaded", function() { UFO.main(id); clearInterval(_t); } , null); // Gecko, Opera 9+
		}
	},

	main: function(id) {
		var _fo = UFO.foList[id];
		if (_fo.mainCalled) return;
		UFO.foList[id].mainCalled = true;
		document.getElementById(id).style.visibility = "hidden";
		if (UFO.hasRequired(id)) {
			if (UFO.hasFlashVersion(parseInt(_fo.majorversion, 10), parseInt(_fo.build, 10))) {
				if (typeof _fo.setcontainercss != "undefined" && _fo.setcontainercss == "true") UFO.setContainerCSS(id);
				UFO.writeSWF(id);
			}
			else if (_fo.xi == "true" && UFO.hasFlashVersion(6, 65)) {
				UFO.createDialog(id);
			}
		}
		document.getElementById(id).style.visibility = "visible";
	},

	createCSS: function(selector, declaration) {
		var _h = document.getElementsByTagName("head")[0];
		var _s = UFO.createElement("style");
		if (!UFO.uaHas("ieWin")) _s.appendChild(document.createTextNode(selector + " {" + declaration + "}")); // bugs in IE/Win
		_s.setAttribute("type", "text/css");
		_s.setAttribute("media", "screen");
		_h.appendChild(_s);
		if (UFO.uaHas("ieWin") && document.styleSheets && document.styleSheets.length > 0) {
			var _ls = document.styleSheets[document.styleSheets.length - 1];
			if (typeof _ls.addRule == "object") _ls.addRule(selector, declaration);
		}
	},

	setContainerCSS: function(id) {
		var _fo = UFO.foList[id];
		var _w = /%/.test(_fo.width) ? "" : "px";
		var _h = /%/.test(_fo.height) ? "" : "px";
		UFO.createCSS("#" + id, "width:" + _fo.width + _w +"; height:" + _fo.height + _h +";");
		if (_fo.width == "100%") {
			UFO.createCSS("body", "margin-left:0; margin-right:0; padding-left:0; padding-right:0;");
		}
		if (_fo.height == "100%") {
			UFO.createCSS("html", "height:100%; overflow:hidden;");
			UFO.createCSS("body", "margin-top:0; margin-bottom:0; padding-top:0; padding-bottom:0; height:100%;");
		}
	},

	createElement: function(el) {
		return (UFO.uaHas("xml") && typeof document.createElementNS != "undefined") ?  document.createElementNS("http://www.w3.org/1999/xhtml", el) : document.createElement(el);
	},

	createObjParam: function(el, aName, aValue) {
		var _p = UFO.createElement("param");
		_p.setAttribute("name", aName);
		_p.setAttribute("value", aValue);
		el.appendChild(_p);
	},

	uaHas: function(ft) {
		var _u = UFO.ua;
		switch(ft) {
			case "w3cdom":
				return (typeof document.getElementById != "undefined" && typeof document.getElementsByTagName != "undefined" && (typeof document.createElement != "undefined" || typeof document.createElementNS != "undefined"));
			case "xml":
				var _m = document.getElementsByTagName("meta");
				var _l = _m.length;
				for (var i = 0; i < _l; i++) {
					if (/content-type/i.test(_m[i].getAttribute("http-equiv")) && /xml/i.test(_m[i].getAttribute("content"))) return true;
				}
				return false;
			case "ieMac":
				return /msie/.test(_u) && !/opera/.test(_u) && /mac/.test(_u);
			case "ieWin":
				return /msie/.test(_u) && !/opera/.test(_u) && /win/.test(_u);
			case "gecko":
				return /gecko/.test(_u) && !/applewebkit/.test(_u);
			case "opera":
				return /opera/.test(_u);
			case "safari":
				return /applewebkit/.test(_u);
			default:
				return false;
		}
	},

	getFlashVersion: function() {
		if (UFO.fv[0] != 0) return;
		if (navigator.plugins && typeof navigator.plugins["Shockwave Flash"] == "object") {
			UFO.pluginType = "npapi";
			var _d = navigator.plugins["Shockwave Flash"].description;
			if (typeof _d != "undefined") {
				_d = _d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
				var _m = parseInt(_d.replace(/^(.*)\..*$/, "$1"), 10);
				var _r = /r/.test(_d) ? parseInt(_d.replace(/^.*r(.*)$/, "$1"), 10) : 0;
				UFO.fv = [_m, _r];
			}
		}
		else if (window.ActiveXObject) {
			UFO.pluginType = "ax";
			try { // avoid fp 6 crashes
				var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
			}
			catch(e) {
				try {
					var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
					UFO.fv = [6, 0];
					_a.AllowScriptAccess = "always"; // throws if fp < 6.47
				}
				catch(e) {
					if (UFO.fv[0] == 6) return;
				}
				try {
					var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
				}
				catch(e) {}
			}
			if (typeof _a == "object") {
				var _d = _a.GetVariable("$version"); // bugs in fp 6.21/6.23
				if (typeof _d != "undefined") {
					_d = _d.replace(/^\S+\s+(.*)$/, "$1").split(",");
					UFO.fv = [parseInt(_d[0], 10), parseInt(_d[2], 10)];
				}
			}
		}
	},

	hasRequired: function(id) {
		var _l = UFO.req.length;
		for (var i = 0; i < _l; i++) {
			if (typeof UFO.foList[id][UFO.req[i]] == "undefined") return false;
		}
		return true;
	},

	hasFlashVersion: function(major, release) {
		return (UFO.fv[0] > major || (UFO.fv[0] == major && UFO.fv[1] >= release)) ? true : false;
	},

	writeSWF: function(id) {
		var _fo = UFO.foList[id];
		var _e = document.getElementById(id);
		if (UFO.pluginType == "npapi") {
			if (UFO.uaHas("gecko") || UFO.uaHas("xml")) {
				while(_e.hasChildNodes()) {
					_e.removeChild(_e.firstChild);
				}
				var _obj = UFO.createElement("object");
				_obj.setAttribute("type", "application/x-shockwave-flash");
				_obj.setAttribute("data", _fo.movie);
				_obj.setAttribute("width", _fo.width);
				_obj.setAttribute("height", _fo.height);
				var _l = UFO.optAtt.length;
				for (var i = 0; i < _l; i++) {
					if (typeof _fo[UFO.optAtt[i]] != "undefined") _obj.setAttribute(UFO.optAtt[i], _fo[UFO.optAtt[i]]);
				}
				var _o = UFO.opt.concat(UFO.optExc);
				var _l = _o.length;
				for (var i = 0; i < _l; i++) {
					if (typeof _fo[_o[i]] != "undefined") UFO.createObjParam(_obj, _o[i], _fo[_o[i]]);
				}
				_e.appendChild(_obj);
			}
			else {
				var _emb = "";
				var _o = UFO.opt.concat(UFO.optAtt).concat(UFO.optExc);
				var _l = _o.length;
				for (var i = 0; i < _l; i++) {
					if (typeof _fo[_o[i]] != "undefined") _emb += ' ' + _o[i] + '="' + _fo[_o[i]] + '"';
				}
				_e.innerHTML = '<embed type="application/x-shockwave-flash" src="' + _fo.movie + '" width="' + _fo.width + '" height="' + _fo.height + '" pluginspage="http://www.macromedia.com/go/getflashplayer"' + _emb + '></embed>';
			}
		}
		else if (UFO.pluginType == "ax") {
			var _objAtt = "";
			var _l = UFO.optAtt.length;
			for (var i = 0; i < _l; i++) {
				if (typeof _fo[UFO.optAtt[i]] != "undefined") _objAtt += ' ' + UFO.optAtt[i] + '="' + _fo[UFO.optAtt[i]] + '"';
			}
			var _objPar = "";
			var _l = UFO.opt.length;
			for (var i = 0; i < _l; i++) {
				if (typeof _fo[UFO.opt[i]] != "undefined") _objPar += '<param name="' + UFO.opt[i] + '" value="' + _fo[UFO.opt[i]] + '" />';
			}
			var _p = window.location.protocol == "https:" ? "https:" : "http:";
			_e.innerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + _objAtt + ' width="' + _fo.width + '" height="' + _fo.height + '" codebase="' + _p + '//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=' + _fo.majorversion + ',0,' + _fo.build + ',0"><param name="movie" value="' + _fo.movie + '" />' + _objPar + '</object>';
		}
	},

	createDialog: function(id) {
		var _fo = UFO.foList[id];
		UFO.createCSS("html", "height:100%; overflow:hidden;");
		UFO.createCSS("body", "height:100%; overflow:hidden;");
		UFO.createCSS("#xi-con", "position:absolute; left:0; top:0; z-index:1000; width:100%; height:100%; background-color:#fff; filter:alpha(opacity:75); opacity:0.75;");
		UFO.createCSS("#xi-dia", "position:absolute; left:50%; top:50%; margin-left: -" + Math.round(parseInt(_fo.xiwidth, 10) / 2) + "px; margin-top: -" + Math.round(parseInt(_fo.xiheight, 10) / 2) + "px; width:" + _fo.xiwidth + "px; height:" + _fo.xiheight + "px;");
		var _b = document.getElementsByTagName("body")[0];
		var _c = UFO.createElement("div");
		_c.setAttribute("id", "xi-con");
		var _d = UFO.createElement("div");
		_d.setAttribute("id", "xi-dia");
		_c.appendChild(_d);
		_b.appendChild(_c);
		var _mmu = window.location;
		if (UFO.uaHas("xml") && UFO.uaHas("safari")) {
			var _mmd = document.getElementsByTagName("title")[0].firstChild.nodeValue = document.getElementsByTagName("title")[0].firstChild.nodeValue.slice(0, 47) + " - Flash Player Installation";
		}
		else {
			var _mmd = document.title = document.title.slice(0, 47) + " - Flash Player Installation";
		}
		var _mmp = UFO.pluginType == "ax" ? "ActiveX" : "PlugIn";
		var _uc = typeof _fo.xiurlcancel != "undefined" ? "&xiUrlCancel=" + _fo.xiurlcancel : "";
		var _uf = typeof _fo.xiurlfailed != "undefined" ? "&xiUrlFailed=" + _fo.xiurlfailed : "";
		UFO.foList["xi-dia"] = { movie:_fo.ximovie, width:_fo.xiwidth, height:_fo.xiheight, majorversion:"6", build:"65", flashvars:"MMredirectURL=" + _mmu + "&MMplayerType=" + _mmp + "&MMdoctitle=" + _mmd + _uc + _uf };
		UFO.writeSWF("xi-dia");
	},

	expressInstallCallback: function() {
		var _b = document.getElementsByTagName("body")[0];
		var _c = document.getElementById("xi-con");
		_b.removeChild(_c);
		UFO.createCSS("body", "height:auto; overflow:auto;");
		UFO.createCSS("html", "height:auto; overflow:auto;");
	},

	cleanupIELeaks: function() {
		var _o = document.getElementsByTagName("object");
		var _l = _o.length
		for (var i = 0; i < _l; i++) {
			_o[i].style.display = "none";
			for (var x in _o[i]) {
				if (typeof _o[i][x] == "function") {
					_o[i][x] = null;
				}
			}
		}
	}

};

if (typeof window.attachEvent != "undefined" && UFO.uaHas("ieWin")) {
	window.attachEvent("onunload", UFO.cleanupIELeaks);
}

maxImageWidth = 419;
maxImageHeight = 419;

var rml_buttons = Array('bold', 'italic', 'underline', 'strike','hline',
						/*'sup', 'sub','hline',*/
						'align_left', 'align_center', 'align_right','hline',
						'list_bullet', 'list_num','hline',
						'color_bg','color_fg','hline',
						'link', 'image','hline',
						'table', 'hr','hline',
						'maximize', 'documentlibrary');

function rateItem(targets)
{
	addEventToTargets(targets, 'click', _rateItem, 'div.block-type-rating ul a');
}

function _rateItem(e)
{
	var rating = this.href;
	var block = this;

	rating = rating.split('/').reverse();

	if(rating[2])
	{
		var request = 'data[reactid]=' + getCookie('ReactID') + '&data[rate]=' + rating[0] + '&data[id]=' + rating[1] + '&data[type]=' + rating[2];
		httpreq_string(request, null, board_script_url + '/rate', false);

		while(!block.id && block.tagName != 'div' && block.tagName != 'html')
			block = block.parentNode;

		new Ajax.Request(board_script_url + '/get_block/'+block.id.split('-')[1], {
			postBody : 'data[rating_type]=' + rating[2] + '&data[rating_id]=' + rating[1],
			onComplete : function(transport)
			{
				block.innerHTML = transport.responseText.replace(/^<div [^>]+>(.*)<\/div><hr \/>$/, '$1');
				_init(events, block);
			}
		});

		e.preventDefault();
	}
}

function attachBlocks(blockId)
{
	var cleanupAttached = false;
	if(blockId && typeof(blockid) == 'string')
	{
		var blocks = new DOMQuery('div#' + blockId);
	}
	else
	{
		var blocks = new DOMQuery('div.block');
		cleanupAttached = true;
	}

	if(cleanupAttached)
	{
		/*
			If we're doing a global attach-blocks, remove all 'attached' classes first.
			This way it's possible to recall attachBlocks from block-editor without the layout falling apart.

			yes, this requires 2 loops over blocks, but if we do so within one loop, and the block following
			a div.attach-next-block has 'attach-next-block' even though no block follows, it loses
			'attached' which it shouldn't.
		*/

		for(var i = 0, block; (block=blocks.get(i)); i++)
			jscss('remove', block, 'attached');
	}

	for(var i = 0, block; (block=blocks.get(i)); i++)
	{
		if(!jscss('check', block, 'attach-next-block'))
			continue;

		/* Tag first block below this one as attached */
		var offset_left = block.offsetLeft;
		var offset_top = block.offsetTop;
		var attached = false;
		var nextBlock;
		for(var j=1; (nextBlock = blocks.get(i + j)); j++)
		{
			/* only consider 'lower' blocks */
			if(nextBlock.offsetTop < offset_top)
				continue;

			if(nextBlock.offsetLeft == offset_left || nextBlock.offsetLeft == offset_left - 1)
			{
				jscss('add', nextBlock, 'attached');
				attached = true;
				break;
			}
		}

		/* If no blocks are found to attach, remove class to fix layout */
		if(!attached)
		{
			jscss('remove', block, 'attach-next-block');
		}
	}
};

function emulateEllipsis(targets)
{
	if(isIE)
		return;

	if(!targets)
		var targets = 'div.block > h2';

	var headings = new DOMQuery(targets);
	var average_char_width = 8;

	for(var i = 0, heading; (heading = headings.get(i)); i++)
	{
		if(heading.firstChild.length * average_char_width > heading.clientWidth)
			heading.firstChild.nodeValue = 	heading.firstChild.nodeValue.substr(0, (heading.clientWidth / average_char_width)) + '...';
	}
}

function fixBrowserIssuesSite()
{
	if(isIE)
	{
		addClassToTargets('div#action-header ol li:last-child, div#action-footer ol li:last-child, ul#navigation-2 li:last-child, ul#footer li:last-child, ul.archive-navigation li:last-child', 'last-child');

		if(isNotIE7)
		{
			addClassToTargets('div.block:first-child', 'block-first-child');
			addClassToTargets('div#action-header ol li:first-child', 'first-child');
			addClassToTargets('a[rel=more]', 'more');
			addClassToTargets('input[type=radio]', 'radio');
			addClassToTargets('a[rel=edit]', 'editlink');

			/* create combined classnames from multiple classes */
			var classes = [
				'block-type-show-topic.limit-1',
				'block.attached',
				'block.attached.block-type-show-topic.limit-1'
			];

			for(var i=0; i < classes.length;i++)
				addClassToTargets('div.' + classes[i], classes[i].replace(/\./g, '-'));

			var adminLinks = new DOMQuery('ul#admin-links').get(0);
			if(adminLinks)
				adminLinks.parentNode.insertBefore(createDOMNode('div', {'style' : 'clear: both;'}, ''), adminLinks.nextSibling);
		}

		/* todo: conditionally create this div */
		var overlay = createDOMNode('div', {'id' : 'iefix-overlay', 'style' : 'height: ' + document.body.clientHeight, 'title' : 'Klik om terug te gaan'}, '');
		addEvent( overlay, 'click',
			function()
			{
 				if( jscss('check', document.body, 'inline-admin') )
				{
					document.body.removeChild(new DOMQuery('iframe.inline-admin').get(0));
					jscss('remove', document.body, 'inline-admin');
				}
 			});
		document.body.appendChild(overlay);
	}
};

function readonlyKeywords()
{
	if(['list_messages', 'list_message', 'insert_topic'].indexOf(board_action) == -1)
		return;

	var editLink = new DOMQuery('ul#admin-links li.edit-blocks a').get(0);
	if(editLink)
		return;

	var fields = new DOMQuery('input#keywords_content, input#keywords_content, input#keywords');

	for(var i=0, field; (field = fields.get(i)); i++)
	{
		if(isIE)
		{
			/* use createAttribute in IE instead of setAttribute */
			var ro = document.createAttribute('readonly');
			ro.value = 'readonly';
			field.setAttributeNode(ro);
		}
		else
		{
			field.setAttribute('readonly', 'readonly');
		}
	}
}
var blockGroups = {
	'page-content' : 'content',
	'sidebar' : 'sidebar'
};
var blockGroupsArray = ['page-content', 'sidebar'];

function makeBlocksEditable(targets)
{
	var adminLinks = new DOMQuery('ul#admin-links').get(0);
	var editLink = 'ul#admin-links li.edit-blocks a';

	if(!adminLinks)
		return false;

	layoutChanges = false;
	orderChanges = false;
	blockLayoutsCurrent = new Array();
	blockLayoutsNew = new Array();
	blockLayoutsChanged = new Array();
	saveButton = createDOMNode('li', {'class' : 'save'}, [
				createDOMNode('a', {'title' : 'Save layout options', 'href' : 'javascript:;', 'event' : ['click', savePage]}, ['Save'])
	]);

	adminLinks.insertBefore(saveButton, adminLinks.firstChild);
	addEventToTargets(targets, 'click', _makeBlocksEditable, editLink);
	addEvent(window, 'unload', checkBlockChanges);

	if(getCookie('edit_blocks') == '1' && new DOMQuery(editLink).get(0))
		_makeBlocksEditable();
}


function _makeBlocksEditable(e)
{
	if(e)
		e.preventDefault();

	var blocks = new DOMQuery('div.block[id]');
	var block, blockId, editLink;
	var editable = true;

	jscss('toggle', new DOMQuery('ul#admin-links li.edit-blocks a').get(0), 'active');

	for(var i = 0, block; (block=blocks.get(i)); i++)
	{
		if(editLink = new DOMQuery('ul.block-actions', block).get(0))
		{
			editLink.parentNode.removeChild(editLink);
			editable = false;
		}
		else
		{
			blockId = block.id.match(/block\-([0-9]+)/i);
			if(!blockId)
				continue;

			blockId = blockId[1];

			blockActions = createDOMNode(
				'ul',
				{ 'class' : 'block-actions' },
				[
					createDOMNode(
						'li',
						{ 'class' : 'editlink' },
						[
							createDOMNode(
								'a',
								{
									'href' : board_adminscript_url + '?action=update_block&data%5Bblock_id%5D=' + blockId,
									'rel' : 'edit',
									'title' : 'Blok aanpassen'/*,
									'event': ['click', blockBackend]*/
								},
								['Blok aanpassen']
							)
						]
					),
					createDOMNode(
						'li',
						{ 'class' : 'layout-menu-link' },
						[
							createDOMNode(
								'a',
								{
									'href' : '#',
									'rel' : 'edit',
									'title' : 'Layout aanpassen',
									'event' : ['click', blockLayoutMenu]
								},
								['Layout']
							)
						]
					)
				]
			);

			block.appendChild(blockActions);
		}
	}

	if(editable)
	{
		makeBlocksSortable();
		setCookie('edit_blocks', '1');
	}
	else
	{
		for(i in blockGroups)
		{
			try
			{
				Sortable.destroy(i);
			}
			catch (e)
			{
				;
			}
		}

		setCookie('edit_blocks', '0');
	}
}

function blockBackend(e)
{
	e.preventDefault();

	var element = $(this).up('div.block');
	this.title = 'Annuleren';

	if (jscss('check', document.body, 'inline-admin'))
	{
		document.body.removeChild(new DOMQuery('iframe.inline-admin').get(0));

		if (!isIE)
			do
			{
				jscss('remove', element, 'highlight');
				element = element.parentNode;
			}
			while(element);

		jscss('remove', document.body, 'inline-admin');
		this.title = 'Blok aanpassen';

		return;
	}

	var inlineAdmin = createDOMNode('iframe', { 'src' : this.href, 'class' : 'inline-admin'}, []);

	document.body.appendChild(inlineAdmin);

	if (!isIE)
		do
		{
			jscss('add', element, 'highlight');
			element = element.parentNode;
		}
		while(element);

	jscss('add', document.body, 'inline-admin');

	return;
}

function blocksToString(container, groupName)
{
	var blocks = new DOMQuery(container + ' div.block');
	var waa = new Array();
	var groupName = groupName || 'content';

	if(blocks.length > 0)
		for(var i = 0, block; (block = blocks.get(i)); i++)
			waa[i] = block.id.split('-')[1];

	return groupName + ':' + waa + ';';
}

function makeBlocksSortable()
{
	for(i in blockGroups)
		if(new DOMQuery('#' + i).get(0))
			Sortable.create(i, {ghosting:false, tag:'div', only:'block', constraint:'', hoverclass:'hover', dropOnEmpty:true, containment:blockGroupsArray, onUpdate:sortablesOnUpdate });
}

function updateBlockOrder()
{
	var ps = '';

	for(i in blockGroups)
		ps += blocksToString('div#' + i, blockGroups[i]);

	var req = httpreq_string('action=xml_update_blockorder&data[block_order]=' + ps, null, board_adminscript_url, null, 'POST');

	req.onreadystatechange = function()
	{
		if (req.readyState != 4)
			return;

		jscss('remove', saveButton, 'busy');
		jscss('add', saveButton, 'done');
		orderChanges = false;
	}
}

function blockLayoutMenu(e)
{
	if(!jscss('check', e, 'block'))
	{
		e = e || fixEvent(e);
		e.preventDefault();
		var element = $(this).up('div.block');
	}
	else
		var element = e;

	var menu = new DOMQuery('div.layout-menu', element).get(0);
	var blockID = element.id.match(/block\-([0-9]+)/i)[1];

	if (menu != null)
	{
		if (jscss('check', menu, 'open'))
			Effect.BlindUp(menu, {duration : .5});
		else
			Effect.BlindDown(menu, {duration : .5});

		jscss('toggle', menu, 'open');
		return;
	}

	var menu = createDOMNode('div', { 'class' : 'layout-menu open', 'style' : 'display: none' }, [ createDOMNode('h3', {}, ['Layout opties']) ] );
	element.insertBefore(menu, element.firstChild);

	var req = httpreq_string('action=xml_get_layouts&data[block_id]=' + blockID, null, board_adminscript_url, true, 'GET');

	req.onreadystatechange = function()
	{
		if (req.readyState != 4)
			return;

		if (req.responseText == '')
			return;

		eval('var layoutOptions = ' + req.responseText);

		var currentLayout = element.className.split(' ').slice(2); // skip block & blocktype class

		var optionChecked = false;
		var ul = createDOMNode('ul', '', '');
		var li, input;
		for (var i=0; i < layoutOptions.length; i++)
		{
			optionChecked = false;

			if (typeof blockLayoutsCurrent[blockID] == 'undefined')
				blockLayoutsCurrent[blockID] = new Array();

			if (currentLayout.indexOf(layoutOptions[i]) != -1)
			{
				optionChecked = true;
				blockLayoutsCurrent[blockID].push(layoutOptions[i]);
			}

			input = createDOMNode('input', {'type' : 'checkbox', 'value' : layoutOptions[i], 'event' : ['click',
					function()
					{
						if (this.checked == true)
						{
							jscss('add', element, this.value);

						}
						else
						{
							jscss('remove', element, this.value);
						}

						jscss('remove', saveButton, 'done');

						checkLayoutChanges(blockID);
					}]
				}, ''
			);

			if (optionChecked == true)
				input.defaultChecked = true;

			switch(layoutOptions[i])
			{
				case 'show-topic-image':
					//addEvent(input, 'click', refreshBlock);
				break;
				case 'attach-next-block':
					addEvent(input, 'click', attachBlocks);
				break;
			}


			li = createDOMNode('li', '', [createDOMNode('label', '', [input, layoutOptions[i]]) ]);
			ul.appendChild(li);
		}

		menu.appendChild(ul);
		Effect.BlindDown(menu, {duration : .5});

	}
}

function layoutMenuIE6Fix(element)
{
	// used @ vrouw
	if(isIE && isNotIE7)
	{
		var bottomDiv = new DOMQuery('div.bottom', element).get(0);

		// Recalculate
		alert(bottomDiv);
		bottomDiv.style.display = 'none';
		bottomDiv.style.display = 'block';
	}
}

function updateBlockLayouts()
{
	if (layoutChanges == false)
		return;

	var layouts = '';

	for (var i = 0, len = blockLayoutsChanged.length; i < len; i++)
	{
		var blockID = blockLayoutsChanged[i];
		layouts += blockID + ':' + blockLayoutsNew[blockID].toString() +  ';';
	}

	blockLayoutsRequest = httpreq_string('action=xml_save_layouts&data[layouts]=' + layouts, null, board_adminscript_url, true);
}

function sortablesOnUpdate()
{
	orderChanges = true;
	jscss('remove', saveButton, 'done');

	checkEmptyGroups();
}

function checkEmptyGroups()
{
	var group, blocks;

	for(i in blockGroups)
	{
		if (!(group = new DOMQuery('div#' + i).get(0)))
			continue;

		blocks = new DOMQuery('div.block', group);

		if(blocks.length == 0)
			jscss('add', group, 'empty');
		else
			jscss('remove', group, 'empty');
	}
}

function checkLayoutChanges(blockID)
{
	if (typeof blockID == 'undefined')
		return false;

	if (typeof blockLayoutsChanged != 'undefined')
		blockLayoutsChanged = blockLayoutsChanged.without(blockID);

	layoutChanges = false;
	blockLayoutsNew[blockID] = new Array();
	var layouts = new DOMQuery('div#block-' + blockID + ' input[type=checkbox]');

	for (var i = 0, layout; (layout = layouts.get(i)); i++)
		if (layout.checked)
			blockLayoutsNew[blockID].push(layout.value);

	if (blockLayoutsNew[blockID].length == blockLayoutsNew[blockID].length)
		for (var i = 0; i < layouts.length; i++)
		{
			if (blockLayoutsNew[blockID][i] != blockLayoutsCurrent[blockID][i])
			{
				layoutChanges = true;
				blockLayoutsChanged.push(blockID);
				break;
			}
		}
	else
	{
		layoutChanges = true;
		blockLayoutsChanged.push(blockID);
	}

	if (blockLayoutsChanged.length > 0)
		layoutChanges = true;
	else
		layoutChanges = false;
}

function checkBlockChanges()
{
	if (layoutChanges == false && orderChanges == false)
		return;

	if (confirm('Save changes?'))
		savePage();
}

function savePage(e)
{
	jscss('add', saveButton, 'busy');

	if (orderChanges == true)
		updateBlockOrder();

	if (layoutChanges == true)
	{
		updateBlockLayouts();
		jscss('add', saveButton, 'busy');

		if (typeof e != 'undefined') // if savebutton is used
			blockLayoutsRequest.onreadystatechange = function()
			{
				if( blockLayoutsRequest.readyState != 4 )
					return;

				refreshBlocks();
				jscss('remove', saveButton, 'busy');
				jscss('add', saveButton, 'done');
			}
	}

	layoutChanges = false;
	orderChanges = false;
}

function refreshBlocks()
{
	if (blockLayoutsChanged.length == 0)
		return false;

	var blockID = blockLayoutsChanged.shift();
	var req = httpreq_string('action=xml_get_block&data[block_id]=' + blockID, null, board_adminscript_url, true, 'GET');

	req.onreadystatechange = function()
	{
		if (req.readyState != 4)
			return;

		var block = document.getElementById('block-' + blockID);
		var layoutMenu = new DOMQuery('div.layout-menu', block).get(0);
		var blockActions = new DOMQuery('ul.block-actions', block).get(0);
		var div = document.createElement('div');
		div.innerHTML = req.responseText;
		var updatedBlock = div.getElementsByTagName('div')[0];
		updatedBlock.insertBefore(layoutMenu, updatedBlock.firstChild);
		updatedBlock.appendChild(blockActions);
		block.parentNode.replaceChild(updatedBlock, block);

		if( blockLayoutsChanged.length == 0 )
			makeBlocksSortable();
	}

	refreshBlocks();
};
function blocksAUG()
{
	var blocks = new DOMQuery('div.rightcolumn>div.block');

	for(var i = 0; block = blocks.get(i); i++)
	{
		if(jscss('check', block, 'dim'))
			continue;

		var bgDiv = createDOMNode('div', {'class': 'bg'}, []);

		while(block.firstChild)
			bgDiv.appendChild(block.removeChild(block.firstChild));

		block.appendChild(bgDiv);
	}
}

function fixBrowserIssuesAUG()
{
	if(isIE && isNotIE7)
	{
		addClassToTargets('a[rel=more]', 'more');
		addClassToTargets('a[rel=edit]', 'editlink');
		addClassToTargets('input[type=checkbox]', 'checkbox');
		addClassToTargets('div.rightcolumn input[type=text]', 'text');

		transparantPNG('span.img');
	}
}

function minicalendarAUG()
{
	var table = new DOMQuery('table#calendar').get(0);
	if(!table)
		return;

	var days = new DOMQuery('tbody td', table);
	var day, tasklist, taskViewer;

	taskViewer = createDOMNode('div', {'id': 'task-viewer'}, []);
	table.parentNode.appendChild(taskViewer);

	for(var i = 0; day = days.get(i); i++)
	{
		if(day.firstChild.nextSibling == null)
			continue;

		addEvent(day, 'mouseover', function()
		{
			tasklist = this.firstChild.nextSibling;

			try
			{
				taskViewer.removeChild(taskViewer.firstChild);
			}
			catch(ex){}

			taskViewer.appendChild(tasklist.cloneNode(true));
		});
	}
};

function fckEditor()
{
	var original = new DOMQuery('textarea#rml_textarea').get(0);
	if(!original)
		return;

	var oFCKeditor = new FCKeditor('rml_textarea');

	oFCKeditor.Config['CustomConfigurationsPath'] = board_template_url + '/js/fckconfig.js';
	oFCKeditor.BasePath = board_template_url + '/js/FCKeditor/';
	oFCKeditor.Width = 540;

	if(board_action == 'list_message' || board_action == 'list_messages')
		oFCKeditor.Height = 150;
	else
		oFCKeditor.Height = 500;

	oFCKeditor.ReplaceTextarea();
};

overloadFunction( 'validateForm', function(form)
{
	updateLinkedField();

	return arguments.callee.previousFunctionDefinition.apply(this, arguments);
});

function updateLinkedField()
{
	if(typeof FCKeditorAPI != 'undefined')
	{
		var editor = FCKeditorAPI.GetInstance('rml_textarea') ;

		if(typeof editor != 'undefined')
			editor.UpdateLinkedField(); /* update hidden textarea before validating forms */
	}
};

var extraValidateFields = [validateNicknameSyntax];

function validateNicknameSyntax(field)
{
	if(field.id != 'nickname')
		return;

	var re = /^[\w_-]+$/;

	if(!re.test(field.value))
		alertUser(field, 'Gebruikersnaam kan alleen letters, nummers en de tekens _- bevatten.');
};

var _validationResultOld = _validationResult;

function _validationResult(request)
{
	if(typeof request != 'undefined' && request != null && request.readyState == 4)
	{
		var response = getElementFromXHR(request, 'div#block-1');

		return response.firstChild.nodeValue;
	}

	return "0";
};

var calenderRepeatDetails = Array();
var calendarRepeat;

function toggleRepeatDetails()
{
	calendarRepeat = new DOMQuery('input#calendar_repeatcheck');

	if(calendarRepeat.length == 0)
	{
		calendarRepeat = null;
		return;
	}

	calendarRepeat = calendarRepeat.get(0);

	addEventToTargets(null, 'change', _toggleRepeatDetails, 'input#calendar_repeatcheck, select#calendar_repeatselect');
	addClassToTargets('dt.calendar-repeat-details, dd.calendar-repeat-details', 'display-none');

	if(calendarRepeat.checked)
	{
		_toggleRepeatDetails();

		if(!isIE && window.location.hash != '#showAdvancedOptions')
			toggleAdvancedOptions();
	}
};

function _toggleRepeatDetails()
{
	var calendarRepeatDetails = new DOMQuery('dt.calendar-repeat-details, dd.calendar-repeat-details');

	for (var i = 0; i < calendarRepeatDetails.length; i++)
	{
		var item = calendarRepeatDetails.get(i);

		if(calendarRepeat.checked)
			jscss('remove',item,'display-none', '');
		else
			jscss('add',item,'display-none', '');
	}

	var frequency = new DOMQuery('select#calendar_repeatselect');

	if(frequency.length > 0)
	{
		frequency = frequency.get(0).options[frequency.get(0).selectedIndex].value;
		var items = new DOMQuery('dt.calendar-repeat-weekly, dd.calendar-repeat-weekly');
		for(i=0, item; (item=items.get(i)); i++)
		{
			jscss('add',item,'display-none', '');

			switch(frequency)
			{
				case 'week':
					if(calendarRepeat.checked)
						jscss('remove',item,'display-none', '');
				break;
			}
		}
	}
};

function easyTimeInputConverter()
{
	addEventToTargets('input#calendar_startdate_time, input#calendar_enddate_time',	'change', _easyTimeInputConverter);

	addEventToTargets('input#calendar_startdate, input#calendar_enddate, input#calendar_startdate_time, input#calendar_enddate_time', 'blur', _ensureCorrectDateRange);
};

function _easyTimeInputConverter()
{
	if(this.value.indexOf(':') > 0)
		return;

	var newValue = this.value;

	switch(newValue.length)
	{
		case 1:				/* '9' => 9h => 09:00		*/
			newValue = '0' + this.value + ':00';
		break;
		case 2:				/* '21' => 21h => 21:00		*/
			newValue = this.value + ':00';
		break;
		case 3:				/* '914' => 914h => 09:14	*/
			newValue = '0'+ this.value.substr(0,1) + ':' + this.value.substr(1,2);
		break;
		case 4:				/* '2125' => 2125h => 21:25	*/
			newValue = this.value.substr(0,2) + ':' + this.value.substr(2,3);
		break;
	}
	this.value = newValue;
};

function _ensureCorrectDateRange()
{
	var startDate = new DOMQuery('input#calendar_startdate').get(0);
	var startTime = new DOMQuery('input#calendar_startdate_time').get(0);
	var endDate = new DOMQuery('input#calendar_enddate').get(0);
	var endTime = new DOMQuery('input#calendar_enddate_time').get(0);

	var datePattern = /0?(\d{1,2})\D0?(\d{1,2})\D(\d{4})/, m;
	var timePattern = /0?([0-9]{1,2}):0?([0-9]{1,2})/, m;

	var startDateMatches = startDate.value.match( datePattern );
	var startTimeMatches = startTime.value.match( timePattern );
	if(!startDateMatches || !startTimeMatches)
		return;

	var startDateObject = new Date(
		parseInt(startDateMatches[3]),  // year
		parseInt(startDateMatches[2]) - 1, // month
		parseInt(startDateMatches[1]), // day
		parseInt(startTimeMatches[1]), // hour
		parseInt(startTimeMatches[2]), // minute
		0, // seconds
		0 // milliseconds
	);

	var endDateMatches = endDate.value.match( datePattern );
	var endTimeMatches = endTime.value.match( timePattern );
	if(!endDateMatches || !endTimeMatches)
		return;

	var endDateObject = new Date(
		parseInt(endDateMatches[3]),  // year
		parseInt(endDateMatches[2]) - 1, // month
		parseInt(endDateMatches[1]), // day
		parseInt(endTimeMatches[1]), // hour
		parseInt(endTimeMatches[2]), // minute
		0, // seconds
		0 // milliseconds
	);

	if(endDateObject >= startDateObject)
		return;

	switch(this.id)
	{
		case 'calendar_startdate':
		case 'calendar_startdate_time':
			endDate.value = startDate.value;
			endTime.value = startTime.value;
		break;
		case 'calendar_enddate':
		case 'calendar_enddate_time':
			startDate.value = endDate.value;
			startTime.value = endTime.value;
		break;
	}
};

var events = [ ];

if(showing_mini_calendar)
{
	events.push(
			minicalendarSetup
		);
}
else
{
	events.push(
		/* board specific and / or overloaded events */
		attachBlocks,
		documentSelector,
		toggleVisibility,
		// rateItem,
		[scaleImages, ['ol.messages div.message-content-content > img']],
		makeBlocksEditable,
		// fixBrowserIssues,
		// fixBrowserIssuesSite,
		// initLightbox,
		// readonlyKeywords,

		/* standard base-grey events */
		// minicalendarCreate,
		// fixBrowserIssues,
		// createFooter,
		pulldownAutoSubmits,
		toggleAuthorLinks,
		[focusFirstFormField, ['div#page-content input.focusable, div#page-content textarea.focusable']],
		validateForms,
		hideAdvancedOptions,
		topicNavigationPulldown,
		attachCalendarSelector,
		rewriteQuoteLinks,
		// privateMessagingCopyContact,
		loginForm,
		doclibInteraction,
		toggleChangeCheckboxTopicAdmin,
		easyTimeInputConverter,
		toggleRepeatDetails,
		// attachRMLToolbar,
		makeSmileysClickable,
		selectAllRows,
		// extraActionsThruXmlHttp,
		autocomplete,
		// stretchTextareas,
		// toggleTagcloudOverflow,

		/* base-grey extra events */
		closeAndSubmit,
		logoutSessions,
		externalLinksInPopup,
		blocksAUG,
		fixBrowserIssuesAUG,
		// minicalendarAUG (TODO)
		fckEditor
	);

	/* extra extra... read all about it */

	/*
		updateMessagesThruXmlHttp,
		indicateAccesskey,
		searchPopup,
		localAnchors,
		slashdotLinks,
		selectAllRows,
		localAnchors,
		closeAndSubmit,
		logoutSessions,
		allPagesNavigation,
		highlightReferrerQuery,
		externalLinksInPopup,
		indicateSecureLink,
		web20_usericons,
		resolveIP2Hostname,
		stretchTextareas
	*/
}


