//****************************************************************
//****************************************************************
// Copyright 2004, www.anitasrecipes.com
// This code may not be reproduced, copied, or distributed
// without the written consent of www.anitasrecipes.com.
//****************************************************************
//****************************************************************


var kIndexURL = "http://www.cyberstitchers.com/BookPage.asp"
var kRecordURL = "http://www.cyberstitchers.com/BookPage.asp?recordID=";
var gTurningPage = false;
var gIndexLoaded = false;

var kContentBufferID = "ContentBuffer";
var kContentIndexID = "ContentIndex";
var kLeftPageID = "LeftPageContent";
var kRightPageID = "RightPageContent";
var kPagesReadID = "PagesRead";
var kPagesRemainingID = "PagesRemaining";
var kDefaultLineHeight = 16;
var gCurrentPage = -2;
var gCurrentDirection = 0;
var gCurrentRecord = 0; 
var gCurrentPageRecord = new Array();
var gPages = "";
var gPagesAdded = 0;
var gRecordIndex = "";
var gRecordName = "";
var gCategoryID = "";
var gPagesReadSectionDividers = "";
var gPagesRemainingSectionDividers = "";
var gCategories = "";
var gCurrentView = "";
var gCurrentSearch = "";
var gIsSearchPage = 0;
var gCategoryNamesById = "";
var gViews = "";
var gViewsByID = "";
var gTotalRecords = 0;
var gResizing = false;
var gHistory = new Array();
var gHistoryIndex = -1;
var gBrowsingHistory = false;
var gLoadingTimer = "";
var gTableOfContents = new Array();

var gRequestedPage = false;

// Book Constants
var kPageThickness = 0.0001;
var kStartPage = { content:"", pageStart:0, pageEnd:0, currentRecord:0 };
var kEndPage = { content:"", pageStart:0, pageEnd:0, currentRecord:gTotalRecords };
var kInitialRecordCookie = "InitialRecord";
var kScreenDpiX = (screen.deviceXDPI || 96);

//===========================================================
// Initialize
//===========================================================
function Initialize( ) {
	try {
		RightPageContent.innerHTML = "";
		LeftPageContent.innerHTML =  "";
		RightPage.style.height = LeftPage.style.height = CalculatePageHeight();
		RightPageContent.style.width = LeftPageContent.style.width = CalculatePageContentWidth();
		RightPageContent.style.height = LeftPageContent.style.height = CalculatePageContentHeight();
		RightTopEdge.style.width = LeftTopEdge.style.width = ((document.body.clientWidth - TopLeftCorner.offsetWidth*2 - GetBookThickness()-24*2)/2 );
		}
	catch( error ) {
		window.status = ( "Initialize: " + error.description );
		}
	}

//================================================================
// GetCookie_CS
//================================================================
function GetCookie_CS(name) {
	var aCookie = document.cookie.split("; ");
	for (var i=0; i < aCookie.length; i++) {
		var nameValuePair = aCookie[i].split("=");
		if (name == nameValuePair[0]) return unescape(nameValuePair[1]);
		}
	return "";
	}



//================================================================
// SetCookie_CS
//================================================================
function SetCookie_CS( name, value ) {
	var today = new Date();
	var domain = document.location.hostname;
	var expires = new Date(today.getTime() + (1000*60*60*24*365));
	var attributes = ";expires=" + expires + ";domain=" + domain;
	document.cookie = name + "=" + value + attributes;
	}


//===========================================================
// ResizePages
//===========================================================
function ResizePages( ) {
	try {
		if (!gResizing) {
			//document.recalc(true);
			gResizing = true; 
			}
		else {
			gResizing = false;	
			Initialize();
			AddSectionDividers();
			ClearPageBuffer(true);
			HandleViewRecord( gCurrentRecord );
			}
		}
	catch( error ) {
		window.status = ( "ResizePages: " + error.description );
		}
	}


//===========================================================
// GetPageThickness
//===========================================================
function GetPageThickness( ) {
	var thickness = kPageThickness;
	try {
		if (gCurrentView == "search") {
			thickness = 1/gTotalRecords;
			if (gTotalRecords < 100)  thickness = 0.01;
			}
		}
	catch( error ) {
		window.status = ( "GetPageThickness: " + error.description );
		}
	return thickness;
	}


//===========================================================
// GetBookThickness
//===========================================================
function GetBookThickness( pageCount ) {
	var thickness = 0;
	try {
		if (pageCount == 0) pageCount = 1; 
		if (!pageCount) pageCount =  gTotalRecords;
		thickness = Math.floor(GetPageThickness()*pageCount*kScreenDpiX);
		}
	catch( error ) {
		window.status = ( "GetBookThickness: " + error.description );
		}
	return thickness;
	}


//===========================================================
// CalculatePageWidth
//===========================================================
function CalculatePageWidth( ) {
	var pageWidth = 0;
	try {
		var pageEdgeWidth = LeftPageEdge.offsetWidth;
		pageWidth = (document.body.clientWidth - TopLeftCorner.offsetWidth*2 - GetBookThickness())/2 - pageEdgeWidth;
		}
	catch( error ) {
		window.status = ( "CalculatePageWidth: " + error.description );
		}
	return pageWidth;
	}



//===========================================================
// CalculatePageContentWidth
// Added kWidthFudge to PageContentRegion to
// account for unknown variation in apparent width of
// content region VS content element.
//===========================================================
function CalculatePageContentWidth( ) {
	var pageContentWidth = 0;
	try {
		var imagePadding = 50;
		var kWidthFudge = 0;
		pageContentWidth = CalculatePageWidth() - imagePadding - kWidthFudge;
		}
	catch( error ) {
		window.status = ( "CalculatePageContentWidth: " + error.description );
		}
	return pageContentWidth;
	}




//===========================================================
// CalculatePageHeight
//===========================================================
function CalculatePageHeight( ) {
	var pageHeight = 0;
	try {
		var padding = 8;	// Needed for correct height - dont' know why.
		pageHeight = document.body.clientHeight - TopLeftCorner.offsetHeight*2 - padding;
		}
	catch( error ) {
		window.status = ( "CalculatePageHeight: " + error.description );
		}
	return pageHeight;
	}


//===========================================================
// CalculatePageContentHeight
//===========================================================
function CalculatePageContentHeight( ) {
	var pageContentHeight = 0;
	try {
		var margins = 2*0;
		pageContentHeight = CalculatePageHeight() - RightPageHeader.offsetHeight - RightPageFooter.offsetHeight - margins;
		}
	catch( error ) {
		window.status = ( "CalculatePageContentHeight: " + error.description );
		}
	return pageContentHeight;
	}


//===========================================================
// HandleContentBufferLoaded
//===========================================================
function HandleContentBufferLoaded() {
	try {
		gRequestedPage = "";
		var contentDocument = document.frames[kContentBufferID].document;
		var lineTest = contentDocument.getElementById("LineHeightTest");
		var contentElement = contentDocument.body;
		var pageElement = contentDocument.getElementById( kRightPageID );
		if (lineTest) {
			kDefaultLineHeight =  lineTest.offsetHeight || kDefaultLineHeight;
			}
		if (gCurrentRecord == 1) {
			var categories =  contentDocument.getElementById( "gCategories" );
			var categoryNames = contentDocument.getElementById( "gCategoryNamesById" );
			var views = contentDocument.getElementById( "gViews" );
			var viewsById = contentDocument.getElementById( "gViewsByID" );
			if (categories) eval( "gCategories = " + categories.innerText + ";" );
			if (categoryNames) eval( "gCategoryNamesById = " + categoryNames.innerText + ";" );
			if (views) eval( "gViews = " + views.innerText + ";" );
			if (viewsById) eval( "gViewsByID = " + viewsById.innerText + ";" );
			AddSectionDividers();
			if (gInitialChapter) {
				gInitialRecord = GetRecordForChapter( gInitialChapter );
				gInitialChapter = "";
				} 
			if (gInitialRecord && gInitialRecord != 1) {
				HandleViewRecord( gInitialRecord );
				gInitialRecord = 0;
				gHandleSearch = false;
				return;
				}
			}
		else {
			var recordName =  contentDocument.getElementById( "RecordName" );
			var recordCategoryID =  contentDocument.getElementById( "RecordCategoryID" );
			//var fileID =  contentDocument.getElementById( "FileID" );
			//gFileID = (fileID ? fileID.innerText : "");
			gRecordName = (recordName ? recordName.innerText : "");	
			gCategoryID = (recordCategoryID ? Number(recordCategoryID.innerText) : 0);
			}
		PaginateContent( contentElement );
		if (HasPages()) {
			DisplayPages();
			} 
		else {
			GetPages();
			}
		}
	catch( error ) {
		window.status = ( "HandleContentBufferLoaded: " + error.description );
		}
	}


//-----------------------------------------------------------
// HilightSearchResults
//-----------------------------------------------------------
function HilightSearchResults( pageInfo ) {
	try {
		if (!pageInfo.hilighted && pageInfo.currentRecord > 1) { 
			var hilightedText = pageInfo.content;
			// replace any HTML Tags & terms to avoid problems!!!
			var searchText = gCurrentSearch;//.replace( /(style|href|font|table)/gi, "");
			if (!searchText) return; 
			if (searchText.match(/^\"[^\"]+\"$/)) {
				searchText = searchText.replace(/\"/g,"");
				hilightedText = pageInfo.content.replace( new RegExp( searchText, "gi"), "<span class=SearchTerm>" + searchText + "</span>" );
				}
			else { 
				searchText = searchText.replace(/\"/g, "").replace( / a /gi, "").replace(/[ ]+/g, "|");
				hilightedText = pageInfo.content.replace( new RegExp( "([ ]{1})(" + searchText + ")([^=>\"]{1})", "gi"), "$1<span class=SearchTerm>$2</span>$3" );
				}
			// fix tags 
			var matches = hilightedText.match( /(ALT|SRC|HREF)=\"([^\"]+)\"/gi );
			for (var item=0; item<matches.length; item++) {
				var attribute = matches[item];
				hilightedText = hilightedText.replace( attribute, attribute.replace( /<[^>]+>/g, "") );
				}
			pageInfo.content = hilightedText;
			pageInfo.hilighted = true;
			}
		}
	catch (error) {
		window.status = ( "HilightSearchResults: " + error.description );
		}
	}


//-----------------------------------------------------------
// GetRecordForChapter
//-----------------------------------------------------------
function GetRecordForChapter( criteria ) {
	var recordIndex = 0;
	try {
		for (var item=0; item<gCategories.length; item++) {
			var category = gCategories[item];
			if (category.Name == criteria) {
				recordIndex = category.RID;
				break;
				}
			}
		if (recordIndex == 0) {
			//Nothing found, try search;
			SetCookie_CS( kInitialRecordCookie, 2 );
			document.location.href = "/Scripts/BookViewer/index.asp?newWindow=1&view=search&search=\"" + criteria + "\"";
			} 
		}
	catch (error) {
		window.status = ( "GetRecordForChapter: " + error.description );
		}
	return recordIndex;
	}


//-----------------------------------------------------------
//  WriteDiagnostics
//-----------------------------------------------------------
function WriteDiagnostics( text, clear ) {
	if (clear) Diagnostics.innerHTML = "";
	Diagnostics.innerHTML += text + "<br>";
	}


//----------------------------------------------------------------
// GetElementLocation
//----------------------------------------------------------------
function GetElementLocation( element ) {
	var screenCoordinates = { left:0, top:0 };
	try {
		var elementWidth = element.offsetWidth;
		var elementHeight = element.offsetHeight;
		while (element) {
			screenCoordinates.left += element.offsetLeft;
			screenCoordinates.top += element.offsetTop;
			element = element.offsetParent;
			}
		screenCoordinates.right = screenCoordinates.left + elementWidth;
		screenCoordinates.bottom = screenCoordinates.top + elementHeight;
		}
	catch (error) {
		window.status = ( "GetElementLocation: " + error.description );
		}
	return screenCoordinates;
	}


//-----------------------------------------------------------
// ClearPageBuffer
//-----------------------------------------------------------
function ClearPageBuffer( clearTOC ) {
	try {
		if (clearTOC) gTableOfContents = new Array(); 
		gPages = new Array();
		gCurrentPage = 0;
		}
	catch (error) {
		window.status = ( "CleatPageBuffer: " + error.description );
		}
	}


//-----------------------------------------------------------
// AddPage
//-----------------------------------------------------------
function AddPage( pageHTML, pageStart, pages ) {
	try {
		var lastPageEnd = (pages.length > 0 ? pages[pages.length-1].pageEnd : 0 );
		pages.push( { content:pageHTML, pageStart:(lastPageEnd ? lastPageEnd : 0), pageEnd:pageStart, currentRecord:gCurrentRecord, name:gRecordName, CID:gCategoryID } );
		if (gCurrentRecord == 1) {
			gTableOfContents.push( pages[pages.length-1] ); 
			}
		//WriteDiagnostics( "AddPage: " + ["lastPageEnd:",lastPageEnd,"pageStart:",pageStart,"Content Height:",pageStart-lastPageEnd ] + "<hr>" );
		}
	catch (error) {
		window.status = ( "AddPage: " + error.description );
		}
	}


//-----------------------------------------------------------
// HasPages
//-----------------------------------------------------------
function HasPages( ) {
	var hasPages = false;
	try {
		// Removed gPagesAdded since it was cuasing duplicate recipes to be added when one page was remaining in
		// page buffer and recipe added was 1 page in length.
		//hasPages = (gPages.length > 0 && gCurrentPage >= 0 && gCurrentPage+1 < gPages.length && gPagesAdded >= 2)
		hasPages = (gPages.length > 0 && gCurrentPage >= 0 && gCurrentPage+1 < gPages.length);
		}
	catch (error) {
		window.status = ( "HasPages: " + error.description );
		}
	return hasPages;
	}


//-----------------------------------------------------------
// GetPageBottom
//-----------------------------------------------------------
function GetPageBottom( pages, pageHeight ) {
	var pageBottom = 0;
	try {
		pageBottom = (pages.length > 0 ? pages[pages.length-1].pageEnd : 0) + pageHeight;
		}
	catch (error) {
		window.status = ( "GetPageBottom: " + error.description );
		}
	return pageBottom;
	}


//-----------------------------------------------------------
// GetTopSpace
//-----------------------------------------------------------
function GetTopSpace( element ) {
	var topSpace = 0;
	try {
		var attributes = "margin,padding".split(",");
		for (var item=0; item<attributes.length; item++) {
			var value = element.style[ attributes[item] ];
			if (value) topSpace += Number(value.replace(/[^0-9]/g, ""));
			}
		}
	catch (error) {
		window.status = ( "GetTopSpace: " + error.description );
		}
	return topSpace;
	}


//-----------------------------------------------------------
// SplitContent
//-----------------------------------------------------------
function SplitContent( contentElement, pageHeight, contentHeight, pages, pageHTML ) {
	try {
		var tagName = contentElement.tagName;
		var isBody = (tagName == "BODY");
		var kPhotoFrameFudgeFactor = -5;
		var contentTop = GetElementLocation(contentElement).top + (contentElement.className == "PhotoFrame" ? kPhotoFrameFudgeFactor : 0)
		var contentBottom = contentTop + contentElement.offsetHeight + (contentElement.className == "PhotoFrame" ? kPhotoFrameFudgeFactor : 0)
		var pageBottom = GetPageBottom( pages, pageHeight );
		//WriteDiagnostics( "SplitContent: " + [contentElement.offsetWidth,pageHeight, contentHeight, contentElement.offsetHeight,contentElement.tagName,"contentTop",contentTop,"contentBottom",contentBottom] );
		//WriteDiagnostics( "contentElement.children.length: " + [contentElement.children.length,contentElement.nodeType,contentElement.isMultiLine ] );
		if (contentBottom <= pageBottom) {
			// fits in page
			//WriteDiagnostics( "fits in page: " + contentElement.tagName + [contentBottom,pageBottom])
			if (contentHeight == 0) { 
				AddPage( pageHTML, contentBottom, pages ) ;
				}
			else {
				contentHeight = contentBottom;
				}
			}
		else if (contentElement.children.length > 0 && !contentElement.className.match(/(bookNote|Note|ProjectInfo|PhotoFrame|BookSubTitle)/g) ) {
			var splitText = false;
			for (var childIndex=0; childIndex<contentElement.childNodes.length; childIndex++) {
				var childNode = contentElement.childNodes.item(childIndex);
				//WriteDiagnostics( "Child Node: " + [contentElement.tagName,childIndex,childNode.nodeType,contentElement.childNodes.length]  ); 
				if (childNode.nodeType == 3 && childNode.length > 1) {
					pageBottom = GetPageBottom( pages, pageHeight );
					//WriteDiagnostics( "<B>SPLIT TEXT NODE</B>: " + [contentElement.tagName,contentElement.offsetHeight] );
					pageBottom = SplitText( contentElement, contentTop, contentBottom, pageBottom, pageHeight, pageHTML, pages );
					contentHeight = contentBottom;
					splitText = true;
					}
				}
			if (!splitText) { 
				//WriteDiagnostics( "PROCESSING CHILDREN: " + contentElement.children.length )
				for (var childIndex=0; childIndex<contentElement.children.length; childIndex++) {
					var child = contentElement.children[childIndex];
					var childTop = GetElementLocation(child).top;
					var childBottom = childTop + child.offsetHeight;
					if (childBottom < 0 || child.tagName.match(/(LINK|STYLE|SCRIPT|XML)/)) continue; 
					// Update in case pages were added!!!
					pageBottom = GetPageBottom( pages, pageHeight );
					//WriteDiagnostics( "SplitContent: CHILD " + [childIndex, childTop,child.offsetHeight,child.offsetWidth,contentHeight,child.tagName,"childTop",childTop,"childBottom",childBottom] );
					if (childBottom <= pageBottom) {
						// fits
						//WriteDiagnostics( "ADDED " + child.tagName + ": " + childBottom + ":" + child.innerText)
						contentHeight = childBottom;
						}
					else {
						// Wont' fit, try splitting Children
						//WriteDiagnostics( "No FIT, SPLITTING " + [child.tagName,childBottom, pageBottom]  )
						contentHeight = SplitContent( child, pageHeight, contentHeight, pages, pageHTML );
						}
					}
				}
			//WriteDiagnostics( "CHILDREN DONE" );
			if (contentHeight > 0 && isBody) AddPage( pageHTML, contentHeight, pages ) 
			}
		else {
			if (tagName.match(/(DIV|P|SPAN)/) && contentElement.innerText.length > 0) {
				pageBottom = SplitText( contentElement, contentTop, contentBottom, pageBottom, pageHeight, pageHTML, pages );
				contentHeight = contentBottom;
				}
			else if (contentElement.offsetHeight <= pageHeight ) { 
				// It all can fit on one page so dont' split, move to next
				//WriteDiagnostics( "<B>ORPHANED to next page</B>" + [tagName,contentHeight, pageHeight,"contentTop",contentTop,"contentBottom",contentBottom ] );
				AddPage( pageHTML, contentTop, pages );
				contentHeight = contentBottom;
				}
			else {
				// Split even though not optimum
				//WriteDiagnostics( "<B>SPLIT UNSPLITTABLE ORPHAN </B>" + [tagName,contentHeight , pageHeight,"contentTop",contentTop,"contentBottom",contentBottom ] );
				AddPage( pageHTML, pageBottom, pages );
				contentHeight = pageBottom + pageHeight;
				}
			}
		if (isBody) {
			// Add extra padding to pageHTML otherwise scrolltop won't work
			pages[pages.length-1].content += "<div style='height:" + 2*pageHeight + "'></div>";
			} 
		}
	catch (error) {
		window.status = ( "SplitContent: " + error.description );
		}
	return contentHeight;
	}


//-----------------------------------------------------------
// SplitText
//-----------------------------------------------------------
function SplitText( contentElement, contentTop, contentBottom, pageBottom, pageHeight, pageHTML, pages ) {
	try {
		var done = false;
		var max = 10;
		do {
			var lineHeight = Number(contentElement.style.lineHeight.replace(/[^0-9]/g,"") || kDefaultLineHeight);
			var spaceAvailable = (pageBottom - contentTop);
			var lines = Math.floor(spaceAvailable/lineHeight);
			splitContent = contentTop + lines*lineHeight + GetTopSpace(contentElement);
			//WriteDiagnostics( "<B>SPLIT ORPHAN: </b>" + [spaceAvailable,contentElement.tagName,splitContent,"contentTop:",contentTop,"contentBottom:",contentBottom] )
			AddPage( pageHTML, splitContent, pages );
			pageBottom = GetPageBottom( pages, pageHeight );
			//WriteDiagnostics( [contentBottom,splitContent,contentBottom - splitContent,pageHeight] )
			if (contentBottom - splitContent > pageHeight) {
				var kOverlapFudge = 0;
				contentTop = splitContent-kOverlapFudge;
				}
			else {
				done = true;
				}
			max -= 1;
			}
		while (!done && max>0);
		}
	catch (error) {
		window.status = ( "SplitText: " + error.description );
		}
	return pageBottom
	}


//-----------------------------------------------------------
// SetPageContent
//-----------------------------------------------------------
function SetPageContent( pageID, pageInfo ) {
	try {
		var contentElement = document.getElementById( pageID );
		var pageContentHeight = (pageInfo.pageEnd - pageInfo.pageStart);
		if (gCurrentSearch) HilightSearchResults( pageInfo );
		//contentElement.FileID = pageInfo.FileID;
		contentElement.RecordName = pageInfo.name;
		contentElement.innerHTML = pageInfo.content;
		contentElement.style.marginBottom = (CalculatePageContentHeight() - pageContentHeight);
		contentElement.style.height = pageContentHeight;
		contentElement.scrollTop = pageInfo.pageStart;
		gCurrentPageRecord[ pageID ] = pageInfo.currentRecord;
		gCurrentRecord = pageInfo.currentRecord;
		SetCookie_CS( kInitialRecordCookie, gCurrentRecord );
		if (pageID.match(/Left/)) { 
			LeftPageEdge.className = "LeftPageEdge" + (IsCoverPage() ? "NoTurn" : "");
			LeftPageEdge.onmouseover = (IsCoverPage() ?  "" : HandleOverPageEdge);
			LeftPageEdge.onmouseleave = (IsCoverPage() ? "" : HandleLeavePageEdge );
			}
		else {
			RightPageEdge.className = "RightPageEdge" + (IsLastPage() ? "NoTurn" : "");
			RightPageEdge.onmouseover = (IsLastPage() ?  "" : HandleOverPageEdge);
			RightPageEdge.onmouseleave = (IsLastPage() ? "" : HandleLeavePageEdge );
			}
		window.status = gCurrentRecord + ":" + gCurrentPage;
		document.all[pageID.replace("Content", "Header")].innerHTML = GetRecordCategory(gCurrentRecord, pageInfo.CID);
		AddToHistory( pageInfo.currentRecord );
		}
	catch( error ) {
		window.status = ( "SetPageContent: " + error.description + ", " + Pack(pageInfo));
		}
	}



//-----------------------------------------------------------
// IsCoverPage
//-----------------------------------------------------------
function IsCoverPage( ) {
	return gCurrentRecord == 1 && gCurrentPage == 0;
	}



//-----------------------------------------------------------
// IsLastPage
//-----------------------------------------------------------
function IsLastPage( ) {
	return gCurrentRecord == gTotalRecords && (gCurrentPage < gPages.length -1 && !gPages[gCurrentPage+1].content)
	}


//-----------------------------------------------------------
// HandleOverPageEdge
//-----------------------------------------------------------
function HandleOverPageEdge( ) {
	this.className = this.id + "Over";
	}


//-----------------------------------------------------------
// HandleLeavePageEdge
//-----------------------------------------------------------
function HandleLeavePageEdge( ) {
	this.className = this.id;
	}


//-----------------------------------------------------------
// PaginateContent
//-----------------------------------------------------------
function PaginateContent( contentElement ) {
	try {	
		//WriteDiagnostics("CURRENT: " + gCurrentRecord);
		var pageElement = document.getElementById( kRightPageID );
		var pageHeight = CalculatePageContentHeight();
		var contentHeight = contentElement.scrollHeight;
		var	pageCount = (contentHeight / pageHeight);
		var pageStart = 0;
		var pageHTML = contentElement.innerHTML;
		var newPages = new Array();
		if (gCurrentRecord == 1) gPages.push( kStartPage );
		var splitPages = new Array();
		SplitContent( contentElement, pageHeight, 0, newPages, pageHTML );
		switch (gCurrentDirection) {
			case 1:
				gPages = gPages.concat(newPages);
				if (gCurrentRecord == gTotalRecords) {
					gPages.push( kEndPage );
					gPages.push( kEndPage );
					}
				break;
			case -1:
				if (gCurrentRecord == 1) {
					newPages = [ kStartPage].concat(newPages);
					}
				gPages = newPages.concat(gPages);
				if (gPagesAdded == 0 && newPages.length >= 2) { // 2 pages filled on first pass
					gCurrentPage = (gCurrentPage == -1 ? 1 : 0) + newPages.length - 2;
					} 
				else if (gPagesAdded == 0 && newPages.length == 1) { // 1 page on first pass
					// dont' adjust
					}
				else if (gPagesAdded > 0 && newPages.length > 0) { // Second pass
					// gCurrentPage addition not needed since gPagesAdded is adjusted for this case
					//gCurrentPage = gPagesAdded + newPages.length + (gCurrentPage == -1 ? 1 : 0) - 2;
					gCurrentPage = gPagesAdded + newPages.length  - 2;
					} 
				break;
			}
		gPagesAdded += newPages.length;
		}
	catch (error) {
		window.status = ( "PaginateContent: " + error.description );
		}
	}



//-----------------------------------------------------------
// GetRecordURL
//-----------------------------------------------------------
function GetRecordURL( recordIndex ) {
	var recordURL = "";
	try {
		if (recordIndex<1) recordIndex = 1; 
		recordURL = kRecordURL + recordIndex + "&pageWidth=" + CalculatePageContentWidth() +  "&pageHeight=" + CalculatePageContentHeight();
		recordURL += "&view=" + gCurrentView + "&newWindow=1" + "&search=" + gCurrentSearch;
		if (gFiltered)  recordURL += "&filtered=1";
		if (recordIndex == 1) recordURL += "&searchPage=" + gIsSearchPage;
		}
	catch (error) {
		window.status = ( "GetRecordURL: " + error.description );
		}
	return recordURL;
	}




//-----------------------------------------------------------
// UpdateLoadingProgress
//-----------------------------------------------------------
function UpdateLoadingProgress( ) {
	LoadingProgress.innerText += ".";
	}


//-----------------------------------------------------------
// ReadIndex
//-----------------------------------------------------------
function ReadIndex( indexLoaded ) {
	try {
		var frame = document.frames[kContentIndexID];
		if (!indexLoaded) { 
			document.body.style.cursor = "wait";
			RightPageContent.innerHTML = "<center><b>Loading....</b></center>";
			frame.document.location.href = kIndexURL + "?view=" + gCurrentView + "&search=" + gCurrentSearch + "&searchPage=" + gIsSearchPage + (gFiltered ? "&filtered=1" : "");
			}
		else {
			var contentElement = frame.document.body;
			gRecordIndex = new Array();
			try {
				var pageContent = unescape(contentElement.innerText);
				// Strip Scritp tags that certain browser return
				// <script language=javascript>postamble()</script>
				pageContent = pageContent.replace( /<script>[^<]+<\/script>/g, "" );
				gTotalRecords = eval( pageContent );
				}
			catch (error) {
				alert( "Sorry, unable to open the Photo Album. The data returned was: " + pageContent );
				}
			if (gTotalRecords > 0 ) {
				kEndPage.currentRecord = gTotalRecords;
				Book.style.display = "";
				Loading.style.display = "none";
				window.clearInterval(gLoadingTimer);
				if (gOpenToTOC) gInitialRecord = 1;
				if (!gInitialRecord) gInitialRecord = (gCurrentSearch ? 2 : GetCookie_CS( kInitialRecordCookie ));
				if (gInitialRecord == 1) gInitialRecord = 0; 
				Initialize();
				ViewContents(false); 
				gIndexLoaded = true;
				}
			else {
				ConnectionError(frame.document.location.href);
				}
			}
		}
	catch (error) {
		window.status = ( "ReadIndex: " + error.description );
		}
	}


//-----------------------------------------------------------
// ConnectionError
//-----------------------------------------------------------
function ConnectionError( url ) {
	window.status = ( "Sorry, unable to connect to " + location.host + ": " +  url);
	}


//-----------------------------------------------------------
// GetNextRecord
//-----------------------------------------------------------
function GetNextRecord( recordIndex ) {
	try {
		if (gRequestedPage) {
			window.status = "Waiting on page: " + gRequestedPage;
			return;
			}	 
		var pageElement = document.getElementById( kLeftPageID );
		var recordURL = GetRecordURL(recordIndex);
		gRequestedPage = recordURL;
		var frame = document.frames[kContentBufferID];
		document.all[kContentBufferID].width = Math.round(CalculatePageContentWidth());
		window.status = "Load " + recordIndex;
		frame.document.location.href = recordURL;
		}
	catch( error ) {
		window.status = ( "GetNextRecord: " + error.description );
		}
	}


//-----------------------------------------------------------
// GetCurrentViewName
//-----------------------------------------------------------
function GetCurrentViewName( ) {
	var viewName = "";
	try {
		viewName = (gViewsByID[gCurrentView] ? gViewsByID[gCurrentView].Name : gCurrentView);
		}
	catch (error) {
		window.status = ( "viewName: " + error.description );
		}
	return viewName;
	}


//-----------------------------------------------------------
// GetRecordCategory
//-----------------------------------------------------------
function GetRecordCategory( recordIndex, categoryID ) {
	var categoryName = "";
	try {
		if (recordIndex == 1) {
			categoryName = (gCurrentSearch ? "Search" : "Table of Contents");
			}
		else if (gCurrentSearch) {
			categoryName = "Projects containing the text <b>" + gCurrentSearch + "</b>";
			} 
		else {
			var viewName = GetCurrentViewName();
			categoryName = gCategoryNamesById["CID" + categoryID ] || "";
			if (!categoryName || categoryName == "undefined") return ""; 
			if (categoryName && viewName) categoryName = viewName + ": " + categoryName;
			}
		}
	catch (error) {
		window.status = ( "GetRecordCategory: " + error.description );
		}
	return categoryName;
	}


//-----------------------------------------------------------
// GetPages		
//-----------------------------------------------------------
function GetPages( turnedPage ) {
	try {
		gCurrentRecord += gCurrentDirection*1;
		if (gCurrentRecord < 1) gCurrentRecord = 1;
		if (gCurrentRecord > gTotalRecords) gCurrentRecord = gTotalRecords;
		GetNextRecord(gCurrentRecord);
		}
	catch( error ) {
		window.status = ( "GetPages: " + error.description );
		}
	}



//-----------------------------------------------------------
// DisplayPages
//-----------------------------------------------------------
function DisplayPages( ) {
	try {
		HideToolTip();
		Wait(true);
		switch (gCurrentDirection) {
			case 1:
				SetPageContent( kLeftPageID, gPages[gCurrentPage] );
				SetPageContent( kRightPageID, gPages[gCurrentPage+1] );
				break;
			case -1:
				SetPageContent( kRightPageID, gPages[gCurrentPage+1] );
				SetPageContent( kLeftPageID, gPages[gCurrentPage] );
				break;
			}
		LeftPageFooter.style.display = (gCurrentRecord <= 1 && gCurrentPage == 0 ? "none" : "");
		LeftPageHeader.style.display = (gCurrentRecord <= 1 && gCurrentPage == 0  ? "none" : "");
		AdjustPageEdges();
		gTurningPage = false;
		}
	catch (error) {
		window.status = ( "DisplayPages: " + error.description );
		}
	}


//-----------------------------------------------------------
// AdjustPageEdges
//-----------------------------------------------------------
function AdjustPageEdges( ) {
	try {
		var pagesRead = GetBookThickness(gCurrentRecord);
		var pageRemaining =  GetBookThickness(gTotalRecords - gCurrentRecord);
		PagesRead.style.width = pagesRead;
		PagesRemaining.style.width = pageRemaining;
		PagesReadSectionTabs.style.width = pagesRead;
		PagesRemainingSectionTabs.style.width = pageRemaining;
		gPagesRemainingSectionDividers.style.pixelLeft = -pagesRead;
		}
	catch (error) {
		window.status = ( "AdjustPageEdges: " + error.description );
		}
	}


//-----------------------------------------------------------
// AddSectionDividers
//-----------------------------------------------------------
function AddSectionDividers( ) {
	try {
		var bookThickness = GetBookThickness();
		var kMinSectionWidth = Math.max( 2, GetBookThickness(bookThickness/gCategories.length) );
		var kTabWidth = (gCurrentView == "gallery" ? 5 : 10);
		var kTabSpacing = 2;
		var pageHeight = CalculatePageHeight();
		var tabHeight = kTabWidth + kTabSpacing;//Math.floor(pageHeight/gCategories.length) - kTabSpacing;
		var tabStart = 0;
		var sectionPageStart = 0;
		var columnDiv = "";
		if (gPagesRemainingSectionDividers) {
			while(gPagesRemainingSectionDividers.children.length > 0) {
				gPagesReadSectionDividers.removeChild(gPagesReadSectionDividers.children[0]);
				gPagesRemainingSectionDividers.removeChild(gPagesRemainingSectionDividers.children[0]);
				}
			PagesReadSectionTabs.style.height = pageHeight;
			PagesRemainingSectionTabs.style.height = pageHeight;
			}
		else {
			gPagesReadSectionDividers = document.createElement("DIV");
			gPagesReadSectionDividers.id = "PagesReadSectionDividers";
			gPagesReadSectionDividers.style.position = "relative";
			gPagesReadSectionDividers.style.width = bookThickness;
			gPagesRemainingSectionDividers = gPagesReadSectionDividers.cloneNode();
			gPagesRemainingSectionDividers.id = "PagesRemainingSectionDividers";
			PagesRemainingSectionTabs.appendChild(gPagesRemainingSectionDividers);
			PagesRemainingSectionTabs.style.width = bookThickness;
			PagesRemainingSectionTabs.style.height = pageHeight;
			PagesReadSectionTabs.appendChild(gPagesReadSectionDividers);
			PagesReadSectionTabs.style.width = 0;
			PagesReadSectionTabs.style.height = pageHeight;
			}
		var pagesReadDividerColumn = "";
		var pagesRemainingDividerColumn = "";
		var totalDividerHeight = 0;
		return;
		for (var item=0; item<gCategories.length; item++) {
			if (!pagesReadDividerColumn) {
				pagesReadDividerColumn = document.createElement("DIV");
				pagesRemainingDividerColumn = document.createElement("DIV");
				pagesReadDividerColumn.style.styleFloat  = (item < gCategories.length-1 ? "left" : "right" );
				pagesRemainingDividerColumn.style.styleFloat  = (item < gCategories.length-1 ? "left" : "right" );
				gPagesReadSectionDividers.appendChild(pagesReadDividerColumn);
				gPagesRemainingSectionDividers.appendChild(pagesRemainingDividerColumn);
				}
			var category = gCategories[item];
			var categoryDiv = document.createElement("DIV");
			var tabLeftMargin = Math.min( bookThickness-kMinSectionWidth, (tabStart) );
			categoryDiv.className = "Section";
			categoryDiv.style.height = tabHeight;
			categoryDiv.style.width = Math.max(GetBookThickness(category.Total),kMinSectionWidth);
			categoryDiv.style.top = item*kTabSpacing;
			categoryDiv.style.marginLeft = tabLeftMargin;
			categoryDiv.style.marginBottom = kTabSpacing;
			categoryDiv.id = category.ID;
			categoryDiv.onclick = HandleSectionDividerClick;
			categoryDiv.onmouseover = ShowSectionCategory;
			categoryDiv.onmouseleave = HideToolTip;
			//gPagesReadSectionDividers.appendChild(categoryDiv);
			pagesReadDividerColumn.appendChild(categoryDiv);
			categoryDiv = categoryDiv.cloneNode();
			categoryDiv.onclick = HandleSectionDividerClick;
			categoryDiv.onmouseover = ShowSectionCategory;
			categoryDiv.onmouseleave = HideToolTip;
			//gPagesRemainingSectionDividers.appendChild(categoryDiv);
			pagesRemainingDividerColumn.appendChild(categoryDiv);
			totalDividerHeight += tabHeight;
			tabStart =  Math.floor(GetPageThickness()*sectionPageStart*kScreenDpiX);
			sectionPageStart += category.Total;
			if (pagesReadDividerColumn.offsetHeight + tabHeight > pageHeight) {
				pagesReadDividerColumn = "";
				totalDividerHeight = 0;
				tabStart = 0;
				sectionPageStart = 0;
				}
			}
		}
	catch (error) {
		alert( "AddSectionDividers: " + error.description );
		}
	}



//-----------------------------------------------------------
// AddToHistory
//-----------------------------------------------------------
function AddToHistory( recordIndex ) {
	try {
		if (gBrowsingHistory) return; 
		if (gHistoryIndex < gHistory.length-1 && gHistoryIndex > -1)  gHistory = gHistory.slice( 0, gHistoryIndex );
		if (recordIndex == gHistory[gHistory.length-1]) return; 
		gHistory.push(recordIndex);
		gHistoryIndex = gHistory.length - 1;
		GoBack[1].className = GoBack[0].className = "Enabled";
		GoBack[1].disabled = GoBack[0].disabled = false;
		}
	catch (error) {
		window.status = ( "AddToHistory: " + error.description );
		}
	
	}


//===========================================================
// HandleViewHistory
//===========================================================
function HandleViewHistory( direction ) {
	try {
		gBrowsingHistory = true;
		var historyIndex = gHistoryIndex + direction;
		if (historyIndex >= 0 && historyIndex < gHistory.length) {
			gHistoryIndex = historyIndex;
			HandleViewRecord( gHistory[ gHistoryIndex ] );
			} 
		GoForward[1].className = GoForward[0].className = (gHistoryIndex == gHistory.length - 1 ? "Disabled" : "Enabled");
		GoBack[1].className = GoBack[0].className = (gHistoryIndex == 0 ? "Disabled" : "Enabled");
		GoForward[1].disabled = GoForward[0].disabled = (GoForward[1].className == "Disabled" ? true : false); 
		GoBack[1].disabled = GoBack[0].disabled = (GoBack[1].className == "Disabled" ? true : false); 
		}
	catch (error) {
		window.status = ( "HandleViewHistory: " + error.description );
		}
	}



//===========================================================
// ShowSectionCategory
//===========================================================
function ShowSectionCategory( ) {
	try {
		var element = window.event.srcElement;
		var elementLocation = GetElementLocation(element).top;
		var isLeftSide = element.parentElement.parentElement.id == "PagesRemainingSectionDividers";
		var categoryName = gCategoryNamesById["CID"+element.id];
		BookToolTip.innerText = categoryName;
		BookToolTip.style.display = "block";
		BookToolTip.style.top = window.event.clientY + 16;
		if (isLeftSide) { 
			BookToolTip.style.left = window.event.clientX - BookToolTip.offsetWidth;
			}
		else {
			BookToolTip.style.left = window.event.clientX;
			}
		}
	catch( error ) {
		window.status = ( "ShowSectionCategory: " + error.description );
		}
	}


//===========================================================
// HideToolTip
//===========================================================
function HideToolTip( ) {
	BookToolTip.style.display = "none";
	}


//===========================================================
// HandleSectionDividerClick
//===========================================================
function HandleSectionDividerClick( ) {
	try {
		window.event.cancelBubble = true;	
		TurnToCategory( window.event.srcElement.id );
		}
	catch( error ) {
		window.status = ( "HandleSectionDividerClick: " + error.description );
		}
	}


//===========================================================
// ViewContents
//===========================================================
function ViewContents( forSearch ) {
	try {
		gIsSearchPage = (forSearch ? 1 : 0);
		HandleViewRecord( 1 );
		}
	catch( error ) {
		window.status = ( "ViewContents: " + error.description );
		}
	}


//===========================================================
// TurnToCategory
//===========================================================
function TurnToCategory( categoryID ) {
	try {
		var recordIndex = 0;
		for (var item=0; item<gCategories.length; item++) {
			var category = gCategories[item];
			if (category.ID == categoryID) {
				recordIndex = category.RID;
				break;
				}
			}
		if (recordIndex) HandleViewRecord(recordIndex);
		}
	catch( error ) {
		window.status = ( "TurnToSection: " + error.description );
		}
	}


//===========================================================
// TurnToNextSection
//===========================================================
function TurnToNextSection( ) {
	try {
		var recordIndex = 0;
		for (var item=0; item<gCategories.length; item++) {
			var category = gCategories[item];
			if (category.RID >= gCurrentRecord) {
				item += (category.RID == gCurrentRecord ? 1 : 0);
				item = Math.min(gCategories.length-1,item);
				category = gCategories[item];
				if (category) recordIndex = category.RID;
				break;
				}
			}
		if (recordIndex) HandleViewRecord(recordIndex);
		}
	catch( error ) {
		window.status = ( "TurnToNextSection: " + error.description );
		}
	}


//===========================================================
// TurnToPreviousSection
//===========================================================
function TurnToPreviousSection( ) {
	try {
		var recordIndex = 0;
		for (var item=0; item<gCategories.length; item++) {
			var category = gCategories[item];
			if (category.RID >= gCurrentRecord) {
				// use previous category to this
				item -= (category.RID == gCurrentRecord ? 1 : 2);
				item = Math.max(0,item);
				category = gCategories[item];
				if (category) recordIndex = category.RID;
				break;
				}
			}
		if (recordIndex) HandleViewRecord(recordIndex);
		}
	catch( error ) {
		window.status = ( "TurnToNextSection: " + error.description );
		}
	}


//-----------------------------------------------------------
// UpdateTOCLoadingTimer
//-----------------------------------------------------------
function UpdateTOCLoadingTimer( ) {
	TOCLoadingProgress.innerText += ".";
	}


//===========================================================
// HandleViewRecord
//===========================================================
function HandleViewRecord( recordIndex, isIndex ) {
	try {
		if (isIndex) {
			SetCookie_CS( "IndexPage", gCurrentPage );
			}
		gCurrentRecord = recordIndex-1;
		gCurrentDirection = 1;
		ClearPageBuffer(gIsSearchPage);
		if (gCurrentRecord == 0 && gTableOfContents.length > 0) {
			gPages.push(kStartPage);
			gPages = gPages.concat(gTableOfContents); 
			gCurrentPage = 0;//(GetCookie_CS( "IndexPage" ) || 0);
			}
		else if (gCurrentRecord == 0) {
			document.body.style.cursor = "wait";
			}
		if (HasPages()) {
			DisplayPages();
			} 
		else {
			GetPages();
			}
		}
	catch( error ) {
		window.status = ( "HandleViewRecord: " + error.description );
		}
	}



//===========================================================
// ShowTip
//===========================================================
function ShowTip( element ) {
	try {
		var elementLocation = GetElementLocation(element);
		BookToolTip.innerText = element.children[0].getAttribute( "tip" );
		BookToolTip.style.display = "block";
		BookToolTip.style.top = elementLocation.top - BookToolTip.offsetHeight - 1;
		BookToolTip.style.left = elementLocation.left - BookToolTip.offsetWidth/2;
		element.onmouseleave = HideToolTip;
		}
	catch( error ) {
		window.status = ( "ShowTip: " + error.description );
		}
	}


//===========================================================
// Wait
//===========================================================
function Wait( clearWait ) {
	var cursor = clearWait ? "" : "wait";
	LeftPageEdge.style.cursor = LeftPageContent.style.cursor = LeftPage.style.cursor = cursor;	
	RightPageEdge.style.cursor = RightPageContent.style.cursor = RightPage.style.cursor = cursor;
	document.body.style.cursor = cursor;
	}


//===========================================================
// HandleTurnPage
//===========================================================
function HandleTurnPage( direction ) {
	try {
		gTurningPage = true;
		if (IsLastPage() && direction > 0) return; 
		if (IsCoverPage() && direction < 0) return; 
		gCurrentPage += direction*2;
		// If we turned back our current page is greater than -2, there's one page already remaining!
		gPagesAdded = (gCurrentPage == -1 ? 1 : 0);
		gBrowsingHistory = false;
		gCurrentDirection = direction;
		LeftPage.style.cursor = RightPage.style.cursor = "wait";
		if (HasPages()) {
			DisplayPages();
			} 
		else {
			// If we turned back our current page is greater than -2, there's one page already remaining! 
			//gPagesAdded = 0;
			gPagesAdded = (gCurrentPage == -1 ? 1 : 0);
			// Adjust current record based on direction!!!
			var prev = gCurrentRecord; 
			gCurrentRecord = Number( gCurrentPageRecord[ gCurrentDirection == 1? kRightPageID : kLeftPageID ] || gCurrentRecord );
			GetPages();
			}
		}
	catch( error ) {
		window.status = ( "HandleTurnPage: " + error.description );
		}
	}



//===========================================================
// HandleTurnToPage
//===========================================================
function HandleTurnToPage( element ) {
	try {
		var isTurnBack = element.id.match(/PagesRead/);
		var records = parseInt(((isTurnBack ? window.event.offsetX : window.event.srcElement.offsetWidth - window.event.offsetX)/kScreenDpiX)/GetPageThickness());
		var pages = 0;
		gPagesAdded = 0;
		gBrowsingHistory = false;
		// 10OCT2004 RFM - changed from what's working on anitasrecipes - not sure why. Probbaly due to the removal of section tabs		
		gCurrentRecord = (isTurnBack ? records : gTotalRecords - records);
		HandleViewRecord( gCurrentRecord );
		}
	catch( error ) {
		window.status = ( "HandleTurnToPage: " + error.description );
		}
	}



//===========================================================
// HandleKeyDown
//===========================================================
function HandleKeyDown( ) {
	try {
		switch( event.keyCode ) {
			case 39:
				if (!gTurningPage) {
					if (event.shiftKey) {
						TurnToNextSection();
						}
					else {
						HandleTurnPage(1);
						}
					}
				break;
			case 37:
				if (!gTurningPage) {
					if (event.shiftKey) {
						TurnToPreviousSection();
						}
					else {
						HandleTurnPage(-1);
						}
					}
				break;
			case 36:	// Home
				if (!gTurningPage) ViewContents();
				break;
			case 33:	// Next Section
				break;
			case 34:	// Previous Section
				break;
			}
		}
	catch( error ) {
		window.status = ( "HandleKeyDown: " + error.description );
		}
	}


//===========================================================
// EmailPage
//===========================================================
function EmailPage( pageElement ) {
	try {
		var recordID = gCurrentPageRecord[ pageElement.id ];
		command = unescape( gEmailPageCommand ).replace( "{{pageURL}}", escape(GetRecordURL(recordID)) );
		command = command.replace( "{{SUBJECT}}", "Recipe: " + pageElement.RecordName );
		eval( command );
		}
	catch( error ) {
		window.status = ( "PrintPage: " + error.description );
		}
	}


//===========================================================
// Search
//===========================================================
function Search( ) {
	try {
		gHandleSearch = true;
		ViewContents(true);
		}
	catch( error ) {
		window.status = ( "Search: " + error.description );
		}
	}


//===========================================================
// Bookmark
//===========================================================
function Bookmark( pageElement ) {
	try {
		var recordID = gCurrentPageRecord[ pageElement.id ];
		window.external.AddFavorite(GetRecordURL(recordID), document.title.split(":")[0] + "- " + pageElement.RecordName );
		}
	catch( error ) {
		window.status = ( "Bookmark: " + error.description );
		}
	}


//===========================================================
// PrintPage
//===========================================================
function PrintPage( pageElement ) {
	try {
		var recipeWindow = OpenPage(pageElement);
		recipeWindow.print();
		}
	catch( error ) {
		window.status = ( "PrintPage: " + error.description );
		}
	}


//===========================================================
// OpenPage
//===========================================================
function OpenPage( pageElement ) {
	var recipeWindow = "";
	try {
		var recordID = gCurrentPageRecord[ pageElement.id ];
		if (recordID == 1) return; 
		var kScrollBarWidth = 18;
		recipeWindow = window.open( GetRecordURL(recordID), "Page" + recordID, "top=100,left=100,width=" + (CalculatePageContentWidth() + kScrollBarWidth) + ",height=" + CalculatePageHeight() + ",resizable=1,scrollbars=1" );
		recipeWindow.focus();
		}
	catch( error ) {
		window.status = ( "OpenPage: " + error.description );
		}
	return recipeWindow;
	}