/*
 * This set of Javascript functions provides general utilities for the system. None
 * of the functions in this file are directly related to look and feel. It is strongly
 * recommended NOT to modify these functions.
 */

/*
 * Hook to be called whenever a page is loaded. 
 * Override this to provide functionality.
 */
function onLoad() {
  // Do nothing
}

/*
 * Hook to be called whenever a page is resized. 
 * Override this to provide functionality.
 */
function onResize() {
  // Do nothing
}

/*
 * Hook to be called whenever a page is left. 
 * Override this to provide functionality.
 */
function onUnload() {
  // Do nothing
}

/*
 * Hook to be called whenever a form is submitted.
 * Override this to provide functionality.
 */
function onSubmit() {
  return true;
}

/*
 * This is the basic action-delegation method called to submit forms to EDU.
 * Most button clicks result in a call to this function.
 */
function doAction(action) {
  var frm = document.forms["edu_form"];
  frm.elements.actionID.value = action;
  if (onSubmit()) {
    frm.submit();
  }
}

/*
 * Read a question response from a Java applet that conforms to the contract of
 * Java question type.
 */
function readAppletItems() {
  var form = document.edu_form;
  var elts = form.elements;
  var pattern = /ans\.(\d+)\.(\d+)/;
  for (var i=0; i<elts.length; i++) {
    var name = elts[i].name;
    if (name.match(pattern) != null) {
      var appl = document[name + ".sro"];
      var resp = null;
      if (appl != null) {
        resp = new String(appl.getResponse());
      } else if ((appl = document[name + ".swf"]) != null) {
        resp = new String(appl.GetVariable("response"));
      }
      if (resp != null) {
        form.elements[i].value = resp;
        if (resp.indexOf("error:") == 0) {
          var errm = resp.substring(6,resp.length);
          if (! confirm(errm)) {
            appl.requestFocus();
            return false;
          }
        }
      }
    }
  }
  return true;
}

/*
 * Return the root URL for the server.
 */
function getBaseURL() {
  var markers = new Array("modules", "classes");
  var loc = window.location; 
  var path = loc.pathname;
  //baseURL is set in frame.html from the cgi var "server url"
  var baseurl = (baseURL != null ? baseURL : "http://" + loc.host);
  //this commented block is not necessary, now that the cgi variable server_url
  //is being used, as this will already contain the proxy url, if it exists
  /*
  for (var i = 0; i<markers.length; i++) {
    var k = path.lastIndexOf("/" + markers[i]);
    if (k != -1) {
      var base = path.substring(0, k);
      return baseurl + base;
    }
  }
  */
  return baseurl;
}

/*
 * Redirect the window to the home page for the ambient class.
 */
function toClassPage() {
  var w = window;
  if (window.parent.frames.controlbar != null) {
    w = window.parent.opener;
  }
  if (w != null) {
	  if (className != "") {
		w.location = "registration.Redirect?className=" + className;
	  } else {
		w.location = getBaseURL();
	  }
	  w.focus();
  }
  if (window.parent.frames.controlbar != null) {
    window.parent.close();
  }
}

/*
 * Draw the content of a popup hints window.
 */
function showHint(hint,hintRef) {
  var w = window.open("", "hints", "width=500,height=300,resizable,scrollbars");
  var d = w.document;
  d.open("text/html");
  d.writeln("<HTML>");
  d.writeln("  <BODY>");
  d.writeln("    <FORM ACTION=\"proctoredTest.ShowHint\" METHOD=\"post\">");
  d.writeln("      <INPUT TYPE=\"hidden\" NAME=\"className\" VALUE=\"" + className + "\">");
  d.writeln("      <INPUT TYPE=\"hidden\" NAME=\"login\" VALUE=\"" + login + "\">");
  d.writeln("      <INPUT TYPE=\"hidden\" NAME=\"hintRef\" VALUE=\"" + hintRef + "\">");
  d.writeln("      <INPUT TYPE=\"hidden\" NAME=\"hint\" VALUE=\"" + hint + "\">");
  d.writeln("    </FORM>");
  d.writeln("  </BODY>");
  d.writeln("</HTML>");
  d.close();
  d.forms[0].submit();
  w.focus();
}

/*
 * Provide help for a user in one of the system roles of instructor, student, administrator, or proctor.
 */
function getHelp(what) {
  var winspec = "scrollbars,resizable,width=800,height=600";
  var help;
  // The definitions of the help urls are in helpURLs.js
  if (what == "instructor") {
    help = INSTRUCTOR_HELP_URL;
  } else if (what == "administrator") {
    help = SYSADMIN_HELP_URL;
  } else if (what == "proctor") {
    help = PROCTOR_HELP_URL;
  } else if (what == "inline_editor") {
    help = INLINE_EDITOR_HELP_URL;
  } else if (what == "math_symbol_mode") {
    help = MATH_SYMBOL_MODE_HELP_URL;
  } else if (what == "math_text_mode") {
    help = MATH_TEXT_MODE_HELP_URL;
  } else if (what == "chem_symbol_mode") {
    help = CHEM_SYMBOL_MODE_HELP_URL;
  } else if (what == "chem_text_mode") {
    help = CHEM_TEXT_MODE_HELP_URL;
  } else {
    help = ASSIGNMENT_TYPE_HELP_URL;
  }
  window.open(getBaseURL() + help, "helpWindow", winspec);
}

/*
 * Set the crumb trail for the current page. Depending on the look and feel of the system,
 * this function may not server any purpose.
 */
function setCrumbTrail(trail) {
  var t;
  if (document.getElementById && (t = document.getElementById("crumb_trail"))) {
    t.innerHTML = trail;
  }
}

/*
 * Utility method. Not called from outside this package.
 */
function getMaplePlotURL(maple, plot, type, libname, driver) {
  var url =
    getBaseURL() + "modules/mapleTA.plotserver.PlotServer"
    + "?maple=" + myEscape(maple)
    + (plot != null ? "&plot=" + myEscape(plot) : "")
    + (type != null ? "&type=" + myEscape(type) : "")
    + (libname != null ? "&libname=" + myEscape(libname) : "")
	+ ((driver == null || driver.length ==0) ? "" : "&plotdriver=" + myEscape(driver));
  return url;
}

/*
 * Create a plot using the provided Maple code.
 * Utility method. Not called from outside this package.
 */
function drawMaplePlot(maple, width, height, libname, driver) {
  var url = getMaplePlotURL(maple, null, null, libname, driver);
  document.write("<IMG ");
  document.write("SRC=\"" + url + "\" ");
  if (width == null) {
    width = 480;
  } 
  if (height == null) {
    height = 360;
  }
  document.write("WIDTH=" + width + " ");
  document.write("HEIGHT=" + height);
  document.write(">");
}

/*
 * Create a popup plot of Maple code.
 */
function popupMaplePlot(maple, plot, type, libname, driver) {
  var url = getMaplePlotURL(maple, plot, type, libname, driver);
  var w = window.open("", "maplepopup", "width=500,height=380,scrollbars=no,resizable=no");
  var d = w.document;
  d.open("text/html");
  d.writeln("<HTML>");
  d.writeln("<HEAD>");
  d.writeln("</HEAD>");
  d.writeln("<BODY>");
  d.writeln("<IMG SRC=\"" + url + "\" WIDTH=480 HEIGHT=360 NAME=plot>");
  d.writeln("</BODY>");
  d.writeln("</HTML>");
  d.close();
  w.focus();
}

/*
 * Utility method to perform URL escaping since there are problems with the Javascript 
 * built-in function.
 */
function myEscape(s) {
  var a = escape(s);
  var b = "";
  for (i=0; i<a.length; i++) { // escape() doesn't handle '+' chars properly
    if (a.charAt(i) == "+") {
      b += "%2B";
    } else {
      b += a.charAt(i);
    }
  }
  return b;
}

/*
 * Generate a popup message
 */
function popupMessage(msg) {
  var w = window.open("", "popup", "width=500,height=380,scrollbars=no,resizable=no,status=no,location=no,dependent=yes");
  var d = w.document;
  d.open("text/html");
  d.writeln("<HTML>");
  d.writeln("<HEAD>");
  d.writeln("</HEAD>");
  d.writeln("<BODY>");
  d.writeln('<TABLE ALIGN="CENTER">');
  d.writeln('<TR VALIGN="CENTER"><TD>');
  d.writeln(msg);
  d.writeln('</TD></TR>');
  d.writeln('</TABLE>');
  d.writeln("</BODY>");
  d.writeln("</HTML>");
  d.close();
  w.focus();
}

var _preview = null;
var _previewEq = null;

function previewFormula(f) {
  var platf = navigator.platform;
  var useJava = (platf != null)  && (platf.indexOf("Win32") == 0 || platf.indexOf("Linux") == 0);
  
  _previewEq = null;
  _previewEq = f;
  
  if (useJava) {
    if (_preview == null || _preview.closed) {
      _preview = window.open("", "previewer", "previewer", "scrollbars,resizable");
      if (_preview.setEquation != null) {
	_preview.setEquation(f);
      } else {
	_preview = window.open(getBaseURL() + "modules/preview/", "previewer");
	_preview.resizeTo(350,200);
      }
      window.focus();
    } else {
      _preview.setEquation(f);
    }
  } else {
    var b = myEscape(f);
    window.open("preview.Preview?eq=" + b, "previewer", "width=300,height=175,resizable");
  }
}

function previewChemistry(f) {
  var b = myEscape(f);
  window.open("preview.Preview?actionID=chemistry&eq=" + b, "previewer", "width=300,height=175,resizable");
}

/*
 * Holds a pointer to an inline question's webeq input control applet.
 * Used by popupMathToolbar() (below) and the JS in mathEditor/toolbar.html.
 */
var _math_toolbar_target;

/*
 * Pop up a toolbar window which writes templates to a webeq IC. Used
 * by the Inline question.
 */
function popupMathToolbar(name) {
  _math_toolbar_target = document[name + ".sro"];
  window.open("mathEditor/toolbar.html", "math_editor_toolbar", "width=240,height=50").focus();
}

/*
 * Pop up a toolbar window which writes templates to a webeq IC. Used
 * by the Inline question.
 */
function popupChemToolbar(name) {
  _math_toolbar_target = document[name + ".sro"];
  window.open("mathEditor/chem_toolbar.html", "math_editor_toolbar", "width=240,height=50").focus();
}

/*
 * Popup describing EDU server, version, etc.
 */
function aboutPopup() {
  window.open("diagnostics.Version", "version_info", "width=500,height=300,resizable,scrollbars");
}

/*
 * Warning that the session timeout is close to expiring.
 */
function warnOfImminentSessionTimeout(k) {
  clearInterval(_sessionTimeoutTimerID);
  var timestamp = new Date();
  self.focus();
  window.focus();
  alert("DISCONNECTION WARNING\n\n"
        + "You may be in danger of losing your work on this page. The internet server\n"
        + "that sent this question to you needs a reply. To save your work and continue\n"
        + "working, do the following within the next "  + (k/(60*1000)) + " minutes:\n\n"
        + "1) Click the Next or Back button above.\n\n"
        + "2) When the new question appears, click the Back or Next button to return to this\n"
        + "question.  Your work will be saved and you can then continue to enter responses\n"
        + "on this page.\n\n"
        + "(If the Next or Back buttons are greyed out, click the Save & Quit button.  You\n"
		+ "will have to log-in again to return to this question, but your work will be preserved.)\n\n"
		+ "Message time: " + (new Date()).toLocaleString());
}

var _sessionTimeoutTimerID = 0;

function startSessionTimeoutWarningTimer(timeout) {
  var k = 5*60*1000;
  var t = timeout - k;
  if (t < 0) {
    t = timeout/2;
  }
  _sessionTimeoutTimerID = setInterval("warnOfImminentSessionTimeout(" + k + ")", t);
}

/*
 *  Get a handle to the object matching the given name
 */
function findObj(n, d) {
  var p,i,x;
  if(!d)
  	d=document;
  if((p=n.indexOf("?")) > 0 && parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document;
    n=n.substring(0,p);
  }
  if(!(x=d[n]) && d.all) x=d.all[n];
  	for (i=0; !x && i < d.forms.length; i++)
		x = d.forms[i][n];
	for(i=0; !x && d.layers && i < d.layers.length; i++)
		x = findObj(n,d.layers[i].document);
	if(!x && d.getElementById)
		x = d.getElementById(n);
	
	return x;
}

/*
 *  Change the visibility of the style element to be hidden
 */
function hide(objName) {
    obj = findObj(objName);
    if (obj.style) {
	obj.style.visibility='hidden';
    }
}

/*
 *  Change the visibility of the style element to be visible
 */
function show(objName) {
    obj = findObj(objName);
    if (obj.style) {
	obj.style.visibility='visible';
    }
}
