// global page wide singletons:
var dragsort= null;
var junkdrawer= null;
var basePath= null;    // Aloha URL path. Needed for ajax stuff etc. Set by DocSession.renderHeadContentOfHtmlPage
var editInPlaceInit= false; // so we call tinymce.init only once.

document.onkeypress= alohakeypress;

//-- handle arrow keys
function alohakeypress(e)
{
	var ev=window.event?event:e;
	if (!ev.ctrlKey )
		return true;
	
	if(document.location.toString().indexOf("CM=toedit")>1)  // bit of a hack: disable page switching when in edit mode
		return true;
	var shift="";
	if (ev.shiftKey)
		shift="&max";
		 
	var c=ev.charCode?ev.charCode:ev.keyCode;   // ->39, <-37, ^38, v40, Pos1=36, End=35,P gUp=33, PgDown=34
	/*
	if(c==39)  
		document.location= basePath+"?CM=nxt"+shift;  // Dsc.PAGE_NAV_NEXT 
	else if (c==37)
		document.location= basePath+"?CM=prv"+shift;  // Dsc.PAGE_NAV_PREV
	else if (c==38) 
		document.location= basePath+"?CM=up"+shift;   // Dsc.PAGE_NAV_UP
	else if (c==40) 
		document.location= basePath+"?CM=dwn"+shift;  // Dsc.PAGE_NAV_DOWN
	else if (c==36) 
		document.location= basePath+"?CM=first"+shift;  // Dsc.PAGE_NAV_FIRST
	else if (c==35) 
		document.location= basePath+"?CM=last"+shift;  // Dsc.PAGE_NAV_LAST
		*/
	if(c==40)  
		document.location= basePath+"?CM=nxt"+shift;  // Dsc.PAGE_NAV_NEXT 
	else if (c==38)
		document.location= basePath+"?CM=prv"+shift;  // Dsc.PAGE_NAV_PREV
	else if (c==37) 
		document.location= basePath+"?CM=up"+shift;   // Dsc.PAGE_NAV_UP
	else if (c==39) 
		document.location= basePath+"?CM=dwn"+shift;  // Dsc.PAGE_NAV_DOWN
	else if (c==36) 
		document.location= basePath+"?CM=first"+shift;  // Dsc.PAGE_NAV_FIRST
	else if (c==35) 
		document.location= basePath+"?CM=last"+shift;  // Dsc.PAGE_NAV_LAST
		

//	else if (c==13 && ev.shiftkey)
//		document.location= basePath+"?max";	
}
	
	
//--- KRIS textCounter ---------------------------------------------------	
// limit user input character count
// field:   name of TEXTAREA to limit
// cntfild: name of INPUT TYPE='text' field to diplay characters left count
function textCounter(field, cntfield, maxlimit)
{
	r= maxlimit - field.value.length;
	if (r<0)
	{
		cntfield.value= 0;	
		field.value= field.value.substring(0, maxlimit);								
		cntfield.style.backgroundColor='red';	
		return false;
	}
	else
	{
		cntfield.value= maxlimit - field.value.length;		
		if (r<=0)
			cntfield.style.backgroundColor='red';					
		else if (r < 15)
			cntfield.style.backgroundColor='yellow';					
		else
			cntfield.style.backgroundColor='white';								
		return true;
	}
}


//--- blind Documents  ---------------------------------------------------
// show blind doc element with given DOM-ID 
function showBlind(elementId)
{
	var el= document.getElementById(elementId);	
	if (el==null)
		return;	 
	el.style.display='block';	 
}

// show blind doc element with given DOM-ID 
function hideBlind(elementId)
{
	var el= document.getElementById(elementId);	
	if (el==null)
		return;
	el.style.display='none';	
}


//--- setCookie ---------------------------------------------------
function setCookie(name, value, expires, path, domain, secure)
{
    document.cookie= name + "=" + escape(value) +
        ((expires) ? "; expires=" + expires.toGMTString() : "") +
        ((path) ? "; path=" + path : "") +
        ((domain) ? "; domain=" + domain : "") +
        ((secure) ? "; secure" : "");
}

//--- getCookie ---------------------------------------------------
function getCookie(name)
{
   var i=0;
   var suche = name+"=";
   while (i<document.cookie.length)
   {
      if (document.cookie.substring(i, i+suche.length)==suche)
      {
         var ende = document.cookie.indexOf(";", i+suche.length);
         ende = (ende>-1) ? ende : document.cookie.length;
         var cook = document.cookie.substring(i+suche.length, ende);
         return unescape(cook);
      }
      i++;
   }
   return null;
}


//--- KRIS helpWindow -------------------------------------------
function helpWindow(winUrl)
{
	window.open(winUrl,"alohaHelp","width=640,height=580,resizable=1,scrollbars=1").focus();
	return false;
}


//--- KRIS showWindow -------------------------------------------
// name ist ID vom fenster, nicht titel. Keine blanks im namen!
function showWin(winUrl,wname, width, height, scrollbars)
{
	var wos="width="+width+",height="+height+",left=0,top=0,resizable=1,scrollbars="+scrollbars;
//	alert(wos);
	window.open(winUrl,wname,wos).focus();
	return false;
}

//--- auto window resize
function rs()
{ 
	var x,y;
  var b=document.body, e=document.documentElement;
  var esw=0, eow=0, bsw=0, bow=0, esh=0, eoh=0, bsh=0, boh=0;
  if (e) {
    esw = e.scrollWidth;
    eow = e.offsetWidth;
    esh = e.scrollHeight;
    eoh = e.offsetHeight;
  }
  if (b) {
    bsw = b.scrollWidth;
    bow = b.offsetWidth;
    bsh = b.scrollHeight;
    boh = b.offsetHeight;
  }
  x= Math.max(esw,eow,bsw,bow);
  y= Math.max(esh,eoh,bsh,boh);
  // alert("y:" +y+" esh:"+esh+" eoh:"+eoh+" bsh: "+bsh+ " boh:"+boh);
	if (y > screen.availHeight-60) 
	{
	 	document.body.style.overflow='auto';
		y= screen.availHeight-60; 		
		// alert("y="+y+", screen.availHeight="+screen.availHeight);		
	}


	if (!document.all) 
	{
	 	window.innerHeight=y;
	} 
	else
	{
//		window.moveTo(0,0);
		window.resizeTo(x+20,y+33);  // IE
		//window.resizeBy(0,y-document.body.clientHeight-document.body.clientTop-3)
	}			
}


function rsOld()
{ 
	var y; 
	var sh= document.body.scrollHeight; 
	var oh= document.body.offsetHeight; 
	if (sh > oh)
		y= sh; 
	else
		y= oh; 
	if (y > screen.availHeight-50) 
	{
	 	document.body.style.overflow='auto';
		y= screen.availHeight-50; 		
//	alert("y="+y+", screen.availHeight="+screen.availHeight);		
	}
	if (!document.all) 
	 	window.innerHeight=y; 
	else
		window.resizeBy(0,y-document.body.clientHeight-document.body.clientTop-3)
}


//--- return window width
function getWindowWidth()
{
	if(typeof window.innerWidth != "undefined") 
		return window.innerWidth; 
	else if(typeof document.documentElement.offsetWidth != "undefined") 
		return document.documentElement.offsetWidth; 
	else 
		return document.body.offsetWidth; 
}

//--- return window height
function getHeight()
{
	if(typeof window.innerHeight != "undefined") 
		return window.innerHeight; 
	else if(typeof document.documentElement.offsetHeight != "undefined") 
		return document.documentElement.offsetHeight; 
	else 
		return document.body.offsetHeight; 
}



//-- KRIS get computed width of element (actung, kann "auto" retournieren, statt pixel-zahl! (iexplorer)
function getWidth(el)
{
	assert(el!=null, "Element for width with shall be evaluated must not be null!.");
	if(typeof window.getComputedStyle != "undefined") 	
     	return window.getComputedStyle(el,"" ).getPropertyValue("width");
	else if(typeof el.currentStyle != "undefined")
		return el.currentStyle.width;
	else if(typeof document.el != "undefined")
   		return document.el.width;
	else if(document.all)
    	return document.all.el.style.width;
}


//-- KRIS get computed height of element 
function getHeight(el)
{
	assert(el!=null, "Element for height with shall be evaluated must not be null!.");
	if(typeof window.getComputedStyle != "undefined") 	
     	return window.getComputedStyle(el,"" ).getPropertyValue("height");
	else if(typeof el.currentStyle != "undefined")
		return el.currentStyle.height;
	else if(typeof document.el != "undefined")
   		return document.el.height;
	else if(document.all)
    	return document.all.el.style.height;
}





//--- KRIS userSelectoinWindow
function openUserSelectorWindow(servletUrl, strQuery)
{
	//alert(strQuery);
  var w= (screen.width*10)/7;
  var h= screen.height/2;
  var iw= window.open(servletUrl+'?'+strQuery,
             'Users', 
             "resizable='yes',width="+(w+100)+",height="+h+",dependent='yes',left=80,top=30,scrollbars='yes'");
  iw.focus();
}


//--- KRIS showTab ---------------------------------------------------
// Tab's
// - Tab headers ID's must be named tab_[name]_0...tab_[name]_[n]. 
// Example: <a href="#" id="tab_edit_1" onClick = "showTab('edit',1);"> Tab One </a>
// - Tab panels  ID's must be named panel_[name]_0...panel_[name]_[n]. 
// Example: 
// <div id="panel_edit_3" class="panel">Content of Panel 3 within tab group named "edit"</div>
// - 'name' ist the name of the tab group and 'n' is an integer value of a specific tab within the named tab group.
// - 'name' shall not contain underscore '_' characters!  
// - n == 0 -> first tab, n==1 -> second tab etc...
// - Invoking method with panelNum== -1 will result in showing the tab number as stored in cookie.


var currPanelMap= [];

//var currentPanel= null;
function showTab(name, panelNum)  
{
	/*
	var x,y;  
	if (self.pageYOffset) // all except Explorer
	{
		x = self.pageXOffset;
		y = self.pageYOffset;
	}
	else if (document.documentElement && document.documentElement.scrollTop)
		// Explorer 6 Strict
	{
		x = document.documentElement.scrollLeft;
		y = document.documentElement.scrollTop;
	}
	else if (document.body) // all other Explorers
	{
		x = document.body.scrollLeft;
		y = document.body.scrollTop;
	}
  alert(x + "  "+y);
  */
	
//	alert(name+"--"+panelNum);
	// if negative panel num is given, we try to fetch last viewed panel from cookie
	if (panelNum== -1)
	{
		panelNum= getCookie(name);
		if (document.getElementById('panel_'+name+'_'+ panelNum) == null)   // panel exists?
			panelNum= 0;
	}
	setCookie(name, panelNum); //,  new Date(new Date().getTime() + 10*24*3600*1000));  //expires in 10 days
	var currentPanel= currPanelMap[name];
	if (currentPanel != null) 	
	{
		document.getElementById('panel_'+name+ '_'+ currentPanel).style.display = 'none';  // hide
		document.getElementById('tab_'+name+ '_'+ currentPanel).className="";
	}	
	// show tab
	var tabId= 'tab_'+name+ '_'+ panelNum;
	var tab=document.getElementById(tabId);
	if (tab== null)
		alert("No such tab: '"+tabId);
	var panelId= 'panel_'+name+ '_'+ panelNum;
	var panel= document.getElementById(panelId);	
	if (panel== null)
		alert("No such panel: '"+panelId);		
		
	tab.className='current';         // show tab
	panel.style.display = 'block';  // show	 panel
	
	currPanelMap[name] = panelNum;	// remember selected tab 	
	turnOnFirstChildPanels(panel);

//	window.scrollTo(x, y); 	 // doesn't work: Flickers and scrolls back...?
}

function turnOnFirstChildPanels(el) 
{
	var elc = el.childNodes;
	if (elc!= null)
	{
		for (var i=0; i< elc.length; i++)
		{			
			if (elc[i]== null)
				continue;
			turnOnFirstChildPanels(elc[i]);
			 var id= elc[i].id;
			 if (id != null && id.substring(0,6)=="panel_")
			 {				
				var infos= id.split("_");
				if (infos.length!=3)
					alert("function turnOnFirstChildPanels()\nInvalid panel ID format, must be 'panel_[name]_[0...n]'\nThis is wrong: "+id);
				
				var last= currPanelMap[infos[1]];
				if (last== null) 
					last='0';
				
				if (currPanelMap[infos[1]]== infos[2])
					continue; // this tab group already shown

				var tabId= "tab_"+infos[1]+"_"+infos[2];
				var tabO= document.getElementById(tabId);
				if (tabO== null)
					alert("function turnOnFirstChildPanels()\nFound no tab header with id= '"+tabId+"' for panel with id='"+id+"'");					
												
				if (infos[2]=='0')
				{						
					tabO.className='current';         // show tab
					elc[i].style.display = 'block';  // show panel
					currPanelMap[infos[1]]= infos[2]; // remember...
	//				alert(id);
				}
				else
				{
					// hide
					//alert("turn off "+ id);
					elc[i].style.display = 'none';  // hide
					tabO.className="";										
				}
			}
		}
	}
}




//--------- ajax stuff by Kris
//
//

//---- dump string "s" at end of page in footer area, last on top
function dump(s)
{
	var f= document.getElementById("footer");
	if (f== null)
		return;
	f.style.textAlign='left';
	f.innerHTML= s+"<br />"+f.innerHTML;
	f.onclick=function() { f.innerHTML="";}
}

function getXMLHttpReq()
{
	try {return new XMLHttpRequest();} catch (error) 	{ 
		try { return new ActiveXObject("Microsoft.XMLHTTP"); }
		catch (e) { window.alert("unable to create XMLHttpRequest. Reason: "+e); return null; }
	}
}


//-- update distinct element of a single doc.
// el: (div) element with ID, format "DOC:<docID>:<entity>", example: "DOC:1000001233:title"
function xupd(el)
{
 	var req = getXMLHttpReq();
	if (req== null)
		return;
	var id= el.id;
	var a= new Array();
	a= id.split(':');
	
//	alert(encodeURIComponent(el.innerHTML));
	// Parameters sent are:
	// ACX="commit" 
	// TYX="DOC"            (type of data to commit. Shall be only DOC for now)
	// DIX=<dcoument id> 
	// DPX=<doc property>   (one of the DOC.DOC_xxxxx properties, example DOC_TITLE) 
	// VALX=element value
   
//	var encVal= encodeURIComponent(el.innerHTML);
	var encVal= encodeURL(el.innerHTML);
	var url= basePath+'?ACX=commit&TYX='+a[0]+'&DIX='+a[1]+'&DPX='+a[2]+'&VALX='+encVal;
	
	
//	alert(url);
    req.open('post', url);   
	req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset:UTF-8');
	
//	if (req.overrideMimeType)
//		req.overrideMimeType('text/html;charset=iso-8859-1');
	    
    req.onreadystatechange= createHandler(req,id);
	req.send(null);    
    dump("Req ID Sended: "+id);
}

function createHandler(req,elId) // request, source element ID
{
	return function()
	{
		if (req.readyState!=4)
			return;
		dump("ResponseText: "+req.responseText);
		dump("source ID: <b>"+elId+"</b> status: "+req.status+" readyState: "+req.readyState+ " statusText: "+req.statusText);
		// 0: uninitialized(never)   1: loading(1x)   2: loaded(1x)  3: interactive(5x) 4: complete(1x)
	}
}



function handleResponse(event) 
{
	alert("handleRes");
    if(http.readyState == 4)
    {
        var response = http.responseText;
        var update = new Array();

        if(response.indexOf('|' != -1)) 
        {
            update = response.split('|');
            document.getElementById(update[0]).innerHTML = update[1];
        }
    }
}

// basierend auf  http://www.101systems.de/ger/AJAX.html
function encodeURL(pp)
{
	var hex = "0123456789ABCDEF"; 
	var strSafeChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.!~*'()";	
	var len= pp.length;	
	var res;
	
	try 
	{ 
		res= new Array((len*4)/3 );
	}
	catch (exc)
	{
		res= new Array();
	}  
	
	for (var i=0; i<len; i++ ) 
	{
		var c = pp.charAt(i); //Schneller
		if (c == " ") 
		    res.push("+");	// x-www-urlencoded, JS Funktion escape macht daraus %20.
		else if (strSafeChars.indexOf(c) != -1) 
		    res.push(c); //Normales sicheres Zeichen
		else 
		{
			var cVal = c.charCodeAt(0); //charCodeAt gibt den UNICODE zurück
			if (cVal > 255) 
			{
				res.push("%26%23"); res.push(cVal); res.push("%3B");
			} 
			else 
			{
				res.push("%");
				res.push(hex.charAt((cVal >> 4) & 0xF)); //Ok we do it in Hex
				res.push(hex.charAt(cVal & 0xF));//Ok we do it in Hex
			}
		}
	} 	
	return res.join('');
};



// basierend auf  http://www.101systems.de/ger/AJAX.html
function encodeURLOld(pp)
{
	// Die escape Funktion macht nicht so ganz was ich dachte das Sie machen soll ...
	
	var hex = "0123456789ABCDEF"; //javascript hat leider keine tohex Funktion
	var strSafeChars = "0123456789" +					// Numerische Zeichen
					"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +	// Alphanumerische Zeichen
					"abcdefghijklmnopqrstuvwxyz" +
					"-_.!~*'()";					
	
	res = ""; //Puffer löschen
	
	for (var i = 0; i < pp.length; i++ ) 
	{
		var c = pp.charAt(i); //Schneller
		if (c == " ") 
		    res += "+";	// x-www-urlencoded, JS Funktion escape macht daraus %20.
		else if (strSafeChars.indexOf(c) != -1) 
		    res += c; //Normales sicheres Zeichen
		else 
		{
			var cVal = c.charCodeAt(0); //charCodeAt gibt den UNICODE zurück
			if (cVal > 255) 
			{
				//Wenn wir einen Unicode haben dann maskieren wir diesen als 
				//HTML-Code &#<UNICODE>;
				
				//natürlich urlencoded
				res += "%26%23"+cVal+"%3B";
				//Keine Angst das kann man einfach speichern.
				//Die Browser setzen das Zeichen wieder um
			} 
			else 
			{
				//Alle anderen Zeichen werden als Hexcode geschrieben
				res += "%";
				res += hex.charAt((cVal >> 4) & 0xF); //Ok we do it in Hex
				res += hex.charAt(cVal & 0xF);//Ok we do it in Hex
			}
		}
	} //for länge der Zeichenkette
	return res;
};


//
// Make block element 'el' Editable by replacing it with a temporary TEXTAREA 
// <div id="title:1001020" onclick='mkEd(event, this);'>Der titel</div>
// During editing, special CSS class "eip" is added. "eip" thus shall mark a border or similar.
function mkEd(event,el)
{
//return;

	if (event== null)
		event = window.event; // iexplorer. 
	if (event!= null && !event.ctrlKey)  
    	return;

	var w= el.offsetWidth;
	var h= el.offsetHeight;
//	alert ("width: "+w+" height: "+h);
// alert(getWidth(el)+" : "+getHeight(el));

	var ta= document.createElement("textarea");	
	ta['oldElement']=el;
	ta.className= el.className+" eip";
	ta.value= el.innerHTML; 
	var tas= ta.style;
	var ns= el.style;
	
//	tas.border= ns.border;
//alert("parent padding: "+ns.padding+ " margin: "+ns.margin);
//	tas.padding= ns.padding;
//	tas.margin= ns.margin;
//	tas.font= ns.font;

	tas.width= w<200?200:w+2; //"500px"; //"100%"; 
	tas.height=h<20?20:h+2;
//	tas.overflow="hidden";
	
	el.parentNode.replaceChild(ta, el);
	 
	ta.focus();	// first::
			
	
	ta.onblur = function(event)
	{
		// alert("onblur");
		if (!event) event = window.event
		if (event.target) 
		{ 
		//alert("moz event type "+event.target.nodeType);
			if (event.target.nodeType== 3) 
				event.target= event.target.parentNode
		} 
		else if (event.srcElement)  // IE event
			event.target= event.srcElement;				
		
		
		var ta= event.target;
		var oldElement= ta['oldElement']; 
		//alert(ta.oldElement.nodeName);				
		if (oldElement==null)
		{
			alert("old element type to restore not found in: "+ ta);
			return;
		}
		if ( oldElement.innerHTML != ta.value)
		{
			oldElement.innerHTML= ta.value;			
			//>>>>>
			xupd(oldElement);  // send content to server
			//<<<<<				
		}	
		ta.parentNode.replaceChild(oldElement, ta);
		ta.value=null;
	}	
	ta.focus();	// second:: we need focus twice. Only arafat knows why...
}


function setupEditInPlace()
{
	if (editInPlaceInit==true)
		return;
	
	tinyMCE.init({
			mode : "none",
			theme : "advanced",
			content_css : '../stylesheet.css',
			convert_urls : false,
			
			plugins : "safari,style,table,save,advhr,advimage,advlink,emotions,iespell,media,searchreplace,contextmenu,paste,visualchars,nonbreaking",
			theme_advanced_buttons1 : "save,cancel,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect",
			theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,forecolor,backcolor",
			theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,",
			theme_advanced_toolbar_location : "bottom",
			theme_advanced_toolbar_align : "left",
			theme_advanced_statusbar_location : "bottom",			
			theme_advanced_resizing : true, 
			   
			save_enablewhendirty : false,
			save_onsavecallback : "saveEditorToAjax",	
			save_oncancelcallback : "cancelEditor"	
		});		
		editInPlaceInit=true; // remember that init is now done, if method invoked a 2nd time, we won't init again.
}

// Make block 'el' element Editable with TINYMCE 
// <div id="body:1001020" onclick='mkEd2(event, this);'>The body</div>
function mkEd2(event,el)
{
//return;

	if (event== null)
		event = window.event; // iexplorer. 
	if (event== null || !event.ctrlKey)  
    	return;

	//alert(basePath);
	
	setupEditInPlace();

	var eOld= tinyMCE.activeEditor;
	if (eOld!= null)
	{
//		alert("removing prev Editor: "+eOld.getElement().id);
		try
		{
			if (eOld.isDirty())
			{
				try { tinyMCE.activeEditor.undoManager.undo(); } catch(err1)	{window.alert("can not undo old editor contents. reason:\n"+err1.toString()); }
				ed.isNotDirty = true; // Force not dirty state
			}
			eOld.remove();
		}
		catch (err)
		{
//			window.alert("error while removing previous tinymce. Reason: "+err.toString());
		}
	}

	var elm = document.getElementById(el);
	if (tinyMCE.getInstanceById(el) == null) 
	{
		tinyMCE.execCommand('mceAddControl', false, el);
//		alert("created: "+el.id);
	}
}

// invoked by tinymce when save icon is clicked, because of line 	
//    save_onsavecallback : "saveEditorToAjax"
// in tinyMCE.init.
function saveEditorToAjax(ed)
{
//	alert(ed.getElement().innerHTML);

	if (ed.isDirty())
	{
//		ed.setProgressState(1);
		var elDiv= ed.getElement();
//		alert("Save using ajax element with id: "+elDiv);
		try
		{				
			xupd(elDiv);
			ed.isNotDirty = true; // Force not dirty state						
		}
		catch (err)
		{
			window.alert("ERROR: Unfortunately, I was not able to send your data to the server.\n" +
					"Please note that your changes to this page are probably lost, even if you see them here. Try reloading the page...\n" +
					"Reason: "+err.toString());
		}
//		ed.setProgressState(0);				
	}
//	ed.hide(); // hide (not removing!)    
	ed.remove();
//	tinyMCE.execCommand('mceRemoveControl', false, ed);
    
    return true; // Continue handling
}


function  cancelEditor()
{
//	alert("cancel clicked");	
	var ed= tinymce.EditorManager.activeEditor;
	var h = tinymce.trim(ed.startContent);
	ed.setContent(h);
	//ed.undoManager.clear();
	//ed.nodeChanged();	
	ed.remove();
//    tinyMCE.execCommand('mceRemoveControl', false, ed);
    return true;		
}




// return null if string is empty, consists of blanks, tabs or \n only or if it is already null
function trim(s)
{
	if (s== null || s.length== 0)
		return null;
	var i;
	var end= s.length;	
	for (i=0; i< end; i++)
	{
		var c= s.charAt(i);
		if ( c!=" " && c!= "\n" && c!="\t" )
			break;
	}
	if (i== end)
		return null;
	var start=i;  // first non blank

	for (end= s.length-1; end> start; end--)
	{
		var c= s.charAt(end);
		if ( c!=" " && c!= "\n" && c!="\t" )
			break;
	}
//	alert("2("+s+") start="+start+" end="+end);	
	if (start==0 && end== s.length-1)
		return s; // unchanged string
	return s.substring(start, end+1);
}

// -- KRIS DOM utilities -----------------------------------------------------------------------------------
function isChecked(elementId)
{
	var elSource=document.getElementById(elementId);
	assert(elSource!=null, "Can't see whether input element '"+elementId+"' is checked: It can not be found in the document.");		
	assert( typeof(elSource.checked) != "undefined",  "The element '"+elementId+"' has no 'checked' property, thus it is not a checkable element.");
	return elSource.checked;
}

function setChecked(elementId, bool)
{
	var elTarget=document.getElementById(elementId);
	assert(elTarget!=null, "Can't check/uncheck input element '"+elementId+"' : It can not be found in the document.");		
	assert( typeof(elTarget.checked) != "undefined",  "The element '"+elementId+"' has no 'checked' property, thus it is not a checkable element.");			
	elTarget.checked= bool;
}

// elementIds: array of ID's of elements that have the "checked" property elements
// returns first element which is checked. Null if none checked.
/* function getCheckedElement(elementIds)
{
	assert(elementIds!=null, "Array parameter that shall contain element Id's can be 'null' ");
	for (i=0; i< elementIds.length; i++)
	{
		if (isChecked(elementIds[i]))
			return getElement(elementIds[i]);
	}
	return null;
}
*/

// nameAttribute: Name attribute of elements to check. Multiple elements may carry the same name attribute.
// All elememts must posess the "isChecked()" method.
// returns only the first element which is checked. Null if none checked.
function getCheckedElementByName(nameAttribute)
{
	assert(nameAttribute!=null, "nameAttribute parameter can not be 'null' ");
	var els= document.getElementsByName(nameAttribute);
	assert(els!=null, "found no elements with name attribute='"+nameAttribute+"'");
	for (i=0; i< els.length; i++)
	{
		if (els[i].checked== true )
			return els[i];
	}
	return null;
}


// nameAttribute: Name attribute of input elements to be enabled or disabled. Multiple elements may carry the same name attribute.
// boole: true= enable, false= disable input element
function enableElementsByName(nameAttribute, bool)
{
//	alert(nameAttribute+" --> "+bool);
	assert(nameAttribute!=null, "nameAttribute parameter can not be 'null' ");
	var els= document.getElementsByName(nameAttribute);
	assert(els!=null, "found no elements with name attribute='"+nameAttribute+"'");
	for (i=0; i< els.length; i++)
		els[i].disabled= !bool;
}


// id: ID of input element to be enabled or disabled. 
// boole: true= enable, false= disable input element
function enableElement(id, bool)
{
//	alert(id+" --> "+bool);
	assert(id!=null, "id parameter can not be 'null' ");
	var el= document.getElementById(id);
	assert(el!=null, "found no element with name id='"+id+"'");
	el.disabled= !bool;
}

// returns element with given ID, assertion fail otherwise.
function getElement(elementId)
{
	assert(elementId!=null, "Can't seek for an element if the given ID is null!");		
	var el= document.getElementById(elementId);
	assert(el!=null, "Can't 'getElementById ('"+elementId+"'): It does not exist in this document!");			
	return el;
}


// returns element with given ID in given doc, assertion fail otherwise.
function getElementInDoc(elementId, doc)
{
	assert(elementId!=null, "Can't seek for an element if the given ID is null!");		
	assert(doc!=null, "Can't seek for an element if the given doc is null!");			
	var el= doc.getElementById(elementId);
	assert(el!=null, "Can't 'getElementById ('"+elementId+"'): It does not exist in the given document!");			
	return el;
}

// -- ASSERTIONS -----------------------------------------------------------------------------------
// The following modified (shrinked) code is taken from jsUnit 2.1.
// http://www.jsunit.net/
// It is available under several licenses: the GPL, LGPL, and MPL.
//

function assert(booleanValue, failureMessage) 
{
  if (!booleanValue)
    throw new JsUnitException("Assertion failure:", failureMessage);
}



function getStackTrace() {
  var result = '';

  if (typeof(arguments.caller) != 'undefined') { // IE, not ECMA
    for (var a = arguments.caller; a != null; a = a.caller) {
      result += '> ' + getFunctionName(a.callee) + '\n';
      if (a.caller == a) {
        result += '*';
        break;
      }
    }
  }
  else { // Mozilla, not ECMA
    // fake an exception so we can get Mozilla's error stack
    var testExcp;
    try
    {
      foo.bar;
    }
    catch(testExcp)
    {
      var stack = parseErrorStack(testExcp);
      for (var i = 3; i < stack.length; i++)
      {
        result += '> ' + stack[i] + '\n';
      }
    }
  }
  return result;
}

function parseErrorStack(excp)
{
  var stack = [];
  var name;
  
  if (!excp || !excp.stack)
    return stack;  
  var stacklist = excp.stack.split('\n');
  for (var i = 0; i < stacklist.length - 1; i++)
  {
    var framedata = stacklist[i];
    name = framedata.match(/^(\w*)/)[1];
    if (!name) 
      name = 'anonymous';
    stack[stack.length] = name;
  }
  // remove top level anonymous functions to match IE

  while (stack.length && stack[stack.length-1]=='anonymous')
    stack.length = stack.length - 1;

  return stack;
}


function getFunctionName(aFunction) {
  var name = aFunction.toString().match(/function (\w*)/)[1];

  if ((name == null) || (name.length == 0))
    name = 'anonymous';

  return name;
}

function JsUnitException(comment, message) {
  this.isJsUnitException = true;
  this.comment           = comment;
  this.jsUnitMessage     = message;
  this.stackTrace        = getStackTrace();
  this.toString= myToString;
  
  function myToString() 
  {
	  return comment+"\n"+message+".\n\nStack trace:\n"+this.stackTrace
  }

  
  alert(this.toString());
}


// Copyright (C) krikkit - krikkit@gmx.net
// --> http://www.krikkit.net/
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
 
function copy_clip(meintext)
{
 if (window.clipboardData) 
   {
	   // the IE-manier
	   window.clipboardData.setData("Text", meintext);
	   // waarschijnlijk niet de beste manier om Moz/NS te detecteren;
	   // het is mij echter onbekend vanaf welke versie dit precies werkt:
   }
   else if (window.netscape) 
   { 

	   var clip= null;
	   try
	   {
		   // dit is belangrijk maar staat nergens duidelijk vermeld:
		   // you have to sign the code to enable this, or see notes below 
		   netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
		   // maak een interface naar het clipboard	   	
		   clip = Components.classes['@mozilla.org/widget/clipboard;1']
		                 .createInstance(Components.interfaces.nsIClipboard);
		}
		catch(e)
		{
			window.alert("You can not use copy-to-clipboard function in mozilla.\n" +
					"Reason: Your web browser security settings do not allow this,\n\n" +
					"you may want to loosen the specific setting:\n"+
					"To do this add this line to your prefs.js file in your firefox/mozilla user profile directory:\n\n"+
					"user_pref(\"signed.applets.codebase_principal_support\", true);\n\n"+
					"or change it from within the browser with calling the \"about:config\" page\n\n"+
					"("+e.toString()+")"
			);
		}
		
		    
	   if (!clip) return;
	   // maak een transferable
	   var trans = Components.classes['@mozilla.org/widget/transferable;1']
	                  .createInstance(Components.interfaces.nsITransferable);
	   if (!trans) return;
	   // specificeer wat voor soort data we op willen halen; text in dit geval
	   trans.addDataFlavor('text/unicode');
	   // om de data uit de transferable te halen hebben we 2 nieuwe objecten 
	   // nodig om het in op te slaan
	   var str = new Object();
	   var len = new Object();
	   
	   var str = Components.classes["@mozilla.org/supports-string;1"]
	                .createInstance(Components.interfaces.nsISupportsString);
	   var copytext=meintext;
	   str.data=copytext;
	   trans.setTransferData("text/unicode",str,copytext.length*2);
	   var clipid=Components.interfaces.nsIClipboard;
	   if (!clip) return false;
	  	clip.setData(trans,null,clipid.kGlobalClipboard);
   }
//   alert("Following info was copied to your clipboard:\n\n" + meintext);
   return false;
}


// Script by hscripts.com 
//        copyright of HIOX INDIA 
// select (highlight) the element (like when marking text). Does not work when BR's are in it..
function selectElement(objId) 
{
//	alert(objId.toString());
	deSelectElement();
	if (document.selection) 
	{
		var range = document.body.createTextRange();
    	range.moveToElementText(document.getElementById(objId));
		range.select();
	}
	else if (window.getSelection) 
	{
		var range = document.createRange();
		range.selectNode(document.getElementById(objId));
		window.getSelection().addRange(range);
	}
}

		
function deSelectElement() 
{
	if (document.selection) 
		document.selection.empty(); 
	else if (window.getSelection)
    	window.getSelection().removeAllRanges();
 }


