source: trunk/www/biomaterials/wizards/move_biomaterial.jsp @ 5927

Last change on this file since 5927 was 5927, checked in by Nicklas Nordborg, 10 years ago

References #1655: GUI improvements

Started with the bioplate event wizards. The 'place-on-plate' and 'move biomaterial' wizards are looking good so far, but there are a few more cases to test. The 'create child plate' remains and the bioplate view page should also be checked.

File size: 27.0 KB
Line 
1<%-- $Id$
2  ------------------------------------------------------------------
3  Copyright (C) 2010 Nicklas Nordborg
4
5  This file is part of BASE - BioArray Software Environment.
6  Available at http://base.thep.lu.se/
7
8  BASE is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License
10  as published by the Free Software Foundation; either version 3
11  of the License, or (at your option) any later version.
12
13  BASE is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with BASE. If not, see <http://www.gnu.org/licenses/>.
20  ------------------------------------------------------------------
21
22  @author Nicklas
23--%>
24<%@ page pageEncoding="UTF-8" session="false"
25  import="net.sf.basedb.core.BioPlate"
26  import="net.sf.basedb.core.BioPlateEvent"
27  import="net.sf.basedb.core.PermissionDeniedException"
28  import="net.sf.basedb.core.BioPlateEventType"
29  import="net.sf.basedb.core.MeasuredBioMaterial"
30  import="net.sf.basedb.core.BioWell"
31  import="net.sf.basedb.core.ItemSubtype"
32  import="net.sf.basedb.core.Hardware"
33  import="net.sf.basedb.core.Protocol"
34  import="net.sf.basedb.core.DbControl"
35  import="net.sf.basedb.core.Item"
36  import="net.sf.basedb.core.ItemContext"
37  import="net.sf.basedb.core.ItemQuery"
38  import="net.sf.basedb.core.SessionControl"
39  import="net.sf.basedb.core.query.Restrictions"
40  import="net.sf.basedb.core.query.Hql"
41  import="net.sf.basedb.util.Values"
42  import="net.sf.basedb.util.formatter.Formatter"
43  import="net.sf.basedb.clients.web.formatter.FormatterFactory"
44  import="net.sf.basedb.clients.web.formatter.FormatterSettings"
45  import="net.sf.basedb.clients.web.Base"
46  import="net.sf.basedb.clients.web.util.HTML"
47  import="java.util.List"
48  import="java.util.Date"
49  import="java.util.Collections"
50%>
51<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
52<%@ taglib prefix="tbl" uri="/WEB-INF/table.tld" %>
53<%
54final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
55final String ID = sc.getId();
56final float scale = Base.getScale(sc);
57final int sourcePlateId = Values.getInt(request.getParameter("sourceplate_id"));
58final ItemContext cc = sc.getCurrentContext(Item.BIOPLATEEVENT, BioPlateEventType.MOVE);
59final DbControl dc = sc.newDbControl();
60try
61{
62  BioPlate sourcePlate = BioPlate.getById(dc, sourcePlateId);
63 
64  // Load recently used items
65  List<Hardware> recentHardware = (List<Hardware>)cc.getRecent(dc, Item.HARDWARE);
66  List<Protocol> recentProtocols = (List<Protocol>)cc.getRecent(dc, Item.PROTOCOL);
67 
68  Item itemType = null;
69  try
70  {
71    itemType = sourcePlate.getBioPlateType().getBioMaterialType();
72  }
73  catch (PermissionDeniedException ex)
74  {}
75  // Find a common itemsubtype (if any)
76  ItemSubtype commonSubtype = null;
77  boolean first = true;
78  for (BioWell well : sourcePlate.getBioWells().list(dc))
79  {
80    try
81    {
82      if (!well.isEmpty())
83      {
84        ItemSubtype subtype = well.getBioMaterial().getItemSubtype();
85        if (first)
86        {
87          commonSubtype = subtype;
88          first = false;
89        }
90        else
91        {
92          if (subtype == null || !subtype.equals(commonSubtype))
93          {
94            commonSubtype = null;
95            break;
96          }
97        }
98      }
99    }
100    catch (PermissionDeniedException ex)
101    {}
102  }
103  if (commonSubtype != null && itemType == null)
104  {
105    itemType = commonSubtype.getMainItemType();
106  }
107 
108  final String clazz = "class=\"text\"";
109  final String requiredClazz = "class=\"text required\"";
110  final Formatter<Date> dateFormatter = FormatterFactory.getDateFormatter(sc);
111  final String dateFormat = FormatterSettings.getDateFormat(sc);
112  final String jsDateFormat = HTML.javaScriptEncode(dateFormat);
113  final String htmlDateFormat = HTML.encodeTags(dateFormat);
114  final boolean showSourceCoordinates = Values.getBoolean(sc.getUserClientSetting("move-biomaterial.show-source-coordinates"), true);
115  %>
116  <base:page type="popup" title="Move biomaterial">
117  <base:head scripts="ajax.js,plate.js,js-draw.js,json2.js" styles="plate.css,toolbar.css">
118    <script language="javascript">
119 
120    // For drawing
121    var graphics;
122    var pen;
123    var selectedPen;
124   
125    // Source and destination plates
126    var sourcePlate;
127    var destPlate;
128   
129    // We can select one well on each plate
130    var selectedSourceWell;
131    var selectedDestWell;
132
133    function init()
134    {
135      // Initialize graphics
136      graphics = new jsGraphics(document.getElementById('canvas'));
137      pen = new jsPen(new jsColor('#2288AA'), 1);
138      selectedPen = new jsPen(new jsColor('#2288AA'), 2);
139      setBioPlateCallback(<%=sourcePlateId%>, '<%=HTML.javaScriptEncode(sourcePlate.getName())%>', true);
140    }
141
142    /**
143      Select the source well that is clicked on. The currently selected well
144      is de-selected. If the clicked well is the same as the currently
145      selected well no new item is selected. If a destination well is already
146      selected a link is made between the source and destination wells.
147    */
148    function sourceWellOnClick(row, column)
149    {
150      var well = sourcePlate.getWell(row, column);
151      if (!well) return;
152
153      // De-select the currently selected source well
154      if (selectedSourceWell)
155      {
156        selectedSourceWell.setSelected(false);
157        if (well == selectedSourceWell)
158        {
159          // Re-draw link with regular pen (eg. same as onmouseover)
160          selectedSourceWell.drawLink(graphics, pen, true);
161          selectedSourceWell = null;
162          return;
163        }
164        else
165        {
166          selectedSourceWell.hideLink(graphics);
167        }
168      }
169     
170      // Select the new source well and draw link to destination well
171      selectedSourceWell = well;
172      selectedSourceWell.setSelected(true);
173      selectedSourceWell.drawLink(graphics, selectedPen, true);
174
175      // Map the source and destination wells
176      if (selectedSourceWell && selectedDestWell)
177      {
178        mapSelectedWells();
179      }
180    }
181   
182    /**
183      Draw a link between the mapped source and destination wells.
184    */
185    function sourceWellOnMouseOver(row, column)
186    {
187      var well = sourcePlate.getWell(row, column);
188      if (!well) return;
189      well.drawLink(graphics, pen, false);
190    }
191   
192    /**
193      Hide the link between the mapped source and destination
194      wells, unless one of them is selected.
195    */
196    function sourceWellOnMouseOut(row, column)
197    {
198      var well = sourcePlate.getWell(row, column);
199      if (!well) return;
200      if (!well.selected && !(well.mappedWell && well.mappedWell.selected))
201      {
202        well.hideLink(graphics);
203      }
204    }
205   
206    function destWellOnClick(row, column)
207    {
208      var well = destPlate.getWell(row, column);
209
210      // De-select the currently selected well
211      if (selectedDestWell)
212      {
213        selectedDestWell.setSelected(false);
214        if (well == selectedDestWell)
215        {
216          // Re-draw link with regular pen (eg. same as onmouseover)
217          selectedDestWell.drawLink(graphics, pen, true);
218          selectedDestWell = null;
219          return;
220        }
221        else
222        {
223          selectedDestWell.hideLink(graphics);
224        }
225      }
226     
227      selectedDestWell = well;
228      selectedDestWell.setSelected(true);
229      selectedDestWell.drawLink(graphics, selectedPen, true);
230
231      if (selectedSourceWell && selectedDestWell)
232      {
233        mapSelectedWells();
234      }
235    }
236   
237    function destWellOnMouseOver(row, column)
238    {
239      var well = destPlate.getWell(row, column);
240      if (!well) return;
241      well.drawLink(graphics, pen, false);
242    }
243   
244    function destWellOnMouseOut(row, column)
245    {
246      var well = destPlate.getWell(row, column);
247      if (!well) return;
248      if (!well.selected && !(well.mappedWell && well.mappedWell.selected))
249      {
250        well.hideLink(graphics);
251      }
252    }
253
254    /**
255      Map the selected source and destination wells. Hide and
256      redraw links as needed.
257    */
258    function mapSelectedWells()
259    {
260      // Hide any links that are currently displayed
261      selectedSourceWell.hideLink(graphics);
262      selectedDestWell.hideLink(graphics);
263     
264      // Map to the new well and draw link
265      if (selectedSourceWell.mappedWell != selectedDestWell)
266      {
267        selectedSourceWell.mapToWell(selectedDestWell);
268        selectedSourceWell.drawLink(graphics, pen, true);
269      }
270      else
271      {
272        selectedSourceWell.unmapWell();
273      }
274     
275      // De-select everything
276      selectedSourceWell.setSelected(false);
277      selectedDestWell.setSelected(false);
278      selectedSourceWell = null;
279      selectedDestWell = null;
280    }
281
282   
283    /**
284      Remove all mappings that have been made so far.
285    */
286    function clearMapping()
287    {
288      if (!destPlate)
289      {
290        alert('No destination plate has been selected');
291        return;
292      }
293      if (!confirm('This will remove all placed biomaterial. Continue?')) return;
294      sourcePlate.unmapAll(graphics);
295      if (selectedSourceWell)
296      {
297        selectedSourceWell.setSelected(false);
298        selectedSourceWell = null;
299      }
300      if (selectedDestWell)
301      {
302        selectedDestWell.setSelected(false);
303        selectedDestWell = null;
304      }
305    }
306   
307    /**
308      Automatically move remaining biomaterial to the destination plate filling rows first.
309      Biomaterial and wells that have already been mapped are skipped.
310    */
311    function placeByRow()
312    {
313      if (!destPlate)
314      {
315        alert('No destination plate has been selected');
316        return;
317      }
318      var srcRow = 0;
319      var srcCol = 0;
320      for (var destRow = 0; destRow < destPlate.rows; destRow++)
321      {
322        for (var destCol = 0; destCol < destPlate.columns; destCol++)
323        {
324          var destWell = destPlate.getWell(destRow, destCol);
325          if (!destWell.mappedWell && !destWell.locked)
326          {
327            var mapped = false;
328            var srcWell = sourcePlate.getWell(srcRow, srcCol);
329            while (srcWell && !mapped)
330            {
331              if (srcWell.id && !srcWell.locked && !srcWell.mappedWell)
332              {
333                srcWell.mapToWell(destWell);
334                mapped = true;
335              }
336              else
337              {
338                srcCol++;
339                if (srcCol >= sourcePlate.columns)
340                {
341                  srcCol = 0;
342                  srcRow++;
343                }
344                srcWell = sourcePlate.getWell(srcRow, srcCol);
345              }
346            }
347          }
348        }
349      }
350    }
351 
352    /**
353      Automatically move remaining biomaterial to the destination plate filling columns first.
354      Biomaterial and wells that have already been mapped are skipped.
355    */
356    function placeByColumn()
357    {
358      if (!destPlate)
359      {
360        alert('No destination plate has been selected');
361        return;
362      }
363      var srcRow = 0;
364      var srcCol = 0;
365      for (var destCol = 0; destCol < destPlate.columns; destCol++)
366      {
367        for (var destRow = 0; destRow < destPlate.rows; destRow++)
368        {
369          var destWell = destPlate.getWell(destRow, destCol);
370          if (!destWell.mappedWell && !destWell.locked)
371          {
372            var mapped = false;
373            var srcWell = sourcePlate.getWell(srcRow, srcCol);
374            while (srcWell && !mapped)
375            {
376              if (srcWell.id && !srcWell.locked && !srcWell.mappedWell)
377              {
378                srcWell.mapToWell(destWell);
379                mapped = true;
380              }
381              else
382              {
383                srcRow++;
384                if (srcRow >= sourcePlate.rows)
385                {
386                  srcCol++;
387                  srcRow = 0;
388                }
389                srcWell = sourcePlate.getWell(srcRow, srcCol);
390              }
391            }
392          }
393        }
394      }
395    }
396
397   
398    function selectBioPlateOnClick()
399    {
400      if (destPlate && !confirm('This will reset all moved biomaterial. Continue?')) return;
401     
402      var url = '../bioplates/index.jsp?ID=<%=ID%>&cmd=UpdateContext&mode=selectone&callback=setBioPlateCallback';
403      url += '&resetTemporary=1&tmpfilter:INT:bioPlateType.bioMaterialType=<%=itemType == null ? "=" : "|" + itemType.getValue()%>'
404      <%
405      if (commonSubtype != null)
406      {
407        %>
408        url += '&tmpfilter:INT:bioPlateType.itemSubtype=|<%=commonSubtype.getId()%>'
409        <%
410      }
411      %>
412      url += '&exclude='+sourcePlate.id;
413      Main.openPopup(url, 'SelectBioPlate', 1000, 700);
414    }
415
416    function setBioPlateCallback(bioPlateId, name, isSourcePlate)
417    {
418      var win = Main.getWindow('SelectBioPlate');
419      if (!isSourcePlate && bioPlateId == sourcePlate.id)
420      {
421        win.alert('It is not possible to use the same plate as both source and destination plate.');
422        return;
423      }
424     
425      var request = Ajax.getXmlHttpRequest();
426      var url = '../bioplates/ajax.jsp?ID=<%=ID%>&cmd=GetFullPlateInfo&item_id=' + bioPlateId;
427      request.open("GET", url, false);
428      // NOTE! 'false' causes code to wait for the response. aka. 'Synchronous AJAX' or SJAX.
429      request.send(null);
430      var plateInfo = Ajax.parseJsonResponse(request.responseText);
431      if (plateInfo.status != 'ok')
432      {
433        win.alert(plateInfo.message);
434        return;
435      }
436
437      // Get plate and well information from the AJAX response
438      var rows = plateInfo.rows
439      var columns = plateInfo.columns;
440     
441      var bigPlate = rows > 12 || columns > 18;
442      var plateClass = bigPlate ? 'plate bigplate' : 'plate';
443
444      // Remove existing mapping
445      if (sourcePlate) sourcePlate.unmapAll(graphics);
446      selectedDestWell = null;
447
448      // Create plate and wells
449      var prefix = isSourcePlate ? 'source' : 'dest';
450      var plate = new Plate(prefix, plateInfo.id, plateInfo.name, rows, columns, isSourcePlate);
451      for (var i = 0; i < plateInfo.wells.length; i++)
452      {
453        var wellInfo = plateInfo.wells[i];
454        var bmInfo = wellInfo.bioMaterial;
455        var row = wellInfo.row;
456        var col = wellInfo.column;
457        var well = plate.getWell(row, col);
458        if (bmInfo)
459        {
460          well.id = bmInfo.id;
461          well.name = bmInfo.name;
462        }
463        well.locked = isSourcePlate ? !wellInfo.canClear : !wellInfo.canAdd || well.id;
464      }
465     
466      // Create html table representing the bioplate
467      var html = '<table class="'+plateClass+'" onmouseout="event.cancelBubble=true">';
468      html += '<tr><td></td>';
469      for (var c = 0; c < plate.columns; c++)
470      {
471        html += '<td class="columnheader">' + (c+1) + '</td>';
472      }
473      html += '</tr>';
474      for (var r = 0; r < plate.rows; r++)
475      {
476        html += '<tr><td class="rowheader">' + Plates.toAlphaCoordinate[r] + '</td>';
477        for (var c = 0; c < plate.columns; c++)
478        {
479          var well = plate.getWell(r, c);
480          var cls = 'well';
481          var onclick = '';
482          var onmouseover = '';
483          var onmouseout = '';
484          var title = well.name ? Main.encodeTags(well.name) : '';
485          if (isSourcePlate)
486          {
487            // We can only move a biomaterial if the well is not empty or locked
488            if (well.id)
489            {
490              if (well.locked)
491              {
492                cls += ' used locked';
493              }
494              else
495              {
496                cls += ' used editable';
497                onclick = ' onclick="sourceWellOnClick('+r+','+c+')"';
498                onmouseover = ' onmouseover=sourceWellOnMouseOver('+r+','+c+')';
499                onmouseout = ' onmouseout=sourceWellOnMouseOut('+r+','+c+')';
500              }
501            }
502            else
503            {
504              cls += ' empty';
505            }
506          }
507          else
508          {
509            // We only add biomaterial to destination well if it is not locked
510            if (well.locked)
511            {
512              cls += ' unmappable';
513            }
514            else
515            {
516              cls += ' empty editable';
517              onclick = ' onclick="destWellOnClick('+r+','+c+')"';
518              onmouseover = ' onmouseover=destWellOnMouseOver('+r+','+c+')';
519              onmouseout = ' onmouseout=destWellOnMouseOut('+r+','+c+')';
520            }
521          }
522          html += '<td id="'+prefix+'.'+r+'.'+c+'" class="' + cls + '"' + onclick + onmouseover + onmouseout+' title="'+title+'">';
523          html += '<div class="info" id="'+prefix+'.'+r+'.'+c+'.info"></div></td>';
524        }
525        html += '</tr>';
526      }
527      html += '</table>';
528      if (isSourcePlate)
529      {
530        document.getElementById('plate.src').innerHTML = html;
531        document.getElementById('plate.src.name').innerHTML = Main.encodeTags(name);
532        sourcePlate = plate;
533      }
534      else
535      {
536        document.getElementById('plate.dest').innerHTML = html;
537        document.getElementById('plate.dest.name').innerHTML = Main.encodeTags(name);
538        destPlate = plate;
539        Main.showHide('plate.dest.options', !bigPlate);
540        showSourceCoordinatesOnClick();
541      }
542    }
543   
544    /**
545      Save the event.
546    */
547    function doMoveBioMaterial()
548    {
549      if (!destPlate)
550      {
551        alert('No destination plate has been selected');
552        return;
553      }
554      var frm = document.forms['main'];
555      if (Main.trimString(frm.name.value) == '')
556      {
557        alert("You must enter a name for the event.");
558        frm.name.focus();
559        return;
560      }
561     
562      frm.destplate_id.value = destPlate.id;
563      frm.rows.value = destPlate.rows;
564      frm.columns.value = destPlate.columns;
565     
566      var numMapped = 0;
567      for (var row = 0; row < destPlate.rows; row++)
568      {
569        for (var column = 0; column < destPlate.columns; column++)
570        {
571          var well = destPlate.getWell(row, column);
572         
573          if (well.mappedWell)
574          {
575            Forms.createHidden(frm, 'well.' + row + '.' + column, well.mappedWell.id);
576            numMapped++;
577          }
578        }
579      }
580     
581      if (numMapped == 0)
582      {
583        alert('No wells have been mapped.');
584        return;
585      }
586     
587      frm.submit();
588    }
589   
590
591    function selectHardwareOnClick()
592    {
593      var frm = document.forms['main'];
594      var url = '../../admin/hardware/index.jsp?ID=<%=ID%>&cmd=UpdateContext&mode=selectone&callback=setHardwareCallback';
595      if (frm.hardware_id.length > 1)
596      {
597        var id = Math.abs(parseInt(frm.hardware_id[1].value));       
598        url += '&item_id='+id;
599      }
600      url += '&resetTemporary=1';
601      <%
602      if (commonSubtype != null)
603      {
604        ItemSubtype hardwareType = commonSubtype.getRelatedSubtype(Item.HARDWARE);
605        if (hardwareType != null)
606        {
607          %>
608          url += '&tmpfilter:INT:itemSubtype=<%=hardwareType.getId()%>';
609          <%
610        }
611      }
612      %>
613      Main.openPopup(url, 'SelectHardware', 1000, 700);
614    }
615    function setHardwareCallback(id, name)
616    {
617      var frm = document.forms['main'];
618      var list = frm.hardware_id;
619      if (list.length < 2 || list[1].value == '0') // >
620      {
621        Forms.addListOption(list, 1, new Option());
622      }
623      list[1].value = id;
624      list[1].text = name;
625      list.selectedIndex = 1;
626    }
627 
628    function selectProtocolOnClick()
629    {
630      var frm = document.forms['main'];
631      var url = '../../admin/protocols/index.jsp?ID=<%=ID%>&cmd=UpdateContext&mode=selectone&callback=setProtocolCallback';
632      if (frm.protocol_id.length > 1)
633      {
634        var id = Math.abs(parseInt(frm.protocol_id[1].value));       
635        url += '&item_id='+id;
636      }
637      url += '&resetTemporary=1';
638      <%
639      ItemSubtype protocolType = null;
640      if (commonSubtype != null)
641      {
642        protocolType = commonSubtype.getRelatedSubtype(Item.PROTOCOL);
643        if (protocolType != null)
644        {
645          %>
646          url += '&tmpfilter:INT:itemSubtype=<%=protocolType.getId()%>';
647          <%
648        }
649      }
650      %>
651      Main.openPopup(url, 'SelectProtocol', 1000, 700);
652    }
653    function setProtocolCallback(id, name)
654    {
655      var frm = document.forms['main'];
656      var list = frm.protocol_id;
657      if (list.length < 2 || list[1].value == '0') // >
658      {
659        Forms.addListOption(list, 1, new Option());
660      }
661      list[1].value = id;
662      list[1].text = name;
663      list.selectedIndex = 1;
664    }
665   
666    function selectPlateMappingOnClick()
667    {
668      if (!destPlate)
669      {
670        alert('No destination plate has been selected');
671        return;
672      }
673      var url = '../../lims/platemappings/index.jsp?ID=<%=ID%>&cmd=UpdateContext&mode=selectone&callback=setPlateMappingCallback';
674      url += '&resetTemporary=1';
675      url += '&tmpfilter:INT:sourceGeometry.rows='+sourcePlate.rows;
676      url += '&tmpfilter:INT:sourceGeometry.columns='+sourcePlate.columns;
677      url += '&tmpfilter:INT:sourceCount=1';
678      url += '&tmpfilter:INT:destinationGeometry.rows='+destPlate.rows;
679      url += '&tmpfilter:INT:destinationGeometry.columns='+destPlate.columns;
680      url += '&tmpfilter:INT:destinationCount=1';
681      Main.openPopup(url, 'SelectPlateMapping', 1000, 700);
682    }
683   
684    function setPlateMappingCallback(plateMappingId, name)
685    {
686      var request = Ajax.getXmlHttpRequest();
687      var url = '../../lims/platemappings/ajax.jsp?ID=<%=ID%>&cmd=GetMappingDetails&item_id=' + plateMappingId;
688      request.open("GET", url, false);
689      request.send(null);
690      var mappingInfo = Ajax.parseJsonResponse(request.responseText);
691      var win = Main.getWindow('SelectPlateMapping');
692      if (mappingInfo.status != 'ok')
693      {
694        win.alert(mappingInfo.message);
695        return false;
696      }
697     
698      if (mappingInfo.sourcePlates != 1 || mappingInfo.sourceRows != sourcePlate.rows || mappingInfo.sourceColumns != sourcePlate.columns)
699      {
700        if (!win.confirm("The selected mapping doesn't match the geometry of the source plate.\nContinue mapping overlapping positions?")) return;
701      }
702      else if (mappingInfo.destinationPlates != 1 || mappingInfo.destinationRows != destPlate.rows || mappingInfo.destinationColumns != destPlate.columns)
703      {
704        if (!win.confirm("The selected mapping doesn't match the geometry of the destination plate.\nContinue mapping overlapping positions?")) return;
705      }
706     
707      var numMapped = 0;
708      for (var i = 0; i < mappingInfo.details.length; i++)
709      {
710        var mapping = mappingInfo.details[i].split(',');
711        var srcWell = sourcePlate.getWell(parseInt(mapping[1]), parseInt(mapping[2]));
712        var destWell = destPlate.getWell(parseInt(mapping[4]), parseInt(mapping[5]));
713        if (srcWell && destWell)
714        {
715          if (!destWell.mappedWell && !destWell.locked && srcWell.id && !srcWell.locked && !srcWell.mappedWell)
716          {
717            srcWell.mapToWell(destWell);
718            numMapped++;
719          }
720        }
721      }
722    }
723   
724    function showSourceCoordinatesOnClick()
725    {
726      var frm = document.forms['main'];
727      Main.addOrRemoveClass(document.getElementById('plate.dest'), 'noinfo', !frm.showSourceCoordinates.checked);
728    }
729    </script>
730  </base:head>
731  <base:body onload="init()">
732    <div id="canvas" style="position: absolute; z-index: 99;"></div>
733    <h1>Move biomaterial to plate <base:help helpid="bioplateevent.move" /></h1>
734    <form name="main" action="index.jsp" method="post">
735    <input type="hidden" name="ID" value="<%=ID%>">
736    <input type="hidden" name="cmd" value="MoveBioMaterial">
737    <input type="hidden" name="sourceplate_id" value="<%=sourcePlateId%>">
738    <input type="hidden" name="destplate_id" value="">
739    <input type="hidden" name="rows" value="">
740    <input type="hidden" name="columns" value=""> 
741   
742    <div class="content" >
743      <div class="absolutefull filled" style="height: 10em;">
744        <table style="width: 100%; background: #FFFFFF;" class="input100">
745        <tr>
746          <td style="width: 50%;">
747            <table class="fullform smaller">
748              <tr>
749                <th>Event name</th>
750                <td><input <%=requiredClazz%> type="text" name="name" 
751                  value="Move biomaterial" 
752                  maxlength="<%=BioPlateEvent.MAX_NAME_LENGTH%>"></td>
753              </tr>
754              <tr>
755                <th>Event date</th>
756                <td>
757                  <table>
758                  <tr>
759                  <td>
760                    <input <%=clazz%> type="text" name="event_date" style="width: 15em;"
761                      value="<%=HTML.encodeTags(dateFormatter.format(new Date()))%>" 
762                      maxlength="20" title="Enter date in format: <%=htmlDateFormat%>">
763                  </td>
764                  <td>
765                  <base:button 
766                    onclick="<%="Dates.selectDate('Event date', 'main', 'event_date', null, '"+jsDateFormat+"')"%>"
767                    image="calendar.png"
768                    title="Calendar&hellip;" 
769                    tooltip="Select a date from a calendar" 
770                  />
771                  </td>
772                  </tr>
773                  </table>
774                </td>
775              </tr>
776              <tr>
777                <th>Protocol</th>
778                <td>
779                  <base:select 
780                    id="protocol_id"
781                    clazz="selectionlist"
782                    required="false"
783                    current="<%=null%>"
784                    recent="<%=recentProtocols%>"
785                    onselect="selectProtocolOnClick()"
786                  />
787                </td>
788              </tr>
789              <tr>
790                <th>Hardware</th>
791                <td>
792                  <base:select 
793                    id="hardware_id"
794                    clazz="selectionlist"
795                    required="false"
796                    current="<%=null%>"
797                    recent="<%=recentHardware%>"
798                    onselect="selectHardwareOnClick()"
799                  />
800                </td>
801              </tr>
802              </table>
803            </td>
804            <td style="width: 50%;">
805              <table style="width: 100%;">
806              <tr>
807                <td><b>Description</b><br>
808                  <textarea <%=clazz%> rows="4" name="description" 
809                  ></textarea></td>
810                <td style="width: 20px;">
811                  <base:icon image="zoom.png" 
812                    onclick="Main.zoom('Description', 'main', 'description')"
813                    tooltip="Edit in larger window"
814                  />
815                </td>
816              </tr>
817              </table>
818            </td>
819          </table>
820          <tbl:toolbar id="toolbar.mappings" subclass="topborder bottomborder">
821            <tbl:button title="Select plate&hellip;" 
822              onclick="javascript:selectBioPlateOnClick()" 
823              image="move_to_plate.png" 
824              tooltip="Select the destination plate"
825            />
826            <tbl:button title="Clear" 
827              onclick="clearMapping()" 
828              image="cancel.png" 
829              tooltip="Clear all mapped wells"
830            />
831            <tbl:button title="Place by row" 
832              onclick="placeByRow()" 
833              image="place_by_row.png" 
834              tooltip="Place remaining items; start with rows"
835            />
836            <tbl:button title="Place by column" 
837              onclick="placeByColumn()" 
838              image="place_by_column.png" 
839              tooltip="Place remaining items; start with columns"
840            />
841            <tbl:button title="Predefined mapping&hellip;" 
842              onclick="selectPlateMappingOnClick()" 
843              image="star.png" 
844              tooltip="Select a predefined plate mapping"
845            />
846          </tbl:toolbar>
847      </div>
848      <div class="absolutefull bottomborder" style="top: 10em;">
849        <div class="absolutefull" style="width: 50%;">
850          <div class="absolutefull filled" style="height: 2em;">
851            <div class="padded">
852            <b>Source plate:</b> <span id="plate.src.name"></span>
853            <%=commonSubtype != null ? "<span class=\"itemsubtype\">[" + HTML.encodeTags(commonSubtype.getName()) + "]</span>" : "" %>
854            </div>
855          </div>
856         
857          <div class="absolutefull topborder" style="top: 2em;">
858            <table style="margin: auto; height: 100%;"><tr><td>
859              <div id="plate.src"></div>
860              <br>
861            </td></tr></table>
862          </div>
863         
864        </div>
865        <div class="absolutefull" style="left: auto; width: 50%;">
866          <div class="absolutefull filled" style="height: 2em;">
867            <div class="padded">
868            <b>Destination plate:</b> <span id="plate.dest.name"><i>not selected</i></span>
869            </div>
870          </div>
871           
872          <div class="absolutefull leftborder topborder" style="top: 2em;">
873            <table style="margin: auto; height: 100%;"><tr><td>
874              <div id="plate.dest"></div>
875              <div id="plate.dest.options" style="display: none;">
876                <input type="checkbox" name="showSourceCoordinates" id="showSourceCoordinates"
877                <%=showSourceCoordinates ? "checked" : ""%> value="1"
878                onclick="showSourceCoordinatesOnClick()"><label for="showSourceCoordinates">Show source coordinates</label>
879              </div>
880            </td></tr></table>
881          </div>
882        </div>
883
884      </div>
885    </div>
886    </form>
887
888    <base:buttongroup subclass="dialogbuttons">
889      <base:button onclick="doMoveBioMaterial()" title="Save" />
890      <base:button onclick="window.close()" title="Cancel" />
891    </base:buttongroup>
892   
893  </base:body>
894  </base:page>
895  <%
896}
897finally
898{
899  if (dc != null) dc.close();
900}
901%>
Note: See TracBrowser for help on using the repository browser.