JAL-1859 embedded Jmol applet example updated for Jmol 14.2 javascript
[jalview.git] / examples / javascript / jalview.js
1 /**
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10  *  
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  * The Jalview Authors are detailed in the 'AUTHORS' file.
18  */
19
20 // default console to report messages
21 var _console = document.getElementById("stdout");
22 var _jvapps = new Array();
23 // jvjmols is a list associating a jmol id to { modelstofiles }
24 var _jvjmols = new Hashtable();
25 // array of model names used to lookup index in Jmol
26 var _modeltofiles = new Array();
27 // counter for jmol structures
28 var mnum = 1;
29
30 function getDocumentBase() {
31         var dburi = document.baseURI;
32         // IE does not support document.baseURI
33         // logic from patch to TYPO3:
34         // http://forge.typo3.org/projects/typo3cms-core/repository/revisions/f61358afad28adb6dcaeb270ba480e998dfb0b79/diff/typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js
35         if (!dburi) {
36                 var baseTags = document.getElementsByTagName('base');
37                 if (baseTags.length > 0) {
38                         dburi = baseTags[0].href;
39                 } else {
40                         dburi = document.URL;
41                 }
42         }
43         return dburi.substring(0, dburi.lastIndexOf("/") + 1);
44 }
45 function setConsole(console) {
46         _console = console;
47 }
48
49 function getDestinationFrms(source, frames) {
50         var frms = new Array();
51         var frid = "";
52         for (frm in frames) {
53                 try {
54                         frid = (source!=null) && (("" + source.getSequenceSetId()) == ("" + frames[frm].currentAlignFrame
55                                         .getSequenceSetId()));
56                 } catch (q) {
57                 };
58                 
59                 if (!frames[frm].equals(source) && !frid
60                                 && !frames[frm].currentAlignFrame.equals(source)) {
61                         frms[frms.length] = frames[frm];
62                 }
63         }
64         return frms;
65 }
66
67 function mouseover(list1, list2, list3, list4) {
68         // list1 = new Object(list1);
69         var list = new Array(("" + list1), ("" + list2), ("" + list3), ("" + list4));
70         var msg = "Mouse over :\n" + "AlignFrame obj: " + list1 + " Seq : "
71                         + list[1] + "\nPos: " + list[2] + "(" + list[3] + ")\n";
72
73         var flist = getDestinationFrms(list1, _jvapps);
74         if (_console) {
75                 _console.value = msg + "\n";
76         }
77
78         for (follower in flist) {
79                 if (_console) {
80                         _console.value += "Sending to " + flist[follower] + "\n";
81                 }
82                 flist[follower].highlight(list[1], list[2], "true");
83         }
84         return true;
85 }
86
87 function sellist(list1, list2, list3, list4) {
88         // list1 = new Object(list1);
89         var list = new Array(("" + list1), ("" + list2), ("" + list3), ("" + list4));
90         var msg = "Selection:\n" + "AlignFrame obj: " + list[0] + " id : "
91                         + list[1] + "\nSeqs " + list[2] + "\nColumns " + list[3] + "\n";
92         var flist = getDestinationFrms(list1, _jvapps);
93         if (_console) {
94                 _console.value = msg + "\n";
95         }
96         
97         for (follower in flist) {
98                 if (_console) {
99                         _console.value += "Sending to " + flist[follower] + "\n";
100                 }
101                 flist[follower].selectIn(flist[follower].getDefaultTargetFrame(),
102                                 list[2], list[3])
103         }
104         return true;
105 }
106
107 function viewlist(list1, list2, list3, list4) {
108         // list1 = new Object(list1);
109         var list = new Array(("" + list1), ("" + list2), ("" + list3), ("" + list4));
110         var msg = "Viewport extent change::\n" + "AlignFrame obj: " + list[0]
111                         + " id : " + list[1] + "\nRow from " + list[2] + " and to "
112                         + list[3] + "\nVisible columns: " + list[4] + "\n";
113         var flist = getDestinationFrms(list1, _jvapps);
114         if (_console) {
115                 _console.value = msg + "\n";
116         }
117
118         for (follower in flist) {
119                 if (_console) {
120                         _console.value += "Sending to " + flist[follower] + "\n";
121                 }
122                 flist[follower].scrollToViewIn(flist[follower].getDefaultTargetFrame(),
123                                 list[2], "-1");
124         }
125         return true;
126 }
127
128 // register a jalview applet and add some handlers to it
129 // jmolView is a reference to a jmol applet that is displaying the PDB files listed (in order) in the modeltofiles Array
130 function linkJvJmol(applet, jmolView, modeltofiles) {
131         var i = _jvapps.length;
132         while (i--) {
133                 if (_jvapps[i].equals(applet)) {
134                         throw ("Ignoring additional linkJvJmol call for "
135                                         + applet.getName() + ".");
136                 }
137         }
138         _jvapps[_jvapps.length] = applet;
139         applet.setMouseoverListener("mouseover");
140         applet.setSelectionListener("sellist");
141         // viewListener not fully implemented in 2.7
142         // try { applet.setViewListener("viewlist"); } catch (err) {};
143         if (jmolView)
144         {
145                 var sep = applet.getSeparator();
146                 var oldjm=jmolView;
147                 // recover full id of Jmol applet
148 //              jmolView=_jmolGetApplet(jmolView).id; // Jmol 12.4
149                 jmolView=JmolFindTarget(jmolView).id; // Jmol 14.2.14
150                 alert("FoundTarget " + jmolView.id);
151                 var jmbinding=_jvjmols.get(jmolView);
152                 if (!jmbinding)
153                 {       
154                         jmbinding=new Object();
155                         jmbinding._modelstofiles=new Array();
156                         jmbinding._fullmpath=new Array();
157                         jmbinding._filetonum=new Hashtable();
158                         jmbinding._jmol=jmolView;
159                         jmbinding._jmhandle=oldjm;
160                         _jvjmols.put(jmolView,jmbinding);
161                 }
162                 
163                 jmbinding._modelstofiles=jmbinding._modelstofiles.concat(jmbinding._modelstofiles,modeltofiles);
164                 jmbinding._jmol=jmolView;
165                 // now update structureListener list
166                 mtf="";
167                 var dbase = getDocumentBase();
168                 for (m in jmbinding._modelstofiles)
169                 { if (m>0) { mtf+=sep; }
170                 mtf+=jmbinding._modelstofiles[m];
171                 if (jmbinding._modelstofiles[m].indexOf("//")==-1)
172                         { jmbinding._fullmpath[m] = dbase+((jmbinding._modelstofiles[m].indexOf("/")==0) ? jmbinding._modelstofiles[m].substring(1) : jmbinding._modelstofiles[m]); }
173                   jmbinding._filetonum.put(jmbinding._modelstofiles[m], m+1); 
174                   jmbinding._filetonum.put(jmbinding._fullmpath[m], m+1);
175                   
176                   }
177                 applet.setStructureListener("_structure", mtf);
178         }
179 }
180
181 /*function _addJmolModel(jmolid, modelname) {
182         modelname=""+modelname;
183         var jminf = _jvjmols[jmolid];
184         if (!jminf) {
185                 jminf = new Object();
186                 jminf._modelstofiles = new Array(); //new Hashtable();
187                 jminf._jmol = jmolid;
188                 jminf._modellist=new Array();
189                 _jvjmols[jmolid] = jminf;
190         }
191         var obj = new Object();
192         jminf._modeltofiles[modelname] = obj; // .put(modelname, obj);
193         obj.id = modelname;
194         obj.mnum = jminf._modeltofiles.length;
195         jminf._modellist+=modelname;
196 }*/
197
198
199
200 // jmol Jalview Methods
201
202 function _structure(list1, list2, list3, list4) {
203         var follower;
204         // if (_console) { if (!_console.value) { _console.value="";} }
205         if (list1 == "mouseover") {
206                 var list = new Array(("" + list1), ("" + list2), ("" + list3),
207                                 ("" + list4));
208                 // 1 is pdb file, 2 is residue number, 3 is chain
209                 // list1 = new Object(list1);
210                 var base = list[1].indexOf(getDocumentBase()); // .indexOf(_path);
211                 if (base==0) { base = getDocumentBase(); }
212                 var sid = list[1]; // .substring(base);
213                 base = list[1].substring(0, base);
214                 if (_console) {
215                         _console.value += "Model is " + list[1] + ", Structure id is : "
216                                         + sid + "\n";
217                 }
218                 ;
219                 var siddat;
220                 for ( var jmolappi in _jvjmols.values()) {
221                         var jmolapp=_jvjmols.values()[jmolappi];
222                         var msg = "";
223                         if (siddat = jmolapp._filetonum.get(sid)) {
224                                 // we don't putin chain number because there isn't one ?
225                                 // skip select 0 bit
226                                 var ch = ""+list[3];
227                                 if ((""+list[2]).trim().length==1)
228                                         {
229                                         ch+=":"+list[2];
230                                         }
231                                 msg = "select (" + ch + " /" + siddat + ") ;";
232                         }
233                         if (msg) {
234                                 if (_console) {
235                                         _console.value += "Sending '" + msg + "' to jmol." + "\n";
236                                 }
237                         }
238                         jmolScriptWait(msg, "" + jmolapp._jmhandle);
239                         // only do highlight for one jmol ?
240                         // return 1;
241                 }
242         }
243         if (list1 == "colourstruct") {
244                 if (_console) {
245                         _console.value += 'colourStruct("' + list1 + '","' + list2
246                         + '") [' + list4 + ']' + "\n";
247                 }
248                 setTimeout('colourStruct("'+list4+'","' + list1 + '","' + list2 + '")', 1);
249                 return 1;
250         }
251         return 1;
252 }
253 // last colour message
254 var _lastMsg = "";
255 // indicator - if _colourStruct==0 then no colouring is going on
256 var _colourStruct = 0;
257
258 function colourStruct(involves, msg, handle) {
259         if (_colourStruct == 0) {
260                 _colourStruct = 1;
261                 for (ap in _jvapps) {
262                         var _msg = "";
263                         do {
264                                 if (_msg.match(/\S/)) {
265                                         _lastMsg += _msg;
266                                 }
267                                 _msg = "" + _jvapps[ap].getJsMessage(msg, handle);
268                         } while (_msg.match(/\S/));
269                 }
270                 // locate the jmol that should get the message
271                 for (var jmol in _jvjmols.values())
272                         {
273                         var jml=_jvjmols.values()[jmol];
274                         if (jml._filetonum.get(involves))
275                                 {
276                                         colourStructs(jml._jmhandle);
277                                 }
278                         }
279                 _colourStruct = 0;
280         } else {
281                 // setTimeout('colourStruct("'+msg+'","'+handle+'")',3);
282         }
283 }
284
285 function colourStructs(jmolapp) {
286         dbg(0, "Colouring the structures\n");
287         jmolScriptWait("set selectionhalos false;" + _lastMsg
288                         + "; select 0; set selectionhalos true;", jmolapp);
289         _lastMsg = "";
290 }
291 var _jmolhovermsg="";
292 function _jmolhover(jmid, atomlabel, atomidx) {
293         var msg=""+jmid+" "+atomlabel+" "+atomidx;
294         if (_jmolhovermsg==msg)
295                 {
296                 return;
297                 }
298         _jmolhovermsg=msg;
299         modeltofiles = _jvjmols.get(jmid)._modelstofiles;
300         // atomlabel=(""+atomlabel).match(/\[(.+)\](\d+):(.)\.(\S+)\s*\/(\d+)\..+/);
301         // relaxed third parameter - may be null or a model number for multi model
302         // views
303         atomlabel = ("" + atomlabel)
304                         .match(/\[(.+)\](\d+):(.)\.([^\/]+)(\/\d+\.|).+/);
305         atomidx = "" + atomidx;
306         if (atomlabel[5]) {
307                 atomlabel[5] = atomlabel[5].match(/\/(.+)\./)[1];
308                 atomlabel[5] = parseInt(atomlabel[5])-1;
309         } else {
310                 // default - first model
311                 atomlabel[5] = 0;
312         }
313         // use atomlabel[5] to look up model filename so we can highlight associated positions in any jalviews
314         for (ap in _jvapps) {
315                 _jvapps[ap].mouseOverStructure(atomlabel[2], atomlabel[3],
316                                 getDocumentBase()
317                                                 + "/" + 
318                                                 modeltofiles[atomlabel[5]]);
319                 msg = _jmolhovermsg;
320         }
321 }
322 function _jmolpick(jmid, atomlabel, atomidx) {
323         atomlabel = "" + atomlabel;
324         atomidx = "" + atomidx;
325         // label is atom id, atom number, and xyz coordinates in the form:
326         // C6 #6 -0.30683374 -1.6836332 -0.716934
327         // atom index, starting with 0.
328
329 }
330 function _jmolMessagecallback(jmid, statmess) {
331         // if (statmess.indexOf("Script Terminated")==0)
332         {
333                 var thisTime = new Date();
334                 if (_console) {
335                         _console.value += "Last script execution took : "
336                                         + (thisTime.valueOf() - _lastTime.valueOf()) / 1000.0
337                                         + " seconds.";
338                 }
339                 _lastTime = thisTime;
340
341         }
342 }