/**
 * engine.js
 *
 * A multi-version manuscript rendering and traversal engine.
 *
 * @author jose b. chua <jose@zebware.com>
 * @version 0.5
 * @revised by Amit Kumar 18th of June 2002 <kumar@umd.edu>
 * @version 0.6 
 * @revised by Amit Kumar 1st of October 2002 <kumar@umd.edu>
 * @revised by Amit Kumar  5th of November 2002 <kumar@umd.edu>
 * @revised by Amit Kumar  4th of Dec 2002 <kumar@umd.edu>
 * @revised by Amit Kumar  24th of Dec 2002 <kumar@umd.edu>
 * @revised by Amit Kumar  20th of April 2003 <kumar@umd.edu>
 * @revision 0.7
 * @revised by Amit Kumar  27th of April 2003 <kumar@umd.edu>
 * swap function does not work in mozilla - NS
 * @revised by Amit Kumar 29th of December 2005 <amitku@uiuc.edu>
 * added notes pane on the right
 * @revised by Amit Kumar 29th of April 2006 <amitku@uiuc.edu>
 * hide the lines that are empty
 * @revised by Sean Daugherty 14th of March 2007 <seancdaug@gmail.com>
 * new image and notes viewer
 */
var numManuscripts = 0;
var witnesses = new Array();
var matchingNodes = new Array();
var matchLine; //current line being matched
var ms;
var witShown = new Array();
var allNotes = ""; //all notes content is stored here
var notesDisplayChoice = "popup";
var appendedNotes = 0;

// MB 2002-12-27
// Globals needed to keep state of tabbed MS page so we can restore
// scroll position after tab change
var showingMS = true;;
var scrollTops = new Array();
var scrollLefts = new Array();

function init() {
	witShown[numManuscripts]=witnesses[0];
	numManuscripts++;
	showWitness(document.getElementById("manuscript"), "first");
	getAllNotes();
	var toggleNotes = document.getElementById("toggleNotes");
	var notesoption = document.getElementById("notesoption");
	/* Hide note display options if no notes are present */
	if (notes.length == 0) {
		notesoption.options.length = 1;
		notesoption.options[0].text = "No notes found!";
		notesoption.disabled="disabled";
	} else {
		notesoption.selectedIndex = 1;
	}
	/* Workaround Konqueror/Safari inline notes bug (KHTML) by disabling inline notes */
	if (BrowserDetect.browser == "Safari" || BrowserDetect.browser == "Konqueror") {
		notesoption.options.length = 2;
	}
	/* Hide line numbers and option if line numbers are not present */
	var numbers = getElementsByClass("linenumber");
	var n = 0;
	var len = numbers.length;
	var notnull = 0;
	var toggleLineNumbers = document.getElementById("toggleLineNumbers");
	for (n = 0; n < len; n++) {
		var linenumber = numbers[n].innerHTML;
		if (linenumber != "") notnull++;
	}
	if (notnull == 0) {
		hideLineNumbers();
		toggleLineNumbers.checked = false;
		toggleLineNumbers.disabled = true;
	}
}

function discreteInit() {
	witShown[numManuscripts]=witnesses[0];
	numManuscripts++;
	showWitness(document.getElementById("manuscript"), "first");
}
function selectWitness(manuscript, witness) {
	var match_string;
	var match = witnesses[witness];
	if(witShown.length == 1) position = 0;
	else if (manuscript.style.left== "50%" || manuscript.style.left=="33%") position = 1;
	else if (manuscript.style.left=="0%") position = 0;
	else if (witShown.length== 2 && manuscript.style.left=="") position = 1;
	else position = getPosition(manuscript);
	witShown[position] = witnesses[manuscript.current];
	var divs = new Array;
	var mypaper;
	divs = manuscript.getElementsByTagName("div");
	ms = divs[divs.length-1];
	for (var i = 0; i<ms.childNodes.length; i++) {
		if (ms.childNodes[i].id != null) {
			var linewit = ms.childNodes[i].getAttribute("wit");
			if (linewit == match | linewit == "all") {
				ms.childNodes[i].style.visibility = "visible";
				ms.childNodes[i].style.display = "block";
				if (ms.childNodes[i].id == matchLine) { }
			} else {
				ms.childNodes[i].style.visibility = "hidden";
				ms.childNodes[i].style.display = "none";
			}
		}
	}
	hideLines();
	navControls(manuscript,witnesses);
	var dropdowns = manuscript.getElementsByTagName("select");
	for (var i=0; i<dropdowns.length; i++) {
		if (dropdowns[i].id == "idlist") {
			var selectbox = dropdowns[i];
			for (var j=0; j<selectbox.options.length; j++) {
				if (selectbox.options[j].value == witnesses[witness]) {
					selectbox.selectedIndex = j;
				}
			}
		}
	}
}

function showWitness(manuscript, witness) {
	// determine which witness to change to
	var match_string;
	if (witness == "first") {
		manuscript.current = 0;
		var match = witnesses[manuscript.current];
	} else if (witness == "last") {
		// last witness is undefined
		manuscript.current = witnesses.length - 1;
		var match = witnesses[manuscript.current];
	} else if (witness == "next" ) {
		if (manuscript.current == null) manuscript.current = 0;
		manuscript.current++;
		if (manuscript.current >= witnesses.length) manuscript.current--;
		var match = witnesses[manuscript.current];
	} else if (witness == "previous") {
		manuscript.current--;
		if (manuscript.current < 0) manuscript.current++;
		var match = witnesses[manuscript.current];	
	} else if (!isNaN(witness)) {
		var match = witnesses[witness];
	} else {
		manuscript.current = numManuscripts - 1;
		var match = witnesses[manuscript.current];	
	}
	var position = 0;
	if(witShown.length == 1) position = 0;
	else if (manuscript.style.left== "50%" || manuscript.style.left=="33%") position = 1;
	else if (manuscript.style.left=="0%") position = 0;
	else if (witShown.length== 2 && manuscript.style.left=="") position = 1;
	else position = getPosition(manuscript);
	witShown[position]= witnesses[manuscript.current];
	/* var idContainer;
	var subspans = new Array;
	subspans = manuscript.getElementsByTagName("span");
	for (var i=0; i<subspans.length; i++) {
		if ( subspans[i].id != null && subspans[i].id == "msID") {
			idContainer = subspans[i];
			break;
		}
	}
	idContainer.innerHTML = witnesses[manuscript.current];
	alert (manuscript.childNodes[1].getAttribute("id"));
	manuscript.childNodes[1].childNodes[10].innerHTML = witnesses[manuscript.current]; */
	//MB-2002-12-26-002
	// Locate the MS "paper" div without hard-coded constants
	// The mspaper is the last div child of each manuscript.
	// This is still not as general as it ought to be, and is
	// undesirably sensitive to markup and XSLT changes, 
	// but it avoids the crucial whitespace counting problems,
	// and puts all browsers and their DOM implementations on the same footing
	// towards the current markup and XSLT
	var divs = new Array;
	var mypaper;
	divs = manuscript.getElementsByTagName("div");
	ms = divs[divs.length-1];
	for (var i = 0; i<ms.childNodes.length; i++) {
		if (ms.childNodes[i].id != null) {
			//MB-2002-12-26-003
			// Use W3C conformant exposure of attribute values.
			// This syntax also works with IE5.5+ and so is preferable to
			// MS proprietary even on MS platforms
			var linewit = ms.childNodes[i].getAttribute("wit");
			if (linewit == match | linewit == "all") {
				ms.childNodes[i].style.visibility = "visible";
				ms.childNodes[i].style.display = "block";
				if (ms.childNodes[i].id == matchLine) { }
				// Hide the empty line.
				/*if (ms.childNodes[i].childNodes.length==2) {
					if (ms.childNodes[i].childNodes[0].nodeValue.length<2) {
						//change the visibility of the peer span class to hidden
						if (ms.childNodes[i].childNodes[1].nodeName =="SPAN") {
							ms.childNodes[i].childNodes[1].style.visibility= "hidden";
							//  ms.childNodes[i].childNodes[1].style.display = "none";
						}
					}
				} else if ((ms.childNodes[i].lastChild != null) && ms.childNodes[i].lastChild.nodeName=="SPAN") {
					// alert(ms.childNodes[i].innerHTML);
					// now if the last child is SPAN we would like to check if
					// the immidiete sibling is br or not if it is a br
					// then this span needs to be moved before all the br
					var foundBR = -1;
					for (j=0; j< ms.childNodes[i].childNodes.length; j++) {
						if (ms.childNodes[i].childNodes[j].nodeName=="BR") {
							foundBR = j;
							break;
						}
					}
					if (foundBR > -1) {
						//ms.childNodes[i].removeChild(ms.childNodes[i].lastChild);
						//alert("Insert BEFORE " + ms.childNodes[i].innerHTML);
						ms.childNodes[i].insertBefore(ms.childNodes[i].lastChild,ms.childNodes[i].childNodes[foundBR]);
						//alert("AFTER INSERT: " +ms.childNodes[i].innerHTML);
					}
				} */
				// check if the child node has the <span class="numbering-line">
				// if it does check if it is the only child
				// if only child then change visibility of the span to hidden
				// else ok
				// check if the child is made up of &nbsp;
			} else {
				ms.childNodes[i].style.visibility = "hidden";
				ms.childNodes[i].style.display = "none";
			}
		}
	}
	hideLines();
	navControls(manuscript,witnesses);
	var dropdowns = manuscript.getElementsByTagName("select");
	for (var i=0; i<dropdowns.length; i++) {
		if (dropdowns[i].id == "idlist") {
			var selectbox = dropdowns[i];
			for (var j=0; j<selectbox.options.length; j++) {
				if (selectbox.options[j].value == match) {
					selectbox.selectedIndex = j;
				}
			}
		}
	}
}

function navControls(manuscript,witnesses) {
	var navspans = manuscript.getElementsByTagName("span");
	for (var i = 0; i < navspans.length; i++) {
		// Disables the "first" and "previous" navigation controls when viewing
		// the first available manuscript, and reenables them when not.
		if (navspans[i].innerHTML == "Previous" || navspans[i].innerHTML == "First") {
			if (manuscript.current <= 0) {
				navspans[i].className = "inactivenavigate";
			} else {
				navspans[i].className = "navigate";
			}
		// Disables the "next" and "last" navigation controls when viewing the
		// last available manuscript, and reenables them when not.
		} else if (navspans[i].innerHTML == "Next" || navspans[i].innerHTML == "Last") {
			if (manuscript.current >= witnesses.length - 1) {
				navspans[i].className = "inactivenavigate";
			} else {
				navspans[i].className = "navigate";
			}
		}
	}
}

function hideLines() {
	// The following code checks each line of the text to ensure that it is not
	// empty. If it is empty, it hides the entire line, including the line
	// numbers. This can be extremely slow when dealing with long texts, so if
	// you notice significant slowdown when using the Versioning Machine, you
	// may wish to comment out the following.
	var lines = getElementsByClass("linetext");
	var numbers = getElementsByClass("linenumber");
	for (i = 0; i < lines.length; i++) {
		/* var content = stripHTML(lines[i].innerHTML); //removes HTML tags from the line for matching purposes */
		var content = lines[i].innerHTML;
		var regexp = new RegExp(/([a-zA-Z0-9])+/);
		if (!content.match(regexp)) {
				lines[i].parentNode.style.display = "none";
		}
	}
}

function stripHTML(oldString) {
	var newString = oldString.replace(/(<([^>]+)>)/ig,"");
	newString = newString.replace(/\r\n/g," ");
	newString = newString.replace(/\n/g," ");
	newString = newString.replace(/\r/g," ");
	newString = trim(newString);
	return newString;
}

function trim(str) {
	str = str.replace(/^\s*|\s*$/g,"");
	return str;
}

//  Get all the notes and stoew in the allNotes global variable
function getAllNotes() {
	for (i=0; i<notes.length; i++) {
		var q = document.getElementById("note."+notes[i]);
		var linenum = q.getAttribute("linenum");
		if (q != null) {
			if (q.innerHTML != null) {
				if (linenum != "") allNotes = allNotes+"<div id=allnote."+notes[i]+" style='border-style:solid; border-width:1px'><em>Line Number:"+linenum+"</em> "+q.innerHTML+"</div>";
				else allNotes = allNotes+"<div id=allnote."+notes[i]+" style='border-style:solid; border-width:1px'>"+q.innerHTML+"</div>";
			}
		}
	}
}

function getPosition(ms) {
	var dumb = 100 / (numManuscripts + 1);
	var num = parseInt(ms.style.left) / dumb;
	num = Math.round(num);
	return num-1;
}

function createManuscript() {
	numManuscripts++;
	matchingNodes = new Array();
	if (numManuscripts > witnesses.length) {
		numManuscripts = witnesses.length;
		alert("Sorry, but the number of manuscript panes cannot exceed the number of available versions.");
		return;
	}
	hidePanel("imageviewer");
	hidePanel("noteviewer");
	witShown[numManuscripts-1] = witnesses[0];
	toggleNotes(true);
	var newpaper = document.getElementById("manuscript").cloneNode(true);
	var msarea = document.getElementById("manuscriptarea");
	msarea.appendChild(newpaper);
	if (notesDisplayChoice == "inline") {
		/* alert(appendedNotes);
		if (appendedNotes == 0) {
			var notesHolder = document.getElementById("allnotes").cloneNode(true);
			msarea.appendChild(notesHolder);
			appendedNotes++;
		} else {
			var msarea = document.getElementById("manuscriptarea");
			var notesHolder = document.getElementById("allnotes");
			msarea.removeChild(notesHolder);
			var notesHolder = document.getElementById("allnotes").cloneNode(true);
			msarea.appendChild(notesHolder);
			appendedNotes++;
			resizeManuscripts();
		} */
		displayNotes(notesDisplayChoice);
	}
	showWitness(newpaper, "increment");
	resizeManuscripts();
	normalStyle();
	/* populateNotes(); */
}

var current = 0;

function moveUp() {
	if (current <= 50) return;
	var obj = document.getElementById("manuscriptarea");
	current = current - 50;
	for (var i = 0; i < obj.childNodes.length; i++) {
		obj.childNodes[i].childNodes[1].style.position = "absolute";
		obj.childNodes[i].childNodes[1].style.top = current;
	}
}

function moveDown() {
	var obj = document.getElementById("manuscriptarea");
	current = current + 50;
	for (var i = 0; i < obj.childNodes.length; i++) {
		obj.childNodes[i].childNodes[1].style.position = "absolute";
		obj.childNodes[i].childNodes[1].style.top = current;
	}
}

function displace() {
	var obj = document.getElementById("manuscriptarea");
	for(i = 0; i < obj.childNodes.length; i++) {
		obj.childNodes[i].childNodes[1].style.position = "absolute";
		obj.childNodes[i].childNodes[1].style.top = current;
	}
}

function removeManuscript(button) {
	if (numManuscripts > 1) {
		numManuscripts--;
		var ms = button.parentNode.parentNode;
		var dumb = 100/(numManuscripts+1);
		var num = parseInt(ms.style.left)/dumb;
		num = Math.round(num)+1;
  		document.getElementById("manuscriptarea").removeChild(ms);
  		resizeManuscripts();
  } else alert("Sorry, but one manuscript must remain.");
  witShown.splice(num-1,1);
}

function resizeManuscripts() {
	var msarea = document.getElementById("manuscriptarea");
	var thisman = -1;
	var notesArea = 0;
	var targetwidth = parseInt(document.body.clientWidth) - (numManuscripts + notesArea); // notes are displayed on the right
	var notesLeft;
	var notesWidth;
	if (notesDisplayChoice == "inline") {
		notesArea = 1; 
		toggleNotes(false);
	} else if (notesDisplayChoice == "hide") {
		toggleNotes(false);
	} else {
		toggleNotes(true);
	}
	for (var i = 0; i < msarea.childNodes.length; i++) {
		var current = msarea.childNodes[i];
		/* var panecontrol = document.getElementById("panecontrol"); */
		if(current.nodeName == "DIV") {
			thisman++;
			if (Math.floor(targetwidth / (numManuscripts + notesArea)) < 400) {
				current.style.width = "400px";
				current.style.left = Math.floor(400 * thisman) + "px";
				/* panecontrol.style.width = Math.floor(((numManuscripts + notesArea) * 400)) + "px"; */
			} else {
				if (numManuscripts == 1) {
					targetwidth = targetwidth - 1;
				}
				current.style.width = (Math.floor(targetwidth / (numManuscripts + notesArea))) + "px";
				current.style.left = (Math.floor(targetwidth / (numManuscripts + notesArea)) * thisman) + "px";
				/* panecontrol.style.width = Math.floor(targetwidth / (numManuscripts + notesArea)) * (numManuscripts + notesArea) + "px"; */
			}
			notesLeft = current.style.left;
			notesWidth = current.style.width;
		}
	}
	if (notesDisplayChoice == "inline") {
		var notesHolder = document.getElementById("allnotes");
		notesHolder.style.width = notesWidth;
		notesHolder.style.left = notesLeft;
		notesHolder.style.display = "block";
	}
	resizeTabs();
}

function resizeTabs() {
	/* var biblioarea = document.getElementById("biblioarea"); */
	/* var panecontrol = document.getElementById("panecontrol"); */
	var targetwidth = parseInt(document.body.clientWidth) - 2;
	targetwidth = Math.floor(targetwidth / 2) * 2;
	/* biblioarea.style.width = targetwidth + "px";
	if (biblioarea.style.display == "block" ) {
		panecontrol.style.width = targetwidth + "px";
	} */
}


function changeTab(tab) {
	hidePanel("noteviewer");
	hidePanel("imageviewer");
	// Make all the tabs unselected
	var mtab = document.getElementById("manuscripttab");
	var btab = document.getElementById("bibliotab");
	/* var barea = document.getElementById("biblioarea"); */
	var marea = document.getElementById("manuscriptarea");
	mtab.className = "tabinactive";
	btab.className = "tabinactive";
	/* barea.style.display = "none"; */
	marea.style.display = "none";
	tab.className = "tabactive";
	switch (tab.id) {
		case "manuscripttab" :
			marea.style.display = "block";
			break;
		case "bibliotab" :
			/* barea.style.display = "block";  */
			break;
	}
	resizeManuscripts();
}


function toggleNotes(toggle) {
	if (toggle) var mode = "inline";
	else var mode = "none";
	var spans = document.getElementsByTagName("span");
	var divs = document.getElementsByTagName("div");
	for (var i = 0; i < spans.length; i++) {
		if (spans[i].id.indexOf("noteicon") == 0) spans[i].style.display = mode;
	}	
	for (var i = 0; i < divs.length; i++) {
		if (divs[i].id.indexOf("note") == 0) divs[i].style.visibility = "hidden";
	}
}

var allPageTags = new Array(); // creates an array 

function toggleLines(theClass) {
	var allPageTags = document.getElementsByTagName("*"); // populate the array with all the page tags
	// cycle through the tags using a for loop
	for (var i = 0; i < allPageTags.length; i++) {
		// pick out the tags with our class name
		if (allPageTags[i].className == theClass) allPageTags[i].style.display = "none";
	}
} 

function displayNote(noteicon,title,e,theInstance,x,y) {
	// hidePanel("imageviewer"); // hides image popup
	var val = eval("document.getElementById(noteicon).innerHTML");
	document.getElementById("title_" + theInstance).innerHTML = "Note type: " + title;
	return showTextPanel(e, theInstance, val, x, y);
} 

function callHome() {
	var popUpRef = window.open("http://www.v-machine.org/", "", "width=500, height=500, location=yes, resizable=yes, scrollbars=yes,toolbar=yes, status=yes");
}

function closeNote(notebutton) {
	notebutton.parentNode.parentNode.style.visibility = "hidden";
}

function imageView(e,theInstance,theImgSrc,x,y,address,witness) {
	var extStart = String(address).lastIndexOf(".");
	var extLength = String(address).length - extStart;
	var extension = String(address).toLowerCase().substr(extStart,extLength);
	if (extension.lastIndexOf(".htm") == "-1") {
		if (BrowserDetect.browser == "Explorer" || BrowserDetect.browser == "Safari") {
			return showImgPanel(e, theInstance, theImgSrc, x, y);
		} else {
			alert("Sorry, but this feature currently only works with Microsoft Internet Explorer and Apple Safari. Mozilla and Firefox users may wish to try the HTML version of this text for image viewing purposes.");
			return false;
		}
	} else {
		hidePanel("noteviewer"); // hides note popup
		document.getElementById("title_" + theInstance).innerHTML = "Image Viewer: " + witness;
		return showImgPanel(e, theInstance, theImgSrc, x, y, witness);	
	}
}

function changeStyle() {
	for (var i = 0; i < matchingNodes.length; i++) {
		if (matchingNodes[i].style.fontWeight == "800") {
			matchingNodes[i].style.fontWeight = "400";
			var innerSpans = matchingNodes[i].getElementsByTagName("span");
			for (var j = 0; j < innerSpans.length; j++) {
				if (innerSpans[j].className == "linenumber") {
					innerSpans[j].style.backgroundColor = "transparent";
				}
			}
		} else {
			matchingNodes[i].style.fontWeight="800";
			var innerSpans = matchingNodes[i].getElementsByTagName("span");
			for (var j = 0; j < innerSpans.length; j++) {
				if (innerSpans[j].className == "linenumber") {
					innerSpans[j].style.backgroundColor = "#B2CCE5";
				}
			}
		}
	}
}

function normalStyleAll() {
	var spans = document.getElementsByTagName("span");
	for (var i = 0; i < spans.length; i++) {
		if (spans[i].className == "linenumber") {
			spans[i].style.backgroundColor = "transparent";
		} else if (spans[i].className == "textline") {
			spans[i].style.fontWeight = "400";
		}
	}
}
	

// normalize the style from bold 
function normalStyle() {
	for (var i = 0; i < matchingNodes.length; i++) {
		matchingNodes[i].style.fontWeight = "400";
		var innerSpans = matchingNodes[i].getElementsByTagName("span");
		for (var j = 0; j < innerSpans.length; j++) {
			if (innerSpans[j].className == "linenumber") {
				innerSpans[j].style.backgroundColor = "transparent";
			}
		}
	}
}

/**
  * 
  *@AK redid this function to work with netscape/mozilla
  * getElementByTag made redundant
  *
  */
  
// line matching function
function getMatching(name) {
	matchingNodes = new Array();
	var numFound=0;
	var obj = document.getElementById("manuscriptarea");
	var temp_node;
	var divs = new Array;
	var mypaper;
	count = 0;
	for (var i = 0; i < obj.childNodes.length; i++) {
		temp_node = obj.childNodes[i];
		if (temp_node != null && temp_node.nodeName == "DIV") {
			divs[count]= temp_node;
			count++;
		}
	}
	for (var k = 0; k < divs.length; k++) {
		mypaper = divs[k];
		for (var r = 0; r < mypaper.childNodes.length; r++) {
			if (mypaper.childNodes[r].nodeName == "DIV") {
				var thisNode = mypaper.childNodes[r];
				for (var j = 0; j < thisNode.childNodes.length; j++) {
					if (thisNode.childNodes[j].id == name) {
						matchingNodes[numFound]= thisNode.childNodes[j];
						numFound++;
					}
				}
			}
		}
		
	}
	changeStyle();
}

var myimages = new Array();

function preloadimages() {
	for (var i = 0; i < preloadimages.arguments.length; i++) {
		myimages[i] = new Image();
		myimages[i].src = preloadimages.arguments[i];
	}
}

function populateNotes() {
	var notesHolderData = document.getElementById("allnotesdata");
	notesHolderData.innerHTML = allNotes;
}

/**
  * Change the Notes display popup or inline
  */

function notesFormat(notesChoice) {
	if (notesChoice.value != null) {
		notesDisplayChoice = notesChoice.value;
	} else {
		notesDisplayChoice = "hide";
	}
	displayNotes(notesDisplayChoice);
}
function displayNotes(notesDisplayChoice) {
	var msarea = document.getElementById("manuscriptarea");
	var notesHolder = document.getElementById("allnotes");
	try {
		msarea.removeChild(notesHolder);
	} catch (e) { }
	if (notesDisplayChoice == "inline") {
		hidePanel("noteviewer");
		var notesHolder = document.getElementById("allnotes").cloneNode(true);
		msarea.appendChild(notesHolder);
		appendedNotes++;
		populateNotes();
		document.getElementById("notesoption").selectedIndex = 2;
	} else {
		appendedNotes = 0;
		if (notesDisplayChoice == "popup") {
			toggleNotes(true);
			document.getElementById("notesoption").selectedIndex = 1;
		} else {
			hidePanel("noteviewer");
			toggleNotes(false);
			document.getElementById("notesoption").selectedIndex = 0;
		}
	}
  resizeManuscripts();
}


/**
  * Show/hide line numbers
  */
  
function toggleLineNumbers(toggle) {
	if (toggle) showLineNumbers();
	else {
		hideLineNumbers();
		normalStyleAll();
	}
}

function showLineNumbers() {
	var linenumber = getElementsByClass("linenumber");
	for (var n = 0; n < linenumber.length; n++) linenumber[n].style.visibility = "visible";
}

function hideLineNumbers() {
	var linenumber = getElementsByClass("linenumber");
	for (var n = 0; n < linenumber.length; n++) linenumber[n].style.visibility = "hidden";
}

function getElementsByClass(searchClass,node,tag) {
	var classElements = new Array();
	if ( node == null ) node = document;
	if ( tag == null ) tag = "*";
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp('(^|\\s)'+searchClass+'(\\s|$)');
	for (var i = 0, j = 0; i < elsLen; i++) {
		if (pattern.test(els[i].className)) {
			classElements[j] = els[i];
			j++;
		}
	}
	return classElements;
}

function getfileextension(inputId) {
	var fileinput = document.getElementById("foo"); 
	if (!fileinput) return ""; 
	var filename = fileinput.value; 
	if (filename.length == 0) return ""; 
	var dot = filename.lastIndexOf("."); 
	if(dot == -1) return ""; 
	var extension = filename.substr(dot,filename.length); 
	return extension; 
}

var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0; i < data.length; i++) {
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
BrowserDetect.init();

function scaleImage(image) {
	var oldwidth = image.offsetWidth;
	var oldheight = image.offsetHeight;
	if (oldwidth > 600) {
		var newwidth = 600;
		var newheight = (newwidth / oldwidth) * oldheight;
	} else {
		var newwidth = oldwidth;
		var newheight = oldheight;
	}
	image.width = newwidth;
	image.height = newheight;
}

/*************************************************************************
* Copyright 2006, Trustees of Indiana University. All rights reserved. This
* file is part of the Chymistry of Isaac Newton website,
* http://www.dlib.indiana.edu/collections/newton
* External javascript libraries have been included here; see
* individual copyright information for those libraries below. 
*************************************************************************/ 
 
/*************************************************************************
 Name: makePanelTop, imgStyleDrag, imgStyleDragEnd
 Desc: These functions are keyed to events handled by the * dom-drag.js
 	   library, below.  They are called within the showImgPanel function.
*************************************************************************/
	   
var panels = [];

makePanelTop = function() {
	var start = this.style.zIndex;
	for (var i = 0; i < panels.length; i++) {
		if (panels[i].style.zIndex + 100 > start ) panels[i].style.zIndex--;
	}
	this.style.zIndex = panels.length + 100 - 1;
}
  
pStyleDrag = function() {
	this.style.opacity = '.70';
	this.style.filter = "alpha(opacity=70)";
}

pStyleDragEnd = function() {
	this.style.opacity = '1.0'; 
	this.style.filter = "alpha(opacity=100)";
}
	
/*************************************************************************
 Name: hidePanel
 Desc: Closes a panel. 
	  
 Params: 
 theInstance - the unique id of the panel to hide (i.e. 70r_screen, 'panel_')
*************************************************************************/

function hidePanel(theInstance) { 
	if (!document.getElementById) return null;
	document.getElementById("panel" + "_" + theInstance).style.visibility = "hidden";
}

/*************************************************************************
 Name: showPanel
 Desc: Opens a new panel. 
 Params: 
 e		   - the event triggering the swap (typically onClick)
 theInstance - the id of the panel to show (i.e. 70r_screen)
 theImgSrc   - relative path to the img (i.e. /collections/newton/img/70r.gif)
 x		   - horizontal offset (in pixels) for new panel
 y		   - vertical offset (in pixels) for new panel 
*************************************************************************/

function showPanel(e,theInstance,x,y) {
	var offx = (x)? x - 0 : 20;
	var offy= (y)? y - 0 : 20;
	var theHandle = document.getElementById("handle" + "_" + theInstance);
	var theRoot   = document.getElementById("panel" + "_" + theInstance);
	Drag.init(theHandle, theRoot);
	theRoot.onDragStart = makePanelTop;
	theRoot.onDrag = pStyleDrag;
	theRoot.onDragEnd = pStyleDragEnd;
	panels[panels.length] = theRoot;
	panels[panels.length-1].style.zIndex = panels.length + 100 - 1;
	positionPanel(e,theRoot,offx,offy);
	theRoot.style.visibility = "visible";
}

/*************************************************************************
 Name: showImgPanel
 Desc: Opens a new image panel. Distinct from showPanel in that the
	   content is written when the panel is made visible.
 NOTE: probably this should be generalized.
 Params: 
 e		   - the event triggering the swap (typically onClick)
 theInstance - the id of the panel to show (i.e. 70r_screen)
 theImgSrc   - relative path to the img (i.e. /collections/newton/img/70r.gif)
 x		   - horizontal offset (in pixels) for new panel
 y		   - vertical offset (in pixels) for new panel 
*************************************************************************/

function showImgPanel(e,theInstance,theImgSrc,x,y) {
	var offx = (x)? x - 0 : 20;
	var offy = (y)? y - 0 : 20;
	var theHandle = document.getElementById("handle" + "_" + theInstance);
	var theRoot   = document.getElementById("panel" + "_" + theInstance);
	var theContent   = document.getElementById("content" + "_" + theInstance);
	var theImg = "<img onmousedown='return false;' oncontextmenu='return false;' onclick='return false;' alt='Page image' title='Page image' onload='scaleImage(this);' src='" + theImgSrc + "'>";
	Drag.init(theRoot, theRoot);
	theRoot.onDragStart=makePanelTop;
	theRoot.onDrag=pStyleDrag;
	theRoot.onDragEnd=pStyleDragEnd;
	panels[panels.length]=theRoot;
	panels[panels.length-1].style.zIndex = panels.length+100;
	positionPanel(e,theRoot,offx,offy);
	theContent.innerHTML = theImg;
	theRoot.style.visibility = "visible";
	relocatePopup(theInstance);
}

function showTextPanel(e,theInstance,theText,x,y) {
	var offx = (x)? x - 0 : 20;
	var offy = (y)? y - 0 : 20;
	var theHandle = document.getElementById("handle" + "_" + theInstance);
	var theRoot   = document.getElementById("panel" + "_" + theInstance);
	var theContent   = document.getElementById("content" + "_" + theInstance);
	Drag.init(theHandle, theRoot);
	theRoot.onDragStart=makePanelTop;
	theRoot.onDrag=pStyleDrag;
	theRoot.onDragEnd=pStyleDragEnd;
	panels[panels.length]=theRoot;
	panels[panels.length-1].style.zIndex = panels.length+100;
	positionPanel(e,theRoot,offx,offy);
	theContent.innerHTML = theText;
	theRoot.style.visibility = "visible";
	relocatePopup(theInstance);
}
	
/*************************************************************************
 Name: positionPanel
 Desc: Uses functions from the dyn-web libraries also in this file to
	   position panels.  
 NOTE: This is not working so well in i.e., needs to be refactored.
 
 Params: 
 e		   - the event from which the position will be determined (typically onClick)
 o		   - the object to position
 offx		- horizontal offset (in pixels) for new panel
 offy		- vertical offset (in pixels) for new panel 
*************************************************************************/
	
function positionPanel(e,o,offX,offY) {
	var x = 0, y = 0; viewport.getAll();
	x = e.pageX? e.pageX: e.clientX + viewport.scrollX;
	y = e.pageY? e.pageY: e.clientY + viewport.scrollY;
	if (y < 0) y = 25;
	if (x < 0) x = 25;
	o.style.left = x + "px"; o.style.top = y + "px";
}

/*************************************************************************
 
 dw_viewport.js
 version date Nov 2003
 
 This code is from Dynamic Web Coding 
 at http://www.dyn-web.com/
 Copyright 2003 by Sharon Paine 
 See Terms of Use at http://www.dyn-web.com/bus/terms.html
 regarding conditions under which you may use this code.
 This notice must be retained in the code as is!
	
*************************************************************************/  
	
var viewport = {
	getWinWidth: function () {
		this.width = 0;
		if (window.innerWidth) this.width = window.innerWidth - 18;
		else if (document.documentElement && document.documentElement.clientWidth)
			this.width = document.documentElement.clientWidth;
		else if (document.body && document.body.clientWidth) 
			this.width = document.body.clientWidth;
	},
	
	getWinHeight: function () {
		this.height = 0;
		if (window.innerHeight) this.height = window.innerHeight - 18;
		else if (document.documentElement && document.documentElement.clientHeight) 
			this.height = document.documentElement.clientHeight;
		else if (document.body && document.body.clientHeight) 
			this.height = document.body.clientHeight;
	},
	
	getScrollX: function () {
		this.scrollX = 0;
		if (typeof window.pageXOffset == "number") this.scrollX = window.pageXOffset;
		else if (document.documentElement && document.documentElement.scrollLeft)
			this.scrollX = document.documentElement.scrollLeft;
		else if (document.body && document.body.scrollLeft) 
			this.scrollX = document.body.scrollLeft; 
		else if (window.scrollX) this.scrollX = window.scrollX;
	},
	
	getScrollY: function () {
		this.scrollY = 0;	
		if (typeof window.pageYOffset == "number") this.scrollY = window.pageYOffset;
		else if (document.documentElement && document.documentElement.scrollTop)
			this.scrollY = document.documentElement.scrollTop;
		else if (document.body && document.body.scrollTop) 
			this.scrollY = document.body.scrollTop; 
		else if (window.scrollY) this.scrollY = window.scrollY;
	},
	
	getAll: function () {
		this.getWinWidth(); this.getWinHeight();
		this.getScrollX();  this.getScrollY();
	}
}
	
/**************************************************
* dom-drag.js
* 09.25.2001
* www.youngpup.net
**************************************************
* This library was borrowed from youngpup.net,
* it has not been altered internally - tlcamero
**************************************************/

var Drag = {
	obj : null,
	init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper) {
		o.onmousedown	= Drag.start;
		o.hmode			= bSwapHorzRef ? false : true ;
		o.vmode			= bSwapVertRef ? false : true ;
		o.root = oRoot && oRoot != null ? oRoot : o ;
		if (o.hmode  && isNaN(parseInt(o.root.style.left  ))) o.root.style.left   = "0px";
		if (o.vmode  && isNaN(parseInt(o.root.style.top   ))) o.root.style.top	= "0px";
		if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right  = "0px";
		if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";
		o.minX	= typeof minX != 'undefined' ? minX : null;
		o.minY	= typeof minY != 'undefined' ? minY : null;
		o.maxX	= typeof maxX != 'undefined' ? maxX : null;
		o.maxY	= typeof maxY != 'undefined' ? maxY : null;
		o.xMapper = fXMapper ? fXMapper : null;
		o.yMapper = fYMapper ? fYMapper : null;
		o.root.onDragStart	= new Function();
		o.root.onDragEnd	= new Function();
		o.root.onDrag		= new Function();
	},
	
	start : function(e) {
		var o = Drag.obj = this;
		e = Drag.fixE(e);
		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
		o.root.onDragStart(x, y);
		o.lastMouseX	= e.clientX;
		o.lastMouseY	= e.clientY;
		if (o.hmode) {
			if (o.minX != null)	o.minMouseX	= e.clientX - x + o.minX;
			if (o.maxX != null)	o.maxMouseX	= o.minMouseX + o.maxX - o.minX;
		} else {
			if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
			if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
		}
		if (o.vmode) {
			if (o.minY != null)	o.minMouseY	= e.clientY - y + o.minY;
			if (o.maxY != null)	o.maxMouseY	= o.minMouseY + o.maxY - o.minY;
		} else {
			if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
			if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
		}
		document.onmousemove	= Drag.drag;
		document.onmouseup = Drag.end;
		return false;
	},

	drag : function(e) {
		e = Drag.fixE(e);
		var o = Drag.obj;
		var ey	= e.clientY;
		var ex	= e.clientX;
		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
		var nx, ny;
		if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
		if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
		if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
		if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);
		nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
		ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));
		if (o.xMapper)		nx = o.xMapper(y)
		else if (o.yMapper)	ny = o.yMapper(x)
		Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
		Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
		Drag.obj.lastMouseX	= ex;
		Drag.obj.lastMouseY	= ey;
		Drag.obj.root.onDrag(nx, ny);
		return false;
	},

	end : function() {
		document.onmousemove = null;
		document.onmouseup   = null;
		Drag.obj.root.onDragEnd(parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]), parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
		Drag.obj = null;
	},

	fixE : function(e) {
		if (typeof e == 'undefined') e = window.event;
		if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
		if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
		return e;
	}
};
function showBiblio(event) {
	document.getElementById('content_biblioarea').style.display='block';
	showPanel(event,'biblioarea',0,0);
	relocatePopup('biblioarea');
}
function hideBiblio() {
	document.getElementById('content_biblioarea').style.display='none';
	return hidePanel('biblioarea');
}
function relocatePopup(type) {
	var notepanel = document.getElementById("panel_" + type);
	var totaldocumentwidth = (document.getElementById('manuscript').clientWidth + 2) * numManuscripts;
	var viewportwidth;
	var viewportheight;
	if (typeof window.innerWidth != 'undefined') {
		viewportwidth = window.innerWidth;
		viewportheight = window.innerHeight;
	} else if (typeof document.documentElement != 'undefined'
		&& typeof document.documentElement.clientWidth != 'undefined'
		&& document.documentElement.clientWidth != 0) {
		viewportwidth = document.documentElement.clientWidth;
		viewportheight = document.documentElement.clientHeight;
	}	
	if ((notepanel.offsetLeft + notepanel.offsetWidth) > totaldocumentwidth) {
		notepanel.style.left = (totaldocumentwidth - notepanel.offsetWidth - 15) + "px";
	}
}