	/*
	 * Loosely based on code from www.dhtmlgoodies.com [RSSBoxes]
	 *
	 * 2008-05-08 VZ Initial version
	 * 2009-10-15 VZ Updated with support for obligatory portlets
	 */

	// Constants
	var numberOfColumns = 3;				// Number of columns for portlets
	var columnIDfixed = "column";			// Fixed part of ID for the column divs
	var portletIDfixed = "dragableBox";		// Fixed part of ID for the draggable portlets

	var transparencyWhenDragging = true;
	var autoScrollSpeed = 4;				// Autoscroll speed	- Higher = faster
	var partialCollapseHeight = 92;
	var partialCollapseOffset = 75;

	var useCookieToRememberPortlets = true;
	var PORTLETS_COOKIE_NAME = "personalisedHome";
	var OBLIGATORIES_COOKIE_NAME = "obligatory";

	var resourcePath = "001";			// First part of path to CSS, images and scripts
	var plusButtonImagePath				= "images/plusButton.gif";
	var plusButtonDisabledImagePath		= "images/plusButtonDisabled.gif";
	var minusButtonImagePath			= "images/minusButton.gif";
	var minusButtonDisabledImagePath	= "images/minusButtonDisabled.gif";

	// Create an array with the colours which are available to the user
	var colours = new Array("rgb(12, 106, 138)", "rgb(75, 86, 118)", "rgb(0, 87, 133)", "rgb(2, 112, 97)", "rgb(76, 112, 22)",
		"rgb(77, 56, 112)", "rgb(105, 30, 121)", "rgb(132, 2, 89)", "rgb(99, 94, 53)", "rgb(80, 70, 56)", "rgb(53, 53, 53)",
		"rgb(133, 22, 7)", "rgb(186, 80, 12)");

	// Global variables
	var updateProvider = null;
	var autoScrollActive = false;
	var draggablePortlets = new Array();
	// Holds the index into the array of colours for all titles
	var mainColourIndex = 0;

	var dragDropCounter = -1;
	var dragObject = false;
	var dragObjectNextSibling = false;
	var dragObjectParent = false;
	var destinationObj = false;

	// Mouse offset relative to portlet being dragged
	var mouse_x;
	var mouse_y;

	var el_x;
	var el_y;	

	var rectangleDiv;
	var okToMove = true;
	var documentHeight = -1;
	var documentScrollHeight = -1;

	var opera = navigator.userAgent.toLowerCase().indexOf("opera") >= 0 ? true : false;

	/*
		These cookie functions have been downloaded from
		http://www.mach5.com/support/analyzer/manual/html/General/CookiesJavaScript.htm
	*/
	function getCookie(name)
	{
		var start = document.cookie.indexOf(name + "=");
		var len = start + name.length + 1;
		if (!start &&
			name != document.cookie.substring(0, name.length))
		{
			return null;
		}
		if (start == -1)
		{
			return null;
		}
		var end = document.cookie.indexOf(";", len);
		if (end == -1)
		{
			end = document.cookie.length;
		}
		return unescape(document.cookie.substring(len, end));
	}

	// This function has been slightly modified
	function setCookie(name, value, expires, path, domain, secure)
	{
		// Multiply by 24 hours (one day)
		expires = expires * 24 * 60 * 60 * 1000;
		var today = new Date();
		var expiresDate = new Date(today.getTime() + expires);
		var cookieString = name + "=" + escape(value) +
		   (expires ? ";expires=" + expiresDate.toGMTString() : "") +
		   (path ? ";path=" + path : "") +
		   (domain ? ";domain=" + domain : "") +
		   (secure ? ";secure" : "");
		document.cookie = cookieString;
	}

	function deleteCookie(name)
	{
		// Expire one day back in time
		setCookie(name, null, -1);
	}

	function restoreDefaultPortlets()
	{
		if (confirm("Indien u OK kiest, verliest u al uw persoonlijke aanpassingen en wordt de originele paginaindeling hersteld!"))
		{
			deleteCookie(PORTLETS_COOKIE_NAME);
			deleteCookie(OBLIGATORIES_COOKIE_NAME);
			// Force page reload
			window.location.reload();
		}
	}

	var slideSpeed = 8;	// Higher value = faster
	var slideTimeout = 4;	// Lower value = faster

	var slideInProgress = false;

	function showHideContent(obj, show, minHeight, maxOffset)
	{
		if (slideInProgress)
		{
			return;
		}
		slideInProgress = true;

		if (show)
		{
			// This is very important; without this, the 'offsetHeight' of 'contentDiv' will be zero!
			obj.style.display = "block";

			// Skip in case there's no content (none of the sub items selected)
			if (obj.offsetHeight != 0)
			{
				// Slide the content into view
				slideContent(slideSpeed, minHeight, maxOffset, obj);
			}
			else
			{
				slideInProgress = false;
			}
		}
		else
		{
			// In case there's no content (none of the sub items selected)
			if (obj.offsetHeight == 0)
			{
				obj.style.display = "none";
				slideInProgress = false;
			}
			else
			{
				// Slide the content out of view
				slideContent(slideSpeed * -1, minHeight, maxOffset, obj);
			}
		}
	}

	// Seemed to be necessary for IE 6, but 'setTimeout' appeared to work again after restarting the browser :(
	var objectToSlide = undefined;
	var globalDirection = undefined;
	var globalMinHeight = undefined;
	var globalMaxOffset = undefined;

	function slideContent(direction, minHeight, maxOffset, obj)
	{
		if (obj != undefined)
		{
			objectToSlide = obj;
			globalDirection = direction;
			globalMinHeight = minHeight;
			globalMaxOffset = maxOffset;
		}

		var height = objectToSlide.parentNode.offsetHeight + globalDirection;
		var rerunFunction = true;
		if (height > objectToSlide.offsetHeight)
		{
			height = objectToSlide.offsetHeight;
			rerunFunction = false;
		}
		if (height <= 0 ||
			(globalMinHeight !== undefined &&
			height <= globalMinHeight))
		{
			height = globalMinHeight !== undefined ? globalMinHeight : 0;
			rerunFunction = false;
		}
		var topPos = height - objectToSlide.offsetHeight;
		if (topPos > 0)
		{
			topPos = 0;
		}
		else if (globalDirection < 0 &&
			globalMaxOffset !== undefined &&
			topPos < -globalMaxOffset)
		{
			topPos = -globalMaxOffset;
		}

		// For some portlets we want to keep a part of the content visible, even while collapsed
		objectToSlide.style.top = topPos + "px";
		objectToSlide.parentNode.style.height = height + "px";

		if (rerunFunction)
		{
			setTimeout(slideContent, slideTimeout);
		}
		else
		{
			if (globalMinHeight !== undefined &&
				height <= globalMinHeight)
			{
				// Do nothing
			}
			else if (height <= 0)
			{
				objectToSlide.style.display = "none";
			}
			else
			{
				// Needed, because after adding/removing items from the portlet, it needs to be able to resize
				// This doesn't work in IE6; effectively will set the height to zero
				if (!document.all ||
					typeof XMLHttpRequest != "undefined")
				{
					objectToSlide.parentNode.style.height = "auto";
				}
			}
			slideInProgress = false;
		}
	}

	function autoScroll(direction, yPos)
	{
		if (document.documentElement.scrollHeight > documentScrollHeight &&
			direction > 0)
		{
			return;
		}
		if (opera)
		{
			return;
		}
		window.scrollBy(0, direction);
		if (!dragObject)
		{
			return;
		}

		var scrollPos = getScrollingPosition();
		if (direction < 0)
		{
			if (scrollPos[1] > 0)
			{
				dragObject.style.top = (el_y - mouse_y + yPos + scrollPos[1]) + "px";		
			}
			else
			{
				autoScrollActive = false;
			}
		}
		else
		{
			if (yPos > documentHeight - 50)
			{	
				dragObject.style.top = (el_y - mouse_y + yPos + scrollPos[1]) + "px";			
			}
			else
			{
				autoScrollActive = false;
			}
		}
		if (autoScrollActive)
		{
			setTimeout("autoScroll(" + direction + "," + yPos + ")", 5);
		}
	}

	function initDragDropBox(e)
	{
		dragDropCounter = 1;
		if (document.all)
		{
			e = event;
		}

		var source = null;
		if (e.target)
		{
			source = e.target;
		}
		else if (e.srcElement)
		{
			source = e.srcElement;
		}
		// Defeat Safari bug (VZ: Is this still needed in current versions?)
		if (source.nodeType == 3)
		{
			source = source.parentNode;
		}

		if (source.tagName.toLowerCase() == "img" || source.tagName.toLowerCase() == "a" || source.tagName.toLowerCase() == "input" ||
			source.tagName.toLowerCase() == "td" || source.tagName.toLowerCase() == "tr" || source.tagName.toLowerCase() == "table")
		{
			return true;
		}

		mouse_x = e.clientX;
		mouse_y = e.clientY;	
		var numericId = getIDNumberFromName(this.parentNode.id);
		el_x = getLeftPos(this.parentNode) / 1;
		el_y = getTopPos(this.parentNode) / 1 - getScrollingPosition()[1];

		dragObject = this.parentNode;
		dragObject.style.borderColor = "gray";

		documentScrollHeight = document.documentElement.scrollHeight + 100 + dragObject.offsetHeight;

		if (dragObject.nextSibling)
		{
			dragObjectNextSibling = dragObject.nextSibling;
			if (dragObjectNextSibling.tagName.toLowerCase() != "div")
			{
				dragObjectNextSibling = dragObjectNextSibling.nextSibling;
			}
		}
		dragObjectParent = draggablePortlets[numericId - 1]["parentObj"];

		dragDropCounter = 0;
		initDragDropBoxTimer();	

		return false;
	}

	function initDragDropBoxTimer()
	{
		if (dragDropCounter >= 0 &&
			dragDropCounter < 10)
		{
			dragDropCounter++;
			setTimeout("initDragDropBoxTimer()", 10);
			return;
		}
		if (dragDropCounter == 10)
		{
//			mouseoutBoxHeader(false, dragObject);
		}
	}

	/**
	 * Copied verbatim from 'http://javascriptmagic.blogspot.com/2006/09/getting-scrolling-position-using.html'.
	 */
	function getScrollingPosition()
	{
		var position = [0, 0];
		if (typeof window.pageYOffset != 'undefined')
		{
			position = [
				window.pageXOffset,
				window.pageYOffset
			];
		}
		else if (typeof document.documentElement.scrollTop != 'undefined' &&
			document.documentElement.scrollTop > 0)
		{
			position = [
				document.documentElement.scrollLeft,
				document.documentElement.scrollTop
			];
		}
		else if (typeof document.body.scrollTop != 'undefined')
		{
			position = [
				document.body.scrollLeft,
				document.body.scrollTop
			];
		}
//window.status = "Scroll Position: " + position[0] + ", " + position[1];
		return position;
	}

	function moveDragableElement(e)
	{
		// Check for IE; doesn't supply the 'e' argument
		if (document.all)
		{
			e = event;
		}
		if (dragDropCounter < 10)
		{
			return;
		}

		// Only the first time
		if (dragObject.parentNode != document.body)
		{
			dragObject.style.width = dragObject.offsetWidth + "px";
			dragObject.style.position = "absolute";	

			if (transparencyWhenDragging)
			{	
				dragObject.style.filter = "alpha(opacity=70)";
				dragObject.style.opacity = "0.7";
			}
			// Show the 'target' div with the same dimensions as the portlet we're dragging; move it before the position of the portlet we're dragging
			dragObject.parentNode.insertBefore(rectangleDiv, dragObject);
			// VZ: Had to _subtract_ 8 here! (After removing the "px" part from the other 'style.width')
			rectangleDiv.style.width = (Number(dragObject.style.width.substring(0, dragObject.style.width.length - 2)) - 8) + "px";
			// VZ: Had to subtract 8 here; why? border?
			rectangleDiv.style.height = (dragObject.offsetHeight - 8) + "px"; 
			rectangleDiv.style.display = "block";

			// Move the portlet we're dragging to the 'body', so we will be able to drag it anywhere
			document.body.appendChild(dragObject);
		}	

		if (e.clientY < 50 || e.clientY > documentHeight - 50)
		{
			if (e.clientY < 50 &&
				!autoScrollActive)
			{
				autoScrollActive = true;
				autoScroll((autoScrollSpeed * -1), e.clientY);
			}

			if (e.clientY > documentHeight - 50 &&
				document.documentElement.scrollHeight <= documentScrollHeight &&
				!autoScrollActive)
			{
				autoScrollActive = true;
				autoScroll(autoScrollSpeed, e.clientY);
			}
		}
		else
		{
			autoScrollActive = false;
		}		

		var scrollPos = getScrollingPosition();
		var leftPos = e.clientX;
		var topPos = e.clientY + scrollPos[1];

		dragObject.style.left = (e.clientX - mouse_x + el_x) + "px";
		dragObject.style.top = (el_y - mouse_y + e.clientY + scrollPos[1]) + "px";

		if (!okToMove)
		{
			return;
		}

		okToMove = false;
		destinationObj = false;

		var objFound = false;
		for (var no = 0; no < draggablePortlets.length; no++)
		{
			if (draggablePortlets[no] == null ||
				draggablePortlets[no]["obj"] == dragObject)
			{
				continue;
			}
			if (!objFound)
			{
				var tmpX = getLeftPos(rectangleDiv);
				var tmpY = getTopPos(rectangleDiv);

				// Overlaps /*top half of*/ 'target' div
				if (leftPos > tmpX &&
					leftPos < tmpX + rectangleDiv.offsetWidth &&
					topPos > tmpY - 20 &&
					topPos < tmpY + rectangleDiv.offsetHeight/* / 2*/)
				{
					// Prevent screen flicker in Fx and Opera (Safari doesn't suffer from this)
					if (rectangleDiv.nextSibling)
					{
						destinationObj = rectangleDiv.nextSibling;
					}
					else
					{
						destinationObj = rectangleDiv.parentNode;
					}
					rectangleDiv.style.display = "block";
					objFound = true;
					break;
				}

				var tmpX = getLeftPos(draggablePortlets[no]["obj"]);
				var tmpY = getTopPos(draggablePortlets[no]["obj"]);

				// The mouse is in the top half of the portlet indexed by 'no'
				if (leftPos > tmpX &&
					leftPos < tmpX + draggablePortlets[no]["obj"].offsetWidth &&
					topPos > tmpY - 20 &&
					topPos < tmpY + draggablePortlets[no]["obj"].offsetHeight / 2)
				{
					// Prevent screen flicker in Fx and Opera (Safari doesn't suffer from this)
					if (destinationObj != draggablePortlets[no]["obj"])
					{
						destinationObj = draggablePortlets[no]["obj"];
						destinationObj.parentNode.insertBefore(rectangleDiv, draggablePortlets[no]["obj"]);
					}
					rectangleDiv.style.display = "block";
					objFound = true;
					break;
				}

				// The mouse is in the bottom half of the portlet indexed by 'no'
				if (leftPos > tmpX &&
					leftPos < (tmpX + draggablePortlets[no]["obj"].offsetWidth) &&
					topPos >= (tmpY + (draggablePortlets[no]["obj"].offsetHeight / 2)) &&
					topPos < (tmpY + draggablePortlets[no]["obj"].offsetHeight))
				{
					objFound = true;
					if (draggablePortlets[no]["obj"].nextSibling)
					{
						// Prevent screen flicker in Fx and Opera (Safari doesn't suffer from this)
						if (destinationObj != draggablePortlets[no]["obj"].nextSibling)
						{
							destinationObj = draggablePortlets[no]["obj"].nextSibling;
							if (destinationObj != null &&
								destinationObj != rectangleDiv)
							{
								destinationObj.parentNode.insertBefore(rectangleDiv, destinationObj);
							}	
						}
					}
					else
					{
						// Prevent screen flicker in Fx and Opera (Safari doesn't suffer from this)
						if (destinationObj != draggablePortlets[no]["obj"].parentNode)
						{
							destinationObj = draggablePortlets[no]["obj"].parentNode;
							draggablePortlets[no]["obj"].parentNode.appendChild(rectangleDiv);
						}
					}
					rectangleDiv.style.display = "block";
					break;					
				}

				// The mouse is below the portlet indexed by 'no'
				if (!draggablePortlets[no]["obj"].nextSibling &&
					leftPos > tmpX &&
					leftPos < tmpX + draggablePortlets[no]["obj"].offsetWidth &&
					topPos > tmpY + draggablePortlets[no]["obj"].offsetHeight)
				{
					// Prevent screen flicker in Fx and Opera (Safari doesn't suffer from this)
					if (destinationObj != draggablePortlets[no]["obj"].parentNode)
					{
						destinationObj = draggablePortlets[no]["obj"].parentNode;
						draggablePortlets[no]["obj"].parentNode.appendChild(rectangleDiv);
					}	
					rectangleDiv.style.display = "block";	
					objFound = true;				
				}
			}
		}

		if (!objFound)
		{
			for (var no = 1; no <= numberOfColumns; no++)
			{
				if (!objFound)
				{
					var obj = document.getElementById(columnIDfixed + no);			
					var left = getLeftPos(obj) / 1;
					var width = obj.offsetWidth;

					// The mouse is (horizontally) inside the current column
					if (leftPos > left && leftPos < left + width)
					{
						// Prevent screen flicker in Fx and Opera (Safari doesn't suffer from this)
						if (destinationObj != obj)
						{
							destinationObj = obj;
							obj.appendChild(rectangleDiv);
						}
						rectangleDiv.style.display = "block";
						objFound = true;
					}				
				}
			}
		}

		setTimeout("okToMove = true", 5);
	}

	function stopDragDropElement()
	{
		if (dragDropCounter < 10)
		{
			dragDropCounter = -1
			return;
		}
		dragDropCounter = -1;

		if (transparencyWhenDragging)
		{
			dragObject.style.filter = null;
			// For Opera (can't handle 'null' here)
			dragObject.style.opacity = "";
		}

		dragObject.style.position = "static";
		dragObject.style.width = null;
		dragObject.style.borderColor = "silver";
		var numericId = getIDNumberFromName(dragObject.id);

		if (destinationObj &&
			destinationObj.id != dragObject.id)
		{
			if (destinationObj.id.indexOf(columnIDfixed) >= 0)
			{
				destinationObj.appendChild(dragObject);
				draggablePortlets[numericId - 1]["parentObj"] = destinationObj;
			}
			else if (destinationObj.parentNode.id.indexOf(columnIDfixed) >= 0)
			{
				destinationObj.parentNode.insertBefore(dragObject,destinationObj);
				draggablePortlets[numericId - 1]["parentObj"] = destinationObj.parentNode;
			}
		}
		else
		{
			if (dragObjectNextSibling)
			{
				dragObjectParent.insertBefore(dragObject, dragObjectNextSibling);	
			}
			else
			{
				dragObjectParent.appendChild(dragObject);
			}				
		}

		autoScrollActive = false;
		rectangleDiv.style.display = "none"; 
		dragObject = false;
		dragObjectNextSibling = false;
		destinationObj = false;

		if (useCookieToRememberPortlets)
		{
			setTimeout("savePortletsCookie()", 100);
		}

		documentHeight = document.documentElement.clientHeight;	
	}

	function savePortletsCookie()
	{
		var cookieString = "";

		// '0' is the default case (rotate colours) and we won't add anything to the cookie string
		if (mainColourIndex != 0)
		{
			cookieString += mainColourIndex;
		}

		for (var columnIndex = 1; columnIndex <= numberOfColumns; columnIndex++)
		{
			var parentObj = document.getElementById(columnIDfixed + columnIndex);

			var divItems = parentObj.getElementsByTagName("div");
			// Empty column
			if (divItems.length == 0)
			{
				// Means 'end of column'
				cookieString += "*";
				continue;
			}

			var divItemIDs = new Array();

			// First div should always be of class 'pageBlock'
			var nextDiv = divItems[0];

			while (nextDiv != null)
			{
				// Make sure it's one of the draggable portlets
				if (nextDiv.id != null &&
					nextDiv.id.substring(0, portletIDfixed.length) == portletIDfixed)
				{
					var blockIndex = getIDNumberFromName(nextDiv.id);
					if (nextDiv.id != "rectangleDiv")
					{
						divItemIDs[divItemIDs.length] = blockIndex;
					}
				}

				// Find the next 'div' sibling, skipping text nodes (nodeType 3)
				do
				{
					nextDiv = nextDiv.nextSibling;
				}			
				while (nextDiv != null &&
					nextDiv.nodeType == 3);
			}

			for (var divIndex = 0; divIndex < divItemIDs.length; divIndex++)
			{
				// Index for 'draggablePortlets' is 0-based
				var blockIndex = divItemIDs[divIndex] - 1;
				var contentCodes = draggablePortlets[blockIndex]["contentCodes"];
				var isOpened = draggablePortlets[blockIndex]["expandedState"];
				cookieString += isOpened ? "+" : "-";
				for (var i = 0; i < contentCodes.length; i++)
				{
					cookieString += contentCodes[i];
					var numberOfItems = draggablePortlets[blockIndex]["numberOfItems"][i];
					var defaultNumberOfItems = -1;
					if (i == 0)
					{
						defaultNumberOfItems = getPortletInfo(contentCodes[0]).defaultNumberOfItems;
					}
					else
					{
						defaultNumberOfItems = getPortletSubItemInfo(contentCodes[0], contentCodes[i]).defaultNumberOfItems;
					}
					// Don't save the default value
					if (numberOfItems != null &&
						numberOfItems != defaultNumberOfItems)
					{
						cookieString += numberOfItems;
					}
				}
			}

			// End of column
			cookieString += "*";
		}

		// Expire after 3000 days (a bit more than 8 years)
		setCookie(PORTLETS_COOKIE_NAME, cookieString, 3000);
	}

	function getIDNumberFromName(name)
	{
		return name.replace(/[^0-9]/g, "");
	}

	function getTopPos(inputObj)
	{		
		var returnValue = inputObj.offsetTop;
		while ((inputObj = inputObj.offsetParent) != null)
		{
			if (inputObj.tagName != "html")
			{
				returnValue += inputObj.offsetTop;
			}
		}
		return returnValue;
	}

	function getLeftPos(inputObj)
	{
		var returnValue = inputObj.offsetLeft;
		while((inputObj = inputObj.offsetParent) != null)
		{
			if (inputObj.tagName != "html")
			{
				returnValue += inputObj.offsetLeft;
			}
		}
		return returnValue;
	}

	function createHelpObjects()
	{
		// Creating helper div for visual feedback of drop target
		rectangleDiv = document.createElement("div");
		rectangleDiv.id = "rectangleDiv";
		rectangleDiv.style.display = "none";

		document.body.appendChild(rectangleDiv);
	}

	function cancelSelectionEvent(e)
	{
		if (document.all)
		{
			e = event;
		}

		if (e.target)
		{
			source = e.target;
		}
		else if (e.srcElement)
		{
			source = e.srcElement;
		}

		if (source.nodeType == 3) // defeat Safari bug
		{
			source = source.parentNode;
		}
		if (source.tagName.toLowerCase() == "input")
		{
			return true;
		}

		if (dragDropCounter >= 0)
		{
			return false;
		}
		else
		{
			return true;
		}	
	}

	function cancelEvent()
	{
		return false;
	}

	function initEvents()
	{
		document.body.onmousemove = moveDragableElement;
		document.body.onmouseup = stopDragDropElement;
		document.body.onselectstart = cancelSelectionEvent;
		document.body.ondragstart = cancelEvent;	

		documentHeight = document.documentElement.clientHeight;
	}

	function createPortletsFromCookie()
	{
		var columnNumber = 1;
		var contentCodes;
		var numberOfItems;
		var isOpened;
		var startIndex = 0;
		var newCookie = false;

		var cookieValue = getCookie(PORTLETS_COOKIE_NAME);

		if (cookieValue == null ||
			cookieValue == "")
		{
			newCookie = true;
			// In case there's no cookie supply default settings
			cookieValue = DEFAULT_PORTLETS_COOKIE;
		}

		// Check for a number at the start, indicating a selected colour
		while (cookieValue.charAt(startIndex) >= '0' &&
			cookieValue.charAt(startIndex) <= '9')
		{
			startIndex++;
		}
		if (startIndex > 0)
		{
			mainColourIndex = Number(cookieValue.substring(0, startIndex));
		}

		var arrayIndex = 0;
		var columnPosition = 0;

		for (var index = startIndex; index < cookieValue.length; )
		{
			if (cookieValue.charAt(index) == '-' ||
				cookieValue.charAt(index) == '+')
			{
				isOpened = cookieValue.charAt(index) == '+';
				index++;
				contentCodes = new Array();
				numberOfItems = new Array();
				var contentIndex = 0;
				while (cookieValue.charAt(index) >= 'a' &&
					cookieValue.charAt(index) <= 'z')
				{
					contentCodes[contentIndex] = cookieValue.charAt(index);
					index++;
					if (cookieValue.charAt(index) >= '0' &&
						cookieValue.charAt(index) <= '9')
					{
						var beginNumberIndex = index;
						while (cookieValue.charAt(index) >= '0' &&
							cookieValue.charAt(index) <= '9')
						{
							index++;
						}
						numberOfItems[contentIndex] = Number(cookieValue.substring(beginNumberIndex, index));
					}
					else
					{
						// Set the default value for 'numberOfItems'
						if (contentIndex == 0)
						{
							numberOfItems[contentIndex] = getPortletInfo(contentCodes[0]).defaultNumberOfItems;
						}
						else
						{
							numberOfItems[contentIndex] = getPortletSubItemInfo(contentCodes[0], contentCodes[contentIndex]).defaultNumberOfItems;
						}
					}
					contentIndex++;
				}
				createAPortlet(arrayIndex++, columnNumber, columnPosition++, contentCodes, numberOfItems, isOpened);
			}
			else if (cookieValue.charAt(index) == '*')
			{
				// Skip this char
				index++;
				columnNumber++;
				if (columnNumber > numberOfColumns)
				{
					break;
				}
			}
			else
			{
				// Error in cookie syntax
				break;
			}
		}

		if (newCookie)
		{
			savePortletsCookie();
		}
	}

	function createOptionsBlock(blockDiv, contentCodes)
	{
		var optionsDiv = document.createElement("div");
		optionsDiv.className = "itemOptions";
		blockDiv.appendChild(optionsDiv);

		var listLeft = document.createElement("ul");
		optionsDiv.appendChild(listLeft);
		var listRight = document.createElement("ul");
		optionsDiv.appendChild(listRight);

		var listItem;
		var inputItem;
		var labelItem;
		var textItem;
		var subItemCodes = getPortletInfo(contentCodes[0]).subItems;
		for (var i = 0; i < subItemCodes.length; i++)
		{
			var itemInfo = getPortletSubItemInfo(contentCodes[0], subItemCodes[i]);

			listItem = document.createElement("li");
			inputItem = document.createElement("input");
			inputItem.type = "checkbox";
			inputItem.id = "option_" + subItemCodes[i];
			inputItem.value = subItemCodes[i];
			inputItem.onclick = toggleOptionsCheckbox;
			// For IE we need to append the element _before_ we set the checked state, otherwise it will not be reflected in the GUI
			listItem.appendChild(inputItem);
			inputItem.checked = getIndexPosOfElement(contentCodes.slice(1), subItemCodes[i]) != -1;

			labelItem = document.createElement("label");
			labelItem.htmlFor = "option_" + subItemCodes[i];

			textItem = document.createTextNode(itemInfo.title);
			labelItem.appendChild(textItem);
			listItem.appendChild(labelItem);
			if (i % 2 == 0)
			{
				listLeft.appendChild(listItem);
			}
			else
			{
				listRight.appendChild(listItem);
			}
		} 

		var clearDiv = document.createElement("div");
		clearDiv.className = "clearFix";
		optionsDiv.appendChild(clearDiv);
	}

	function createBrowseButtons(titleDiv)
	{
		// Create and add the button that makes it possible to browse backward through the pictures
		var previousButton = document.createElement("a");
		previousButton.className = "prevTT";
		previousButton.href = "javascript:void(0)";
		previousButton.title = "Vorige pagina";
		previousButton.onclick = browseTT;
		titleDiv.appendChild(previousButton);

		// Create and add the button that makes it possible to browse forward through the pictures
		var nextButton = document.createElement("a");
		nextButton.className = "nextTT";
		nextButton.href = "javascript:void(0)";
		nextButton.title = "Volgende pagina";
		nextButton.onclick = browseTT;
		titleDiv.appendChild(nextButton);
	}

	function createPlusMinusButtons(titleDiv)
	{
		// Create and add the button that makes it possible to increase the number of items visible in the list
		var addButton = document.createElement("a");
		addButton.className = "add";
		addButton.href = "javascript:void(0)";
		addButton.onclick = addItem;
		addButton.style.backgroundRepeat = "no-repeat";
		titleDiv.appendChild(addButton);

		// Create and add the button that makes it possible to decrease the number of items visible in the list
		var removeButton = document.createElement("a");
		removeButton.className = "remove";
		removeButton.href = "javascript:void(0)";
		removeButton.onclick = removeItem;
		removeButton.style.backgroundRepeat = "no-repeat";
		titleDiv.appendChild(removeButton);
	}

	// Create a sub item block within the main block
	function createASubItem(contentDiv, insertBeforeElement, title, link, contentString, isCanChangeNumber)
	{
		var subItemDiv = document.createElement("div");
		subItemDiv.className = "subItem" + " contentFor_" + contentString;

		if (insertBeforeElement == null)
		{
			contentDiv.appendChild(subItemDiv);
		}
		else
		{
			insertBeforeElement.parentNode.insertBefore(subItemDiv, insertBeforeElement);
		}

		var subItemTitleDiv = document.createElement("div");
		subItemTitleDiv.className = "itemTitle";
		var header = document.createElement("h5");
		var titleLink = document.createElement("a");
		if (link != null)
		{
			titleLink.href = link;
		}
		var headerText = document.createTextNode(title);
		titleLink.appendChild(headerText);
		header.appendChild(titleLink);
		subItemTitleDiv.appendChild(header);
		subItemDiv.appendChild(subItemTitleDiv);

		if (isCanChangeNumber)
		{
			createPlusMinusButtons(subItemTitleDiv);
		}

		return subItemDiv;
	}

	function createASpinnerImage(containerDiv)
	{
		var spinnerImage = document.createElement("img");
		spinnerImage.src = resourcePath + "/images/spinner.gif";
		spinnerImage.className = "spinner";
		containerDiv.appendChild(spinnerImage);
	}

	function createAImageBrowseItemBlock(containerDiv)
	{
		var image = document.createElement("img");
		containerDiv.appendChild(image);
	}

	function createAHTMLItemBlock(containerDiv, numberOfVisibleItems, maxItems)
	{
		for (var i = 0; i < maxItems; i++)
		{
			if (maxItems > 1)
			{
				var titleDiv = document.createElement("div");
				var header = document.createElement("h5");
				var anchor = document.createElement("a");
				anchor.href = "javascript:void(0)";
				var anchorText = document.createTextNode("");
				anchor.appendChild(anchorText);
				header.appendChild(anchor);
				titleDiv.appendChild(header);
				titleDiv.className = "itemTitle hidden";
				containerDiv.appendChild(titleDiv);
			}

			var contentDiv = document.createElement("div");
			contentDiv.className = "itemContent hidden";
			containerDiv.appendChild(contentDiv);
		}
	}

	function createAItemList(containerDiv, numberOfVisibleItems, maxItems)
	{
		var list = document.createElement("ul");
		for (var i = 0; i < maxItems; i++)
		{
			var listItem = document.createElement("li");
			var moreInfoLink = document.createElement("a");
			moreInfoLink.href = "javascript:void(0)";
			// Add two text nodes, separated by a 'br' element to the anchor, so
			// as to have an optional second line available
			// The first text node is inside a 'span' element so we can style it differently
			var span = document.createElement("span");
			var linkText = document.createTextNode("");
			span.appendChild(linkText);
			moreInfoLink.appendChild(span);
			var breakElement = document.createElement("br");
			moreInfoLink.appendChild(breakElement);
			linkText = document.createTextNode("");
			moreInfoLink.appendChild(linkText);
			listItem.appendChild(moreInfoLink);
			listItem.className = "hidden";
			list.appendChild(listItem);
		}
		containerDiv.appendChild(list);
	}

	function createAPortlet(arrayIndex, columnNumber, columnPosition, contentCodes, numberOfItems, isOpened)
	{
		var portletInfo = getPortletInfo(contentCodes[0]);
		var columnDiv = document.getElementById(columnIDfixed + columnNumber);

		var mainBlockDiv = document.createElement("div");
		mainBlockDiv.className = "pageBlock";
		if (portletInfo.type == portletTypes.imageBrowse)
		{
			mainBlockDiv.className += " imageBrowser";
		}
		// We don't want to use a 0-based index in the name
		mainBlockDiv.id = portletIDfixed + (arrayIndex + 1);

		// Create and add the (possibly draggable) title bar
		var titleBarDiv = document.createElement("div");
		titleBarDiv.className = "titleOfBlock";
		if (portletInfo.moveable)
		{
			titleBarDiv.onmousedown = initDragDropBox;
			titleBarDiv.style.cursor = "move";
		}
		mainBlockDiv.appendChild(titleBarDiv);

		if (portletInfo.collapseable)
		{
			// Create and add the toggler button that makes it possible to collapse and expand the portlet
			var toggleButton = document.createElement("a");
			// We don't use an anchor ('#') here, because that would cause scrolling of the page
			toggleButton.className = "toggler";
			toggleButton.href = "javascript:void(0)";
			toggleButton.onclick = toggleView;
			if (isOpened)
			{
				toggleButton.style.backgroundImage = "url(\"" + resourcePath + "/images/smallArrowDown.gif\")";
			}
			else
			{
				toggleButton.style.backgroundImage = "url(\"" + resourcePath + "/images/smallArrowRight.gif\")";
			}
			titleBarDiv.appendChild(toggleButton);
		}

		// Create and add the title that links to more general info
		var header = document.createElement("h4");
		var titleLink = document.createElement("a");
		titleLink.href = portletInfo.link;
		var headerText = document.createTextNode(portletInfo.title);
		titleLink.appendChild(headerText);
		header.appendChild(titleLink);
		titleBarDiv.appendChild(header);

		// In case there are no options (sub items) for this portlet, don't put an edit button in the title bar
		var hasSubItems = portletInfo.subItems.length > 0;
		if (!hasSubItems)
		{
			if (portletInfo.changeNumber)
			{
				createPlusMinusButtons(titleBarDiv);
			}
			else if (portletInfo.type == portletTypes.imageBrowse)
			{
				createBrowseButtons(titleBarDiv);
			}
		}
		else
		{
			// Add the 'Wijzig' button for adding and removing topics to the upper-right corner of the title bar
			var editButton = document.createElement("a");
			editButton.className = "edit";
			editButton.href = "javascript:void(0)";
			editButton.onclick = editItems;
			titleBarDiv.appendChild(editButton);

			createOptionsBlock(mainBlockDiv, contentCodes);
		}

		if ((portletInfo.type == portletTypes.standard ||
			portletInfo.type == portletTypes.standardPlusTopImage ||
			portletInfo.type == portletTypes.standardPlusRollOvers) &&
			portletInfo.partialCollapse)
		{
			// Use a separate div here for the rollover items/top image and use the enclosing 'div' blocks for the slide effect for the next part
			var contentDiv = document.createElement("div");
			contentDiv.className = "nonHideableBlockContent";
			mainBlockDiv.appendChild(contentDiv);
		}
		else
		{
			// Use two 'div' blocks in order to enable the 'slide' effect on expanding and collapsing the portlet
			var slideDiv = document.createElement("div");
			slideDiv.className = "slideArea";
			var contentDiv = document.createElement("div");
			contentDiv.className = "blockContent";
		}

		// For the time being and for simplicity's sake we add the rollover items even if we don't use them (they will stay hidden)
		if (portletInfo.type == portletTypes.standard ||
			portletInfo.type == portletTypes.standardPlusRollOvers)
		{
			// Create a div that holds any rollover image items
			var rolloverImageDiv = document.createElement("div");
			rolloverImageDiv.className = "rolloverImage";

			var imageItem;
			var listItem;
			var linkText;
			var moreInfoLink;
			moreInfoLink = document.createElement("a");
			// Create an extra div in order to center the resized picture with the same aspect-ratio
			// and fill the non-used space with a background colour
			var imageSpacerDiv = document.createElement("div");
			imageSpacerDiv.className = "imageSpacer";
			moreInfoLink.appendChild(imageSpacerDiv);
			// Create 3 'img' elements, but show only the first
			for (var i = 0; i < 3; i++)
			{
				imageItem = document.createElement("img");
				if (i > 0)
				{
					imageItem.style.display = "none";
				}
				imageSpacerDiv.appendChild(imageItem);
			}
			var clearFixDiv = document.createElement("div");
			clearFixDiv.className = "clearFix";
			imageSpacerDiv.appendChild(clearFixDiv);
			rolloverImageDiv.appendChild(moreInfoLink);
			// Create a list with 3 anchors, each with a text node
			var list = document.createElement("ul");
			for (var i = 0; i < 3; i++)
			{
				listItem = document.createElement("li");
				if (i == 0)
				{
					listItem.className = "active";
				}
				listItem.onmouseover = showRolloverImage;
				moreInfoLink = document.createElement("a");
				linkText = document.createTextNode("");
				moreInfoLink.appendChild(linkText);
				listItem.appendChild(moreInfoLink);
				list.appendChild(listItem);
			}
			rolloverImageDiv.appendChild(list);
			clearFixDiv = document.createElement("div");
			clearFixDiv.className = "clearFix";
			rolloverImageDiv.appendChild(clearFixDiv);
			contentDiv.appendChild(rolloverImageDiv);
		}
		else if (portletInfo.type == portletTypes.standardPlusTopImage)
		{
			// Create a div that holds the fixed image
			var imageDiv = document.createElement("div");
			imageDiv.className = "topImage";

			// Create an extra div in order to center the resized picture with the same aspect-ratio
			// and fill the non-used space with a background colour
			var imageSpacerDiv = document.createElement("div");
			imageSpacerDiv.className = "imageSpacer";
			var imageItem = document.createElement("img");
			imageSpacerDiv.appendChild(imageItem);
			imageDiv.appendChild(imageSpacerDiv);
			contentDiv.appendChild(imageDiv);
		}

		if ((portletInfo.type == portletTypes.standard ||
			portletInfo.type == portletTypes.standardPlusRollOvers ||
			portletInfo.type == portletTypes.standardPlusTopImage) &&
			portletInfo.partialCollapse)
		{
			// Use two 'div' blocks in order to enable the 'slide' effect on expanding and collapsing the portlet
			var slideDiv = document.createElement("div");
			slideDiv.className = "slideArea";
			var contentDiv = document.createElement("div");
			contentDiv.className = "blockContent";
		}

		var startIndex = 0;
		if (hasSubItems)
		{
			// Skip the first contentCode, which just signifies the type for the main block
			startIndex = 1;
		}
		else
		{
			// Make sure there is a unique class name for every content type
			// (for sub items this is set on its enclosing div)
			contentDiv.className += " contentFor_" + contentCodes[0];
		}

		for (var i = startIndex; i < contentCodes.length; i++)
		{
			var subItemDiv = null;
			var subItemInfo = null;
			if (hasSubItems)
			{
				subItemInfo = getPortletSubItemInfo(contentCodes[0], contentCodes[i]);
				if (subItemInfo != null)
				{
					subItemDiv = createASubItem(contentDiv, null, subItemInfo.title, subItemInfo.link, contentCodes[0] + contentCodes[i], subItemInfo.changeNumber);
				}
			}

			// Have the content show an animated 'spinner' image, indicating that we are busy loading
			createASpinnerImage(hasSubItems ? subItemDiv : contentDiv);

			switch(portletInfo.type)
			{
			case portletTypes.standard: // Fall through!
			case portletTypes.standardPlusRollOvers:
			case portletTypes.standardPlusTopImage:
				// Create the list with text items (which are also links to the article for which they represent the title)
				createAItemList(hasSubItems ? subItemDiv : contentDiv, numberOfItems[i], hasSubItems ? subItemInfo.maxNumberOfItems : portletInfo.maxNumberOfItems);
				break;
			case portletTypes.htmlItems:
				createAHTMLItemBlock(contentDiv, numberOfItems[i], portletInfo.maxNumberOfItems);
				break;
			case portletTypes.imageBrowse:
				createAImageBrowseItemBlock(contentDiv);
				break;
			default:
				// Nothing, for the moment
			}
		}

		slideDiv.appendChild(contentDiv);
		mainBlockDiv.appendChild(slideDiv);

		if (isOpened)
		{
			contentDiv.style.display = "block";
		}
		else
		{
			if (portletInfo.type == portletTypes.imageBrowse &&
				portletInfo.partialCollapse)
			{
				contentDiv.style.top = -partialCollapseOffset + "px";
				slideDiv.style.height = partialCollapseHeight + "px";
			}
			else
			{
				// We need to set the display style to 'none' here because this is used when expanding/collapsing the portlet
				contentDiv.style.display = "none";
				slideDiv.style.height = "0px";
			}
		}

		// Find the divs in this column that represent the already present portlets
		// in order to decide where to place the new portlet
		var subDivs = columnDiv.getElementsByTagName("div");
		var columnPortlets = new Array();
		for (var index = 0; index < subDivs.length; index++)
		{
			// Just consider moveable portlets
			if (subDivs[index].id.indexOf(portletIDfixed) == 0)
			{
				var classNames = subDivs[index].className.split(" ");
				if (classNames != null)
				{
					for (var i = 0; i < classNames.length; i++)
					{
						if (classNames[i] == "pageBlock")
						{
							columnPortlets[columnPortlets.length] = subDivs[index];
						}
					}
				}
			}
		}

		// Place the new portlet in its column
		if (columnPortlets.length > 0 && columnPosition < columnPortlets.length)
		{
			columnDiv.insertBefore(mainBlockDiv, columnPortlets[columnPosition]);
		}
		else
		{
			columnDiv.appendChild(mainBlockDiv);
		}

		draggablePortlets[arrayIndex] = new Array();
		draggablePortlets[arrayIndex]["obj"] = mainBlockDiv;
		draggablePortlets[arrayIndex]["parentObj"] = mainBlockDiv.parentNode;
		draggablePortlets[arrayIndex]["contentCodes"] = contentCodes;
		draggablePortlets[arrayIndex]["expandedState"] = isOpened ? 1 : 0;
		draggablePortlets[arrayIndex]["numberOfItems"] = numberOfItems;
		draggablePortlets[arrayIndex]["itemProvider"] = new AutoUpdater(mainBlockDiv, arrayIndex + 1, contentCodes, updateProvider);
		updateProvider.addBlock(draggablePortlets[arrayIndex]["itemProvider"]);
	}

	function adjustButtonImages(plusButton, minusButton, numberOfVisibleItems, numberOfItems)
	{
		if (numberOfVisibleItems < numberOfItems)
		{
			// Make the add button look enabled
			plusButton.style.backgroundImage = "url(\"" + resourcePath + "/" + plusButtonImagePath + "\")";
			// Also make sure the 'hand' cursor will show while hovering
			plusButton.style.cursor = "pointer";
		}
		else
		{
			// Make the add button look disabled
			plusButton.style.backgroundImage = "url(\"" + resourcePath + "/" + plusButtonDisabledImagePath + "\")";
			// Also make sure the 'hand' cursor will _not_ show while hovering
			plusButton.style.cursor = "default";
		}

		if (numberOfVisibleItems > 1)
		{
			// Make the subtract button look enabled
			minusButton.style.backgroundImage = "url(\"" + resourcePath + "/" + minusButtonImagePath + "\")";
			// Also make sure the 'hand' cursor will show while hovering
			minusButton.style.cursor = "pointer";
		}
		else
		{
			// Make the subtract button look disabled
			minusButton.style.backgroundImage = "url(\"" + resourcePath + "/" + minusButtonDisabledImagePath + "\")";
			// Also make sure the 'hand' cursor will _not_ show while hovering
			minusButton.style.cursor = "default";
		}
	}

	function showRolloverImage()
	{
		var listItems = this.parentNode.childNodes;
		var images = this.parentNode.parentNode.getElementsByTagName("img");
		var imageAnchor = this.parentNode.parentNode.getElementsByTagName("a")[0];

		for (var i = 0; i < images.length && i < listItems.length; i++)
		{
			if (listItems[i] == this)
			{
				// Set the destination of the image anchor to that of the selected item
				imageAnchor.href = listItems[i].firstChild.href;
				images[i].style.display = "inline";
				listItems[i].className = "active";
			}
			else
			{
				images[i].style.display = "none";
				listItems[i].className = null;
			}
		}
	}

	function insertAfter(newElement, targetElement)
	{
		var parent = targetElement.parentNode;

		// If the parent's last child is the target element...
		if (parent.lastchild == targetElement)
		{
			// Add the new element after the target element
			parent.appendChild(newElement);
		}
		else
		{
			// If the target has siblings, insert the new element between the target and its next sibling
			parent.insertBefore(newElement, targetElement.nextSibling);
		}
	}

	function getElementsWithClassName(elementList, className, maxItems)
	{
		var foundItems = new Array();
		for (var index = 0; index < elementList.length && foundItems.length < maxItems; index++)
		{
			if (containsClassName(elementList[index].className, className))
			{
				// Append it to the list
				foundItems[foundItems.length] = elementList[index];
			}
		}
		return foundItems;
	}

	function containsClassName(classesString, className)
	{
		var classNames = classesString.split(" ");
		if (classNames != null)
		{
			for (var i = 0; i < classNames.length; i++)
			{
				if (classNames[i] == className)
				{
					return true;
				}
			}
		}
		return false;
	}

	function ToggleShowMore(buttonImage, listName)
	{
		// Get the list item after this one (the one with the image button)
		var listItem = buttonImage.parentNode.nextSibling;
		var doShow = true;

		if (listItem != null &&
			listItem.nodeType == 3)
		{
			// Skip text node
			listItem = listItem.nextSibling
		}
		if (listItem != null &&
			listItem.className == "")
		{
			doShow = false;
		}
		// Change the button image and its details
		if (doShow)
		{
			buttonImage.src = "001/images/b_min.gif";
			buttonImage.alt = "Toon minder " + listName;
			buttonImage.title = buttonImage.alt;
		}
		else
		{
			if (listName == "boeken")
			{
				buttonImage.src = "001/images/b_plus_meer_titels.gif";
			}
			else
			{
				buttonImage.src = "001/images/b_plus.gif";
			}
			buttonImage.alt = "Toon meer " + listName;
			buttonImage.title = buttonImage.alt;
		}
		// Show or hide the list items below the button
		while (listItem != null)
		{
			if (doShow)
			{
				listItem.className = "";
			}
			else
			{
				listItem.className = "outOfSight";
			}
			listItem = listItem.nextSibling;
			if (listItem != null &&
				listItem.nodeType == 3)
			{
				// Skip text node
				listItem = listItem.nextSibling
			}
		}
		// Adjust the height of column 3 to make sure it is always more than that of the fixed portlet
		adjustColumn3ToFixedPortlets();
	}

	// New version with jQuery for Leestips
	function ToggleShowMoreJq(buttonImage, listName)
	{
		// Get the list item after this one (the one with the image button)
		var listItem = buttonImage.parentNode.nextSibling;
		var doShow = false;

		// Find our parent container ul or ol or <div class="textDetail"></div> 
		var par;

		if (listName == "leestips")
		{
			par = $(buttonImage).closest("ul,ol");
		}
		else
		{
			par = $(buttonImage).closest("div.textDetail");
		}

		if ($(par).find(".outOfSight:hidden").length > 0)
		{
			doShow = true;
		}

		// Change the button image and its details
		if (doShow)
		{
			buttonImage.src = "001/images/b_min.gif";
			buttonImage.alt = "Toon minder " + listName;
			buttonImage.title = buttonImage.alt;
		}
		else
		{
			if (listName == "boeken")
			{
				buttonImage.src = "001/images/b_plus_meer_titels.gif";
			}
			else
			{
				buttonImage.src = "001/images/b_plus.gif";
			}
			buttonImage.alt = "Toon meer " + listName;
			buttonImage.title = buttonImage.alt;
		}

		// Show or hide the list items below the button		
		if (doShow)
		{
			$(par).find(".outOfSight").show();
		}
		else
		{
			$(par).find(".outOfSight").hide();
		}

		// Adjust the height of column 3 to make sure it is always more than that of the fixed portlet
		adjustColumn3ToFixedPortlets();
	}

	function toggleView(that)
	{
		var me = null;

		if (that !== undefined &&
			that.type != "click")
		{
			me = that;
		}
		else
		{
			me = this;
		}

		var mainDiv = me.parentNode.parentNode;
		var numericId = getIDNumberFromName(mainDiv.id);
		var portletInfo = getPortletInfo(draggablePortlets[numericId - 1]["contentCodes"][0]);
		var minHeight = undefined;
		var maxOffset = undefined;
		if (portletInfo.type == portletTypes.imageBrowse &&
			portletInfo.partialCollapse)
		{
			minHeight = partialCollapseHeight;
			maxOffset = partialCollapseOffset;
		}
		var divs = mainDiv.getElementsByTagName("div");
		var contentDiv = getElementsWithClassName(divs, "blockContent", 1)[0];
		// Block collapsed?
		if (contentDiv.style.display == "none" ||
			(portletInfo.type == portletTypes.imageBrowse &&
			portletInfo.partialCollapse &&
			contentDiv.parentNode.style.height == partialCollapseHeight + "px"))
		{
			showHideContent(contentDiv, true, minHeight, maxOffset);
			me.style.backgroundImage = "url(\"" + resourcePath + "/images/smallArrowDown.gif\")";
			// Array is 0-based
			draggablePortlets[numericId - 1]["expandedState"] = 1;
		}
		else
		{
			showHideContent(contentDiv, false, minHeight, maxOffset);
			me.style.backgroundImage = "url(\"" + resourcePath + "/images/smallArrowRight.gif\")";
			// Array is 0-based
			draggablePortlets[numericId - 1]["expandedState"] = 0;
		}

		if (useCookieToRememberPortlets)
		{
			savePortletsCookie();
		}
	}

	function browseTT()
	{
		var offset = 0;
		if (this.className == "nextTT")
		{
			offset = 1;
		}
		else if (this.className == "prevTT")
		{
			offset = -1;
		}
		var images = this.parentNode.parentNode.getElementsByTagName("img");
		// Make sure we don't use the 'spinner' image
		var images = getElementsWithClassName(images, "", 99);
		var visibleImage = -1;

		for (var i = 0; i < images.length &&
			visibleImage == -1; i++)
		{
			if (images[i].style.display != "none")
			{
				visibleImage = i;
			}
		}
		// One image should be visible
		if (visibleImage != -1)
		{
			var desiredImage = visibleImage + offset;
			if (desiredImage >= 0 &&
				desiredImage < images.length)
			{
				images[visibleImage].style.display = "none";
				images[desiredImage].style.display = "block";
				var prevLink = null;
				var nextLink = null;
				if (desiredImage < visibleImage)
				{
					prevLink = this;
					if (this.nextSibling.nodeType != 3)
					{
						nextLink = this.nextSibling;
					}
					else
					{
						// We skip the text node
						nextLink = this.nextSibling.nextSibling;
					}
				}
				else
				{
					nextLink = this;
					if (this.previousSibling.nodeType != 3)
					{
						prevLink = this.previousSibling;
					}
					else
					{
						// We skip the text node
						prevLink = this.previousSibling.previousSibling;
					}
				}
				if (desiredImage == 0)
				{
					prevLink.style.backgroundImage = "url(\"" + resourcePath + "/images/prevTTButtonDisabled.gif\")";
					// Also make sure the 'hand' cursor will _not_ show while hovering
					prevLink.style.cursor = "default";
				}
				else
				{
					prevLink.style.backgroundImage = "url(\"" + resourcePath + "/images/prevTTButton.gif\")";
					// Also make sure the 'hand' cursor will show while hovering
					prevLink.style.cursor = "pointer";
				}
				if (desiredImage == images.length - 1)
				{
					nextLink.style.backgroundImage = "url(\"" + resourcePath + "/images/nextTTButtonDisabled.gif\")";
					// Also make sure the 'hand' cursor will _not_ show while hovering
					nextLink.style.cursor = "default";
				}
				else
				{
					nextLink.style.backgroundImage = "url(\"" + resourcePath + "/images/nextTTButton.gif\")";
					// Also make sure the 'hand' cursor will show while hovering
					nextLink.style.cursor = "pointer";
				}
			}
		}
	}

	function getIndexPosOfElement(listOfElements, element)
	{
		for (var i = 0; i < listOfElements.length; i++)
		{
			if (element == listOfElements[i])
			{
				return i;
			}
		}
		return -1;
	}

	function addItem()
	{
		var mainDiv = this.parentNode.parentNode;
		var indexPos = 0;
		var numericId = -1;
		var itemInfo = null;
		if (containsClassName(mainDiv.className, "subItem"))
		{
			numericId = getIDNumberFromName(mainDiv.parentNode.parentNode.parentNode.id);
			// Find out the position of this sub item block
			var subItemDivs = getElementsWithClassName(mainDiv.parentNode.getElementsByTagName("div"), "subItem", 20);
			// We have to add 1 to the index position because we must skip the main block code
			indexPos = getIndexPosOfElement(subItemDivs, mainDiv) + 1;
			itemInfo = getPortletSubItemInfo(draggablePortlets[numericId - 1]["contentCodes"][0], draggablePortlets[numericId - 1]["contentCodes"][indexPos]);
		}
		else
		{
			numericId = getIDNumberFromName(mainDiv.id);
			itemInfo = getPortletInfo(draggablePortlets[numericId - 1]["contentCodes"][0]);
		}
		var unorderedLists = mainDiv.getElementsByTagName("ul");
		// Refer to the last UL in this DIV
		var itemList = unorderedLists[unorderedLists.length - 1];
		var items = itemList.getElementsByTagName("li");
		var numberOfItems = Number(draggablePortlets[numericId - 1]["numberOfItems"][indexPos]);
		// Suppress addition of empty items (those for which no data was available)
		if (numberOfItems < itemInfo.maxNumberOfItems &&	
			items[numberOfItems].firstChild.firstChild.firstChild.nodeValue != "")
		{
			// Unhide the next item
			items[numberOfItems].className = null;
			numberOfItems++;
			draggablePortlets[numericId - 1]["numberOfItems"][indexPos] = numberOfItems;
			if (useCookieToRememberPortlets)
			{
				savePortletsCookie();
			}

			if (numberOfItems == itemInfo.maxNumberOfItems ||
				items[numberOfItems].firstChild.firstChild.firstChild.nodeValue == "")
			{
				// Make this button look disabled
				this.style.backgroundImage = "url(\"" + resourcePath + "/" + plusButtonDisabledImagePath + "\")";
				// Also make sure the 'hand' cursor will _not_ show while hovering
				this.style.cursor = "default";
			}
			// Make sure the button for removal isn't disabled (anymore)
			this.nextSibling.style.backgroundImage = "url(\"" + resourcePath + "/" + minusButtonImagePath + "\")";
			// Also make sure the 'hand' cursor will show while hovering
			this.nextSibling.style.cursor = "pointer";
		}
	}

	function removeItem()
	{
		var mainDiv = this.parentNode.parentNode;
		var indexPos = 0;
		var numericId = -1;
		if (containsClassName(mainDiv.className, "subItem"))
		{
			// Find out the number of this sub item block
			var subItemDivs = getElementsWithClassName(mainDiv.parentNode.getElementsByTagName("div"), "subItem", 20);
			// We have to add 1 to the index position because we must skip the main block code
			indexPos = getIndexPosOfElement(subItemDivs, mainDiv) + 1;
			numericId = getIDNumberFromName(mainDiv.parentNode.parentNode.parentNode.id);
		}
		else
		{
			numericId = getIDNumberFromName(mainDiv.id);
		}
		var unorderedLists = mainDiv.getElementsByTagName("ul");
		// Refer to the last UL in this DIV
		var itemList = unorderedLists[unorderedLists.length - 1];
		var items = itemList.getElementsByTagName("li");
		var numberOfItems = Number(draggablePortlets[numericId - 1]["numberOfItems"][indexPos]);
		if (numberOfItems > 1)
		{
			// Hide the last item
			items[numberOfItems - 1].className = "hidden";
			numberOfItems--;
			draggablePortlets[numericId - 1]["numberOfItems"][indexPos] = numberOfItems;
			if (useCookieToRememberPortlets)
			{
				savePortletsCookie();
			}

			if (numberOfItems == 1)
			{
				// Make this button look disabled
				this.style.backgroundImage = "url(\"" + resourcePath + "/" + minusButtonDisabledImagePath + "\")";
				// Also make sure the 'hand' cursor will _not_ show while hovering
				this.style.cursor = "default";
			}
			// Make sure the button for adding isn't disabled (anymore)
			this.previousSibling.style.backgroundImage = "url(\"" + resourcePath + "/" + plusButtonImagePath + "\")";
			// Also make sure the 'hand' cursor will show while hovering
			this.previousSibling.style.cursor = "pointer";
		}
	}

	function editItems()
	{
		var mainDiv = this.parentNode.parentNode;
		var numericId = getIDNumberFromName(mainDiv.id);
		var optionsDiv = getElementsWithClassName(mainDiv.getElementsByTagName("div"), "itemOptions", 1)[0];
		if (optionsDiv != null)
		{
			if (optionsDiv.style.display == "block")
			{
				optionsDiv.style.display = "none";
			}
			else
			{
				optionsDiv.style.display = "block";
			}
		}

		// For IE 6, we need to set the 'checked' state even later! Well, actually 'just in time' (not to say at the last minute!)
		if (document.all &&
			typeof XMLHttpRequest == "undefined")
		{
			var blockContentCodes = draggablePortlets[numericId - 1]["contentCodes"];
			var inputItems = optionsDiv.getElementsByTagName("input");
			for (var i = 0; i < inputItems.length; i++)
			{
				inputItems[i].checked = getIndexPosOfElement(blockContentCodes.slice(1), inputItems[i].value) != -1;
			}
		}
	}

	function toggleOptionsCheckbox()
	{
		var contentCode = this.value;
		// Find the main div enclosing this block
		var mainDiv = this;
		do
		{
			mainDiv = mainDiv.parentNode;
		}
		while (mainDiv.className != "pageBlock" &&
			mainDiv.tagName != "html");
		var numericId = getIDNumberFromName(mainDiv.id);
		var blockContentCodes = draggablePortlets[numericId - 1]["contentCodes"];
		// Only check the part after the first index (so only the sub item codes)
		var oldIndexPos = getIndexPosOfElement(blockContentCodes.slice(1), contentCode) + 1;
		var possibleSubItemCodes = getPortletInfo(blockContentCodes[0]).subItems;
		var subDivsOfMain = mainDiv.getElementsByTagName("div");
		var newIndexPos = -1;

		var subItemDiv = null;
		// Existing sub item?
		if (oldIndexPos != 0)
		{
			// Get the div for the affected sub item block
			var subItemDivs = getElementsWithClassName(subDivsOfMain, "subItem", 20);
			// Subtract 1 from 'oldIndexPos', because the list of <div>'s is 0-based
			subItemDiv = subItemDivs[oldIndexPos - 1];
		}
		else
		{
			// Add the new code to the end for now
			blockContentCodes[blockContentCodes.length] = contentCode;
		}

		if (this.checked == true)
		{
			// Sanity check (to avoid worse in case we hit a referential integrity problem)
			if (oldIndexPos == 0)
			{
				var subItemInfo = null;
				// Add the new code into the correct position of the 'contentCodes' array
				// Build a new content codes array in order to get the codes in the correct order
				var newBlockContentCodes = new Array();
				// Begin with the main content code
				newBlockContentCodes[newBlockContentCodes.length] = blockContentCodes[0];
				for (var i = 0; i < possibleSubItemCodes.length; i++)
				{
					if (getIndexPosOfElement(blockContentCodes.slice(1), possibleSubItemCodes[i]) != -1)
					{
						newBlockContentCodes[newBlockContentCodes.length] = possibleSubItemCodes[i];
					}
					if (contentCode == possibleSubItemCodes[i])
					{
						// Subtract 2 from 'newIndexPos', because we need a 0-based index and the 'length' property is one
						// higher than the last index pos and we skip the first position (for the main block code) 
						newIndexPos = newBlockContentCodes.length - 2;
						subItemInfo = getPortletSubItemInfo(blockContentCodes[0], possibleSubItemCodes[i]);
					}
				}
				if (newIndexPos == -1 ||
					subItemInfo == null)
				{
					// This should never happen
					return;
				}

				// Copy the new array into the original
				blockContentCodes = newBlockContentCodes;
				draggablePortlets[numericId - 1]["contentCodes"] = blockContentCodes;

				// Rearrange the 'numberOfItems' array as well, inserting the default value at the correct position
				// We skip the first position (for the main block)
				draggablePortlets[numericId - 1]["numberOfItems"].splice(newIndexPos + 1, 0, subItemInfo.defaultNumberOfItems);

				var contentDiv = getElementsWithClassName(subDivsOfMain, "blockContent", 1)[0];

				// Get the div for the sub item that should succeed the new one in this portlet
				var subItemDivs = getElementsWithClassName(subDivsOfMain, "subItem", 20);
				var nextSubItemDiv;
				if (newIndexPos < subItemDivs.length)
				{
					nextSubItemDiv = subItemDivs[newIndexPos];
				}
				else
				{
					// We will append the new sub item to the end of the portlet
					nextSubItemDiv = null;
				}

				// Create the sub item div and add it to the portlet
				subItemDiv = createASubItem(contentDiv, nextSubItemDiv, subItemInfo.title, subItemInfo.link, blockContentCodes[0] + blockContentCodes[newIndexPos + 1], subItemInfo.changeNumber);
				// Add a 'spinner' image in order to indicate time-consuming activity
				createASpinnerImage(subItemDiv);
				// Create the list with text items (which are also links to the article for which they represent the title)
				createAItemList(subItemDiv, subItemInfo.defaultNumberOfItems, subItemInfo.maxNumberOfItems);
				// Make sure the AJAX updates will use the extra sub item
				var autoUpdater = draggablePortlets[numericId - 1]["itemProvider"];
				autoUpdater.contentCodes = blockContentCodes;
				autoUpdater.setupSubItemArrays();
				// Force an immediate update, effectively cancelling the pending one
				autoUpdater.providerObject.requestUpdate();
			}
		}
		else
		{
			// Found?
			if (subItemDiv != null)
			{
				// Remove this code from the 'blockContentCodes' array
				blockContentCodes.splice(oldIndexPos, 1);
				draggablePortlets[numericId - 1]["contentCodes"] = blockContentCodes;
				// Rearrange the 'numberOfItems' array as well, deleting the value at the found position
				draggablePortlets[numericId - 1]["numberOfItems"].splice(oldIndexPos, 1);
				// Remove the affected sub item div from the portlet
				subItemDiv.parentNode.removeChild(subItemDiv);
				// Make sure the AJAX updates will no longer use the removed sub item
				draggablePortlets[numericId - 1]["itemProvider"].contentCodes = blockContentCodes;
				draggablePortlets[numericId - 1]["itemProvider"].setupSubItemArrays();
			}
		}

		if (useCookieToRememberPortlets)
		{
			savePortletsCookie();
		}
	}

	function toggleItemCheckbox()
	{
		var contentCodes = new Array();
		var numberOfItems = new Array();
		//var hasSubItems = getItemOptionsForContentCode(contentCodes[0]).length > 0;
		for (var i = 0; i < this.value.length; i++)
		{
			contentCodes[i] = this.value.charAt(i);
			if (i == 0)
			{
				numberOfItems[i] = getPortletInfo(contentCodes[0]).defaultNumberOfItems;
			}
			else
			{ 
				numberOfItems[i] = getPortletSubItemInfo(contentCodes[0], contentCodes[i]).defaultNumberOfItems;
			}
		}
		if (this.checked == true)
		{
			// Add the new portlet to the first empty position of the array
			var firstEmpty = getFirstEmptyCell(draggablePortlets);
			// Create it as the first portlet of the first column
			createAPortlet(firstEmpty, 1, 0, contentCodes, numberOfItems, true);
			updateProvider.requestUpdate();
		}
		else
		{
			// Remove the portlet from the array and from the column
			var arrayIndex = findContentCodeInPortletsArray(contentCodes[0]);
			// Found
			if (arrayIndex != -1)
			{
				// Stop de auto updater
				updateProvider.removeBlock(draggablePortlets[arrayIndex]["itemProvider"]);

				// Remove the affected div from its column
				draggablePortlets[arrayIndex]["parentObj"].removeChild(draggablePortlets[arrayIndex]["obj"]);
				draggablePortlets[arrayIndex] = null;
			}
		}

		if (useCookieToRememberPortlets)
		{
			savePortletsCookie();
		}
	}

	function getFirstEmptyCell(array)
	{
		for (var i = 0; i < array.length; i++)
		{
			if (array[i] == null)
			{
				return i;
			}
		}
		// None found, add a new element to the end
		return array.length;
	}

	function findContentCodeInPortletsArray(contentCode)
	{
		var arrayIndex = -1;
		for (var i = 0; i < draggablePortlets.length && arrayIndex == -1; i++)
		{
			if (draggablePortlets[i] != null &&
				draggablePortlets[i]["contentCodes"][0] == contentCode)
			{
				arrayIndex = i;
			}
		}
		return arrayIndex;
	}

	function setupAndHotwireSettings(currentColourIndex)
	{
		var settingsDiv = document.getElementById("settings");
		var checkBoxes = settingsDiv.getElementsByTagName("input");
		if (checkBoxes != null)
		{
			for (var i = 0; i < checkBoxes.length; i++)
			{
				checkBoxes[i].onclick = toggleItemCheckbox;
				var contentCode = checkBoxes[i].value.charAt(0);
				var arrayIndex = findContentCodeInPortletsArray(contentCode);
				// Check this box if found (which means visible)
				checkBoxes[i].checked = arrayIndex != -1;
			}
		}

		selectCurrentColourAndSetupAndHotwireBoxes(true, currentColourIndex);
	}

	function selectCurrentColourAndSetupAndHotwireBoxes(setupAndHotwire, currentColourIndex)
	{
		var colourChooserDiv = document.getElementById("colorChooser");
		var lists = colourChooserDiv.getElementsByTagName("ul");
		// Setup the 'rotate colours' selection (show the current colour or draw a random colour)
		var rotateColoursItem = lists[0].getElementsByTagName("li")[0];
		if (setupAndHotwire)
		{
			rotateColoursItem.onclick = toggleColourBox;
		}
		rotateColoursItem.style.backgroundColor = colours[currentColourIndex - 1];
		if (mainColourIndex == 0)
		{
			rotateColoursItem.className = "current";
		}
		else
		{
			rotateColoursItem.className = null;
		}
		// Setup the list with colours
		var colourBoxes = lists[1].getElementsByTagName("li");
		if (colourBoxes != null)
		{
			for (var i = 0; i < colourBoxes.length; i++)
			{
				if (setupAndHotwire)
				{
					colourBoxes[i].onclick = toggleColourBox;
					colourBoxes[i].style.backgroundColor = colours[i];
				}
				// Make sure the box for the currently selected colour is marked
				if (i == mainColourIndex - 1)
				{
					colourBoxes[i].className = "current";
				}
				else
				{
					colourBoxes[i].className = null;
				}
			}
		}
	}

	function getCurrentColour()
	{
		if (mainColourIndex == 0)
		{
			// Generate a random number between 0 (inclusive) and 'colours.length'
			var randomIndex = Math.floor(Math.random() * colours.length);
			return randomIndex + 1;
		}
		else if (mainColourIndex - 1 < colours.length)
		{
			// 0-based array, but we use '0' for option 'rotate colours'
			return mainColourIndex;
		}
		else
		{
			// Default to black
			return 1;
		}
	}

	function toggleColourBox()
	{
		mainColourIndex = Number(getIDNumberFromName(this.id));
		// Just in case a random colour is chosen
		var currentColourIndex = changeMainColour();
		selectCurrentColourAndSetupAndHotwireBoxes(false, currentColourIndex);

		if (useCookieToRememberPortlets)
		{
			savePortletsCookie();
		}
	}

	function changeMainColour()
	{
		var mainDiv = document.getElementById("vob");
		// Store it for use in this method, because in case of option 'rotate colours' it
		// would change randomly every time 'getCurrentColour()' is called
		var currentColourIndex = getCurrentColour();
		mainDiv.className = "main" + " " + "colour" + currentColourIndex;
		return currentColourIndex;
	}

	// Needs 'colour' in this format: 'rgb(xxx, yyy, zzz)'
	function makeColourLighter(colour)
	{
		// Retrieve what's between 'rgb(' and ')'
		var colourString = colour.substring(colour.indexOf("(") + 1, colour.indexOf(")"));
		var colourRed = Number(colourString.substring(0, colourString.indexOf(",")));
		var colourGreen = Number(colourString.substring(colourString.indexOf(",") + 1, colourString.lastIndexOf(",")));
		var colourBlue = Number(colourString.substring(colourString.lastIndexOf(",") + 1));

		return "rgb(" + makeColourComponentLighter(colourRed) + "," + makeColourComponentLighter(colourGreen) + "," + makeColourComponentLighter(colourBlue) + ")";
	}

	function makeColourComponentLighter(colour)
	{
		if (colour < 100)
		{
			colour *= 1.7;
		}
		else if (colour < 170)
		{
			colour *= 1.4;
		}
		else if (colour < 200)
		{
			colour *= 1.2;
		}
		else if (colour < 240)
		{
			colour *= 1.04;
		}
		else if (colour < 250)
		{
			colour *= 1.01;
		}
		else
		{
			colour += 1;
		}
		// Convert to int
		return Math.floor(colour);
	}

	function showHideSettings()
	{
		var settingsDiv = document.getElementById("settings");
		var settingsButton = document.getElementById("portletChoicesButton");
		var settingsButtonImage = settingsButton.getElementsByTagName("img")[0];

		if (settingsDiv.style.display == "block")
		{
			settingsDiv.style.display = "none";
			settingsButtonImage.src = "001/images/b_keuze_on.gif";
		}
		else
		{
			settingsDiv.style.display = "block";
			settingsButtonImage.src = "001/images/b_keuze_off.gif";
		}
	}

	// Needs to be this big because the TinyMCE editor increases in size just after having loaded
	var safeOffset = 110;

	// Another option is to also create the fixed portlets from JavaScript (probably after retrieving a list with the selected portlets via AJAX)
	// For now we only adjust the height of column 3 so that it is as high as the fixed portlet plus whichever of column 1 and 2 is the highest
	function adjustColumn3ToFixedPortlets()
	{
		var column3 = document.getElementById("column" + 3);
		var fixedBlock = document.getElementById("nonDragableBox1");

		var column1Height = document.getElementById("column" + 1).offsetHeight;
		var column2Height = document.getElementById("column" + 2).offsetHeight;
		// Get the one with the biggest height
		var column3Height = Math.max(column1Height, column2Height);
		// In case the fixed portlet spans only the first 2 columns, the height
		// of column 3 should be increased with that of the fixed portlet
		if (fixedBlock.offsetWidth / column3.offsetWidth < 3)
		{
			column3Height += fixedBlock.offsetHeight;
		}

		column3.style.minHeight = (column3Height + safeOffset) + "px";
		// IE 6 doesn't support CSS 'min-height'
		if (document.all &&
			typeof XMLHttpRequest == "undefined")
		{
			column3.style.height = (column3Height + safeOffset) + "px";
		}
	}

	function setupFixedPortletUpdaters()
	{
		var portlet;
		var contentCodes = null;

		// 'fixedPortletsContentCodes' is a global array, filled in JSP files that have a fixed portlet
		for (var i = 0; i < fixedPortletsContentCodes.length; i++)
		{
			portlet = document.getElementById("nonDragableBox" + (i + 1));
			if (portlet != null)
			{
				contentCodes = new Array();
				contentCodes[contentCodes.length] = fixedPortletsContentCodes[i];
				updateProvider.addBlock(new AutoUpdater(portlet, i + 1, contentCodes, updateProvider));
			}
		}
	}

	function initPersonalisedSettings()
	{
		// Don't change this order!
		createHelpObjects();
		initEvents();

		if (updateProvider == null)
		{
			updateProvider = new UpdateProvider();
		}

		setupFixedPortletUpdaters();
		if (useCookieToRememberPortlets)
		{
			if (getCookie(OBLIGATORIES_COOKIE_NAME) == null)
			{
				// Remove the portlets cookie for browsers which haven't used the new 'Specials'
				// version yet, thus enforcing the new default cookie
				deleteCookie(PORTLETS_COOKIE_NAME);
			}
			// Create the portlets from the cookie info and add them to the appropriate columns
			createPortletsFromCookie();
		}

		updateProvider.requestUpdate();

		var currentColourIndex = changeMainColour();
		setupAndHotwireSettings(currentColourIndex);

		// We would like to do this even later, because at this point the Ajax-updates will
		// probably still not have completed, influencing the definitive height of the portlets
		// and, thus, the columns... 
		adjustColumn3ToFixedPortlets();
	}

	// Make sure the DOM is ready
	if (window.addEventListener)
	{
		window.addEventListener("load", initPersonalisedSettings, false);
	}
	else
	{
		window.attachEvent("onload", initPersonalisedSettings);
	}
