// Begin: Code to support IE 4.x & IE 5.0, which don't support the Array.push() or splice() methods.
function array_push( object )
{
	this[this.length] = object
}
if ( Array.prototype.push == null )
	Array.prototype.push = array_push;

// Code to support IE 4.x & IE 5.0, which don't support the
// Array.splice() method.
function array_splice(start, count)
{
	var nLength = this.length;

	if ( arguments.length <= 2 )
	{
		// Deletion
		if ( arguments.length < 1 )
			start = 0
		if ( arguments.length < 2 )
			count = nLength-start;

		if ( count > nLength )
			count = nLength

		for ( var i = start, j = start + count; j < nLength; i++, j++ )
		{
			this[i] = this[j];
		}
		this.length = nLength - count;
	}
	else if ( arguments.length > 2 )
	{
		// Insertion
		var nNewElements = arguments.length - 2
		this.length = nLength + nNewElements

		// First move elements to make room
		for ( var i = nLength; i >= start+nNewElements; i-- )
		{
			this[i] = this[i-nNewElements]
		}

		// Now copy in the values
		for ( var i = start, j = 2; i < nNewElements; i++, j++ )
		{
			this[i] = arguments[j]
		}
	}
}
if ( Array.prototype.splice == null )
	Array.prototype.splice = array_splice;
// End: Code to support IE 4.x & IE 5.0, which don't support the Array.push() or splice() methods.

function BlankPage()
	{
	return "<html><head></head><body></body></html>"
	}

// Wrap a string in single quotes (escaping other single quotes)
function quoteString( sVal )
	{
	return '\'' + sVal.replace(/'/g, '\\\'') + '\''
	}

function useModal()
	{
	// Have problems with IE on the Mac and displaying messages in a modal dialog.
	return ( (window.showModalDialog != null) && !isMac() )
	}

function pause(numberMillis)
	{
	if ( useModal() )
		{
		var dialogScript = 
			'window.setTimeout(' +
			' function () { window.close(); }, ' + numberMillis + ');';

		var result =  window.showModalDialog(
			'javascript:document.writeln(' +
			'"<script>' + dialogScript + '<' + '/script>")');
		}
	else
		{
        var now = new Date();
        var exitTime = now.getTime() + numberMillis;
        while (true)
			{
            now = new Date();
            if (now.getTime() > exitTime)
                return;
			}
		}
	}

// Function isNav returns true if current browser is Netscape Navigator
function isNav()
	{
    // convert all characters to lowercase to simplify testing
    var agt=navigator.userAgent.toLowerCase();

    return ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
                && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
                && (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1));
	}

function isNav4()
	{
    return (isNav() && (parseInt(navigator.appVersion) == 4));
	}

function getIEVersion()
	{
	var ua = window.navigator.userAgent
	var msie = ua.indexOf ( "MSIE " )

	if ( msie > 0 )      // If Internet Explorer, return version number
		return parseFloat (ua.substring (msie+5))
	else                 // If another browser, return 0
		return 0
	}

// Browser-sniffing functions below are based off of "The Ultimate JavaScript Client Sniffer"
// available from Mozilla.org

// Function isIE returns true if current browser is Microsoft Internet Explorer
function isIE()
	{
    // convert all characters to lowercase to simplify testing
    var agt=navigator.userAgent.toLowerCase();

    return ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
	}

function isIE55Plus()
	{
	return (getIEVersion() >= 5.5)
	}

function isNetscape6()
	{
	// This method detects "Netscape6" as any Mozilla 5.0-based browser.
	// It does not explicitly check for Netscape6 in the userAgent string.
	// Thus, this will currently detect Netscape 7 as Netscape 6.

	var agt = navigator.userAgent.toLowerCase()
	var is_nav  = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
	            && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
	            && (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1));

	return ( is_nav && parseInt(navigator.appVersion) == 5)
	}

function isNetscape7()
	{
	// Do very simple Netscape 7 detection.
	// Currently we really have no reason to do this.  There is no Netscape 7 functionality
	// that we take advantage of.
	var agt = navigator.userAgent.toLowerCase()
	var is_nav  = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
	            && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
	            && (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1));

	var nsString = 'netscape/'
	var nsVer = -1
	var nsLoc = agt.indexOf(nsString)
	if ( nsLoc > -1 )
		{
		nsVer = parseInt(agt.substring(nsLoc + nsString.length))
		}

	return ( is_nav && (parseInt(navigator.appVersion) == 5) && (nsVer >= 7) )
	}

function isMac()
	{
	var agt = navigator.userAgent.toLowerCase()
	return (agt.indexOf("mac") != -1);
	}

// End browser-sniffing

// Utility routine for extracting query string arguments
function GetQSValue( sSearch, sName )
	{
	// Grab the query string and replace the leading "?" with an & for our searches
	if ( sSearch.indexOf("?") == 0 )
		sSearch = sSearch.substring(1)
	sSearch = "&" + sSearch

	// Initialize our return value
	var sValue = ''

	// Look for &varname=
	var nPos = sSearch.indexOf( "&"+sName+"=" )
	if ( nPos >= 0 )
		{
		// Trim out everything up to the equal sign
		sValue = sSearch.substring( nPos+sName.length+2, sSearch.length )

		// Trim out any trailing parameters
		nPos = sValue.indexOf( "&" )
		if (nPos >= 0)
			sValue = sValue.substring( 0, nPos )

		// Unescape the value
		sValue = unescape( sValue )
		}
				
	return sValue
	}

function isLowRes() {
   /*
   ** Check if the browser is running in a low-resolution environment
   ** try to use the screen object. If not available, try to use Java.
   ** If not available, assume low-res.
   **     
   ** Returns true if in a low-resolution environment (width < 800 pixels)
   */
   if (self.screen) 
      {
      // Available in JavaScript 1.2
      return (screen.width < 800);
      }
   else 
      {
      // Available in JavaScript 1.1
      if (navigator.javaEnabled && navigator.javaEnabled())
         return (java.awt.Toolkit.getDefaultToolkit().getScreenSize().width < 800);
      else
         return true;
      }
}

function debugDisplayObject( name, obj, bShallow )
{
	if ( obj != null )
	{
		if ( bShallow == null ) bShallow = false

		for ( var i in obj )
		{
			alert( name + '[' + i + '] = ' + typeof( obj[i] ) + '[' +  obj[i] + ']' )
			if ( (!bShallow) && (typeof( obj[i] ) == 'object') )
				displayObject( i, obj[i], bShallow )
		}
	}
}

// Clone an Object
// if bShallow is set to true, then child objects are not cloned -
//    only their references are copied.
// if bCreateNewFunctions is true, then we use the Function object
// to create new instances of the function to avoid getting the
// "Cannot execute code from a freed script" error.
function clone( obj, bShallow, bCreateNewFunctions )
{
	var o = null
	if ( obj != null )
	{
		if ( bShallow == null ) bShallow = false;
		if ( bCreateNewFunctions == null ) bCreateNewFunctions = false;

		if ( isDate( obj ) )
			o = new obj.constructor( obj )
		else
			o = new obj.constructor()

		for ( var i in obj )
		{
			// alert( i + ' = ' + typeof( obj[i] ) + '[' +  obj[i] + ']' )
			if ( (!bShallow) && (typeof( obj[i] ) == 'object') )
				o[i] = clone( obj[i], bShallow, bCreateNewFunctions )
			else if ( (bCreateNewFunctions) && (typeof( obj[i] ) == 'function') )
				o[i] = new Function( obj[i].toString() );
			else
				o[i] = obj[i]
		}
	}

	return o;
}

// Function isDate()
// Returns true if the object is a date, false if not
function isDate( obj )
{
	// Make sure a valid object is passed.
	if ( obj == null )
		return false;

	// Checking the constructor to determine if something is a date
	// does not always work, though it isn't clear why.
	if ( obj.constructor == Date )
		return true;

	// Check some somewhat obscure date methods to see if they exist
	// in the object.
	if ( (obj['getUTCMilliseconds'] != null) && (obj['setUTCMonth'] != null) )
		return true;

	return false;
}

function Type(p)
{
	var Rspc = "[\\s]*";
	var Rwd = "[\\w]+";

	var REtxt = "function" + Rspc + "(" + Rwd + ")\\(";
	var typeRE = new RegExp(REtxt, "i");
	var REout = typeRE.exec(String(p.constructor));

	return REout == null ? null : String(REout[1]).toLowerCase();
}


// Function isEmptyString()
// Returns true if the specified string is:
//    * null
//    * zero length
//    * comprised only of space, tab, and newline characters
function isEmptyString( sString )
{
	return ( ( sString == null ) ||
	         ( sString+'' == '' ) ||
	         ( (sString+'').search(/[^ \t\n]/) < 0 )
	       );
}

// Function isNull()
// Returns the first argument if it is not-null.
// Returns the second argument if the first argument is null.
function isNull( var1, var2 )
{
	if ( var1 == null )
		return var2;
	else
		return var1;
}

function HtmlEncode( sString, fLFToBR )
{
	if ( sString == null )
		return ''

	// Make sure the value is a string
	sString = sString.toString()

	// Replace < > & " with their "entity reference".
	sString = sString.replace(/&/g, '&amp;')
	sString = sString.replace(/</g, '&lt;')
	sString = sString.replace(/>/g, '&gt;')
	sString = sString.replace(/"/g, '&quot;')

	// Replace newlines with <br> tags.
	if ( fLFToBR )
		{
		sString = sString.replace(/\n/g, '<br>')
		}

	return sString;
}

function JSEncode( sString )
{
	if ( sString == null )
		return ''

	// Make sure the value is a string
	sString = sString.toString()

	// Escape \r, \n, ", ', \, /
	// Must do the \ first!
	sString = sString.replace(/\\/g, '\\\\')

	sString = sString.replace(/\r/g, '\\r')
	sString = sString.replace(/\n/g, '\\n')
	sString = sString.replace(/"/g, '\\"')
	sString = sString.replace(/'/g, '\\\'')
	sString = sString.replace(/\//g, '\\\/')

	return sString
}

function doubleDigit( nVal )
{
	nVal = parseInt(nVal,10)
	if ( nVal < 10 )
		return '0' + nVal;
	else
		return '' + nVal;
}

function formatDate( date, fIncludeTime )
{
	if ( date == null )
		return ''

	if ( !isDate(date) )
	{
		//alert( 'isDate returned false for ' + date.constructor  + '\n' + ( date.constructor == Date ));
		return date.toString()
	}

	var str = null;
	var chSep = scLocalize.sDateSep;
	if (scLocalize.sDateFormat == 'YMD')
	{
		str = date.getFullYear() + chSep + 
		      doubleDigit(date.getMonth() + 1) + chSep +
		      doubleDigit(date.getDate());
	}
	else if (scLocalize.sDateFormat == 'DMY')
	{
		str = doubleDigit(date.getDate()) + chSep +
		      doubleDigit(date.getMonth() + 1) + chSep +
			  date.getFullYear();
	}
	else // if (scLocalize.sDateFormat == 'MDY')
	{
		str = doubleDigit(date.getMonth() + 1) + chSep +
		      doubleDigit(date.getDate()) + chSep +
			  date.getFullYear();
	}

	if ( fIncludeTime )
		str += ' ' + formatTimeStr( date.getHours(), date.getMinutes(), date.getSeconds() );

	return str;
}

function unFormatDate( sDate )
{
	if ( isEmptyString(sDate) )
		return null

	var year  = 0
	var month = 0
	var day   = 0

	var chSep = scLocalize.sDateSep;

	var arParts = sDate.split(chSep)

	// We should have 3 parts
	if ( arParts.length != 3 )
		return null

	if (scLocalize.sDateFormat == 'YMD')
	{
		year  = arParts[0]
		month = arParts[1]
		day   = arParts[2]
	}
	else if (scLocalize.sDateFormat == 'DMY')
	{
		day   = arParts[0]
		month = arParts[1]
		year  = arParts[2]
	}
	else // if (scLocalize.sDateFormat == 'MDY')
	{
		month = arParts[0]
		day   = arParts[1]
		year  = arParts[2]
	}

	return new Date(year, month-1, day)
}

function formatTime( s24hrTime )
{
	// Convert a date in 24-hour format to 12-hour format.
	// Hopefully someday, JavaScript will support internationalized date/time formats.

	if ( isEmptyString( s24hrTime ) && (hours == null) )
		return ''

	// Tokenize the string on colons.
	// If no colon-found, then we expect a HHMMSS or HHMM format.
	var hours   = ''
	var minutes = ''
	var seconds = ''
	if ( s24hrTime.indexOf(scLocalize.sTimeSep) >= 0 )
	{
		var arPieces = s24hrTime.split(scLocalize.sTimeSep)
		if ( arPieces.length > 0 )
			hours   = arPieces[0]
		if ( arPieces.length > 1 )
			minutes = arPieces[1]
		if ( arPieces.length > 2 )
			seconds = arPieces[2]
	}
	else
	{
		hours   = s24hrTime.substring(0,2)
		minutes = s24hrTime.substring(2,2)
		seconds = s24hrTime.substring(4,2)
	}

	return formatTimeStr( hours, minutes, seconds )
}

function formatTimeStr( hours, minutes, seconds )
{
	var fAM = true
	if ( hours >= 12 )
	{
		fAM = false
		hours -= 12
	}

	if ( hours == 0 )
		hours = 12

	var sRet = null
	if ( seconds > '' )
		sRet = doubleDigit(hours) + scLocalize.sTimeSep + doubleDigit(minutes) + ':' + doubleDigit(seconds)
	else
		sRet = doubleDigit(hours) + scLocalize.sTimeSep + doubleDigit(minutes)

	if ( fAM )
		sRet += ' ' + scLocalize.sAM
	else
		sRet += ' ' + scLocalize.sPM

	return sRet
}

// Compare two dates - null values get sorted BEFORE non-null values
function dateComp( d1, d2 )
{
	var nD1 = (d1 == null) ? Number.NEGATIVE_INFINITY : d1.getTime()
	var nD2 = (d2 == null) ? Number.NEGATIVE_INFINITY : d2.getTime()

	if ( nD1 > nD2 )
		return 1
	else if ( nD1 < nD2 )
		return -1

	return 0
}

function numberToString( expr )
{
	if ( expr == null )
		return ''
	return expr + ''
}

function formatNumber(expr, decplaces, decchar)
{
	if ( isEmptyString(numberToString(expr)) )
		return expr

   if ( expr == "---" )
		return expr;
		
	if (decchar == null)
		{
		if ( (self.scLocalize != null) && (!isEmptyString(scLocalize.sDecimal)) )
			decchar = scLocalize.sDecimal
		else
			decchar = '.'
		}

	var str = "" + Math.round(eval(expr) * Math.pow(10,decplaces));

	while (str.length <= decplaces)
	{
		str = "0" + str;
	}

	var decpoint = str.length - decplaces;

	// decplaces of zero is a special case...
	if (decplaces == 0)
		str = str.substring(0,decpoint)
	else
		str = str.substring(0,decpoint) + decchar + str.substring(decpoint, str.length);

	// If the value is negative (and between -1 and 0), we need to be sure not to return
	// "-.55".  This should be "-0.55".
	if ( (str.charAt(0) == '-') && (str.charAt(1) == decchar) )
		str = '-0' + str.substring(1)

	return str
}

function isInteger( val )
{
	if ( val == null )
		return false

	var intVal = parseInt(val)
	if ( isNaN(intVal) )
		return false

	var floatVal = parseFloat(val)
	if ( intVal != floatVal )
		return false

	return true
}

function makeMediaPath( sImg )
{
	return objCore.makePath(objCore.sMediaPath, sImg);
}

function makeTemplatePath( sTemplate )
{
	return objCore.makePath(objCore.templatePath, sTemplate);
}

function makeApplicationURL( sQueryString )
{
	return objCore.phnxapp + sQueryString;
}

// Functions used to get the From and To dates for Class Searches
function getFromDate( nLookbackHorizon )
{
    if ( (nLookbackHorizon==null) || (nLookbackHorizon < 1) || (nLookbackHorizon > 9999) )
		nLookbackHorizon = 0;

	var dFromDate = new Date();
	dFromDate.setHours(0);
	dFromDate.setMinutes(0);
	dFromDate.setSeconds(0);
	dFromDate.setMilliseconds(0);
	dFromDate.setDate(dFromDate.getDate() - nLookbackHorizon);

	return dFromDate;
}
function getFromDateStr( nLookbackHorizon )
{
	return formatDate( getFromDate( nLookbackHorizon ) );
}

function getToDate( nHorizon )
{
    if ( (nHorizon < 1) || (nHorizon > 9999) )
		nHorizon = 9999

	var dToDate = new Date();
	dToDate.setHours(0);
	dToDate.setMinutes(0);
	dToDate.setSeconds(0);
	dToDate.setMilliseconds(0);

	dToDate.setDate(dToDate.getDate() + nHorizon);
	
	return dToDate;
}
function getToDateStr( nHorizon )
{
	return formatDate( getToDate( nHorizon ) );
}

function isSameDate( objDate1, objDate2 )
{
	return ( objDate1.valueOf() == objDate2.valueOf() );
}

//
// Logon state-related functions
//

// The "STCSession" cookie is created client-side and used to prevent
// someone from having two browser windows for the same session.
var STC_SESSION_COOKIE = 'STCSession'
function hasSTCSession()
{
	var s = GetCookie(STC_SESSION_COOKIE)
	return (s == 'Y')
}

function initSTCSession()
{
	SetCookie(STC_SESSION_COOKIE, 'Y')
}

function clearSTCSession()
{
	SetCookie(STC_SESSION_COOKIE, 'N')
}

// Connection info is stored in a cookie "ConnInfo".
// The ConnInfo is then a series of name/value pairs.
function getConnectInfo( sName )
{
	// Fix for weird IE 4 bug which would show up when desktop.htm would
	// call getConnectionClient() - sName would be null!
	sName = arguments[0]

	var sValue = null

	var sConnInfo = GetCookie('ConnInfo')

	if ( !isEmptyString(sConnInfo) )
	{
		if ( sConnInfo.charAt(0) == '"' )
			sConnInfo = sConnInfo.substr(1)
		if ( sConnInfo.charAt(sConnInfo.length-1) == '"' )
			sConnInfo = sConnInfo.substr(0,sConnInfo.length-1)

		var arPairs = sConnInfo.split( '&' )

		var sName = sName + '='
		for ( var i = 0; i < arPairs.length; i++ )
		{
			if ( arPairs[i].indexOf(sName) == 0 )
			{
				sValue = arPairs[i].substring(sName.length)
				break
			}
		}
	}

	return sValue
}

function clearConnectInfo()
{
	SetCookie('ConnInfo', '')
}

//function setConnectInfo( sName, sValue )
//{
//	This should only occur server side
//}

// True if logged in, false otherwise
function isLoggedIn()
{
	if ( (objCore.userProperties == null)
	  || (objCore.isEmptyString(objCore.userProperties.userid)) )
		return false;
	else
		return true;
}

function getConnectionID()
{
	return getConnectInfo('connid')
}

function getSessionID()
{
	return getConnectInfo('sid')
}

function getSiteID()
{
	return getConnectInfo('siteid')
}

function getConnectionClient()
{
	return getConnectInfo('client')
}

function getLinkID()
{
	// Get the current link id
	var linkid = GetCookie("linkid")
	if ( linkid == null )
	{
		// Set the link id based on the current time
		linkid = new Date().getTime() % 1000000
	}
	else
	{
		// Convert the string linkid value to integer
		linkid = parseInt(linkid)
	}

	// Increment the link id
	var idNew = linkid + 1

	// Reset the linkid cookie
	SetCookie("linkid", idNew)

	return linkid
}

function getUniqueKey()
{
	if ( objCore.userProperties != null )
		return objCore.userProperties.uniquekey
	return null
}

function getYUniqueKey()
{
	if ( objCore.userProperties != null )
		return objCore.userProperties.userid
	return null
}

function getSessionFirstName()
{
	if ( objCore.userProperties != null )
		return objCore.userProperties.firstname
	return null
}

function getSessionLastName()
{
	if ( objCore.userProperties != null )
		return objCore.userProperties.lastname
	return null
}

function getSessionPersonName()
{
	var	sFirstName = objCore.getSessionFirstName();
	var	sLastName  = objCore.getSessionLastName();

	var sPersonName = '';
	if ( !isEmptyString(sFirstName) || !isEmptyString(sLastName) )
		sPersonName = sFirstName + ' ' + sLastName
	
	return sPersonName;
}

function getSessionUserIsManager()
	{
	if ( objCore.userProperties != null )
		return objCore.userProperties.isManager
	return false
	}

function getEffectiveUserFirstName()
{
	if ( objCore.oEffectiveUser != null )
		return objCore.oEffectiveUser.firstname
	return null
}

function getEffectiveUserLastName()
{
	if ( objCore.oEffectiveUser != null )
		return objCore.oEffectiveUser.lastname
	return null
}

function getEffectiveUserPersonName()
{
	var	sFirstName = objCore.getEffectiveUserFirstName();
	var	sLastName  = objCore.getEffectiveUserLastName();

	var sPersonName = '';
	if ( !isEmptyString(sFirstName) || !isEmptyString(sLastName) )
		sPersonName = sFirstName + ' ' + sLastName
	
	return sPersonName;
}

function copyConnectData( pd )
{
	if ( pd == null )
	{
		objCore.userProperties = null
		SetCookie('PN', '')  // Person Name cookie (from WSS 4)
	}
	else
	{
		if ( pd.userProperties != null )
			objCore.userProperties = cloneUser( pd.userProperties );

		SetCookie('PN', pd.userProperties.firstname + ' ' + pd.userProperties.lastname)
	}
	objCore.fRefresh = 0
}

function copyEffectiveUserData( pd )
	{
	objCore.oEffectiveUser = null

	if ( (pd != null) && (pd.oEffectiveUser != null) )
		objCore.oEffectiveUser = cloneEffectiveUser( pd.oEffectiveUser );
	}
	
// Not sure if this is really needed anymore. It was added for setting
// course variables.  The "escape" call used to not encode pluses properly.
function escapeEx( str )
   {
   var ret = escape( str, 1 )
   var pos = ret.indexOf( '+' )
   while (pos != -1)
      {
      ret = ret.substring( 0, pos ) + "%2B" + ret.substring( pos+1 )
      pos = ret.indexOf( '+' )
      }
   return ret
   }


// Recovery code for excessive use of the forward and back buttons
// (particular in IE).
// This gets called by all pages in the Course Search (or Class Search) area.
// If the page is displayed and the top-level frame has no arInputs,
// then the user went back several pages all in one step, and then
// when they went forward, it attempted to go forward all in one step,
// but did not process each of the main frame's child pages along the way.
function CCSearchRecoveryCheck()
{
	var fMainFrame = objCore.getFrameByName( self, objCore.WSSFrameIDs.MAIN )
	if ( (fMainFrame.arInputs == null)
	  && ( (fMainFrame.ePageID == objCore.WSSPageIDs.CLASSSEARCH)
	    || (fMainFrame.ePageID == objCore.WSSPageIDs.COURSESEARCH) ) )
	{	    
		fMainFrame.location.replace( fMainFrame.location.href )
	}
}

function GetDocumentHeight( doc )
	{
	// NN7 returns the "scrollHeight" of the tabbed frame to be too large in the case where we
	// have already resized the tabbed folder to something "large" (like expanding a content object).
	// If the frame contents become smaller (on the same tab) than the frame itself (like collapsing
	// a content object), then the scrollHeight is returned identical to the clientHeight.
	// I found that we could set the style.height of the frame to 0 here, which then caused NN7 to return the proper scrollHeight:
	//
	// if ( objCore.isNetscape7() )
	//		document.getElementById( folderID ).style.height = '0px'
	//
	// However, NN6 does not even support scrollHeight.  Instead, for both NN6 and NN7, we use the
	// height property of the document, rather than body.scrollHeight;
	if ( objCore.isNetscape6() )
		{
		return doc.height;
		}
	else // IE
		{
		return doc.body.scrollHeight;
		}
	}

function GetOffsetLeft( oElem )
	{
	// Calculate the location of the element within the frame.  Need to walk up the offsetParent's
	// and total up the offset.  Note that in NN7, the offsetParent appears to always just be the BODY.
	var nElemLeft = oElem.offsetLeft;
	var p = oElem.offsetParent;
	while ( p != null )
		{
		nElemLeft += p.offsetLeft;
		p = p.offsetParent;
		}

	return nElemLeft;
	}

function GetOffsetTop( oElem )
	{
	// Calculate the location of the element within the frame.  Need to walk up the offsetParent's
	// and total up the offset.  Note that in NN7, the offsetParent appears to always just be the BODY.
	var nElemTop = oElem.offsetTop;
	var p = oElem.offsetParent;
	while ( p != null )
		{
		nElemTop += p.offsetTop;
		p = p.offsetParent;
		}

	return nElemTop;
	}

// This function is intended to resize a "tabbed folder" which is currently
// always above the FOOTER div.
function ResizeElementAboveFixed( w, idElem, idFixed, nMinHeight )
	{
	var doc = w.document
	var oElem = doc.getElementById( idElem )
	if ( oElem )
		{
		var oFixed = doc.getElementById(idFixed);

		// Calculate the location of the element within the frame.  Need to walk up the offsetParent's
		// and total up the offset.  Note that in NN7, the offsetParent appears to always just be the BODY.
		var nElemTop = GetOffsetTop( oElem )

		// Get the frame height
		var nFrameHeight = doc.body.clientHeight;
		if ( nFrameHeight == null ) // NN6
			nFrameHeight = w.innerHeight;

		// Calculate the height.  Extra 10 pixels added for NN7; calculation was off for unknown reasons.
		var nHeight = (nFrameHeight-nElemTop-oFixed.offsetHeight)-10
		if ( nHeight < nMinHeight )
			nHeight = nMinHeight;
		if ( nHeight >= 0 )
			oElem.style.height = nHeight + 'px'
		}
	}
 
function clWindowSizing( nTargetWidth, nTargetHeight )
	{
	if ( nTargetWidth == null )
		nTargetWidth = 800;
	if ( nTargetHeight == null )
		nTargetHeight = 600;

	// We have to allow for the title bar and status bar (effects height),
	// as well as the left and right window borders.
	// In addition, we don't know where the Task Bar is going to be, so we size
	// and position our window to be centered in the available height or width.

	// Generic padding
	var xPad = 10
	var yPad = 50

	// Determine our unavailable space
	var uaWidth  = screen.width - screen.availWidth;
	var uaHeight = screen.height - screen.availHeight;

	this.width = nTargetWidth;
	this.height = nTargetHeight
	if ( screen.availWidth <= nTargetWidth )
		{
		this.x = uaWidth;
		this.width = screen.availWidth - uaWidth - xPad;
		}
	else
		{
		this.x = (screen.availWidth - nTargetWidth) / 2;
		}

	if ( screen.availHeight <= nTargetHeight )
		{
		this.height = screen.availHeight - uaHeight - yPad;
		this.y = uaHeight;
		}
	else
		{
		this.y = (screen.availHeight - nTargetHeight) / 2;
		}
	 
	return this
	}

// Private function which handles both confirmDlg and alertDlg.
function private_confirmDlg( message, fDoAlert, fNoPing, theOpener )
	{
	if ( useModal() )
		{
		// Pick a default size.  Confirm.htm will resize the height.
		var nWidth = 400;
		var nHeight = 200;

		var dialogTop = (screen.availHeight - nHeight) / 2;
		var dialogLeft = (screen.availWidth - nWidth) / 2;

		// LoadTemplate is not necessary here because Cofirm.htm
		// does not have any includes.  This is done to prevent
		// a ping when displaying the idle timeout error.
		var src = objCore.makeTemplatePath("Confirm.htm");

		var dialogArgs = new Array();
		dialogArgs[0] = new Object();
		dialogArgs[0].g_centerTop = g_centerTop;
		dialogArgs[0].sMessage = message;
		dialogArgs[0].fDoAlert = fDoAlert;
		dialogArgs[0].fNoPing = ( fNoPing == null ? false : fNoPing );
		
		if ( theOpener == null )
			theOpener = self;
		dialogArgs.opener = theOpener;

		// Let theOpener open the modal dialog.  If theOpener is a pop-up window, then letting
		// objCore open the modal cause the pop-up to be hidden while the modal dialog is displayed.
		return theOpener.window.showModalDialog(src, dialogArgs, 
		                              "dialogHeight:"+nHeight+"px;dialogWidth:"+nWidth+"px;dialogTop:"+dialogTop+"px;dialogLeft:"+dialogLeft+"px;center:No;help:No;resizable:Yes;status:No;");
		}
	else
		{
		if ( fDoAlert )
			return alert( message );
		else
			return confirm( message );
		}
	}

function confirmDlg( message )
	{
	return private_confirmDlg( message, false );
	}

function alertDlg( message, fNoPing, theOpener )
	{
	return private_confirmDlg( message, true, ( fNoPing == null ? false : true ), theOpener );
	}


function getPopWindowLocStr( fUseShowModalFormat )
	{
	var left = (objCore.window.screenX != null) ? objCore.window.screenX : objCore.window.screenLeft
	var top  = (objCore.window.screenY != null) ? objCore.window.screenY : objCore.window.screenTop

	left += 100

	var loc = null;
	if ( fUseShowModalFormat )
		{
		loc = ';dialogLeft:' + left + 'px;dialogTop:' + top + 'px;'
		}
	else
		{
		loc = ',screenX=' + left + ',screenY=' + top 
		    + ',left='    + left + ',top='     + top 
		}

	return loc
	}
	