/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 

function IsIE()
{
	return navigator.appName.indexOf("Internet Explorer") != -1;
}

function UserPrompt( instructions, value)
{
	var result = prompt(instructions, value);
	if(result == undefined && IsIE())
		alert('Please enable user prompts (see "scripted windows" notice above)');
	return result;
}

function doBrowserCheck(appName)
{
    var browsers = [	{match: "MSIE ", 		minVersion:  6.0, 	name:  "Internet Explorer 6.0"},
                        {match: "NETSCAPE/",	minVersion:  7.1,  	name:  "Netscape 7.1"},
                        {match: "FIREFOX/",		minVersion:  1.5,	name:  "Firefox 1.5"},
                        {match: "CHROME/",      minVersion:  5.0,  	name:  "Chrome 5.0"} ];

    var userAgent = navigator.userAgent.toUpperCase();
    var browserNames = "";
    for(var n=0;  n < browsers.length;  n++) {
        var match = browsers[n].match;
        var k = userAgent.indexOf(match) + match.length;
        if(k > match.length && parseFloat(userAgent.substring(k,k+3)) >= browsers[n].minVersion)
            return null;
        browserNames += browsers[n].name + ", ";
    }

    return "Your browser is not compatible with " + appName + ". Compatible browsers include <br/>" +
           browserNames + "and later versions of each.";
    // + "<br/>The browser signature is: " + navigator.userAgent;
}

//---------------------------------------------------------------------------
//	Augment the built in String type with some convenience methods
//---------------------------------------------------------------------------
String.prototype.contains = function(string)
{
	return this.indexOf(string) != -1;
}

var trimRegex;
String.prototype.trim = function()
{
	if(!trimRegex)
		trimRegex = /^[\s\r\n]*(.*?)[\s\r\n]*$/;
	return this.replace(trimRegex, "$1");
}

String.prototype.compareToIngoreCase = function(string)
{
	var a = this.toLowerCase();
	var b = string.toLowerCase();
	return (a == b) ? 0 : (a < b ? -1 : 1);
}

String.prototype.startsWith = function(string)
{
	return this.indexOf(string) == 0;
}

String.prototype.ucFirstLetter = function()
{
	return this.substring(0,1).toUpperCase() + this.substring(1);
}
//---------------------------------------------------------------------------
String.prototype.truncate = function(limit, termination, breakChars)
{
	if(this == null || this == "" || this.length <= limit)
		return this;

	if(typeof termination == "undefined")
		termination = "...";

	var substringLength = limit - termination.length;

    if((breakChars != null) && (breakChars.length > 0))
    {
        while(substringLength > 0)
        {
            var chr = this.charAt(substringLength);
            if(breakChars.indexOf(chr) >= 0)
                break;
            substringLength--;
        }
    }
	if(substringLength < 0)
		return this;

	return this.substring(0,substringLength) + termination;
}

//---------------------------------------------------------------------------
//  Set the first character of a string to lower case or upper case
//---------------------------------------------------------------------------
function SetFirstCharToUC(string)
{
	if(!string)
		return string;
	return string.substring(0,1).toUpperCase() + string.substring(1);
}

function SetFirstCharToLC(string)
{
	if(!string)
		return string;
	return string.substring(0,1).toLowerCase() + string.substring(1);
}

//---------------------------------------------------------------------------
//	MakeEmptyWindow:
//---------------------------------------------------------------------------
function MakeEmptyWindow(url, dialogWinName)    // returns the window object
{
	if(url.indexOf("/Dialog/S/") >= 0)
		return MakePopupWindow(dialogWinName, 0, 250, null);

	if(url.indexOf("/Dialog/") >= 0)
		return MakePopupWindow(dialogWinName);

	return MakeNewWindow("", "W"+ new Date().getTime());
}

//---------------------------------------------------------------------------
function NewWindow(url, winName)    // returns the window name
{
    var win = MakeNewWindow(url, winName);
    return win ? win.name : null;
}

function MakeNewWindow(url, winName)    // returns the window object
{
	var newWindow = null;
	if(winName) {
		newWindow = window.open( url, winName );
        if(newWindow)
            newWindow.focus();
    }
	else
		newWindow = window.open( url );

    if(null == newWindow)
        alert("Please enable popup windows in your browser.");

	return newWindow;
}

//---------------------------------------------------------------------------

function PopupWindow(winName, width, height, url)    // returns the window name
{
    var win = MakePopupWindow(winName, width, height, url);
    return win ? win.name : null;
}

function MakePopupWindow(winName, width, height, url)    // returns the window object
{
	var wWidth  = Math.min(width  ? width  : 600, window.screen.availWidth-10);
	var wHeight	= Math.min(height ? height : 500, window.screen.availHeight-40);
	wLeft 		= (window.screen.availWidth  - wWidth)/2;
	wTop 		= (window.screen.availHeight - wHeight)/2;
	winName 	= winName.replace(/ /g,"");
	attribs		= "width=" + wWidth + ",height=" + wHeight + ",top=" + wTop + ",left=" + wLeft;
	attribs		= attribs + ",screenX=" + wLeft + ",screenY=" + wTop + ", location=0, menubar=0, resizable=1, scrollbars=1";
	var newWindow = window.open(url ? url : "", winName, attribs);
    
    if(newWindow)
        newWindow.focus();
    else
        alert("Please enable popup windows in your browser.");
    
    return newWindow;
}

//---------------------------------------------------------------------------
function GetDefined( value, defaultValue )
{
	return typeof value == 'undefined' ? defaultValue : value;
}

//---------------------------------------------------------------------------
function GetString( value, defaultValue ) {
	return typeof value == 'undefined' ? defaultValue : value;
}

//---------------------------------------------------------------------------
function GetElement( id ) {
	if( document.getElementById )
		x = document.getElementById(id);
	else
		x = document.all[id];

	if( !x ) {
		alert( "GetElement:  Coudn't find element " + id );
		return "";
	}
	return x;
}

//---------------------------------------------------------------------------
function GetValue( id )
{
	if( document.getElementById )
		x = document.getElementById(id);
	else
		x = document.all[id];

	if( !x ) {
		alert( "GetValue:  Coudn't find element " + id );
		return "";
	}

	return x.value;
}

//---------------------------------------------------------------------------
function SetValue( id, value )
{
	if( document.getElementById )
		x = document.getElementById(id);
	else
		x = document.all[id];

	if( !x ) {
		alert( "GetValue:  Coudn't find element " + id );
		return "";
	}

	x.value = value;
}

//---------------------------------------------------------------------------
function GetHtml( id )
{
	if( document.getElementById )
		x = document.getElementById(id);
	else
		x = document.all[id];

	if( !x )
		alert( "SetHtml:  Coudn't find element " + id );
	return x.innerHTML;
}

//---------------------------------------------------------------------------
function SetHtml( id, html )
{
	if( document.getElementById )
		x = document.getElementById(id);
	else
		x = document.all[id];

	if( !x )
		alert( "SetHtml:  Coudn't find element " + id );
	else
		x.innerHTML = html;
}

//---------------------------------------------------------------------------
function SetText( id, html )
{
	if( document.getElementById )
		x = document.getElementById(id);
	else
		x = document.all[id];

	if( !x )
		alert( "SetText:  Coudn't find element " + id );
	else
		x.innerText = html;
}

//---------------------------------------------------------------------------
function SetCheckboxes( form, value )
{
	if( !value || value != 1 )
		value = 0;

 	for( var n=0;  n < form.elements.length; n++ ) {
  		var element = form.elements[n];
  		if( element.type.substring(0,3).toLowerCase() == "che"  )
   			element.checked = value;
	}
}

/******************************************************************************
ToStringArray: Return a boolean value telling whether the first argument is an array
******************************************************************************/
function ToStringArray( stringOrArray ) {
	if( typeof stringOrArray == "undefined" )
		return [];

	if(IsString(stringOrArray))
		return [stringOrArray];

	if( !IsString(stringOrArray[0]) )
		alert( "ToStringArray given non-string data" );

	return stringOrArray;
}

/******************************************************************************
IsObject: Return a boolean value telling whether the argument is an object
******************************************************************************/
function IsObject( arg ) {
	return  (typeof arg) == 'object';
}

/******************************************************************************
IsString: Return a boolean value telling whether the first argument is a string
******************************************************************************/
function IsString( arg ) {
	if (typeof arg == 'string')
		return true;

	if (typeof arg == 'object') {
  		var criterion = arg.constructor.toString().match(/string/i);
   		return (criterion != null);
  	}
	return false;
}

/******************************************************************************
IsArray: Return a boolean value telling whether the first argument is an array
******************************************************************************/
function IsArray( arg ) {
	if (typeof arg == 'object') {
  		var criterion = arg.constructor.toString().match(/array/i);
   		return (criterion != null);
  	}
	return false;
}

/******************************************************************************
WriteButtonGroup:
******************************************************************************/
function WriteButtonGroup(){
	document.write( CreateButtonGroup(arguments) );
}

/******************************************************************************
CreateButtonGroup:
******************************************************************************/
function CreateButtonGroup(args, isStdButtons) {
	isStdButtons = GetDefined(isStdButtons, true);
	if( args.length == 1)
		args=arguments;

	var doButton = args[0];
	var html = '<TABLE class="' + (isStdButtons ? 'stdButtons' : 'buttons') + '" + cellspacing="10px"><TR>\n';

	for(var n=1;  n < args.length;  n+=2) {
		var caption = args[n];
		var cmd = args[n+1];
		var type = "button";
		if(caption.charAt(0) == '!') {
			caption = caption.substring(1);
			type = "submit";
		}
		if(cmd.charAt(0) == '!') {
			cmd = cmd.substring(1);
			type = "submit";
		}

		if(true)
			html = html + '<TD><INPUT type=' + type + ' value="'+ caption +
					'" onClick="Javascript:' + doButton + '(\'' + cmd + '\');return false;"</INPUT></TD>\n';
		else
			html = html + '<TD nowrap><A href="Javascript:' + doButton + '(\'' +
						cmd + '\')">' + caption + '</A></TD>\n';
	}
	html = html + '</TR></TABLE>';
	return html;
}

/******************************************************************************
UrlEncode:  UrlEncode the string, protecting characters not escaped by
            Javascript's escape() function
******************************************************************************/

var hex 		= new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
             		 'A', 'B', 'C', 'D', 'E', 'F');

var unsafeChrs	= " \"%\\^`+$,&?";	// Must escape the space due to Tomcat 3.2.3 processing problems.

function UrlEncode(string) {
	var newString  = new Array(3*string.length);
	var charCount = 0;

    for( i=0; i < string.length; i++ )  {
    	var chr = string.charAt(i);
    	var num = chr.charCodeAt(0);
		if(num < 255)  {
			if(unsafeChrs.indexOf(chr) == -1 && num > 32 && num < 123)
				newString[charCount++] = chr;
			else {
				newString[charCount++] = '%';
				newString[charCount++] = hex[Math.floor(num / 16)];
				newString[charCount++] = hex[num % 16];
			}
		}
		else	// We don't handle unicode chars of the form %uXXXX
			alert("Found a non-ISO-8859-1 character in string:   " + string);
	}

    return newString.slice(0,charCount).join('');
}

//***********************************************************************************************************
// Standard formatting of date/time stamps
//***********************************************************************************************************

function FormatDate(dateTimeStamp, format) {
    if(dateTimeStamp == null)
        return "";
    if(format)
        format = format.toLowerCase();
    dateTimeStamp = dateTimeStamp.trim();
    if (dateTimeStamp.indexOf("/") > 0)
        return dateTimeStamp;
    else if((dateTimeStamp.length == 14) || (dateTimeStamp.length == 8)) {
        var year = dateTimeStamp.substring(0,4);
        var month = dateTimeStamp.substring(4,6);
        var day = dateTimeStamp.substring(6,8);
        switch(format) {
            case "dmy":
                return day + '/' + month + '/' + year;
            case "ymd":
                return year + '/' + month + '/' + day;
            case "mdy":
            default:
                return month + '/' + day + '/' + year;
        }
    }
    else if(dateTimeStamp.length == 6) {
        var year = dateTimeStamp.substring(0,4);
        var month = dateTimeStamp.substring(4,6);
        switch(format) {
            case "ymd":
                return year + '/' + month;
            default:
                return month + '/' + year;
        }
    }
    else
        return dateTimeStamp;
}

function FormatTime(dateTimeStamp) {
    if(dateTimeStamp == null)
        return "";
    dateTimeStamp = dateTimeStamp.trim();
    if(dateTimeStamp.length == 14)
        return dateTimeStamp.substring(8,10) + ':' + dateTimeStamp.substring(10,12) + ':' + dateTimeStamp.substring(12,14);
    else
        return "";
}

function FormatDateTime(dateTimeStamp, format) {
    if(dateTimeStamp == null)
        return "";
    if(format)
        format = format.toLowerCase();
    dateTimeStamp = dateTimeStamp.trim();
    if(dateTimeStamp.length == 14) {
        var year = dateTimeStamp.substring(0,4);
        var month = dateTimeStamp.substring(4,6);
        var day = dateTimeStamp.substring(6,8);
        switch(format) {
            case "dmy":
                var date = day + '/' + month + '/' + year;
            case "ymd":
                var date = year + '/' + month + '/' + day;
            case "mdy":
            default:
                var date = month + '/' + day + '/' + year;
        }
        return date + '&nbsp;&nbsp;'
                + dateTimeStamp.substring(8,10) + ':' + dateTimeStamp.substring(10,12) + ':' + dateTimeStamp.substring(12,14);
    }
    else
        return dateTimeStamp;
}

function ParseDate(value) {
    if(value == null)
        return "";
    // remove '/' characters from date string & put into standard format
    var i = value.indexOf('/');
    if(i == 4)
    {
        var year = value.substring(0, i);
        value = value.substring(i+1);
        i = value.indexOf('/');
        if(i > 0)
        {
            var month = value.substring(0, i);
            var day = value.substring(i+1);
            if(month.length == 1)
                month = "0" + month;
            if(day.length == 1)
                day = "0" + day;
            return year + month + day;
        }
    }
    var regex = new RegExp('/', 'g');
    return value.replace(regex, '');
}

//***********************************************************************************************************
//  CLASS:  HtmlBuff
//
// Html buffer providing utility methods for accumulating HTML.  The approach is to store the individual
// string sections in an array and concatenate that array later. This approach is used because IE is very
// slow when creating large strings by doing multiple statements of the form  string = string + '.....".
// It is much faster to accumulate the separate snippets and use the join() at the end.
//***********************************************************************************************************

function HtmlBuff(maxStrings) {
	if(!maxStrings)
		maxStrings = 300;

	this.nStrings = 0,
	this.strings  = new Array(maxStrings);

    if(typeof(_HtmlBuff_prototype_called) == 'undefined')
    {
        _HtmlBuff_prototype_called   	= true ;
        HtmlBuff.prototype.toString  	= HtmlBuff_Concat;
        HtmlBuff.prototype.add       	= HtmlBuff_Add;
        HtmlBuff.prototype.addAttrib  	= HtmlBuff_AddAttrib;
        HtmlBuff.prototype.addJsString 	= HtmlBuff_AddJsString;
        HtmlBuff.prototype.addQuoted 	= HtmlBuff_AddQuoted;
        HtmlBuff.prototype.addCData  	= HtmlBuff_AddCData;
        HtmlBuff.prototype.addText  	= HtmlBuff_AddCData;
    }
	//***************************************************************************************
	// Concatenate the array of substrings to create the composite string
	//***************************************************************************************
	function HtmlBuff_Concat(accum) {
		return this.strings.join("");
	}
	//**************************************************************************************
	// Add a string snippet to the string accumulator
	//**************************************************************************************
	function HtmlBuff_Add(string) {
		// If we're at the end of the array, allocate some more
		if(this.nStrings == this.strings.length)
			this.strings[this.nStrings+500] = "";

		this.strings[this.nStrings++] = string;
	}
	//******************************************************************************************
	// Add a string HTML attribute snippet of the form name="value".  If the name value is null,
	// the attribute is not added.  If the value has a '"' or a '\', the character is escaped.
	//******************************************************************************************
	function HtmlBuff_AddAttrib(name, value) {
		var attribChars 	= "\n\r\t&\"";
		var attribEntities	= ["&#10;", "&#13;", "&#09;", "&amp;", "&quot;"];

		if(!name || !value)
			return;
		var string = ' ' + name + '="' + CreateSpecialText(value+"", attribChars, attribEntities) + '"';
		this.add(string);
	}
	//******************************************************************************************
	// Add a string HTML attribute snippet of the form name="value".  If the name value is null,
	// the attribute is not added.  If the value has a '"' or a '\', the character is escaped.
	//******************************************************************************************
	function HtmlBuff_AddJsString(name, value) {
		var stringChars 	= "\n\r\t\\'\"";
		var stringEntities	= ["\n", "\r", "\t", "\\\\", "'",  "&quot;"];

		if(!name || !value)
			return;
		var string = ' ' + name + '="' + CreateSpecialText(value+"", stringChars, stringEntities) + '"';
		this.add(string);
	}
	//***********************************************************************************
	// Add a text that is going to be exposed as CDATA
	//***********************************************************************************
	function HtmlBuff_AddCData(text) {
		if(!text)
			return;

		var cDataChars 		= "\n\r\t<>&\"";
		var cDataEntities	= ["&#10;", "&#13;", "&#09;", "&lt;", "&gt;", "&amp;", "&quot;"];
		var string = CreateSpecialText(text, cDataChars, cDataEntities);
		this.add(string);
	}
	//*************************************************************************************
	// Add a string enclosed by double quotes ('"').  If the string contains a '"'
	// or '\', it is escaped using a '\'.   Useful for creating JavaScript stringsin
	// the <SCRIPT> part of the HTML
	//*************************************************************************************
	function HtmlBuff_AddQuoted(value) {
		var nFrom = 0;

		for(var n=0;  n < value.length;  n++) {
			var chr = value.charAt(n);
			if(chr == '"' || chr == '\\') {
				this.add(value.substring(nFrom,n) + '\\' + chr);
				nFrom = n + 1;
			}
		}
		if(nFrom < n)
			this.add(value.substring(nFrom,n));
	}
}

//***********************************************************************************************************
// Add a text for which certain special characters are going to be replaced by a string equivalent.  Used
// for substituting characters such as < > & " in HTML and XML
//***********************************************************************************************************

function CreateSpecialText(text, specialChars, specialStrings) {
	var nFrom = 0;
	var nOut  = 0;
	var out   = new Array(20);		// The size of the array is the typical maximum number of
	                                // special chars one expects in the text.
	for(var n = 0; n < text.length; n++) {
		var chr = text.charAt(n);
		var m = specialChars.indexOf(chr);
		if(m >= 0) {
			out[nOut++] = text.substring(nFrom,n) + specialStrings[m];
			nFrom = n+1;
		}
	}

	if(nFrom < text.length)
		out[nOut++] = text.substring(nFrom,text.length);

	return out.join("");
}

//***********************************************************************************************************
// Debug Console Utilities.
//
//		Attach debug window object to parent for common access for all frames.
//***********************************************************************************************************

function Debug(msg)
{
	DebugText(msg);
}

function  DebugText(text)
{
	var debug = window.parent.debug;
	if(!debug) {
		debug = { window: null, count: 0,  html: new HtmlBuff(20) };
		window.parent.debug = debug;
	}

	debug.html.add("<b>Line " + debug.count + ":</b>  ");
	debug.html.addText(text);
	debug.html.add("<br/>");

	if(!debug.window || debug.window.closed) {
		var name     = "DebugConsole" +  Math.round(100*Math.random()) + "_" + Math.round(100*Math.random());
		var title    = name + " for " + window.location.href;

		var html = new HtmlBuff(10);
		html.add("<html><title>" + title + "</title><body><hr></body><script>\n");
		html.add("var xxxxx=0; \n");
		html.add("window.opener.parent.scrollDebug = function() { window.scrollTo(0,document.body.scrollHeight);}\n");
		html.add("window.opener.parent.writeDebug = function(s)\n");
		html.add("{\n");
		html.add("document.write('<input type=checkbox id=xxxxx' + (++xxxxx) + '>');\n");
		html.add("document.write(s);\n");
		html.add("document.write('</input>');\n");
		html.add("}");
		html.add("</script></html>");


		var opts 	 = 'toolbar=yes,status=yes,scrollbars=1,location=1,menubar=1,directories=1,resizable=1';
		opts 	 += 'top=0, left=0, width=800';

		debug.window = window.open("", name, opts);
		if(debug.window == null)
			return;
		debug.window.document.write(html.toString());
	}

	parent.writeDebug(debug.html.toString());
	parent.scrollDebug();
	debug.count++;

	debug.html = new HtmlBuff(10);
}

function DebugXml(jsObject)
{
	DebugText(ObjectToXml(jsObject));
}

function DebugOn()
{
	DebugText();
	parent.debug.enabled = true;
}

function DebugOff()
{
	DebugText();
	parent.debug.enabled = false;
}

function DebugDumpObject(label, o) {
    DebugText("Dumping object " + label + " = " + ObjectToJs(o));
}

function DebugShowObjectContents(label, o) {
    var properties = "";
    for (var prop in o) {
        // Seperate each name:value by an ampersand.
        DebugText(label + " - " +  prop + "=" + o[prop]);
    }
}

//***********************************************************************************************************
// Lookup of objects from a DataSet
//***********************************************************************************************************

function ShowEntityMenu(uid, event, tsName)
{
	// If tsName is undefined, default ts for that entity type is used
	var entityMenu = GetEntityMenu(uid);
	if(!entityMenu.contextMenu)
	{
		var actionMenu = MakeDetailActionMenu(entityMenu, "Actions", "5555555");
		entityMenu.contextMenu = makeContextMenu(actionMenu);
	}
	entityMenu.contextMenu.setLabel(entityMenu.entityLabel + " " + ParseUid(uid).entityId);
	entityMenu.contextMenu.activateAtClick(event, [uid, tsName]);
	UiCancelEvent(event);
}

function GetEntityMenu(uid)
{
	if(uid.indexOf(':') == -1)
		alert("GetEntityMenu(uid) - missing entityTypeCd")

	var entityTypeCd = ParseUid(uid).entityTypeCd;

	if(entityTypeCd == 'US')  debugger;
	if(entityTypeCd == 'USA') debugger;

	for(n = 0; n < gRes.entityActions.Item.length; n++)
	{
		var entityMenu = gRes.entityActions.Item[n];
		if(entityMenu.entityTypeCd == entityTypeCd)
			return entityMenu;
	}
	return null;
}

function getTableSourceByName(tsName, tableSources) {  	// Legacy.   Remove after updating GeneralListView.jsp
	return FindTableSource(tableSources, tsName);
}

function FindEntity(dataSet, paramName, isOptional) {
	return FindDataSetItem(dataSet, "entityTypeCd", paramName, isOptional);
}

function FindTableSource(dataSet, paramName, isOptional) {
	return FindDataSetItem(dataSet, "name", paramName, isOptional);
}

function FindDataSetItem(dataSet, paramName, paramValue, isOptional)
{
	var items = dataSet.Item;
	if(!items) {
		alert( "Bad DataSet for param '" + paramName + "'");
		debugger;
		return null;
	}

	if(items.length > 0 && !items[0][paramName]) {
		alert( "No param named '" + paramName + "' in DataSet");
		debugger;
		return null;
	}

	for(var i=0; i < items.length;  i++ ) {
		var item = items[i];
		if( item[paramName] == paramValue)
			return item;
	}

	if(!isOptional)
		alert( "Couldn't find DataSet item: " + paramName + "=" + paramValue);

	return null;
}

function FindPrimaryColIndex(table)
{
    var colDefs = table.ColumnDefs;
    for(var k = 0; k < colDefs.length; k++)
    {
        primary = colDefs[k].primary;
        if(primary == 'true')
            return k;
    }
    return -1;
}

function FindEntityIndex(table, entityTypeCd)
{
    var colDefs = table.ColumnDefs;
    for(var k = 0; k < colDefs.length; k++)
    {
        if(colDefs[k].subType == entityTypeCd)
            return k;
    }
    return -1;
}

/**
 * Creates a pipe delimited string of entityIds from the table rows
 */
function CreateIdList(table, entityIdIndex)
{
    var n = 0;
	var idlist = new Array();
	for (var i=0; i < table.Rows.length; i++)
	    idlist[n++] = table.Rows[i][entityIdIndex];
	return "|" + idlist.join("|") + "|";
}
/******************************************************************************
AlertIfEmpty - pop-up an alert if the field is empty. Also set focus to the
  field in error.
******************************************************************************/

function AlertIfEmpty(formElement, alertMsg){
    var isEmpty = ("checkbox" == formElement.type) ? (false == formElement.checked) : (0 == formElement.value);
    if (isEmpty) {
        alert(alertMsg);
        formElement.focus();
        return true;
    }
    return false;
}

function AlertIfNoSelection(formElement, alertMsg){
    if (formElement.selectedIndex==0) {
        alert(alertMsg);
        formElement.focus();
        return true;
    }
    return false;
}

function AlertIfEmailAddressIncorrect(formElement, alertMsg)
{
	var filter  = /^([a-zA-Z0-9_\.\-\/])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})$/;
	if (filter.test(formElement.value)) return false;
	alert(alertMsg);
	formElement.focus();
	return true;
}

function AlertIfEmailAddressListIncorrect(formElement, alertMsg)
{
	var filter  = /^(([a-zA-Z0-9_\.\-\/])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4}),? *)+$/;
	if (filter.test(formElement.value)) return false;
	alert(alertMsg);
	formElement.focus();
	return true;
}

function AlertIfNotInRange(formElement, lower, upper, alertMsg)
{
    if (formElement.value < lower || formElement.value > upper) {
        alert(alertMsg);
        formElement.focus();
        return true;
    }
    return false;
}

function AlertIfLessThan(formElement, min, alertMsg)
{
    if (formElement.value < min) {
        alert(alertMsg);
        formElement.focus();
        return true;
    }
    return false;
}

//***********************************************************************************************************
// Serialize functions
//***********************************************************************************************************

function ObjectToJs(object)
{
	if(object == null)
		return "null";

	var isArray = object.constructor.toString().indexOf("Array") != -1;
	var string = isArray ? "[" : "{";

	for(var property in object) {
    	var elem = object[property];
		var type = typeof elem;
		// Ignore internal properties that begin with '$'.
        if(property.charAt(0) == '$' || typeof elem == "function" || type == "undefined")
			continue;

		if(type == "object")
			var value = ObjectToJs(elem);
		else
			var value = (type == "string") ? JsString(elem) : elem.toString();

		var separator = (string.length > 1) ? ", " : "";
		if(isArray)
			string += separator + value;
		else
			string += separator + property + ": " + value;
	}

	string += (isArray ? "]" : "}")
	return string;
}

/**
 * Make a single quoted Javascript string with special characters escaped
 */
var jsStringReplace;

function JsString(string)
{
	if(string == null)
		return "null";

	if(!jsStringReplace) {
		jsStringReplace = [
			{chr: '\\', 	regex: /\\/g, 	string: "\\\\"},		// Backslash replacement must be first!!
			{chr: '\n',		regex: /\n/g, 	string: "\\n"},
			{chr: '\r', 	regex: /\r/g, 	string: "\\r"},
			{chr: '\'', 	regex: /'/g,  	string: "\\'"}
		];
	}

	for(var n=0;  n < jsStringReplace.length;  n++) {
		var replace = jsStringReplace[n];
		if(string.indexOf(replace.chr) != -1)
			string = string.replace(replace.regex, replace.string);
	}

	return "'" + string + "'";
}

//***********************************************************************************************************
//  Make a deep or a shalow copy of an object.  Shalow copy only copies top level properties.
//  with objects being copied by reference.
//***********************************************************************************************************

function CloneObject(object, shallow)
{
	if(object == null)
		return null;

	var objectClone = new object.constructor();
	for(var property in object)
		if(shallow)
			objectClone[property] = object[property];
		else if (typeof object[property] == 'object')
				objectClone[property] = CloneObject(object[property], shallow);
		else
			objectClone[property] = object[property];
	return objectClone;
}

//***********************************************************************************************************
// Open the Customer Request window. Save the current page state so it can be retrieved
// by the email page.
//***********************************************************************************************************

function OpenEmailWindow()
{
    PageStateTable.savePageState(pageState);
    window.open("/Email.act?origPageId=" + pageState.pageID, '_self');
}

//***********************************************************************************************************
// CreateXmlHttpObject - create a new XmlHttp object as supported by browser
//***********************************************************************************************************

function CreateXmlHttpObject()
{
    var xmlHttp;
    if (window.XMLHttpRequest)
        xmlHttp = new XMLHttpRequest();
    else if(window.ActiveXObject)
        xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
    else
        xmlHttp = null;
    return xmlHttp;
}

//***********************************************************************************************************
// DoTxRequest:   Client callback will be called with (txData, object) as arguments
//***********************************************************************************************************

function DoTxRequest(params, clientCallback, object)
{
	var uri = "/Direct/TxServer.act";
	if(typeof clientCallback != "function") {
		var jsText = DoWaitHttpRequest(uri, params);
		return DoTxRequestData(jsText)
	}
	else {
		var callback = function(jsText) {
			clientCallback(DoTxRequestData(jsText),object)
		}
		DoCallbackHttpRequest(uri, params, callback);
	}
}

function DoTxRequestData(jsText)
{
	eval(jsText);

	txData = {};
	txData.txInfo = (typeof txInfo != "object")  ? null : txInfo;
	txData.txError =(typeof txError != "string") ? null : txError;

	if(txData.txError)
		alert(txData.txError);
	return txData;
}

//***********************************************************************************************************
// DoHttpRequest
//***********************************************************************************************************

function DoCallbackHttpRequest(uri, params, callback, object) 	{ return DoHttpRequest(uri,params,callback, object); }
function DoWaitHttpRequest(uri, params) 						{ return DoHttpRequest(uri,params); }

function DoHttpRequest(url, params, callback, object)
//	If params are absent, do a GET.  Otherwise do a POST.
//	If callback is not defined, block on the request.  If not blocking, callback when done, with object as second argument.
{
	var requestType = (!params) ? "GET" : "POST";
	var isAsync 	= (typeof callback == "function");

	var request = CreateXmlHttpObject();
	request.onreadystatechange = function() {
		if(request.readyState == 4) {
			if(request.status == 200) {
				if(isAsync)
					callback(request.responseText.trim(), object);
			} else
				alert ( "Error " + request.status + " on " + requestType + " to " + url);
		}
	};

	request.open(requestType, url, isAsync);
	request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	request.send(params);

	if(!isAsync)
		return (request.status == 200) ? request.responseText.trim() : null;
}


function DoFileChooserUids(replyCmd, selectDocPath, bounds)
{
	DoFileChooser(replyCmd, selectDocPath, bounds, "DoFileChooserUids.callback");
	DoFileChooserUids.callback = function(replyCmd, data) {
		var pipeSet = DoHttpRequest("/Direct/EntityIds.act", "docPath=" + escape(data.docPath));
		doAction(replyCmd, pipeSet);	// Execute the page's doAction()
	}
}

function DoFileChooser(replyCmd, selectDocPath, bounds, jsCallback)
{
	if(!selectDocPath)
		selectDocPath = GC.DIR_NAME_USERS + "/" + gEnv.userId + "/" + GC.DOCUMENT_TEMP_DIR;
	if(!bounds)
		bounds = {width: 800, height: 600};
	if(!bounds.top)
		bounds.top =  (window.screen.availHeight-10-bounds.height)/2;
	if(!bounds.left)
		bounds.left =  (window.screen.availWidth-10-bounds.width)/2;

	var url = "/Dialog/FileChoose.act?selectDocPath="+ escape(selectDocPath)+ "&replyCmd=" + replyCmd;
	if(jsCallback)
	    url = url + "&jsCallback=" + jsCallback;
	var fileSelectWindow = window.open(url, "DocumentSelect",
			"scrollbars,  resizable, top=" + bounds.top + ", left=" + bounds.left + ", width=" + bounds.width + ", height=" + bounds.height);
	fileSelectWindow.focus();
}

function DocPathToUri(docPath, docId, useDocExplorer)
{
    var baseUri = ("fts" == gEnv.orgId) ? "http://see-the-forest.com"
            : (gEnv.orgId.indexOf("_local") < 0) ? "http://ipvisioninc.com/g3" : "http://" + window.location.host;

    if(useDocExplorer)
        var action = "/UserDocExplorer.act?openDoc=true&" + (docId ? "docId=" + docId : "selectDocPath=" + docPath);
    else
        var action = "/DocumentRecall.act?" + (docId ? "docId=" + docId : "docPath=" + docPath);

    return baseUri + action + "&orgId=" + gEnv.orgId;
}

