source: trunk/www/biomaterials/wizards/place_on_plate.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.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 23.4 KB
Line 
1<%-- $Id: place_on_plate.jsp 5927 2012-01-16 14:18:58Z 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(new jsColor('#2288AA'), 1);
105      selectedPen = new jsPen(new jsColor('#2288AA'), 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+'" 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" style="position: absolute; z-index: 99;"></div>
632    <h1>Place biomaterial on plate <base:help helpid="bioplateevent.place-on-plate" /></h1>
633    <form name="main" action="index.jsp" method="post">
634      <input type="hidden" name="ID" value="<%=ID%>">
635      <input type="hidden" name="cmd" value="PlaceOnPlate">
636      <input type="hidden" name="itemType" value="<%=itemType.name()%>">
637      <input type="hidden" name="plate_id" value="">
638      <input type="hidden" name="rows" value="">
639      <input type="hidden" name="columns" value="">
640   
641    <div class="content">
642    <%
643    if (bioMaterial.size() == 0)
644    {
645      %>
646      <div class="messagecontainer 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      <div class="absolutefull filled" style="height: 10em;">
656          <table style="width: 100%; background: #FFFFFF;" class="input100">
657          <tr>
658            <td style="width: 50%;">
659              <table class="fullform smaller">
660              <tr>
661                <th>Event name</th>
662                <td><input <%=requiredClazz%> type="text" name="name" 
663                  value="Place biomaterial on plate" 
664                  maxlength="<%=BioPlateEvent.MAX_NAME_LENGTH%>"></td>
665              </tr>
666              <tr>
667                <th>Event date</th>
668                <td>
669                  <table>
670                  <tr>
671                  <td>
672                    <input <%=clazz%> type="text" name="event_date" style="width: 15em;"
673                      value="<%=HTML.encodeTags(dateFormatter.format(new Date()))%>" 
674                      maxlength="20" title="Enter date in format: <%=htmlDateFormat%>">
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                <th>Protocol</th>
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                <th>Hardware</th>
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              <table style="width: 100%;">
718              <tr>
719                <td><b>Description</b><br>
720                  <textarea <%=clazz%> rows="4" name="description" 
721                  ></textarea></td>
722                <td style="width: 20px;">
723                  <base:icon image="zoom.png" 
724                    onclick="Main.zoom('Description', 'main', 'description')"
725                    tooltip="Edit in larger window"
726                  />
727                </td>
728              </tr>
729              </table>
730            </td>
731          </table>
732          <tbl:toolbar id="toolbar.mappings" subclass="topborder bottomborder">
733            <tbl:button title="Select plate&hellip;" 
734              onclick="javascript:selectBioPlateOnClick()" 
735              image="place_on_plate.png" 
736              tooltip="Select the destination plate"
737            />
738            <tbl:button title="Clear" 
739              onclick="clearMapping()" 
740              image="cancel.png" 
741              tooltip="Clear all mapped wells"
742            />
743            <tbl:button title="Place by row" 
744              onclick="placeByRow()" 
745              image="place_by_row.png" 
746              tooltip="Place remaining items; start with rows"
747            />
748            <tbl:button title="Place by column" 
749              onclick="placeByColumn()" 
750              image="place_by_column.png" 
751              tooltip="Place remaining items; start with columns"
752            />
753          </tbl:toolbar>
754      </div>
755     
756      <div class="absolutefull bottomborder" style="top: 10em;">
757        <div class="absolutefull rightborder" style="width: 280px;">
758          <div class="absolutefull filled" style="height: 2em;">
759            <div class="padded">
760            <b>Items to place</b> <%=commonSubtype != null ? "<span class=\"itemsubtype\">[" + HTML.encodeTags(commonSubtype.getName()) + "]</span>" : "" %>
761            </div>
762          </div>
763
764          <div id="itemlist" class="absolutefull biomateriallist topborder" 
765            style="top: 2em; bottom: 2em;" onscroll="onItemListScroll()">
766              <table style="width: 100%; height: 100%;">
767              <%
768              for (MeasuredBioMaterial bm : bioMaterial)
769              {
770                String itemId = Integer.toString(bm.getId());
771                String fullLabel = bm.getName();
772                String label = Values.trimString(fullLabel, 30);
773                %>
774                <tr style="height: 1.5em;" class="item" id="itemlist.<%=itemId%>" title="<%=fullLabel == label ? "" : HTML.encodeTags(fullLabel)%>"
775                  onclick="itemOnClick(<%=itemId%>)" onmouseover="itemOnMouseOver(<%=itemId%>)" onmouseout="itemOnMouseOut(<%=itemId%>)">
776                  <td class="info" id="itemlist.<%=itemId%>.info"></td>
777                  <td class="label" id="itemlist.<%=itemId%>.label"><%=HTML.encodeTags(label)%></td>
778                </tr>
779                <%
780              }
781              %>
782              <tr style="height: auto;" class="item">
783                <td class="info"></td>
784                <td></td>
785              </tr>
786              </table>
787          </div>
788          <div class="absolutefull filled topborder" style="top: auto; height: 2em;">
789              <input type="checkbox" name="autoSelectUnmappedItem" id="autoSelectUnmappedItem"
790                <%=autoSelectUnmappedItem ? "checked" : ""%> value="1"><label for="autoSelectUnmappedItem">Auto-select next unmapped item</label>
791          </div>
792        </div>
793        <div class="absolutefull" style="left: 280px;">
794          <div class="absolutefull filled" style="height: 2em;">
795            <div class="padded">
796            <b>Destination plate:</b> <span id="plate.name"><i>no plate selected</i></span>
797            </div>
798          </div>
799          <div class="absolutefull topborder" style="top: 2em;">
800            <table style="margin: auto; height: 100%;"><tr><td>
801            <div id="plate"></div>
802            </td></tr></table>
803          </div>
804        </div>
805      </div>
806      <%
807    }
808    %>
809  </div>
810  </form>
811   
812  <base:buttongroup subclass="dialogbuttons">
813    <base:button disabled="<%=bioMaterial.size() == 0 %>" onclick="doPlaceOnPlate()" title="Save" />
814    <base:button onclick="window.close()" title="Cancel" />
815  </base:buttongroup>
816   
817  </base:body>
818  </base:page>
819  <%
820}
821finally
822{
823  if (dc != null) dc.close();
824}
825%>
Note: See TracBrowser for help on using the repository browser.