var debug = false;
	
var MAC = (navigator.platform.indexOf("PPC") > 0);
var IE5 = (navigator.userAgent.indexOf("MSIE 5") > 0);
var SAFARI=(navigator.userAgent.indexOf("Safari") > 0);
var FIREFOX = (navigator.userAgent.indexOf("Firefox") > 0);

var isIE = navigator.appName.indexOf('Microsoft') != -1;
var isNetscape = navigator.appName.indexOf('Netscape') != -1;
var isMac = navigator.userAgent.toLowerCase().indexOf('mac') != -1;

// disable the global event handlers if we are in the unittesting framework
// because the framework use them too.
// todo: ask the jsunit guys to add a identifier of some kind.
if(typeof(newOnLoadEvent) == 'undefined')
{
	// Mozilla, Safari & Mac Explorer
	if(document.addEventListener)
	{
		if(SAFARI) // safari don't support the keyup event
        	document.onkeyup = keyListener;
        else
        	document.addEventListener("keyup",keyListener,false);

        window.addEventListener("load",doLoad,false);
		debugprint("add load for:" + window.name);

		window.addEventListener("unload",doUnLoad,false);
	}
	// Windows Explorer
	else
	{
		document.onkeyup = keyListener;
		window.onload    = doLoad;
		window.onunload  = doUnLoad;
	}
}

// global variable used to lock the links
// (actually only the instance of this variable in the details window is used to lock the links)
var linksUnlocked = false;

function eatEvent(e)
{
	if (!e) return;
	if (e.preventBubble)
	{
		e.preventBubble();	// NN6
	}
	else if (typeof(e.cancelBubble) == 'boolean')
	{
		event.cancelBubble = true;	// IE5+
	}
}

function debugprint( msg )
{
	if ( debug != false )
	{
		if(SAFARI)
		{
			if(window.console) 
			{
				window.console.log(msg);
			}		
		}
		else {
			try
			{
				var debugWindow = null;
			
				if ( top.debugWindow )
				{
					debugWindow = top.debugWindow;
				}
				
				if ( ( debugWindow == null ) || ( debugWindow.closed ) )
				{
					debugWindow = window.open( "", "debugWindow", "width=400, height=800, resizable=yes, scrollbars=yes" );
					debugWindow.document.open( "text/plain" );
				
					top.debugWindow = debugWindow;
				}
		
		        var now = new Date();
		        var prefix = 	((now.getHours() < 10) ? '0' + now.getHours() : now.getHours())  + ":" + 
		        				((now.getMinutes() < 10) ? '0' + now.getMinutes() : now.getMinutes()) + ":" + 
		        				((now.getSeconds() < 10) ? '0' + now.getSeconds() : now.getSeconds());
				
				debugWindow.document.writeln( prefix + " " + msg );
				debugWindow.focus();
			}
			catch(e)
			{
				// alert("Caught exception: \n" + e.message + "\nWhile trying to log message: \n" + msg);
			}		
		}
	}
}

function unlockSubmission()
{
	debugprint( 'unlocking submission' );

	var updateForm = document.getElementById("updateForm");
	if ( updateForm )
	{
		updateForm.submitting = false;
	}

	return false;
}

function lockSubmission()
{
	debugprint( 'lock submission' );

	var updateForm = document.getElementById("updateForm");
	if ( updateForm &&  !updateForm.submitting )
	{
		// debugprint( 'locking submission' );

		updateForm.submitting = true;
		return true;

	}

	debugprint( 'sorry, submission locked' );

	return false;
}

// MS IE resets the field when you press ESC the first time.
// MS IE also resets the form  when you press ESC the second time.
// The latter is something we don't want so we implement our own
// onreset event handler which cancels the editable form instead.
function cancelForm()
{
//	if (parent.frames.actionBar && parent.frames.actionBar.doCancel)
//		return parent.actionBar.doCancel();
//	else
		return false;
}

function getMainFrame()
{
	return top;
}

function showFrame(target)
{
	var frame = getMainFrame();
	
	if (frame && frame.showFrame)
	{
		frame.showFrame(target);									
	}
}

function showContentFrame()
{
	showFrame("content");	
}

function doLoad()
{
	debugprint("doLoad(): " + window.name);
	// hook reset event for all forms in the "details" frame

	//Mamun - used to avoid the submiting if the return key is pressed
    if(MAC)
        setOnSubmitEventHandler();

    if (window.name == "details" && document.forms)
	{
		for (var i = 0; i < document.forms.length; i++)
		{
			var frm = document.forms[i];
			frm.onreset = cancelForm;
		}
	}

	unlockSubmission();
	
	if (window.name == "details")
	{		
		window.loaded = true;	// needed to know for initializing actions
		showContentFrame();
		// only for the details window, clear the actions (we may need the row actions in confirmation windows)
		SetRowActions( document.getElementById("updateForm"), "" );
		
		// after loading the details window unlocks the links and enables the info select boxes
		// unlockLinksAndInfoSelects(); // moved to delanohtml:form (AccessFormTag)		
	}
	
	if (window.name == "info")
	{
		debugprint("window.name == info");
		// after loading the info window, update the info select boxes that were disabled by default
		if (!linksAreLocked())
		{
			enableInfoSelects();
		}
	}
	
	// needed to avoid problems on mac ie with accentuated characters in drop down boxes
	if (MAC && IE5)
	{
		triggerSelects();
	}

	
    if(document.initialize)
    {
    	document.initialize();
    }

	if ( document.initializeSelection )
	{
		document.initializeSelection();
	}
}


// needed to avoid problems on mac ie with accentuated characters in drop down boxes
function triggerSelects()
{
	// avoid triggering the selects twice
	if (!document.selectsTriggered || document.selectsTriggered != 'true')
	{
		var selects = document.getElementsByTagName('select');
		if (selects)
		{
			for (var i=0; i<selects.length;i++)
			{
				for (var j=0; j<selects[i].options.length; j++)
				{
					selects[i].options[j].text = selects[i].options[j].text;
				}
			}
		}
		document.selectsTriggered = 'true';
	}
}


// used to bring the element into view (mainly when going up from 1 resonde to a table

function scrollToElement( targetId ) // should be renamed to scrollToElementById and call scrollToElement
{
	if ( targetId && ( targetId.length > 0 ) )
	{
		var element = document.getElementById( targetId );

		if ( element )
		{
		    if ( window.scrollTo )
			{
				var position = absolutePosition( element );
				var offset = 25;
				var y = ( position.y > offset ) ? position.y - offset : position.y;
				window.scrollTo( 0, y );
			}

			/*
			if ( element.scrollIntoView )
			{
				element.scrollIntoView( false );
			}
			else if ( window.scrollTo && element.y )
			{
				window.scrollTo( 0, element.y );
			}
			else if ( document.scrollTo && element.y )
			{
				document.scrollTo( 0, element.y );
			}
			else if ( window.scrollTo )
			{
				var position = absolutePosition( element );

				window.scrollTo( 0, position.y );
			}
			else if ( document.scrollTo )
			{
				var position = absolutePosition( element );

				document.scrollTo( 0, position.y );
			}
			else
			{
				// alert( "no scrolling" );
			}
			*/
		}
	}
	
}

function scrollToElementEx( element ) // should be renamed to scrollToElement
{
	if ( element && window.scrollTo)
	{
		var position = absolutePosition( element );
		var offset = 25;
		var y = ( position.y > offset ) ? position.y - offset : position.y;
		window.scrollTo( 0, y );
	}
}


function scrollToTop()
{
    if ( window.scrollTo )
	{
		window.scrollTo( 0, 0 );
	}
}

// used to avoid the submiting if the return key is pressed
// test the content of the flag submitting

function canSubmit()
{
    var updateForm = document.getElementById("updateForm");

    if ( updateForm &&  updateForm.submitting )
    {
        return updateForm.submitting;
    }

    return false;
}

// used to avoid the submiting if the return key is pressed
// init the onSubmit EventHandler for the updateForm

function setOnSubmitEventHandler()
{
	var updateForm = document.getElementById("updateForm");

	if ( updateForm )
	{
        updateForm.onsubmit=canSubmit;
	}
}


function closeDialogWindow(myDocument)
{
	if(myDocument)
    {
		if(myDocument.dialog)
	    {
			if(/*myDocument.dialog.open &&*/ !myDocument.dialog.closed)
		    {
		    	myDocument.dialog.close();    	
		    	myDocument.dialog = null;
			}
		}
    }
}

function doUnLoad()
{
	closeDialogWindow(document);

    unlockSubmission();
	SetRowActions( document.getElementById("updateForm"), "" );
}


function keyListener(e)
{
	var continueToBubble = true;
	var keyCode = 0;
	if(window.event) {
		keyCode = window.event.keyCode;
	}
	else {
		keyCode = e.keyCode;
	}

	switch (keyCode)
	{
		case 27:
			if (!document.all) // NN
			{
				// NN does not do the "fancy" ESC handling IE does (i.e. no
				// field and form resetting), so the form reset event is never
				// fired when the user presses ESC, which in turn means our reset
				// event handler never gets called so the form doesn't get cancelled.
				// That's why we cancel the form "manually" here.
				cancelForm();
				continueToBubble = false;
			}
			// note that for MS IE, we allow the event to bubble
			// up all the way to the browser so it can
			// fire the reset event for either the field or the form.
			// In the latter case we handle the event and cancel
			// the form (see window.onload)
			break;
		case 13:
			if (parent.actionBar && parent.actionBar.doSave)
			{
				//mamun younes privent submision
				//parent.actionBar.doSave();
			}
			continueToBubble = false;
			break;
		case 0:
		default:
			continueToBubble = true;
			break;
	}
	return continueToBubble;
}

function updateClock()
{
    // changed to use id which is also defined on the clock input field.
    var clock = document.getElementById("input:clock");
    if ( clock )
    {
        var time = new Date();
        timezoneoffset = time.getTimezoneOffset();
        if ( ( navigator.appVersion.indexOf( 'MSIE 3' ) != -1 ) ) timezoneoffset = timezoneoffset * ( -1 );
        var hours   = time.getHours();
        var minutes = time.getMinutes();

        var seconds = time.getSeconds();
	  clock.innerHTML = ((hours < 10) ? '0' + hours : hours) +
                                  ':' + ((minutes < 10) ? '0' + minutes : minutes) +
                                  ':' + ((seconds < 10) ? '0' + seconds : seconds);
        setTimeout( "updateClock()", 1000 );
    }
}

function resizeInfoFrame()
{
	var infodiv = document.getElementById("infodiv");
	var contentFrameSet = parent.document.getElementById("inner");
	if ( ( infodiv != null ) &&
		 ( infodiv.style != null ) &&
		 ( infodiv.style.height != null ) )
	{
		var rows = contentFrameSet.rows;
		var row  = rows.split(",");

		row[ 1 ] = infodiv.style.height;

		contentFrameSet.rows = row.join();
	}
}

function loadInTopFrame()
{
	if ( top.location != self.location )
	{
		top.location.replace( self.location.href );
	}
}

function loadInContentFrame(action)
{
	if ( top.location == self.location )
	{
		top.location.replace( "main.do" );
    }
    else if (action && (action != null) && (action.length > 0) && (action != 'null'))
    {
    	location.href = action;
    }
}

function showPreview( preview, title )
{

	if ( ( preview != null ) && ( preview.length > 0 ) )
	{
		// construct a valid window name by replacing all (g)
		// series (+) of non-word characters (\W) with an underscore
		var windowname       = title.replace( /\W+/g, "_" );
		var previewWindow 	 = window.open( '', windowname, 'resizable=yes, scrollbars=yes' );
		var previewDocument	 = previewWindow.document;

		previewDocument.open();
		previewDocument.writeln( '<html>' );
		previewDocument.writeln( '	<head>' );
		previewDocument.writeln( '		<title>' + title + '</title>' );
		previewDocument.writeln( '	</head>' );
		previewDocument.writeln( '	<frameset rows="*" cols="*" border="0" framespacing="0" frameborder="no">' );
		previewDocument.writeln( '		<frame src="' + preview + '">' );
		previewDocument.writeln( '	</frameset>' );
		previewDocument.writeln( '</html>' );
		previewDocument.close();
	}

	return false;
}

function downloadSunJRE(url)
{
	var width = 1016;
	var height = 900;
	var staticWindowOptions = "status=no,scrollbars=yes,resizable=yes,toolbar=no,menubar=no";
	var LeftPosition = (screen.width) ? (screen.width-width)/2 : 100;
	var TopPosition = (screen.height) ? (screen.height-height)/2 : 100;
	var settings = 'height=' + height + ',width=' + width + ',top=' + TopPosition + ',left=' + LeftPosition + ',' + staticWindowOptions;
	if(!url)
		url = "http://dlres.java.sun.com/PluginBrowserCheck";

	var dialog = window.open(url, "download", settings).focus();
}

function SetRowActions( form, action, prefix )
{
	if ( form )
	{
		var inputs = form.getElementsByTagName( "INPUT" );

		for ( var index = 0; index < inputs.length; index++ )
		{
			var input = inputs[ index ];

			// set all inputs matching "row[index].action" to action.
			if ( input.name && input.name.match( /row\S\d+\S\.action$/ ) )
			{

				if ( prefix )
				{
					if ( input.name.indexOf( prefix ) == 0 )
					{
						input.value = action;
					}
				}
				else
				{
					input.value = action;
				}
			}

        }
    }
}

// this "get" function should only be used from getNext or xxxAndGetNext
function get( next )
{
	var updateForm = document.getElementById("updateForm");

	if ( updateForm.next )
	{
		updateForm.next.maxLength = next.length + 1;
		updateForm.next.value = next;

        // call the pre submit initialization, previously this was done inside an overriden
        // submit button. but is changed because mac ie doesn't support this feature for browser objects.
        if(document._submit)
        {
         	document._submit(updateForm);
        }
		
	  	// submit the form	
		try 
		{ 
			updateForm.submit(); 
		} 
		catch (e) 
		{ 
			unlockSubmission();
			if(self.displayWarning) 
				displayWarning();
		}
	}

	return false;
}


function unlockLinksAndInfoSelects()
{
	unlockLinksAndInfoSelectsDefaultImpl();
}

function unlockLinksAndInfoSelectsDefaultImpl()
{
	unlockLinks();
	if (parent && parent.info && parent.info.enableInfoSelects)
	{
		parent.info.enableInfoSelects();
	}
}

// this function should be called only directly from info bar
function enableInfoSelects()
{
	try
	{
		if (document)
		{
			var infoDoc = document;
			var selects = infoDoc.getElementsByTagName('select');
			if (selects)
			{
				for (var i=0; i< selects.length; i++)
				{
					var select = selects[i];
					if (select)
					{
						select.disabled = false;
						debugprint("select.disabled = false");
					}
				}
			}
		}	
	} 
	catch (ex) 
	{
		debugprint("exception: " + e.message);
  	}
	
}

function unlockLinks()
{
	linksUnlocked = true;
}

function detailsPresent()
{
	if (parent && parent.details)
		return true;
	return false;
}

function linksAreLocked()
{
	if ( detailsPresent() && !parent.details.linksUnlocked)
		return true;
	return false;
}

function getNext( next )
{
	if (linksAreLocked())
		return;

	var frame = null;
	
	if ( parent && parent.details )
	{
		frame = parent.details;
	}
	else if ( parent && parent.content )
	{
		frame = (!parent.content.details) ? parent.content : parent.content.details;
	}
	
	if (frame)
	{
		var document = frame.document;

		// added "interactive" to avoid freeze of links in some cases
		if (document && document.all && document.readyState != "complete" && document.readyState != "interactive")
		{
			return false;
		}
		
		if (frame.internalGetNext)
		{
			return frame.internalGetNext( next );
		}
	}

	return false;
}

function internalGetNext( next ) // formerly called getNext
{
	var updateForm = document.getElementById("updateForm");

	if ( updateForm && updateForm.edited )
	{
		if ( updateForm.edited.value == "true" || updateForm.edited.value == true )
		{
			updateForm.handleMethod.value = "confirm";
		}
		else
		{
			return cancelAndGetNext( next );
		}
	}

	if ( updateForm && lockSubmission() == true )
	{
		return get( next );
	}

	return false;
}

function saveAndGetNext( next )
{
	if ( lockSubmission() == true )
	{
		var updateForm = document.getElementById("updateForm");
		if ( updateForm && updateForm.handleMethod )
		{
			updateForm.handleMethod.value = "yes";
			return get( next );
		}
	}

	return false;
}

function cancelAndGetNext( next )
{
   	if ( lockSubmission() == true )
   	{
  		var cancelForm = document.getElementById("cancelForm");
  		if ( cancelForm && cancelForm.handleMethod )
  		{
  			cancelForm.handleMethod.value = "no";
			if ( cancelForm.next )
			{
				var encodedNext = '';
				var keyValuePairs = next.split('&');

				for ( var i=0; i<keyValuePairs.length; i++)
				{
					var keyValuePair = keyValuePairs[i];
					var paramValue = keyValuePair.split('=');
					if ( paramValue[1] )
					{
					    if ( encodedNext=='' )
					    {
					        if ( paramValue[1]=='' )
							{
							    paramValue[1] = '&';
							    encodedNext = paramValue[0] + '=' + escape(paramValue[1]);
							}
							else
							{
							    encodedNext = paramValue[0] + '=' + /*escape(*/paramValue[1]/*)*/;
							}
					    }
					    else
					    {
					        if ( paramValue[1]=='' )
							{
							    paramValue[1] = '&';
	         					    encodedNext = encodedNext + '&' + paramValue[0] + '=' + escape(paramValue[1]);
							}
							else
							{
							    encodedNext = encodedNext + '&' + paramValue[0] + '=' + /*escape(*/paramValue[1]/*)*/;
							}
					    }
					}
					// case of only one single key (i.e. next does not represent a set of key value pairs)
					else if ( encodedNext=='' )
					{
						encodedNext = paramValue[0];
					}
				}

				//cancelForm.next.maxLength = next.length + 1;
				//cancelForm.next.value = next;
				cancelForm.next.maxLength = encodedNext.length + 1;
				cancelForm.next.value = encodedNext;
				cancelForm.submit();
			}
  		}
   	}
   	return false;
}

function cancelAndReloadNext( next )
{
   	if ( lockSubmission() == true )
   	{
  		var cancelForm = document.getElementById("cancelForm");
  		if ( cancelForm && cancelForm.handleMethod )
  		{
  			cancelForm.handleMethod.value = "no";
			if ( cancelForm.next )
			{
				cancelForm.next.maxLength = next.length + 1;
				cancelForm.next.value = next;
				// replace action with reload (but keep SSL switch if present)
				// $ is needed to anchor the match at the end (avoiding problems in FireFox if the hostname also contains 'do', e.g. dover.be.local : APO-9189)
				var regexp = new RegExp('[a-zA-Z]*.do$');
				cancelForm.action = cancelForm.action.replace(regexp,'reload.do');

				// wrong (SSL switch not kept) cancelForm.action = "reload.do"; // perhaps better to replace */*.do by */reload.do
				cancelForm.submit();
			}
  		}
   	}
   	return false;
}

function deleteAndGetNext( next )
{
	setActionAndGetNext( "delete", next );
}

function setActionAndGetNext( action, next )
{
	var updateForm = document.getElementById("updateForm");
	if ( lockSubmission() == true )
	{
		if ( updateForm && updateForm.edited && updateForm.handleMethod )
		{
			SetRowActions( updateForm, action );

			// don't set the 'edited' flag
			// document.updateForm.edited.value    = true;
			updateForm.handleMethod.value = "yes";

			return get( next );
		}
	}

	return false;
}

function saveOrRefresh(next)
{
		var updateForm = document.getElementById("updateForm");
		if ( lockSubmission() == true ) 
		{
			if ( updateForm && updateForm.handleMethod) 
			{
				if (!updateForm.edited || (updateForm.edited.value != "true" && updateForm.edited.value != true) )
				{
					updateForm.handleMethod.value = "cancel";
					updateForm.action = "reload.do";
				} 
				else 
				{
					updateForm.handleMethod.value = "yes";
				}
				if ( updateForm.next )
				{
					updateForm.next.maxLength = next.length + 1;
					updateForm.next.value = next;
				}
				try 
				{ 
					updateForm.submit(); 
				} 
				catch (e) 
				{ 
					unlockSubmission();
					if(self.displayWarning) 
						displayWarning();
				}
			}
		}
		return false;
}

// For this function to do anything, status must be 0 or 1
// and imagesrc must end with _0.* or _1.*
function getImageUrlWithStatus(imagesrc, status)
{
	var dot_rows	= imagesrc.split(".");
	var dotrowindex = dot_rows.length - 2;
	if (dotrowindex >= 0)
	{
		var underscore_rows	= dot_rows[dotrowindex].split("_");
		var last_index	= underscore_rows.length - 1;
		if (underscore_rows[last_index] == "1" || underscore_rows[last_index] == "0")
		{
			underscore_rows[last_index] = String(status);
			dot_rows[dotrowindex] = underscore_rows.join("_");
			imagesrc = dot_rows.join(".");
		}
	}
	
//	var url_rows = imagesrc.split("%");
//	if(url_rows.length == 2) // remove "%20" suffix if needed
//	{
//		imagesrc = url_rows[0];
//		return imagesrc;
//	}
	
	return imagesrc;
}

// this function sets edited to true
function setEdited(form,editedField,keyCode)
{
    if(keyCode == 9 || keyCode == 16) return;
    form.edited.value = true;
    form[editedField].value = true;
}

// this function removes the extra blank option from the specified select element, if it is set to a non blank option
function removeBlankOption(select)
{
	if (selectSet(select))
	{
		for (i=0; i < select.options.length;i++)
		{
			if (select.options[i].text == "")
			{
				select.options[i] = null;
				// the select box is refreshed completely to avoid problems on Mozilla
				// (after removing the blank option, clicking the select box without selecting another option would change the selection)
				updateSelect(select);
				break;
			}
		}
	}
}


// the following filtering code was taken from pageproperties.js

var KEYCODE_NO_CODE        		= -1;
var KEYCODE_BACKSPACE      		= 8;
var KEYCODE_TAB            		= 9;
var KEYCODE_ENTER_BR       		= 3;	// bottom right enter  
var KEYCODE_ENTER          		= 13;
var KEYCODE_SHIFT          		= 16;
var KEYCODE_COMMA          		= 44;	// char ,
var KEYCODE_DOT            		= 46;	// char .
var KEYCODE_DIGIT_0        		= 48;
var KEYCODE_DIGIT_9        		= 57;
var KEYCODE_DELETE         		= 127;
var KEYCODE_DOUBLE_QUOTE		= 34;	// char  "
var KEYCODE_HASH				= 35;	// char  #
var KEYCODE_SINGLE_QUOTE		= 39;	// char  '
var KEYCODE_LESS_THAN       	= 60;	// char  <
var KEYCODE_GREATER_THAN    	= 62;	// char  >
var KEYCODE_VERTICAL_LINE   	= 124;	// char |
var KEYCODE_MINUS           	= 45;   // char -
var KEYCODE_TILDE           	= 126;  // char ~
var KEYCODE_SLASH           	= 47;	// char /
var KEYCODE_BACKSLASH			= 92;	// char \
var KEYCODE_ASTERISK			= 42;	// char *
var KEYCODE_AMPERSAND			= 38;	// char &
var KEYCODE_QUESTION_MARK		= 63;	// char ?
var KEYCODE_EXCLAMATION_MARK	= 33;	// char !
var KEYCODE_COLON				= 58;	// char :
var KEYCODE_SEMI_COLON			= 59;	// char ;
var KEYCODE_LEFT_ARROW_CODE			= 63234;// left arrow on Safari
var KEYCODE_RIGHT_ARROW_CODE		= 63235;// right arrow on Safari

var KEYCODE_PERCENT				= 0x25;	// char %
var KEYCODE_AMPERSAND			= 0x26;	// char &
var KEYCODE_LOWLINE				= 0x5F;	// char _
var KEYCODE_PLUS				= 0x2B;	// char +

// keycodes used in combination with CTRL key to detect keyboards shortcuts for copy/paste/delete
var KEYCODE_C				= 99;	// char c
var KEYCODE_V				= 118;	// char v
var KEYCODE_X				= 120;	// char x

function isAltKey(event)
{
  if (window.event && window.event.keyCode )
  	return window.event.altKey;
  else if (event && event.which)
  	return event.modifiers & Event.ALT_MASK;
  else
  	return false;
}

function isCtrlKey(event)
{
  if (window.event && window.event.keyCode )
  	return window.event.ctrlKey;
  else if (event && event.which)
  	return event.modifiers & Event.CONTROL_MASK;
  else
  	return false;
}

function isShiftKey(event)
{
  if (window.event && window.event.keyCode )
  	return window.event.shiftKey;
  else if (event && event.which)
  	return event.modifiers & Event.SHIFT_MASK;
  else
  	return false;
}
function isMetaKey(event)
{
  if (window.event && window.event.keyCode )
  	return window.event.metaKey;
  else if (event && event.which)
  	return event.modifiers & Event.META_MASK;
  else
  	return false;
}

function unsignedInt( value, event )
{
	var code = getKeyCode( event );

	var ok = ( ( ( code >= KEYCODE_DIGIT_0 ) && ( code <= KEYCODE_DIGIT_9 ) ) ||
				  ( code == KEYCODE_NO_CODE ) ||
				  ( code == KEYCODE_DELETE ) ||
				  ( code == KEYCODE_BACKSPACE ) ||
				  ( code == KEYCODE_LEFT_ARROW_CODE ) || 
				  ( code == KEYCODE_RIGHT_ARROW_CODE ) || // LEFT AND RIGHT ARROWS treated as a key on Safari --> hence needed here
				  ( code == KEYCODE_TAB) ||			// TAB treated as a key on Safari --> hence needed here
				  ( (isCtrlKey(event) || isMetaKey(event)) && (( code == KEYCODE_C ) || ( code == KEYCODE_V ) || ( code == KEYCODE_X )) )  // keyboard shortcuts for copy/paste/delete
			);
	return ok;
}

function disableEnterKey(e)
{
	var code = getKeyCode(e);
	return (code == KEYCODE_ENTER || code == KEYCODE_ENTER_BR) ? false : true;
}			


function unsignedFloat( value, event )
{
	var ok = unsignedInt( value, event );

	if ( ok == false )
	{
		var code = getKeyCode( event );

		if ( ( code == KEYCODE_COMMA ) || ( code == KEYCODE_DOT ) )
		{
			if ( ( value.indexOf( String.fromCharCode( KEYCODE_COMMA ) ) < 0 ) &&
			     ( value.indexOf( String.fromCharCode( KEYCODE_DOT ) )   < 0 ) )
			{
				ok = true;
			}

			if ( ( ok == true ) && ( decimalPoint != null ) )
			{
			    setKeyCode( event, decimalPoint.charCodeAt( 0 ) );
			}
		}
	}

	return ok && disableEnterKey(event);
}

function signedFloat( value, event )
{
	var ok = unsignedFloat( value, event );

	if ( ok == false )
	{
		var code = getKeyCode( event );

		if ((code == KEYCODE_MINUS) && (value.indexOf( String.fromCharCode( KEYCODE_MINUS ) ) < 0)) 
			ok = true;
	}

	return ok && disableEnterKey(event);
}

function rangeSpecification( value, event )
{
	var ok = unsignedInt( value, event );

	if ( ok == false )
	{
		var code = getKeyCode( event );

		if ( ( code == KEYCODE_MINUS ) || ( code == KEYCODE_TILDE ) )
		{
			ok = true;
		}
	}

	return ok && disableEnterKey(event);
}

function collectionSpecification( value, event )
{
	var ok = rangeSpecification( value, event );

	if ( ok == false )
	{
		var code = getKeyCode( event );

		if ( ( code == KEYCODE_SLASH ) || ( code == KEYCODE_COMMA ) )
		{
			ok = true;
		}
	}

	return ok && disableEnterKey(event);
}

function namingConventionFilter( value, event )
{
	var code = getKeyCode( event );

	var ok = !isNotCorrectCharForNamingConvention(code);

	return ok && disableEnterKey(event);
}

function namingConventionCodeFilter( value, event )
{
	var code = getKeyCode( event );
 
	var ok = !isNotCorrectCharForNamingConventionCode(code);
 
	return ok && disableEnterKey(event);
}

function getKeyCode( event )
{
	var code = KEYCODE_NO_CODE;

	if ( window.event && window.event.keyCode )
	{
      code = window.event.keyCode; // IE
	}
	else if ( event && event.which )
	{
      code = event.which; // NS4 & NS6
	}

	return code;
}

function setKeyCode( event, code )
{
   if ( window.event && window.event.keyCode )
   {
      window.event.keyCode = code; // IE
   }
//   else if ( event && event.which )
//   {
//      event.which = code; // NS4 & NS6
//   }
   
}

// the above filtering code was taken from pagepropertie.js

function checkAllowedValues(tag, allowedValues, decimalPoint)
{
	if (decimalPoint == null) decimalPoint = 46; // . is the default decimal point symbol

	// replace all localized decimal points with dots
	allowedValues = allowedValues.split(decimalPoint).join(".");

	var valid = false;
	var numericalValue = parseFloat(tag.value.split(decimalPoint).join("."));
	if (numericalValue != Number.NaN)
	{
		var discreteValues = allowedValues.split(";");
		for (i = 0; i < discreteValues.length; i++)
		{
			var allowedValue = discreteValues[i].split(decimalPoint).join(".");
			var rangeElements = allowedValue.split("~");
			if (rangeElements.length == 2)
			{
				// check whether the value is inside the current value range
				var from = parseFloat(rangeElements[0].split(decimalPoint).join("."));
				var to   = parseFloat(rangeElements[1].split(decimalPoint).join("."));
				if (numericalValue >= from && numericalValue <= to)
				{
					valid = true;
					break;
				}
			}
			else
			{
				// check whether the value matches the current allowed value
				if (numericalValue == parseFloat(allowedValue))
				{
					valid = true;
					break;
				}
			}
		}
	}

	// update the style class, according to the value's validity
	var classNamePos = tag.className.indexOf("valueNotAllowed");
	if (valid == false)
	{
		// if not valid, add the "valueNotAllowed" style class (if necessary)
		if (classNamePos == -1)
		{
			tag.className = tag.className + " valueNotAllowed";
		}
	}
	else
	{
		// if valid, remove the "valueNotAllowed" style class (if necessary)
		if (classNamePos != -1)
		{
			tag.className = tag.className.split("valueNotAllowed").join("");
		}
	}
}

function alphaKeyCodesOnly(e)
{
    // returns true if A-Z, a-z or ' or backspace or del hit or browser isn't IE or NS, otherwise false
    var nKey = -1;
    if (e && e.which)
        nKey = e.which; // NS4 & NS6
    else if (window.event && window.event.keyCode)
        nKey = window.event.keyCode; // IE

    // 97 = a, 122 = z, 65 = A, 90 = Z, 45 = -, 59 = ';', 8 = BS, 127 = del, 9 = TAB
    return (nKey > -1 ? (
        (nKey > 96 && nKey < 123) ||
        (nKey > 64 && nKey< 91) ||
        nKey == 45 ||
        nKey == 59 ||
        nKey == 8 ||
        nKey == 127 ||
        nKey == 9
        ) : true);
}

function numericalKeyCodesOnly(e, decimalPoint)
{
    // returns true if '0'-'9', ';', decimalPoint, '-' or backspace or del hit or
    // browser isn't IE or NS, otherwise false
    // (where decimalPoint 44 = ',' or 46 = '.'  (typically))
    var nKey = -1;
    if (e && e.which)
        nKey = e.which; // NS4 & NS6
    else if (window.event && window.event.keyCode)
        nKey = window.event.keyCode; // IE
    // 48 = '0' , 57 = '9' , 45 = '-' , 59 = ';' , 8 = backspace, 127 = del, 9 = TAB
    return (nKey > -1 ?
            (
             (nKey > 47 && nKey < 58) ||
             (decimalPoint != null && nKey == decimalPoint) ||
             nKey == 45 ||
             nKey == 59 ||
             nKey == 8 ||
             nKey == 127 ||
             nKey == 9
            ) : true);
}

// problematic filter characters are % & +
function allExceptProblematicFilterCharacters( value, event )
{
	var code = getKeyCode( event );
	return isCorrectCharForFilterString( code )
}

/*
 * returns the absolute position of an element
 * used by: componentBuilder.js,table.js,taskChainBuilder.js,partBuilder.js
 */
function absolutePosition(element)
{
    // calculate absolute position of an element.
    var absoluteLeft=element.offsetLeft;
    var absoluteTop=element.offsetTop;
    var _parent = element;
    while(_parent.offsetParent)
    {
        _parent = _parent.offsetParent;
        absoluteLeft += _parent.offsetLeft;
        absoluteTop  += _parent.offsetTop;
    }
    return new Position(absoluteLeft,absoluteTop);
}

/* A simple xy position object. */
function Position(x,y)
{
    this.x = x;
    this.y = y;
}

/*
 * Check if x and y coordinations are inside element
 * returns true if x and y are inside, false otherwise
 * elementPos may be given to cache an already calculated
 * elements position
 */
function inside(element,x,y,elementPos)
{
    if(!elementPos)
    {
        elementPos = absolutePosition(element);
    }
    var vertical   = (elementPos.x < x && elementPos.x + element.offsetWidth  > x );
    var horizontal = (elementPos.y < y && elementPos.y + element.offsetHeight > y );
    return (vertical && horizontal);
}

// The following methods should be used to encode/decode cookie values at client side,
// in order to make them symmetrical with URLEncoder/URLDecoder at server side
// (so a cookie set at client side can be read at server side and reversely without problems)
function encodeCookieValue(value)
{
	// replace "+" with "%2B" in order to be recognized as a "+" instead of a " " by URLDecoder at server side
	var encodedValue = escape(value).split("+").join("%2B");
	return encodedValue;
}

function decodeCookieValue(value)
{
	// replace "+" with "%20" in order to be recognized as a " " instead of a "+" by unescape at client side
	var decodedValue = unescape(value.split("+").join("%20"));
	return decodedValue;
}

function setCookie( name, value, expires )
{
	var expiration = "";

	if ( expires == false )
	{
		var date = new Date();

		date.setTime( date.getTime() + ( 365 * 24 * 60 * 60 * 1000 ) );

		expiration = "; expires=" + date.toGMTString();
	}
	document.cookie = name + "=" + encodeCookieValue( value ) + expiration;
}

function getCookieValue( name, defaultValue )
{
	var nameEquals = name + "=";
	var value   = defaultValue;
	var length  = nameEquals.length;
	var data    = document.cookie;
	var index   = 0;
	var eon     = 0;
	var eov     = 0;

	while ( index < data.length )
	{
		eon = index + length;

		if ( data.substring( index, eon ) == nameEquals )
		{
			eov = data.indexOf( ";", eon );

			if ( eov == -1 )
			{
			   eov = data.length;
			}
			else if (eov <= eon)
			{
				eov = eon; // force value to be an empty string 
			}
			value = decodeCookieValue( data.substring( eon, eov ) );
			// we found most specific cookie value
			return value;
		}
		else
		{
			index++;
		}
	}

	return value;
}

function getMultipleCookieValue(name)
{
	var multipleCookieList = new Array();
	var multipleCookieValue = getCookieValue( name, '');
	if(multipleCookieValue.length > 0)
	{
		var cookieTokenizer = new StringTokenizer(multipleCookieValue, ',');
		while (cookieTokenizer.hasMoreTokens())
		{
				var cookieKey = cookieTokenizer.nextToken();

				if (cookieTokenizer.hasMoreTokens())
				{
					var cookieValue = cookieTokenizer.nextToken();
					
					if (cookieKey.length > 0 && cookieValue.length > 0)
					{
						multipleCookieList[multipleCookieList.length] = {key: cookieKey, value: cookieValue};
					}
				}
		}
	}
	
	return multipleCookieList;
}

function getMultipleCookie(name, key, defaultValue)
{
	var value = defaultValue ? defaultValue : '';

	var multipleCookieValueList = getMultipleCookieValue(name);
	for(var i = 0; i < multipleCookieValueList.length; i++)
	{
		if(multipleCookieValueList[i].key == key)
		{
			value = multipleCookieValueList[i].value;
			break;
		}
	}

	return value;	
}

function setMultipleCookie( name, key, value, expires )
{
	var replaced = false;

	var multipleCookieValueList = getMultipleCookieValue(name);
	for(var i = 0; i < multipleCookieValueList.length; i++)
	{
		if(multipleCookieValueList[i].key == key)
		{
			multipleCookieValueList[i].value = value;
			replaced = true;
			break;
		}
	}
	
	if(!replaced)
	{
		multipleCookieValueList[multipleCookieValueList.length] = {key: key, value: value};
	}
	
	var multipleCookieValue = convertMCVtoString( multipleCookieValueList );
	
	setCookie( name, multipleCookieValue, expires );
}

function convertMCVtoString( multipleCookieValueList )
{
	var multipleCookieValue = '';
	for(var i = 0; i < multipleCookieValueList.length; i++)
	{
		multipleCookieValue += multipleCookieValueList[i].key + "," + multipleCookieValueList[i].value;
		if(i != multipleCookieValueList.length - 1)
		{
			multipleCookieValue += ",";
		}
	}
	return multipleCookieValue;
}

/*
 * create an hidden (not hidden on mac ie) field.
 * and append it to the form.
 */
function createField(form,name,value)
{
	// debugprint("field: name="+name+", value="+value);

    var field = document.createElement("INPUT");

    if(MAC && IE5)
    {
        //field.type="hidden";
        field.name=name;
        field.value=value;
    }
    else
    {
        field.setAttribute("type","hidden");
        field.setAttribute("name",name);
        field.setAttribute("value",value);
    }

    form.appendChild(field);
}

/*
 * create an hidden (not hidden on mac ie) field.
 * and append it to the form.
 */
function createField(form, name, value, id)
{
	// debugprint("field: name="+name+", value="+value);

    var field = document.createElement("INPUT");

    if(MAC && IE5)
    {
        //field.type="hidden";
        field.name=name;
        field.value=value;
        field.id=id;
    }
    else
    {
        field.setAttribute("type","hidden");
        field.setAttribute("name",name);
        field.setAttribute("value",value);
        field.setAttribute("id",id);
    }

    form.appendChild(field);
}


function arrayContains(arr,item)
{
	for(var i=0; i < arr.length;i++)
	{
		if(arr[i] == item)
		{
			return true;
		}
	}
	return false;
}

function arrayIndexOf(arr,item)
{
	for(var i=0; i < arr.length;i++)
	{
		if(arr[i] == item)
		{
			return i;
		}
	}
	return -1;
}

function arrayRemove(arr,item)
{
	var start = arrayIndexOf(arr,item);
	
	if (start != -1) 
	{
		var end = arr.length - 1;
		
		for(var i= start; i < end; i++) 
		{
			arr[i] = arr[i+1];
		}
		arr.length--;
		
		return true;
	}
	
	return false;
}

function arrayAdd(arr,item)
{
	if (!arrayContains(arr,item))
	{
		arr[ arr.length ] = item;
	}
}

function centerOfWindow()
{
	var clientHeight;
	var clientWidth;
	var docTop;
	var docLeft;

    if (document.all)
    {
      clientHeight = document.body.clientHeight;
      clientWidth  = document.body.clientWidth;
      docTop       = document.body.scrollTop;
      docLeft      = document.body.scrollLeft;
    }
    else
    {
      // Fudge for the scrollbars
      clientHeight = window.innerHeight -20;
      clientWidth  = window.innerWidth  -20;
      docTop       = window.pageYOffset;
      docLeft      = window.pageXOffset;
    }

    var loc = new Object();
    loc.x = docLeft + clientWidth/2;
    loc.y = docTop  + clientHeight/2;
    return loc;
}

/**
 * Number of days in a partical month.
 */
function getDaysInMonth(year,month)
{

    var days;

    if (month==0 || month==2 || month==4 || month==6 || month==7 || month==9 || month==11)
    {
        days=31;
    }
    else if (month==3 || month==5 || month==8 || month==10)
    {
        days=30;
    }
    else if (month==1)
    {
        if (isLeapYear(year))
        {
            days=29;
        }
        else
        {
            days=28;
        }
    }
    return days;
}

function isLeapYear (year) {

    if (((year % 4)==0) && ((year % 100)!=0) || ((year % 400)==0)) {
        return true;
    }
    else {
        return false;
    }
}

/**
 * Returns an object with x and y properties of mouse pointer.
 */
function getCurrentMousePosition(e)
{
    var mouseX, mouseY;
    if(window.event)
    {
        mouseX  = window.event.clientX + document.body.scrollLeft;
        mouseY  = window.event.clientY + document.body.scrollTop;
    }
    else
    {
        // netscape and mozilla
        mouseX  = e.pageX;
        mouseY  = e.pageY;
    }

    return {x:mouseX,y:mouseY};
}

/**
 * Show / hide element
 */
 
var DISPLAY_STYLE_VISIBLE = "";
var DISPLAY_STYLE_INLINE = "inline";
var DISPLAY_STYLE_BLOCK = "block";
var DISPLAY_STYLE_TABLE_ROW = "table-row";
var DISPLAY_STYLE_HIDDEN = "none";

var objectIdToElementMap = new Object();

function getCachedElementById(id)
{
	var el = objectIdToElementMap[id];
	if(!el)
	{
		el = document.getElementById(id);
		objectIdToElementMap[id] = el;
	}
	
	return el;
}


function showElementById(id, displayStyle)
{
	var el = getCachedElementById(id);
	showElement(el, displayStyle);
}

function showElement(el, displayStyle)
{
	if (el)
		el.style.display = displayStyle ? displayStyle : DISPLAY_STYLE_VISIBLE;
}

function isElementShown(el)
{
	if (el && DISPLAY_STYLE_VISIBLE == getDisplayStyle(el))
		return true;
	else
		return false;
}

function hideElementById(id)
{
	var el = getCachedElementById(id);
	hideElement(el);
}

function hideElement(el)
{
	if (el)
		el.style.display = DISPLAY_STYLE_HIDDEN;
}

// this method can be used to show all elements with the same tagName and className
// it is useful to show a group of elements, that belong together
// (one cannot use id, which should be unique per element, nor name, which is not supported for all tag names)
function showElementsByTagNameAndClassName(tagName, className)
{
	var els = document.getElementsByTagName(tagName);
	if (els && els.length > 0)
	{
		for (var i=0; i<els.length; i++)
		{
			var elClassName = els[i].className;
			// JavaScript compares Strings by value (so we can use == here)
			if (elClassName && className && (elClassName == className))
				showElement(els[i]);
		}
	}
}

// this method can be used to hide all elements with the same tagName and className
// it is useful to hide a group of elements, that belong together
// (one cannot use id, which should be unique per element, nor name, which is not supported for all tag names)
function hideElementsByTagNameAndClassName(tagName, className)
{
	var els = document.getElementsByTagName(tagName);
	if (els && els.length > 0)
	{
		for (var i=0; i<els.length; i++)
		{
			var elClassName = els[i].className;
			// JavaScript compares Strings by value (so we can use == here)
			if (elClassName && className && (elClassName == className))
				hideElement(els[i]);
		}
	}
}

function getDisplayStyle(el)
{
	if(!el)
		return null;
	return el.style.display;
}

function makeElementVisible(id)
{
	var el = document.getElementById(id);
 	if(el != null)
	{
 		el.style.visibility = "visible";
 	}
}
 
function makeElementUnvisible(id)
{
	var el = document.getElementById(id);
	if(el != null)
	{
 		el.style.visibility = "hidden";
 	}
}


/**
 * Enable / disable element
 */
 
function isEnabled(id)
{
	var el = getCachedElementById(id);
	if (el)
	{
		if (el.disabled)
			return !el.disabled;
		else
			return true;
	}
	else
	{
		return false;
	}
}
 
function enableElement(id)
{
	var el = getCachedElementById(id);
	if (el)
	{
		el.disabled = false;
	}
}

function disableElement(id)
{
	var el = getCachedElementById(id);
	if (el)
	{
		el.disabled = true;
	}
}


function validateRangeSpecification(field, event)
{
	if (isCorrectRangeSpecification(field))
	{
		field.lastValidValue = field.value;
		field.caretPos = getCaretPos(field);
	} 
	else 
	{
		if(!field.lastValidValue)
			field.lastValidValue = "";
			
		field.value = field.lastValidValue;
		moveCaretToPos(field, field.caretPos);
	}
}

function validateCollectionSpecification(field, event)
{
	if (isCorrectCollectionSpecification(field))
	{
		field.lastValidValue = field.value;
		field.caretPos = getCaretPos(field);
	} 
	else 
	{
		if(!field.lastValidValue)
			field.lastValidValue = "";
			
		field.value = field.lastValidValue;
		moveCaretToPos(field, field.caretPos);
	}
}

function validateNamingConvention(field, event)
{
	if (isCorrectNamingConvention(field))
	{
		field.lastValidValue = field.value;
		field.caretPos = getCaretPos(field);
	} 
	else 
	{
		if(!field.lastValidValue)
			field.lastValidValue = "";
			
		field.value = field.lastValidValue;
		moveCaretToPos(field, field.caretPos);
	}
}

function validateNamingConventionCode(field, event)
{
	if (isCorrectNamingConventionCode(field))
	{
		field.lastValidValue = field.value;
		field.caretPos = getCaretPos(field);
	} 
	else 
	{
		if(!field.lastValidValue)
			field.lastValidValue = "";
			
		field.value = field.lastValidValue;
		moveCaretToPos(field, field.caretPos);
	}
}

function validateUnsignedInt(field, event)
{
	if (isCorrectUnsignedInt(field))
	{
		field.lastValidValue = field.value;
		field.caretPos = getCaretPos(field);
	} 
	else 
	{
		if(!field.lastValidValue)
			field.lastValidValue = "";
			
		field.value = field.lastValidValue;
		moveCaretToPos(field, field.caretPos);
	}
}

function validateUnsignedIntInRange(field, event, left, right)
{
	if (isCorrectUnsignedInt(field) && isUnsignedIntInRange(field, left, right))
	{
		field.lastValidValue = field.value;
		field.caretPos = getCaretPos(field);
	} 
	else 
	{
		if(!field.lastValidValue)
			field.lastValidValue = "";
			
		field.value = field.lastValidValue;
		moveCaretToPos(field, field.caretPos);
	}
}

function validateUnsignedFloat(field, event)
{
	if (isCorrectUnsignedFloat(field))
	{
		// required for paste action
		replaceDotOrCommaWithDecimalPointIfNeeded(field);
		field.lastValidValue = field.value;
		field.caretPos = getCaretPos(field);
	} 
	else 
	{
		if(!field.lastValidValue)
			field.lastValidValue = "";
			
		field.value = field.lastValidValue;
		moveCaretToPos(field, field.caretPos);
	}
}


function validateSignedFloat(field, event)
{
	if (isCorrectSignedFloat(field))
	{
		// required for paste action
		replaceDotOrCommaWithDecimalPointIfNeeded(field);
		field.lastValidValue = field.value;
		field.caretPos = getCaretPos(field);
	} 
	else 
	{
		if(!field.lastValidValue)
			field.lastValidValue = "";
			
		field.value = field.lastValidValue;
		moveCaretToPos(field, field.caretPos);
	}
}


function validateFilterString(field, event)
{
	if (isCorrectFilterString(field))
	{
		field.lastValidValue = field.value;
		field.caretPos = getCaretPos(field);
	} 
	else 
	{
		if(!field.lastValidValue)
			field.lastValidValue = "";
			
		field.value = field.lastValidValue;
		moveCaretToPos(field, field.caretPos);
	}
}


function isCorrectRangeSpecification(field)
{
	if(!field)
		return false;
	var value = field.value;
	if(!value || value.length == 0)
		return true;
	
	for(var i = 0; i < value.length; i++)
	{
		if(!isCorrectCharForRangeSpecification(value.charCodeAt(i)))
			return false;
	}

	/*
	 * The following code was omitted, to avoid problems when trying to delete some characters
	var minusOrTilde = false;
	for(var i = 0; i < value.length; i++)
	{
		var charCode = value.charCodeAt(i);
		if(( charCode == KEYCODE_MINUS ) || ( charCode == KEYCODE_TILDE ))
		{
			if(minusOrTilde == true)
				return false;
			else 
				minusOrTilde = true;
		}
			
  	}
  	*/
			
	return true;
}

function isCorrectCollectionSpecification(field)
{
	if(!field)
		return false;
	var value = field.value;
	if(!value || value.length == 0)
		return true;
	
	for(var i = 0; i < value.length; i++)
	{
		if(!isCorrectCharForCollectionSpecification(value.charCodeAt(i)))
			return false;
	}

	/*
	 * The following code was omitted, to avoid problems when trying to delete some characters
	 * (e.g. trying to delete a COMMA between two MINUS signs )
	var minusOrTilde = false;
	for(var i = 0; i < value.length; i++)
	{
		var charCode = value.charCodeAt(i);
		if(( charCode == KEYCODE_SLASH ) || ( charCode == KEYCODE_COMMA ))
		{
			minusOrTilde = false;
		}
		else if (( charCode == KEYCODE_MINUS ) || ( charCode == KEYCODE_TILDE ))
		{
			if (minusOrTilde == true)
				return false;
			minusOrTilde = true;
		}	
  	}
  	*/
			
	return true;
}


function isCorrectNamingConvention(field)
{
	if(!field)
		return false;
	var value = field.value;
	if(!value || value.length == 0)
		return true;
	
	for(var i = 0; i < value.length; i++)
	{
		if(isNotCorrectCharForNamingConvention(value.charCodeAt(i)))
			return false;
	}

	return true;
}

function isCorrectNamingConventionCode(field)
{
	if(!field)
		return false;
	var value = field.value;
	if(!value || value.length == 0)
		return true;
	
	for(var i = 0; i < value.length; i++)
	{
		if(isNotCorrectCharForNamingConventionCode(value.charCodeAt(i)))
			return false;
	}

	return true;
}

function isCorrectUnsignedInt(field)
{
	if(!field)
		return false;
	var value = field.value;
	if(!value || value.length == 0)
		return true;
	
	for(var i = 0; i < value.length; i++)
	{
		if(!isCorrectCharForUnsignedInt(value.charCodeAt(i)))
			return false;
	}

	return true;
}

function isUnsignedIntInRange(field, left, right)
{
	if(!field)
	{
		return false;
	}

	var leftBorder = left;
	var rightBorder = right;
	
	if(!left)
	{
		leftBorder = 0;
	}
	if(!right)
	{
		rightBorder = Number.POSITIVE_INFINITY;
	}
		
	var value = field.value;
	if(!value || value.length == 0)
		return true;

	if(value < left || value > right)	
	{
		return false;
	}
	
	return true;
}

function isCorrectUnsignedFloat(field)
{
	if(!field)
		return false;
	var value = field.value;
	if(!value || value.length == 0)
		return true;
	
	for(var i = 0; i < value.length; i++)
	{
		if(!isCorrectCharForUnsignedFloat(value.charCodeAt(i)))
			return false;
	}

	var numComma = getNumChar(value, KEYCODE_COMMA);
	var numDot = getNumChar(value, KEYCODE_DOT);
	if(numComma > 1 || numDot > 1 || (numDot == 1 && numComma == 1))
		return false;

	return true;
}


function isCorrectSignedFloat(field)
{
	if(!field)
		return false;
	var value = field.value;
	if(!value || value.length == 0)
		return true;
	
	for(var i = 0; i < value.length; i++)
	{
		if(!isCorrectCharForSignedFloat(value.charCodeAt(i)))
			return false;
	}

	var numComma = getNumChar(value, KEYCODE_COMMA);
	var numDot = getNumChar(value, KEYCODE_DOT);
	if(numComma > 1 || numDot > 1 || (numDot == 1 && numComma == 1))
		return false;
		
	
	if(getNumChar(value, KEYCODE_MINUS) > 1 || value.indexOf('-') > 0)
		return false;
		
	return true;
}

function isCorrectFilterString(field)
{
	if(!field)
		return false;
	var value = field.value;
	if(!value || value.length == 0)
		return true;
	
	for(var i = 0; i < value.length; i++)
	{
		if(!isCorrectCharForFilterString(value.charCodeAt(i)))
			return false;
	}

	return true;
}


function isCorrectCharForRangeSpecification(charCode)
{
	var ok = ( isCorrectCharForUnsignedInt(charCode)  ||
				  ( charCode == KEYCODE_MINUS ) ||
				  ( charCode == KEYCODE_TILDE ));

	return ok;
}

function isCorrectCharForCollectionSpecification(charCode)
{
	var ok = ( isCorrectCharForRangeSpecification(charCode)  ||
				  ( charCode == KEYCODE_SLASH ) ||
				  ( charCode == KEYCODE_COMMA ));

	return ok;
}

function isNotCorrectCharForNamingConvention(charCode)
{
	var ok = ( charCode == KEYCODE_DOUBLE_QUOTE ||
					charCode == KEYCODE_LESS_THAN ||
				    charCode == KEYCODE_GREATER_THAN ||
				    charCode == KEYCODE_VERTICAL_LINE );

	return ok;
}

function isNotCorrectCharForNamingConventionCode(charCode)
{
	var ok = ( 	charCode == KEYCODE_DOUBLE_QUOTE ||
			charCode == KEYCODE_SINGLE_QUOTE ||
 			charCode == KEYCODE_LESS_THAN ||
 			charCode == KEYCODE_GREATER_THAN ||
 			charCode == KEYCODE_COMMA ||
 			charCode == KEYCODE_DOT ||
 			charCode == KEYCODE_ASTERISK ||
 			charCode == KEYCODE_AMPERSAND ||
 			charCode == KEYCODE_QUESTION_MARK ||
 			charCode == KEYCODE_EXCLAMATION_MARK ||
 			charCode == KEYCODE_COLON ||
 			charCode == KEYCODE_SEMI_COLON ||
 			charCode == KEYCODE_SLASH ||
 			charCode == KEYCODE_BACKSLASH ||
			charCode == KEYCODE_HASH ||
 			charCode == KEYCODE_VERTICAL_LINE );

	return ok;
}

function isCorrectCharForUnsignedInt(charCode)
{
	var ok = ( ( charCode >= KEYCODE_DIGIT_0 ) && ( charCode <= KEYCODE_DIGIT_9 ) );

	return ok;
}

function isCorrectCharForUnsignedFloat(charCode)
{
	var ok = ( isCorrectCharForUnsignedInt(charCode)  ||
				  ( charCode == KEYCODE_COMMA ) ||
				  ( charCode == KEYCODE_DOT ));

	return ok;
}

function isCorrectCharForSignedFloat(charCode)
{
	var ok = ( isCorrectCharForUnsignedFloat(charCode) || ( charCode == KEYCODE_MINUS ));

	return ok;
}

// problematic filter characters are % & +
function isCorrectCharForFilterString( code )
{
	var ok = ( (code != KEYCODE_PERCENT) && 
				(code !=  KEYCODE_AMPERSAND) &&
				(code !=  KEYCODE_PLUS) );
	return ok;
}



function replaceDotOrCommaWithDecimalPointIfNeeded(field)
{
	if ( decimalPoint != null )
	{
		if((getNumChar(field.value, KEYCODE_COMMA) == 1) && (decimalPoint.charCodeAt( 0 ) != KEYCODE_COMMA))
		{
			var pos = getCaretPos(field);
			field.value = field.value.replace(",", decimalPoint);
			moveCaretToPos(field, pos);
		}
		else if(getNumChar(field.value, KEYCODE_DOT) == 1 && (decimalPoint.charCodeAt( 0 ) != KEYCODE_DOT))
		{
			var pos = getCaretPos(field);
			field.value = field.value.replace(".", decimalPoint);
			moveCaretToPos(field, pos);
		}
	}
}

function getNumChar(value, charCode)
{
	var num = 0;
	for(var i = 0; i < value.length; i++)
	{
		if(charCode == value.charCodeAt(i))
			num++;
	}
	return num;
}

function initLastValidValue(field)
{
	field.caretPos = getCaretPos(field);
	if(!field.lastValidValue)
	{
		field.lastValidValue = field.value;
	}
}

function getCaretPos(field)
{
    // for mozilla
    if(isNetscape)
    {
    	if(field.selectionEnd)
	    	return field.selectionEnd;
	    return 0; // when cursor in the begining of field then selectionEnd is null
    }

    // for IE
    if(field.createTextRange)
    {
		var docrange = document.selection.createRange();
		
		var fieldRange = field.createTextRange();
		// added the check inRange(...) to avoid problems when docrange is not within fieldRange
		// (the function setEndPoint gives an error then)
		if(fieldRange && fieldRange.setEndPoint && docrange && fieldRange.inRange(docrange))
		{
			fieldRange.setEndPoint('EndToStart', docrange);
			return fieldRange.text.length;
		}
	}
    return field.value.length; // other browsers don't provide a method that I know of
}

function moveCaretToPos(field, pos)
{
    if(field.selectionStart) // for mozilla
      field.selectionStart = field.selectionEnd = pos;
    else if(field.createTextRange) // for IE
    {
      var docRange = document.selection.createRange();
      var fieldRange = field.createTextRange();
      fieldRange.move('character',pos);
      fieldRange.select();
    }
    
    // other browsers don't have a method that I know of
}

/**
 * Add element id to the list if it's isn't already in the list.
 */
function addListElement(list, id)
{
	var tokens = list.split(",");
	var found = false;

	for( var i = 0; i < tokens.length; i++ ) {
		if( id == tokens[i] )
		{
			found = true;
		}
	}

	if( !found )
	{
		tokens[tokens.length] = id;
		list = tokens.join(",");
	}

	return list;
}

/**
 * Remove the element id from the list.
 */
function removeListElement(list, id)
{
	var tokens = list.split(",");
	var found = false;
	var newTokens = new Array();
	var j = 0;

	for( var i = 0; i < tokens.length; i++ ) {
		if( id != tokens[i] )
		{
			newTokens[j] = tokens[i];
			j++;
		}
	}

	list = newTokens.join(",");

	return list;
}

var showSignatures = "";
var signatures = new Array();

function setRowsDisplayStyle(params, style)
{
	for ( var index = 0; index < params.length; index++ )
	{
		//First row = signature row, this row is already visible, therefor index > 0.
		if( index > 0 && document.getElementById(params[index]) )
		{
			showElementById(params[index], style);
		}
	}
}

function showAllRows(params)
{
	var idPrefix = null;
	var idShow = null;
	var idHide = null;

	for( var i = 0; i < params.length; i++ )
	{
		if( i == 0 )
		{
			idPrefix = params[i];
			idShow = idPrefix + "_plus";
			idHide = idPrefix + "_minus";

			hideElementById(idShow);
			showElementById(idHide);
		}
		showElementById(params[i]);
	}
}

function hideAllRows(params)
{
	var idPrefix = null;
	var idShow = null;
	var idHide = null;

	for( var i = 0; i < params.length; i++ )
	{
		if( i == 0 )
		{
			idPrefix = params[i];
			idShow = idPrefix + "_plus";
			idHide = idPrefix + "_minus";

			showElementById(idShow);
			hideElementById(idHide);
		}
		else
		{
			//First signature table row may not collapse.
			hideElementById(params[i]);
		}
	}
}

function showRows(params)
{
	var idPrefix = params[0];
	var idShow = idPrefix + "_plus";
	var idHide = idPrefix + "_minus";

	if( document.getElementById(idPrefix) && document.getElementById(idShow) && document.getElementById(idHide) )
	{
		//Only store the first id of the toggling parameter in a cookie.
		showSignatures = addListElement(showSignatures, idPrefix)
		setCookie("showSignatures", showSignatures, true);
		setRowsDisplayStyle(params, DISPLAY_STYLE_VISIBLE);

		hideElementById(idShow);
		showElementById(idHide);
	}
	else
	{
		showSignatures = "";
		setCookie("showSignatures", showSignatures, true);
	}
}

function hideRows(params)
{
	var idPrefix = params[0];
	var idShow = idPrefix + "_plus";
	var idHide = idPrefix + "_minus";

	if( document.getElementById(idPrefix) && document.getElementById(idShow) && document.getElementById(idHide) )
	{
		showSignatures = removeListElement(showSignatures, idPrefix)
		setCookie("showSignatures", showSignatures, true);
		setRowsDisplayStyle(params, DISPLAY_STYLE_HIDDEN);

		showElementById(idShow);
		hideElementById(idHide);
	}
}

function calculateScrollbarPosition() 
{
	if( parent && parent.details && !(MAC && IE5) )
	{
		var detailsDocument = parent.details.document;
		var detailsWindow = parent.details.window;

		if(detailsDocument.body)
		{
			var offset = detailsDocument.body.scrollTop;		//Upper position of the scrollblock starting from the top of the scrollbar.
			var height = 0;										//Total height of the scrollblock.
			var length = detailsDocument.body.scrollHeight;		//Total length of the scrollable area (scrollbar).
			var position = 0;
	
			if( isIE )
			{
				height = detailsDocument.body.offsetHeight;
			}
			else if( isNetscape )
			{
				height = detailsWindow.innerHeight;
			}
	
			if( length > 0 && offset > 0 )
			{
				position = Math.round((offset + (height / 2)) / length * 100);
			}
	
			var form = detailsDocument.getElementById("updateForm");
			if( form ) {
				form.scrollbarPosition.value = position;
			}
			form = detailsDocument.getElementById("cancelForm");
			if( form ) {
				form.scrollbarPosition.value = position;
			}
		}
	}
}

function setScrollbar() {
	var form = document.getElementById("updateForm");

	if( form && !(MAC && IE5) )
	{
		var position = form.scrollbarPosition.value;
		var height = 0;
		var length = document.body.scrollHeight;
		var offset = 0;

		if( isIE )
		{
			height = document.body.offsetHeight;
		}
		else if( isNetscape )
		{
			height = window.innerHeight;
		}

		if( parseInt(position) > 0 )
		{
			offset = (parseInt(position) / 100 * length) - (height / 2);
			document.body.scrollTop = offset;
			form.scrollbarPosition.value = 0;
			form = document.getElementById("cancelForm");
			form.scrollbarPosition.value = 0;
		}
	}
}

//This method checks for a Safari browser if its version is too old
//so that the shakeWindow bugfix must be executed.
function shakeWindow(amount)
{
	if( SAFARI || (isMac && FIREFOX))
	{
		// there used to be a check here on the version but problems occur in all versions
		doShake(amount);
	}
}

//Fix for svg plugin for Safari. Sometimes the svg plugin isn't visible.
//When the browserscreen is resized, the svg plugin becomes visible.
function doShake(amount)
{
	for( var i = 0; i < amount; i++ )
	{
		setTimeout( "top.resizeBy(1, 0); top.resizeBy(-1, 0);", (i + 1) * 750);
	}
}

var leftDetailsPosition = 0;
var topDetailsPosition = 0;

function shiftPositions()
{
	leftDetailsPosition += 20;
	if (leftDetailsPosition > 200) leftDetailsPosition = 0;
	topDetailsPosition += 20;
	if (topDetailsPosition > 200) topDetailsPosition = 0;
}

// show a details window at a shifted position
function showDetailsWindow( link, name, id, width, height )
{
	if ( link )
	{
		var windowname = getNameWithoutDots(name) + id; // open other window for each different id
		var staticWindowOptions = "status=no, scrollbars=yes, resizable=yes, toolbar=no, menubar=no";
		shiftPositions();
		var settings;
		if (width && height)
		{
			settings = 'width='+width+',height='+height+',left='+leftDetailsPosition+',top='+topDetailsPosition+','+staticWindowOptions;
		}
		else
		{
			settings = 'left='+leftDetailsPosition+',top='+topDetailsPosition+','+staticWindowOptions;
		}
		var previewWindow = window.open( link, windowname, settings );
		previewWindow.focus();
		return previewWindow;
	}

	return false;
}

function getNameWithoutDots(name)
{
	var nameParts = name.split('.');
	var nameWithoutDots = "";
	
	for ( var i=0; i<nameParts.length; i++)
	{
		nameWithoutDots += nameParts[i];
	}

	return ((nameWithoutDots.length > 0) ? nameWithoutDots : "noname" );
}



function createXMLHttpRequest() 
{
	var request;
	
	try 
  	{
		if (window.XMLHttpRequest) // Non-IE browsers
		{ 
			request = new XMLHttpRequest();
		}
		else if (window.ActiveXObject) // IE
		{
	  		request = new ActiveXObject("Microsoft.XMLHTTP");	
		}
	}
	catch(e)
	{
		// alert(e);
	}
	
	return request;
}

function sendXMLHttpRequest(request, url, handler) 
{
	try 
  	{
		if (request) 
		{
			request.onreadystatechange = handler;
			request.open("GET", url, true);
			
			if (window.XMLHttpRequest) // Non-IE browsers
			{ 
				request.send(null);
			}
			else if (window.ActiveXObject) // IE
			{
				request.send();
			}
		}
	}
	catch(e)
	{
		// alert(e);
	}
}

function updateSelect(selectEl)
{
	// this function updates the specified select box (this trigger is needed to display the correct selections on IE/MAC)
	if (selectEl && selectEl.options && selectEl.options.length > 0 && selectEl.selectedIndex > -1)
	{
		// first store the selected index and all options
		var selectedIndex = selectEl.selectedIndex;
		var optionList = new Array();
		for (var i=0; i<selectEl.options.length; i++)
		{
			optionList[optionList.length] = new Option(selectEl.options[i].text, selectEl.options[i].value);
		}
	
		// then reset the select element
		selectEl.options.length = 0;
		selectEl.selectedIndex = -1;
		
		// finally recreate the options
		for (var i=0; i<optionList.length; i++)
		{
			selectEl.options[i] = new Option(optionList[i].text, optionList[i].value);
		}
		selectEl.selectedIndex = selectedIndex;
	}
}

function updateSelects(id)
{
	// this function updates all select boxes below the element with the specified id
	var el = document.getElementById(id);
	if (el)
	{
		var selects = el.getElementsByTagName('select');
		if (selects && selects.length > 0)
		{
			for (var i=0; i<selects.length; i++)
			{
				var sel = selects[i];
				updateSelect(sel);
			}
		}
	}
}

function showDefaultValues(show, noDefaults, defaults)		
{
	if (show)
	{
		hideElementById(noDefaults);
		showElementById(defaults);
		if (MAC && IE5)
			updateSelects(defaults); // needed to display the correct selections for IE/MAC
		scrollToElement(defaults);
	}
	else
	{
		hideElementById(defaults);
		showElementById(noDefaults);
		if (MAC && IE5)
			updateSelects(noDefaults); // needed to display the correct selections for IE/MAC
	}

	shakeWindow(1);
}

function toggleCollapseHierarchy()
{
	toggleHierarchy(getCookieValue("collapsedHierarchy", "false") != "true");
}

function toggleHierarchy(collapsed) 
{
	if (collapsed)
	{
		hideElementById("fullhierarchy");
		showElementById("collapsedhierarchy");
	}
	else
	{
		hideElementById("collapsedhierarchy");
		showElementById("fullhierarchy");
	}

	setCookie("collapsedHierarchy", collapsed ? "true" : "false", false);
}

function convertStringToBoolean(strBool)
{
	if(strBool == null || strBool == "")
		return false;
		
	if(strBool == 'true' || strBool == '1')
		return true;
    else if(strBool == 'false' || strBool == '0' ) 
		return false;
    
	return strBool; // assume that it is of type boolean
}

function getSelectedPageRange()
{
	var startPage = -1;
	var endPage = -1;
	
	var checkboxes = findAllCheckboxes( document.getElementById("updateForm") );	
	
	for ( var index = 0; index < checkboxes.length; index++ )
	{
		var checkbox = checkboxes[index];
	
		if ( checkbox )
		{
			if(checkbox.checked)
			{
				if(startPage < 0)
				{
					startPage = index;
				} 
				else
				{
					endPage = index;
				}
			}
		}
	}

	if (startPage < 0)
	{
		// no pages selected :make startPage larger than end page to obtain an empty page range
		startPage = 0;
		endPage = -1;
	}
	else if (endPage < 0)
	{
		// only start page selected : single page range
		endPage = startPage;
	}
		
	
	var pages = "";
	for ( var index = startPage; index <= endPage; index++ )
	{
		pages += new String(pageListSequenceNumber[index]);
		if (index < endPage)
			pages += ",";
	}
	
	
	var pagesCollection = new RangeCollection(pages);

	return pagesCollection.getDescription();			
}

function resetCheckBox(id)
{
	setCheckBox(id, false);
}

function setCheckBox(id, check)
{
	var checkBoxElement = getCachedElementById(id);
	if(checkBoxElement)
		checkBoxElement.checked = check;
}
	
function resizeApplet() 
{
	var width, height;
	if (isIE) 
	{
	    width = document.body.clientWidth;
	    height = document.body.clientHeight;
	} 
	else 
	{
	    var netscapeScrollWidth = 15;
	    width = window.innerWidth - netscapeScrollWidth;
	    height = window.innerHeight - netscapeScrollWidth;
	}
	
	
	var applet = getApplet();
	applet.setSize(width, height);
	window.scroll(0,0);
}

////////////// Helper functions for select fields /////////////////////////////////////

// this function returns true if the specified element is a select element
function isSelect(el)
{
	return (el && el.tagName=='SELECT');
}

// this function returns true if both values are equal (both can be strings or numbers)
function equal(value1, value2)
{
	// we use explicitly the radix 10 to avoid problems for numbers starting with "0" (e.g. "08")
	var v1 = parseInt(value1, 10);
	var v2 = parseInt(value2, 10);
	return ((isNaN(v1) && isNaN(v2) && value1 == value2) ||
				(v1 == v2));
}

// this function returns the selected value
function getSelectedValue(select)
{
	var result = null;
	if (select != null && select.options.length > 0 && select.selectedIndex >= 0 && select.options.selectedIndex < select.options.length)
		result = select.options[select.selectedIndex].value;
	return result;
}

// this function returns true when the specified select element exists and is set
function selectSet(select)
{
	return (select != null) && (select.selectedIndex >= 0) && (select.options[select.selectedIndex].text != "");
}

// this function returns true when the specified select element exists and is cleared
function selectCleared(select)
{
	return (select != null) && (select.selectedIndex >= 0) &&(select.options[select.selectedIndex].text == "");
}

// this function returns true when the first select element exists and is set
// and the second element does not exist or exists and is set too
function selectsSet(select1, select2)
{
	return 	selectSet(select1) && ((select2 == null) || selectSet(select2));
}

// this function returns true when the first select element exists and is cleared
// or when the first select element exists and is set, but the second element exists and is cleared
function selectsCleared(select1, select2)
{
	return selectCleared(select1) || (selectSet(select1) && selectCleared(select2));
}


// set a select element to the specified value (or to the first option if not found)
// return true if the value was found, false otherwise
function setSelect(select, value)
{
	var found = false;
	if ((select!=null) && (select.options) && (value!=null))
	{
		for (var i=0; i < select.options.length;i++)
		{
			var val = select.options[i].value;
			if (equal(value, val))
			{
				select.selectedIndex = i;
				found = true;
				break;
			}
		}
		if (found == false)
		{
			if (select.options.length > 0)
				select.selectedIndex = 0;
			else
				select.selectedIndex = -1;
		}
	}
	return found;
}

// get the index of a select element's value (return -1 if the value is not found)
function getIndex(select, value)
{
	var result = -1;
	if ((select!=null) && (select.options) && (value!=null))
	{
		for (var i=0; i < select.options.length;i++)
		{
			var val = select.options[i].value;
			// use the radix 10 explicitly to avoid problems for numbers starting with "0" (e.g. "08")
			var v1 = parseInt(value, 10);
			var v2 = parseInt(val, 10);
			if ((isNaN(v1) && isNaN(v2) && value == val) ||
				(v1 == v2))
			{
				result = i;
				break;
			}
		}
		return result;
	}
}

// clear a select element (i.e. set it to the blank option, if possible)
function clearSelect(select)
{
	if (select!=null)
	{
		for (i=0; i < select.options.length;i++)
		{
			if (select.options[i].text == "")
			{
				select.selectedIndex = i;
				select.value = select.options[i].value;
				break;
			}
		}
	}
}

// set a select element to the specified index
function setSelectIndex(select, index)
{
	if ((select!=null) && (index!=null) && (index >= 0))
	{
		select.selectedIndex = index;
	}
}

// check whether a select element has a blank option
function hasBlankOption(select)
{
	var result = false;
	
	if (select!=null)
	{
		for (i=0; i < select.options.length;i++)
		{
			if (select.options[i].text == "")
			{
				result = true;
				break;
			}
		}
	}
	return result;
}


function setDocumentValue( field, value )
{
	if ( field.value )
	{
		field.value = value;
	}
	else
	{
		var noChilds = false;
		try {
			noChilds = !field.childNodes[0];
		} catch (e) {
			noChilds = true;		
		}
		
		if (noChilds)
		{
			field.appendChild( document.createTextNode( value ) );
		}
		else
		{
			field.childNodes[0].nodeValue = value;
		}
	}
}

function updateOnKeyUpHandler(id, funcName)
{	
	var element = document.getElementById(id);
	if(element)
	{
		element._onkeyup = element.onkeyup;
		element.onkeyup = new Function("event", "this._onkeyup(event);" + funcName);
	}
}

function updateOnChangeHandler(id, funcName)
{	
	var element = document.getElementById(id);
	if(element)
	{
		element._onchange = element.onchange;
		element.onchange = new Function("event", "this._onchange(event);" + funcName);
	}
}

function changeElementTextColor(id, color)
{
	var inputField = document.getElementById(id);
	if(inputField)
		inputField.style.color = color;
}


function selectOption(list, key)
{
	var listElement = list;
	if(list.constructor == String)
	{
		var listId = list;
		listElement = getCachedElementById(listId);
	}

	selectElementOption(listElement, key);	
}

function selectElementOption(list, key)	
{
	if(list)
	{
		for(var i = 0; i < list.length; i++)
		{
			if(list.options[i].value == key)
			{
				list.selectedIndex = i;
				return;
			}
		}
	}
}





