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

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

References #1597: Subtypes of items

The place-on-plate wizard now uses item subtypes when selecting plate, protocol and hardware if all selected items are of the same subtype.

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