// Return the first child element (ignoring e.g. white space nodes)
function getFirstChildElement(node)
{
	var x = node.firstChild;
	while(x.nodeType!=1)
	{
		x=x.nextSibling;
	}
	return x;
}

function displayErrorMsg(divId, message) {

	//hideAjaxLoadingSpinner();

	if(!divId) {
		return;
	}
		
	var div = dojo.byId(divId);	
	if(!div) {
		return;
	}
	
	// Put out a little "error" icon and message:			
	var ajaxError = document.createElement('div');
	// ajaxError.className = args.tree.ajaxErrorCSSStyle;
	var errorMsg = document.createTextNode(message);
	ajaxError.appendChild(errorMsg);				
	div.replaceChild(ajaxError, getFirstChildElement(div));													
}	

// Get the table of content tree (object) for the current page
function getTocTree() {
	var tocTree;
	var tocTreeElem = dojo.byId("tocTree");
	if(tocTreeElem) {
		tocTree = tocTreeElem.getAttribute('tocTree');
		if(!tocTree) tocTree = tocTreeElem.tocTree;	
	}	
	
	return tocTree;
}

// Get the elsExpansionPane object (if it's available on the current page), otherwise: undefined. 
function getElsExpansionPane() {
	var xPane; 
	var xPaneWidget = dojo.widget.byId("main");
	if(xPaneWidget) {
		xPane = xPaneWidget.xPane;
	}
	if(!xPane) {
		var leftPaneElement = dojo.byId("leftContentPane");
		if(leftPaneElement) {
			xPane = leftPaneElement.getAttribute('xPane');
			if(!xPane) xPane = leftPaneElement.xPane;	
		}
	}
	return xPane;
}

// Get the elsSmartTabs object (if it's available on the current page), otherwise: undefined. 
function getElsSmartTabs() {
	var smartTabs; 
	var smartTabsElem = dojo.byId("leftPaneTabs");
	if(smartTabsElem) {
		smartTabs = smartTabsElem.smartTabs;	
	}
	return smartTabs;
}

// Get the currently displayed eid for the content pane.
function getCurrentEid() {
	var currentEid;
	var contentAreaElement = dojo.byId("bookContentPane");
	if(contentAreaElement) {
		// This attribute is written by elsBookPlayerState whenever
		// the content is updated.
		currentEid = contentAreaElement.requestedEid;
	}
	return currentEid;
}
	
// Get the current value of the specified element on the page
function getElementValue(elementId) {
	var elem = dojo.byId(elementId);
	var value;
	if(elem) {
		value = elem.value;
	}
	
	return value;
}

// Set the current value of the specified element on the page
function setElementValue(elementId, value) {
	var elem = dojo.byId(elementId);
	if(elem) {
		elem.value = value;
	}
}

// Return the specified named anchor beneath the specified element, if it exists
function findNamedAnchor(anchorName, beneathElementId) {

	var namedAnchor;

	// Find the element (e.g. div) to look beneath
	var beneath = dojo.byId(beneathElementId);
	if(beneath) {

		// Find all anchor tags beneath this area:
		var aTags = beneath.getElementsByTagName('a');
		
		// For each anchor:
		for(var no=0;!namedAnchor && no<aTags.length;no++) {
			var name = aTags[no].getAttribute('name');		 
			if(!name) name = aTags[no].name;
			
			// Is this the one?
			if(name == anchorName) {
				namedAnchor = aTags[no];
			}		
		}
	}
	
	return namedAnchor;
}

function parseTagValue(xmlText, tagName, idAttribute, idValue) {
	var value;
	if(xmlText) {		
		var startTag = '<' + tagName;		
		var start = xmlText.indexOf(startTag);
		if(start != -1) {
			// There could be attributes:
			var endOfStartTag = xmlText.indexOf('>', start);
			var endTag = '</' + tagName + '>';		
			var end = xmlText.indexOf(endTag);
			if(end != -1) {
				value = xmlText.substring(endOfStartTag + 1, end);
			}
		}	
	}
	
	return value;		
};

function parseAttributeValue(xmlText, tagName, attribute, idAttribute, idValue) {
	var value;
	if(xmlText) {
		var tag = '<' + tagName;				
		var start = xmlText.indexOf(tag);
		while(start != -1 && !value) {
			var endOfTag = xmlText.indexOf('>', start);
			var attributes = xmlText.substring(start + tag.length + 1, endOfTag);
			if(idAttribute) {
				var idAttributeVal = getAttribute(attributes, idAttribute);
				if(idAttributeVal == idValue) {
					value = getAttribute(attributes, attribute);
				}
			}	
			else {
				value = getAttribute(attributes, attribute);			
			}	
					
			start = xmlText.indexOf(tag, endOfTag);			
		}
	}
		
	return value;				
};	

function getAttribute(tagText, attribute) {
	var value;
	var re = new RegExp(attribute + "\s*\=\s*[\'\"]([^\'\"]*)[\'\"]");
	var m = re.exec(tagText);
	if (m) {
		value = m[1];
	}
	
	return value;
};	

// Set a param value into the given url's query string parameters
// Note:  This currently assumes a plain url without the hash on the end.
function setQueryParam(url, paramName, paramValue, appendIfNotThere) {
	var result = url;
	var startPos = url.indexOf(paramName+"=");
	if(startPos > 0) {	
		var firstPart = url.substring(0, startPos+paramName.length+1);
		var endPart = "";		
		var endPos = url.indexOf("&", startPos);
		if(endPos > 0) {
			endPart = url.substring(endPos, url.length);
		}
		result = firstPart + paramValue + endPart;		
	}
	else {
		if(appendIfNotThere && appendIfNotThere == true) {
			result = url + "&" + paramName + "=" + paramValue;		
		}
	}
	
	return result;
}	

// Remove the specified param value from the given url.
function removeQueryParam(url, paramName) {
	var result = url;
	var startPos = url.indexOf(paramName+"=");
	if(startPos >= 0) {	
		var firstPart = url.substring(0, startPos);
		var endPart = "";		
		var endPos = url.indexOf("&", startPos);
		if(endPos >= 0) {
			endPart = url.substring(endPos+1, url.length);
		}
		else {
			endPart = url.indexOf("#", startPos);
			if(endPos >= 0) {
				endPart = url.substring(endPos, url.length);
			}			
		}
		result = firstPart + endPart;		
	}
	
	return result;
}	

// Get a param value from the given url's query string parameters, where
// the url can optionally include the hash (#) info on the end.
function getQueryParam(url, paramName, defaultValue) {
	var paramVal;
	if(url) {
		// Be careful if there's a hash in the url it will throw us off
		var urlParts = url.split("#");
		if(urlParts.length > 1) {
			url = urlParts[0]; 
		}
		
		paramVal = getParam(url, paramName, defaultValue);
	}
	
	return paramVal;
}

// Get a param value from the given string's parameters
// Note:  This is designed to work whether str is an actual url, or the YUI history hash
//        (which also has query-string like "parameters")
function getParam(str, paramName, defaultValue) {
	var paramVal;
	if(str) {		
		var startPos = str.indexOf(paramName+"=");
		if(startPos > 0) {				
			var endPos = str.indexOf("&", startPos);
			if(endPos > 0) {			
				paramVal = str.substring(startPos+paramName.length+1, endPos);
			}
			else {
				paramVal = str.substring(startPos+paramName.length+1, str.length);				
			}
		}
	
		if(!paramVal && defaultValue) {
			paramVal = defaultValue;
		}
	}
	
	return paramVal;
}

// Bookmark the current book player state (i.e. what section is displayed, what 
// tab is forward, etc.), in a form that will make it to the server and be preserved
// through the eRights redirects when they're not logged in.  Normally we lose the
// hash information in this scenario, so here we bookmark not the actual browser
// address line but the equivalent with the hash info converted to query params. 

function bookmarkCurrentBookPlayerState() {								
	if(dojo.render.html.ie && window.external) { 
		// IE is the only browser that currently provides a workable
		// way to add a favorite via javascript:		
		var serverFriendlyUrl = toServerFriendlyUrl(window.location.href);		
		window.external.AddFavorite(serverFriendlyUrl, document.title); 
	} else {	
		var rightClickMenu = "right click";  // How do you display the right click menu on this browser?
		var addBookMark = "\"Bookmark This Link...\"";     // How do you add a book mark from the right click menu?
		if(dojo.render.html.safari) { 				
			rightClickMenu = "control click";
			addBookMark = "\"Add Link to Bookmarks...\"";
		} else if(dojo.render.html.opera) {
			addBookMark = "\"Bookmark link...\"";
		}

		var instructions = "To bookmark this page, " + rightClickMenu + " over the blue plus sign, and choose " + addBookMark;		
		alert(instructions);		
		return false;	
	}
}

// Convert the specified ajax history url to a server friendly url, meaning 
// that the Yahoo History Manager "state" info after the hash gets baked 
// into query params of the url proper, since browsers do not send the hash 
// to the server:
function toServerFriendlyUrl(ajaxHistoryUrl, retainHash) {
	
	if(typeof(isLinkToBookMarkURL) != 'undefined' && isLinkToBookMarkURL){
		if(ajaxHistoryUrl.indexOf("book.d") != -1) {
			var linkToBookMarkUrl;
			var urlParts = ajaxHistoryUrl.split("#");		
			var historyHash = urlParts[1];
			var domain = getUrlDomain(ajaxHistoryUrl);	
			var eid = getQueryParam(ajaxHistoryUrl, 'eid');
			var figureEid = getQueryParam(ajaxHistoryUrl, 'figureEid');
			var displayedEid = getQueryParam(ajaxHistoryUrl, 'displayedEid');
			var isbn = getQueryParam(ajaxHistoryUrl, 'isbn');
			var type = getQueryParam(ajaxHistoryUrl, 'type');
			var from = getQueryParam(ajaxHistoryUrl, 'from');
			var lpState = getQueryParam(ajaxHistoryUrl, 'lpState');
			var lpTab = getQueryParam(ajaxHistoryUrl, 'lpTab')			
			linkToBookMarkUrl = 'http://'+domain+contextPath+'/'+urlType+'/linkTo?';
			if(isbn) {
				linkToBookMarkUrl = linkToBookMarkUrl + 'isbn='+isbn;
			}
			if(eid) {
				linkToBookMarkUrl = linkToBookMarkUrl + '&eid='+eid;
			}			
			if(from) {
				linkToBookMarkUrl = linkToBookMarkUrl + '&from='+from;
			}
			if(lpState) {
				linkToBookMarkUrl = linkToBookMarkUrl + '&lpState='+lpState;
			}
			if(lpTab) {
				linkToBookMarkUrl = linkToBookMarkUrl + '&lpTab='+lpTab;
			}			
			if(figureEid) {
				linkToBookMarkUrl = linkToBookMarkUrl + '&figureEid='+figureEid;
			}
			if(displayedEid) {
				linkToBookMarkUrl = linkToBookMarkUrl + '&displayedEid='+displayedEid;
			}
			if(type) {
				if(type == "about") {				
					linkToBookMarkUrl = linkToBookMarkUrl+"&type=BookHome";
				} else {
					linkToBookMarkUrl = linkToBookMarkUrl + '&type='+type;
				}
			}
			if(urlParts.length < 2 || urlParts[1] == "") {							
				// There was no yahoo history hash:		
				return linkToBookMarkUrl;	
			}			
			ajaxHistoryUrl = linkToBookMarkUrl+'#'+historyHash;
		}
	}
	var urlParts = ajaxHistoryUrl.split("#");
	if(urlParts.length < 2 || urlParts[1] == "") {
		// There was no yahoo history hash:
		return ajaxHistoryUrl;	
	}

	var urlPart = urlParts[0];
	var historyHash = urlParts[1];
		
	var hashParams = historyHash.split("&");
		
	for(var hpNum = 0; hpNum < hashParams.length; hpNum++) {
		var hashParamNVP = hashParams[hpNum].split("=");
		if(hashParamNVP && hashParamNVP.length >= 2) {
			var hpName = hashParamNVP[0];
			var hpValue = hashParamNVP[1];
			if(hpValue) {
				hpValue = unescape(hpValue);
			}
	
			// The mapping from the history hash params to the 
			// query params is not direct:
			if(hpName == "content") {
				// "content" in the hash params becomes "eid" in the query params:
				var contentParts = hpValue.split(";");
				var contentAreaEid = contentParts[0];
				var hitTerms;
				var type;
				var from;
				var sectionEid;				
				for(var statePartNum = 1; statePartNum < contentParts.length; statePartNum++) {
					var statePartNVP = contentParts[statePartNum].split("=");
					if(statePartNVP.length > 1) {
						if(statePartNVP[0] == "hitTerms") {
							hitTerms = statePartNVP[1];
						}		
						if(statePartNVP[0] == "type") {
							type = statePartNVP[1];
						}															
						if(statePartNVP[0] == "from") {
							from = statePartNVP[1];
						}	
						if(statePartNVP[0] == "sectionEid") {
							sectionEid = statePartNVP[1];
						}												
					}
				}

				// Replace/append the query param equivalent of the hash param:				
				if(contentAreaEid) {
					urlPart = setQueryParam(urlPart, "eid", contentAreaEid, true);
				}	
				if(type) {
					if(type == "figureFromContent") {
						// having a problem right now bookmarking this type -
						// temporarily just making it book mark where the thumbnail is:
						urlPart = setQueryParam(urlPart, "bookPage", type, true);					
					}
					else {
						urlPart = setQueryParam(urlPart, "type", type, true);
					}				
					if(sectionEid  && type == "figurePage" || type == "figureFromContent") {												
						urlPart = setQueryParam(urlPart, "eid", sectionEid, true);	
						urlPart = setQueryParam(urlPart, "figureEid", contentAreaEid, true);	
					}						
				}							
				if(hitTerms) {
					urlPart = setQueryParam(urlPart, "hitTerms", hitTerms, true);													
				}				
				if(from) {
					urlPart = setQueryParam(urlPart, "from", from, true);	
				}											
			}	
			else if(hpName == "search") {
				// The default search is simply the search query, but it can
				// optionally have semicolon delimited "parts" for type and page num.
				var searchStateParts = hpValue.split(";");
				var searchQuery = searchStateParts[0];	
				var searchPage = "1";
				var searchType = "new";	
				if(searchStateParts.length > 1) {
					// For each semi colon delimited part of the "state":
					for(var part=1;part<searchStateParts.length;part++) {		
						var partNvp = searchStateParts[part].split("=");
						if(partNvp.length > 1) {
							if(partNvp[0] == "type") {
								searchType = partNvp[1];				
							}			
							if(partNvp[0] == "pg") {
								searchPage = partNvp[1];				
							}
						}
					}
				}
			
				// Replace/append the query param equivalent of the hash params:
				if(searchQuery != "none") {
					urlPart = setQueryParam(urlPart, "searchQuery", searchQuery, true);	
					urlPart = setQueryParam(urlPart, "searchType", searchType, true);								
					urlPart = setQueryParam(urlPart, "searchPg", searchPage, true);					
				}							
			}
			else {
				// Replace/append the query param equivalent of the hash param:
				urlPart = setQueryParam(urlPart, hpName, hpValue, true);
			}			
		}
	}	
	
	// It causes confusion if the "destMessage" parameter get's included:		
	urlPart = removeQueryParam(urlPart, "destMessage");
	
	var serverFriendlyUrl = urlPart;
	
	if(historyHash && retainHash && retainHash == true) {

		// If we've got an eid in the hash we need to replace it in the query string.	
		serverFriendlyUrl += ("#" + historyHash);
	}
		
	return serverFriendlyUrl;
} 

// "Remember" the current state of the book player, by storing the
// current browser address in a cookie, and storing the bookmarkable
// server-friendly version of the current url as the href of our "add
// bookmark" button.
function rememberCurrentBookPlayerUrl() {
	
	// Update the cookie which remembers the last book section they've read:
	// Note:  Path is intentionally broader than the default "current page path"
	var currentSectionCookie = new elsCookie("lastBookUrl",0,"/expertconsult");

	// Store the "server friendly" url on our "add bookmark" button...	
	var serverFriendlyUrl = toServerFriendlyUrl(window.location.href);	

	// Simply store the url for getting back to this section:
	currentSectionCookie.set(serverFriendlyUrl);
		
		
    // get ISBN for book as suffix for the cookie name:
	var bookIsbn = getQueryParam(serverFriendlyUrl, 'isbn');
	
	// Setup bookmark for Premium or Basic book navigation when navigating between versions:
    if (serverFriendlyUrl.indexOf('\/p\/') > 0)
    {
	   var premiumSectionCookie = new elsCookie("lastPremiumBookUrl"+bookIsbn,0,"/expertconsult");
	   premiumSectionCookie.set(serverFriendlyUrl);
    }
    else
    {
	   var basicSectionCookie = new elsCookie("lastBasicBookUrl"+bookIsbn,0,"/expertconsult");
	   basicSectionCookie.set(serverFriendlyUrl);
    }
    
	var bookContentPane = dojo.byId("bookContentPane");
	
	var figureEid = getQueryParam(serverFriendlyUrl, 'figureEid');
	
	if(bookContentPane && serverFriendlyUrl) {	
		bookContentPane.setAttribute("serverFriendlyUrl", serverFriendlyUrl);
		if(figureEid) {
			bookContentPane.setAttribute("figureEid", figureEid);
		}	
	}	
	
	if(updateContentTools) {
		updateContentTools(bookContentPane);	
	}
}

// Return the browser to the last book player url the user was viewing.
// Note:  This directly changes the browser address line - it's
//        designed to call directly as an onclick method for a 
//        button or link.
function restoreLastBookPlayerUrl() {
	// Read the cookie which stores an indication of the last section they'd read:
	// Note:  Path is intentionally broader than the default "current page path"	
	var currentSectionCookie = new elsCookie("lastBookUrl",0,"/expertconsult");

	// Currently this literally holds that last book player url visited:
	var lastReadUrl = currentSectionCookie.get();

	if(lastReadUrl) 
	{
		window.location.href = lastReadUrl;
	}
	// Don't follow the link/button that uses this method onclick:
	return false;
}

// Return the browser to the last Basic book player url the user was viewing.
// Note:  This directly changes the browser address line - it's
//        designed to call directly as an onclick method for a 
//        button or link.
function restoreLastBasicBookPlayerUrl(newBasicBookUrl, basicIsbnSuffix) {
	// Read the cookie which stores an indication of the last section they'd read:
	// Note:  Path is intentionally broader than the default "current page path"	
	var lastBasicBookWithIsbnURL = "lastBasicBookUrl" +  basicIsbnSuffix;
	var currentSectionCookie = new elsCookie(lastBasicBookWithIsbnURL,0,"/expertconsult");

	// Currently this literally holds that last book player url visited:
	var lastReadUrl = currentSectionCookie.get();

	if(lastReadUrl) {
		window.location.href = lastReadUrl;
	}
	else
	{
		window.location.href = newBasicBookUrl;
	}

	// Don't follow the link/button that uses this method onclick:
	return false;
}


// Return the browser to the last Premium book player url the user was viewing.
// Note:  This directly changes the browser address line - it's
//        designed to call directly as an onclick method for a 
//        button or link.
function restoreLastPremiumBookPlayerUrl(premiumIsbnSuffix) {
	// Read the cookie which stores an indication of the last section they'd read:
	// Note:  Path is intentionally broader than the default "current page path"	
	var lastPremiumBookWithIsbnURL = "lastPremiumBookUrl" +  premiumIsbnSuffix;
	var currentSectionCookie = new elsCookie(lastPremiumBookWithIsbnURL,0,"/expertconsult");

	// Currently this literally holds that last book player url visited:
	var lastReadUrl = currentSectionCookie.get();

	if(lastReadUrl) {
		window.location.href = lastReadUrl;
	}

	// Don't follow the link/button that uses this method onclick:
	return false;
}


// Get the domain (and port if it's there) from the specified url
function getUrlDomain(url) {
	var domain;
	
	if(!url) {
		return domain;
	}
	
	domain = url;
	
	// if we start with http://
	if(url.indexOf("http://") == 0) {
		// Skip over it:
		domain = url.substring(7);
	}
	
	var endSlashPos =  domain.indexOf("/");
	if(endSlashPos != -1) {
		domain = domain.substring(0,endSlashPos);
	}
	
	return domain;
}

// Display the login page, and make sure A&E sends us back to 
// the *current* page if/when they successfully log back on.
//
// Note: Originally we attempted here to forcibly expire the
//       current A&E session by doing an Ajax call to  the
//       very same url we use for our logoff link.  But that
//       logoff action redirects the browser to the sso logoff
//       url on the SSO domain, which is a security violation 
//       for Ajax - and this was causing Safari to crash!
//       So - we've decided to simply let the original A&E
//       session timeout all on it's own.... 
//
function reloginUser() {
	if(((typeof(inactivityLogout) != 'undefined') && inactivityLogout == 'false')) {
		// They've explicitly indicated they don't want the user to be logged out!
		return;
	}
	
	if(inactivityLogoutUrl) {
		// alert("Logging out the user due to inactivity");					
		var destUrl = toServerFriendlyUrl(window.location.href);			
		var loginUrl = "http://" + getUrlDomain(window.location.href) +
						inactivityLogoutUrl + escape(destUrl);
		window.location.href = loginUrl;
	}	
}

// During the grace period, whether the user has activity or not, A&E will be
// prevented from timing out.  After the grace period A&E's timer will be allowed
// to timeout after the A&E standard timeout period (15 minute).

// So the total timeout is the grace period duration, plus the inactivity duration
// (15 minutes).

// Timer for the amount of "grace period" before the inactivity timer begins:
var inactivityGracePeriodTimer;

// Timer goes off after a period of inactivity in the book player.
var inactivityTimer;

// Initialize the grace period
function initInactivityGracePeriod() {
	// alert("initInactivityGracePeriod()");
	// For ACC User, Expertconsult application should maintain the everlasting session.
	if(((typeof(inactivityLogout) != 'undefined') && inactivityLogout != 'true')) {
		// They want to keep the A&E session alive forever
		keepAlive();
		
		// And keep alive will keep pinging the server forever
		// (since we won't start the grace period or inactivity timers)
		return;
	}
	else {
		// Start the grace period followed by inactivity timer combination
		startInactivityGracePeriod();
	}
}

// Reset the inactivity timers as needed
function resetInactivityPeriod() {
	// alert("resetInactivityPeriod()");
	// The inactivity period is optional:
	//   a.  An ACC User does the "keep alive" forever.
	//   b.  MDC completely disables auto-logout due to inactivity.
	if((typeof(inactivityLogout) == 'undefined') || inactivityLogout != 'true' ||
		inactivityLogoutMinutes <= 0) {
			// Don't do anything:
			return true;
	}

	// Were we in the grace period?
	if(inactivityGracePeriodTimer) {
		// alert("clearTimeout(inactivityGracePeriodTimer)");	
		clearTimeout(inactivityGracePeriodTimer);
		inactivityGracePeriodTimer = undefined;
	}

	// Clear the inactivity timer if it was going:
	if(inactivityTimer) {
		// alert("clearTimeout(inactivityTimer);");
		clearTimeout(inactivityTimer);
		inactivityTimer = undefined;
	}

	// Start the grace period from the beginning:
	startInactivityGracePeriod();		
}

// Start the grace period (this will simply start the inactivity period if there is no grace period):
function startInactivityGracePeriod() {
	// alert("startInactivityGracePeriod()");
	// The grace period is optional:
	if((typeof(inactivityGracePeriodMinutes) == 'undefined') || inactivityGracePeriodMinutes <= 0) {
		// If no grace go straight into inactivity time period:
		startInactivityTimer();
	}
	else {	
		if(inactivityGracePeriodTimer) {
			// alert("skipping start of inactivityGracePeriodTimer because there already is one!");	
			return;
		}
			
		// Until the Grace period ends, keep their session alive no matter what.
		// alert("keepAlive(inactivityGracePeriodMinutes)");		
		keepAlive(inactivityGracePeriodMinutes);
		
		// And after the grace period we will start the normal inactivity timeout period:	
		// alert("starting inactivityGracePeriodTimer");			
		var millisecondsGrace = inactivityGracePeriodMinutes * 60 * 1000; 
		inactivityGracePeriodTimer = window.setTimeout(endTheInactivityGracePeriod, millisecondsGrace);	
	}
}

// There's been inactivityGracePeriodMinutes of inactivity:
function endTheInactivityGracePeriod() {
	// alert("endTheInactivityGracePeriod()");
	
	// Clearing the timer
	inactivityGracePeriodTimer = undefined;
		
	// And start the inactivity timeout which we keep that
	// should timeout slightly *before* A&E (because if we 
	// let A&E timeout Ajax calls fail!):
	startInactivityTimer();
}

// Start the inactivity period timer:
function startInactivityTimer() {
	// alert("startInactivityTimer()");

	// Don't start more than one!
	if(inactivityTimer) {
		// alert("Skipping startInactivityTimer because one is already defined!");
		return;
	}

	// We allow at most 14 minutes of inactivity before sending
	// them to the login page.  Make sure this time is less than 
	// the A&E session timeout (currently 15 minutes), because our
	// ajax calls get indeterminate errors if A&E tries to redirect 
	// them (since A&E redirects them to the SSO server, ajax throws 
	// a security exception - but it's different between browsers).
	if((typeof(inactivityLogoutMinutes) != 'undefined') && inactivityLogoutMinutes > 0) {	
	
		var maxInactivity = inactivityLogoutMinutes * 60 * 1000; 
		
		// And start a new timer
		inactivityTimer = window.setTimeout(reloginUser, maxInactivity);
	}
}

// The user has performed some activity which hit the
// server and extended their A&E session
function userActivity() {

	// alert("userActivity()");

	// Restart the timers from the beginning of the grace period
	resetInactivityPeriod();
	
	// We return true only because this method is being used as a
	// "toggleOpenOrClosed" callback for elsAjaxTree.
	return true;	
}
