//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// debug alerts numbered # 1 through # 13
// util.js WAS ADDED BY ERIC MARTZ.
/*

COLOR CONTROL MECHANISM:

The colors specified for body in dvrblite.css are overridden.
No other elements in dvrblite.js specify colors.

Functions such as setTextColor(c) and setBackgroundColor(c) in dvrblite.js
set variables such as text_color and text_background.

The defaults for these variables are in config.js.

These are later reported by functions in resizable.js (inappropriately
there?) such as getTextBackground().

resizable.js writes styles inline into the page (not a function call).

*/
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

var initSpt = "[NOT SET]";

var show_author_info = false;

var showZoomSlider = true; // set true in each chapter as needed.
var showSlabSlider = false; // set true in each chapter as needed.
var sliderMode = "zoom"; // or "slab", see setSliderAction()
//var slabPositionInitialized = false;
var previousSlidingAction = "zoom";
var slabPosition = 50;
var zoomPosition = 10;
var zoomValue = 100;
var maxZoomValue = 500;
var minZoomValue = 80;
var viewZoomValue = 100;
var startingZoomPosition = 10;

// zoomAutoslide is the mechanism that automatically slides the zoom
// slider to synch it with zooming by mouse. It runs "show zoom" every
// second, and moves the slider when zoom changes.
var zoomAutoslideTimerStarted = false;
var checkZoomAutoslideValueTimerHandle = -1;
var debugZoomAutoslideTimer = false;
var zoomAutoSlidePollingInterval = 1500; // milliseconds
// see also disablePolling in _jsutil/config2.js
// disablePolling should be temporarily true when you need
// to use the console. It suppresses
// the script-per-second clutter that makes the console unusable.
var lastMessagedZoomValue = 0;

var jmolAntialiasing = true;

var centerMode = false;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function makeControls()
{
	var ctrls = "";

	// TOP NAVIGATION BUTTONS?
	if ( getNavigation() == 'top' ) 
		ctrls += makeNavigation();

	// AUTHOR INFO FOR NON-CONTENTS PAGES [OBSOLETE]
//	if (!isContents)
//	{
//		ctrls += "<div style='margin: 10px;'>" +
//			makeAuthorInfo(0) + "</div>"; // Zero is for initial view
//	}

	// MAKE VIEW BUTTONS FOR NON-CONTENTS PAGES
	if (!isContents)
	{
		var buttonCount = getButtonCount();
		
		for ( var i = 1; i <= buttonCount; i++ ) 
			ctrls += makeJTATButton(i); // was makeButton(i);
	}
	else // isContents
	{
		ctrls += makeContentsDetails("top");
		ctrls += contentsText;
		ctrls += makeContentsDetails("bottom");
	}

	return ctrls;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function makeBottomMatter()
{
	var bmt = '';

	// BOTTOM NAVIGATION BUTTONS?
	if ( getNavigation() == 'bottom' ) 
		bmt += makeNavigation();

	bmt += makeFontSizeHelp();

	bmt += makeTroubleshootingLink();

	// Footer contains "how to" and licence info.
	bmt += makeFooter();

	return bmt;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function writeControls()
{
	document.writeln(makeControls());
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function writeBottomMatter()
{
	document.writeln(makeBottomMatter());
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// This also works: document.title = windowTitle;

// DEBUGGING: If window title is not shown in legacy pages,
// check for an empty <title></title> preceding putWindowTitle();

function putWindowTitle()
{
	// BEGIN section for backward version compatibility.
	if ((typeof(windowTitle) == "undefined" || windowTitle == "")
		&& typeof(tutorialTitle) != "undefined")
		windowTitle = tutorialTitle; // tutorialTitle was the old variable.
	// END backward version compatibility section.

	document.writeln("<title>" + windowTitle + "</title>");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// This function is present only to support legacy contents.htm files
// made before the release of JTAT.
function make_script_filename(bnum)
{
	return makeAuthorInfo(bnum);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

var authoring_mode_message_color = "a0a0a0";

var script_showing = new Array();

function makeAuthorInfo(bnum)
{
	if (!authoring_mode)
		return "";

	script_showing[bnum] = false;

	var msg = makeAuthorInfoText(bnum);

	return(msg);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function makeAuthorInfoText(bnum)
{
	// for buttons in a control panel, bnum 1-N
	// bnum == 0 for the contents page

	if (bnum > 0 && !show_author_info)
		return "";

	var msg = "";

	if (show_author_info || bnum == 0)
		msg += "<div id='show_script" + bnum + "'>\n" +
			"<font color='#" + authoring_mode_message_color + "'>\n";

	var ck = "";
	if (show_author_info)
		ck = " checked";

	if (bnum == 0) // initial view
	{
		if (!isContents)
		{
			msg +=
				"<input type='checkbox' name='authinfo' \n" +
				"onClick='reWriteControls()'" + ck + ">Show Info for Author \n" +
				"(authoring_mode is true).<br>";
		}

		if (show_author_info || isContents)
			msg += "Initial View:<br>\n";
	}

	if (show_author_info || isContents)
	{
		msg +=
			"&nbsp; &quot;" + buttons[bnum][iMoleculeFilename] + "&quot;, \n" +
			"&quot;" + buttons[bnum][iScript] + "&quot;\n";

		if (script_showing[bnum])
			msg += make_script_listing(bnum);

		else
			msg +=
				"<div align='right'>\n<a href='javascript: show_script(" + bnum + ")'>Show Script</a></div>\n";
	}

	if (bnum == 0)
		msg +=
			"Change authoring_mode (in _jsutil/config2.js) to false \n" +
			"in order to hide all messages in this color.\n";

	if (show_author_info || bnum == 0)
		msg += "</font></div>\n";

	return msg;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function show_script(bnum)
{
	var divId = "show_script" + bnum;

	script_showing[bnum] = true;
	
	document.getElementById(divId).innerHTML = makeAuthorInfoText(bnum);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function make_script_listing(bnum)
{
	var spt = _jmol.scripts[bnum + 1];
	if (bnum == 0)
		spt = initSpt;
	spt = spt.replace(/;/g, "<br>\n");
	spt = spt.replace(/script/g, "<big><big>script</big></big>");

	var hidelk =
		"<div align='right'><a href='javascript: hide_script(" +
		bnum + ")'>hide script</a></div>";


	var msg = "<div class='script'>" +
		"<font color='#" + authoring_mode_message_color + "'>" +
		 spt + hidelk + "</font></div>";

	return msg;	
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function hide_script(bnum)
{
	var divId = "show_script" + bnum;

	script_showing[bnum] = false;
	var msg = makeAuthorInfoText(bnum);

	document.getElementById(divId).innerHTML = msg;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function reWriteControls()
{
	if (authoring_mode && !isContents)
	{
		show_author_info = document.baseForm.authinfo.checked;
	}

	document.getElementById("controlsDiv").innerHTML =
		makeControls();	
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function script2Jmol(spt)
{
	// This assumes there is only one Jmol, jmolApplet0.

	jmolScript(spt, "0");	
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function footerHidden()
{
	var hideFooter = false;

	// Cookie plan failed because cookies belonging to chapter.htm are
	// distinct from those belonging to contents.htm.
//	if (getCookie("hideFooter") == "1")

	if (window.name == "hideFooter")
		hideFooter = true;

	return hideFooter;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function makeFooter()
{
//	alert("util.js #1: footerHidden() returns " + footerHidden());

	var msg = "<div id='footerDiv' class='templateLink'>";

	if (footerHidden())
		msg += makeFooterHiddenText();
	else
		msg += makeFooterText();

	msg += "</div>\n";

	return msg;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function makeFooterHiddenText()
{
	msg = "Show <a href='javascript: toggleHideFooter()'>\n" +
		"<b>How To, Open Access, ";
	if (tutorialCredits.length == 0)
		msg += "& License";
	else
		msg += "License, & Credits";
	msg += "</b></a>.\n";
	return msg;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function toggleHideFooter()
{
//	alert("util.js #2: window.name = " + window.name);

	var hideFooter = footerHidden();
	if (hideFooter)
		window.name = "showFooter"; // stop hiding
	else		
		window.name = "hideFooter"; // start hiding

	hideFooter = !hideFooter; // toggle value

	if (hideFooter)
		document.getElementById("footerDiv").innerHTML =
			makeFooterHiddenText();
	else
		document.getElementById("footerDiv").innerHTML =
			makeFooterText();
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function makeFooterText()
{
	var msg =
		"<div align='right'>(<a href='javascript: toggleHideFooter()'>" +
		"Hide Everything Below</a>)</div>" +
		"<center><b>How To ...</b>\n" +
//		"&nbsp; (<a href='javascript: toggleHideFooter()'>Hide</a>)" +
		"</center>Would you like:\n" +
		"<ul>\n" +
		"<li>A <a href='../../_docs/slides.htm' " +
			"target='_blank'><b>Powerpoint&reg; slide</b></a> " +
			"containing this view?</li>\n" +

		"<br><li>A <a href='../../_docs/tutuse.htm#bkg' " +
			"target='_blank'><b>different background color</b></a>?</li>\n" +
		"<li>A <a href='../../_docs/tutuse.htm#colors' " +
			"target='_blank'><b>different color scheme</b></a>?</li>\n" +

		"<br><li>To <a href='../../_docs/tutuse.htm#identify' " +
			"target='_blank'><b>identify</b></a> an atom?</li>\n" +
		"<li>To <a href='../../_docs/tutuse.htm#measure' " +
			"target='_blank'><b>measure</b></a> distances or angles?</li>\n" +

		"</ul>\n" +

		makeMoleculeLinks2FGiJ() +

		"<br><big>You " +
		"can make interactive 3D molecular structure tutorials like this one! " +
		"<a href='http://bioinformatics.org/jmol-tutorials/wiki' target='_blank'><b>" +
		"Here`s how</b>.</a></big>" +

		"<br><br>" +
		makeLicenseAndCredits() +

		"<center><br>" +
		"<small>[JTAT version: " + JTATVersion + "]</small></center>";

	return msg;
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function makeMoleculeLinks2FGiJ()
{
	var msg = "";

	// LEGACY support
	if (typeof(totalMolecules) != "undefined")
		if (totalMolecules == -1)
			return "";

	if (!showListOfMolecules)
		return "";

	// SHOW RED MESSAGE FOR AUTHORS IF NO MOLECULES ARE SPECIFIED.
	var have1pdb = true;
	if (typeof(moleculeCoordinates[1]) == "undefined")
		have1pdb = false;
	else if (moleculeCoordinates[1] == "")
		have1pdb = false;

	if (!have1pdb)
		msg = 

"<big><font color='red'><b>Authors: please list PDB codes and \n\
descriptions of the molecules shown in this tutorial in the file \n\
js4all/molecules.js!</b> The list will then appear here, with links \n\
for further exploration. (Alternatively, you can suppress this message \n\
with a setting in that file.)</font></big>";

	else
	{
		msg += "Explore further the molecule(s) in this Tutorial:<ul>\n" 

//			"using <a href='../../_docs/tutuse.htm#fgij' " +
//			"target='_blank'><i>FirstGlance in Jmol</i></a> or " +
//			"[<i><a href='http://proteopedia.org' " +
//			"target='_blank'>Proteopedia</a></i>]:" +
//		"<ul>\n";

		var moldis, molcoords, molchaps;

		var nextMolecule = 1;
		while (nextMolecule > 0)
		{
			if (typeof(moleculeCoordinates[nextMolecule]) == "undefined")
				break; // we're done

			molcoords = moleculeCoordinates[nextMolecule];
			if (molcoords.length == 0)
				break; // we're done

			// DESCRIPTION
			if (typeof(moleculeDescription[nextMolecule]) == "undefined")
				// we have a PDB code, so just leave the description blank
				moldis = "";
			else
				moldis = moleculeDescription[nextMolecule];

			// CHAPTERS
			if (typeof(moleculeChapters[nextMolecule]) == "undefined")
				// we have a PDB code, so just leave the chapters blank
				molchaps = "";
			else
				molchaps = moleculeChapters[nextMolecule];

			// CONSTRUCT REPORT

			// Punctuate end of description:
			if (moldis.length > 0)
				moldis += ": ";

			// molcoords types:
			// "1abc" = get it from the PDB, in Proteopedia.
			// "1abc_x.mmol" = from PQS; can see related PDB in Proteopedia. *
			// "blahblah.pdb" = unknown. *
			//    *can look in FirstGlance if tutorial is online
			//		getting PDB file from molecules4all.
			// molcoords will never be a URL. In order to list a atomic coordinate
			// file in JTAT, it must be in molecules4all.

			// Reject URL's.
			if (molcoords.indexOf("/") != -1 ||
				molcoords.indexOf(":") != -1)
			{
				alert("ERROR by Tutorial Author in js4all/molecules.js\n" +
					"moleculeCoordinates[" + nextMolecule + "]\n" +
					"(" + molcoords + ")\n" +
					"is not in the correct format. Please see the instructions\n" +
					"in js4all/molecules.js.");
				return "";
			}

			var ppda = "";
			var notpdb = "";
			var pdbid = "";
			var pdburl = "";
			var fgijurl = "";

			// is molcoords a PDB code?			
			if (isPDBCode(molcoords))
			{
				pdbid = molcoords;
			}

			else // not a pdb code
			{
				// If the first 4 characters of the filename are a PDB code, use it.
				if (isPDBCode(molcoords.substring(0, 4)))
					pdbid = molcoords.substring(0, 4);

				if (molcoords.indexOf(".mmol") != -1)
				{
					notpdb = " These <a " +
						"href=\"http://proteopedia.org/wiki/index.php/Atomic_coordinate_file\">" +
						"atomic coordinates</a> are a subset of, or are a specific oligomer " +
						"generated by symmetry operations from, the published <a " +
						"href=\"http://proteopedia.org/wiki/index.php/PDB_file\">" +
						"PDB file</a>. The coordinates were generated by the " +
						"<a href=\"http://pqs.ebi.ac.uk\">Probable Quaternary " +
						"Structure Server</a>.";
				}
				else
				{
					notpdb = " This molecule is not available, at least in the form " +
						"shown here, from the <a " +
						"href=\"http://proteopedia.org/wiki/index.php/Protein_Data_Bank\">" +
						"PDB</a>.";
				}

				pdburl = getPDBURL(molcoords);
			}

			// Make proteopedia link
			if (pdbid.length > 0)
			{
				ppda = "<a href='http://www.proteopedia.org/wiki/index.php/" +
				pdbid + "' target='_blank'><i>Proteopedia</i></a> " +
				"or in ";
			}

			// Make FGiJ URL:
			var fgijbase = "http://firstglance.jmol.org/fg.htm?mol=";
	
			// If there is a URL to an online file not avail from the PDB, use it:
			if (pdburl.length > 0)
				fgijurl = fgijbase + pdburl;
			// Otherwise, use the PDB code.
			else if (pdbid.length > 0)
				fgijurl = fgijbase + pdbid;
			// If offline, and no code, no URL.

			// Chapters in which molecules appear
			var tchaps = "";
			var schap = " ";
			if (molchaps.indexOf(",") != -1 || molchaps.indexOf(" ") != -1)
				schap = "s ";
			if (molchaps.length > 0)
				tchaps = " This molecule appears in Chapter" + schap + molchaps + ".";

			// Set color for PDB ID according to background color.
			var pdbRGB = "ffff00"; // yellow
			if (mainBackgroundColor == whiteRGB)
				pdbRGB = "ff8000"; // orange

			// Make PDB code or file text
			var pdbtext = "<b><font color='#" + pdbRGB + "'>";
			if (pdbid.length > 0)
				pdbtext +=  pdbid;
			else
				pdbtext +=  molcoords;
			pdbtext += "</font></b> in ";

			// Assemble final message.
			msg += "<li>" + moldis + pdbtext + ppda +
				"<a href='" + fgijurl +
				"' target='_blank'><i>FirstGlance&nbsp;in&nbsp;Jmol</i>" +
				"</a>. " +
				tchaps + notpdb +
				"</li>";

				nextMolecule++;
		}
		msg += "</ul>\n";
	}

	return msg;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function getPDBURL(molcoords)
{
	var pdburl;

				// Is our URL online? Does it lack "?"?
				// If yes and yes, we'll use it to build the URL to the PDB file.
				pdburl = document.location.href;
				if (pdburl.substring(0, 4) != "http" || pdburl.indexOf("?") != -1)
					pdburl = "";
				else
				{
					// Make PDB file URL for FirstGlance.
					// Typical starting URL:
					// http://www.bioinformatics.org/jmol-tutorials/jtat/jtatdemo/contents/contents.htm

					// remove last slash and what follows
					var islash = pdburl.lastIndexOf("/");
					pdburl = pdburl.substring(0, islash);

//					alert("util.js #8a pdburl:\n" + pdburl);

					// remove penultimate slash and what follows
					islash = pdburl.lastIndexOf("/");
					pdburl = pdburl.substring(0, islash);

					// Now we have the URL for the tutorial
					// http://www.bioinformatics.org/jmol-tutorials/jtat/jtatdemo

					pdburl += "/molecules4all/" + molcoords;
					pdburl = escape(pdburl); // convert : to %3A

				}

//	alert("util.js #8b pdburl:\n" + pdburl);

	return pdburl;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function getInitialViewNumber()
{
	var veq = "view=";
	var iveq = document.search.indexOf(veq);

	if (iveq == -1)
		return 1;

	var ivs = document.search.substring(iveq + veq.length);
	var ivn = parseInt(ivs);

	alert("util.js #9 ivs=" + ivs + " ivn=" + ivn);

	return (-1) * ivn;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// Angel's original simple demo of slabslider:
// http://biomodel.uah.es/Jmol/slab-slider/

function writeSlider()
{
	if (showSlabSlider || showZoomSlider)
		document.writeln(makeSlider());
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function makeSlider()
{
	var slsl = '';

	slsl +=
// style class slabslider is defined in resizabl.js
'<div id="slabSliderDiv" class="slabsliderdivclass'; // single quote unclosed!

	if (mainBackgroundColor == whiteRGB)
		slsl += ' lightgraybackground';
	else
		slsl += ' darkgraybackground';

	slsl += '">\n\
<table border="0" cellpadding="2" class="slabsliderfont"><tr>\n\
<td class="noborder">\n';

if (showSlabSlider && showZoomSlider)
{
	slsl +=
'<small style="font-weight: normal">\n\
<input type="radio" name="zoomslab" value="zoom" \n\
onClick="setSlidingAction(this.value)" checked>\
Zoom / '

+ slabSliderLabel +

'<input type="radio" name="zoomslab" value="slab" \n\
onClick="setSlidingAction(this.value)">\n\
</small>\n\
\n\
&nbsp; &nbsp;\n\
\n\
<span id="sliderLabel">Zoom</span>\n';

}
else if (showZoomSlider)
	slsl += 'Zoom\n';
else // Slab
	slsl += slabSliderLabel + '\n';

	slsl +=
'<img name="track" src="../../_imgutil/track.gif" width="104" height="29" \n\
alt="" title="" align="absmiddle"> \n\
<img name="thumb" src="../../_imgutil/sliderthumb.gif" width="18" height="29" \n\
alt="" title="move me" align="absmiddle">= <span id="posi">100</span>% \n\
<span id="zoomtimerdebug"></span><span id="zoomtimerstarteddebug"></span>\
<span id="memoryWatchSpan">\n\
</td></tr></table>\n\
</div>\n\
';

	return slsl;

}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function setSlidingAction(svalue)
{
	if (svalue == "slab")
	{
		var jcmd = "spin off; slab on;";
		if (previousSlidingAction == "slab")
		{
			jmolScript(jcmd, "all");
		}
		else // change from zoom to slab
		{
			jcmd += " slab " + slabPosition + ";";
//			alert("util.js #4 jcmd=\n" + jcmd);
			jmolScript(jcmd, "all");

			// force percent numerals to current slab value
			document.getElementById("posi").innerHTML= "" + slabPosition;

			var slabel =	"&nbsp;&nbsp;" + slabSliderLabel;
			if (slabSliderLabel.length == 3) // "Cut"
				slabel = "&nbsp; " + slabel;

			document.getElementById("sliderLabel").innerHTML = slabel;

			// move thumb to current slab position
			dd.elements.thumb.moveTo(
				eval("dd.elements.track.x+" + (100 - slabPosition)),
				dd.elements.track.y);
		}
	}
	else // zoom
	{
		jmolScript("slab off; zoom " + zoomValue + ";", "all");

		if (previousSlidingAction != "zoom") // slab to zoom
		{
			// force percent numerals to current slab value
			document.getElementById("posi").innerHTML= makeZoomValue();
			document.getElementById("sliderLabel").innerHTML= "Zoom";
	
			// move thumb to current slab position
			dd.elements.thumb.moveTo(
				eval("dd.elements.track.x+" + (zoomPosition)),
				dd.elements.track.y);
		}
	}
	previousSlidingAction = svalue;
	sliderMode = svalue; // redundant with previousSlidingAction, OK.
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// resetSlider() is called when a new view is displayed.
// It changes the slider mode to zoom, and resets zoom to 100% and slab
// to 50%.

function resetSlider()
{
	previousSlidingAction = "zoom";
	sliderMode = "zoom";
	zoomValue = 100;
	zoomPosition = startingZoomPosition;

	if (showZoomSlider)
	{
		// force percent numerals to 100%
		document.getElementById("posi").innerHTML= makeZoomValue();
		if (showSlabSlider)
			document.getElementById("sliderLabel").innerHTML= "Zoom";
	
		// move thumb to starting position
		dd.elements.thumb.moveTo(
			eval("dd.elements.track.x+" + (startingZoomPosition)),
			dd.elements.track.y);
	}

	if (showZoomSlider && showSlabSlider)
	{
		// reset radio buttons
		document.baseForm.zoomslab[0].checked = true;
	}

	// slab turned off in _sptutil/vreset.spt
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
/* Uses Walter Zorn's Drag'n'Drop & DHTML Library (GNU LGPL). 
	wz_dragdrop.js
   Integration with Jmol by Angel Herráez.
*/

function sliderAction()
{
	if (previousSlidingAction == "slab")
	{
		slabPosition =
			100 - (dd.elements.thumb.x - dd.elements.thumb.defx) - 10;
//		alert("util.js #3: slabPosition=" + slabPosition);

	  jmolScript( 'slab ' + slabPosition + ";", "all");
	
	  document.getElementById("posi").innerHTML = "" + slabPosition;
	}
	else // zoom
	{
		//zoom slider goes from 80% to 600% at scale breakpoint 10 = 100%
		zoomPosition =
			startingZoomPosition + dd.elements.thumb.x - dd.elements.thumb.defx;

		if (zoomPosition <= startingZoomPosition) 
			zoomValue = 80 + (2 * zoomPosition);
		else // >startingZoomPosition
		{
			zoomValue = 100 + ((zoomPosition - startingZoomPosition) * 4.444444);
			zoomValue = parseInt(zoomValue + 0.5);
		}

	  jmolScript( 'exit; zoom ' + zoomValue + ";", "all");
	
	  document.getElementById("posi").innerHTML = makeZoomValue();
	}
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// INLINE INITIALIZATION!

/*  Courtesy of Walter Zorn; 
	Drag'nDrop & DHTML Library  (c)Walter Zorn under the LGPL (Lesser General Public License, http://www.gnu.org/copyleft/lesser.html
*/

// must be called AFTER the slider is inserted!

function initSlider()
{

	if (showSlabSlider || showZoomSlider)
	{
	
//SET_DHTML("thumb"+MAXOFFLEFT+20+MAXOFFRIGHT+80+HORIZONTAL,"track"+NO_DRAG);

SET_DHTML("thumb"+MAXOFFLEFT+10+MAXOFFRIGHT+90+HORIZONTAL,"track"+NO_DRAG);

//dd.elements.thumb.moveTo(dd.elements.track.x+20, dd.elements.track.y);
dd.elements.thumb.moveTo(dd.elements.track.x+10, dd.elements.track.y); // startingZoomPosition

dd.elements.thumb.setZ(dd.elements.track.z+1);
dd.elements.track.addChild("thumb");

//dd.elements.thumb.defx = dd.elements.track.x+20; 
dd.elements.thumb.defx = dd.elements.track.x+10; // startingZoomPosition

dd.elements.thumb.setDragFunc(sliderAction);

//alternative, if it cannot cope with the other
//dd.elements.thumb.setDropFunc(sliderAction);

	}

}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function toggleAntialiasing()
{
	var link1 = '<a href="javascript: toggleAntialiasing()">Smoother ';
	var link2 = '</a>';

	if (jmolAntialiasing)
	{
		jmolScript("exit; set antialiasDisplay off; set antialiasTranslucent off;",
			"all");
		document.getElementById("smootherSpan").innerHTML =
			link1 + "Graphics" + link2;
		jmolAntialiasing = false;
	}
	else
	{
		jmolScript("exit; set antialiasDisplay on; set antialiasTranslucent on;", "all");
		document.getElementById("smootherSpan").innerHTML =
			link1 + "Rotation" + link2;
		jmolAntialiasing = true;
	}
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function setZoomValue() // slider
{
	if (!disablePolling)
	{
		if (!zoomAutoslideTimerStarted)
		{
			startZoomAutoslideTimer();
			zoomAutoslideTimerStarted = true;
			debugZoomAutoslideTimerStarted();
		}
	}

	if (lastMessagedZoomValue == viewZoomValue)
		return;

	lastMessagedZoomValue = viewZoomValue;

	zoomValue = viewZoomValue;
	getZoomPosition();

	if (sliderMode == "slab")
		return;

	if (showZoomSlider)
	{
		// force percent numerals to actual zoom
		document.getElementById("posi").innerHTML= makeZoomValue();
	
		// move thumb to starting position
		dd.elements.thumb.moveTo(
			eval("dd.elements.track.x+" + (zoomPosition)),
			dd.elements.track.y);

	}
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function getZoomPosition() // slider
{
	if (zoomValue == 100)
		zoomPosition = startingZoomPosition;

	if (zoomValue < 100)
		zoomPosition = (zoomValue - 80) / 2;

	if (zoomValue > 100)
// inverse of this calculation:
//			zoomValue = 100 + ((zoomPosition - startingZoomPosition) * 4.444444);
		zoomPosition = ((zoomValue - 100) / 4.444444) + startingZoomPosition;

	// round to integer
	zoomValue = parseInt(zoomValue + 0.5);
	zoomPosition = parseInt(zoomPosition + 0.5);

	if (zoomPosition > 100)
		zoomPosition = 100;

	if (zoomPosition < 0)
		zoomPosition = 0;

//	alert("util.js #5: zoomValue = " + zoomValue +
//		"\n zoomPosition = " + zoomPosition);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function setupSlider()
{
	writeSlider();
	initSlider();
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// checkZoomAutoslideValue() checks the current zoom level in Jmol 1 (only)
// every second. This enables the zoom slider to be automatically
// corrected after a zoom with the mouse.

function checkZoomAutoslideValue() // slider
{
	// No "exit" here! Otherwise it would kill a running movie before
	// the final zoom is achieved.

	// check zoom now
	var autospt =
		'message !  To use console, stop zoom polling by entering\n' +
		'message !  exit; javascript disablePolling=true;\n' +
		'message !  In downloaded JTAT, make it true in _jsutil/config2.js\n' +
		'message ' + viewZoomValueMsg + ';\n' +
		'show zoom;\n';

	jmolScript(autospt, 1);

	// check again after one second
	if (!disablePolling) // allow dynamic diabling from console
		startZoomAutoslideTimer();
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function makeZoomValue() // slider
{
	var zv = "" + zoomValue;
	if (parseInt(zoomValue) > maxZoomValue)
		zv = ">" + maxZoomValue;
	if (parseInt(zoomValue) < minZoomValue)
		zv = "<" + minZoomValue;
	return zv;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function startZoomAutoslideTimer()
{
	checkZoomAutoslideValueTimerHandle =
		setTimeout('checkZoomAutoslideValue()', zoomAutoSlidePollingInterval);

		// displays handle to right of zoom % numerals, for debugging.
	if (debugZoomAutoslideTimer)
		document.getElementById("zoomtimerdebug").innerHTML = 
			checkZoomAutoslideValueTimerHandle;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// for debugging:
// shows + when the timer is running, - when it is not (to right of zoom %).

function debugZoomAutoslideTimerStarted()
{
	if (!debugZoomAutoslideTimer)	
		return;

	var aflag = "-";
	if (zoomAutoslideTimerStarted)
		aflag = "+";

	document.getElementById("zoomtimerstarteddebug").innerHTML = aflag;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// centering mechanism:
// 

function processPickCallback(jmolId_, atomId_)
{
	var jmolId = "" + jmolId_;
	var atomId = "" + atomId_;

//	alert("util.js #10 pickCall: centerMode = " + centerMode +
//		"\n jmolId = " + jmolId +
//		"\n atomId = " + atomId);

	if (!centerMode)
		return;

	centerMode = false;
	document.jmolForm.checkcenter.checked = false;

	// get jmol ID number
	var jmolN = jmolId.charAt(jmolId.length - 1);

	// get atom serial number, following #
	var ipound = atomId.indexOf("#");
	if (ipound == -1)
		return;

	var atomSerial = atomId.substring(ipound + 1, atomId.indexOf(" ", ipound));

	var cspt = "exit;\n" +
		"set echo centerButton off;\n" +
		"set echo promptcenter off;\n";

	jmolScript(cspt, "all"); // turn off prompts in all Jmols.

	cspt = "zoomTo 1.5 (atomno=" + atomSerial + ") *1;";

	// In Win98 FF, this alert makes centering work. Without the alert,
	// centering does not work. So I put in the timeout.
//	alert("util.js #12\n" + cspt);

	// center only in the Jmol clicked.
	var toc = 'jmolScript("' + cspt + '", "' + jmolN + '")';
//	alert("util.js #13:\n" + toc);
	setTimeout(toc, 100);

	// When >1 jmol, turn off the centering invitation in the non-clicked ones.
	// Harmless when there is 1 jmol.
	// No exit here to avoid killing centering process.
	jmolScript("set echo promptcenter off;", "all"); // redundant for clicked Jmol
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function promptCenter()
{
	var jCount = buttons[currentButtonNumber][iJmolCount];
	var fontsize = 25;
	if (jCount > 1)
		fontsize = 22;
	if (jCount == 4)
		fontsize = 18;

//	var offcolor = "black";
//	if (mainBackgroundColor == whiteRGB)
//		offcolor = "white";

	var pcs = "exit;\n";

	if (centerModeUsed)
	{
		pcs += makeCenterAllButton();
	}

	// background translucent 1.0 counteracts the pan-echo background set
	// by makeCenterAllButton().

	pcs +=
		"set echo promptcenter 0% 85%;\n" +
//		"set echo promptcenter center;\n" +
//		"set echo promptcenter display;\n" +
		"font echo " + fontsize + " sans bold;\n" +
		"color echo red;\n" +
		"color echo background translucent 1.0 white;\n" +
		"echo Click Atom To Center;\n" +
		"delay 0.3;\n" +
		"color echo orange;\n" +
		"delay 0.3;\n" +
		"color echo red;\n" +
		"delay 0.3;\n" +
		"color echo orange;\n" +
		"delay 0.7;\n" +
		"set echo promptcenter off;\n"; // hidden = problem, needs redisplay

//		"color echo " + offcolor + ";\n"; +

//	alert("util.js #11 promptCenter:\n" + pcs);
	jmolScript(pcs, "all");
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function makeTroubleshootingLink()
{
	var tsl =
		'<div class="fontSizeLink">\n' +
		'Can\'t see the molecule? See \n' +
		'<a href="../../_docs/tutuse.htm#troubleshooting" target="_blank">Troubleshooting</a>' +
		'</div>\n';

	return tsl;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function makeCenterAllButton()
{
	var cas = '';

//	cas =
//'set echo centerButton IMAGE ' +
//
//'"../../_imgutil/green_arrow_small_transparent_l.gif";\n\
//set echo centerButton 50% 10%;\n\
//set echo centerButton center;\n\
//font echo 25;\n\
//set echo centerButton script "select protein; color red;";\n\

	cas = 
'#\n\
# BEGIN centerButton echo commands.\n\
# \n\
set echo centerButton 50% 0%;\n\
set echo centerButton center;\n\
color echo background translucent 0.8 white;\n\
echo " Click Here to Center All ";\n\
font echo 18 sansserif bold;\n\
set echo centerButton script "message RequestingDoCenterAll;";\n\
#\n\
# END centerButton echo commands.\n\
# \n\
';

	return cas;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function doCenterAll()
{
//	alert("util.js #7 doCenterAll()");

	document.jmolForm.checkcenter.checked = false;

	// unconditionally center all Jmols
	jmolScript("set echo centerButton off;zoomTo 1.5 (all) *1;", "all");
			
	// When >1 jmol, turn off the centering invitation in the non-clicked ones.
	// Harmless when there is 1 jmol.
	// No exit here to avoid killing centering process.
	jmolScript("set echo promptcenter off;", "all"); // redundant for clicked Jmol
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function isPDBCode(ppcode)
{
	ppcode = ppcode.toUpperCase();

	// LENGTH 4?
	if (ppcode.length != 4)
		return false;

	// NUMERAL IN FIRST POSITION?
	var c1 = ppcode.charAt(0);
	if (c1 < "0" || c1 > "9")
		return false;

	// REMAINDER ALPHANUMERIC?
	var ic;
	for (ic = 1; ic <= 3; ic++)
	{
		c1 = ppcode.charAt(ic);
		if (c1 < "0" || c1 > "Z")
			return false;
	}

	return true;		
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
