/*
 * © Copyright 2008 IdeFA gruppen
 *
 * Current Version is 1.5
 *
 * v0.0 - 1.0	Debug releases
 * v1.0			First stable release
 * v1.1			added support for toggling Visibility
 * v1.2			Ajax form submitting now includes (single) select boxes, if action is missing current page is used.
 * v1.3			Ajax form submit now supports multiple select boxes.
 * v1.4			Added aditional robustness/error tolerance to the e function.
				Added support for text area
				Bug: formsubmits no longer works in IE ( is this still the case? )
				Bug: forms are not submitted in the page charset
 * v1.5			Addes replaceElement as a handy shortcut to oldelement.parentNode.replaceChild(...)
 */

var IdeFA_JS_version_major=1;
var IdeFA_JS_version_minor=5;

function addOnLoadEvent(func) {
	addOnLoadEventSrc(func,window);
	//addOnLoadEventSrc(function(){debug(func);},window); - used to display load order for verification
}

/**
 * IE_LOADORDER_FIX_BEGIN
 * This is a work arround to ensure that atleast the event added through this library
 * will load in the correct order.
 **/

var IdeFA_OnLoads= new Array();
var IdeFA_last_anonymID=0;
var IdeFA_anonymous_ID_string="IdeFA_NOID_";

function IE_eventBugFixEventOrder(elem){
	for (var i=0;i<IdeFA_OnLoads[elem].length;i++){
		IdeFA_OnLoads[elem][i]();
	}
}

/**
 * IE_LOADORDER_FIX_END
 **/

function addOnLoadEventSrc(func,src) {
	if (src.attachEvent){ //Internet Exploder
		if ( src.id == undefined ){
			IdeFA_last_anonymID++;
			src.id=""+IdeFA_anonymous_ID_string+IdeFA_last_anonymID;
		}
		if ( IdeFA_OnLoads[src.id] == undefined ){
			IdeFA_OnLoads[src.id]=new Array();
			src.attachEvent("onload",function(){IE_eventBugFixEventOrder(src.id);});
		}
		IdeFA_OnLoads[src.id][IdeFA_OnLoads[src.id].length]=func;

//		src.attachEvent("onload",func); // FILO queue, above is a work arround for that.
		return;
	}
	if (src.addEventListener){ //W3C, DOM level 2
//		src.addEventListener("DOMContentLoaded",func,false); //works for page load, but not for iframes ?
		src.addEventListener("load",func,false);
		return;
	}else if ( src=window && document.addEventListener != undefined ){
		document.addEventListener("load",func,false); //Opera 7 aparently
	}

	var oldonload = src.onload;
	if (typeof src.onload != 'function') {
		src.onload = func;
	} else {
		src.onload = function() {
			if (oldonload) {
				oldonload();
			}
			func();
		}
	}
}

function e(hvad){
	if (typeof(hvad)=='object'){return hvad;}
	return document.getElementById(hvad);
}

function kopier(fra,til){
	addOnLoadEvent( function(){ if (e(til)&&e(fra)){ e(til).innerHTML=e(fra).innerHTML;}});
}

function skjul(element){
	e(element).style.display="none";
}

function vis(element){
		e(element).style.display="block";
}

function skiftSynlighed(element){
	var elm=e(element);
	if ( elm.style.display == "block" || elm.style.display == "" ) {
			e(element).style.display="none";
	}else{
			e(element).style.display="block";
	}
}

function skjulOnLoad(element){
	addOnLoadEvent( function() { skjul(element); });
}

/*
 * This replaces an element somewhere on the page with the supplied new element
 */
function replaceElement(oldElement,newElement){
	oldElement.parentNode.replaceChild(newElement,oldElement);
}

/**
 * loadIframe( iframe, url, ignoreWidth )
 *
 * iframe - the id of the iframe to use
 *
 * url - the url to load
 *
 * ignoreWidth - if true does not attempt to set width
 *
 * this function will load the url into the iframe, and then attempt to resize
 * the iframe to the size of the conent.
 *
 * NOTE: this will not work if the page and the url are from different domains ( this includes the lack of www )
 * NOTE2: inorder to be allowed to navigate away from the currently set url that url must also resided on the 
 *			same domain, ie. it would be a good idea to set it to a blank page per default.
 *
 * For the IE part we follow microsoft's own suggestions: http://support.microsoft.com/kb/278469
 * however it seems to render it a good bit wider than needed.
 **/

function loadIframe(iframe, url,ignoreWidth){
	if ( ignoreWidth == undefined ) { ignoreWidth=false;}
	var elm=e(iframe);
	var f=function(){
			iw=ignoreWidth;
			try{
				if (elm.contentDocument)
				{
					dd=elm.contentDocument;
					width = Math.max(dd.body.scrollWidth,dd.body.offsetWidth);
					height = Math.max(dd.body.scrollHeight,dd.body.offsetHeight);
				}else{
					oBody=elm.document.body;
					//The ms way:
					width= oBody.scrollWidth + (oBody.offsetWidth - oBody.clientWidth);
					height=oBody.scrollHeight + (oBody.offsetHeight - oBody.clientHeight);
					//My way: - the 4px is to accound for some wierd border shit IE does.
					dd=elm.contentWindow.document.body;
					width= Math.max(dd.scrollWidth,dd.offsetWidth)+4;
					height=Math.max(dd.scrollHeight, dd.offsetHeight)+4;
					
				}
//alert("h:"+height+",w:"+width);
				elm.style.height=height+"px";	
				if ( !iw) {
					elm.style.width=width+"px";
				}
			}catch(e){
					window.status =	'Error: ' + e.number + '; ' + e.description;
			}
		};
	addOnLoadEventSrc( f,elm);
	elm.src=url;
}


/*********************Tabbed menu code***************************/

	/*handles the tab menu
	 *
	 * each tab's content must be enclosed in an elemenent with the name tab#Content
	 * there must be _no_ gaps in the tab numbers
	 *
	 * TODO: update to v2 of the sliding doors thing
	 * 
	 */
	var totalTabs=0;
	
	/**
	 * The make tabs function is rather specialized
	 * and can be omitted, but if this is done be sure to adjust
	 * totalTabs to the number of tabs -1 
	 *
	 * also make sure to set onclick to 'selectTab(this.id);this.blur();'
	 *
	 * The currently selected tab will have the id "current"
	 *
	 * So to style it use #current{}
	 *
	 **/
	function makeTabs(tabString)
	{
		tabs=tabString.split("|");
		totalTabs=0;
		var out="<div id=\"header\"><ul>";
		for (i=0; i < tabs.length; i++)
		{
				out+="<li><a ID='tab"+(i+1)+"' onclick='selectTab(this.id);this.blur();'>"+tabs[i]+"</a></li>";
				totalTabs++;
		}
		document.body.innerHTML=out+"</ul></div>"+document.body.innerHTML;
		
	}
	
	function selectTab(valgt)
	{ //crude but works:
		for (i=0; i < totalTabs; i++)
		{
			e("tab"+(i+1)).parentNode.id="";
			e("tab"+(i+1)+"Content").style.display='none';
		}
		e(valgt).parentNode.id="current";
		e(valgt+"Content").style.display="block";
	}

/************************* Custom element styling code ************************/

function IdeFA_elements(){
	this.autoReapplyStyle=true;

	this.inputs = new Array();
	this.inputs['text'] = new Array();
	this.inputs['password'] = new Array();
	this.inputs['submit'] = new Array();
	this.inputs['reset'] = new Array();
	this.inputs['file'] = new Array();
	this.inputs['hidden'] = new Array();
	this.inputs['image'] = new Array();
	this.inputs['button'] = new Array();
//Special cases since we will allow
	this.inputs['checkbox'] = new Array();
	this.inputs['radio'] = new Array();
	
	this.radios= new Array(); //styleRadio saves it's on/off images here
	this.checkboxes = new Array(); //styleCheckbox saves it's on/off images here

	this.insertedElements=new Array();

}
var customElements= new IdeFA_elements();

/**
 * This "reapplies" style to dynamically loaded elements
 *
 **/
function reapplyStyles(){
	var temp=customElements;
	customElements=new IdeFA_elements();
	for (var i=0; i < temp.insertedElements.length; i++){
		el=temp.insertedElements[i];
		if (el.parentNode!=undefined)
		{
			el.parentNode.removeChild(el);
		}
	}
	findInputs();
	for ( keyVar in temp.radios ){
		//		debug(keyVar);
		styleRadio(keyVar, temp.radios[keyVar]['onImg'],temp.radios[keyVar]['offImg']);
	}
	for ( keyVar in temp.checkboxes ){
		//		debug(keyVar);
		styleCheckbox(keyVar, temp.checkboxes[keyVar]['onImg'],temp.checkboxes[keyVar]['offImg']);
	}
	customElements.autoReapplyStyles=temp.autoReapplyStyles;
}

function findInputs(){
	elements=document.getElementsByTagName('input');
	for (var i=0;i < elements.length; i++ ){
		el=elements[i];
		type=el.getAttribute('type').toLowerCase();
		customElements.inputs[type][customElements.inputs[type].length]=el;
		if (el.className==""){
			el.className=type;
		}
	}
}


function styleRadio(className,onImg,offImg){	
	if (customElements.inputs['radio'].length==0){
		//Initilazation order is quite wonkey in IE
		findInputs();
	}
	var elements=customElements.inputs['radio'];
	customElements.radios[className]=new Array();
	customElements.radios[className]['onImg']=onImg;
	customElements.radios[className]['offImg']=offImg;
	for (var i=0;i < elements.length; i++ ){
		var el=elements[i];
		if ( el.className.match(className)){
			var ClickCatcher= document.createElement("a");
			var fakeStyle= document.createElement("img");
			fakeStyle.src=el.checked?onImg:offImg;
			ClickCatcher.className=className;
			ClickCatcher.appendChild(fakeStyle);
			el.parentNode.insertBefore(ClickCatcher,el);
			el.style.display="none"; //Collapse the space it occupied
			//should use ClickCatcher.setAttribute('onclick',...)  - but IE dont like that
			customElements.insertedElements[customElements.insertedElements.length]=ClickCatcher;
			ttt=el.name;
			ClickCatcher.onclick=function(){
				var Name=ttt;
				if ( !this.nextSibling.disabled ){
					//this.nextSibling.checked=!this.nextSibling.checked;
					this.nextSibling.checked=true;
				}
				var elements=document.getElementsByName(Name);
				for (var i=0;i < elements.length; i++ ){
					var el=elements[i];
					if (el.checked==true){
						el.previousSibling.firstChild.src=customElements.radios[className]['onImg'];
					}else{
						el.previousSibling.firstChild.src=customElements.radios[className]['offImg'];
					}
				}
			};			
		}
	}
}

function styleCheckbox(className,onImg,offImg){
	if (customElements.inputs['radio'].length==0){
		//Initilazation order is quite wonkey in IE
		findInputs();
	}
	var elements=customElements.inputs['checkbox'];
	customElements.checkboxes[className]=new Array();
	customElements.checkboxes[className]['onImg']=onImg;
	customElements.checkboxes[className]['offImg']=offImg;
	for (var i=0;i < elements.length; i++ ){
		var el=elements[i];
		if ( el.className.match(className)){
			var ClickCatcher= document.createElement("a");
			var fakeStyle= document.createElement("img");
			fakeStyle.src=el.checked?onImg:offImg;
			ClickCatcher.className=className;
			ClickCatcher.appendChild(fakeStyle);
			el.parentNode.insertBefore(ClickCatcher,el);
			el.style.display="none"; //Collapse the space it occupied
			//should use ClickCatcher.setAttribute('onclick',...)  - but IE dont like that
			customElements.insertedElements[customElements.insertedElements.length]=ClickCatcher;
			ClickCatcher.onclick=function(){
				if ( !this.nextSibling.disabled ){
					this.nextSibling.checked=!this.nextSibling.checked;
				}
				if (this.nextSibling.checked==true){
					this.firstChild.src=customElements.checkboxes[className]['onImg'];
				}else{
					this.firstChild.src=customElements.checkboxes[className]['offImg'];
				}
			};
		}
	}
}

function IdeFA_lib_init(){
	findInputs();
}
addOnLoadEvent(IdeFA_lib_init);


function debug(hvad){
	bugs=e("debugArea");
	if (bugs==undefined ||  bugs==null){
		document.body.innerHTML+='<div id="debugArea">Debug statements goes here:<br></div>';
		bugs=e("debugArea");
	}
	bugs.innerHTML+=hvad+"<br>";
}

/********************** AJAX crap ***********************/
function IdeFA_AJAX_Get(url,func,content) {
	var httpRequest;
	if (window.XMLHttpRequest) { // Mozilla, Safari, ...
		httpRequest = new XMLHttpRequest();
		if (httpRequest.overrideMimeType) {
				httpRequest.overrideMimeType(content);
		}
	} 
	else if (window.ActiveXObject) { // IE
		try {
			httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
		}catch (e) {
			try {
				httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
            }catch (e) {}
		}
	}
	if (!httpRequest) {
			window.status ='Sorry your browser is not AJAX compatible';
			alert('Sorry your browser is not AJAX compatible');
			return false;
	}
		httpRequest.onreadystatechange = function() { func(httpRequest); };
		httpRequest.open('GET', url, true);
		httpRequest.setRequestHeader("Cache-Control", "no-cache");
		httpRequest.setRequestHeader("Connection", "close");
	//	httpRequest.setRequestHeader("Content-Type", content+"; charset=UTF-8");
		httpRequest.send('');
}


function IdeFA_AJAX_Post(pForm,func,content) {
	var httpRequest;
	if (typeof(pForm)=='object'){
		var form=pForm;
	}else{
		var form = window.e(pForm);
	}
	if (form==null ||form==undefined){	return false;	}
	var url=form.action;
	if ( url=="" || url==undefined ) { url=location.href; }
	var param=UrlEncodeForm(pForm);
	if (!param){ return false; }
	if (window.XMLHttpRequest) { // Mozilla, Safari, ...
		httpRequest = new XMLHttpRequest();
		if (httpRequest.overrideMimeType) {
				httpRequest.overrideMimeType(content);
		}
	} 
	else if (window.ActiveXObject) { // IE
		try {
			httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
		}catch (e) {
			try {
				httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
            }catch (e) {}
		}
	}
	if (!httpRequest) {
			window.status ='Sorry your browser is not AJAX compatible';
			alert('Sorry your browser is not AJAX compatible');
			return false;
	}
		httpRequest.onreadystatechange = function() { func(httpRequest); };
		httpRequest.open('POST', url, true);
		httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		httpRequest.setRequestHeader("Content-length", param.length);
		httpRequest.setRequestHeader("Cache-Control","no-cache");
		httpRequest.setRequestHeader("Connection", "close");
		httpRequest.send(param);
	return true;
}

function UrlEncodeForm(pForm){
	if (typeof(pForm)=='object'){
		var form=pForm;
	}else{
		var form = window.e(pForm);
	}
	if (form==null ||form==undefined){	return false;	}
	var out="";
		elements=form.getElementsByTagName('input');
	for (var i=0;i < elements.length; i++ ){
		el=elements[i];
		type=el.getAttribute('type').toLowerCase();
		if( el.name!="" ) { // cant submit something that has no name..
			switch(type){
				case 'checkbox':
				case 'radio':
						if (el.checked){
							out+="&"+el.name+"="+el.value;
						}
					break;

				case 'hidden':
				case 'text':
				case 'password':
						out+="&"+el.name+"="+encodeURIComponent(el.value);
					break;
				case 'submit':
						//onclick migth be worth executing...
						//but if we do that maybe we should exec the forms onsubmit aswell.. :-/
						// ultimately however it is not our job.
					break;
				//file,button,image,reset:
				default:
					break;
			}
		}
	}
	elements=form.getElementsByTagName('textarea');
	for (var i=0;i < elements.length; i++ ){
		el=elements[i];
		if( el.name!="" ) { 
			out+="&"+el.name+"="+encodeURIComponent(el.value);
		}
	}
	elements=form.getElementsByTagName('select');
	for (var i=0;i < elements.length; i++ ){
		el=elements[i];
		type=el.type.toLowerCase(); //it's a run time type - not sure if this works in IE..
		if( el.name!="" ) { // cant submit something that has no name..
			switch(type){
				case 'select-one':
					out+="&"+el.name+"="+el.value;
					break;
				default: //select-multiple
					for ( var j=0; j < el.length; j++ ){
						if (el.options[j].selected){ 
							// if the name does not have '[]' at the end I suppose we could add it - 
							//only for regulare forms it seems to no work with a traditional submit 
							//unless you have them so..
							out+="&"+el.name+"="+el.options[j].value;
						}
					}
					
					break;
			}
		}
	}	
	if ( out!="" ){
		out=out.substring(1); //cut off the first &
	}
	return out;
}


/*
 * Url		Url to load
 * Element	Id of the element whose content we should replace
 * BodyOnly	Only load the contents of the <Body> tag
 **/
function IdeFA_loadUrlIntoElement(Url,Element,BodyOnly){
	if ( BodyOnly==undefined ) {BodyOnly=false;}
	var func= function (httpRequest){
		try {
			if (httpRequest.readyState == 4) {
				if (httpRequest.status == 200) {
					if ( !BodyOnly ){
						window.e(Element).innerHTML=httpRequest.responseText;	
					}else{
						window.e(Element).innerHTML=IdeFA_string_BodyContent(httpRequest.responseText);
					}
					if ( customElements.autoReapplyStyle ){
						reapplyStyles();
					}
				} else {
					window.status='AJAX request failed.';
					alert('AJAX request failed.');
				}
			}
		}
	        catch( e ) {
        	   window.status ='Caught Exception: ' + e.description;
			   alert('AJAX Caught Exception: ' + e.description);
        	}
	};

	IdeFA_AJAX_Get(Url,func,'text/html');

}


function IdeFA_AJAX_Submit(pForm,display){
	if ( display==undefined){display=pForm;}
	var func=function ( httpRequest ){
		try {
			if (httpRequest.readyState == 4) {
				if (httpRequest.status == 200) {
					window.e(display).innerHTML=window.IdeFA_string_BodyContent(httpRequest.responseText); 
					//IE needes the window. to make it for for the e function aparently it confuses it with the yet undeclared e we catch below o.O
					if ( customElements.autoReapplyStyle ){
						reapplyStyles();
					}
				} else {
					window.status='AJAX request failed.';
					alert('AJAX request failed.');
				}
			}
		}
	        catch( Err ) {
        	   window.status ='Caught Exception: ' + Err.description;
			//	debugger;
			    alert('AJAX Caught Exception: ' + Err.description);
        	}
	}
	form=e(pForm);
	if ( form.method.toLowerCase() == "get" ){
		IdeFA_AJAX_Get(form.action+"?"+UrlEncodeForm(pForm),func,'text/html');
	}else{
		IdeFA_AJAX_Post(pForm,func,'text/html');
	}
}

/*
 * returns the contents of the <body></body> tag in Haystack, 
 * or Haystack if no body tag was found.
 **/
	var IDEFA_bodystrip_re = /<body[^>]*>([\S\s]*)<\/body>/ig;
function IdeFA_string_BodyContent(Haystack){
	res = IDEFA_bodystrip_re.exec(Haystack);
//Yes this is stupid, but every second time we use the .exec it will return null
//for no aparent reason.. -.-
	dump=IDEFA_bodystrip_re.exec(Haystack); 
	if ( res == undefined ){
		res=Haystack;
	}else{
		res=res[1];
	}
	return res;
}

/************************ Fade In/Out ****************************/
/**
 * TODO: rewrite to a generic animation model
 *
 **/
			var IdeFA_faders = new Array();
			/* worker function, should no be called directly */
			function fader(what,current,increment,end,handle,callback)
			{
				this.element=(typeof(what)=='string'?e(what):what);
				this.start=current;
				this.increment=increment;
				this.current=current;
				this.end=end;
				this.handle=handle;
				this.callback=callback;
				this.active=false;
			}
			/* worker function, should no be called directly */
			function fade(me)
			{
				me=IdeFA_faders[me];
				if ( me.start > me.end ){
					now=me.current-me.increment;
				}else{
					now=me.current+me.increment;
				}
				setOpacity(me.element,now);
				me.current=now;	
				stop=false;
				if ((me.start >= me.end) && (now <= me.end) ){stop=true;}			
				if ((me.start <= me.end) && (now >= me.end) ){stop=true;}			
				if (stop){
					clearInterval(me.handle);
					me.active=false;
					if (me.callback){
						eval(me.callback);
					}
				}				
			}
			
			function setFade(what,from,to,steps,time,callback)
			{
					time=(time>100?time:time*1000);//This does not allow resolutions finer than 0.1 second but who needs that?
					increment=(to-from)/steps;
					index=String(what.id);//faders.length;
					if (!IdeFA_faders[index]){					
							IdeFA_faders[index]= new fader (what,
														from,
														increment,
														to,
														setInterval("fade('"+index+"');",time/steps),
														callback);
							IdeFA_faders[index].active=true;
					}
					else if (!IdeFA_faders[index].active){
						IdeFA_faders[index].what=what;
						IdeFA_faders[index].start=from;
						IdeFA_faders[index].current=from;
						IdeFA_faders[index].increment=increment;
						IdeFA_faders[index].end=to;
						IdeFA_faders[index].handle=setInterval("fade('"+index+"');",time/steps);
						IdeFA_faders[index].callback=callback;
						IdeFA_faders[index].active=true;
					}

			}

			function fadeTo(what,targetOpacity, increment, incrementTime, callback){
				index=String(what.id);
				from=(what.style.opacity)*100;
				
				if (!IdeFA_faders[index]){	
					IdeFA_faders[index]= new fader (what,
													from,
													increment,
													targetOpacity,
													setInterval("fade('"+index+"');",incrementTime),
													callback);
					IdeFA_faders[index].active=true;					
				}else{
					clearInterval(IdeFA_faders[index].handle); //stop the oldTimeout
					IdeFA_faders[index].what=what;
					IdeFA_faders[index].start=from;
					IdeFA_faders[index].current=from;
					IdeFA_faders[index].increment=increment;
					IdeFA_faders[index].end=targetOpacity;
					IdeFA_faders[index].callback=callback;
					IdeFA_faders[index].active=true;
					IdeFA_faders[index].handle=setInterval("fade('"+index+"');",incrementTime);

				}	
			}

			function setOpacity(what,opacity)
			{
				opacity=Math.round(opacity);
				what.style.opacity=(opacity>=100?1:"."+(opacity<10?"0":"")+opacity);
				what.style.filter=(opacity>=100?"":"alpha(opacity="+opacity+")");
			}

