/**
 * Common system functions used by other script files
 * 
 * @package		System
 *
 * @author		ignat <iignatov@verasoft.com>
 * @version		1.3
 */


/**
 * Check if the variable is set
 * 
 * @param			mixed			variable to check
 * @return		boolean		true if the variable is set, false - otherwise
 *
 * @version		1.0
 */
function isSet(pVar) {
	return ((typeof(pVar) != 'undefined') && (pVar != null));
}



/**
 * Check if the value is in the specified array
 * 
 * @param			mixed			value for which to check
 * @param			array			array to search in
 * @return		boolean		true if the value exists in array, false - otherwise
 *
 * @version		1.0
 */
function inArray(pVal, pArr, pStrict) {
	for (var i=0; i<pArr.length; i++) {
		if (isSet(pStrict) && pStrict == true) {
			if (pArr[i] === pVal) return true;
		} else {
			if (pArr[i] == pVal) return true;
		}
	}
	return false;
}



/**
 * Check if variable is an array
 * 
 * @param			mixed			variable to check
 * @param			boolean		if true it will not consider objects for arrays
 * @return		boolean		true if the variable is array, false - otherwise
 *
 * @version		1.0
 */
function isArray(pVar, pStrict) {
	if (typeof(pStrict) == 'undefined') var pStrict = false;
	if (pStrict) {
		return ((typeof(pVar) == 'object') && (pVar.constructor.toString().indexOf("Array") != -1));
	} else {
		return (typeof(pVar) == 'object');
	}
}



/**
 * Universal function to get element by name or id
 * 
 * @param			string		element name or id
 * @param			object		document object in which the element exists
 * @return		mixed			element object if found, false if not found
 *
 * @version		1.2
 */
function getElement(pName, pDoc) {
	var mainDoc = ((isSet(pDoc)) ? pDoc : window.document), theElement = false;
	
	if (!inArray(pName, ['document', 'window'])) {
		if (typeof(document.getElementsByName) != 'undefined') {
			theElement = mainDoc.getElementsByName(pName);
			if (theElement.length == 0) {
				theElement = false;
			} else if (theElement.length == 1) {
				theElement = theElement[0];
			}
		}
		
		if (!theElement && typeof(document.getElementById) != 'undefined') {
			theElement = mainDoc.getElementById(pName);
		}
	}
	else if (pName == 'document') {
		theElement = document;
	}
	else if (pName == 'window') {
		theElement = window;
	}
	
	
	return (isSet(theElement) ? theElement : false);
}



/**
 * Get first of the parent elements of the given element by tag name
 * 
 * @param			object		child element
 * @param			string		tagname for which to search in parents
 * @param			object		document object in which the element exists
 * @return		mixed			element object if found, false if not found
 *
 * @version		1.0
 */
function getParentElementByTagName(pElement, pTagName, pDoc) {
	var mainDoc = ((isSet(pDoc)) ? pDoc : window.document);
	var theElement = false;
	
	if (isSet(pElement.parentElement)) {
		theElement = pElement.parentElement;
		while ((theElement.tagName != pTagName.toUpperCase()) && isSet(theElement.parentElement)) {
			theElement = theElement.parentElement;
		}
	}
	
	return (isSet(theElement) ? theElement : false);
}



/**
 * Get first of the previous elements of the given element by tag name
 * 
 * @param			object		child element
 * @param			string		tagname for which to search in parents
 * @param			object		document object in which the element exists
 * @return		mixed			element object if found, false if not found
 *
 * @version		1.0
 */
function getPreviousElementByTagName(pElement, pTagName, pDoc) {
	var mainDoc = ((isSet(pDoc)) ? pDoc : window.document);
	var theElement = false;
	
	if (isSet(pElement.previousSibling)) {
		theElement = pElement.previousSibling;
		
		while ((!isSet(theElement.tagName) || (theElement.tagName != pTagName.toUpperCase())) && isSet(theElement.previousSibling)) {
			theElement = theElement.previousSibling;
		}
	}
	
	return (isSet(theElement) ? theElement : false);
}



/**
 * Get value of element
 * 
 * @param			string		name of the element which value to get
 * @return		string		element's value if any, or empty string
 *
 * @version		1.3
 */
function getElementValue(pElName) {
	var lElement, elValue = '' , lInfoElement;
	
	if (isSet(pElName) && (lElement = getElement(pElName))) {
		
		if (isSet(lElement.length)) {
			lInfoElement = lElement[0];
		} else {
			lInfoElement = lElement;
		}
		
		switch (lInfoElement.tagName) {
			case 'INPUT':
				switch (lInfoElement.type) {
					case 'radio':
						for (var i=0; i<lElement.length; i++) {
					    if (lElement[i].checked == true) {
					    	elValue = lElement[i].value;
					    	break;
					    }
						}
						break;
					
					case 'checkbox':
						for (var i=0; i<lElement.length; i++) {
							elValue = new Array();
					    if (lElement[i].checked == true) {
					    	elValue[elValue.length] = lElement[i].value;
					    }
						}
						break;
					
					default:
						if (isSet(lElement.value)) elValue = lElement.value;
						break;
				}
				break;
			
			case 'SELECT':
				elValue = lElement.options[lElement.selectedIndex].value;
				break;
			
			case 'SPAN':
			case 'DIV':
				elValue = lElement.innerHTML;
				break;
			
			case 'TEXTAREA':
			case 'OPTION':
			default:
				if (isSet(lElement.value)) elValue = lElement.value;
				break;
		}
	}
	
	return elValue;
}

/**
 * get value of element, using getElementValue and convert it to number
 * 
 * @param			string		name of the element
 * @return		number    element value
 *
 * @version		1.0
 */

function getElementAndConvert(pElName) {
	return convertToRealNumber(getElementValue(pElName), ".");
}


/**
 * Set value of element
 * 
 * @param			string		name of the element
 * @param			mixed			new value of the element
 * @param			integer		how to deal with onChange method
 * @return		void
 *
 * @version		1.0
 */
function setElementValue(pElName, pNewValue, pOnChangeTriggerMethod, pCondition) {
	
	if (isSet(pCondition)) {
		if (!pCondition) return;
	}
	
	var lTargetObj = getElement(pElName, self.document), lTriggerOnChange = false;
	
	if (lTargetObj) {

		if (lTargetObj.length > 1) {
			lTagName = lTargetObj[0].tagName;
			lObjectType = lTargetObj[0].type;
		} else {
			lTagName = lTargetObj.tagName;
			lObjectType = lTargetObj.type;
		}
		
		switch (lTagName) {
			case 'INPUT':
				switch (lObjectType) {
					case 'radio':
						for (var i=0; i<lTargetObj.length; i++) {
					    if ((lTargetObj[i].value == pNewValue) && !lTargetObj[i].checked) {
					    	lTargetObj[i].checked = true;
					    	lTriggerOnChange = true;
					    	break;
					    }
						}
						break;
					
					case 'checkbox':
						if (typeof(pNewValue) != 'integer') {
							pNewValue = 0;
						}
						for (var i=0; i<lTargetObj.length; i++) {
							var lChecked = (isArray(pNewValue) ? inArray(lTargetObj[i].value, pNewValue) : (lTargetObj[i].value & pNewValue));
							if (lTargetObj[i].checked != lChecked) {
								lTargetObj[i].checked = lChecked;
								lTriggerOnChange = true;
							}
						}
						break;
					
					default:
						if (isSet(lTargetObj.value) && (lTargetObj.value != pNewValue)) {
							lTargetObj.value = pNewValue;
							lTriggerOnChange = true;
						}
						break;
				}
				break;
			
			case 'SELECT':
				for (var i=0; i<lTargetObj.options.length; i++) {
					if ((lTargetObj.options[i].value == pNewValue) && !lTargetObj.options[i].selected) {
						lTargetObj.options[i].selected = true;
						lTriggerOnChange = true;
						break;
					}
				}
				break;
			
			case 'SPAN':
			case 'DIV':
			case 'TD':
				lTargetObj.innerHTML = pNewValue;
				break;
			
			case 'TEXTAREA':
			case 'OPTION':
			default:
				if (isSet(lTargetObj.value) && (lTargetObj.value != pNewValue)) {
					lTargetObj.value = pNewValue;
					lTriggerOnChange = true;
				}
				break;
		}
		
		if (isSet(pOnChangeTriggerMethod)) {
			if ((typeof(pOnChangeTriggerMethod) == 'boolean') && pOnChangeTriggerMethod) pOnChangeTriggerMethod = -1;
		} else {
			pOnChangeTriggerMethod = 0;
		}
		
		switch (pOnChangeTriggerMethod) {
			case  1: // always trigger onChange
				lTriggerOnChange = true;
				break;
				
			case -1: // don't trigger onChange
				lTriggerOnChange = false;
				break;
				
			case  0:
			default:
				// trigger onChange if element's value was changed, use current value of lTriggerOnChange
				// lTriggerOnChange = lTriggerOnChange;
				break;
		}
		
		if (lTriggerOnChange && (lTargetObj.onchange != null)) lTargetObj.onchange();
	}
}

/**
 * get value of element, using getElementValue and convert it to number
 * 
 * @param			string		name of the element
 * @return		number    element value
 *
 * @version		1.0
 */

function setElementAndConvert(pElName, newValue) {
	newValue = genericNumberFormatting(newValue, 'money');
	setElementValue(pElName, newValue);
}

/**
 * Escape value of the element to be safe for adding to URL
 * 
 * @param			string		name of the element which value to escape
 * @return		string		escaped value, or empty string if no name specified
 *
 * @version		1.0
 */
function escElementValue(pElName) {
	return (isSet(pElName) ? escape(getElementValue(pElName)) : '');
}



/**
 * Escape value of the element to be safe for adding to URL (alias of escElementValue)
 * 
 * @param			string		name of the element which value to escape
 * @return		string		escaped value, or empty string if no name specified
 *
 * @version		1.0
 *
 * @see				escElementValue
 */
function escval(pElName) {
	return escElementValue(pElName);
}



/**
 * Handle data assignment for different web elements, by element tag name
 * 
 * @param			array			keys - names of the fields to set, values - new values
 * @return		void
 *
 * @version		1.4
 */
function uniDataHandling(pData, pOnChangeTriggerMethod) {
	
	if (isSet(pData) && isArray(pData)) {
		for (lFieldName in pData) {
			if (typeof(pData[lFieldName]) != 'number') {
				setElementValue(lFieldName, pData[lFieldName], pOnChangeTriggerMethod);
			}
		}
		for (lFieldName in pData) {
			if (typeof(pData[lFieldName]) == 'number') {
				setElementValue(lFieldName, pData[lFieldName], pOnChangeTriggerMethod);
			}
		}
	} else {
		alert('uniDataHandling: Bad data passed!');
	}
}



/**
 * Set values of many elements at once
 * 
 * @param			array			keys are elements' names, values - elements' values
 * @return		void
 *
 * @version		1.0
 *
 * @see				setElementValue
 */
function setElementsValues(pData, pOnChangeTriggerMethod) {
	if (isSet(pData) && isArray(pData)) {
		uniDataHandling(pData, pOnChangeTriggerMethod);
	}
}



/**
 * Clear value of element
 * 
 * @param			string		name of the element
 * @return		void
 *
 * @version		1.0
 *
 * @see				setElementValue
 */
function clearElementValue(pName, pOnChangeTriggerMethod) {
	setElementValue(pName, '', pOnChangeTriggerMethod);
}



/**
 * Clear values of many elements at once
 * 
 * @param			array			array of elements' names
 * @return		void
 *
 * @version		1.0
 *
 * @see				setElementValue
 */
function clearElementsValues(pElements, pOnChangeTriggerMethod) {
	// elements array must be ordered and not associative (the second check)
	if (isSet(pElements) && isSet(pElements.length) && isArray(pElements)) {
		var lData = new Array();
		for (var i=0; i<pElements.length; i++) {
			lData[pElements[i]] = '';
		}
		uniDataHandling(lData, pOnChangeTriggerMethod);
	}
}


// this variable is used when redirectWindow is used with setInterval for DynSql queries
var gRedirectInterval = null;
/**
 * Redirect window to another location
 * 
 * @param			string		new location
 * @return		void
 *
 * @version		1.0
 *
 */
function redirectWindow(pLocation, pNumOfTries) {
	if (!isSet(pNumOfTries)) pNumOfTries = 0;
	
	if ((gPendingSqlQueries <= 0) || (gRedirectTryCount >= pNumOfTries))
	{
		window.location = pLocation;
		if (isSet(gRedirectInterval)) clearInterval(gRedirectInterval);
	}
	else
	{
		gRedirectTryCount++;
	}
}


function hilightSelectedRow(pElement, pHighlight, pMarkColor, pHighlightColor) {
	var lRow = getParentElementByTagName(pElement, 'TR');
	
	if (lRow) {
		if (pHighlight) {
			lRow.defaultBgColor = oLastRowBGColor;
			if (isSet(pHighlightColor)) lRow.customHighlightColor = pHighlightColor;
			oLastRowBGColor = pMarkColor;
			lRow.style.backgroundColor = pMarkColor;
		} else {
			oLastRowBGColor = lRow.defaultBgColor;
			lRow.style.backgroundColor = lRow.defaultBgColor;
			lRow.defaultBgColor = undefined;
			if (isSet(lRow.customHighlightColor)) lRow.customHighlightColor = undefined;
		}
	}
}

function isElementHidden(pName, pTableEnclosed) {
	lResult = false;

	var lElement = getElement(pName);

	if (isSet(pTableEnclosed) && pTableEnclosed) {
		lElementToCheck = getParentElementByTagName(lElement, "TABLE");
	} else {
		lElementToCheck = lElement;
	}
	
	if (isSet(lElementToCheck) && isSet(lElementToCheck.style) && isSet(lElementToCheck.style.display)) {
		if (lElementToCheck.style.display == 'none') lResult = true;
	}
	
	return lResult;
}

function hideElement(pName, pTableEnclosed) {
	var lElement = getElement(pName);

	if (isSet(pTableEnclosed) && pTableEnclosed) {
		lElementToHide = getParentElementByTagName(lElement, "TABLE");
	} else {
		lElementToHide = lElement;
	}
	
	if (isSet(lElementToHide) && isSet(lElementToHide.style) && isSet(lElementToHide.style.display)) {
		lElementToHide.style.display = 'none';
	}
}

function showElement(pName, pTableEnclosed) {
	var lElement = getElement(pName);
	
	if (isSet(pTableEnclosed) && pTableEnclosed) {
		lElementToShow = getParentElementByTagName(lElement, "TABLE");
	} else {
		lElementToShow = lElement;
	}
	
	if (isSet(lElementToShow) && isSet(lElementToShow.style) && isSet(lElementToShow.style.display)) {
		lElementToShow.style.display = '';
	}
}

function changeElementVisibility(pName, pVisible) {
	if (isSet(pVisible) && pVisible) {
		showElement(pName);
	} else {
		hideElement(pName);
	}
}

function changeWholeElementVisibility(pName, pVisible) {
	changeElementVisibility(pName, pVisible);
	changeElementVisibility(pName+'_label', pVisible);
	changeElementVisibility(pName+'_content', pVisible);
}

function changeContainerVisibility(pName, pVisible) {
	var lContainerElement = getElement(pName);
	if (lContainerElement) {
		if (isSet(lContainerElement.all)) {
			for (var i=0; i<lContainerElement.all.length; i++) {
				// hide all controls
				if (isSet(lContainerElement.all[i].name) && (lContainerElement.all[i].name != '')) {
//					alert(lContainerElement.all[i].name + " : " + lContainerElement.all[i].tagName + " : " + (pVisible ? 'ON' : 'OFF'));
					changeElementVisibility(lContainerElement.all[i].name, pVisible);
				}
			}
		}
		changeElementVisibility(pName, pVisible);
	}
}

function switchElementVisibility(pName) {
	var lElement = getElement(pName);
	
	changeElementVisibility(pName, (lElement && isSet(lElement.style) && (lElement.style.display == 'none')));
}

function enableElement(pName)
{
	var lElement = getElement(pName);
	
	if (lElement && isSet(lElement.disabled))
	{
		if (inArray(lElement.tagName.toUpperCase(), ['TD']))
		{
			lElement.isCellDisabled = false;
			lElement.style.color = (isSet(lElement.oldColor) ? lElement.oldColor : '#000000');
		}	
		else
		{
			lElement.disabled = false;
			if (inArray(lElement.type, ['text']) && isSet(lElement.style))
			{
				lElement.style.backgroundColor = (isSet(lElement.oldBackgroundColor) ? lElement.oldBackgroundColor : '#FFFFFF');
				lElement.style.borderColor = (isSet(lElement.oldBorderColor) ? lElement.oldBorderColor : '#808080');
			}
		}
	}
}

function disableElement(pName)
{
	var lElement = getElement(pName);
	
	if (lElement && isSet(lElement.disabled))
	{
		if (inArray(lElement.tagName.toUpperCase(), ['TD']))
		{
			if (!isSet(lElement.isCellDisabled) || !lElement.isCellDisabled)
			{
				lElement.isCellDisabled = true;
				if (isSet(lElement.style.color)) lElement.oldColor = lElement.style.color;
				lElement.style.color = '#999999';
			}
		}
		else
		{
			if (inArray(lElement.type, ['text']) && !lElement.disabled)
			{
				if (isSet(lElement.style.backgroundColor)) lElement.oldBackgroundColor = lElement.style.backgroundColor;
				lElement.style.backgroundColor = '#EEEEEE';
				
				if (isSet(lElement.style.borderColor)) lElement.oldBorderColor = lElement.style.borderColor;
				lElement.style.borderColor = '#CCCCCC';
			}
			lElement.disabled = true;
		}
	}
}

function enableElements (pElementsArray) {
	
	for (var i in pElementsArray) {
		enableElement(pElementsArray[i]);
	}
}

function disableElements (pElementsArray) {
	
	for (var i in pElementsArray) {
		disableElement(pElementsArray[i]);
	}
}

function changeElementState(pName, pEnabled) {
	if (isSet(pEnabled) && pEnabled) {
		enableElement(pName);
	} else {
		disableElement(pName);
	}
}

function switchElementState(pName) {
	var lElement = getElement(pName);
	
	changeElementState(lElement && isSet(lElement.disabled) && (lElement.disabled == true));
}

function callElementMethod(pName, pMethod, pUseFireEvent)
{
	var lElement = getElement(pName);
	
	if (!isSet(lElement.dontTriggerEvents) || !lElement.dontTriggerEvents)
	{
		pMethod = pMethod.toLowerCase();
	
		if (lElement && isSet(lElement[pMethod])) {
			if (pUseFireEvent == true) {
				lElement.fireEvent(pMethod);
			} else {
				eval('getElement(pName).'+pMethod+'();');
			}
		}
	}
}

function callRSElementMethod(pRSName, pControlName, pMethod, pUseFireEvent) {
	lSections = eval("RS"+pRSName+"Sections");
	for (i=0; i< lSections.length; i++) {
		callElementMethod(pControlName+"____"+i, pMethod, pUseFireEvent)
	}
}

function getRSBaseControlName(pControlName) {
	lResult = pControlName;
	
	lRSAppendStrPos = lResult.indexOf("____");
	
	//if it is a repeating section expanded control name
	if (lRSAppendStrPos != -1) {
		lResult = lResult.substring(0, lRSAppendStrPos);
	}
	
	return lResult;
}

function callEventOnEntireForm(pForm, pEvent, pExcludeControls) {
	if (!isSet(pExcludeControls) || !isArray(pExcludeControls)) var pExcludeControls = [];
	if (isSet(pForm)) {
		var formElements = pForm.elements;
		for (var i=0; i<formElements.length; i++) {
			if (isSet(formElements[i][pEvent.toLowerCase()])) {
				if ( !inArray(getRSBaseControlName(formElements[i].id), pExcludeControls) && !inArray(getRSBaseControlName(formElements[i].name), pExcludeControls) && (!isSet(formElements[i].dontTriggerEvents) || !formElements[i].dontTriggerEvents)) {
					formElements[i].fireEvent(pEvent);
				}
			}
		}
	}
}

function callElementsMethod(pElements, pMethod) {
	var lElementName;
	
	if (isSet(pElements) && isArray(pElements)) {
		for (lElementName in pElements) {
			callElementMethod(lElementName, pMethod);
		}
	}
}

function cloneObject(what) {
  for (i in what) {
    if (typeof what[i] == 'object') {
       this[i] = new cloneObject(what[i]);
    } else {
       this[i] = what[i];
    }
  }
}

function makeElementVisible(pElement)
{
	switch (gBrowserInfo.type)
	{
		case gBrowserInfo.IE4:
		case gBrowserInfo.IE5:
			pElement.style.visibility = "visible";
			break;
			
		case gBrowserInfo.NS4:
			pElement.visibility = "show";
			break;
			
		case gBrowserInfo.NS6:
			pElement.style.visibility = "visible";
			break;
	}
}

function makeElementInvisible(pElement)
{
	switch (gBrowserInfo.type)
	{
		case gBrowserInfo.IE4:
		case gBrowserInfo.IE5:
			pElement.style.visibility = "hidden";
			break;
			
		case gBrowserInfo.NS4:
			pElement.visibility = "hide";
			break;
			
		case gBrowserInfo.NS6:
			pElement.style.visibility = "hidden";
			break;
	}
}

function moveElement(pElement, x, y)
{
	if ((gBrowserInfo.type == gBrowserInfo.IE4) || (gBrowserInfo.type == gBrowserInfo.IE5))
	{
		pElement.style.left = x;
		pElement.style.top = y;
	}
	else if (gBrowserInfo.type == gBrowserInfo.NS4)
	{
		pElement.left = x;
		pElement.top = y;
	}
	else if (gBrowserInfo.type == gBrowserInfo.NS6)
	{
		pElement.style.left = x + "px";
		pElement.style.top = y + "px";
	}
}

function appendEventHandlingCode(pObjectName, pEventName, pHandlingCode)
{
	pEventName = pEventName.toLowerCase();
	var lObject = getElement(pObjectName);
	lObject["handler_"+pEventName] = lObject[pEventName];
	eval(
		"lObject['"+pEventName+"'] = function(e, innerCall)" +
		"	{" +
		"		var lObject = getElement('"+pObjectName+"');" +
		"		if (lObject['handler_"+pEventName+"'] && !isSet(innerCall))" +
		"		{" +
		"			lObject['handler_"+pEventName+"'](e, true);" +
		"		}" +
		"		" + pHandlingCode + ";" +
		"	};"
	);
}


/**
 * Copy the content of an anchor to clipboard
 *
 * @version		1.0
 *
 */
function copy2Clipboard(pElement) {
    var holdtext = document.all['holdtext'];
    holdtext.innerText = pElement.innerText;
    Copied = holdtext.createTextRange();
    Copied.execCommand("Copy");
    // alert('The address was copied to the clipboard.');
}

function CopyElement2Clipboard(pElement, pLabel, pShowAlert) {
    if (!getElement('holdtext')) {
        holdtext = document.createElement('TEXTAREA');
    }
    if (pElement.innerText != '') {
        holdtext.innerText = pElement.innerText;
    } else {
        holdtext.innerText = ' ';
    }
	Copied = holdtext.createTextRange();
	Copied.execCommand("Copy");
	if (isSet(pLabel) && pLabel && pShowAlert) {
		// alert('The '+pLabel+' was copied to the clipboard.');
	} else if (pShowAlert) {
		// alert('Copied to the clipboard.');
	} else {
		return true;
	}
}

function transferControlValues(pRemapArray) {
	var lResultArray = new Object(), lElement;
	
	if (isSet(pRemapArray) && isArray(pRemapArray)) {
		for (lElement in pRemapArray) {
			lResultArray[lElement] = getElementValue(pRemapArray[lElement]);
		}
	}
	
	return lResultArray;
}

/**
 * base64 constants
 *
 */
var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var base64DecodeChars = new Array(
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);

/**
 * Do a base64 encoding
 *
 */
function base64encode(str) {
    var out, i, len;
    var c1, c2, c3;

    len = str.length;
    i = 0;
    out = "";
    while(i < len) {
	c1 = str.charCodeAt(i++) & 0xff;
	if(i == len)
	{
	    out += base64EncodeChars.charAt(c1 >> 2);
	    out += base64EncodeChars.charAt((c1 & 0x3) << 4);
	    out += "==";
	    break;
	}
	c2 = str.charCodeAt(i++);
	if(i == len)
	{
	    out += base64EncodeChars.charAt(c1 >> 2);
	    out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
	    out += base64EncodeChars.charAt((c2 & 0xF) << 2);
	    out += "=";
	    break;
	}
	c3 = str.charCodeAt(i++);
	out += base64EncodeChars.charAt(c1 >> 2);
	out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
	out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
	out += base64EncodeChars.charAt(c3 & 0x3F);
    }
    return out;
}

/**
 * Do a base64 decoding
 *
 */
function base64decode(str) {
    var c1, c2, c3, c4;
    var i, len, out;

    len = str.length;
    i = 0;
    out = "";
    while(i < len) {
	/* c1 */
	do {
	    c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
	} while(i < len && c1 == -1);
	if(c1 == -1)
	    break;

	/* c2 */
	do {
	    c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
	} while(i < len && c2 == -1);
	if(c2 == -1)
	    break;

	out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));

	/* c3 */
	do {
	    c3 = str.charCodeAt(i++) & 0xff;
	    if(c3 == 61)
		return out;
	    c3 = base64DecodeChars[c3];
	} while(i < len && c3 == -1);
	if(c3 == -1)
	    break;

	out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));

	/* c4 */
	do {
	    c4 = str.charCodeAt(i++) & 0xff;
	    if(c4 == 61)
		return out;
	    c4 = base64DecodeChars[c4];
	} while(i < len && c4 == -1);
	if(c4 == -1)
	    break;
	out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
    }
    return out;
}

/**
 * Format IDs
 *
 * Needed in groups -  for multiple select popups
 *
 * Receive an array an format the ids in the array by separating them with :
 * The result is passed to the main window url.
 *
 */
function groups_FormatIDs (pData, pIdName) {
    var lRes = "";
    for (var i=0; i<pData.length; i++) {
        lRes = lRes + pData[i][pIdName] + ":";
    }
    return lRes;
}

/**
 * Format IDs
 *
 * Receive an array an format the ids in the array by separating them with :
 * The result is passed to the main window url.
 *
 */
function multiSelectPopUp_FormatIDs (pData, pIdName) {
    var lRes = "";
    for (var i=0; i<pData.length; i++) {
        lRes = lRes + pData[i][pIdName] + ":";
    }
    return lRes;
}

String.prototype.trim = function() {
  return(this.replace(/^\s+/,'').replace(/\s+$/,''));
}


function removeDOMelement(pName) {
	if (getElement(pName)) {
		getElement(pName).parentNode.removeChild(getElement(pName));
	}
}

function getBrowserType(){
  if (document.layers) return "NS";
  if (document.all) {
		// But is it really IE?
		// convert all characters to lowercase to simplify testing
		var agt=navigator.userAgent.toLowerCase();
		var is_opera = (agt.indexOf("opera") != -1);
		var is_konq = (agt.indexOf("konqueror") != -1);
		if(is_opera) {
			return "OPR";
		} else {
			if(is_konq) {
				return "KONQ";
			} else {
				// Really is IE
				return "IE";
			}
		}
  }
  if (document.getElementById) return "MOZ";
  return "OTHER";
}

function js_in_array (the_needle, the_haystack) {
    var res = false;
    var i = 0;
    while (the_haystack[i] != undefined) {
        if (the_haystack[i] == the_needle) {
            res = true;
            break;
        }
        i++;
    }
    return res;
}    

function checkDateSet (pTimeCtrlName, pStartDateCtrlName, pStartTimeCtrlName, pFinishDateCtrlName, pFinishTimeCtrlName) {
	
	if (pTimeCtrlName == pStartTimeCtrlName) {
		if (getElementValue(pStartDateCtrlName) == '' || getElementValue(pStartDateCtrlName) == undefined) {
			return false;
		} else {
			return true;
		}
	} else if (pTimeCtrlName == pFinishTimeCtrlName) {
		if (getElementValue(pFinishDateCtrlName) == '' || getElementValue(pFinishDateCtrlName) == undefined) {
			return false;
		} else {
			return true;
		}
	}
}

function setGap (pStartDate, pStartTime, pFinishDate, pFinishTime) {
	// If we have at least dates set, get the gap
	if (getElementValue(pStartDate) != '' && getElementValue(pFinishDate) != '') {			
		startDateValue 	= getElementValue(pStartDate);			
		startHoursValue = getElementValue(pStartTime + '_hrs');
		startMinutes		=	getElementValue(pStartTime + '_min');
		startAmPm				= getElementValue(pStartTime + '_ind');
				
		finishDateValue 	= getElementValue(pFinishDate);	
		finishHoursValue  = getElementValue(pFinishTime + '_hrs');
		finishMinutes			=	getElementValue(pFinishTime + '_min');
		finishAmPm				= getElementValue(pFinishTime + '_ind');
		
		if (startHoursValue != '' && finishHoursValue == '') {
			gGapTimestamp = 0;
		}
		else {				
			if (startHoursValue == '') {
				startHoursValue = 0;
			}		
			
			if (startMinutes == '') {
				startMinutes = 0;
			}		
			
			if (finishHoursValue == '') {
				finishHoursValue = 0;
			}		
			
			if (finishMinutes == '') {
				finishMinutes = 0;
			}				
		
			var StartDateTime 	= new Date(startDateValue + ' ' + startHoursValue + ':' + startMinutes + ' ' + startAmPm);
			var FinishDateTime 	= new Date(finishDateValue + ' ' + finishHoursValue + ':' + finishMinutes + ' ' + finishAmPm);		
									
			gGapTimestamp = FinishDateTime.getTime() - StartDateTime.getTime();		
		}			
	}
	else {
		gGapTimestamp = 0;
	}
}

/**
 * Check Time & Date Dependencies
 *
 * This function is used in the common time and date controls to test the dependencies between them
 * 
 * @param		string		The name of the StartDate Control
 * @param		string		The name of the StartTime Control
 * @param		string		The name of the FinishDate Control
 * @param		string		The name of the FinishTime Control
 * @param		string		The name of the TimeZone Control
 * @param		string		The name of the control from which the onchange event was triggered
 * @param		string		The exact name of the control from which the onchange event was triggered (with _hrs, _min ... suffixes)
 *
 * @return 		void
 *
 * @version		2.2		
 *
 */

var gStopCascadeUpdates = false; 
 
function startFinishDependenciesManage (pStartDate, pStartTime, pFinishDate, pFinishTime, pTimeZone, pTriggeredFrom, pSubTrigger) {	
		if (gStopCascadeUpdates) {
			return ;
		}
		
		gStopCascadeUpdates = true;	
			
		var doOnlyDatesUpdate = false;
	
		// take all elements
		var lStartDate 		= getElement(pStartDate);
    var lStartTimeHrs = getElement(pStartTime+'_hrs');
    var lStartTimeMin = getElement(pStartTime+'_min');
    var lStartTimeInd = getElement(pStartTime+'_ind');
    
    var lFinishDate 	 = getElement(pFinishDate);
    var lFinishTimeHrs = getElement(pFinishTime+'_hrs');
    var lFinishTimeMin = getElement(pFinishTime+'_min');
    var lFinishTimeInd = getElement(pFinishTime+'_ind');    

    // if the user set the start date and is valid date and finish date is empty or it's not valid date, set it.
    if (pTriggeredFrom == pStartDate && isValidDate(lStartDate.value) && (lFinishDate.value == '' || !isValidDate(lFinishDate.value))) {
     	lFinishDate.value = lStartDate.value;
    }
    
    // if the user set the end date and is valid date and start date is empty or it's not valid date, set it.
    if (pTriggeredFrom == pFinishDate && isValidDate(lFinishDate.value) && (lStartDate.value == '' || !isValidDate(lStartDate.value))) {
     	lStartDate.value = lFinishDate.value;
    }            
 
    // maybe we should set the date to today, instead of this
    // Do not allow StartTime if there is no StartDate    
    if ((lStartTimeHrs.value != '' || lStartTimeMin.value != '' || lStartTimeInd.value != 'AM') && !isValidDate(lStartDate.value)) {    
    	lStartTimeHrs.value = '';
      lStartTimeMin.value = '';
    	lStartTimeInd.value = 'AM';
    }    
    
    if ((lFinishTimeHrs.value != '' || lFinishTimeMin.value != '' || lFinishTimeInd.value != 'AM') && !isValidDate(lFinishDate.value)) {    
    	lFinishTimeHrs.value = '';
      lFinishTimeMin.value = '';
    	lFinishTimeInd.value = 'AM';
    }   
    
    // if the event is triggered by the start time hours and it's empty, probably the user wants to remove the start and end time.
    if ((lStartTimeHrs.value == '' && pSubTrigger == pStartTime+'_hrs') || (lFinishTimeHrs.value == '' && pSubTrigger == pFinishTime+'_hrs')) {
    	lStartTimeHrs.value = '';
      lStartTimeMin.value = '';
    	lStartTimeInd.value = 'AM';
    	
    	lFinishTimeHrs.value = '';
      lFinishTimeMin.value = '';
    	lFinishTimeInd.value = 'AM';    	    	    	
    }        
    // end if the event is triggered by the start time hours and it's empty, probably the user wants to remove the start and end time.    
    
    if (lStartTimeHrs.value == '' && lStartTimeMin.value == '' && lStartTimeInd.value == 'AM' && !isValidDate(lStartDate.value)) {
    	gStopCascadeUpdates = false;
    	return;    	
    }     

    // create the dates objects
		startDateValue 	= getElementValue(pStartDate);			
		startHoursValue = getElementValue(pStartTime + '_hrs');
		startMinutes		=	getElementValue(pStartTime + '_min');
		startAmPm				= getElementValue(pStartTime + '_ind');
				
		finishDateValue 	= getElementValue(pFinishDate);	
		finishHoursValue  = getElementValue(pFinishTime + '_hrs');
		finishMinutes			=	getElementValue(pFinishTime + '_min');
		finishAmPm				= getElementValue(pFinishTime + '_ind');	
		
		if (startHoursValue == '' && finishHoursValue == '') {
			doOnlyDatesUpdate = true;
		}	
		
		if (startHoursValue == '') {
			startHoursValue = 0;
		}		
		
		if (startMinutes == '') {
			startMinutes = 0;
		}		
		
		if (finishHoursValue == '') {
			finishHoursValue = 0;
		}		
		
		if (finishMinutes == '') {
			finishMinutes = 5;
		}				    
        
		var StartDateTime 	= new Date(startDateValue + ' ' + startHoursValue + ':' + startMinutes + ' ' + startAmPm);
		var FinishDateTime 	= new Date(finishDateValue + ' ' + finishHoursValue + ':' + finishMinutes + ' ' + finishAmPm);
						
		if (startHoursValue != 0 && finishHoursValue == 0) {						
			FinishDateTime.setTime(StartDateTime.getTime() + 60*60*1000 + gGapTimestamp);			
		}		
		// if finish date + time is less then start time
		else if (StartDateTime.getTime() >= FinishDateTime.getTime()) {
			if (pSubTrigger == pFinishTime+'_hrs') {					
				if (StartDateTime.getHours() == FinishDateTime.getHours()) {
					FinishDateTime.setTime(FinishDateTime.getTime() + 1000*15*60);						
				}								
				else if (startAmPm == 'AM') {
					FinishDateTime.setTime(FinishDateTime.getTime() + 1000*12*60*60);					
				}		
				else {
					// just return the old gap
					FinishDateTime.setTime(StartDateTime.getTime() + gGapTimestamp);							
				}
			}
			else {
				// just return the old gap
				FinishDateTime.setTime(StartDateTime.getTime() + gGapTimestamp);		
			}
		}          
		else {						
			if (pSubTrigger == pStartDate || pSubTrigger == (pStartTime + '_hrs') || pSubTrigger == (pStartTime + '_min') || pSubTrigger == (pStartTime + '_ind')) {
				FinishDateTime.setTime(StartDateTime.getTime() + gGapTimestamp);				
			}						
		}
		
	if (true) {
					
		// Get the parts of the Date objects and put them in our controls
		
		// Start Time Year
		var STYear = StartDateTime.getFullYear();
		// Start Time Month
		var STMonth = StartDateTime.getMonth();
		STMonth++;
		if (STMonth < 10) {
			STMonth = '0' + STMonth;
		}
		// Start Time Date
		var STDate = StartDateTime.getDate();
		if (STDate < 10) {
			STDate = '0' + STDate;
		}
				
		// Start Time Hours
		var STHours = StartDateTime.getHours();
		if (STHours > 11) {
			if (!doOnlyDatesUpdate) {
				setElementValue(pStartTime + '_ind', 'PM', -1);
			}
		} else {
			if (!doOnlyDatesUpdate) {
				setElementValue(pStartTime + '_ind', 'AM', -1);
			}
		}
		if (STHours == 0) {
			STHours = '12';
		} else if (STHours < 10) {
			STHours = '0' + STHours;
		} else if (STHours < 13) {
			STHours = STHours;
		} else if (STHours > 12 && STHours < 22) {
			STHours = '0' + (STHours - 12);
		} else if (STHours > 21) {
			STHours = STHours - 12;
		}
		// Start Time Minutes
		var STMinutes = StartDateTime.getMinutes();
		if (STMinutes < 10) {
			STMinutes = '0' + STMinutes;
		}
		
		// Set the values for Start Controls
		if (isValidDate(STMonth + '/' + STDate + '/' + STYear)) {
			setElementValue(pStartDate, STMonth + '/' + STDate + '/' + STYear, -1);
		} else {
			setElementValue('', -1);
		}
		//alert('Start Time Hours: ' + STHours);
		//alert('Start Time Minutes: ' + STMinutes);
		if (!doOnlyDatesUpdate) {
			setElementValue(pStartTime + '_hrs', STHours, -1);
			setElementValue(pStartTime + '_min', STMinutes, -1);
		}

		// Finish Time Year
		var FTYear = FinishDateTime.getFullYear();
		// Finish Time Month
		var FTMonth = FinishDateTime.getMonth();
		FTMonth++;
		if (FTMonth < 10) {
			FTMonth = '0' + FTMonth;
		}
		// Finish Time Date
		var FTDate = FinishDateTime.getDate();
		if (FTDate < 10) {
			FTDate = '0' + FTDate;
		}
		// Finish Time Hours
		var FTHours = FinishDateTime.getHours();
		if (FTHours > 11) {
			setElementValue(pFinishTime + '_ind', 'PM');
		} else {
			setElementValue(pFinishTime + '_ind', 'AM');
		}
		if (FTHours == 0) {
			FTHours = '12';
		} else if (FTHours < 10) {
			FTHours = '0' + FTHours;
		} else if (FTHours < 13) {
			FTHours = FTHours;
		} else if (FTHours > 12 && FTHours < 22) {
			FTHours = '0' + (FTHours - 12);
		} else if (FTHours > 21) {
			FTHours = FTHours - 12;
		}
		// Finish Time Minutes
		var FTMinutes = FinishDateTime.getMinutes();
		if (FTMinutes < 10) {
			FTMinutes = '0' + FTMinutes;
		}
		
		// Set the values for Finish Controls
		if (isValidDate(FTMonth + '/' + FTDate + '/' + FTYear)) {
			setElementValue(pFinishDate,  FTMonth + '/' + FTDate + '/' + FTYear, -1);
		} else {
			setElementValue(pFinishDate,  '', -1);
		}
		//alert('Finish Time Hours: ' + FTHours);
		//alert('Finish Time Minutes: ' + FTMinutes);
		if (!doOnlyDatesUpdate) {
			setElementValue(pFinishTime + '_hrs', FTHours, -1);
			setElementValue(pFinishTime + '_min', FTMinutes, -1);
		}
	}

		// Show/Hide TimeZone Control
    if (pTimeZone != '') {
        manageControlVisibility((getElementValue(pStartDate) != '' || getElementValue(pFinishDate) != ''), 'def1', pTimeZone);
    }
    setGap (pStartDate, pStartTime, pFinishDate, pFinishTime);

    gStopCascadeUpdates = false;
}

function isValidDate (pDate) {
    
    var lSeparators = new Array (".", "/", "\\", "-");
        
    var lSep1 = pDate.substr(2, 1);
    var lSep2 = pDate.substr(5, 1);
        
    if (inArray(lSep1, lSeparators, false) && inArray(lSep2, lSeparators, false)) {
        return true;
    } else {
        return false;
    }
}


function days_between(pStartDate, pEndDate) {
  var ONE_DAY = 1000 * 60 * 60 * 24;

  var date1 = new Date(pStartDate.substr(pStartDate.lastIndexOf('/')+1,4), (Number(pStartDate.substr(0,pStartDate.indexOf('/'))) - 1), pStartDate.substr(pStartDate.indexOf('/')+1,(pStartDate.lastIndexOf('/')-pStartDate.indexOf('/')-1)));
  var date2 = new Date(pEndDate.substr(pEndDate.lastIndexOf('/')+1,4), (Number(pEndDate.substr(0,pEndDate.indexOf('/')))-1), pEndDate.substr(pEndDate.indexOf('/')+1,(pEndDate.lastIndexOf('/')-pEndDate.indexOf('/')-1)));
  var date1_ms = date1.getTime();
  var date2_ms = date2.getTime();

  // Calculate the difference in milliseconds
  var difference_ms = date2_ms - date1_ms;

  // Convert back to days and return
  return Math.round(difference_ms/ONE_DAY);
}

function gSetReq (pSetReq, pElement) {
    if (pSetReq) {
        pElement.className = 'reqtd';
    } else {
        pElement.className = 'normaltd';
    }
}

function gCalcDuration (pStartDate, pStartTimeHours, pStartTimeMinutes, pStartTimeInd, pEndDate, pEndTimeHours, pEndTimeMinutes, pEndTimeInd, pConcatText) {

    var ONE_HOUR = 1000 * 60 * 60;
    var lError = false;
    var lRes = '';
    
    var lStartDay = Number(pStartDate.substr(pStartDate.indexOf('/')+1,(pStartDate.lastIndexOf('/')-pStartDate.indexOf('/')-1)));
    var lStartMonth = Number(pStartDate.substr(0,pStartDate.indexOf('/')));
    var lStartYear = Number(pStartDate.substr(pStartDate.lastIndexOf('/')+1,4));
    
    if (lStartDay < 1 || lStartDay > 31) {
        lError = true;
    } else if (lStartMonth < 1 || lStartMonth > 12) {
        lError = true;
    } else if (lStartYear < 1970 || lStartYear > 2030) {
        lError = true;
    }
    
    if (pStartTimeHours == '') {
        lError = true;
    }

    var lEndDay = Number(pEndDate.substr(pEndDate.indexOf('/')+1,(pEndDate.lastIndexOf('/')-pEndDate.indexOf('/')-1)));
    var lEndMonth = Number(pEndDate.substr(0,pEndDate.indexOf('/')));
    var lEndYear = Number(pEndDate.substr(pEndDate.lastIndexOf('/')+1,4));

    if (lEndDay < 1 || lEndDay > 31) {
        lError = true;
    } else if (lEndMonth < 1 || lEndMonth > 12) {
        lError = true;
    } else if (lEndYear < 1970 || lEndYear > 2030) {
        lError = true;
    }

    if (pEndTimeHours == '') {
        lError = true;
    }
    
    if (!lError) {
        
        // convert to 24h format
        if (pStartTimeInd == 'PM' && pStartTimeHours != '12') {
            var lStartHours = Number(Number(pStartTimeHours) + 12);
        } else if ((pStartTimeInd == 'AM' && pStartTimeHours != '12') || (pStartTimeInd == 'PM' && pStartTimeHours == '12')) {
            var lStartHours = Number(pStartTimeHours);
        } else if (pStartTimeInd == 'AM' && pStartTimeHours == '12') {
            var lStartHours = 0;
        }

        // convert to 24h format
        if (pEndTimeInd == 'PM' && pEndTimeHours != '12') {
            var lEndHours = Number(Number(pEndTimeHours) + 12);
        } else if ((pEndTimeInd == 'AM' && pEndTimeHours != '12') || (pEndTimeInd == 'PM' && pEndTimeHours == '12')) {
            var lEndHours = Number(pEndTimeHours);
        } else if (pEndTimeInd == 'AM' && pEndTimeHours == '12') {
            var lEndHours = 0;
        }

        var lStartMinutes = Number(pStartTimeMinutes);
        var lEndMinutes = Number(pEndTimeMinutes);
        
        var lStartDate = new Date(lStartYear, lStartMonth, lStartDay, lStartHours, lStartMinutes);
        var lEndDate = new Date(lEndYear, lEndMonth, lEndDay, lEndHours, lEndMinutes);
                
        var lDuration = parseFloat((lEndDate.getTime() - lStartDate.getTime()) / ONE_HOUR);
        
        lDuration = lDuration.toFixed(2);
        
        lRes = lDuration + pConcatText;        
    }
    
    return lRes;
}

function removeValueFromArray(pArray, pValue) {
	if (!isSet(pArray) || !isArray(pArray)) {
		return false;
	}
	
	var lValueRemoved;
	
	do {
		lValueRemoved = false;
		for(var i=0; i<pArray.length; i++) {
			if (pArray[i] == pValue) {
				pArray.splice(i,1);
				lValueRemoved = true;
				break;
			}
		}	
	} while (lValueRemoved);
	
	return pArray;
}

/**
 * Append value to element
 * 
 * @param		string		name of the element
 * @param		mixed		value to append
 * @param		integer		how to deal with onChange method
 * @return		void
 *
 * @version		1.0
 */

 function appendElementValue(pElName, pNewValue, pValuesSeparator, pOnChangeTriggerMethod, pCondition) {
	
	var lOldValue = getElementValue(pElName);
	
	var lNewValue = lOldValue;
	
	if (lNewValue != '') {
		lNewValue = lNewValue + pValuesSeparator;
	}
	
	lNewValue = lNewValue + pNewValue;
	
	setElementValue(pElName, lNewValue, pOnChangeTriggerMethod, pCondition);
}


function cookieTime(hours){
	var now = new Date();
	var exp = new Date();
	var x = Date.parse(now) + hours*60*60*1000;
	exp.setTime(x);
	str = exp.toUTCString();
	re = '/(\d\d)\s(\w\w\w)\s\d\d(\d\d))/';
	return str.replace(re,"$1-$2-$3");
}
 
function setCookie (id, value, hours) {
	document.cookie = id+'='+value+';path=/;expires='+cookieTime(hours);
}
 

function getCookie (id, defaultValue ) {
	var re = new RegExp(id+'=(.*)');
	var value = re.exec(document.cookie);
	return (value) ? value[1].split(';')[0] : defaultValue;
}
