Array.prototype.contains = function (elem) {
	for (var i=0; i<this.length; i++)
		if (this[i]==elem) return true;
	return false;
}

var w = window;
var d = document;

function object(id) {
	var obj = d.getElementById(id);
	// sadly, IE interprets this method as getElementByIdOrName
	return (obj && obj.id==id) ? obj : null;
}

function $(id) {
	return object(id);
}

// in beta version!!! doesn't create clones of attributes which are objects
function clone(obj) {
	var cObj = {};
	for (var i in obj) {
		cObj[i] = obj[i]}
	return cObj;
}

function getKey() {
	return Math.round(Math.random()*1000000);
}

function encodeDashes(str) {
	return str.replace(/-/g,'DASH');
}

function decodeDashes(str) {
	return str.replace(/DASH/g,'-');
}

function toTextOnly(html) {
	return html.replace(/<[^>]+>/g,' ').replace(/&nbsp;/g,' '); // remove tags & format nbsp's
}

function formatNumber(num,minDigits) {
	var numStr = num.toString();
	while (numStr.length<minDigits) numStr = '0' + numStr;
	return numStr;
}

function cancelBubble(e) { // e = event
	if (!e) e = window.event;
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
}


//------------------------------- window geometry -------------------------------

// returns absolute x or y coordinate of an object relative to the window
function getAbsPos(obj,which) { // which : 'Left' : 'Top';
	var i = 0;
	while (obj) {
		i += obj['offset' + which];
		obj = obj.offsetParent}
	return i;
}

function getInnerWindowDimensions() {
	var de = d.documentElement, b = d.body;
	var width = (w.innerWidth) ? w.innerWidth : (de && de.clientWidth) ? de.clientWidth : b.clientWidth;
	var height = (w.innerHeight) ? w.innerHeight : (de && de.clientHeight) ? de.clientHeight : b.clientHeight;
	return {w: width, h: height};
}

// This should work all the time for WinIE and most of the time for other browsers
function getInnerWindowPosition() {
	var x = w.screenLeft, y = w.screenTop, outPos = getOuterWindowPosition();
	if (x==null || (x==outPos.x && y==outPos.y)) { // mozilla or safari
		var outDim = getOuterWindowDimensions();
		var inDim = getInnerWindowDimensions();
		x = outPos.x + ((outDim.w - inDim.w)/2);
		y = outPos.y - inDim.h + outDim.h}
	else if (outPos.y<-4) { // opera
		x = 0;
		y = 0 - outPos.y}
	return {x: x, y: y};
}

function getOuterWindowDimensions() {
	return {w: w.outerWidth, h: w.outerHeight};
}

function getOuterWindowPosition() {
	return {x: w.screenX, y: w.screenY};
}

// Get the absolute position of an object on the screen
function getPosition(obj) {
	var x, y, b = d.body, s = screen;
	if (obj && b.scrollLeft!=null) {
		x = getAbsPos(obj,"Left") - b.scrollLeft;
		y = getAbsPos(obj,"Top") - b.scrollTop;
		var iwPos = getInnerWindowPosition();
		if (iwPos.x!=null) {
			x += iwPos.x;
			y += iwPos.y}}
	return {x: x, y: y};
}


//------------------------------- frames -------------------------------

// resizes top & bottom frames to the size of object('mainTable')
function resizeFrame(fType) { // fType is frame type = "top" | "bottom"
	if (fType && w != top) {
		var mT = object('mainTable'), p = parent;
		var fs = p.document.getElementById('ps_win_frameset');
		if (mT && fs) {
			p[fType+'FrameHeight'] = mT.offsetHeight;
			var tH = p.topFrameHeight, bH = p.bottomFrameHeight;
			if (tH>=0 && bH>=0) fs.rows = tH+',*,'+bH}}
}

// Function used to resize automatically a frame depending of the objects it contains
// oUsed : Array of id used to compute the new frame height
function resizeFrameByObjects(oUsed) {
	var fIndex = -1;

	// Get the index of the current frame in the framset
	for(var i=0; i < parent.frames.length; i++) {
		if(parent.frames[i] == window)
			fIndex = i;
	}

	if(fIndex >= 0) {
		// Get the current frame's size set in the framset
		var fSizes = parent.document.body.rows.split(',');

		// Compute the real frame size and set it in the array
		// representing the frames size
		if(oUsed && oUsed.length) {
			var size = 0;

			for(var i=0; i < oUsed.length; i++) {
				var object = document.getElementById(oUsed[i]);

				if(object) size += object.offsetHeight;
			}

			if(size > fSizes[fIndex]) fSizes[fIndex] = size;
		}

		// Set the new size in the framset
		var rows = '';
		for(var i=0; i < fSizes.length; i++) {
			if(i > 0 ) rows += ',';

			rows += fSizes[i];
		}

		parent.document.body.rows = rows;
	}
}


//------------------------------- popups -------------------------------
var g_pops = {}; // maps popup window names to window Objects

var INIT_POPUP_SIZE = {w: 150, h: 100};
var MAX_POPUP_SIZE = {w: 1024, h: 768};
//Oldies:
//var MAX_POPUP_SIZE = {w: 800, h: 600};
//var MAX_POPUP_SIZE = {w: screen.width, h: screen.height};

//Init popup size, right now:
initPopupSize();

function initPopupSize() { 	
	//Normally, MAX_POPUP_SIZE.w = 1024px and MAX_POPUP_SIZE.h = 768px
	
	if (screen.width <= MAX_POPUP_SIZE.w)
		INIT_POPUP_SIZE.w = Math.floor(screen.width * 0.9); // 90% of screenwidth
	else
		INIT_POPUP_SIZE.w = MAX_POPUP_SIZE.w;
	
	if (screen.height <= MAX_POPUP_SIZE.h)
		INIT_POPUP_SIZE.h = Math.floor(screen.height * 0.9); // 90% of height
	else
		INIT_POPUP_SIZE.h = MAX_POPUP_SIZE.h;
}


function isPopup() { // test if this window was opened using an 'openPopup' function
	if (w.name && /^popup_\w+/.test(w.name)) return true;
	try {
		var o = opener;
		return (o!=null && o.g_pops!=null && o.g_pops[w.name]!=null);
	} catch (e) {
		return false}
}

Popup = {

	resizeByDims : {
		w: 0,
		h: 0,
		isZero: function() {return (this.w==0 && this.h==0)}}

	//Don't forget to use comas if there are other Popup object functionnalities:
	//,

	//-----------------------
	// /!\ NO MORE RESIZING:
	//-----------------------
	/**
	 * A listener that expires once the popup has been correctly resized.
	 */
	/*
	resize : function() {
		try {resizePopup()}
		catch (e) {}
		if (this.resizeByDims.isZero()) return;
		setTimeout('Popup.resize()',50);
	}
	*/
		

	//------------------------------
	// /!\ ... BUT A "re-centering":
	//------------------------------
	//-----------------------------------------------
	//Not really smooth visually (especially for IE):
	//Re-Centering is now disabled.
	//-----------------------------------------------
		
	/**
	 * A listener that expires once the popup has been correctly resized.
	 * This function will be called, again, when the pop-up is resized manually by the user 
	 * (see "savePopUpSizeInACookieAndCenterIt" function in "utils.js")
	 */
	/*
	recenter : function() {
		try {
			recenterPopup();
			if ($j.browser.msie) {
				clearTimeout('Popup.recenter()');
			}
		} catch (e) {}
		//if (this.resizeByDims.isZero()) return;
		if ($j.browser.msie) {
			setTimeout('Popup.recenter()', 100);
			//clearTimeout('Popup.recenter()');
		}
	}
	*/
}

function recenterPopup() {
	$j(document).ready(function(){
		var arrayPageSize = getPageSize();
		window.moveTo(screen.width/2 - arrayPageSize[2]/2, screen.height/2 - arrayPageSize[3]/2);
	});
}

/**
 * Resizes inner window to dimensions of first child element of BODY element.
 * @param {Object} args {minWidth,minHeight,maxWidth,maxHeight,overrideMax,overrideWidth}
 */
function resizePopup(args) {
	//alert("dans resizePopUp");
	var de = d.documentElement;
	var getFirstChildElement = function(obj) {
		var cNs = obj.childNodes;
		var i = 0;
		while (cNs[i] && (!cNs[i].tagName || cNs[i].nodeName=="#comment"))
			i++;
		
		return cNs[i];
	}
	
	// get first child element dimensions
	var obj = getFirstChildElement(d.body);
	if (!obj) 
		return;
	
	while (obj.tagName.toUpperCase()=='FORM') {
		obj = getFirstChildElement(obj);
		if (!obj) 
			return;
	}

	//Calculate FKeyset Table's height, which will be used for specified pop-up height dimension for the refresh:
	var lkTableHeight = 0;
	
	$j(document).ready(function(){
		var lkTable = $j("div[id*='shadow_FKeySet_tFId_']");
		if (lkTable != null) {
			lkTableHeight = lkTable.css("height");
			if (lkTableHeight != null && lkTableHeight.indexOf('px') != -1) {
				lkTableHeight = lkTableHeight.substring(0, lkTableHeight.indexOf('px'));
				lkTableHeight = (new Number(lkTableHeight)) + 5;// Conversion, adding 5 px for the CSS shadow of this table. 
			}
		}
	});
	
	
	//Check if the content contains an image which has to be displayed in full size: 
	var imgMainImg = $j("img[class='mainImg']");
	var imgMainImgDisplayValue = $j("img[class='mainImg']").css("display");
	//Re-define popups maximum size if needed:
	MAX_POPUP_SIZE.w = !Boolean(imgMainImgDisplayValue) ? 800 : screen.width;
	MAX_POPUP_SIZE.h = !Boolean(imgMainImgDisplayValue) ? 600 : screen.height;
	
	
	var objDim;
	//if (typeof document.body.style.maxHeight === "undefined") {//if IE 6
	if (isIE()) {
	//if ($j.browser.msie) {
		objDim = {w: obj.offsetWidth, h: (lkTableHeight != null && lkTableHeight > obj.offsetHeight ? lkTableHeight : obj.offsetHeight)};
		//alert("IE : obj.offsetWidth=" + obj.offsetWidth + "et objDim.w = " + objDim.w);
		//alert("IE : lkTableHeight=" + lkTableHeight + " et obj.offsetHeight=" + obj.offsetHeight + "et objDim.h = " + objDim.h);
	} else {
		
		//Only for pages which are not "blank.jsp" (containing a "mainTable" div tag):
		var divMainTable = $j("div[id='mainTable']");
		var divMainTableWidthValue = $j(divMainTable).css("width");
		
		if (!Boolean(divMainTableWidthValue))
			obj.style.width = '1px';
		
		//Check if the content contains an image which has to be displayed in full size: 
		var widthAdds = !Boolean(imgMainImgDisplayValue) ? 100 : 0;
		var heightAdds = !Boolean(imgMainImgDisplayValue) ? 100 : 0;
		
		
		objDim = {w: obj.offsetWidth + widthAdds, h: (lkTableHeight != null && lkTableHeight > obj.offsetHeight ? lkTableHeight : obj.offsetHeight + heightAdds)};
		obj.style.width = '100%';
		//alert("FF : obj.offsetWidth=" + obj.offsetWidth + "et objDim.w = " + objDim.w);
		//alert("FF : lkTableHeight=" + lkTableHeight + " et obj.offsetHeight=" + obj.offsetHeight + "et objDim.h = " + objDim.h);
	}
	
	
	// apply max dimensions
	if (!args || args.overrideMax!=true) {
		var maxW = (args && args.maxWidth) ? args.maxWidth : MAX_POPUP_SIZE.w;
		if (objDim.w>maxW) 
			objDim.w = maxW;
		
		var maxH = (args && args.maxHeight) ? args.maxHeight : MAX_POPUP_SIZE.h;
		if (objDim.h>maxH) 
			objDim.h = maxH;
	}
	// apply min dimensions
	if (args && args.minWidth && objDim.w<args.minWidth) objDim.w = args.minWidth;
	if (args && args.minHeight && objDim.h<args.minHeight) objDim.h = args.minHeight;
	// get inner window dimensions
	var inDim = getInnerWindowDimensions();
	// resize window
	var rbDim = {w: objDim.w - inDim.w, h: objDim.h - inDim.h};


	// TEMPTATIVE FOR TAKING INTO ACCOUNT IFRAME HEIGHT
	var iframe = document.getElementById('recIFrame');
	if (iframe != null) {
		var iFrameHeightInPx = iframe.style.height;
		if (iFrameHeightInPx.indexOf("px") != -1)
			iFrameHeightInPx = iFrameHeightInPx.substring(0, iFrameHeightInPx.length - 2);
		//rbDim.h = new String((parseInt(rbDim.h) + parseInt(iFrameHeightInPx))/* + "px"*/);
		rbDim.h = parseInt(iFrameHeightInPx);
	}
	
	
	// override width changes if required
	if (args && args.overrideWidth==true) rbDim.w = 0;
	Popup.resizeByDims.w = rbDim.w;
	Popup.resizeByDims.h = rbDim.h;
	// check that complete surface of window will be visible

	/*
	var inPos = getInnerWindowPosition(), s = screen;
	var mbPos = {x: s.width - inPos.x - objDim.w, y: s.height - inPos.y - objDim.h - 40};
	try {
		if (mbPos.x<0 || mbPos.y<0) {
			mbPos.x = (mbPos.x>=0) ? 0 : mbPos.x-25;
			mbPos.y = (mbPos.y>=0) ? 0 : mbPos.y-25;
			w.moveBy(mbPos.x, mbPos.y);
		}
	} catch (e) {};
	*/
	
	//-----------------------
	// /!\ NO MORE RESIZING:
	//-----------------------
	//w.resizeBy(rbDim.w, rbDim.h);
	
	//TODO: voir le max resize (cf. Manu grande taille verticale car 2 écrans l'un au dessus de l'autre).
	
	//---------------------------------
	// /!\ BUT STILL GOOD POSITIONNING:
	//---------------------------------
	//Then, after a resizing, re-move the window to the good position:
	//if (isIE()) {
	w.moveTo(screen.width/2 - getWindowWidth()/2, screen.height/2 - getWindowHeight()/2);
	//}
}

// Opens a popup window with default PS attributes & adds it to g_pops array
function openPopup(url,name,props) {
	if (!url) url = '';
	if (!name) name = 'popup_SEPARATORforKEY' + getKey();
	name = encodeDashes(name); // IE doesn't like dashes
	
	var popupShortName = name;
	//popup's name is based on a string + a custom date, each second will produce a new name.	
	//So ...
	//alert("popupShortName : "+popupShortName);
	if (popupShortName.indexOf("SEPARATORforKEY") != -1 )
		popupShortName = popupShortName.substring(0, popupShortName.indexOf("SEPARATORforKEY"));
	//else if (popupShortName.lastIndexOf("_") != -1 )
	//	popupShortName = popupShortName.substring(0, popupShortName.lastIndexOf("_"));
	
	//alert("popupShortName : "+popupShortName);
	
	//Getting cookie values for this pop-up, containing  user's manual pop-up resizing informations
	//Or default values:
	var goodWidth, goodHeight;
	
	if (readCookie("wSize_for_" + popupShortName) != null) {
		//alert("cookie w: "+readCookie("wSize_for_" + popupShortName));
		goodWidth = readCookie("wSize_for_" + popupShortName);
	} else
		goodWidth = INIT_POPUP_SIZE.w;
		
	if (readCookie("hSize_for_" + popupShortName) != null) {
		//alert("cookie h: "+readCookie("hSize_for_" + popupShortName));
		goodHeight = readCookie("hSize_for_" + popupShortName);
	} else
		goodHeight = INIT_POPUP_SIZE.h;
	
	
	
	//alert("props before: "+props);
	if (!props) {
		props = 'scrollbars=1, resizable, width='+goodWidth+', height='+goodHeight;
	} else {
		if (props.indexOf("width") != -1 && props.indexOf("height") != -1 ) {
			var newProps = "";
			//Beginning:
			var propsTMP = props.substring(0, props.indexOf("width"));
			//cleaning:
			props = props.replace(propsTMP, '');
			//alert("(Beginning) propsTMP : "+propsTMP);
			
			newProps += propsTMP + 'width = ' + goodWidth;
			//alert("newProps : "+newProps);
			
			//Middle:
			propsTMP = props.substring( (props.indexOf(",") != -1 ? props.indexOf(",") : props.length), props.indexOf("height"));
			//cleaning:
			props = props.replace(propsTMP, '');
			//alert("(Middle) propsTMP : "+propsTMP);
			
			newProps += propsTMP + 'height = ' + goodHeight;
			//alert("newProps : "+newProps);
			
			//End:
			propsTMP = props.substring((props.indexOf(",") != -1 ? props.indexOf(",") : props.length) , props.length);
			//alert("(end) propsTMP : "+propsTMP);
			
			newProps += propsTMP;
			//alert("newProps : "+newProps);
			
			//And we set it:
			props = newProps;
			
		} else
			props += ', width='+goodWidth+', height='+goodHeight;
	}
	
	//alert("props after: "+props);
	
	
	var n = w.open(url, name, props); // new window
	
	g_pops[name] = n;
	n.focus();
	
	
	//See recordModify.jsp for the use of this function.
	//n.window.onResize = savePopUpSizeInACookieAndCenterIt(popupShortName);
	
//	$j(n).resize(function(){
//		savePopUpSizeInACookieAndCenterIt(popupShortName);
//	});
//	
	
	//When the pop-up is opened, place it in the center of the screen, using its good dimensions.
	n.moveTo(screen.width/2 - goodWidth/2, screen.height/2 - goodHeight/2);
	//Note that when the pooup is manually resized by the user, the dimensions are saved in a specific cookie and the popup is,
	//once again, centered in the screen, using its new size value.
	//(see in "utils.js", function "savePopUpSizeInACookieAndCenterIt")
	
	return n;
	
}

// Opens a popup window and writes a message in it
function openPopupMessage(name,props,msg) {
	var n = openPopup(null,name,props);
	n.document.write(msg); // write content in popup
	return n;
}

// Opens a popup window positioned according to obj
function openPositionedPopup(url,name,obj) {
	var pos = getPosition(obj);
	var x = (pos.x!=null) ? pos.x : 0;
	var y = (pos.y!=null) ? pos.y + obj.offsetHeight + 6 : 0;
	return openPopup(url,name,'scrollbars=1,resizable,width='+INIT_POPUP_SIZE.w+',height='+INIT_POPUP_SIZE.h+',left='+x+',top='+y);
}

// Opens a popup window using MAX_POPUP_SIZE, with scrollbars & resizable
function openExternalPopup(url) {
	var props = 'scrollbars=1,resizable,width='+MAX_POPUP_SIZE.w+',height='+MAX_POPUP_SIZE.h;
	openPopup(url,null,props);
}

function resizeAndCenterPopup(W,H) {
	var s = screen;
	w.resizeTo(W,H);
	w.moveTo(s.width/2 - W/2, s.height/2 - H/2);
}

// Maps popup window names to response functions
PopupResponseFunctions = {

	map : {},

	set : function(winName,fResponse) {
		this.map[winName] = fResponse},

	call : function(winName) {
		this.map[winName](g_pops[winName].XML)}
}


//------------------------------- show/hide element/s -------------------------------

function hideGroup(grId) {
	toggleGroup('hide',gpId)}

function showGroup(grId) {
	toggleGroup('show',gpId)}

// Toggles 'display' property of 3 objects: o1, o2 & o3
// o1 is a block level element
// o2 & o3 are inline
function toggleGroup(cmd,gpId) { // cmd : 'show' | 'hide'
	var o1 = object(gpId),
			o2 = object(gpId+'_ex'),
			o3 = object(gpId+'_col'),
			s1 = '',
			s2 = 'none';
	if (cmd=='hide') {s1 = 'none'; s2 = ''}
	if (o1!=null) o1.style.display = s1;
	if (o2!=null) o2.style.display = s2;
	if (o3!=null) o3.style.display = s1;
	if (cmd=='show') adjustAllRows()}

function showTrs(gpId,gpParId) { // gpParId is the group parent id
	var gpParent = (gpParId) ? object(gpParId) : d;
	toggleTrs('show',gpId,gpParent)}

function hideTrs(gpId,gpParId) { // gpParId is the group parent id
	var gpParent = (gpParId) ? object(gpParId) : d;
	toggleTrs('hide',gpId,gpParent)}

function toggleTrs(showHide,gpId,gpParent) { // showHide : 'show' | 'hide'; gpParent is an obj that contains the TR elements
	if (!gpParent) gpParent = d;
	var trs = gpParent.getElementsByTagName('tr'),
			oE = object(gpId+'Expand'),
			oC = object(gpId+'Collapse'),
			isToHide = (showHide=='hide');
	for (var i=0; i<trs.length; i++) {
		if (trs[i].id.indexOf(gpId+'-')==0) trs[i].style.display = (isToHide) ? 'none' : ''}
	if (oE!=null) oE.style.display = (isToHide) ? '' : 'none';
	if (oC!=null) oC.style.display = (isToHide) ? 'none' : '';
	if (!isToHide) adjustAllRows();
}

function toggleAllTrs(showHide,gpPrefix,gpParent) {
	if (!gpParent) gpParent = d;
	var tO = gpParent.getElementsByTagName('tr'),
			gpId = null;
	for (var i=0; i<tO.length; i++) {
		if (tO[i].id.indexOf(gpPrefix)==0) {
			var trGpId = tO[i].id.split('-')[0];
			if (trGpId!=gpId) { // if this tr is not in the same group as the last tr
				gpId = trGpId;
				toggleTrs(showHide,gpId,gpParent)}}}}


// ----------------- Automatic resizing of TEXTAREA rows ----------------------------
// Adjusts the number of rows of a textarea object to fit the content

function adjustRows(obj) { // obj is a TEXTAREA object
	if (!obj) obj = this;
	var initRows = obj.rows;
	if (obj && obj.tagName=='TEXTAREA' && obj.clientHeight && obj.scrollHeight && obj.offsetHeight && obj.scrollHeight!=obj.offsetHeight && obj.rows) {
		// method supported by MSIE
		while (obj.scrollHeight<obj.clientHeight && obj.rows>1) obj.rows--;
		while (obj.scrollHeight>obj.clientHeight) obj.rows++;}
	else { // open standard method
		var text = obj.value.replace(/\t/g,'        '); // replace tabs
		var blocks = text.split('\n'); // split line returns
		var rows = 0;
		for (var i=0; i<blocks.length; i++) { // now calculate number of lines in each block of text
			rows += Math.ceil((blocks[i].length+1)/obj.cols)}
		obj.rows = rows}
	obj.scrollTop = 0;
	//if (isPopup() && initRows!=obj.rows) resizePopup({overrideWidth:true});
	}

// Gets the number of cols of the 1st text area & applies it to the others
function initTextAreaObjs() {
	var tAs = d.getElementsByTagName('TEXTAREA');
	var cols = 0;
	for (var i=0; i<tAs.length; i++) {
		// remove class that refers to width
		if (/(^| )wide( |$)/.test(tAs[i].className)) {
			tAs[i].className = tAs[i].className.replace(/wide ?/g,'');
			tAs[i].style.width = '100%'}
		// set min width of 200px
		if (tAs[i].style.display=='' && tAs[i].clientWidth && tAs[i].clientWidth<200) {
			tAs[i].style.width='200px'}
		// set cols according to first qualifying text area width
		if (cols==0 && tAs[i].style.display=='' && tAs[i].clientWidth) {
			var initialWidth = tAs[i].clientWidth;
			tAs[i].style.width = '';
			tAs[i].cols = 1;
			while (tAs[i].clientWidth < initialWidth) tAs[i].cols++;
			if (tAs[i].cols>1) tAs[i].cols--;
			cols = tAs[i].cols}
		else if (cols>0) {
			tAs[i].style.width = '';
			tAs[i].cols = cols}
		// adjust rows
		if (tAs[i].style.display=='') adjustRows(tAs[i]);}}

function adjustAllRows() {
	var tAs = d.getElementsByTagName('TEXTAREA');
	for (var i=0; i<tAs.length; i++) adjustRows(tAs[i])}


// ----------------- Automatic resizing of Text Inputs' size ----------------------------

function autoTextInputSize(minSize) {
	var osInput = d.getElementsByTagName('INPUT');
	for (var i=0; i<osInput.length; i++) {
		if (osInput[i].type=='text' && osInput[i].value!='') {
			var chars = osInput[i].value.length * 1.2;
			if (chars>minSize && chars>osInput[i].size) osInput[i].size = chars;}}
	setTimeout('autoTextInputSize('+minSize+')',500)}


// ----------------- drop down menus ----------------------------

DDMenus = {

	DELAY : 1000, // in milliseconds
	map : {}, // maps Menu instances by id

	Menu : function(id) { // private object
		this.obj = object(id+'Menu'); // HTML DIV element
		this.timeoutId = -1;
		DDMenus.map[id] = this}, // add this to map

	show : function(obj,id,hOffset,vOffset) { // previously showMenu
		// hide all menu objs
		this.hideAll();
		// create new menu instance
		var m = new this.Menu(id);
		// show menu
		if (m.obj) {
			var mos = m.obj.style;
			mos.left = (getAbsPos(obj,'Left') + hOffset) + 'px';
			mos.top = (getAbsPos(obj,'Top') + obj.offsetHeight + vOffset) + 'px';
			mos.visibility = 'visible'}},

	hideAll : function() {
		for (var i in this.map) {
			this.stopTimer(i);
			this.hide(i)}},

	startTimer : function(id) { // previously startMenuTimer
		this.map[id].timeoutId = setTimeout('DDMenus.hide("'+id+'")', this.DELAY)},

	stopTimer : function(id) { // previously stopMenuTimer
		var m = this.map[id];
		w.clearTimeout(m.timeoutId);
		m.timeoutId = -1},

	hide : function(id) { // private
		var mo = this.map[id].obj;
		if (mo) mo.style.visibility = 'hidden'}
}


// ----------------------- cookies ---------------------------------------

Cookies = {
	set : function(id,value) {
		var date = new Date();
		date.setTime(date.getTime() + (100*365*24*60*60*1000));
		d.cookie = id + '=' + value + '; path=' + location.pathname + '; expires=' + date.toGMTString()},
	get : function(id) {
		var c = d.cookie;
		if (c) {
			(new RegExp(id+"=([^;]+)")).test(c);
			return RegExp.$1}},
	del : function(id) {
		if (this.get(id)) {
			var date = new Date();
			date.setTime(date.getTime() - (24*60*60*1000));
			d.cookie = id + '=; path=' + location.pathname + '; expires=' + (new Date()).toGMTString()}}
}


// ----------------------- A log display opened in a popup window -----------------------
g_blogWin = null;

function blog(str) {
	try {
		if (!g_blogWin || !g_blogWin.document) {
			g_blogWin = window.open('','psw_blog');
			g_blogWin.document.write('<HTML><HEAD></HEAD><BODY></BODY></HTML>')}
		var now = new Date();
		g_blogWin.document.body.innerHTML += '<P style="font: 12px monospace; white-space: nowrap">'
		+ formatNumber(now.getHours(),2) + ':'
		+ formatNumber(now.getMinutes(),2) + ':'
		+ formatNumber(now.getSeconds(),2) + ':'
		+ formatNumber(now.getMilliseconds(),3) + ' '
		+ str.replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\n/g,'<BR>').replace(/\t/g,'&nbsp;&nbsp;&nbsp;&nbsp;').replace(/ /g,'&nbsp;')
		+ '</P>'}
	catch (e) {
				alert(str)}}


/**
 * Gets the height of the frame
 */
function getWindowHeight() {
        var windowHeight = 0;


                if (document.documentElement && document.documentElement.clientHeight) {
                        windowHeight = document.documentElement.clientHeight;
                } else {
                        if (document.body && document.body.clientHeight) {
                                windowHeight = document.body.clientHeight;
                        }
                }

        return windowHeight;
}

/**
 * Gets the width of the frame
 */
function getWindowWidth() {
        var windowWidth = 0;

                if (document.documentElement && document.documentElement.clientWidth) {
                        windowWidth = document.documentElement.clientWidth;
                } else {
                        if (document.body && document.body.clientWidth) {
                                windowWidth = document.body.clientWidth;
                        }
                }

        return windowWidth;
}