Merge branch 'master' of https://source.jalview.org/git/jalviewjs.git
[jalviewjs.git] / site / swingjs / js / JSmol.js
index aa9751f..764cb39 100644 (file)
-// JSmol.js -- Jmol pure JavaScript version\r
-// author: Bob Hanson, hansonr@stolaf.edu      4/16/2012\r
-// author: Takanori Nakane biochem_fan 6/12/2012\r
-\r
-// BH 3/28/2015 6:18:33 AM refactoring to generalize for non-Jmol-related SwingJS applications\r
-// BH 9/6/2014 5:42:32 PM  two-point gestures broken\r
-// BH 5/8/2014 11:16:40 AM j2sPath starting with "/" fails to add idiom\r
-// BH 1/16/2014 8:44:03 PM   __execDelayMS = 100; // FF bug when loading into a tab that is not \r
-//                           immediately focused and not using jQuery for adding the applet and having  \r
-//                           multiple applets.\r
-// BH 12/6/2013 10:12:30 AM adding corejmoljsv.z.js\r
-// BH 9/17/2013 10:18:40 AM  file transfer functions moved to JSmolCore \r
-// BH 3/5/2013 9:54:16 PM added support for a cover image: Info.coverImage, coverScript, coverTitle, deferApplet, deferUncover\r
-// BH 1/3/2013 4:54:01 AM mouse binding should return false -- see d.bind(...), and d.bind("contextmenu") is not necessary\r
-\r
-// This library requires prior inclusion of \r
-\r
-//  jQuery 9 or higher\r
-//     JSmoljQueryExt.js\r
-//     JSmolCore.js\r
-//  j2sjmol.js    (Clazz and associated classes)\r
-\r
-// these:\r
-//\r
-//  JSmolApplet.js\r
-//  JSmolApi.js\r
-//  JSmolThree.js\r
-//  JSmolGLmol.js\r
-//  \r
-//  are optional \r
-\r
-;(function (Jmol) {\r
-\r
-       Jmol._isAsync = false; // testing only\r
-       Jmol._asyncCallbacks = {};\r
-       \r
-       Jmol._coreFiles = []; // required for package.js\r
-\r
-\r
-///////////////////\r
-// This section provides an asynchronous loading sequence\r
-//\r
-\r
-// methods and fields starting with double underscore are private to this .js file\r
-\r
-  var __clazzLoaded = false;\r
-       var __execLog = [];\r
-       var __execStack = [];\r
-       var __execTimer = 0;\r
-       var __coreSet = [];\r
-       var __coreMore = [];\r
-       var __execDelayMS = 100; // must be > 55 ms for FF\r
-\r
-       var __nextExecution = function(trigger) {\r
-    arguments.length || (trigger = true);\r
-               delete __execTimer;\r
-               var es = __execStack;\r
-               var e;\r
-               while (es.length > 0 && (e = es[0])[4] == "done")\r
-                       es.shift();\r
-               if (es.length == 0)\r
-                       return;\r
-               if (!Jmol._isAsync && !trigger) {\r
-                       setTimeout(__nextExecution,10)\r
-                       return;\r
-               }\r
-               e.push("done");\r
-               var s = "JSmol exec " + e[0]._id + " " + e[3] + " " + e[2];\r
-               if (self.System)\r
-                       System.out.println(s);\r
-                       //alert(s)\r
-               if (self.console)console.log(s + " -- OK")\r
-               __execLog.push(s);\r
-               e[1](e[0],e[2]);        \r
-       };\r
-\r
-       var __loadClazz = function(applet) {\r
-               if (!__clazzLoaded) {\r
-                       __clazzLoaded = true;\r
-                       // create the Clazz object\r
-                       LoadClazz();\r
-                       if (applet._noMonitor)\r
-                               Clazz._LoaderProgressMonitor.showStatus = function() {}\r
-                       LoadClazz = null;\r
-      if (applet.__Info.uncompressed)\r
-        Clazz.loadClass(); // for now; allows for no compression \r
-                       Clazz._Loader.onGlobalLoaded = function (file) {\r
-                        // not really.... just nothing more yet to do yet\r
-                               Clazz._LoaderProgressMonitor.showStatus("Application loaded.", true);\r
-                               if (!Jmol._debugCode || !Jmol.haveCore) {\r
-                                       Jmol.haveCore = true;\r
-                                       __nextExecution();\r
-                               }\r
-                       };\r
-                 // load package.js and j2s/core/core.z.js\r
-                       Clazz._Loader.loadPackageClasspath("java", null, true, __nextExecution);\r
-                       return;\r
-               }\r
-               __nextExecution();\r
-       };\r
-\r
-       var __loadClass = function(applet, javaClass) {\r
-               Clazz._Loader.loadClass(javaClass, function() {__nextExecution()});\r
-       };\r
-\r
-       Jmol.showExecLog = function() { return __execLog.join("\n") }; \r
-\r
-       Jmol._addExec = function(e) {\r
-    e[1] || (e[1] = __loadClass);\r
-               var s = "JSmol load " + e[0]._id + " " + e[3];\r
-               if (self.console)console.log(s + "...")\r
-               __execLog.push(s);   \r
-               __execStack.push(e);\r
-       }\r
-\r
-       Jmol._addCoreFile = function(type, path, more) {\r
-  \r
-    // BH 3/15: idea here is that when both Jmol and JSV are present, \r
-    // we want to load a common core file -- jmoljsv.z.js --\r
-    // instead of just one. Otherwise we do a lot of duplication.\r
-    // It is not clear how this would play with other concurrent\r
-    // apps. So this will take some thinking. But the basic idea is that\r
-    // core file to load is \r
-     \r
-    type = type.toLowerCase().split(".")[0]; // package name only \r
-\r
-    // return if type is already part of the set.    \r
-               if (__coreSet.join("").indexOf(type) >= 0) return;\r
-    \r
-    // create a concatenated lower-case name for a core file that includes\r
-    // all Java applets on the page\r
-    \r
-               __coreSet.push(type);\r
-               __coreSet.sort();\r
-               Jmol._coreFiles = [path + "/core/core" + __coreSet.join("") + ".z.js" ];\r
-               if (more && (more = more.split(" ")))\r
-                       for (var i = 0; i < more.length; i++)\r
-                               if (__coreMore.join("").indexOf(more[i]) < 0)\r
-                                       __coreMore.push(path + "/core/core" + more[i] + ".z.js")\r
-               for (var i = 0; i < __coreMore.length; i++)\r
-                       Jmol._coreFiles.push(__coreMore[i]);\r
-       }               \r
-\r
-       Jmol._Canvas2D = function(id, Info, type, checkOnly){\r
-               // type: Jmol or JSV\r
-               this._uniqueId = ("" + Math.random()).substring(3);\r
-               this._id = id;\r
-               this._is2D = true;\r
-               this._isJava = false;\r
-               this._jmolType = "Jmol._Canvas2D (" + type + ")";\r
-    this._isLayered = Info._isLayered || false;\r
-    this._isSwing = Info._isSwing || false;\r
-    this._isJSV = Info._isJSV || false;\r
-    this._isAstex = Info._isAstex || false;            \r
-    this._platform = Info._platform || "";\r
-               if (checkOnly)\r
-                       return this;\r
-               window[id] = this;\r
-               this._createCanvas(id, Info);\r
-               if (!Jmol._document || this._deferApplet)\r
-                       return this;\r
-               this._init();\r
-               return this;\r
-       };\r
-\r
-       Jmol._setAppletParams = function(availableParams, params, Info, isHashtable) {\r
-               for (var i in Info)\r
-                       if(!availableParams || availableParams.indexOf(";" + i.toLowerCase() + ";") >= 0){\r
-                               if (Info[i] == null || i == "language" && !Jmol.featureDetection.supportsLocalization())\r
-                                       continue;\r
-                               if (isHashtable)\r
-                                       params.put(i, (Info[i] === true ? Boolean.TRUE: Info[i] === false ? Boolean.FALSE : Info[i]))\r
-                               else\r
-                                       params[i] = Info[i];\r
-                       }\r
-       }     \r
-        \r
-       Jmol._jsSetPrototype = function(proto) {\r
-               proto._init = function() {\r
-                       this._setupJS();\r
-                       this._showInfo(true); \r
-                       if (this._disableInitialConsole)\r
-                               this._showInfo(false);\r
-               };\r
-\r
-               proto._createCanvas = function(id, Info, glmol) {\r
-                       Jmol._setObject(this, id, Info);\r
-                       if (glmol) {\r
-                               this._GLmol = glmol;\r
-                               this._GLmol.applet = this;\r
-                               this._GLmol.id = this._id;\r
-                       }      \r
-                       var t = Jmol._getWrapper(this, true);\r
-                       if (this._deferApplet) {\r
-                       } else if (Jmol._document) {\r
-                               Jmol._documentWrite(t);\r
-                               this._newCanvas(false);                                 \r
-                               t = "";\r
-                       } else {\r
-                               this._deferApplet = true;\r
-                               t += '<script type="text/javascript">' + id + '._cover(false)</script>';\r
-                       }\r
-                       t += Jmol._getWrapper(this, false);\r
-                       if (Info.addSelectionOptions)\r
-                               t += Jmol._getGrabberOptions(this);\r
-                       if (Jmol._debugAlert && !Jmol._document)\r
-                               alert(t);\r
-                       this._code = Jmol._documentWrite(t);\r
-               };\r
-\r
-               proto._newCanvas = function(doReplace) {\r
-                       if (this._is2D)\r
-                               this._createCanvas2d(doReplace);\r
-                       else\r
-                               this._GLmol.create();\r
-               };\r
-\r
-//////// swingjs.api.HTML5Applet interface    \r
-    proto._getHtml5Canvas = function() { return this._canvas }; \r
-    proto._getWidth = function() { return this._canvas.width }; \r
-    proto._getHeight = function() { return this._canvas.height };\r
-    proto._getContentLayer = function() { return Jmol.$(this, "contentLayer")[0] };\r
-    proto._repaintNow = function() { Jmol._repaint(this, false) }; \r
-////////\r
-\r
-\r
-               proto._createCanvas2d = function(doReplace) {\r
-                       var container = Jmol.$(this, "appletdiv");\r
-                       //if (doReplace) {\r
-      \r
-                       try {\r
-                       container[0].removeChild(this._canvas);\r
-                       if (this._canvas.frontLayer)\r
-                               container[0].removeChild(this._canvas.frontLayer);\r
-                       if (this._canvas.rearLayer)\r
-                               container[0].removeChild(this._canvas.rearLayer);\r
-                       if (this._canvas.contentLayer)\r
-                               container[0].removeChild(this._canvas.contentLayer);\r
-                       Jmol._jsUnsetMouse(this._mouseInterface);\r
-                       } catch (e) {}\r
-                       //}\r
-                       var w = Math.round(container.width());\r
-                       var h = Math.round(container.height());\r
-                       var canvas = document.createElement( 'canvas' );\r
-                       canvas.applet = this;\r
-                       this._canvas = canvas;\r
-                       canvas.style.width = "100%";\r
-                       canvas.style.height = "100%";\r
-                       canvas.width = w;\r
-                       canvas.height = h; // w and h used in setScreenDimension\r
-                       canvas.id = this._id + "_canvas2d";\r
-                       container.append(canvas);\r
-                       Jmol._$(canvas.id).css({"z-index":Jmol._getZ(this, "main")});\r
-                       if (this._isLayered){\r
-                               var img = document.createElement("div");\r
-                               canvas.contentLayer = img;\r
-                               img.id = this._id + "_contentLayer";\r
-                               container.append(img);\r
-                               Jmol._$(img.id).css({zIndex:Jmol._getZ(this, "image"),position:"absolute",left:"0px",top:"0px",\r
-        width:(this._isSwing ? w : 0) + "px", height:(this._isSwing ? h : 0) +"px", overflow:"hidden"});\r
-        if (this._isSwing) {\r
-               var d = document.createElement("div");\r
-          d.id = this._id + "_swingdiv";\r
-               Jmol._$(this._id + "_appletinfotablediv").append(d);\r
-                                 Jmol._$(d.id).css({zIndex:Jmol._getZ(this, "rear"),position:"absolute",left:"0px",top:"0px", width:w +"px", height:h+"px", overflow:"hidden"});\r
-                               this._mouseInterface = canvas.contentLayer;\r
-          canvas.contentLayer.applet = this;\r
-        } else {\r
-                               this._mouseInterface = this._getLayer("front", container, w, h, false);\r
-        }\r
-                               //this._getLayer("rear", container, w, h, true);\r
-                               //Jmol._$(canvas.id).css({background:"rgb(0,0,0,0.001)", "z-index":Jmol._z.main}); \r
-                       } else {\r
-                               this._mouseInterface = canvas;\r
-                       }\r
-                       Jmol._jsSetMouse(this._mouseInterface);\r
-               }\r
-    \r
-    proto._getLayer = function(name, container, w, h, isOpaque) {\r
-               var c = document.createElement("canvas");\r
-                       this._canvas[name + "Layer"] = c;\r
-                       c.style.width = "100%";\r
-                       c.style.height = "100%";\r
-                       c.id = this._id + "_" + name + "Layer";\r
-                       c.width = w;\r
-                       c.height = h; // w and h used in setScreenDimension\r
-                       container.append(c);\r
-                       c.applet = this;\r
-                       Jmol._$(c.id).css({background:(isOpaque ? "rgb(0,0,0,1)" : "rgb(0,0,0,0.001)"), "z-index": Jmol._getZ(this,name),position:"absolute",left:"0px",top:"0px",overflow:"hidden"});\r
-                       return c;       \r
-    }\r
-    \r
-    \r
-               proto._setupJS = function() {\r
-                       window["j2s.lib"] = {\r
-                               base : this._j2sPath + "/",\r
-                               alias : ".",\r
-                               console : this._console,\r
-                               monitorZIndex : Jmol._getZ(this, "monitorZIndex")\r
-                       };\r
-                       var isFirst = (__execStack.length == 0);\r
-                       if (isFirst)\r
-                               Jmol._addExec([this, __loadClazz, null, "loadClazz"]);\r
-      this._addCoreFiles();\r
-                       Jmol._addExec([this, this.__startAppletJS, null, "start applet"])\r
-                       this._isSigned = true; // access all files via URL hook\r
-                       this._ready = false; \r
-                       this._applet = null;\r
-                       this._canScript = function(script) {return true;};\r
-                       this._savedOrientations = [];\r
-                       __execTimer && clearTimeout(__execTimer);\r
-                       __execTimer = setTimeout(__nextExecution, __execDelayMS);\r
-               };\r
-\r
-               proto.__startAppletJS = function(applet) {\r
-                       if (Jmol._version.indexOf("$Date: ") == 0)\r
-                               Jmol._version = (Jmol._version.substring(7) + " -").split(" -")[0] + " (JSmol/j2s)"\r
-                       var viewerOptions = Clazz._4Name("java.util.Hashtable").newInstance();\r
-                       Jmol._setAppletParams(applet._availableParams, viewerOptions, applet.__Info, true);\r
-                       viewerOptions.put("appletReadyCallback","Jmol._readyCallback");\r
-                       viewerOptions.put("applet", true);\r
-                       viewerOptions.put("name", applet._id);// + "_object");\r
-                       viewerOptions.put("syncId", Jmol._syncId);\r
-                       if (Jmol._isAsync)\r
-                               viewerOptions.put("async", true);\r
-                       if (applet._color) \r
-                               viewerOptions.put("bgcolor", applet._color);\r
-                       if (applet._startupScript)\r
-                               viewerOptions.put("script", applet._startupScript)\r
-                       if (Jmol._syncedApplets.length)\r
-                               viewerOptions.put("synccallback", "Jmol._mySyncCallback");\r
-                       viewerOptions.put("signedApplet", "true");\r
-                       viewerOptions.put("platform", applet._platform);\r
-                       if (applet._is2D)\r
-                               viewerOptions.put("display",applet._id + "_canvas2d");\r
-\r
-                       // viewerOptions.put("repaintManager", "J.render");\r
-                       viewerOptions.put("documentBase", document.location.href);\r
-                       var codePath = applet._j2sPath + "/";\r
-      \r
-                       if (codePath.indexOf("://") < 0) {\r
-                               var base = document.location.href.split("#")[0].split("?")[0].split("/");\r
-                               if (codePath.indexOf("/") == 0)\r
-                                       base = [base[0], codePath.substring(1)];\r
-                               else\r
-                                       base[base.length - 1] = codePath;\r
-                               codePath = base.join("/");\r
-                       }\r
-                       viewerOptions.put("codePath", codePath);\r
-                       Jmol._registerApplet(applet._id, applet);\r
-                       try {\r
-                               applet._newApplet(viewerOptions);\r
-                       } catch (e) {\r
-                               System.out.println((Jmol._isAsync ? "normal async abort from " : "") + e);\r
-                               return;\r
-                       }\r
-      \r
-                       applet._jsSetScreenDimensions();\r
-                       __nextExecution();\r
-               };\r
-\r
-    if (!proto._restoreState)\r
-               proto._restoreState = function(clazzName, state) {\r
-        // applet-dependent\r
-                 }\r
-       \r
-               proto._jsSetScreenDimensions = function() {\r
-                               if (!this._appletPanel)return\r
-                               // strangely, if CTRL+/CTRL- are used repeatedly, then the\r
-                               // applet div can be not the same size as the canvas if there\r
-                               // is a border in place.\r
-                               var d = Jmol._getElement(this, (this._is2D ? "canvas2d" : "canvas"));\r
-                               this._appletPanel.setScreenDimension(d.width, d.height);\r
-               };\r
-\r
-               proto._show = function(tf) {\r
-                       Jmol.$setVisible(Jmol.$(this,"appletdiv"), tf);\r
-                       if (tf)\r
-                               Jmol._repaint(this, true);\r
-               };\r
-\r
-               proto._canScript = function(script) {return true};\r
-\r
-//             proto._delay = function(eval, sc, millis) {\r
-//    alert("_delay???")\r
-//             // does not take into account that scripts may be added after this and\r
-//             // need to be cached.\r
-//                     this._delayID = setTimeout(function(){eval.resumeEval(sc,false)}, millis);              \r
-//             }\r
-/*\r
-               proto._createDomNode = function(id, data) { // moved to org.jmol.adapter.readers.xml.XmlReader.java\r
-                       id = this._id + "_" + id;\r
-                       var d = document.getElementById(id);\r
-                       if (d)\r
-                               document.body.removeChild(d);\r
-                       if (!data)\r
-                               return;\r
-                       if (data.indexOf("<?") == 0)\r
-                               data = data.substring(data.indexOf("<", 1));\r
-                       if (data.indexOf("/>") >= 0) {\r
-                               // no doubt there is a more efficient way to do this.\r
-                               // Firefox, at least, does not recognize "/>" in HTML blocks\r
-                               // that are added this way.\r
-                               var D = data.split("/>");\r
-                               for (var i = D.length - 1; --i >= 0;) {\r
-                                       var s = D[i];\r
-                                       var pt = s.lastIndexOf("<") + 1;\r
-                                       var pt2 = pt;\r
-                                       var len = s.length;\r
-                                       var name = "";\r
-                                       while (++pt2 < len) {\r
-                                               if (" \t\n\r".indexOf(s.charAt(pt2))>= 0) {\r
-                                                       var name = s.substring(pt, pt2);\r
-                                                       D[i] = s + "></"+name+">";\r
-                                                       break;\r
-                                               }               \r
-                                       }\r
-                               }\r
-                               data = D.join('');\r
-                       }\r
-                       d = document.createElement("_xml")\r
-                       d.id = id;\r
-                       d.innerHTML = data;\r
-                       d.style.display = "none";\r
-                       document.body.appendChild(d);\r
-                       return d;\r
-               }               \r
-*/\r
-               proto.equals = function(a) { return this == a };\r
-               proto.clone = function() { return this };\r
-               proto.hashCode = function() { return parseInt(this._uniqueId) };  \r
-\r
-\r
-               proto._processGesture = function(touches) {\r
-                       return this._appletPanel.processTwoPointGesture(touches);\r
-               }\r
-\r
-               proto._processEvent = function(type, xym) {\r
-                       this._appletPanel.processMouseEvent(type,xym[0],xym[1],xym[2],System.currentTimeMillis());\r
-               }\r
-\r
-               proto._resize = function() {\r
-                       var s = "__resizeTimeout_" + this._id;\r
-                       // only at end\r
-                       if (Jmol[s])\r
-                               clearTimeout(Jmol[s]);\r
-                       var me = this;\r
-                       Jmol[s] = setTimeout(function() {Jmol._repaint(me, true);Jmol[s]=null}, 100);\r
-               }\r
-\r
-               return proto;\r
-       };\r
-\r
-       Jmol._repaint = function(applet, asNewThread) {\r
-               // asNewThread: true is from RepaintManager.repaintNow()\r
-               // false is from Repaintmanager.requestRepaintAndWait()\r
-               // called from apiPlatform Display.repaint()\r
-\r
-               //alert("_repaint " + Clazz.getStackTrace())\r
-               if (!applet || !applet._appletPanel)return;\r
-\r
-               // asNewThread = false;\r
-               var container = Jmol.$(applet, "appletdiv");\r
-               var w = Math.round(container.width());\r
-               var h = Math.round(container.height());\r
-               if (applet._is2D && (applet._canvas.width != w || applet._canvas.height != h)) {\r
-                       applet._newCanvas(true);\r
-                       applet._appletPanel.setDisplay(applet._canvas);\r
-               }\r
-               applet._appletPanel.setScreenDimension(w, h);\r
-    var f = function(){\r
-      if (applet._appletPanel.paint)\r
-        applet._appletPanel.paint(null);\r
-      else\r
-        applet._appletPanel.update(null)\r
-    };\r
-               if (asNewThread) {\r
-                       setTimeout(f);\r
-               } else {\r
-      f();\r
-               }\r
-               // System.out.println(applet._appletPanel.getFullName())\r
-       }\r
-\r
-       Jmol._getHiddenCanvas = function(applet, id, width, height, forceNew) {\r
-               id = applet._id + "_" + id;\r
-               var d = document.getElementById(id);\r
-               if (d && forceNew) {\r
-                       d = null;\r
-               }\r
-               if (!d)\r
-                       d = document.createElement( 'canvas' );\r
-                       // for some reason both these need to be set, or maybe just d.width?\r
-               d.width = d.style.width = width;\r
-               d.height = d.style.height = height;\r
-               // d.style.display = "none";\r
-               if (d.id != id) {\r
-                       d.id = id;\r
-               }\r
-               return d;\r
-       }\r
-\r
-       Jmol._loadImage = function(platform, echoNameAndPath, bytes, fOnload, image) {\r
-       // bytes would be from a ZIP file -- will have to reflect those back from\r
-       // server as an image after conversion to base64\r
-       // ah, but that's a problem, because that image would be needed to be\r
-       // posted, but you can't post an image call.\r
-       // so we would have to go with <image data:> which does not work in all\r
-       // browsers. Hmm.\r
-\r
-               var path = echoNameAndPath[1];\r
-\r
-               if (image == null) {\r
-                       var image = new Image();\r
-                       image.onload = function() {Jmol._loadImage(platform, echoNameAndPath, null, fOnload, image)};\r
-\r
-                       if (bytes != null) {      \r
-                               bytes = J.io.Base64.getBase64(bytes).toString();      \r
-                               var filename = path.substring(url.lastIndexOf("/") + 1);                                    \r
-                               var mimetype = (filename.indexOf(".png") >= 0 ? "image/png" : filename.indexOf(".jpg") >= 0 ? "image/jpg" : "");\r
-                                // now what?\r
-                       }\r
-                       image.src = path;\r
-                       return true; // as far as we can tell!\r
-               }\r
-               var width = image.width;\r
-               var height = image.height; \r
-               var id = "echo_" + echoNameAndPath[0];  \r
-               var canvas = Jmol._getHiddenCanvas(platform.vwr.html5Applet, id, width, height, true);\r
-               canvas.imageWidth = width;\r
-               canvas.imageHeight = height;\r
-               canvas.id = id;\r
-               canvas.image=image;\r
-               Jmol._setCanvasImage(canvas, width, height);\r
-               // return a null canvas and the error in path if there is a problem\r
-               fOnload(canvas,path);\r
-       };\r
-\r
-       Jmol._setCanvasImage = function(canvas, width, height) {\r
-    // called from org.jmol.awtjs2d.Platform\r
-               canvas.buf32 = null;\r
-               canvas.width = width;\r
-               canvas.height = height;\r
-               canvas.getContext("2d").drawImage(canvas.image, 0, 0, width, height);\r
-       };\r
-\r
-})(Jmol);\r
+// JSmol.js -- Jmol pure JavaScript version
+// author: Bob Hanson, hansonr@stolaf.edu      4/16/2012
+// author: Takanori Nakane biochem_fan 6/12/2012
+
+// BH 3/28/2015 6:18:33 AM refactoring to generalize for non-Jmol-related SwingJS applications
+// BH 9/6/2014 5:42:32 PM  two-point gestures broken
+// BH 5/8/2014 11:16:40 AM j2sPath starting with "/" fails to add idiom
+// BH 1/16/2014 8:44:03 PM   __execDelayMS = 100; // FF bug when loading into a tab that is not 
+//                           immediately focused and not using jQuery for adding the applet and having  
+//                           multiple applets.
+// BH 12/6/2013 10:12:30 AM adding corejmoljsv.z.js
+// BH 9/17/2013 10:18:40 AM  file transfer functions moved to JSmolCore 
+// BH 3/5/2013 9:54:16 PM added support for a cover image: Info.coverImage, coverScript, coverTitle, deferApplet, deferUncover
+// BH 1/3/2013 4:54:01 AM mouse binding should return false -- see d.bind(...), and d.bind("contextmenu") is not necessary
+
+// This library requires prior inclusion of 
+
+//  jQuery 9 or higher
+//     JSmoljQueryExt.js
+//     JSmolCore.js
+//  j2sjmol.js    (Clazz and associated classes)
+
+// these:
+//
+//  JSmolApplet.js
+//  JSmolApi.js
+//  JSmolThree.js
+//  JSmolGLmol.js
+//  
+//  are optional 
+
+;(function (Jmol) {
+
+       Jmol._isAsync = false; // testing only
+       Jmol._asyncCallbacks = {};
+       
+       Jmol._coreFiles = []; // required for package.js
+
+
+///////////////////
+// This section provides an asynchronous loading sequence
+//
+
+// methods and fields starting with double underscore are private to this .js file
+
+  var __clazzLoaded = false;
+       var __execLog = [];
+       var __execStack = [];
+       var __execTimer = 0;
+       var __coreSet = [];
+       var __coreMore = [];
+       var __execDelayMS = 100; // must be > 55 ms for FF
+
+       var __nextExecution = function(trigger) {
+    arguments.length || (trigger = true);
+               delete __execTimer;
+               var es = __execStack;
+               var e;
+               while (es.length > 0 && (e = es[0])[4] == "done")
+                       es.shift();
+               if (es.length == 0)
+                       return;
+               if (!Jmol._isAsync && !trigger) {
+                       setTimeout(__nextExecution,10)
+                       return;
+               }
+               e.push("done");
+               var s = "JSmol exec " + e[0]._id + " " + e[3] + " " + e[2];
+               if (self.System)
+                       System.out.println(s);
+                       //alert(s)
+               if (self.console)console.log(s + " -- OK")
+               __execLog.push(s);
+               e[1](e[0],e[2]);        
+       };
+
+       var __loadClazz = function(applet) {
+               if (!__clazzLoaded) {
+                       __clazzLoaded = true;
+                       // create the Clazz object
+                       LoadClazz();
+                       if (applet._noMonitor)
+                               Clazz._LoaderProgressMonitor.showStatus = function() {}
+                       LoadClazz = null;
+      if (applet.__Info.uncompressed)
+        Clazz.loadClass(); // for now; allows for no compression 
+                       Clazz._Loader.onGlobalLoaded = function (file) {
+                        // not really.... just nothing more yet to do yet
+                               Clazz._LoaderProgressMonitor.showStatus("Application loaded.", true);
+                               if (!Jmol._debugCode || !Jmol.haveCore) {
+                                       Jmol.haveCore = true;
+                                       __nextExecution();
+                               }
+                       };
+                 // load package.js and j2s/core/core.z.js
+                       Clazz._Loader.loadPackageClasspath("java", null, true, __nextExecution);
+                       return;
+               }
+               __nextExecution();
+       };
+
+       var __loadClass = function(applet, javaClass) {
+               Clazz._Loader.loadClass(javaClass, function() {__nextExecution()});
+       };
+
+       Jmol.showExecLog = function() { return __execLog.join("\n") }; 
+
+       Jmol._addExec = function(e) {
+    e[1] || (e[1] = __loadClass);
+               var s = "JSmol load " + e[0]._id + " " + e[3];
+               if (self.console)console.log(s + "...")
+               __execLog.push(s);   
+               __execStack.push(e);
+       }
+
+       Jmol._addCoreFile = function(type, path, more) {
+  
+    // BH 3/15: idea here is that when both Jmol and JSV are present, 
+    // we want to load a common core file -- jmoljsv.z.js --
+    // instead of just one. Otherwise we do a lot of duplication.
+    // It is not clear how this would play with other concurrent
+    // apps. So this will take some thinking. But the basic idea is that
+    // core file to load is 
+     
+    type = type.toLowerCase().split(".")[0]; // package name only 
+
+    // return if type is already part of the set.    
+               if (__coreSet.join("").indexOf(type) >= 0) return;
+    
+    // create a concatenated lower-case name for a core file that includes
+    // all Java applets on the page
+    
+               __coreSet.push(type);
+               __coreSet.sort();
+               Jmol._coreFiles = [path + "/core/core" + __coreSet.join("") + ".z.js" ];
+               if (more && (more = more.split(" ")))
+                       for (var i = 0; i < more.length; i++)
+                               if (__coreMore.join("").indexOf(more[i]) < 0)
+                                       __coreMore.push(path + "/core/core" + more[i] + ".z.js")
+               for (var i = 0; i < __coreMore.length; i++)
+                       Jmol._coreFiles.push(__coreMore[i]);
+       }               
+
+       Jmol._Canvas2D = function(id, Info, type, checkOnly){
+               // type: Jmol or JSV
+               this._uniqueId = ("" + Math.random()).substring(3);
+               this._id = id;
+               this._is2D = true;
+               this._isJava = false;
+               this._jmolType = "Jmol._Canvas2D (" + type + ")";
+    this._isLayered = Info._isLayered || false;
+    this._isSwing = Info._isSwing || false;
+    this._isJSV = Info._isJSV || false;
+    this._isAstex = Info._isAstex || false;            
+    this._platform = Info._platform || "";
+               if (checkOnly)
+                       return this;
+               window[id] = this;
+               this._createCanvas(id, Info);
+               if (!Jmol._document || this._deferApplet)
+                       return this;
+               this._init();
+               return this;
+       };
+
+       Jmol._setAppletParams = function(availableParams, params, Info, isHashtable) {
+               for (var i in Info)
+                       if(!availableParams || availableParams.indexOf(";" + i.toLowerCase() + ";") >= 0){
+                               if (Info[i] == null || i == "language" && !Jmol.featureDetection.supportsLocalization())
+                                       continue;
+                               if (isHashtable)
+                                       params.put(i, (Info[i] === true ? Boolean.TRUE: Info[i] === false ? Boolean.FALSE : Info[i]))
+                               else
+                                       params[i] = Info[i];
+                       }
+       }     
+        
+       Jmol._jsSetPrototype = function(proto) {
+               proto._init = function() {
+                       this._setupJS();
+                       this._showInfo(true); 
+                       if (this._disableInitialConsole)
+                               this._showInfo(false);
+               };
+
+               proto._createCanvas = function(id, Info, glmol) {
+                       Jmol._setObject(this, id, Info);
+                       if (glmol) {
+                               this._GLmol = glmol;
+                               this._GLmol.applet = this;
+                               this._GLmol.id = this._id;
+                       }      
+                       var t = Jmol._getWrapper(this, true);
+                       if (this._deferApplet) {
+                       } else if (Jmol._document) {
+                               Jmol._documentWrite(t);
+                               this._newCanvas(false);                                 
+                               t = "";
+                       } else {
+                               this._deferApplet = true;
+                               t += '<script type="text/javascript">' + id + '._cover(false)</script>';
+                       }
+                       t += Jmol._getWrapper(this, false);
+                       if (Info.addSelectionOptions)
+                               t += Jmol._getGrabberOptions(this);
+                       if (Jmol._debugAlert && !Jmol._document)
+                               alert(t);
+                       this._code = Jmol._documentWrite(t);
+               };
+
+               proto._newCanvas = function(doReplace) {
+                       if (this._is2D)
+                               this._createCanvas2d(doReplace);
+                       else
+                               this._GLmol.create();
+               };
+
+//////// swingjs.api.HTML5Applet interface    
+    proto._getHtml5Canvas = function() { return this._canvas }; 
+    proto._getWidth = function() { return this._canvas.width }; 
+    proto._getHeight = function() { return this._canvas.height };
+    proto._getContentLayer = function() { return Jmol.$(this, "contentLayer")[0] };
+    proto._repaintNow = function() { Jmol._repaint(this, false) }; 
+////////
+
+
+               proto._createCanvas2d = function(doReplace) {
+                       var container = Jmol.$(this, "appletdiv");
+                       //if (doReplace) {
+      
+                       try {
+                       container[0].removeChild(this._canvas);
+                       if (this._canvas.frontLayer)
+                               container[0].removeChild(this._canvas.frontLayer);
+                       if (this._canvas.rearLayer)
+                               container[0].removeChild(this._canvas.rearLayer);
+                       if (this._canvas.contentLayer)
+                               container[0].removeChild(this._canvas.contentLayer);
+                       Jmol._jsUnsetMouse(this._mouseInterface);
+                       } catch (e) {}
+                       //}
+                       var w = Math.round(container.width());
+                       var h = Math.round(container.height());
+                       var canvas = document.createElement( 'canvas' );
+                       canvas.applet = this;
+                       this._canvas = canvas;
+                       canvas.style.width = "100%";
+                       canvas.style.height = "100%";
+                       canvas.width = w;
+                       canvas.height = h; // w and h used in setScreenDimension
+                       canvas.id = this._id + "_canvas2d";
+                       container.append(canvas);
+                       Jmol._$(canvas.id).css({"z-index":Jmol._getZ(this, "main")});
+                       if (this._isLayered){
+                               var img = document.createElement("div");
+                               canvas.contentLayer = img;
+                               img.id = this._id + "_contentLayer";
+                               container.append(img);
+                               Jmol._$(img.id).css({zIndex:Jmol._getZ(this, "image"),position:"absolute",left:"0px",top:"0px",
+        width:(this._isSwing ? w : 0) + "px", height:(this._isSwing ? h : 0) +"px", overflow:"hidden"});
+        if (this._isSwing) {
+               var d = document.createElement("div");
+          d.id = this._id + "_swingdiv";
+               Jmol._$(this._id + "_appletinfotablediv").append(d);
+                                 Jmol._$(d.id).css({zIndex:Jmol._getZ(this, "rear"),position:"absolute",left:"0px",top:"0px", width:w +"px", height:h+"px", overflow:"hidden"});
+                               this._mouseInterface = canvas.contentLayer;
+          canvas.contentLayer.applet = this;
+        } else {
+                               this._mouseInterface = this._getLayer("front", container, w, h, false);
+        }
+                               //this._getLayer("rear", container, w, h, true);
+                               //Jmol._$(canvas.id).css({background:"rgb(0,0,0,0.001)", "z-index":Jmol._z.main}); 
+                       } else {
+                               this._mouseInterface = canvas;
+                       }
+                       Jmol._jsSetMouse(this._mouseInterface);
+               }
+    
+    proto._getLayer = function(name, container, w, h, isOpaque) {
+               var c = document.createElement("canvas");
+                       this._canvas[name + "Layer"] = c;
+                       c.style.width = "100%";
+                       c.style.height = "100%";
+                       c.id = this._id + "_" + name + "Layer";
+                       c.width = w;
+                       c.height = h; // w and h used in setScreenDimension
+                       container.append(c);
+                       c.applet = this;
+                       Jmol._$(c.id).css({background:(isOpaque ? "rgb(0,0,0,1)" : "rgb(0,0,0,0.001)"), "z-index": Jmol._getZ(this,name),position:"absolute",left:"0px",top:"0px",overflow:"hidden"});
+                       return c;       
+    }
+    
+    
+               proto._setupJS = function() {
+                       window["j2s.lib"] = {
+                               base : this._j2sPath + "/",
+                               alias : ".",
+                               console : this._console,
+                               monitorZIndex : Jmol._getZ(this, "monitorZIndex")
+                       };
+                       var isFirst = (__execStack.length == 0);
+                       if (isFirst)
+                               Jmol._addExec([this, __loadClazz, null, "loadClazz"]);
+      this._addCoreFiles();
+                       Jmol._addExec([this, this.__startAppletJS, null, "start applet"])
+                       this._isSigned = true; // access all files via URL hook
+                       this._ready = false; 
+                       this._applet = null;
+                       this._canScript = function(script) {return true;};
+                       this._savedOrientations = [];
+                       __execTimer && clearTimeout(__execTimer);
+                       __execTimer = setTimeout(__nextExecution, __execDelayMS);
+               };
+
+               proto.__startAppletJS = function(applet) {
+                       if (Jmol._version.indexOf("$Date: ") == 0)
+                               Jmol._version = (Jmol._version.substring(7) + " -").split(" -")[0] + " (JSmol/j2s)"
+                       var viewerOptions = Clazz._4Name("java.util.Hashtable").newInstance();
+                       Jmol._setAppletParams(applet._availableParams, viewerOptions, applet.__Info, true);
+                       viewerOptions.put("appletReadyCallback","Jmol._readyCallback");
+                       viewerOptions.put("applet", true);
+                       viewerOptions.put("name", applet._id);// + "_object");
+                       viewerOptions.put("syncId", Jmol._syncId);
+                       if (Jmol._isAsync)
+                               viewerOptions.put("async", true);
+                       if (applet._color) 
+                               viewerOptions.put("bgcolor", applet._color);
+                       if (applet._startupScript)
+                               viewerOptions.put("script", applet._startupScript)
+                       if (Jmol._syncedApplets.length)
+                               viewerOptions.put("synccallback", "Jmol._mySyncCallback");
+                       viewerOptions.put("signedApplet", "true");
+                       viewerOptions.put("platform", applet._platform);
+                       if (applet._is2D)
+                               viewerOptions.put("display",applet._id + "_canvas2d");
+
+                       // viewerOptions.put("repaintManager", "J.render");
+                       viewerOptions.put("documentBase", document.location.href);
+                       var codePath = applet._j2sPath + "/";
+      
+                       if (codePath.indexOf("://") < 0) {
+                               var base = document.location.href.split("#")[0].split("?")[0].split("/");
+                               if (codePath.indexOf("/") == 0)
+                                       base = [base[0], codePath.substring(1)];
+                               else
+                                       base[base.length - 1] = codePath;
+                               codePath = base.join("/");
+                       }
+                       viewerOptions.put("codePath", codePath);
+                       Jmol._registerApplet(applet._id, applet);
+                       try {
+                               applet._newApplet(viewerOptions);
+                       } catch (e) {
+                               System.out.println((Jmol._isAsync ? "normal async abort from " : "") + e);
+                               return;
+                       }
+      
+                       applet._jsSetScreenDimensions();
+                       __nextExecution();
+               };
+
+    if (!proto._restoreState)
+               proto._restoreState = function(clazzName, state) {
+        // applet-dependent
+                 }
+       
+               proto._jsSetScreenDimensions = function() {
+                               if (!this._appletPanel)return
+                               // strangely, if CTRL+/CTRL- are used repeatedly, then the
+                               // applet div can be not the same size as the canvas if there
+                               // is a border in place.
+                               var d = Jmol._getElement(this, (this._is2D ? "canvas2d" : "canvas"));
+                               this._appletPanel.setScreenDimension(d.width, d.height);
+               };
+
+               proto._show = function(tf) {
+                       Jmol.$setVisible(Jmol.$(this,"appletdiv"), tf);
+                       if (tf)
+                               Jmol._repaint(this, true);
+               };
+
+               proto._canScript = function(script) {return true};
+
+//             proto._delay = function(eval, sc, millis) {
+//    alert("_delay???")
+//             // does not take into account that scripts may be added after this and
+//             // need to be cached.
+//                     this._delayID = setTimeout(function(){eval.resumeEval(sc,false)}, millis);              
+//             }
+/*
+               proto._createDomNode = function(id, data) { // moved to org.jmol.adapter.readers.xml.XmlReader.java
+                       id = this._id + "_" + id;
+                       var d = document.getElementById(id);
+                       if (d)
+                               document.body.removeChild(d);
+                       if (!data)
+                               return;
+                       if (data.indexOf("<?") == 0)
+                               data = data.substring(data.indexOf("<", 1));
+                       if (data.indexOf("/>") >= 0) {
+                               // no doubt there is a more efficient way to do this.
+                               // Firefox, at least, does not recognize "/>" in HTML blocks
+                               // that are added this way.
+                               var D = data.split("/>");
+                               for (var i = D.length - 1; --i >= 0;) {
+                                       var s = D[i];
+                                       var pt = s.lastIndexOf("<") + 1;
+                                       var pt2 = pt;
+                                       var len = s.length;
+                                       var name = "";
+                                       while (++pt2 < len) {
+                                               if (" \t\n\r".indexOf(s.charAt(pt2))>= 0) {
+                                                       var name = s.substring(pt, pt2);
+                                                       D[i] = s + "></"+name+">";
+                                                       break;
+                                               }               
+                                       }
+                               }
+                               data = D.join('');
+                       }
+                       d = document.createElement("_xml")
+                       d.id = id;
+                       d.innerHTML = data;
+                       d.style.display = "none";
+                       document.body.appendChild(d);
+                       return d;
+               }               
+*/
+               proto.equals = function(a) { return this == a };
+               proto.clone = function() { return this };
+               proto.hashCode = function() { return parseInt(this._uniqueId) };  
+
+
+               proto._processGesture = function(touches) {
+                       return this._appletPanel.processTwoPointGesture(touches);
+               }
+
+               proto._processEvent = function(type, xym) {
+                       this._appletPanel.processMouseEvent(type,xym[0],xym[1],xym[2],System.currentTimeMillis());
+               }
+
+               proto._resize = function() {
+                       var s = "__resizeTimeout_" + this._id;
+                       // only at end
+                       if (Jmol[s])
+                               clearTimeout(Jmol[s]);
+                       var me = this;
+                       Jmol[s] = setTimeout(function() {Jmol._repaint(me, true);Jmol[s]=null}, 100);
+               }
+
+               return proto;
+       };
+
+       Jmol._repaint = function(applet, asNewThread) {
+               // asNewThread: true is from RepaintManager.repaintNow()
+               // false is from Repaintmanager.requestRepaintAndWait()
+               // called from apiPlatform Display.repaint()
+
+               //alert("_repaint " + Clazz.getStackTrace())
+               if (!applet || !applet._appletPanel)return;
+
+               // asNewThread = false;
+               var container = Jmol.$(applet, "appletdiv");
+               var w = Math.round(container.width());
+               var h = Math.round(container.height());
+               if (applet._is2D && (applet._canvas.width != w || applet._canvas.height != h)) {
+                       applet._newCanvas(true);
+                       applet._appletPanel.setDisplay(applet._canvas);
+               }
+               applet._appletPanel.setScreenDimension(w, h);
+    var f = function(){
+      if (applet._appletPanel.paint)
+        applet._appletPanel.paint(null);
+      else
+        applet._appletPanel.update(null)
+    };
+               if (asNewThread) {
+                       setTimeout(f);
+               } else {
+      f();
+               }
+               // System.out.println(applet._appletPanel.getFullName())
+       }
+
+       Jmol._getHiddenCanvas = function(applet, id, width, height, forceNew) {
+               id = applet._id + "_" + id;
+               var d = document.getElementById(id);
+               if (d && forceNew) {
+                       d = null;
+               }
+               if (!d)
+                       d = document.createElement( 'canvas' );
+                       // for some reason both these need to be set, or maybe just d.width?
+               d.width = d.style.width = width;
+               d.height = d.style.height = height;
+               // d.style.display = "none";
+               if (d.id != id) {
+                       d.id = id;
+               }
+               return d;
+       }
+
+       Jmol._loadImage = function(platform, echoNameAndPath, bytes, fOnload, image) {
+       // bytes would be from a ZIP file -- will have to reflect those back from
+       // server as an image after conversion to base64
+       // ah, but that's a problem, because that image would be needed to be
+       // posted, but you can't post an image call.
+       // so we would have to go with <image data:> which does not work in all
+       // browsers. Hmm.
+
+               var path = echoNameAndPath[1];
+
+               if (image == null) {
+                       var image = new Image();
+                       image.onload = function() {Jmol._loadImage(platform, echoNameAndPath, null, fOnload, image)};
+
+                       if (bytes != null) {      
+                               bytes = J.io.Base64.getBase64(bytes).toString();      
+                               var filename = path.substring(url.lastIndexOf("/") + 1);                                    
+                               var mimetype = (filename.indexOf(".png") >= 0 ? "image/png" : filename.indexOf(".jpg") >= 0 ? "image/jpg" : "");
+                                // now what?
+                       }
+                       image.src = path;
+                       return true; // as far as we can tell!
+               }
+               var width = image.width;
+               var height = image.height; 
+               var id = "echo_" + echoNameAndPath[0];  
+               var canvas = Jmol._getHiddenCanvas(platform.vwr.html5Applet, id, width, height, true);
+               canvas.imageWidth = width;
+               canvas.imageHeight = height;
+               canvas.id = id;
+               canvas.image=image;
+               Jmol._setCanvasImage(canvas, width, height);
+               // return a null canvas and the error in path if there is a problem
+               fOnload(canvas,path);
+       };
+
+       Jmol._setCanvasImage = function(canvas, width, height) {
+    // called from org.jmol.awtjs2d.Platform
+               canvas.buf32 = null;
+               canvas.width = width;
+               canvas.height = height;
+               canvas.getContext("2d").drawImage(canvas.image, 0, 0, width, height);
+       };
+
+})(Jmol);