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