1 // JSmolCore.js -- Jmol core capability
\r
3 // allows Jmol applets to be created on a page with more flexibility and extendability
\r
4 // provides an object-oriented interface for JSpecView and syncing of Jmol/JSpecView
\r
6 // see JSmolApi.js for public user-interface. All these are private functions
\r
8 // BH 5/30/2015 9:33:12 AM adds class swingjs-ui to ignore
\r
9 // BH 5/9/2015 3:38:52 PM adds data-ignoreMouse attribute for JTextField
\r
10 // BH 3/30/2015 9:46:53 PM adds JSAppletPanel for ready callback
\r
11 // BH 12/6/2014 3:32:54 PM Jmol.setAppletCss() broken
\r
12 // BH 9/13/2014 2:15:51 PM embedded JSME loads from SEARCH when Jmol should
\r
13 // BH 8/14/2014 2:52:38 PM drag-drop cache should not be cleared if SPT file is dropped
\r
14 // BH 8/5/2014 6:39:54 AM unnecessary messages about binary for PDB finally removed
\r
15 // BH 8/4/2014 5:30:00 AM automatically switch to no document after page loading
\r
16 // BH 8/2/2014 5:22:40 PM drag-drop broken in JSmol/HTML5
\r
17 // BH 7/23/2014 5:34:08 PM setting a parameter such as readyFunction to null stops file loading
\r
18 // BH 7/3/2014 12:30:28 AM lost drag-drop of models
\r
19 // BH 7/2/2014 4:47:55 AM adding pdbe.org to direct database calls
\r
20 // BH 5/30/2014 7:20:07 AM better dragging for console and menu
\r
21 // BH 4/27/2014 6:31:52 PM allows _USE=SIGNED HTML5 as well as _USE=JAVA HTML5
\r
22 // BH 3/8/2014 5:50:51 PM adds support for dataURI download in FF and Chrome
\r
23 // BH 3/8/2014 8:43:10 AM moves PubChem access to https
\r
24 // BH 3/4/2014 8:40:15 PM adds Jmol.Cache for JSV/Jmol sharing files
\r
25 // BH 2/10/2014 10:07:14 AM added Info.z and Info.zIndexBase
\r
26 // BH 2/9/2014 9:56:06 PM updated JSmolCore.js with option to extend Viewer with code PRIOR to loading Viewer classes
\r
27 // BH 2/6/2014 8:46:25 AM disabled Jmol._tracker for localhost and 127.x.x.x
\r
28 // BH 1/29/2014 8:02:23 AM Jmol.View and Info.viewSet
\r
29 // BH 1/21/2014 12:06:59 PM adding Jmol.Info.cacheFiles (applet, true/false) and applet._cacheFiles and Jmol._fileCache
\r
30 // BH 1/13/2014 2:12:38 PM adding "http://www.nmrdb.org/tools/jmol/predict.php":"%URL", to _DirectDatabaseCalls
\r
31 // BH 12/21/2013 6:38:35 PM applet sync broken
\r
32 // BH 12/6/2013 6:18:32 PM cover.htm and coverImage fix
\r
33 // BH 12/4/2013 7:44:26 PM fix for JME independent search box
\r
34 // BH 12/3/2013 6:30:08 AM fix for ready function returning Boolean instead of boolean in HTML5 version
\r
35 // BH 11/30/2013 10:31:37 AM added type:"GET" for jQuery.ajax() requests instead of using defaults
\r
36 // BH 11/30/2013 10:31:37 AM added cache:true for jQuery.ajax() requests; can override with cache:"NO", not cache:false
\r
37 // BH 11/28/2013 11:09:27 AM added Jmol._alertNoBinary:true
\r
38 // BH 11/26/2013 8:19:55 PM fix !xxxx search commmand entry and stop MSIE from duplicating command
\r
39 // BH 11/25/2013 7:38:31 AM adds Jmol._tracker: option for GoogleAnalytics tracking
\r
40 // BH 11/25/2013 7:39:03 AM adds URL options _J2S= _JAR= _USE=
\r
41 // BH 11/23/2013 10:51:37 PM adds JNLP support for local applet
\r
42 // BH 11/2/2013 12:05:11 PM JSmolJSME fixes; https access fixed
\r
43 // BH 10/31/2013 7:50:06 PM Jmol.Dialog as SwingController; Jmol._mouseOwner added
\r
44 // BH 10/19/2013 7:05:04 AM adding Jmol._ajaxCall for Error Contacting Server; database POST method enabled
\r
45 // BH 10/17/2013 1:40:51 PM adding javajs/swing and Jmol.Dialog
\r
46 // BH 9/30/2013 6:42:24 PM: pdb.gz switch pdb should only be for www.rcsb.org
\r
47 // BH 9/17/2013 10:17:51 AM: asynchronous file reading and saving
\r
48 // BH 8/16/2013 12:02:20 PM: JSmoljQueryExt.js pulled out
\r
49 // BH 8/16/2013 12:02:20 PM: Jmol._touching used properly
\r
51 // BH 3/22/2013 5:53:02 PM: Adds noscript option, JSmol.min.core.js
\r
52 // BH 1/17/2013 5:20:44 PM: Fixed problem with console not getting initial position if no first click
\r
53 // 1/13/2013 BH: Fixed MSIE not-reading-local-files problem.
\r
54 // 11/28/2012 BH: Fixed MacOS Safari binary ArrayBuffer problem
\r
55 // 11/21/2012 BH: restructuring of files as JS... instead of J...
\r
56 // 11/20/2012 BH: MSIE9 cannot do a synchronous file load cross-domain. See Jmol._getFileData
\r
57 // 11/4/2012 BH: RCSB REST format change "<structureId>" to "<dimStructure.structureId>"
\r
58 // 9/13/2012 BH: JmolCore.js changes for JSmol doAjax() method -- _3ata()
\r
59 // 6/12/2012 BH: JmolApi.js: adds Jmol.setInfo(applet, info, isShown) -- third parameter optional
\r
60 // 6/12/2012 BH: JmolApi.js: adds Jmol.getInfo(applet)
\r
61 // 6/12/2012 BH: JmolApplet.js: Fixes for MSIE 8
\r
62 // 6/5/2012 BH: fixes problem with Jmol "javascript" command not working and getPropertyAsArray not working
\r
63 // 6/4/2012 BH: corrects problem with MSIE requiring mouse-hover to activate applet
\r
64 // 5/31/2012 BH: added JSpecView interface and api -- see JmolJSV.js
\r
65 // also changed "jmolJarPath" to just "jarPath"
\r
66 // jmolJarFile->jarFile, jmolIsSigned->isSigned, jmolReadyFunction->readyFunction
\r
67 // also corrects a double-loading issue
\r
68 // 5/14/2012 BH: added AJAX queue for ChemDoodle option with multiple canvases
\r
69 // 8/12/2012 BH: adds support for MSIE xdr cross-domain request (jQuery.iecors.js)
\r
71 // BH 4/25 -- added text option. setAppletCss(null, "style=\"xxxx\"")
\r
72 // note that since you must add the style keyword, this can be used to add any attribute to these tags, not just css.
\r
74 // required/optional libraries (preferably in the following order):
\r
76 // jquery/jquery.js -- at least jQuery.1.9
\r
77 // js/JSmoljQueryext.js -- required for binary file transfer; otherwise standard jQuery should be OK
\r
78 // js/JSmolCore.js -- required
\r
79 // js/j2sjmol.js -- required
\r
80 // js/JSmol.js -- required
\r
81 // js/JSmolApplet.js -- required; internal functions for _Applet and _Image; must be after JSmolCore
\r
82 // js/JSmolControls.js -- optional; internal functions for buttons, links, menus, etc.; must be after JSmolCore
\r
83 // js/JSmolConsole.js -- optional; for the pop-up console
\r
84 // js/JSmolApi.js -- required; all user functions; must be after JSmolCore
\r
85 // js/JSmolTHREE.js -- optional; WebGL library required for JSmolGLmol.js
\r
86 // js/JSmolGLmol.js -- optional; WebGL version of JSmol.
\r
87 // js/JSmolJME.js -- optional; JSME (2D editor)
\r
88 // jsme/jsme/jsme.nocache.js -- required for JSME
\r
89 // js/JSmolMenu.js -- optional; required for menuing in JSV
\r
90 // js/JSmolJSV.js -- optional; for creating and interacting with a JSpecView applet
\r
92 // most of these will be loaded automatically, and for most installations, all you need is JSmol.min.js
\r
95 // Allows Jmol-like objects to be displayed on Java-challenged (iPad/iPhone)
\r
96 // or applet-challenged (Android/iPhone) platforms, with automatic switching to
\r
98 // For your installation, you should consider putting JmolData.jar and jsmol.php
\r
99 // on your own server. Nothing more than these two files is needed on the server, and this
\r
100 // allows more options for MSIE and Chrome when working with cross-domain files (such as RCSB or pubChem)
\r
102 // The NCI and RCSB databases are accessed via direct AJAX if available (xhr2/xdr).
\r
105 if(typeof(jQuery)=="undefined") alert ("Note -- JSmoljQuery is required for JSmol, but it's not defined.")
\r
107 // An example of how to extend Jmol with code PRIOR to JSmolCore.js or JSmol.min.js follows:
\r
112 // extend: function(what, obj) {if (what == "viewer") { obj._testing = true } }
\r
115 self.Jmol || (Jmol = {});
\r
117 if (!Jmol._version)
\r
118 Jmol = (function(document) {
\r
119 var z=Jmol.z || 9000;
\r
120 var getZOrders = function(z) {
\r
129 dialog:z++, // could be several of these, JSV only
\r
130 menu:z+90000, // way front
\r
131 console:z+91000, // even more front
\r
132 consoleImage:z+91001, // bit more front; increments
\r
133 monitorZIndex:z+99999 // way way front
\r
137 _version: "$Date: 2015-04-26 10:57:08 -0500 (Sun, 26 Apr 2015) $", // svn.keywords:lastUpdated
\r
138 _alertNoBinary: true,
\r
139 // this url is used to Google Analytics tracking of Jmol use. You may remove it or modify it if you wish.
\r
140 _allowedJmolSize: [25, 2048, 300], // min, max, default (pixels)
\r
141 /* By setting the Jmol.allowedJmolSize[] variable in the webpage
\r
142 before calling Jmol.getApplet(), limits for applet size can be overriden.
\r
143 2048 standard for GeoWall (http://geowall.geo.lsa.umich.edu/home.html)
\r
145 _appletCssClass: "",
\r
146 _appletCssText: "",
\r
147 _fileCache: null, // enabled by Jmol.setFileCaching(applet, true/false)
\r
148 _jarFile: null, // can be set in URL using _JAR=
\r
149 _j2sPath: null, // can be set in URL using _J2S=
\r
150 _use: null, // can be set in URL using _USE=
\r
151 _j2sLoadMonitorOpacity: 90, // initial opacity for j2s load monitor message
\r
153 _asynchronous: true,
\r
155 _getZOrders: getZOrders,
\r
157 _debugCode: true, // set false in process of minimization
\r
159 _databasePrefixes: "$=:",
\r
160 _fileLoadScript: ";if (_loadScript = '' && defaultLoadScript == '' && _filetype == 'Pdb') { select protein or nucleic;cartoons Only;color structure; select * };",
\r
161 _nciLoadScript: ";n = ({molecule=1}.length < {molecule=2}.length ? 2 : 1); select molecule=n;display selected;center selected;",
\r
162 _pubChemLoadScript: "",
\r
163 _DirectDatabaseCalls:{
\r
164 // these sites are known to implement access-control-allow-origin *
\r
165 "cactus.nci.nih.gov": "%URL",
\r
166 "www.rcsb.org": "%URL",
\r
167 "pdbe.org": "%URL",
\r
168 "www.ebi.ac.uk": "%URL",
\r
169 "wwwdev.ebi.ac.uk": "%URL",
\r
170 "pubchem.ncbi.nlm.nih.gov":"%URL",
\r
171 "http://www.nmrdb.org/tools/jmol/predict.php":"%URL",
\r
172 "$": "http://cactus.nci.nih.gov/chemical/structure/%FILENCI/file?format=sdf&get3d=True",
\r
173 "$$": "http://cactus.nci.nih.gov/chemical/structure/%FILENCI/file?format=sdf",
\r
174 "=": "http://www.rcsb.org/pdb/files/%FILE.pdb",
\r
175 "*": "http://www.ebi.ac.uk/pdbe/entry-files/download/%FILE.cif",
\r
176 "==": "http://www.rcsb.org/pdb/files/ligand/%FILE.cif",
\r
177 ":": "http://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/%FILE/SDF?record_type=3d"
\r
179 _restQueryUrl: "http://www.rcsb.org/pdb/rest/search",
\r
180 _restQueryXml: "<orgPdbQuery><queryType>org.pdb.query.simple.AdvancedKeywordQuery</queryType><description>Text Search</description><keywords>QUERY</keywords></orgPdbQuery>",
\r
181 _restReportUrl: "http://www.pdb.org/pdb/rest/customReport?pdbids=IDLIST&customReportColumns=structureId,structureTitle"
\r
183 _debugAlert: false,
\r
184 _document: document,
\r
186 _lastAppletID: null,
\r
189 _serverUrl: "http://your.server.here/jsmol.php",
\r
190 _syncId: ("" + Math.random()).substring(3),
\r
192 _XhtmlElement: null,
\r
193 _XhtmlAppendChild: false
\r
196 var ref = document.location.href.toLowerCase();
\r
197 j._httpProto = (ref.indexOf("https") == 0 ? "https://" : "http://");
\r
198 j._isFile = (ref.indexOf("file:") == 0);
\r
199 j._ajaxTestSite = j._httpProto + "google.com";
\r
200 var isLocal = (j._isFile || ref.indexOf("http://localhost") == 0 || ref.indexOf("http://127.") == 0);
\r
201 j._tracker = (j._httpProto == "http://" && !isLocal && 'http://chemapps.stolaf.edu/jmol/JmolTracker.htm?id=UA-45940799-1');
\r
203 j._isChrome = (navigator.userAgent.toLowerCase().indexOf("chrome") >= 0);
\r
204 j._isSafari = (!j._isChrome && navigator.userAgent.toLowerCase().indexOf("safari") >= 0);
\r
205 j._isMsie = (window.ActiveXObject !== undefined);
\r
206 j._useDataURI = !j._isSafari && !j._isMsie; // safari may be OK here -- untested
\r
208 for(var i in Jmol) j[i] = Jmol[i]; // allows pre-definition
\r
210 })(document, Jmol);
\r
213 (function (Jmol, $) {
\r
215 // this library is organized into the following sections:
\r
217 // jQuery interface
\r
218 // protected variables
\r
219 // feature detection
\r
220 // AJAX-related core functionality
\r
221 // applet start-up functionality
\r
222 // misc core functionality
\r
226 ////////////////////// jQuery interface ///////////////////////
\r
228 // hooks to jQuery -- if you have a different AJAX tool, feel free to adapt.
\r
229 // There should be no other references to jQuery in all the JSmol libraries.
\r
231 // automatically switch to returning HTML after the page is loaded
\r
232 $(document).ready(function(){ Jmol._document = null });
\r
234 Jmol.$ = function(objectOrId, subdiv) {
\r
235 // if a subdiv, then return $("#objectOrId._id_subdiv")
\r
236 // or if no subdiv, then just $(objectOrId)
\r
237 if (objectOrId == null)alert (subdiv + arguments.callee.caller.toString());
\r
238 return $(subdiv ? "#" + objectOrId._id + "_" + subdiv : objectOrId);
\r
241 Jmol._$ = function(id) {
\r
242 // either the object or $("#" + id)
\r
243 return (typeof id == "string" ? $("#" + id) : id);
\r
246 /// special functions:
\r
248 Jmol.$ajax = function (info) {
\r
249 Jmol._ajaxCall = info.url;
\r
250 info.cache = (info.cache != "NO");
\r
251 if (info.url.indexOf("http://pubchem.ncbi.nlm.nih") == 0)
\r
252 info.url = "https://" + info.url.substring(7);
\r
253 // fluke at pubchem --- requires https now from all pages 3/8/2014
\r
254 // don't let jQuery add $_=... to URL unless we
\r
255 // use cache:"NO"; other packages might use $.ajaxSetup() to set this to cache:false
\r
256 return $.ajax(info);
\r
259 Jmol._getNCIInfo = function(identifier, what, fCallback) {
\r
260 return Jmol._getFileData("http://cactus.nci.nih.gov/chemical/structure/"+identifier +"/" + (what == "name" ? "names" : what));
\r
265 Jmol.$appEvent = function(app, subdiv, evt, f) {
\r
266 var o = Jmol.$(app, subdiv);
\r
267 o.off(evt) && f && o.on(evt, f);
\r
270 Jmol.$resize = function (f) {
\r
271 return $(window).resize(f);
\r
274 //// full identifier expected (could be "body", for example):
\r
276 Jmol.$after = function (what, s) {
\r
277 return $(what).after(s);
\r
280 Jmol.$append = function (what, s) {
\r
281 return $(what).append(s);
\r
284 Jmol.$bind = function(what, list, f) {
\r
285 return (f ? $(what).bind(list, f) : $(what).unbind(list));
\r
288 Jmol.$closest = function(what, d) {
\r
289 return $(what).closest(d);
\r
292 Jmol.$get = function(what, i) {
\r
293 return $(what).get(i);
\r
296 // element id expected
\r
298 Jmol.$documentOff = function(evt, id) {
\r
299 return $(document).off(evt, "#" + id);
\r
302 Jmol.$documentOn = function(evt, id, f) {
\r
303 return $(document).on(evt, "#" + id, f);
\r
306 Jmol.$getAncestorDiv = function(id, className) {
\r
307 return $("div." + className + ":has(#" + id + ")")[0];
\r
310 Jmol.$supportsIECrossDomainScripting = function() {
\r
311 return $.support.iecors;
\r
314 //// element id or jQuery object expected:
\r
316 Jmol.$attr = function (id, a, val) {
\r
317 return Jmol._$(id).attr(a, val);
\r
320 Jmol.$css = function(id, style) {
\r
321 return Jmol._$(id).css(style);
\r
324 Jmol.$find = function(id, d) {
\r
325 return Jmol._$(id).find(d);
\r
328 Jmol.$focus = function(id) {
\r
329 return Jmol._$(id).focus();
\r
332 Jmol.$html = function(id, html) {
\r
333 return Jmol._$(id).html(html);
\r
336 Jmol.$offset = function(id) {
\r
337 return Jmol._$(id).offset();
\r
340 Jmol.$windowOn = function(evt, f) {
\r
341 return $(window).on(evt, f);
\r
344 Jmol.$prop = function(id, p, val) {
\r
345 var o = Jmol._$(id);
\r
346 return (arguments.length == 3 ? o.prop(p, val) : o.prop(p));
\r
349 Jmol.$remove = function(id) {
\r
350 return Jmol._$(id).remove();
\r
353 Jmol.$scrollTo = function (id, n) {
\r
354 var o = Jmol._$(id);
\r
355 return o.scrollTop(n < 0 ? o[0].scrollHeight : n);
\r
358 Jmol.$setEnabled = function(id, b) {
\r
359 return Jmol._$(id).attr("disabled", b ? null : "disabled");
\r
362 Jmol.$setSize = function(id, w, h) {
\r
363 return Jmol._$(id).width(w).height(h);
\r
366 Jmol.$setVisible = function(id, b) {
\r
367 var o = Jmol._$(id);
\r
368 return (b ? o.show() : o.hide());
\r
371 Jmol.$submit = function(id) {
\r
372 return Jmol._$(id).submit();
\r
375 Jmol.$val = function (id, v) {
\r
376 var o = Jmol._$(id);
\r
377 return (arguments.length == 1 ? o.val() : o.val(v));
\r
380 ////////////// protected variables ///////////
\r
383 Jmol._clearVars = function() {
\r
384 // only on page closing -- appears to improve garbage collection
\r
389 delete SwingController;
\r
399 delete c$; // used in p0p; could be gotten rid of
\r
402 ////////////// feature detection ///////////////
\r
404 Jmol.featureDetection = (function(document, window) {
\r
407 features.ua = navigator.userAgent.toLowerCase()
\r
409 features.os = (function(){
\r
410 var osList = ["linux","unix","mac","win"]
\r
411 var i = osList.length;
\r
414 if (features.ua.indexOf(osList[i])!=-1) return osList[i]
\r
419 features.browser = function(){
\r
420 var ua = features.ua;
\r
421 var browserList = ["konqueror","webkit","omniweb","opera","webtv","icab","msie","mozilla"];
\r
422 for (var i = 0; i < browserList.length; i++)
\r
423 if (ua.indexOf(browserList[i])>=0)
\r
424 return browserList[i];
\r
427 features.browserName = features.browser();
\r
428 features.browserVersion= parseFloat(features.ua.substring(features.ua.indexOf(features.browserName)+features.browserName.length+1));
\r
429 features.supportsXhr2 = function() {return ($.support.cors || $.support.iecors)}
\r
430 features.allowDestroy = (features.browserName != "msie");
\r
431 features.allowHTML5 = (features.browserName != "msie" || navigator.appVersion.indexOf("MSIE 8") < 0);
\r
432 features.getDefaultLanguage = function() {
\r
433 return navigator.language || navigator.userLanguage || "en-US";
\r
436 features._webGLtest = 0;
\r
438 features.supportsWebGL = function() {
\r
439 if (!Jmol.featureDetection._webGLtest) {
\r
441 Jmol.featureDetection._webGLtest = (
\r
442 window.WebGLRenderingContext
\r
443 && ((canvas = document.createElement("canvas")).getContext("webgl")
\r
444 || canvas.getContext("experimental-webgl")) ? 1 : -1);
\r
446 return (Jmol.featureDetection._webGLtest > 0);
\r
449 features.supportsLocalization = function() {
\r
450 //<meta charset="utf-8">
\r
451 var metas = document.getElementsByTagName('meta');
\r
452 for (var i= metas.length; --i >= 0;)
\r
453 if (metas[i].outerHTML.toLowerCase().indexOf("utf-8") >= 0) return true;
\r
457 features.supportsJava = function() {
\r
458 if (!Jmol.featureDetection._javaEnabled) {
\r
459 if (Jmol._isMsie) {
\r
460 if (!navigator.javaEnabled()) {
\r
461 Jmol.featureDetection._javaEnabled = -1;
\r
463 //more likely -- would take huge testing
\r
464 Jmol.featureDetection._javaEnabled = 1;
\r
467 Jmol.featureDetection._javaEnabled = (navigator.javaEnabled() && (!navigator.mimeTypes || navigator.mimeTypes["application/x-java-applet"]) ? 1 : -1);
\r
470 return (Jmol.featureDetection._javaEnabled > 0);
\r
473 features.compliantBrowser = function() {
\r
474 var a = !!document.getElementById;
\r
475 var os = features.os;
\r
476 // known exceptions (old browsers):
\r
477 if (features.browserName == "opera" && features.browserVersion <= 7.54 && os == "mac"
\r
478 || features.browserName == "webkit" && features.browserVersion < 125.12
\r
479 || features.browserName == "msie" && os == "mac"
\r
480 || features.browserName == "konqueror" && features.browserVersion <= 3.3
\r
485 features.isFullyCompliant = function() {
\r
486 return features.compliantBrowser() && features.supportsJava();
\r
489 features.useIEObject = (features.os == "win" && features.browserName == "msie" && features.browserVersion >= 5.5);
\r
490 features.useHtml4Object = (features.browserName == "mozilla" && features.browserVersion >= 5) ||
\r
491 (features.browserName == "opera" && features.browserVersion >= 8) ||
\r
492 (features.browserName == "webkit"/* && features.browserVersion >= 412.2 && features.browserVersion < 500*/); // 500 is a guess; required for 536.3
\r
494 features.hasFileReader = (window.File && window.FileReader);
\r
498 })(document, window);
\r
501 ////////////// AJAX-related core functionality //////////////
\r
503 Jmol._ajax = function(info) {
\r
505 return Jmol.$ajax(info).responseText;
\r
507 Jmol._ajaxQueue.push(info)
\r
508 if (Jmol._ajaxQueue.length == 1)
\r
511 Jmol._ajaxDone = function() {
\r
512 var info = Jmol._ajaxQueue.shift();
\r
513 info && Jmol.$ajax(info);
\r
516 Jmol._grabberOptions = [
\r
517 ["$", "NCI(small molecules)"],
\r
518 [":", "PubChem(small molecules)"],
\r
519 ["=", "RCSB(macromolecules)"],
\r
520 ["*", "PDBe(macromolecules)"]
\r
523 Jmol._getGrabberOptions = function(applet) {
\r
524 // feel free to adjust this look to anything you want
\r
525 if (Jmol._grabberOptions.length == 0)
\r
529 var s = '<input type="text" id="ID_query" onfocus="jQuery(this).select()" onkeypress="if(13==event.which){Jmol._applets[\'ID\']._search();return false}" size="32" value="" />';
\r
530 var b = '<button id="ID_submit" onclick="Jmol._applets[\'ID\']._search()">Search</button></nobr>'
\r
531 if (Jmol._grabberOptions.length == 1) {
\r
532 s = '<nobr>' + s + '<span style="display:none">';
\r
535 s += '<br /><nobr>'
\r
537 s += '<select id="ID_select">'
\r
538 for (var i = 0; i < Jmol._grabberOptions.length; i++) {
\r
539 var opt = Jmol._grabberOptions[i];
\r
540 s += '<option value="' + opt[0] + '" ' + (i == 0 ? 'selected' : '') + '>' + opt[1] + '</option>';
\r
542 s = (s + '</select>' + b).replace(/ID/g, applet._id);
\r
543 return '<br />' + s;
\r
546 Jmol._getScriptForDatabase = function(database) {
\r
547 return (database == "$" ? Jmol.db._nciLoadScript : database == ":" ? Jmol.db._pubChemLoadScript : Jmol.db._fileLoadScript);
\r
550 // <dataset><record><structureId>1BLU</structureId><structureTitle>STRUCTURE OF THE 2[4FE-4S] FERREDOXIN FROM CHROMATIUM VINOSUM</structureTitle></record><record><structureId>3EUN</structureId><structureTitle>Crystal structure of the 2[4Fe-4S] C57A ferredoxin variant from allochromatium vinosum</structureTitle></record></dataset>
\r
552 Jmol._setInfo = function(applet, database, data) {
\r
555 if (data.indexOf("ERROR") == 0)
\r
558 switch (database) {
\r
560 var S = data.split("<dimStructure.structureId>");
\r
561 var info = ["<table>"];
\r
562 for (var i = 1; i < S.length; i++) {
\r
563 info.push("<tr><td valign=top><a href=\"javascript:Jmol.search(" + applet._id + ",'=" + S[i].substring(0, 4) + "')\">" + S[i].substring(0, 4) + "</a></td>");
\r
564 info.push("<td>" + S[i].split("Title>")[1].split("</")[0] + "</td></tr>");
\r
566 info.push("</table>");
\r
567 header = (S.length - 1) + " matches";
\r
570 case ":": // pubChem
\r
575 applet._infoHeader = header;
\r
576 applet._info = info.join("");
\r
577 applet._showInfo(true);
\r
580 Jmol._loadSuccess = function(a, fSuccess) {
\r
587 Jmol._loadError = function(fError){
\r
589 Jmol.say("Error connecting to server: " + Jmol._ajaxCall);
\r
590 null!=fError&&fError()
\r
593 Jmol._isDatabaseCall = function(query) {
\r
594 return (Jmol.db._databasePrefixes.indexOf(query.substring(0, 1)) >= 0);
\r
598 Jmol._getDirectDatabaseCall = function(query, checkXhr2) {
\r
599 if (checkXhr2 && !Jmol.featureDetection.supportsXhr2())
\r
603 var call = Jmol.db._DirectDatabaseCalls[query.substring(0,pt)];
\r
605 call = Jmol.db._DirectDatabaseCalls[db = query.substring(0,--pt)];
\r
608 var ql = query.toLowerCase();
\r
609 if (!isNaN(parseInt(query.substring(1)))) {
\r
610 query = "cid/" + query.substring(1);
\r
611 } else if (ql.indexOf(":smiles:") == 0) {
\r
612 call += "?POST?smiles=" + query.substring(8);
\r
614 } else if (ql.indexOf(":cid:") == 0) {
\r
615 query = "cid/" + query.substring(5);
\r
617 if (ql.indexOf(":name:") == 0)
\r
618 query = query.substring(5);
\r
619 else if (ql.indexOf(":cas:") == 0)
\r
620 query = query.substring(4);
\r
621 query = "name/" + encodeURIComponent(query.substring(pt));
\r
624 query = encodeURIComponent(query.substring(pt));
\r
626 if (call.indexOf("FILENCI") >= 0) {
\r
627 query = query.replace(/\%2F/g, "/");
\r
628 query = call.replace(/\%FILENCI/, query);
\r
630 query = call.replace(/\%FILE/, query);
\r
636 Jmol._getRawDataFromServer = function(database,query,fSuccess,fError,asBase64,noScript){
\r
637 // note that this method is now only enabled for "_"
\r
638 // server-side processing of database queries was too slow and only useful for
\r
639 // the IMAGE option, which has been abandoned.
\r
641 "?call=getRawDataFromDatabase&database=" + database + (query.indexOf("?POST?") >= 0 ? "?POST?" : "")
\r
642 + "&query=" + encodeURIComponent(query)
\r
643 + (asBase64 ? "&encoding=base64" : "")
\r
644 + (noScript ? "" : "&script=" + encodeURIComponent(Jmol._getScriptForDatabase(database)));
\r
645 return Jmol._contactServer(s, fSuccess, fError);
\r
648 Jmol._checkFileName = function(applet, fileName, isRawRet) {
\r
649 if (Jmol._isDatabaseCall(fileName)) {
\r
651 Jmol._setQueryTerm(applet, fileName);
\r
652 fileName = Jmol._getDirectDatabaseCall(fileName, true);
\r
653 if (Jmol._isDatabaseCall(fileName)) {
\r
654 // xhr2 not supported (MSIE)
\r
655 fileName = Jmol._getDirectDatabaseCall(fileName, false);
\r
656 isRawRet && (isRawRet[0] = true);
\r
662 Jmol._checkCache = function(applet, fileName, fSuccess) {
\r
663 if (applet._cacheFiles && Jmol._fileCache && !fileName.endsWith(".js")) {
\r
664 var data = Jmol._fileCache[fileName];
\r
666 System.out.println("using " + data.length + " bytes of cached data for " + fileName);
\r
670 fSuccess = function(fileName, data) { fSuccess(Jmol._fileCache[fileName] = data) };
\r
676 Jmol._loadFileData = function(applet, fileName, fSuccess, fError){
\r
678 fileName = Jmol._checkFileName(applet, fileName, isRaw);
\r
679 fSuccess = Jmol._checkCache(applet, fileName, fSuccess);
\r
681 Jmol._getRawDataFromServer("_",fileName,fSuccess,fError);
\r
688 async: Jmol._asynchronous,
\r
689 success: function(a) {Jmol._loadSuccess(a, fSuccess)},
\r
690 error: function() {Jmol._loadError(fError)}
\r
692 Jmol._checkAjaxPost(info);
\r
696 Jmol._getInfoFromDatabase = function(applet, database, query){
\r
697 if (database == "====") {
\r
698 var data = Jmol.db._restQueryXml.replace(/QUERY/,query);
\r
703 contentType:"application/x-www-form-urlencoded",
\r
704 url: Jmol.db._restQueryUrl,
\r
705 data: encodeURIComponent(data) + "&req=browser",
\r
706 success: function(data) {Jmol._ajaxDone();Jmol._extractInfoFromRCSB(applet, database, query, data)},
\r
707 error: function() {Jmol._loadError(null)},
\r
708 async: Jmol._asynchronous
\r
710 return Jmol._ajax(info);
\r
712 query = "?call=getInfoFromDatabase&database=" + database
\r
713 + "&query=" + encodeURIComponent(query);
\r
714 return Jmol._contactServer(query, function(data) {Jmol._setInfo(applet, database, data)});
\r
717 Jmol._extractInfoFromRCSB = function(applet, database, query, output) {
\r
718 var n = output.length/5;
\r
721 if (query.length == 4 && n != 1) {
\r
722 var QQQQ = query.toUpperCase();
\r
723 var pt = output.indexOf(QQQQ);
\r
724 if (pt > 0 && "123456789".indexOf(QQQQ.substring(0, 1)) >= 0)
\r
725 output = QQQQ + "," + output.substring(0, pt) + output.substring(pt + 5);
\r
727 output = output.substring(0, 250);
\r
728 output = output.replace(/\n/g,",");
\r
729 var url = Jmol._restReportUrl.replace(/IDLIST/,output);
\r
730 Jmol._loadFileData(applet, url, function(data) {Jmol._setInfo(applet, database, data) });
\r
734 Jmol._checkAjaxPost = function(info) {
\r
735 var pt = info.url.indexOf("?POST?");
\r
737 info.data = info.url.substring(pt + 6);
\r
738 info.url = info.url.substring(0, pt);
\r
739 info.type = "POST";
\r
740 info.contentType = "application/x-www-form-urlencoded";
\r
743 Jmol._contactServer = function(data,fSuccess,fError){
\r
747 url: Jmol._serverUrl + data,
\r
748 success: function(a) {Jmol._loadSuccess(a, fSuccess)},
\r
749 error:function() { Jmol._loadError(fError) },
\r
750 async:fSuccess ? Jmol._asynchronous : false
\r
752 Jmol._checkAjaxPost(info);
\r
753 return Jmol._ajax(info);
\r
756 Jmol._setQueryTerm = function(applet, query) {
\r
757 if (!query || !applet._hasOptions || query.substring(0, 7) == "http://")
\r
759 if (Jmol._isDatabaseCall(query)) {
\r
760 var database = query.substring(0, 1);
\r
761 query = query.substring(1);
\r
762 if (query.substring(0,1) == database && "=$".indexOf(database) >= 0)
\r
763 query = query.substring(1);
\r
764 var d = Jmol._getElement(applet, "select");
\r
765 if (d && d.options)
\r
766 for (var i = 0; i < d.options.length; i++)
\r
767 if (d[i].value == database)
\r
768 d[i].selected = true;
\r
770 Jmol.$val(Jmol.$(applet, "query"), query);
\r
773 Jmol._search = function(applet, query, script) {
\r
774 arguments.length > 1 || (query = null);
\r
775 Jmol._setQueryTerm(applet, query);
\r
776 query || (query = Jmol.$val(Jmol.$(applet, "query")))
\r
777 if (query.indexOf("!") == 0) {
\r
778 // command prompt in this box as well
\r
779 // remove exclamation point "immediate" indicator
\r
780 applet._script(query.substring(1));
\r
783 query && (query = query.replace(/\"/g, ""));
\r
784 applet._showInfo(false);
\r
785 Jmol._searchMol(applet, query, script, true);
\r
788 Jmol._searchMol = function(applet, query, script, checkView) {
\r
790 if (Jmol._isDatabaseCall(query)) {
\r
791 database = query.substring(0, 1);
\r
792 query = query.substring(1);
\r
794 database = (applet._hasOptions ? Jmol.$val(Jmol.$(applet, "select")) : "$");
\r
796 if (database == "=" && query.length == 3)
\r
797 query = "=" + query; // this is a ligand
\r
798 var dm = database + query;
\r
799 if (!query || dm.indexOf("?") < 0 && dm == applet._thisJmolModel) {
\r
802 applet._thisJmolModel = dm;
\r
804 if (checkView && applet._viewSet != null && (view = Jmol.View.__findView(applet._viewSet, {chemID:dm})) != null) {
\r
805 Jmol.View.__setView(view, applet, false);
\r
809 if (database == "$" || database == ":")
\r
810 applet._jmolFileType = "MOL";
\r
811 else if (database == "=")
\r
812 applet._jmolFileType = "PDB";
\r
813 applet._searchDatabase(query, database, script);
\r
816 Jmol._searchDatabase = function(applet, query, database, script) {
\r
817 applet._showInfo(false);
\r
818 if (query.indexOf("?") >= 0) {
\r
819 Jmol._getInfoFromDatabase(applet, database, query.split("?")[0]);
\r
822 if (Jmol.db._DirectDatabaseCalls[database]) {
\r
823 applet._loadFile(database + query, script);
\r
829 Jmol._syncBinaryOK="?";
\r
831 Jmol._canSyncBinary = function(isSilent) {
\r
832 if (Jmol._isAsync) return true;
\r
833 if (self.VBArray) return (Jmol._syncBinaryOK = false);
\r
834 if (Jmol._syncBinaryOK != "?") return Jmol._syncBinaryOK;
\r
835 Jmol._syncBinaryOK = true;
\r
837 var xhr = new window.XMLHttpRequest();
\r
838 xhr.open( "text", Jmol._ajaxTestSite, false );
\r
839 if (xhr.hasOwnProperty("responseType")) {
\r
840 xhr.responseType = "arraybuffer";
\r
841 } else if (xhr.overrideMimeType) {
\r
842 xhr.overrideMimeType('text/plain; charset=x-user-defined');
\r
845 var s = "JSmolCore.js: synchronous binary file transfer is requested but not available";
\r
846 System.out.println(s);
\r
847 if (Jmol._alertNoBinary && !isSilent)
\r
849 return Jmol._syncBinaryOK = false;
\r
854 Jmol._binaryTypes = [".gz",".jpg",".gif",".png",".zip",".jmol",".bin",".smol",".spartan",".mrc",".pse", ".map", ".omap"];
\r
856 Jmol._isBinaryUrl = function(url) {
\r
857 for (var i = Jmol._binaryTypes.length; --i >= 0;)
\r
858 if (url.indexOf(Jmol._binaryTypes[i]) >= 0) return true;
\r
862 Jmol._getFileData = function(fileName, fSuccess, doProcess) {
\r
863 // use host-server PHP relay if not from this host
\r
864 var isBinary = Jmol._isBinaryUrl(fileName);
\r
865 var isPDB = (fileName.indexOf("pdb.gz") >= 0 && fileName.indexOf("http://www.rcsb.org/pdb/files/") == 0);
\r
866 var asBase64 = (isBinary && !Jmol._canSyncBinary(isPDB));
\r
867 if (asBase64 && isPDB) {
\r
868 // avoid unnecessary binary transfer
\r
869 fileName = fileName.replace(/pdb\.gz/,"pdb");
\r
870 asBase64 = isBinary = false;
\r
872 var isPost = (fileName.indexOf("?POST?") >= 0);
\r
873 if (fileName.indexOf("file:/") == 0 && fileName.indexOf("file:///") != 0)
\r
874 fileName = "file://" + fileName.substring(5); /// fixes IE problem
\r
875 var isMyHost = (fileName.indexOf("://") < 0 || fileName.indexOf(document.location.protocol) == 0 && fileName.indexOf(document.location.host) >= 0);
\r
876 var isDirectCall = Jmol._isDirectCall(fileName);
\r
877 //if (fileName.indexOf("http://pubchem.ncbi.nlm.nih.gov/") == 0)isDirectCall = false;
\r
879 var cantDoSynchronousLoad = (!isMyHost && Jmol.$supportsIECrossDomainScripting());
\r
881 if ((!fSuccess || asBase64) && (cantDoSynchronousLoad || asBase64 || !isMyHost && !isDirectCall)) {
\r
882 data = Jmol._getRawDataFromServer("_",fileName, fSuccess, fSuccess, asBase64, true);
\r
884 fileName = fileName.replace(/file:\/\/\/\//, "file://"); // opera
\r
885 var info = {dataType:(isBinary ? "binary" : "text"),async:!!fSuccess};
\r
887 info.type = "POST";
\r
888 info.url = fileName.split("?POST?")[0]
\r
889 info.data = fileName.split("?POST?")[1]
\r
892 info.url = fileName;
\r
895 info.success = function(data) { fSuccess(Jmol._xhrReturn(info.xhr))};
\r
896 info.error = function() { fSuccess(info.xhr.statusText)};
\r
898 info.xhr = Jmol.$ajax(info);
\r
900 data = Jmol._xhrReturn(info.xhr);
\r
905 if (data == null) {
\r
909 isBinary && (isBinary = Jmol._canSyncBinary(true));
\r
910 return (isBinary ? Jmol._strToBytes(data) : JU.SB.newS(data));
\r
913 Jmol._xhrReturn = function(xhr){
\r
914 if (!xhr.responseText || self.Clazz && Clazz.instanceOf(xhr.response, self.ArrayBuffer)) {
\r
915 // Safari or error
\r
916 return xhr.response || xhr.statusText;
\r
918 return xhr.responseText;
\r
921 Jmol._isDirectCall = function(url) {
\r
922 for (var key in Jmol.db._DirectDatabaseCalls) {
\r
923 if (key.indexOf(".") >= 0 && url.indexOf(key) >= 0)
\r
929 Jmol._cleanFileData = function(data) {
\r
930 if (data.indexOf("\r") >= 0 && data.indexOf("\n") >= 0) {
\r
931 return data.replace(/\r\n/g,"\n");
\r
933 if (data.indexOf("\r") >= 0) {
\r
934 return data.replace(/\r/g,"\n");
\r
939 Jmol._getFileType = function(name) {
\r
940 var database = name.substring(0, 1);
\r
941 if (database == "$" || database == ":")
\r
943 if (database == "=")
\r
944 return (name.substring(1,2) == "=" ? "LCIF" : "PDB");
\r
945 // just the extension, which must be PDB, XYZ..., CIF, or MOL
\r
946 name = name.split('.').pop().toUpperCase();
\r
947 return name.substring(0, Math.min(name.length, 3));
\r
950 Jmol._getZ = function(applet, what) {
\r
951 return applet && applet._z && applet._z[what] || Jmol._z[what];
\r
954 Jmol._incrZ = function(applet, what) {
\r
955 return applet && applet._z && ++applet._z[what] || ++Jmol._z[what];
\r
958 Jmol._loadFileAsynchronously = function(fileLoadThread, applet, fileName, appData) {
\r
959 if (fileName.indexOf("?") != 0) {
\r
960 // LOAD ASYNC command
\r
961 var fileName0 = fileName;
\r
962 fileName = Jmol._checkFileName(applet, fileName);
\r
963 var fSuccess = function(data) {Jmol._setData(fileLoadThread, fileName, fileName0, data, appData)};
\r
964 fSuccess = Jmol._checkCache(applet, fileName, fSuccess);
\r
965 if (fileName.indexOf("|") >= 0)
\r
966 fileName = fileName.split("|")[0];
\r
967 return (fSuccess == null ? null : Jmol._getFileData(fileName, fSuccess));
\r
969 // we actually cannot suggest a fileName, I believe.
\r
970 if (!Jmol.featureDetection.hasFileReader)
\r
971 return fileLoadThread.setData("Local file reading is not enabled in your browser", null, null, appData);
\r
972 if (!applet._localReader) {
\r
973 var div = '<div id="ID" style="z-index:'+Jmol._getZ(applet, "fileOpener") + ';position:absolute;background:#E0E0E0;left:10px;top:10px"><div style="margin:5px 5px 5px 5px;"><input type="file" id="ID_files" /><button id="ID_loadfile">load</button><button id="ID_cancel">cancel</button></div><div>'
\r
974 Jmol.$after("#" + applet._id + "_appletdiv", div.replace(/ID/g, applet._id + "_localReader"));
\r
975 applet._localReader = Jmol.$(applet, "localReader");
\r
977 Jmol.$appEvent(applet, "localReader_loadfile", "click");
\r
978 Jmol.$appEvent(applet, "localReader_loadfile", "click", function(evt) {
\r
979 var file = Jmol.$(applet, "localReader_files")[0].files[0];
\r
980 var reader = new FileReader();
\r
981 reader.onloadend = function(evt) {
\r
982 if (evt.target.readyState == FileReader.DONE) { // DONE == 2
\r
983 Jmol.$css(Jmol.$(applet, "localReader"), {display : "none"});
\r
984 Jmol._setData(fileLoadThread, file.name, file.name, evt.target.result, appData);
\r
987 reader.readAsArrayBuffer(file);
\r
989 Jmol.$appEvent(applet, "localReader_cancel", "click");
\r
990 Jmol.$appEvent(applet, "localReader_cancel", "click", function(evt) {
\r
991 Jmol.$css(Jmol.$(applet, "localReader"), {display: "none"});
\r
992 fileLoadThread.setData(null, null, null, appData);
\r
994 Jmol.$css(Jmol.$(applet, "localReader"), {display : "block"});
\r
997 Jmol._setData = function(fileLoadThread, filename, filename0, data, appData) {
\r
998 data = Jmol._strToBytes(data);
\r
999 if (filename.indexOf(".jdx") >= 0)
\r
1000 Jmol.Cache.put("cache://" + filename, data);
\r
1001 fileLoadThread.setData(filename, filename0, data, appData);
\r
1004 Jmol._toBytes = function(data) {
\r
1005 if (typeof data == "string")
\r
1006 return data.getBytes();
\r
1007 // ArrayBuffer assumed here
\r
1008 data = new Uint8Array(data);
\r
1009 var b = Clazz.newByteArray(data.length, 0);
\r
1010 for (var i = data.length; --i >= 0;)
\r
1015 Jmol._doAjax = function(url, postOut, dataOut) {
\r
1016 // called by org.jmol.awtjs2d.JmolURLConnection.doAjax()
\r
1017 url = url.toString();
\r
1019 if (dataOut != null)
\r
1020 return Jmol._saveFile(url, dataOut);
\r
1022 url += "?POST?" + postOut;
\r
1023 return Jmol._getFileData(url, null, true);
\r
1026 // Jmol._localFileSaveFunction -- // do something local here; Maybe try the FileSave interface? return true if successful
\r
1028 Jmol._saveFile = function(filename, data, mimetype, encoding) {
\r
1029 if (Jmol._localFileSaveFunction && Jmol._localFileSaveFunction(filename, data))
\r
1031 var filename = filename.substring(filename.lastIndexOf("/") + 1);
\r
1032 mimetype || (mimetype = (filename.indexOf(".pdf") >= 0 ? "application/pdf"
\r
1033 : filename.indexOf(".png") >= 0 ? "image/png"
\r
1034 : filename.indexOf(".gif") >= 0 ? "image/gif"
\r
1035 : filename.indexOf(".jpg") >= 0 ? "image/jpg" : ""));
\r
1036 var isString = (typeof data == "string");
\r
1038 data = (JU ? JU : J.util).Base64.getBase64(data).toString();
\r
1039 encoding || (encoding = (isString ? "" : "base64"));
\r
1040 var url = Jmol._serverUrl;
\r
1041 url && url.indexOf("your.server") >= 0 && (url = "");
\r
1042 if (Jmol._useDataURI || !url) {
\r
1043 // Asynchronous output generated using an anchor tag
\r
1044 encoding || (data = btoa(data));
\r
1045 var a = document.createElement("a");
\r
1046 a.href = "data:" + mimetype + ";base64," + data;
\r
1047 a.type = mimetype || (mimetype = "text/plain");
\r
1048 a.download = filename;
\r
1049 a.target = "_blank";
\r
1050 $("body").append(a);
\r
1054 // Asynchronous outputto be reflected as a download
\r
1055 if (!Jmol._formdiv) {
\r
1056 var sform = '<div id="__jsmolformdiv__" style="display:none">\
\r
1057 <form id="__jsmolform__" method="post" target="_blank" action="">\
\r
1058 <input name="call" value="saveFile"/>\
\r
1059 <input id="__jsmolmimetype__" name="mimetype" value=""/>\
\r
1060 <input id="__jsmolencoding__" name="encoding" value=""/>\
\r
1061 <input id="__jsmolfilename__" name="filename" value=""/>\
\r
1062 <textarea id="__jsmoldata__" name="data"></textarea>\
\r
1065 Jmol.$after("body", sform);
\r
1066 Jmol._formdiv = "__jsmolform__";
\r
1068 Jmol.$attr(Jmol._formdiv, "action", url + "?" + (new Date()).getMilliseconds());
\r
1069 Jmol.$val("__jsmoldata__", data);
\r
1070 Jmol.$val("__jsmolfilename__", filename);
\r
1071 Jmol.$val("__jsmolmimetype__", mimetype);
\r
1072 Jmol.$val("__jsmolencoding__", encoding);
\r
1073 Jmol.$submit("__jsmolform__");
\r
1074 Jmol.$val("__jsmoldata__", "");
\r
1075 Jmol.$val("__jsmolfilename__", "");
\r
1080 Jmol._strToBytes = function(s) {
\r
1081 if (Clazz.instanceOf(s, self.ArrayBuffer))
\r
1082 return Jmol._toBytes(s);
\r
1083 var b = Clazz.newByteArray(s.length, 0);
\r
1084 for (var i = s.length; --i >= 0;)
\r
1085 b[i] = s.charCodeAt(i) & 0xFF;
\r
1089 ////////////// applet start-up functionality //////////////
\r
1091 Jmol._setConsoleDiv = function (d) {
\r
1092 if (!self.Clazz)return;
\r
1093 Clazz.setConsoleDiv(d);
\r
1096 Jmol._registerApplet = function(id, applet) {
\r
1097 return window[id] = Jmol._applets[id] = Jmol._applets[applet] = Jmol._applets[id + "__" + Jmol._syncId + "__"] = applet;
\r
1100 Jmol._readyCallback = function (appId,fullId,isReady,javaApplet,javaAppletPanel) {
\r
1101 appId = appId.split("_object")[0];
\r
1102 javaAppletPanel || (javaAppletPanel = javaApplet);
\r
1103 isReady = (isReady.booleanValue ? isReady.booleanValue() : isReady);
\r
1104 // necessary for MSIE in strict mode -- apparently, we can't call
\r
1105 // jmol._readyCallback, but we can call Jmol._readyCallback. Go figure...
\r
1106 var applet = Jmol._applets[appId];
\r
1107 applet._appletPanel = javaAppletPanel;
\r
1108 applet._applet = javaApplet;
\r
1109 Jmol._track(applet._readyCallback(appId, fullId, isReady));
\r
1112 Jmol._getWrapper = function(applet, isHeader) {
\r
1114 // id_appletinfotablediv
\r
1117 // id_infotablediv
\r
1118 // id_infoheaderdiv
\r
1119 // id_infoheaderspan
\r
1120 // id_infocheckboxspan
\r
1124 // for whatever reason, without DOCTYPE, with MSIE, "height:auto" does not work,
\r
1125 // and the text scrolls off the page.
\r
1126 // So I'm using height:95% here.
\r
1127 // The table was a fix for MSIE with no DOCTYPE tag to fix the miscalculation
\r
1128 // in height of the div when using 95% for height.
\r
1129 // But it turns out the table has problems with DOCTYPE tags, so that's out.
\r
1130 // The 95% is a compromise that we need until the no-DOCTYPE MSIE solution is found.
\r
1131 // (100% does not work with the JME linked applet)
\r
1133 // ... here are just for clarification in this code; they are removed immediately
\r
1136 if (applet._coverImage){
\r
1137 var more = " onclick=\"Jmol.coverApplet(ID, false)\" title=\"" + (applet._coverTitle) + "\"";
\r
1138 var play = "<image id=\"ID_coverclickgo\" src=\"" + applet._j2sPath + "/img/play_make_live.jpg\" style=\"width:25px;height:25px;position:absolute;bottom:10px;left:10px;"
\r
1139 + "z-index:" + Jmol._getZ(applet, "coverImage")+";opacity:0.5;\"" + more + " />"
\r
1140 img = "<div id=\"ID_coverdiv\" style=\"background-color:red;z-index:" + Jmol._getZ(applet, "coverImage")+";width:100%;height:100%;display:inline;position:absolute;top:0px;left:0px\"><image id=\"ID_coverimage\" src=\""
\r
1141 + applet._coverImage + "\" style=\"width:100%;height:100%\"" + more + "/>" + play + "</div>";
\r
1143 var css = Jmol._appletCssText.replace(/\'/g,'"');
\r
1144 css = (css.indexOf("style=\"") >= 0 ? css.split("style=\"")[1] : "\" " + css);
\r
1146 ...<div id=\"ID_appletinfotablediv\" style=\"width:Wpx;height:Hpx;position:relative;font-size:14px;text-align:left\">IMG\
\r
1147 ......<div id=\"ID_appletdiv\" style=\"z-index:" + Jmol._getZ(applet, "header") + ";width:100%;height:100%;position:absolute;top:0px;left:0px;" + css + ">";
\r
1148 var height = applet._height;
\r
1149 var width = applet._width;
\r
1150 if (typeof height !== "string" || height.indexOf("%") < 0)
\r
1152 if (typeof width !== "string" || width.indexOf("%") < 0)
\r
1154 s = s.replace(/IMG/, img).replace(/Hpx/g, height).replace(/Wpx/g, width);
\r
1158 ......<div id=\"ID_2dappletdiv\" style=\"position:absolute;width:100%;height:100%;overflow:hidden;display:none\"></div>\
\r
1159 ......<div id=\"ID_infotablediv\" style=\"width:100%;height:100%;position:absolute;top:0px;left:0px\">\
\r
1160 .........<div id=\"ID_infoheaderdiv\" style=\"height:20px;width:100%;background:yellow;display:none\"><span id=\"ID_infoheaderspan\"></span><span id=\"ID_infocheckboxspan\" style=\"position:absolute;text-align:right;right:1px;\"><a href=\"javascript:Jmol.showInfo(ID,false)\">[x]</a></span></div>\
\r
1161 .........<div id=\"ID_infodiv\" style=\"position:absolute;top:20px;bottom:0px;width:100%;height:100%;overflow:auto\"></div>\
\r
1165 return s.replace(/\.\.\./g,"").replace(/[\n\r]/g,"").replace(/ID/g, applet._id);
\r
1168 Jmol._documentWrite = function(text) {
\r
1169 if (Jmol._document) {
\r
1170 if (Jmol._isXHTML && !Jmol._XhtmlElement) {
\r
1171 var s = document.getElementsByTagName("script");
\r
1172 Jmol._XhtmlElement = s.item(s.length - 1);
\r
1173 Jmol._XhtmlAppendChild = false;
\r
1175 if (Jmol._XhtmlElement)
\r
1176 Jmol._domWrite(text);
\r
1178 Jmol._document.write(text);
\r
1183 Jmol._domWrite = function(data) {
\r
1187 while (Ptr[0] < data.length) {
\r
1188 var child = Jmol._getDomElement(data, Ptr);
\r
1191 if (Jmol._XhtmlAppendChild)
\r
1192 Jmol._XhtmlElement.appendChild(child);
\r
1194 Jmol._XhtmlElement.parentNode.insertBefore(child, _jmol.XhtmlElement);
\r
1198 Jmol._getDomElement = function(data, Ptr, closetag, lvel) {
\r
1200 // there is no "document.write" in XHTML
\r
1202 var e = document.createElement("span");
\r
1203 e.innerHTML = data;
\r
1204 Ptr[0] = data.length;
\r
1209 closetag || (closetag = "");
\r
1210 lvel || (lvel = 0);
\r
1213 while (pt < data.length && data.charAt(pt) != "<")
\r
1216 var text = data.substring(pt0, pt);
\r
1218 return document.createTextNode(text);
\r
1222 while (pt < data.length && "\n\r\t >".indexOf(ch = data.charAt(pt)) < 0)
\r
1224 var tagname = data.substring(pt0, pt);
\r
1225 var e = (tagname == closetag || tagname == "/" ? ""
\r
1226 : document.createElementNS ? document.createElementNS('http://www.w3.org/1999/xhtml', tagname)
\r
1227 : document.createElement(tagname));
\r
1232 while (pt < data.length && (ch = data.charAt(pt)) != ">") {
\r
1233 while (pt < data.length && "\n\r\t ".indexOf(ch = data.charAt(pt)) >= 0)
\r
1236 while (pt < data.length && "\n\r\t =/>".indexOf(ch = data.charAt(pt)) < 0)
\r
1238 var attrname = data.substring(pt0, pt).toLowerCase();
\r
1239 if (attrname && ch != "=")
\r
1240 e.setAttribute(attrname, "true");
\r
1241 while (pt < data.length && "\n\r\t ".indexOf(ch = data.charAt(pt)) >= 0)
\r
1246 } else if (ch == "=") {
\r
1247 var quote = data.charAt(++pt);
\r
1249 while (pt < data.length && (ch = data.charAt(pt)) != quote)
\r
1251 var attrvalue = data.substring(pt0, pt);
\r
1252 e.setAttribute(attrname, attrvalue);
\r
1257 while (Ptr[0] < data.length) {
\r
1258 var child = Jmol._getDomElement(data, Ptr, "/" + tagname, lvel+1);
\r
1261 e.appendChild(child);
\r
1267 Jmol._setObject = function(obj, id, Info) {
\r
1270 Info.z && Info.zIndexBase && (Jmol._z = Jmol._getZOrders(Info.zIndexBase));
\r
1271 for (var i in Info)
\r
1272 obj.__Info[i] = Info[i];
\r
1273 (obj._z = Info.z) || Info.zIndexBase && (obj._z = obj.__Info.z = Jmol._getZOrders(Info.zIndexBase));
\r
1274 obj._width = Info.width;
\r
1275 obj._height = Info.height;
\r
1276 obj._noscript = !obj._isJava && Info.noscript;
\r
1277 obj._console = Info.console;
\r
1278 obj._cacheFiles = !!Info.cacheFiles;
\r
1279 obj._viewSet = (Info.viewSet == null || obj._isJava ? null : "Set" + Info.viewSet);
\r
1280 if (obj._viewSet != null) {
\r
1281 Jmol.View.__init(obj);
\r
1282 obj._currentView = null;
\r
1284 !Jmol._fileCache && obj._cacheFiles && (Jmol._fileCache = {});
\r
1285 if (!obj._console)
\r
1286 obj._console = obj._id + "_infodiv";
\r
1287 if (obj._console == "none")
\r
1288 obj._console = null;
\r
1290 obj._color = (Info.color ? Info.color.replace(/0x/,"#") : "#FFFFFF");
\r
1291 obj._disableInitialConsole = Info.disableInitialConsole;
\r
1292 obj._noMonitor = Info.disableJ2SLoadMonitor;
\r
1293 Jmol._j2sPath && (Info.j2sPath = Jmol._j2sPath);
\r
1294 obj._j2sPath = Info.j2sPath;
\r
1295 obj._coverImage = Info.coverImage;
\r
1296 obj._isCovered = !!obj._coverImage;
\r
1297 obj._deferApplet = Info.deferApplet || obj._isCovered && obj._isJava; // must do this if covered in Java
\r
1298 obj._deferUncover = Info.deferUncover && !obj._isJava; // can't do this with Java
\r
1299 obj._coverScript = Info.coverScript;
\r
1300 obj._coverTitle = Info.coverTitle;
\r
1302 if (!obj._coverTitle)
\r
1303 obj._coverTitle = (obj._deferApplet ? "activate 3D model" : "3D model is loading...")
\r
1304 obj._containerWidth = obj._width + ((obj._width==parseFloat(obj._width))? "px":"");
\r
1305 obj._containerHeight = obj._height + ((obj._height==parseFloat(obj._height))? "px":"");
\r
1307 obj._infoHeader = obj._jmolType + ' "' + obj._id + '"'
\r
1308 obj._hasOptions = Info.addSelectionOptions;
\r
1309 obj._defaultModel = Info.defaultModel;
\r
1310 obj._readyScript = (Info.script ? Info.script : "");
\r
1311 obj._readyFunction = Info.readyFunction;
\r
1312 if (obj._coverImage && !obj._deferApplet)
\r
1313 obj._readyScript += ";javascript " + id + "._displayCoverImage(false)";
\r
1314 obj._src = Info.src;
\r
1318 Jmol._addDefaultInfo = function(Info, DefaultInfo) {
\r
1319 for (var x in DefaultInfo)
\r
1320 if (typeof Info[x] == "undefined")
\r
1321 Info[x] = DefaultInfo[x];
\r
1322 Jmol._use && (Info.use = Jmol._use);
\r
1323 if (Info.use.indexOf("SIGNED") >= 0) {
\r
1324 if (Info.jarFile.indexOf("Signed") < 0)
\r
1325 Info.jarFile = Info.jarFile.replace(/Applet/,"AppletSigned");
\r
1326 Info.use = Info.use.replace(/SIGNED/, "JAVA");
\r
1327 Info.isSigned = true;
\r
1331 Jmol._syncedApplets = [];
\r
1332 Jmol._syncedCommands = [];
\r
1333 Jmol._syncedReady = [];
\r
1334 Jmol._syncReady = false;
\r
1335 Jmol._isJmolJSVSync = false;
\r
1337 Jmol._setReady = function(applet) {
\r
1338 Jmol._syncedReady[applet] = 1;
\r
1340 for (var i = 0; i < Jmol._syncedApplets.length; i++) {
\r
1341 if (Jmol._syncedApplets[i] == applet._id) {
\r
1342 Jmol._syncedApplets[i] = applet;
\r
1343 Jmol._syncedReady[i] = 1;
\r
1344 } else if (!Jmol._syncedReady[i]) {
\r
1349 if (n != Jmol._syncedApplets.length)
\r
1351 Jmol._setSyncReady();
\r
1354 Jmol._setDestroy = function(applet) {
\r
1355 //MSIE bug responds to any link click even if it is just a JavaScript call
\r
1357 if (Jmol.featureDetection.allowDestroy)
\r
1358 Jmol.$windowOn('beforeunload', function () { Jmol._destroy(applet); } );
\r
1361 Jmol._destroy = function(applet) {
\r
1363 if (applet._appletPanel) applet._appletPanel.destroy();
\r
1364 applet._applet = null;
\r
1365 Jmol._unsetMouse(applet._canvas)
\r
1366 applet._canvas = null;
\r
1368 for (var i = 0; i < Jmol._syncedApplets.length; i++) {
\r
1369 if (Jmol._syncedApplets[i] == applet)
\r
1370 Jmol._syncedApplets[i] = null;
\r
1371 if (Jmol._syncedApplets[i])
\r
1376 Jmol._clearVars();
\r
1380 ////////////// misc core functionality //////////////
\r
1382 Jmol._setSyncReady = function() {
\r
1383 Jmol._syncReady = true;
\r
1385 for (var i = 0; i < Jmol._syncedApplets.length; i++)
\r
1386 if (Jmol._syncedCommands[i])
\r
1387 s += "Jmol.script(Jmol._syncedApplets[" + i + "], Jmol._syncedCommands[" + i + "]);"
\r
1388 setTimeout(s, 50);
\r
1391 Jmol._mySyncCallback = function(appFullName,msg) {
\r
1392 app = Jmol._applets[appFullName];
\r
1393 if (app._viewSet) {
\r
1394 // when can we do this?
\r
1395 // if (app._viewType == "JSV" && !app._currentView.JMOL)
\r
1396 Jmol.View.updateFromSync(app, msg);
\r
1399 if(!Jmol._syncReady || !Jmol._isJmolJSVSync)
\r
1400 return 1; // continue processing and ignore me
\r
1401 for (var i = 0; i < Jmol._syncedApplets.length; i++) {
\r
1402 if (msg.indexOf(Jmol._syncedApplets[i]._syncKeyword) >= 0)
\r
1403 Jmol._syncedApplets[i]._syncScript(msg);
\r
1405 return 0 // prevents further Jmol sync processing
\r
1408 Jmol._getElement = function(applet, what) {
\r
1409 var d = document.getElementById(applet._id + "_" + what);
\r
1413 Jmol._evalJSON = function(s,key){
\r
1417 if(s.charAt(0) != "{") {
\r
1418 if(s.indexOf(" | ") >= 0)
\r
1419 s = s.replace(/\ \|\ /g, "\n");
\r
1422 var A = (new Function( "return " + s ) )();
\r
1423 return (!A ? null : key && A[key] != undefined ? A[key] : A);
\r
1426 Jmol._sortMessages = function(A){
\r
1428 * private function
\r
1430 function _sortKey0(a,b){
\r
1431 return (a[0]<b[0]?1:a[0]>b[0]?-1:0);
\r
1434 if(!A || typeof (A) != "object")
\r
1437 for(var i = A.length - 1; i >= 0; i--)
\r
1438 for(var j = 0, jj= A[i].length; j < jj; j++)
\r
1439 B[B.length] = A[i][j];
\r
1442 B = B.sort(_sortKey0);
\r
1446 //////////////////// mouse events //////////////////////
\r
1448 Jmol._setMouseOwner = function(who, tf) {
\r
1449 if (who == null || tf)
\r
1450 Jmol._mouseOwner = who;
\r
1451 else if (Jmol._mouseOwner == who)
\r
1452 Jmol._mouseOwner = null;
\r
1455 Jmol._jsGetMouseModifiers = function(ev) {
\r
1456 var modifiers = 0;
\r
1457 switch (ev.button) {
\r
1459 modifiers = 16;//J.api.Event.MOUSE_LEFT;
\r
1462 modifiers = 8;//J.api.Event.MOUSE_MIDDLE;
\r
1465 modifiers = 4;//J.api.Event.MOUSE_RIGHT;
\r
1469 modifiers += 1;//J.api.Event.SHIFT_MASK;
\r
1471 modifiers += 8;//J.api.Event.ALT_MASK;
\r
1473 modifiers += 2;//J.api.Event.CTRL_MASK;
\r
1477 Jmol._jsGetXY = function(canvas, ev) {
\r
1478 if (!canvas.applet._ready || Jmol._touching && ev.type.indexOf("touch") < 0)
\r
1480 //ev.preventDefault(); // removed 5/9/2015 -- caused loss of focus on text-box clicking in SwingJS
\r
1481 var offsets = Jmol.$offset(canvas.id);
\r
1483 var oe = ev.originalEvent;
\r
1484 // drag-drop jQuery event is missing pageX
\r
1485 ev.pageX || (ev.pageX = oe.pageX);
\r
1486 ev.pageY || (ev.pageY = oe.pageY);
\r
1487 Jmol._mousePageX = ev.pageX;
\r
1488 Jmol._mousePageY = ev.pageY;
\r
1489 if (oe.targetTouches && oe.targetTouches[0]) {
\r
1490 x = oe.targetTouches[0].pageX - offsets.left;
\r
1491 y = oe.targetTouches[0].pageY - offsets.top;
\r
1492 } else if (oe.changedTouches) {
\r
1493 x = oe.changedTouches[0].pageX - offsets.left;
\r
1494 y = oe.changedTouches[0].pageY - offsets.top;
\r
1496 x = ev.pageX - offsets.left;
\r
1497 y = ev.pageY - offsets.top;
\r
1499 return (x == undefined ? null : [Math.round(x), Math.round(y), Jmol._jsGetMouseModifiers(ev)]);
\r
1502 Jmol._gestureUpdate = function(canvas, ev) {
\r
1503 ev.stopPropagation();
\r
1504 ev.preventDefault();
\r
1505 var oe = ev.originalEvent;
\r
1506 switch (ev.type) {
\r
1507 case "touchstart":
\r
1508 Jmol._touching = true;
\r
1511 Jmol._touching = false;
\r
1514 if (!oe.touches || oe.touches.length != 2) return false;
\r
1515 switch (ev.type) {
\r
1516 case "touchstart":
\r
1517 canvas._touches = [[],[]];
\r
1520 var offsets = Jmol.$offset(canvas.id);
\r
1521 var t0 = canvas._touches[0];
\r
1522 var t1 = canvas._touches[1];
\r
1523 t0.push([oe.touches[0].pageX - offsets.left, oe.touches[0].pageY - offsets.top]);
\r
1524 t1.push([oe.touches[1].pageX - offsets.left, oe.touches[1].pageY - offsets.top]);
\r
1525 var n = t0.length;
\r
1531 canvas.applet._processGesture(canvas._touches);
\r
1537 Jmol._jsSetMouse = function(canvas) {
\r
1539 var doIgnore = function(ev) { return (ev.target.className.indexOf("swingjs-ui") >= 0) };
\r
1541 Jmol.$bind(canvas, 'mousedown touchstart', function(ev) {
\r
1544 Jmol._setMouseOwner(canvas, true);
\r
1545 ev.stopPropagation();
\r
1546 var ui = ev.target["data-UI"];
\r
1547 if (!ui || !ui.handleJSEvent(canvas, 501, ev))
\r
1548 ev.preventDefault();
\r
1549 canvas.isDragging = true;
\r
1550 if ((ev.type == "touchstart") && Jmol._gestureUpdate(canvas, ev))
\r
1552 Jmol._setConsoleDiv(canvas.applet._console);
\r
1553 var xym = Jmol._jsGetXY(canvas, ev);
\r
1555 if (ev.button != 2)
\r
1556 Jmol.Swing.hideMenus(canvas.applet);
\r
1557 canvas.applet._processEvent(501, xym); //java.awt.Event.MOUSE_DOWN
\r
1562 Jmol.$bind(canvas, 'mouseup touchend', function(ev) {
\r
1565 Jmol._setMouseOwner(null);
\r
1566 ev.stopPropagation();
\r
1567 var ui = ev.target["data-UI"];
\r
1568 if (!ui || !ui.handleJSEvent(canvas, 502, ev))
\r
1569 ev.preventDefault();
\r
1570 canvas.isDragging = false;
\r
1571 if (ev.type == "touchend" && Jmol._gestureUpdate(canvas, ev))
\r
1573 var xym = Jmol._jsGetXY(canvas, ev);
\r
1575 canvas.applet._processEvent(502, xym);//java.awt.Event.MOUSE_UP
\r
1579 Jmol.$bind(canvas, 'mousemove touchmove', function(ev) { // touchmove
\r
1582 // defer to console or menu when dragging within this canvas
\r
1583 if (Jmol._mouseOwner && Jmol._mouseOwner != canvas && Jmol._mouseOwner.isDragging) {
\r
1584 if (!Jmol._mouseOwner.mouseMove)
\r
1586 Jmol._mouseOwner.mouseMove(ev);
\r
1589 return Jmol._drag(canvas, ev);
\r
1592 Jmol._drag = function(canvas, ev) {
\r
1594 ev.stopPropagation();
\r
1595 ev.preventDefault();
\r
1597 var isTouch = (ev.type == "touchmove");
\r
1598 if (isTouch && Jmol._gestureUpdate(canvas, ev))
\r
1600 var xym = Jmol._jsGetXY(canvas, ev);
\r
1601 if(!xym) return false;
\r
1603 if (!canvas.isDragging)
\r
1606 var ui = ev.target["data-UI"];
\r
1607 if (canvas.isdragging && (!ui || !ui.handleJSEvent(canvas, 506, ev))) {}
\r
1608 canvas.applet._processEvent((canvas.isDragging ? 506 : 503), xym); // java.awt.Event.MOUSE_DRAG : java.awt.Event.MOUSE_MOVE
\r
1612 Jmol.$bind(canvas, 'DOMMouseScroll mousewheel', function(ev) { // Zoom
\r
1615 ev.stopPropagation();
\r
1616 ev.preventDefault();
\r
1617 // Webkit or Firefox
\r
1618 canvas.isDragging = false;
\r
1619 var oe = ev.originalEvent;
\r
1620 var scroll = (oe.detail ? oe.detail : (Jmol.featureDetection.os == "mac" ? 1 : -1) * oe.wheelDelta); // Mac and PC are reverse; but
\r
1621 var modifiers = Jmol._jsGetMouseModifiers(ev);
\r
1622 canvas.applet._processEvent(-1,[scroll < 0 ? -1 : 1,0,modifiers]);
\r
1626 // context menu is fired on mouse down, not up, and it's handled already anyway.
\r
1628 Jmol.$bind(canvas, "contextmenu", function() {return false;});
\r
1630 Jmol.$bind(canvas, 'mouseout', function(ev) {
\r
1633 if (Jmol._mouseOwner && !Jmol._mouseOwner.mouseMove)
\r
1634 Jmol._setMouseOwner(null);
\r
1635 if (canvas.applet._appletPanel)
\r
1636 canvas.applet._appletPanel.startHoverWatcher(false);
\r
1637 //canvas.isDragging = false;
\r
1638 var xym = Jmol._jsGetXY(canvas, ev);
\r
1641 //canvas.applet._processEvent(502, xym);//J.api.Event.MOUSE_UP
\r
1642 //canvas.applet._processEvent(505, xym);//J.api.Event.MOUSE_EXITED
\r
1646 Jmol.$bind(canvas, 'mouseenter', function(ev) {
\r
1649 if (canvas.applet._appletPanel)
\r
1650 canvas.applet._appletPanel.startHoverWatcher(true);
\r
1651 if (ev.buttons === 0 || ev.which === 0) {
\r
1652 canvas.isDragging = false;
\r
1653 var xym = Jmol._jsGetXY(canvas, ev);
\r
1656 canvas.applet._processEvent(504, xym);//J.api.Event.MOUSE_ENTERED
\r
1657 canvas.applet._processEvent(502, xym);//J.api.Event.MOUSE_UP
\r
1662 Jmol.$bind(canvas, 'mousemoveoutjsmol', function(evspecial, target, ev) {
\r
1665 if (canvas == Jmol._mouseOwner && canvas.isDragging) {
\r
1666 return Jmol._drag(canvas, ev);
\r
1670 if (canvas.applet._is2D)
\r
1671 Jmol.$resize(function() {
\r
1672 if (!canvas.applet)
\r
1674 canvas.applet._resize();
\r
1677 Jmol.$bind('body', 'mouseup touchend', function(ev) {
\r
1680 if (canvas.applet)
\r
1681 canvas.isDragging = false;
\r
1682 Jmol._setMouseOwner(null);
\r
1687 Jmol._jsUnsetMouse = function(canvas) {
\r
1688 canvas.applet = null;
\r
1689 Jmol.$bind(canvas, 'mousedown touchstart mousemove touchmove mouseup touchend DOMMouseScroll mousewheel contextmenu mouseout mouseenter', null);
\r
1690 Jmol._setMouseOwner(null);
\r
1694 ////// Jmol.Swing interface for Javascript implementation of Swing dialogs and menus
\r
1699 menuInitialized:0,
\r
1704 (function(Swing) {
\r
1706 SwingController = Swing; // see javajs.api.SwingController
\r
1708 Swing.setDraggable = function(Obj) {
\r
1710 var proto = Obj.prototype;
\r
1711 if (proto.setContainer)
\r
1714 // for menus, console, and
\r
1715 proto.setContainer = function(container) {
\r
1716 this.container = container;
\r
1717 container.obj = this;
\r
1718 this.isDragging = false;
\r
1719 this.ignoreMouse = false;
\r
1721 container.bind('mousedown touchstart', function(ev) {
\r
1722 if (me.ignoreMouse) {
\r
1723 me.ignoreMouse = false;
\r
1726 Jmol._setMouseOwner(me, true);
\r
1727 me.isDragging = true;
\r
1728 me.pageX = ev.pageX;
\r
1729 me.pageY = ev.pageY;
\r
1732 container.bind('mousemove touchmove', function(ev) {
\r
1733 if (me.isDragging && Jmol._mouseOwner == me) {
\r
1738 container.bind('mouseup touchend', function(ev) {
\r
1740 Jmol._setMouseOwner(null);
\r
1744 proto.mouseUp = function(ev) {
\r
1745 if (this.isDragging && Jmol._mouseOwner == this) {
\r
1746 this.pageX0 += (ev.pageX - this.pageX);
\r
1747 this.pageY0 += (ev.pageY - this.pageY);
\r
1748 this.isDragging = false;
\r
1751 Jmol._setMouseOwner(null);
\r
1754 proto.setPosition = function() {
\r
1755 if (Jmol._mousePageX === null) {
\r
1756 var id = this.applet._id + "_" + (this.applet._is2D ? "canvas2d" : "canvas");
\r
1757 var offsets = Jmol.$offset(id);
\r
1758 Jmol._mousePageX = offsets.left;
\r
1759 Jmol._mousePageY = offsets.top;
\r
1761 this.pageX0 = Jmol._mousePageX;
\r
1762 this.pageY0 = Jmol._mousePageY;
\r
1763 var pos = { top: Jmol._mousePageY + 'px', left: Jmol._mousePageX + 'px' };
\r
1764 this.container.css(pos);
\r
1767 proto.mouseMove = function(ev) {
\r
1768 if (this.isDragging && Jmol._mouseOwner == this) {
\r
1769 this.timestamp = System.currentTimeMillis(); // used for menu closure
\r
1770 var x = this.pageX0 + (ev.pageX - this.pageX);
\r
1771 var y = this.pageY0 + (ev.pageY - this.pageY);
\r
1772 Jmol._mousePageX = x;
\r
1773 Jmol._mousePageY = y;
\r
1774 this.container.css({ top: y + 'px', left: x + 'px' })
\r
1778 proto.dragBind = function(isBind) {
\r
1779 this.applet._ignoreMouse = !isBind;
\r
1780 this.container.unbind('mousemoveoutjsmol');
\r
1781 this.container.unbind('touchmoveoutjsmol');
\r
1782 this.container.unbind('mouseupoutjsmol');
\r
1783 this.container.unbind('touchendoutjsmol');
\r
1784 Jmol._setMouseOwner(null);
\r
1787 this.container.bind('mousemoveoutjsmol touchmoveoutjsmol', function(evspecial, target, ev) {
\r
1790 this.container.bind('mouseupoutjsmol touchendoutjsmol', function(evspecial, target, ev) {
\r
1799 Swing.JSDialog = function () {
\r
1802 Swing.setDraggable(Swing.JSDialog);
\r
1804 ///// calls from javajs and other Java-derived packages /////
\r
1806 Swing.getScreenDimensions = function(d) {
\r
1807 d.width = $(window).width();
\r
1808 d.height = $(window).height();
\r
1811 Swing.dispose = function(dialog) {
\r
1812 Jmol.$remove(dialog.id + "_mover");
\r
1813 delete Swing.htDialogs[dialog.id]
\r
1814 dialog.container.obj.dragBind(false);
\r
1815 // var btns = $("#" + dialog.id + " *[id^='J']"); // add descendents with id starting with "J"
\r
1816 // for (var i = btns.length; --i >= 0;)
\r
1817 // delete Dialog.htDialogs[btns[i].id]
\r
1818 //System.out.println("JSmolCore.js: dispose " + dialog.id)
\r
1821 Swing.register = function(dialog, type) {
\r
1822 dialog.id = type + (++Swing.count);
\r
1823 Swing.htDialogs[dialog.id] = dialog;
\r
1824 //System.out.println("JSmolCore.js: register " + dialog.id)
\r
1828 Swing.setDialog = function(dialog) {
\r
1829 Jmol._setMouseOwner(null);
\r
1830 Jmol.$remove(dialog.id);
\r
1831 //System.out.println("removed " + dialog.id)
\r
1832 var id = dialog.id + "_mover";
\r
1833 var container = Jmol._$(id);
\r
1835 //System.out.println("JSmolCore.js: setDialog " + dialog.id);
\r
1836 if (container[0]) {
\r
1837 container.html(dialog.html);
\r
1838 jd = container[0].jd;
\r
1840 Jmol.$after("body","<div id='" + id + "' style='position:absolute;left:0px;top:0px;'>" + dialog.html + "</div>");
\r
1841 var jd = new Swing.JSDialog();
\r
1842 container = Jmol._$(id);
\r
1843 dialog.container = container;
\r
1844 jd.applet = dialog.manager.vwr.html5Applet;
\r
1845 jd.setContainer(container);
\r
1846 jd.dialog = dialog;
\r
1847 jd.setPosition();
\r
1848 jd.dragBind(true);
\r
1849 container[0].jd = jd;
\r
1851 Jmol.$bind("#" + dialog.id + " .JButton", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
\r
1852 Jmol.$bind("#" + dialog.id + " .JComboBox", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
\r
1853 Jmol.$bind("#" + dialog.id + " .JCheckBox", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
\r
1854 Jmol.$bind("#" + dialog.id + " .JTextField", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
\r
1855 Jmol.$bind("#" + dialog.id + " .JTable", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
\r
1856 Jmol.$bind("#" + dialog.id + " .JScrollPane", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
\r
1857 Jmol.$bind("#" + dialog.id + " .JEditorPane", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
\r
1861 Swing.setSelected = function(chk) {
\r
1862 Jmol.$prop(chk.id, 'checked', !!chk.selected);
\r
1865 Swing.setSelectedIndex = function(cmb) {
\r
1866 Jmol.$prop(cmb.id, 'selectedIndex', cmb.selectedIndex);
\r
1869 Swing.setText = function(btn) {
\r
1870 Jmol.$prop(btn.id, 'value', btn.text);
\r
1873 Swing.setVisible = function(c) {
\r
1874 Jmol.$setVisible(c.id, c.visible);
\r
1877 Swing.setEnabled = function(c) {
\r
1878 Jmol.$setEnabled(c.id, c.enabled);
\r
1881 /// callbacks from the HTML elements ////
\r
1883 Swing.click = function(element, keyEvent) {
\r
1884 var component = Swing.htDialogs[element.id];
\r
1886 //System.out.println("click " + element + " " + component)
\r
1887 var info = component.toString();
\r
1888 // table cells will have an id but are not registered
\r
1889 if (info.indexOf("JCheck") >= 0) {
\r
1890 component.selected = element.checked;
\r
1891 } else if (info.indexOf("JCombo") >= 0) {
\r
1892 component.selectedIndex = element.selectedIndex;
\r
1893 } else if (component.text != null) { // JButton, JTextField
\r
1894 component.text = element.value;
\r
1895 if (keyEvent && ((keyEvent.charCode || keyEvent.keyCode) != 13))
\r
1899 var dialog = Swing.htDialogs[Jmol.$getAncestorDiv(element.id, "JDialog").id];
\r
1900 var key = (component ? component.name : dialog.registryKey + "/" + element.id);
\r
1901 //System.out.println("JSmolCore.js: click " + key);
\r
1902 dialog.manager.actionPerformed(key);
\r
1905 Swing.setFront = function(dialog) {
\r
1906 var applet = dialog.manager.vwr.html5Applet;
\r
1907 if (dialog.zIndex != Jmol._getZ(applet, "dialog"))
\r
1908 dialog.zIndex = Jmol._incrZ(applet, "dialog");
\r
1909 dialog.container && ((dialog.container[0] || dialog.container).style.zIndex = dialog.zIndex);
\r
1912 Swing.hideMenus = function(applet) {
\r
1913 // called from LEFT-DOWN mouse event
\r
1914 var menus = applet._menus;
\r
1916 for (var i in menus)
\r
1917 if (menus[i].visible)
\r
1918 Swing.hideMenu(menus[i]);
\r
1921 Swing.windowClosing = function(element) {
\r
1922 var dialog = Swing.htDialogs[Jmol.$getAncestorDiv(element.id, "JDialog").id];
\r
1923 if (dialog.registryKey) {
\r
1924 //System.out.println("JSmolCore.js: windowClosing " + dialog.registryKey);
\r
1925 dialog.manager.processWindowClosing(dialog.registryKey);
\r
1927 //System.out.println("JSmolCore.js: windowClosing " + dialog.title);
\r
1934 Jmol._track = function(applet) {
\r
1935 // this function inserts an iFrame that can be used to track your page's applet use.
\r
1936 // By default it tracks to a page at St. Olaf College, but you can change that.
\r
1937 // and you can use
\r
1939 // delete Jmol._tracker
\r
1941 // yourself to not have you page execute this
\r
1943 if (Jmol._tracker){
\r
1945 var url = Jmol._tracker + "&applet=" + applet._jmolType + "&version=" + Jmol._version
\r
1946 + "&appver=" + Jmol.___JmolVersion + "&url=" + encodeURIComponent(document.location.href);
\r
1947 var s = '<iframe style="display:none" width="0" height="0" frameborder="0" tabindex="-1" src="' + url + '"></iframe>'
\r
1948 Jmol.$after("body", s);
\r
1952 delete Jmol._tracker;
\r
1957 Jmol.getProfile = function() {
\r
1958 window["j2s.doProfile"] = true;
\r
1959 if (self.Clazz && self.JSON) {
\r
1960 Clazz._profile || (Clazz._profile = {});
\r
1961 return Clazz.getProfile();
\r
1965 Jmol._getInChIKey = function(applet, data) {
\r
1966 if (data.indexOf("MOL=") >= 0)
\r
1967 data = data.split("MOL=")[1].split("\"")[0];
\r
1971 Jmol._getAttr = function(s, a) {
\r
1972 var pt = s.indexOf(a + "=");
\r
1973 return (pt >= 0 && (pt = s.indexOf('"', pt)) >= 0
\r
1974 ? s.substring(pt+1, s.indexOf('"', pt+1)) : null);
\r
1978 viewUpdatedCallback: null
\r
1983 // The objective of Jmol.View is to coordinate
\r
1984 // asynchronous applet loading and atom/peak picking
\r
1985 // among any combination of Jmol, JME, and JSV.
\r
1987 // basic element is a view object:
\r
1989 // viewType1: viewRecord1,
\r
1990 // viewType2: viewRecord2,
\r
1991 // viewType3: viewRecord3
\r
1993 // where viewType is one of (Jmol, JME, JSV)
\r
1994 // and a viewRecord is an object
\r
1995 // with elements .chemID, .applet, .data, .script
\r
1997 // Jmol.View.sets is a list of cached views[0..n]
\r
1998 // for a given group of applet objects with common Info.viewSet
\r
2000 // Bob Hanson 1/22/2014 7:05:38 AM
\r
2009 // methods called from other modules have no "_" in their name
\r
2011 View.updateView = function(applet, Info, _View_updateView) {
\r
2012 // Info.chemID, Info.data, possibly Info.viewID if no chemID
\r
2013 // return from applet after asynchronous download of new data
\r
2014 if (applet._viewSet == null)
\r
2016 Info.chemID || (applet._searchQuery = null);
\r
2017 Info.data || (Info.data = "N/A");
\r
2018 Info.type = applet._viewType;
\r
2019 if((applet._currentView = View.__findView(applet._viewSet, Info)) == null)
\r
2020 applet._currentView = View.__createViewSet(applet._viewSet, Info.chemID, Info.viewID || Info.chemID);
\r
2021 applet._currentView[Info.type].data = Info.data;
\r
2022 applet._currentView[Info.type].smiles = applet._getSmiles();
\r
2023 if (Jmol.User.viewUpdatedCallback)
\r
2024 Jmol.User.viewUpdatedCallback(applet, "updateView");
\r
2025 View.__setView(applet._currentView, applet, false);
\r
2028 View.updateFromSync = function(applet, msg) {
\r
2029 applet._updateMsg = msg;
\r
2030 var id = Jmol._getAttr(msg, "sourceID") || Jmol._getAttr(msg, "file");
\r
2033 var view = View.__findView(applet._viewSet, {viewID:id});
\r
2035 return Jmol.updateView(applet, msg); // JSV has been updated internally
\r
2036 if (view != applet._currentView)
\r
2037 View.__setView(view, applet, true);
\r
2038 var A = ((id = Jmol._getAttr(msg, "atoms")) && msg.indexOf("selectionhalos ON") >= 0
\r
2039 ? eval("[" + id + "]") : []);
\r
2040 setTimeout(function(){if (applet._currentView == view)View.updateAtomPick(applet, A)}, 10);
\r
2041 if (Jmol.User.viewUpdatedCallback)
\r
2042 Jmol.User.viewUpdatedCallback(applet, "updateFromSync");
\r
2045 View.updateAtomPick = function(applet, A, _View_updateAtomPick) {
\r
2046 var view = applet._currentView;
\r
2049 for (var viewType in view) {
\r
2050 if (viewType != "info" && view[viewType].applet != applet)
\r
2051 view[viewType].applet._updateAtomPick(A);
\r
2053 if (Jmol.User.viewUpdatedCallback)
\r
2054 Jmol.User.viewUpdatedCallback(applet, "updateAtomPick");
\r
2057 View.dumpViews = function(setID) {
\r
2058 var views = View.sets[setID];
\r
2061 var s = "View set " + setID + ":\n";
\r
2062 var applets = View.applets[setID];
\r
2063 for (var i in applets)
\r
2064 s += "\napplet " + applets[i]._id
\r
2065 + " currentView=" + (applets[i]._currentView ? applets[i]._currentView.info.viewID : null);
\r
2066 for (var i = views.length; --i >= 0;) {
\r
2067 var view = views[i];
\r
2068 s += "\n\n<b>view=" + i
\r
2069 + " viewID=" + view.info.viewID
\r
2070 + " chemID=" + view.info.chemID + "</b>\n"
\r
2072 for (var viewType in view)
\r
2073 if (viewType != "info")
\r
2074 s += "\nview=" + i + " type=" + viewType + " applet="
\r
2075 + ((v = view[viewType]).applet ? v.applet._id : null)
\r
2076 + " SMILES=" + v.smiles + "\n"
\r
2077 + " atomMap=" + JSON.stringify(v.atomMap) + "\n"
\r
2078 + " data=\n" + v.data + "\n"
\r
2084 // methods starting with "__" are "private" to JSmolCore.js
\r
2086 View.__init = function(applet) {
\r
2087 var set = applet._viewSet;
\r
2088 var a = View.applets;
\r
2089 a[set] || (a[set] = {});
\r
2090 a[set][applet._viewType] = applet;
\r
2093 View.__findView = function(set, Info) {
\r
2094 var views = View.sets[set];
\r
2095 if (views == null)
\r
2096 views = View.sets[set] = [];
\r
2097 for (var i = views.length; --i >= 0;) {
\r
2098 var view = views[i];
\r
2099 if (Info.viewID) {
\r
2100 if (view.info.viewID == Info.viewID)
\r
2102 } else if (Info.chemID != null && Info.chemID == view.info.chemID) {
\r
2105 for (var viewType in view) {
\r
2106 if (viewType != "info") {
\r
2107 if (Info.data != null && view[viewType].data != null ? Info.data == view[viewType].data
\r
2108 : Info.type == viewType)
\r
2117 View.__createViewSet = function(set, chemID, viewID, _createViewSet) {
\r
2119 var view = {info:{chemID: chemID, viewID: viewID || "model_" + View.count}};
\r
2121 for (var id in Jmol._applets) {
\r
2122 var a = Jmol._applets[id];
\r
2123 if (a._viewSet == set)
\r
2124 view[a._viewType] = {applet:a, data: null};
\r
2126 View.sets[set].push(view);
\r
2130 View.__setView = function(view, applet, isSwitch, _setView) {
\r
2131 // called from Jmol._searchMol and Jmol.View.setCurrentView
\r
2132 // to notify the applets in the set that there may be new data for them
\r
2133 // skip the originating applet itself and cases where the data has not changed.
\r
2134 // stop at first null data, because that will initiate some sort of asynchronous
\r
2135 // call that will be back here afterward.
\r
2137 for (var viewType in view) {
\r
2138 if (viewType == "info")
\r
2140 var rec = view[viewType];
\r
2141 var a = rec.applet;
\r
2142 var modified = (isSwitch || a != null && a._molData == "<modified>");
\r
2144 if (a == null || a == applet && !modified)
\r
2145 continue; // may be a mol3d required by JSV but not having a corresponding applet
\r
2146 var wasNull = (rec.data == null);
\r
2147 var haveView = (a._currentView != null);
\r
2148 a._currentView = view;
\r
2149 if (haveView && view[viewType].data == rec.data && !wasNull & !modified)
\r
2151 a._loadModelFromView(view);
\r
2156 // Either all are taken care of or one was null,
\r
2157 // in which case we have started an asynchronous
\r
2158 // process to get the data, and we can quit here.
\r
2159 // In either case, we are done.
\r
2164 Jmol.Cache = {fileCache: {}};
\r
2166 Jmol.Cache.get = function(filename) {
\r
2167 return Jmol.Cache.fileCache[filename];
\r
2170 Jmol.Cache.put = function(filename, data) {
\r
2171 Jmol.Cache.fileCache[filename] = data;
\r
2174 Jmol.Cache.setDragDrop = function(me) {
\r
2175 Jmol.$appEvent(me, "appletdiv", "dragover", function(e) {
\r
2176 e = e.originalEvent;
\r
2177 e.stopPropagation();
\r
2178 e.preventDefault();
\r
2179 e.dataTransfer.dropEffect = 'copy';
\r
2181 Jmol.$appEvent(me, "appletdiv", "drop", function(e) {
\r
2182 var oe = e.originalEvent;
\r
2183 oe.stopPropagation();
\r
2184 oe.preventDefault();
\r
2185 var file = oe.dataTransfer.files[0];
\r
2186 if (file == null) {
\r
2187 // FF and Chrome will drop an image here
\r
2188 // but it will be only a URL, not an actual file.
\r
2190 file = "" + oe.dataTransfer.getData("text");
\r
2191 if (file.indexOf("file:/") == 0 || file.indexOf("http:/") == 0) {
\r
2192 me._scriptLoad(file);
\r
2198 // some other format
\r
2201 // MSIE will drop an image this way, though, and load it!
\r
2202 var reader = new FileReader();
\r
2203 reader.onloadend = function(evt) {
\r
2204 if (evt.target.readyState == FileReader.DONE) {
\r
2205 var cacheName = "cache://DROP_" + file.name;
\r
2206 var bytes = Jmol._toBytes(evt.target.result);
\r
2207 if (!cacheName.endsWith(".spt"))
\r
2208 me._appletPanel.cacheFileByName("cache://DROP_*",false);
\r
2209 if (me._viewType == "JSV" || cacheName.endsWith(".jdx")) // shared by Jmol and JSV
\r
2210 Jmol.Cache.put(cacheName, bytes);
\r
2212 me._appletPanel.cachePut(cacheName, bytes);
\r
2213 var xym = Jmol._jsGetXY(me._canvas, e);
\r
2214 if(xym && (!me._appletPanel.setStatusDragDropped || me._appletPanel.setStatusDragDropped(0, xym[0], xym[1], cacheName))) {
\r
2215 me._appletPanel.openFileAsyncSpecial(cacheName, 1);
\r
2219 reader.readAsArrayBuffer(file);
\r