biojs-vis-pdbviewer
Version:
A BioJS 2.0 component to view protein structures
608 lines (535 loc) • 18.1 kB
JavaScript
/*
* JSpecView Utility functions
* Version 2.0, Copyright(c) 2006-2012, Dept of Chemistry, University of the West Indies, Mona
* Robert J Lancashire robert.lancashire@uwimona.edu.jm
*
*
* 12:19 PM 3/8/2012 added support for JSpecViewAppletPro -- BH
* 5/21/2012 -- incorporated as JmolJSV.js into Jmol
*
*/
// BH 2/2/2014 11:39:44 AM Jmol/JSME/JSV working triad
// BH 1/30/2014 1:04:09 PM adds Info.viewSet
// BH 10/10/2013 1:25:28 PM JSV HTML5 option
/*
Inserts the JSpecView applet in any compatible User Agent using the <object> tag
uses IE conditional comments to distinguish between IE and Mozilla
see http://msdn.microsoft.com/workshop/author/dhtml/overview/ccomment_ovw.asp
*/
;(function (Jmol, document, $) {
Jmol._JSVApplet = function(id, Info, checkOnly){
this._version="2.0";
this._jmolType = "Jmol._JSVApplet" + (Info.isSigned ? " (signed)" : "");
this._viewType = "JSV";
this._id = id;
this._uniqueId = ("" + Math.random()).substring(3);
this._isJava = true;
Jmol._setObject(this, id, Info);
this._startupScript = Jmol._JSVApplet.getStartupScript(this, Info);
this._syncKeyword = "JSpecView:"
if (checkOnly)
return this;
this._width = Info.width;
this._height = Info.height;
this._isSigned = Info.isSigned;
this._isJava = true;
this._isPro = this._isSigned;
this._dataMultiplier=1;
this._hasOptions = Info.addSelectionOptions;
this._info = "";
this._infoHeader = this._jmolType + ' "' + this._id + '"'
this._defaultModel = Info.defaultModel;
this._readyFunction = Info.readyFunction;
this._ready = false;
this._applet = null;
this._jarFile = Info.jarFile || (Info.isSigned ? "JSpecViewAppletSigned.jar" : "JSpecViewApplet.jar");
this._jarPath = Info.jarPath || "java";
this._memoryLimit = Info.memoryLimit || 512;
this._canScript = function(script) {return true;};
this._containerWidth = this._width + ((this._width==parseFloat(this._width))? "px":"");
this._containerHeight = this._height + ((this._height==parseFloat(this._height))? "px":"");
this._initialize = function(codebaseDirectory, fileNameOrUseSignedApplet) {
Jmol.controls == undefined || Jmol.controls._onloadResetForms();
}
this._create(id, Info);
return this;
}
;(function (Applet, proto) {
Applet._get = function(id, Info, checkOnly) {
// note that the variable name the return is assigned to MUST match the first parameter in quotes
// applet = Jmol.getJSVApplet("applet", Info)
Info || (Info = {});
var DefaultInfo = {
width: 800,
height: 300,
debug: false,
color: "#A0A0A0",
jarPath: "java",
jarFile: "JSpecViewApplet.jar",
j2sPath: "j2s",
use: "HTML5",
isSigned: false,
initParams: null,
readyFunction: null,
script: null
};
Jmol._addDefaultInfo(Info, DefaultInfo);
Info.serverURL && (Jmol._serverUrl = Info.serverURL);
var javaAllowed = false;
var applet = null;
var List = Info.use.toUpperCase().split("#")[0].split(" ");
for (var i = 0; i < List.length; i++) {
switch (List[i]) {
case "JAVA":
javaAllowed = true;
if (Jmol.featureDetection.supportsJava())
applet = new Applet(id, Info, checkOnly);
break;
case "WEBGL":
case "HTML5":
Jmol._Canvas2D.prototype = Jmol._jsSetPrototype(new Applet(id,Info, true));
applet = new Jmol._Canvas2D(id, Info, "JSV", checkOnly);
break;
}
if (applet != null)
break;
}
if (applet == null) {
if (checkOnly || !javaAllowed)
applet = {_jmolType : "none" };
else if (javaAllowed)
applet = new Applet(id, Info);
}
return (checkOnly ? applet : Jmol._registerApplet(id, applet));
}
Applet.getStartupScript = function(applet, Info) {
return (Info.initParams ? Info.initParams : "")
+ ';appletID ' + applet._id + ';syncID '+ Jmol._syncId
+ ';backgroundcolor ' + applet._color
+ ';appletReadyCallbackFunctionName Jmol._readyCallback'// + applet._id + '._readyCallback'
+ ';syncCallbackFunctionName Jmol._mySyncCallback;';
}
proto._create = function(id, Info){
Jmol._setObject(this, id, Info);
this._startupScript = Applet.getStartupScript(this, Info);
var params = {
boxbgcolor: this._color,
boxfgcolor: "white",
syncId: Jmol._syncId,
code:"jspecview.applet.JSVApplet" + (this._isSigned ? "Pro" : "")
};
Jmol._Applet._createApplet(this, Info, params);
}
proto._readyCallback = function(id, fullid, isReady, applet) {
if (!isReady)
return; // ignore -- page is closing
this._ready = true;
this._applet = applet;
this._readyScript && setTimeout(id + "._script(" + id + "._readyScript)",50);
this._showInfo(true);
this._showInfo(false);
this._readyFunction && this._readyFunction(this);
Jmol.Cache.setDragDrop(this);
Jmol._setReady(this);
}
proto._checkDeferred = function(script) {
return false;
}
proto._scriptLoad = function(file, script, _jsv_scriptLoad) {
script || (script = "");
var doscript = (this._isJava || !this._noscript);
if (!this._isSigned || this._viewSet != null)
return false;
if (doscript)
this._script("load \"" + file + "\";" + script);
else
this._applet.openFile(file);
this._checkDeferred("");
return true;
}
proto._clearConsole = Jmol._Applet.prototype._clearConsole;
proto._showInfo = Jmol._Applet.prototype._showInfo;
proto._show = Jmol._Applet.prototype._show;
proto._search = function(query, script){
query || (query = Jmol.$val(Jmol.$(this, "query")))
var a = this;
if (a._viewSet && !query.startsWith("!")) {
a = Jmol.View.applets[a._viewSet];
a = a.Jmol || a.JSV || this;
}
Jmol._search(a, query);
}
proto._searchDatabase = function(query, database) {
return this._applet.runScript("load ID \"" + query + "\" " + database + query)
}
proto._script = function(script) {
if (!this._ready) {
this._readyScript || (this._readyScript = ";");
this._readyScript += ";" + script;
return;
}
this._applet.runScript(script);
}
proto._syncScript = function(script) {
this._applet.syncScript(script);
}
proto._getPropertyAsJSON = function(sKey) {
return "" + this._applet.getPropertyAsJSON(sKey);
}
proto._getPropertyAsJavaObject = function(sKey) {
return this._applet.getPropertyAsJavaObject(sKey);
}
proto._getPropertyAsArray = function(sKey,sValue) {
return Jmol._evalJSON(this._getPropertyAsJSON(sKey,sValue),sKey);
}
proto._resizeApplet = Jmol._Applet.prototype._resizeApplet;
proto._loadFile = function(fileName, params){
this._showInfo(false);
params || (params = "");
this._thisJSVModel = "" + Math.random();
// TODO
// this._script("zap;set echo middle center;echo Retrieving data...");
if (this._jvsIsSigned && this._viewSet == null) {
this._script("load \"" + fileName + "\"" + params);
return;
}
var me = this;
Jmol._loadFileData(this, fileName, function(data){me._loadInline(data)}, function(data){me._loadInline(null)});
}
proto._loadInline = function(data) {
// called when loading JDX data
this._currentView = null;
if (data != null)
this._applet.loadInline(data);
if (this._viewSet != null)
Jmol.View.updateView(this, {data:data});
}
proto._loadModelFromView = function(view, _jsv_loadModelFromView) {
// called request to update view with view.JSV.data==null from Jmol.View
// we must get the simulation from MOL data
this._currentView = view;
var molData = null;
var rec = view.JSV;
var vJmol = view.Jmol;
var vJME = view.JME;
if (!vJME && !vJmol && view.info.chemID == null) {
rec.data = "N/A"; // this has to be a simulation to work
return;
}
var v = null;
if (vJmol) {
molData = vJmol.data;
if (molData ? true : vJmol.applet && vJME && vJME.data)
v = vJmol
}
if (!molData && !v && (v = vJME) != null)
molData = vJME.data;
if (v && !molData) {
// complete Jmol or JME needs first
v.applet._loadModelFromView(view);
return;
}
if (this._getAppletInfo("SOURCEID") == view.info.viewID) {
this._applet.runScriptNow("SELECT ID \"" + view.info.viewID + "\"");
return;
}
// get the simulation into JSpecView
var script = this.__Info.preloadScript;
if (script == null)
script = "CLOSE VIEWS;CLOSE SIMULATIONS > 1";
script += "; LOAD ID \"" + view.info.viewID + "\" APPEND \"http://SIMULATION/MOL=" + molData.replace(/\n/g,"\\n") + "\"";
this._applet.runScriptNow(script);
// update Jmol and/or JME to correspond with the model returned.
molData = this._getAppletInfo("DATA_mol");
if (!molData)
return;
Jmol.View.updateView(this, {chemID:view.info.chemID, data:molData});
this._propagateView(view, molData);
}
proto._propagateView = function(view, molData) {
var vJmol = view.Jmol;
var vJME = view.JME;
if (vJmol) {
vJmol.data = molData;
if (vJmol.applet)
vJmol.applet._loadModelFromView(this._currentView);
if (vJME)
vJME.applet._loadFromJmol(vJmol.applet);
} else if (vJME) {
vJME.data = molData;
vJME.applet._loadModelFromView(this._currentView);
}
this.__selectSpectrum();
}
proto._updateView = function(msgOrPanel, peakData, _jsv_updateView) {
if (this._viewSet == null || !this._applet || msgOrPanel && msgOrPanel.vwr)
return;
// JSV applet will call this, but we don't care for now
if (!peakData) {
// comming from JSmolCore.js -- view not found; new load
// generally we will IGNORE THIS as an actual spectrum load, but if there
// is a MOL file, that should be recognized.
var msg = msgOrPanel;
if (msg && (msg.indexOf("http://SIMULATION" >= 0) || msg.indexOf("cache://") >= 0)) {
var molData = this._getAppletInfo("DATA_mol");
if (molData) {
Jmol.View.updateView(this, { chemID: "", viewID: Jmol._getAttr(msg, "file"), data:molData});
this._propagateView(this._currentView, molData);
}
}
return;
}
// called from file load or panel selection or peak selection
Jmol.View.updateFromSync(this, peakData);
}
proto.__selectSpectrum = function() {
// not entirely clear why this should be necessary, but it is, especially
// after a peak pick
var me = this;
setTimeout(function() {me._applet.runScript("SELECT ID \"" + me._currentView.info.viewID + "\"")},10);
}
proto._updateAtomPick = function(A) {
// from JSmolCore.js
// send the message to JSpecView to highlight a peak;
// will result in a return to _updateView providing a <PeakData record
this._applet.syncScript('<PeakData atom="' + A[0] + '" sourceID="' + this._currentView.info.viewID + '">');
// seems to be necessary when there are two spectra and when this atom is clicked,
// this structure is not yet highlighted.
this.__selectSpectrum();
}
proto._getAppletInfo = function(key) {
return "" + this._applet.getPropertyAsJavaObject(key).get(key)
}
proto.__loadModel = function(data, chemID, viewID) {
// retun from asynchronous call in loadModelFromView
if (data == null)
return;
Jmol.View.updateView(this, {chemID:chemID, data:data, viewID:viewID});
}
proto._showStatus = function(msg, title) {
// from JSV
title && (msg = title + "\n\n\n" + msg);
alert (msg);
}
proto._getSmiles = function() {
return null;
}
})(Jmol._JSVApplet, Jmol._JSVApplet.prototype);
////// additional API for JSpecView ////////////
/**
* returns a Java Map<String, Object>
* -- use key = "" for full set
* -- key can drill down into spectra selecting specific subsets of data
*/
Jmol.jsvGetPropertyAsJavaObject = function(jsvApplet, key) {
return jsvApplet._applet.getPropertyAsJavaObject(key)
}
/**
* returns a JSON equivalent of jsvGetPropertyAsJavaObject
* -- use key = "" for full set
* -- key can drill down into spectra selecting specific subsets of data
*/
Jmol.jsvGetPropertyAsJSON = function(jsvApplet, key) {
return "" + jsvApplet._applet.getPropertyAsJSON(key)
}
Jmol.jsvIsPro = function(jsvApplet) {
return (jsvApplet._applet.isPro() ? true : false);
}
Jmol.jsvIsSigned = function(jsvApplet) {
return (jsvApplet._applet.isSigned() ? true : false);
}
/**
* Returns the calculated colour of a visible spectrum (Transmittance)
*
* @return Color as a string
*/
Jmol.jsvGetSolnColour = function(jsvApplet) {
return "" + jsvApplet._applet.getSolnColour();
}
/**
* Method that can be called from another applet or from javascript to return
* the coordinate of clicked point in the plot area of the <code>
* JSVPanel</code>
*
* @return A String representation of the coordinate
*/
Jmol.jsvGetCoordinate = function(jsvApplet) {
return "" + jsvApplet._applet.getCoordinate();
}
/**
* Delivers spectrum coded as desired: XY, SQZ, PAC, DIF, DIFDUP, FIX, AML, CML
*
* @param type
* @param n -- nth spectrum in set: -1 for current; 0->[nSpec-1] for a specific one
* @return data or "only <nSpec> spectra available"
*
*/
Jmol.jsvExport = function(jsvApplet, exportType, n) {
return "" + jsvApplet._applet.exportSpectrum(exportType, n);
}
/**
* runs a script right now, without queuing it, and returns
* only after completion
* returns TRUE if succesful (ureliably; under development)
*/
Jmol.jsvRunScriptNow = function(jsvApplet, script) {
return (jsvApplet._applet.runScriptNow(script) ? true : false);
}
/**
* runs a script using a queue, possibly waiting until an applet is ready
* same as Jmol.script(jsvApplet, script)
*
* @param script
*/
Jmol.jsvRunScript = function(jsvApplet, script) {
jsvApplet.runScript(script);
}
/**
* Loads in-line JCAMP-DX data into the existing applet window
*
* @param data
* String
*/
Jmol.jsvLoadInline = function(jsvApplet, data, params) {
jsvApplet._loadInline(data);
// currently params are ignored
}
Jmol.jsvSetFilePath = function(jsvApplet, tmpFilePath) {
jsvApplet._applet.setFilePath(tmpFilePath);
}
/**
* Sets the spectrum to the specified block number
* same as SPECTRUMNUMBER n
* @param n -- starting with 1
*/
Jmol.jsvSetSpectrumNumber = function(jsvApplet, n) {
jsvApplet._applet.setSpectrumNumber(n);
}
/**
* toggles the grid on/off
*/
Jmol.jsvToggleGrid = function(jsvApplet) {
jsvApplet._applet.toggleGrid();
}
/**
* toggles the coordinate display
*/
Jmol.jsvToggleCoordinate = function(jsvApplet) {
jsvApplet._applet.toggleCoordinate();
}
/**
* toggles the integration graph on/off
*/
Jmol.jsvToggleIntegration = function(jsvApplet) {
jsvApplet._applet.toggleIntegration();
}
/**
* adds a highlight to a portion of the plot area
*
* @param x1
* the starting x value
* @param x2
* the ending x value
* @param r
* the red portion of the highlight color or -1
* @param g
* the green portion of the highlight color or -1
* @param b
* the blue portion of the highlight color or -1
* @param a
* the alpha portion of the highlight color or -1
*/
Jmol.jsvAddHighlight = function(jsvApplet, x1, x2, r, g, b, a) {
if (arguments.length == 7)
jsvApplet._applet.addHighlight(x1, x2, r, g, b, a);
}
/**
* removes all highlights from the plot area
*/
Jmol.jsvRemoveAllHighlights = function(jsvApplet) {
jsvApplet._applet.removeAllHighlights();
}
/**
* removes a highlight from the plot area
*
* @param x1
* the starting x value
* @param x2
* the ending x value
*/
Jmol.jsvRemoveHighlight = function(jsvApplet, x1, x2) {
jsvApplet._applet.removeHighlight(x1, x2);
}
/**
* Method that can be called from another applet or from javascript that
* toggles reversing the plot on a <code>JSVPanel</code>
*/
Jmol.jsvReversePlot = function(jsvApplet) {
jsvApplet._applet.reversePlot();
}
/**
* Writes a message to the status label
*
* @param msg
* the message
*/
Jmol.jsvWriteStatus = function(jsvApplet, msg) {
jsvApplet._applet.writeStatus(msg);
}
Jmol.jsvSetVisible = function(jsvApplet, TF) {
jsvApplet._applet.setVisible(TF);
}
Jmol.getJSVAppletHtml = function(applet, Info) {
// optional Info here
if (Info) {
var d = Jmol._document;
Jmol._document = null;
applet = Jmol.getJSVApplet(applet, Info);
Jmol._document = d;
}
return applet._code;
}
Jmol._newGrayScaleImage = function(context, image, width, height, grayBuffer) {
var c;
if (image == null) {
var id = ("" + Math.random()).substring(3);
c = document.createElement("canvas");
c.id = id;
c.style.width = width + "px";
c.style.height = height + "px";
c.width = width;
c.height = height;
var appId = context.canvas.applet._id;
var layer = document.getElementById(appId + "_imagelayer");
image = new Image();
image.canvas = c;
image.appId = appId;
image.id = appId + "_image";
image.layer = layer;
image.w = width;
image.h = height;
image.onload = function(e) {
try {
URL.revokeObjectURL(image.src);
} catch (e) {}
};
var div = document.createElement("div");
image.div = div;
div.style.position="relative";
layer.appendChild(div);
div.appendChild(image);
}
c = image.canvas.getContext("2d");
var imageData = c.getImageData(0, 0, width, height);
var buf = imageData.data;
var ng = grayBuffer.length;
var pt = 0;
for (var i = 0; i < ng; i++) {
buf[pt++] = buf[pt++] = buf[pt++] = grayBuffer[i];
buf[pt++] = 0xFF;
}
c.putImageData(imageData, 0, 0);
image.canvas.toBlob(function(blob){image.src = URL.createObjectURL(blob)});
return image;
}
})(Jmol, document, jQuery);