//****************************************************************************************
//
//	document.js
//
//	Manages the document display 
//
//	Depends On:
//				
//
//	Copyright: 	David Horne, Tuross Technologies Australia P/L, 2009.
//				dkhorne@bigpond.net.au
//
//****************************************************************************************

//****************************************************************************************
//	DataSources
//****************************************************************************************


//****************************************************************************************
//	Support Data and functions
//****************************************************************************************
//	var Zoom = [50, 60, 80, 90, 100];
	
	var FrameworkOptions = 
		[
			{'ID': '1-page', 'Name': 'Single Page', 'Mode': 'Pages', 'Pages': 1, 'Flags': {'Navigation': true, 'Zoom': true}, 'Image': 'navigation/1page.gif'},
			{'ID': '2-page', 'Name': 'Double Page', 'Mode': 'Pages', 'Pages': 2, 'Flags': {'Navigation': true, 'Zoom': true}, 'Image': 'navigation/2page.gif'},
			{'ID': 'thumbs', 'Name': 'Thumbnails', 'Mode': 'Thumbs', 'Pages': -1, 'Flags': {'Navigation': false, 'Zoom': false}, 'Image': 'navigation/thumbs.gif'},
			{'ID': 'bookmarks', 'Name': 'Table of Contents', 'Mode': 'Bookmarks', 'Pages': -1, 'Flags': {'Navigation': false, 'Zoom': false}, 'Image': ''},
			{'ID': 'results', 'Name': 'Search Results', 'Mode': 'Results', 'Pages': -1, 'Flags': {'Navigation': false, 'Zoom': false, 'Image': 'navigation/search-results.gif'}}
		]
		
	var FrameworkHTML =					"<table name='framework' id='framework' cellpadding='0' cellspacing='0'></table>"		

	var PageHTML =						"<img src='" + constants.appPath + "images/blank.gif' id='image-[PAGENUMBER]' class='page-image' /><div id='caption-[PAGENUMBER]' class='page-caption'></div>";

	var ThumbHTML =						"<a id='link-[PAGENUMBER]'><img src='" + constants.appPath + "images/blank.gif' id='image-[PAGENUMBER]' class='page-image' /><div id='caption-[PAGENUMBER]' class='page-caption'></div></a>";

	var TitleHTML =						"[TITLE]";

	var BookmarkHTML =					"<div class='bookmark-list'><a id='link-[PAGENUMBER]'><span id='content-[PAGENUMBER]' class='page-caption'></span></a></div>";

	var ResultsHTML =					"<div class='block search-results'>" + 
										"	<div class='search-page block-item'>" + ThumbHTML + "</div>" + 
										"	<div id='content-[PAGENUMBER]' class='search-content block-item'></div>" + 
										"</div>";

	var NavigationSearchHTML =			"<input type='text' id='search-text' class='search-text' title='Search for text in the document' />&nbsp;<button name='search-button' class='search' title='Search for text in the document' onclick='[DOCUMENTOBJECT].Navigate(\"Search\")'></button>";
	
//	var NavigationBookmarkHTML =		"<select name='bookmark-list' class='category-list' title='Navigate to a bookmark in the document' onchange='[DOCUMENTOBJECT].Navigate(\"bookmark\", this.value)'><option value='-1'>Please select...</option></select>";
	var NavigationBookmarkHTML =		"<select name='bookmark-list' class='category-list' title='Navigate to a bookmark in the document' onchange='[DOCUMENTOBJECT].Navigate(\"bookmark\", this.value)'><option value='-1'>Please select...</option>[OPTIONS]</select>";
	
	var NavigationInternalLinksHTML = "";
	
	var NavigationExternalLinksHTML = "";
	
	var NavigationZoomHTML =			"<button id='navigation-zoom-more' class='nav-zoom-more' title='Zoom in' onclick='[DOCUMENTOBJECT].Zoom(1)'></button>" + 
										"<img id='navigation-zoom-display' class='nav-zoom block' src='" + constants.appPath + "images/zoom_3.gif'>" + 
										"<button id='navigation-zoom-less' class='nav-zoom-less' title='Zoom out' onclick='[DOCUMENTOBJECT].Zoom(-1)'></button>"

	var NavigationLayoutHTML =			"";
	for (var i = 0; i < constants.LayoutOptions.length; i++) 
		NavigationLayoutHTML +=			"<button id='navigation-layout-" + constants.LayoutOptions[i] + "' class='nav-" + FrameworkOptions[constants.LayoutOptions[i]].ID + "' title='" + FrameworkOptions[constants.LayoutOptions[i]].Name + "' onclick='[DOCUMENTOBJECT].Layout(" + constants.LayoutOptions[i] + ")'></button>";
	
	var NavigationPageHTML =			"<button id='navigation-first' class='nav-first' title='First page' onclick='[DOCUMENTOBJECT].Navigate(\"first\")'></button>" + 
										"<button id='navigation-prev' class='nav-prev' title='Previous page' onclick='[DOCUMENTOBJECT].Navigate(\"prev\")'></button>" + 
										"<button id='navigation-next' class='nav-next' title='Next page' onclick='[DOCUMENTOBJECT].Navigate(\"next\")'></button>" + 
										"<button id='navigation-last' class='nav-last' title='Last page' onclick='[DOCUMENTOBJECT].Navigate(\"last\")'></button>";

	var NavigationPrintHTML =			"<button id='navigation-first' class='print' title='Print Current Page(s)' onclick='[DOCUMENTOBJECT].PrintDocument()'></button>";

		

//****************************************************************************************
//	Framework object - draws the Framework for a given Framework option
//****************************************************************************************
	function Framework() {
	
//*********************************
//	Properties
		this.Document;									//	The document associated with this Framework.

		this.Option = FrameworkOptions[1];				//	Default Framework
		this.CurrentFramework = null;					//	Current Framework object
		
		this.CurrentMode = "";							//	Description of current framework mode

//*********************************
//	Methods
		this.Mode = Framework_Mode;						//	Returns the current mode of the Framework
		this.Set = Framework_Set;						//	Resets certain elements of the framework
		this.Draw = Framework_Draw;						//	Draws the page Framework
		this.Navigation = Framework_Navigation;			//	Draws the page navigation
		this.AddPage = Framework_AddPage				//	Adds a page to the Framework
		this.AddTitle = Framework_AddTitle				//	Adds a title to the framework
		this.Display = Framework_Display;				//	Displays the image at the given page
		this.DisplayPage = Framework_DisplayPage;		//	Displays the given page
		this.HidePage = Framework_HidePage;				//	Hides the image at the given page
	}

//******************************************************************
//	Returns the current mode of the framework
//******************************************************************
	function Framework_Mode() {
		return this.Option.Mode.toLowerCase();
	}

//******************************************************************
//	Sets the Framework option and draws it
//******************************************************************
	function Framework_Set() {
	}
	
//******************************************************************
//	Sets elements of the Framework
//******************************************************************
	function Framework_Set(Action, Value) {

		switch (Action.toLowerCase()) {
			
			case "zoom":
				var ZoomElement = DOM.getElementById("navigation-zoom-display");
				if (ZoomElement != null)
					ZoomElement.src = ZoomElement.src.replace(/zoom_./g, "zoom_" + this.Document.CurrentZoom);
				break;
				
			case "bookmarks":
				var BookmarkOption;

				if ((Value.length) && (Value.length > 0)) {
					var Options = "";
					for (var j = 0; j < Value.length; j++)
						Options += "<option value='" + j + "'>" + Value[j].Title.replace(/~/g, "&nbsp;&nbsp;&nbsp;") + "</option>";
					DOM.setInnerHTML("navigation-bookmark", NavigationBookmarkHTML.replace(/\[DOCUMENTOBJECT\]/g, this.Document.ObjectName).replace(/\[OPTIONS\]/g, Options));
				} else {
					DOM.setInnerHTML("navigation-bookmark", "");
				}
				break;

			case "selectedbookmark":
				var selectedBookmark = -1;
				for (var i = 0; i < this.Document.Bookmarks.length; i++) {				
					if (this.Document.Bookmarks[i].Actions[0].Page <= (this.Document.CurrentPage + 1)) 
						selectedBookmark = i; 
					else
						break;
				}
				
				var BookmarkList = DOM.getElementsByName("bookmark-list");
				for (var i = 0; i < BookmarkList.length; i++)
					BookmarkList[i].selectedIndex = (selectedBookmark + 1);
				break;
				
		}
	
	}
	
//******************************************************************
//	Draws the page Framework framework at the target specified
//******************************************************************
	function Framework_Draw() {
		DOM.setInnerHTML("display-document", FrameworkHTML.replace(/\[FRAMEWORKID\]/g, this.Option.ID));
		this.CurrentFramework = DOM.getElementById("framework");

		var DisplayPages;
		var PagesPerRow;
		switch (this.Mode()) {
			case "thumbs":
				DisplayPages = this.Document.Pages.length;
				PagesPerRow = constants.PagesPerRow;
				break;
			
			case "bookmarks":
				this.AddTitle(this.Option.Name);
				DisplayPages = this.Document.Bookmarks.length;
				PagesPerRow = 1;
				break;
			
			case "results":
				this.AddTitle(this.Option.Name);
				DisplayPages = this.Document.Results.length;
				PagesPerRow = 1;
				break;
			
			case "pages":
				DisplayPages = this.Option.Pages;
				PagesPerRow = 2;
				break;
		}

		var NewRow;
		var IsCover;
		for (var i = 0; i < DisplayPages; i++) {
			if (i % PagesPerRow == 0)
				NewRow = this.CurrentFramework.insertRow(-1);

			IsCover = ((i == 0) || (i == (DisplayPages - 1)))

			this.AddPage(NewRow, i, IsCover);
		}
			
		this.Navigation();
	}
	
//******************************************************************
//	Draws the page navigation type at the target specified
//******************************************************************
	function Framework_Navigation() {
		var HTML = NavigationSearchHTML;
		if ((this.Document != null) && (this.Document.Results != null) && (this.Document.Results.length > 0))
			HTML += "&nbsp<button class='nav-search-results' title='" + FrameworkOptions[constants.SearchOption].Name + "' onclick='[DOCUMENTOBJECT].Navigate(\"SearchAgain\")'>&nbsp;</button>";

		DOM.setInnerHTML("navigation-search", HTML.replace(/\[DOCUMENTOBJECT\]/g, this.Document.ObjectName));

		DOM.setInnerHTML("navigation-bookmark", NavigationBookmarkHTML.replace(/\[DOCUMENTOBJECT\]/g, this.Document.ObjectName));

		DOM.setInnerHTML("navigation-internal-links", (this.Option.Flags.Navigation ? NavigationInternalLinksHTML : ""));
		DOM.setInnerHTML("navigation-external-links", (this.Option.Flags.Navigation ? NavigationExternalLinksHTML : ""));

		DOM.setInnerHTML("navigation-zoom", (this.Option.Flags.Zoom ? NavigationZoomHTML.replace(/\[DOCUMENTOBJECT\]/g, this.Document.ObjectName) : ""));

		DOM.setInnerHTML("navigation-layout", NavigationLayoutHTML.replace(/\[DOCUMENTOBJECT\]/g, this.Document.ObjectName));

		DOM.setInnerHTML("navigation-page", (this.Option.Flags.Navigation ? NavigationPageHTML.replace(/\[DOCUMENTOBJECT\]/g, this.Document.ObjectName) : ""));

   		DOM.setInnerHTML("navigation-print", ((this.Mode() != "thumbs") ? NavigationPrintHTML.replace(/\[DOCUMENTOBJECT\]/g, this.Document.ObjectName) : ""));
		
		this.Set("Zoom");
		this.Set("Bookmarks", this.Document.Bookmarks);
		this.Set("SelectedBookmark");
	}
	
//******************************************************************
//	Adds a page to the framework
//******************************************************************
	function Framework_AddPage(Row, Number, IsCover) {
		var Page = Row.insertCell(-1);
		Page.id = "page-" + Number;
		Page.className = "page " + this.Mode();
		
		switch (this.Mode()) {
			case "thumbs":
				if (!IsCover)
					Page.className += " " + (Number % 2 == 0 ? "even" : "odd");

				Page.innerHTML = ThumbHTML.replace(/\[PAGENUMBER\]/g, Number);
				break;
				
			case "bookmarks":
				Page.innerHTML = BookmarkHTML.replace(/\[PAGENUMBER\]/g, Number);
				break;
				
			case "pages":
				Page.innerHTML = PageHTML.replace(/\[PAGENUMBER\]/g, Number);
				break;
				
			case "results":
				Page.innerHTML = ResultsHTML.replace(/\[PAGENUMBER\]/g, Number);
				break;
		}
	}
	
//******************************************************************
//	Adds a title to the framework
//******************************************************************
	function Framework_AddTitle(Title) {
		var TitleElement = this.CurrentFramework.insertRow(-1).insertCell(-1);
		TitleElement.id = "title";
		TitleElement.className = "title";
		TitleElement.innerHTML = TitleHTML.replace(/\[TITLE\]/g, Title);
	}
	
//******************************************************************
//	Displays the image at the given page
//******************************************************************

	function Framework_Display() {

		var TheElement;
		var iPage;
		
		if (!this.Document.Loaded) {
			message.raise("Document", "Cannot display document.", "Document not loaded.", false);
			return;
		}

		document.title = this.Document.ScreenTitle();

		switch (this.Mode()) {
			case "thumbs":
				for (var i = 0; i < this.Document.Pages.length; i++) 
					this.DisplayPage(i, this.Document.Pages[i], "", true, (i == this.Document.CurrentPage));
				break;

			case "bookmarks":
				var Page;
				for (var i = 0; i < this.Document.Bookmarks.length; i++) {
					Page = this.Document.Bookmarks[i].Actions[0].Page - 1;
					this.DisplayPage(i, this.Document.Pages[Page], this.Document.Bookmarks[i].Title.replace(/~/g, "&nbsp;&nbsp;&nbsp;"), true, (Page == this.Document.CurrentPage));
				}
				break;

			case "results":
				var strContent;
				if (this.Document.Results.length > 0) {
					var strResult = "";
					for (var i = 0; i < this.Document.Results.length; i++) 
						this.DisplayPage(i, this.Document.Results[i].Page, "<p>" + this.Document.Results[i].Content.join("</p><p>") + "</p>", true, (this.Document.Results[i].Page.Page == this.Document.CurrentPage));
				}
				break;

			case "pages":
				var Page1 = (Math.ceil(this.Document.CurrentPage / this.Option.Pages) * this.Option.Pages) - (this.Option.Pages - 1);
				for (var i = 0; i < this.Option.Pages; i++) 
					if (this.Document.Pages[Page1 + i] != null)
						this.DisplayPage(i, this.Document.Pages[Page1 + i], "", false, false);
					else
						this.HidePage(i);
				break;
		}
	}

//******************************************************************
//	Displays the page given by PageNumber
//******************************************************************
	function Framework_DisplayPage(i, Page, Content, AddLink, Selected) {

	//	Display Page
		var TheElement = DOM.getElementById("page-" + i);
		if (TheElement != null)
			TheElement.style.display = "";

	//	Update link
		TheElement = DOM.getElementById("link-" + i);
		if (AddLink && (TheElement != null)) {
			switch (this.Mode()) {
				case "bookmarks":
					TheElement.href = "javascript:" + this.Document.ObjectName + ".Navigate('bookmark', " + i + ")";
					break;
				
				default:
					TheElement.href = "javascript:" + this.Document.ObjectName + ".Navigate('goto', " + Page.Page + ")";
					break;
			}
		}

	//	Update image
		var PageImage;
		var PageCaption;
		switch (this.Mode()) {
			case "thumbs":
			case "results":
			case "bookmarks":
				PageImage = constants.appPath + this.Document.Location.images + this.Document.DocumentName + "." + Page.Page + ".0." + this.Document.ImageType;
				PageCaption = Page.Name;
				break;
				
			default:
				PageImage = constants.appPath + this.Document.Location.images + this.Document.DocumentName + "." + Page.Page + "." + this.Document.CurrentZoom + "." + this.Document.ImageType;
				PageCaption = "";
				break;
		}
		
		TheElement = DOM.getElementById("image-" + i);
		if (TheElement != null) {
			TheElement.className = TheElement.className.replace(/[ ]*selected/g, "") + (Selected ? " selected" : "");
			TheElement.src = PageImage;
		}

	//	Update caption
		DOM.setInnerHTML("caption-" + i, PageCaption);

	//	Update content
		DOM.setInnerHTML("content-" + i, Content);
	}

//******************************************************************
//	Hides the page given by PageNumber
//******************************************************************
	function Framework_HidePage(PageNum) {
		var TheElement = DOM.getElementById("page-" + PageNum);
		if (TheElement != null)
			TheElement.style.display = "none";
	}
	

//****************************************************************************************
//	Main document object
//****************************************************************************************

	function CreateDocument(Name, Organisation, Code, DocumentData)
	{
		var TheDocument = new Document(Name, Organisation, Code, DocumentData);
		TheDocument.Framework.Document = TheDocument;
		TheDocument.Load();
		self[Name] = TheDocument;
		return TheDocument;
	}

	function Document(Name, Organisation, Code, DocumentData) {
	
//*********************************
//	Properties
		this.ObjectName = Name;							//	Object name of the document variable

		this.Title = DocumentData.Title;				//	Title of document
		this.Organisation = Organisation;				//	Organisation that owns the document
		this.Code = Code;								//	Code for Organisation - used to locate documents
		this.DocumentID = DocumentData.DocumentID;		//	DB ID of document;
		this.Details = null;							//	Details of document
		this.Location = DocumentData.Location;			//	FS location of document
		this.DocumentName = DocumentData.DocumentName;	//	Base filename.
		this.ImageType = DocumentData.ImageType;		//	Type of image
		this.Target = "document";						//	Default location for document display
		this.Framework = new Framework();				//	Default Framework
		this.XML = "";									//	XML representation of the document
		this.JSON = "";									//	JSON representation of the document
		this.Pages = new Array();						//	Array of page information
		this.Bookmarks = new Object();					//	Object to hold bookmark information
		this.Links = new Object();						//	Object to hold link information
		
		this.Metrics = null;							//	Object to hold the metrics data for this page;
		
		this.Loaded = false;							//	Whether document is loaded or not
		this.CurrentPage = 0;							//	Display Page
		this.CurrentOption = 0;							//	Display Option
		this.CurrentZoom = constants.DefaultZoom;		//	Display Zoom
//*********************************
		
//*********************************
//	Methods
		this.PDF = Document_PDF;						//	Displays the Table of Contents (bookmarks)
		this.PrintDocument = Document_PrintDocument;	//	Prints the current page
		this.GetPage = Document_GetPage;				//	Gets the specified Page;
		this.Length = Document_Length;					//	Returns the number of pages in the document.
		this.ScreenTitle = Document_ScreenTitle;		//	Returns the description of the current display

//		this.Process = Document_Process;
//		this.FetchStatus = Document_FetchStatus;

		this.Load = Document_Load;						//	Load a document into this object
		this.Set = Document_Set;						//	Sets the layout for a document
		this.Layout = Document_Layout;					//	Set layout for document and redisplay
		this.Zoom = Document_Zoom;						//	Set zoom factor for document and redisplay

		this.Navigate = Document_Navigate;				//	Navigates trhough the document
		this.Display = Document_Display;				//	Displays the document using the framework
		this.Page = Document_Page;						//	Sets pages for display
		this.ToC = Document_ToC;						//	Sets Table of Contents (bookmarks)
		this.Bookmark = Document_Bookmark;				//	Processes a bookmark
		this.Search = Document_Search;					//	Searches for given words in the document content
		this.FindResults = Document_FindResults;		//	Returns array of pages that meet search term

		this.ProcessAction = Document_ProcessAction;	//	Processes the PDF Action
		this.AddMetric = Document_AddMetric;			//	Store metrics about document use;
		this.State = Document_State;					//	Unique Code identifying the state of the display

		this.DefaultState = this.State();
		
//*********************************

		
	}
	
//******************************************************************
//	Download the PDF
//******************************************************************
	function Document_PDF() {
		window.open(constants.appPath + this.Location.documents + this.DocumentName + ".pdf");
	}

//******************************************************************
//	Prints the current page
//******************************************************************

	var iPage;
	function Document_PrintDocument() {
		var PrintFrame = DOM.findWindow("print_frame");
		if (PrintFrame != null) {
			while (PrintFrame.document.body.childNodes.length > 0)
				PrintFrame.document.body.removeChild(PrintFrame.document.body.firstChild);
			
			iPage = 0;
			LoadImage();
			this.AddMetric(this.CurrentPage, "Print", "");
		}
	}
	
	function LoadImage() {
		var PrintFrame = DOM.findWindow("print_frame");
		if (PrintFrame != null) {
			var Page = DOM.getElementById("image-" + iPage++)
			if (Page != null) {
				var image = PrintFrame.document.createElement("img");
				image.id = "print-image" + iPage;
				image.onload = function() { LoadImage(); }
				PrintFrame.document.body.appendChild(image);
				image.width = 592;
				image.src = Page.src.replace(/(\.[0-9]+\.)[^\.]*/i, "$1print");
			} else {
    			PrintFrame.focus();				
	    		PrintFrame.print();
	    	}
		}
	}
            
//******************************************************************
//	Gets the specified Page
//******************************************************************
	function Document_GetPage(PageNum) {
		return this.Pages[PageNum];
	}


//******************************************************************
//	Returns the number of pages in the document
//******************************************************************
	function Document_Length() {
		return this.Pages.length - 1;
	}

//******************************************************************
//	Returns the description of the current display
//******************************************************************
	function Document_ScreenTitle() {
		var Title = "";
		switch (this.Framework.Mode()) {
			case "thumbs":
				Title = "thumbnails";
				break;
			
			case "bookmarks":
				Title = "table of contents";
				break;
			
			case "results":
				Title = "search results";
				break;
			
			case "pages":
				Title = "page " + this.GetPage(this.CurrentPage).Name;
				break;
		}
		return this.Organisation + " - " + this.Title + ": " + Title;
	}
	
//******************************************************************
//	Process a document on the server
//******************************************************************
/*	var iTmp = 0;
	function Document_Process(Organisation, Code, DocumentID, DocumentName) {
		try {
			var Details = {"Organisation" : Organisation, "Code" : Code, "DocumentID" : DocumentID, "DocumentName" : DocumentName};
			DSM.request(constants.appPath + constants.DocumentProcessFile, "ProcessDocument", "", Details, true);
		}
		catch (err) {
			message.raise("Document", "Unable to process document.", err.description, false);
		}
	}*/

//******************************************************************
//	Fetch the Document Status
//******************************************************************
/*	function Document_FetchStatus(Organisation, Code, DocumentID, DocumentName, ID) {
		try {
			var Details = {"Organisation" : Organisation, "Code" : Code, "DocumentID" : DocumentID, "DocumentName" : DocumentName};
			var Results = DSM.request(constants.appPath + constants.DocumentProcessFile, "FetchStatus", "", Details, false);
			if (Results.OK)
				return eval("(" + Results.Data + ")");
			else
				message.raise("Document", "Unable to fetch the status of document - " + DocumentName, Results.Error, true);
		}
		catch (err) {
			message.raise("Document", "Unable to load document.", err.description, false);
		}
		return null;
	}*/

//******************************************************************
//	Load a document into the document object
//******************************************************************
	function Document_Load() {

		try {
			var Details = {"Code" : this.Code, "DocumentName" : this.DocumentName};
			var data = DSM.request(constants.appPath + constants.DocumentProcessFile, "OpenDocument", "", Details, false);
			if (data.ok) {
				this.Title = data.data.Base.Title;
				this.Location = data.data.Base.Location;
				this.Details = data.data.Base.Details
				this.DocumentName = data.data.Base.DocumentName;
				this.Pages = data.data.Content;
				this.Bookmarks = ProcessBookmarks(data.data.Bookmarks);
				this.Loaded = true;
			} else {
				throw data.error;
			}
		}
		catch (err) {
			message.raise("Document", "Unable to load document.", (err.message != null ? err.message : err), false);
		}
	}

	function ProcessBookmarks(Bookmarks, Prefix) {
		var BookmarkArray = new Array();
		Prefix = (Prefix != null ? Prefix : "");

		for (var j = 0; j < Bookmarks.length; j++) {
			BookmarkArray.push({Title: Prefix + Bookmarks[j].Title, Actions: Bookmarks[j].Actions});
			
			if ((Bookmarks[j].Bookmarks != null) && (Bookmarks[j].Bookmarks.length > 0))
				BookmarkArray = BookmarkArray.concat(ProcessBookmarks(Bookmarks[j].Bookmarks, Prefix + "~"));
		}
		
		return BookmarkArray;
	}


//******************************************************************
//	Sets the display options for the document
//******************************************************************
	function Document_Set(Option) {
		this.CurrentOption = ((Option < FrameworkOptions.length) ? Option : 1);
		this.Framework.Option = FrameworkOptions[this.CurrentOption];
		this.Framework.Draw();
	}

//******************************************************************
//	Set layout for document and redisplay
//******************************************************************
	function Document_Layout(Option) {
		this.Set(Option);
		this.CurrentPagesOption = (this.Framework.Mode() == "pages" ? Option : this.CurrentPagesOption);
		this.Framework.Display();

		//Add History
		History.Add(document.title, this.State());
	}
	
//******************************************************************
//	Set zoom factor for document and redisplay
//******************************************************************
	function Document_Zoom(ZoomDelta) {
		this.CurrentZoom = Math.min(constants.MaxZoom, Math.max(1, this.CurrentZoom + ZoomDelta));
		this.Framework.Set("Zoom");
		this.Framework.Display();

		//Add History
		History.Add(document.title, this.State());
	}
	
//******************************************************************
//	Navigate through the document
//******************************************************************
	function Document_Navigate(Action, Value) {
		switch (Action.toLowerCase()) {

			case "first":
				this.Page(0);
				break;
	
			case "prev":
				this.Page((this.CurrentPage - this.Framework.Option.Pages));
				break;
	
			case "next":
				this.Page((this.CurrentPage + this.Framework.Option.Pages));
				break;
	
			case "last":
				this.Page(this.Length());
				break;
	
			case "goto":
				this.Page(Value);
				break;
		
			case "bookmark":
				this.Bookmark(Value);
				break;
		
			case "search":
				this.Search();
				break;
	
			case "searchagain":
				if ((this.Results != null) && (this.Results.length > 0)) {
					this.Set(constants.SearchOption);
					this.Framework.Display();
				}
				break;
	
			default:
				return;		
		}
	}

//******************************************************************
//	Display document at target using Framework
//******************************************************************
	function Document_Display() {
	//	If the framework is not set for displaying a page then set it.
		if (this.Framework.Mode() != "pages") 
			this.Set(this.CurrentPagesOption);

		this.Framework.Display();
		this.Framework.Set("SelectedBookmark", this.Bookmarks.selected);

		//Add History and Metrics
		this.AddMetric(this.CurrentPage, "View", "");
		History.Add(document.title, this.State());
	}

//******************************************************************
//	Displays the page
//******************************************************************
	function Document_Page(iPage) {
		this.CurrentPage = Math.min(this.Length(), Math.max(0, iPage));
		this.Display();
	}

//******************************************************************
//	Displays the Table of Contents for a document
//******************************************************************
	function Document_ToC() {
		if (this.Bookmarks.length > 0) {
			this.Set(constants.BookmarkOption);
			this.Framework.Display();

			//Add History and Metrics
			this.AddMetric(this.CurrentPage, "ToC", "");
			History.Add(document.title, this.State());
		} else {
			alert("This document does not have any Table of Contents");
		}
	}

//******************************************************************
//	Processes the bookmark
//******************************************************************
	function Document_Bookmark(iBookmark) {
		if ((iBookmark >= 0) && (iBookmark < this.Bookmarks.length)) {
			if (this.ProcessAction(this.Bookmarks[iBookmark].Actions)) {
				this.Display();

				//Add History and Metrics
				History.Add(document.title, this.State());
				this.AddMetric(this.CurrentPage, "Bookmark", this.Bookmarks[iBookmark].Title);
			}
		}
	}

//******************************************************************
//	Searches the document for given words
//******************************************************************
	function Document_Search() {
		var SearchTextbox = DOM.getElementById("search-text");
		var SearchTerm = (SearchTextbox != null ? SearchTextbox.value : "");

		if (SearchTerm != "") {
			this.Results = this.FindResults(SearchTerm);
			if (this.Results.length > 0) {
				this.Set(constants.SearchOption);
				this.Framework.Display();

				//Add History and Metrics
				History.Add(document.title, this.State());
				this.AddMetric(this.CurrentPage, "Search", SearchTerm);
			} else {
				alert("This search produced no results");
			}
		}
	}
	
	function Document_FindResults(SearchTerm) {
		var Results = new Array();
		var FoundPage;
		
		if (SearchTerm != "") {
			var regTest = new RegExp(SearchTerm, "i");
			var regExtract = new RegExp("(?:\\s+\\S+?){0,4}\\s*(" + SearchTerm + ")\\s*(?:\\S+?\\s+){0,4}", "gi");
			var Segment;

			for (var iPage = 0; iPage < this.Pages.length; iPage++) {
				FoundPage = new Object();
				FoundPage.Page = this.Pages[iPage];
				FoundPage.Content = new Array();
				
				for (var i = 0; i < this.Pages[iPage].Content.length; i++) {
					if (regTest.test(this.Pages[iPage].Content[i])) {
						while ((Segment = regExtract.exec(this.Pages[iPage].Content[i])) != null)
							FoundPage.Content.push("..." + Segment[0].replace(Segment[1], "<b>" + Segment[1] + "</b>") + "...");
					}
				}
				
				if (FoundPage.Content.length > 0)
					Results.push(FoundPage);
			}
		}
		return Results;
	}

//******************************************************************
//	Processes the PDF Action
//******************************************************************
	function Document_ProcessAction(Actions) {
		var Display = false;
		
		for (var i = 0; i < Actions.length; i++) {
			
			switch (Actions[i].Type.toLowerCase()) {
			
				case "gotoaction":
					this.CurrentPage = Actions[i].Page - (this.Framework.Option.Pages > 0 ? (Actions[i].Page % this.Framework.Option.Pages) : 0) - 1;
					Display = true;
					break;
					
				default:
					break;
			
			}
		}
		
		return Display;
	}
	
//******************************************************************
//	Metrics Procesing
//******************************************************************
	var CaptureMetrics = true;
	function Document_AddMetric(CurrentPage, Metric, Value) {
		if (CaptureMetrics) {
			var Details = {"Code" : this.Code, "DocumentID" : this.DocumentID, "DocumentName" : this.DocumentName, "CurrentPage" : CurrentPage, "Metric" : Metric, "Value" : Value};
			var Result = DSM.request(constants.appPath + constants.DocumentProcessFile, "AddMetrics", "", Details, true);
		}
	}
	
//******************************************************************
//	Returns the code that represents the current display state
//******************************************************************
	function Document_State() {
		return this.CurrentPage + "." + this.CurrentZoom + "." + this.CurrentOption;
	}
	
	function LoadState(Code) {
		var Items = Code.split(".");
		with (TheOrganisation.Document) {
			CurrentPage = parseInt(Items[0]);
			CurrentZoom = parseInt(Items[1]);
			CurrentOption = parseInt(Items[2]);
			Set(CurrentOption);
			Framework.Display();
		}
	}
	
//******************************************************************
//	History Processing
//******************************************************************
	function AddHistory(Title, Code) {
		History.Add(Title, Code);
	}
	
	var History = function() {
		return {
			DefaultState:	"",
			CurrentState:	"",
			CheckTimer:		null,
			Frame:			null,
			isIE7:			((browser.code == "MSIE") && (browser.major < 8)),

			Init:			History_Init,
			Timer:			History_Timer,
			Add:			History_Add,
			Check:			History_Check,
			OnChange:		null
		}
	}();

	function History_Init(State, OnChange) {
		this.DefaultState = State;
		this.OnChange = OnChange;

		if (History.isIE7) {
			var HistoryFrame = document.createElement("iframe");
			HistoryFrame.name = "history";
			HistoryFrame.className = "history-frame";
			HistoryFrame.src = constants.appPath + "blank.html";
			document.body.appendChild(HistoryFrame);
			this.Frame = HistoryFrame;
		}
	}

	function History_Timer(On) {
		if (On) 
			this.CheckTimer = window.setInterval("History.Check()", 250);
		else if (this.CheckTimer != null)
			window.clearInterval(this.CheckTimer);
	}

	function History_Add(Title, StateCode) {
	    window.setTimeout("SetHistory('" + Title + "', '" + StateCode + "')", 5);
	}
	
	function SetHistory(Title, StateCode) {
		History.Timer(false);
		
		History.CurrentState = (StateCode != History.DefaultState ? StateCode : "");

		var Location = document.location.href;
		var iHash = Location.indexOf("#");

		if (History.isIE7)
			History.Frame.src = constants.appPath + "history.html?Title=" + Title + "#" + History.CurrentState;
		else if ((History.CurrentState != "") || (document.location.href.indexOf("#") > 0))
			document.location.hash = History.CurrentState;
	
		History.Timer(true);
	}
	
	function History_Check() {

		var Hash = "";
		if (History.isIE7)
			Hash = this.Frame.contentWindow.location.hash.substr(1);
		else
			Hash = document.location.hash.substr(1);

		if (this.CurrentState != Hash) {
			this.Timer(false);
			
			if (this.OnChange != null)
				this.OnChange((Hash != "" ? Hash : this.DefaultState));
				
			this.CurrentState = Hash;
			this.Timer(true);
		}
	}



