-// JSmolCore.js -- Jmol core capability \r
-\r
-// allows Jmol applets to be created on a page with more flexibility and extendability\r
-// provides an object-oriented interface for JSpecView and syncing of Jmol/JSpecView\r
-\r
-// see JSmolApi.js for public user-interface. All these are private functions\r
-\r
-// BH 5/30/2015 9:33:12 AM adds class swingjs-ui to ignore \r
-// BH 5/9/2015 3:38:52 PM adds data-ignoreMouse attribute for JTextField\r
-// BH 3/30/2015 9:46:53 PM adds JSAppletPanel for ready callback\r
-// BH 12/6/2014 3:32:54 PM Jmol.setAppletCss() broken\r
-// BH 9/13/2014 2:15:51 PM embedded JSME loads from SEARCH when Jmol should \r
-// BH 8/14/2014 2:52:38 PM drag-drop cache should not be cleared if SPT file is dropped\r
-// BH 8/5/2014 6:39:54 AM unnecessary messages about binary for PDB finally removed\r
-// BH 8/4/2014 5:30:00 AM automatically switch to no document after page loading\r
-// BH 8/2/2014 5:22:40 PM drag-drop broken in JSmol/HTML5 \r
-// BH 7/23/2014 5:34:08 PM setting a parameter such as readyFunction to null stops file loading\r
-// BH 7/3/2014 12:30:28 AM lost drag-drop of models\r
-// BH 7/2/2014 4:47:55 AM adding pdbe.org to direct database calls\r
-// BH 5/30/2014 7:20:07 AM better dragging for console and menu\r
-// BH 4/27/2014 6:31:52 PM allows _USE=SIGNED HTML5 as well as _USE=JAVA HTML5\r
-// BH 3/8/2014 5:50:51 PM adds support for dataURI download in FF and Chrome\r
-// BH 3/8/2014 8:43:10 AM moves PubChem access to https\r
-// BH 3/4/2014 8:40:15 PM adds Jmol.Cache for JSV/Jmol sharing files\r
-// BH 2/10/2014 10:07:14 AM added Info.z and Info.zIndexBase\r
-// BH 2/9/2014 9:56:06 PM updated JSmolCore.js with option to extend Viewer with code PRIOR to loading Viewer classes\r
-// BH 2/6/2014 8:46:25 AM disabled Jmol._tracker for localhost and 127.x.x.x \r
-// BH 1/29/2014 8:02:23 AM Jmol.View and Info.viewSet\r
-// BH 1/21/2014 12:06:59 PM adding Jmol.Info.cacheFiles (applet, true/false) and applet._cacheFiles and Jmol._fileCache\r
-// BH 1/13/2014 2:12:38 PM adding "http://www.nmrdb.org/tools/jmol/predict.php":"%URL", to _DirectDatabaseCalls\r
-// BH 12/21/2013 6:38:35 PM applet sync broken\r
-// BH 12/6/2013 6:18:32 PM cover.htm and coverImage fix\r
-// BH 12/4/2013 7:44:26 PM fix for JME independent search box\r
-// BH 12/3/2013 6:30:08 AM fix for ready function returning Boolean instead of boolean in HTML5 version\r
-// BH 11/30/2013 10:31:37 AM added type:"GET" for jQuery.ajax() requests instead of using defaults\r
-// BH 11/30/2013 10:31:37 AM added cache:true for jQuery.ajax() requests; can override with cache:"NO", not cache:false\r
-// BH 11/28/2013 11:09:27 AM added Jmol._alertNoBinary:true\r
-// BH 11/26/2013 8:19:55 PM fix !xxxx search commmand entry and stop MSIE from duplicating command\r
-// BH 11/25/2013 7:38:31 AM adds Jmol._tracker: option for GoogleAnalytics tracking\r
-// BH 11/25/2013 7:39:03 AM adds URL options _J2S= _JAR= _USE=\r
-// BH 11/23/2013 10:51:37 PM adds JNLP support for local applet\r
-// BH 11/2/2013 12:05:11 PM JSmolJSME fixes; https access fixed\r
-// BH 10/31/2013 7:50:06 PM Jmol.Dialog as SwingController; Jmol._mouseOwner added\r
-// BH 10/19/2013 7:05:04 AM adding Jmol._ajaxCall for Error Contacting Server; database POST method enabled\r
-// BH 10/17/2013 1:40:51 PM adding javajs/swing and Jmol.Dialog\r
-// BH 9/30/2013 6:42:24 PM: pdb.gz switch pdb should only be for www.rcsb.org\r
-// BH 9/17/2013 10:17:51 AM: asynchronous file reading and saving\r
-// BH 8/16/2013 12:02:20 PM: JSmoljQueryExt.js pulled out\r
-// BH 8/16/2013 12:02:20 PM: Jmol._touching used properly\r
-\r
-// BH 3/22/2013 5:53:02 PM: Adds noscript option, JSmol.min.core.js\r
-// BH 1/17/2013 5:20:44 PM: Fixed problem with console not getting initial position if no first click\r
-// 1/13/2013 BH: Fixed MSIE not-reading-local-files problem.\r
-// 11/28/2012 BH: Fixed MacOS Safari binary ArrayBuffer problem\r
-// 11/21/2012 BH: restructuring of files as JS... instead of J...\r
-// 11/20/2012 BH: MSIE9 cannot do a synchronous file load cross-domain. See Jmol._getFileData\r
-// 11/4/2012 BH: RCSB REST format change "<structureId>" to "<dimStructure.structureId>"\r
-// 9/13/2012 BH: JmolCore.js changes for JSmol doAjax() method -- _3ata()\r
-// 6/12/2012 BH: JmolApi.js: adds Jmol.setInfo(applet, info, isShown) -- third parameter optional \r
-// 6/12/2012 BH: JmolApi.js: adds Jmol.getInfo(applet) \r
-// 6/12/2012 BH: JmolApplet.js: Fixes for MSIE 8\r
-// 6/5/2012 BH: fixes problem with Jmol "javascript" command not working and getPropertyAsArray not working\r
-// 6/4/2012 BH: corrects problem with MSIE requiring mouse-hover to activate applet\r
-// 5/31/2012 BH: added JSpecView interface and api -- see JmolJSV.js\r
-// also changed "jmolJarPath" to just "jarPath"\r
-// jmolJarFile->jarFile, jmolIsSigned->isSigned, jmolReadyFunction->readyFunction\r
-// also corrects a double-loading issue\r
-// 5/14/2012 BH: added AJAX queue for ChemDoodle option with multiple canvases \r
-// 8/12/2012 BH: adds support for MSIE xdr cross-domain request (jQuery.iecors.js)\r
-\r
- // BH 4/25 -- added text option. setAppletCss(null, "style=\"xxxx\"")\r
- // note that since you must add the style keyword, this can be used to add any attribute to these tags, not just css. \r
-\r
-// required/optional libraries (preferably in the following order):\r
-\r
-// jquery/jquery.js -- at least jQuery.1.9\r
-// js/JSmoljQueryext.js -- required for binary file transfer; otherwise standard jQuery should be OK\r
-// js/JSmolCore.js -- required\r
-// js/j2sjmol.js -- required\r
-// js/JSmol.js -- required\r
-// js/JSmolApplet.js -- required; internal functions for _Applet and _Image; must be after JSmolCore\r
-// js/JSmolControls.js -- optional; internal functions for buttons, links, menus, etc.; must be after JSmolCore\r
-// js/JSmolConsole.js -- optional; for the pop-up console\r
-// js/JSmolApi.js -- required; all user functions; must be after JSmolCore\r
-// js/JSmolTHREE.js -- optional; WebGL library required for JSmolGLmol.js\r
-// js/JSmolGLmol.js -- optional; WebGL version of JSmol.\r
-// js/JSmolJME.js -- optional; JSME (2D editor)\r
-// jsme/jsme/jsme.nocache.js -- required for JSME \r
-// js/JSmolMenu.js -- optional; required for menuing in JSV\r
-// js/JSmolJSV.js -- optional; for creating and interacting with a JSpecView applet \r
-\r
-// most of these will be loaded automatically, and for most installations, all you need is JSmol.min.js\r
-\r
-\r
-// Allows Jmol-like objects to be displayed on Java-challenged (iPad/iPhone)\r
-// or applet-challenged (Android/iPhone) platforms, with automatic switching to \r
-\r
-// For your installation, you should consider putting JmolData.jar and jsmol.php \r
-// on your own server. Nothing more than these two files is needed on the server, and this \r
-// allows more options for MSIE and Chrome when working with cross-domain files (such as RCSB or pubChem) \r
-\r
-// The NCI and RCSB databases are accessed via direct AJAX if available (xhr2/xdr).\r
-\r
-\r
-if(typeof(jQuery)=="undefined") alert ("Note -- JSmoljQuery is required for JSmol, but it's not defined.")\r
-\r
-// An example of how to extend Jmol with code PRIOR to JSmolCore.js or JSmol.min.js follows:\r
-//\r
-// \r
-// Jmol = {\r
-// z:3000,\r
-// extend: function(what, obj) {if (what == "viewer") { obj._testing = true } }\r
-// }\r
-\r
-self.Jmol || (Jmol = {});\r
-\r
-if (!Jmol._version)\r
-Jmol = (function(document) {\r
- var z=Jmol.z || 9000;\r
- var getZOrders = function(z) {\r
- return {\r
- rear:z++,\r
- header:z++,\r
- main:z++,\r
- image:z++,\r
- front:z++,\r
- fileOpener:z++,\r
- coverImage:z++,\r
- dialog:z++, // could be several of these, JSV only\r
- menu:z+90000, // way front\r
- console:z+91000, // even more front\r
- consoleImage:z+91001, // bit more front; increments\r
- monitorZIndex:z+99999 // way way front\r
- }\r
- };\r
- var j = {\r
- _version: "$Date: 2015-04-26 10:57:08 -0500 (Sun, 26 Apr 2015) $", // svn.keywords:lastUpdated\r
- _alertNoBinary: true,\r
- // this url is used to Google Analytics tracking of Jmol use. You may remove it or modify it if you wish. \r
- _allowedJmolSize: [25, 2048, 300], // min, max, default (pixels)\r
- /* By setting the Jmol.allowedJmolSize[] variable in the webpage\r
- before calling Jmol.getApplet(), limits for applet size can be overriden.\r
- 2048 standard for GeoWall (http://geowall.geo.lsa.umich.edu/home.html)\r
- */\r
- _appletCssClass: "",\r
- _appletCssText: "",\r
- _fileCache: null, // enabled by Jmol.setFileCaching(applet, true/false)\r
- _jarFile: null, // can be set in URL using _JAR=\r
- _j2sPath: null, // can be set in URL using _J2S=\r
- _use: null, // can be set in URL using _USE=\r
- _j2sLoadMonitorOpacity: 90, // initial opacity for j2s load monitor message\r
- _applets: {},\r
- _asynchronous: true,\r
- _ajaxQueue: [],\r
- _getZOrders: getZOrders,\r
- _z:getZOrders(z),\r
- _debugCode: true, // set false in process of minimization\r
- db: {\r
- _databasePrefixes: "$=:",\r
- _fileLoadScript: ";if (_loadScript = '' && defaultLoadScript == '' && _filetype == 'Pdb') { select protein or nucleic;cartoons Only;color structure; select * };",\r
- _nciLoadScript: ";n = ({molecule=1}.length < {molecule=2}.length ? 2 : 1); select molecule=n;display selected;center selected;",\r
- _pubChemLoadScript: "",\r
- _DirectDatabaseCalls:{\r
- // these sites are known to implement access-control-allow-origin * \r
- "cactus.nci.nih.gov": "%URL", \r
- "www.rcsb.org": "%URL",\r
- "pdbe.org": "%URL", \r
- "www.ebi.ac.uk": "%URL", \r
- "wwwdev.ebi.ac.uk": "%URL", \r
- "pubchem.ncbi.nlm.nih.gov":"%URL",\r
- "http://www.nmrdb.org/tools/jmol/predict.php":"%URL",\r
- "$": "http://cactus.nci.nih.gov/chemical/structure/%FILENCI/file?format=sdf&get3d=True",\r
- "$$": "http://cactus.nci.nih.gov/chemical/structure/%FILENCI/file?format=sdf",\r
- "=": "http://www.rcsb.org/pdb/files/%FILE.pdb",\r
- "*": "http://www.ebi.ac.uk/pdbe/entry-files/download/%FILE.cif",\r
- "==": "http://www.rcsb.org/pdb/files/ligand/%FILE.cif",\r
- ":": "http://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/%FILE/SDF?record_type=3d"\r
- },\r
- _restQueryUrl: "http://www.rcsb.org/pdb/rest/search",\r
- _restQueryXml: "<orgPdbQuery><queryType>org.pdb.query.simple.AdvancedKeywordQuery</queryType><description>Text Search</description><keywords>QUERY</keywords></orgPdbQuery>",\r
- _restReportUrl: "http://www.pdb.org/pdb/rest/customReport?pdbids=IDLIST&customReportColumns=structureId,structureTitle"\r
- },\r
- _debugAlert: false,\r
- _document: document,\r
- _isXHTML: false,\r
- _lastAppletID: null,\r
- _mousePageX: null,\r
- _mouseOwner: null,\r
- _serverUrl: "http://your.server.here/jsmol.php",\r
- _syncId: ("" + Math.random()).substring(3),\r
- _touching: false,\r
- _XhtmlElement: null,\r
- _XhtmlAppendChild: false\r
- }\r
- \r
- var ref = document.location.href.toLowerCase();\r
- j._httpProto = (ref.indexOf("https") == 0 ? "https://" : "http://"); \r
- j._isFile = (ref.indexOf("file:") == 0);\r
- j._ajaxTestSite = j._httpProto + "google.com";\r
- var isLocal = (j._isFile || ref.indexOf("http://localhost") == 0 || ref.indexOf("http://127.") == 0);\r
- j._tracker = (j._httpProto == "http://" && !isLocal && 'http://chemapps.stolaf.edu/jmol/JmolTracker.htm?id=UA-45940799-1');\r
- \r
- j._isChrome = (navigator.userAgent.toLowerCase().indexOf("chrome") >= 0);\r
- j._isSafari = (!j._isChrome && navigator.userAgent.toLowerCase().indexOf("safari") >= 0);\r
- j._isMsie = (window.ActiveXObject !== undefined);\r
- j._useDataURI = !j._isSafari && !j._isMsie; // safari may be OK here -- untested\r
-\r
- for(var i in Jmol) j[i] = Jmol[i]; // allows pre-definition\r
- return j;\r
-})(document, Jmol);\r
-\r
-\r
-(function (Jmol, $) {\r
-\r
-// this library is organized into the following sections:\r
-\r
- // jQuery interface \r
- // protected variables\r
- // feature detection\r
- // AJAX-related core functionality\r
- // applet start-up functionality\r
- // misc core functionality\r
- // mouse events\r
-\r
-\r
- ////////////////////// jQuery interface ///////////////////////\r
-\r
- // hooks to jQuery -- if you have a different AJAX tool, feel free to adapt.\r
- // There should be no other references to jQuery in all the JSmol libraries.\r
-\r
- // automatically switch to returning HTML after the page is loaded\r
- $(document).ready(function(){ Jmol._document = null });\r
-\r
- Jmol.$ = function(objectOrId, subdiv) {\r
- // if a subdiv, then return $("#objectOrId._id_subdiv") \r
- // or if no subdiv, then just $(objectOrId)\r
- if (objectOrId == null)alert (subdiv + arguments.callee.caller.toString());\r
- return $(subdiv ? "#" + objectOrId._id + "_" + subdiv : objectOrId);\r
- } \r
-\r
- Jmol._$ = function(id) {\r
- // either the object or $("#" + id)\r
- return (typeof id == "string" ? $("#" + id) : id);\r
- }\r
-\r
- /// special functions:\r
-\r
- Jmol.$ajax = function (info) {\r
- Jmol._ajaxCall = info.url;\r
- info.cache = (info.cache != "NO");\r
- if (info.url.indexOf("http://pubchem.ncbi.nlm.nih") == 0)\r
- info.url = "https://" + info.url.substring(7);\r
- // fluke at pubchem --- requires https now from all pages 3/8/2014\r
- // don't let jQuery add $_=... to URL unless we \r
- // use cache:"NO"; other packages might use $.ajaxSetup() to set this to cache:false\r
- return $.ajax(info);\r
- }\r
-\r
- Jmol._getNCIInfo = function(identifier, what, fCallback) {\r
- return Jmol._getFileData("http://cactus.nci.nih.gov/chemical/structure/"+identifier +"/" + (what == "name" ? "names" : what));\r
- }\r
- \r
-\r
-\r
- Jmol.$appEvent = function(app, subdiv, evt, f) {\r
- var o = Jmol.$(app, subdiv); \r
- o.off(evt) && f && o.on(evt, f);\r
- } \r
-\r
- Jmol.$resize = function (f) {\r
- return $(window).resize(f);\r
- }\r
-\r
- //// full identifier expected (could be "body", for example):\r
-\r
- Jmol.$after = function (what, s) {\r
- return $(what).after(s);\r
- }\r
-\r
- Jmol.$append = function (what, s) {\r
- return $(what).append(s);\r
- }\r
-\r
- Jmol.$bind = function(what, list, f) {\r
- return (f ? $(what).bind(list, f) : $(what).unbind(list));\r
- }\r
-\r
- Jmol.$closest = function(what, d) {\r
- return $(what).closest(d);\r
- }\r
- \r
- Jmol.$get = function(what, i) {\r
- return $(what).get(i);\r
- }\r
- \r
- // element id expected\r
- \r
- Jmol.$documentOff = function(evt, id) {\r
- return $(document).off(evt, "#" + id);\r
- }\r
-\r
- Jmol.$documentOn = function(evt, id, f) {\r
- return $(document).on(evt, "#" + id, f);\r
- }\r
-\r
- Jmol.$getAncestorDiv = function(id, className) {\r
- return $("div." + className + ":has(#" + id + ")")[0];\r
- }\r
-\r
- Jmol.$supportsIECrossDomainScripting = function() {\r
- return $.support.iecors;\r
- }\r
-\r
- //// element id or jQuery object expected:\r
-\r
- Jmol.$attr = function (id, a, val) {\r
- return Jmol._$(id).attr(a, val);\r
- }\r
-\r
- Jmol.$css = function(id, style) {\r
- return Jmol._$(id).css(style);\r
- }\r
- \r
- Jmol.$find = function(id, d) {\r
- return Jmol._$(id).find(d);\r
- }\r
- \r
- Jmol.$focus = function(id) {\r
- return Jmol._$(id).focus();\r
- }\r
-\r
- Jmol.$html = function(id, html) {\r
- return Jmol._$(id).html(html);\r
- }\r
- \r
- Jmol.$offset = function(id) {\r
- return Jmol._$(id).offset();\r
- }\r
-\r
- Jmol.$windowOn = function(evt, f) {\r
- return $(window).on(evt, f);\r
- }\r
-\r
- Jmol.$prop = function(id, p, val) {\r
- var o = Jmol._$(id);\r
- return (arguments.length == 3 ? o.prop(p, val) : o.prop(p));\r
- }\r
-\r
- Jmol.$remove = function(id) {\r
- return Jmol._$(id).remove();\r
- }\r
-\r
- Jmol.$scrollTo = function (id, n) {\r
- var o = Jmol._$(id);\r
- return o.scrollTop(n < 0 ? o[0].scrollHeight : n);\r
- }\r
-\r
- Jmol.$setEnabled = function(id, b) {\r
- return Jmol._$(id).attr("disabled", b ? null : "disabled"); \r
- }\r
-\r
- Jmol.$setSize = function(id, w, h) {\r
- return Jmol._$(id).width(w).height(h);\r
- }\r
-\r
- Jmol.$setVisible = function(id, b) {\r
- var o = Jmol._$(id);\r
- return (b ? o.show() : o.hide()); \r
- }\r
-\r
- Jmol.$submit = function(id) {\r
- return Jmol._$(id).submit();\r
- }\r
-\r
- Jmol.$val = function (id, v) {\r
- var o = Jmol._$(id);\r
- return (arguments.length == 1 ? o.val() : o.val(v));\r
- }\r
-\r
- ////////////// protected variables ///////////\r
-\r
-\r
- Jmol._clearVars = function() {\r
- // only on page closing -- appears to improve garbage collection\r
-\r
- delete jQuery;\r
- delete $;\r
- delete Jmol;\r
- delete SwingController;\r
- delete J;\r
- delete JM;\r
- delete JS;\r
- delete JSV;\r
- delete JU;\r
- delete JV;\r
- delete java;\r
- delete javajs;\r
- delete Clazz;\r
- delete c$; // used in p0p; could be gotten rid of\r
- }\r
-\r
- ////////////// feature detection ///////////////\r
-\r
- Jmol.featureDetection = (function(document, window) {\r
-\r
- var features = {};\r
- features.ua = navigator.userAgent.toLowerCase()\r
-\r
- features.os = (function(){\r
- var osList = ["linux","unix","mac","win"]\r
- var i = osList.length;\r
-\r
- while (i--){\r
- if (features.ua.indexOf(osList[i])!=-1) return osList[i]\r
- }\r
- return "unknown";\r
- })();\r
-\r
- features.browser = function(){\r
- var ua = features.ua;\r
- var browserList = ["konqueror","webkit","omniweb","opera","webtv","icab","msie","mozilla"];\r
- for (var i = 0; i < browserList.length; i++)\r
- if (ua.indexOf(browserList[i])>=0) \r
- return browserList[i];\r
- return "unknown";\r
- }\r
- features.browserName = features.browser();\r
- features.browserVersion= parseFloat(features.ua.substring(features.ua.indexOf(features.browserName)+features.browserName.length+1));\r
- features.supportsXhr2 = function() {return ($.support.cors || $.support.iecors)}\r
- features.allowDestroy = (features.browserName != "msie");\r
- features.allowHTML5 = (features.browserName != "msie" || navigator.appVersion.indexOf("MSIE 8") < 0);\r
- features.getDefaultLanguage = function() {\r
- return navigator.language || navigator.userLanguage || "en-US";\r
- };\r
-\r
- features._webGLtest = 0;\r
-\r
- features.supportsWebGL = function() {\r
- if (!Jmol.featureDetection._webGLtest) { \r
- var canvas;\r
- Jmol.featureDetection._webGLtest = ( \r
- window.WebGLRenderingContext \r
- && ((canvas = document.createElement("canvas")).getContext("webgl") \r
- || canvas.getContext("experimental-webgl")) ? 1 : -1);\r
- }\r
- return (Jmol.featureDetection._webGLtest > 0);\r
- };\r
-\r
- features.supportsLocalization = function() {\r
- //<meta charset="utf-8"> \r
- var metas = document.getElementsByTagName('meta'); \r
- for (var i= metas.length; --i >= 0;) \r
- if (metas[i].outerHTML.toLowerCase().indexOf("utf-8") >= 0) return true;\r
- return false;\r
- };\r
-\r
- features.supportsJava = function() {\r
- if (!Jmol.featureDetection._javaEnabled) {\r
- if (Jmol._isMsie) {\r
- if (!navigator.javaEnabled()) {\r
- Jmol.featureDetection._javaEnabled = -1;\r
- } else {\r
- //more likely -- would take huge testing\r
- Jmol.featureDetection._javaEnabled = 1;\r
- }\r
- } else {\r
- Jmol.featureDetection._javaEnabled = (navigator.javaEnabled() && (!navigator.mimeTypes || navigator.mimeTypes["application/x-java-applet"]) ? 1 : -1);\r
- }\r
- }\r
- return (Jmol.featureDetection._javaEnabled > 0);\r
- };\r
-\r
- features.compliantBrowser = function() {\r
- var a = !!document.getElementById;\r
- var os = features.os;\r
- // known exceptions (old browsers):\r
- if (features.browserName == "opera" && features.browserVersion <= 7.54 && os == "mac"\r
- || features.browserName == "webkit" && features.browserVersion < 125.12\r
- || features.browserName == "msie" && os == "mac"\r
- || features.browserName == "konqueror" && features.browserVersion <= 3.3\r
- ) a = false;\r
- return a;\r
- }\r
-\r
- features.isFullyCompliant = function() {\r
- return features.compliantBrowser() && features.supportsJava();\r
- }\r
-\r
- features.useIEObject = (features.os == "win" && features.browserName == "msie" && features.browserVersion >= 5.5);\r
- features.useHtml4Object = (features.browserName == "mozilla" && features.browserVersion >= 5) ||\r
- (features.browserName == "opera" && features.browserVersion >= 8) ||\r
- (features.browserName == "webkit"/* && features.browserVersion >= 412.2 && features.browserVersion < 500*/); // 500 is a guess; required for 536.3\r
-\r
- features.hasFileReader = (window.File && window.FileReader);\r
-\r
- return features;\r
-\r
-})(document, window);\r
-\r
-\r
- ////////////// AJAX-related core functionality //////////////\r
-\r
- Jmol._ajax = function(info) {\r
- if (!info.async) {\r
- return Jmol.$ajax(info).responseText;\r
- }\r
- Jmol._ajaxQueue.push(info)\r
- if (Jmol._ajaxQueue.length == 1)\r
- Jmol._ajaxDone()\r
- }\r
- Jmol._ajaxDone = function() {\r
- var info = Jmol._ajaxQueue.shift();\r
- info && Jmol.$ajax(info);\r
- }\r
-\r
- Jmol._grabberOptions = [\r
- ["$", "NCI(small molecules)"],\r
- [":", "PubChem(small molecules)"],\r
- ["=", "RCSB(macromolecules)"],\r
- ["*", "PDBe(macromolecules)"]\r
- ];\r
-\r
- Jmol._getGrabberOptions = function(applet) {\r
- // feel free to adjust this look to anything you want\r
- if (Jmol._grabberOptions.length == 0)\r
- return ""\r
-\r
-\r
- 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
- var b = '<button id="ID_submit" onclick="Jmol._applets[\'ID\']._search()">Search</button></nobr>'\r
- if (Jmol._grabberOptions.length == 1) {\r
- s = '<nobr>' + s + '<span style="display:none">';\r
- b = '</span>' + b;\r
- } else {\r
- s += '<br /><nobr>'\r
- }\r
- s += '<select id="ID_select">'\r
- for (var i = 0; i < Jmol._grabberOptions.length; i++) {\r
- var opt = Jmol._grabberOptions[i];\r
- s += '<option value="' + opt[0] + '" ' + (i == 0 ? 'selected' : '') + '>' + opt[1] + '</option>';\r
- }\r
- s = (s + '</select>' + b).replace(/ID/g, applet._id);\r
- return '<br />' + s;\r
- }\r
-\r
- Jmol._getScriptForDatabase = function(database) {\r
- return (database == "$" ? Jmol.db._nciLoadScript : database == ":" ? Jmol.db._pubChemLoadScript : Jmol.db._fileLoadScript);\r
- }\r
-\r
- // <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
-\r
- Jmol._setInfo = function(applet, database, data) {\r
- var info = [];\r
- var header = "";\r
- if (data.indexOf("ERROR") == 0)\r
- header = data;\r
- else\r
- switch (database) {\r
- case "=":\r
- var S = data.split("<dimStructure.structureId>");\r
- var info = ["<table>"];\r
- for (var i = 1; i < S.length; i++) {\r
- 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
- info.push("<td>" + S[i].split("Title>")[1].split("</")[0] + "</td></tr>");\r
- }\r
- info.push("</table>");\r
- header = (S.length - 1) + " matches";\r
- break; \r
- case "$": // NCI\r
- case ":": // pubChem\r
- break;\r
- default:\r
- return;\r
- }\r
- applet._infoHeader = header;\r
- applet._info = info.join("");\r
- applet._showInfo(true);\r
- }\r
-\r
- Jmol._loadSuccess = function(a, fSuccess) {\r
- if (!fSuccess)\r
- return;\r
- Jmol._ajaxDone();\r
- fSuccess(a);\r
- }\r
-\r
- Jmol._loadError = function(fError){\r
- Jmol._ajaxDone();\r
- Jmol.say("Error connecting to server: " + Jmol._ajaxCall); \r
- null!=fError&&fError()\r
- }\r
-\r
- Jmol._isDatabaseCall = function(query) {\r
- return (Jmol.db._databasePrefixes.indexOf(query.substring(0, 1)) >= 0);\r
- }\r
-\r
- \r
- Jmol._getDirectDatabaseCall = function(query, checkXhr2) {\r
- if (checkXhr2 && !Jmol.featureDetection.supportsXhr2())\r
- return query;\r
- var pt = 2;\r
- var db;\r
- var call = Jmol.db._DirectDatabaseCalls[query.substring(0,pt)];\r
- if (!call)\r
- call = Jmol.db._DirectDatabaseCalls[db = query.substring(0,--pt)];\r
- if (call) {\r
- if (db == ":") {\r
- var ql = query.toLowerCase();\r
- if (!isNaN(parseInt(query.substring(1)))) {\r
- query = "cid/" + query.substring(1);\r
- } else if (ql.indexOf(":smiles:") == 0) {\r
- call += "?POST?smiles=" + query.substring(8);\r
- query = "smiles";\r
- } else if (ql.indexOf(":cid:") == 0) {\r
- query = "cid/" + query.substring(5);\r
- } else {\r
- if (ql.indexOf(":name:") == 0)\r
- query = query.substring(5);\r
- else if (ql.indexOf(":cas:") == 0)\r
- query = query.substring(4);\r
- query = "name/" + encodeURIComponent(query.substring(pt));\r
- }\r
- } else {\r
- query = encodeURIComponent(query.substring(pt)); \r
- }\r
- if (call.indexOf("FILENCI") >= 0) {\r
- query = query.replace(/\%2F/g, "/"); \r
- query = call.replace(/\%FILENCI/, query);\r
- } else {\r
- query = call.replace(/\%FILE/, query);\r
- }\r
- } \r
- return query;\r
- }\r
-\r
- Jmol._getRawDataFromServer = function(database,query,fSuccess,fError,asBase64,noScript){\r
- // note that this method is now only enabled for "_"\r
- // server-side processing of database queries was too slow and only useful for \r
- // the IMAGE option, which has been abandoned.\r
- var s = \r
- "?call=getRawDataFromDatabase&database=" + database + (query.indexOf("?POST?") >= 0 ? "?POST?" : "")\r
- + "&query=" + encodeURIComponent(query)\r
- + (asBase64 ? "&encoding=base64" : "")\r
- + (noScript ? "" : "&script=" + encodeURIComponent(Jmol._getScriptForDatabase(database)));\r
- return Jmol._contactServer(s, fSuccess, fError);\r
- }\r
-\r
- Jmol._checkFileName = function(applet, fileName, isRawRet) {\r
- if (Jmol._isDatabaseCall(fileName)) {\r
- if (isRawRet)\r
- Jmol._setQueryTerm(applet, fileName);\r
- fileName = Jmol._getDirectDatabaseCall(fileName, true);\r
- if (Jmol._isDatabaseCall(fileName)) {\r
- // xhr2 not supported (MSIE)\r
- fileName = Jmol._getDirectDatabaseCall(fileName, false);\r
- isRawRet && (isRawRet[0] = true);\r
- }\r
- }\r
- return fileName;\r
- }\r
- \r
- Jmol._checkCache = function(applet, fileName, fSuccess) {\r
- if (applet._cacheFiles && Jmol._fileCache && !fileName.endsWith(".js")) {\r
- var data = Jmol._fileCache[fileName];\r
- if (data) {\r
- System.out.println("using " + data.length + " bytes of cached data for " + fileName);\r
- fSuccess(data);\r
- return null;\r
- } else {\r
- fSuccess = function(fileName, data) { fSuccess(Jmol._fileCache[fileName] = data) }; \r
- }\r
- }\r
- return fSuccess;\r
- }\r
- \r
- Jmol._loadFileData = function(applet, fileName, fSuccess, fError){\r
- var isRaw = [];\r
- fileName = Jmol._checkFileName(applet, fileName, isRaw);\r
- fSuccess = Jmol._checkCache(applet, fileName, fSuccess);\r
- if (isRaw[0]) {\r
- Jmol._getRawDataFromServer("_",fileName,fSuccess,fError); \r
- return;\r
- } \r
- var info = {\r
- type: "GET",\r
- dataType: "text",\r
- url: fileName,\r
- async: Jmol._asynchronous,\r
- success: function(a) {Jmol._loadSuccess(a, fSuccess)},\r
- error: function() {Jmol._loadError(fError)}\r
- }\r
- Jmol._checkAjaxPost(info);\r
- Jmol._ajax(info);\r
- }\r
-\r
- Jmol._getInfoFromDatabase = function(applet, database, query){\r
- if (database == "====") {\r
- var data = Jmol.db._restQueryXml.replace(/QUERY/,query);\r
-\r
- var info = {\r
- dataType: "text",\r
- type: "POST",\r
- contentType:"application/x-www-form-urlencoded",\r
- url: Jmol.db._restQueryUrl,\r
- data: encodeURIComponent(data) + "&req=browser",\r
- success: function(data) {Jmol._ajaxDone();Jmol._extractInfoFromRCSB(applet, database, query, data)},\r
- error: function() {Jmol._loadError(null)},\r
- async: Jmol._asynchronous\r
- }\r
- return Jmol._ajax(info);\r
- } \r
- query = "?call=getInfoFromDatabase&database=" + database\r
- + "&query=" + encodeURIComponent(query);\r
- return Jmol._contactServer(query, function(data) {Jmol._setInfo(applet, database, data)});\r
- }\r
-\r
- Jmol._extractInfoFromRCSB = function(applet, database, query, output) {\r
- var n = output.length/5;\r
- if (n == 0)\r
- return; \r
- if (query.length == 4 && n != 1) {\r
- var QQQQ = query.toUpperCase();\r
- var pt = output.indexOf(QQQQ);\r
- if (pt > 0 && "123456789".indexOf(QQQQ.substring(0, 1)) >= 0)\r
- output = QQQQ + "," + output.substring(0, pt) + output.substring(pt + 5);\r
- if (n > 50)\r
- output = output.substring(0, 250);\r
- output = output.replace(/\n/g,",");\r
- var url = Jmol._restReportUrl.replace(/IDLIST/,output);\r
- Jmol._loadFileData(applet, url, function(data) {Jmol._setInfo(applet, database, data) }); \r
- }\r
- }\r
-\r
- Jmol._checkAjaxPost = function(info) {\r
- var pt = info.url.indexOf("?POST?");\r
- if (pt > 0) {\r
- info.data = info.url.substring(pt + 6);\r
- info.url = info.url.substring(0, pt);\r
- info.type = "POST";\r
- info.contentType = "application/x-www-form-urlencoded";\r
- }\r
- }\r
- Jmol._contactServer = function(data,fSuccess,fError){\r
- var info = {\r
- dataType: "text",\r
- type: "GET",\r
- url: Jmol._serverUrl + data,\r
- success: function(a) {Jmol._loadSuccess(a, fSuccess)},\r
- error:function() { Jmol._loadError(fError) },\r
- async:fSuccess ? Jmol._asynchronous : false\r
- }\r
- Jmol._checkAjaxPost(info);\r
- return Jmol._ajax(info);\r
- }\r
-\r
- Jmol._setQueryTerm = function(applet, query) {\r
- if (!query || !applet._hasOptions || query.substring(0, 7) == "http://")\r
- return;\r
- if (Jmol._isDatabaseCall(query)) {\r
- var database = query.substring(0, 1);\r
- query = query.substring(1);\r
- if (query.substring(0,1) == database && "=$".indexOf(database) >= 0)\r
- query = query.substring(1);\r
- var d = Jmol._getElement(applet, "select");\r
- if (d && d.options)\r
- for (var i = 0; i < d.options.length; i++)\r
- if (d[i].value == database)\r
- d[i].selected = true;\r
- }\r
- Jmol.$val(Jmol.$(applet, "query"), query);\r
- }\r
-\r
- Jmol._search = function(applet, query, script) {\r
- arguments.length > 1 || (query = null);\r
- Jmol._setQueryTerm(applet, query);\r
- query || (query = Jmol.$val(Jmol.$(applet, "query")))\r
- if (query.indexOf("!") == 0) {\r
- // command prompt in this box as well\r
- // remove exclamation point "immediate" indicator\r
- applet._script(query.substring(1));\r
- return;\r
- } \r
- query && (query = query.replace(/\"/g, ""));\r
- applet._showInfo(false);\r
- Jmol._searchMol(applet, query, script, true);\r
- }\r
-\r
- Jmol._searchMol = function(applet, query, script, checkView) {\r
- var database;\r
- if (Jmol._isDatabaseCall(query)) {\r
- database = query.substring(0, 1);\r
- query = query.substring(1);\r
- } else {\r
- database = (applet._hasOptions ? Jmol.$val(Jmol.$(applet, "select")) : "$");\r
- }\r
- if (database == "=" && query.length == 3)\r
- query = "=" + query; // this is a ligand \r
- var dm = database + query;\r
- if (!query || dm.indexOf("?") < 0 && dm == applet._thisJmolModel) {\r
- return; \r
- }\r
- applet._thisJmolModel = dm;\r
- var view;\r
- if (checkView && applet._viewSet != null && (view = Jmol.View.__findView(applet._viewSet, {chemID:dm})) != null) {\r
- Jmol.View.__setView(view, applet, false);\r
- return;\r
- }\r
-\r
- if (database == "$" || database == ":")\r
- applet._jmolFileType = "MOL";\r
- else if (database == "=")\r
- applet._jmolFileType = "PDB";\r
- applet._searchDatabase(query, database, script);\r
- }\r
-\r
- Jmol._searchDatabase = function(applet, query, database, script) {\r
- applet._showInfo(false);\r
- if (query.indexOf("?") >= 0) {\r
- Jmol._getInfoFromDatabase(applet, database, query.split("?")[0]);\r
- return true;\r
- }\r
- if (Jmol.db._DirectDatabaseCalls[database]) {\r
- applet._loadFile(database + query, script);\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- Jmol._syncBinaryOK="?";\r
-\r
- Jmol._canSyncBinary = function(isSilent) {\r
- if (Jmol._isAsync) return true;\r
- if (self.VBArray) return (Jmol._syncBinaryOK = false);\r
- if (Jmol._syncBinaryOK != "?") return Jmol._syncBinaryOK;\r
- Jmol._syncBinaryOK = true;\r
- try {\r
- var xhr = new window.XMLHttpRequest();\r
- xhr.open( "text", Jmol._ajaxTestSite, false );\r
- if (xhr.hasOwnProperty("responseType")) {\r
- xhr.responseType = "arraybuffer";\r
- } else if (xhr.overrideMimeType) {\r
- xhr.overrideMimeType('text/plain; charset=x-user-defined');\r
- }\r
- } catch( e ) {\r
- var s = "JSmolCore.js: synchronous binary file transfer is requested but not available";\r
- System.out.println(s);\r
- if (Jmol._alertNoBinary && !isSilent)\r
- alert (s)\r
- return Jmol._syncBinaryOK = false;\r
- }\r
- return true; \r
- }\r
-\r
- Jmol._binaryTypes = [".gz",".jpg",".gif",".png",".zip",".jmol",".bin",".smol",".spartan",".mrc",".pse", ".map", ".omap"];\r
-\r
- Jmol._isBinaryUrl = function(url) {\r
- for (var i = Jmol._binaryTypes.length; --i >= 0;)\r
- if (url.indexOf(Jmol._binaryTypes[i]) >= 0) return true;\r
- return false;\r
- }\r
-\r
- Jmol._getFileData = function(fileName, fSuccess, doProcess) {\r
- // use host-server PHP relay if not from this host\r
- var isBinary = Jmol._isBinaryUrl(fileName);\r
- var isPDB = (fileName.indexOf("pdb.gz") >= 0 && fileName.indexOf("http://www.rcsb.org/pdb/files/") == 0);\r
- var asBase64 = (isBinary && !Jmol._canSyncBinary(isPDB));\r
- if (asBase64 && isPDB) {\r
- // avoid unnecessary binary transfer\r
- fileName = fileName.replace(/pdb\.gz/,"pdb");\r
- asBase64 = isBinary = false;\r
- }\r
- var isPost = (fileName.indexOf("?POST?") >= 0);\r
- if (fileName.indexOf("file:/") == 0 && fileName.indexOf("file:///") != 0)\r
- fileName = "file://" + fileName.substring(5); /// fixes IE problem\r
- var isMyHost = (fileName.indexOf("://") < 0 || fileName.indexOf(document.location.protocol) == 0 && fileName.indexOf(document.location.host) >= 0);\r
- var isDirectCall = Jmol._isDirectCall(fileName);\r
- //if (fileName.indexOf("http://pubchem.ncbi.nlm.nih.gov/") == 0)isDirectCall = false;\r
-\r
- var cantDoSynchronousLoad = (!isMyHost && Jmol.$supportsIECrossDomainScripting());\r
- var data = null;\r
- if ((!fSuccess || asBase64) && (cantDoSynchronousLoad || asBase64 || !isMyHost && !isDirectCall)) {\r
- data = Jmol._getRawDataFromServer("_",fileName, fSuccess, fSuccess, asBase64, true);\r
- } else {\r
- fileName = fileName.replace(/file:\/\/\/\//, "file://"); // opera\r
- var info = {dataType:(isBinary ? "binary" : "text"),async:!!fSuccess};\r
- if (isPost) {\r
- info.type = "POST";\r
- info.url = fileName.split("?POST?")[0]\r
- info.data = fileName.split("?POST?")[1]\r
- } else {\r
- info.type = "GET";\r
- info.url = fileName;\r
- }\r
- if (fSuccess) {\r
- info.success = function(data) { fSuccess(Jmol._xhrReturn(info.xhr))};\r
- info.error = function() { fSuccess(info.xhr.statusText)};\r
- }\r
- info.xhr = Jmol.$ajax(info);\r
- if (!fSuccess) {\r
- data = Jmol._xhrReturn(info.xhr);\r
- }\r
- }\r
- if (!doProcess)\r
- return data;\r
- if (data == null) {\r
- data = "";\r
- isBinary = false;\r
- }\r
- isBinary && (isBinary = Jmol._canSyncBinary(true));\r
- return (isBinary ? Jmol._strToBytes(data) : JU.SB.newS(data));\r
- }\r
- \r
- Jmol._xhrReturn = function(xhr){\r
- if (!xhr.responseText || self.Clazz && Clazz.instanceOf(xhr.response, self.ArrayBuffer)) {\r
- // Safari or error \r
- return xhr.response || xhr.statusText;\r
- } \r
- return xhr.responseText;\r
- }\r
-\r
- Jmol._isDirectCall = function(url) {\r
- for (var key in Jmol.db._DirectDatabaseCalls) {\r
- if (key.indexOf(".") >= 0 && url.indexOf(key) >= 0)\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- Jmol._cleanFileData = function(data) {\r
- if (data.indexOf("\r") >= 0 && data.indexOf("\n") >= 0) {\r
- return data.replace(/\r\n/g,"\n");\r
- }\r
- if (data.indexOf("\r") >= 0) {\r
- return data.replace(/\r/g,"\n");\r
- }\r
- return data;\r
- };\r
-\r
- Jmol._getFileType = function(name) {\r
- var database = name.substring(0, 1);\r
- if (database == "$" || database == ":")\r
- return "MOL";\r
- if (database == "=")\r
- return (name.substring(1,2) == "=" ? "LCIF" : "PDB");\r
- // just the extension, which must be PDB, XYZ..., CIF, or MOL\r
- name = name.split('.').pop().toUpperCase();\r
- return name.substring(0, Math.min(name.length, 3));\r
- };\r
-\r
- Jmol._getZ = function(applet, what) {\r
- return applet && applet._z && applet._z[what] || Jmol._z[what];\r
- }\r
- \r
- Jmol._incrZ = function(applet, what) {\r
- return applet && applet._z && ++applet._z[what] || ++Jmol._z[what];\r
- }\r
- \r
- Jmol._loadFileAsynchronously = function(fileLoadThread, applet, fileName, appData) {\r
- if (fileName.indexOf("?") != 0) {\r
- // LOAD ASYNC command\r
- var fileName0 = fileName;\r
- fileName = Jmol._checkFileName(applet, fileName);\r
- var fSuccess = function(data) {Jmol._setData(fileLoadThread, fileName, fileName0, data, appData)};\r
- fSuccess = Jmol._checkCache(applet, fileName, fSuccess);\r
- if (fileName.indexOf("|") >= 0)\r
- fileName = fileName.split("|")[0];\r
- return (fSuccess == null ? null : Jmol._getFileData(fileName, fSuccess)); \r
- }\r
- // we actually cannot suggest a fileName, I believe.\r
- if (!Jmol.featureDetection.hasFileReader)\r
- return fileLoadThread.setData("Local file reading is not enabled in your browser", null, null, appData);\r
- if (!applet._localReader) {\r
- 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
- Jmol.$after("#" + applet._id + "_appletdiv", div.replace(/ID/g, applet._id + "_localReader"));\r
- applet._localReader = Jmol.$(applet, "localReader");\r
- }\r
- Jmol.$appEvent(applet, "localReader_loadfile", "click");\r
- Jmol.$appEvent(applet, "localReader_loadfile", "click", function(evt) {\r
- var file = Jmol.$(applet, "localReader_files")[0].files[0]; \r
- var reader = new FileReader();\r
- reader.onloadend = function(evt) {\r
- if (evt.target.readyState == FileReader.DONE) { // DONE == 2\r
- Jmol.$css(Jmol.$(applet, "localReader"), {display : "none"});\r
- Jmol._setData(fileLoadThread, file.name, file.name, evt.target.result, appData);\r
- }\r
- };\r
- reader.readAsArrayBuffer(file);\r
- });\r
- Jmol.$appEvent(applet, "localReader_cancel", "click");\r
- Jmol.$appEvent(applet, "localReader_cancel", "click", function(evt) {\r
- Jmol.$css(Jmol.$(applet, "localReader"), {display: "none"});\r
- fileLoadThread.setData(null, null, null, appData);\r
- });\r
- Jmol.$css(Jmol.$(applet, "localReader"), {display : "block"});\r
- }\r
-\r
- Jmol._setData = function(fileLoadThread, filename, filename0, data, appData) {\r
- data = Jmol._strToBytes(data);\r
- if (filename.indexOf(".jdx") >= 0)\r
- Jmol.Cache.put("cache://" + filename, data);\r
- fileLoadThread.setData(filename, filename0, data, appData);\r
- }\r
- \r
- Jmol._toBytes = function(data) {\r
- if (typeof data == "string") \r
- return data.getBytes();\r
- // ArrayBuffer assumed here\r
- data = new Uint8Array(data);\r
- var b = Clazz.newByteArray(data.length, 0);\r
- for (var i = data.length; --i >= 0;)\r
- b[i] = data[i];\r
- return b;\r
- }\r
-\r
- Jmol._doAjax = function(url, postOut, dataOut) {\r
- // called by org.jmol.awtjs2d.JmolURLConnection.doAjax()\r
- url = url.toString();\r
-\r
- if (dataOut != null) \r
- return Jmol._saveFile(url, dataOut);\r
- if (postOut)\r
- url += "?POST?" + postOut;\r
- return Jmol._getFileData(url, null, true);\r
- }\r
-\r
- // Jmol._localFileSaveFunction -- // do something local here; Maybe try the FileSave interface? return true if successful\r
- \r
- Jmol._saveFile = function(filename, data, mimetype, encoding) {\r
- if (Jmol._localFileSaveFunction && Jmol._localFileSaveFunction(filename, data))\r
- return "OK";\r
- var filename = filename.substring(filename.lastIndexOf("/") + 1);\r
- mimetype || (mimetype = (filename.indexOf(".pdf") >= 0 ? "application/pdf" \r
- : filename.indexOf(".png") >= 0 ? "image/png" \r
- : filename.indexOf(".gif") >= 0 ? "image/gif" \r
- : filename.indexOf(".jpg") >= 0 ? "image/jpg" : ""));\r
- var isString = (typeof data == "string");\r
- if (!isString)\r
- data = (JU ? JU : J.util).Base64.getBase64(data).toString();\r
- encoding || (encoding = (isString ? "" : "base64"));\r
- var url = Jmol._serverUrl;\r
- url && url.indexOf("your.server") >= 0 && (url = "");\r
- if (Jmol._useDataURI || !url) {\r
- // Asynchronous output generated using an anchor tag\r
- encoding || (data = btoa(data));\r
- var a = document.createElement("a");\r
- a.href = "data:" + mimetype + ";base64," + data;\r
- a.type = mimetype || (mimetype = "text/plain"); \r
- a.download = filename;\r
- a.target = "_blank";\r
- $("body").append(a);\r
- a.click();\r
- a.remove(); \r
- } else {\r
- // Asynchronous outputto be reflected as a download\r
- if (!Jmol._formdiv) {\r
- var sform = '<div id="__jsmolformdiv__" style="display:none">\\r
- <form id="__jsmolform__" method="post" target="_blank" action="">\\r
- <input name="call" value="saveFile"/>\\r
- <input id="__jsmolmimetype__" name="mimetype" value=""/>\\r
- <input id="__jsmolencoding__" name="encoding" value=""/>\\r
- <input id="__jsmolfilename__" name="filename" value=""/>\\r
- <textarea id="__jsmoldata__" name="data"></textarea>\\r
- </form>\\r
- </div>'\r
- Jmol.$after("body", sform);\r
- Jmol._formdiv = "__jsmolform__";\r
- }\r
- Jmol.$attr(Jmol._formdiv, "action", url + "?" + (new Date()).getMilliseconds());\r
- Jmol.$val("__jsmoldata__", data);\r
- Jmol.$val("__jsmolfilename__", filename);\r
- Jmol.$val("__jsmolmimetype__", mimetype);\r
- Jmol.$val("__jsmolencoding__", encoding);\r
- Jmol.$submit("__jsmolform__");\r
- Jmol.$val("__jsmoldata__", "");\r
- Jmol.$val("__jsmolfilename__", "");\r
- }\r
- return "OK";\r
- }\r
-\r
- Jmol._strToBytes = function(s) {\r
- if (Clazz.instanceOf(s, self.ArrayBuffer))\r
- return Jmol._toBytes(s);\r
- var b = Clazz.newByteArray(s.length, 0);\r
- for (var i = s.length; --i >= 0;)\r
- b[i] = s.charCodeAt(i) & 0xFF;\r
- return b;\r
- }\r
-\r
- ////////////// applet start-up functionality //////////////\r
-\r
- Jmol._setConsoleDiv = function (d) {\r
- if (!self.Clazz)return;\r
- Clazz.setConsoleDiv(d);\r
- }\r
-\r
- Jmol._registerApplet = function(id, applet) {\r
- return window[id] = Jmol._applets[id] = Jmol._applets[applet] = Jmol._applets[id + "__" + Jmol._syncId + "__"] = applet;\r
- } \r
-\r
- Jmol._readyCallback = function (appId,fullId,isReady,javaApplet,javaAppletPanel) {\r
- appId = appId.split("_object")[0];\r
- javaAppletPanel || (javaAppletPanel = javaApplet);\r
- isReady = (isReady.booleanValue ? isReady.booleanValue() : isReady);\r
- // necessary for MSIE in strict mode -- apparently, we can't call \r
- // jmol._readyCallback, but we can call Jmol._readyCallback. Go figure...\r
- var applet = Jmol._applets[appId];\r
- applet._appletPanel = javaAppletPanel;\r
- applet._applet = javaApplet;\r
- Jmol._track(applet._readyCallback(appId, fullId, isReady));\r
- }\r
-\r
- Jmol._getWrapper = function(applet, isHeader) {\r
-\r
- // id_appletinfotablediv\r
- // id_appletdiv\r
- // id_coverdiv\r
- // id_infotablediv\r
- // id_infoheaderdiv\r
- // id_infoheaderspan\r
- // id_infocheckboxspan\r
- // id_infodiv\r
-\r
-\r
- // for whatever reason, without DOCTYPE, with MSIE, "height:auto" does not work, \r
- // and the text scrolls off the page.\r
- // So I'm using height:95% here.\r
- // The table was a fix for MSIE with no DOCTYPE tag to fix the miscalculation\r
- // in height of the div when using 95% for height. \r
- // But it turns out the table has problems with DOCTYPE tags, so that's out. \r
- // The 95% is a compromise that we need until the no-DOCTYPE MSIE solution is found. \r
- // (100% does not work with the JME linked applet)\r
- var s;\r
- // ... here are just for clarification in this code; they are removed immediately\r
- if (isHeader) {\r
- var img = ""; \r
- if (applet._coverImage){\r
- var more = " onclick=\"Jmol.coverApplet(ID, false)\" title=\"" + (applet._coverTitle) + "\"";\r
- 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
- + "z-index:" + Jmol._getZ(applet, "coverImage")+";opacity:0.5;\"" + more + " />" \r
- 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
- + applet._coverImage + "\" style=\"width:100%;height:100%\"" + more + "/>" + play + "</div>";\r
- }\r
- var css = Jmol._appletCssText.replace(/\'/g,'"');\r
- css = (css.indexOf("style=\"") >= 0 ? css.split("style=\"")[1] : "\" " + css);\r
- s = "\\r
-...<div id=\"ID_appletinfotablediv\" style=\"width:Wpx;height:Hpx;position:relative;font-size:14px;text-align:left\">IMG\\r
-......<div id=\"ID_appletdiv\" style=\"z-index:" + Jmol._getZ(applet, "header") + ";width:100%;height:100%;position:absolute;top:0px;left:0px;" + css + ">";\r
- var height = applet._height;\r
- var width = applet._width;\r
- if (typeof height !== "string" || height.indexOf("%") < 0) \r
- height += "px";\r
- if (typeof width !== "string" || width.indexOf("%") < 0)\r
- width += "px";\r
- s = s.replace(/IMG/, img).replace(/Hpx/g, height).replace(/Wpx/g, width);\r
- } else {\r
- s = "\\r
-......</div>\\r
-......<div id=\"ID_2dappletdiv\" style=\"position:absolute;width:100%;height:100%;overflow:hidden;display:none\"></div>\\r
-......<div id=\"ID_infotablediv\" style=\"width:100%;height:100%;position:absolute;top:0px;left:0px\">\\r
-.........<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
-.........<div id=\"ID_infodiv\" style=\"position:absolute;top:20px;bottom:0px;width:100%;height:100%;overflow:auto\"></div>\\r
-......</div>\\r
-...</div>";\r
- }\r
- return s.replace(/\.\.\./g,"").replace(/[\n\r]/g,"").replace(/ID/g, applet._id);\r
- }\r
-\r
- Jmol._documentWrite = function(text) {\r
- if (Jmol._document) {\r
- if (Jmol._isXHTML && !Jmol._XhtmlElement) {\r
- var s = document.getElementsByTagName("script");\r
- Jmol._XhtmlElement = s.item(s.length - 1);\r
- Jmol._XhtmlAppendChild = false;\r
- }\r
- if (Jmol._XhtmlElement)\r
- Jmol._domWrite(text);\r
- else\r
- Jmol._document.write(text);\r
- }\r
- return text;\r
- }\r
-\r
- Jmol._domWrite = function(data) {\r
- var pt = 0\r
- var Ptr = []\r
- Ptr[0] = 0\r
- while (Ptr[0] < data.length) {\r
- var child = Jmol._getDomElement(data, Ptr);\r
- if (!child)\r
- break;\r
- if (Jmol._XhtmlAppendChild)\r
- Jmol._XhtmlElement.appendChild(child);\r
- else\r
- Jmol._XhtmlElement.parentNode.insertBefore(child, _jmol.XhtmlElement);\r
- }\r
- }\r
-\r
- Jmol._getDomElement = function(data, Ptr, closetag, lvel) {\r
-\r
- // there is no "document.write" in XHTML\r
-\r
- var e = document.createElement("span");\r
- e.innerHTML = data;\r
- Ptr[0] = data.length;\r
-\r
-/*\r
- // unnecessary ? \r
-\r
- closetag || (closetag = "");\r
- lvel || (lvel = 0);\r
- var pt0 = Ptr[0];\r
- var pt = pt0;\r
- while (pt < data.length && data.charAt(pt) != "<") \r
- pt++\r
- if (pt != pt0) {\r
- var text = data.substring(pt0, pt);\r
- Ptr[0] = pt;\r
- return document.createTextNode(text);\r
- }\r
- pt0 = ++pt;\r
- var ch;\r
- while (pt < data.length && "\n\r\t >".indexOf(ch = data.charAt(pt)) < 0) \r
- pt++;\r
- var tagname = data.substring(pt0, pt);\r
- var e = (tagname == closetag || tagname == "/" ? ""\r
- : document.createElementNS ? document.createElementNS('http://www.w3.org/1999/xhtml', tagname)\r
- : document.createElement(tagname));\r
- if (ch == ">") {\r
- Ptr[0] = ++pt;\r
- return e;\r
- }\r
- while (pt < data.length && (ch = data.charAt(pt)) != ">") {\r
- while (pt < data.length && "\n\r\t ".indexOf(ch = data.charAt(pt)) >= 0) \r
- pt++;\r
- pt0 = pt;\r
- while (pt < data.length && "\n\r\t =/>".indexOf(ch = data.charAt(pt)) < 0) \r
- pt++;\r
- var attrname = data.substring(pt0, pt).toLowerCase();\r
- if (attrname && ch != "=")\r
- e.setAttribute(attrname, "true");\r
- while (pt < data.length && "\n\r\t ".indexOf(ch = data.charAt(pt)) >= 0) \r
- pt++;\r
- if (ch == "/") {\r
- Ptr[0] = pt + 2;\r
- return e;\r
- } else if (ch == "=") {\r
- var quote = data.charAt(++pt);\r
- pt0 = ++pt;\r
- while (pt < data.length && (ch = data.charAt(pt)) != quote) \r
- pt++;\r
- var attrvalue = data.substring(pt0, pt);\r
- e.setAttribute(attrname, attrvalue);\r
- pt++;\r
- }\r
- }\r
- Ptr[0] = ++pt;\r
- while (Ptr[0] < data.length) {\r
- var child = Jmol._getDomElement(data, Ptr, "/" + tagname, lvel+1);\r
- if (!child)\r
- break;\r
- e.appendChild(child);\r
- }\r
-*/\r
- return e; \r
- }\r
-\r
- Jmol._setObject = function(obj, id, Info) {\r
- obj._id = id;\r
- obj.__Info = {};\r
- Info.z && Info.zIndexBase && (Jmol._z = Jmol._getZOrders(Info.zIndexBase));\r
- for (var i in Info)\r
- obj.__Info[i] = Info[i];\r
- (obj._z = Info.z) || Info.zIndexBase && (obj._z = obj.__Info.z = Jmol._getZOrders(Info.zIndexBase));\r
- obj._width = Info.width;\r
- obj._height = Info.height;\r
- obj._noscript = !obj._isJava && Info.noscript;\r
- obj._console = Info.console;\r
- obj._cacheFiles = !!Info.cacheFiles;\r
- obj._viewSet = (Info.viewSet == null || obj._isJava ? null : "Set" + Info.viewSet);\r
- if (obj._viewSet != null) {\r
- Jmol.View.__init(obj);\r
- obj._currentView = null;\r
- }\r
- !Jmol._fileCache && obj._cacheFiles && (Jmol._fileCache = {});\r
- if (!obj._console)\r
- obj._console = obj._id + "_infodiv";\r
- if (obj._console == "none")\r
- obj._console = null;\r
-\r
- obj._color = (Info.color ? Info.color.replace(/0x/,"#") : "#FFFFFF");\r
- obj._disableInitialConsole = Info.disableInitialConsole;\r
- obj._noMonitor = Info.disableJ2SLoadMonitor;\r
- Jmol._j2sPath && (Info.j2sPath = Jmol._j2sPath);\r
- obj._j2sPath = Info.j2sPath;\r
- obj._coverImage = Info.coverImage;\r
- obj._isCovered = !!obj._coverImage; \r
- obj._deferApplet = Info.deferApplet || obj._isCovered && obj._isJava; // must do this if covered in Java\r
- obj._deferUncover = Info.deferUncover && !obj._isJava; // can't do this with Java\r
- obj._coverScript = Info.coverScript;\r
- obj._coverTitle = Info.coverTitle;\r
-\r
- if (!obj._coverTitle)\r
- obj._coverTitle = (obj._deferApplet ? "activate 3D model" : "3D model is loading...")\r
- obj._containerWidth = obj._width + ((obj._width==parseFloat(obj._width))? "px":"");\r
- obj._containerHeight = obj._height + ((obj._height==parseFloat(obj._height))? "px":"");\r
- obj._info = "";\r
- obj._infoHeader = obj._jmolType + ' "' + obj._id + '"'\r
- obj._hasOptions = Info.addSelectionOptions;\r
- obj._defaultModel = Info.defaultModel;\r
- obj._readyScript = (Info.script ? Info.script : "");\r
- obj._readyFunction = Info.readyFunction;\r
- if (obj._coverImage && !obj._deferApplet)\r
- obj._readyScript += ";javascript " + id + "._displayCoverImage(false)";\r
- obj._src = Info.src;\r
-\r
- }\r
-\r
- Jmol._addDefaultInfo = function(Info, DefaultInfo) {\r
- for (var x in DefaultInfo)\r
- if (typeof Info[x] == "undefined")\r
- Info[x] = DefaultInfo[x];\r
- Jmol._use && (Info.use = Jmol._use);\r
- if (Info.use.indexOf("SIGNED") >= 0) {\r
- if (Info.jarFile.indexOf("Signed") < 0)\r
- Info.jarFile = Info.jarFile.replace(/Applet/,"AppletSigned");\r
- Info.use = Info.use.replace(/SIGNED/, "JAVA");\r
- Info.isSigned = true;\r
- }\r
- }\r
-\r
- Jmol._syncedApplets = [];\r
- Jmol._syncedCommands = [];\r
- Jmol._syncedReady = [];\r
- Jmol._syncReady = false;\r
- Jmol._isJmolJSVSync = false;\r
-\r
- Jmol._setReady = function(applet) {\r
- Jmol._syncedReady[applet] = 1;\r
- var n = 0;\r
- for (var i = 0; i < Jmol._syncedApplets.length; i++) {\r
- if (Jmol._syncedApplets[i] == applet._id) {\r
- Jmol._syncedApplets[i] = applet;\r
- Jmol._syncedReady[i] = 1;\r
- } else if (!Jmol._syncedReady[i]) {\r
- continue;\r
- }\r
- n++;\r
- }\r
- if (n != Jmol._syncedApplets.length)\r
- return;\r
- Jmol._setSyncReady();\r
- }\r
-\r
- Jmol._setDestroy = function(applet) {\r
- //MSIE bug responds to any link click even if it is just a JavaScript call\r
-\r
- if (Jmol.featureDetection.allowDestroy)\r
- Jmol.$windowOn('beforeunload', function () { Jmol._destroy(applet); } );\r
- }\r
-\r
- Jmol._destroy = function(applet) {\r
- try {\r
- if (applet._appletPanel) applet._appletPanel.destroy();\r
- applet._applet = null;\r
- Jmol._unsetMouse(applet._canvas)\r
- applet._canvas = null;\r
- var n = 0;\r
- for (var i = 0; i < Jmol._syncedApplets.length; i++) {\r
- if (Jmol._syncedApplets[i] == applet)\r
- Jmol._syncedApplets[i] = null;\r
- if (Jmol._syncedApplets[i])\r
- n++;\r
- }\r
- if (n > 0)\r
- return;\r
- Jmol._clearVars();\r
- } catch(e){}\r
- }\r
-\r
- ////////////// misc core functionality //////////////\r
-\r
- Jmol._setSyncReady = function() {\r
- Jmol._syncReady = true;\r
- var s = ""\r
- for (var i = 0; i < Jmol._syncedApplets.length; i++)\r
- if (Jmol._syncedCommands[i])\r
- s += "Jmol.script(Jmol._syncedApplets[" + i + "], Jmol._syncedCommands[" + i + "]);"\r
- setTimeout(s, 50); \r
- }\r
-\r
- Jmol._mySyncCallback = function(appFullName,msg) {\r
- app = Jmol._applets[appFullName];\r
- if (app._viewSet) {\r
- // when can we do this?\r
-// if (app._viewType == "JSV" && !app._currentView.JMOL)\r
- Jmol.View.updateFromSync(app, msg);\r
- return;\r
- }\r
- if(!Jmol._syncReady || !Jmol._isJmolJSVSync)\r
- return 1; // continue processing and ignore me\r
- for (var i = 0; i < Jmol._syncedApplets.length; i++) {\r
- if (msg.indexOf(Jmol._syncedApplets[i]._syncKeyword) >= 0)\r
- Jmol._syncedApplets[i]._syncScript(msg);\r
- }\r
- return 0 // prevents further Jmol sync processing \r
- } \r
-\r
- Jmol._getElement = function(applet, what) {\r
- var d = document.getElementById(applet._id + "_" + what);\r
- return (d || {});\r
- } \r
- \r
- Jmol._evalJSON = function(s,key){\r
- s = s + "";\r
- if(!s)\r
- return [];\r
- if(s.charAt(0) != "{") {\r
- if(s.indexOf(" | ") >= 0)\r
- s = s.replace(/\ \|\ /g, "\n");\r
- return s;\r
- }\r
- var A = (new Function( "return " + s ) )();\r
- return (!A ? null : key && A[key] != undefined ? A[key] : A);\r
- }\r
-\r
- Jmol._sortMessages = function(A){\r
- /*\r
- * private function\r
- */\r
- function _sortKey0(a,b){\r
- return (a[0]<b[0]?1:a[0]>b[0]?-1:0);\r
- }\r
-\r
- if(!A || typeof (A) != "object")\r
- return [];\r
- var B = [];\r
- for(var i = A.length - 1; i >= 0; i--)\r
- for(var j = 0, jj= A[i].length; j < jj; j++)\r
- B[B.length] = A[i][j];\r
- if(B.length == 0)\r
- return;\r
- B = B.sort(_sortKey0);\r
- return B;\r
- }\r
-\r
- //////////////////// mouse events //////////////////////\r
-\r
- Jmol._setMouseOwner = function(who, tf) {\r
- if (who == null || tf)\r
- Jmol._mouseOwner = who;\r
- else if (Jmol._mouseOwner == who)\r
- Jmol._mouseOwner = null;\r
- }\r
-\r
- Jmol._jsGetMouseModifiers = function(ev) {\r
- var modifiers = 0;\r
- switch (ev.button) {\r
- case 0:\r
- modifiers = 16;//J.api.Event.MOUSE_LEFT;\r
- break;\r
- case 1:\r
- modifiers = 8;//J.api.Event.MOUSE_MIDDLE;\r
- break;\r
- case 2:\r
- modifiers = 4;//J.api.Event.MOUSE_RIGHT;\r
- break;\r
- }\r
- if (ev.shiftKey)\r
- modifiers += 1;//J.api.Event.SHIFT_MASK;\r
- if (ev.altKey)\r
- modifiers += 8;//J.api.Event.ALT_MASK;\r
- if (ev.ctrlKey)\r
- modifiers += 2;//J.api.Event.CTRL_MASK;\r
- return modifiers;\r
- }\r
-\r
- Jmol._jsGetXY = function(canvas, ev) {\r
- if (!canvas.applet._ready || Jmol._touching && ev.type.indexOf("touch") < 0)\r
- return false;\r
- //ev.preventDefault(); // removed 5/9/2015 -- caused loss of focus on text-box clicking in SwingJS\r
- var offsets = Jmol.$offset(canvas.id);\r
- var x, y;\r
- var oe = ev.originalEvent;\r
- // drag-drop jQuery event is missing pageX\r
- ev.pageX || (ev.pageX = oe.pageX);\r
- ev.pageY || (ev.pageY = oe.pageY);\r
- Jmol._mousePageX = ev.pageX;\r
- Jmol._mousePageY = ev.pageY;\r
- if (oe.targetTouches && oe.targetTouches[0]) {\r
- x = oe.targetTouches[0].pageX - offsets.left;\r
- y = oe.targetTouches[0].pageY - offsets.top;\r
- } else if (oe.changedTouches) {\r
- x = oe.changedTouches[0].pageX - offsets.left;\r
- y = oe.changedTouches[0].pageY - offsets.top;\r
- } else {\r
- x = ev.pageX - offsets.left;\r
- y = ev.pageY - offsets.top;\r
- }\r
- return (x == undefined ? null : [Math.round(x), Math.round(y), Jmol._jsGetMouseModifiers(ev)]);\r
- }\r
-\r
- Jmol._gestureUpdate = function(canvas, ev) {\r
- ev.stopPropagation();\r
- ev.preventDefault();\r
- var oe = ev.originalEvent;\r
- switch (ev.type) {\r
- case "touchstart":\r
- Jmol._touching = true;\r
- break;\r
- case "touchend":\r
- Jmol._touching = false;\r
- break;\r
- }\r
- if (!oe.touches || oe.touches.length != 2) return false;\r
- switch (ev.type) {\r
- case "touchstart":\r
- canvas._touches = [[],[]];\r
- break;\r
- case "touchmove":\r
- var offsets = Jmol.$offset(canvas.id);\r
- var t0 = canvas._touches[0];\r
- var t1 = canvas._touches[1];\r
- t0.push([oe.touches[0].pageX - offsets.left, oe.touches[0].pageY - offsets.top]);\r
- t1.push([oe.touches[1].pageX - offsets.left, oe.touches[1].pageY - offsets.top]);\r
- var n = t0.length;\r
- if (n > 3) {\r
- t0.shift();\r
- t1.shift();\r
- }\r
- if (n >= 2)\r
- canvas.applet._processGesture(canvas._touches);\r
- break;\r
- }\r
- return true;\r
- } \r
-\r
- Jmol._jsSetMouse = function(canvas) {\r
-\r
- var doIgnore = function(ev) { return (ev.target.className.indexOf("swingjs-ui") >= 0) };\r
- \r
- Jmol.$bind(canvas, 'mousedown touchstart', function(ev) {\r
- if (doIgnore(ev))\r
- return true;\r
- Jmol._setMouseOwner(canvas, true);\r
- ev.stopPropagation();\r
- var ui = ev.target["data-UI"];\r
- if (!ui || !ui.handleJSEvent(canvas, 501, ev)) \r
- ev.preventDefault();\r
- canvas.isDragging = true;\r
- if ((ev.type == "touchstart") && Jmol._gestureUpdate(canvas, ev))\r
- return !!ui;\r
- Jmol._setConsoleDiv(canvas.applet._console);\r
- var xym = Jmol._jsGetXY(canvas, ev);\r
- if(xym) {\r
- if (ev.button != 2)\r
- Jmol.Swing.hideMenus(canvas.applet);\r
- canvas.applet._processEvent(501, xym); //java.awt.Event.MOUSE_DOWN\r
- }\r
- return !!ui;\r
- });\r
- \r
- Jmol.$bind(canvas, 'mouseup touchend', function(ev) {\r
- if (doIgnore(ev))\r
- return true;\r
- Jmol._setMouseOwner(null);\r
- ev.stopPropagation();\r
- var ui = ev.target["data-UI"];\r
- if (!ui || !ui.handleJSEvent(canvas, 502, ev))\r
- ev.preventDefault();\r
- canvas.isDragging = false;\r
- if (ev.type == "touchend" && Jmol._gestureUpdate(canvas, ev))\r
- return !!ui;\r
- var xym = Jmol._jsGetXY(canvas, ev);\r
- if(xym)\r
- canvas.applet._processEvent(502, xym);//java.awt.Event.MOUSE_UP\r
- return !!ui;\r
- });\r
- \r
- Jmol.$bind(canvas, 'mousemove touchmove', function(ev) { // touchmove\r
- if (doIgnore(ev))\r
- return true;\r
- // defer to console or menu when dragging within this canvas\r
- if (Jmol._mouseOwner && Jmol._mouseOwner != canvas && Jmol._mouseOwner.isDragging) {\r
- if (!Jmol._mouseOwner.mouseMove)\r
- return true;\r
- Jmol._mouseOwner.mouseMove(ev);\r
- return false;\r
- }\r
- return Jmol._drag(canvas, ev);\r
- });\r
- \r
- Jmol._drag = function(canvas, ev) {\r
- \r
- ev.stopPropagation();\r
- ev.preventDefault();\r
- \r
- var isTouch = (ev.type == "touchmove");\r
- if (isTouch && Jmol._gestureUpdate(canvas, ev))\r
- return false;\r
- var xym = Jmol._jsGetXY(canvas, ev);\r
- if(!xym) return false;\r
- \r
- if (!canvas.isDragging)\r
- xym[2] = 0;\r
-\r
- var ui = ev.target["data-UI"];\r
- if (canvas.isdragging && (!ui || !ui.handleJSEvent(canvas, 506, ev))) {}\r
- canvas.applet._processEvent((canvas.isDragging ? 506 : 503), xym); // java.awt.Event.MOUSE_DRAG : java.awt.Event.MOUSE_MOVE\r
- return !!ui;\r
- }\r
- \r
- Jmol.$bind(canvas, 'DOMMouseScroll mousewheel', function(ev) { // Zoom\r
- if (doIgnore(ev))\r
- return true;\r
- ev.stopPropagation();\r
- ev.preventDefault();\r
- // Webkit or Firefox\r
- canvas.isDragging = false;\r
- var oe = ev.originalEvent;\r
- var scroll = (oe.detail ? oe.detail : (Jmol.featureDetection.os == "mac" ? 1 : -1) * oe.wheelDelta); // Mac and PC are reverse; but \r
- var modifiers = Jmol._jsGetMouseModifiers(ev);\r
- canvas.applet._processEvent(-1,[scroll < 0 ? -1 : 1,0,modifiers]);\r
- return false;\r
- });\r
-\r
- // context menu is fired on mouse down, not up, and it's handled already anyway.\r
-\r
- Jmol.$bind(canvas, "contextmenu", function() {return false;});\r
-\r
- Jmol.$bind(canvas, 'mouseout', function(ev) {\r
- if (doIgnore(ev))\r
- return true;\r
- if (Jmol._mouseOwner && !Jmol._mouseOwner.mouseMove) \r
- Jmol._setMouseOwner(null);\r
- if (canvas.applet._appletPanel)\r
- canvas.applet._appletPanel.startHoverWatcher(false);\r
- //canvas.isDragging = false;\r
- var xym = Jmol._jsGetXY(canvas, ev);\r
- if (!xym)\r
- return false;\r
- //canvas.applet._processEvent(502, xym);//J.api.Event.MOUSE_UP\r
- //canvas.applet._processEvent(505, xym);//J.api.Event.MOUSE_EXITED\r
- return false;\r
- });\r
-\r
- Jmol.$bind(canvas, 'mouseenter', function(ev) {\r
- if (doIgnore(ev))\r
- return true;\r
- if (canvas.applet._appletPanel)\r
- canvas.applet._appletPanel.startHoverWatcher(true);\r
- if (ev.buttons === 0 || ev.which === 0) {\r
- canvas.isDragging = false;\r
- var xym = Jmol._jsGetXY(canvas, ev);\r
- if (!xym)\r
- return false;\r
- canvas.applet._processEvent(504, xym);//J.api.Event.MOUSE_ENTERED \r
- canvas.applet._processEvent(502, xym);//J.api.Event.MOUSE_UP\r
- return false;\r
- }\r
- });\r
-\r
- Jmol.$bind(canvas, 'mousemoveoutjsmol', function(evspecial, target, ev) {\r
- if (doIgnore(ev))\r
- return true;\r
- if (canvas == Jmol._mouseOwner && canvas.isDragging) {\r
- return Jmol._drag(canvas, ev);\r
- }\r
- });\r
-\r
- if (canvas.applet._is2D)\r
- Jmol.$resize(function() {\r
- if (!canvas.applet)\r
- return;\r
- canvas.applet._resize();\r
- });\r
- \r
- Jmol.$bind('body', 'mouseup touchend', function(ev) {\r
- if (doIgnore(ev))\r
- return true;\r
- if (canvas.applet)\r
- canvas.isDragging = false;\r
- Jmol._setMouseOwner(null);\r
- });\r
-\r
- }\r
-\r
- Jmol._jsUnsetMouse = function(canvas) {\r
- canvas.applet = null;\r
- Jmol.$bind(canvas, 'mousedown touchstart mousemove touchmove mouseup touchend DOMMouseScroll mousewheel contextmenu mouseout mouseenter', null);\r
- Jmol._setMouseOwner(null);\r
- }\r
-\r
-\r
-////// Jmol.Swing interface for Javascript implementation of Swing dialogs and menus\r
-\r
-Jmol.Swing = {\r
- // a static class\r
- count:0,\r
- menuInitialized:0,\r
- menuCounter:0,\r
- htDialogs:{}\r
-};\r
-\r
-(function(Swing) {\r
-\r
-SwingController = Swing; // see javajs.api.SwingController\r
-\r
-Swing.setDraggable = function(Obj) {\r
- \r
- var proto = Obj.prototype;\r
- if (proto.setContainer)\r
- return;\r
- \r
- // for menus, console, and \r
- proto.setContainer = function(container) {\r
- this.container = container;\r
- container.obj = this;\r
- this.isDragging = false;\r
- this.ignoreMouse = false;\r
- var me = this;\r
- container.bind('mousedown touchstart', function(ev) {\r
- if (me.ignoreMouse) {\r
- me.ignoreMouse = false;\r
- return true;\r
- }\r
- Jmol._setMouseOwner(me, true);\r
- me.isDragging = true;\r
- me.pageX = ev.pageX;\r
- me.pageY = ev.pageY;\r
- return false;\r
- });\r
- container.bind('mousemove touchmove', function(ev) {\r
- if (me.isDragging && Jmol._mouseOwner == me) {\r
- me.mouseMove(ev);\r
- return false;\r
- }\r
- });\r
- container.bind('mouseup touchend', function(ev) {\r
- me.mouseUp(ev);\r
- Jmol._setMouseOwner(null);\r
- });\r
- };\r
-\r
- proto.mouseUp = function(ev) {\r
- if (this.isDragging && Jmol._mouseOwner == this) {\r
- this.pageX0 += (ev.pageX - this.pageX);\r
- this.pageY0 += (ev.pageY - this.pageY);\r
- this.isDragging = false;\r
- return false;\r
- }\r
- Jmol._setMouseOwner(null);\r
- }\r
-\r
- proto.setPosition = function() {\r
- if (Jmol._mousePageX === null) {\r
- var id = this.applet._id + "_" + (this.applet._is2D ? "canvas2d" : "canvas");\r
- var offsets = Jmol.$offset(id);\r
- Jmol._mousePageX = offsets.left;\r
- Jmol._mousePageY = offsets.top;\r
- }\r
- this.pageX0 = Jmol._mousePageX;\r
- this.pageY0 = Jmol._mousePageY;\r
- var pos = { top: Jmol._mousePageY + 'px', left: Jmol._mousePageX + 'px' };\r
- this.container.css(pos);\r
- };\r
-\r
- proto.mouseMove = function(ev) {\r
- if (this.isDragging && Jmol._mouseOwner == this) {\r
- this.timestamp = System.currentTimeMillis(); // used for menu closure\r
- var x = this.pageX0 + (ev.pageX - this.pageX);\r
- var y = this.pageY0 + (ev.pageY - this.pageY);\r
- Jmol._mousePageX = x;\r
- Jmol._mousePageY = y;\r
- this.container.css({ top: y + 'px', left: x + 'px' })\r
- }\r
- };\r
-\r
- proto.dragBind = function(isBind) {\r
- this.applet._ignoreMouse = !isBind;\r
- this.container.unbind('mousemoveoutjsmol');\r
- this.container.unbind('touchmoveoutjsmol');\r
- this.container.unbind('mouseupoutjsmol');\r
- this.container.unbind('touchendoutjsmol');\r
- Jmol._setMouseOwner(null);\r
- if (isBind) {\r
- var me = this;\r
- this.container.bind('mousemoveoutjsmol touchmoveoutjsmol', function(evspecial, target, ev) {\r
- me.mouseMove(ev);\r
- });\r
- this.container.bind('mouseupoutjsmol touchendoutjsmol', function(evspecial, target, ev) {\r
- me.mouseUp(ev);\r
- });\r
- }\r
- };\r
-}\r
-\r
-// Dialog //\r
-\r
-Swing.JSDialog = function () {\r
-}\r
-\r
-Swing.setDraggable(Swing.JSDialog);\r
-\r
-///// calls from javajs and other Java-derived packages /////\r
-\r
-Swing.getScreenDimensions = function(d) {\r
- d.width = $(window).width();\r
- d.height = $(window).height();\r
-}\r
-\r
-Swing.dispose = function(dialog) {\r
- Jmol.$remove(dialog.id + "_mover");\r
- delete Swing.htDialogs[dialog.id]\r
- dialog.container.obj.dragBind(false);\r
-// var btns = $("#" + dialog.id + " *[id^='J']"); // add descendents with id starting with "J"\r
-// for (var i = btns.length; --i >= 0;)\r
-// delete Dialog.htDialogs[btns[i].id]\r
- //System.out.println("JSmolCore.js: dispose " + dialog.id)\r
-}\r
- \r
-Swing.register = function(dialog, type) {\r
- dialog.id = type + (++Swing.count);\r
- Swing.htDialogs[dialog.id] = dialog;\r
- //System.out.println("JSmolCore.js: register " + dialog.id)\r
-\r
-}\r
-\r
-Swing.setDialog = function(dialog) {\r
- Jmol._setMouseOwner(null);\r
- Jmol.$remove(dialog.id);\r
- //System.out.println("removed " + dialog.id)\r
- var id = dialog.id + "_mover";\r
- var container = Jmol._$(id);\r
- var jd;\r
- //System.out.println("JSmolCore.js: setDialog " + dialog.id);\r
- if (container[0]) {\r
- container.html(dialog.html);\r
- jd = container[0].jd;\r
- } else {\r
- Jmol.$after("body","<div id='" + id + "' style='position:absolute;left:0px;top:0px;'>" + dialog.html + "</div>");\r
- var jd = new Swing.JSDialog();\r
- container = Jmol._$(id);\r
- dialog.container = container;\r
- jd.applet = dialog.manager.vwr.html5Applet;\r
- jd.setContainer(container);\r
- jd.dialog = dialog;\r
- jd.setPosition(); \r
- jd.dragBind(true);\r
- container[0].jd = jd; \r
- }\r
- Jmol.$bind("#" + dialog.id + " .JButton", "mousedown touchstart", function(event) { jd.ignoreMouse=true });\r
- Jmol.$bind("#" + dialog.id + " .JComboBox", "mousedown touchstart", function(event) { jd.ignoreMouse=true });\r
- Jmol.$bind("#" + dialog.id + " .JCheckBox", "mousedown touchstart", function(event) { jd.ignoreMouse=true });\r
- Jmol.$bind("#" + dialog.id + " .JTextField", "mousedown touchstart", function(event) { jd.ignoreMouse=true });\r
- Jmol.$bind("#" + dialog.id + " .JTable", "mousedown touchstart", function(event) { jd.ignoreMouse=true });\r
- Jmol.$bind("#" + dialog.id + " .JScrollPane", "mousedown touchstart", function(event) { jd.ignoreMouse=true });\r
- Jmol.$bind("#" + dialog.id + " .JEditorPane", "mousedown touchstart", function(event) { jd.ignoreMouse=true });\r
-\r
-}\r
- \r
-Swing.setSelected = function(chk) {\r
- Jmol.$prop(chk.id, 'checked', !!chk.selected);\r
-}\r
-\r
-Swing.setSelectedIndex = function(cmb) {\r
- Jmol.$prop(cmb.id, 'selectedIndex', cmb.selectedIndex);\r
-}\r
-\r
-Swing.setText = function(btn) {\r
- Jmol.$prop(btn.id, 'value', btn.text);\r
-}\r
-\r
-Swing.setVisible = function(c) {\r
- Jmol.$setVisible(c.id, c.visible);\r
-}\r
-\r
-Swing.setEnabled = function(c) {\r
- Jmol.$setEnabled(c.id, c.enabled);\r
-}\r
-\r
-/// callbacks from the HTML elements ////\r
- \r
-Swing.click = function(element, keyEvent) {\r
- var component = Swing.htDialogs[element.id];\r
- if (component) {\r
- //System.out.println("click " + element + " " + component)\r
- var info = component.toString();\r
- // table cells will have an id but are not registered\r
- if (info.indexOf("JCheck") >= 0) {\r
- component.selected = element.checked;\r
- } else if (info.indexOf("JCombo") >= 0) {\r
- component.selectedIndex = element.selectedIndex;\r
- } else if (component.text != null) { // JButton, JTextField\r
- component.text = element.value;\r
- if (keyEvent && ((keyEvent.charCode || keyEvent.keyCode) != 13))\r
- return;\r
- } \r
- }\r
- var dialog = Swing.htDialogs[Jmol.$getAncestorDiv(element.id, "JDialog").id];\r
- var key = (component ? component.name : dialog.registryKey + "/" + element.id);\r
- //System.out.println("JSmolCore.js: click " + key); \r
- dialog.manager.actionPerformed(key);\r
-}\r
-\r
-Swing.setFront = function(dialog) {\r
- var applet = dialog.manager.vwr.html5Applet;\r
- if (dialog.zIndex != Jmol._getZ(applet, "dialog"))\r
- dialog.zIndex = Jmol._incrZ(applet, "dialog");\r
- dialog.container && ((dialog.container[0] || dialog.container).style.zIndex = dialog.zIndex);\r
-}\r
-\r
-Swing.hideMenus = function(applet) {\r
- // called from LEFT-DOWN mouse event\r
- var menus = applet._menus;\r
- if (menus)\r
- for (var i in menus)\r
- if (menus[i].visible)\r
- Swing.hideMenu(menus[i]);\r
-}\r
-\r
-Swing.windowClosing = function(element) {\r
- var dialog = Swing.htDialogs[Jmol.$getAncestorDiv(element.id, "JDialog").id];\r
- if (dialog.registryKey) {\r
- //System.out.println("JSmolCore.js: windowClosing " + dialog.registryKey); \r
- dialog.manager.processWindowClosing(dialog.registryKey);\r
- } else {\r
- //System.out.println("JSmolCore.js: windowClosing " + dialog.title); \r
- dialog.dispose();\r
- }\r
-}\r
-\r
-})(Jmol.Swing);\r
-\r
-Jmol._track = function(applet) {\r
- // this function inserts an iFrame that can be used to track your page's applet use. \r
- // By default it tracks to a page at St. Olaf College, but you can change that. \r
- // and you can use\r
- //\r
- // delete Jmol._tracker\r
- //\r
- // yourself to not have you page execute this \r
- //\r
- if (Jmol._tracker){\r
- try { \r
- var url = Jmol._tracker + "&applet=" + applet._jmolType + "&version=" + Jmol._version \r
- + "&appver=" + Jmol.___JmolVersion + "&url=" + encodeURIComponent(document.location.href);\r
- var s = '<iframe style="display:none" width="0" height="0" frameborder="0" tabindex="-1" src="' + url + '"></iframe>'\r
- Jmol.$after("body", s);\r
- } catch (e) {\r
- // ignore\r
- }\r
- delete Jmol._tracker;\r
- }\r
- return applet;\r
-}\r
-\r
-Jmol.getProfile = function() {\r
- window["j2s.doProfile"] = true;\r
- if (self.Clazz && self.JSON) {\r
- Clazz._profile || (Clazz._profile = {});\r
- return Clazz.getProfile();\r
- }\r
-}\r
-\r
-Jmol._getInChIKey = function(applet, data) {\r
- if (data.indexOf("MOL=") >= 0)\r
- data = data.split("MOL=")[1].split("\"")[0];\r
-\r
-}\r
-\r
-Jmol._getAttr = function(s, a) {\r
- var pt = s.indexOf(a + "=");\r
- return (pt >= 0 && (pt = s.indexOf('"', pt)) >= 0 \r
- ? s.substring(pt+1, s.indexOf('"', pt+1)) : null);\r
-}\r
-\r
-Jmol.User = {\r
- viewUpdatedCallback: null\r
-}\r
-\r
-Jmol.View = {\r
-\r
-// The objective of Jmol.View is to coordinate\r
-// asynchronous applet loading and atom/peak picking\r
-// among any combination of Jmol, JME, and JSV.\r
-// \r
-// basic element is a view object:\r
-// view = {\r
-// viewType1: viewRecord1,\r
-// viewType2: viewRecord2,\r
-// viewType3: viewRecord3\r
-// }\r
-// where viewType is one of (Jmol, JME, JSV)\r
-// and a viewRecord is an object\r
-// with elements .chemID, .applet, .data, .script\r
-//\r
-// Jmol.View.sets is a list of cached views[0..n]\r
-// for a given group of applet objects with common Info.viewSet\r
-//\r
-// Bob Hanson 1/22/2014 7:05:38 AM\r
-\r
- count: 0,\r
- applets: {},\r
- sets: {}\r
-};\r
-\r
-(function(View) {\r
-\r
-// methods called from other modules have no "_" in their name\r
-\r
-View.updateView = function(applet, Info, _View_updateView) {\r
- // Info.chemID, Info.data, possibly Info.viewID if no chemID\r
- // return from applet after asynchronous download of new data\r
- if (applet._viewSet == null)\r
- return;\r
- Info.chemID || (applet._searchQuery = null);\r
- Info.data || (Info.data = "N/A");\r
- Info.type = applet._viewType;\r
- if((applet._currentView = View.__findView(applet._viewSet, Info)) == null)\r
- applet._currentView = View.__createViewSet(applet._viewSet, Info.chemID, Info.viewID || Info.chemID);\r
- applet._currentView[Info.type].data = Info.data;\r
- applet._currentView[Info.type].smiles = applet._getSmiles();\r
- if (Jmol.User.viewUpdatedCallback)\r
- Jmol.User.viewUpdatedCallback(applet, "updateView");\r
- View.__setView(applet._currentView, applet, false);\r
-}\r
-\r
-View.updateFromSync = function(applet, msg) {\r
- applet._updateMsg = msg;\r
- var id = Jmol._getAttr(msg, "sourceID") || Jmol._getAttr(msg, "file");\r
- if (!id)\r
- return;\r
- var view = View.__findView(applet._viewSet, {viewID:id});\r
- if (view == null)\r
- return Jmol.updateView(applet, msg); // JSV has been updated internally\r
- if (view != applet._currentView)\r
- View.__setView(view, applet, true);\r
- var A = ((id = Jmol._getAttr(msg, "atoms")) && msg.indexOf("selectionhalos ON") >= 0 \r
- ? eval("[" + id + "]") : []);\r
- setTimeout(function(){if (applet._currentView == view)View.updateAtomPick(applet, A)}, 10);\r
- if (Jmol.User.viewUpdatedCallback)\r
- Jmol.User.viewUpdatedCallback(applet, "updateFromSync");\r
-}\r
-\r
-View.updateAtomPick = function(applet, A, _View_updateAtomPick) {\r
- var view = applet._currentView;\r
- if (view == null)\r
- return;\r
- for (var viewType in view) {\r
- if (viewType != "info" && view[viewType].applet != applet)\r
- view[viewType].applet._updateAtomPick(A);\r
- }\r
- if (Jmol.User.viewUpdatedCallback)\r
- Jmol.User.viewUpdatedCallback(applet, "updateAtomPick");\r
-}\r
-\r
-View.dumpViews = function(setID) {\r
- var views = View.sets[setID];\r
- if (!views)\r
- return;\r
- var s = "View set " + setID + ":\n";\r
- var applets = View.applets[setID];\r
- for (var i in applets)\r
- s += "\napplet " + applets[i]._id\r
- + " currentView=" + (applets[i]._currentView ? applets[i]._currentView.info.viewID : null);\r
- for (var i = views.length; --i >= 0;) {\r
- var view = views[i];\r
- s += "\n\n<b>view=" + i \r
- + " viewID=" + view.info.viewID \r
- + " chemID=" + view.info.chemID + "</b>\n"\r
- var v;\r
- for (var viewType in view) \r
- if (viewType != "info")\r
- s += "\nview=" + i + " type=" + viewType + " applet=" \r
- + ((v = view[viewType]).applet ? v.applet._id : null) \r
- + " SMILES=" + v.smiles + "\n"\r
- + " atomMap=" + JSON.stringify(v.atomMap) + "\n"\r
- + " data=\n" + v.data + "\n"\r
- }\r
- return s\r
-}\r
-\r
-\r
-// methods starting with "__" are "private" to JSmolCore.js\r
-\r
-View.__init = function(applet) {\r
- var set = applet._viewSet;\r
- var a = View.applets;\r
- a[set] || (a[set] = {});\r
- a[set][applet._viewType] = applet;\r
-}\r
-\r
-View.__findView = function(set, Info) {\r
- var views = View.sets[set];\r
- if (views == null)\r
- views = View.sets[set] = [];\r
- for (var i = views.length; --i >= 0;) {\r
- var view = views[i];\r
- if (Info.viewID) {\r
- if (view.info.viewID == Info.viewID)\r
- return view;\r
- } else if (Info.chemID != null && Info.chemID == view.info.chemID) {\r
- return view;\r
- } else {\r
- for (var viewType in view) { \r
- if (viewType != "info") {\r
- if (Info.data != null && view[viewType].data != null ? Info.data == view[viewType].data \r
- : Info.type == viewType)\r
- return view;\r
- }\r
- }\r
- }\r
- }\r
- return null; \r
-}\r
-\r
-View.__createViewSet = function(set, chemID, viewID, _createViewSet) {\r
- View.count++;\r
- var view = {info:{chemID: chemID, viewID: viewID || "model_" + View.count}};\r
-\r
- for (var id in Jmol._applets) {\r
- var a = Jmol._applets[id];\r
- if (a._viewSet == set)\r
- view[a._viewType] = {applet:a, data: null};\r
- }\r
- View.sets[set].push(view);\r
- return view;\r
-}\r
-\r
-View.__setView = function(view, applet, isSwitch, _setView) {\r
- // called from Jmol._searchMol and Jmol.View.setCurrentView \r
- // to notify the applets in the set that there may be new data for them\r
- // skip the originating applet itself and cases where the data has not changed.\r
- // stop at first null data, because that will initiate some sort of asynchronous\r
- // call that will be back here afterward.\r
-\r
- for (var viewType in view) {\r
- if (viewType == "info") \r
- continue;\r
- var rec = view[viewType];\r
- var a = rec.applet;\r
- var modified = (isSwitch || a != null && a._molData == "<modified>");\r
-\r
- if (a == null || a == applet && !modified)\r
- continue; // may be a mol3d required by JSV but not having a corresponding applet\r
- var wasNull = (rec.data == null);\r
- var haveView = (a._currentView != null);\r
- a._currentView = view; \r
- if (haveView && view[viewType].data == rec.data && !wasNull & !modified)\r
- continue;\r
- a._loadModelFromView(view);\r
- if (wasNull)\r
- break;\r
- }\r
-\r
- // Either all are taken care of or one was null,\r
- // in which case we have started an asynchronous\r
- // process to get the data, and we can quit here.\r
- // In either case, we are done.\r
-}\r
-\r
-}) (Jmol.View);\r
-\r
-Jmol.Cache = {fileCache: {}};\r
-\r
-Jmol.Cache.get = function(filename) {\r
- return Jmol.Cache.fileCache[filename];\r
-}\r
-\r
-Jmol.Cache.put = function(filename, data) {\r
- Jmol.Cache.fileCache[filename] = data;\r
-}\r
-\r
- Jmol.Cache.setDragDrop = function(me) {\r
- Jmol.$appEvent(me, "appletdiv", "dragover", function(e) {\r
- e = e.originalEvent;\r
- e.stopPropagation();\r
- e.preventDefault();\r
- e.dataTransfer.dropEffect = 'copy';\r
- });\r
- Jmol.$appEvent(me, "appletdiv", "drop", function(e) {\r
- var oe = e.originalEvent;\r
- oe.stopPropagation();\r
- oe.preventDefault();\r
- var file = oe.dataTransfer.files[0];\r
- if (file == null) {\r
- // FF and Chrome will drop an image here\r
- // but it will be only a URL, not an actual file. \r
- try {\r
- file = "" + oe.dataTransfer.getData("text");\r
- if (file.indexOf("file:/") == 0 || file.indexOf("http:/") == 0) {\r
- me._scriptLoad(file);\r
- return;\r
- }\r
- } catch(e) {\r
- return;\r
- }\r
- // some other format\r
- return;\r
- }\r
- // MSIE will drop an image this way, though, and load it!\r
- var reader = new FileReader();\r
- reader.onloadend = function(evt) {\r
- if (evt.target.readyState == FileReader.DONE) {\r
- var cacheName = "cache://DROP_" + file.name;\r
- var bytes = Jmol._toBytes(evt.target.result);\r
- if (!cacheName.endsWith(".spt"))\r
- me._appletPanel.cacheFileByName("cache://DROP_*",false);\r
- if (me._viewType == "JSV" || cacheName.endsWith(".jdx")) // shared by Jmol and JSV\r
- Jmol.Cache.put(cacheName, bytes);\r
- else\r
- me._appletPanel.cachePut(cacheName, bytes);\r
- var xym = Jmol._jsGetXY(me._canvas, e);\r
- if(xym && (!me._appletPanel.setStatusDragDropped || me._appletPanel.setStatusDragDropped(0, xym[0], xym[1], cacheName))) {\r
- me._appletPanel.openFileAsyncSpecial(cacheName, 1);\r
- }\r
- }\r
- };\r
- reader.readAsArrayBuffer(file);\r
- });\r
- }\r
- \r
-})(Jmol, jQuery);\r
+// JSmolCore.js -- Jmol core capability
+
+// allows Jmol applets to be created on a page with more flexibility and extendability
+// provides an object-oriented interface for JSpecView and syncing of Jmol/JSpecView
+
+// see JSmolApi.js for public user-interface. All these are private functions
+
+// BH 5/30/2015 9:33:12 AM adds class swingjs-ui to ignore
+// BH 5/9/2015 3:38:52 PM adds data-ignoreMouse attribute for JTextField
+// BH 3/30/2015 9:46:53 PM adds JSAppletPanel for ready callback
+// BH 12/6/2014 3:32:54 PM Jmol.setAppletCss() broken
+// BH 9/13/2014 2:15:51 PM embedded JSME loads from SEARCH when Jmol should
+// BH 8/14/2014 2:52:38 PM drag-drop cache should not be cleared if SPT file is dropped
+// BH 8/5/2014 6:39:54 AM unnecessary messages about binary for PDB finally removed
+// BH 8/4/2014 5:30:00 AM automatically switch to no document after page loading
+// BH 8/2/2014 5:22:40 PM drag-drop broken in JSmol/HTML5
+// BH 7/23/2014 5:34:08 PM setting a parameter such as readyFunction to null stops file loading
+// BH 7/3/2014 12:30:28 AM lost drag-drop of models
+// BH 7/2/2014 4:47:55 AM adding pdbe.org to direct database calls
+// BH 5/30/2014 7:20:07 AM better dragging for console and menu
+// BH 4/27/2014 6:31:52 PM allows _USE=SIGNED HTML5 as well as _USE=JAVA HTML5
+// BH 3/8/2014 5:50:51 PM adds support for dataURI download in FF and Chrome
+// BH 3/8/2014 8:43:10 AM moves PubChem access to https
+// BH 3/4/2014 8:40:15 PM adds Jmol.Cache for JSV/Jmol sharing files
+// BH 2/10/2014 10:07:14 AM added Info.z and Info.zIndexBase
+// BH 2/9/2014 9:56:06 PM updated JSmolCore.js with option to extend Viewer with code PRIOR to loading Viewer classes
+// BH 2/6/2014 8:46:25 AM disabled Jmol._tracker for localhost and 127.x.x.x
+// BH 1/29/2014 8:02:23 AM Jmol.View and Info.viewSet
+// BH 1/21/2014 12:06:59 PM adding Jmol.Info.cacheFiles (applet, true/false) and applet._cacheFiles and Jmol._fileCache
+// BH 1/13/2014 2:12:38 PM adding "http://www.nmrdb.org/tools/jmol/predict.php":"%URL", to _DirectDatabaseCalls
+// BH 12/21/2013 6:38:35 PM applet sync broken
+// BH 12/6/2013 6:18:32 PM cover.htm and coverImage fix
+// BH 12/4/2013 7:44:26 PM fix for JME independent search box
+// BH 12/3/2013 6:30:08 AM fix for ready function returning Boolean instead of boolean in HTML5 version
+// BH 11/30/2013 10:31:37 AM added type:"GET" for jQuery.ajax() requests instead of using defaults
+// BH 11/30/2013 10:31:37 AM added cache:true for jQuery.ajax() requests; can override with cache:"NO", not cache:false
+// BH 11/28/2013 11:09:27 AM added Jmol._alertNoBinary:true
+// BH 11/26/2013 8:19:55 PM fix !xxxx search commmand entry and stop MSIE from duplicating command
+// BH 11/25/2013 7:38:31 AM adds Jmol._tracker: option for GoogleAnalytics tracking
+// BH 11/25/2013 7:39:03 AM adds URL options _J2S= _JAR= _USE=
+// BH 11/23/2013 10:51:37 PM adds JNLP support for local applet
+// BH 11/2/2013 12:05:11 PM JSmolJSME fixes; https access fixed
+// BH 10/31/2013 7:50:06 PM Jmol.Dialog as SwingController; Jmol._mouseOwner added
+// BH 10/19/2013 7:05:04 AM adding Jmol._ajaxCall for Error Contacting Server; database POST method enabled
+// BH 10/17/2013 1:40:51 PM adding javajs/swing and Jmol.Dialog
+// BH 9/30/2013 6:42:24 PM: pdb.gz switch pdb should only be for www.rcsb.org
+// BH 9/17/2013 10:17:51 AM: asynchronous file reading and saving
+// BH 8/16/2013 12:02:20 PM: JSmoljQueryExt.js pulled out
+// BH 8/16/2013 12:02:20 PM: Jmol._touching used properly
+
+// BH 3/22/2013 5:53:02 PM: Adds noscript option, JSmol.min.core.js
+// BH 1/17/2013 5:20:44 PM: Fixed problem with console not getting initial position if no first click
+// 1/13/2013 BH: Fixed MSIE not-reading-local-files problem.
+// 11/28/2012 BH: Fixed MacOS Safari binary ArrayBuffer problem
+// 11/21/2012 BH: restructuring of files as JS... instead of J...
+// 11/20/2012 BH: MSIE9 cannot do a synchronous file load cross-domain. See Jmol._getFileData
+// 11/4/2012 BH: RCSB REST format change "<structureId>" to "<dimStructure.structureId>"
+// 9/13/2012 BH: JmolCore.js changes for JSmol doAjax() method -- _3ata()
+// 6/12/2012 BH: JmolApi.js: adds Jmol.setInfo(applet, info, isShown) -- third parameter optional
+// 6/12/2012 BH: JmolApi.js: adds Jmol.getInfo(applet)
+// 6/12/2012 BH: JmolApplet.js: Fixes for MSIE 8
+// 6/5/2012 BH: fixes problem with Jmol "javascript" command not working and getPropertyAsArray not working
+// 6/4/2012 BH: corrects problem with MSIE requiring mouse-hover to activate applet
+// 5/31/2012 BH: added JSpecView interface and api -- see JmolJSV.js
+// also changed "jmolJarPath" to just "jarPath"
+// jmolJarFile->jarFile, jmolIsSigned->isSigned, jmolReadyFunction->readyFunction
+// also corrects a double-loading issue
+// 5/14/2012 BH: added AJAX queue for ChemDoodle option with multiple canvases
+// 8/12/2012 BH: adds support for MSIE xdr cross-domain request (jQuery.iecors.js)
+
+ // BH 4/25 -- added text option. setAppletCss(null, "style=\"xxxx\"")
+ // note that since you must add the style keyword, this can be used to add any attribute to these tags, not just css.
+
+// required/optional libraries (preferably in the following order):
+
+// jquery/jquery.js -- at least jQuery.1.9
+// js/JSmoljQueryext.js -- required for binary file transfer; otherwise standard jQuery should be OK
+// js/JSmolCore.js -- required
+// js/j2sjmol.js -- required
+// js/JSmol.js -- required
+// js/JSmolApplet.js -- required; internal functions for _Applet and _Image; must be after JSmolCore
+// js/JSmolControls.js -- optional; internal functions for buttons, links, menus, etc.; must be after JSmolCore
+// js/JSmolConsole.js -- optional; for the pop-up console
+// js/JSmolApi.js -- required; all user functions; must be after JSmolCore
+// js/JSmolTHREE.js -- optional; WebGL library required for JSmolGLmol.js
+// js/JSmolGLmol.js -- optional; WebGL version of JSmol.
+// js/JSmolJME.js -- optional; JSME (2D editor)
+// jsme/jsme/jsme.nocache.js -- required for JSME
+// js/JSmolMenu.js -- optional; required for menuing in JSV
+// js/JSmolJSV.js -- optional; for creating and interacting with a JSpecView applet
+
+// most of these will be loaded automatically, and for most installations, all you need is JSmol.min.js
+
+
+// Allows Jmol-like objects to be displayed on Java-challenged (iPad/iPhone)
+// or applet-challenged (Android/iPhone) platforms, with automatic switching to
+
+// For your installation, you should consider putting JmolData.jar and jsmol.php
+// on your own server. Nothing more than these two files is needed on the server, and this
+// allows more options for MSIE and Chrome when working with cross-domain files (such as RCSB or pubChem)
+
+// The NCI and RCSB databases are accessed via direct AJAX if available (xhr2/xdr).
+
+
+if(typeof(jQuery)=="undefined") alert ("Note -- JSmoljQuery is required for JSmol, but it's not defined.")
+
+// An example of how to extend Jmol with code PRIOR to JSmolCore.js or JSmol.min.js follows:
+//
+//
+// Jmol = {
+// z:3000,
+// extend: function(what, obj) {if (what == "viewer") { obj._testing = true } }
+// }
+
+self.Jmol || (Jmol = {});
+
+if (!Jmol._version)
+Jmol = (function(document) {
+ var z=Jmol.z || 9000;
+ var getZOrders = function(z) {
+ return {
+ rear:z++,
+ header:z++,
+ main:z++,
+ image:z++,
+ front:z++,
+ fileOpener:z++,
+ coverImage:z++,
+ dialog:z++, // could be several of these, JSV only
+ menu:z+90000, // way front
+ console:z+91000, // even more front
+ consoleImage:z+91001, // bit more front; increments
+ monitorZIndex:z+99999 // way way front
+ }
+ };
+ var j = {
+ _version: "$Date: 2015-04-26 10:57:08 -0500 (Sun, 26 Apr 2015) $", // svn.keywords:lastUpdated
+ _alertNoBinary: true,
+ // this url is used to Google Analytics tracking of Jmol use. You may remove it or modify it if you wish.
+ _allowedJmolSize: [25, 2048, 300], // min, max, default (pixels)
+ /* By setting the Jmol.allowedJmolSize[] variable in the webpage
+ before calling Jmol.getApplet(), limits for applet size can be overriden.
+ 2048 standard for GeoWall (http://geowall.geo.lsa.umich.edu/home.html)
+ */
+ _appletCssClass: "",
+ _appletCssText: "",
+ _fileCache: null, // enabled by Jmol.setFileCaching(applet, true/false)
+ _jarFile: null, // can be set in URL using _JAR=
+ _j2sPath: null, // can be set in URL using _J2S=
+ _use: null, // can be set in URL using _USE=
+ _j2sLoadMonitorOpacity: 90, // initial opacity for j2s load monitor message
+ _applets: {},
+ _asynchronous: true,
+ _ajaxQueue: [],
+ _getZOrders: getZOrders,
+ _z:getZOrders(z),
+ _debugCode: true, // set false in process of minimization
+ db: {
+ _databasePrefixes: "$=:",
+ _fileLoadScript: ";if (_loadScript = '' && defaultLoadScript == '' && _filetype == 'Pdb') { select protein or nucleic;cartoons Only;color structure; select * };",
+ _nciLoadScript: ";n = ({molecule=1}.length < {molecule=2}.length ? 2 : 1); select molecule=n;display selected;center selected;",
+ _pubChemLoadScript: "",
+ _DirectDatabaseCalls:{
+ // these sites are known to implement access-control-allow-origin *
+ "cactus.nci.nih.gov": "%URL",
+ "www.rcsb.org": "%URL",
+ "pdbe.org": "%URL",
+ "www.ebi.ac.uk": "%URL",
+ "wwwdev.ebi.ac.uk": "%URL",
+ "pubchem.ncbi.nlm.nih.gov":"%URL",
+ "http://www.nmrdb.org/tools/jmol/predict.php":"%URL",
+ "$": "http://cactus.nci.nih.gov/chemical/structure/%FILENCI/file?format=sdf&get3d=True",
+ "$$": "http://cactus.nci.nih.gov/chemical/structure/%FILENCI/file?format=sdf",
+ "=": "http://www.rcsb.org/pdb/files/%FILE.pdb",
+ "*": "http://www.ebi.ac.uk/pdbe/entry-files/download/%FILE.cif",
+ "==": "http://www.rcsb.org/pdb/files/ligand/%FILE.cif",
+ ":": "http://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/%FILE/SDF?record_type=3d"
+ },
+ _restQueryUrl: "http://www.rcsb.org/pdb/rest/search",
+ _restQueryXml: "<orgPdbQuery><queryType>org.pdb.query.simple.AdvancedKeywordQuery</queryType><description>Text Search</description><keywords>QUERY</keywords></orgPdbQuery>",
+ _restReportUrl: "http://www.pdb.org/pdb/rest/customReport?pdbids=IDLIST&customReportColumns=structureId,structureTitle"
+ },
+ _debugAlert: false,
+ _document: document,
+ _isXHTML: false,
+ _lastAppletID: null,
+ _mousePageX: null,
+ _mouseOwner: null,
+ _serverUrl: "http://your.server.here/jsmol.php",
+ _syncId: ("" + Math.random()).substring(3),
+ _touching: false,
+ _XhtmlElement: null,
+ _XhtmlAppendChild: false
+ }
+
+ var ref = document.location.href.toLowerCase();
+ j._httpProto = (ref.indexOf("https") == 0 ? "https://" : "http://");
+ j._isFile = (ref.indexOf("file:") == 0);
+ j._ajaxTestSite = j._httpProto + "google.com";
+ var isLocal = (j._isFile || ref.indexOf("http://localhost") == 0 || ref.indexOf("http://127.") == 0);
+ j._tracker = (j._httpProto == "http://" && !isLocal && 'http://chemapps.stolaf.edu/jmol/JmolTracker.htm?id=UA-45940799-1');
+
+ j._isChrome = (navigator.userAgent.toLowerCase().indexOf("chrome") >= 0);
+ j._isSafari = (!j._isChrome && navigator.userAgent.toLowerCase().indexOf("safari") >= 0);
+ j._isMsie = (window.ActiveXObject !== undefined);
+ j._useDataURI = !j._isSafari && !j._isMsie; // safari may be OK here -- untested
+
+ for(var i in Jmol) j[i] = Jmol[i]; // allows pre-definition
+ return j;
+})(document, Jmol);
+
+
+(function (Jmol, $) {
+
+// this library is organized into the following sections:
+
+ // jQuery interface
+ // protected variables
+ // feature detection
+ // AJAX-related core functionality
+ // applet start-up functionality
+ // misc core functionality
+ // mouse events
+
+
+ ////////////////////// jQuery interface ///////////////////////
+
+ // hooks to jQuery -- if you have a different AJAX tool, feel free to adapt.
+ // There should be no other references to jQuery in all the JSmol libraries.
+
+ // automatically switch to returning HTML after the page is loaded
+ $(document).ready(function(){ Jmol._document = null });
+
+ Jmol.$ = function(objectOrId, subdiv) {
+ // if a subdiv, then return $("#objectOrId._id_subdiv")
+ // or if no subdiv, then just $(objectOrId)
+ if (objectOrId == null)alert (subdiv + arguments.callee.caller.toString());
+ return $(subdiv ? "#" + objectOrId._id + "_" + subdiv : objectOrId);
+ }
+
+ Jmol._$ = function(id) {
+ // either the object or $("#" + id)
+ return (typeof id == "string" ? $("#" + id) : id);
+ }
+
+ /// special functions:
+
+ Jmol.$ajax = function (info) {
+ Jmol._ajaxCall = info.url;
+ info.cache = (info.cache != "NO");
+ if (info.url.indexOf("http://pubchem.ncbi.nlm.nih") == 0)
+ info.url = "https://" + info.url.substring(7);
+ // fluke at pubchem --- requires https now from all pages 3/8/2014
+ // don't let jQuery add $_=... to URL unless we
+ // use cache:"NO"; other packages might use $.ajaxSetup() to set this to cache:false
+ return $.ajax(info);
+ }
+
+ Jmol._getNCIInfo = function(identifier, what, fCallback) {
+ return Jmol._getFileData("http://cactus.nci.nih.gov/chemical/structure/"+identifier +"/" + (what == "name" ? "names" : what));
+ }
+
+
+
+ Jmol.$appEvent = function(app, subdiv, evt, f) {
+ var o = Jmol.$(app, subdiv);
+ o.off(evt) && f && o.on(evt, f);
+ }
+
+ Jmol.$resize = function (f) {
+ return $(window).resize(f);
+ }
+
+ //// full identifier expected (could be "body", for example):
+
+ Jmol.$after = function (what, s) {
+ return $(what).after(s);
+ }
+
+ Jmol.$append = function (what, s) {
+ return $(what).append(s);
+ }
+
+ Jmol.$bind = function(what, list, f) {
+ return (f ? $(what).bind(list, f) : $(what).unbind(list));
+ }
+
+ Jmol.$closest = function(what, d) {
+ return $(what).closest(d);
+ }
+
+ Jmol.$get = function(what, i) {
+ return $(what).get(i);
+ }
+
+ // element id expected
+
+ Jmol.$documentOff = function(evt, id) {
+ return $(document).off(evt, "#" + id);
+ }
+
+ Jmol.$documentOn = function(evt, id, f) {
+ return $(document).on(evt, "#" + id, f);
+ }
+
+ Jmol.$getAncestorDiv = function(id, className) {
+ return $("div." + className + ":has(#" + id + ")")[0];
+ }
+
+ Jmol.$supportsIECrossDomainScripting = function() {
+ return $.support.iecors;
+ }
+
+ //// element id or jQuery object expected:
+
+ Jmol.$attr = function (id, a, val) {
+ return Jmol._$(id).attr(a, val);
+ }
+
+ Jmol.$css = function(id, style) {
+ return Jmol._$(id).css(style);
+ }
+
+ Jmol.$find = function(id, d) {
+ return Jmol._$(id).find(d);
+ }
+
+ Jmol.$focus = function(id) {
+ return Jmol._$(id).focus();
+ }
+
+ Jmol.$html = function(id, html) {
+ return Jmol._$(id).html(html);
+ }
+
+ Jmol.$offset = function(id) {
+ return Jmol._$(id).offset();
+ }
+
+ Jmol.$windowOn = function(evt, f) {
+ return $(window).on(evt, f);
+ }
+
+ Jmol.$prop = function(id, p, val) {
+ var o = Jmol._$(id);
+ return (arguments.length == 3 ? o.prop(p, val) : o.prop(p));
+ }
+
+ Jmol.$remove = function(id) {
+ return Jmol._$(id).remove();
+ }
+
+ Jmol.$scrollTo = function (id, n) {
+ var o = Jmol._$(id);
+ return o.scrollTop(n < 0 ? o[0].scrollHeight : n);
+ }
+
+ Jmol.$setEnabled = function(id, b) {
+ return Jmol._$(id).attr("disabled", b ? null : "disabled");
+ }
+
+ Jmol.$setSize = function(id, w, h) {
+ return Jmol._$(id).width(w).height(h);
+ }
+
+ Jmol.$setVisible = function(id, b) {
+ var o = Jmol._$(id);
+ return (b ? o.show() : o.hide());
+ }
+
+ Jmol.$submit = function(id) {
+ return Jmol._$(id).submit();
+ }
+
+ Jmol.$val = function (id, v) {
+ var o = Jmol._$(id);
+ return (arguments.length == 1 ? o.val() : o.val(v));
+ }
+
+ ////////////// protected variables ///////////
+
+
+ Jmol._clearVars = function() {
+ // only on page closing -- appears to improve garbage collection
+
+ delete jQuery;
+ delete $;
+ delete Jmol;
+ delete SwingController;
+ delete J;
+ delete JM;
+ delete JS;
+ delete JSV;
+ delete JU;
+ delete JV;
+ delete java;
+ delete javajs;
+ delete Clazz;
+ delete c$; // used in p0p; could be gotten rid of
+ }
+
+ ////////////// feature detection ///////////////
+
+ Jmol.featureDetection = (function(document, window) {
+
+ var features = {};
+ features.ua = navigator.userAgent.toLowerCase()
+
+ features.os = (function(){
+ var osList = ["linux","unix","mac","win"]
+ var i = osList.length;
+
+ while (i--){
+ if (features.ua.indexOf(osList[i])!=-1) return osList[i]
+ }
+ return "unknown";
+ })();
+
+ features.browser = function(){
+ var ua = features.ua;
+ var browserList = ["konqueror","webkit","omniweb","opera","webtv","icab","msie","mozilla"];
+ for (var i = 0; i < browserList.length; i++)
+ if (ua.indexOf(browserList[i])>=0)
+ return browserList[i];
+ return "unknown";
+ }
+ features.browserName = features.browser();
+ features.browserVersion= parseFloat(features.ua.substring(features.ua.indexOf(features.browserName)+features.browserName.length+1));
+ features.supportsXhr2 = function() {return ($.support.cors || $.support.iecors)}
+ features.allowDestroy = (features.browserName != "msie");
+ features.allowHTML5 = (features.browserName != "msie" || navigator.appVersion.indexOf("MSIE 8") < 0);
+ features.getDefaultLanguage = function() {
+ return navigator.language || navigator.userLanguage || "en-US";
+ };
+
+ features._webGLtest = 0;
+
+ features.supportsWebGL = function() {
+ if (!Jmol.featureDetection._webGLtest) {
+ var canvas;
+ Jmol.featureDetection._webGLtest = (
+ window.WebGLRenderingContext
+ && ((canvas = document.createElement("canvas")).getContext("webgl")
+ || canvas.getContext("experimental-webgl")) ? 1 : -1);
+ }
+ return (Jmol.featureDetection._webGLtest > 0);
+ };
+
+ features.supportsLocalization = function() {
+ //<meta charset="utf-8">
+ var metas = document.getElementsByTagName('meta');
+ for (var i= metas.length; --i >= 0;)
+ if (metas[i].outerHTML.toLowerCase().indexOf("utf-8") >= 0) return true;
+ return false;
+ };
+
+ features.supportsJava = function() {
+ if (!Jmol.featureDetection._javaEnabled) {
+ if (Jmol._isMsie) {
+ if (!navigator.javaEnabled()) {
+ Jmol.featureDetection._javaEnabled = -1;
+ } else {
+ //more likely -- would take huge testing
+ Jmol.featureDetection._javaEnabled = 1;
+ }
+ } else {
+ Jmol.featureDetection._javaEnabled = (navigator.javaEnabled() && (!navigator.mimeTypes || navigator.mimeTypes["application/x-java-applet"]) ? 1 : -1);
+ }
+ }
+ return (Jmol.featureDetection._javaEnabled > 0);
+ };
+
+ features.compliantBrowser = function() {
+ var a = !!document.getElementById;
+ var os = features.os;
+ // known exceptions (old browsers):
+ if (features.browserName == "opera" && features.browserVersion <= 7.54 && os == "mac"
+ || features.browserName == "webkit" && features.browserVersion < 125.12
+ || features.browserName == "msie" && os == "mac"
+ || features.browserName == "konqueror" && features.browserVersion <= 3.3
+ ) a = false;
+ return a;
+ }
+
+ features.isFullyCompliant = function() {
+ return features.compliantBrowser() && features.supportsJava();
+ }
+
+ features.useIEObject = (features.os == "win" && features.browserName == "msie" && features.browserVersion >= 5.5);
+ features.useHtml4Object = (features.browserName == "mozilla" && features.browserVersion >= 5) ||
+ (features.browserName == "opera" && features.browserVersion >= 8) ||
+ (features.browserName == "webkit"/* && features.browserVersion >= 412.2 && features.browserVersion < 500*/); // 500 is a guess; required for 536.3
+
+ features.hasFileReader = (window.File && window.FileReader);
+
+ return features;
+
+})(document, window);
+
+
+ ////////////// AJAX-related core functionality //////////////
+
+ Jmol._ajax = function(info) {
+ if (!info.async) {
+ return Jmol.$ajax(info).responseText;
+ }
+ Jmol._ajaxQueue.push(info)
+ if (Jmol._ajaxQueue.length == 1)
+ Jmol._ajaxDone()
+ }
+ Jmol._ajaxDone = function() {
+ var info = Jmol._ajaxQueue.shift();
+ info && Jmol.$ajax(info);
+ }
+
+ Jmol._grabberOptions = [
+ ["$", "NCI(small molecules)"],
+ [":", "PubChem(small molecules)"],
+ ["=", "RCSB(macromolecules)"],
+ ["*", "PDBe(macromolecules)"]
+ ];
+
+ Jmol._getGrabberOptions = function(applet) {
+ // feel free to adjust this look to anything you want
+ if (Jmol._grabberOptions.length == 0)
+ return ""
+
+
+ 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="" />';
+ var b = '<button id="ID_submit" onclick="Jmol._applets[\'ID\']._search()">Search</button></nobr>'
+ if (Jmol._grabberOptions.length == 1) {
+ s = '<nobr>' + s + '<span style="display:none">';
+ b = '</span>' + b;
+ } else {
+ s += '<br /><nobr>'
+ }
+ s += '<select id="ID_select">'
+ for (var i = 0; i < Jmol._grabberOptions.length; i++) {
+ var opt = Jmol._grabberOptions[i];
+ s += '<option value="' + opt[0] + '" ' + (i == 0 ? 'selected' : '') + '>' + opt[1] + '</option>';
+ }
+ s = (s + '</select>' + b).replace(/ID/g, applet._id);
+ return '<br />' + s;
+ }
+
+ Jmol._getScriptForDatabase = function(database) {
+ return (database == "$" ? Jmol.db._nciLoadScript : database == ":" ? Jmol.db._pubChemLoadScript : Jmol.db._fileLoadScript);
+ }
+
+ // <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>
+
+ Jmol._setInfo = function(applet, database, data) {
+ var info = [];
+ var header = "";
+ if (data.indexOf("ERROR") == 0)
+ header = data;
+ else
+ switch (database) {
+ case "=":
+ var S = data.split("<dimStructure.structureId>");
+ var info = ["<table>"];
+ for (var i = 1; i < S.length; i++) {
+ 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>");
+ info.push("<td>" + S[i].split("Title>")[1].split("</")[0] + "</td></tr>");
+ }
+ info.push("</table>");
+ header = (S.length - 1) + " matches";
+ break;
+ case "$": // NCI
+ case ":": // pubChem
+ break;
+ default:
+ return;
+ }
+ applet._infoHeader = header;
+ applet._info = info.join("");
+ applet._showInfo(true);
+ }
+
+ Jmol._loadSuccess = function(a, fSuccess) {
+ if (!fSuccess)
+ return;
+ Jmol._ajaxDone();
+ fSuccess(a);
+ }
+
+ Jmol._loadError = function(fError){
+ Jmol._ajaxDone();
+ Jmol.say("Error connecting to server: " + Jmol._ajaxCall);
+ null!=fError&&fError()
+ }
+
+ Jmol._isDatabaseCall = function(query) {
+ return (Jmol.db._databasePrefixes.indexOf(query.substring(0, 1)) >= 0);
+ }
+
+
+ Jmol._getDirectDatabaseCall = function(query, checkXhr2) {
+ if (checkXhr2 && !Jmol.featureDetection.supportsXhr2())
+ return query;
+ var pt = 2;
+ var db;
+ var call = Jmol.db._DirectDatabaseCalls[query.substring(0,pt)];
+ if (!call)
+ call = Jmol.db._DirectDatabaseCalls[db = query.substring(0,--pt)];
+ if (call) {
+ if (db == ":") {
+ var ql = query.toLowerCase();
+ if (!isNaN(parseInt(query.substring(1)))) {
+ query = "cid/" + query.substring(1);
+ } else if (ql.indexOf(":smiles:") == 0) {
+ call += "?POST?smiles=" + query.substring(8);
+ query = "smiles";
+ } else if (ql.indexOf(":cid:") == 0) {
+ query = "cid/" + query.substring(5);
+ } else {
+ if (ql.indexOf(":name:") == 0)
+ query = query.substring(5);
+ else if (ql.indexOf(":cas:") == 0)
+ query = query.substring(4);
+ query = "name/" + encodeURIComponent(query.substring(pt));
+ }
+ } else {
+ query = encodeURIComponent(query.substring(pt));
+ }
+ if (call.indexOf("FILENCI") >= 0) {
+ query = query.replace(/\%2F/g, "/");
+ query = call.replace(/\%FILENCI/, query);
+ } else {
+ query = call.replace(/\%FILE/, query);
+ }
+ }
+ return query;
+ }
+
+ Jmol._getRawDataFromServer = function(database,query,fSuccess,fError,asBase64,noScript){
+ // note that this method is now only enabled for "_"
+ // server-side processing of database queries was too slow and only useful for
+ // the IMAGE option, which has been abandoned.
+ var s =
+ "?call=getRawDataFromDatabase&database=" + database + (query.indexOf("?POST?") >= 0 ? "?POST?" : "")
+ + "&query=" + encodeURIComponent(query)
+ + (asBase64 ? "&encoding=base64" : "")
+ + (noScript ? "" : "&script=" + encodeURIComponent(Jmol._getScriptForDatabase(database)));
+ return Jmol._contactServer(s, fSuccess, fError);
+ }
+
+ Jmol._checkFileName = function(applet, fileName, isRawRet) {
+ if (Jmol._isDatabaseCall(fileName)) {
+ if (isRawRet)
+ Jmol._setQueryTerm(applet, fileName);
+ fileName = Jmol._getDirectDatabaseCall(fileName, true);
+ if (Jmol._isDatabaseCall(fileName)) {
+ // xhr2 not supported (MSIE)
+ fileName = Jmol._getDirectDatabaseCall(fileName, false);
+ isRawRet && (isRawRet[0] = true);
+ }
+ }
+ return fileName;
+ }
+
+ Jmol._checkCache = function(applet, fileName, fSuccess) {
+ if (applet._cacheFiles && Jmol._fileCache && !fileName.endsWith(".js")) {
+ var data = Jmol._fileCache[fileName];
+ if (data) {
+ System.out.println("using " + data.length + " bytes of cached data for " + fileName);
+ fSuccess(data);
+ return null;
+ } else {
+ fSuccess = function(fileName, data) { fSuccess(Jmol._fileCache[fileName] = data) };
+ }
+ }
+ return fSuccess;
+ }
+
+ Jmol._loadFileData = function(applet, fileName, fSuccess, fError){
+ var isRaw = [];
+ fileName = Jmol._checkFileName(applet, fileName, isRaw);
+ fSuccess = Jmol._checkCache(applet, fileName, fSuccess);
+ if (isRaw[0]) {
+ Jmol._getRawDataFromServer("_",fileName,fSuccess,fError);
+ return;
+ }
+ var info = {
+ type: "GET",
+ dataType: "text",
+ url: fileName,
+ async: Jmol._asynchronous,
+ success: function(a) {Jmol._loadSuccess(a, fSuccess)},
+ error: function() {Jmol._loadError(fError)}
+ }
+ Jmol._checkAjaxPost(info);
+ Jmol._ajax(info);
+ }
+
+ Jmol._getInfoFromDatabase = function(applet, database, query){
+ if (database == "====") {
+ var data = Jmol.db._restQueryXml.replace(/QUERY/,query);
+
+ var info = {
+ dataType: "text",
+ type: "POST",
+ contentType:"application/x-www-form-urlencoded",
+ url: Jmol.db._restQueryUrl,
+ data: encodeURIComponent(data) + "&req=browser",
+ success: function(data) {Jmol._ajaxDone();Jmol._extractInfoFromRCSB(applet, database, query, data)},
+ error: function() {Jmol._loadError(null)},
+ async: Jmol._asynchronous
+ }
+ return Jmol._ajax(info);
+ }
+ query = "?call=getInfoFromDatabase&database=" + database
+ + "&query=" + encodeURIComponent(query);
+ return Jmol._contactServer(query, function(data) {Jmol._setInfo(applet, database, data)});
+ }
+
+ Jmol._extractInfoFromRCSB = function(applet, database, query, output) {
+ var n = output.length/5;
+ if (n == 0)
+ return;
+ if (query.length == 4 && n != 1) {
+ var QQQQ = query.toUpperCase();
+ var pt = output.indexOf(QQQQ);
+ if (pt > 0 && "123456789".indexOf(QQQQ.substring(0, 1)) >= 0)
+ output = QQQQ + "," + output.substring(0, pt) + output.substring(pt + 5);
+ if (n > 50)
+ output = output.substring(0, 250);
+ output = output.replace(/\n/g,",");
+ var url = Jmol._restReportUrl.replace(/IDLIST/,output);
+ Jmol._loadFileData(applet, url, function(data) {Jmol._setInfo(applet, database, data) });
+ }
+ }
+
+ Jmol._checkAjaxPost = function(info) {
+ var pt = info.url.indexOf("?POST?");
+ if (pt > 0) {
+ info.data = info.url.substring(pt + 6);
+ info.url = info.url.substring(0, pt);
+ info.type = "POST";
+ info.contentType = "application/x-www-form-urlencoded";
+ }
+ }
+ Jmol._contactServer = function(data,fSuccess,fError){
+ var info = {
+ dataType: "text",
+ type: "GET",
+ url: Jmol._serverUrl + data,
+ success: function(a) {Jmol._loadSuccess(a, fSuccess)},
+ error:function() { Jmol._loadError(fError) },
+ async:fSuccess ? Jmol._asynchronous : false
+ }
+ Jmol._checkAjaxPost(info);
+ return Jmol._ajax(info);
+ }
+
+ Jmol._setQueryTerm = function(applet, query) {
+ if (!query || !applet._hasOptions || query.substring(0, 7) == "http://")
+ return;
+ if (Jmol._isDatabaseCall(query)) {
+ var database = query.substring(0, 1);
+ query = query.substring(1);
+ if (query.substring(0,1) == database && "=$".indexOf(database) >= 0)
+ query = query.substring(1);
+ var d = Jmol._getElement(applet, "select");
+ if (d && d.options)
+ for (var i = 0; i < d.options.length; i++)
+ if (d[i].value == database)
+ d[i].selected = true;
+ }
+ Jmol.$val(Jmol.$(applet, "query"), query);
+ }
+
+ Jmol._search = function(applet, query, script) {
+ arguments.length > 1 || (query = null);
+ Jmol._setQueryTerm(applet, query);
+ query || (query = Jmol.$val(Jmol.$(applet, "query")))
+ if (query.indexOf("!") == 0) {
+ // command prompt in this box as well
+ // remove exclamation point "immediate" indicator
+ applet._script(query.substring(1));
+ return;
+ }
+ query && (query = query.replace(/\"/g, ""));
+ applet._showInfo(false);
+ Jmol._searchMol(applet, query, script, true);
+ }
+
+ Jmol._searchMol = function(applet, query, script, checkView) {
+ var database;
+ if (Jmol._isDatabaseCall(query)) {
+ database = query.substring(0, 1);
+ query = query.substring(1);
+ } else {
+ database = (applet._hasOptions ? Jmol.$val(Jmol.$(applet, "select")) : "$");
+ }
+ if (database == "=" && query.length == 3)
+ query = "=" + query; // this is a ligand
+ var dm = database + query;
+ if (!query || dm.indexOf("?") < 0 && dm == applet._thisJmolModel) {
+ return;
+ }
+ applet._thisJmolModel = dm;
+ var view;
+ if (checkView && applet._viewSet != null && (view = Jmol.View.__findView(applet._viewSet, {chemID:dm})) != null) {
+ Jmol.View.__setView(view, applet, false);
+ return;
+ }
+
+ if (database == "$" || database == ":")
+ applet._jmolFileType = "MOL";
+ else if (database == "=")
+ applet._jmolFileType = "PDB";
+ applet._searchDatabase(query, database, script);
+ }
+
+ Jmol._searchDatabase = function(applet, query, database, script) {
+ applet._showInfo(false);
+ if (query.indexOf("?") >= 0) {
+ Jmol._getInfoFromDatabase(applet, database, query.split("?")[0]);
+ return true;
+ }
+ if (Jmol.db._DirectDatabaseCalls[database]) {
+ applet._loadFile(database + query, script);
+ return true;
+ }
+ return false;
+ }
+
+ Jmol._syncBinaryOK="?";
+
+ Jmol._canSyncBinary = function(isSilent) {
+ if (Jmol._isAsync) return true;
+ if (self.VBArray) return (Jmol._syncBinaryOK = false);
+ if (Jmol._syncBinaryOK != "?") return Jmol._syncBinaryOK;
+ Jmol._syncBinaryOK = true;
+ try {
+ var xhr = new window.XMLHttpRequest();
+ xhr.open( "text", Jmol._ajaxTestSite, false );
+ if (xhr.hasOwnProperty("responseType")) {
+ xhr.responseType = "arraybuffer";
+ } else if (xhr.overrideMimeType) {
+ xhr.overrideMimeType('text/plain; charset=x-user-defined');
+ }
+ } catch( e ) {
+ var s = "JSmolCore.js: synchronous binary file transfer is requested but not available";
+ System.out.println(s);
+ if (Jmol._alertNoBinary && !isSilent)
+ alert (s)
+ return Jmol._syncBinaryOK = false;
+ }
+ return true;
+ }
+
+ Jmol._binaryTypes = [".gz",".jpg",".gif",".png",".zip",".jmol",".bin",".smol",".spartan",".mrc",".pse", ".map", ".omap"];
+
+ Jmol._isBinaryUrl = function(url) {
+ for (var i = Jmol._binaryTypes.length; --i >= 0;)
+ if (url.indexOf(Jmol._binaryTypes[i]) >= 0) return true;
+ return false;
+ }
+
+ Jmol._getFileData = function(fileName, fSuccess, doProcess) {
+ // use host-server PHP relay if not from this host
+ var isBinary = Jmol._isBinaryUrl(fileName);
+ var isPDB = (fileName.indexOf("pdb.gz") >= 0 && fileName.indexOf("http://www.rcsb.org/pdb/files/") == 0);
+ var asBase64 = (isBinary && !Jmol._canSyncBinary(isPDB));
+ if (asBase64 && isPDB) {
+ // avoid unnecessary binary transfer
+ fileName = fileName.replace(/pdb\.gz/,"pdb");
+ asBase64 = isBinary = false;
+ }
+ var isPost = (fileName.indexOf("?POST?") >= 0);
+ if (fileName.indexOf("file:/") == 0 && fileName.indexOf("file:///") != 0)
+ fileName = "file://" + fileName.substring(5); /// fixes IE problem
+ var isMyHost = (fileName.indexOf("://") < 0 || fileName.indexOf(document.location.protocol) == 0 && fileName.indexOf(document.location.host) >= 0);
+ var isDirectCall = Jmol._isDirectCall(fileName);
+ //if (fileName.indexOf("http://pubchem.ncbi.nlm.nih.gov/") == 0)isDirectCall = false;
+
+ var cantDoSynchronousLoad = (!isMyHost && Jmol.$supportsIECrossDomainScripting());
+ var data = null;
+ if ((!fSuccess || asBase64) && (cantDoSynchronousLoad || asBase64 || !isMyHost && !isDirectCall)) {
+ data = Jmol._getRawDataFromServer("_",fileName, fSuccess, fSuccess, asBase64, true);
+ } else {
+ fileName = fileName.replace(/file:\/\/\/\//, "file://"); // opera
+ var info = {dataType:(isBinary ? "binary" : "text"),async:!!fSuccess};
+ if (isPost) {
+ info.type = "POST";
+ info.url = fileName.split("?POST?")[0]
+ info.data = fileName.split("?POST?")[1]
+ } else {
+ info.type = "GET";
+ info.url = fileName;
+ }
+ if (fSuccess) {
+ info.success = function(data) { fSuccess(Jmol._xhrReturn(info.xhr))};
+ info.error = function() { fSuccess(info.xhr.statusText)};
+ }
+ info.xhr = Jmol.$ajax(info);
+ if (!fSuccess) {
+ data = Jmol._xhrReturn(info.xhr);
+ }
+ }
+ if (!doProcess)
+ return data;
+ if (data == null) {
+ data = "";
+ isBinary = false;
+ }
+ isBinary && (isBinary = Jmol._canSyncBinary(true));
+ return (isBinary ? Jmol._strToBytes(data) : JU.SB.newS(data));
+ }
+
+ Jmol._xhrReturn = function(xhr){
+ if (!xhr.responseText || self.Clazz && Clazz.instanceOf(xhr.response, self.ArrayBuffer)) {
+ // Safari or error
+ return xhr.response || xhr.statusText;
+ }
+ return xhr.responseText;
+ }
+
+ Jmol._isDirectCall = function(url) {
+ for (var key in Jmol.db._DirectDatabaseCalls) {
+ if (key.indexOf(".") >= 0 && url.indexOf(key) >= 0)
+ return true;
+ }
+ return false;
+ }
+
+ Jmol._cleanFileData = function(data) {
+ if (data.indexOf("\r") >= 0 && data.indexOf("\n") >= 0) {
+ return data.replace(/\r\n/g,"\n");
+ }
+ if (data.indexOf("\r") >= 0) {
+ return data.replace(/\r/g,"\n");
+ }
+ return data;
+ };
+
+ Jmol._getFileType = function(name) {
+ var database = name.substring(0, 1);
+ if (database == "$" || database == ":")
+ return "MOL";
+ if (database == "=")
+ return (name.substring(1,2) == "=" ? "LCIF" : "PDB");
+ // just the extension, which must be PDB, XYZ..., CIF, or MOL
+ name = name.split('.').pop().toUpperCase();
+ return name.substring(0, Math.min(name.length, 3));
+ };
+
+ Jmol._getZ = function(applet, what) {
+ return applet && applet._z && applet._z[what] || Jmol._z[what];
+ }
+
+ Jmol._incrZ = function(applet, what) {
+ return applet && applet._z && ++applet._z[what] || ++Jmol._z[what];
+ }
+
+ Jmol._loadFileAsynchronously = function(fileLoadThread, applet, fileName, appData) {
+ if (fileName.indexOf("?") != 0) {
+ // LOAD ASYNC command
+ var fileName0 = fileName;
+ fileName = Jmol._checkFileName(applet, fileName);
+ var fSuccess = function(data) {Jmol._setData(fileLoadThread, fileName, fileName0, data, appData)};
+ fSuccess = Jmol._checkCache(applet, fileName, fSuccess);
+ if (fileName.indexOf("|") >= 0)
+ fileName = fileName.split("|")[0];
+ return (fSuccess == null ? null : Jmol._getFileData(fileName, fSuccess));
+ }
+ // we actually cannot suggest a fileName, I believe.
+ if (!Jmol.featureDetection.hasFileReader)
+ return fileLoadThread.setData("Local file reading is not enabled in your browser", null, null, appData);
+ if (!applet._localReader) {
+ 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>'
+ Jmol.$after("#" + applet._id + "_appletdiv", div.replace(/ID/g, applet._id + "_localReader"));
+ applet._localReader = Jmol.$(applet, "localReader");
+ }
+ Jmol.$appEvent(applet, "localReader_loadfile", "click");
+ Jmol.$appEvent(applet, "localReader_loadfile", "click", function(evt) {
+ var file = Jmol.$(applet, "localReader_files")[0].files[0];
+ var reader = new FileReader();
+ reader.onloadend = function(evt) {
+ if (evt.target.readyState == FileReader.DONE) { // DONE == 2
+ Jmol.$css(Jmol.$(applet, "localReader"), {display : "none"});
+ Jmol._setData(fileLoadThread, file.name, file.name, evt.target.result, appData);
+ }
+ };
+ reader.readAsArrayBuffer(file);
+ });
+ Jmol.$appEvent(applet, "localReader_cancel", "click");
+ Jmol.$appEvent(applet, "localReader_cancel", "click", function(evt) {
+ Jmol.$css(Jmol.$(applet, "localReader"), {display: "none"});
+ fileLoadThread.setData(null, null, null, appData);
+ });
+ Jmol.$css(Jmol.$(applet, "localReader"), {display : "block"});
+ }
+
+ Jmol._setData = function(fileLoadThread, filename, filename0, data, appData) {
+ data = Jmol._strToBytes(data);
+ if (filename.indexOf(".jdx") >= 0)
+ Jmol.Cache.put("cache://" + filename, data);
+ fileLoadThread.setData(filename, filename0, data, appData);
+ }
+
+ Jmol._toBytes = function(data) {
+ if (typeof data == "string")
+ return data.getBytes();
+ // ArrayBuffer assumed here
+ data = new Uint8Array(data);
+ var b = Clazz.newByteArray(data.length, 0);
+ for (var i = data.length; --i >= 0;)
+ b[i] = data[i];
+ return b;
+ }
+
+ Jmol._doAjax = function(url, postOut, dataOut) {
+ // called by org.jmol.awtjs2d.JmolURLConnection.doAjax()
+ url = url.toString();
+
+ if (dataOut != null)
+ return Jmol._saveFile(url, dataOut);
+ if (postOut)
+ url += "?POST?" + postOut;
+ return Jmol._getFileData(url, null, true);
+ }
+
+ // Jmol._localFileSaveFunction -- // do something local here; Maybe try the FileSave interface? return true if successful
+
+ Jmol._saveFile = function(filename, data, mimetype, encoding) {
+ if (Jmol._localFileSaveFunction && Jmol._localFileSaveFunction(filename, data))
+ return "OK";
+ var filename = filename.substring(filename.lastIndexOf("/") + 1);
+ mimetype || (mimetype = (filename.indexOf(".pdf") >= 0 ? "application/pdf"
+ : filename.indexOf(".png") >= 0 ? "image/png"
+ : filename.indexOf(".gif") >= 0 ? "image/gif"
+ : filename.indexOf(".jpg") >= 0 ? "image/jpg" : ""));
+ var isString = (typeof data == "string");
+ if (!isString)
+ data = (JU ? JU : J.util).Base64.getBase64(data).toString();
+ encoding || (encoding = (isString ? "" : "base64"));
+ var url = Jmol._serverUrl;
+ url && url.indexOf("your.server") >= 0 && (url = "");
+ if (Jmol._useDataURI || !url) {
+ // Asynchronous output generated using an anchor tag
+ encoding || (data = btoa(data));
+ var a = document.createElement("a");
+ a.href = "data:" + mimetype + ";base64," + data;
+ a.type = mimetype || (mimetype = "text/plain");
+ a.download = filename;
+ a.target = "_blank";
+ $("body").append(a);
+ a.click();
+ a.remove();
+ } else {
+ // Asynchronous outputto be reflected as a download
+ if (!Jmol._formdiv) {
+ var sform = '<div id="__jsmolformdiv__" style="display:none">\
+ <form id="__jsmolform__" method="post" target="_blank" action="">\
+ <input name="call" value="saveFile"/>\
+ <input id="__jsmolmimetype__" name="mimetype" value=""/>\
+ <input id="__jsmolencoding__" name="encoding" value=""/>\
+ <input id="__jsmolfilename__" name="filename" value=""/>\
+ <textarea id="__jsmoldata__" name="data"></textarea>\
+ </form>\
+ </div>'
+ Jmol.$after("body", sform);
+ Jmol._formdiv = "__jsmolform__";
+ }
+ Jmol.$attr(Jmol._formdiv, "action", url + "?" + (new Date()).getMilliseconds());
+ Jmol.$val("__jsmoldata__", data);
+ Jmol.$val("__jsmolfilename__", filename);
+ Jmol.$val("__jsmolmimetype__", mimetype);
+ Jmol.$val("__jsmolencoding__", encoding);
+ Jmol.$submit("__jsmolform__");
+ Jmol.$val("__jsmoldata__", "");
+ Jmol.$val("__jsmolfilename__", "");
+ }
+ return "OK";
+ }
+
+ Jmol._strToBytes = function(s) {
+ if (Clazz.instanceOf(s, self.ArrayBuffer))
+ return Jmol._toBytes(s);
+ var b = Clazz.newByteArray(s.length, 0);
+ for (var i = s.length; --i >= 0;)
+ b[i] = s.charCodeAt(i) & 0xFF;
+ return b;
+ }
+
+ ////////////// applet start-up functionality //////////////
+
+ Jmol._setConsoleDiv = function (d) {
+ if (!self.Clazz)return;
+ Clazz.setConsoleDiv(d);
+ }
+
+ Jmol._registerApplet = function(id, applet) {
+ return window[id] = Jmol._applets[id] = Jmol._applets[applet] = Jmol._applets[id + "__" + Jmol._syncId + "__"] = applet;
+ }
+
+ Jmol._readyCallback = function (appId,fullId,isReady,javaApplet,javaAppletPanel) {
+ appId = appId.split("_object")[0];
+ javaAppletPanel || (javaAppletPanel = javaApplet);
+ isReady = (isReady.booleanValue ? isReady.booleanValue() : isReady);
+ // necessary for MSIE in strict mode -- apparently, we can't call
+ // jmol._readyCallback, but we can call Jmol._readyCallback. Go figure...
+ var applet = Jmol._applets[appId];
+ applet._appletPanel = javaAppletPanel;
+ applet._applet = javaApplet;
+ Jmol._track(applet._readyCallback(appId, fullId, isReady));
+ }
+
+ Jmol._getWrapper = function(applet, isHeader) {
+
+ // id_appletinfotablediv
+ // id_appletdiv
+ // id_coverdiv
+ // id_infotablediv
+ // id_infoheaderdiv
+ // id_infoheaderspan
+ // id_infocheckboxspan
+ // id_infodiv
+
+
+ // for whatever reason, without DOCTYPE, with MSIE, "height:auto" does not work,
+ // and the text scrolls off the page.
+ // So I'm using height:95% here.
+ // The table was a fix for MSIE with no DOCTYPE tag to fix the miscalculation
+ // in height of the div when using 95% for height.
+ // But it turns out the table has problems with DOCTYPE tags, so that's out.
+ // The 95% is a compromise that we need until the no-DOCTYPE MSIE solution is found.
+ // (100% does not work with the JME linked applet)
+ var s;
+ // ... here are just for clarification in this code; they are removed immediately
+ if (isHeader) {
+ var img = "";
+ if (applet._coverImage){
+ var more = " onclick=\"Jmol.coverApplet(ID, false)\" title=\"" + (applet._coverTitle) + "\"";
+ 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;"
+ + "z-index:" + Jmol._getZ(applet, "coverImage")+";opacity:0.5;\"" + more + " />"
+ 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=\""
+ + applet._coverImage + "\" style=\"width:100%;height:100%\"" + more + "/>" + play + "</div>";
+ }
+ var css = Jmol._appletCssText.replace(/\'/g,'"');
+ css = (css.indexOf("style=\"") >= 0 ? css.split("style=\"")[1] : "\" " + css);
+ s = "\
+...<div id=\"ID_appletinfotablediv\" style=\"width:Wpx;height:Hpx;position:relative;font-size:14px;text-align:left\">IMG\
+......<div id=\"ID_appletdiv\" style=\"z-index:" + Jmol._getZ(applet, "header") + ";width:100%;height:100%;position:absolute;top:0px;left:0px;" + css + ">";
+ var height = applet._height;
+ var width = applet._width;
+ if (typeof height !== "string" || height.indexOf("%") < 0)
+ height += "px";
+ if (typeof width !== "string" || width.indexOf("%") < 0)
+ width += "px";
+ s = s.replace(/IMG/, img).replace(/Hpx/g, height).replace(/Wpx/g, width);
+ } else {
+ s = "\
+......</div>\
+......<div id=\"ID_2dappletdiv\" style=\"position:absolute;width:100%;height:100%;overflow:hidden;display:none\"></div>\
+......<div id=\"ID_infotablediv\" style=\"width:100%;height:100%;position:absolute;top:0px;left:0px\">\
+.........<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>\
+.........<div id=\"ID_infodiv\" style=\"position:absolute;top:20px;bottom:0px;width:100%;height:100%;overflow:auto\"></div>\
+......</div>\
+...</div>";
+ }
+ return s.replace(/\.\.\./g,"").replace(/[\n\r]/g,"").replace(/ID/g, applet._id);
+ }
+
+ Jmol._documentWrite = function(text) {
+ if (Jmol._document) {
+ if (Jmol._isXHTML && !Jmol._XhtmlElement) {
+ var s = document.getElementsByTagName("script");
+ Jmol._XhtmlElement = s.item(s.length - 1);
+ Jmol._XhtmlAppendChild = false;
+ }
+ if (Jmol._XhtmlElement)
+ Jmol._domWrite(text);
+ else
+ Jmol._document.write(text);
+ }
+ return text;
+ }
+
+ Jmol._domWrite = function(data) {
+ var pt = 0
+ var Ptr = []
+ Ptr[0] = 0
+ while (Ptr[0] < data.length) {
+ var child = Jmol._getDomElement(data, Ptr);
+ if (!child)
+ break;
+ if (Jmol._XhtmlAppendChild)
+ Jmol._XhtmlElement.appendChild(child);
+ else
+ Jmol._XhtmlElement.parentNode.insertBefore(child, _jmol.XhtmlElement);
+ }
+ }
+
+ Jmol._getDomElement = function(data, Ptr, closetag, lvel) {
+
+ // there is no "document.write" in XHTML
+
+ var e = document.createElement("span");
+ e.innerHTML = data;
+ Ptr[0] = data.length;
+
+/*
+ // unnecessary ?
+
+ closetag || (closetag = "");
+ lvel || (lvel = 0);
+ var pt0 = Ptr[0];
+ var pt = pt0;
+ while (pt < data.length && data.charAt(pt) != "<")
+ pt++
+ if (pt != pt0) {
+ var text = data.substring(pt0, pt);
+ Ptr[0] = pt;
+ return document.createTextNode(text);
+ }
+ pt0 = ++pt;
+ var ch;
+ while (pt < data.length && "\n\r\t >".indexOf(ch = data.charAt(pt)) < 0)
+ pt++;
+ var tagname = data.substring(pt0, pt);
+ var e = (tagname == closetag || tagname == "/" ? ""
+ : document.createElementNS ? document.createElementNS('http://www.w3.org/1999/xhtml', tagname)
+ : document.createElement(tagname));
+ if (ch == ">") {
+ Ptr[0] = ++pt;
+ return e;
+ }
+ while (pt < data.length && (ch = data.charAt(pt)) != ">") {
+ while (pt < data.length && "\n\r\t ".indexOf(ch = data.charAt(pt)) >= 0)
+ pt++;
+ pt0 = pt;
+ while (pt < data.length && "\n\r\t =/>".indexOf(ch = data.charAt(pt)) < 0)
+ pt++;
+ var attrname = data.substring(pt0, pt).toLowerCase();
+ if (attrname && ch != "=")
+ e.setAttribute(attrname, "true");
+ while (pt < data.length && "\n\r\t ".indexOf(ch = data.charAt(pt)) >= 0)
+ pt++;
+ if (ch == "/") {
+ Ptr[0] = pt + 2;
+ return e;
+ } else if (ch == "=") {
+ var quote = data.charAt(++pt);
+ pt0 = ++pt;
+ while (pt < data.length && (ch = data.charAt(pt)) != quote)
+ pt++;
+ var attrvalue = data.substring(pt0, pt);
+ e.setAttribute(attrname, attrvalue);
+ pt++;
+ }
+ }
+ Ptr[0] = ++pt;
+ while (Ptr[0] < data.length) {
+ var child = Jmol._getDomElement(data, Ptr, "/" + tagname, lvel+1);
+ if (!child)
+ break;
+ e.appendChild(child);
+ }
+*/
+ return e;
+ }
+
+ Jmol._setObject = function(obj, id, Info) {
+ obj._id = id;
+ obj.__Info = {};
+ Info.z && Info.zIndexBase && (Jmol._z = Jmol._getZOrders(Info.zIndexBase));
+ for (var i in Info)
+ obj.__Info[i] = Info[i];
+ (obj._z = Info.z) || Info.zIndexBase && (obj._z = obj.__Info.z = Jmol._getZOrders(Info.zIndexBase));
+ obj._width = Info.width;
+ obj._height = Info.height;
+ obj._noscript = !obj._isJava && Info.noscript;
+ obj._console = Info.console;
+ obj._cacheFiles = !!Info.cacheFiles;
+ obj._viewSet = (Info.viewSet == null || obj._isJava ? null : "Set" + Info.viewSet);
+ if (obj._viewSet != null) {
+ Jmol.View.__init(obj);
+ obj._currentView = null;
+ }
+ !Jmol._fileCache && obj._cacheFiles && (Jmol._fileCache = {});
+ if (!obj._console)
+ obj._console = obj._id + "_infodiv";
+ if (obj._console == "none")
+ obj._console = null;
+
+ obj._color = (Info.color ? Info.color.replace(/0x/,"#") : "#FFFFFF");
+ obj._disableInitialConsole = Info.disableInitialConsole;
+ obj._noMonitor = Info.disableJ2SLoadMonitor;
+ Jmol._j2sPath && (Info.j2sPath = Jmol._j2sPath);
+ obj._j2sPath = Info.j2sPath;
+ obj._coverImage = Info.coverImage;
+ obj._isCovered = !!obj._coverImage;
+ obj._deferApplet = Info.deferApplet || obj._isCovered && obj._isJava; // must do this if covered in Java
+ obj._deferUncover = Info.deferUncover && !obj._isJava; // can't do this with Java
+ obj._coverScript = Info.coverScript;
+ obj._coverTitle = Info.coverTitle;
+
+ if (!obj._coverTitle)
+ obj._coverTitle = (obj._deferApplet ? "activate 3D model" : "3D model is loading...")
+ obj._containerWidth = obj._width + ((obj._width==parseFloat(obj._width))? "px":"");
+ obj._containerHeight = obj._height + ((obj._height==parseFloat(obj._height))? "px":"");
+ obj._info = "";
+ obj._infoHeader = obj._jmolType + ' "' + obj._id + '"'
+ obj._hasOptions = Info.addSelectionOptions;
+ obj._defaultModel = Info.defaultModel;
+ obj._readyScript = (Info.script ? Info.script : "");
+ obj._readyFunction = Info.readyFunction;
+ if (obj._coverImage && !obj._deferApplet)
+ obj._readyScript += ";javascript " + id + "._displayCoverImage(false)";
+ obj._src = Info.src;
+
+ }
+
+ Jmol._addDefaultInfo = function(Info, DefaultInfo) {
+ for (var x in DefaultInfo)
+ if (typeof Info[x] == "undefined")
+ Info[x] = DefaultInfo[x];
+ Jmol._use && (Info.use = Jmol._use);
+ if (Info.use.indexOf("SIGNED") >= 0) {
+ if (Info.jarFile.indexOf("Signed") < 0)
+ Info.jarFile = Info.jarFile.replace(/Applet/,"AppletSigned");
+ Info.use = Info.use.replace(/SIGNED/, "JAVA");
+ Info.isSigned = true;
+ }
+ }
+
+ Jmol._syncedApplets = [];
+ Jmol._syncedCommands = [];
+ Jmol._syncedReady = [];
+ Jmol._syncReady = false;
+ Jmol._isJmolJSVSync = false;
+
+ Jmol._setReady = function(applet) {
+ Jmol._syncedReady[applet] = 1;
+ var n = 0;
+ for (var i = 0; i < Jmol._syncedApplets.length; i++) {
+ if (Jmol._syncedApplets[i] == applet._id) {
+ Jmol._syncedApplets[i] = applet;
+ Jmol._syncedReady[i] = 1;
+ } else if (!Jmol._syncedReady[i]) {
+ continue;
+ }
+ n++;
+ }
+ if (n != Jmol._syncedApplets.length)
+ return;
+ Jmol._setSyncReady();
+ }
+
+ Jmol._setDestroy = function(applet) {
+ //MSIE bug responds to any link click even if it is just a JavaScript call
+
+ if (Jmol.featureDetection.allowDestroy)
+ Jmol.$windowOn('beforeunload', function () { Jmol._destroy(applet); } );
+ }
+
+ Jmol._destroy = function(applet) {
+ try {
+ if (applet._appletPanel) applet._appletPanel.destroy();
+ applet._applet = null;
+ Jmol._unsetMouse(applet._canvas)
+ applet._canvas = null;
+ var n = 0;
+ for (var i = 0; i < Jmol._syncedApplets.length; i++) {
+ if (Jmol._syncedApplets[i] == applet)
+ Jmol._syncedApplets[i] = null;
+ if (Jmol._syncedApplets[i])
+ n++;
+ }
+ if (n > 0)
+ return;
+ Jmol._clearVars();
+ } catch(e){}
+ }
+
+ ////////////// misc core functionality //////////////
+
+ Jmol._setSyncReady = function() {
+ Jmol._syncReady = true;
+ var s = ""
+ for (var i = 0; i < Jmol._syncedApplets.length; i++)
+ if (Jmol._syncedCommands[i])
+ s += "Jmol.script(Jmol._syncedApplets[" + i + "], Jmol._syncedCommands[" + i + "]);"
+ setTimeout(s, 50);
+ }
+
+ Jmol._mySyncCallback = function(appFullName,msg) {
+ app = Jmol._applets[appFullName];
+ if (app._viewSet) {
+ // when can we do this?
+// if (app._viewType == "JSV" && !app._currentView.JMOL)
+ Jmol.View.updateFromSync(app, msg);
+ return;
+ }
+ if(!Jmol._syncReady || !Jmol._isJmolJSVSync)
+ return 1; // continue processing and ignore me
+ for (var i = 0; i < Jmol._syncedApplets.length; i++) {
+ if (msg.indexOf(Jmol._syncedApplets[i]._syncKeyword) >= 0)
+ Jmol._syncedApplets[i]._syncScript(msg);
+ }
+ return 0 // prevents further Jmol sync processing
+ }
+
+ Jmol._getElement = function(applet, what) {
+ var d = document.getElementById(applet._id + "_" + what);
+ return (d || {});
+ }
+
+ Jmol._evalJSON = function(s,key){
+ s = s + "";
+ if(!s)
+ return [];
+ if(s.charAt(0) != "{") {
+ if(s.indexOf(" | ") >= 0)
+ s = s.replace(/\ \|\ /g, "\n");
+ return s;
+ }
+ var A = (new Function( "return " + s ) )();
+ return (!A ? null : key && A[key] != undefined ? A[key] : A);
+ }
+
+ Jmol._sortMessages = function(A){
+ /*
+ * private function
+ */
+ function _sortKey0(a,b){
+ return (a[0]<b[0]?1:a[0]>b[0]?-1:0);
+ }
+
+ if(!A || typeof (A) != "object")
+ return [];
+ var B = [];
+ for(var i = A.length - 1; i >= 0; i--)
+ for(var j = 0, jj= A[i].length; j < jj; j++)
+ B[B.length] = A[i][j];
+ if(B.length == 0)
+ return;
+ B = B.sort(_sortKey0);
+ return B;
+ }
+
+ //////////////////// mouse events //////////////////////
+
+ Jmol._setMouseOwner = function(who, tf) {
+ if (who == null || tf)
+ Jmol._mouseOwner = who;
+ else if (Jmol._mouseOwner == who)
+ Jmol._mouseOwner = null;
+ }
+
+ Jmol._jsGetMouseModifiers = function(ev) {
+ var modifiers = 0;
+ switch (ev.button) {
+ case 0:
+ modifiers = 16;//J.api.Event.MOUSE_LEFT;
+ break;
+ case 1:
+ modifiers = 8;//J.api.Event.MOUSE_MIDDLE;
+ break;
+ case 2:
+ modifiers = 4;//J.api.Event.MOUSE_RIGHT;
+ break;
+ }
+ if (ev.shiftKey)
+ modifiers += 1;//J.api.Event.SHIFT_MASK;
+ if (ev.altKey)
+ modifiers += 8;//J.api.Event.ALT_MASK;
+ if (ev.ctrlKey)
+ modifiers += 2;//J.api.Event.CTRL_MASK;
+ return modifiers;
+ }
+
+ Jmol._jsGetXY = function(canvas, ev) {
+ if (!canvas.applet._ready || Jmol._touching && ev.type.indexOf("touch") < 0)
+ return false;
+ //ev.preventDefault(); // removed 5/9/2015 -- caused loss of focus on text-box clicking in SwingJS
+ var offsets = Jmol.$offset(canvas.id);
+ var x, y;
+ var oe = ev.originalEvent;
+ // drag-drop jQuery event is missing pageX
+ ev.pageX || (ev.pageX = oe.pageX);
+ ev.pageY || (ev.pageY = oe.pageY);
+ Jmol._mousePageX = ev.pageX;
+ Jmol._mousePageY = ev.pageY;
+ if (oe.targetTouches && oe.targetTouches[0]) {
+ x = oe.targetTouches[0].pageX - offsets.left;
+ y = oe.targetTouches[0].pageY - offsets.top;
+ } else if (oe.changedTouches) {
+ x = oe.changedTouches[0].pageX - offsets.left;
+ y = oe.changedTouches[0].pageY - offsets.top;
+ } else {
+ x = ev.pageX - offsets.left;
+ y = ev.pageY - offsets.top;
+ }
+ return (x == undefined ? null : [Math.round(x), Math.round(y), Jmol._jsGetMouseModifiers(ev)]);
+ }
+
+ Jmol._gestureUpdate = function(canvas, ev) {
+ ev.stopPropagation();
+ ev.preventDefault();
+ var oe = ev.originalEvent;
+ switch (ev.type) {
+ case "touchstart":
+ Jmol._touching = true;
+ break;
+ case "touchend":
+ Jmol._touching = false;
+ break;
+ }
+ if (!oe.touches || oe.touches.length != 2) return false;
+ switch (ev.type) {
+ case "touchstart":
+ canvas._touches = [[],[]];
+ break;
+ case "touchmove":
+ var offsets = Jmol.$offset(canvas.id);
+ var t0 = canvas._touches[0];
+ var t1 = canvas._touches[1];
+ t0.push([oe.touches[0].pageX - offsets.left, oe.touches[0].pageY - offsets.top]);
+ t1.push([oe.touches[1].pageX - offsets.left, oe.touches[1].pageY - offsets.top]);
+ var n = t0.length;
+ if (n > 3) {
+ t0.shift();
+ t1.shift();
+ }
+ if (n >= 2)
+ canvas.applet._processGesture(canvas._touches);
+ break;
+ }
+ return true;
+ }
+
+ Jmol._jsSetMouse = function(canvas) {
+
+ var doIgnore = function(ev) { return (ev.target.className.indexOf("swingjs-ui") >= 0) };
+
+ Jmol.$bind(canvas, 'mousedown touchstart', function(ev) {
+ if (doIgnore(ev))
+ return true;
+ Jmol._setMouseOwner(canvas, true);
+ ev.stopPropagation();
+ var ui = ev.target["data-UI"];
+ if (!ui || !ui.handleJSEvent(canvas, 501, ev))
+ ev.preventDefault();
+ canvas.isDragging = true;
+ if ((ev.type == "touchstart") && Jmol._gestureUpdate(canvas, ev))
+ return !!ui;
+ Jmol._setConsoleDiv(canvas.applet._console);
+ var xym = Jmol._jsGetXY(canvas, ev);
+ if(xym) {
+ if (ev.button != 2)
+ Jmol.Swing.hideMenus(canvas.applet);
+ canvas.applet._processEvent(501, xym); //java.awt.Event.MOUSE_DOWN
+ }
+ return !!ui;
+ });
+
+ Jmol.$bind(canvas, 'mouseup touchend', function(ev) {
+ if (doIgnore(ev))
+ return true;
+ Jmol._setMouseOwner(null);
+ ev.stopPropagation();
+ var ui = ev.target["data-UI"];
+ if (!ui || !ui.handleJSEvent(canvas, 502, ev))
+ ev.preventDefault();
+ canvas.isDragging = false;
+ if (ev.type == "touchend" && Jmol._gestureUpdate(canvas, ev))
+ return !!ui;
+ var xym = Jmol._jsGetXY(canvas, ev);
+ if(xym)
+ canvas.applet._processEvent(502, xym);//java.awt.Event.MOUSE_UP
+ return !!ui;
+ });
+
+ Jmol.$bind(canvas, 'mousemove touchmove', function(ev) { // touchmove
+ if (doIgnore(ev))
+ return true;
+ // defer to console or menu when dragging within this canvas
+ if (Jmol._mouseOwner && Jmol._mouseOwner != canvas && Jmol._mouseOwner.isDragging) {
+ if (!Jmol._mouseOwner.mouseMove)
+ return true;
+ Jmol._mouseOwner.mouseMove(ev);
+ return false;
+ }
+ return Jmol._drag(canvas, ev);
+ });
+
+ Jmol._drag = function(canvas, ev) {
+
+ ev.stopPropagation();
+ ev.preventDefault();
+
+ var isTouch = (ev.type == "touchmove");
+ if (isTouch && Jmol._gestureUpdate(canvas, ev))
+ return false;
+ var xym = Jmol._jsGetXY(canvas, ev);
+ if(!xym) return false;
+
+ if (!canvas.isDragging)
+ xym[2] = 0;
+
+ var ui = ev.target["data-UI"];
+ if (canvas.isdragging && (!ui || !ui.handleJSEvent(canvas, 506, ev))) {}
+ canvas.applet._processEvent((canvas.isDragging ? 506 : 503), xym); // java.awt.Event.MOUSE_DRAG : java.awt.Event.MOUSE_MOVE
+ return !!ui;
+ }
+
+ Jmol.$bind(canvas, 'DOMMouseScroll mousewheel', function(ev) { // Zoom
+ if (doIgnore(ev))
+ return true;
+ ev.stopPropagation();
+ ev.preventDefault();
+ // Webkit or Firefox
+ canvas.isDragging = false;
+ var oe = ev.originalEvent;
+ var scroll = (oe.detail ? oe.detail : (Jmol.featureDetection.os == "mac" ? 1 : -1) * oe.wheelDelta); // Mac and PC are reverse; but
+ var modifiers = Jmol._jsGetMouseModifiers(ev);
+ canvas.applet._processEvent(-1,[scroll < 0 ? -1 : 1,0,modifiers]);
+ return false;
+ });
+
+ // context menu is fired on mouse down, not up, and it's handled already anyway.
+
+ Jmol.$bind(canvas, "contextmenu", function() {return false;});
+
+ Jmol.$bind(canvas, 'mouseout', function(ev) {
+ if (doIgnore(ev))
+ return true;
+ if (Jmol._mouseOwner && !Jmol._mouseOwner.mouseMove)
+ Jmol._setMouseOwner(null);
+ if (canvas.applet._appletPanel)
+ canvas.applet._appletPanel.startHoverWatcher(false);
+ //canvas.isDragging = false;
+ var xym = Jmol._jsGetXY(canvas, ev);
+ if (!xym)
+ return false;
+ //canvas.applet._processEvent(502, xym);//J.api.Event.MOUSE_UP
+ //canvas.applet._processEvent(505, xym);//J.api.Event.MOUSE_EXITED
+ return false;
+ });
+
+ Jmol.$bind(canvas, 'mouseenter', function(ev) {
+ if (doIgnore(ev))
+ return true;
+ if (canvas.applet._appletPanel)
+ canvas.applet._appletPanel.startHoverWatcher(true);
+ if (ev.buttons === 0 || ev.which === 0) {
+ canvas.isDragging = false;
+ var xym = Jmol._jsGetXY(canvas, ev);
+ if (!xym)
+ return false;
+ canvas.applet._processEvent(504, xym);//J.api.Event.MOUSE_ENTERED
+ canvas.applet._processEvent(502, xym);//J.api.Event.MOUSE_UP
+ return false;
+ }
+ });
+
+ Jmol.$bind(canvas, 'mousemoveoutjsmol', function(evspecial, target, ev) {
+ if (doIgnore(ev))
+ return true;
+ if (canvas == Jmol._mouseOwner && canvas.isDragging) {
+ return Jmol._drag(canvas, ev);
+ }
+ });
+
+ if (canvas.applet._is2D)
+ Jmol.$resize(function() {
+ if (!canvas.applet)
+ return;
+ canvas.applet._resize();
+ });
+
+ Jmol.$bind('body', 'mouseup touchend', function(ev) {
+ if (doIgnore(ev))
+ return true;
+ if (canvas.applet)
+ canvas.isDragging = false;
+ Jmol._setMouseOwner(null);
+ });
+
+ }
+
+ Jmol._jsUnsetMouse = function(canvas) {
+ canvas.applet = null;
+ Jmol.$bind(canvas, 'mousedown touchstart mousemove touchmove mouseup touchend DOMMouseScroll mousewheel contextmenu mouseout mouseenter', null);
+ Jmol._setMouseOwner(null);
+ }
+
+
+////// Jmol.Swing interface for Javascript implementation of Swing dialogs and menus
+
+Jmol.Swing = {
+ // a static class
+ count:0,
+ menuInitialized:0,
+ menuCounter:0,
+ htDialogs:{}
+};
+
+(function(Swing) {
+
+SwingController = Swing; // see javajs.api.SwingController
+
+Swing.setDraggable = function(Obj) {
+
+ var proto = Obj.prototype;
+ if (proto.setContainer)
+ return;
+
+ // for menus, console, and
+ proto.setContainer = function(container) {
+ this.container = container;
+ container.obj = this;
+ this.isDragging = false;
+ this.ignoreMouse = false;
+ var me = this;
+ container.bind('mousedown touchstart', function(ev) {
+ if (me.ignoreMouse) {
+ me.ignoreMouse = false;
+ return true;
+ }
+ Jmol._setMouseOwner(me, true);
+ me.isDragging = true;
+ me.pageX = ev.pageX;
+ me.pageY = ev.pageY;
+ return false;
+ });
+ container.bind('mousemove touchmove', function(ev) {
+ if (me.isDragging && Jmol._mouseOwner == me) {
+ me.mouseMove(ev);
+ return false;
+ }
+ });
+ container.bind('mouseup touchend', function(ev) {
+ me.mouseUp(ev);
+ Jmol._setMouseOwner(null);
+ });
+ };
+
+ proto.mouseUp = function(ev) {
+ if (this.isDragging && Jmol._mouseOwner == this) {
+ this.pageX0 += (ev.pageX - this.pageX);
+ this.pageY0 += (ev.pageY - this.pageY);
+ this.isDragging = false;
+ return false;
+ }
+ Jmol._setMouseOwner(null);
+ }
+
+ proto.setPosition = function() {
+ if (Jmol._mousePageX === null) {
+ var id = this.applet._id + "_" + (this.applet._is2D ? "canvas2d" : "canvas");
+ var offsets = Jmol.$offset(id);
+ Jmol._mousePageX = offsets.left;
+ Jmol._mousePageY = offsets.top;
+ }
+ this.pageX0 = Jmol._mousePageX;
+ this.pageY0 = Jmol._mousePageY;
+ var pos = { top: Jmol._mousePageY + 'px', left: Jmol._mousePageX + 'px' };
+ this.container.css(pos);
+ };
+
+ proto.mouseMove = function(ev) {
+ if (this.isDragging && Jmol._mouseOwner == this) {
+ this.timestamp = System.currentTimeMillis(); // used for menu closure
+ var x = this.pageX0 + (ev.pageX - this.pageX);
+ var y = this.pageY0 + (ev.pageY - this.pageY);
+ Jmol._mousePageX = x;
+ Jmol._mousePageY = y;
+ this.container.css({ top: y + 'px', left: x + 'px' })
+ }
+ };
+
+ proto.dragBind = function(isBind) {
+ this.applet._ignoreMouse = !isBind;
+ this.container.unbind('mousemoveoutjsmol');
+ this.container.unbind('touchmoveoutjsmol');
+ this.container.unbind('mouseupoutjsmol');
+ this.container.unbind('touchendoutjsmol');
+ Jmol._setMouseOwner(null);
+ if (isBind) {
+ var me = this;
+ this.container.bind('mousemoveoutjsmol touchmoveoutjsmol', function(evspecial, target, ev) {
+ me.mouseMove(ev);
+ });
+ this.container.bind('mouseupoutjsmol touchendoutjsmol', function(evspecial, target, ev) {
+ me.mouseUp(ev);
+ });
+ }
+ };
+}
+
+// Dialog //
+
+Swing.JSDialog = function () {
+}
+
+Swing.setDraggable(Swing.JSDialog);
+
+///// calls from javajs and other Java-derived packages /////
+
+Swing.getScreenDimensions = function(d) {
+ d.width = $(window).width();
+ d.height = $(window).height();
+}
+
+Swing.dispose = function(dialog) {
+ Jmol.$remove(dialog.id + "_mover");
+ delete Swing.htDialogs[dialog.id]
+ dialog.container.obj.dragBind(false);
+// var btns = $("#" + dialog.id + " *[id^='J']"); // add descendents with id starting with "J"
+// for (var i = btns.length; --i >= 0;)
+// delete Dialog.htDialogs[btns[i].id]
+ //System.out.println("JSmolCore.js: dispose " + dialog.id)
+}
+
+Swing.register = function(dialog, type) {
+ dialog.id = type + (++Swing.count);
+ Swing.htDialogs[dialog.id] = dialog;
+ //System.out.println("JSmolCore.js: register " + dialog.id)
+
+}
+
+Swing.setDialog = function(dialog) {
+ Jmol._setMouseOwner(null);
+ Jmol.$remove(dialog.id);
+ //System.out.println("removed " + dialog.id)
+ var id = dialog.id + "_mover";
+ var container = Jmol._$(id);
+ var jd;
+ //System.out.println("JSmolCore.js: setDialog " + dialog.id);
+ if (container[0]) {
+ container.html(dialog.html);
+ jd = container[0].jd;
+ } else {
+ Jmol.$after("body","<div id='" + id + "' style='position:absolute;left:0px;top:0px;'>" + dialog.html + "</div>");
+ var jd = new Swing.JSDialog();
+ container = Jmol._$(id);
+ dialog.container = container;
+ jd.applet = dialog.manager.vwr.html5Applet;
+ jd.setContainer(container);
+ jd.dialog = dialog;
+ jd.setPosition();
+ jd.dragBind(true);
+ container[0].jd = jd;
+ }
+ Jmol.$bind("#" + dialog.id + " .JButton", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
+ Jmol.$bind("#" + dialog.id + " .JComboBox", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
+ Jmol.$bind("#" + dialog.id + " .JCheckBox", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
+ Jmol.$bind("#" + dialog.id + " .JTextField", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
+ Jmol.$bind("#" + dialog.id + " .JTable", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
+ Jmol.$bind("#" + dialog.id + " .JScrollPane", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
+ Jmol.$bind("#" + dialog.id + " .JEditorPane", "mousedown touchstart", function(event) { jd.ignoreMouse=true });
+
+}
+
+Swing.setSelected = function(chk) {
+ Jmol.$prop(chk.id, 'checked', !!chk.selected);
+}
+
+Swing.setSelectedIndex = function(cmb) {
+ Jmol.$prop(cmb.id, 'selectedIndex', cmb.selectedIndex);
+}
+
+Swing.setText = function(btn) {
+ Jmol.$prop(btn.id, 'value', btn.text);
+}
+
+Swing.setVisible = function(c) {
+ Jmol.$setVisible(c.id, c.visible);
+}
+
+Swing.setEnabled = function(c) {
+ Jmol.$setEnabled(c.id, c.enabled);
+}
+
+/// callbacks from the HTML elements ////
+
+Swing.click = function(element, keyEvent) {
+ var component = Swing.htDialogs[element.id];
+ if (component) {
+ //System.out.println("click " + element + " " + component)
+ var info = component.toString();
+ // table cells will have an id but are not registered
+ if (info.indexOf("JCheck") >= 0) {
+ component.selected = element.checked;
+ } else if (info.indexOf("JCombo") >= 0) {
+ component.selectedIndex = element.selectedIndex;
+ } else if (component.text != null) { // JButton, JTextField
+ component.text = element.value;
+ if (keyEvent && ((keyEvent.charCode || keyEvent.keyCode) != 13))
+ return;
+ }
+ }
+ var dialog = Swing.htDialogs[Jmol.$getAncestorDiv(element.id, "JDialog").id];
+ var key = (component ? component.name : dialog.registryKey + "/" + element.id);
+ //System.out.println("JSmolCore.js: click " + key);
+ dialog.manager.actionPerformed(key);
+}
+
+Swing.setFront = function(dialog) {
+ var applet = dialog.manager.vwr.html5Applet;
+ if (dialog.zIndex != Jmol._getZ(applet, "dialog"))
+ dialog.zIndex = Jmol._incrZ(applet, "dialog");
+ dialog.container && ((dialog.container[0] || dialog.container).style.zIndex = dialog.zIndex);
+}
+
+Swing.hideMenus = function(applet) {
+ // called from LEFT-DOWN mouse event
+ var menus = applet._menus;
+ if (menus)
+ for (var i in menus)
+ if (menus[i].visible)
+ Swing.hideMenu(menus[i]);
+}
+
+Swing.windowClosing = function(element) {
+ var dialog = Swing.htDialogs[Jmol.$getAncestorDiv(element.id, "JDialog").id];
+ if (dialog.registryKey) {
+ //System.out.println("JSmolCore.js: windowClosing " + dialog.registryKey);
+ dialog.manager.processWindowClosing(dialog.registryKey);
+ } else {
+ //System.out.println("JSmolCore.js: windowClosing " + dialog.title);
+ dialog.dispose();
+ }
+}
+
+})(Jmol.Swing);
+
+Jmol._track = function(applet) {
+ // this function inserts an iFrame that can be used to track your page's applet use.
+ // By default it tracks to a page at St. Olaf College, but you can change that.
+ // and you can use
+ //
+ // delete Jmol._tracker
+ //
+ // yourself to not have you page execute this
+ //
+ if (Jmol._tracker){
+ try {
+ var url = Jmol._tracker + "&applet=" + applet._jmolType + "&version=" + Jmol._version
+ + "&appver=" + Jmol.___JmolVersion + "&url=" + encodeURIComponent(document.location.href);
+ var s = '<iframe style="display:none" width="0" height="0" frameborder="0" tabindex="-1" src="' + url + '"></iframe>'
+ Jmol.$after("body", s);
+ } catch (e) {
+ // ignore
+ }
+ delete Jmol._tracker;
+ }
+ return applet;
+}
+
+Jmol.getProfile = function() {
+ window["j2s.doProfile"] = true;
+ if (self.Clazz && self.JSON) {
+ Clazz._profile || (Clazz._profile = {});
+ return Clazz.getProfile();
+ }
+}
+
+Jmol._getInChIKey = function(applet, data) {
+ if (data.indexOf("MOL=") >= 0)
+ data = data.split("MOL=")[1].split("\"")[0];
+
+}
+
+Jmol._getAttr = function(s, a) {
+ var pt = s.indexOf(a + "=");
+ return (pt >= 0 && (pt = s.indexOf('"', pt)) >= 0
+ ? s.substring(pt+1, s.indexOf('"', pt+1)) : null);
+}
+
+Jmol.User = {
+ viewUpdatedCallback: null
+}
+
+Jmol.View = {
+
+// The objective of Jmol.View is to coordinate
+// asynchronous applet loading and atom/peak picking
+// among any combination of Jmol, JME, and JSV.
+//
+// basic element is a view object:
+// view = {
+// viewType1: viewRecord1,
+// viewType2: viewRecord2,
+// viewType3: viewRecord3
+// }
+// where viewType is one of (Jmol, JME, JSV)
+// and a viewRecord is an object
+// with elements .chemID, .applet, .data, .script
+//
+// Jmol.View.sets is a list of cached views[0..n]
+// for a given group of applet objects with common Info.viewSet
+//
+// Bob Hanson 1/22/2014 7:05:38 AM
+
+ count: 0,
+ applets: {},
+ sets: {}
+};
+
+(function(View) {
+
+// methods called from other modules have no "_" in their name
+
+View.updateView = function(applet, Info, _View_updateView) {
+ // Info.chemID, Info.data, possibly Info.viewID if no chemID
+ // return from applet after asynchronous download of new data
+ if (applet._viewSet == null)
+ return;
+ Info.chemID || (applet._searchQuery = null);
+ Info.data || (Info.data = "N/A");
+ Info.type = applet._viewType;
+ if((applet._currentView = View.__findView(applet._viewSet, Info)) == null)
+ applet._currentView = View.__createViewSet(applet._viewSet, Info.chemID, Info.viewID || Info.chemID);
+ applet._currentView[Info.type].data = Info.data;
+ applet._currentView[Info.type].smiles = applet._getSmiles();
+ if (Jmol.User.viewUpdatedCallback)
+ Jmol.User.viewUpdatedCallback(applet, "updateView");
+ View.__setView(applet._currentView, applet, false);
+}
+
+View.updateFromSync = function(applet, msg) {
+ applet._updateMsg = msg;
+ var id = Jmol._getAttr(msg, "sourceID") || Jmol._getAttr(msg, "file");
+ if (!id)
+ return;
+ var view = View.__findView(applet._viewSet, {viewID:id});
+ if (view == null)
+ return Jmol.updateView(applet, msg); // JSV has been updated internally
+ if (view != applet._currentView)
+ View.__setView(view, applet, true);
+ var A = ((id = Jmol._getAttr(msg, "atoms")) && msg.indexOf("selectionhalos ON") >= 0
+ ? eval("[" + id + "]") : []);
+ setTimeout(function(){if (applet._currentView == view)View.updateAtomPick(applet, A)}, 10);
+ if (Jmol.User.viewUpdatedCallback)
+ Jmol.User.viewUpdatedCallback(applet, "updateFromSync");
+}
+
+View.updateAtomPick = function(applet, A, _View_updateAtomPick) {
+ var view = applet._currentView;
+ if (view == null)
+ return;
+ for (var viewType in view) {
+ if (viewType != "info" && view[viewType].applet != applet)
+ view[viewType].applet._updateAtomPick(A);
+ }
+ if (Jmol.User.viewUpdatedCallback)
+ Jmol.User.viewUpdatedCallback(applet, "updateAtomPick");
+}
+
+View.dumpViews = function(setID) {
+ var views = View.sets[setID];
+ if (!views)
+ return;
+ var s = "View set " + setID + ":\n";
+ var applets = View.applets[setID];
+ for (var i in applets)
+ s += "\napplet " + applets[i]._id
+ + " currentView=" + (applets[i]._currentView ? applets[i]._currentView.info.viewID : null);
+ for (var i = views.length; --i >= 0;) {
+ var view = views[i];
+ s += "\n\n<b>view=" + i
+ + " viewID=" + view.info.viewID
+ + " chemID=" + view.info.chemID + "</b>\n"
+ var v;
+ for (var viewType in view)
+ if (viewType != "info")
+ s += "\nview=" + i + " type=" + viewType + " applet="
+ + ((v = view[viewType]).applet ? v.applet._id : null)
+ + " SMILES=" + v.smiles + "\n"
+ + " atomMap=" + JSON.stringify(v.atomMap) + "\n"
+ + " data=\n" + v.data + "\n"
+ }
+ return s
+}
+
+
+// methods starting with "__" are "private" to JSmolCore.js
+
+View.__init = function(applet) {
+ var set = applet._viewSet;
+ var a = View.applets;
+ a[set] || (a[set] = {});
+ a[set][applet._viewType] = applet;
+}
+
+View.__findView = function(set, Info) {
+ var views = View.sets[set];
+ if (views == null)
+ views = View.sets[set] = [];
+ for (var i = views.length; --i >= 0;) {
+ var view = views[i];
+ if (Info.viewID) {
+ if (view.info.viewID == Info.viewID)
+ return view;
+ } else if (Info.chemID != null && Info.chemID == view.info.chemID) {
+ return view;
+ } else {
+ for (var viewType in view) {
+ if (viewType != "info") {
+ if (Info.data != null && view[viewType].data != null ? Info.data == view[viewType].data
+ : Info.type == viewType)
+ return view;
+ }
+ }
+ }
+ }
+ return null;
+}
+
+View.__createViewSet = function(set, chemID, viewID, _createViewSet) {
+ View.count++;
+ var view = {info:{chemID: chemID, viewID: viewID || "model_" + View.count}};
+
+ for (var id in Jmol._applets) {
+ var a = Jmol._applets[id];
+ if (a._viewSet == set)
+ view[a._viewType] = {applet:a, data: null};
+ }
+ View.sets[set].push(view);
+ return view;
+}
+
+View.__setView = function(view, applet, isSwitch, _setView) {
+ // called from Jmol._searchMol and Jmol.View.setCurrentView
+ // to notify the applets in the set that there may be new data for them
+ // skip the originating applet itself and cases where the data has not changed.
+ // stop at first null data, because that will initiate some sort of asynchronous
+ // call that will be back here afterward.
+
+ for (var viewType in view) {
+ if (viewType == "info")
+ continue;
+ var rec = view[viewType];
+ var a = rec.applet;
+ var modified = (isSwitch || a != null && a._molData == "<modified>");
+
+ if (a == null || a == applet && !modified)
+ continue; // may be a mol3d required by JSV but not having a corresponding applet
+ var wasNull = (rec.data == null);
+ var haveView = (a._currentView != null);
+ a._currentView = view;
+ if (haveView && view[viewType].data == rec.data && !wasNull & !modified)
+ continue;
+ a._loadModelFromView(view);
+ if (wasNull)
+ break;
+ }
+
+ // Either all are taken care of or one was null,
+ // in which case we have started an asynchronous
+ // process to get the data, and we can quit here.
+ // In either case, we are done.
+}
+
+}) (Jmol.View);
+
+Jmol.Cache = {fileCache: {}};
+
+Jmol.Cache.get = function(filename) {
+ return Jmol.Cache.fileCache[filename];
+}
+
+Jmol.Cache.put = function(filename, data) {
+ Jmol.Cache.fileCache[filename] = data;
+}
+
+ Jmol.Cache.setDragDrop = function(me) {
+ Jmol.$appEvent(me, "appletdiv", "dragover", function(e) {
+ e = e.originalEvent;
+ e.stopPropagation();
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ });
+ Jmol.$appEvent(me, "appletdiv", "drop", function(e) {
+ var oe = e.originalEvent;
+ oe.stopPropagation();
+ oe.preventDefault();
+ var file = oe.dataTransfer.files[0];
+ if (file == null) {
+ // FF and Chrome will drop an image here
+ // but it will be only a URL, not an actual file.
+ try {
+ file = "" + oe.dataTransfer.getData("text");
+ if (file.indexOf("file:/") == 0 || file.indexOf("http:/") == 0) {
+ me._scriptLoad(file);
+ return;
+ }
+ } catch(e) {
+ return;
+ }
+ // some other format
+ return;
+ }
+ // MSIE will drop an image this way, though, and load it!
+ var reader = new FileReader();
+ reader.onloadend = function(evt) {
+ if (evt.target.readyState == FileReader.DONE) {
+ var cacheName = "cache://DROP_" + file.name;
+ var bytes = Jmol._toBytes(evt.target.result);
+ if (!cacheName.endsWith(".spt"))
+ me._appletPanel.cacheFileByName("cache://DROP_*",false);
+ if (me._viewType == "JSV" || cacheName.endsWith(".jdx")) // shared by Jmol and JSV
+ Jmol.Cache.put(cacheName, bytes);
+ else
+ me._appletPanel.cachePut(cacheName, bytes);
+ var xym = Jmol._jsGetXY(me._canvas, e);
+ if(xym && (!me._appletPanel.setStatusDragDropped || me._appletPanel.setStatusDragDropped(0, xym[0], xym[1], cacheName))) {
+ me._appletPanel.openFileAsyncSpecial(cacheName, 1);
+ }
+ }
+ };
+ reader.readAsArrayBuffer(file);
+ });
+ }
+
+})(Jmol, jQuery);