JAL-2759 Keep numColumns up to date
[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=jmolFindTarget(jmolView)._id; // Jmol 14.2.14
157                 var jmbinding=_jvjmols.get(jmolView);
158                 if (!jmbinding)
159                 {       
160                         jmbinding=new Object();
161                         jmbinding._modelstofiles=new Array();
162                         jmbinding._fullmpath=new Array();
163                         jmbinding._filetonum=new Hashtable();
164                         jmbinding._jmol=jmolView;
165                         jmbinding._jmhandle=oldjm;
166                         _jvjmols.put(jmolView,jmbinding);
167                 }
168                 
169                 jmbinding._modelstofiles=jmbinding._modelstofiles.concat(jmbinding._modelstofiles,modeltofiles);
170                 jmbinding._jmol=jmolView;
171                 // now update structureListener list
172                 mtf="";
173                 var dbase = getDocumentBase();
174                 for (m in jmbinding._modelstofiles)
175                 { if (m>0) { mtf+=sep; }
176                 mtf+=jmbinding._modelstofiles[m];
177                 if (jmbinding._modelstofiles[m].indexOf("//")==-1)
178                         { jmbinding._fullmpath[m] = dbase+((jmbinding._modelstofiles[m].indexOf("/")==0) ? jmbinding._modelstofiles[m].substring(1) : jmbinding._modelstofiles[m]); }
179                   jmbinding._filetonum.put(jmbinding._modelstofiles[m], m+1); 
180                   jmbinding._filetonum.put(jmbinding._fullmpath[m], m+1);
181                   
182                   }
183                 applet.setStructureListener("_structure", mtf);
184         }
185 }
186
187 /*function _addJmolModel(jmolid, modelname) {
188         modelname=""+modelname;
189         var jminf = _jvjmols[jmolid];
190         if (!jminf) {
191                 jminf = new Object();
192                 jminf._modelstofiles = new Array(); //new Hashtable();
193                 jminf._jmol = jmolid;
194                 jminf._modellist=new Array();
195                 _jvjmols[jmolid] = jminf;
196         }
197         var obj = new Object();
198         jminf._modeltofiles[modelname] = obj; // .put(modelname, obj);
199         obj.id = modelname;
200         obj.mnum = jminf._modeltofiles.length;
201         jminf._modellist+=modelname;
202 }*/
203
204
205
206 // jmol Jalview Methods
207
208 function _structure(list1, list2, list3, list4) {
209         var follower;
210         // if (_console) { if (!_console.value) { _console.value="";} }
211         if (list1 == "mouseover") {
212                 var list = new Array(("" + list1), ("" + list2), ("" + list3),
213                                 ("" + list4));
214                 // 1 is pdb file, 2 is residue number, 3 is chain
215                 // list1 = new Object(list1);
216                 var base = list[1].indexOf(getDocumentBase()); // .indexOf(_path);
217                 if (base==0) { base = getDocumentBase(); }
218                 var sid = list[1]; // .substring(base);
219                 base = list[1].substring(0, base);
220                 if (_console) {
221                         _console.value += "Model is " + list[1] + ", Structure id is : "
222                                         + sid + "\n";
223                 }
224                 ;
225                 var siddat;
226                 for ( var jmolappi in _jvjmols.values()) {
227                         var jmolapp=_jvjmols.values()[jmolappi];
228                         var msg = "";
229                         if (siddat = jmolapp._filetonum.get(sid)) {
230                                 // we don't putin chain number because there isn't one ?
231                                 // skip select 0 bit
232                                 var ch = ""+list[3];
233                                 if ((""+list[2]).trim().length==1)
234                                         {
235                                         ch+=":"+list[2];
236                                         }
237                                 msg = "select (" + ch + " /" + siddat + ") ;";
238                         }
239                         if (msg) {
240                                 if (_console) {
241                                         _console.value += "Sending '" + msg + "' to jmol." + "\n";
242                                 }
243                         }
244                         jmolScriptWait(msg, "" + jmolapp._jmhandle);
245                         // only do highlight for one jmol ?
246                         // return 1;
247                 }
248         }
249         if (list1 == "colourstruct") {
250                 if (_console) {
251                         _console.value += 'colourStruct("' + list1 + '","' + list2
252                         + '") [' + list4 + ']' + "\n";
253                 }
254                 setTimeout('colourStruct("'+list4+'","' + list1 + '","' + list2 + '")', 1);
255                 return 1;
256         }
257         return 1;
258 }
259 // last colour message
260 var _lastMsg = "";
261 // indicator - if _colourStruct==0 then no colouring is going on
262 var _colourStruct = 0;
263
264 function colourStruct(involves, msg, handle) {
265         if (_colourStruct == 0) {
266                 _colourStruct = 1;
267                 for (ap in _jvapps) {
268                         var _msg = "";
269                         do {
270                                 if (_msg.match(/\S/)) {
271                                         _lastMsg += _msg;
272                                 }
273                                 _msg = "" + _jvapps[ap].getJsMessage(msg, handle);
274                         } while (_msg.match(/\S/));
275                 }
276                 // locate the jmol that should get the message
277                 for (var jmol in _jvjmols.values())
278                         {
279                         var jml=_jvjmols.values()[jmol];
280                         if (jml._filetonum.get(involves))
281                                 {
282                                         colourStructs(jml._jmhandle);
283                                 }
284                         }
285                 _colourStruct = 0;
286         } else {
287                 // setTimeout('colourStruct("'+msg+'","'+handle+'")',3);
288         }
289 }
290
291 function colourStructs(jmolapp) {
292         dbg(0, "Colouring the structures\n");
293         jmolScriptWait("set selectionhalos false;" + _lastMsg
294                         + "; select 0; set selectionhalos true;", jmolapp);
295         _lastMsg = "";
296 }
297 var _jmolhovermsg="";
298 function _jmolhover(jmid, atomlabel, atomidx) {
299         var msg=""+jmid+" "+atomlabel+" "+atomidx;
300         if (_jmolhovermsg==msg)
301                 {
302                 return;
303                 }
304         _jmolhovermsg=msg;
305         modeltofiles = _jvjmols.get(jmid)._modelstofiles;
306         // atomlabel=(""+atomlabel).match(/\[(.+)\](\d+):(.)\.(\S+)\s*\/(\d+)\..+/);
307         // relaxed third parameter - may be null or a model number for multi model
308         // views
309         atomlabel = ("" + atomlabel)
310                         .match(/\[(.+)\](\d+):(.)\.([^\/]+)(\/\d+\.|).+/);
311         atomidx = "" + atomidx;
312         if (atomlabel[5]) {
313                 atomlabel[5] = atomlabel[5].match(/\/(.+)\./)[1];
314                 atomlabel[5] = parseInt(atomlabel[5])-1;
315         } else {
316                 // default - first model
317                 atomlabel[5] = 0;
318         }
319         // use atomlabel[5] to look up model filename so we can highlight associated positions in any jalviews
320         for (ap in _jvapps) {
321                 pdb = getDocumentBase() + modeltofiles[atomlabel[5]];
322                 _jvapps[ap].mouseOverStructure(atomlabel[2], atomlabel[3], pdb);
323                 msg = _jmolhovermsg;
324         }
325 }
326 function _jmolpick(jmid, atomlabel, atomidx) {
327         atomlabel = "" + atomlabel;
328         atomidx = "" + atomidx;
329         // label is atom id, atom number, and xyz coordinates in the form:
330         // C6 #6 -0.30683374 -1.6836332 -0.716934
331         // atom index, starting with 0.
332
333 }
334 function _jmolMessagecallback(jmid, statmess) {
335         // if (statmess.indexOf("Script Terminated")==0)
336         {
337                 var thisTime = new Date();
338                 if (_console) {
339                         _console.value += "Last script execution took : "
340                                         + (thisTime.valueOf() - _lastTime.valueOf()) / 1000.0
341                                         + " seconds.";
342                 }
343                 _lastTime = thisTime;
344
345         }
346 }
347
348
349   function lJvApp() {
350     setTimeout(function() {
351        //alert("in lJvApp");
352        var jvapp = document.getElementById("jvapp");
353        var jvfollower = document.getElementById("jvfollower");
354        //console.log(">>>>>>>> lJvApp" + jvapp);
355        linkJvJmol(jvapp);
356     }, 200);
357     setConsole(document.getElementById("stdout"));
358   };
359
360   function lJvFollow() {
361     setTimeout(function() {
362        //alert("in lJvFollow");
363        var jvapp = document.getElementById("jvapp");
364        var jvfollower = document.getElementById("jvfollower");
365        console.log(">>>>>>> lJvFollow" + jvfollower);
366        linkJvJmol(jvfollower);
367     }, 200);
368   };
369
370   function lJvA() {
371     setTimeout(function() {
372       //alert("lJvA");
373       jvfollower = document.getElementById("jvA");
374       setConsole(document.getElementById("stdout"));  
375       //sep = jvfollower.getSeparator();
376       //jvapp.setSeparator(""+jvapp.getSeparator());
377       linkJvJmol(jvfollower, "jmolView", modeltofiles);
378     }, 100);
379   };
380