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