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

Last change on this file since 5722 was 5722, checked in by Nicklas Nordborg, 12 years ago

References #1597: Subtypes of items

Update the "Move biomaterial" plate event wizard to use item subtypes when possible.

Display item subtype for biomaterials in tooltip on the single-item page for plates.

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