Annotation of loncom/html/adm/jmol/Jmol.js, revision 1.4

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>