Subversion Repositories wimsdev

Rev

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

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