var GC = {
	USER_FILES_FOLDER_NAME: 'My Files',
	SHARED_FILES_FOLDER_NAME: 'Shared Files',
	IPVISION_FILES_FOLDER_NAME: 'IPVision',
	USER_JOBS_FOLDER_NAME: 'My Jobs',
	USER_NO_PASSWORD: '[no password]',
	EXPORT_TEMP_DIR: 'ExportTemp',
	DOCUMENT_TEMP_DIR: 'Temporary Documents',
	IPVISION_WORK_DIR: '--IPVision--',
	IPVISION_WORK_TEMP_DIR: '--IPVision--/Temporary Files',
	DOC_SYSTEM_FOLDERS: ['ExportTemp', 'Temporary Documents', '--IPVision--/Temporary Files']
,
	DOC_PATH_SELECT: 'selectDocPath',
	DOC_PATH_DELETE: 'deleteDocPath',
	DOC_HISTORY_REMOVED: 'REMOVED',
	DIR_NAME_IMPORT_FILES: 'DataLoads/Data Files',
	DIR_NAME_TSS_RES: 'DataLoads/Table Source Specifications',
	DIR_NAME_TS_RES: 'TableSources',
	DIR_NAME_FORM_TEMPLATES: 'Templates/Form',
	DIR_NAME_PRINT_TEMPLATES: 'Templates/Print',
	DIR_NAME_CHART_TEMPLATES: 'Templates/Chart',
	DIR_NAME_ENT_RES: 'Entities',
	DIR_NAME_MULTI_TABLE_RES: 'MultiTableDefs',
	DIR_NAME_USERS: 'Users',
	DIR_NAME_ROLES: 'Roles',
	DIR_NAME_UI_RES: 'UI',
	DIR_NAME_ATTACHMENTS: 'Attachments',
	DIR_NAME_CHART_ATTACHMENTS: 'Attachments/Chart',
	JOBS_TREE_NODE_PREFIX: '__ipv_jobs/',
	US_CLASS_ENT_CD: 'usClass',
	US_MAIN_CLASS_ENT_CD: 'usMainClass',
	US_PATENT_ENT_CD: 'usPatent',
	US_CLAIM_ENT_CD: 'claim',
	US_APPLICATION_ENT_CD: 'usApplication',
	EURO_APPLICATION_ENT_CD: 'EPA',
	EURO_PATENT_ENT_CD: 'EPB',
	INVENTOR_ENT_CD: 'Inventor',
	USERS_ENT_CD: 'Users',
	SUMMARY_ENT_CD: 'Summary',
	SPECIAL_ENT_CD: 'Special',
	INVENT_DISCLOSURE_ENT_CD: 'inventDisc',
	UNPUB_APPLICATION_ENT_CD: 'unpubApp',
	PUBLICATION_ENT_CD: 'publication',
	PATENT_ENT_CD: 'patent',
	FIELD_NAME_TABLE_SOURCE: 'tsName',
	FIELD_NAME_ENTITY_TYPE_CODE: 'entityTypeCd',
	FIELD_NAME_ACTION_CODE: 'actionCd',
	FIELD_NAME_SEARCH_TYPE: 'searchType',
	FIELD_NAME_TABLE_SPEC: 'name',
	FIELD_NAME_ROLE_NAME: 'name',
	FIELD_NAME_MENU_NAME: 'name',
	FEATURE_KIOSK: 'kiosk',
	FEATURE_FILE_INFO: 'fileInfo',
	FEATURE_USER_ADMIN: 'useradmin',
	ACTION_CODE_SAVE: 'save',
	ACTION_CODE_CANCEL: 'cancel',
	ACTION_CODE_DELETE: 'delete',
	ACTION_CODE_ERROR: 'error',
	ACTION_CODE_GET: 'get',
	ACTION_CODE_LOAD: 'load',
	ACTION_CODE_INSERT: 'insert',
	ACTION_CODE_UPDATE: 'update',
	ACTION_CODE_SEND: 'send',
	ACTION_CODE_FORMAT_TO_PRINT: 'formattoprint',
	ACTION_CODE_SAVE_DOCUMENT: 'saveDocument',
	ACTION_CODE_MAKE_PORTFOLIO: 'saveListAsPortfolio',
	ACTION_CODE_SAVE_AS_REPORT_MAKER: 'saveAsReportMaker',
	ACTION_CODE_COPY_DOCUMENT: 'copyDocument',
	ACTION_CODE_MOVE_DOCUMENT: 'moveDocument',
	ACTION_CODE_MOVE_CONTENTS: 'moveContents',
	ACTION_CODE_RENAME_DOCUMENT: 'renameDocument',
	ACTION_CODE_ADD_DOCUMENT_NOTE: 'addDocNote',
	ACTION_CODE_CREATE_FWD_CITATION_LIST: 'createCitationList',
	ACTION_CODE_CREATE_BWD_CITATION_LIST: 'createBwdCitationList',
	ACTION_CODE_CREATE_ENTITY_LIST: 'createEntityList',
	ACTION_CODE_MERGE_ENTITY_LISTS: 'mergeEntityLists',
	ACTION_CODE_SEARCH_DYNAMIC: 'dynamic',
	ACTION_CODE_SEARCH_ENTITY_ID: 'entityId',
	ACTION_CODE_SEARCH_US_CLASSES: 'usClasses',
	ACTION_CODE_SEARCH_MULTIPLE_FIELDS: 'multiple',
	ACTION_CODE_SEARCH_ADVANCED: 'advanced',
	ACTION_CODE_SEARCH_FULL_TEXT: 'fullText',
	ACTION_CODE_COMPARE: 'compare',
	ACTION_CODE_COMBINE: 'combine',
	ACTION_CODE_RESET: 'reset',
	ACTION_CODE_INTERSECT: 'intersect',
	ACTION_CODE_MERGE: 'merge',
	ACTION_CODE_SOURCE_INDEX: 'sourceIndex',
	ACTION_CODE_SUBLIST: 'sublist',
	ACTION_CODE_REMOVE: 'remove',
	ACTION_CODE_SUBTRACT: 'subtract',
	ACTION_CODE_XOR: 'xor',
	ACTION_CODE_FILTER: 'filter',
	ACTION_CODE_RATIO: 'ratio',
	ACTION_CODE_RESUBMIT: 'resubmit',
	ACTION_CODE_SHAPE_DROP: 'shapeDrop',
	ACTION_CODE_REFETCH: 'refetch',
	ACTION_CODE_REFINE: 'refine',
	ACTION_PAGE_ENTITY_DETAIL: 'EntityDetail.act',
	ACTION_PAGE_ENTITY_VIEW: 'EntityView.act',
	MAP_ITEM_FADE_ATTRIBUTE_NAME: 'fade',
	MAP_ITEM_FADE_BACK_COLOR: 'white',
	MAP_ITEM_FADE_FORE_COLOR: '#CCCCCC',
	CLASS_SEARCH_TYPE_ALL: 'All Classes',
	CLASS_SEARCH_TYPE_MAIN: 'Main Only',
	CLASS_SEARCH_TYPE_PRIMARY: 'Primary Only',
	CLASS_SEARCH_TYPE_SECONDARY: 'Secondary Only',
	MAP_TYPE_SOURCE_LIST_SHAPE_DROP: 'sourceListShapeDrop',
	MAP_TYPE_STATS_VALUE_SHAPE_DROP: 'statsValueShapeDrop',
	MAP_TYPE_ENTITY_TYPE_SHAPE_DROP: 'entityTypeShapeDrop',
	MAP_TYPE_HISTORY: 'history',
	DELIMITER_SPACE: 'Space',
	DELIMITER_COMMA: 'Comma',
	DELIMITER_SEMICOLON: 'Semi-Colon',
	DEFAULT_ID_DELIMITERS: ' \t\n\r,;|',
	DATA_TYPE_STRING: 'string',
	DATA_TYPE_TEXT: 'text',
	DATA_TYPE_MEDIUM_TEXT: 'mediumText',
	DATA_TYPE_DATE: 'date',
	DATA_TYPE_INT: 'int',
	DATA_TYPE_FLOAT: 'float',
	DATA_TYPE_AUTO_INT: 'autoInt',
	DATA_TYPE_TIMESTAMP: 'timestamp',
	DATA_TYPE_ENTITY: 'entity',
	DATA_TYPE_ENTITY_SET: 'entitySet',
	DATA_TYPE_LABEL_SET: 'labelSet',
	USER_TYPE_SUPER_SEARCHER: 'supersearcher',
	TABLESOURCE_IPV_PATENTS: 'UsptoData',
	TABLESOURCE_IPV_DATA: 'IPVData',
	TABLESOURCE_US_PATENTS: 'UsPatentData',
	TABLESOURCE_US_APPLICATIONS: 'UsApplicationData',
	TABLESOURCE_IPV_DATA_US_APP: 'IPVDataUsApp',
	TABLESOURCE_EURO_APPLICATIONS: 'EPA',
	TABLESOURCE_EURO_PATENTS: 'EPB',
	TABLESOURCE_MULTI: 'multi',
	TABLESOURCE_INHERIT: '__inherit',
	ENTITY_ID_PATENTS: 'patentNumber',
	FIELD_NAME_PRIM_CLASS: 'primaryUsClasses',
	FIELD_NAME_SEC_CLASS: 'secondaryUsClasses',
	FIELD_NAME_MASTER_CLASS: 'mainClass',
	TRUE: 'true',
	FALSE: 'false',
	EMPTY: '',
	COMMA: ',',
	QUOTE: '\'',
	QUOTE_COMMA_QUOTE: '\',\'',
	CHAR_NEW_LINE: '\n',
	CHAR_RETURN: '\r',
	CHAR_TAB: '\t',
	CHAR_SINGLE_QUOTE: '\'',
	CHAR_DOUBLE_QUOTE: '\"',
	CHAR_SEMI_COLON: ';',
	CHAR_COMMA: ',',
	CHAR_SPACE: ' ',
	CHAR_UNDERBAR: '_',
	CHAR_PIPE: '|',
	CHAR_BACK_SLASH: '\\',
	CHAR_FORWARD_SLASH: '/',
	CHAR_ESCAPE_CHAR: 0,
	RES_CD_ENTITY: 'ent',
	RES_CD_TABLE_SPEC: 'tss',
	RES_CD_TABLE_SOURCE: 'ts',
	RES_CD_DOC_REPOS: 'docr',
	RES_CD_UNKNOWN: 'unk',
	RES_CD_ROLE: 'role',
	RES_CD_ACT: 'act',
	RES_CD_MENU: 'menu',
	RES_CD_MULTI_TABLE: 'multi',
	DOC_CD_FS_HANDLER: 'fs',
	DOC_HIDDEN_PREFIX: '__',
	DIR_HIDDEN_CD: '__dir_hidden',
	ACCESS_TYPE_CD_ALLOW: 'allow',
	ACCESS_TYPE_CD_DENY: 'deny',
	ACCESS_TYPE_CD_DISABLE: 'disable',
	MAIL_PRIORITY_HIGH: 'high',
	MAIL_PRIORITY_NORMAL: 'normal',
	MAIL_PRIORITY_LOW: 'low',
	UTF8_ENCODING: 'UTF-8',
	IPV_FIND_URL: 'http://www.ipvisioninc.com/findurl.php',
	MSG_RESET_ORG_ENTITY_MGR: 'resetOrgEntityMgr',
	MSG_RECONFIGURE_APP: 'reconfigureApp',
	RESOURCES_JS: 'Resources.js',
	HEADER_RENDER_CD: 'header',
	BODY_RENDER_CD: 'body',
	CONNECT_RENDER_CD: 'connect',
	OVAL_RENDER_CD: 'oval',
	PENTAGON_RENDER_CD: 'pentagon',
	SIDES_RENDER_CD: 'sides',
	STAR_RENDER_CD: 'star',
	CUSTOM_RENDER_CD: 'custom',
	FADE_RENDER_CD: 'fade',
	HIDE_RENDER_CD: 'hide',
	X_CONNECT_TYPE: 'xc',
	ALL_RENDER_CD: ['body', 'connect', '_', 'oval', 'pentagon', 'sides', 'star', 'custom', '_', 'fade', 'hide']
,
	ACCENT_RENDER_CD: ['body', 'oval', 'pentagon', 'sides', 'star', 'custom']
,
	LEGEND_SELECT_NONE: -1,
	LEGEND_SELECT_DEFAULT: -2,
	URL_HOT_SPOT: 'url',
	ENTITY_ID_HOT_SPOT: 'entityId',
	ENTITY_SELECT_HOT_SPOT: 'entitySelect'
};

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 
 //-----------------------------------------------------------------------------
// GetAppMenu:   Return application menubar data object
//-----------------------------------------------------------------------------

function GetAppMenu()
{
	return gRes.appMenu;
}

//-----------------------------------------------------------------------------
// WriteAppMenu:   Render the application menu toolbar.
//-----------------------------------------------------------------------------

function WriteAppMenu()
{
	var appMenu = GetAppMenu();
	if (appMenu == null)
		return;
	var appMenuToolbar = MakeAppMenuToolbar(appMenu);

	appMenuToolbar.render();
}

//-----------------------------------------------------------------------------
// WriteAppDashboard():   Render the application menu as a sidebar.
//-----------------------------------------------------------------------------

function WriteAppDashboard(message)
{
	document.write(GetAppDashboardHtml(message));
}

//-----------------------------------------------------------------------------
GetAppDashboard:
//-----------------------------------------------------------------------------

function GetAppDashboardHtml(message){
	if(typeof message == 'undefined')
		message = "Active Intellectual Property Management For the Enterprise";
	var html = new Array(10);
	var nHtml = 0;

	html[nHtml++] = '<TABLE cellpadding="0" cellspacing="0"><TR>';
	html[nHtml++] = '<TD class="motto">' + message + '</TD>\n';
 	html[nHtml++] = '<TD class="ipvision"><IMG src="/img/info1.gif"></IMG>&nbsp;IPVision<SUP><SPAN class="ipvisionsm">SM</SPAN></SUP></TD>\n';
 	html[nHtml++] = '</TR></TABLE>';
	return html.join("");
}

//-----------------------------------------------------------------------------
// GetAppNavbarHtml:   Render the HTML for the applicationn navigation sidebar.
//-----------------------------------------------------------------------------

function GetAppNavbarHtml(env)
{
	var html = new Array(300);
	var nHtml = 0;

	html[nHtml++] = '<TABLE class="navMenu" width="100%" cellspacing="0" cellpadding="0">\n';

	if( gEnv != null )
	{
		html[nHtml++] = "<TR><TD class='navLogo'><IMG SRC='" + gEnv.orgIcon + "'/></TD></TR>\n";
		if(gEnv.projectId)
		    html[nHtml++] = "<TR><TD>Project ID: " + gEnv.projectId + "</TD></TR>\n";
    }

	mainMenus = GetAppMenu().AppMenus;

	var mainStyle = (mainMenus.length < 3) ? 'style="font-size: 10pt"' : '';
	var subStyle  = (mainMenus.length < 3) ? 'style="font-size: 10pt"' : '';

	for(var n=0;  n < mainMenus.length;  n++ ) {
		if(mainMenus[n].title != "_none")
			html[nHtml++] = '<TR><TD class="navMenu1" ' + mainStyle + ' nowrap>' + mainMenus[n].title.toUpperCase() + '<BR/></TD></TR>' + "\n";
		subMenus = mainMenus[n].AppMenuItems;
		for(var m=0;  m < subMenus.length;  m++) {
			// Actions that are in single quotes need to be evaluated.  This is the approach for creating
			// menu items that need parameter substitution from gEnv.  Fix this by doing the substitution
			// on the server side or up in GetAppMenus().  UIMenu has similar hack in it.
			var action = subMenus[m].action;
			var href = (action.indexOf("'") == 0) ? eval(action) : action;

			var anchor = '<A href="' + href + '">';
			if(href.toLowerCase().indexOf("javascript:") == 0)
				anchor = '<A href="Javascript:void(0)" onClick="UiCancel(event);' + href + '">';

			var text = subMenus[m].title;
			if(subMenus[m].isDisabled == 'true')
			    html[nHtml++] = '<TR><TD class="navMenu2D" ' + subStyle + ' nowrap>' + text + '</TD></TR>' + "\n";
			else if(action == '#')
			    html[nHtml++] = '<TR><TD class="navMenu2" ' + subStyle + 'nowrap>' + text + '</TD></TR>' + "\n";
			else
			    html[nHtml++] = '<TR><TD class="navMenu2" ' + subStyle + 'nowrap>' + anchor + text + '</A></TD></TR>' + "\n";
		}
    }

	html[nHtml++] = "</TABLE>\n";
	return html.join("");
}

//-----------------------------------------------------------------------------
// GetAppFooter:   Render the application menu as a sidebar.
//-----------------------------------------------------------------------------

function GetAppFooter(verbose)
{
	var isRes  = (typeof gRes == "object");
	var footer = [ isRes && gRes.footerLeft ?gRes.footerLeft : "(C) 2002-YYYY, IPVision, All Rights Reserved, Patents Pending", "", ""];

	if(verbose) {
		if(gEnv.orgId && gEnv.userId)
			footer[1] = (isRes && gRes.footerRight) ? gRes.footerRight : ("User: " + gEnv.userId + ",&nbsp;&nbsp;Org: " + gEnv.orgId + "(" + gEnv.orgDbId + ")");
		footer[2] = (isRes && gRes.footerCenter) ? gRes.footerCenter : ("Server: " + gEnv.appServerName + "-" + gEnv.appVersion);
	}

	footer[0] = footer[0].replace("YYYY", new Date().getFullYear());

	var html = '<table class="footer" width="100%"><tr width="100%"><td align="left">' + footer[0] + '<td align="center" style="padding: 0 12 0 12">' + footer[1] + '<td align="right">' + footer[2] + '</table>';
	return html;
}

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 
// A custom cookie object for storing and retrieving cookies. Its writes each property
// without a leading '$' to the cookie.
function Cookie(document, name, hours, path, domain, secure) {
    // All predefined properties begin with '$' to distinguish them from other properties.
    this.$document = document;
    this.$name = name;
    if (path)
        this.$path = path;
    else
        this.$path = null;
    if (hours)
       this.$expiration = new Date((new Date()).getTime() + hours*3600000);
    else
       this.$expiration = null;
    if (domain)
       this.$domain = domain;
    else
       this.$domain = null;
    if (secure)
       this.$secure = true;
    else
       this.$secure = false;
}

// Write the cookie contents to the document cookie.
Cookie.prototype.store = function() {
    // Create a string from the properties.
    var cookieval = "";
    for (var prop in this) {
        // Ignore properties that begin with '$'. Also ignore methods.
        var type = typeof this[prop];
        if ((prop.charAt(0) == '$') || type == "function" || type == "undefined")
            continue;
        // Seperate each name:value by an ampersand.
        if (cookieval != "") cookieval += '&';
        cookieval += prop + ":" + escape(this[prop]);
    }
    //DebugText("saving cookie " + this.$name + " = " + cookieval);
    // Save the cookie
    var theCookie = this.$name + "=" + escape (cookieval) +
        ((this.$expiration)	? "; expires=" + this.$expiration.toGMTString() : "") +
        ((this.$path)       ? "; path="    + this.$path   : "") +
        ((this.$domain)  	? "; domain="  + this.$domain : "") +
        ((this.$secure)     ? "; secure"            : "");
    this.$document.cookie = theCookie;
}

// Read the cookie. Populate cookie instance variables with the cookie matching the cookie name.
Cookie.prototype.load = function() {
    // Look for cookie
    var allcookies = this.$document.cookie;
    if (allcookies == "") return false;
    //DebugText("allCookies = " + allcookies);

    // Extract the named cookie
    var start = allcookies.indexOf(this.$name + "=");
    if (start == -1) return false;
    start += this.$name.length + 1;
    var end = allcookies.indexOf(';', start);
    if (end == -1) end = allcookies.length;
    var cookieval = allcookies.substring(start,end);
    //
    //DebugText(this.$name + " cookie = " + cookieval);
    var ecookieval = unescape(cookieval)
    //DebugText(this.$name + " ecookie = " + ecookieval);
    //
    // Break the value into individual state values.
    //
    var a = ecookieval.split('&');
    for (var i=0; i<a.length; i++)
        a[i] = a[i].split(':');

    for (var i=0; i<a.length; i++) {
        //this[a[i][0]] = unescape(a[i][1]);
        eval("this."+a[i][0] + " = unescape('"+a[i][1]+"');");
    }
    return true;
}

// Delete the cookie with the matching cookie name.
Cookie.prototype.remove = function() {
    var cookie;
    cookie = name + "=";
    if (this.$path) cookie += ';path=' + this.$path;
    if (this.$domain) cookie += ';domain=' + this.$domain;
    cookie += ';expires=Thu, 01-Jan-70 00:00:01 GMT';
    this.$document.cookie=cookie;
}
/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 

function IsIE()
{
	return navigator.appName.indexOf("Internet Explorer") != -1;
}

//---------------------------------------------------------------------------
//	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) {
	if(url.indexOf("/Dialog/S/") >= 0)
		return PopupWindow(dialogWinName, null, 250);

	if(url.indexOf("/Dialog/") >= 0)
		return PopupWindow(dialogWinName);

	return NewWindow("", "W"+ new Date().getTime());
}

//---------------------------------------------------------------------------
function NewWindow(url, winName) {
	if(winName) {
		newWindow = window.open( url, winName );
		newWindow.focus();
    }
	else
		newWindow = window.open( url );
	return winName;
}

//---------------------------------------------------------------------------
function PopupWindow(winName, width, height, url)
{
	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";
	var newWindow = window.open(url ? url : "", winName, attribs);
	newWindow.focus();
	return winName;
}

//---------------------------------------------------------------------------
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) {
    if(dateTimeStamp == null)
        return "";
    dateTimeStamp = dateTimeStamp.trim();
    if (dateTimeStamp.indexOf("/") > 0)
        return dateTimeStamp;
    else if((dateTimeStamp.length == 14) || (dateTimeStamp.length == 8))
        return dateTimeStamp.substring(0,4) + '/' + dateTimeStamp.substring(4,6) + '/' + dateTimeStamp.substring(6,8);
    else if(dateTimeStamp.length == 6)
        return dateTimeStamp.substring(0,4) + '/' + dateTimeStamp.substring(4,6);
    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) {
    if(dateTimeStamp == null)
        return "";
    dateTimeStamp = dateTimeStamp.trim();
    if(dateTimeStamp.length == 14)
        return dateTimeStamp.substring(0,4) + '/' + dateTimeStamp.substring(4,6) + '/' + dateTimeStamp.substring(6,8) + '&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 comma 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){
    if (formElement.value == 0) {
        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 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("/jsp/Direct/EntityIds.jsp", "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 = (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 + "&userId=" + gEnv.userId + "&orgId=" + gEnv.orgId;
}

/*
 * Copyright IPVision, Inc 2005 - 2006.   All rights reserved.
 */

var KIOSK_MAIN_WIN_CD   = "kioskMainWinCd";

//------------------------------------------------------------------------------------------//

function MakeKioskWindowName()
{
    return "_kiosk_" + gEnv.userSessionId.replace( /\W/g, "_");
}

function FocusKioskMainWindow()
{
    var mainWindow = window.open("", MakeKioskWindowName());
	if(mainWindow.location == "about:blank")		// If the window is new, the location will be blank
		mainWindow.location = "UserDocExplorer.act";

	mainWindow.focus();
}

function SetKioskMainWindowUrl(url)
{
	var mainWindow = window.open(url, MakeKioskWindowName());
	mainWindow.focus();
}

function OrderLandscapeMap(idList) {
    var MAX_MULTI_PAT = 4;
    if(idList.length == 0) {
        alert("No patents selected");
        return true;
    }
    if(idList.length > MAX_MULTI_PAT) {
        alert("Multi-patent maps are limited to " + MAX_MULTI_PAT + " patents");
        return true;
    }
    if(idList.length > 1) {
        var uidList = ParseUidList(idList);
        if(uidList)
            idList = uidList.entityIdList;
        var entityId = '|' + idList.join('|') + '|';
        var descr = "Landscape Map of US Patents " + idList.join(', ');
        var relDocDir = "Multi-patent Maps";
    }
    else {
        var entityId = ParseUid(idList[0], GC.US_PATENT_ENT_CD).entityId;
        var descr = "Landscape Map of US Patent " + entityId;
        var relDocDir = "US Patent " + entityId;
    }
    var txn = {entityId: entityId, actionCd: "landscapeMap", descr: descr, relDocDir: relDocDir, status: "", price: 0};
    var order = {mName: "Order", status: "UNREVIEWED", Transaction: [txn]};
    var url = "Order.act?xmlOrder=" + ObjectToXml(order);

    SetKioskMainWindowUrl(url);
}


/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 

/////////////////////////////////////////////////////////////////////////////////////////////////
// Convert an Object to XML
/////////////////////////////////////////////////////////////////////////////////////////////////

function ObjectToXml(elem, elemName, filter)
{
	if(typeof elem == "string" && typeof elemName == "object")	{
		var temp = elemName;
		elemName = elem;
		elem = temp;
	}

	if(!elemName) {
		if(elem.mName)
			elemName = elem.mName;
		else if(elem.mType)
			elemName = elem.mType;
		else
			elemName = "DataAPI";
	}

	var tagName = ToXmlTagName(elemName);
	var xml     = '<' + tagName;
	var elems   = '';

	for(var childName in elem)
	{
		var child = elem[childName];
		var type = typeof child;
		if(type == "function" || type == "undefined" || (filter && !filter(childName)))
			continue;

		if(type == "object") {
		    if(child == null) // apparently a null member variable is considered an object
		        continue;
			if(child.constructor.toString().match(/array/i) == null)
				elems += ObjectToXml(child, childName, filter);
			else
				elems += ArrayToXml(child, childName);
		}
		else
			xml += " " + childName + '="' + ToXmlText(child) + '"';
	}

	if(elems.length > 0)
		xml += '>\n' + elems +  '</' + tagName + '>\n';
	else
		xml += '/>\n';

	return xml;
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// Convert a Javascript array into an XML document.  Legacy naming of arrays and their child
// components is performed by ToXmlArrayTagName().
/////////////////////////////////////////////////////////////////////////////////////////////////

function ArrayToXml(elem, elemName)
{
	var csv = null;
	var tagNames =  ToXmlArrayTagName(elemName, elem);

	var elemXml = new Array(elem.length);
	for (var n=0; n < elem.length;  n++) {
		var child = elem[n];
		if (typeof child == 'object') {

			if (child.constructor.toString().match(/array/i) == null)
				elemXml[n] = ObjectToXml(child, tagNames.childName);
			else
				elemXml[n] = ArrayToXml(child, tagNames.childName);
		}
		else
			csv = (csv == null) ? elem[n] : (csv + "," + elem[n]);
	}

	var xml = '<' + tagNames.startTag;

	if (csv != null)
		xml += ' csv="' + ToXmlText(csv) + '"';

	xml += '>\n' + elemXml.join('') +  '</' + tagNames.endTag + '>\n';

	return xml;
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// Create the name of the parent array and the name of child arrays (if they exist).
/////////////////////////////////////////////////////////////////////////////////////////////////

function ToXmlArrayTagName(elemName, elem)
{
	var tagName = ToXmlTagName(elemName);
	var n;

	for (n=0; n < elem.length;  n++) {
		if (typeof elem[n] == 'object')
			break;
	}

	if (n > 0 && n == elem.length)	// Special "csv" case where all array elements are scalars
		return {startTag: 'List mName="' + tagName + '"', endTag: 'List', childName: '' + tagName + ''};

	var childname;
	if (tagName == 'Rows')
		childname = 'Row';
	else if (tagName == 'ColumnDefs')
		childname = 'ColumnDef';
	else
		childname = null;   // This allows each child to specify its own type

	return {startTag: 'List mName="' + tagName + '"', endTag: 'List', childName: childname};
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// Convert an element name to a tag name.  By convention (in the future) we will
// capitalize the first letters when in XML but not in Java or Javascript
/////////////////////////////////////////////////////////////////////////////////////////////////

function ToXmlTagName(tagName)
{
	if(tagName.length == 0)
		return "BlankTag";

	var chr = tagName.charAt(0);

	if (chr <'a' || chr >'z')
		return tagName;

	return tagName.substring(0,1).toUpperCase() + tagName.substring(1);
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// Escape a string so that it is a legal XML attribute value or text in the body of an element.
/////////////////////////////////////////////////////////////////////////////////////////////////

var toXmlTextReplace = null;
var toXmlTextReplaceTest = null;

function ToXmlText(text)
{
	if(!text)
		return "";

	if(typeof text != "string")
		return text + "";			// In case they passed in a number;

	if(!toXmlTextReplace) {
		toXmlTextReplaceTest = /[&\n\t\t<>"]/;
		toXmlTextReplace = [
			{chr: '&',  regex: /&/g,  string: "&amp;"},		// Ampersand replacement must be first!!
			{chr: '\n', regex: /\n/g, string: "&#10;"},
			{chr: '\r', regex: /\r/g, string: "&#13;"},
			{chr: '\t', regex: /\t/g, string: "&#09;"},
			{chr: '<',  regex: /</g,  string: "&lt;"},
			{chr: '>',  regex: />/g,  string: "&gt;"},
			{chr: '"',  regex: /"/g,  string: "&quot;"}
		];
	}

	if(!text.match(toXmlTextReplaceTest))
		return text;

	for(var n=0;  n < toXmlTextReplace.length;  n++) {
		var replace = toXmlTextReplace[n];
		if(text.indexOf(replace.chr) != -1)
			text = text.replace(replace.regex, replace.string);
	}

	return text;
}




/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 

/**
 * Execute an entity request on a single entity or entity list
 */
function EntityRequestActionHandler(ev, form, contextDocPath)
{
    var txRequest = {contextDocPath: contextDocPath};

    if(ev.eventCd == ENTITY_SET_SELECT_CD)
    {
        if(GetDefaultTsName(ev.entityTypeCd) == GC.TABLESOURCE_MULTI)
            var uidList = ParseUidList(ev.entityIdList);

        var actionPageName      = "GeneralListViewer.act";
        txRequest.mName 		= 'SearchRequest';
        txRequest.searchType 	= 'entityId';
        txRequest.searchValue 	= '|' + (uidList ? uidList.entityIdList.join('|') : ev.entityIdList.join('|')) + '|';
        txRequest.entityTypeCd  = uidList ? uidList.entityTypeCd : ev.entityTypeCd;
        txRequest.descrTemplate = ev.descrTemplate;
    }
    else if(ev.eventCd == ENTITY_SELECT_CD)
    {
        var uid = ParseUid(ev.entityIdList[0], ev.entityTypeCd);

        var actionPageName      = ev.focusCol ? "EntityDetail.act#" + ev.focusCol : "EntityDetail.act";
        txRequest.mName 		= 'EntityRequest';
        txRequest.entityId      = uid.entityId;
        txRequest.entityTypeCd  = uid.entityTypeCd;

        var uidString = MakeUid(uid.entityTypeCd, uid.entityId);
        var winName = "ED" + uidString.replace(/[ .:\/\-]+/g,"");
        var newWindow = window.open("about:blank", winName);
    }
    else
        return;

	// If not the primary column for the table source, take columns from the default (main)
	// table for that entity type.
	if(!ev.tsName)
		txRequest.tsName = GetDefaultTsName(txRequest.entityTypeCd);
	else
		txRequest.tsName = ev.tsName;

    if(ev.eventCd == ENTITY_SELECT_CD)
        form.sidebar.value = "none";

    form.xmlRequest.value = ObjectToXml(txRequest);
    form.action = actionPageName;
	form.target = winName ? winName : "_blank";
    form.submit();

    if(newWindow)
        newWindow.focus();
}

/**
 * Creates the XML request for a 'entityRequest' type of transaction
 *
 */
function MakeXmlEntityRequest(jspName, entityTypeCd, entityId, isForeignKey, tsName, docPath, actionCd)
{
    // build the xmlRequest object
    var txRequest = new Object();

    // If this is a piped list of entity IDs, parse and flatten them.
	if(entityId != null && entityId.charAt(0) == '|' && entityId.charAt(entityId.length-1) == '|')
    	var entityIdArray = PipeSetToArrayAll(entityId, true);

    if((entityIdArray != null) && (entityIdArray.length > 1))
    {
        var requestName = 'SearchRequest';
        txRequest.searchType = 'entityId';
        txRequest.searchValue = '|' + entityIdArray.join('|') + '|';
    }
    else
    {
        var requestName = 'EntityRequest';
        txRequest.entityId = entityId;
    }

    txRequest.entityTypeCd = entityTypeCd;
    txRequest.tsName = tsName;
    txRequest.contextDocPath = docPath;

    if(actionCd != null)
        txRequest.actionCd = actionCd;
	if (/formattoprint/.test(jspName)) //If the action is in the URL
		txRequest.actionCd = 'formattoprint';

    if(isForeignKey)
        txRequest.tsName = GetDefaultTsName(entityTypeCd);

    var xmlRequest = ObjectToXml(txRequest, requestName);
//    alert('XML request: ' + xmlRequest);

    return xmlRequest;
}

/**
 * Creates the XML request for a 'entityRequest' type of transaction
 * Uses the passed in form to build a table object
 */
function makeXmlEntityRequestFromForm(mainForm, actionForm, entityId, docPath)
{
    // build the xmlRequest object
    var entityRequest = new Object();

    entityRequest.tsName = actionForm.tsName.value;
	entityRequest.entityTypeCd = actionForm.entityTypeCd.value;
	entityRequest.actionCd = actionForm.actionCd.value;

    entityRequest.entityId = entityId;
    entityRequest.contextDocPath = docPath;

	var ColumnDef = new Object();
	var Row = new Object();
	Row.csv = '';
    var columnDefs = new Array();
	var addComma = false;
	var value = '';

	for (var i=0; i<mainForm.elements.length; i++)
	{
		if ((mainForm.elements[i].type == "text") ||
		    (mainForm.elements[i].type == "textarea") ||
			(mainForm.elements[i].type == "hidden"))
		{
			ColumnDef = new Object();
			ColumnDef.name = mainForm.elements[i].name;
			columnDefs[i] = ColumnDef;
			value = mainForm.elements[i].value;
			if ((/,/.test(value)) || (/\'/.test(value)) || (/\"/.test(value)) )
			{   //There is a comma or quote or double quote in the string
				if (addComma) Row.csv += ",'";
				else Row.csv += "'";
				Row.csv += value.replace(/\'/g, "''");
				Row.csv += "'";
			}
			else
			{
				if (addComma) Row.csv += ',';
				Row.csv += value;
			}
			addComma = true;
		}
	}
	entityRequest.Table = new Object();
	entityRequest.Table.ColumnDefs = columnDefs;
	var rows = new Array();
	rows[0] = Row;
	entityRequest.Table.Rows = rows;
    var xmlRequest = ObjectToXml(entityRequest, 'EntityRequest');
	//alert('XML request: ' + xmlRequest);
    return xmlRequest;
}

/**
 * Creates an XML dynamic search request object.
 */
function MakeXmlSearchRequest(entityTypeCd, searchFilter, tsName, actionCd, cols, params, contextDocPath)
{
    if (params != null)
        eval("var searchRequest = " + params);  // eval the Javascript to create request object
    else
        var searchRequest = new Object();
	searchRequest.mType        = 'SearchRequest';
	searchRequest.mName        = 'SearchRequest';
	searchRequest.searchType = 'dynamic';
    if (entityTypeCd != null)
        searchRequest.entityTypeCd = entityTypeCd;
    if (searchFilter != null)
        searchRequest.Filter = searchFilter;
    if (tsName != null)
        searchRequest.tsName = tsName;
	if (actionCd != null)
	    searchRequest.actionSubCd  = actionCd;
    if (cols != null)
        searchRequest.Column = cols;
 	searchRequest.contextDocPath  = contextDocPath;
    return ObjectToXml(searchRequest);
}

/**
 * Creates an XML dynamic search request object.
 */
function MakeXmlSearchByClassRequest(entityTypeCd, classSearchType, searchValue, tsName, cols, params, contextDocPath)
{
    if (params != null)
        eval("var searchRequest = " + params);  // eval the Javascript to create request object
    else
        var searchRequest = new Object();
	searchRequest.mType        = 'SearchRequest';
	searchRequest.mName        = 'SearchRequest';
	searchRequest.searchType = 'usClasses';
    if (entityTypeCd != null)
        searchRequest.entityTypeCd = entityTypeCd;
    if (searchValue != null)
        searchRequest.searchValue = searchValue;
    if (classSearchType != null)
        searchReq.classSearchType
    if (tsName != null)
        searchRequest.tsName = tsName;
    if (cols != null)
        searchRequest.Column = cols;
	searchRequest.contextDocPath  = contextDocPath;
    return ObjectToXml(searchRequest);
}

/**
 * Creates an XML Search By Id request object.
 */
function MakeXmlSearchByIdRequest(actionSubCd, entityTypeCd, entityIdList, tsName, cols, params, contextDocPath)
{
    if (params != null)
        eval("var searchRequest = " + params);  // eval the Javascript to create request object
    else
        var searchRequest = new Object();
	searchRequest.mType        = 'SearchRequest';
	searchRequest.mName        = 'SearchRequest';
	searchRequest.searchType = 'entityId';
	if (actionSubCd != null)
	    searchRequest.actionSubCd = actionSubCd;
    if (entityTypeCd != null)
        searchRequest.entityTypeCd = entityTypeCd;
    if (entityIdList != null)
        searchRequest.searchValue = entityIdList;
    if (tsName != null)
        searchRequest.tsName = tsName;
    if (cols != null)
        searchRequest.Column = cols;
 	searchRequest.contextDocPath  = contextDocPath;
    return ObjectToXml(searchRequest);
}

/**
 * Get the icon image of the result info with the highest priority (ok, warning, error).
 * Subrequests are searched by default.
 */
function GetResultInfoIconImg(txRecord, includeSubRequests)
{
    if  (includeSubRequests == null)
        includeSubRequests = true;
    var maxIndex = getMaxResultInfoTypeIndex(txRecord, includeSubRequests);
    return resultInfoTypes[maxIndex].iconImg;
}

/**
 * Get the icon image for this result info.
 */
function GetResultInfoTypeIconImg(resultInfo)
{
    return resultInfoTypes[getResultInfoTypeIndex(resultInfo)].iconImg;
}

/**
 * The result info icon image is the most severe type (ok, warning, error) of all result info
 * entries. Subrequests are searched by default.
 */
function getMaxResultInfoTypeIndex(txRecord, includeSubRequests)
{
    var maxIndex = 0;
    if (txRecord.ResultInfo && txRecord.ResultInfo.length > 0)
    {
	    for ( var iResult = 0; iResult < txRecord.ResultInfo.length; iResult++ )
	    {
	        var result = txRecord.ResultInfo[iResult];
            var typeIndex = getResultInfoTypeIndex(result);
	        if (typeIndex > maxIndex)
	            maxIndex = typeIndex;
        }
    }
    if (maxIndex == resultInfoTypes.length)
        return maxIndex;

    if (includeSubRequests && txRecord.SubRequest && txRecord.SubRequest.length > 0)
    {
	    for ( var iSubRequest = 0; iSubRequest < txRecord.SubRequest.length; iSubRequest++ )
	    {
	        var subrequest = txRecord.SubRequest[iSubRequest];
            var subMaxIndex = getMaxResultInfoTypeIndex(subrequest, true)
            if (subMaxIndex > maxIndex)
	            maxIndex = subMaxIndex;
        }
    }
    return maxIndex;
}

/**
 * Get the type index for this result info.
 */
function getResultInfoTypeIndex(resultInfo)
{
    if (resultInfo == null)
        return;

    var typeIndex = 0;
    for (var n = 0; n < resultInfoTypes.length; n++)
    {
	    if (resultInfo.type == resultInfoTypes[n].type)
	    {
	        typeIndex=n;
	        break;
        }
     }
	 return typeIndex;
}

/**
 * The order is based on priority (low to high). 'ok' doesn't have an icon image defined because
 * success is assumed when an icon is not show.
 */
var resultInfoTypes = [ { type : 'ok' }, { type : 'warning', iconImg : 'warning.gif' }, { type : 'error', iconImg : 'error.gif'} ];

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 
// The page state table holds page state instances. Each uniquely identified
// by a pageID. A JSPs only needs to call PageStatetable.savePageState() when ready to
// store its page state.
function PageStateTable() {
    this.entries = new Array(1);
    this.curIndex = -1;
}

// A class property defining the maximum entries contained in the table.
PageStateTable.$maxSize = 1;        // Only one is supported now.

// The page state is saved in a cookie. The current state is read, updated,
// and written. There is a small window of "opportunity" for a page state
// to be lost if two threads call this method at the same time.
PageStateTable.savePageState = function(pageState) {
    //DebugDumpObject("saving page state", pageState);
    // Get the current state.
    var pt = PageStateTable.restore();
    // Add the new page state. Possibly, overwriting the oldest entry.
    if (pt.replacePageState(pageState))
    {
        pt.store();
        return;
    }
    // A match not found. Add it.
    pt.addPageState(pageState);
    //DebugDumpObject("savePageState", pt);
    // Store the new state
    pt.store();
}

// Get a page state with the matching page ID. Returns null if a matching page
// state is not found.
PageStateTable.getPageState = function(pageID) {
    // Get the current state.
    var pt = PageStateTable.restore();
    //DebugDumpObject("getPageState", pt);
    // Find a page state with a matching pageID
    for (var i=0; i<PageStateTable.$maxSize; i++) {
        var e = pt.entries[i];
        if (e == null)
            continue;
        if (e.pageID==null)
            continue;
        //DebugText("Comparing " + e.pageID + " and " + pageID);
        if (e.pageID == pageID)
            return e;
    }
    return null;
}

// Add a page state instance to the internal array. This function is considered "private".
PageStateTable.prototype.addPageState = function(ps) {

    // Its an object literal if 'ps' is a string. Eval it so it becomes an object.
    var state = ps;
    if (typeof ps == "string")
        eval('state = '  + ps);

    // Not found. Add the page state possibly overriding the oldest entry.
    if (this.curIndex >= PageStateTable.$maxSize-1)
        this.curIndex=0;
    else
        this.curIndex++;

    this.entries[this.curIndex]=state;
}

// Search for a match page state. Replace its contents with the new one.
PageStateTable.prototype.replacePageState = function(ps) {

    // Its an object literal if 'ps' is a string. Eval it so it becomes an object.
    var state = ps;
    if (typeof ps == "string")
        eval("state = " + ps + ";");
    // Check to see if a matching page ID is defined. Replace it if found.
    for (var i=0; i<PageStateTable.$maxSize; i++) {
        var e = this.entries[i];
        if (e == null)
            continue;
        //DebugText("Comparing " + e.pageID + " and " + state.pageID);
        if (e.pageID == state.pageID)
        {
            this.entries[i]=state;
            return true;
        }
    }
    return false;
}

// Write the this instance's contents to the "PageStateTable" cookie. This function
// is considered "private".
PageStateTable.prototype.store = function() {
    // Cookie is valid only for this page.
    var pageStateCookie = new Cookie(document, "PageStateTable", null);
 /*
    for (var i=0; i<PageStateTable.$maxSize; i++) {
        var e = this.entries[i];
        if (e != null)
        {
            var s = ObjectToJs(e);
            eval("pageStateCookie.pageState_"+ i.toString() + " = \"" + s + "\";");
        }
    }
 */
    pageStateCookie.pageState = ObjectToJs(this.entries[0]);
    //DebugDumpObject("pageStateCookie", pageStateCookie);
    pageStateCookie.store();
}

// Create a PageStateTable instance. Populate with the "PageStateTable" cookie. This
// function is considered "private".
PageStateTable.restore = function() {
    var table = new PageStateTable();
    // First, read the current page state stored in the cookie
    var pageStateCookie = new Cookie(document, "PageStateTable", null, "/");
    pageStateCookie.load();

    //DebugDumpObject("pageStateCookie", pageStateCookie);
    var index=0;
    for (var prop in pageStateCookie) {
        // Ignore all properties except those begining with "pageState".
        if (prop.indexOf("pageState") != 0)
            continue;
        table.addPageState(pageStateCookie[prop]);
    }
    return table;
}

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 
//	Core UI classes and helper routines

//// DEPRECATED FUNCTIONS  //////////
function getObject(domElemId) 	{ return GetDomElem(domElemId); };
function getElem(id)			{ return GetUiElem(id); }

////////////////////////////////////

var FWK_CONTROL 		= window;
var IMG_PATH 			= '/img/';
var SHIM 				= '<img src="' + IMG_PATH + 'shim.gif" border="0" height="1" width="1">';
var UI_ELEMENT_ARRAY 	= new Array;
var UI_ELEMENT_ID_COUNTER = 0;

var UI_SELECT_HILITE	= "#FFD279";//"Khaki"

var gColors = {
	fg:  			"#F4F8FD",
	fgLight:		"#FCFCFE",
	fgDark:			"#003399",
	fgMajor:		"#49499E",
	fgNormal:		"#000080",
	fgError:		"#FF0000",
	bg:  			"#0000FF",
	bgHilite:		"Khaki"
	};

//--------------------------------------------------------------------------------//
var UI_PROTO = "<proto>"

function UiPrototype(uiClass)
{
	return new uiClass(UI_PROTO);
}

function IsUiProtoRequest(args)
{
	return (args.length == 1 && args[0] == UI_PROTO);
}

//--------------------------------------------------------------------------------//
//	Manage popups:
//	Keep track of popups so that we can dismiss them if there's a click  outside the popup.
//--------------------------------------------------------------------------------//
var popupRegistry = new Array();
var popupDebug = false;

function UiPostPopup(domElem, uiElem, uiElemOwner)
{
	// The domElem is the containing Dom Element that encloses the HTML for the popup.
	// It does not need to be the Dom Element identified by uiElem.domElemId.

	// If reusing a container, clear out all previous references to it
	for(n=0;  n < popupRegistry.length;  n++) {
		var popup = popupRegistry[n];
		if(popup.domElem == domElem)
			popup.time = -1;
	}

	var popup = {domElem: domElem, uiElem: uiElem, uiElemOwner: uiElemOwner, time: new Date().getTime()};
	popup.domElem.style.display = "block";
	popupRegistry.push(popup);

	if(popupDebug)
		DebugText("Register Popup:  containerDomId=" + popup.domElem.id +
				",  uiElem.domElemId=" + popup.uiElem.domElemId +
				", x="+ domElem.style.left + ", y=" + domElem.style.top);
}

//--------------------------------------------------------------------------------//
function UiHidePopups()
{
	var time = new Date().getTime();
	if(popupDebug)
		DebugText("Clear popups:" + time);

	for(n=0;  n < popupRegistry.length;  n++) {
		var popup = popupRegistry[n];
		if(popupDebug)
			DebugText("Consider Hide it:  containerDomId=" + popup.domElem.id + ",  uiElem.domElemId=" + popup.uiElem.domElemId + ", time - popup.time=" + (time - popup.time) );
		// Dismiss poupu only if it's been up for at 500 msec.  This helps keep the click that raises
		// the popup from dismissing it.
		if(popup.time > 0 && (true || time - popup.time > 500)) {
			popup.domElem.style.display = "none";
			if(popup.uiElemOwner && popup.uiElemOwner.hide)
				popup.uiElemOwner.hide(popup.domElem, popup.uiElem);	// Tell uiElem owner that we hid its uiElem

			popup.time = 0;
			if(popupDebug)
				DebugText("Hide it:  containerDomId=" + popup.domElem.id + ",  uiElem.domElemId=" + popup.uiElem.domElemId)
		}
		else
			if(popupDebug)
				DebugText("Reject the hide:  containerDomId=" + popup.domElem.id + ",  uiElem.domElemId="
						+ popup.uiElem.domElemId + ",  delta Time =" + (time-popup.time));
	}
}

//--------------------------------------------------------------------------------//
//	Utilities for Dom Elements
//--------------------------------------------------------------------------------//
function GetDomElem(domElemId)
{
	return document.getElementById(domElemId);
}

function GetAbsBounds(domElem)
{
	var bounds = {left: 0, top: 0, right: domElem.offsetWidth, bottom: domElem.offsetHeight};
	while(domElem.offsetParent) {
		bounds.left  += domElem.offsetLeft - domElem.scrollLeft;
		bounds.top  += domElem.offsetTop  - domElem.scrollTop;
		domElem = domElem.offsetParent;
	}
	bounds.right += bounds.left;
	bounds.bottom += bounds.top;
	return bounds;
}

function GetAbsPos(domElem, container)
{
	if(typeof domElem == "string")
		domElem = GetDomElem(domElem);

	var pos = {left: 0, top: 0};

	while(domElem.offsetParent) {
		pos.left  += domElem.offsetLeft - domElem.scrollLeft;
		pos.top  += domElem.offsetTop  - domElem.scrollTop;
		domElem = domElem.offsetParent;
		if(container && domElem != container)
			break;
	}
	return pos;
}

//--------------------------------------------------------------------------------//
// Returns the left-most pixel location of a given DOM element given an object reference.
//--------------------------------------------------------------------------------//
function GetAbsLeft(domElem)
{
	if(typeof domElem == "string")
		domElem = GetDomElem(domElem);

	var left = 0
	while(domElem.offsetParent) {
		left   += domElem.offsetLeft - domElem.scrollLeft;
		domElem = domElem.offsetParent;
	}
	return left;
}

//--------------------------------------------------------------------------------//
//	Returns the top-most pixel location of a given DOM element given an object reference.
//--------------------------------------------------------------------------------//

function GetAbsTop(domElem)
{
	if(typeof domElem == "string")
		domElem = GetDomElem(domElem);

	var top = 0
	while(domElem.offsetParent) {
		top    += domElem.offsetTop - domElem.scrollTop;
		domElem = domElem.offsetParent;
	}
	return top;
}

//--------------------------------------------------------------------------------//
// Returns an UIElement object from the array containing all the UIElement objects
//--------------------------------------------------------------------------------//
function GetUiElem(id)
{
	return UI_ELEMENT_ARRAY[id];
}

function ForgetUiElem(uiElem)
{
	if(uiElem != undefined && uiElem != null && uiElem.isUIElement) {
		if(typeof uiElem.dispose == "function")
			uiElem.dispose();
		UI_ELEMENT_ARRAY[uiElem.id] = null;
	}
}

function SetHTML(domElem, html)
{
	if(typeof domElem == "string")
		domElem = GetDomElem(domElem);
	domElem.innerHTML = html;
}

//--------------------------------------------------------------------------------//
// BEGIN: UIElement Class
//--------------------------------------------------------------------------------//

//--------------------------------------------------------------------------------//
//Deprecated uiElementInit() called by the old style of UI Objects.  Has to manually
// set all the methods since the old objects don't use prototype based "inheritance."
//--------------------------------------------------------------------------------//

function uiElementInit(object)
{
	object.addButton 			= UIElement.prototype.addButton;
	object.addHTML 				= UIElement.prototype.addHTML;
	object.getHTML 				= UIElement.prototype.getHTML;
	object.pushHTML				= UIElement.prototype.pushHTML;
	object.resetHTML 			= UIElement.prototype.resetHTML;
	object.build				= UIElement.prototype.build;
	object.pushDiv				= UIElement.prototype.pushDiv;
	object.render				= UIElement.prototype.render;
	object.getPopupContainerId	= UIElement.prototype.getPopupContainerId;
	object.addMilestone			= UIElement.prototype.addMilestone;

	object.isUIElement			= true;
	object.classId				= "ui";

	object.uiElementInit 		= UIElement.prototype.uiElementInit;
	object.uiElementInit();
}

//--------------------------------------------------------------------------------//
// The base UI Element class, defining the interface for all .js user interface element objects.
//	This can be used as a template for any element that is not a container.
//--------------------------------------------------------------------------------//
function UIElement(html)
{
	if(arguments.length == 1 && arguments[0] == UI_PROTO)
		return;

	this.uiElementInit();
	if(html)
		this.addHTML(html);
}

UIElement.prototype.classId = "ui";
UIElement.prototype.isUIElement = true;

UIElement.prototype.uiElementInit = function()
{
	this.id 		= UI_ELEMENT_ID_COUNTER++;			// Unique sequence number for the element
	this.domElemId 	= this.classId + "." + this.id;		// ID of the browser DOM element that corresponds to this object
	this.HTML 		= "";
	this.htmlArray 	= null;
	this.htmlIndex 	= 0;

	UI_ELEMENT_ARRAY[this.id] = this;
}

//--------------------------------------------------------------------------------//
//	Add a standard button
//--------------------------------------------------------------------------------//
 UIElement.prototype.addButton = function(label, style, action, target)
{
	var actionPrefix = ""
	if(typeof target == "object" && target != window)
		actionPrefix = GetGlobalName(target) + '.';

	if(typeof action == "string") {
		if(action.indexOf('(') == -1)
			action = 'doAction(\'' + action + '\')';
	}
	else
		action = "doAction(" + action.join(",") + ")";

	// Old compatibility.   Allow an (1) a number for width or (2) a string that is the style attributre.
	if(typeof style == "number")
		style = "width: " + style + "; margin-left: 10px; margin-right: 10px;";
	else if(style == "+")
		style = "margin-right: 14px;";
	else if(!style)
		style = "";

	var onClick = ' onClick="UiCancel(event);' + actionPrefix + action.replace(/"/g,'\\"') + '"';
	if(false) {
		var onMouse = ' onMouseover="this.style.backgroundColor=\'Khaki\'" onMouseout="this.style.backgroundColor=\'Cornsilk\'" onFocus="this.blur()"';
		this.addHTML('<input class="button" type="button" style="' + style + '" ' + onClick + onMouse + ' value="' + label + '">');
	}
	else {
		this.addHTML('<input type="button" style="' + style + '" ' + onClick + ' value="' + label + '"></input>');
	}
}

 UIElement.prototype.addRadioButton = function(label, action, checked, target)
{
	var actionPrefix = ""
	if(typeof target == "object" && target != window)
		actionPrefix = GetGlobalName(target) + '.';

	if(typeof action == "string") {
		if(action.indexOf('(') == -1)
			action = 'doAction(\'' + action + '\')';
	}
	else
		action = "doAction(" + action.join(",") + ")";

	var onClick = ' onClick="' + actionPrefix + action + '" ';
	this.addHTML('<input name="' + this.domElemId + '.radio" type="radio" '  + (checked ? 'checked ' : '') + onClick + '>' + label + '</input>');
}



//--------------------------------------------------------------------------------//
//	Adds a string to the HTML of the current element
//--------------------------------------------------------------------------------//
UIElement.prototype.addHTML = function(html)
{
	if(this.htmlArray == null)
		this.htmlArray = new Array(this.nHtmlArray ? this.nHtmlArray : 100);
	this.htmlArray[this.htmlIndex++] = html;
}

//--------------------------------------------------------------------------------//
//	Returns the HTML representing the given element and builds it if it does not yet exist.
//--------------------------------------------------------------------------------//
UIElement.prototype.getHTML = function()
{
	if(!this.HTML) {
		if( this.htmlIndex == 0 )
			this.build();
		if(this.htmlIndex > 0)
			this.HTML = this.htmlArray.join("");
	}
	return this.HTML;
}

//--------------------------------------------------------------------------------//
//	Resets the HTML contents of the element
//--------------------------------------------------------------------------------//
UIElement.prototype.resetHTML = function()
{
	if(this.htmlIndex > 0) {
		this.htmlIndex = 0;
		this.htmlArray = null;
		this.HTML = "";
	}
}

//--------------------------------------------------------------------------------//
//	Builds the HTML for a generic UI Element
//--------------------------------------------------------------------------------//
UIElement.prototype.build = function()
{
	if(this.HTML == "")
		this.HTML = "(no content)";		// Should't really be used.  Just indicates that build was not overridden.
}

//--------------------------------------------------------------------------------//
//	Forces the HTML for this object into a designated object.
//	If the input is a string, it is assumed to be an object id.  If it is an object,
//	it is assumed to be the DOM element.
//--------------------------------------------------------------------------------//
UIElement.prototype.pushDiv = function(arg)
{
 	this.pushHTML(arg);	// Backward compatibility;  pushDiv() should should be replaced in the JSPs by pushHTML()
 }

UIElement.prototype.pushHTML = function(arg)
{
	var domElem = arg;

	if(typeof arg == "string")
		domElem = GetDomElem(arg);

	domElem.innerHTML = this.getHTML();
}

//--------------------------------------------------------------------------------//
//	Renders the container to the document inline as a write command
//--------------------------------------------------------------------------------//
UIElement.prototype.render = function()
{
	document.write(this.getHTML());
}

//--------------------------------------------------------------------------------//
//	Container for non-menu popups
//--------------------------------------------------------------------------------//
UIElement.prototype.getPopupContainerId = function()
{
	return this.domElemId + ".popup";
}

//--------------------------------------------------------------------------------//
//	Timestamps a milestone string and adds it to the object history for
//	debugging and optimization purposes.
//--------------------------------------------------------------------------------//
 UIElement.prototype.addMilestone = function(label)
 {
 	if(!this.timing) {
		this.timing = new Array;
		this.time = new Array;
		this.nextMilestone = 0;
	}

	var time = new Date().getTime()
	var delta = (this.nextMilestone > 0) ? time - this.time[this.nextMilestone-1] : 0;
	this.timing[this.nextMilestone] = time + " > " + label + " (" + delta + ")";
	this.time[this.nextMilestone++] = time;
 }

//--------------------------------------------------------------------------------//
function UIButton(label, action, width)
{	// If width is not present in 4th position, it is assumed to be 3rd
	this.uiElementInit();
	this.addButton(label, width, action);
}

UIButton.prototype = UiPrototype(UIElement);

///--------------------------------------------------------------------------------//
function UIContainer(parentContainerId)
{
	if(this.header || this.footer)
		alert("Fix the code that called this UIContainer() initialization");
	uiContainerInit(this);
}

function uiContainerInit(object)
{
	uiElementInit(object);
	object.contents 	= new Array;
	object.addElement 	= uiContainerAddElement;			/** Adds a uiElement or string to the container */
	object.build 		= uiContainerBuildHTML;				/** Creates the HTML for the container */
}

function uiContainerAddElement(element, divId)
{
	this.contents.push({element: element, divId: divId});
}

/**
 * Builds the HTML for a FrameBox object by building the
 * containment HTML and then iterating over the elements
 * contained therein.
 */
function uiContainerBuildHTML()
{
	for(var n = 0; n < this.contents.length; n++) {
		var item = this.contents[n];
		if(item.divId) {
			this.addHTML('<div id="' + item.divId + '">');
			if(typeof item.element.setContainerId == "function")
				item.element.setContainerId(divId);
		}

		if(typeof item.element.getHTML == "function")
			this.addHTML(item.element.getHTML());
		else
			this.addHTML(item.element.toString());

		if(item.divId)
			this.addHTML('</div>');
	}

	if(this.contents.length == 0)
		this.addHTML(SHIM);
}

//--------------------------------------------------------------------------------//
// UIWidget Class
//--------------------------------------------------------------------------------//

//--------------------------------------------------------------------------------//
//	Deprecated uiElementInit() called by the old style of UI Objects.  Has to manually
//	set all the methods since the old objects don't use prototype based "inheritance."
//--------------------------------------------------------------------------------//
function uiWidgetInit(object)
{
	uiElementInit(object);

	object.getContainerId 		= UIWidget.prototype.getContainerId;
	object.setContainerId 		= UIWidget.prototype.setContainerId;
	object.getContainerDomElem	= UIWidget.prototype.getContainerDomElem;
	object.pushHTML				= UIWidget.prototype.pushHTML;

	object.uiWidgetInit			= UIWidget.prototype.uiWidgetInit;
	object.uiWidgetInit();
}

//--------------------------------------------------------------------------------//
//	A Widget is a composite, high-level object that lives in a <div> container
//	Created new on 12/15/2003 to be the ancestor of complex widgets like
//	UIView, UIMap, UIFolderTree, UIBasic Table, etc
//--------------------------------------------------------------------------------//
function UIWidget(containerId)
{
	if(arguments.length == 1 && arguments[0] == UI_PROTO)
		return;

	if(containerId)
		this.containerId = containerId;

	this.uiWidgetInit();
}

UIWidget.prototype 			= UiPrototype(UIElement);
UIWidget.prototype.cssClass	= "uiWidget";

UIWidget.prototype.uiWidgetInit = function()
{
	this.uiElementInit();
	this.containerId 		= null;		// HTML id of container, typically a <div>
	this.containerDomElem 	= null;		// Dom element corresponding to containerId
}

UIWidget.prototype.getContainerId = function()
{
	return this.containerId;
}

UIWidget.prototype.setContainerId = function(containerId)
{
	this.containerId = containerId;
	this.containerDomElem = null;
}

UIWidget.prototype.getContainerDomElem = function()
{
	if(!this.containerDomElem)
		this.containerDomElem = GetDomElem(this.containerId);
	return this.containerDomElem;
}

UIWidget.prototype.pushHTML = function(target)
{
	if(typeof target == "object") {
		this.setContainerId(target.id);		// Assume target to be a domDomElem
		this.containerDomElem = target;
	}
	else
		this.setContainerId(target);		// Assume target to be a domDomElemId

	this.getContainerDomElem().innerHTML = this.getHTML();
}

//--------------------------------------------------------------------------------//
//	Utilities for mouse and event
//--------------------------------------------------------------------------------//

var uiMouseClient = null;
var uiMousePropagateUnhandledEvent = true;
var uiMouseInhibitGeneralSelect = true;

var gMouseupCounter = 0;
var gMousedownCounter = 0;
var gEventTarget;

function UiMouseInhibitGeneralSelect(inhibitGeneralSelect)
{
	uiMouseInhibitGeneralSelect = inhibitGeneralSelect;
}

function UiMouseExclusiveClient(uiClient, propagateUnhandledEvents)
{
	uiMouseClient = uiClient;
	uiMousePropagateUnhandledEvent = uiClient ? !(!propagateUnhandledEvents) : true;
}

//--------------------------------------------------------------------------------//
//	Set the browser's event handlers so that we can override the routing of events to a uiClient object.
//--------------------------------------------------------------------------------//
UiMouseExclusiveClientInit();

function UiMouseExclusiveClientInit()
{
	var gEventTarget = document;

	if(document.captureEvents) {
		gEventTarget = window;
		gEventTarget.captureEvents(Event.CLICK | Event.MOUSEDOWN | Event.MOUSEUP | Event.MOUSEMOVE | Event.MOUSEOVER | Event.MOUSEOUT | Event.ONSELECT| Event.ONSELECTSTART);
	}

	gEventTarget.onclick = function(event) {
							if(!uiMouseClient || !uiMouseClient.click)
								return uiMousePropagateUnhandledEvent;
							return uiMouseClient.click(event ? event : window.event);
						}
	gEventTarget.onmousedown = function(event) {
							gMousedownCounter++;
							if(!uiMouseClient || !uiMouseClient.mousedown)
								return uiMousePropagateUnhandledEvent;
							return uiMouseClient.mousedown(event ? event : window.event);
						}
	gEventTarget.onmouseup = function(event) {
							gMouseupCounter++;
							if(!uiMouseClient || !uiMouseClient.mouseup)
								return uiMousePropagateUnhandledEvent;
							return uiMouseClient.mouseup(event ? event : window.event);
						}
	gEventTarget.onmousemove = function(event) {
							if(!uiMouseClient || !uiMouseClient.mousemove)
								return uiMousePropagateUnhandledEvent;
							return uiMouseClient.mousemove(event ? event : window.event);
						}
	gEventTarget.onmouseover = function(event) {
							if(!uiMouseClient || !uiMouseClient.mouseover)
								return uiMousePropagateUnhandledEvent;
							return uiMouseClient.mouseover(event ? event : window.event);
						}
	gEventTarget.onmouseout = function(event) {
							if(!uiMouseClient || !uiMouseClient.mouseout)
								return uiMousePropagateUnhandledEvent;
							return uiMouseClient.mouseout(event ? event : window.event);
						}
	gEventTarget.onselectstart = function(event) {
							if(!event)
								event = window.event;
							if(!uiMouseInhibitGeneralSelect || event.altKey)
								return true;
							var tagName = UiTargetElem(event).tagName;
							if(tagName == "INPUT" || tagName == "TEXTAREA")
								return true;
							event.cancelBubble = true;
							return false;
						}
	gEventTarget.onselect = function(event) {
							if(!uiMouseInhibitGeneralSelect)
								return true;
							if(!event)
								event = window.event;
							var tagName = UiTargetElem(event).tagName;
							if(tagName == "INPUT" || tagName == "TEXTAREA")
								return true;
							DebugText(event.srcElement.tagName + " select --- " + event.srcElement.name );
							event.cancelBubble = true;
							return false;
						}
}

function UiTargetElem(event)
{
	var elem = event.target ? event.target : event.srcElement;
	return (elem.nodeType == 1 || elem.nodeType == 9) ? elem : elem.parentNode;
}

//--------------------------------------------------------------------------------//
//	Routines for modifying event porpagation
//--------------------------------------------------------------------------------//

function UiCancelEvent(event)
{
	if(event.stopPropagation) {
		event.stopPropagation();
		event.preventDefault();
	}
	else {
		window.event.cancelBubble = true;
		window.event.returnValue = false;
	}
}

function UiCancel(event)
{
	UiCancelEvent(event);
	UiHidePopups();
}
//--------------------------------------------------------------------------------//
//	Repackage a browser event, computing the absolute window coordinates of the mouse
//--------------------------------------------------------------------------------//
function UiMouseEvent(event)
{
	var e;
	if(window.event) {
		x = window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
		y = window.event.clientY + document.documentElement.scrollTop  + document.body.scrollTop;
		e = {x: x, y: y, event: window.event};
	}
	else {
		x = event.clientX + window.scrollX;
		y = event.clientY + window.scrollY;
		e = {x: x, y: y, event: event};
	}
	return e;
}
//--------------------------------------------------------------------------------//
//	Compute the event coordinates relative to the target DOM element
//--------------------------------------------------------------------------------//
function UiMouseToElemCoord(event)
{
	var coords = {x: event.clientX, y: event.clientY};
	for(var domElem=event.target ? event.target : event.srcElement;  domElem;  domElem=domElem.offsetParent) {
		coords.x -= domElem.offsetLeft - domElem.scrollLeft;
		coords.y -= domElem.offsetTop  - domElem.scrollTop;
	}
	return coords;
}

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 

/**
 * Constructor
 *
 */
function UIDialog(title, width, style, collapse)
{
// INITIALIZE
	uiDialogInit(this);

// ARGUMENT INITIALIZATION

	this.title = title;
	this.width = width;
	this.style = style;		
	if ( collapse != null )
		this.collapse = collapse;
}


/** 
 * Initializer (inherits)
 */
function uiDialogInit(object)
{
// INHERIT
	uiContainerInit(object);

// MEMBER VARIABLES
	object.colImg = IMG_PATH + 'ico_sect_aro_right.gif';
	object.expImg = IMG_PATH + 'ico_sect_aro_down.gif';
	object.stdImg = IMG_PATH + 'ico_ipv.gif';
	object.title = null;
	object.width = null;
	object.style = "default";
	object.collapse = false;
	object.isOpen = false;
	object.summary = '[Unknown]';
	object.child = false;

// PUBLIC METHODS

// INTERNAL METHODS

	/** contructs the header for the container */
	object.makeHeader = uiDialogMakeHeader;
	/** constructs the footer for the container */
	object.makeFooter = uiDialogMakeFooter;
	/** toggles the display of the content on and off */
	object.toggleDisplay = uiDialogToggleDisplay;
	/** resets the summary for the Collapsable dialog */
	object.resetSummary = uiDialogResetSummary;
	/** resets the title for the Dialog */
	object.resetTitle = uiDialogResetTitle;

// STATIC INITIALIZATION

}

//------------------------------------------------------------------
// PUBLIC CLASS METHODS
//------------------------------------------------------------------

/** Display or undisplay the content of the dialog */
function uiDialogToggleDisplay()
{

	var img = GetDomElem('dlg.img.' + this.id);
	var text = GetDomElem('dlg.inner.cont.' + this.id);
	var summ = GetDomElem('dlg.sum.' + this.id);

	if ( this.child )
		this.summary = '<font class="info">' + this.child.getSummary() + '</font>';
	summ.innerHTML = this.summary;

	if ( this.collapse )
	{
		text.style.display = 'block';
		summ.style.display = 'none';
		img.src = this.expImg;
		this.collapse = false;
	}
	else
	{
		text.style.display = 'none';
		summ.style.display = 'block';
		img.src = this.colImg;
		this.collapse = true;
	}
}

/** Resets the dialog summary */
function uiDialogResetSummary()
{
	var summ = GetDomElem('dlg.sum.' + this.id);
	if ( this.child )
		this.summary = '<font class="info">' + this.child.getSummary() + '</font>';
	summ.innerHTML = this.summary;
}

/** Changes the Title for a UIDialog Object */
function uiDialogResetTitle(title)
{
	this.title = title;
	var titleSpan = GetDomElem('dlg.title.' + this.id);
	titleSpan.innerHTML = this.title;		
}

//------------------------------------------------------------------
// INTERNAL CLASS METHODS
//------------------------------------------------------------------

/**
 * Builds the Header HTML for the basic dialog, according to the set
 * width of the dialog, and including the dialog title.
 *
 */
function uiDialogMakeHeader()
{

	if ( this.child )
		this.summary = this.child.getSummary();

	var widthA = this.width;
	var widthB = this.width - 12;
	var widthC = this.width - 2;
	var SPACER = IMG_PATH + "shim.gif";
	var BG_LINE_COLOR = "#64ACF6";
	var BG_MED = "#ADD8FA";
	var BG_LIGHT = "#f7f7f7";
	var display = 'block';
	if ( this.collapse )
		display = 'none';

	var html = 	'';

	html +=	'<table cellSpacing="0" cellPadding="0" width="' + widthA + '" border="0" class="dialog">';		
	html +=	'<tr>';
	html +=	'<td colspan="6" width="' + widthA + '" bgColor="'+ BG_LINE_COLOR +'" height="1"><img src="' + SPACER +'" width="1" height="1"></td>';
	html +=	'</tr>';
	html +=	'<tr>';
	html +=	'<td width="1" bgColor="'+ BG_LINE_COLOR +'"><img src="'+ SPACER +'" width="1" height="5"></td>';
	html +=	'<td width="'+ widthC +'" bgColor="'+ BG_MED +'" colspan="4"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'<td width="1" bgColor="'+ BG_LINE_COLOR +'"><img src="'+ SPACER +'" width="1" height="5"></td>';
	html +=	'</tr>';
	html +=	'<tr>';
	html +=	'<td width="1" bgColor="'+ BG_LINE_COLOR +'" rowSpan="2"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'<td width="5" bgColor="'+ BG_MED +'"><img src="'+ SPACER +'" width="1" height="1"></td>';

	if ( !this.collapse )	
	{
		html += '<td width="14" bgColor="'+ BG_MED +'"><img width="13" height="13" src="' + SPACER + '"></td>';
		html +=	'<td width="' + (widthB - 14) + '" bgColor="'+ BG_MED +'"><span id="dlg.title.' + this.id + '" class="dlgTitle">'+ this.title + '</span></td>';
	}
	else
	{
		html += '<td width="14" bgColor="'+ BG_MED +'"><a href="javascript:GetUiElem(' + this.id + ').toggleDisplay()" class="nft"><img src="' + this.colImg + '" id="dlg.img.' + this.id + '"></a></td>';
		html +=	'<td width="'+ (widthB - 14) +'" bgColor="'+ BG_MED +'"><a href="javascript:GetUiElem(' + this.id + ').toggleDisplay()" class="nft"><span id="dlg.title.' + this.id + '" class="dlgTitle">'+ this.title + '</span></a></td>';
	}


	html +=	'<td width="5" bgColor="'+ BG_MED +'"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'<td width="1" bgColor="'+ BG_LINE_COLOR +'" rowSpan="2"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'</tr>';
	html +=	'<tr>';
	html +=	'<td width="'+ widthC +'" bgColor="'+ BG_MED +'" colSpan="4" height="3"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'</tr>';
	html +=	'<tr>';
	html +=	'<td width="1" bgColor="'+ BG_LINE_COLOR +'"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'<td width="'+ widthC +'" bgColor="'+ BG_LINE_COLOR +'" colSpan="4" height="1"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'<td width="1" bgColor="'+ BG_LINE_COLOR +'"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'</tr>';
	html +=	'<tr>';
	html +=	'<td width="1" bgColor="'+ BG_LINE_COLOR +'" rowSpan="2"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'<td width="5" bgColor="'+ BG_LIGHT +'" rowSpan="2"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'<td align="left" width="'+ widthB +'" bgColor="'+ BG_LIGHT +'" colspan="2"><img border="0" src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'<td width="5" bgColor="'+ BG_LIGHT +'" rowSpan="2"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'<td width="1" bgColor="'+ BG_LINE_COLOR +'" rowSpan="2"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'</tr>';
	html +=	'<tr>';
	html +=	'<td class="bgLightShade" colspan="2"><div id="dlg.inner.cont.' + this.id + '" style="display: ' + display + '">';				

	return html;
}

/**
 * Builds the footer HTML for the Dialog
 */
function uiDialogMakeFooter()
{
	var widthA = this.width;
	var widthB = this.width - 12;
	var widthC = this.width - 2;
	var SPACER = IMG_PATH + "shim.gif";
	var BG_LINE_COLOR = "#64ACF6";
	var BG_MED = "#ADD8FA";
	var BG_LIGHT = "#f7f7f7";

	var html = '';

	html +=	'</div>';

	if ( this.collapse )
		html += '<div id="dlg.sum.' + this.id + '" style="display: block"><font class="info">' + this.summary + '</font></div>';

	html += '</td>';
	html +=	'</tr>';
	html +=	'<tr>';
	html +=	'<td width="1" bgColor="'+ BG_LINE_COLOR +'"><img src="'+ SPACER +'" width="1" height="5"></td>';
	html +=	'<td width="'+ widthC +'" bgColor="'+ BG_LIGHT +'" colspan="4"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'<td width="1" bgColor="'+ BG_LINE_COLOR +'"><img src="'+ SPACER +'" width="1" height="5"></td>';
	html +=	'</tr>';
	html +=	'<tr>';
	html +=	'<td colspan="6" width="'+ widthA +'" bgColor="'+ BG_LINE_COLOR +'" height="1"><img src="'+ SPACER +'" width="1" height="1"></td>';
	html +=	'</tr>';		
	html +=	'</table>';

	return html;
}

//========================================================================
// END: UIDialog Class 
//========================================================================

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 

function UIExpander(title, contents, summary, isOpen)
{
	this.uiExpanderInit(title, contents, summary, isOpen);
}

//------------------------------------------------------------------------------------------//
UIExpander.prototype 				= UiPrototype(UIElement);
UIExpander.prototype.openImage 		= IMG_PATH + 'ico_sect_aro_down.gif';
UIExpander.prototype.closedImage 	= IMG_PATH + 'ico_sect_aro_right.gif';;
UIExpander.prototype.bgLineColor	= '#64ACF6';
UIExpander.prototype.emptyContents	= "&nbsp;";

UIExpander.prototype.title 			= '[Default Title]';
UIExpander.prototype.summary 		= '';
UIExpander.prototype.isOpen			= false;

//------------------------------------------------------------------------------------------//
UIExpander.prototype.uiExpanderInit = function(title, contents, summary, isOpen)
{
	this.uiElementInit();

	this.title = title;
	this.contents = contents;
	this.summary = summary;
	this.isOpen = isOpen;

	this.contentHtml = null;
}

//------------------------------------------------------------------------------------------//
UIExpander.prototype.build = function()
{
	var SPACER = IMG_PATH + 'shim.gif';
	this.resetHTML();
	this.addHTML('<table border="0" width="100%" cellspacing="0" cellpadding="0">');
	this.addHTML('<tr><td bgColor="' + this.bgLineColor + '" colspan="5"><img border="0" src="' + SPACER +'" width="1" height="1"></td></tr>');
	this.addHTML('<tr><td bgColor="' + this.bgLineColor + '" width="1"><img border="0"   src="' + SPACER +'" width="1" height="1"></td>');
	this.addHTML('<td class="formSect" width="3"><img border="0" src="' + SPACER +'" width="3" height="1"></td>');
	this.addHTML('<td class="formSect">');
	this.addHTML('<table border="0" width="100%" cellspacing="0" cellpadding="2">');
	this.addHTML('<tr><td width="13"><span onClick="UiCancel(event);GetUiElem(' + this.id + ').toggleSect()" class="nft">');
	this.addHTML( '<img id="' + this.domElemId + '.image"src="' + (this.isOpen ? this.openImage : this.closedImage) + '" width="13" height="13"></span></td>');
	this.addHTML('<td class="formSect"><span id="' + this.domElemId + '.title" onClick="GetUiElem(' + this.id + ').toggleSect()" class="nft">' + this.title + '</span></td>');
	this.addHTML('</tr></table></td>');
	this.addHTML('<td class="formSect" width="3"><img border="0" src="' + SPACER +'" width="3" height="1"></td>');
	this.addHTML('<td bgColor="' + this.bgLineColor + '" width="1"><img border="0" src="' + SPACER +'" width="1" height="1"></td>');
	this.addHTML('</tr><tr>');
	this.addHTML('<td bgColor="' + this.bgLineColor + '" colspan="5"><img border="0" src="' + SPACER +'" width="1" height="1"></td>');
	this.addHTML('</tr><tr>');
	this.addHTML('<td bgColor="' + this.bgLineColor + '" width="1"><img border="0" src="' + SPACER +'" width="1" height="1"></td>');
	this.addHTML('<td width="3"><img border="0" src="' + SPACER +'" width="3" height="1"></td>');

	this.addHTML('<td><table border="0" cellpadding="3" cellspacing="0">');
		this.addHTML('<tr><td><div id="' + this.domElemId + '.contents" ');
		this.addHTML(' style="display: ' + (this.isOpen ? 'block' : 'none') + '">');
		this.addHTML(this.getContentsHtml());
		this.addHTML('</td></tr></div>');

		this.addHTML('<tr><td><div id="' + this.domElemId + '.summary" style="display: ' + (this.isOpen ? 'none' : 'block') + '">' + this.getSummaryHtml() + '</div>');
	this.addHTML('</td></tr></table></td>');

	this.addHTML('<td width="3"><img border="0" src="' + SPACER +'" width="3" height="1"></td>');
	this.addHTML('<td bgColor="' + this.bgLineColor + '" width="1"><img border="0" src="' + SPACER +'" width="1" height="1"></td>');
	this.addHTML('</tr><tr><td bgColor="' + this.bgLineColor + '" colspan="5"><img border="0" src="' + SPACER +'" width="1" height="1"></td>');
	this.addHTML('</tr></table>');
}

//------------------------------------------------------------------------------------------//
UIExpander.prototype.toggleSect = function(isOpen)
{
	if(typeof isOpen == "undefined")
		this.isOpen = !this.isOpen;

	var imageDomElem = GetDomElem(this.domElemId + ".image");

	if(imageDomElem) {
		var contentsDomElem = GetDomElem(this.domElemId + ".contents");
		if(this.isOpen && this.contentsHtml == null)
			contentsDomElem.innerHTML = this.getContentsHtml();

		var summaryDomElem = GetDomElem(this.domElemId + ".summary");
		summaryDomElem.innerHTML = this.getSummaryHtml();

		imageDomElem.src				= this.isOpen ? this.openImage	: this.closedImage;
		contentsDomElem.style.display 	= this.isOpen ? "block" 	: "none";
		summaryDomElem.style.display 	= this.isOpen ? "none"		: "block";
	}
}

//------------------------------------------------------------------------------------------//
UIExpander.prototype.setContent = UIExpander.prototype.setContents = function(contents)
{
	this.contents = contents;
	this.contentsHtml = null;

	var domElem = GetDomElem(this.domElemId + ".contents");
	if(domElem)
		domElem.innerHTML = this.getContentsHtml();
	this.resetSummary();
}

//------------------------------------------------------------------------------------------//
UIExpander.prototype.getContentsHtml = function()
{
	if(this.contentsHtml == null) {
		if(this.contents) {
			if(this.contents.getHTML)
				this.contentsHtml = this.contents.getHTML();
			else {
				// This section which takes HTML form a <div> is deprecated
				var domElem = GetDomElem(this.contents);
				if(domElem) {
					this.contentsHtml = domElem.innerHTML;
					domElem.innerHTML = "";
				}
			}
		}
	}
//	DebugText("RETURNING CONTENTS: " + (this.contentsHtml ? this.contentsHtml.length : "empty"));
	return this.contentsHtml ? this.contentsHtml : this.emptyContents;
}

//------------------------------------------------------------------------------------------//
UIExpander.prototype.resetTitle = function(title)
{
	this.title = title;
	var domElem = GetDomElem(this.domElemId + ".title");
	if(domElem)
		domElem.innerHTML = this.title;
}

//------------------------------------------------------------------------------------------//
UIExpander.prototype.resetSummary = function(summary)
{
	// Note that this.summary is ignored if contents.getSummary() exists
	if(typeof summary != "undefined")
		this.summary = summary;
	this.summaryHtml = null;

	var domElem = GetDomElem(this.domElemId + ".summary");
	if(domElem)
		domElem.innerHTML = this.getSummaryHtml();
}

//------------------------------------------------------------------------------------------//
UIExpander.prototype.getSummaryHtml = function()
{
	var summary = this.summary;
	if(this.contents && this.contents.getSummary)
		summary = this.contents.getSummary();
//	DebugText("SETTING SUMMARY: " + summary);
	if(summary == undefined)
		return "";
	return '<font class="info">' +  ((summary || summary == "") ? summary : '[Open to show contents]') + '</font>';
}

	
/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 

//========================================================================
// BEGIN: UIForm Class
//========================================================================

/**
 * Constructs a new UIForm object with the given title, using the
 * ColumnDefs and display settings as a guideline for building the
 * Form.
 */
function UIForm(title, columnDef, display)
{
// INITIALIZE
	uiFormInit(this);

// ARGUMENT INITIALIZATION
	this.display = display;
	this.columnDef = columnDef;
}


/**
 * Initializer (inherits from uiDialog)
 */
function uiFormInit(object)
{
// INHERIT
	uiDialogInit(object);

// MEMBER VARIABLES
	object.table = null;
	object.hasTable = false;
	object.rowIndex = null;
	object.submitAction = null;
	object.display = null;
	object.columnDef = null;

// PUBLIC METHODS
	object.setValues = 		uiFormSetValues;
	object.getValues = 		uiFormGetValues;
	object.setFocus = 		uiFormSetFocus;
	object.setTable =		uiFormSetTable;
	object.setRow = 		uiFormSetRow;
	object.setAction = 		uiFormSetAction;
	object.doAction = 		uiFormDoAction;
	object.getInputType =	uiFormGetInputType;

// INTERNAL METHODS

// STATIC INITIALIZATION

}

//------------------------------------------------------------------
// PUBLIC CLASS METHODS
//------------------------------------------------------------------



//------------------------------------------------------------------
// INTERNAL CLASS METHODS
//------------------------------------------------------------------

/**
 * Maps field types from a columnDef to default input types
 */
function uiFormGetInputType(coldef)
{
	var type = coldef.type;
	var size = coldef.size;

	if ( type == "" )
		return
}

//------------------------------------------------------------------
// GLOBAL HELPER METHODS
//------------------------------------------------------------------

/**
 * Converts an Object to XML
 */
function ObjXml(elem) {
	var tagName = XmlTagName(elem.mType);
	var xml     = '<' + tagName;
	var elems   = '';

	for(var childName in elem) {
		var child = elem[childName];
		if(typeof child == 'object') {
			if(child.constructor.toString().match(/array/i) == null)
				elems += ObjXml(child);
			else
				elems += ArrayXml(childName, child);
		}
		else {
			xml += " " + childName + '="' + ToXmlText(child) + '"';
		}
	}

	if(elems.length > 0)
		xml += '>\n' + elems +  '</' + tagName + '>\n';
	else
		xml += '/>\n';

	return xml;
}

//***********************************************************************************************
// Convert a Javascript array into an XML document.  Legacy naming of arrays and their child
// components is performed by ToXmlArrayTagName().
//***********************************************************************************************

function ArrayXml(elemName, elem) {
	var csv = null;
	var elems = "";
	var tagNames =  XmlArrayTagName(elemName, elem);

	for(var n=0; n < elem.length;  n++) {
		var child = elem[n];
		if(typeof child == 'object') {
			if(child.constructor.toString().match(/array/i) == null)
				elems += ObjXml(child);
			else
				elems += ArrayXml(tagNames.childName, child);
		}
		else {
			csv = (csv == null) ? elem[n] : (csv + "," + elem[n]);
		}
	}

	var xml = '<' + tagNames.arrayName + ' mName="' + elemName + '"';

	if(csv != null)
		xml += ' csv="' + ToXmlText(csv) + '"';

	if(elems.length > 0)
		xml += '>\n' + elems +  '</' + tagNames.arrayName + '>\n';
	else
		xml += '/>\n';
	return xml;
}

//***********************************************************************************************
// Create the name of the parent array and the name of child arrays (if they exist).
//***********************************************************************************************

function XmlArrayTagName(elemName, elem) {
	var tagName = XmlTagName(elemName);
	var n;

	for(n=0; n < elem.length;  n++) {
		if(typeof elem[n] == 'object')
			break;
	}

	if(n > 0 && n == elem.length)	// Special "csv" case where all array elements are scalars
		return {arrayName: tagName, childName: tagName};

	if(tagName == 'Rows')
		return {arrayName: 'Rows', childName: 'Row'};

	if(tagName == 'ColumnDefs')
		return {arrayName: 'ColumnDefs', childName: 'ColumnDef'};

	return {arrayName: 'List', childName: tagName};
}

//***********************************************************************************************
// Create the name of the object
//***********************************************************************************************

function XmlTagName(elemName) {
	if(elemName) {
		if(elemName.length == 0)
			return "BlankTag";

		var chr = elemName.charAt(0);
		if(chr <'a' || chr >'z')
			return elemName;

		tagName =  elemName.substring(0,1).toUpperCase() + elemName.substring(1);
	}
	else
		tagName = "BlankTag";

	return tagName;
}

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
var IMG_PATH2 = '/img/';

function UIFormInput(width)
{
	uiFormInputInit(this);
	if(width != null )
		this.width = width;
}

/**
 * Initializer (inherits)
 */
function uiFormInputInit(object)
{
// INHERIT
	uiElementInit(object);

// MEMBER VARIABLES
	object.value = null;
	object.name = null;
	object.parent = null;
	object.width = 200;
	object.useLabel = true;

// PUBLIC METHODS
	/** Builds the HTML for the selector */
	object.build = uiFormInputBuild;
	/** Returns the value of the form input */
	object.getValue = uiFormInputGetValue;
	/** Sets the value of the form input */
	object.setValue = uiFormInputSetValue;
	/** Returns the name of the Form Input */
	object.getName = uiFormInputGetName;
	/** Sets the parent Form object */
	object.setParent = uiFormInputSetParent;

// INTERNAL METHODS
	/** Retrieves a pointer to the form input DOM object */
	object.getInput = uiFormInputGetInput;
	/** Resets the internal value for the input based on the current input value */
	object.updateValue = uiFormInputUpdateValue;
	/** Returns the key for the input element */
	object.getInputId = uiFormInputGetInputId;

// STATIC INITIALIZATION

}

//------------------------------------------------------------------
// PUBLIC CLASS METHODS
//------------------------------------------------------------------

/**
 * Constructs the input with a label
 */
function uiFormInputBuild()
{
	this.resetHTML();
	this.addHTML('<table>');

	if(this.label)
		this.addHTML('<tr><td class="inputLabel">' + this.addHTML(this.label) + '</td></tr>');

	this.addHTML('<tr><td>');
	this.addHTML('<input style="width: ' + this.width +'" id="' + this.getInputId() + '" type="text" class="textInput" ');
	if(this.value)
		this.addHTML('value="' + this.addHTML(this.value) + '" ');
	if(this.name)
		this.addHTML('name="' + this.addHTML(this.name) + '" ');

	this.addHTML(' onchange="GetUiElem(' + this.id + ').updateValue()"></td></tr></table>');
}

/** Returns the internal value for the basic input */
function uiFormInputGetValue()
{
	var domElem = this.getInput();
	if(domElem)
		this.value = domElem.value;
	return this.value;
}

/** Sets the internal value and the form input value for the object */
function uiFormInputSetValue(value)
{
	var domElem = this.getInput();
	if(domElem)
		domElem.value = value;
	this.value = value;
}

/** Returns the object name */
function uiFormInputGetName()
{
	return this.name;
}

/** Sets the parent Form for the input */
function uiFormInputSetParent(parent)
{
	this.parent = parent;
}

//------------------------------------------------------------------
// INTERNAL CLASS METHODS
//------------------------------------------------------------------

/** Returns the uniform id for the underlying INPUT DOM object */
function uiFormInputGetInputId()
{
	return 'form.input.' + this.id;
}

/** Returns the INPUT DOM object from the document */
function uiFormInputGetInput()
{
	return GetDomElem( this.getInputId() );
}

/** Updates the internal value to reflect the INPUT DOM object value */
function uiFormInputUpdateValue()
{
	this.value = this.getInput().value;
}

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 
/**
 * Handles border blocks for the user interface that may contain
 * tools, toolbars, menus, and other 3-D delineated objects that
 * frame the UI, or a UI element.
 */
function UIFrame(uiElement, cssClass)
{
	uiFrameInit(this);

	if(cssClass)
		this.cssClass = cssClass;
	if(uiElement)
		this.addElement(uiElement);
}

/**
 * Initializes the Frame Object
 */
function uiFrameInit(object)
{
// INHERIT

	uiContainerInit(object);

// ATTRIBUTES
	object.cssClass		= "uiFrame";
	object.width 		= null;
	object.height 		= null;

// METHODS

	object.baseBuild 	= object.build;		// Save the build of the base class so we can call it during our build.
	object.build 		= uiFrameBuildHTML;
	object.setSize		= uiFrameSetSize;
}

/**
 *   Set width and size for the frame div
 */

function uiFrameSetSize(width, height)
{
	this.width	= width;
	this.height	= height
}

/**
 * Builds the header for the UIFrame object and returns the HTML
 */
function uiFrameBuildHTML()
{
	this.addHTML('<table class="' + this.cssClass + '" id="' + this.domElemId + '" style="');
	if(this.height != null)
		this.addHTML('height: ' + this.height + '; ');
	if(this.width  != null)
		this.addHTML('width: ' + this.width + '; ');
	this.addHTML('"><tr><td>');

	this.baseBuild();

	this.addHTML('<td><tr></table>');
}


/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 
//========================================================================
// GLOBAL UTILITIES THAT DEAL WITH THE DATA:
//			Entities, TableSources, Tables
//========================================================================

var AGGREGATOR_ITEM_CLICK_CD	= "aggregatorItemClick";
var LIST_ACTION_MENU_CLICK_CD	= "listActionMenuClick";
var ACTION_MENU_CLICK_CD	    = "actionMenuClick";
var ENTITY_SET_SELECT_CD	    = "entitySetSelect";
var ENTITY_SELECT_CD	        = "entitySelect";
var APP_HELP_CD					= "appHelp";
var APP_PAGE_SUBMIT				= "submit";

var TABLE_CELL_MAX_CHARS        = 250;


//------------------------------------------------------------------------------------------//
function CloseWindows(isLogout, action)
{
	var remainingWindow = window.windowRoot;
	if(remainingWindow.closed || remainingWindow.opener)
		remainingWindow = window;

 	remainingWindow.focus();
 	if(isLogout)
    	Logout(remainingWindow, action);

	var value = [window.windowRootId, remainingWindow.windowId, new Date().getTime()].toString();
	SetCookie(CloseWindows.COOKIE_NAME, value);
}

CloseWindows.COOKIE_NAME = "CloseWindows";
CloseWindows.MONITOR_INTERVAL_MS = 1000;
//------------------------------------------------------------------------------------------//
function CloseWindowsMonitor()
{
	if(!window.windowId) {
		window.windowId = "" + new Date().getTime();

		var isChild = false;
		try {
			isChild = window.opener && !window.opener.closed && window.opener.windowRoot && window.opener.windowRootId;
		} catch(error) {
			// If the opener is in a different domain than our server, we can't access it, so this
			// windows becomes the root.
		}
		window.windowRoot   = isChild ? window.opener.windowRoot   : window;
		window.windowRootId = isChild ? window.opener.windowRootId : window.windowId;

		setTimeout("CloseWindowsMonitor()", CloseWindows.MONITOR_INTERVAL_MS);
		return;
	}

	var value = GetCookie(CloseWindows.COOKIE_NAME);
	if(value) {
		array = value.split(",");
		if(array[0] == window.windowRootId && array[1] != window.windowId && array[2] >= window.windowId) {
			window.close();
			return;
		}
	}
	setTimeout("CloseWindowsMonitor()", CloseWindows.MONITOR_INTERVAL_MS);
}
//---------------------------------------------------------------------------
function GetCookie(name)
{
	var cookie = document.cookie;
	var iStart = cookie.indexOf(name + "=");

	if(iStart != -1) {
		iStart += (name.length + 1);
		var iEnd = cookie.indexOf(";", iStart);
		return unescape(cookie.substring(iStart, (iEnd == -1 ? cookie.length : iEnd)));
	}
	return null;
}

function SetCookie(name, value, expiresMs, path)
{
	var path = path ? "; path=/" : "";
	var expires = "";
	if(expiresMs) {
		var date = new Date(0);
		date.setTime(new Date().getTime() - date.getTime() + expiresMs);
		expires = "; expires=" + date.toGMTString();
	}
	document.cookie = name + "=" + escape(value) + path + expires;
}

function DeleteCookie(name)
{
	document.cookie = name + "=; expires=Thu, 01-Jan-70 00:00:01 GMT";
}
//------------------------------------------------------------------------------------------//
function Logout(targetWindow, action)
{
    var orgId = gEnv == null ? '' : gEnv.orgId;
    if(action == null)
        var url = "/Login/Login.act?logout=" + orgId;
    else
        var url = action + "?orgId=" + orgId;
    
    (targetWindow ? targetWindow : window).location = url;
}

/**
 * Handle a UI event
 */
function DoEvent(ev)
{
	if(typeof doEvent == 'function')
		doEvent(ev);	// Pass it to the local event handler.
	else
		alert("Unhandled event:\n", ObjectToJs(ev));
}

/**
 * Creates HTML for a table cell.  Special formatting and hyperlinking for
 * based on the data type.
 */
function MakeTableCellHtml(uiTable, row, col, uiObjectName, truncate)
{
	var text		= uiTable.Rows[row][col];
	var columnDef	= uiTable.ColumnDefs[col];

	if(!text)
		return "";

    if(columnDef.type == 'date')
        return FormatDate(text);
    else if(columnDef.type == 'timestamp')
        return FormatDateTime(text);

	// TODO:  This code does not know how to handle nested pipe sets.
    if(text.charAt(0) == '|' && text.charAt(text.length-1) == '|') {
        if(text.indexOf(':') > 0)
            text = text.replace( /\|\w*:/g, '|');   // removes entityTypeCd prefix from universal IDs
    	var delimiter = (columnDef.type == 'labelSet') ? ';  ' : ', ';
    	text = text.slice(1,-1).replace( /\|/g, delimiter);
    }
    text = ReplaceNewlines(text);
    
	if(columnDef.type == 'entity' || columnDef.type == 'entitySet') {
	    if(columnDef.renderFormat && columnDef.renderFormat == 'supressIds') {
            if(columnDef.type == 'entitySet')
                text = 'Show List';
            else
                text = 'Show Detail';
	    }
		else if(text.length > TABLE_CELL_MAX_CHARS) {
			var n = text.lastIndexOf(', ', TABLE_CELL_MAX_CHARS) + 2;
			if(n < 40)
				n = TABLE_CELL_MAX_CHARS;
			text = text.substring(0,n) + "...";
		}
		if(columnDef.type == 'entity') {
		    var uid = ParseUid(text);
		    if(uid)
		        text = uid.entityId;  // remove entityType prefix from UIDs for display purposes
		}
		text   = '<a href="Javascript:void(0)" onClick="' + uiObjectName + '.cellClick(' + row + ',' + col + ',event); UiCancelEvent(event);">' +text + '</a>';
   	}
   	else if(columnDef.type == "menu") {
   		text = '<a href="#">' + text + '</a>';
   	}
   	else if(columnDef.type == "url") {
   	    text = '<a href="' + text + '" target="_blank">' + text + '</a>';
   	}
   	else if(text.indexOf('href=') < 0) {
	    var n = text.indexOf('__jit');
	    if((n == -1) && truncate && text.length > TABLE_CELL_MAX_CHARS) {
            n = text.lastIndexOf(' ', TABLE_CELL_MAX_CHARS);
            if(n < 40)
                n = TABLE_CELL_MAX_CHARS;
        }
        if(n >= 0) {
            var linkText = (n > 0) ? "click for more..." : "click for details...";
            text = (n > 0) ? text.substring(0,n) + "... " : "";
            text = text + '<a href="Javascript:void(0)" onClick="' + uiObjectName + '.cellClick(' + row + ',' + col + ',event, true);UiCancelEvent(event);">' + linkText + '</a>';
        }
    }
    return text;
}

/**
 * Replaces newlines within table cell text.
 */
var newlineRegex;

function ReplaceNewlines(text)
{
    if((text.indexOf('\n') < 0) && (text.indexOf('&#10;') < 0))
        return text;

	if(!newlineRegex)
		newlineRegex =  /\n|&#10;/g;
	return text.replace(newlineRegex, "<br>" );
}

/**
 * Returns a

  globally unique name that is the name of an object that is a reference
 * to the object passed in.
 */

 var globalNameCounter = {};	// Global counters for objects that need a fixed tag

 function GetGlobalName(object, prefix)
 {
 	if(object.isUIElement)
 		return 'GetUiElem(' + object.id + ')';

 	if(typeof object.globalName == 'undefined')
 	{
 		if(!prefix)
 			prefix = "G";
 		if(typeof globalNameCounter[prefix] == 'undefined')
 			globalNameCounter[prefix] = 0;

 		object.globalName = prefix + (globalNameCounter[prefix]++);
 		eval(object.globalName + " = object");
 	}
 	return object.globalName;
 }

/**
 *  Creates an array of all the elements of the set.  If the flattenFlag is true, nested sets
 *  are flattened, e.g.  "|A|B|\\|C\\|D\\||E|" --> [A B C D E] instead of [A B [C D] E]
 */
function PipeSetToArrayAll(set, flattenFlag)
{
	var array = PipeSetToArray(set);

	// In most cases the elements are not nested.  Check for this common case.
	for(var n=0;  n < array.length;  n++) {
		if(array[n].charAt(0) == '|')
			break;
	}

	if(n == array.length)
		return array;

	// Build a new array that contains all the nested elements flattened out
	  outArray = new Array();

	for(var n=0;  n < array.length;  n++) {
		if(array[n].charAt(0) == '|')
			array[n] = PipeSetToArrayAll(array[n], isFlattening);

		if(flattenFlag)
			outArray = outArray.concat(array[n]);
		else
			outArray.push(array[n]);
	}

	return outArray;
}

/**
 * Split a string of pipe delimited strings into an array of items.  Characters can be
 * escaped by a '\'.    There is a leading and trainling delimiter '|'
 */
function PipeSetToArray(set) {
	var delimChar  = '|';
	var escapeChar = '\\';

	if(!set || set.length == 0)
		return [];

	var items   = new Array(0);
	var item    = "";

	var nTo = set.length - 1;
	if(set.charAt(0) != delimChar || set.charAt(nTo) != delimChar || nTo == 0)
	{
	    items.push(set);
		return items;
    }

	for(var n = 1; n < nTo; n++)
	{
		var chr = set.charAt(n);
		if(chr == escapeChar) {
			item += set.charAt(++n);
			continue;
		}

		if(chr != delimChar) {
			item += chr;
			if(n + 1 < nTo)
				continue;
		}

		items.push(item);

		item  = "";
		nFrom = n + 1;

		// If the last field is blank, there will be a trailing deliminator with nothing after it.
		if(chr == delimChar && nFrom == nTo)
			items.push("");
	}

	return items;
}

//========================================================================
// Entity and Table Source Utilities
//========================================================================

/**
 * Get the default table source name for a given entity type
 */
function GetDefaultTsName(entityTypeCd)
{
    if(gRes.tsDefaults == null)
    {
        alert("No default table sources defined");
        return '';
    }
    var list = gRes.tsDefaults.DefaultTsNames;
    for(var k = 0; k < list.length; k++)
    {
        if(list[k].entityTypeCd == entityTypeCd)
            return list[k].tsName;
    }
//    alert("No default table source for entity type: " + entityTypeCd);
    return entityTypeCd;
}

/**
 * Pulls out the components of a table source where each component is from a primary table source.
 */
function GetTsComponents(tableSource)
{
    var columns = tableSource.ColumnDef;
    var sourceInfo = tableSource.SourceInfo;
    var nCols = columns.length;
    var sourceLabel = '???';
    var component;
    var iComp = 0;
    var jCol = 0;

    var returnObj = new Array();
    var sourceLabels = new Array();

    for (var iCol = 0; iCol < nCols; iCol++)
    {
        var newLabel = columns[iCol].sourceLabel;
        if((newLabel == null) || (newLabel == ''))
            newLabel = tableSource.label;
        if(sourceLabel != newLabel)
        {
            for(var k = 0; k < iComp; k++)
            {
                if(sourceLabels[k] == newLabel)
                {
                    sourceLabel = sourceLabels[k];
                    component = returnObj[k];
                    jCol = component.ColumnDef.length;
                    break;
                }
            }
        }
        if(sourceLabel != newLabel)
        {
            sourceLabel = newLabel;
            sourceLabels[iComp] = sourceLabel;
            component = {};
            if((sourceInfo != null) && (sourceInfo[iComp] != null))
            {
                var infoText = '';
                if(sourceInfo[iComp].rowCount > 0)
                    var infoText = sourceInfo[iComp].rowCount + ' entries.';

                var sourceDate = sourceInfo[iComp].sourceDate;
                if(sourceDate != null)
                    infoText = infoText + ' Data current through ' + FormatDate(sourceDate);

                if(infoText.length > 0)
                    component.sourceLabel = sourceLabel + '  (' + infoText + ')';
                else
                    component.sourceLabel = sourceLabel;
            }
            else
                component.sourceLabel = sourceLabel;
            component.ColumnDef = new Array();
            returnObj[iComp] = component;
            iComp++;
            jCol = 0;
        }
        component.ColumnDef[jCol] = columns[iCol];
        jCol++;
    }
//    alert(ObjectToXml(returnObj));
    return returnObj;
}

/**
 * TODO: replace this with a resource-based lookup
 */
function DecodeEntityType(prefix)
{
    if(prefix == "US")
        return "usPatent";
    else if(prefix == "USA")
        return "usApplication";
    else if(prefix == "EP")
        return "EPB";
    else if(prefix == "PAIR")
        return "usptoPair";
    else
        return prefix;
}

/**
 * TODO: replace this with a resource-based lookup
 */
function MakeUid(entityTypeCd, entityId)
{
    if(entityTypeCd == "usPatent")
        return "US:" + entityId;
    else if(entityTypeCd == "usApplication")
        return "USA:" + entityId;
    else if(entityTypeCd == "EPB")
        return "EP:" + entityId;
    else if(entityTypeCd == "usptoPair")
        return "PAIR:" + entityId;
    else
        return entityTypeCd + ":" + entityId;
}

/**
 * Convert to universal ID, if necessary, based on simple format rules
 */
function UniveralizeId(id)
{
    if(id && id.indexOf(':') == -1)
    {
        var begin = id.substring(0, 2);
        if(begin == "EP")
            return "EP:" + id;
        else if(id.charAt(2) == '/' || id.charAt(3) == '/')
            return "PAIR:" + id;
        else if(id.length == 11 && (begin == "19" || begin == "20"))
            return "USA:" + id;
        else
            return "US:" + id;
    }
    else
        return id;
}

function UniversalizeIdPipeSet(idPipeSet)
{
    var idArray = idPipeSet.split('|');
    for(var k in idArray)
        idArray[k] = UniveralizeId(idArray[k]);

    return idArray.join('|');
}

/**
 * Attempts to parse universal ID into entityTypeCd and entityId; otherwise returns null
 */
function ParseUid(id, defaultTypeCd)
{
    var idx = id.indexOf(':');
    if(idx > 0)
        return {entityTypeCd: DecodeEntityType(id.substring(0,idx)), entityId: id.substring(idx+1, id.length)};
    else if(defaultTypeCd)
        return {entityTypeCd: defaultTypeCd, entityId: id};
    else
        return null;
}

/**
 * Attempts to parse universal ID list into entityTypeCd and entityId list for
 * special case where all IDs have the same entityTypeCd; otherwise returns null
 */
function ParseUidList(list)
{
    var isUniform = true;
    var entityTypeCd;
    var entityIdList = new Array(list.length);
    for(var k = 0; k < list.length; k++) {
        var uid = ParseUid(list[k]);
        if(!uid)
            return null;
        if(isUniform) {
            if(k == 0)
                entityTypeCd = uid.entityTypeCd;
            else if(entityTypeCd != uid.entityTypeCd)
                isUniform = false;
            entityIdList[k] = uid.entityId;
        }
//        list[k] = uid.entityTypeCd + ':' + uid.entityId;
    }
    return isUniform ? {entityTypeCd: entityTypeCd, entityIdList: entityIdList} : null;
}


function ValueToEntitySet(text)
{
	return "|" + text.trim().replace(/[\s]*[\t\r\n,;]+[\s]*/g, "|") + "|";
}

function EntitySetToValue(entitySet)
{
	if(!entitySet)
		return "";
	if(typeof entitySet == "object" && entitySet.length > 0 && typeof entitySet[0] == "string")
		return entitySet;
	return entitySet.substring(1, entitySet.length - 1).replace(/\|/g, ", ").trim();
}

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 
/**
 * Constructor
 *
 */
function UIInfoTree()
{
// INITIALIZE
	uiInfoTreeInit(this);

// ARGUMENT INITIALIZATION

}


/**
 * Initializer (inherits)
 */
function uiInfoTreeInit(object)
{
// INHERIT
	uiInfoNodeInit(object);

// MEMBER VARIABLES
	object.level = -1;
	object.descr = 'Info Tree';

// PUBLIC METHODS

// INTERNAL METHODS
	object.build = uiInfoTreeBuild;
// STATIC INITIALIZATION

}

//------------------------------------------------------------------
// PUBLIC CLASS METHODS
//------------------------------------------------------------------



//------------------------------------------------------------------
// INTERNAL CLASS METHODS
//------------------------------------------------------------------

function uiInfoTreeBuild()
{
	this.HTML = '';

	for (var iChld = 0; iChld < this.children.length; iChld++)
		this.HTML += this.children[iChld].getHTML();
}

//------------------------------------------------------------------
// GLOBAL HELPER METHODS
//------------------------------------------------------------------

/**
 * Adapts an Info Tree object from the new Request Structure
 *
 */
function adaptInfoTree(history)
{
	var topTree = new UIInfoTree();
	var reqList = history.SubRequest;

	if(docInfo.resultTimestamp != null)
		var explText = 'This document was created on ' + FormatDateTime(docInfo.resultTimestamp) + '. It';
	else
		var explText = 'This document';

	var firstLetter = history.opLabel.substring(0, 1).toLowerCase();
	if(firstLetter == 'i' || firstLetter == 'a')
		explText = explText + ' is an ' + history.opLabel;
	else
		explText = explText + ' is a ' + history.opLabel;

	var iconImg;
	if ( reqList != null && reqList.length > 0 )
	{
		explText += ' of: ';
		iconImg = GetResultInfoIconImg(history, true);
	}
	topTree.addChild( new UIInfoNode(explText, null, topTree, iconImg));

	for ( var iReq = 0; iReq < reqList.length; iReq++)
	{
		var req = reqList[iReq];
		topTree.addChild( adaptInfoNode( req, topTree ));
	}

	return topTree;
}

/**
 * constructs an Info Node from a request object
 *
 */
function adaptInfoNode(request, parent)
{
	var topReq = new UIInfoNode( request.description, request, parent, GetResultInfoIconImg(request, false));

	var reqs = request.SubRequest;
	if( reqs != null )
	{
		var firstLetter = request.opLabel.substring(0, 1).toLowerCase();
		if(firstLetter == 'i' || firstLetter == 'a')
			var explText = 'which is an ' + request.opLabel + ' of:';
		else
			var explText = 'which is a ' + request.opLabel + ' of:';

		if ( reqs.length > 0 )
			topReq.addChild( new UIInfoNode( explText, null, topReq ));

		for ( var iHx = 0; iHx < reqs.length; iHx++ )
		{
			topReq.addChild ( adaptInfoNode( reqs[iHx], topReq));
		}
	}

	return topReq;
}


//========================================================================
// END: UIInfoTree Class
//========================================================================

//========================================================================
// BEGIN: UIInfoNode Class
//========================================================================

/**
 * Constructor
 *
 */
function UIInfoNode( descr, request, parent, iconImg )
{
// INITIALIZE
	uiInfoNodeInit(this);

// ARGUMENT INITIALIZATION
	if ( descr && descr != null)
		this.descr = descr.truncate(200, "...", ", ");
	if ( request && request != null)
		this.request = request;
	if ( parent && parent != null )
		this.level = parent.level + 1;
	if (iconImg && iconImg != null)
		this.iconImg = iconImg;
}

/**
 * Initializer (inherits)
 */
function uiInfoNodeInit(object)
{
// INHERIT
	uiElementInit(object);

// MEMBER VARIABLES
	object.descr = 'unknown';
	object.request = false;
	object.level = 0;
	object.parent = null;
	object.isOpen = false;
	object.children = new Array;

// PUBLIC METHODS
	object.open = uiInfoNodeOpen;
	object.close = uiInfoNodeClose;

// INTERNAL METHODS
	object.build = uiInfoNodeBuild;
	object.addChild = uiInfoNodeAddChild;
	object.doAction = uiInfoNodeDoAction;

// STATIC INITIALIZATION

}

//------------------------------------------------------------------
// PUBLIC CLASS METHODS
//------------------------------------------------------------------

function uiInfoNodeOpen()
{
	var childDiv = GetDomElem('node.children.' + this.id);
	var nodeIcon = GetDomElem('node.state.icon.' + this.id);
	var btn = '-'
	var btnAct = 'GetUiElem(' + this.id + ').close()';
	nodeIcon.innerHTML = new UIButton(btn, btnAct, 20).getHTML();
	childDiv.style.display = 'block';
}

function uiInfoNodeClose()
{
	var childDiv = GetDomElem('node.children.' + this.id);
	var nodeIcon = GetDomElem('node.state.icon.' + this.id);
	var btn = '+'
	var btnAct = 'GetUiElem(' + this.id + ').open()';
	nodeIcon.innerHTML = new UIButton(btn, btnAct, 20).getHTML();
	childDiv.style.display = 'none';
}

function uiInfoNodeAddChild(node)
{
	// alert ( "Adding\n" + node.descr + "\nTo\n" + this.descr );
	var idx = this.children.length;
	this.children[idx] = node;
}

//------------------------------------------------------------------
// INTERNAL CLASS METHODS
//------------------------------------------------------------------

function uiInfoNodeBuild()
{

	var btn = '';
	var btnAct = '';
	var displayChildren = '';
	var text = '<font class="info">' + this.descr + '</font>';

	if ( this.request )
		text = '<a href="javascript:GetUiElem(' + this.id + ').doAction()">' + text + '</a>';

	if ( this.isOpen )
	{
		btn = '-';
		btnAct = 'GetUiElem(' + this.id + ').close()';
		displayChildren = 'block';
	}
	else
	{
		btn = '+';
		btnAct = 'GetUiElem(' + this.id + ').open()';
		displayChildren = 'none';
	}

	var shim = '<img src="' + IMG_PATH + 'shim.gif" width="20">';

	if ( this.children.length == 0 )
		var button = shim;
	else
		var button = new UIButton(btn, btnAct, 20).getHTML();

	this.HTML = 	'<TABLE width="100%" border="0" cellpadding="2" cellspacing="0"><TR>';

	for ( var iLev = 0; iLev < this.level; iLev++)
		this.HTML += '<TD width="19">' + shim + '</TD>';

	if ( this.request )
		this.HTML +=	'<TD valign="top" id="node.state.icon.' + this.id +'" width="19">' +  button + '</TD>';

	if (this.iconImg)
		this.HTML += '<TD><img src="' + IMG_PATH + this.iconImg + '" width=17 height=16 </img></TD>';
	this.HTML += 	'<TD valign="top">' + text + '</TD>';
	this.HTML += 	'</TR></TABLE>';
	this.HTML += 	'<div id="node.children.' + this.id + '" style="display: ' + displayChildren + '">'

	for (var iChld = 0; iChld < this.children.length; iChld++)
	{
		this.HTML += this.children[iChld].getHTML();
	}

	this.HTML += 	'</div>';
}

/**
 * Performs the recall action on an information node
 */
function uiInfoNodeDoAction()
{
	var actionPageName = this.request.jsp;
	if ( actionPageName == null )
	{
		actionPageName = this.request.Action.actionPageName;
	}

	InfoRecall(this.request.docPath, this.request, actionPageName);
}


//========================================================================
// END: UIInfoNode Class
//========================================================================

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 
function UIInputSelector(items, width, valueParam, labelParam, groupParam)
{
	if(IsUiProtoRequest(arguments))
		return;
	this.uiInputSelectorInit(items, width, valueParam, labelParam, groupParam);
}
//--------------------------------------------------------------------------------//

UIInputSelector.prototype = UiPrototype(UIElement);

UIInputSelector.prototype.valueParam = "name";
UIInputSelector.prototype.labelParam = "label";
UIInputSelector.prototype.groupParam = "group";

UIInputSelector.prototype.selectedIndex = 0;
UIInputSelector.prototype.width = 200;
UIInputSelector.onSelect = null;
UIInputSelector.disabled = false;

UIInputSelector.prototype.uiInputSelectorInit = function(items, width, valueParam, labelParam, groupParam)
{
	this.uiElementInit();
	this.items = items;
	if(width)
		this.width = width;	if(valueParam)
		this.valueParam = valueParam;
	if(labelParam)
		this.labelParam = labelParam;
	if(groupParam)
		this.groupParam = groupParam;
}

//--------------------------------------------------------------------------------//
UIInputSelector.prototype.build = function()
{
	var style = "width: " + this.width + "px;";
	var onChange = 'GetUiElem(' + this.id +').setSelectedIndex(this.selectedIndex)';
	var disabled = this.disabled ? "disabled" : "";

	this.addHTML('<select id="' + this.domElemId + '" style="' + style + '" onChange="' + onChange + '" ' + disabled + '>');

	var prevGroup = null;
	for(var n = 0; n < this.items.length; n++ ) {
		var item = this.items[n];
		var value = item[this.valueParam];
		var label = item[this.labelParam];
		var group = item[this.groupParam];

		if(!label.trim())
			continue;

		if(group != prevGroup) {
			if(prevGroup)
				this.addHTML('</optgroup>');
			if(group)
				this.addHTML('<optgroup label="' + group + '">');
			prevGroup = group;
		}

		var selected = (n == this.selectedIndex) ? " selected " : "";
		this.addHTML('<option label="' + label + '" value="' + value + '" ' + selected + '>' + label + '</option>');
	}

	if(prevGroup)
		this.addHTML('</optgroup>');
	this.addHTML('></select>');
}
//--------------------------------------------------------------------------------//
UIInputSelector.prototype.getSelectedLabel = function()
{
	return this.items[this.selectedIndex][this.labelParam];
}
//--------------------------------------------------------------------------------//
UIInputSelector.prototype.getValue = function()
{
	return this.items[this.selectedIndex][this.valueParam];
}
//--------------------------------------------------------------------------------//
UIInputSelector.prototype.setValue = function(value)
{
	for(var n=0; n < this.items.length; n++)
		if(value == this.items[n][this.valueParam]) {
			this.setSelectedIndex(n);
			break;
		}
}
//--------------------------------------------------------------------------------//
UIInputSelector.prototype.setSelectedIndex = function(n)
{
	if(n == this.selectedIndex)
		return;

	this.selectedIndex = n;

	if(this.HTML) {
		var domElem = GetDomElem(this.domElemId);
		if(domElem)
			domElem.selectedIndex = this.selectedIndex;
	}
	if(this.onSelect )
		this.onSelect();
}
//--------------------------------------------------------------------------------//
UIInputSelector.prototype.setEnable = function(isEnabled)
{
	this.disabled = !isEnabled;
	var domElem = GetDomElem(this.domElemId)
	if(domElem)
		domElem.disabled = this.disabled;
}

//--------------------------------------------------------------------------------//
//	UISearchCriteria - Custom widget for table search information
//--------------------------------------------------------------------------------//

function UISearchCriteria(data, setLabelAttr, innerArrayAttr, itemNameAttr, itemLabelAttr, repeat)
{
	this.uiElementInit();
	var fieldData = new Array(data.length);

	for(var n=0; n < data.length; n++) {
		var inArray  = data[n][innerArrayAttr];
		var setArray = new Array(inArray.length);

		for(var m=0; m < inArray.length; m++ )
			setArray[m]  = {name: inArray[m][itemNameAttr], label: inArray[m][itemLabelAttr], type: inArray[m].type};
		fieldData[n] = {label: data[n][setLabelAttr], ColumnDefs: setArray};
	}

	this.searchSet = new Array(fieldData.length);
	for(var n=0; n < fieldData.length; n++) {
		this.searchSet[n] = {label: fieldData[n].label, ColumnDefs: fieldData[n].ColumnDefs,
									fldInputs: [], oprInputs: [],  trmInputs: [],
									cnjInputs: [], opr2Inputs: [], trm2Inputs: []}
		var set = this.searchSet[n];
		for(var m=0;  m < repeat;  m++) {
			set.fldInputs[m]  = new UIInputSelector(fieldData[n].ColumnDefs, 200);
			set.oprInputs[m]  = new UIInputSelector(this.operations, 120);
			set.trmInputs[m]  = new UIFormInput(200);
			set.cnjInputs[m]  = new UIInputSelector(this.conjunction, 70);
			set.opr2Inputs[m] = new UIInputSelector(this.operations, 120);
			set.trm2Inputs[m] = new UIFormInput(200);
		}
	}
}
//--------------------------------------------------------------------------------//
UISearchCriteria.prototype = UiPrototype(UIElement);
UISearchCriteria.prototype.operations = [	{name: 'cont', label: 'containing'},
											{name: 'ncont', label: 'not containing'},
											{name: 'begin', label: 'begins with'},
											{name: 'eq', label: 'equal to'},
											{name: 'neq', label: 'not equal to'},
											{name: '>', label: 'greater than'},
											{name: '<', label: 'less than'},
											{name: '>=', label: 'greater/equal'},
											{name: '<=', label: 'less/equal'} ];

UISearchCriteria.prototype.conjunction = [	{name: 'and', label: 'AND'},
											{name: 'or', label: 'OR'} ];
//--------------------------------------------------------------------------------//
UISearchCriteria.prototype.build = function()
{
	this.addHTML('<table width="100%">');
	for(var iSet=0; iSet < this.searchSet.length; iSet ++) {
		this.addHTML('<tr><td colspan="3" class="formSect">' + this.searchSet[iSet].label +'</td></tr>');

		for(var iPut = 0; iPut < this.searchSet[iSet].fldInputs.length; iPut++) {
			if(iPut > 0)
				this.addHTML('<tr><td height="3" colspan="3" class="formSect"></td></tr>');
			this.addHTML('<tr><td>');
			this.addHTML(this.searchSet[iSet].fldInputs[iPut].getHTML());
			this.addHTML('</td><td>');
			this.addHTML(this.searchSet[iSet].oprInputs[iPut].getHTML());
			this.addHTML('</td><td>');
			this.addHTML(this.searchSet[iSet].trmInputs[iPut].getHTML());
			this.addHTML('</td></tr><tr><td align="right">');
			this.addHTML(this.searchSet[iSet].cnjInputs[iPut].getHTML());
			this.addHTML('</td><td>');
			this.addHTML(this.searchSet[iSet].opr2Inputs[iPut].getHTML());
			this.addHTML('</td><td>');
			this.addHTML(this.searchSet[iSet].trm2Inputs[iPut].getHTML());
			this.addHTML('</td><td>');
		}
	}
	this.addHTML('</table>');
}
//--------------------------------------------------------------------------------//
UISearchCriteria.prototype.clear = function()
{
	for(var iSet=0; iTab < this.searchSet.length; iSet++) {
		var set =  this.searchSet[iSet];
		for(var n=0; n < set.fldInputs.length; n ++) {
			set.trmInputs[n].setValue("");
			set.trm2Inputs[n].setValue("");
		}
	}
}
 //--------------------------------------------------------------------------------//
UISearchCriteria.prototype.setState = function(searchFilters)
{
	for(var n=0;  n < searchFilters.length;  n++) {
		var filter = searchFilters[n];
		var set = this.searchSet[filter.searchSetIndex];
		var fldIndex = filter.fldIndex;

		set.fldInputs[fldIndex].setValue(filter.colName);
		set.oprInputs[fldIndex].setValue(filter.operation);
		set.trmInputs[fldIndex].setValue(filter.opParameters);
		set.cnjInputs[fldIndex].setValue(filter.conjunction);
		set.opr2Inputs[fldIndex].setValue(filter.operation2);
		set.trm2Inputs[fldIndex].setValue(filter.op2Parameters);
	}
}
//--------------------------------------------------------------------------------//
UISearchCriteria.prototype.getState = function()
{
	var filters = new Array();
	var nFilters = 0;

	for(var iSet = 0; iSet < this.searchSet.length; iSet++ ) {
		var set = this.searchSet[iSet];
		for(var iPut = 0; iPut < set.fldInputs.length; iPut ++ ) {
			var fldInput = set.fldInputs[iPut];
			var conj = set.cnjInputs[iPut].getValue();
			var values = [set.trmInputs[iPut].getValue(), set.trm2Inputs[iPut].getValue()];
			var opers = [set.oprInputs[iPut].getValue(), set.opr2Inputs[iPut].getValue()];
			var type = set.ColumnDefs[fldInput.selectedIndex].type;

			var nOper = 0;
			var filter = new Object();
			for(var j = 0; j < 2; j++) {
				if(values[j] != null)
					var value = values[j].trim();
				else
					var value = "";
				if(value == "" && (opers[j] != "eq") && (opers[j] != "neq"))
					continue;
				if(type == 'date' || type == 'timestamp') {
				    value = ParseDate(value);
				}
				if(nOper == 0) {
					filter.operation = opers[j];
					filter.opParameters = value;
				}
				else {
					filter.conjunction = conj;
					filter.operation2 = opers[j];
					filter.op2Parameters = value;
				}
				nOper++;
			}
			if(nOper > 0) {
				filter.colName = fldInput.getValue();
				filter.dataType = type;
				filter.mType = 'SearchFilter';
				filter.searchSetIndex = iSet;
				filter.fldIndex = iPut;
				filters[nFilters++] = filter;
			}
		}
	}
	return filters;
}
//--------------------------------------------------------------------------------//
UISearchCriteria.prototype.getSummary = function()
{
	var nFilters = 0;
	var sum = '';

	for(var iSet=0;  iSet < this.searchSet.length;  iSet++ )	{
		var set = this.searchSet[iSet];
		for(var iPut = 0; iPut < set.fldInputs.length; iPut ++ ) {
			var fldInput = set.fldInputs[iPut];
			var trmInput = set.trmInputs[iPut];
			var oprInput = set.oprInputs[iPut];
			var trm2Input = set.trm2Inputs[iPut];
			if(trmInput.getValue() != "" ) 	{
				if(sum)
					sum += ' and ';
				sum += fldInput.getSelectedLabel() + ' ' + oprInput.getSelectedLabel() + ' &quot;' + trmInput.getValue() + '&quot;';

				if(trm2Input.getValue() != "" ) {
					oprInput = set.opr2Inputs[iPut];
					sum += ' ' + set.cnjInputs[iPut].getValue() + ' ';
					sum += oprInput.getSelectedLabel() + ' &quot;' + trm2Input.getValue() + '&quot;';
				}
				nFilters++;
			}
		}
	}
	return nFilters ? sum : 'All Records';
}

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */


function UIInputFieldSelect(name, label, fields, customFields, customAction)
{
// INITIALIZE
	this.customFields = customFields;
	this.customAction = customAction;
	uiInputFieldSelectInit(this);

// ARGUMENT INITIALIZATION
	this.name = name;
	this.label = label;
	this.fields = fields;
}

/**
 * Initializer (inherits)
 */
function uiInputFieldSelectInit(object)
{
// INHERIT
	uiFormInputInit(object);

// MEMBER VARIABLES
	object.fields = null;
	object.colWidth = 150;
	object.cols = 3;
	object.defaults = '';
	object.lockedOn = 'none';
	object.lockedOff = 'none';

// PUBLIC METHODS
	/** Builds the HTML for the selector */
	object.build = uiInputFieldSelectBuild;
	/** Returns the value of the form input */
	object.getValue = uiInputFieldSelectGetValue;
	/** Restores all fields in the selector */
	object.restoreAll = uiInputFieldSelectRestoreAll
	/** Unselects all fields in the selector */
	object.unselectAll = uiInputFieldSelectUnselectAll;
	/** Unselects all fields in the selector */
	object.selectAll = uiInputFieldSelectSelectAll;
	/** Selects a custom set of fields in the selector */
	object.selectCustom = uiInputFieldSelectSelectCustom;
	/** Retrieves a summary for the selector */
	object.getSummary = uiInputFieldSelectorGetSummary;
	/** Retrieves the field names selected. */
	object.getSelectedNames = uiInputFieldSelectorGetSelectedFieldNames;
	object.setSelectedNames = uiInputFieldSelectorSetSelectedFieldNames;

	/** Adds a default field */
	object.addDefault = uiInputFieldSelectorAddDefault;
	/** Sets the locked on Fields */
	object.addLockOn = uiInputFieldSelectorAddLockOn;
	/** Sets the locked off Fields */
	object.addLockOff = uiInputFieldSelectorAddLockOff;

// INTERNAL METHODS
	/** Toggles fields between selection and non-selection */
	object.toggleOpt = uiInputFieldSelectToggleOpt;
	object.toggleOpt2 = uiInputFieldSelectToggleOpt2;
	/** Tells whether a named field is locked On */
	object.isLockedOn = uiInputFieldSelectorFieldIsLockedOn;
	/** Tells whether a named field is locked Off */
	object.isLockedOff = uiInputFieldSelectorFieldIsLockedOff;
	/** Tells whether a named field is a default field */
	object.fieldIsDefault = uiInputFieldSelectorFieldIsDefault;
	/** Sets a field on or off by name */
	object.setField = uiInputFieldSelectorSetField;

// STATIC INITIALIZATION
	object.buttons = new UIElement();
	object.buttons.addButton("Reset", "width: 140; bpadding-right: 200px", 'unselectAll()', object);
	object.buttons.addButton("Select All", 140, 'selectAll()', object);

	if(object.customFields && object.customFields.length) {
		var customBtns = new Array(object.customFields.length);
		for(k in object.customFields) {
			var label = object.customFields[k].label;
			customBtns[k] = new UIButton(label, 'GetUiElem(' + object.id + ').selectCustom('+k+')', 300);
		}
		object.customBtns = customBtns;
	}
}

//------------------------------------------------------------------
// PUBLIC CLASS METHODS
//------------------------------------------------------------------

/**
 * Constructs the input with a label
 */
function uiInputFieldSelectBuild()
{
	this.resetHTML();
	var totalWidth = this.colWidth * this.cols;
	this.addHTML('<input id="' + this.getInputId() + '" type="hidden" value="');
	this.addHTML(this.value);
	this.addHTML('" name="');
	this.addHTML(this.name);
	this.addHTML('">');
	this.addHTML('<table width="' + this.width + '"><tr><td colspan="2" class="inputLabel">' + this.label + '</td></tr></table>');
	this.addHTML('<table class="input" border="1" width="' + totalWidth + '" cellspacing="0" cellpadding="2">');

	for(var iSeg = 0; iSeg < this.fields.length; iSeg ++) {
		var col = 1;
		var label = this.fields[iSeg].label;

		// START THE SEGMENT HTML
		this.addHTML('<tr><td width="100%" colspan="' + this.cols + '" class="bgLightShade"><B>Fields From ' + label + '</B></td></tr>');

		var colObjs = this.fields[iSeg].ColumnDefs;
		for(var iCol = 0; iCol < colObjs.length; iCol ++) {
			if ( col == 1 )
				this.addHTML('<tr>'); // START THE ROW

			var chkImg = IMG_PATH2 + 'ico_unselected.gif';
			if ( colObjs[iCol].selected )
				chkImg = IMG_PATH2 + 'ico_selected.gif';

			// MAKE THE FIELD COLUMN
			this.addHTML('<td width="' + this.colWidth + '">');
			this.addHTML('<table border="0" width="100%" cellspacing="0" cellpadding="2"><tr onclick="GetUiElem(' + this.id + ').toggleOpt2(' + iSeg + ',' + iCol + ')">');
			this.addHTML('<td align="center" width="17">');
			this.addHTML('<img border="0" id="chk.img.' + iSeg + '.' + iCol + '.' + this.id + '" src="' + chkImg + '" width="10" height="10"></td><td><font class="smallText">');
			this.addHTML(colObjs[iCol].label);
			this.addHTML('</td></tr></table></td>');

			col++;
			if(col > this.cols) {
				this.addHTML('</tr>'); // END THE ROW
				col = 1;
			}
		}

		if(col > 1) {
			var remCols = this.cols - col + 1;
			if ( remCols > 0 )
			for(var irm = 0; irm < remCols; irm++)
				this.addHTML('<td width="' + this.colWidth + '">&nbsp;</td>');
			this.addHTML('</tr>'); // END THE ROW
		}
	}

	// END THE SELECTOR MAIN SECTION
	this.addHTML('</table>');

	// ADD THE CONTROL BUTTONS FOR THE SELECTOR
	this.addHTML('<table width="100%" border="0" cellpadding="2">');
	this.addHTML('<tr><td nowrap align="center">' + this.buttons.getHTML()  + '</td></tr>');
	if(this.customBtns) {
		this.addHTML('<tr><td height="20"></td></tr>');
		nRows = Math.ceil(this.customBtns.length/2);
		for(var k = 0; k < nRows; k++) {
			this.addHTML('<tr><td nowrap align="left">');
			this.addHTML(this.customBtns[k].getHTML());
			if(k+nRows < this.customBtns.length) {
				this.addHTML('</td><td>');
				this.addHTML(this.customBtns[k+nRows].getHTML());
			}
			this.addHTML('</td></tr>');
		}
	}
-	    this.addHTML('</table>');
}

/** Returns the internal value for the basic input */
function uiInputFieldSelectGetValue(filter)
{
	var selCols = new Array();
	var nSelCols = 0;

	for(var iSeg = 0; iSeg < this.fields.length; iSeg ++ ) {
		var colObjs = this.fields[iSeg].ColumnDefs;
		for(var iCol = 0; iCol < colObjs.length; iCol ++ ) {
			var isSelected = false;
			var colObj = colObjs[iCol];
			if ( colObj.selected )
				isSelected = true;
			else if (filter) {
				for(var n = 0; n < filter.length; n++ ) {
					if(filter[n].colName == colObj.name) {
						isSelected = true;
						break;
					}
				}
			}
			if ( isSelected ) {
				selCols[nSelCols++] = colObj;
				colObj.mType = 'ColumnDef';
			}
		}
	}
	return selCols;
}

/** Restores all selections to saved state */
function uiInputFieldSelectRestoreAll()
{
	for(var iSeg = 0; iSeg < this.fields.length; iSeg ++ ) {
		var colObjs = this.fields[iSeg].ColumnDefs;
		for(var iCol = 0; iCol < colObjs.length; iCol ++ ) {
			var colObj = colObjs[iCol];
			if ( colObj.selected && !this.fieldIsDefault(colObj.name))
				this.toggleOpt(iSeg, iCol);
			if ( !colObj.selected && this.fieldIsDefault(colObj.name))
				this.toggleOpt(iSeg, iCol);
		}
	}
}

/** Unselects all selections for the Field Selector */
function uiInputFieldSelectUnselectAll()
{
	for(var iSeg = 0; iSeg < this.fields.length; iSeg ++ ) {
		var colObjs = this.fields[iSeg].ColumnDefs;
		for(var iCol = 0; iCol < colObjs.length; iCol ++ ) {
			var colObj = colObjs[iCol];
			if (colObj.selected && !this.isLockedOn(colObj.name))
				this.toggleOpt(iSeg, iCol);
		}
	}
}

/** Selects all selections for the Field Selector */
function uiInputFieldSelectSelectAll()
{
	for(var iSeg = 0; iSeg < this.fields.length; iSeg ++ ) {
		var colObjs = this.fields[iSeg].ColumnDefs;
		for(var iCol = 0; iCol < colObjs.length; iCol ++ ) {
			var colObj = colObjs[iCol];
			if (!colObj.selected && !this.isLockedOff(colObj.name))
				this.toggleOpt(iSeg, iCol);
		}
	}
}

/** Selects all fields that appear on a pre-defined piped set of fields */
function uiInputFieldSelectSelectCustom(index)
{
	var selectedColNames = this.customFields[index].colNames;
	for(var iSeg = 0; iSeg < this.fields.length; iSeg ++ )
	{
		var colObjs = this.fields[iSeg].ColumnDefs;
		for(var iCol = 0; iCol < colObjs.length; iCol ++ )
		{
			var colObj = colObjs[iCol];
			var colName = colObj.name;
			var selected = this.isLockedOn(colName) || (selectedColNames.indexOf('|'+colName+'|') >= 0);
			if ( (colObj.selected && !selected) || (!colObj.selected && selected) )
				this.toggleOpt(iSeg, iCol);
		}
	}
	if(this.customAction)
		eval(this.customAction);
}

function uiInputFieldSelectToggleOpt2(set, field)
{
	this.toggleOpt(set, field);
	if(this.onChange)
		this.onChange(this, set, field);
}

function uiInputFieldSelectToggleOpt(set, field)
{
	var theImg = GetDomElem('chk.img.' + set + '.' + field + '.' + this.id);
	if ( this.fields[set].ColumnDefs[field].locked )
		return;

	var fieldName = this.fields[set].ColumnDefs[field].name;

	// Check for a lock on
	if(this.isLockedOn(fieldName)) {
		alert('This field is required');
		return;
	}

	// Check for a lock off
	if(this.isLockedOff(fieldName)) {
		alert('This field is not available or is locked out');
		return;
	}

	var selected = this.fields[set].ColumnDefs[field].selected;
	this.fields[set].ColumnDefs[field].selected = !this.fields[set].ColumnDefs[field].selected;
	if(theImg != null) {
		if(!selected)
			theImg.src = IMG_PATH2 + 'ico_selected.gif';
		else
			theImg.src = IMG_PATH2 + 'ico_unselected.gif';
	}
}

function getSelections()
{
	var ColumnDefs = new Array();
	var rdx = 0;
	for(var iSeg = 0; iSeg < multiSel.options.length; iSeg ++ )
	{
		var colObjs = multiSel.options[iSeg].ColumnDefs;
		for(var iCol = 0; iCol < colObjs.length; iCol ++ )
		{
			if ( colObjs[iCol].selected )
				ColumnDefs[rdx++] = colObjs[iCol];
		}

	}

	//alert("DONE");
	return ColumnDefs;
}

/** Returns a text summary of the current value for the selector */
function uiInputFieldSelectorGetSummary()
{
	var iSelected = 0;
	var defSum = '[Default Fields]';
	var summary = '';

	for(var iSeg = 0; iSeg < this.fields.length; iSeg ++ )
	{
		var colObjs = this.fields[iSeg].ColumnDefs;
		for(var iCol = 0; iCol < colObjs.length; iCol ++ ) {
			var colObj = colObjs[iCol];
			if ( colObj.selected )
			{
				iSelected ++;
				if ( summary != '' )
					summary += ', ';
				summary += colObj.label;
			}
		}
	}

	if ( iSelected == 0 )
		return defSum;
	else
		return summary;
}

/** Returns a text summary of the current value for the selector */
function uiInputFieldSelectorGetSelectedFieldNames()
{
	var iSelected = 0;
	var names = '';

	for(var iSeg = 0; iSeg < this.fields.length; iSeg ++ )
	{
		var colObjs = this.fields[iSeg].ColumnDefs;
		for(var iCol = 0; iCol < colObjs.length; iCol ++ )
		{
			var colObj = colObjs[iCol];
			if ( colObj.selected )
			{
				if ( names != '' )
					names += ', ';
				names += colObj.name;
			}
		}
	}

	return names;
}

/** Returns a text summary of the current value for the selector */
function uiInputFieldSelectorSetSelectedFieldNames(csvNames)
{
	fieldSelector.unselectAll();
	cols = csvNames.split(",");
	for(var i=0; i < cols.length; i++)
		this.setField(cols[i].trim(), 'on');
}


/** Adds a default field */
function uiInputFieldSelectorAddDefault(field)
{
	if(this.defaults.indexOf(' ' + field) < 0)
        this.defaults += ' ' + field;
	this.setField(field, 'on');
}

/** Adds a locked on Fields */
function uiInputFieldSelectorAddLockOn(field)
{
	if ( this.lockedOn == 'none' )
		this.lockedOn = '';
	if(this.lockedOn.indexOf(' ' + field) < 0)
        this.lockedOn += ' ' + field;
	this.setField(field, 'on');
}

/** Adds a locked off Fields */
function uiInputFieldSelectorAddLockOff(field)
{
	if ( this.lockedOff == 'none' )
		this.lockedOff = '';
	if(this.lockedOff.indexOf(' ' + field) < 0)
        this.lockedOff += ' ' + field;
	this.setField(field, 'off');
}

//------------------------------------------------------------------
// INTERNAL CLASS METHODS
//------------------------------------------------------------------

function uiInputFieldSelectorFieldIsLockedOn(field)
{
	if ( this.lockedOn.indexOf(field) > - 1 )
		return true;
	else
		return false;
}

function uiInputFieldSelectorFieldIsLockedOff(field)
{
	if ( this.lockedOff.indexOf(field) > - 1 )
		return true;
	else
		return false;
}

function uiInputFieldSelectorFieldIsDefault(field)
{
	if ( this.defaults.indexOf(field) > - 1 )
		return true;
	else
		return false;
}

/** Sets a named field on or off, based on the passed value */
function uiInputFieldSelectorSetField(field, onOff)
{
	var selected = true;
	if ( onOff == 'off' )
		selected = false;

	for(var iSeg = 0; iSeg < this.fields.length; iSeg ++ )
	{
		var colObjs = this.fields[iSeg].ColumnDefs;
		for(var iCol = 0; iCol < colObjs.length; iCol ++ )
		{
			var colObj = colObjs[iCol];
			if ( colObj.name ==  field )
			{
				//DebugText("setting " + colObj.name + " to " + selected);
				colObj.selected = selected;
			}
		}
	}
}


//------------------------------------------------------------------
// GLOBAL HELPER METHODS
//------------------------------------------------------------------

/**
 * Constructs a field selector object from any nested array of objects.
 */
function makeFieldSelectorFromArray(name, label, data, setLabelAttr, innerArrayAttr, itemNameAttr, itemLabelAttr, cols, customFields, customAction)
{
	var compare = function( obj, obj2 ) {
		var label = obj.label.toLowerCase();
		var label2 = obj2.label.toLowerCase();
		if( label < label2 )
			return -1;
		if( label > label2 );
			return +1;
		return 0;
	}

	var fieldData = new Array();

	for(var iSet = 0; iSet < data.length; iSet ++) {
		var setObj = new Object();
		var inArray = data[iSet][innerArrayAttr];
		setObj.label = data[iSet][setLabelAttr];

		var setArray = new Array();
		for(var iIn = 0; iIn < inArray.length; iIn++) {
			var fldObj = new Object();
			fldObj.name = inArray[iIn][itemNameAttr];
			fldObj.label = inArray[iIn][itemLabelAttr];
			setArray[iIn] = fldObj;
		}
		setArray.sort(compare);

		setObj.ColumnDefs = setArray;
		fieldData[iSet] = setObj;
	}

	var input = new UIInputFieldSelect(name, label, fieldData, customFields, customAction);
	input.cols = cols;
	return input;
}

/** Sets the default fields for the table Source */
function setUIFieldSelectorDefaultFields(tableSource, selector, selectCols)
{
	if(selectCols) {
		for(var iCol = 0; iCol < selectCols.length; iCol++ )
			selector.addDefault(selectCols[iCol].name);
	}
	selector.addDefault(tableSource.entityIdColumnName);
	selector.addDefault(tableSource.entityLabelColumnName);

	selector.addLockOn(tableSource.entityIdColumnName);
	selector.addLockOn(tableSource.entityLabelColumnName);

	for(var k =0; k < tableSource.ColumnDef.length; k++) {
		var colDef = tableSource.ColumnDef[k];
		if(colDef.isDerived == 'true') {
			selector.addDefault(colDef.name);
			selector.addLockOn(colDef.name);
		}
		else if(!selectCols && colDef.required == "true") {
			selector.addDefault(colDef.name);
		}
	}
}

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 

function UIMenuItem(label, action, disabled)
{
// INITIALIZATION
	uiMenuItemInit(this);

// ARGUMENT INITIALIZATION
	this.icon		= null;			// If there's no '.' in the name, it is assumed to be a color
	this.label 		= label;
	this.action 	= action;
	this.disabled 	= disabled;
}

/**
 * Initializes a uiMenuItem object (Inherits from uiFrame)
 */
function uiMenuItemInit(object)
{
// INHERIT

	uiElementInit(object);

// MEMBER VARIABLES

	object.domElemId 	= "uiMenuItem." + object.id;
	object.cssClass 	= "uiMenuItem";

// PUBLIC METHODS

	object.build = uiMenuItemBuildHTML;				/** Creates the HTML for the Menu Item */
	object.getReference = uiMenuItemGetReference;	/** Builds the HTML for the Menu Item Reference */
	object.lite = uiMenuItemLite;					/** Highlights the Menu Item */
	object.dark = uiMenuItemDark;					/** Un-highlights the Menu Item */
	object.activate = uiMenuItemActivate;			/** Performs the Menu Item Action */
}

//------------------------------------------------------------------
// PUBLIC CLASS METHODS
//------------------------------------------------------------------

/**
 * Returns the item's simplest HTML representation for use in menus
 * and lists
 */
function uiMenuItemGetReference()
{
	return this.getHTML();
}

//------------------------------------------------------------------
// INTERNAL CLASS METHODS
//------------------------------------------------------------------

/**
 * Builds the HTML for a MenuItem.
 */
function uiMenuItemBuildHTML()
{
	var onMouseover = 'onMouseover="GetUiElem(' + this.id + ').lite()" ';
	var onMouseout 	= 'onMouseout="GetUiElem(' + this.id + ').dark()" ';
	var onClick 	= 'onclick="GetUiElem(' + this.id + ').activate(); UiCancelEvent(event);" ';

	this.resetHTML();
	this.addHTML('<div class="uiMenuItem">');

	if(this.disabled)
		this.addHTML('<div class="' + this.cssClass + 'Disable" ' + this.domElemId + '">');
	else
		this.addHTML('<div id="' + this.domElemId + '" ' + onMouseover + onMouseout + onClick + '>');

	var isUrl = this.action.indexOf('(') == -1;
	if(isUrl)
		this.addHTML('<a class="uiMenuAnchor" target="_blank" href="' + this.action + '">');

	this.addHTML('<div class="uiMenuItemPad">');
	if(this.icon != null) {
		if(this.icon && typeof this.icon == "string") {
			if(this.icon.indexOf('.') > 0)
				this.addHTML('<img src='+ this.icon +' class="uiMenuIcon"></img>')
			else
				this.addHTML('<span class="uiMenuIcon" style="background: ' + this.icon + '"></span>')
		}
		else
			this.addHTML('<img src="/img/shim.gif" class="uiMenuIcon"></img>')
	}

	this.addHTML(this.label + '</div>');
	if(isUrl)
		this.addHTML('</a>');

	this.addHTML('</div></div>');
}

/**
 * Lights up the Menu item on mouseover selection
 */
function uiMenuItemLite()
{
	var div = GetDomElem(this.domElemId);
	div.className = this.cssClass + "Lite";
}

/**
 * Darkens the Menu item (normal state)
 */
function uiMenuItemDark()
{
	var div = GetDomElem(this.domElemId);
	div.className = this.cssClass + "Dark";
}

/**
 * Performs the action as indicated in the action setting.
 */
function uiMenuItemActivate()
{
	UiHidePopups();

	var parent = this.parent;
	var args = null;
	while(!args && parent && parent.isMenu) {
		args   = parent.args;
		parent = parent.parent;
	}

	var action = this.action;

	// Right now two action paradigms are mixed together.  One passes an event object to
	// the menu item.  The other passes a template with arguments for substitution.

	if(args && args.length) {  						// Check if we have values to substitute
		if(this.ev && this.ev.entityId) {
			this.ev.entityId = args[0]; 			// Model 1:  An event object is attached.  Substitute the entityId
			this.ev.tsName = (args[1] ? args[1] : null);	// TODO:  Rework menus to make Model 1 obsolete
		}
		else {
			for (var n = 0;  n < args.length;  n++)	// Model 2: Substitute values into the action string
				action = action.replace("\$" + n, args[n]);
		}
	}

	if(action.indexOf("(") != -1 && action.indexOf(")") != -1)
		setTimeout(action, 100);
	else
		this.action.indexOf("/Dialog/") == -1 ? NewWindow(this.action) : PopupWindow(this.action);
}

//========================================================================
// END: UIMenuItem Class
//========================================================================

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 

var FLYOVER_ZINDEX	= 100000;
var POPUP_ZINDEX	= 100001;
var MENU_SEPARATOR	= "---";

var menuDebugFlag = false;

function MenuDebug(text) {
	if(menuDebugFlag)
		DebugText(text);
}

function MenuEnter(object, method) {
	if(!menuDebugFlag)
		return;

	var info = object.label + "." + method + " {" + object.domElemId + "}, parent(s)=";
	object = object.parent;
	while(object) {
		info += object.domElemId + " ";
		object = object.parent;
	}
	MenuDebug(info);
}

//========================================================================
// BEGIN: UIMenu Class
//========================================================================

	/**
	 * Constructor
	 */
	function UIMenu(label)
	{
		uiMenuInit(this);
		this.label = label;
	}


	/**
	 * UIMenu Initializer (inherits from UIMenuItem)
	 */
	function uiMenuInit(object)
	{
	// INHERIT
		uiMenuItemInit(object);

	// MEMBER VARIABLES

		object.domElemId 	= "uiMenu." + object.id;
		object.items 		= new Array;
		object.nItems 		= 0;
		object.isMenu 		= true;
		object.isActive		= false;
		object.frameCssClass= "uiMenuFrame";
		object.cssClass 	= "uiMenuItem";
		object.drop 		= "bottom-left";
		object.respond 		= null;		// Rollover means post on rollover (instead of click)


		object.addMenu		= uiMenuAddMenu;				/** Creates and adds an empty menu */
		object.addItem		= uiMenuAddItem;				/** Adds a Menu Item */
		object.addAnchorItem = uiMenuAddAnchorItem;			/** Adds a Menu item for an URL. Can be right clicked and saved.*/
		object.build 		= uiMenuBuildHTML;				/** Builds the Menu HTML */
		object.getReference = uiMenuGetReference;			/** Get HTML suitable for putting in a parent menu */
		object.getItemsHTML	= uiMenuGetItemsHTML;			/** Get HTML suitable for a standalone dropdown menu */
		object.lite 		= uiMenuLite;					/** Overrides the light method from MenuItem */
		object.dark 		= uiMenuDark;					/** Overrides the dark method from MenuItem */
		object.activate 	= uiMenuActivate;
		object.popupMenu 	= uiMenuPopupMenu;				/** Posts a popup menu */
		object.hide  		= uiMenuHideMenu;				/** Hide the menu */
	}

//------------------------------------------------------------------
// PUBLIC CLASS METHODS
//------------------------------------------------------------------

	/**
	 * Create a new menu, add it to the existing menu and return it.
	 */
	function uiMenuAddMenu(label)
	{
		var uiMenu = new UIMenu(label);
		this.addItem(uiMenu);
		return uiMenu;
	}

	/**
	 * Adds a menu Item to the function.  This method is overloaded
	 * and can take a UIMenuItem() argument or the arguments icon, label, action, disabled.
	 */
	function uiMenuAddItem(arg1, label, action, disabled)
	{
		var item = arg1;

		if(uiMenuAddItem.arguments.length > 1) {
			item = new UIMenuItem(label, action, disabled);
			item.icon = arg1;
		}
		else {
			if(typeof arg1 == "string" && arg1.indexOf(MENU_SEPARATOR) == 0)
				item = new UIMenuItem( arg1, "", true);
		}

		var index = this.nItems++;
		this.items[index] = item;
		item.parent = this;
	}

	/**
	 * Adds a menu Item whose action is to open a new window showing the URL
	 */
	function uiMenuAddAnchorItem(icon, label, url, disabled)
	{
		this.addItem(icon, label, url, disabled);
	}

	/**
	 * Builds a reference object
	 */
	function uiMenuGetReference(showArrow)
	{
		MenuEnter(this, "getReference()");
		var onMouseover = ' onMouseover="GetUiElem(' + this.id + ').lite()" ';
		var onMouseout 	= ' onMouseout="GetUiElem(' + this.id + ').dark()" ';
		var onClick  	= ' onClick="GetUiElem(' + this.id + ').activate(); UiCancelEvent(event);" ';

		var html =	'<div style="vertical-align: top;" class="' + this.cssClass + '" ' +  onClick + onMouseover + onMouseout + '>';
		html +=	'<div id="' + this.domElemId + '"><div class="uiMenuItemPad">' + this.label + '&nbsp;';

		if(showArrow) {
			if(this.drop.indexOf("right") != -1)
				arrow = IMG_PATH + 'ico_rt_arrow_11.gif';
			else
				arrow = IMG_PATH + 'ico_dn_arrow_11.gif';

			html += '<img style="vertical-align: middle;" id="' + this.domElemId + '.arrow" src="' + arrow +'" height="11" width="11">';
		}

		html +=	'</div></div>';
		return html;
	}
	/**
	 * Activates (posts) a menu
	 */
	function uiMenuActivate()
	{
		MenuEnter(this, "activate()");
		if(this.isActive)
			return;

		this.lite(true);

		if(!this.parent || !this.parent.isMenu || !this.parent.isActive)
			UiHidePopups();

		this.isActive = true;
		this.popupMenu();

		if(this.parent && this.parent.reportChildActivate)
			this.parent.reportChildActivate(this);
	}
	/**
	 * Called when the popup container for this menu Hides
	 */
	 function uiMenuHideMenu(domElemId)
	 {
		MenuEnter(this, "hide()");

		domElemId.innerHTML = "";
	 	this.isActive = false;
	 	this.dark();

	 	if(this.parent && this.parent.reportChildHide)
	 		this.parent.reportChildHide(this);
	 }
	/**
	 * Lights up the Menu item
	 */
	function uiMenuLite(isActivating)
	{
		MenuEnter(this, "lite()");

		var domElem = GetDomElem(this.domElemId);
		var className =  this.cssClass + "Lite";
		if(!domElem || domElem.className == className)
			return;

		domElem.className = className;

		var arrow = GetDomElem(this.domElemId + ".arrow");
		if(arrow) {
			if(this.drop.indexOf("right") != -1)
				arrow.src = IMG_PATH + 'ico_rt_arrow_11_white.gif';
			else
				arrow.src = IMG_PATH + 'ico_dn_arrow_11_white.gif';
		}

		if(this.parent && this.parent.reportChildLite)
			this.parent.reportChildLite(this);

//		if(!isActivating && !this.isActive && this.drop == "right-top")
//			this.activate();
	}

	/**
	 * Darkens the Menu item on another selection
	 */
	function uiMenuDark()
	{
		MenuEnter(this, "dark()");

		var domElem = GetDomElem(this.domElemId);
		var className =  this.cssClass + "Dark";
		if(!domElem || domElem.className == className)
			return;

		domElem.className = className;

		var arrow = GetDomElem(this.domElemId + ".arrow");
		if(arrow) {
			if(this.drop.indexOf("right") != -1)
				arrow.src = IMG_PATH + 'ico_rt_arrow_11.gif';
			else
				arrow.src = IMG_PATH + 'ico_dn_arrow_11.gif';
		}
	}

//------------------------------------------------------------------
// INTERNAL CLASS METHODS
//------------------------------------------------------------------

	/**
	 * Builds HTML for the menu itself
	 */

	function uiMenuBuildHTML()
	{
		this.addHTML('<table id="' + this.domElemId + '.standaloneFrame" class="' + this.frameCssClass + '"><tr><td>' + this.getReference(true) + '</td></tr></table>');
	}

	/**
	 * Builds the HTML for the menu items
	 */
	function uiMenuGetItemsHTML()
	{
		var html = new Array();

		// The outer table is needed for NS 7.1 to keep from oversizing the menu items
		html.push('<table id="' + this.domElemId + '.frame" class="' + this.frameCssClass + '">');

		if(this.isContextMenu && this.label)
			html.push('<tr><td class="' + this.cssClass + '"  style="font-weight: bold; border-bottom: 2px solid Blue;" >&nbsp;' + this.label + '&nbsp;</td></tr>');

		for(var n=0; n < this.nItems;  n++)
		{
			html.push('<tr><td>');

			var item = this.items[n];
			if(item.label.indexOf(MENU_SEPARATOR) != 0) {
				var showArrow = (item.isMenu && item.drop.indexOf("right") == 0);
				html.push(this.items[n].getReference(showArrow));
			}
			else {	// Mozilla and IE interpret HR style differently.  Need background and foreground color.
				html.push('<hr noshade style="height: 1px; border: 0px; color: Gray; background: Gray;">');
				if(item.label != MENU_SEPARATOR)
					html.push('<font class="' + this.cssClass + '" style="color: black; font-style: italic">' + item.label.substring(3));
			}
			html.push('</td></tr>');
		}

		html.push('</table>');

		return html.join("");
	}


	/**
	 * Brings up the Menu when the reference is highlighted.  Typically the parent object has to provide a <div>
	 * for the popup container.  If they don't we use the <div id="global.popup"> written below.
	 */

	document.write('<div id="global.flyover" style="position:absolute; display:none; left:0; top:0;">&nbsp;</div>');
	document.write('<div id="global.popup.0" style="position:absolute; display:none; left:0; top:0; z-index:100002"></div>');
	document.write('<div id="global.popup.1" style="position:absolute; display:none; left:0; top:0; z-index:100002"></div>');

	var uiMenuContainerNumber = 0;

	function uiMenuPopupMenu(popupPosition)
	 {
		MenuEnter(this, "popupMenu()");

		container = GetDomElem("global.popup." + (uiMenuContainerNumber++ % 2));
		container.innerHTML = '<div align=left>' + this.getItemsHTML() + '</div>';

		if(typeof popupPosition == "undefined") {
			var frameBounds = {top: 0, left: 0, bottom: 0, right: 0}

			if(this.parent && this.parent.isMenu)	// If this is a submenu, use parent items frame for positioning
				var frameDomElem = GetDomElem(this.parent.domElemId + ".frame");
			if(!frameDomElem)						// If this is a standalone menu, then use its own frame
				frameDomElem = GetDomElem(this.domElemId + ".standaloneFrame");
			if(frameDomElem)
				frameBounds = GetAbsBounds(frameDomElem);

			// Default bounds are the inner text area of the menu reference
			var bounds = GetAbsBounds(GetDomElem(this.domElemId));

			if(this.drop == "right-top" || this.drop == null) {
				container.style.left = frameBounds.right ? frameBounds.right : bounds.right;
				container.style.top  = bounds.top;
			}
			else {
				container.style.left = bounds.left;
				container.style.top  = frameBounds.bottom ? frameBounds.bottom : bounds.bottom;
			}
		}
		else {
			container.style.left = popupPosition.left;
			container.style.top  = popupPosition.top;
		}

		UiPostPopup(container, this, this);
		this.isActive = true;
	 }


//========================================================================
// END: UIMenu Class
//========================================================================


//------------------------------------------------------------------
// GLOBAL HELPER METHODS
//------------------------------------------------------------------

	/**
	 * Constructs a working menu from a serialized JS object
	 */
	function makeMenu(menu, isContextMenu)
	{
		if(menu.length)
			menuData = menu[0].data;	// menu received as an items array of length 1
		else
			menuData = menu;

		if(isContextMenu)
			var uiMenu = new UIContextMenu(menuData.title);
		else
			var uiMenu = new UIMenu(menuData.title);


		if(menuData.drop && menuData.drop != null)
			uiMenu.drop = menuData.drop;

		for (var iItm = 0; iItm < menuData.items.length; iItm ++)
		{
			var item = menuData.items[iItm];
			if(item.type == 'item') {
				var uiMenuItem = new UIMenuItem(item.data[0], item.data[1], item.data[2]);
				if(item.data.length > 3)
					uiMenuItem.ev = item.data[3];		// TODO:  Fix HACK
				uiMenu.addItem(uiMenuItem);
			}
			else if(item.type == 'separator')
				uiMenu.addItem(new UIMenuItem(MENU_SEPARATOR,"",true));
			else if(item.type == 'menu')
				uiMenu.addItem(makeMenu(item.data));
		}

		return uiMenu;
	}

	//////////////////////////////////////////////////////////////////////////////////////////
	//   Constructs an Action Menu data object from an ActionSet. Used for a table action menu.
	//////////////////////////////////////////////////////////////////////////////////////////

	function MakeTableActionMenu(actionSet, menuTemplate, contextDocPath, table)
	{
		var tableMenuTemplate = [
			{title: "File", itemCdSet: "|saveDocument|saveAsReportMaker|saveListAsPortfolio|-|addDocNote|-|exportasCSV|exportasExcel|-|test|"},
			{title: "Edit", itemCdSet: "|selectByList|-|removeChecked|removeUnchecked|-|mergeEntityLists|createEntityList|" },
			{title: "Citations", itemCdSet: "|forwardCitationList|fwdCousins|-|backwardCitationList|createFwdCitationList|bwdCousins|-|citationAssignees|citationCurrentAssignees|citationAssigneesEx|citationCurrentAssigneesEx|" },
			{title: "Mapping", itemCdSet: "|interconnectionMap|landscapeMap|-|forwardLandscape,1Level|forwardLandscape,2Levels|backwardLandscape,1Level|backwardLandscape,2Levels|backwardLandscape,3Levels|-|keyPriorArt|licensingOpportunity|-|fwd.CitationCrossDependencies|bwd.CitationCrossDependencies|"},
			{title: "Cluster", itemCdSet: "|generalClusterMap|-|clusterMapbyAgent|clusterMapbyClass|clusterMapbyFirstAssignee|clusterMapbyFirstInventor|"},
			{title: "Analytics", itemCdSet: "|standardAgent|standardApplicant|standardAssignees|standardCurrentAssignees||standardExaminer|standardInventors|-|standardApplDate|standardApplicationDate|standardIssueDate|standardFilingDate|standardPublicationDate|-|standardMainClass|standardPrimaryClass|classMainPrimaryUsClasses|classPairPrimaryUsClasses|-|findSimilar|"},
			{title: "Workflow", itemCdSet: "|workflowMapbyDocumentType|workflowMapbySourceList|"},
			{title: "Special", itemCdSet: "_ANY_"}
		];

		//////////////////////////////////////////////////////////////////////////////////////////
		// TODO:  This next "if" statement is a special  case that allows us to transition to the new model
		// in which a menu template is used to create a menu data object from the action set
		// The third argument "menuTemplate" is a string in cases where the call is for the old API
		//////////////////////////////////////////////////////////////////////////////////////////

		if(typeof menuTemplate == "string") {
			if(menuTemplate.indexOf("Action") == 0)
				menuTemplate = gRes.tableMenuTemplate ? eval(gRes.tableMenuTemplate) : tableMenuTemplate;
			else
				menuTemplate = [{title: menuTemplate, itemCdSet: "_ANY_"}];
		}

		var menus = menuToolbarInitializeItems(menuTemplate);
		var items = actionSet.Action;

		for(var n = 0; n < items.length; n ++)
		{
			var act = items[n];				
		    var disabled = (act.isDisabled && act.isDisabled == 'true');
			var item = new Object();
			item.type = 'item';
			item.data = new Array(3);
            if(act.actionIconName)
            {
                var iconName = (disabled) ? IMG_PATH + 'ico_disabled.gif' : act.actionIconName;
                item.data[0] = '<img class="uiMenuIcon"  src="' + iconName + '"> ' + act.actionLabel;
            }
            else
                item.data[0] = act.actionLabel;

            var ev 		 = {eventCd: LIST_ACTION_MENU_CLICK_CD, action: act, contextDocPath: contextDocPath, table: table};
            item.data[1] = 'DoEvent(' + GetGlobalName(ev,"ev") + ')';
            item.data[2] = disabled;

			item.itemCd  = mapActionToItemCd(act);

  			var itemCdSetTemp = "|" + item.itemCd + "|";
  			var mAnalytics = menus.length;
            var mCluster = menus.length;
            for(var m=0; m < menus.length;  m++) {
            	var itemCdSet = menus[m].data.itemCdSet;
            	if(itemCdSet.indexOf(itemCdSetTemp) != -1)
            		break;
                if(menus[m].data.title == "Analytics")
                    mAnalytics = m;
                else if(menus[m].data.title == "Cluster")
                    mCluster = m;
            }
            if(m == menus.length  &&  item.itemCd.indexOf("standard") == 0)
                m = mAnalytics;
            else if(m == menus.length  &&  item.itemCd.indexOf("clusterMap") == 0)
                m = mCluster;

			if(m == menus.length) {
				if(menus[m-1].data.itemCdSet == "_ANY_")
					menus[m-1].data.items.push(item);
			}
			else
				menus[m].data.items.push(item);
		}

		toolbarMenus = menuToolbarArrangeMenus(menus);
		return toolbarMenus;
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////
	// Attempt to extract a unique code from the action set item.  The odd logic points out that
	// the codes could stand some standardization.
	//////////////////////////////////////////////////////////////////////////////////////////////////
	function mapActionToItemCd(action)
	{
		var itemCd = action.actionCd;
		if(itemCd == "txRequest")
		{
			if(action.explicitParams)
			{
				eval("params=" + action.explicitParams);
				if(params.mType == "AnalysisRequest")
                {
					itemCd = params.analysisType + SetFirstCharToUC(params.analysisColName);
                    if((params.analysisType == "citation") && eval(params.excludeSelfCited))
                        itemCd += "Ex";
                }
                else if(params.mType == "CompoundRequest")
					itemCd = params.txName;
				else
					itemCd = null;
			}
		}

		// Default item code is the label with spaces removed and first letter lower case
		if(!itemCd || itemCd == "entityRequest")
			itemCd = SetFirstCharToLC(action.actionLabel.replace(/ /g, ""));

//		DebugText("===> Returned " + itemCd);
		return itemCd;
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////
	// Remove menus that have no items.
	//////////////////////////////////////////////////////////////////////////////////////////////////
	function menuToolbarInitializeItems(menuTemplates)
	{
		var menus = new Array(menuTemplates.length);

		for(var n=0;  n < menus.length;  n++)
		{
			var menu 		= new Object();
			menu.title		= menuTemplates[n].title;
			menu.itemCdSet	= menuTemplates[n].itemCdSet;
			menu.respond 	= 'click';
			menu.drop 		= 'bottom-left';
			menu.items 		= new Array(0);
			menus[n] 		= {type: 'menu', data: menu};
		}
		return menus;
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////
	// Remove menus that have no items.  Arrange items in the menus according to the template definition
	//////////////////////////////////////////////////////////////////////////////////////////////////
	function menuToolbarArrangeMenus(menus)
	{
		var nonEmptyMenus = new Array(0);
		for(var n=0;  n < menus.length;  n++)
		{
			var menu = menus[n].data;
			if(menu.items.length >0) {
				menuArrangeItems(menu);
				nonEmptyMenus.push(menus[n]);
			}
		}
		return nonEmptyMenus;
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////
	// Arrange items according to the order in which they appear in the menu's itemCdSet pipe set.
	// An item code of '-' is a special case that indicates a separator
	//////////////////////////////////////////////////////////////////////////////////////////////////
	function menuArrangeItems(menu)
	{
		var itemCdList  = PipeSetToArray(menu.itemCdSet);
		var sortedItems = new Array(itemCdList.length);

		for(var n=0;  n < menu.items.length;  n++)
		{
			var itemCd = menu.items[n].itemCd;
			for(var m=0;  m < itemCdList.length;  m++) {
				if(itemCdList[m] == itemCd)
					break;
			}
			if(m < itemCdList.length)
				sortedItems[m] = menu.items[n];
			else
				sortedItems.push(menu.items[n]);
		}

		var items = new Array(0);
		for(var n=0;  n < sortedItems.length;  n++) {
			if(itemCdList[n] == "-" && items.length > 0 && items[items.length-1].type != 'separator')
				items.push({type: 'separator'});
			if(sortedItems[n])
				items.push(sortedItems[n]);
		}
		if(items[items.length-1].type == 'separator')
			items.pop();

		menu.items = items;
	}
	/**
	 * Constructs an Action Menu data object from an ActionSet
	 * Used for a entity detail page action menu.
	 */
	function MakeDetailActionMenu(actionSet, title, entityId, suppressActionPage, tsName)
	{
		var menu = new Object();
		menu.title = title;
		menu.drop = "bottom-left";
		menu.items = new Array();
		var items = actionSet.Action;

        var menuItem = 0;
		for (var itm = 0; itm < items.length; itm ++ )
		{
			var act = items[itm];
			var disabled = (act.isDisabled == 'true');
			if (act.actionPageName == suppressActionPage)
				continue;

			var item = new Object();
			item.type = 'item';
			item.data = new Array(4);
			item.data[0] = act.actionLabel; 						// display text
            var ev = {eventCd: ACTION_MENU_CLICK_CD, action: act, entityId: entityId, tsName: tsName};
            item.data[1] = 'DoEvent(' + GetGlobalName(ev,"ev") + ')';
            item.data[2] = disabled;
            item.data[3] = ev;
			menu.items[menuItem++] = item;
		}

		return menu;
	}

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 

/**
 * Constructor
 *
 */
function UIContextMenu(label)
{
	uiContextMenuInit(this);
	this.label = label;
}

/** 
 * Initializer (inherits from UIMenu)
 */
function uiContextMenuInit(object)
{
// INHERIT
	uiMenuInit(object);

// MEMBER VARIABLES
	object.domElemId 			= "uiContextMenu." + object.id;
	object.isContextMenu		= true;

// PUBLIC METHODS
	object.setLabel				= function(label) { this.label = label; }
	object.activateAtClick 		= uiContextMenuActivateAtClick;

// INTERNAL METHODS

// STATIC INITIALIZATION
}


/**
 * Activates (posts) a menu at the specified location
 */
function uiContextMenuActivateAtClick(event, args)
{
	UiHidePopups();
	event.cancelBubble = true;

	var e = UiMouseEvent(event);
	var dropPos = {left: e.x, top: e.y - (this.label ? 16 :0)};

	this.args = args;
	this.popupMenu(dropPos);
}

function makeContextMenu(menuData)
{
	return makeMenu(menuData, true);

}

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 

/**
 * Constructor, takes an array of menu objects
 *
 */
function UIMenuToolbar(label)
{
// INITIALIZE
	uiMenuToolbarInit(this);
	this.label = label;
}

/**
 * Initializer (inherits)
 */
function uiMenuToolbarInit(object)
{
// INHERIT
	uiMenuInit(object);

// MEMBER VARIABLES
	object.domElemId 	 		= "uiMenuToolbar." + object.id;
	object.frameCssName			= "uiMenuFrame";
	object.activeChildMenu		= null;

// PUBLIC METHODS
	object.build 				= uiMenuToolbarBuild;
	object.dark					= function() {}
	object.lite					= function() {}
	object.reportChildLite		= uiMenuToolbarReportChildLite;
	object.reportChildActivate	= uiMenuToolbarReportChildActivate;
	object.reportChildHide		= uiMenuToolbarReportChildHide;
}

//------------------------------------------------------------------
// PUBLIC CLASS METHODS
//------------------------------------------------------------------

function uiMenuToolbarReportChildLite(childMenu)
{
	MenuEnter(this, "reportChildLite(), isActive=" + this.isActive + ", childMenu.domElemId=" + childMenu.domElemId + ", childMenu.label=" + childMenu.label);

	if(!this.isActive || this.activeChildMenu == childMenu) {
		MenuDebug("this.activeChildMenu == childMenu");
		return;
	}

	MenuDebug("UiHidePopups()");

	UiHidePopups();
	childMenu.activate();
}

function uiMenuToolbarReportChildActivate(childMenu)
{
	MenuEnter(this, "reportChildActivate(), isActive=" + this.isActive + ", childMenu.domElemId=" + childMenu.domElemId+ ", childMenu.label=" + childMenu.label);
	this.isActive = true;
	this.activeChildMenu = childMenu;
}

function uiMenuToolbarReportChildHide(childMenu)
{
	MenuEnter(this, "reportChildHide(), isActive=" + this.isActive + ", childMenu.domElemId=" + childMenu.domElemId);

	if(this.activeChildMenu == childMenu) {
		this.activeChildMenu = null;
		this.isActive = false;
	}
}

//------------------------------------------------------------------
// INTERNAL CLASS METHODS
//------------------------------------------------------------------

/**
 * Builds the HTML for the MenuToolbar
 */
function uiMenuToolbarBuild()
{
	this.addHTML('<table class="' + this.frameCssName + '" id="' + this.domElemId + '.frame" style="margin: 2px;"><tr>');

	if(this.label)
		this.addHTML('<td class="uiMenuItem"><b>' + this.label + '</td>');

	for (var iItem = 0; iItem < this.nItems; iItem ++)
		this.addHTML('<td style="padding: 2px;">' + this.items[iItem].getReference(this.nItems == 1) + '</td>');

	if(this.label)
		this.addHTML('<td>' + this.trailer + '</td>');

	this.addHTML('</tr></table>');
}

//------------------------------------------------------------------
// GLOBAL HELPER METHODS
//------------------------------------------------------------------

function MakeAppMenuToolbar( menuData )
{
	var topMenu = new UIMenuToolbar();

	for (var iItm = 0; iItm < menuData.AppMenus.length; iItm ++)
	{
		var item = menuData.AppMenus[iItm];
		var menu = makeAppMenu(item);
		topMenu.addItem(menu);
	}

	return topMenu;
}

/**
 * Constructs a working menu from a serialized JS object
 */
function makeAppMenu(menuData)
{
	var topMenu = new UIMenu(menuData.title);

	if(menuData.drop && menuData.drop != null )
		topMenu.drop = menuData.drop;

	if(menuData.respond != null )
		topMenu.respond = menuData.respond;

	for(var iItm = 0; iItm < menuData.AppMenuItems.length; iItm ++)
	{
		var item = menuData.AppMenuItems[iItm];
		// Actions that are in single quotes need to be evaluated.  This is the approach for creating
		// menu items that need parameter substitution from gEnv.  Fix this by doing the substitution
		// on the server side or in GetAppMenus().   AppMenus.js has the same hack in it.
		var action = (item.action.indexOf("'") == 0) ? eval(item.action) : item.action;
		var disabled = (item.isDisabled == 'true');
		topMenu.addItem(new UIMenuItem(item.title, action, disabled));
	}

	return topMenu;
}


function MakeMenuToolbar( toolbarItems )
{
	var menuToolbar = new UIMenuToolbar();

	for (var n=0; n < toolbarItems.length; n ++)
	{
		var item = toolbarItems[n];
		if (item.type == 'item')
			menuToolbar.addItem(new UIMenuItem(item.data[0], item.data[1], item.data[2]));
		else
			if (item.type == 'menu') {
				var menu = makeMenu(item.data);
				menuToolbar.addItem(menu);
			}
	}

	return menuToolbar;
}

/**
 * Copy the content of a pre-existing menu to a toolbar
 */
function CopyMenuToToolbar(menuToolbar, menu)
{
    var newMenu = menuToolbar.addMenu(menu.title);
    for(var n in menu.items) {
        if(menu.items[n].type == 'item') {
            var data = menu.items[n].data;
            newMenu.addItem( null, data[0], data[1], data[2]);
        }
        else if(menu.items[n].type == 'separator')
            newMenu.addItem( MENU_SEPARATOR );
    }
}

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */

function UITabSet()
{
	this.uiTabSetInit();
}

UITabSet.prototype 						= UiPrototype(UIElement);
UITabSet.classId						= "uiTabSet";
UITabSet.prototype.nowrap				= true;
UITabSet.prototype.selectedTabStyle		= "tabSetTabSelected";
UITabSet.prototype.unselectedTabStyle	= "tabSetTab";
UITabSet.prototype.fontStyle			= ""; // Default to font style from CSS

UITabSet.prototype.uiTabSetInit = function()
{
	this.uiElementInit();
	this.tabs 				= new Array();
	this.nTabs 				= 0;
	this.selectedIndex 		= -1;
}

/*----METHODS-------------------------------------------------------
	build
	makeTabHTML

	setNowrap
	setFontStyle
	addTab
	selectTab  			(also setTab, deprecated)
	getTabDivName
	setTabHTML
	setCallback
	setExtraHTML
------------------------------------------------------------------*/

/** Builds the HTML for the Tab Set object **/
UITabSet.prototype.build = function()
{
	if(this.selectedIndex == -1 && this.nTabs > 0)
		this.selectedIndex = 0;

	this.resetHTML();
	this.addHTML('<table class="tabSet"><tr>');

	for ( var index = 0; index < this.nTabs; index ++ )
		this.addHTML( this.makeTabHTML(index, "tabSetTab") );

	if(this.extraHTML)
		this.addHTML('<td style="float: right;"  align="right">' + this.extraHTML + '</td>');

	this.addHTML('</tr></table>');

	// Put in the vertical separator.   Need the &nbsp because IE 6 SP1 will not respect the line-height style
	// attribute without some content.
	this.addHTML('<div class="tabSetSeparator">&nbsp</div>');

	for (var index = 0; index < this.nTabs; index++)
	{
		var divName = this.tabs[index].divName;
		if(divName == 'auto')
		{
			divName = 'tab.div.' + this.id + '.' + index;
			var tab = this.tabs[index];
			tab.divName = divName;

			var html = "&nbsp;";
			var display = "none";

			if(index == this.selectedIndex) {
				if(tab.uiWidget && !tab.uiWidgetIsInitialized) {
					if(tab.uiWidget.setContainerId)
						tab.uiWidget.setContainerId(tab.divName);
					html = tab.uiWidget.getHTML();
					tab.uiWidgetIsInitialized = true;
				}
				display = "block";
			}

			this.addHTML('<div style="display: ' + display + '" id="' + tab.divName + '">' + html + '</div>\n');
		}
	}
}

/** Builds the HTML for a tab */
UITabSet.prototype.makeTabHTML = function(index)
{
	var tab = this.tabs[index];
	var className = (index == this.selectedIndex) ? this.selectedTabStyle : this.unselectedTabStyle;

	this.addHTML('<td class="' + className + '" ');
	if(this.nowrap)
		this.addHTML('nowrap ');
	this.addHTML('id="tab.text.' + this.id + '.' + index + '" ')
	this.addHTML('onclick="GetUiElem(' + this.id +').setTab(' + index + ',true)" ');
	this.addHTML('>');

	if(this.fontStyle)
		this.addHTML('<font style="' + this.fontStyle + '">' + tab.label + '</font>');
	else
	this.addHTML(tab.label);

	if (tab.iconImage)
	   this.addHTML('<img src="' + IMG_PATH + tab.iconImage + '" style="margin-left: 3px; "' + '></img>');

	this.addHTML('</td>');
	this.addHTML('<td>&nbsp</td>');	// put space between tabs
}

/** Set whether the tab labels can wrap around **/
UITabSet.prototype.setNowrap = function(nowrap)
{
	this.nowrap = nowrap;
}

UITabSet.prototype.setFontStyle = function(fontStyle)
{
	this.fontStyle = fontStyle;
}

UITabSet.prototype.addTab = function(label, divName, iconImage, uiWidget)
{
	// API has two forms --  divName and uiWidget can be swapped
	//  The divName is intended to become obsolete
	if(divName && divName.isUIElement) {
		var temp = uiWidget;
		uiWidget = divName;
		divName = temp;
	}
	if(!divName)
		divName = 'auto';

	var tab = { label: 		label,
				divName: 	divName,
				iconImage:	iconImage,
				uiWidget:	uiWidget,
				uiWidgetIsInitialized:	false }

	this.tabs[this.nTabs] = tab;
	return this.nTabs++;
}

/** Sets the current active tab -- DEPRECATED */
UITabSet.prototype.setTab = function(index, doCallback)
{
	this.selectTab(index, doCallback);
}

UITabSet.prototype.selectTab = function(index, doCallback)
{
	if(!this.HTML) {
		this.selectedIndex = index;
		return;
	}

	if(this.selectedIndex == index)
		return;

	if(doCallback && this.tabSelectCallback)
		this.tabSelectCallback(index);

	var tab = this.tabs[index];
	if(tab.uiWidget && !tab.uiWidgetIsInitialized) {
		if(tab.uiWidget.setContainerId)
			tab.uiWidget.setContainerId(tab.divName);
		tab.uiWidget.pushHTML(tab.divName);
		tab.uiWidgetIsInitialized = true;
	}

	var tabText = GetDomElem('tab.text.' + this.id + '.' + index);
	var tabPage = GetDomElem(this.tabs[index].divName);

	tab.borderBottomColor = tabText.style.borderBottomColor;
	tab.backgroundColor = tabText.style.backgroundColor;

	tabText.className = this.selectedTabStyle;

	if(this.selectedIndex >= 0) {
		var prevTab = this.tabs[this.selectedIndex];
		var prevText = GetDomElem('tab.text.' + this.id + '.' + this.selectedIndex);
		var prevPage = GetDomElem(prevTab.divName);
		prevPage.style.display = 'none';
		prevText.className = this.unselectedTabStyle;
	}

	tabPage.style.display = 'block';
	this.selectedIndex = index;
}

/** Returns the name of the indexed Tab Div */
UITabSet.prototype.getTabDivName = function(index)
{
	return this.tabs[index].divName;
}

UITabSet.prototype.setTabHTML = function(index, html)
{
	GetDomElem(this.tabs[index].divName).innerHTML = html;
}


UITabSet.prototype.setCallback = function(tabSelectCallback)
{
	this.tabSelectCallback = tabSelectCallback;
}

UITabSet.prototype.setExtraHTML = function(extraHTML)
{
	this.extraHTML = extraHTML;
}

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 

// sorting variables

var TBL_VLINE = '<td width="1" class="bgBrdrLit">' + SHIM + '</td>';
var TBL_PAD_S = '<table width="100%" border="0" cellpadding="2" cellspacing="0"><tr><td>';
var TBL_PAD_E = '</td></tr></table>';
var ROW_BG_STD = 'WHITE';
var ROW_BG_LIT = 'YELLOW';
var ROW_BG_SEL = UI_SELECT_HILITE;//'#B9D3FA';

var STATS_IMG_CLOSED = '<IMG border="0" src="' + IMG_PATH + 'ico_sect_aro_right.gif" width="13" height="13">';
var STATS_IMG_OPENED = '<IMG border="0" src="' + IMG_PATH + 'ico_sect_aro_down.gif" width="13" height="13">';
var STATS_COL_TITLE = '<FONT class="fgDark"><FONT class="uiTableCell">statistics</FONT></FONT>';

//========================================================================
// BEGIN: UIBasicTable Class
//========================================================================

/**
 * Constructor, builds a new table object based on
 *
 */
function UIBasicTable(table, display, rowMenuData, tableMenuData, entityIdCol)
{
// INITIALIZE
	uiBasicTableInit(this);
	this.addMilestone("Construction begun");

// ARGUMENT INITIALIZATION
	this.ColumnDefs = table.ColumnDefs;				/** The table column definition */
	this.Rows = table.Rows;							/** The rows in the table */
	this.title = table.title;						/** The name of the list */
	this.tsName = table.tsName;
	this.display = display;
	this.entityIdCol = entityIdCol ? entityIdCol : 0;

	if (this.Rows.length == 0)
	{
		this.display.number = false;
		this.display.select = false;
	}

	if (rowMenuData != null) { // Overloaded 3rd arg. May be array of row menu data (new API), or single row menu (old API)
	    if(IsArray(rowMenuData))
		    this.entityMenus = rowMenuData;
		else
		    this.entityMenus = [{entityTypeCd: table.entityTypeCd, entityLabel: table.ColumnDefs[entityIdCol].label, menuData: rowMenuData}];
    }

	if(tableMenuData != null)
	{
		this.tableMenu = MakeMenuToolbar(tableMenuData);
		this.tableMenu.parent = this;
	}

	if(display.filter)
		this.filter = display.filter;

	if(display.limitSelect)
		this.limitSelect = display.limitSelect;

	if(display.sortState)
		this.sortState = display.sortState;

	var nBlanks = 0;
	var nbrIdx  = 0;

	this.stats = new Array();
	this.statsHtml = new Array();
	for(var iCol = 0; iCol < this.ColumnDefs.length;  iCol++) {
        var dataType = this.ColumnDefs[iCol].type;
        if(dataType == 'int' || dataType == 'float' || dataType == 'date')
            this.statsHtml[iCol] = '<A href="javascript:GetUiElem('+ this.id +').statsOpen('+ iCol +')">' + STATS_IMG_CLOSED + '</A>' + STATS_COL_TITLE;
        else
            this.statsHtml[iCol] = '';
	}

	table.uiTable = this;   // Provide a 'hook' for table data object to access this UI object

	this.addMilestone("Construction complete");
	this.postConstruct();
	this.addMilestone("Post Construction complete");
}


/**
 * Initializer (inherits)
 */
function uiBasicTableInit(object)
{
// INHERIT
	uiWidgetInit(object);

// MEMBER VARIABLES
	object.domElemId = "uiBasicTable." + object.id;
	object.ColumnDefs = null;
	object.Rows = null;
	object.title = null;
	object.tsName = null;
	object.actions = null;
	object.display = null;
	object.entityIdCol = 0;
	object.nCols = 0;
	object.entityMenus = null;
	object.tableMenu = null;
	object.isTable = true;
	object.page = 1;
	object.cells = new Array;
	object.hasCells = false;
	object.nPages = null;
	object.iFirstRow = null;			// Index for first visible row
	object.iLastRow = null;				// Index+1 of last visible row
	object.lastSelect = null;
	object.filter = false;
	object.nSelected = 0;
	object.limitSelect = false;
	object.statsHtml = null;
	object.nHtmlArray = 10000;			// Allocate a large array for HTML accumulation

// SPECIAL SORT STATUS VARIABLES
	object.iSortCol = -1;
	object.sortState = {iSortCol: -1, columnDef: null, isAscendingSort: false, isSorting: false};

// PUBLIC METHODS

	object.build 		= uiBasicTableBuild;
	object.redraw 		= uiBasicTableRedraw;
	object.getContainer = uiBasicTableGetContainer;
	object.sort			= uiBasicTableSort;

// INTERNAL METHODS

	object.buildHeader 	= uiBasicTableBuildHeader;			/** Builds the column headings for the table */
	object.buildRow 	= uiBasicTableBuildRow;
	object.buildNullRow = uiBasicTableBuildNullRow;			/** Builds a row in the table when it has no rows */
	object.cellClick    = uiBasicTableCellClick;
	object.rowClick     = uiBasicTableRowClick;
	object.rowRightClick= uiBasicTableRowRightClick;
	object.statsOpen    = uiBasicTableStatsOpen;
	object.statsClose   = uiBasicTableStatsClose;
	object.getStats     = uiBasicTableGetStats;
	object.makeLink		= uiBasicTableMakeLink;
	object.visibleCols	= uiBasicTableVisibleCols;			/** Indicates the number of visible columns in the table */
	object.getRow 		= uiBasicTableGetRow;				/** Returns a specified row in the table */
	/** Returns the number of pages in the Table */
	object.getNumPages = uiBasicTableGetNumPages;			//[-]
	/** Returns the HTML for page navigation */
	object.makePageNav = uiBasicTableMakePageNav;			//[-]
	/** Moves to the next page */
	object.nextPage = uiBasicTableNextPage;					//[+]
	/** Moves to the previous page */
	object.prevPage = uiBasicTablePrevPage;					//[+]
	/** Moves to a specific page */
	object.setPage = uiBasicTableSetPage;					//[+]
	/** Selects a row in the table */
	object.selectRow = uiBasicTableSelectRow;				//[+]
	/** select or deselect all the rows in a table */
	object.selectAllRows = uiBasicTableSelectAllRows;		//[+]
	/** lites a row in the table, if it is visible */
	object.liteRow = uiBasicTableLiteRow;					//[+]
	/** Returns a pipe delimited string of selected entityIds */
	object.getSelectedIds = uiBasicTableGetSelectedIds;
	/** Returns a pipe delimited string of unselected entityIds */
	object.getUnselectedIds = uiBasicTableGetUnselectedIds;
	/** Removes selected Rows from the table */
	object.removeSelected = uiBasicTableRemoveSelected;
	/** Removes un-selected Rows from the table */
	object.removeUnselected = uiBasicTableRemoveUnselected;
	object.postConstruct = uiBasicTablePostConstruct;
	/* Returns the sort state */
	object.getSortState = uiBasicTableGetSortState;

// STATIC INITIALIZATION
}

/**
 * A generic object post-construction transformer for the table data.
 * Adds an invisible column to the table data, automatically allowing
 * certain rows to be selected and un-selected.
 *
 * @param object -- the table object (from constructor)
 */
function uiBasicTablePostConstruct()
{
	var selectCol = {name: 'select', label: 'Selected', type: 'boolean', size: '', role: '', dbRole: ''};

	if(this.ColumnDefs.length > this.display.columns.length ) {
		for(var ird = 0; ird < this.ColumnDefs.length; ird ++) {
			if(this.display.columns[ird] == null )
				this.display.columns[ird] = { sort: true, show: true };
		}
	}

	var displayCol = { sort: false, show: false };
	var rdSize = this.ColumnDefs.length;
	this.ColumnDefs[rdSize] = selectCol;
	this.display.columns[rdSize] = displayCol;

	// add the column to every row.
	if(this.display.select ) {
		for (var iRow = 0; iRow < this.Rows.length; iRow++)
			this.Rows[iRow][rdSize] = false;
	}

	this.selectCol = rdSize;
	this.totalCols = (this.visibleCols() * 2) + 1;
	this.tblHLine = '<tr class="bgBrdrLit"><td colspan="' + this.totalCols + '">' + SHIM + '</td></tr>';
}

//------------------------------------------------------------------
// PUBLIC CLASS METHODS
//------------------------------------------------------------------

/**
 * Builds the functional HTML for the display of the table object
 * based on the underlying table data.
 *
 */
function uiBasicTableBuild()
{
	this.addMilestone("Begin title construction");

	// If it's not a redraw, we need to create the <div> to hold the table.
	// For a redraw, we'll just replace the innerHTML of the existing <div>
	if(!this.isRedraw)
		this.addHTML('<div id="'+ this.domElemId + '">');

	if(this.display.showTitle)
	{
		var titleCol = "&nbsp;" + this.title;
		var menuCol  = this.tableMenu ? this.tableMenu.getHTML() : '&nbsp;';
		var navCol   = this.display.page ? this.makePageNav() : '&nbsp;';

		this.addHTML('<table class="uiFrame" cellpadding="0" cellspacing="0" width="100%"><tr>');
		this.addHTML('<td class="uiTableHead" align="left">' + titleCol + '</td>');
		this.addHTML('<td class="uiTableHead" align="center">' + menuCol + '</td>');
		this.addHTML('<td style="vertical-align: middle;" align="right">'  + navCol + '</td>');
		this.addHTML('</tr></table>');
	}


	this.addHTML('<table border="0" cellpadding="0" cellspacing="0" width="100%">');
	this.addMilestone("Begin Header Construction");
	this.buildHeader();
	this.addMilestone("Complete Header Construction");

	if(this.display.page) {
		this.iFirstRow = (this.page - 1) * this.display.page;
		this.iLastRow  = Math.min(this.iFirstRow+this.display.page, this.Rows.length);
	}
	else {
		this.iFirstRow = 0;
		this.iLastRow  = this.Rows.length;
	}

	var nCols = this.ColumnDefs.length;

	this.addMilestone("Begin Row Rendering");

	for(var iRow=this.iFirstRow ; iRow < this.iLastRow; iRow++)
		this.buildRow(iRow);

	this.addMilestone("End Row Rendering");

	if(this.iLastRow == 0 )
		this.addHTML(this.buildNullRow());

	this.addHTML('</table>');
	this.addHTML('<div style="position: absolute; z-index: 99999;" id="' + this.getPopupContainerId() + '"></div>');

	if(!this.isRedraw)
		this.addHTML('</div>');
	this.addMilestone("Complete HTML Rendering");
}

/**
 * Returns the row in the table according to its index
 */
function uiBasicTableGetRow(row)
{
	return this.Rows[row];
}

 /**
  * Returns a pipe delimited string of selected entityIds.
  */
 function uiBasicTableGetSelectedIds()
 {
    var n = 0;
	var idList = new Array();
    for(var iRow = 0; iRow < this.Rows.length; iRow++)
    {
        if(this.Rows[iRow][this.selectCol])
        {
            var id = this.Rows[iRow][this.entityIdCol];
            if(id.indexOf('|') != -1)
                id = id.replace( /\|/g, '\\|');
            idList[n++] = id;
        }
    }
    if(n > 0)
        return '|' + idList.join('|') + '|';
    else
        return '';
 }

 /**
  * Returns a pipe delimited string of unselected entityIds.
  */
 function uiBasicTableGetUnselectedIds()
 {
    var n = 0;
	var idList = new Array();
    for(var iRow = 0; iRow < this.Rows.length; iRow++)
    {
        if(!this.Rows[iRow][this.selectCol])
        {
            var id = this.Rows[iRow][this.entityIdCol];
            if(id.indexOf('|') != -1)
                id = id.replace( /\|/g, '\\|');
            idList[n++] = id;
        }
    }
    if(n > 0)
        return '|' + idList.join('|') + '|';
    else
        return '';
 }


/**
 * Returns a pipe delimited string of selected entityIds.
 */
   UIBasicTable.prototype.getSelectedRowNumbers = function()
{
	var list = new Array();
	for(var iRow = 0; iRow < this.Rows.length; iRow++) {
		if(this.Rows[iRow][this.selectCol])
			list.push(iRow);
	}
	return list;
}

/**
 * Removes selected rows from the table and causes a redraw
 */
function uiBasicTableRemoveSelected(redraw)
{
	var subSet = new Object;
	subSet.Rows = new Array;
	var rowcount = 0;

	for ( var iRow = 0; iRow < this.Rows.length; iRow++)
	{
		if ( !this.Rows[iRow][this.selectCol] )
			subSet.Rows[rowcount++] = this.Rows[iRow];
	}

	this.nPages = null;
	this.Rows = subSet.Rows;

	if( redraw )
		this.redraw();
}

/**
 * Removes un-selected rows from the table and causes a redraw
 */
function uiBasicTableRemoveUnselected(redraw)
{
	var subSet = new Object;
	subSet.Rows = new Array;
	var rowcount = 0;

	for ( var iRow = 0; iRow < this.Rows.length; iRow++)
	{
		if ( this.Rows[iRow][this.selectCol] )
		{
			this.Rows[iRow][this.selectCol] = false;
			subSet.Rows[rowcount++] = this.Rows[iRow];
		}
	}

	this.nPages = null;
	this.Rows = subSet.Rows;

	if( redraw )
		this.redraw();
}

//------------------------------------------------------------------
// INTERNAL CLASS METHODS
//------------------------------------------------------------------

/**
 * Creates the table headings for all columns in the table, along
 * with header information.
 *
 * @param table -- The table object
 */
function uiBasicTableBuildHeader()
{
	var SORT_ASC = IMG_PATH + "ico_sort_asc.gif";
	var SORT_DSC = IMG_PATH + "ico_sort_desc.gif";
	var SORT_NA = IMG_PATH + "ico_sort_na.gif";

	var cols = this.ColumnDefs.length;
	var tCols = (this.visibleCols() * 2) + 1;
	var TBL_HLINE = '<tr class="bgBrdrLit"><td colspan="' + tCols + '">' + SHIM + '</td></tr>';

	this.addHTML(TBL_HLINE + '<tr class="bgLightShade">' + TBL_VLINE);

	if (this.display.select && this.display.select != "single" && ! this.limitSelect) {
		this.addHTML('<td><span class="listspace">' );
		this.addHTML('<input  id="row.sel.' + this.id + '" type="checkbox" onclick="GetUiElem(' + this.id + ').selectAllRows()"');

		// If we've just moved to a new page, column level checkbox from it's previouls value.  Not too elegant.
		var checkbox = GetDomElem("row.sel." + this.id);
		if(checkbox && checkbox.checked)
			this.addHTML(' checked');

		this.addHTML('></spa></td>' + TBL_VLINE);
		}
    else if (this.display.select && this.display.select == "single")
        this.addHTML('<td><span class="listspace"></spa></td>' + TBL_VLINE);
	if (this.display.number)
		this.addHTML('<td><span class="listspace"></span></td>' + TBL_VLINE);

	for (var iCol = 0; iCol < cols; iCol++)
	{
		if (this.sortState.iSortCol == iCol && this.sortState.isAscendingSort)
			var arrow = SORT_ASC;
		else if(this.sortState.iSortCol == iCol)
			var arrow = SORT_DSC;
		else
			var arrow = SORT_NA;

		if(this.display.columns[iCol].show) {
			if(this.display.columns[iCol].sort)
				this.addHTML('<td><table width="100%" cellpadding="3" cellpacing="0"><tr><td style="white-space: no-wrap"><a href="javascript:GetUiElem('+ this.id +').sort('+ iCol +')"><font class="fgDark"><font class="uiTableHead">' + this.ColumnDefs[iCol].label + '</font></font></a></td><td width="8"><img src="' + arrow + '" align="right"></td></tr></table></td>' + TBL_VLINE);
			else
				this.addHTML('<td style="white-space: no-wrap"><table cellpadding="3" width="100%"><tr><td><font class="fgDark"><font class="uiTableHead">' + this.ColumnDefs[iCol].label + '</font></font></td></tr></table></td>' + TBL_VLINE);
		}
	}
	this.addHTML('</tr><tr class="bgLightShade">' + TBL_VLINE);

    if(this.display.select)
        this.addHTML('<td></td>' + TBL_VLINE);
    if(this.display.number)
        this.addHTML('<td></td>' + TBL_VLINE);

	for(var iCol = 0; iCol < cols; iCol++) {
		if ( this.display.columns[iCol].show )
		    this.addHTML('<td style="white-space: no-wrap">' + this.statsHtml[iCol] + '</td>' + TBL_VLINE);
	}
	this.addHTML('</tr>' + TBL_HLINE);
}

/**
 * Builds a single row in table form for editing
 *
 * @param row -- The row index to build
 * @return String -- The HTML needed to render a spreadsheet row for editing
 */
function uiBasicTableBuildRow(row)
{
	if(this.Rows[row][this.selectCol]) {
		var rowStyle = 'style="background-color: ' + ROW_BG_SEL + '" ';
		var rowSelect = '<input id="row.sel.' + this.id + '.' + row + '" type="checkbox" onclick="GetUiElem(' + this.id + ').selectRow(' + row + ')" checked>';
	}
	else {
		var rowStyle = 'style="background-color: ' + ROW_BG_STD + '" ';
		var rowSelect = '<input id="row.sel.' + this.id + '.' + row + '" type="checkbox" onclick="GetUiElem(' + this.id + ').selectRow(' + row + ')">';
	}

	this.addHTML('<tr id="row.'+ this.id + '.' + row + '" ' + rowStyle + ' onContextMenu="return false;">' + TBL_VLINE);

	if ( this.display.select )
		this.addHTML('<td class="uiTableCell" width="15">' + rowSelect + '</td>' + TBL_VLINE);
	if ( this.display.number )
		this.addHTML('<td class="uiTableCell" align="right" width="30">' +  (row+1) + '.</td>' + TBL_VLINE);

	for (var iCol=0;  iCol < this.ColumnDefs.length;  iCol++) {
		if ( this.display.columns[iCol].show ) {
		    if(this.ColumnDefs[iCol].type == GC.DATA_TYPE_ENTITY || this.ColumnDefs[iCol].type == GC.DATA_TYPE_ENTITY_SET) {
				var onRightClick = ' onContextMenu="return GetUiElem(' + this.id + ').rowRightClick(' + row + ',' + iCol + ',event);" ';
			    this.addHTML('<td class="uiTableCell"' + onRightClick + '>');
			}
			else
			    this.addHTML('<td class="uiTableCell">');
			this.makeLink(row, iCol);
			this.addHTML('</td>' + TBL_VLINE);
		}
	}

	this.addHTML('</tr>' + this.tblHLine);
}

/**
 * Builds a single row in table form showing that there is no data in the table
 *
 * @return String -- The HTML needed to render a spreadsheet row for editing
 */
function uiBasicTableBuildNullRow()
{
	this.addHTML('<tr>' + TBL_VLINE + '<td colspan="' + this.totalCols + '"><table cellpadding="3" width="100%"><tr><td>No Data in Results</td></tr></table></td>' + TBL_VLINE);
	this.addHTML('</tr>' + this.tblHLine);
}

/**
 * Rebuilds the entire HTML Table for the Table object and pushes it
 * to the screen.
 */
function uiBasicTableRedraw()
{
	// There is a trick here.  We assume that the table has already been rendered.
	// We'll leave the containing <div> in place and replace only the inner part of that <div>
	// This is taken care of the this.isRedraw in the build() method.
	this.resetHTML();
	this.isRedraw = true;
	GetDomElem(this.domElemId).innerHTML = this.getHTML();
	this.isRedraw = false;
}

/**
 * Returns the table's surrounding container div identified by table id,
 * allowing the table to be redrawn from within the div.
 */
function uiBasicTableGetContainer()
{
	return GetDomElem(this.container);
}

/**
 * Runs the default row action for the Table object, if any
 */
function uiBasicTableCellClick(iRow, iCol, event, isTruncatedDetail)
{
	var cellValue	= this.Rows[iRow][iCol];
	var cellColDef	= this.ColumnDefs[iCol];
	var idColValue  = this.Rows[iRow][this.entityIdCol];
	var idColDef    = this.ColumnDefs[this.entityIdCol];

    if(true) {

	    if(isTruncatedDetail) {
            var entityTypeCd = idColDef.subType;
            var entityIdList = [ idColValue ];
            var focusCol = cellColDef.name;
        }
        else if(cellColDef.subType == 'self') {
            var uid = ParseUid(idColValue, idColDef);
            var entityTypeCd = uid.entityTypeCd;
            var entityIdList = PipeSetToArrayAll(cellValue, true);
		    var focusCol = "";
        }
        else {
            var entityTypeCd = cellColDef.subType;
            var entityIdList = PipeSetToArrayAll(cellValue, true);
		    var focusCol = "";
        }

        if(!this.tsName && !GetDefaultTsName(entityTypeCd)) {
	        if(event)
	            this.rowRightClick(iRow, iCol, event)
			else
	            alert("Detail not available - right click for other options.");
            return;
        }

	    var eventCd = (cellColDef.type == GC.DATA_TYPE_ENTITY_SET) ? ENTITY_SET_SELECT_CD : ENTITY_SELECT_CD;
	    var descrTemplate = '$(rowCount) ' + cellColDef.label + ' from ' + idColDef.label + ' ' + idColValue;
	    var ev = {eventCd: eventCd, entityIdList: entityIdList, entityTypeCd: entityTypeCd, focusCol: focusCol, descrTemplate: descrTemplate};
	    if(isTruncatedDetail || (iCol == this.entityIdCol && cellValue.indexOf(':') == -1))
	        ev.tsName = this.tsName;    // inherit tsName for entityIdCol, unless its a UID

        DoEvent(ev);
    }
    else {
        var entityIdValue = this.Rows[iRow][this.entityIdCol];
        var entityIdLabel = this.ColumnDefs[this.entityIdCol].label;
        var title   = cellColDef.label.replace(/ /g,"") + ' for ' + entityIdLabel + ' ' + entityIdValue;
        var html    = '<html><title>' + title + '</title>' + ReplaceNewlines(cellValue) + '</html>';
        var wWidth  = 750;
        var wHeight	= 500;
        var wLeft   = (window.screen.availWidth - wWidth)/2;
        var wTop    = (window.screen.height - wHeight)/2;
        var attr    = "width=" + wWidth + ",height=" + wHeight + ",top=" + wTop + ",left=" + wLeft;
        attr        = attr + ",screenX=" + wLeft + ",screenY=" + wTop + ",scrollbars,resizable";
        var newWind = window.open(null, '_blank', attr);
        newWind.document.write(html);
    }
}

/**
 * Runs the default row action for the Table object, if any
 * (currently does nothing)...
 *
 */
function uiBasicTableRowClick(row, event)
{
	if (!this.Rows[row][this.selectCol])
		this.liteRow(row, ROW_BG_STD);
}

function uiBasicTableRowRightClick(iRow, iCol, event)
{
	var value = this.Rows[iRow][iCol].trim();
	if(!value)
		return false;

    if(this.ColumnDefs[iCol].type == GC.DATA_TYPE_ENTITY_SET) {
        // TODO: Move the menu construction somewhere else
        var MAX_ITEMS = 25;
        var entityTypeCd = this.ColumnDefs[iCol].subType;
        var entityLabel = this.ColumnDefs[iCol].label;

	    if(entityLabel.charAt(entityLabel.length - 1) == 's')
		    entityLabel = entityLabel.substring(0, entityLabel.length - 1);

	    var entityIds = PipeSetToArray(value);
	    var idCount = Math.min(entityIds.length, MAX_ITEMS);

	    var contextMenu = new UIContextMenu(idCount < entityIds.length ? 'Show Detail (first ' + idCount +')' : 'Show Detail');
	    for(var n = 0; n < idCount; n++)
	    {
		    var label = entityLabel + " " + entityIds[n];
		    var string = '{ actionCd: "entityRequest", entityTypeCd: "' + entityTypeCd + '", actionPageName: "/EntityDetail.act" }';
		    var action = 'DoEvent({ eventCd: ACTION_MENU_CLICK_CD, action: ' + string + ', entityId: "' + entityIds[n] + '"})';
		    contextMenu.addItem(null, label, action);
	    }

	    contextMenu.activateAtClick(event);
        return false;
    }

    var uid = ParseUid(value, this.ColumnDefs[iCol].subType);

	var tsName = this.tsName;
	if(this.ColumnDefs[iCol].primary != "true")
		tsName = GetDefaultTsName(uid.entityTypeCd);

	var menus = gRes.entityActions.Item;
	for(var n=0;  n < menus.length;  n++ ) {
		if(menus[n].entityTypeCd == uid.entityTypeCd)
			break;
	}

	if(n == menus.length)
		return true;

	if(!menus[n].contextMenu) {
		var actionMenu = MakeDetailActionMenu(menus[n], "Actions", "5555555", null, null);
		menus[n].contextMenu = makeContextMenu(actionMenu);
	}

	menus[n].contextMenu.setLabel(menus[n].entityLabel + ' ' + uid.entityId);
	menus[n].contextMenu.activateAtClick(event, [uid.entityId, tsName]);
	return false;
}

/**
 * Closes the column statistics
 */
function uiBasicTableStatsClose(col)
{
    this.statsHtml[col] = '<A href="javascript:GetUiElem('+ this.id +').statsOpen('+ col +')">' + STATS_IMG_CLOSED + '</A>' + STATS_COL_TITLE;
    this.redraw()
    return;
}

/**
 * Opens the column statistics
 */
function uiBasicTableStatsOpen(col)
{
    var stats = this.getStats(col);
    if(stats == null) {
        var html    = '<TABLE>';
        html = html + '<TR><TD colspan="2"><A href="javascript:GetUiElem('+ this.id +').statsClose('+ col +')">' + STATS_IMG_OPENED + '</A>' + STATS_COL_TITLE + '</TD></TR>';
        html = html + '<TR><TD colspan="2"><FONT class="uiTableCell">not available</FONT></TD></TR>';
        html = html + '</TABLE>';
        this.statsHtml[col] = html;
        this.redraw()
        return;
    }

    var dataType = this.ColumnDefs[col].type;
    var html = '<TABLE>';
    html = html + '<TR><TD colspan="2"><A href="javascript:GetUiElem('+ this.id +').statsClose('+ col +')">' + STATS_IMG_OPENED + '</A>' + STATS_COL_TITLE + '</TD></TR>';
    html = html + '<TR><TD><FONT class="uiTableCell">min:</FONT></TD><TD><FONT class="uiTableCell">' + stats.minimum + '</FONT></TD></TR>';
    html = html + '<TR><TD><FONT class="uiTableCell">max:</FONT></TD><TD><FONT class="uiTableCell">' + stats.maximum + '</FONT></TD></TR>';
    html = html + '<TR><TD><FONT class="uiTableCell">median:</FONT></TD><TD><FONT class="uiTableCell">' + stats.median + '</FONT></TD></TR>';
    if(dataType == 'int')
    {
        html = html + '<TR><TD><FONT class="uiTableCell">mean:</FONT></TD><TD><FONT class="uiTableCell">' + stats.mean.toFixed(1) + '</FONT></TD></TR>';
        html = html + '<TR><TD><FONT class="uiTableCell">total:</FONT></TD><TD><FONT class="uiTableCell">' + stats.sum + '</FONT></TD></TR>';
    }
    else if(dataType == 'date')
        html = html + '<TR><TD><FONT class="uiTableCell">median age:</FONT></TD><TD valign="bottom"><FONT class="uiTableCell">' + stats.medianAge.toFixed(1) + ' years</FONT></TD></TR>';
    html = html + '</TABLE>';

    this.statsHtml[col] = html;
    this.redraw();
}

/**
 * Get the column statistics
 */
function uiBasicTableGetStats(col)
{
    if(this.stats[col] != null)
        return this.stats[col];

    var dataType = this.ColumnDefs[col].type;
    var values = new Array();
    var sum = 0;
    var n = 0;
    for(var k = 0; k < this.Rows.length; k++) {
        var value = this.Rows[k][col];
        if(value != null && value.length > 0) {
            if(dataType == 'int') {
                sum = sum + parseInt(value);
                values[n] = padWithBlanks(value);
                // It is more efficient to pad 'int' fields to 6 characters with leading blanks
                // and perform a standard alpha sort than to perform a numeric sort.
                }
            else
                values[n] = value;
            n = n + 1;
        }
    }
    if(n == 0)
        return null;

    values.sort();

    var m = Math.floor(n/2);
    var median = values[m];
    var minimum = values[0];
    var maximum = values[n-1];
    var mean = sum / n;
    var medianAge = null;
    if(dataType == 'date') {
        var today = new Date();
        medianAge = (today.getFullYear() - parseInt(median.slice(0,4)))
                + (today.getMonth() + 1 - parseInt(median.slice(4,6)))/12
                + (today.getDate() - parseInt(median.slice(6,8)))/365;
        median = FormatDate(median);
        minimum = FormatDate(minimum);
        maximum = FormatDate(maximum);
    }
    this.stats[col] = {medianAge: medianAge, median: median, minimum: minimum, maximum: maximum, mean: mean, sum: sum};
    return this.stats[col];
}

function padWithBlanks(str)
{
    switch(6 - str.length) {
        case 5:
            return '     ' + str;
        case 4:
            return '    ' + str;
        case 3:
            return '   ' + str;
        case 2:
            return '  ' + str;
        case 1:
            return ' ' + str;
        default:
            return str;
    }
}

/**
 * Sorts the entire table in order, according to the designated
 * Only the iSortCol is required.
 */
function uiBasicTableSort(iSortCol, supressRedraw, isAscendingSort)
{
	var sortState = this.sortState;
	if(sortState.isSorting) {
		alert("Still doing previous sort");
		return;
	}
	sortState.isSorting = true;

	var columnDef 	= this.ColumnDefs[iSortCol];
	// The sort comparison involves a single item or a set of items
	var sortCompare = uiBasicTableSortComp(sortState);
	if(columnDef.type == 'entitySet')
		sortCompare = uiBasicTableEntitySetSortComp(sortState);

	// Commparisons that depend on data type or subType
	if(columnDef.type == 'int')
		sortState.sortColumnCompare = uiBasicTableIntCompare;
	else if(columnDef.type == 'float')
		sortState.sortColumnCompare = uiBasicTableFloatCompare;
	else if(columnDef.subType == 'usClass')
		sortState.sortColumnCompare = uiBasicTableUsClassCompare;
	else
		sortState.sortColumnCompare = uiBasicTableStringCompare;

	var isReversing 	= (iSortCol == sortState.iSortCol);
	sortState.iSortCol 	= iSortCol;
	sortState.columnDef = columnDef;


	// Figure out in which direction to sort
	if(typeof isAscendingSort == 'undefined')
		sortState.isAscendingSort = !(isReversing && sortState.isAscendingSort);
	else
		sortState.isAscendingSort = isAscendingSort;

	if(sortState.doActionCmd) {
		doAction(sortState.doActionCmd, this.sortState);
		return;
	}

    if(isReversing)
	    this.Rows.reverse();
	else
	    this.Rows.sort(sortCompare);

	this.page = 1;
	if(!supressRedraw)
		this.redraw();

	sortState.cache		= null;
	sortState.isSorting = false;
}

/**
 * Compares two rows in the table, based on the current sort Column
 * (passed to the standard sort() method on Arrays)
 */
function uiBasicTableSortComp(sortState)
{
	return function( row, row2 ) {
		var iSortCol = sortState.iSortCol;
		var result = sortState.sortColumnCompare(row[iSortCol], row2[iSortCol]);
		return sortState.isAscendingSort ? result : -result;
	}
}

function uiBasicTableEntitySetSortComp(sortState)
{
	sortState.cache = new Array();
	
	return function(row, row2) {
		var iSortCol = sortState.iSortCol;
		var items = sortState.cache[row[iSortCol]];
		if(!items) {
			items = PipeSetToArray(row[iSortCol]);
			sortState.cache[row[iSortCol]] = items;
		}

		var items2 = sortState.cache[row2[iSortCol]];
		if(!items2) {
			items2 = PipeSetToArray(row2[iSortCol]);
			sortState.cache[row2[iSortCol]] = items;
		}

		for(var n=0;  true;  n++) {
			if(items.length == n)
				return (items2.length == n) ? 0 : (sortState.isAscendingSort ? -1 : 1);
			if(items2.length == n)
				return sortState.isAscendingSort ? 1 : -1;

			var result = sortState.sortColumnCompare(items[n], items2[n]);
		//	alert( "n=" + n + ":  compare " + items[n] + " to " + items2[n] + " result = " + result + " -- items.length=" + items.length + ", items2.length=" + items2.length);
			if(result != 0)
				return sortState.isAscendingSort ? result : -result;
		}
	}
}
/**
 *
 */
function uiBasicTableStringCompare(a, b) {
	a 	= a.toLowerCase();
	b 	= b.toLowerCase();
	return (a < b) ? -1 : (a == b ? 0 : 1);
}

function uiBasicTableIntCompare(a, b) {
	aa 	= parseInt(a);
	bb 	= parseInt(b);

    if(isNaN(aa))
        return isNaN(bb) ? uiBasicTableStringCompare(a, b) : -1;
    if(isNaN(bb))
        return 1;

	return (aa < bb) ? -1 : (aa == bb ? 0 : 1);
}

function uiBasicTableFloatCompare(a, b) {
	aa 	= parseFloat(a);
	bb 	= parseFloat(b);

    if(isNaN(aa))
        return isNaN(bb) ? uiBasicTableStringCompare(a, b) : -1;
    if(isNaN(bb))
        return 1;

	return (aa < bb) ? -1 : (aa == bb ? 0 : 1);
}

function uiBasicTableUsClassCompare(a, b) {
	var a = a.split('/');
	var b = b.split('/');

	var diff = 0;
	for(var n=0;  diff == 0 && n < 2; n++ ) {
		if(a.length == n)
			return (b.length == n) ? 0 : -1;
		if(b.length == n)
			return 1;

		aa = parseFloat(a[n]);
		bb = parseFloat(b[n]);

		if(aa == bb || isNaN(aa) || isNaN(bb))
			diff = (a[n] < b[n]) ? -1 : (a[n] == b[n] ? 0 : 1);
		else
			diff = (aa < bb) ? -1 : 1;
	}
	return diff;
}

/**
 * builds a link for the given column text in the row
 */
function uiBasicTableMakeLink(row, col)
{
    var	text = MakeTableCellHtml(this, row, col, GetGlobalName(this), true);

	this.addHTML(text);
}

/**
 * Reveals the number of visible columns in the table (including menus and numbers)
 */
 function uiBasicTableVisibleCols()
 {
	if ( this.nCols > 0 )
		return this.nCols;

	var count = 0;

	for (var iCol = 0; iCol < this.display.columns.length; iCol ++)
	{
		if ( this.display.columns[iCol].show )
			count ++;
	}

	if ( this.display.number )
		count++;

	if ( this.display.select )
		count++;

	this.nCols = count;
	return count;
 }

 /**
  * Determines and returns the number of pages in the Table
  * object, depending on the page settings
  */
 function uiBasicTableGetNumPages()
 {
	if(this.display.page) {
		var rows = this.Rows.length;
		var pages = (rows / this.display.page);
		this.nPages = Math.round(pages);
		if ( this.nPages < pages || this.nPages == 0 )
			this.nPages++;
	}
	else
		this.nPages = 1;

	return this.nPages;

 }

 /**
  * Renders the page navigation HTML for the current page number
  * and page settings.
  */
 function uiBasicTableMakePageNav()
 {
 	var pages = this.getNumPages();
	var html = '<font class="form">Page ' + this.page + ' of ' + pages + (pages > 1 ? ':' : '') + '&nbsp;</font>';

	if(this.getNumPages() > 1) {
		var anchor = '<a href="#" class="uiTablePager" onClick="GetUiElem(' + this.id + ').';
		html +=	anchor + 'setPage(1)">[&lt;&lt;]</a> ';
		html +=	anchor + 'prevPage()">[&lt;]</a> ';
		html +=	anchor + 'nextPage()">[&gt;]</a> ';
		html +=	anchor + 'setPage('+ pages + ')">[&gt;&gt;]</a>&nbsp;';
	}

	return html;
 }

 /**
  * Sets the page to the previous page in the set
  */
 function uiBasicTableNextPage()
 {
	if ( this.page < this.getNumPages())
	{
		this.page++;
		this.redraw();
	}
 }

 /**
  * Sets the page to the next page in the set
  */
 function uiBasicTablePrevPage()
 {
	if ( this.page > 1)
	{
		this.page--;
		this.redraw();
	}
 }

 /**
  * Sets the page to the given page, if it is in the set.
  */
 function uiBasicTableSetPage(page)
 {
	if ( page > 0 && page <= this.getNumPages() && page != this.page)
	{
		this.page = page;
		this.redraw();
	}
	else if ( page != this.page )
		alert ('Invalid page selection');

 }


UIBasicTable.prototype.setUiSibbling = function(uiSibbling)
{
	this.uiSibbling = uiSibbling;
}

/**
  * Changes all rows to the specified selectedstate
  */
 function uiBasicTableSelectAllRows(isSelected)
 {
	var checkbox = GetDomElem('row.sel.' + this.id);		// Column heading checkbox
	if(typeof isSelected == 'undefined')
		isSelected = checkbox.checked;

	for(var iRow=0;  iRow < this.Rows.length;  iRow++)
		this.selectRow(iRow, isSelected);

	if(this.uiSibbling && this.uiSibbling.setItemSelectAllFromSibbling)
		this.uiSibbling.setItemSelectAllFromSibbling(isSelected);
}

UIBasicTable.prototype.setItemSelectFromSibbling = function(itemUid, isSelected)
{
    for(var iRow in this.Rows)
    {
        if(this.getRowUid(iRow) == itemUid)
        {
            this.selectRow(iRow, isSelected, true);
            break;
        }
    }
}

/**
  * Selects rows with IDs specified by pipe set
  */
UIBasicTable.prototype.setItemSelectFromUids = function(pipeSet)
{
    if(!pipeSet)
        return 0;

    var nMatched = 0;
	for(var iRow=0;  iRow < this.Rows.length;  iRow++) {
        var uid = ParseUid(this.Rows[iRow][this.entityIdCol], this.ColumnDefs[this.entityIdCol].subType);
	    var target1 = '|' + uid.entityId + '|';
	    if((pipeSet.indexOf(target1) >= 0) || (pipeSet.indexOf('|' + MakeUid(uid.entityTypeCd, uid.entityId) + '|') >= 0)) {
		    this.selectRow(iRow, true);
		    nMatched++;
		}
	}
	return nMatched;
}

UIBasicTable.prototype.getRowUid = function(iRow)
{
    var entityId = this.Rows[iRow][this.entityIdCol];
    if(entityId.indexOf(':') == -1)
    {
        var entityTypeCd = this.ColumnDefs[this.entityIdCol].subType;
        entityId = MakeUid(entityTypeCd, entityId);
    }
    return entityId;
}

/**
  * Selects a single row from the table, and un-selects the table row
  * last selected, if the table is in single-select mode.
  */

function uiBasicTableSelectRow(row, isSelected, skipNotifySibbling)
 {
    if(row < 0 || row >= this.Rows.length)
        return;

  	if(typeof isSelected == 'undefined')
 		isSelected = !this.Rows[row][this.selectCol];

 	if(isSelected == this.Rows[row][this.selectCol] )
 		return;

	if(isSelected)
	{
		if(this.limitSelect && this.nSelected == this.limitSelect)
		{
			// uncheck the checkbox setting for the row
			var checkbox = GetDomElem('row.sel.' + this.id + '.' + row);
			if ( checkbox && checkbox != null )
				checkbox.checked = false;

			alert ('Must unselect one item to select this item');
			return;
		}
		else
		{
			this.Rows[row][this.selectCol] = true;
			this.liteRow(row, ROW_BG_SEL);

			if(this.display.select == "single" && this.lastSelect != null)
			{
				this.Rows[this.lastSelect][this.selectCol] = false;
				this.liteRow(this.lastSelect, ROW_BG_STD);

				// Uncheck the checkbox setting for the row if it is on screen
				var checkbox = GetDomElem('row.sel.' + this.id + '.' + this.lastSelect);
				if(checkbox && checkbox != null )
					checkbox.checked = false;
			}

			this.lastSelect = row;
			this.nSelected++;
		}
	}
	else
	{
		this.lastSelect = null;
		this.Rows[row][this.selectCol] = false;
		this.liteRow(row, ROW_BG_STD);
		this.nSelected--;
	}

	if(this.iFirstRow <= row && row < this.iLastRow) {
		var checkbox = GetDomElem('row.sel.' + this.id + '.' + row);
		if(checkbox)
			checkbox.checked = isSelected;
	}

	if(!skipNotifySibbling && this.uiSibbling && this.uiSibbling.setItemSelectFromSibbling)
        this.uiSibbling.setItemSelectFromSibbling(this.getRowUid(row), isSelected);
 }

 /**
  * Changes the style of the given row <TR> html element.
  */
 function uiBasicTableLiteRow(iRow, color)
 {
 	if(this.iFirstRow <= iRow && iRow < this.iLastRow)
 	{
		var trObj = GetDomElem('row.'+ this.id + '.' + iRow);
		if ( trObj && trObj != null )
			trObj.style.background = color;
	}
 }

 /**
  * Returns the sort state
  */
 function uiBasicTableGetSortState()
 {
    return this.sortState;
 }

//========================================================================
// END: UIBasicTable Class
//========================================================================

/*
 * Copyright IPVision, Inc 2003 - 2005.   All rights reserved.
 */
 

function UITableRowPager(label, table, detailMenuData, entityIdCol, tsLabel, tsName)
{
// INITIALIZE
	uiTableRowPagerInit(this);

// ARGUMENT INITIALIZATION
	if(label != null)
		this.label = label;

	// TODO:  Put the table entity ID column number into the basic table defintion so it does not
	// have to be hacked into the table.  It is needed by the code that generates the automatic
	// actions.
	table.entityIdCol = entityIdCol;
	this.table = table;
	this.tsLabel = tsLabel;
	this.ColumnDefs = table.ColumnDefs;
	this.Rows = table.Rows;

	if(detailMenuData) {
		var entityTypeCd = this.table.ColumnDefs[entityIdCol].subType;
		var entityId = this.table.Rows[0][entityIdCol];

		var menus = gRes.entityActions.Item;
		for(var n=0;  n < menus.length;  n++ ) {
			if(menus[n].entityTypeCd == entityTypeCd)
				break;
		}

		var actionMenu = MakeDetailActionMenu(menus[n], "Actions Menu", entityId, GC.ACTION_PAGE_ENTITY_DETAIL, tsName);
		this.detailMenu = makeMenu(actionMenu);
		this.detailMenu.parent = this;
		if(this.detailMenu.items.length > 0)
			this.entityIdLink = "Javascript:" + this.detailMenu.items[0].action;
	}

	if(false && detailMenuData != null )
	{
		this.detailMenu = makeMenu(detailMenuData);
		this.detailMenu.parent = this;
		var subMenu = this.detailMenu;
		if(subMenu.items.length > 0)
			this.entityIdLink = "Javascript:" + subMenu.items[0].action;
	}
}

/**
 * UITableRowPage Initializer (inherits from UIElement)
 */
function uiTableRowPagerInit(object)
{
// INHERIT
	uiBasicTableInit(object);

// MEMBER VARIABLES
	object.label = '[Default Label]';
	object.table = null;
	object.tsLabel = null;
	object.rowIdx = 0;
	object.tblHLine = '<tr class="bgBrdrLit"><td colspan="5">' + SHIM + '</td></tr>';
	object.tblVLine = '<td width="1" class="bgBrdrLit">' + SHIM + '</td>';
	object.usePaging = false;
	object.detailMenu = null;
	object.detailLink = null;

// PUBLIC METHODS

	/** Builds the Menu HTML */
	object.build = uiTableRowPagerBuildHTML;

// INTERNAL METHODS
	/** Makes the Page Navigation for the Header */
	object.makePageNav = uiTableRowPagerMakePageNav;
	/** Moves to the next page */
	object.nextPage = uiTableRowPagerNextPage;
	/** Moves to the previous page */
	object.prevPage = uiTableRowPagerPrevPage;
	/** Sets the page */
	object.setPage = uiTableRowPagerSetPage;

// STATIC INITIALIZATION

}

//------------------------------------------------------------------
// PUBLIC CLASS METHODS
//------------------------------------------------------------------

/**
 * Builds the HTML for the Page
 */
function uiTableRowPagerBuildHTML()
{
	this.resetHTML();

	// If it's not a redraw, we need to create the <div> to hold the table.
	// For a redraw, we'll just replace the innerHTML of the existing <div>
	if(!this.isRedraw)
		this.addHTML('<div id="'+ this.domElemId + '">');

	var usePaging = this.usePaging;

	// SETUP TITLE BAR
	var titleBar = new UIFrame();
	titleBar.setSize("100%", 16);
	if ( usePaging )
		titleBar.addElement('<table cellpadding="0" cellspacing="0" border="0" width="100%"><tr><td>');
	if ( this.detailMenu != null )
	{
		titleBar.addElement('<table cellpadding="0" cellspacing="0" border="0"><tr>');
		titleBar.addElement('<td nowrap width="200" style="vertical-align: middle"><font class="fgDark"><font class="uiTableHead">' + this.label + '</font></font></td>');
		titleBar.addElement('<td nowrap width="200"><font class="fgDark"><font class="uiTableHead">' + this.detailMenu.getHTML() + '</font></font></td></tr></table>');
	}
	else
		titleBar.addElement('<font class="fgDark"><font class="uiTableHead">' + this.label + '</font></font>');
	if ( usePaging )
		titleBar.addElement('</td><td nowrap align="right">' + this.makePageNav() + '</td></tr></table>');
	this.addHTML(titleBar.getHTML());

	if(this.table.Rows.length == 0)
		return;

	// RENDER THE ROW OBJECT
	var curRow = this.table.Rows[this.rowIdx];
	var columnDefs = this.table.ColumnDefs;
	var sourceLabel = '???';
	var sourceLabels = new Array();

	for ( var iCol = 0; iCol < curRow.length; iCol ++)
	{
		if( columnDefs[iCol].name == 'select' )
			continue;
		var newSourceLabel = columnDefs[iCol].sourceLabel;
		if( sourceLabel != newSourceLabel )
		{
			for(var k = 0; k < sourceLabels.length; k++)
			{
				if(sourceLabels[k] == newSourceLabel)
					break;
			}
			if(k == sourceLabels.length)
				sourceLabels[k] = newSourceLabel;
			sourceLabel = newSourceLabel;
		}
	}

	this.addHTML('<table width="100%" border="0" cellpadding="0" cellspacing="0">');
	for ( var iSource = 0; iSource < sourceLabels.length; iSource++)
	{
		if( this.tsLabel != null )
		{
			var sourceInfo = this.tsLabel + ' Portfolio: ' + sourceLabels[iSource];
			this.addHTML(this.tblHLine);
			this.addHTML(this.tblVLine);
			this.addHTML('<td width="150" valign="top" class="bgLightShade"><table width="100%" cellpadding="3" cellpacing="0"><tr><td><font class="fgDark"><font class="uiTableHead">' + '</font></font></td></tr></table></td>');
			this.addHTML(this.tblVLine);
			this.addHTML('<td valign="top" class="bgLightShade"><table width="100%" cellpadding="3" cellpacing="0"><tr><td align="center"><font class="fgDark"><font class="uiTableHead">' + sourceInfo + '</font></font></td></tr></table></td>');
			this.addHTML(this.tblVLine);
		}
		for ( var iCol = 0; iCol < curRow.length; iCol ++)
		{
			if( columnDefs[iCol].name == 'select' )
				continue;
			if( columnDefs[iCol].sourceLabel != sourceLabels[iSource] )
				continue;

			if((iCol == this.table.entityIdCol) && (this.entityIdLink != null))
				var text = '<a href="' + this.entityIdLink + '">' + curRow[iCol] + '</a>';
			else
				var text = MakeTableCellHtml(this.table, this.rowIdx, iCol, GetGlobalName(this));

			var label = 'Unknown Field';
			if ( iCol < columnDefs.length )
				label = columnDefs[iCol].label;

			this.addHTML(this.tblHLine);
			this.addHTML(this.tblVLine);
			this.addHTML('<td width="150" valign="top" class="bgLightShade" id="' + columnDefs[iCol].name + '">');
				this.addHTML('<table width="100%" cellpadding="3" cellpacing="0"><tr><td>')
				this.addHTML('<font class="fgDark"><font class="uiTableHead">' + label + '</font></font></td></tr>');
				this.addHTML('</table>');
			this.addHTML('</td>');
			this.addHTML(this.tblVLine);
			this.addHTML('<td valign="top"><table width="100%" cellpadding="3" cellpacing="0"><tr><td><font class="uiTableCell">' + text + '</font></td></tr></table></td>');
			this.addHTML(this.tblVLine);
		}
	}
	this.addHTML(this.tblHLine);
	this.addHTML('</table>');

	if(!this.isRedraw)
		this.addHTML('</div>');
}

//------------------------------------------------------------------
// INTERNAL CLASS METHODS
//------------------------------------------------------------------

/**
 * Constructs the Page Navigators for the header
 */
function uiTableRowPagerMakePageNav()
{
	var html = '';
	var pages = this.table.Rows.length;
	var curRow = this.rowIdx + 1;

	html += '<font class="form">Page ' + curRow + ' of ' + pages + ': ';
	html +=	'<a href="javascript:GetUiElem(' + this.id + ').setPage(0)">[&lt;&lt;]</a> ';
	html +=	'<a href="javascript:GetUiElem(' + this.id + ').prevPage()">[&lt;]</a> ';
	html +=	'<a href="javascript:GetUiElem(' + this.id + ').nextPage()">[&gt;]</a> ';
	html +=	'<a href="javascript:GetUiElem(' + this.id + ').setPage('+ (pages-1) + ')">[&gt;&gt;]</a></font>';

	return html;
}

/** Moves to the next page */
function uiTableRowPagerNextPage()
{
	if ( this.rowIdx < this.table.Rows.length - 1 )
	{
		this.rowIdx++;
		this.redraw();
	}
}

/** Moves to the previous page */
function uiTableRowPagerPrevPage()
{
	if ( this.rowIdx > 0 )
	{
		this.rowIdx--;
		this.redraw();
	}
}

/** Sets the page */
function uiTableRowPagerSetPage(page)
{
	if ( this.rowIdx != page )
	{
		this.rowIdx = page;
		this.redraw();
	}
}

//========================================================================
// END: UITableRowPager Class
//========================================================================
