source: trunk/www/biomaterials/wizards/place_on_plate.jsp @ 5724

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

References #1590: Documentation cleanup

Added section about bioplate events in the biomaterials chapter. No screenshots yet.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 22.6 KB
Line 
1<%-- $Id: place_on_plate.jsp 5724 2011-09-08 07:12:06Z nicklas $
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.BioPlateEvent"
26  import="net.sf.basedb.core.BioPlateEventType"
27  import="net.sf.basedb.core.MeasuredBioMaterial"
28  import="net.sf.basedb.core.Hardware"
29  import="net.sf.basedb.core.Protocol"
30  import="net.sf.basedb.core.ItemSubtype"
31  import="net.sf.basedb.core.DbControl"
32  import="net.sf.basedb.core.SystemItems"
33  import="net.sf.basedb.core.Item"
34  import="net.sf.basedb.core.ItemContext"
35  import="net.sf.basedb.core.ItemQuery"
36  import="net.sf.basedb.core.SessionControl"
37  import="net.sf.basedb.core.query.Restrictions"
38  import="net.sf.basedb.core.query.Hql"
39  import="net.sf.basedb.util.Values"
40  import="net.sf.basedb.util.formatter.Formatter"
41  import="net.sf.basedb.clients.web.formatter.FormatterFactory"
42  import="net.sf.basedb.clients.web.formatter.FormatterSettings"
43  import="net.sf.basedb.clients.web.Base"
44  import="net.sf.basedb.clients.web.util.HTML"
45  import="java.util.List"
46  import="java.util.Date"
47  import="java.util.Collections"
48%>
49<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
50<%@ taglib prefix="tbl" uri="/WEB-INF/table.tld" %>
51<%
52final Item itemType = Item.valueOf(request.getParameter("itemType"));
53final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
54final ItemContext cc = sc.getCurrentContext(Item.BIOPLATEEVENT, BioPlateEventType.PLACE_ON_PLATE);
55final String ID = sc.getId();
56final float scale = Base.getScale(sc);
57final DbControl dc = sc.newDbControl();
58try
59{
60  // Load recently used items
61  List<Hardware> recentHardware = (List<Hardware>)cc.getRecent(dc, Item.HARDWARE);
62  List<Protocol> recentProtocols = (List<Protocol>)cc.getRecent(dc, Item.PROTOCOL);
63 
64  ItemQuery<MeasuredBioMaterial> query = (ItemQuery<MeasuredBioMaterial>)cc.getQuery();
65  List<MeasuredBioMaterial> bioMaterial = Collections.emptyList();
66  ItemSubtype commonSubtype = null;
67  if (query != null)
68  {
69    query.restrict(Restrictions.eq(Hql.property("bioWell"), null));
70    query.setMaxResults(-1);
71    query.setFirstResult(0);
72    bioMaterial = query.list(dc);
73    cc.setQuery(null);
74  }
75  final String clazz = "class=\"text\"";
76  final String requiredClazz = "class=\"text required\"";
77  final Formatter<Date> dateFormatter = FormatterFactory.getDateFormatter(sc);
78  final String dateFormat = FormatterSettings.getDateFormat(sc);
79  final String jsDateFormat = HTML.javaScriptEncode(dateFormat);
80  final String htmlDateFormat = HTML.encodeTags(dateFormat);
81  final boolean autoSelectUnmappedItem = Values.getBoolean(sc.getUserClientSetting("place-on-plate.auto-select-unmapped-item"), true);
82  %>
83  <base:page type="popup" title="Place biomaterial on plate">
84  <base:head scripts="ajax.js,plate.js,js-draw.js,json2.js" styles="plate.css,toolbar.css">
85    <script language="javascript">
86 
87    // We have one list of items and one bioplate
88    var itemList;
89    var plate;
90   
91    // We can select one item and one well
92    var selectedItem;
93    var selectedWell;
94
95    // For drawing
96    var graphics;
97    var pen;
98    var selectedPen;
99   
100    function init()
101    {
102      // Initialize graphics
103      graphics = new jsGraphics(document.getElementById('canvas'));
104      pen = new jsPen();
105      selectedPen = new jsPen(new jsColor('445577'), 2);
106      // Create the list of items
107      itemList = new ItemList('itemlist');
108      <%
109      boolean first = true;
110      for (MeasuredBioMaterial bm : bioMaterial)
111      {
112        String itemId = Integer.toString(bm.getId());
113        if (first)
114        {
115          commonSubtype = bm.getItemSubtype();
116          first = false;
117        }
118        else if (commonSubtype != null)
119        {
120          if (!commonSubtype.equals(bm.getItemSubtype()))
121          {
122            commonSubtype = null;
123          }
124        }
125        %>
126        itemList.addItem(<%=itemId%>, '<%=HTML.javaScriptEncode(bm.getName())%>');
127        <%
128      }
129      %>
130    }
131
132    /**
133      Draw a link between the item and it's mapped well.
134    */
135    function itemOnMouseOver(itemId)
136    {
137      var item = itemList.getItem(itemId);
138      if (!item) return;
139      item.drawLink(graphics, pen, false);
140    }
141
142    /**
143      Hide the link between the item and it's mapped well,
144      unless the item (or it's mapped well) is selected.
145    */
146    function itemOnMouseOut(itemId)
147    {
148      var item = itemList.getItem(itemId);
149      if (!item) return;
150      if (!item.selected && !(item.mappedWell && item.mappedWell.selected))
151      {
152        item.hideLink(graphics);
153      }
154    }
155   
156    /**
157      Draw a link between the well and it's mapped item.
158    */
159    function wellOnMouseOver(row, column)
160    {
161      var well = plate.getWell(row, column);
162      if (!well || !well.mappedItem) return;
163      well.mappedItem.scrollIntoView();
164      well.mappedItem.drawLink(graphics, pen, false);
165    }
166 
167    /**
168      Hide the link between the well and it's mapped item,
169      unless the well (or it's mapped item) is selected.
170    */
171    function wellOnMouseOut(row, column)
172    {
173      var well = plate.getWell(row, column);
174      if (!well || !well.mappedItem) return;
175      if (!well.selected && !(well.mappedItem && well.mappedItem.selected))
176      {
177        well.hideLink(graphics);
178      }
179    }
180
181    /**
182      Select the item that is clicked on. The currently selected item
183      is de-selected. If the clicked item is the same as the currently
184      selected item no new item is selected. If a well is already selected
185      a link is made between the well and the newly selected item.
186    */
187    function itemOnClick(itemId)
188    {
189      var item = itemList.getItem(itemId);
190
191      // De-select the currently selected item
192      if (selectedItem)
193      {
194        selectedItem.setSelected(false);
195        if (item == selectedItem)
196        {
197          // Re-draw link with regular pen (eg. same as onmouseover)
198          selectedItem.drawLink(graphics, pen, true);
199          selectedItem = null;
200          return;
201        }
202        else
203        {
204          selectedItem.hideLink(graphics);
205        }
206      }
207     
208      // Select the new item and draw link to mapped well
209      selectedItem = item;
210      selectedItem.setSelected(true);
211      selectedItem.drawLink(graphics, selectedPen, true);
212
213      // Map the item to the selected well
214      if (selectedWell && selectedItem)
215      {
216        placeSelectedOnPlate();
217      }
218    }
219   
220    /**
221      Select the well that is clicked on. The currently selected well is
222      de-selected. If the clicked well is the same as the currently
223      selected well no new well is selected. If an item is already selected
224      a link is made between the item and the newly selected well.
225    */
226    function wellOnClick(row, column)
227    {
228      var well = plate.getWell(row, column);
229
230      // De-select the currently selected well
231      if (selectedWell)
232      {
233        selectedWell.setSelected(false);
234        if (well == selectedWell)
235        {
236          // Re-draw link with regular pen (eg. same as onmouseover)
237          selectedWell.drawLink(graphics, pen, true);
238          selectedWell = null;
239          return;
240        }
241        else
242        {
243          selectedWell.hideLink(graphics);
244        }
245      }
246     
247      selectedWell = well;
248      selectedWell.setSelected(true);
249      selectedWell.drawLink(graphics, selectedPen, true);
250
251      if (selectedWell && selectedItem)
252      {
253        var nextItem = document.forms['main'].autoSelectUnmappedItem.checked ?
254            itemList.nextUnmappedItem(selectedItem) : null;
255        placeSelectedOnPlate();
256        if (nextItem)
257        {
258          nextItem.setSelected(true);
259          nextItem.scrollIntoView();
260          selectedItem = nextItem;
261        }
262      }
263    }
264   
265    /**
266      Redraw the link to the selected item/well when the item list scrolls.
267    */
268    function onItemListScroll()
269    {
270      var item = selectedItem;
271      if (!item && selectedWell) item = selectedWell.mappedItem;
272      if (item) item.drawLink(graphics, selectedPen, true);
273    }
274   
275    /**
276      Map the selected item with the selected well. Hide and
277      redraw links as needed.
278    */
279    function placeSelectedOnPlate()
280    {
281      // Hide any links that are currently displayed
282      selectedItem.hideLink(graphics);
283      selectedWell.hideLink(graphics);
284     
285      // Map to the new well and draw link
286      if (selectedItem.mappedWell != selectedWell)
287      {
288        selectedItem.mapToWell(selectedWell);
289        selectedItem.scrollIntoView();
290        selectedItem.drawLink(graphics, pen, true);
291      }
292      else
293      {
294        selectedItem.unmapWell();
295      }
296     
297      // De-select everything
298      selectedItem.setSelected(false);
299      selectedWell.setSelected(false);
300      selectedItem = null;
301      selectedWell = null;
302    }
303   
304    /**
305      Remove all mappings that have been made so far.
306    */
307    function clearMapping()
308    {
309      if (!plate)
310      {
311        alert('No destination plate has been selected');
312        return;
313      }
314      if (!confirm('This will remove all placed biomaterial. Continue?')) return;
315      itemList.unmapAll(graphics);
316      if (selectedItem)
317      {
318        selectedItem.setSelected(false);
319        selectedItem = null;
320      }
321      if (selectedWell)
322      {
323        selectedWell.setSelected(false);
324        selectedWell = null;
325      }
326    }
327 
328    /**
329      Automatically place unplaced biomaterial on the plate filling rows first.
330      Biomaterial and wells that have already been mapped are skipped.
331    */
332    function placeByRow()
333    {
334      if (!plate)
335      {
336        alert('No destination plate has been selected');
337        return;
338      }
339      var index = 0;
340      var numItems = itemList.items.length;
341      for (var row = 0; row < plate.rows; row++)
342      {
343        for (var column = 0; column < plate.columns; column++)
344        {
345          var well = plate.getWell(row, column);
346          if (!well.mappedItem && !well.locked)
347          {
348            var mapped = false;
349            while (index < itemList.items.length && !mapped)
350            {
351              var item = itemList.items[index];
352              index++;
353              if (!item.mappedWell)
354              {
355                item.mapToWell(well);
356                mapped = true;
357              }
358            }
359          }
360        }
361      }
362    }
363   
364    /**
365      Automatically place unplaced biomaterial on the plate filling columns first.
366      Biomaterial and wells that have already been mapped are skipped.
367    */
368    function placeByColumn()
369    {
370      if (!plate)
371      {
372        alert('No destination plate has been selected');
373        return;
374      }
375      var index = 0;
376      var numItems = itemList.items.length;
377      for (var column = 0; column < plate.columns; column++)
378      {
379        for (var row = 0; row < plate.rows; row++)
380        {
381          var well = plate.getWell(row, column);
382          if (!well.mappedItem && !well.locked)
383          {
384            var mapped = false;
385            while (index < itemList.items.length && !mapped)
386            {
387              var item = itemList.items[index];
388              index++;
389              if (!item.mappedWell)
390              {
391                item.mapToWell(well);
392                mapped = true;
393              }
394            }
395          }
396        }
397      }
398    }
399   
400    function selectBioPlateOnClick()
401    {
402      if (plate && !confirm('This will remove all placed biomaterial. Continue?')) return;
403     
404      var url = '../bioplates/index.jsp?ID=<%=ID%>&cmd=UpdateContext&mode=selectone&callback=setBioPlateCallback';
405      url += '&resetTemporary=1&tmpfilter:INT:bioPlateType.bioMaterialType=|<%=itemType.getValue()%>'
406      <%
407      if (commonSubtype != null)
408      {
409        %>
410        url += '&tmpfilter:INT:bioPlateType.itemSubtype=|<%=commonSubtype.getId()%>'
411        <%
412      }
413      %>
414      Main.openPopup(url, 'SelectBioPlate', 1000, 700);
415    }
416
417    function setBioPlateCallback(bioPlateId, name)
418    {
419      var request = Ajax.getXmlHttpRequest();
420      var url = '../bioplates/ajax.jsp?ID=<%=ID%>&cmd=GetFullPlateInfo&item_id=' + bioPlateId;
421      request.open("GET", url, false); 
422      // NOTE! 'false' causes code to wait for the response. aka. 'Synchronous AJAX' or SJAX.
423      request.send(null);
424      var plateInfo = Ajax.parseJsonResponse(request.responseText);
425      if (plateInfo.status != 'ok')
426      {
427        alert(plateInfo.message);
428        return false;
429      }
430     
431      // Get plate and well information from the AJAX response
432      var rows = plateInfo.rows;
433      var columns = plateInfo.columns;
434     
435      var bigPlate = rows > 12 || columns > 18;
436      var plateClass = bigPlate ? 'plate bigplate' : 'plate';
437
438      // Remove existing mapping
439      itemList.unmapAll(graphics);
440
441      // Create plate and wells
442      plate = new Plate('dest', plateInfo.id, plateInfo.name, rows, columns);
443      for (var i = 0; i < plateInfo.wells.length; i++)
444      {
445        var wellInfo = plateInfo.wells[i];
446        var bmInfo = wellInfo.bioMaterial;
447        var row = parseInt(wellInfo.row);
448        var col = parseInt(wellInfo.column);
449        var well = plate.getWell(row, col);
450        well.locked = !wellInfo.canAdd || bmInfo;
451        well.name = bmInfo ? bmInfo.name : '';
452      }
453     
454      document.getElementById('plate.name').innerHTML = Main.encodeTags(name);
455     
456      // Create html table representing the bioplate
457      var html = '<table class="'+plateClass+'" cellspacing="0" cellpadding="0" onmouseout="event.cancelBubble=true">';
458      html += '<tr><td></td>';
459      for (var c = 0; c < plate.columns; c++)
460      {
461        html += '<td class="columnheader">' + (c+1) + '</td>';
462      }
463      html += '</tr>';
464      for (var r = 0; r < plate.rows; r++)
465      {
466        html += '<tr><td class="rowheader">' + Plates.toAlphaCoordinate[r] + '</td>';
467        for (var c = 0; c < plate.columns; c++)
468        {
469          var well = plate.getWell(r, c);
470          var cls = 'well';
471          var onclick = '';
472          var onmouseover = '';
473          var onmouseout = '';
474          var title = '';
475          if (well.locked) 
476          {
477            cls+= ' unmappable';
478            if (well.name) 
479            {
480              title = 'This well is used by: ' + Main.encodeTags(well.name);
481            }
482            else
483            {
484              title = 'This well has already been used';
485            }
486          }
487          else
488          {
489            cls += ' empty editable';
490            onclick = ' onclick="wellOnClick('+r+','+c+')""';
491            onmouseover = ' onmouseover=wellOnMouseOver('+r+','+c+')';
492            onmouseout = ' onmouseout=wellOnMouseOut('+r+','+c+')';
493          }
494          html += '<td id="dest.'+r+'.'+c+'" class="' + cls + '"' + onclick + onmouseover + onmouseout+' title="'+title+'"></td>';
495        }
496        html += '</tr>';
497      }
498      html += '</table>';
499      document.getElementById('plate').innerHTML = html;
500      Main.show('toolbar.mappings');
501    }
502   
503    /**
504      Save the event.
505    */
506    function doPlaceOnPlate()
507    {
508      if (!plate)
509      {
510        alert('No plate has been selected');
511        return;
512      }
513      var frm = document.forms['main'];
514      if (Main.trimString(frm.name.value) == '')
515      {
516        alert("You must enter a name for the event.");
517        frm.name.focus();
518        return;
519      }
520     
521      frm.plate_id.value = plate.id;
522      frm.rows.value = plate.rows;
523      frm.columns.value = plate.columns;
524     
525      var numMapped = 0;
526      for (var row = 0; row < plate.rows; row++)
527      {
528        for (var column = 0; column < plate.columns; column++)
529        {
530          var well = plate.getWell(row, column);
531         
532          if (well.mappedItem)
533          {
534            Forms.createHidden(frm, 'well.' + row + '.' + column, well.mappedItem.id);
535            numMapped++;
536          }
537        }
538      }
539     
540      if (numMapped == 0)
541      {
542        alert('No biomaterial has been mapped to wells');
543        return;
544      }
545     
546      frm.submit();
547    }
548   
549    function selectHardwareOnClick()
550    {
551      var frm = document.forms['main'];
552      var url = '../../admin/hardware/index.jsp?ID=<%=ID%>&cmd=UpdateContext&mode=selectone&callback=setHardwareCallback';
553      if (frm.hardware_id.length > 1)
554      {
555        var id = Math.abs(parseInt(frm.hardware_id[1].value));       
556        url += '&item_id='+id;
557      }
558      url += '&resetTemporary=1';
559      <%
560      if (commonSubtype != null)
561      {
562        ItemSubtype hardwareType = commonSubtype.getRelatedSubtype(Item.HARDWARE);
563        if (hardwareType != null)
564        {
565          %>
566          url += '&tmpfilter:INT:itemSubtype=<%=hardwareType.getId()%>';
567          <%
568        }
569      }
570      %>
571      Main.openPopup(url, 'SelectHardware', 1000, 700);
572    }
573    function setHardwareCallback(id, name)
574    {
575      var frm = document.forms['main'];
576      var list = frm.hardware_id;
577      if (list.length < 2 || list[1].value == '0') // >
578      {
579        Forms.addListOption(list, 1, new Option());
580      }
581      list[1].value = id;
582      list[1].text = name;
583      list.selectedIndex = 1;
584    }
585 
586    function selectProtocolOnClick()
587    {
588      var frm = document.forms['main'];
589      var url = '../../admin/protocols/index.jsp?ID=<%=ID%>&cmd=UpdateContext&mode=selectone&callback=setProtocolCallback';
590      if (frm.protocol_id.length > 1)
591      {
592        var id = Math.abs(parseInt(frm.protocol_id[1].value));       
593        url += '&item_id='+id;
594      }
595      url += '&resetTemporary=1';
596      <%
597      ItemSubtype protocolType = null;
598      if (commonSubtype != null)
599      {
600        protocolType = commonSubtype.getRelatedSubtype(Item.PROTOCOL);
601      }
602      if (protocolType == null)
603      {
604        String defaultId = Protocol.getDefaultSystemId(itemType);
605        if (defaultId != null) protocolType = ItemSubtype.getById(dc, SystemItems.getId(defaultId));
606      }
607      if (protocolType != null)
608      {
609        %>
610        url += '&tmpfilter:INT:itemSubtype=<%=protocolType.getId()%>';
611        <%
612      }
613      %>
614      Main.openPopup(url, 'SelectProtocol', 1000, 700);
615    }
616    function setProtocolCallback(id, name)
617    {
618      var frm = document.forms['main'];
619      var list = frm.protocol_id;
620      if (list.length < 2 || list[1].value == '0') // >
621      {
622        Forms.addListOption(list, 1, new Option());
623      }
624      list[1].value = id;
625      list[1].text = name;
626      list.selectedIndex = 1;
627    }
628    </script>
629  </base:head>
630  <base:body onload="init()">
631    <div id="canvas"></div>
632    <h3>Place biomaterial on plate <base:help helpid="bioplateevent.place-on-plate" /></h3>
633    <div class="boxedbottom" style="height: <%=(int)(scale*500)%>px; padding: 0px;">
634      <form name="main" action="index.jsp" method="post">
635      <input type="hidden" name="ID" value="<%=ID%>">
636      <input type="hidden" name="cmd" value="PlaceOnPlate">
637      <input type="hidden" name="itemType" value="<%=itemType.name()%>">
638      <input type="hidden" name="plate_id" value="">
639      <input type="hidden" name="rows" value="">
640      <input type="hidden" name="columns" value="">
641     
642    <%
643    if (bioMaterial.size() == 0)
644    {
645      %>
646      <div class="error">
647      No biomaterial selected. Please close this window and select one or more items that
648      are not already placed on a plate.
649      </div>
650      <%
651    }
652    else
653    {
654      %>
655      <table cellspacing="0" border="0" width="100%" style="background: #e0e0e0; padding-bottom: 6px;">
656      <tr valign="top">
657        <td style="width: 50%;">
658          <table class="form" cellspacing=0>
659          <tr>
660            <td class="prompt" style="width: 90px;">Event name</td>
661            <td><input <%=requiredClazz%> type="text" name="name" 
662              value="Place biomaterial on plate" 
663              size="40" maxlength="<%=BioPlateEvent.MAX_NAME_LENGTH%>"></td>
664          </tr>
665          <tr>
666            <td class="prompt">Event date</td>
667            <td>
668              <table border="0" cellspacing="0" cellpadding="0">
669              <tr>
670              <td>
671                <input <%=clazz%> type="text" name="event_date" 
672                  value="<%=HTML.encodeTags(dateFormatter.format(new Date()))%>" 
673                  size="20" maxlength="20" title="Enter date in format: <%=htmlDateFormat%>">
674                &nbsp;
675              </td>
676              <td>
677              <base:button 
678                onclick="<%="Dates.selectDate('Event date', 'main', 'event_date', null, '"+jsDateFormat+"')"%>"
679                image="calendar.png"
680                title="Calendar&hellip;" 
681                tooltip="Select a date from a calendar" 
682              />
683              </td>
684              </tr>
685              </table>
686            </td>
687          </tr>
688          <tr>
689            <td class="prompt">Protocol</td>
690            <td>
691              <base:select 
692                id="protocol_id"
693                clazz="selectionlist"
694                required="false"
695                current="<%=null%>"
696                recent="<%=recentProtocols%>"
697                onselect="selectProtocolOnClick()"
698              />
699            </td>
700          </tr>
701          <tr>
702            <td class="prompt">Hardware</td>
703            <td>
704              <base:select 
705                id="hardware_id"
706                clazz="selectionlist"
707                required="false"
708                current="<%=null%>"
709                recent="<%=recentHardware%>"
710                onselect="selectHardwareOnClick()"
711              />
712            </td>
713          </tr>
714          </table>
715        </td>
716        <td style="width: 50%;">
717          <b>Description</b><br>
718          <textarea <%=clazz%> rows="4" cols="40" name="description" wrap="virtual"
719            ></textarea>
720          <a href="javascript:Main.zoom('Description', 'main', 'description')"
721            title="Edit in larger window"><base:icon image="zoom.gif" /></a>
722        </td>
723      </tr>
724      </table>
725     
726      <tbl:toolbar id="toolbar.mappings" style="border-left: 0px; border-right: 0px;">
727        <tbl:button title="Select plate&hellip;" 
728          onclick="javascript:selectBioPlateOnClick()" 
729          image="place_on_plate.png" 
730          tooltip="Select the destination plate"
731        />
732        <tbl:button title="Clear" 
733          onclick="clearMapping()" 
734          image="cancel.gif" 
735          tooltip="Clear all mapped wells"
736        />
737        <tbl:button title="Place by row" 
738          onclick="placeByRow()" 
739          image="place_by_row.png" 
740          tooltip="Place remaining items; start with rows"
741        />
742        <tbl:button title="Place by column" 
743          onclick="placeByColumn()" 
744          image="place_by_column.png" 
745          tooltip="Place remaining items; start with columns"
746        />
747      </tbl:toolbar>
748     
749      <table cellspacing="0" cellpadding="0" border="0" width="100%" style="padding: 4px;">
750      <tr valign="top">
751        <td style="width: 280px;">
752          <b>Items to place</b> <%=commonSubtype != null ? "<span class=\"itemsubtype\">[" + HTML.encodeTags(commonSubtype.getName()) + "]</span>" : "" %>
753          <div id="itemlist" class="biomateriallist" style="height: <%=(int)(scale*320)%>px; width:270px;" onscroll="onItemListScroll()">
754          <table border="0" cellspacing="0" cellpadding="0" width="100%">
755          <%
756          for (MeasuredBioMaterial bm : bioMaterial)
757          {
758            String itemId = Integer.toString(bm.getId());
759            String fullLabel = bm.getName();
760            String label = Values.trimString(fullLabel, 30);
761            %>
762            <tr class="item" id="itemlist.<%=itemId%>" title="<%=fullLabel == label ? "" : HTML.encodeTags(fullLabel)%>"
763              onclick="itemOnClick(<%=itemId%>)" onmouseover="itemOnMouseOver(<%=itemId%>)" onmouseout="itemOnMouseOut(<%=itemId%>)">
764              <td class="info" id="itemlist.<%=itemId%>.info"></td>
765              <td class="label" id="itemlist.<%=itemId%>.label"><%=HTML.encodeTags(label)%></td>
766            </tr>
767            <%
768          }
769          %>
770          </table>
771          </div>
772          <input type="checkbox" name="autoSelectUnmappedItem" 
773            <%=autoSelectUnmappedItem ? "checked" : ""%> value="1">Auto-select next unmapped item
774        </td>
775        <td>
776          <div style="max-height: <%=(int)(scale*350)%>px; overflow: auto;">
777            <b>Destination plate:</b> <span id="plate.name"><i>no plate selected</i></span>
778            <div id="plate"></div>
779          </div>
780        </td>
781      </tr>
782      </table>
783      <%
784    }
785    %>
786      </form>
787    </div>
788    <table align="center">
789    <tr>
790      <td width="50%"><base:button disabled="<%=bioMaterial.size() == 0 %>" onclick="doPlaceOnPlate()" title="Save" /></td>
791      <td width="50%"><base:button onclick="window.close()" title="Cancel" /></td>
792    </tr>
793    </table>
794   
795  </base:body>
796  </base:page>
797  <%
798}
799finally
800{
801  if (dc != null) dc.close();
802}
803%>
Note: See TracBrowser for help on using the repository browser.