// Next time, please don't leave this broken for everyone, ok?
// Hint: See Apache directive AccessFileName
//<?
//require_once("../servercom/__server_setup.php");
//?>
//MPW - FIX ME this needs to come from ../servercom/__server_setup.php MPW
var SERVER = "PRD";
var ebooksBaseURL = "";

if (SERVER == "DEV")
  {
    ebooksBaseURL = "dev-ebooks.bfwpub.com";
  }
else if (SERVER == "STG")
  {
    ebooksBaseURL = "stg-ebooks.bfwpub.com";
  }
else if (SERVER == "PRD")
  {
   ebooksBaseURL = "ebooks.bfwpub.com";
  }

// ******************************************
// Navigation functions
// ******************************************

// Constants for some special sections
var TITLE_PAGE = 1;
var MAIN_TOC = 2;

// Called once: by the onload event handler of text.php
var firstPageLoaded = false;
function LoadMainTextWindow() {
	// PW: On 11/18/2008, I replaced all calls to ShowPopInWindow() with ShowPopInWindow_ebook()
	// to eliminate a conflict in v3 Portal with the ShowPopInWindow function used by other parts of the portal.
	// But just in case some ebook pages are calling ShowPopInWindow directly, if ShowPopInWindow isn't defined,
	// assign ShowPopInWindow to ShowPopInWindow_ebook 
	// (and same thing for ClosePopInWindow/ClosePopInWindow_ebook
	if (window.ShowPopInWindow == null) {
		window.ShowPopInWindow = ShowPopInWindow_ebook;
		window.ClosePopInWindow = ClosePopInWindow_ebook;
	}

	// If we're in a comment eBook, do some special initialization there
	if (commentStyle == 1) {
		InitializeCommentEBook();

		// comment-style books don't actually have title pages, so use the main_toc
		// KC: except for tap4e, which is "quasi-Comment-style"?
		if ((bookId != 'tap4v1')&&(bookId != 'tap4v2')&&(bookId != 'hunt3v1')&&(bookId != 'hunt3v2')&&(bookId != 'tapdocs4e')) {
			TITLE_PAGE = 2;
		}
	}
	
	// Add custom sections to the left TOC
	AddRegisteredCSsToTOC(chaptercontentsF);

	// Add supplement links to the left TOC
        AddAllSuppsToTOC(chaptercontentsF);

	// Write the bookmark menu
	WriteBookmarkMenu();
	
	// Load the glossary and any other supplemental info (used to be "glossary/textglossaryframe.html")
	glossaryF.location.replace(urlStartBookID + "dataframe.html");
	
	// Load the username frame
	usernameF.location.reload();
	
	// Set the following so we know that a page has been loaded.
	firstPageLoaded = true;
	
	// Check the user's browser
	BrowserDetect();
	
	// Check the user's expiration date
	Check_Expiration();
	
	// If the startPage variable was set by text.php, we now immediately
	// jump to a different page.  Also jump to the specified hash, if there is one.
	if (startPage != "") {
		JumpToPageNumber(startPage, startHash);
		startPage = "";		// Probably not necessary, but just to be safe.
		return;
	}

	// Initialize the first page.  This function is also called by the onload
	// event handler of each section, but that call will be rejected for the very
	// first loaded page.
	InitializeSection();

	// Do some more initialization of the title page if we're there
	// Note the exception for speakersguide3e, which has no title page
	// Instead BSM wants these links on main TOC
	if (curSection == TITLE_PAGE || (curSection == MAIN_TOC && bookId == 'speakersguide3e')) {	
		if (lastSection == "" || lastSection == "../0_0.html?1") {
			SetVisibility(main.document.getElementById('startDiv'), "visible");
	
		// Else show the "Return to last-visited" link
		} else {
			SetVisibility(main.document.getElementById('returnDiv'), "visible");
		}
	}
}

// Called once: when the main text window is closed
function UnloadMainTextWindow() {
	// Close the supplemental window, since it won't work with this window closed, anyway
	CloseSuppWindow();
	
	// Close the help window
	if (hw != null && !hw.closed) {
		hw.close();
	}
	
	// Close any open note windows
/*	for (var key in nw) {
		if (nw[key] != null && !nw[key].closed) {
			nw[key].close();
		}	
	}
*/
}

// ca fns in ebookCA.js

// KC: returns chapter number given section id number
// this is necessary due to the St. Martin's Guide's 200+ section in Chapter 29
function GetChapterFromSID(n) {

	if (bookId == 'theguide8e' && n >= 2900) {
		return 29;
	} else {
		return Math.floor(n / 100);
	}
	
}

// Given a section id (sections[] index), return whether the section is:
//		-3: In a chapter that doesn't exist
//		-2: In an uncompleted chapter
//		-1: In a completed chapter that isn't available in the user's version
//		 0: In an available chapter, but the section doesn't exist
//		 1: Available for the user's use
function SectionAvailable(sid) {

	if (IsCustomSection(sid)) {
		if (sections[sid] != null) {
			return 1;
		} else {
			return -3;	// OR MAYBE RETURN SOMETHING SPECIAL?
		}
	}

	var c = GetChapterFromSID(sid);
	
	// Chapter doesn't exist
	if (c < 0 || c > chaptersInStandardVersion) {	// Set in text.php
		return -3;
	
	// Chapter hasn't been completed yet
	} else if (c > 0 && completedChapters[c] != true) {
		return -2;
	
	// Chapter is complete but not available
	} else if (c > 0 && !ca(c)) {
		return -1;
	
	// Chapter is available...
	} else {
		// ...But section doesn't exit
		if (sections[sid] == null) {
			return 0;
		
		// ... or everythings hunkey-dorey
		} else {
			return 1;
		}
	}
}

function SectionNotAvailableAlert(id) {
	switch(id) {
		case -3: return "This chapter does not exist in this book.";
		case -2: return "This chapter has not yet been put online.";
		case -1: 
			if (username == "guest") {
				return "This chapter is not available for Preview users. " + guestChaptersAvailable;
			} else {
				return "This chapter is not available in your version of the ebook.";
			}
		case 0: return "This section does not exist.";
	}
}

// Load a new section into the main frame
var curSection = null;
function LoadSection(newSection, hash) {
	// Load the specified page

	// Angel version
	if (angelStyle == 1) {
		// have to deal with hash later
		
		// start constructing the url
		// we use the angel "processPageRequest" script to make sure we really go to
		// the next thing in angel (which might not be the next eBook section in our sequence)
		var url = angelServer + '/processPageRequest.asp?page_id=' + bookId + "_";
		
		if (newSection == "prev") {
			// If BFW_PreviousPage is defined in the section title frame, run it
			if (main.parent.frames != null && main.parent.frames[0].BFW_PreviousPage != null) {
				main.parent.frames[0].BFW_PreviousPage();
				return;
			// else if we have a SendMainTo function, use it (this is G3)
			} else if (top.SendMainTo != null) {
				top.SendMainTo('previous');
				return;
			}
			url += sections[curSection].fn + '&toDo=Previous';
		} else if (newSection == "next") {
			// If BFW_NextPage is defined in the section title frame, run it
			if (main.parent.frames != null && main.parent.frames[0].BFW_NextPage != null) {
				main.parent.frames[0].BFW_NextPage();
				return;
			// else if we have a SendMainTo function, use it (this is G3)
			} else if (top.SendMainTo != null) {
				top.SendMainTo('next');
				return;
			}
			url += sections[curSection].fn + '&toDo=Next';
		} else if (newSection == "reload") {
			// If BFW_ReloadPage is defined in the section title frame, run it
			if (main.parent.frames != null && main.parent.frames[0].BFW_ReloadPage != null) {
				main.parent.frames[0].BFW_ReloadPage();
				return;
			}
			url += sections[curSection].fn;
		} else {
			// Check to make sure the newSection exists; if not, throw an error
			var sa = SectionAvailable(newSection);
			if (sa != 1) {
				alert(SectionNotAvailableAlert(sa));
				return;
			}

			url += sections[newSection].fn;
		}
		
		// We don't have to call PrepareForNewSection(newSection) here
		// because we've set to do it onunload for angel.

		// use angel function to jump to that page
		contentFrame.location = url;

	// Standalone version		
	} else {
		// Deal with "prev" and "next"
		if (newSection == "prev") {
			if (curSection == 1) {
				alert("No previous section to go to.");
				return;
			} else {
				newSection = GetPreviousSection();
				
				// We shouldn't ever get to here, but just in case...
				if (newSection == 0) {
					alert("No previous section to go to.");
					return;
				}
			}
		} else if (newSection == "next") {
			newSection = GetNextSection();
	
			// Special case for henretta6e
			if(bookId == "henretta6e"){
				if(newSection == 0 && curSection == 3901){
					// go from part 7 opener to chapter 30
					newSection = 3001;
				} else if (newSection == 3301 && curSection == 3220){
					// go from end of chapter 32 to NOWHERE!
					newSection = 0;
				}
			}

			// We shouldn't ever get to here, but just in case...
			if (newSection == 0) {
				alert("No next section to go to.");
				return;
			}
		} else if (newSection == "reload") {
			newSection = curSection;
		}

		// Check to make sure the newSection exists; if not, throw an error
		var sa = SectionAvailable(newSection);
		if (sa != 1) {
			alert(SectionNotAvailableAlert(sa));
			return;
		}
	
		// Construct the new filename, including the new value for curSection.
		// We have to set curSection AFTER the page loads, because otherwise if the user
		// presses their browser's back button, curSection will not be set properly.
		var url = urlStartBookID + "sections/" + SectionURL(newSection, hash);
		
		// Get ready for the new section
		PrepareForNewSection(newSection);

		// Exception for development of wiki ebooks
		// KC 1/12/2009: this is now value set in bookAccount table of eBooks database
		if (wikiUser != null) {
		       if (wikiUser == 1) {
				// should we pass wikiSetId in as well?
                                var wikiSetId;
                                if (wikiSets != null && wikiSets[0] != null && wikiSets[0].setId != null) {
                                        wikiSetId = wikiSets[0].setId;
                                }
				//url = url.replace(/(http:\/\/)/, "$1ebooks.bfwpub.com/ebook_wiki/wiki_proxy.php?wikiuserId=" + wikiuserId + "&page=");
				//Dev hack use one above for prod.
				// Probably don't need wiki functionality for custom sections, main TOC
				if (url.indexOf("customsection") < 0 
				 //&& url.indexOf("0_1") < 0
								) {
					if (wikiSetId != null) {
						url = url.replace(/(http:\/\/)/, "http://" + ebooksBaseURL + "/ebook_wiki/wiki_proxy.php?accountType=" + accountType + "&wikiuserId=" + wikiuserId + "&wikiSetId=" + wikiSetId + "&page=");
					} else {
						url = url.replace(/(http:\/\/)/, "http://" + ebooksBaseURL + "/ebook_wiki/wiki_proxy.php?accountType=" + accountType + "&wikiuserId=" + wikiuserId + "&page=");
					}
					url = url.replace(/\?(\d+)$/, "\&$1");
				}
				// this won't work if we're trying to go to a custom section; the resulting URL is
				// http://ebooks.bfwpub.com/ebook_wiki/wiki_proxy.php?wikiuserId=84717&page=ebooks.bfwpub.com/physse6e/sections/../../notes/customsection.php&102787
				// which resolves to
				// http://ebooks.bfwpub.com/ebook_wiki/wiki_proxy.php?wikiuserId=84717&page=ebooks.bfwpub.com/notes/customsection.php&102787

				// if the user is going to the ebook via www.ebooks.bfwpub.com rather than ebooks.bfwpub.com, the above won't work, in IE at least.  
				// we need to know the referrer to fix this
				//alert(urlStartBookID);
				if (urlStartBookID.indexOf("www.ebooks") != -1) {
					url = url.replace(/ebooks/, "www.ebooks");
				}
				//alert(url);
		      }
		}
		
		main.location = url;
		// KC: bring main frame into focus in case we're loading from a supp window
		main.focus();
	}
}

function PrepareForNewSection(newSection) {	
	// Unless we're reloading, de-highlight the current section in the left-side TOC
	if (newSection != curSection) {
		ClearLeftHighlight();
	}

	// Record any changes in highlighting, if necessary; they'll get saved when the
	// next page is loaded.
	RecordHighlighting();

	// Initialize the CS (chapter summary) stuff.  We have to do this here (before the page
	// starts loading) because as the summary questions are drawn they need access to the
	// variables set in InitializeCS().
	InitializeCS();
	
	// If the note editor was open, close it
	if (noteBeingEdited != null) {
		EditNoteStop(false);
	}
}


// PW 10/1/08: return the filename (minus extension -- e.g. "3_1" associated with the section with number s
function SectionFilename(s) {
	if (sections[s] != null && sections[s].fn != null) {
        	return sections[s].fn;
	}
}

function CurrentSectionFilename() {
        return SectionFilename(curSection);
}

function SectionNumberFromFilename(fn) {
        for (var i = 0; i < sections.length; ++i) {
                if (sections[i] != null && sections[i].fn == fn) {
                        return i;
                }
        }

        return null;
}


function SectionURL(s, hash) {
	if (IsCustomSection(s)) {
		return "../../notes/customsection.php?" + s;
	} else {
		// By default, extension is assumed to be "html"
		var ext = "html";
		// if we have an ext defined, use it
		if (sections[s].ext != null) {
			ext = sections[s].ext;
		// else if this is the main toc, use "php"
		// Note for bedhand7e, main toc is still htm
		} else if (s == MAIN_TOC) {
			ext = "php";
		}
		var fn = sections[s].fn + "." + ext;

		fn += "?" + s;
		
		// If we got a hash value, add it to the url
		if (hash != null && hash != "") {
			fn += "#" + hash;
		}

		return fn;
	}
}

/*
- Multiple custom sections are added to a section in this order:
	 - before 2
	 - before 3
	 - before 6
	-- "real" section
	 - after 5
	 - after 4
	 - after 1
	 - after 0
*/

function GetPreviousSection() {
	var s;

	// If we're in a custom section...
	if (IsCustomSection()) {
		// Get the cs, its attachee, and the cs's index in attSec.cs
		var theCS = sections[curSection];
		var attSec = sections[theCS.attacheeSection];
		for (var attSecCSIndex = 0; attSecCSIndex < attSec.cs.length; ++attSecCSIndex) {
			if (attSec.cs[attSecCSIndex] == curSection) {
				break;
			}
		}
		
		// If the cs is before its attachee...
		if (theCS.relativeLocation == "before") {
			// If there is another BEFORE custom section BEFORE this one in the cs array, that's previous
			for (var i = attSecCSIndex - 1; i >= 0; --i) {
				if (sections[attSec.cs[i]].relativeLocation == "before") {
					return attSec.cs[i];
				}
			}
			// If we made it through the above loop, the previous section is 
			// the section previous to attSec, so drop through to the code below
			s = theCS.attacheeSection;
		
		// Else the cs is after its attachee...
		} else {
			// If there is another AFTER custom section AFTER this one in the cs array, that's previous
			for (var i = attSecCSIndex + 1; i < attSec.cs.length; ++i) {
				if (sections[attSec.cs[i]].relativeLocation == "after") {
					return attSec.cs[i];
				}
			}
			// If we made it through the above loop, the next section is the attSec
			return theCS.attacheeSection;
		}
	// Else this isn't a custom section, so...
	} else {
		s = curSection;

		//alert("s = " + s);

		// If the section has custom sections attached, check those
		if (sections[s].cs != null) {
			// Previous section would be the last BEFORE cs in the array
			for (var i = sections[s].cs.length - 1; i >= 0; --i) {
				if (sections[sections[s].cs[i]].relativeLocation == "before") {
					return sections[s].cs[i];
				}
			}
			// If we make it through the above loop, there were no before sections,
			// so fall through to find the previous true section.
		}
	}
	
	// If we're at section 1 (title page), return 0, because there is no previous
	if (s == 1) {
		return 0;
	}
	
	// Get the chapter of the current section
	curChapter = GetChapterFromSID(s);
	
	// Find the previous section.
	// Multiply by one to assure number
	var newSection = s * 1 - 1;
	while (SectionAvailable(newSection) != 1 && newSection >= 0) {
		--newSection;
	}
	
	// If the value of newSection we just got is in the same chapter as s,
	// return newSection, because the previous page is still in the same chapter.
	var newChapter = GetChapterFromSID(newSection);
	if (newChapter == curChapter) {
		return GetPreviousSectionCheckCS(newSection);
	}
	
	// Otherwise we're moving to a new chapter, so we have to figure out which one.
	newChapter = 0;
	
	// Go through all the available chapters in order
	for (var i = 0; i < nca(); ++i) {
		// If we hit the curChapter, break
		if (co[i] == curChapter) {
			break;
		}
		// Otherwise store this chapter in newChapter
		newChapter = co[i];
	}
	// The value of newChapter when we exit the above loop should be the next
	// chapter we're going to.  If we were in the first chapter, we'll exit
	// with newChapter being 0, which is correct
	
	if (bookId == "henrettaconcise4e") {
            if (newChapter > 18 && curChapter == 16) {
                return GetPreviousSectionCheckCS(MAIN_TOC);
            }
        }
	if (bookId == "henrettaconcise4ev2") {
            if (newChapter > 32 && curChapter == 16) {
                return GetPreviousSectionCheckCS(3601);
            }
        }

	// KT: Special case for henretta6e (partOpeners)
	if(bookId == "henretta6e"){
		if(newChapter == 29 && curChapter == 30){
			return GetPreviousSectionCheckCS(3901);
		} else if(newChapter == 25 && curChapter == 26){
			return GetPreviousSectionCheckCS(3801);
		} else if(newChapter == 21 && curChapter == 22){
			return GetPreviousSectionCheckCS(3701);
		} else if(newChapter == 15 && curChapter == 16){
			return GetPreviousSectionCheckCS(3601);
		} else if(newChapter == 8 && curChapter == 9){
			return GetPreviousSectionCheckCS(3501);
		} else if(newChapter == 4 && curChapter == 5){
			return GetPreviousSectionCheckCS(3401);
		} else if(newChapter == 0 && curChapter == 1){
			return GetPreviousSectionCheckCS(3301);
		}

		// Also handle previous section from part openers
		if(newChapter == 32 && curChapter == 33){
			// Now we really are going back to main TOC
			return GetPreviousSectionCheckCS(MAIN_TOC);
		} else if(newChapter == 33 && curChapter == 34){
			newChapter = 4;
		} else if(newChapter == 34 && curChapter == 35){
			newChapter = 8;
		} else if(newChapter == 35 && curChapter == 36){
			newChapter = 15;
		} else if(newChapter == 36 && curChapter == 37){
			newChapter = 21;
		} else if(newChapter == 37 && curChapter == 38){
			newChapter = 25;
		} else if(newChapter == 38 && curChapter == 39){
			newChapter = 29;
		}
	}
	
	// if newChapter somehow ended up with null (shouldn't ever happen) return 0
	if (newChapter == null) {
		alert("Problem moving to previous page: 994");
		return 0;
	}
	
	// if newChapter ended up with 0, we must be moving back to the TOC from
	// the first available chapter, so return MAIN_TOC
//	if (newChapter == 0) {
//		return GetPreviousSectionCheckCS(MAIN_TOC);
//	}
	
	// otherwise find the last available section of the newChapter
	// If we fail to find one below, return 0
	newSection = 0;
	for (var i = newChapter * 100 + chapterStartSectionOffset; 	// chapterStartSectionOffset is set in config.js
			i < (newChapter + 1) * 100; ++i) {
		if (SectionAvailable(i) == 1) {
			newSection = i;
		}
	}
	return GetPreviousSectionCheckCS(newSection);
	
	// Have to check for custom sections before returning
	function GetPreviousSectionCheckCS(s) {
		if (sections[s] == null) {
			return s;
		}

		// If the previous section has custom sections, we want to go to the first AFTER cs
		if (sections[s].cs != null) {
			for (var i = 0; i < sections[s].cs.length; ++i) {
				if (sections[sections[s].cs[i]].relativeLocation == "after") {
					return sections[s].cs[i];
				}
			}
		}
		// If we fall through to here for any reason, return s
		return s;
	}
}

function GetNextSection() {
	var s;

	// If we're in a custom section...
	if (IsCustomSection()) {
		// Get the cs, its attachee, and the cs's index in attSec.cs
		var theCS = sections[curSection];
		var attSec = sections[theCS.attacheeSection];
		for (var attSecCSIndex = 0; attSecCSIndex < attSec.cs.length; ++attSecCSIndex) {
			if (attSec.cs[attSecCSIndex] == curSection) {
				break;
			}
		}
		
		// If the cs is before its attachee...
		if (theCS.relativeLocation == "before") {
			// If there is another BEFORE custom section AFTER this one in the cs array, that's next
			for (var i = attSecCSIndex + 1; i < attSec.cs.length; ++i) {
				if (sections[attSec.cs[i]].relativeLocation == "before") {
					return attSec.cs[i];
				}
			}
			// If we made it through the above loop, the next section is the attSec
			return theCS.attacheeSection;
		
		// Else the cs is after its attachee...
		} else {
			// If there is another AFTER custom section BEFORE this one in the cs array, that's next
			for (var i = attSecCSIndex - 1; i >= 0; --i) {
				if (sections[attSec.cs[i]].relativeLocation == "after") {
					return attSec.cs[i];
				}
			}
			// If we made it through the above loop, the next section is 
			// the next section after attSec, so drop through to the code below
			s = theCS.attacheeSection;
		}
	// Else this isn't a custom section, so...
	} else {
	
		s = curSection;
		//alert("s = " + s);

		// If the section has custom sections attached, check those
		if (sections[s] != null && sections[s].cs != null) {
			// Next section would be the last AFTER cs in the array
			for (var i = sections[s].cs.length - 1; i >= 0; --i) {
				if (sections[sections[s].cs[i]].relativeLocation == "after") {
					return sections[s].cs[i];
				}
			}
			// If we make it through the above loop, there were no after sections,
			// so fall through to find the next true section.
		}			
	}

	// Get the chapter of the current section
	curChapter = GetChapterFromSID(s);
	//alert("curChapter = " + curChapter);
	
	// Find the next section.
	// We multiply by 1 so that we're sure this is a number
	var newSection = s * 1 + 1;
	//alert("section " + newSection + " available?  " + SectionAvailable(newSection));
	//alert("lastTrueSectionIndex = " + lastTrueSectionIndex);
	while (SectionAvailable(newSection) != 1 && newSection < lastTrueSectionIndex) {
		++newSection;
	}
	
	// If the value of newSection we just got is a) valid and
	// b) in the same chapter as s,
	// return newSection, because the next page is still in the same chapter.
	if (SectionAvailable(newSection) == 1 && GetChapterFromSID(newSection) == curChapter) {
		return GetNextSectionCheckCS(newSection);
	}
	
	// Otherwise we're moving to a new chapter, so we have to figure out which one.
	
	// Extra-special case: if we're in Henretta6e and at the TOC, we want to go to part 1 opener,
	// and not the first page of the first chapter
	if(bookId == "henretta6e" && curChapter == 0) {
		return GetNextSectionCheckCS(3301); // hard coded sectionIndex since we need to go there.
	}
	
	if (bookId == "henrettaconcise4e" && curChapter == 0) {
            return GetNextSectionCheckCS(1601);
        }
	if (bookId == "henrettaconcise4ev2" && curChapter == 36) {
	    return GetNextSectionCheckCS(1601);
	}

	// Special case: if we're at the TOC, we know we want to go to the first page
	// of the first available chapter.
	if (curChapter == 0) {
		return GetNextSectionCheckCS(co[0] * 100 + chapterStartSectionOffset);
	}
	
	// Go through all the available chapters in order, starting with co[1]
	// There's got to be at least one chapter in every version.
	for (var i = 1; i < nca(); ++i) {
		// If the previous co is curChapter, break
		if (co[i - 1] == curChapter) {
			break;
		}
	}
	
	// If we made it all the way through the above loop, 
	// there is no next chapter to go to, so return 0. (This should never happen)
	if (i == nca()) {
		return 0;
	}
	
	//KT: Special case for henretta6e
	// part openers in between chapters/TOC etc..
	if(bookId == "henretta6e"){
		// first handle next sections from part openers

		if(i == 33){
			return GetNextSectionCheckCS(101);
		} else if (i == 34){
			return GetNextSectionCheckCS(501);			
		} else if (i == 35){
			return GetNextSectionCheckCS(901);			
		} else if (i == 36){
			return GetNextSectionCheckCS(1601);			
		} else if (i == 37){
			return GetNextSectionCheckCS(2201);			
		} else if (i == 38){
			return GetNextSectionCheckCS(2601);			
		} else if (i == 39){
			return GetNextSectionCheckCS(3001);			
		}

		// KT: Then check for loading the next part opener
		// Note that a mysterious increment is sneaking in and increasing i by one
		// from these values, so they will be correct in the end.

		if(i == 0){
			i = 32;
		} else if (i == 4){
			i = 33;
		} else if (i == 8){
			i = 34;
		} else if (i == 15){
			i = 35;
		} else if (i == 21){
			i = 36;
		} else if (i == 25){
			i = 37;
		} else if (i == 29){
			i = 38;
		}

	}
	// Otherwise, the value of i when we exit the loop is 
	// the index in co of the next chapter.
	// This is true even if there is only one chapter in the book
	// So return the first section of this chapter
	return GetNextSectionCheckCS(co[i] * 100 + chapterStartSectionOffset);

	function GetNextSectionCheckCS(s) {
		if (sections[s] == null) {
			return s;
		}

		// If the next section has custom sections, we want to go to the first BEFORE cs
		if (sections[s].cs != null) {
			for (var i = 0; i < sections[s].cs.length; ++i) {
				if (sections[sections[s].cs[i]].relativeLocation == "before") {
					return sections[s].cs[i];
				}
			}
		}
		// If we fall through to here for any reason, return s
		return s;
	}
}

function ReturnToLastVisited() {
	// lastSection is set by text.php.
	// It is set to "filename?sectionNumber", so that text.php
	// can use it.  If we're using it from here, we just need the sectionNumber,
	// so pull it out
	LoadSection(lastSection.substr(lastSection.indexOf("?") + 1));
}

// Jump to a specified page number in the print book
function JumpToPageNumber(p, hash) {
	// Set a loadDefault variable to false.  If it gets set to true, we might
	// need to jump to a default page at the end of the function
	var loadDefault = false;
	
	// If p is null, it was specified by the user in the banner text box, so get it
	if (p == null) {
	    if (bookId == 'nohenrettaconcise4e' || bookId == 'henrettaconcise4ev2') {
                p = bannerleftF.document.jumpForm.page.value;
            }
            else {
                p = bannerrightF.document.jumpForm.page.value;
            }
	}

	// KC: if p is still null, or is "", chances are someone clicked on "Go to page"
	// without having entered a page number
	if (p == null || p == "") {
		if (bookId == 'rules6e') {
			alert("Please enter section number");
		} else {
			alert("Please enter page number or section number");
		}
		return;
	}
	
	// KC: if p > 99999, chances are it's an error
	if (p > 99999) {
		alert("You cannot enter more than 5 digits");
		return;
	}
	
	
	// If we're in a "comment-style" eBook, check a few things first...
	// KC: but we also need to make sure that goToPage (defined in config.js) is null; if it's 1, then this means that we are using normal "Go to Page" functionality
	// alert("goToPage" + goToPage + "; commentStyle" + commentStyle);
	if (commentStyle == 1 && goToPage == null) {
		// if p starts with "p" followed by some numbers, assume it's actually a page number
		
		// KC: unfortunately, some users in REF have tried typing "p1" to get to section P1,
		// which is then assumed to be a page number call
		
		// so we should make it capital
		if (p.charAt(0) == "p" && bookId == 'writersref6e') {
			p = p.replace(/p/,"P");
		}
		
		
		
		if (p.charAt(0) == "p" && p.substr(1) * 1 > 0) {
			// so get the page number and drop through to the rest of the function, where we'll load it.
			
			p = p.substr(1) * 1;
		
		// if p starts with "section" (e.g. "section4_0", assume it's actually a section number
		} else if (p.substr(0,7) == "section") {
			p = p.substr(7);

		// Otherwise look for the p string in the .jt fields of sections[]
		} else {
			// but make p lower case and take out dashes first
			var psearch = p.toLowerCase();
			psearch = psearch.replace(/-/g, "");
			// the Georgia Tech custom eBook has sections like 1.1a
			if (bookId != 'gatech07142008' && bookId != 'gatech') {
				psearch = psearch.replace(/\./g, "");
			}
	
			for (var i = 0; i < sections.length; ++i) {
				if (sections[i] != null && sections[i].jt != null && sections[i].jt.toLowerCase() == psearch) {
					LoadSection(i, hash);
					return;
				}
			}
			
			// If we didn't find it and it ends in a letter, try the search without the letter
			if (psearch.toLowerCase().charAt(psearch.length - 1) >= 'a' && psearch.toLowerCase().charAt(psearch.length - 1) <= 'z') {
				var pabb = psearch.substr(0, psearch.length - 1);
				for (var i = 0; i < sections.length; ++i) {
					if (sections[i] != null && sections[i].jt != null && sections[i].jt.toLowerCase() == pabb.toLowerCase()) {
						LoadSection(i, hash);
						return;
					}
				}
			}			
			
			// and if we make it through to here, report an error
					if (p == '') {
					alert("Please enter a section.");
				} else {
					alert("Section " + p + " does not exist.");
				}
			if (curSection == null) {
				LoadSection(TITLE_PAGE, hash);
			}
			return;
		}
	}
	
	// If p includes .'s or -'s or _'s, it's a section number, so...
	if (String(p).indexOf(".") != -1 || String(p).indexOf("-") != -1 || String(p).indexOf("_") != -1) {
		// Change .'s and -'s to _'s
		sec = p.replace(/[\.-]/g, "_");
		
		// Some books now (e.g. dtu8e) use "5_1_0" for 5.1; create an alt
		// to check for this.  Note this won't work with parts; but don't 
		// worry about that for now
		var sec_alt = sec + "_0";
		
		// Part 1's don't have the part numbers in the filenames, so take these out if necessary
		sec = sec.replace(/\/1/g, "");
		sec = sec.replace(/__1/g, "");
		
		// Change / or -- to -
		sec = sec.replace(/\//g, "-");
		sec = sec.replace(/__/g, "-");
		
		// Make sure the section exists
		var s;
		for (s = 0; s < lastTrueSectionIndex; ++s) {
			if (sections[s] != null && (sections[s].fn == sec || sections[s].fn == sec_alt)) {
				break;
			}
		}
		
		if (s != lastTrueSectionIndex) {
			// Load section will take care of deciding whether or not the user
			// has access to the section
			LoadSection(s, hash);
		
		// The specified section isn't in the sections[] array, so...
		} else {
			// Be smarter about this???
			alert("Section " + p + " does not exist.");
			loadDefault = true;
		}
		
	// Else it's a page number. Try to find the page directly in the pages array
	} else {
	
		// KC: Find last page number
		var lastPageNo = pages.length-1;

		// KC: e.g. "page 47" or "Page 47"
		if (isNaN(p)) {
			if ((p.substr(0,4) == "page" || p.substr(0,4) == "Page") && p.substr(5) * 1 > 0) {
				p = p.substr(5) * 1;
			}
		}
	
		if (pages[p] != null) {
			// Load section will take care of deciding whether or not the user
			// has access to the section
			LoadSection(pages[p], hash);

		// If we can't, search backwards until we find one or reach 0
		} else {
			for (var i = p; i > 0; --i) {
				if (pages[i] != null) {
					break;
				}
			}
			if (i > 0) {
				if (p > lastPageNo) {
					alert("Outside page range.  You will be sent to the last eBook page.");
				}
				LoadSection(pages[i], hash);
			} else {
				// Be smarter about this???
				
				alert("Page " + p + " is not available.");
				loadDefault = true;
			}
		}
	}

	// If curSection is null and loadDefault is true, the user probably clicked
	// on a link with a bad section or page number, so go to the title page
	if (curSection == null && loadDefault == true && angelStyle != 1) {
		LoadSection(TITLE_PAGE, hash);
	}
}

// WriteChapterMenu is defined in config.js

// Jump to a specified chapter
// KC: added frame argument to account for possibility that drop down is chaptercontents, not bannerrightF, which is the default

function JumpToChapter(c,frame) {
  var chlist;
  var chidx;
  var chname;
	// If c is null, it was specified by the user in the banner pull-down, so get it
	if (c == null) {
		if (frame == 'chaptercontentsF') {
			c = chaptercontentsF.document.chform.chapter.value;
		} else {
			c = bannerrightF.document.chform.chapter.value;
		}
	}
	
	if (c == 0) {
		if (curSection == MAIN_TOC) {
			alert("You're already at the Table of Contents.");
		} else {
			LoadSection(MAIN_TOC);
		}
	} else if (c == CurrentChapter()) {
		if (bookId == "krugmanwells_micro" || bookId == 'krugmanwells_econ') {
			if (c == 36) {
				c = '2A';
			} else if (c == 37) {
				c = '11A';
			} else if (c == 38) {
				c = '12A';
			}
		}
		
		if (frame == 'chaptercontentsF') {
			chlist = chaptercontentsF.document.chform.chapter;
		} else {
			chlist = bannerrightF.document.chform.chapter;
		}

    chname = chlist.options[chlist.selectedIndex].text;
    
		// need to deal with myers peculiarities
		if (bookId == "expmod") {
			if (c == 46) {
				alert("You're already in Appendix A");
			} else {
				alert("You're already in Module " + c + ".");
			}
		} else if (bookId == "exploring") {
			if (c == 16) {
				alert("You're already in Appendix A");
			} else if (c == 17) {
				alert("You're already in Appendix B");
			}
		} else {
		
			alert("You're already in " + chname + ".");
		}
	} else if (c != -1) {
		if (completedChapters[c]) {		// This array is created in sections.js
			// Jump to section c*100 + 1
			LoadSection(c * 100 + chapterStartSectionOffset);	// see defaults.js
		} else {
			if (bookId != 'tap4e' && bookId != 'tap4v1' && 
bookId != 'tap4v2') {
				alert("Chapter " + c + " is not yet available.");
                        }
                        if (username == "guest") {
                                if (bookId != 'tap4e' && bookId != 
'tap4v1' && bookId != 'tap4v2') {
                                        alert(guestChaptersAvailable);
                                } else {
                                        var tempGCA =
guestChaptersAvailable;
                                        // remove the period
                                        tempGCA = tempGCA.replace(/\./,"");
                                        alert(tempGCA + " for preview.");
                                }

                        }


		}
	}

	// Whatever we do, make sure the top option is selected when we're done.
	if (frame == 'chaptercontentsF') {
		chaptercontentsF.document.chform.chapter.options[0].selected = true;
	} else if (bannerrightF != null) {
		bannerrightF.document.chform.chapter.options[0].selected = true;
	}

}

// Parse the url search string into a PHP-like GET array
// id=value pairs get parsed to GET['id']=value
// single values get parsed to GET['un1']=value
// e.g. 'home.html?blah&foo=bar' will be parsed to:
//    GET['un0'] = 'blah'
//    GET['foo'] = 'bar'
var GET;
function ParseGet(win) {
	if (win == null) {
		win = this;
	}
	GET = new Object();
	
	var getA = win.location.search.substr(1).split('&');
	for (var i = 0; i < getA.length; ++i) {
		var getI = getA[i].split('=');
		if (getI.length == 2) {
			GET[getI[0]] = getI[1];
		} else {
			GET['un' + i] = getA[i];
		}
	}
}

// Do some things that should or need to be done BEFORE the page starts loading
var bannerTitle = "";	// Note: this variable could be used by other scripts as a short version of the section title
function PreInitializeSection(newBannerTitle, mainWin, thisPageBookId) {
	//alert("PreInitializeSection");
	if (angelStyle == 1) {
		// Retrieve this book's variables if necessary
		// (for multi-book portals)
		RetrieveBookVars(thisPageBookId);
		
		// set main
		main = mainWin;

		// Get curSection based on the pageId
		
		// determine the stump of the filename -- this will be the pageId value
		ParseGet(main); 
		var fn = GET['pageId'];
		
		// strip out "_alt" if there
		if (fn.indexOf("_alt") > 0) {
			fn = fn.substr(0, fn.indexOf("_alt"));
		}
		
		// Note: in standalone we could use:
		/*
		var fn = main.location.pathname.split("/");
		fn = fn[fn.length-1];
		fn = fn.substr(0, fn.indexOf("."));
		*/

		// Now go through all the sections until we find the value of curSection.
		var s;
		for (s = 0; s < lastTrueSectionIndex; ++s) {
			if (sections[s] != null && sections[s].fn == fn) {
				break;
			}
		}
		
		if (s != lastTrueSectionIndex) {
			curSection = s;
		} else {
			curSection = 0;
		}
		
		// If we have a bannerFrame...
		if (bannerFrame != null) {
			// set the tab to the correct tab.
            // Try the content2 tab (resources) first; this would be the correct one
            // for compclass courses that have the ebook tab hidden
			bannerFrame.changeTab('content2');

			// Now try the ebook ('content') tab
			// This won't do anything if the ebook tab is hidden
			bannerFrame.changeTab('content');
			
			// For alternate bookIds, the tab id might be 'content_bookId'.
			// again, this call won't do anything if this tab doesn't exist.
			if (bookId != primaryBookId) {
				bannerFrame.changeTab('content_' + bookId);
			}
		}

		// PW: Make sure the left-side toc is visible; see jsBFWMap.js
		// This doesn't work, at least in FF Mac...
		/*
		if (top.ANGEL_COURSE_MAIN != null) {
			top.ANGEL_COURSE_MAIN.hideMap = false;
			top.BFWShowMap();
			alert('hidemap off!!!');
		}
		*/
		
	} else {
	
		// Set curSection based on the search string of main's location
		var mls = main.location.search;
		//alert("mls = " + mls);
                if (wikiUser != null && wikiUser == 1) {
                        var mre = new RegExp("\\d+$");
                        var mcs = mls.match(mre);
                        curSection = mcs;

		} else {
                        curSection = main.location.search.substr(1) * 1;
                }

	/*	if (ss.indexOf('&') != -1) {
			curSection = ss.replace(/.*&/, "");
		} else {
			curSection = ss;
		}
		curSection *= 1; */ 


		//alert("curSection = " + curSection);

	}
		

	// Write the user's preferred styles
	// (Can't do this for the title page, because it'll overwrite the page!)
	if (curSection != TITLE_PAGE) {
		WritePrefStyleSheet();
	}

	// Write an event handler to bring the editor into focus when it's loaded.
	main.document.write('<script language="JavaScript">'
		, 'function FCKeditor_OnComplete(e) { if (top.noteBeingEdited != null) { top.SetNoteEditorText(); e.Focus(); } }'
		, '</script>');	// e.Focus()

	// for angel we're done now	
	if (angelStyle == 1) {
		return;
	}
	
	// For standalone, write out the script to include fck, plus another function
	// to initialize it
	main.document.write(
		'<script language="JavaScript" src="', urlStart, 'apis3/fckeditor/fckeditor.js" type="text/javascript"></script>'
		, '<script language="JavaScript">\n'
		, "function InsertFCK() {\n"
		, "if (document.getElementById('noteTA') != null) { \n"
		, "var oFCKeditor = new FCKeditor( 'noteTA' ) ;\n"
		, "oFCKeditor.BasePath = '", urlStart, "apis3/fckeditor/' ;\n"
		, "oFCKeditor.Width = document.getElementById('noteTA').style.width;\n"
		, "oFCKeditor.Config['AutoGrowMin'] = 250;\n"
		, "oFCKeditor.ReplaceTextarea() ;\n"
		, "}"
		, "}"
		, "</script>"
		);
	
	// If curSection wasn't there or is not available, jump to the TITLE_PAGE
	if (curSection == null || curSection == 0 || sections[curSection] == null && angelStyle != 1) {
		//alert('title_page');
		LoadSection(TITLE_PAGE);
		return;
	}

	// Get the bannertitle for comment-style ebook pages
	if (newBannerTitle == null && bookId == 'bedhand7e') {
		newBannerTitle = sections[curSection].jt;
	}
	
	// Write the banner title
	bannerTitle = newBannerTitle;
	WriteLeftBanner();
	// bannerleftF.location.replace(urlStart + "bannerleft.html");

	// Make sure the title images in the other frames are hidden
	if (firstPageLoaded) {
		SetVisibility(logoF.document.getElementById('titlepic'), 'hidden');
		SetVisibility(leftlinksF.document.getElementById('titlepic'), 'hidden');
		SetVisibility(chaptercontentsF.document.getElementById('titlepic1'), 'hidden');
		SetVisibility(chaptercontentsF.document.getElementById('titlepic2'), 'hidden');
	}
	
	// If we're in the title page, do some stuff done in the WriteNotes function
	// for other sections
	if (curSection == TITLE_PAGE) {
		WritePopInWindow_ebook();
	}
}

// Initialize a newly-loaded section 
// Called by the onload event handler of each section page, so happens AFTER the page loads
// This is called by LoadMainTextWindow
function InitializeSection() {
	//alert("curSection in InitializeSection = " + curSection);
	if (loadedFromSearch != null) {
		ParseSearchString(loadedFromSearch);	
		loadedFromSearch = null;
	}	
	
	// Shift focus to the main frame so that the user can use the keyboard to navigate
	// This doesn't seem to work with Safari, but it does with Firefox...
	main.focus();
	
	// For the very first page, InitializeSection must be called by LoadMainTextWindow,
	// because otherwise we might try to do things here (e.g. manipulate the left-side
	// toc) that aren't available.
	if (!firstPageLoaded) {
		return;
	}
	
	// If we happen to be at the last section, hide the forward arrow at the bottom of the screen
	if (GetNextSection() == 0) {
		main.document.getElementById("nextspan").style.visibility = "hidden";
	}
	
	// Special case for henretta6e
	if(bookId == "henretta6e"){
		if(curSection == 3220 && GetNextSection() == 3301){
			main.document.getElementById("nextspan").style.visibility = "hidden";
		} else if(curSection == 3901){
			main.document.getElementById("nextspan").style.visibility = "visible";
		}
	}
	

	// Draw any supplemental links
	if (window.DrawSuppLinks != null) {
        DrawSuppLinks();
    }

	// Initialize the popInWindow for the section
	InitializePopInWindow_ebook();

	// dataframe code location -- the frame where js called by defintions, footnotes, etc. lives
	// This has to be something different if the ebook is displayed in a CMS
	// We have to store it here so that it's set in the main frame -- storing it in text.php wouldn't work
	main.DFCL = top;
	
	// Do any initial highlighting for the section
	InitializeHighlighting();
	
	// Set the bookmark icon and menu appropriately
	SetBookmarkIcon();
	UpdateBookmarkMenu();
	//WriteBookmarkMenu();

	// If we're in a "comment-style" eBook, do some more initialization
	if (commentStyle == 1) {
		InitializeCommentPage();
	}

	// Store the current section URL, assuming we know the username
	if (username != null) {
		var s = "storeLastSection&multisession=" + ums + "&sessionId=" + sessionId + "&section="
			+ escape(SectionURL(curSection)) + "&secId=" + curSection;
		// Yes, curSection is included in SectionURL, but it's convenient to send it in separately
		
		// Add highlighting info from the previous section if there
		if (hlSection > 0) {
			s += "&hlSection=" + hlSection + "&codeString=" + hlCodeString;
		}

		// Send the info to the server
		Servercom(s);
	}

	// Show an alert in the popin window, if the user hasn't dismissed it
	// and it hasn't been shown yet. initialAlert will be set by text.php
	// alert("initial:" + initialAlert);
	if (GetPref("initialMessageDismissed") == 0 && initialAlert != "") {
		ShowPopInWindow_ebook(initialAlertTitle
				, initialAlert
				, initialAlertLink
				, 500
		);
		initialAlert = "";
		SetPref("initialMessageDismissed", 1);

	}
	
	// Show StickyNotes
	WriteStickyNotes();

	// For standalone, call function inserted in preinitizlize, 
	// which inserts the fck editor into notes
	if (angelStyle == 0) {
		main.InsertFCK();
	}

	// for angel do a few more things, then we're done
	if (angelStyle == 1) {
		InitializeToolsMenu();
		
		// Set an onunload event to call PrepareForNewSection, since the user
		// might switch to another section using the Angel controls
		// Note that this would remove any existing onunload handlers,
		// but we don't have them in eBook sections.
		main.onunload = PrepareForNewSection;
		
		// If we're in a new window, kill the "open in new window" link
		if (main.parent.top != this) {
			var oinwl = main.parent.lsn_header.document.getElementById('openInNewWindowLink');
			if (oinwl != null && oinwl.parentNode != null) {
				oinwl.parentNode.style.display = "none";
			}
		}
		
		// If we have any ARGA stuff on the page, start it up
		if (main.includes_arga != null) {
			ARGA_InitializePage(main);
		}
		
	} else {
		
		// Update the left side TOC:
		// Show the proper chapter menu
		DropDownLeftChapter();
		
		// For TAP4e, they want all subsections showing too, ie TOC fully expanded by default
		if (bookId == 'tap4e' || bookId == 'tap4v1' || bookId == 
'tap4v2' || bookId == 'hunt3e' || bookId == 'hunt3v1' ||
bookId == 'hunt3v2' || bookId == 'tapdocs4e') {
			var c = CurrentChapter();
		
		//	alert ("dropping down all left sections");
			for (i = 1; i <= 90; i++) {
//				alert(c + "_" + i);
				DropDownLeftSections(c + "_" + i, "block");
			}
			
		}

	
		// Collapse all sections if they're collapsible; 
		// we'll reopen one below if necessary
		
		// KC: If we do this when n-head is open with many n+1-heads beneath it, we get a jumpy effect in browser....
		if (sections[curSection].nl == 2 || sections[curSection].nl == 3) {
			// do nothing
		} else {
			// henrettadocs6e???
			// Paul R. suggested setting top.suppressCollapseAllSections in config.js for each book rather than adding bookIds here.  Good idea, long overdue.
			if (bookId != 'writersref6e' && bookId != 'smhandbook6e' &&
                bookId != 'rules6e' && bookId != 'bedguide8e' && bookId != 'tap4e' &&
                bookId != 'hunt3e' && bookId != 'tap4v1' && bookId != 'tap4v2' &&
                bookId != 'hunt3v1' && bookId != 'hunt3v2' &&  bookId != 'tapdocs4e' &&
                bookId != 'gatech07142008' && bookId != 'gatech' && bookId != 'bedsearch3e' &&
                bookId != 'everydaywriter4e' && bookId != 'howtowrite' &&
                // Hey, next time, instead of adding yet another bookId here, why not set this in your config.js?
                !top.suppressCollapseAllSections) {
              //alert("collapsing all sections");
				CollapseAllSections();
			}
		}
	
		// If we're in a level n+1 head and the eBook supports level n drop-downs, 
		// expand its enclosing level n head.  Note that the .par field of the sections
		// array will only be something other than null if this feature is supported.
		
		// alert(sections[curSection].par);
		
		if (sections[curSection].par != null) {
			// (DropDownLeftSections will take care of highlighting the lev 2 head)
			DropDownLeftSections(sections[curSection].par, "block");
			
			// KC: AND drop down any sections underneath THIS
	//		alert (sections[curSection].fn);
			DropDownLeftSections(sections[curSection].fn, "block");
	
			LeftHighlight(sections[curSection].fn);
	
		// Otherwise we're in a level n head or an eBook that doesn't support level-n
		// drop downs, so...
		} else {
			// If it has lev n+1 heads, drop them down
			if (sections[curSection].nl == 2) {
				DropDownLeftSections(sections[curSection].fn, "block");
			}
			
			// Highlight the section
			LeftHighlight(sections[curSection].fn);
		}
		
		// Initialize the title page if we're there
		if (curSection == TITLE_PAGE) {	
			// Show the titlepics in the other frames
			SetVisibility(logoF.document.getElementById('titlepic'), 'visible');
			SetVisibility(leftlinksF.document.getElementById('titlepic'), 'visible');
			SetVisibility(chaptercontentsF.document.getElementById('titlepic1'), 'visible');
			SetVisibility(chaptercontentsF.document.getElementById('titlepic2'), 'visible');
			
			// If we're coming to this page after first logging in, we're done.
			if (firstPageLoaded) {
				return;
		
			// Else if lastSection was not stored, or was the title page, show the "startDiv" link
			} else {
				if (lastSection == "" || lastSection == "../0_0.html?1") {
					SetVisibility(main.document.getElementById('startDiv'), "visible");
			
				// Else show the "Return to last-visited" link
				} else {
					SetVisibility(main.document.getElementById('returnDiv'), "visible");
				}
			}
		}
		
		// Add custom sections to the main TOC if we're there
		if (curSection == MAIN_TOC) {
			AddRegisteredCSsToTOC(main);
		}
	}
	
	// If there is a book-specific initialization function for this book, run it
	var BookInitializeFn = this["InitializeSection_" + bookId];
	if (BookInitializeFn != null) {
		BookInitializeFn();
	}
}

var wlbTries = 0;
function WriteLeftBanner() {
	// If the eBook has just been loaded, then
	// bannerleftF may not have loaded by the time this function is first called
	// (by PreinitializeSection).  If this is the case, try again half a second later
	// (but if we try for 50 seconds and it still doesn't work, assume that something
	// more drastic is wrong and stop trying.)
	if (!firstPageLoaded) {
		++wlbTries;
		if (wlbTries < 100) {
			setTimeout(WriteLeftBanner, 500);
		}
		return;
	}
	
	// Hide or show previous/next arrows
	if (curSection == 1) {
		SetVisibility(bannerleftF.document.getElementById('bannerPrevBtnDiv'), 'hidden');
	} else {
		SetVisibility(bannerleftF.document.getElementById('bannerPrevBtnDiv'), 'visible');
	}

	if (GetNextSection() == 0) {
		SetVisibility(bannerleftF.document.getElementById('bannerNextBtnDiv'), 'hidden');
	} else {
		SetVisibility(bannerleftF.document.getElementById('bannerNextBtnDiv'), 'visible');
	}
	
	//Special case for henretta6e:
	if(bookId == "henretta6e"){
		if(curSection == 3220){
			SetVisibility(bannerleftF.document.getElementById('bannerNextBtnDiv'), 'hidden');
		} else if(curSection == 3901){
			SetVisibility(bannerleftF.document.getElementById('bannerNextBtnDiv'), 'visible');
		}
	}
	
	// Put the title in
	bannerleftF.document.getElementById('bannerTitleDiv').innerHTML = bannerTitle;
}


function CurrentSectionNumber() {
	// Take out the part number if present
	var sn = sections[curSection].fn;
	var dash = sn.indexOf("-");
	var pn = "";
	if (dash > -1) {
		pn = sn.substr(dash+1);
		sn = sn.substring(0, dash);
	}
	sn = sn.replace(/_/g, ".");
	if (pn != "") {
		sn = sn + " (" + pn + ")";
	}
	return sn;
	var dash = sn.indexOf("-");
	if (dash > -1) {
		sn = sn.substring(0, dash);
	}
	return sn.replace(/_/g, ".");
}

function SectionNumber(s) {
	// Take out the part number if present
	var sn = sections[s].fn;
	var dash = sn.indexOf("-");
	var pn = "";
	if (dash > -1) {
		pn = sn.substr(dash+1);
		sn = sn.substring(0, dash);
	}
	sn = sn.replace(/_/g, ".");
	if (pn != "") {
		sn = sn + " (" + pn + ")";
	}
	return sn;
}

function CurrentChapter() {
	// If we're in a custom section ...
	if (IsCustomSection()) {
		// Find the section the CS is attached to
		var s = CustomSectionAttachee();
		return GetChapterFromSID(s);
		
	// Else it's easy
	} else {
		return GetChapterFromSID(curSection);
	}
}

// Number of sections in the current version
function NumberOfSectionsAvailable() {
	var n = 0;
	for (var i = 0; i < lastTrueSectionIndex; ++i) {
		if (sections[i] != null) {
			++n;
		}
	}
	return n;
}

// Clean things up before logging out
// Note that a user can also be logged out via textfn.php
function Logout() {
	// reset the username/password cookies
/*	alert('cookie val: ' + GetCookieVal(bookId + "_password"));
	ClearCookie(bookId + "_username");
	ClearCookie(bookId + "_password");
	alert('cookie val: ' + GetCookieVal(bookId + "_password"));
*/	
/*	if (bookId == "speakersguide3e") {
		top.window.close();
		return;
	}
*/	
	UnloadMainTextWindow();

	// If any highlighting info was changed, we have to save it before closing the window
	RecordHighlighting();
	if (hlSection > 0) {
		Servercom("logout&hlSection=" + hlSection + "&codeString=" + hlCodeString);
	} else {
		top.location = "../" + logoutFileName + ".php?logout";
	}
}

function EasterEgg() {
	// Jump to a random page
	var p = 100000000;
	while (sections[p] == null) {
		p = Math.floor(Math.random()*lastTrueSectionIndex);
	}
	LoadSection(p);
}

// Sniff the user's browser and warn them if they're using something that
// might not work.
// Most of this code was borrowed from http://www.quirksmode.org/index.html?/js/events_compinfo.html
// The script on that page was written in 1/2004
function BrowserDetect() {
	// Helper function
	function checkIt(string) {
		place = detect.indexOf(string) + 1;
		thestring = string;
		return place;
	}
	
	// Detect the browser, version, and OS
	var detect = navigator.userAgent.toLowerCase();
	
	// alert ("This is the value of detect: " + detect);
	
	var OS, browser, version, total, thestring;
	
	if (checkIt('konqueror')) {
		browser = "Konqueror";
		OS = "Linux";
	}
	else if (checkIt('safari')) browser = "Safari";
	else if (checkIt('omniweb')) browser = "OmniWeb";
	else if (checkIt('opera')) browser = "Opera";
	else if (checkIt('webtv')) browser = "WebTV";
	else if (checkIt('icab')) browser = "iCab";
	else if (checkIt('msie')) browser = "Internet Explorer";
	else if (checkIt('firefox')) browser = "Firefox";
	else if (checkIt('netscape')) browser = "Netscape";
	/* KC: not sure if this is relevant anymore
	else if (!checkIt('compatible')) {
		browser = "Netscape Navigator";
		version = detect.charAt(8);
	}
	*/
	else browser = "An unknown browser";


	
	if (!version) version = detect.substr(place + thestring.length);
//	detect.charAt(place + thestring.length);
	
	// detect does not correctly give the version for Safari
	
	// this array pairs version number with build number (which is given in detect)
	// table from which array was assembled is at
	// http://en.wikipedia.org/wiki/Safari_%28web_browser%29
	var SafariVersionBuildArray = new Array ("0.8","48","0.8.1","51","0.8.2","60","0.9","73","0.9","74","1.0","85","1.0","85.5","1.1","100","1.1.1","100.1","1.0.1","85.6","1.2","125","1.0.2","85.7","1.2.1","125.1","1.2.2","125.7","1.2.2","125.8","1.0.3","85.8","1.0.3","85.8.1","1.2.3","125.9","1.2.4","125.11","1.2.4","125.12","1.3","312","2.0","412","2.0","412.2","2.0","412.2.2","1.3.1","312.3","2.0.1","412.5","2.0.2","416.12");
	
	
	if (browser == "Safari") {
		var buildNo = version;
		for (i = 0; i <= SafariVersionBuildArray.length; i++) {
		
			if (buildNo == SafariVersionBuildArray[i]) {
				version = SafariVersionBuildArray[i - 1];
			}
		}
	}
			
	
	if (!OS) {
		if (checkIt('linux')) OS = "Linux";
		else if (checkIt('x11')) OS = "Unix";
		else if (checkIt('mac')) OS = "Mac";
		else if (checkIt('win')) OS = "Windows";
		else OS = "an unknown operating system";
	}
	
	// Now warn if we're not using:
		// on the Macintosh:
			// Safari
			// Firefox v1+
			// Netscape 6+
		// on Windows:
			// IE 5+
			// Firefox v1+
			// Netscape 6+

	// now that we've dealt with Safari we might as well do this
	version = version.charAt(0);
	
	// KC: not sure what this is accomplishing...changing text to number?
	version = version * 1;
	
	
	if (OS == "Mac") {
		if (! (
			(browser == "Safari")
		||	(browser == "Firefox" && version >= 1)
		||  (browser == "Netscape" && version >= 6)
		)) {
		
			alert ("On the Macintosh, the " + bookTitle + " eBook was designed to be viewed using Apple's Safari browser, Firefox version 1 or above, or Netscape version 6 or above.  You appear to be browsing the eBook with a different browser (" + browser + " version " + version + ").  You are welcome to do so, but be warned that some features may not work correctly.  Instructions on downloading one of the supported browsers can be found by clicking the \"System Check\" link from the Table of Contents.");
		}
		
	} else if (OS == "Windows") {
//		if (browser == "Internet Explorer" && version >= 7) {
//			alert ("The " + bookTitle + " eBook has not been adapted to work with Internet Explorer 7. Please use IE 6 or Firefox to use the eBook at this time.")
//		} else 
		if (! (
			(browser == "Internet Explorer" && version >= 5)
		||	(browser == "Firefox" && version >= 1)
		||  (browser == "Netscape" && version >= 6)
		)) {
		
			alert ("On Windows, the " + bookTitle + " eBook was designed to be viewed using Internet Explorer version 5 or above, Firefox version 1 or above, or Netscape version 6 or above.  You appear to be browsing the eBook with a different browser (" + browser + " version " + version + ").  You are welcome to do so, but be warned that some features may not work correctly.  Instructions on downloading one of the supported browsers can be found by clicking the \"System Check\" link from the Table of Contents.");
		}
	}
	
	// alert("You are using " + browser + " with version " + version);

}

// Pop up an alert if the user's account is due to expire soon
var expAlrtCookieName = bookId + '-' + username + '-expalrt';
function Check_Expiration() {
	// Guest login never expires
	if (username == "guest") {
		return;
	}
		
	if (daysleft > -1 && daysleft <= 60) {
		// First check for a cookie saying when we last reminded the user
		var lastAlert = GetCookieVal(expAlrtCookieName);
		
		// If there are 21-60 days left, only alert if we haven't yet shown an alert
		if (daysleft > 20) {
			if (lastAlert == null) {
				Show_Expiration_Alert();
			}

		// If there are 10-20 days left, alert if the last alert was with more than 21 days left
		} else if (daysleft > 9) {
			if (lastAlert == null || lastAlert > 21) {
				Show_Expiration_Alert();
			}
				
		// If there are 1-9 days left, alert unless we already showed an alert today
		} else {
			if (lastAlert != daysleft) {
				Show_Expiration_Alert();
			}
		}
	}
}

function Show_Expiration_Alert() {
	var alertText = "Your subscription to this eBook will expire in " + daysleft + " day" + ((daysleft == 1 ? "" : "s")) + ". To renew your subscription, log out of the eBook, click the PURCHASE link, enter your *EXISTING* username and password when prompted, and complete the purchase.";
	alert(alertText);
	
	// Show an additional alert if this is life and they haven't been alerted before
	if (bookId == "life" && GetCookieVal(expAlrtCookieName) == null) {
		alertText = "You are also now eligible to purchase a printed copy of Life, Seventh Edition for US $30.00 (plus shipping). To purchase, please call Sinauer Associates at (413) 549-4300.";
		alert(alertText);
	}
	
	// Set the cookie saying when we last reminded the user
	StoreCookie(expAlrtCookieName, daysleft);
}

function OpenGradebook() {
	OpenSupp('bcs', 'QUIZ GRADEBOOK', 'http://tests.sasmp.com/reports/qm3testing/instruct_1.asp?email=' + email);
}

// *************************************************************
function ______LEFT_SIDE_TOC______() {}

// Drop down the menu for the current chapter (and collapse any other chapters if necessary)
var curDroppedChapter = -1;
function DropDownLeftChapter() {
	// Get the current chapter
	var c = CurrentChapter();

	// If the current chapter isn't the chapter that's currently dropped down...
	if (c != curDroppedChapter) {
		// Collapse the old chapter
		// except for writer's ref and SMH and rules
		if (bookId != 'writersref6e' && bookId != 'smhandbook6e' && bookId != 'rules6e') {
			if (curDroppedChapter > -1) {
				SetDisplay(chaptercontentsF.document.getElementById("div" + curDroppedChapter), "none");

			// for wonky SMG TOC (and wonky Media & Culture TOC?)
			SetDisplay(chaptercontentsF.document.getElementById("chapter" + curDroppedChapter), "none");
		
				// If a comment-style book, show the "bulrt" pic
				if (commentStyle == 1 && chaptercontentsF.document['dd' + curDroppedChapter] != null) {
					chaptercontentsF.document['dd' + curDroppedChapter].src = bulrt.src;
				}
			}
		}
		
		// Set curDroppedChapter to c
		curDroppedChapter = c;
		
		
		
		// for wonky SMG TOC (and wonky Media & Culture TOC?)
		SetDisplay(chaptercontentsF.document.getElementById("chapter" + curDroppedChapter), "block");
		
		
		
		// Expand the new chapter
		//alert("expanding chapter" + curDroppedChapter);
		
		SetDisplay(chaptercontentsF.document.getElementById("div" + curDroppedChapter), "block");
		
		//alert("epxanded" + curDroppedChapter);
		//alert("status is " + chaptercontentsF.document.getElementById("div" + curDroppedChapter).style.display);
		
		// If a comment-style book, show the "buldn" pic
		if (commentStyle == 1 && chaptercontentsF.document['dd' + c] != null) {
			chaptercontentsF.document['dd' + c].src = buldn.src;
		}
	}
}

// Highlight a section in the toc, de-highlighting whatever was highlighted previously
var curLeftHighlightedDiv = null;
var curLeftHighlightedPart = null;
function LeftHighlight(div) {
	// Remove part number from div, if present
	var dash = div.indexOf("-");
	var part = null;
	if (dash > -1) {
		part = div.substr(dash + 1) * 1;
		div = div.substring(0, dash);
	}
	
	// Part 1's don't have a part number in their div titles...
	if (part == null && chaptercontentsF.document.getElementById("tdc" + div + "p1") != null) {
		part = 1;
	}
	
	// De-highlight whatever is currently highlighted
	if (curLeftHighlightedDiv != null) {
		ClearLeftHighlight();
	}
	
	// Highlight the requested div, if it exists
	var tda = chaptercontentsF.document.getElementById("tda" + div);
	if (tda != null) {
		tda.style.backgroundColor = leftHighlightBgdColor;	// defined in defaults.js
		var tdb = chaptercontentsF.document.getElementById("tdb" + div);
		if (tdb != null) {
			tdb.style.backgroundColor = leftHighlightBgdColor;	// defined in defaults.js
		}

		if (part != null) {
			var tdc = chaptercontentsF.document.getElementById("tdc" + div + "p" + part);
			if (tdc != null) {
				tdc.style.borderColor = leftHighlightPartBorderColorHighlighted;
				curLeftHighlightedPart = part;
			}
		}
		
		// Also make sure the left side menu is scrolled down to show the div
		// Find scroll position of tda (adapted from http://www.quirksmode.org/js/findpos.html)
		if (tda.offsetParent) {		// Should be true for any v5+ browser
			var obj = tda;
			var top = 0;
			while (obj.offsetParent) {
				top += obj.offsetTop;
				obj = obj.offsetParent;
			}
			
			// And scroll to it
			chaptercontentsF.scrollTo(0, top - 100);
		}
	}

	// Reset curLeftHighlightedDiv
	curLeftHighlightedDiv = div;
}

// De-highlight whatever section is currently highlighted in the toc
function ClearLeftHighlight() {
	if (curLeftHighlightedDiv == null) {
		return;
	}
	
	var tda = chaptercontentsF.document.getElementById("tda" + curLeftHighlightedDiv);
	if (tda != null) {
		tda.style.backgroundColor = "transparent";
	}

	var tdb = chaptercontentsF.document.getElementById("tdb" + curLeftHighlightedDiv);
	if (tdb != null) {
		tdb.style.backgroundColor = "transparent";	
	}

	var tdc = chaptercontentsF.document.getElementById("tdc" + curLeftHighlightedDiv + "p" + curLeftHighlightedPart);
	if (curLeftHighlightedPart != null && tdc != null) {
		tdc.style.borderColor = leftHighlightPartBorderColorNormal;
	}
	
	curLeftHighlightedDiv = null;
	curLeftHighlightedPart = null;
}

// Some eBooks (e.g. Life) have collapsible first-level sections, so that by default,
// second-level sections are not shown until you are within a first-level section
// that contains second-level sections.

// Declare an associative array to keep track of which section divs are dropped down
// so we can un-drop them all when necessary
var leftDropped = new Object();

// preload the arrow-bullets for the toc.  If the eBook doesn't include drop-downs,
// the files won't be found, but they won't be used, either.
var bulrt = new Image(); bulrt.src = urlStartBookID + "pics/dropSmallRight.gif";
var buldn = new Image(); buldn.src = urlStartBookID + "pics/dropSmallDown.gif";


function DropDownLeftSections(div, newState) {
// This function drops down the contents (i.e. the second-level sections)
// of a level 1 head.
	
  if (bookId == "listen6e") {newState="block";}
  	
	// In some books,
	// Each level 1 head has a div for its lev 2 heads, plus a "T" div for its tutorials.
	// When we're SHOWING the lev2 heads, we want to be HIDING the T div, and vice-versa
	var style = chaptercontentsF.document.getElementById("div" + div);
	var styleT = chaptercontentsF.document.getElementById("divT" + div);
	// Return if the "style" element doesn't exist (styleT is optional)
	if (style == null) {
		return;
	} else {
		style = style.style;
		if (styleT != null) {
			styleT = styleT.style;
		}
	}
	
	// If no state specified, toggle
	if (newState == "toggle" || newState == null) {
		if (style.display == "block") {
			newState = "none";
		} else {
			newState = "block";
		}
	}
	
	// Set the display and update leftDropped
	if (newState == "none") {
		style.display = "none";
		if (styleT != null) {
			styleT.display = "block";
		}
		
		if (chaptercontentsF.document["dd" + div] != null) {
		
			chaptercontentsF.document["dd" + div].src = bulrt.src;
			
		}
		
		leftDropped[div] = null;
	} else {
		style.display = "block";
		if (styleT != null) {
			styleT.display = "none";
		}
		
		if (chaptercontentsF.document["dd" + div] != null) {
	
			chaptercontentsF.document["dd" + div].src = buldn.src;
		
		}
		leftDropped[div] = true;
	}

//	alert ("div" + div + "newState" + newState);	

	// If we're collapsing a drop-down menu that contains the current section,
	// highlight the enclosing section.
	// Likewise, if we're expanding a menu that contains the current section,
	// de-highlight the enclosing section
	if (div == sections[curSection].par) {
		if (newState == "none") {	// collapsing, so highlight enclosing section
			LeftHighlight(div);
		} else {					// expanding, so highlight this section
			LeftHighlight(sections[curSection].fn);
		}
	}
}

// "Undrop" all currently dropped-down level 1 heads
// If the eBook doesn't support level 1 drop-downs, leftDropped will never
// contain anything, so nothing will happen here.
function CollapseAllSections() {
	for (var div in leftDropped) {
		DropDownLeftSections(div, "none");
	}
}

// Write some links that only appear on the TOC
function WriteSpecialTOCLinks() {
	WriteBookSpecificLeftSideStuff();	// config.js
	return;
}

function DismissInitialAlert() {
	ClosePopInWindow_ebook();
	SetPref("initialMessageDismissed", 1);
}

// highlighting functions adapted from http://www.nsftools.com/misc/SearchAndHighlight.htm


/*
 * This is the function that actually highlights a text string by
 * adding HTML tags before and after all occurrences of the search
 * term. You can pass your own tags if you'd like, or if the
 * highlightStartTag or highlightEndTag parameters are omitted or
 * are empty strings then the default <font> tags will be used.
 */
function doHighlight(bodyText, searchTerm, highlightStartTag, highlightEndTag) 
{
  // the highlightStartTag and highlightEndTag parameters are optional
  if ((!highlightStartTag) || (!highlightEndTag)) {
    highlightStartTag = "<font style='color:blue; background-color:yellow;'>";
    highlightEndTag = "</font>";
  }
  
  if (searchTerm == "" || searchTerm == " ") {
  	return;
  }
  
  // alert("searchTerm is: '" + searchTerm + "'");
  
  // we should also skip so-called "stop" words
  // the following list is taken from www.ranks.nl/tools/stopwords.html
  var foundStopWord = 0;
   var stopWords = new Array ("I","a","about","an","are","as","at","be","by","com","de","en","for","from","how","in","is","it","la","of","on","or","that","the","this","to","was","what","when","where","who","will","with","und","the","www");
   for (j = 0; j <= stopWords.length; j++) {
   	// alert("Checking stopword:" + stopWords[j]);
   	if (searchTerm == stopWords[j]) {
   		// alert("Found stopword:" + searchTerm);
   		foundStopWord = 1;
   	}
   }
   
   if (foundStopWord == 1) {
   	// do nothing
    return bodyText;
   }
  
 // alert("::" + searchTerm + "::");
  
  // find all occurences of the search term in the given text,
  // and add some "highlight" tags to them (we're not using a
  // regular expression search, because we want to filter out
  // matches that occur within HTML tags and script blocks, so
  // we have to do a little extra validation)
  var newText = "";
  var i = -1;
  var lcSearchTerm = searchTerm.toLowerCase();
  var lcBodyText = bodyText.toLowerCase();
    
  while (bodyText.length > 0) {
    i = lcBodyText.indexOf(lcSearchTerm, i+1);
    if (i < 0) {
      newText += bodyText;
      bodyText = "";
    } else {
      // skip anything inside an HTML tag
      if (bodyText.lastIndexOf(">", i) >= bodyText.lastIndexOf("<", i)) {
        // skip anything inside a <script> block
        if (lcBodyText.lastIndexOf("/script>", i) >= lcBodyText.lastIndexOf("<script", i)) {
          newText += bodyText.substring(0, i) + highlightStartTag + bodyText.substr(i, searchTerm.length) + highlightEndTag;
          bodyText = bodyText.substr(i + searchTerm.length);
          lcBodyText = bodyText.toLowerCase();
          i = -1;
        }
      }
    }
  }
  
  // alert(newText);
  return newText;
}


/*
 * This is sort of a wrapper function to the doHighlight function.
 * It takes the searchText that you pass, optionally splits it into
 * separate words, and transforms the text on the current web page.
 * Only the "searchText" parameter is required; all other parameters
 * are optional and can be omitted.
 */
function highlightSearchTerms(searchText, treatAsPhrase, warnOnFailure, highlightStartTag, highlightEndTag)
{
  // if the treatAsPhrase parameter is true, then we should search for 
  // the entire phrase that was entered; otherwise, we will split the
  // search string so that each word is searched for and highlighted
  // individually
  if (treatAsPhrase) {
    searchArray = [searchText];
  } else {
    searchArray = searchText.split(" ");
  }
  
  if (!document.body || typeof(main.document.body.innerHTML) == "undefined") {
    if (warnOnFailure) {
      alert("Sorry, for some reason the text of this page is unavailable. Searching will not work.");
    }
    return false;
  }
  
  var bodyText = main.document.body.innerHTML;
  for (var i = 0; i < searchArray.length; i++) {
  	if (searchArray[i] == "" || searchArray[i] == " ") {
  		// skip
  	} else {
	    bodyText = doHighlight(bodyText, searchArray[i], highlightStartTag, highlightEndTag);
	}
  //  alert("bodyText in loop:" + bodyText);
  }

 // alert("bodyText after loop:" + bodyText);
  main.document.body.innerHTML = bodyText;
  return true;
}


/*
 * This displays a dialog box that allows a user to enter their own
 * search terms to highlight on the page, and then passes the search
 * text or phrase to the highlightSearchTerms function. All parameters
 * are optional.
 */

var loadedFromSearch = null;

function ParseSearchString(terms) {
	// Get rid of *'s in the search terms
	terms = terms.replace(/\*/g, '');

	var textColor = "#000000";
	var bgColor = "#ffff66";

  	var highlightStartTag = "<font style='color:" + textColor + "; background-color:" + bgColor + ";'>";
    var highlightEndTag = "</font>";

	// var searchTerms = new Array ();
	var searchTerms = new Array();
	searchTerms = terms.split("+");
	
	// i = 1???
	for (i = 0; i < searchTerms.length; i++) {
		// alert(i + ":" + searchTerms[i]);
		var searchText = searchTerms[i];
		
		// alert("searchText" + searchText);
		if (searchText == "" || searchText == " ") {
			//skip
		} else {
			highlightSearchTerms(searchText, false, true, highlightStartTag, highlightEndTag)
		}
	}
	
}


// KT: adding this as a debug for R&R

function DropDownChapter(chapter) {
	// bulrt and buldn are defined in ebookNavigation.js
	var d = chaptercontentsF.document.getElementById('div' + chapter);
//	alert(d);
	if (d.style.display == 'block') {
		d.style.display = 'none';
		chaptercontentsF.document['dd' + chapter].src = bulrt.src;
	} else {
		d.style.display = 'block';
		chaptercontentsF.document['dd' + chapter].src = buldn.src;
	}
}

// KC: function for jumping to glossary defs in historybooks
function JumpToTerm(sectionId, hash, searchTerms) {

	// KC: as of 7/8/2008, they just want to go to top of specified 
	// page
	LoadSection(sectionId);
//	top.loadedFromSearch = searchTerms;
}
