Subversion Repositories wimsdev

Rev

Rev 17 | Rev 2876 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /* Jmol 11.7 script library Jmol.js  15:32 06.12.2008 Bob Hanson
  2.  
  3.  checkbox heirarchy -- see http://chemapps.stolaf.edu/jmol/docs/examples-11/check.htm
  4.  
  5.     based on:
  6.  *
  7.  * Copyright (C) 2004-2005  Miguel, Jmol Development, www.jmol.org
  8.  *
  9.  * Contact: hansonr@stolaf.edu
  10.  *
  11.  *  This library is free software; you can redistribute it and/or
  12.  *  modify it under the terms of the GNU Lesser General Public
  13.  *  License as published by the Free Software Foundation; either
  14.  *  version 2.1 of the License, or (at your option) any later version.
  15.  *
  16.  *  This library is distributed in the hope that it will be useful,
  17.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19.  *  Lesser General Public License for more details.
  20.  *
  21.  *  You should have received a copy of the GNU Lesser General Public
  22.  *  License along with this library; if not, write to the Free Software
  23.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  24.  *  02111-1307  USA.
  25.  */
  26.  
  27. // for documentation see www.jmol.org/jslibrary
  28.  
  29. try{if(typeof(_jmol)!="undefined")exit()
  30.  
  31. // place "?NOAPPLET" on your command line to check applet control action with a textarea
  32. // place "?JMOLJAR=xxxxx" to use a specific jar file
  33.  
  34. // bob hanson -- jmolResize(w,h) -- resizes absolutely or by percent (w or h 0.5 means 50%)
  35. // bob hanson -- jmolEvaluate -- evaluates molecular math 8:37 AM 2/23/2007
  36. // bob hanson -- jmolScriptMessage -- returns all "scriptStatus" messages 8:37 AM 2/23/2007
  37. // bob hanson -- jmolScriptEcho -- returns all "scriptEcho" messages 8:37 AM 2/23/2007
  38. // bob hanson -- jmolScriptWait -- 11:31 AM 5/2/2006
  39. // bob hanson -- remove trailing separatorHTML in radio groups -- 12:18 PM 5/6/2006
  40. // bob hanson -- adds support for dynamic DOM script nodes 7:04 AM 5/19/2006
  41. // bob hanson -- adds try/catch for wiki - multiple code passes 7:05 AM 5/19/2006
  42. // bob hanson -- auto-initiates to defaultdir/defaultjar -- change as desired.
  43. // bob hanson -- adding save/restore orientation w/ and w/o delay 11:49 AM 5/25/2006
  44. // bob hanson -- adding AjaxJS service 11:16 AM 6/3/2006
  45. // bob hanson -- fix for iframes not available for finding applet
  46. // bob hanson -- added applet fake ?NOAPPLET URL flag
  47. // bob hanson -- added jmolSetCallback(calbackName, funcName) 3:32 PM 6/13/2006
  48. //                      used PRIOR to jmolApplet() or jmolAppletInline()
  49. //               added 4th array element in jmolRadioGroup -- title
  50. //               added <span> and id around link, checkbox, radio, menu
  51. //               fixing AJAX loads for MSIE/Opera-Mozilla incompatibility
  52. //            -- renamed Jmol-11.js from Jmol-new.js; JmolApplet.jar from JmolAppletProto.jar
  53. //               renamed Jmol.js for Jmol 11 distribution
  54. //            -- modified jmolRestoreOrientation() to be immediate, no 1-second delay
  55. // bob hanson -- jmolScriptWait always returns a string -- 11:23 AM 9/16/2006
  56. // bh         -- jmolCommandInput()
  57. // bh         -- jmolSetTranslation(TF) -- forces translation even if there might be message callback issues
  58. // bh         -- minor fixes suggested by Angel
  59. // bh         -- adds jmolSetSyncId() and jmolGetSyncId()
  60. // bh 3/2008  -- adds jmolAppendInlineScript() and jmolAppendInlineArray()
  61. // bh 3/2008  -- fixes IE7 bug in relation to jmolLoadInlineArray()
  62. // bh 6/2008  -- adds jmolSetAppletWindow()
  63. // Angel H. 6/2008  -- added html <label> tags to checkboxes and radio buttons [in jmolCheckbox() and _jmolRadio() functions]
  64. // bh 7/2008  -- code fix "for(i..." not "for(var i..."
  65. // bh 12/2008 -- jmolLoadInline, jmolLoadInlineArray, jmolLoadInlineScript, jmolAppendInlineScript, jmolAppendInlineArray all return error message or null (Jmol 11.7.16)
  66. // bh 12/2008 -- jmolScriptWaitOutput() -- waits for script to complete and delivers output normally sent to console
  67.  
  68. var defaultdir = "."
  69. var defaultjar = "JmolApplet.jar"
  70.  
  71.  
  72. // Note added 12:41 PM 9/21/2008 by Bob Hanson, hansonr@stolaf.edu:
  73.  
  74. // JMOLJAR=xxxxx.jar on the URL for this page will override
  75. // the JAR file specified in the jmolInitialize() call.
  76.  
  77. // The idea is that it can be very useful to test a web page with different JAR files
  78. // Or for an expert user to substitute a signed applet for an unsigned one
  79. // so as to use a broader range of models or to create JPEG files, for example.
  80.  
  81. // If the JAR file is not in the current directory (has any sort of "/" in its name)
  82. // then the user is presented with a warning and asked whether it is OK to change Jar files.
  83. // The default action, if the user just presses "OK" is to NOT allow the change.
  84. // The user must type the word "yes" in the prompt box for the change to be approved.
  85.  
  86. // If you don't want people to be able to switch in their own JAR file on your page,
  87. // simply set this next line to read "var allowJMOLJAR = false".
  88.  
  89.  
  90. var allowJMOLJAR = true  
  91.  
  92.  
  93. var undefined; // for IE 5 ... wherein undefined is undefined
  94.  
  95. ////////////////////////////////////////////////////////////////
  96. // Basic Scripting infrastruture
  97. ////////////////////////////////////////////////////////////////
  98.  
  99. function jmolInitialize(codebaseDirectory, fileNameOrUseSignedApplet) {
  100.   if (_jmol.initialized)
  101.     return;
  102.   _jmol.initialized = true;
  103.   if(allowJMOLJAR && document.location.search.indexOf("JMOLJAR=")>=0) {
  104.     var f = document.location.search.split("JMOLJAR=")[1].split("&")[0];
  105.     if (f.indexOf("/") >= 0) {
  106.       alert ("This web page URL is requesting that the applet used be " + f + ". This is a possible security risk, particularly if the applet is signed, because signed applets can read and write files on your local machine or network.")
  107.       var ok = prompt("Do you want to use applet " + f + "? ","yes or no")
  108.       if (ok == "yes") {
  109.         codebaseDirectory = f.substring(0, f.lastIndexOf("/"));
  110.         fileNameOrUseSignedApplet = f.substring(f.lastIndexOf("/") + 1);
  111.       } else {
  112.         _jmolGetJarFilename(fileNameOrUseSignedApplet);
  113.         alert("The web page URL was ignored. Continuing using " + _jmol.archivePath + ' in directory "' + codebaseDirectory + '"');
  114.       }
  115.     } else {
  116.       fileNameOrUseSignedApplet = f;
  117.     }
  118.   }
  119.   _jmolSetCodebase(codebaseDirectory);
  120.   _jmolGetJarFilename(fileNameOrUseSignedApplet);
  121.   _jmolOnloadResetForms();
  122. }
  123.  
  124. function jmolSetTranslation(TF) {
  125.   _jmol.params.doTranslate = ''+TF;
  126. }
  127.  
  128. function _jmolGetJarFilename(fileNameOrFlag) {
  129.   _jmol.archivePath =
  130.     (typeof(fileNameOrFlag) == "string"  ? fileNameOrFlag : (fileNameOrFlag ?  "JmolAppletSigned" : "JmolApplet") + "0.jar");
  131. }
  132.  
  133. function jmolSetDocument(doc) {
  134.   _jmol.currentDocument = doc;
  135. }
  136.  
  137. function jmolSetAppletColor(boxbgcolor, boxfgcolor, progresscolor) {
  138.   _jmolInitCheck();
  139.   _jmol.params.boxbgcolor = boxbgcolor;
  140.   if (boxfgcolor)
  141.     _jmol.params.boxfgcolor = boxfgcolor
  142.   else if (boxbgcolor == "white" || boxbgcolor == "#FFFFFF")
  143.     _jmol.params.boxfgcolor = "black";
  144.   else
  145.     _jmol.params.boxfgcolor = "white";
  146.   if (progresscolor)
  147.     _jmol.params.progresscolor = progresscolor;
  148.   if (_jmol.debugAlert)
  149.     alert(" boxbgcolor=" + _jmol.params.boxbgcolor +
  150.           " boxfgcolor=" + _jmol.params.boxfgcolor +
  151.           " progresscolor=" + _jmol.params.progresscolor);
  152. }
  153.  
  154. function jmolSetAppletWindow(w) {
  155.   _jmol.appletWindow = w;
  156. }
  157.  
  158. function jmolApplet(size, script, nameSuffix) {
  159.   _jmolInitCheck();
  160.   return _jmolApplet(size, null, script, nameSuffix);
  161. }
  162.  
  163. ////////////////////////////////////////////////////////////////
  164. // Basic controls
  165. ////////////////////////////////////////////////////////////////
  166.  
  167. function jmolButton(script, label, id, title) {
  168.   _jmolInitCheck();
  169.   if (id == undefined || id == null)
  170.     id = "jmolButton" + _jmol.buttonCount;
  171.   if (label == undefined || label == null)
  172.     label = script.substring(0, 32);
  173.   ++_jmol.buttonCount;
  174.   var scriptIndex = _jmolAddScript(script);
  175.   var t = "<span id=\"span_"+id+"\""+(title ? " title =\"" + title + "\"":"")+"><input type='button' name='" + id + "' id='" + id +
  176.           "' value='" + label +
  177.           "' onClick='_jmolClick(" + scriptIndex + _jmol.targetText +
  178.           ")' onMouseover='_jmolMouseOver(" + scriptIndex +
  179.           ");return true' onMouseout='_jmolMouseOut()' " +
  180.           _jmol.buttonCssText + "/></span>";
  181.   if (_jmol.debugAlert)
  182.     alert(t);
  183.   return _jmolDocumentWrite(t);
  184. }
  185.  
  186. function jmolCheckbox(scriptWhenChecked, scriptWhenUnchecked,
  187.                       labelHtml, isChecked, id, title) {
  188.   _jmolInitCheck();
  189.   if (id == undefined || id == null)
  190.     id = "jmolCheckbox" + _jmol.checkboxCount;
  191.   ++_jmol.checkboxCount;
  192.   if (scriptWhenChecked == undefined || scriptWhenChecked == null ||
  193.       scriptWhenUnchecked == undefined || scriptWhenUnchecked == null) {
  194.     alert("jmolCheckbox requires two scripts");
  195.     return;
  196.   }
  197.   if (labelHtml == undefined || labelHtml == null) {
  198.     alert("jmolCheckbox requires a label");
  199.     return;
  200.   }
  201.   var indexChecked = _jmolAddScript(scriptWhenChecked);
  202.   var indexUnchecked = _jmolAddScript(scriptWhenUnchecked);
  203.   var eospan = "</span>"
  204.   var t = "<span id=\"span_"+id+"\""+(title ? " title =\"" + title + "\"":"")+"><input type='checkbox' name='" + id + "' id='" + id +
  205.           "' onClick='_jmolCbClick(this," +
  206.           indexChecked + "," + indexUnchecked + _jmol.targetText +
  207.           ")' onMouseover='_jmolCbOver(this," + indexChecked + "," +
  208.           indexUnchecked +
  209.           ");return true' onMouseout='_jmolMouseOut()' " +
  210.           (isChecked ? "checked " : "") + _jmol.checkboxCssText + "/>"
  211.   if (labelHtml.toLowerCase().indexOf("<td>")>=0) {
  212.         t += eospan
  213.         eospan = "";
  214.   }
  215.   t += "<label for=\"" + id + "\">" + labelHtml + "</label>" +eospan;
  216.   if (_jmol.debugAlert)
  217.     alert(t);
  218.   return _jmolDocumentWrite(t);
  219. }
  220.  
  221. function jmolStartNewRadioGroup() {
  222.   ++_jmol.radioGroupCount;
  223. }
  224.  
  225. function jmolRadioGroup(arrayOfRadioButtons, separatorHtml, groupName, id, title) {
  226.   /*
  227.  
  228.     array: [radio1,radio2,radio3...]
  229.     where radioN = ["script","label",isSelected,"id","title"]
  230.  
  231.   */
  232.  
  233.   _jmolInitCheck();
  234.   var type = typeof arrayOfRadioButtons;
  235.   if (type != "object" || type == null || ! arrayOfRadioButtons.length) {
  236.     alert("invalid arrayOfRadioButtons");
  237.     return;
  238.   }
  239.   if (separatorHtml == undefined || separatorHtml == null)
  240.     separatorHtml = "&nbsp; ";
  241.   var len = arrayOfRadioButtons.length;
  242.   jmolStartNewRadioGroup();
  243.   if (!groupName)
  244.     groupName = "jmolRadioGroup" + (_jmol.radioGroupCount - 1);
  245.   var t = "<span id='"+(id ? id : groupName)+"'>";
  246.   for (var i = 0; i < len; ++i) {
  247.     if (i == len - 1)
  248.       separatorHtml = "";
  249.     var radio = arrayOfRadioButtons[i];
  250.     type = typeof radio;
  251.     if (type == "object") {
  252.       t += _jmolRadio(radio[0], radio[1], radio[2], separatorHtml, groupName, (radio.length > 3 ? radio[3]: (id ? id : groupName)+"_"+i), (radio.length > 4 ? radio[4] : 0), title);
  253.     } else {
  254.       t += _jmolRadio(radio, null, null, separatorHtml, groupName, (id ? id : groupName)+"_"+i, title);
  255.     }
  256.   }
  257.   t+="</span>"
  258.   if (_jmol.debugAlert)
  259.     alert(t);
  260.   return _jmolDocumentWrite(t);
  261. }
  262.  
  263.  
  264. function jmolRadio(script, labelHtml, isChecked, separatorHtml, groupName, id, title) {
  265.   _jmolInitCheck();
  266.   if (_jmol.radioGroupCount == 0)
  267.     ++_jmol.radioGroupCount;
  268.   var t = _jmolRadio(script, labelHtml, isChecked, separatorHtml, groupName, (id ? id : groupName + "_" + _jmol.radioCount), title ? title : 0);
  269.   if (_jmol.debugAlert)
  270.     alert(t);
  271.   return _jmolDocumentWrite(t);
  272. }
  273.  
  274. function jmolLink(script, label, id, title) {
  275.   _jmolInitCheck();
  276.   if (id == undefined || id == null)
  277.     id = "jmolLink" + _jmol.linkCount;
  278.   if (label == undefined || label == null)
  279.     label = script.substring(0, 32);
  280.   ++_jmol.linkCount;
  281.   var scriptIndex = _jmolAddScript(script);
  282.   var t = "<span id=\"span_"+id+"\""+(title ? " title =\"" + title + "\"":"")+"><a name='" + id + "' id='" + id +
  283.           "' href='javascript:_jmolClick(" + scriptIndex + _jmol.targetText + ");' onMouseover='_jmolMouseOver(" + scriptIndex +
  284.           ");return true;' onMouseout='_jmolMouseOut()' " +
  285.           _jmol.linkCssText + ">" + label + "</a></span>";
  286.   if (_jmol.debugAlert)
  287.     alert(t);
  288.   return _jmolDocumentWrite(t);
  289. }
  290.  
  291. function jmolCommandInput(label, size, id, title) {
  292.   _jmolInitCheck();
  293.   if (id == undefined || id == null)
  294.     id = "jmolCmd" + _jmol.cmdCount;
  295.   if (label == undefined || label == null)
  296.     label = "Execute";
  297.   if (size == undefined || isNaN(size))
  298.     size = 60;
  299.   ++_jmol.cmdCount;
  300.   var t = "<span id=\"span_"+id+"\""+(title ? " title =\"" + title + "\"":"")+"><input name='" + id + "' id='" + id +
  301.           "' size='"+size+"'><input type=button value = '"+label+"' onClick='jmolScript(document.getElementById(\""+id+"\").value" + _jmol.targetText + ")'/></span>";
  302.   if (_jmol.debugAlert)
  303.     alert(t);
  304.   return _jmolDocumentWrite(t);
  305. }
  306.  
  307. function jmolMenu(arrayOfMenuItems, size, id, title) {
  308.   _jmolInitCheck();
  309.   if (id == undefined || id == null)
  310.     id = "jmolMenu" + _jmol.menuCount;
  311.   ++_jmol.menuCount;
  312.   var type = typeof arrayOfMenuItems;
  313.   if (type != null && type == "object" && arrayOfMenuItems.length) {
  314.     var len = arrayOfMenuItems.length;
  315.     if (typeof size != "number" || size == 1)
  316.       size = null;
  317.     else if (size < 0)
  318.       size = len;
  319.     var sizeText = size ? " size='" + size + "' " : "";
  320.     var t = "<span id=\"span_"+id+"\""+(title ? " title =\"" + title + "\"":"")+"><select name='" + id + "' id='" + id +
  321.             "' onChange='_jmolMenuSelected(this" + _jmol.targetText + ")'" +
  322.             sizeText + _jmol.menuCssText + ">";
  323.     for (var i = 0; i < len; ++i) {
  324.       var menuItem = arrayOfMenuItems[i];
  325.       type = typeof menuItem;
  326.       var script, text;
  327.       var isSelected = undefined;
  328.       if (type == "object" && menuItem != null) {
  329.         script = menuItem[0];
  330.         text = menuItem[1];
  331.         isSelected = menuItem[2];
  332.       } else {
  333.         script = text = menuItem;
  334.       }
  335.       if (text == undefined || text == null)
  336.         text = script;         
  337.           if (script=="#optgroup") {
  338.         t += "<optgroup label='" + text + "'>";  
  339.           } else if (script=="#optgroupEnd") {
  340.         t += "</optgroup>";      
  341.           } else {             
  342.         var scriptIndex = _jmolAddScript(script);
  343.         var selectedText = isSelected ? "' selected>" : "'>";
  344.         t += "<option value='" + scriptIndex + selectedText + text + "</option>";
  345.           }
  346.     }
  347.     t += "</select></span>";
  348.     if (_jmol.debugAlert)
  349.       alert(t);
  350.     return _jmolDocumentWrite(t);
  351.   }
  352. }
  353.  
  354. function jmolHtml(html) {
  355.   return _jmolDocumentWrite(html);
  356. }
  357.  
  358. function jmolBr() {
  359.   return _jmolDocumentWrite("<br />");
  360. }
  361.  
  362. ////////////////////////////////////////////////////////////////
  363. // advanced scripting functions
  364. ////////////////////////////////////////////////////////////////
  365.  
  366. function jmolDebugAlert(enableAlerts) {
  367.   _jmol.debugAlert = (enableAlerts == undefined || enableAlerts)
  368. }
  369.  
  370. function jmolAppletInline(size, inlineModel, script, nameSuffix) {
  371.   _jmolInitCheck();
  372.   return _jmolApplet(size, _jmolSterilizeInline(inlineModel),
  373.                      script, nameSuffix);
  374. }
  375.  
  376. function jmolSetTarget(targetSuffix) {
  377.   _jmol.targetSuffix = targetSuffix;
  378.   _jmol.targetText = targetSuffix ? ",\"" + targetSuffix + "\"" : "";
  379. }
  380.  
  381. function jmolScript(script, targetSuffix) {
  382.   if (script) {
  383.     _jmolCheckBrowser();
  384.     if (targetSuffix == "all") {
  385.       with (_jmol) {
  386.         for (var i = 0; i < appletSuffixes.length; ++i) {
  387.           var applet = _jmolGetApplet(appletSuffixes[i]);
  388.           if (applet) applet.script(script);
  389.         }
  390.       }
  391.     } else {
  392.       var applet=_jmolGetApplet(targetSuffix);
  393.       if (applet) applet.script(script);
  394.     }
  395.   }
  396. }
  397.  
  398. function jmolLoadInline(model, targetSuffix) {
  399.   if (!model)return "ERROR: NO MODEL"
  400.   var applet=_jmolGetApplet(targetSuffix);
  401.   if (!applet)return "ERROR: NO APPLET"
  402.   if (typeof(model) == "string")
  403.     return applet.loadInlineString(model, "", false);
  404.   else
  405.     return applet.loadInlineArray(model, "", false);
  406. }
  407.  
  408.  
  409. function jmolLoadInlineScript(model, script, targetSuffix) {
  410.   if (!model)return "ERROR: NO MODEL"
  411.   var applet=_jmolGetApplet(targetSuffix);
  412.   if (!applet)return "ERROR: NO APPLET"
  413.   return applet.loadInlineString(model, script, false);
  414. }
  415.  
  416.  
  417. function jmolLoadInlineArray(ModelArray, script, targetSuffix) {
  418.   if (!model)return "ERROR: NO MODEL"
  419.   if (!script)script=""
  420.   var applet=_jmolGetApplet(targetSuffix);
  421.   if (!applet)return "ERROR: NO APPLET"
  422.   try {
  423.     return applet.loadInlineArray(ModelArray, script, false);
  424.   } catch (err) {
  425.     //IE 7 bug
  426.     return applet.loadInlineString(ModelArray.join("\n"), script, false);
  427.   }
  428. }
  429.  
  430. function jmolAppendInlineArray(ModelArray, script, targetSuffix) {
  431.   if (!model)return "ERROR: NO MODEL"
  432.   if (!script)script=""
  433.   var applet=_jmolGetApplet(targetSuffix);
  434.   if (!applet)return "ERROR: NO APPLET"
  435.   try {
  436.     return applet.loadInlineArray(ModelArray, script, true);
  437.   } catch (err) {
  438.     //IE 7 bug
  439.     return applet.loadInlineString(ModelArray.join("\n"), script, true);
  440.   }
  441. }
  442.  
  443. function jmolAppendInlineScript(model, script, targetSuffix) {
  444.   if (!model)return "ERROR: NO MODEL"
  445.   var applet=_jmolGetApplet(targetSuffix);
  446.   if (!applet)return "ERROR: NO APPLET"
  447.   return applet.loadInlineString(model, script, true);
  448. }
  449.  
  450. function jmolCheckBrowser(action, urlOrMessage, nowOrLater) {
  451.   if (typeof action == "string") {
  452.     action = action.toLowerCase();
  453.     if (action != "alert" && action != "redirect" && action != "popup")
  454.       action = null;
  455.   }
  456.   if (typeof action != "string")
  457.     alert("jmolCheckBrowser(action, urlOrMessage, nowOrLater)\n\n" +
  458.           "action must be 'alert', 'redirect', or 'popup'");
  459.   else {
  460.     if (typeof urlOrMessage != "string")
  461.       alert("jmolCheckBrowser(action, urlOrMessage, nowOrLater)\n\n" +
  462.             "urlOrMessage must be a string");
  463.     else {
  464.       _jmol.checkBrowserAction = action;
  465.       _jmol.checkBrowserUrlOrMessage = urlOrMessage;
  466.     }
  467.   }
  468.   if (typeof nowOrLater == "string" && nowOrLater.toLowerCase() == "now")
  469.     _jmolCheckBrowser();
  470. }
  471.  
  472. ////////////////////////////////////////////////////////////////
  473. // Cascading Style Sheet Class support
  474. ////////////////////////////////////////////////////////////////
  475.  
  476. function jmolSetAppletCssClass(appletCssClass) {
  477.   if (_jmol.hasGetElementById) {
  478.     _jmol.appletCssClass = appletCssClass;
  479.     _jmol.appletCssText = appletCssClass ? "class='" + appletCssClass + "' " : "";
  480.   }
  481. }
  482.  
  483. function jmolSetButtonCssClass(buttonCssClass) {
  484.   if (_jmol.hasGetElementById) {
  485.     _jmol.buttonCssClass = buttonCssClass;
  486.     _jmol.buttonCssText = buttonCssClass ? "class='" + buttonCssClass + "' " : "";
  487.   }
  488. }
  489.  
  490. function jmolSetCheckboxCssClass(checkboxCssClass) {
  491.   if (_jmol.hasGetElementById) {
  492.     _jmol.checkboxCssClass = checkboxCssClass;
  493.     _jmol.checkboxCssText = checkboxCssClass ? "class='" + checkboxCssClass + "' " : "";
  494.   }
  495. }
  496.  
  497. function jmolSetRadioCssClass(radioCssClass) {
  498.   if (_jmol.hasGetElementById) {
  499.     _jmol.radioCssClass = radioCssClass;
  500.     _jmol.radioCssText = radioCssClass ? "class='" + radioCssClass + "' " : "";
  501.   }
  502. }
  503.  
  504. function jmolSetLinkCssClass(linkCssClass) {
  505.   if (_jmol.hasGetElementById) {
  506.     _jmol.linkCssClass = linkCssClass;
  507.     _jmol.linkCssText = linkCssClass ? "class='" + linkCssClass + "' " : "";
  508.   }
  509. }
  510.  
  511. function jmolSetMenuCssClass(menuCssClass) {
  512.   if (_jmol.hasGetElementById) {
  513.     _jmol.menuCssClass = menuCssClass;
  514.     _jmol.menuCssText = menuCssClass ? "class='" + menuCssClass + "' " : "";
  515.   }
  516. }
  517.  
  518. ////////////////////////////////////////////////////////////////
  519. // functions for INTERNAL USE ONLY which are subject to change
  520. // use at your own risk ... you have been WARNED!
  521. ////////////////////////////////////////////////////////////////
  522. var _jmol = {
  523.   currentDocument: document,
  524.  
  525.   debugAlert: false,
  526.  
  527.   codebase: "",
  528.   modelbase: ".",
  529.  
  530.   appletCount: 0,
  531.   appletSuffixes: [],
  532.   appletWindow: null,
  533.  
  534.   buttonCount: 0,
  535.   checkboxCount: 0,
  536.   linkCount: 0,
  537.   cmdCount: 0,
  538.   menuCount: 0,
  539.   radioCount: 0,
  540.   radioGroupCount: 0,
  541.  
  542.   appletCssClass: null,
  543.   appletCssText: "",
  544.   buttonCssClass: null,
  545.   buttonCssText: "",
  546.   checkboxCssClass: null,
  547.   checkboxCssText: "",
  548.   radioCssClass: null,
  549.   radioCssText: "",
  550.   linkCssClass: null,
  551.   linkCssText: "",
  552.   menuCssClass: null,
  553.   menuCssText: "",
  554.  
  555.   targetSuffix: 0,
  556.   targetText: "",
  557.   scripts: [""],
  558.   params: {
  559.         syncId: ("" + Math.random()).substring(3),
  560.         progressbar: "true",
  561.         progresscolor: "blue",
  562.         boxbgcolor: "black",
  563.         boxfgcolor: "white",
  564.         boxmessage: "Downloading JmolApplet ..."
  565.   },
  566.   ua: navigator.userAgent.toLowerCase(),
  567.   uaVersion: parseFloat(navigator.appVersion),
  568.  
  569.   os: "unknown",
  570.   browser: "unknown",
  571.   browserVersion: 0,
  572.   hasGetElementById: !!document.getElementById,
  573.   isJavaEnabled: navigator.javaEnabled(),
  574.   isNetscape47Win: false,
  575.   isIEWin: false,
  576.   useIEObject: false,
  577.   useHtml4Object: false,
  578.  
  579.   windowsClassId: "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93",
  580.   windowsCabUrl:
  581.    "http://java.sun.com/update/1.5.0/jinstall-1_5_0_05-windows-i586.cab",
  582.  
  583.   isBrowserCompliant: false,
  584.   isJavaCompliant: false,
  585.   isFullyCompliant: false,
  586.  
  587.   initialized: false,
  588.   initChecked: false,
  589.  
  590.   browserChecked: false,
  591.   checkBrowserAction: "alert",
  592.   checkBrowserUrlOrMessage: null,
  593.  
  594.   archivePath: null, // JmolApplet0.jar OR JmolAppletSigned0.jar
  595.  
  596.   previousOnloadHandler: null,
  597.   ready: {}
  598. }
  599.  
  600. with (_jmol) {
  601.   function _jmolTestUA(candidate) {
  602.     var ua = _jmol.ua;
  603.     var index = ua.indexOf(candidate);
  604.     if (index < 0)
  605.       return false;
  606.     _jmol.browser = candidate;
  607.     _jmol.browserVersion = parseFloat(ua.substring(index+candidate.length+1));
  608.     return true;
  609.   }
  610.  
  611.   function _jmolTestOS(candidate) {
  612.     if (_jmol.ua.indexOf(candidate) < 0)
  613.       return false;
  614.     _jmol.os = candidate;
  615.     return true;
  616.   }
  617.  
  618.   _jmolTestUA("konqueror") ||
  619.   _jmolTestUA("safari") ||
  620.   _jmolTestUA("omniweb") ||
  621.   _jmolTestUA("opera") ||
  622.   _jmolTestUA("webtv") ||
  623.   _jmolTestUA("icab") ||
  624.   _jmolTestUA("msie") ||
  625.   (_jmol.ua.indexOf("compatible") < 0 && _jmolTestUA("mozilla"));
  626.  
  627.   _jmolTestOS("linux") ||
  628.   _jmolTestOS("unix") ||
  629.   _jmolTestOS("mac") ||
  630.   _jmolTestOS("win");
  631.  
  632.   isNetscape47Win = (os == "win" && browser == "mozilla" &&
  633.                      browserVersion >= 4.78 && browserVersion <= 4.8);
  634.  
  635.   if (os == "win") {
  636.     isBrowserCompliant = hasGetElementById;
  637.   } else if (os == "mac") { // mac is the problem child :-(
  638.     if (browser == "mozilla" && browserVersion >= 5) {
  639.       // miguel 2004 11 17
  640.       // checking the plugins array does not work because
  641.       // Netscape 7.2 OS X still has Java 1.3.1 listed even though
  642.       // javaplugin.sf.net is installed to upgrade to 1.4.2
  643.       eval("try {var v = java.lang.System.getProperty('java.version');" +
  644.            " _jmol.isBrowserCompliant = v >= '1.4.2';" +
  645.            " } catch (e) { }");
  646.     } else if (browser == "opera" && browserVersion <= 7.54) {
  647.       isBrowserCompliant = false;
  648.     } else {
  649.       isBrowserCompliant = hasGetElementById &&
  650.         !((browser == "msie") ||
  651.           (browser == "safari" && browserVersion < 125.12));
  652.     }
  653.   } else if (os == "linux" || os == "unix") {
  654.     if (browser == "konqueror" && browserVersion <= 3.3)
  655.       isBrowserCompliant = false;
  656.     else
  657.       isBrowserCompliant = hasGetElementById;
  658.   } else { // other OS
  659.     isBrowserCompliant = hasGetElementById;
  660.   }
  661.  
  662.   // possibly more checks in the future for this
  663.   isJavaCompliant = isJavaEnabled;
  664.  
  665.   isFullyCompliant = isBrowserCompliant && isJavaCompliant;
  666.  
  667.   // IE5.5 works just fine ... but let's push them to Sun Java
  668.   isIEWin = (os == "win" && browser == "msie" && browserVersion >= 5.5);
  669.   useIEObject = isIEWin;
  670.   useHtml4Object =
  671.    (os != "mac" && browser == "mozilla" && browserVersion >= 5) ||
  672.    (os == "win" && browser == "opera" && browserVersion >= 8) ||
  673.    (os == "mac" && browser == "safari" && browserVersion >= 412.2);
  674.  
  675.  doTranslate = true;
  676.  haveSetTranslate = false;
  677. }
  678.  
  679.  
  680. function jmolSetCallback(callbackName,funcName) {
  681.   _jmol.params[callbackName] = funcName
  682. }
  683.  
  684. function jmolSetSyncId(n) {
  685.   return _jmol.params["syncId"] = n
  686. }
  687.  
  688. function jmolGetSyncId() {
  689.   return _jmol.params["syncId"]
  690. }
  691.  
  692. function jmolSetLogLevel(n) {
  693.   _jmol.params.logLevel = ''+n;
  694. }
  695.  
  696.         /*  AngelH, mar2007:
  697.                 By (re)setting these variables in the webpage before calling jmolApplet(),
  698.                 a custom message can be provided (e.g. localized for user's language) when no Java is installed.
  699.         */
  700. if (noJavaMsg==undefined) var noJavaMsg =
  701.         "You do not have Java applets enabled in your web browser, or your browser is blocking this applet.<br />\n" +
  702.         "Check the warning message from your browser and/or enable Java applets in<br />\n" +
  703.         "your web browser preferences, or install the Java Runtime Environment from <a href='http://www.java.com'>www.java.com</a><br />";
  704. if (noJavaMsg2==undefined) var noJavaMsg2 =
  705.         "You do not have the<br />\n" +
  706.         "Java Runtime Environment<br />\n" +
  707.         "installed for applet support.<br />\n" +
  708.         "Visit <a href='http://www.java.com'>www.java.com</a>";
  709. function _jmolApplet(size, inlineModel, script, nameSuffix) {
  710.         /*  AngelH, mar2007
  711.                 Fixed percent / pixel business, to avoid browser errors:
  712.                 put "px" where needed, avoid where not.        
  713.         */
  714.   with (_jmol) {
  715.     if (! nameSuffix)
  716.       nameSuffix = appletCount;
  717.     appletSuffixes.push(nameSuffix);
  718.     ++appletCount;
  719.     if (! script)
  720.       script = "select *";
  721.     var sz = _jmolGetAppletSize(size);
  722.     var widthAndHeight = " width='" + sz[0] + "' height='" + sz[1] + "' ";
  723.     var tHeader, tFooter;
  724.     if (!codebase)
  725.         jmolInitialize(".");
  726.     if (useIEObject || useHtml4Object) {
  727.       params.name = 'jmolApplet' + nameSuffix;
  728.       params.archive = archivePath;
  729.       params.mayscript = 'true';
  730.       params.codebase = codebase;
  731.     }
  732.     if (useIEObject) { // use MSFT IE6 object tag with .cab file reference
  733.       winCodebase = (windowsCabUrl ? " codebase='" + windowsCabUrl + "'\n" : "");
  734.       params.code = 'JmolApplet';
  735.       tHeader =
  736.         "<object name='jmolApplet" + nameSuffix +
  737.         "' id='jmolApplet" + nameSuffix + "' " + appletCssText + "\n" +
  738.         " classid='" + windowsClassId + "'\n" + winCodebase + widthAndHeight + ">\n";
  739.       tFooter = "</object>";
  740.     } else if (useHtml4Object) { // use HTML4 object tag
  741.       tHeader =
  742.         "<object name='jmolApplet" + nameSuffix +
  743.         "' id='jmolApplet" + nameSuffix + "' " + appletCssText + "\n" +
  744.         " classid='java:JmolApplet'\n" +
  745.         " type='application/x-java-applet'\n" +
  746.         widthAndHeight + ">\n";
  747.       tFooter = "</object>";
  748.     } else { // use applet tag
  749.       tHeader =
  750.         "<applet name='jmolApplet" + nameSuffix +
  751.         "' id='jmolApplet" + nameSuffix +
  752.         "' " + appletCssText +
  753.         " code='JmolApplet'" +
  754.         " archive='" + archivePath + "' codebase='" + codebase + "'\n" +
  755.                 widthAndHeight +
  756.         " mayscript='true'>\n";
  757.       tFooter = "</applet>";
  758.     }
  759.     var visitJava;
  760.     if (isIEWin || useHtml4Object) {
  761.                 var szX = "width:" + sz[0]
  762.                 if ( szX.indexOf("%")==-1 ) szX+="px"
  763.                 var szY = "height:" + sz[1]
  764.                 if ( szY.indexOf("%")==-1 ) szY+="px"
  765.       visitJava =
  766.         "<p style='background-color:yellow; color:black; " +
  767.                 szX + ";" + szY + ";" +
  768.         // why doesn't this vertical-align work?
  769.         "text-align:center;vertical-align:middle;'>\n" +
  770.                 noJavaMsg +
  771.         "</p>";
  772.     } else {
  773.       visitJava =
  774.         "<table bgcolor='yellow'><tr>" +
  775.         "<td align='center' valign='middle' " + widthAndHeight + "><font color='black'>\n" +
  776.                 noJavaMsg2 +
  777.         "</font></td></tr></table>";
  778.     }
  779.     params.loadInline = (inlineModel ? inlineModel : "");
  780.     params.script = (script ? _jmolSterilizeScript(script) : "");
  781.     var t = tHeader + _jmolParams() + visitJava + tFooter;
  782.     jmolSetTarget(nameSuffix);
  783.     ready["jmolApplet" + nameSuffix] = false;
  784.     if (_jmol.debugAlert)
  785.       alert(t);
  786.     return _jmolDocumentWrite(t);
  787.   }
  788. }
  789.  
  790. function _jmolParams() {
  791.  var t = "";
  792.  for (i in _jmol.params)
  793.         if(_jmol.params[i]!="")
  794.                  t+="  <param name='"+i+"' value='"+_jmol.params[i]+"' />\n";
  795.  return t
  796. }
  797.  
  798. function _jmolInitCheck() {
  799.   if (_jmol.initChecked)
  800.     return;
  801.   _jmol.initChecked = true;
  802.   jmolInitialize(defaultdir, defaultjar)
  803. }
  804.  
  805. function _jmolCheckBrowser() {
  806.   with (_jmol) {
  807.     if (browserChecked)
  808.       return;
  809.     browserChecked = true;
  810.  
  811.     if (isFullyCompliant)
  812.       return true;
  813.  
  814.     if (checkBrowserAction == "redirect")
  815.       location.href = checkBrowserUrlOrMessage;
  816.     else if (checkBrowserAction == "popup")
  817.       _jmolPopup(checkBrowserUrlOrMessage);
  818.     else {
  819.       var msg = checkBrowserUrlOrMessage;
  820.       if (msg == null)
  821.         msg = "Your web browser is not fully compatible with Jmol\n\n" +
  822.               "browser: " + browser +
  823.               "   version: " + browserVersion +
  824.               "   os: " + os +
  825.               "\n\n" + ua;
  826.       alert(msg);
  827.     }
  828.   }
  829.   return false;
  830. }
  831.  
  832. function _jmolDocumentWrite(text) {
  833.   if (_jmol.currentDocument)
  834.     _jmol.currentDocument.write(text);
  835.   return text;
  836. }
  837.  
  838. function _jmolPopup(url) {
  839.   var popup = window.open(url, "JmolPopup",
  840.                           "left=150,top=150,height=400,width=600," +
  841.                           "directories=yes,location=yes,menubar=yes," +
  842.                           "toolbar=yes," +
  843.                           "resizable=yes,scrollbars=yes,status=yes");
  844.   if (popup.focus)
  845.     poup.focus();
  846. }
  847.  
  848. function _jmolReadyCallback(name) {
  849.   if (_jmol.debugAlert)
  850.     alert(name + " is ready");
  851.   _jmol.ready["" + name] = true;
  852. }
  853.  
  854. function _jmolSterilizeScript(script) {
  855.   var inlineScript = script.replace(/'/g, "&#39;");
  856.   if (_jmol.debugAlert)
  857.     alert("script:\n" + inlineScript);
  858.   return inlineScript;
  859. }
  860.  
  861. function _jmolSterilizeInline(model) {
  862.   var inlineModel =
  863.     model.replace(/\r|\n|\r\n/g, "|").replace(/'/g, "&#39;");
  864.   if (_jmol.debugAlert)
  865.     alert("inline model:\n" + inlineModel);
  866.   return inlineModel;
  867. }
  868.  
  869.         /*  AngelH, mar2007:
  870.                 By (re)setting this variable in the webpage before calling jmolApplet(), limits for applet size can be overriden.
  871.         */
  872.  
  873.         /* hansonr, jun2007:
  874.                 2048 standard for GeoWall (http://geowall.geo.lsa.umich.edu/home.html)
  875.         */
  876.  
  877. if (allowedJmolSize==undefined) var allowedJmolSize = [1, 2048, 300]   // min, max, default (pixels)
  878. function _jmolGetAppletSize(size) {
  879.         /*  AngelH, mar2007
  880.                 Accepts single number or 2-value array, each one can be either:
  881.            percent (text string ending %), decimal 0 to 1 (percent/100), number, or text string (interpreted as nr.)
  882.            Size is now returned as string or number, no "px".
  883.         */
  884.   var width, height;
  885.   if ( (typeof size) == "object" && size != null ) {
  886.     width = size[0]; height = size[1];
  887.   } else {
  888.     width = height = size;
  889.   }
  890.   // if percent, leave it as it is:
  891.   if ( width.toString().charAt(width.toString().length-1) != "%" ) {
  892.     width = parseFloat(width);  // convert to nr., or strip text, or make zero
  893.         if ( width <= 1 && width > 0 ) { width = (width*100)+"%" }      // decimal: convert to percent and quit
  894.         else if ( width >= allowedJmolSize[0] && width <= allowedJmolSize[1] ) { width = parseInt(width) }      // accept only that range (pixels)
  895.         else { width = allowedJmolSize[2] }     // default size 300 pixels
  896.   }
  897.   if ( height.toString().charAt(height.toString().length-1) != "%" ) {
  898.     height = parseFloat(height);
  899.         if ( height <= 1 && height > 0 ) { height = (height*100)+"%" }
  900.         else if ( height >= allowedJmolSize[0] && height <= allowedJmolSize[1] ) { height = parseInt(height) }
  901.         else { height = allowedJmolSize[2] }
  902.   }
  903.   return [width, height];
  904. }
  905.  
  906. function _jmolRadio(script, labelHtml, isChecked, separatorHtml, groupName, id, title) {
  907.   ++_jmol.radioCount;
  908.   if (groupName == undefined || groupName == null)
  909.     groupName = "jmolRadioGroup" + (_jmol.radioGroupCount - 1);
  910.   if (!script)
  911.     return "";
  912.   if (labelHtml == undefined || labelHtml == null)
  913.     labelHtml = script.substring(0, 32);
  914.   if (! separatorHtml)
  915.     separatorHtml = "";
  916.   var scriptIndex = _jmolAddScript(script);
  917.   var eospan = "</span>"
  918.   var t = "<span id=\"span_"+id+"\""+(title ? " title =\"" + title + "\"":"")+"><input name='"
  919.         + groupName + "' id='"+id+"' type='radio' onClick='_jmolClick(" +
  920.          scriptIndex + _jmol.targetText + ");return true;' onMouseover='_jmolMouseOver(" +
  921.          scriptIndex + ");return true;' onMouseout='_jmolMouseOut()' " +
  922.          (isChecked ? "checked " : "") + _jmol.radioCssText + "/>"
  923.   if (labelHtml.toLowerCase().indexOf("<td>")>=0) {
  924.         t += eospan
  925.         eospan = "";
  926.   }
  927.   t += "<label for=\"" + id + "\">" + labelHtml + "</label>" +eospan + separatorHtml;
  928.  
  929.   return t;
  930. }
  931.  
  932. function _jmolFindApplet(target) {
  933.   // first look for the target in the current window
  934.   var applet = _jmolFindAppletInWindow(_jmol.appletWindow != null ? _jmol.appletWindow : window, target);
  935.   // THEN look for the target in child frames
  936.   if (applet == undefined)
  937.     applet = _jmolSearchFrames(window, target);
  938.   // FINALLY look for the target in sibling frames
  939.   if (applet == undefined)
  940.     applet = _jmolSearchFrames(top, target); // look starting in top frame
  941.   return applet;
  942. }
  943.  
  944. function _jmolGetApplet(targetSuffix){
  945.  var target = "jmolApplet" + (targetSuffix ? targetSuffix : "0");
  946.  var applet = _jmolFindApplet(target);
  947.  if (applet) return applet
  948.  if(!_jmol.alerted)alert("could not find applet " + target);
  949.  _jmol.alerted = true;
  950.  return null
  951. }
  952.  
  953. function _jmolSearchFrames(win, target) {
  954.   var applet;
  955.   var frames = win.frames;
  956.   if (frames && frames.length) { // look in all the frames below this window
  957.    try{
  958.     for (var i = 0; i < frames.length; ++i) {
  959.       applet = _jmolSearchFrames(frames[i], target);
  960.       if (applet)
  961.         return applet;
  962.     }
  963.    }catch(e) {
  964.         if (_jmol.debugAlert)
  965.                 alert("Jmol.js _jmolSearchFrames cannot access " + win.name + ".frame[" + i + "] consider using jmolSetAppletWindow()")
  966.    }
  967.   }
  968.   return applet = _jmolFindAppletInWindow(win, target)
  969. }
  970.  
  971. function _jmolFindAppletInWindow(win, target) {
  972.     var doc = win.document;
  973.     // getElementById fails on MacOSX Safari & Mozilla 
  974.     if (_jmol.useHtml4Object || _jmol.useIEObject)
  975.       return doc.getElementById(target);
  976.     else if (doc.applets)
  977.       return doc.applets[target];
  978.     else
  979.       return doc[target];
  980. }
  981.  
  982. function _jmolAddScript(script) {
  983.   if (! script)
  984.     return 0;
  985.   var index = _jmol.scripts.length;
  986.   _jmol.scripts[index] = script;
  987.   return index;
  988. }
  989.  
  990. function _jmolClick(scriptIndex, targetSuffix, elementClicked) {
  991.   _jmol.element = elementClicked;
  992.   jmolScript(_jmol.scripts[scriptIndex], targetSuffix);
  993. }
  994.  
  995. function _jmolMenuSelected(menuObject, targetSuffix) {
  996.   var scriptIndex = menuObject.value;
  997.   if (scriptIndex != undefined) {
  998.     jmolScript(_jmol.scripts[scriptIndex], targetSuffix);
  999.     return;
  1000.   }
  1001.   var len = menuObject.length;
  1002.   if (typeof len == "number") {
  1003.     for (var i = 0; i < len; ++i) {
  1004.       if (menuObject[i].selected) {
  1005.         _jmolClick(menuObject[i].value, targetSuffix);
  1006.         return;
  1007.       }
  1008.     }
  1009.   }
  1010.   alert("?Que? menu selected bug #8734");
  1011. }
  1012.  
  1013.  
  1014. _jmol.checkboxMasters = {};
  1015. _jmol.checkboxItems = {};
  1016.  
  1017. function jmolSetCheckboxGroup(chkMaster,chkBox) {
  1018.         var id = chkMaster;
  1019.         if(typeof(id)=="number")id = "jmolCheckbox" + id;
  1020.         chkMaster = document.getElementById(id);
  1021.         if (!chkMaster)alert("jmolSetCheckboxGroup: master checkbox not found: " + id);
  1022.         var m = _jmol.checkboxMasters[id] = {};
  1023.         m.chkMaster = chkMaster;
  1024.         m.chkGroup = {};
  1025.         for (var i = 1; i < arguments.length; i++){
  1026.                 var id = arguments[i];
  1027.                 if(typeof(id)=="number")id = "jmolCheckbox" + id;
  1028.                 checkboxItem = document.getElementById(id);
  1029.                 if (!checkboxItem)alert("jmolSetCheckboxGroup: group checkbox not found: " + id);
  1030.                 m.chkGroup[id] = checkboxItem;
  1031.                 _jmol.checkboxItems[id] = m;
  1032.         }
  1033. }
  1034.  
  1035. function _jmolNotifyMaster(m){
  1036.         //called when a group item is checked
  1037.         var allOn = true;
  1038.         var allOff = true;
  1039.         for (var chkBox in m.chkGroup){
  1040.                 if(m.chkGroup[chkBox].checked)
  1041.                         allOff = false;
  1042.                 else
  1043.                         allOn = false;
  1044.         }
  1045.         if (allOn)m.chkMaster.checked = true;  
  1046.         if (allOff)m.chkMaster.checked = false;
  1047.         if ((allOn || allOff) && _jmol.checkboxItems[m.chkMaster.id])
  1048.                 _jmolNotifyMaster(_jmol.checkboxItems[m.chkMaster.id])
  1049. }
  1050.  
  1051. function _jmolNotifyGroup(m, isOn){
  1052.         //called when a master item is checked
  1053.         for (var chkBox in m.chkGroup){
  1054.                 var item = m.chkGroup[chkBox]
  1055.                 item.checked = isOn;
  1056.                 if (_jmol.checkboxMasters[item.id])
  1057.                         _jmolNotifyGroup(_jmol.checkboxMasters[item.id], isOn)
  1058.         }
  1059. }
  1060.  
  1061. function _jmolCbClick(ckbox, whenChecked, whenUnchecked, targetSuffix) {
  1062.   _jmol.control = ckbox
  1063.   _jmolClick(ckbox.checked ? whenChecked : whenUnchecked, targetSuffix);
  1064.   if(_jmol.checkboxMasters[ckbox.id])
  1065.         _jmolNotifyGroup(_jmol.checkboxMasters[ckbox.id], ckbox.checked)
  1066.   if(_jmol.checkboxItems[ckbox.id])
  1067.         _jmolNotifyMaster(_jmol.checkboxItems[ckbox.id])
  1068. }
  1069.  
  1070. function _jmolCbOver(ckbox, whenChecked, whenUnchecked) {
  1071.   window.status = _jmol.scripts[ckbox.checked ? whenUnchecked : whenChecked];
  1072. }
  1073.  
  1074. function _jmolMouseOver(scriptIndex) {
  1075.   window.status = _jmol.scripts[scriptIndex];
  1076. }
  1077.  
  1078. function _jmolMouseOut() {
  1079.   window.status = " ";
  1080.   return true;
  1081. }
  1082.  
  1083. function _jmolSetCodebase(codebase) {
  1084.   _jmol.codebase = codebase ? codebase : ".";
  1085.   if (_jmol.debugAlert)
  1086.     alert("jmolCodebase=" + _jmol.codebase);
  1087. }
  1088.  
  1089. function _jmolOnloadResetForms() {
  1090.   // must be evaluated ONLY once
  1091.   _jmol.previousOnloadHandler = window.onload;
  1092.   window.onload =
  1093.   function() {
  1094.     with (_jmol) {
  1095.       if (buttonCount+checkboxCount+menuCount+radioCount+radioGroupCount > 0) {
  1096.         var forms = document.forms;
  1097.         for (var i = forms.length; --i >= 0; )
  1098.           forms[i].reset();
  1099.       }
  1100.       if (previousOnloadHandler)
  1101.         previousOnloadHandler();
  1102.     }
  1103.   }
  1104. }
  1105.  
  1106. ////////////////////////////////////
  1107. /////extensions for getProperty/////
  1108. ////////////////////////////////////
  1109.  
  1110.  
  1111. function _jmolEvalJSON(s,key){
  1112.  s=s+""
  1113.  if(!s)return []
  1114.  if(s.charAt(0)!="{"){
  1115.         if(s.indexOf(" | ")>=0)s=s.replace(/\ \|\ /g, "\n")
  1116.         return s
  1117.  }
  1118.  var A = eval("("+s+")")
  1119.  if(!A)return
  1120.  if(key && A[key])A=A[key]
  1121.  return A
  1122. }
  1123.  
  1124. function _jmolEnumerateObject(A,key){
  1125.  var sout=""
  1126.  if(typeof(A) == "string" && A!="null"){
  1127.         sout+="\n"+key+"=\""+A+"\""
  1128.  }else if(!isNaN(A)||A==null){
  1129.         sout+="\n"+key+"="+(A+""==""?"null":A)
  1130.  }else if(A.length){
  1131.     sout+=key+"=[]"
  1132.     for(var i=0;i<A.length;i++){
  1133.         sout+="\n"
  1134.         if(typeof(A[i]) == "object"||typeof(A[i]) == "array"){
  1135.                 sout+=_jmolEnumerateObject(A[i],key+"["+i+"]")
  1136.         }else{
  1137.                 sout+=key+"["+i+"]="+(typeof(A[i]) == "string" && A[i]!="null"?"\""+A[i].replace(/\"/g,"\\\"")+"\"":A[i])
  1138.         }
  1139.     }
  1140.  }else{
  1141.     if(key != ""){
  1142.         sout+=key+"={}"
  1143.         key+="."
  1144.     }
  1145.    
  1146.     for(var i in A){
  1147.         sout+="\n"
  1148.         if(typeof(A[i]) == "object"||typeof(A[i]) == "array"){
  1149.                 sout+=_jmolEnumerateObject(A[i],key+i)
  1150.         }else{
  1151.                 sout+=key+i+"="+(typeof(A[i]) == "string" && A[i]!="null"?"\""+A[i].replace(/\"/g,"\\\"")+"\"":A[i])
  1152.         }
  1153.     }
  1154.  }
  1155.  return sout
  1156. }
  1157.  
  1158.  
  1159. function _jmolSortKey0(a,b){
  1160.  return (a[0]<b[0]?1:a[0]>b[0]?-1:0)
  1161. }
  1162.  
  1163. function _jmolSortMessages(A){
  1164.  if(!A || typeof(A)!="object")return []
  1165.  var B = []
  1166.  for(var i=A.length-1;i>=0;i--)for(var j=0;j<A[i].length;j++)B[B.length]=A[i][j]
  1167.  if(B.length == 0) return
  1168.  B=B.sort(_jmolSortKey0)
  1169.  return B
  1170. }
  1171.  
  1172. /////////additional extensions //////////
  1173.  
  1174.  
  1175. function _jmolDomScriptLoad(URL){
  1176.  //open(URL) //to debug
  1177.  _jmol.servercall=URL
  1178.  var node = document.getElementById("_jmolScriptNode")
  1179.  if (node && _jmol.browser!="msie"){
  1180.     document.getElementsByTagName("HEAD")[0].removeChild(node)
  1181.     node=null
  1182.  }
  1183.  if (node) {
  1184.    node.setAttribute("src",URL)
  1185.  } else {
  1186.    node=document.createElement("script")
  1187.    node.setAttribute("id","_jmolScriptNode")
  1188.    node.setAttribute("type","text/javascript")
  1189.    node.setAttribute("src",URL)
  1190.    document.getElementsByTagName("HEAD")[0].appendChild(node)
  1191.  }
  1192. }
  1193.  
  1194.  
  1195. function _jmolExtractPostData(url){
  1196.  S=url.split("&POST:")
  1197.  var s=""
  1198.  for(var i=1;i<S.length;i++){
  1199.         KV=S[i].split("=")
  1200.         s+="&POSTKEY"+i+"="+KV[0]
  1201.         s+="&POSTVALUE"+i+"="+KV[1]
  1202.  }
  1203.  return "&url="+escape(S[0])+s
  1204. }
  1205.  
  1206. function _jmolLoadModel(targetSuffix,remoteURL,array,isError,errorMessage){
  1207.  //called by server, but in client
  1208.  //overload this function to customize return
  1209.  _jmol.remoteURL=remoteURL
  1210.  if(isError)alert(errorMessage)
  1211.  jmolLoadInlineScript(array.join("\n"),_jmol.optionalscript,targetSuffix)
  1212. }
  1213.  
  1214. //////////user property/status functions/////////
  1215.  
  1216. function jmolGetStatus(strStatus,targetSuffix){
  1217.  return _jmolSortMessages(jmolGetPropertyAsArray("jmolStatus",strStatus,targetSuffix))
  1218. }
  1219.  
  1220. function jmolGetPropertyAsArray(sKey,sValue,targetSuffix) {
  1221.  return _jmolEvalJSON(jmolGetPropertyAsJSON(sKey,sValue,targetSuffix),sKey)
  1222. }
  1223.  
  1224. function jmolGetPropertyAsString(sKey,sValue,targetSuffix) {
  1225.  var applet = _jmolGetApplet(targetSuffix);
  1226.  if(!sValue)sValue=""
  1227.  return (applet ? applet.getPropertyAsString(sKey,sValue) + "" : "")
  1228. }
  1229.  
  1230. function jmolGetPropertyAsJSON(sKey,sValue,targetSuffix) {
  1231.  if(!sValue)sValue = ""
  1232.  var applet = _jmolGetApplet(targetSuffix);
  1233.  try {
  1234.   return (applet ? applet.getPropertyAsJSON(sKey,sValue) + "" : "")
  1235.  } catch(e) {
  1236.   return ""
  1237.  }
  1238. }
  1239.  
  1240. function jmolGetPropertyAsJavaObject(sKey,sValue,targetSuffix) {
  1241.  if(!sValue)sValue = ""
  1242.  var applet = _jmolGetApplet(targetSuffix);
  1243.  return (applet ? applet.getProperty(sKey,sValue) : null)
  1244. }
  1245.  
  1246.  
  1247. function jmolDecodeJSON(s) {
  1248.  return _jmolEnumerateObject(_jmolEvalJSON(s),"")
  1249. }
  1250.  
  1251.  
  1252. ///////// synchronous scripting ////////
  1253.  
  1254. function jmolScriptWait(script, targetSuffix) {
  1255.   if(!targetSuffix)targetSuffix="0"
  1256.   var Ret=jmolScriptWaitAsArray(script, targetSuffix)
  1257.   var s = ""
  1258.   for(var i=Ret.length;--i>=0;)
  1259.   for(var j=0;j< Ret[i].length;j++)
  1260.         s+=Ret[i][j]+"\n"
  1261.   return s
  1262. }
  1263.  
  1264. function jmolScriptWaitOutput(script, targetSuffix) {
  1265.   if(!targetSuffix)targetSuffix="0"
  1266.   var ret = ""
  1267.   try{
  1268.    if (script) {
  1269.     _jmolCheckBrowser();
  1270.     var applet=_jmolGetApplet(targetSuffix);
  1271.     if (applet) ret += applet.scriptWaitOutput(script);
  1272.    }
  1273.   }catch(e){
  1274.   }
  1275.  return ret;
  1276. }
  1277.  
  1278. function jmolEvaluate(molecularMath, targetSuffix) {
  1279.  
  1280.   //carries out molecular math on a model
  1281.  
  1282.   if(!targetSuffix)targetSuffix="0"
  1283.   var result = "" + jmolGetPropertyAsJavaObject("evaluate", molecularMath, targetSuffix);
  1284.   var s = result.replace(/\-*\d+/,"")
  1285.   if (s == "" && !isNaN(parseInt(result)))return parseInt(result);
  1286.   var s = result.replace(/\-*\d*\.\d*/,"")
  1287.   if (s == "" && !isNaN(parseFloat(result)))return parseFloat(result);
  1288.   return result;
  1289. }
  1290.  
  1291. function jmolScriptEcho(script, targetSuffix) {
  1292.   // returns a newline-separated list of all echos from a script
  1293.   if(!targetSuffix)targetSuffix="0"
  1294.   var Ret=jmolScriptWaitAsArray(script, targetSuffix)
  1295.   var s = ""
  1296.   for(var i=Ret.length;--i>=0;)
  1297.   for(var j=Ret[i].length;--j>=0;)
  1298.         if (Ret[i][j][1] == "scriptEcho")s+=Ret[i][j][3]+"\n"
  1299.   return s.replace(/ \| /g, "\n")
  1300. }
  1301.  
  1302.  
  1303. function jmolScriptMessage(script, targetSuffix) {
  1304.   // returns a newline-separated list of all messages from a script, ending with "script completed\n"
  1305.   if(!targetSuffix)targetSuffix="0"
  1306.   var Ret=jmolScriptWaitAsArray(script, targetSuffix)
  1307.   var s = ""
  1308.   for(var i=Ret.length;--i>=0;)
  1309.   for(var j=Ret[i].length;--j>=0;)
  1310.         if (Ret[i][j][1] == "scriptStatus")s+=Ret[i][j][3]+"\n"
  1311.   return s.replace(/ \| /g, "\n")
  1312. }
  1313.  
  1314.  
  1315. function jmolScriptWaitAsArray(script, targetSuffix) {
  1316.  var ret = ""
  1317.  try{
  1318.   jmolGetStatus("scriptEcho,scriptMessage,scriptStatus,scriptError",targetSuffix)
  1319.   if (script) {
  1320.     _jmolCheckBrowser();
  1321.     var applet=_jmolGetApplet(targetSuffix);
  1322.     if (applet) ret += applet.scriptWait(script);
  1323.     ret = _jmolEvalJSON(ret,"jmolStatus")
  1324.     if(typeof ret == "object")
  1325.         return ret
  1326.   }
  1327.  }catch(e){
  1328.  }
  1329.   return [[ret]]
  1330. }
  1331.  
  1332.  
  1333.  
  1334. ////////////   save/restore orientation   /////////////
  1335.  
  1336. function jmolSaveOrientation(id, targetSuffix) {  
  1337.  if(!targetSuffix)targetSuffix="0"
  1338.   return _jmol["savedOrientation"+id] = jmolGetPropertyAsArray("orientationInfo","info",targetSuffix).moveTo
  1339. }
  1340.  
  1341. function jmolRestoreOrientation(id, targetSuffix) {
  1342.  if(!targetSuffix)targetSuffix="0"
  1343.  var s=_jmol["savedOrientation"+id]
  1344.  if (!s || s == "")return
  1345.  s=s.replace(/1\.0/,"0")
  1346.  return jmolScriptWait(s,targetSuffix)
  1347. }
  1348.  
  1349. function jmolRestoreOrientationDelayed(id, delay, targetSuffix) {
  1350.  if(arguments.length < 2)delay=1;
  1351.  if(!targetSuffix)targetSuffix="0"
  1352.  var s=_jmol["savedOrientation"+id]
  1353.  if (!s || s == "")return
  1354.  s=s.replace(/1\.0/,delay)
  1355.  return jmolScriptWait(s,targetSuffix)
  1356. }
  1357.  
  1358. ////////////  add parameter /////////////
  1359. /*
  1360.  * for adding callbacks or other parameters. Use:
  1361.  
  1362.    jmolSetDocument(0)
  1363.    var s= jmolApplet(....)
  1364.    s = jmolAppletAddParam(s,"messageCallback", "myFunctionName")
  1365.    document.write(s)
  1366.    jmolSetDocument(document) // if you want to then write buttons and such normally
  1367.  
  1368.  */
  1369.  
  1370. function jmolAppletAddParam(appletCode,name,value){
  1371.   if(value == "")return appletCode
  1372.   return appletCode.replace(/\<param/,"\n<param name='"+name+"' value='"+value+"' />\n<param")
  1373. }
  1374.  
  1375. ///////////////auto load Research Consortium for Structural Biology (RCSB) data ///////////
  1376.  
  1377. function jmolLoadAjax_STOLAF_RCSB(fileformat,pdbid,optionalscript,targetSuffix){
  1378.  
  1379.  if(!_jmol.thismodel)_jmol.thismodel = "1crn"
  1380.  if(!_jmol.serverURL)_jmol.serverURL="http://fusion.stolaf.edu/chemistry/jmol/getajaxjs.cfm"
  1381.  if(!_jmol.RCSBserver)_jmol.RCSBserver="http://www.rcsb.org"
  1382.  if(!_jmol.defaultURL_RCSB)_jmol.defaultURL_RCSB=_jmol.RCSBserver+"/pdb/files/1CRN.CIF"
  1383.  if(!fileformat)fileformat="PDB"
  1384.  if(!pdbid)pdbid=prompt("Enter a 4-digit PDB ID:",_jmol.thismodel)
  1385.  if(!pdbid || pdbid.length != 4)return ""
  1386.  if(!targetSuffix)targetSuffix="0"
  1387.  if(!optionalscript)optionalscript=""
  1388.  var url=_jmol.defaultURL_RCSB.replace(/1CRN/g,pdbid.toUpperCase())
  1389.  if(fileformat!="CIF")url=url.replace(/CIF/,fileformat)
  1390.  _jmol.optionalscript=optionalscript
  1391.  _jmol.thismodel=pdbid
  1392.  _jmol.thistargetsuffix=targetSuffix
  1393.  _jmol.thisurl=url
  1394.  _jmol.modelArray = []
  1395.  url=_jmol.serverURL+"?returnfunction=_jmolLoadModel&returnArray=_jmol.modelArray&id="+targetSuffix+_jmolExtractPostData(url)
  1396.  _jmolDomScriptLoad(url)
  1397.  return url
  1398. }
  1399.  
  1400. /////////////// St. Olaf College AJAX server -- ANY URL ///////////
  1401.  
  1402. function jmolLoadAjax_STOLAF_ANY(url, userid, optionalscript,targetSuffix){
  1403.  _jmol.serverURL="http://fusion.stolaf.edu/chemistry/jmol/getajaxjs.cfm"
  1404.  if(!_jmol.thisurlANY)_jmol.thisurlANY = "http://www.stolaf.edu/depts/chemistry/mo/struc/data/ycp3-1.mol"
  1405.  if(!url)url=prompt("Enter any (uncompressed file) URL:", _jmol.thisurlANY)
  1406.  if(!userid)userid="0"
  1407.  if(!targetSuffix)targetSuffix="0"
  1408.  if(!optionalscript)optionalscript=""
  1409.  _jmol.optionalscript=optionalscript
  1410.  _jmol.thistargetsuffix=targetSuffix
  1411.  _jmol.modelArray = []
  1412.  _jmol.thisurl = url
  1413.  url=_jmol.serverURL+"?returnfunction=_jmolLoadModel&returnArray=_jmol.modelArray&id="+targetSuffix+_jmolExtractPostData(url)
  1414.  _jmolDomScriptLoad(url)
  1415. }
  1416.  
  1417.  
  1418. /////////////// Mineralogical Society of America (MSA) data /////////
  1419.  
  1420. function jmolLoadAjax_MSA(key,value,optionalscript,targetSuffix){
  1421.  
  1422.  if(!_jmol.thiskeyMSA)_jmol.thiskeyMSA = "mineral"
  1423.  if(!_jmol.thismodelMSA)_jmol.thismodelMSA = "quartz"
  1424.  if(!_jmol.ajaxURL_MSA)_jmol.ajaxURL_MSA="http://rruff.geo.arizona.edu/AMS/result.php?mineral=quartz&viewing=ajaxjs"
  1425.  if(!key)key=prompt("Enter a field:", _jmol.thiskeyMSA)
  1426.  if(!key)return ""
  1427.  if(!value)value=prompt("Enter a "+key+":", _jmol.thismodelMSA)
  1428.  if(!value)return ""
  1429.  if(!targetSuffix)targetSuffix="0"
  1430.  if(!optionalscript)optionalscript=""
  1431.  if(optionalscript == 1)optionalscript='load "" {1 1 1}'
  1432.  var url=_jmol.ajaxURL_MSA.replace(/mineral/g,key).replace(/quartz/g,value)
  1433.  _jmol.optionalscript=optionalscript
  1434.  _jmol.thiskeyMSA=key
  1435.  _jmol.thismodelMSA=value
  1436.  _jmol.thistargetsuffix=targetSuffix
  1437.  _jmol.thisurl=url
  1438.  _jmol.modelArray = []
  1439.  loadModel=_jmolLoadModel
  1440.  _jmolDomScriptLoad(url)
  1441.  return url
  1442. }
  1443.  
  1444.  
  1445.  
  1446. function jmolLoadAjaxJS(url, userid, optionalscript,targetSuffix){
  1447.  if(!userid)userid="0"
  1448.  if(!targetSuffix)targetSuffix="0"
  1449.  if(!optionalscript)optionalscript=""
  1450.  _jmol.optionalscript=optionalscript
  1451.  _jmol.thismodel=userid
  1452.  _jmol.thistargetsuffix=targetSuffix
  1453.  _jmol.modelArray = []
  1454.  _jmol.thisurl = url
  1455.  url+="&returnFunction=_jmolLoadModel&returnArray=_jmol.modelArray&id="+targetSuffix
  1456.  _jmolDomScriptLoad(url)
  1457. }
  1458.  
  1459.  
  1460. //// in case Jmol library has already been loaded:
  1461.  
  1462. }catch(e){}
  1463.  
  1464. ///////////////moving atoms //////////////
  1465.  
  1466. // HIGHLY experimental!!
  1467.  
  1468. function jmolSetAtomCoord(i,x,y,z,targetSuffix){
  1469.     _jmolCheckBrowser();
  1470.       var applet=_jmolGetApplet(targetSuffix);
  1471.       if (applet) applet.getProperty('jmolViewer').setAtomCoord(i,x,y,z)
  1472. }
  1473.  
  1474. function jmolSetAtomCoordRelative(i,x,y,z,targetSuffix){
  1475.     _jmolCheckBrowser();
  1476.       var applet=_jmolGetApplet(targetSuffix);
  1477.       if (applet) applet.getProperty('jmolViewer').setAtomCoordRelative(i,x,y,z)
  1478. }
  1479.  
  1480.  
  1481. ///////////////applet fake for testing buttons/////////////
  1482.  
  1483.  
  1484. if(document.location.search.indexOf("NOAPPLET")>=0){
  1485.         jmolApplet = function(w){
  1486.                 var s="<table style='background-color:black' width="+w+"><tr height="+w+">"
  1487.                 +"<td align=center valign=center style='background-color:white'>"
  1488.                 +"Applet would be here"
  1489.                 +"<p><textarea id=fakeApplet rows=5 cols=50></textarea>"
  1490.                 +"</td></tr></table>"
  1491.                 return _jmolDocumentWrite(s)
  1492.         }
  1493.  
  1494.         _jmolFindApplet = function(){return jmolApplet0}
  1495.  
  1496.         jmolApplet0 = {
  1497.          script: function(script){document.getElementById("fakeApplet").value="\njmolScript:\n"+script}
  1498.         ,scriptWait: function(script){document.getElementById("fakeApplet").value="\njmolScriptWait:\n"+script}
  1499.         ,loadInline: function(data,script){document.getElementById("fakeApplet").value="\njmolLoadInline data:\n"+data+"\n\nscript:\n"+script}
  1500.         }
  1501. }
  1502.  
  1503.  
  1504. ///////////////////////////////////////////
  1505.  
  1506. //new 9:49 AM 3/6/2007:
  1507.  
  1508. //both w and h are optional.
  1509. //if either is between 0 and 1, then it is taken as percent/100.
  1510. //if either is greater than 1, then it is taken as a size.
  1511. function jmolResize(w,h) {
  1512.  _jmol.alerted = true;
  1513.  var percentW = (!w ? 100 : w <= 1  && w > 0 ? w * 100 : 0)
  1514.  var percentH = (!h ? percentW : h <= 1 && h > 0 ? h * 100 : 0)
  1515.  if (_jmol.browser=="msie") {
  1516.    var width=document.body.clientWidth;
  1517.    var height=document.body.clientHeight;
  1518.  } else {
  1519.    var netscapeScrollWidth=15;
  1520.    var width=window.innerWidth - netscapeScrollWidth;
  1521.    var height=window.innerHeight-netscapeScrollWidth;
  1522.  }
  1523.  var applet = _jmolGetApplet(0);
  1524.  if(!applet)return;
  1525.  applet.style.width = (percentW ? width * percentW/100 : w)+"px"
  1526.  applet.style.height = (percentH ? height * percentH/100 : h)+"px"
  1527.  title=width +  " " + height + " " + (new Date())
  1528. }
  1529.  
  1530.