//JavaScript for explanatory windows on client side maps
//Set up browser-dependent parameters for the new windows. The challenge is 
//to position appropriately sized explanatory windows on screen for a range
//of screen sizes, resolutions, browser types and version numbers.
var bn, sw, sh;       //browser type, screen width and height
var ex, ey;           //mouseover event location
var sx=0, sy=0;       //scroll position [Netscape only]
var newwindow;        //pop-up window for explanatory text
var tempwindow;       //pop-up window for diagrams etc
var testwindow;       //pop-up window for self-assessment tests
var offset;           //horizontal offset for pop-up windows
var bv=parseInt(navigator.appVersion);
//bn=1 for old browser, 2 for Netscape, 3 for Microsoft, bv = version no.
if (bv < 4) {window.alert("Please update your browser to fully exploit this website. We recommend Netscape version 4.5 or better."); bn=1; sw=640; sh=400} else {sw=screen.width; sh=screen.height};
if (navigator.appName == "Netscape") {bn=2}
if (navigator.appName == "Microsoft Internet Explorer") {bn=3}
var ww=Math.ceil(sw/2.2); //pop-up window width in pixcels
var wh=105;               //pop-up window default height
var hsos=Math.ceil(sw/2); //half screen offset in pixcels
var lh=Math.ceil(sh/30);  //message line height in pixcels
var specs="toolbar=no,directories=no,resizable,width=";
var keyflag=true;
//
//The following function displays explanatory text within
//a new adjustable window in response to mouseover events. 
function Display(ex, ey, key, msg) {
var chars=msg.length;
var lines=Math.ceil(chars/50);
if (key != 0) {lines ++}
wh=Math.ceil(lh*lines);
var moreH=",height=" + wh;
var moreX;
if (ex<=hsos) {offset=sw-ww-10;} else {offset=0};
if (bn==2) {sx=window.pageXOffset; ex -= sx; moreX=",screenX="+offset;}
else moreX=",left="+offset;
var fullspec = specs + ww + moreH + moreX
if (newwindow!=null) {
if (newwindow.closed!=true) {newwindow.close();}}
newwindow = window.open("","brief",fullspec);
newwindow.document.open();
newwindow.document.writeln('<HEAD><SCRIPT>');
newwindow.document.writeln('document.onkeydown = function() {opener.keyflag=false;}');
newwindow.document.writeln('</SCRIPT><STYLE>');
newwindow.document.writeln('<!--');
newwindow.document.writeln('BODY {');
if (bn==2) {newwindow.document.writeln('}')} else {
newwindow.document.writeln('margin: 6pt; border: inset 1.5pt}')}
newwindow.document.writeln('-->');
newwindow.document.writeln('</STYLE></HEAD>');
newwindow.document.writeln('<BODY onResize="opener.Bodger();">');
if (key > 0) {newwindow.document.writeln('<FONT COLOR="FF0000">THIS IS CORE MATERIAL! </FONT>')}
newwindow.document.writeln(msg);
if (key < 0) {newwindow.document.writeln('<FONT COLOR="0000FF"> (Background information.)</FONT>')}
newwindow.document.writeln('</BODY>');
newwindow.document.close();
}
//The following function clears the message on mouse out, 
//unless a key has been pressed.
function RubOut() {
if (keyflag) {newwindow.close()}
else {keyflag=true}
}
//The following function modifies the message space estimates
//after the user has manually re-sized a message window. It is
//called from within the child window, but runs in the parent.
function Bodger() {
var nww=newwindow.innerWidth;
var nwh=newwindow.innerHeight;
ww = nww;
lh = lh * nwh / wh;
}

function OpenWindow(url) {
newwindow = window.open(url,"nat","resizable,width=400,height=400")}

//Temporary window. This function opens a new window in a "distant" area of the screen with
//the specified dimensions and displays the additional resources specified in "filename".
function TempWindow(ex, ey, xdim, ydim, filename) {
if (tempwindow!=null) {
if (tempwindow.closed!=true) {tempwindow.close();}}
if (ex<=hsos) {offset=sw-xdim-10;} else {offset=0};
var tempspec="width="+xdim+",height="+ydim+",left="+offset;
tempwindow = window.open("","temporary",tempspec);
tempwindow.location.href=filename; 
return true;
}

function ShutIt() {
tempwindow.close();}

function Dummy(A,B,C,D) {
return true;}

//Mini self-assessment tests. This function opens a new window in a "distant" area of the screen
//and displays the self-test materials specified in "filename".
function MiniTest(ex, filename) {
if (testwindow!=null) {
if (testwindow.closed!=true) {testwindow.close();}}
if (ex<=hsos) {offset=sw-460;} else {offset=0};
var testspec="resizable,width=450,height=400,left="+offset;
testwindow = window.open("","selftest",testspec);
testwindow.location.href=filename; 
return true;
}

//Self-assessment test marking: "instr" is the list of correct answers
//and "full" controls the amount of detail in the remedial text
function marktest(fname) {
var fmax = document.forms.length;
for (var iname=0; iname<fmax; iname++) {
var tname = document.forms[iname].name;
if (tname == fname) {break;}
}
var maxfield=document.forms[iname].elements.length - 1;
var alist = document.forms[iname].instr.value.split(",");
var prolix = document.forms[iname].full.selectedIndex;
var elist="";
var errcount=0;
for (var field=0; field<maxfield; field++) {
var temp = document.forms[iname].elements[field].value;
//break out if we have reached the end of the questions and answers
if (temp == "Submit Answers") {break;}
//check for drop down menus with selectable options
if (temp == null) {temp = document.forms[iname].elements[field].selectedIndex;}
if (alist[field] != temp)
{numb=field+1; elist=elist + numb + " "; errcount++;}
}
if (prolix==0) {
switch(errcount) {
case 0:
alert("No mistakes"); break;
case 1:
alert("One mistake"); break;
default:
alert("You made "+errcount+" mistakes");
}}
else if (prolix==1) {
switch(errcount) {
case 0:
alert("No mistakes"); break;
case 1:
alert("One mistake in field "+elist); break;
default:
alert("Mistakes in fields "+elist);
}}
else if (prolix=2) {
switch(errcount) {
case 0:
alert("No mistakes"); break;
default:
//First parse the remedial text for this form into an array of feedback
//strings and a matching array of error indicators. Each element in the
//indicator array is itself an array of error numbers, so that each error
//number may call forth several remedial strings, and each remedial string
//may match several different error numbers.
var feedback = document.forms[iname].feedbk.value;
if (feedback=="") {
alert("No feedback for this form. Error(s) in field(s) "+elist); break;
}
var lastchar = feedback.length;
var indicate = new Array();
var fstrings = new Array();
var tcnt1=0, tcnt2=0, tcnt3=0;
for (var mescnt = 0; mescnt<maxfield; mescnt++) {
tcnt1 = feedback.indexOf("{",tcnt3);
if (tcnt1 == -1) {alert("format error A"); return(false);};
tcnt2 = feedback.indexOf("}",tcnt1);
if (tcnt2 == -1) {alert("format error B"); return(false);};
indicate[mescnt] = feedback.slice(tcnt1+1,tcnt2);
tcnt3 = feedback.indexOf("{",tcnt2);
if (tcnt3 == -1) {break;}
fstrings[mescnt] = feedback.slice(tcnt2+1,tcnt3);
}
fstrings[mescnt] = feedback.slice(tcnt2+1,lastchar);
var maxmes=mescnt;

//Work though the list of error numbers, comparing each one against the
//indicator array. If they match, append the remedial text to the output. 
var blist=elist.split(" ");
var laste=blist.length-1;
for (var ecnt=0; ecnt<laste; ecnt++) {
var fldnum = blist[ecnt];
var rstring = "";
for (mescnt=0; mescnt<maxmes+1; mescnt++){
var clist=indicate[mescnt].split(",");
var lasti=indicate[mescnt].length;
for (var icnt=0; icnt<lasti; icnt++) {
if (fldnum==clist[icnt]) {rstring=rstring+fstrings[mescnt];}
}
}
alert("Error in field "+fldnum+": "+rstring);
}
}
}
else	{alert("not ready yet");}
}

function clearout(fname) {
fmax = document.forms.length;
for (iname=0; iname<fmax; iname++) {
tname = document.forms[iname].name;
if (tname == fname) {break;}
}
maxfield=document.forms[iname].elements.length - 1;
for (field=0; field<maxfield; field++) {
temp = document.forms[iname].elements[field].value;
if (temp == "Submit Answers") {break;}
document.forms[iname].elements[field].value=0;
}
}


