/* <documentation about="ABOUT library.js" type="GENERAL">
	<summary>This file is a library: it contains general functions used for the entire application.
		No page initialisation calls are made in this file; there is one exception: Lib.addEvent(window, "unload", Lib.eventCache.flush): This removes all attached events.
		Make your function calls in the specific javascript files, in the [namespace].init()
	</summary>
	<namespace>Lib</namespace>
</documentation> */
var Lib = {};


/* <documentation about="Lib.debug/Lib.allowAlert" type="global variables">
	<summary>These variables are used for debugging - do not change</summary>
	<namespace>Lib</namespace>
</documentation> */
Lib.debug = false;
Lib.allowAlert = true;


/* <documentation about="Global variables" type="global variables">
	<summary>Global variables</summary>
	<namespace>Lib</namespace>
</documentation> */
Lib.safari = (navigator.userAgent.toLowerCase().indexOf('safari') != - 1);
Lib.opera = window.opera ? true : false;
Lib.ie = (document.all && document.getElementById) ? true : false;
Lib.ie6 = ((navigator.platform.toLowerCase() != -1) && (navigator.userAgent.toLowerCase().indexOf("msie 6")!=-1)) ? true : false;
Lib.pageIsStyled = false;
Lib.selectIsClicked = false;
Lib.selectAlternates = [];

/* ========== CORE ============================================================================ */
/* <documentation about="Lib.addEvent" type="CORE FUNCTION">
	<summary>Adds events to elements of the DOM</summary>
	<namespace>Lib</namespace>
	<param type="object" descr="A reference to the node on which the event has been set (HTML element).">obj</param>
	<param type="string" descr="The name of the event ">evt</param>
	<param type="object" descr="A reference to the function which handles the event.">fn</param>
</documentation> */
Lib.addEvent = function (obj,evt,fn) {
	if (obj.addEventListener)
		obj.addEventListener(evt,fn,false);
	else if (obj.attachEvent)
		obj.attachEvent('on'+evt,fn);
}

/* <documentation about="Lib.removeEvent" type="CORE FUNCTION">
	<summary>Removes events to elements of the DOM</summary>
	<namespace>Lib</namespace>
	<param type="object" descr="A reference to the node on which the event has been set (HTML element).">obj</param>
	<param type="string" descr="The name of the event ">evt</param>
	<param type="object" descr="A reference to the function which handles the event.">fn</param>
</documentation> */
Lib.removeEvent = function (obj,evt,fn) {
	if (obj.removeEventListener)
		obj.removeEventListener(evt,fn,false);
	else if (obj.detachEvent)
		obj.detachEvent('on'+evt,fn);
}

Lib.eventCache = function(){
	try {
		var listEvents = [];

		/*  Implement array.push for browsers which don't support it natively. (used in EventCache)
		Please remove this if it's already in other code */
		if(Array.prototype.push == null){
			Array.prototype.push = function(){
				for(var i = 0; i < arguments.length; i++){
					this[this.length] = arguments[i];
		       	};
		        return this.length;
			};
		};

	    return {
			listEvents : listEvents,

			/* <documentation about="Lib.eventCache.add" type="CORE FUNCTION">
				<summary>Keeping track of all the attached events</summary>
				<namespace>Lib</namespace>
				<param type="object" descr="A reference to the node on which the event has been set (HTML element).">node</param>
				<param type="string" descr="The name of the event">sEventName</param>
				<param type="object" descr="A reference to the function which handles the event. ">fHandler</param>
				<param type="bool" descr="A boolean which determines whether the event is triggered in capture mode or not. Does not apply to Internet Explorer.">bCapture</param>
			</documentation> */
			add : 	function(node, sEventName, fHandler, bCapture){
						listEvents.push(arguments);
					},

		 	/* <documentation about="Lib.eventCache.flush" type="CORE FUNCTION">
				<summary>Used to remove (detach) all cached events.</summary>
			</documentation> */
			flush : 	function(){
					var i, item;
					for(i = listEvents.length - 1; i >= 0; i = i - 1){
						item = listEvents[i];
	                 	Lib.removeEvent(item[0], item[1], item[2])

						item[0][item[1]] = null;
					};
			}
	      };
	} catch (ex){ Lib.errHandler(ex); }
}();

/* <documentation about="Lib.debugAlert" type="CORE FUNCTION">
	<summary>Displays alert with error message, if alert is allowed (not cancelled in confirm) and Lib.debug = true</summary>
	<namespace>Lib</namespace>
	<param type="string" descr="Message to display in alert">message</param>
</documentation> */
Lib.debugAlert = function (message) {
		if(Lib.allowAlert && Lib.debug) { Lib.allowAlert = confirm(message); }
	}


/* <documentation about="Lib.errHandler" type="CORE FUNCTION">
	<summary>Handles errors in javascript application</summary>
	<namespace>Lib</namespace>
	<param type="object" descr="Error object">err</param>
</documentation> */
Lib.errHandler = function (err) {
		var errorText = "";
		for (var i in err) { errorText += i + "=" + err[i] + "\n"; }
		Lib.debugAlert("An error has occured: \n\n" + errorText + "\nSee Firefox browser for correct linenumbers.");
		return true;
	}
/* ========== END CORE ====================================================================== */

/* ========== GENERAL FUNCTIONS ============================================================= */
/* <documentation about="Lib.getElementsByClassName" type="general function">
	<summary>Used to find HTML elements with certain classname</summary>
	<namespace>Lib</namespace>
	<param type="string" descr="Classname you are looking for">searchClass</param>
	<param type="string" descr="An optional tag name to narrow the search to specific tags e.g. 'a' for links (optional, defaults to ‘*’).">tagName</param>
	<param type="string" descr="An optional object container to search inside. This narrows the scope of the search (optional, defaults to document).">elem</param>
	<returns>Array of HTML elements</returns>
</documentation> */
Lib.getElementsByClassName = function (searchClass, tagName, containerElement) {
	tagName = tagName || "*";
	containerElement = containerElement || document;

	var allElements = containerElement.getElementsByTagName(tagName);
	if (!allElements.length &&  tagName == "*" &&  containerElement.all) allElements = containerElement.all;

	var elementsFound = new Array();
	var delim = searchClass.indexOf("|") != -1  ? '|' : " ";

	var arrClass = searchClass.split(delim);
	for (var i = 0, j = allElements.length; i < j; i++) {
		var arrObjClass = allElements[i].className.split(" ");
		if (delim == " " && arrClass.length > arrObjClass.length) { continue; }
		var c = 0;
		comparisonLoop:
			for (var k = 0, l = arrObjClass.length; k < l; k++) {
				for (var m = 0, n = arrClass.length; m < n; m++) {
					if (arrClass[m] == arrObjClass[k]) c++;
					if (( delim == "|" && c == 1) || (delim == " " && c == arrClass.length)) {
						elementsFound.push(allElements[i]);
					break comparisonLoop;
				}
			}
		}
	}
	return elementsFound;
}


/* <documentation about="Lib.addStyleSheet" type="general function">
	<summary>Adds stylesheet to the document</summary>
	<namespace>Lib</namespace>
	<param type="string" descr="Relative path to the stylesheet for example '../static/css/stylesheet.css'">relPath</param>
</documentation> */
Lib.addStyleSheet = function (relPath) {
	if(document.getElementsByTagName("head"))
	{
		var head = document.getElementsByTagName("head")[0];
		var newStyle = document.createElement("link");
   		newStyle.setAttribute("type", "text/css");
		newStyle.setAttribute("rel", "stylesheet");
		newStyle.setAttribute("href", relPath);
		head.appendChild(newStyle);
	}
}

/* <documentation about="Lib.removeStyleSheet" type="general function">
	<summary>Removes (or disables) stylesheet in document</summary>
	<namespace>Lib</namespace>
	<param type="string" descr="File name of stylesheet for example 'stylesheet.css'">stylesheetFileName</param>
</documentation> */
Lib.removeStyleSheet = function (stylesheetFileName) {
	if(document.getElementsByTagName("head"))
	{
		var head = document.getElementsByTagName("head")[0];
		var linkElements = head.getElementsByTagName("link");

		for(var i=0; i<linkElements.length; i++) {

			var href = linkElements[i].getAttribute("href");
			if( href.indexOf(stylesheetFileName) != -1) {
				linkElements[i].disabled=true;
				head.removeChild(linkElements[i]);
			}
		}
	}
}

/* <documentation about="Lib.getNextElement" type="general function">
	<summary>Gets next element in DOM tree; while ignoring text nodes</summary>
	<namespace>Lib</namespace>
	<param type="object" descr="HTML element">elem</param>
	<returns>HTML element</returns>
</documentation> */
Lib.getNextElement = function ( elem ) {
    do { elem = elem.nextSibling; }
	while ( elem && elem.nodeType != 1 );
    return elem;
}

/* <documentation about="Lib.findElementPosition" type="general function">
	<summary>Find position of a HTML element relative to window</summary>
	<namespace>Lib</namespace>
	<param type="object" descr="HTML element">elem</param>
	<returns>array [left (integer), top (integer)]</returns>
</documentation> */
Lib.findElementPosition = function (elem){
	var curleft = curtop = 0;
	if (elem.offsetParent) {

		curleft = elem.offsetLeft
		curtop = elem.offsetTop
		while (elem = elem.offsetParent) {
			curleft += elem.offsetLeft
			curtop += elem.offsetTop
		}
	}
	return [curleft,curtop];
}

/* <documentation about="Lib.elementsExists" type="general function">
	<summary>Checks if all the elements with the id specified in the arguments of this function exist; returns true if they do exist; false if one or more do not exist</summary>
	<namespace>Lib</namespace>
	<param type="array of strings" descr="Id's of HTML elements">[array]</param>
	<returns>boolean</returns>
</documentation> */
Lib.elementsExists = function () {
	var result = true;
	for(var i=0; i< arguments.length; i++) {
		if(!document.getElementById(arguments[i])) result=false;
	}
	return result;
}

/* <documentation about="Lib.removeElements" type="general function">
	<summary>Used to remove HTML elements</summary>
	<namespace>Lib</namespace>
	<param type="string" descr="An optional tag name to narrow the search to specific tags e.g. "a" for links (optional, defaults to "*").">tagName</param>
	<param type="string" descr="Classname you are looking for">searchClass</param>
	<param type="string" descr="An optional object container to search inside. This narrows the scope of the search (optional, defaults to document).">elem</param>
</documentation> */
Lib.removeElements = function (tagName, searchClass, containerElement) {
	var elementToRemove = Lib.getElementsByClassName(searchClass, tagName, containerElement);
	
	for(var i=0; i< elementToRemove.length; i++) {
		elementToRemove[i].parentNode.removeChild(elementToRemove[i]);
	}
}

/* <documentation about="Lib.trim" type="general function">
	<summary>Used to trim a variable (removing spaces left and right)</summary>
	<namespace>Lib</namespace>
	<param type="string" descr="Variables that you want to trim">stringToTrim</param>
	<returns>Trimmed variable (string)</returns>
</documentation> */
Lib.trim = function(stringToTrim) {
	return stringToTrim.replace(/^\s+|\s+$/g, '') ;
}

/* <documentation about="Lib.getBodyId" type="general function">
	<summary>Gets  id of body element</summary>
	<namespace>Lib</namespace>
	<returns>id (string)</returns>
</documentation> */
Lib.getBodyId = function ()  {
 	try {
		var body = document.getElementsByTagName("body")[0];
		return body.id;
	} catch (ex){ Lib.errHandler(ex); }
 }

 /* <documentation about="Lib.inputAutoClear" type="general function">
	<summary>Resets default value in text field when text field is left empty</summary>
	<namespace>Lib</namespace>
</documentation> */
Lib.inputAutoClear = function () {
	for (var i=0; i< arguments.length; i++) {
		var inputField = document.getElementById(arguments[i]);
		if(!inputField) { continue; }
		inputField.setAttribute("default", inputField.value);

		// Add a onfocus to every text input with class "text"
		// This will store the initial value for restoring it when the box stays empty when losing focus
		inputField.onfocus = function() {  if (this.getAttribute("default")== this.value) { this.value = ""; this.className = "text active"; }};
		Lib.eventCache.add(inputField, "onfocus", function() {  if (this.getAttribute("default")== this.value) { this.value = "";  this.className = "text active"; }}, false);

		// Add a onblur to every text input with class "text"
		// This will restore the initial value if no value is inserted
		inputField.onblur = function() { if (this.value.length==0) { this.value = this.getAttribute("default"); this.className = "text"; } };
		Lib.eventCache.add(inputField, "onblur", function() { if (this.value.length==0) { this.value = this.getAttribute("default");this.className = "text";} }, false);
		
		var findParentForm = function(elem){
			var parentForm;
			var parentFormFound = false;
			while (elem && !parentFormFound) {
				elem = elem.parentNode;
				if(elem.tagName.toLowerCase()=="form"){
					parentForm = elem;
					parentFormFound = true;
				}
			}
			return parentForm;
			
		}
		var inputParentForm = findParentForm(inputField);
		inputParentForm.clearSearch = inputField;
		
		// preserve the original onsubmit
	   var orinalOnSubmitFunction = inputParentForm.onsubmit;

		inputParentForm.onsubmit = function(){
			if(this.clearSearch.value == this.clearSearch.getAttribute("default")){
				this.clearSearch.value = "";
				//alert(this.clearSearch.value);
			}
			if (orinalOnSubmitFunction !=null){
				// execute the original onsubmit function
				return orinalOnSubmitFunction();
			}
		}
	}
}

 /* <documentation about="Lib.styleDropdowns" type="specific function">
	<summary>Replaces dropdowns with classname "_dhtml-select" (selects) with styled dropdowns</summary>
	<namespace>Lib</namespace>
</documentation> */
Lib.styleDropdowns = function () {
	var documentClick = function() {
		if(!Lib.selectIsClicked) {
			closeSelects();
		}
		else { Lib.selectIsClicked = false; }
	}

	var openSelect = function (selectReplace) {
		Lib.selectIsClicked = selectReplace.getAttribute('orig_id');
		var targetSelect	= document.getElementById(selectReplace.getAttribute('orig_id') + '_alt');
		var targetSelectDD 	= document.getElementById(selectReplace.getAttribute('orig_id') + '_alt_dropdown');
		lastClickedItem		= selectReplace.getAttribute('orig_id') + '_alt_dropdown';

		if (targetSelectDD.getAttribute('open') == 'true') {
			targetSelectDD.setAttribute('open', 'false');
			targetSelectDD.style.display = 'none';
			targetSelectDD.style.height = "auto";
			targetSelectDD.style.overflow = "visible";
			
			if(Lib.ie6){
				selectReplace.ieFrame.style.top = targetSelectDD.offsetTop + "px";
				selectReplace.ieFrame.style.width = targetSelectDD.offsetWidth + "px";
				selectReplace.ieFrame.style.height = targetSelectDD.offsetHeight + "px";
				selectReplace.ieFrame.className = "closed-iframe";
			}
		}
		else {
			closeSelects();

			targetSelectDD.setAttribute('open', 'true');
			targetSelectDD.style.display = 'block';

			/*var body = document.getElementsByTagName("body")[0];
			var firstDiv = document.getElementsByTagName("div")[0];
			body.insertBefore(targetSelectDD, firstDiv);
			targetSelectDD.style.left = targetSelect.offsetLeft + "px";
			targetSelectDD.style.top = targetSelect.offsetTop + "px"; */

			// If text is wider than current width make dropdown bigger:
			if(targetSelectDD.offsetWidth<selectReplace.finalTextWidth+30) {
				if(targetSelectDD.offsetHeight>196) targetSelectDD.style.width = (selectReplace.finalTextWidth+40)+"px";
				else targetSelectDD.style.width = (selectReplace.finalTextWidth+30)+"px";
			}
			
			if(targetSelectDD.offsetHeight>196) {
				targetSelectDD.style.overflow = "auto";
				targetSelectDD.style.overflowY = "scroll";
				targetSelectDD.style.overflowX = "hidden";
				targetSelectDD.style.height = "196px";
			}
			
			if(Lib.ie6){
				selectReplace.ieFrame.style.top = targetSelectDD.offsetTop + "px";
				selectReplace.ieFrame.style.left = targetSelectDD.offsetLeft + "px";
				selectReplace.ieFrame.style.width = targetSelectDD.offsetWidth + "px";
				selectReplace.ieFrame.style.height = targetSelectDD.offsetHeight + "px";
				selectReplace.ieFrame.className = "open-iframe";
			}
		}
	}

	var closeSelects = function () {
		var options = Lib.getElementsByClassName("dhtml-select_options", "div");
		for (var i=0; i<options.length; i++) {
			options[i].setAttribute('open', 'false');
			options[i].style.display = 'none';
			
			if(Lib.ie6){
				var hideFrameId = options[i].id.replace("_dropdown","");
				var ieFrame = document.getElementById(hideFrameId).ieFrame;
				if(ieFrame.className.indexOf("closed-iframe")<0) ieFrame.className = "closed-iframe";
			}
		}
	}

	var optionClick = function (optionReplaceLink) {
        var selectElement = document.getElementById(optionReplaceLink.getAttribute('select'));

        if (selectElement.selectedIndex != optionReplaceLink.getAttribute('position')) {
            selectElement.options[optionReplaceLink.getAttribute('position')].selected = "selected";
            
            if (Lib.ie) {
                selectElement.fireEvent('onchange');
            } else {
                var event = document.createEvent("HTMLEvents");
                event.initEvent("change", false, true);
                selectElement.dispatchEvent(event);
            }
        } 

		var newOption = document.createElement('dt');
		newOption.className = "selected-option";

		if (!optionReplaceLink.text) { newOption.innerHTML = "<span>"+ optionReplaceLink.childNodes[0].toString() + "</span>"; }
		else { newOption.innerHTML = "<span>"+ optionReplaceLink.text+ "</span>"; }

		document.getElementById(optionReplaceLink.getAttribute('select_alt')).childNodes[0].replaceChild(newOption, document.getElementById(optionReplaceLink.getAttribute('select_alt')).childNodes[0].childNodes[0]);
	}

	if(Lib.pageIsStyled) {
		var candidates = Lib.getElementsByClassName("_dhtml-select", "select");
		for (var i=0; i<candidates.length; i++) {
			// Retrieve the required information from the original select box
			var origSelect = candidates[i];
			var origClass = origSelect.className.replace(" hide", "").substring(1);

			// Create replacement select box
			Lib.selectAlternates[Lib.selectAlternates.length] = origSelect.getAttribute('id') + '_alt_dropdown';

			var selectReplace = document.createElement('div');
				selectReplace.setAttribute('id', origSelect.getAttribute('id') + '_alt');
				selectReplace.setAttribute('orig_id', origSelect.getAttribute('id'));
				selectReplace.className = origClass;

			selectReplace.onclick = function() { openSelect (this); };
			Lib.eventCache.add(selectReplace, "onclick", function() { openSelect (this); }, false);
			  
// Create a div to calculate textlength:
			var testTextLengthDiv = document.createElement('div');
			testTextLengthDiv.className = "textLengthCheck";
			document.getElementsByTagName("body")[0].appendChild(testTextLengthDiv);
			selectReplace.finalTextWidth = 0;

            // Find selected option from the original selection box.
            var indexSelectedOption = 0;
            
            for (var j = 0; j < origSelect.options.length; j++) {
                
                if (Lib.ie) {
	                if (origSelect.options[j].getAttribute('selected')) {
	                    indexSelectedOption = j;
	                    break;
	                }
	            } else {
	                if (origSelect.options[j].getAttribute('selected') != null) {
	                    indexSelectedOption = j;
	                    break;
	                }
	            }
            }
            
            // Create selected
			var selectReplaceList = document.createElement('dl');
			var optionReplace = document.createElement('dt');
			// add classname to selected item to enable more stylesheet control over this element:
			optionReplace.className = "selected-option";
			var selectReplaceText = document.createTextNode(origSelect.options[indexSelectedOption].text);
			
			// check current width for value:
			testTextLengthDiv.innerHTML = origSelect.options[0].text;
			var currentTextWidth = testTextLengthDiv.offsetWidth;
			if(currentTextWidth>selectReplace.finalTextWidth) selectReplace.finalTextWidth = currentTextWidth;
			testTextLengthDiv.innerHTML = selectReplace.finalTextWidth; 
			
			optionReplace.appendChild(selectReplaceText);
			selectReplaceList.appendChild(optionReplace);
			selectReplace.appendChild(selectReplaceList);			

			// Create replacement select box dropdown
			var selectReplaceOptions = document.createElement('div');
			selectReplaceOptions.setAttribute('id', origSelect.getAttribute('id') + '_alt_dropdown');
			selectReplaceOptions.className = origClass + '_options';
			var selectReplaceList = document.createElement('dl');
			
			for (var j= 0; j<origSelect.options.length; j++) {
		      		var optionReplace = document.createElement('dt');
					optionReplaceLink = document.createElement('a')
					optionReplaceLink.href= "#";
					optionReplaceLink.setAttribute('position', j);
					optionReplaceLink.setAttribute('select_alt', origSelect.getAttribute('id') + '_alt');
					optionReplaceLink.setAttribute('select', origSelect.getAttribute('id'));
                optionReplaceLink.setAttribute('selectElement', origSelect);
				optionReplaceLink.setAttribute('value', origSelect.options[j].getAttribute('value'));

					optionReplaceLink.onclick = function() { optionClick(this); return false; };
					Lib.eventCache.add(optionReplaceLink, "onclick", function() { optionClick(this); return false;}, false);

					optionReplaceText = document.createTextNode(origSelect.options[j].text);
					
					// check current width for value:
					testTextLengthDiv.innerHTML = origSelect.options[j].text;
					currentTextWidth = testTextLengthDiv.offsetWidth;
					if(currentTextWidth>selectReplace.finalTextWidth) selectReplace.finalTextWidth = currentTextWidth;
					testTextLengthDiv.innerHTML = selectReplace.finalTextWidth; 
					
					optionReplaceLink.appendChild(optionReplaceText);
					optionReplace.appendChild(optionReplaceLink);
					selectReplaceList.appendChild(optionReplace);
			}

			
			
			if(selectReplace.finalTextWidth>400) selectReplace.finalTextWidth = 400;
			//alert(selectReplace.finalTextWidth);
			
			//Remove textlength Check:
			Lib.removeElements("div", "textLengthCheck");
			
			// Append the replacement selectbox to the form
			selectReplaceOptions.appendChild(selectReplaceList);
			selectReplace.appendChild(selectReplaceOptions);
			origSelect.parentNode.insertBefore(selectReplace, origSelect);
			
			// create iframe for IE6:
			if(Lib.ie6){
				var ieFrame = document.createElement('iframe');
				ieFrame.className = "closed-iframe";
				selectReplace.parentNode.appendChild(ieFrame);
				selectReplace.ieFrame = ieFrame;
			}

			// Hide the original selectbox
			origSelect.className = "hide";
		}
		Lib.addEvent (document, "click", documentClick);
		Lib.eventCache.add(document, "click", documentClick, false);
	}
}

Lib.setPageIsStyled = function () {
	if(Lib.elementsExists("content")) { if(parseInt(document.getElementById("content").offsetLeft) >10) { Lib.pageIsStyled = true; }	 }
	if(!Lib.pageIsStyled) { Lib.removeStyleSheet ("javascript-enabled.css"); }
}

Lib.cacheBackgroundImages = function(){
	if(Lib.ie){
		try { document.execCommand("BackgroundImageCache", false, true); } catch(ex) { Lib.errHandler(ex);}
	}	
}
/* ========== END GENERAL FUNCTIONS ============================================================= */

/* <documentation about="Add eventhandler Lib.eventCache.flush on window unload" type="FUNCTION CALL">
	<summary>Calling Lib.addEvent: Add Lib.eventCache.flush as eventhandler on window onunload: Detach all attached events (solves memory leak in ie)</summary>
</documentation> */
Lib.addEvent(window, "unload", Lib.eventCache.flush);

