source: extensions/net.sf.basedb.reggie/trunk/resources/libprep/pool_protocol2.jsp @ 2188

Last change on this file since 2188 was 2188, checked in by Nicklas Nordborg, 8 years ago

References #555: Specify amount to use from *.dil items in pool

Implemented the same functionality in the "Create manual pool" wizard. Also discovered and fixed some bugs introduced by #553 (submitting mixingStrategy and target volume as properties of the pool).

File size: 21.6 KB
Line 
1<%@ page
2  pageEncoding="UTF-8"
3  session="false"
4  import="net.sf.basedb.core.User"
5  import="net.sf.basedb.core.DbControl"
6  import="net.sf.basedb.core.SessionControl"
7  import="net.sf.basedb.core.Application"
8  import="net.sf.basedb.core.Extract"
9  import="net.sf.basedb.core.BioMaterial"
10  import="net.sf.basedb.core.MeasuredBioMaterial"
11  import="net.sf.basedb.core.BioMaterialEventSource"
12  import="net.sf.basedb.core.BioPlate"
13  import="net.sf.basedb.core.BioWell"
14  import="net.sf.basedb.core.PermissionDeniedException"
15  import="net.sf.basedb.core.ItemQuery"
16  import="net.sf.basedb.core.query.Restrictions"
17  import="net.sf.basedb.core.query.Hql"
18  import="net.sf.basedb.core.query.Orders"
19  import="net.sf.basedb.util.Values"
20  import="net.sf.basedb.util.formatter.WellCoordinateFormatter"
21  import="net.sf.basedb.util.extensions.Extension"
22  import="net.sf.basedb.clients.web.Base" 
23  import="net.sf.basedb.clients.web.util.HTML"
24  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
25  import="java.util.List"
26  import="java.util.ArrayList"
27%>
28<%
29final SessionControl sc = Base.getExistingSessionControl(request, true);
30final String ID = sc.getId();
31final String home = ExtensionsControl.getHomeUrl("net.sf.basedb.reggie");
32final String root = request.getContextPath();
33DbControl dc = null;
34try
35{
36  dc = sc.newDbControl();
37  final Extension reggie = ExtensionsControl.get(dc).getExtension("net.sf.basedb.reggie");
38  final User user = User.getById(dc, sc.getLoggedInUserId());
39 
40  Integer[] pools = Values.getInt(request.getParameterValues("pools"));
41 
42  int libPlateId = Values.getInt(request.getParameter("bioplate"));
43  BioPlate libPlate = libPlateId == 0 ? null : BioPlate.getById(dc, libPlateId);
44  String view = Values.getString(request.getParameter("view"), "list");
45%>
46<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
47<html>
48<head>
49  <%
50  if (libPlate != null)
51  {
52    %>
53    <title>Lab protocol for pooling <%=HTML.encodeTags(libPlate.getName())%> - <%=view.equals("list") ? "list" : "table"%></title>
54    <%
55  }
56  else
57  {
58    %>
59    <title>Lab protocol for library pooling - <%=view.equals("list") ? "list" : "table"%></title>
60    <%
61  }
62  %>
63  <link rel="SHORTCUT ICON" href="<%=home%>/images/flowcell.png">
64  <link rel="stylesheet" type="text/css" href="<%=home %>/css/printable.css">
65  <link rel="stylesheet" type="text/css" href="<%=home %>/css/plate.css">
66  <link rel="stylesheet" type="text/css" href="<%=home %>/css/reggie.css">
67  <script language="JavaScript" src="<%=root%>/include/scripts/main.js" type="text/javascript" charset="UTF-8"></script>
68  <script language="JavaScript" src="<%=root%>/include/scripts/ajax.js" type="text/javascript" charset="UTF-8"></script>
69  <script language="JavaScript" src="<%=home %>/reggie.js" type="text/javascript" charset="UTF-8"></script>
70  <script language="JavaScript" src="pools.js" type="text/javascript" charset="UTF-8"></script>
71  <script language="JavaScript" src="plate.js" type="text/javascript" charset="UTF-8"></script>
72 
73  <script language="JavaScript">
74  var debug = 0;
75  var currentStep = 1;
76 
77  // Loaded from servlet when getting Library information
78  var POOL_CURRENT_SCHEMA;
79  var POOL_CURRENT_BARCODE_VARIANT;
80 
81  function init()
82  {
83    // Load information about Library bioplate
84    var libPlate;
85    <%
86    if (libPlateId != 0)
87    {
88      %>
89      // Load Libraries and related info from the selected pools
90      var request = Ajax.getXmlHttpRequest();
91      try
92      {
93        showLoadingAnimation('Loading library bioplate information...');
94        var url = '../Pool.servlet?ID=<%=ID%>&cmd=GetLibPlateInfo&bioplate=<%=libPlateId%>';   
95        request.open("GET", url, false);
96        request.send(null);
97      }
98      finally
99      {
100        hideLoadingAnimation();
101      }
102     
103      if (debug) Main.debug(request.responseText);
104      var response = JSON.parse(request.responseText);
105      if (response.status != 'ok')
106      {
107        setFatalError(response.message);
108        return false;
109      }
110     
111      libPlate = response.libPlate;
112      POOL_CURRENT_SCHEMA = PoolSchema.getById(libPlate.poolSchema);
113      POOL_CURRENT_BARCODE_VARIANT = PoolSchema.getBarcodeVariantByName(POOL_CURRENT_SCHEMA, libPlate.barcodeVariant);
114      Plate.init(8, 12, POOL_CURRENT_SCHEMA, WellPainter);
115      <%
116    }
117    %>
118   
119    var pools = [<%=Values.getString(java.util.Arrays.asList(pools), ",", true)%>];
120
121    // Load Libraries and related info from the selected pools
122    var request = Ajax.getXmlHttpRequest();
123    try
124    {
125      showLoadingAnimation('Loading pooled library information...');
126      var url = '../Pool.servlet?ID=<%=ID%>&cmd=GetLibraryInfoForPools&pools='+pools.join(',')+'&bioplate=<%=libPlateId%>';   
127      request.open("GET", url, false);
128      request.send(null);
129    }
130    finally
131    {
132      hideLoadingAnimation();
133    }
134   
135    if (debug) Main.debug(request.responseText);
136    var response = JSON.parse(request.responseText);
137    if (response.status != 'ok')
138    {
139      setFatalError(response.message);
140      return false;
141    }
142   
143    var pools = response.pools;
144    var poolInfo = response.poolInfo;
145
146    var pageTitle = 'Lab protocol for pooling ';
147    // Pre-process the Library items
148    for (var i = 0; i < pools.length; i++)
149    {
150      var pool = pools[i];
151      if (i > 0) pageTitle += ','
152      pageTitle += ' ' + pool.name;
153     
154      // Calculate some pool quantities
155      pool.volume = 1000 * pool.originalQuantity / pool.conc;
156
157      for (var libNo = 0; libNo < pool.libraries.length; libNo++)
158      {
159        var lib = pool.libraries[libNo];
160        PoolMix.calculateLibVolumeForProtocol(lib, pool.targetPoolMolarity, pool.targetVolumePerLib, pool.mixingStrategy, true);
161        PoolMix.calculateEbVolume(lib, pool.targetPoolMolarity, pool.targetVolumePerLib, pool.mixingStrategy);
162        checkAndPreProcessLibrary(lib, pool, POOL_CURRENT_SCHEMA, POOL_CURRENT_BARCODE_VARIANT, '<%=view%>');       
163      }
164
165      pool.extra = PoolMix.calculateFinalPoolInfo(pool.libraries, pool.targetPoolMolarity, pool.targetVolumePerLib, pool.mixingStrategy);
166    }
167   
168    if (!libPlate)
169    {
170      document.title = pageTitle + ' - <%=view%>';
171    }
172   
173    <%
174    if (view.equals("list"))
175    {
176      %>
177      viewAsList(pools, POOL_CURRENT_SCHEMA, POOL_CURRENT_BARCODE_VARIANT);
178      <%
179    }
180    else
181    {
182      %>
183      viewAsPlate(pools, POOL_CURRENT_SCHEMA, POOL_CURRENT_BARCODE_VARIANT);
184      <%
185    }
186    %>
187  }
188 
189  function checkAndPreProcessLibrary(lib, pool, schema, barcodeVariant, view)
190  {
191    var well = lib.bioWell;
192    var remarks = [];
193
194    // Check if default barcode has been modified
195    if (barcodeVariant)
196    {
197      var indexSet = barcodeVariant.indexSets[well.column];
198      if (indexSet)
199      {
200        var defaultBarcode = indexSet.barcodes[well.row];
201        if (defaultBarcode && lib.barcode.name != defaultBarcode)
202        {
203          remarks[remarks.length] = 'Modified barcode';
204          lib.barcode.modified = true;
205        }
206      }
207    }
208   
209    if (lib.molarity)
210    {
211      if (lib.speedVacConc != null)
212      {
213        remarks[remarks.length] = 'SpeedVac';
214      }
215 
216      if (lib.mixFactor > 1)
217      {
218        // Larger mix than default
219        if (view != 'plate')
220        {
221          remarks[remarks.length] = '<span class="mix-remark">Mix <span class="volume">'+Numbers.formatNumber(lib.actualVolume*lib.mixFactor, 1) + '</span>+<span class="eb">' + Numbers.formatNumber(lib.actualEb*lib.mixFactor, 1)+'µl</span></span>';
222        }
223        remarks[remarks.length] = 'Use <b>' + Numbers.formatNumber(lib.actualVolume+lib.actualEb, 1) + 'µl</b> in pool';
224      }
225
226      lib.remarks = remarks;
227    }
228   
229    if (lib.comment) remarks[remarks.length] = lib.comment;
230  }
231 
232  /**
233    Get the plate coordinate string for a well, optionally including the plate
234    name or not.
235  */
236  function getPlateCoordinate(well, includePlateName)
237  {
238    var c = '';
239    if (well)
240    {
241      if (includePlateName) c += well.bioPlate.name;
242      c += ' ' + WELL_ALPHA[well.row] + (well.column+1);
243    }
244    return c;
245  }
246 
247 
248  function viewAsList(pools, schema, barcodeVariant)
249  {
250    for (var poolNo = 0; poolNo < pools.length; poolNo++)
251    {
252      var pool = pools[poolNo];
253      var wellsInPool = null;
254      if (schema)
255      {
256        var realPoolNo = schema.getPoolNumForColumn(pool.libraries[0].bioWell.column);
257        wellsInPool = Plate.getPool(realPoolNo);
258      }
259
260     
261      var html = '';
262      var tbody = document.getElementById('listview.'+pool.id+'.body');
263     
264      var wellIndex = 0;
265      for (var j = 0; j < pool.libraries.length; j++)
266      {
267        var lib = pool.libraries[j];
268        var well = lib.bioWell;
269       
270        var tr = document.createElement('tr');
271        if (schema)
272        {
273          wellIndex = createMissingRows(tbody, wellsInPool, wellIndex, well, barcodeVariant);
274          tr.className = well.column % 2 == 0 ? "evencol" : "oddcol";
275        }
276        else
277        {
278          tr.className = 'evencol';
279        }
280   
281        if (barcodeVariant)
282        {
283          var indexSet = barcodeVariant.indexSets[well.column];
284          if (indexSet)
285          {
286            tr.className = lib && lib.barcode.modified ? 'bg-modified' : indexSet.color;
287          }
288        }
289
290        addColumn(tr, 'lib', lib.name);
291        addColumn(tr, 'remain', Numbers.formatNumber((lib.remainingVolume), 1));
292        addColumn(tr, 'molarity', Numbers.formatNumber(lib.molarity, 2));
293        <%
294        if (libPlate==null)
295        {
296          %>
297          addColumn(tr, 'workplate', well.bioPlate.name + ' ' + well.location);
298          <%
299        }
300        else
301        {
302          %>
303          addColumn(tr, 'workplate', well.location);
304          <%
305        }
306        %>
307        var mixFactor = lib.mixFactor || 1.0;
308        addColumn(tr, 'volume', mixFactor > 1.0 ? '—' : Numbers.formatNumber(lib.actualVolume, 1));
309        addColumn(tr, 'eb', pool.mixingStrategy == 'dynamic' || mixFactor > 1.0 ? '—' : Numbers.formatNumber(lib.actualEb, 1));
310        addColumn(tr, "remarks", lib.remarks.join('; '));
311        tbody.appendChild(tr);
312      }
313      if (schema)
314      {
315        createMissingRows(tbody, wellsInPool, wellIndex, null, barcodeVariant);
316      }
317     
318      var poolData = '<div class="pool-data">';
319      poolData += pool.libraries.length + ' libs; ';
320      poolData += Numbers.formatNumber(pool.molarity, 2)+'nM; ';
321      poolData += Numbers.formatNumber(pool.volume, 1) + 'µl';
322      poolData += '<br>Mixing strategy: ' + pool.mixingStrategy;
323      poolData += '</div>';
324      setInnerHTML('molarity.'+pool.id, poolData);
325      setInnerHTML('eb-volume.'+pool.id, Numbers.formatNumber(Math.max(0, pool.extra.ebVolumeExtra), 1));
326      Main.show('pool.'+pool.id);
327    }
328  }
329 
330  function createMissingRows(table, wellsInPool, wellIndex, well, barcodeVariant)
331  {
332    var wellAtIndex = wellsInPool[wellIndex]; // Empty??
333    if (!well) well = {'row': -1, 'column': -1};
334    while (wellAtIndex.row != well.row || wellAtIndex.column != well.column)
335    {
336      var tr = document.createElement('tr');
337      tr.className = 'empty';
338      if (barcodeVariant)
339      {
340        var indexSet = barcodeVariant.indexSets[wellAtIndex.column];
341        if (indexSet) tr.className += ' ' + indexSet.color;
342      }
343     
344      addColumn(tr, 'lib', 'not pooled');
345      addColumn(tr, 'remain', '');
346      addColumn(tr, 'molarity', '');
347      addColumn(tr, 'workplate', WELL_ALPHA[wellAtIndex.row] + (wellAtIndex.column+1));
348      addColumn(tr, 'volume', '');
349      addColumn(tr, 'eb', '');
350      addColumn(tr, 'remarks', '');
351      table.appendChild(tr);
352      wellIndex++;
353      if (wellIndex >= wellsInPool.length) break;
354      wellAtIndex = wellsInPool[wellIndex];
355    }
356    return wellIndex+1;
357  }
358 
359  function addColumn(tr, className, html)
360  {
361    var td = document.createElement('td');
362    td.className = className;
363    td.innerHTML = html;
364    tr.appendChild(td);
365  }
366 
367  function viewAsPlate(pools, schema, barcodeVariant)
368  {
369    for (var poolNo = 0; poolNo < pools.length; poolNo++)
370    {
371      var pool = pools[poolNo];
372      for (var libNo = 0; libNo < pool.libraries.length; libNo++)
373      {
374        var lib = pool.libraries[libNo];
375        var well = lib.bioWell;
376        Plate.getWell(well.row, well.column).setExtract(lib);
377      }
378    }
379
380    WellPainter.barcodeVariant = barcodeVariant;
381    PoolSchema.buildPoolTableRow(schema, 12);
382    Main.show('plateview');
383   
384    for (var poolNo = 0; poolNo < pools.length; poolNo++)
385    {
386      var pool = pools[poolNo];
387      var realPoolNo = schema.getPoolNumForColumn(pool.libraries[0].bioWell.column);
388      Plate.paint(Plate.getPool(realPoolNo));
389     
390      var poolData = '<div class="pool-data">';
391      poolData += pool.libraries.length + ' libs  ';
392      poolData += Numbers.formatNumber(pool.molarity, 2)+'nM  ';
393      poolData += Numbers.formatNumber(pool.volume, 1) + 'µl';
394      if (pool.mixingStrategy == 'dynamic')
395      {
396        poolData += '  <span class="pool-eb">'+Numbers.formatNumber(pool.extra.ebVolumeExtra, 1, 'µl')+'</span>';
397      }
398      poolData += '<br>Mixing strategy: ' + pool.mixingStrategy;
399      poolData += '<div class="comments">'+pool.comments+'</div>';
400      poolData += '</div>';
401     
402      document.getElementById('pool.'+realPoolNo).innerHTML = pool.name + poolData;
403    }
404  }
405
406  var WellPainter = function()
407  {
408    var painter = {};
409   
410    painter.getClassNameForWell = function(well, schema)
411    {
412      var cls = '';
413      var indexSet = painter.barcodeVariant.indexSets[well.column];
414      if (indexSet)
415      {
416        var lib = well.extract;
417        cls += lib && lib.barcode.modified ? 'bg-modified' : indexSet.color;
418      }
419      return cls;
420    }
421   
422    painter.getWellText = function(well, schema)
423    {
424      var text = '';
425      var lib = well.extract;
426      if (lib)
427      {
428        var name = lib.name;
429        var mixFactor = lib.mixFactor || 1.0;
430        var i = name.indexOf('.m');
431        text += '<div class="lib">'+name.substring(0, i)+'.<br>&nbsp;'+name.substring(i)+'</div>';
432        text += '<div><span class="volume">'+Numbers.formatNumber(lib.actualVolume*mixFactor, 1)+'µl</span>';
433        if (lib.mixingStrategy == 'fixed' || lib.mixFactor > 1)
434        {
435          text += '<span class="eb">'+Numbers.formatNumber(lib.actualEb*mixFactor, 1)+'µl</span>';
436        }
437        else
438        {
439          text += '<span class="eb"></span>';
440        }
441        //text+=lib.eb+':'+lib.mixFactor;
442        text += '</div>';
443        text += '<div class="remarks">'+ lib.remarks.join('; ') + '</div>';
444      }
445      return text;
446    }
447
448    return painter;
449  }();
450  </script>
451  <style>
452  table.protocolheader
453  {
454    width: 100%;
455    border: 1px solid #000000;
456    margin-bottom: 1em;
457    border-collapse: collapse;
458  }
459
460  table.protocolheader > tbody > tr
461  {
462    vertical-align: top;
463    height: 1.25em;
464  }
465
466  table.protocolheader > tbody > tr > th
467  {
468    text-align: left;
469    font-size: 1em;
470    background-color: #F0F0F0;
471    padding: 2px;
472  }
473 
474  table.protocolheader > tbody > tr > td
475  {
476    text-align: left;
477    font-size: 1em;
478    padding: 2px;
479  }
480
481  .pool-section
482  {
483    page-break-inside: avoid;
484  }
485
486  table.poolheader
487  {
488    margin-top: 1em;
489    width: 100%;
490    border: 1px solid #000000;
491    border-bottom: 0px;
492    border-collapse: collapse;
493  }
494
495  table.poolheader > tbody > tr
496  {
497    height: 1.25em;
498  }
499
500  table.poolheader > tbody > tr > th
501  {
502    text-align: left;
503    font-size: 1.25em;
504    padding: 1px;
505  }
506 
507  .listview
508  {
509    width: 100%;
510    font-size: 85%;
511    border-collapse: collapse;
512    border: 1px solid #000000;
513  }
514 
515  .listview tr.oddcol
516  {
517    background-color: #F0F0F0;
518  }
519 
520  .listview thead
521  {
522    border: 1px solid #000000;
523    background-color: #F0F0F0;
524  }
525 
526  .listview th
527  {
528    border-left: 1px solid #000000;
529  }
530 
531  .listview td
532  {
533    border-left: 1px solid #000000;
534    border-top: 1px dotted #666666;
535    vertical-align: middle;
536    padding: 2px;
537  }
538 
539  .listview .summary
540  {
541    border-top: 1px solid #000000;
542  }
543 
544  .listview .col-num
545  {
546    width: 1.75em;
547    text-align: center;
548    font-size: 125%;
549    font-weight: bold;
550    vertical-align: top;
551  }
552 
553  .listview .lib
554  {
555    width: 15em;
556    text-align: center;
557  }
558 
559  .listview .empty .lib
560  {
561    font-style: italic;
562    color: #666666;
563    text-align: center;
564  }
565 
566  .listview .workplate
567  {
568 
569    width: <%=libPlate==null ? "14em" : "7em"%>;
570    text-align: center;
571  }
572 
573  .listview .pool
574  {
575    width: 7em;
576    text-align: center;
577  }
578 
579  .listview .remain, .listview .molarity
580  {
581    width: 4.5em;
582    padding-right: 0.5em;
583    text-align: right;
584  }
585
586  .listview .volume
587  {
588    width: 3.5em;
589    padding-right: 0.5em;
590    text-align: right;
591    color: #C80000;
592  }
593 
594  .listview .eb
595  {
596    width: 3.5em;
597    padding-right: 0.5em;
598    text-align: right;
599    color: #0000C8;
600  }
601 
602  .listview .remarks
603  {
604    vertical-align: top;
605    padding-left: 0.25em;
606  }
607 
608  .mix-remark .volume, .mix-remark .eb
609  {
610    padding: 0;
611    text-align: inherit;
612    width: inherit;
613    font-weight: bold;
614  }
615
616 
617 
618  /* Divide the 12 wells across the full page */
619  #plateview .well
620  {
621    width: 8.2%;
622    max-width: 8.2%;
623    min-width: 8.2%;
624    padding: 4px;
625  }
626 
627  #plateview .well:hover
628  {
629    padding: 3px;
630  }
631 
632  #plateview .rowheader
633  {
634    width: 2em;
635  }
636 
637  #plateview .lib
638  {
639    font-weight: bold;
640    margin-bottom: 0.25em;
641  }
642  #plateview .volume
643  {
644    color: #C80000;
645  }
646  #plateview .eb
647  {
648    color: #0000C8;
649    float: right;
650  }
651 
652  #plateview .remarks
653  {
654    color: #C80000;
655    font-style: italic;
656  }
657 
658  #plateview .mix-remark
659  {
660    display: none;
661  }
662 
663  .pool-eb
664  {
665    color: #0000C8;
666  }
667 
668  #pool-row th
669  {
670    border-top: 0;
671    border-bottom: 1px solid #808080;
672    vertical-align: top;
673    padding: 0;
674  }
675 
676  #plateview .pool-data
677  {
678    font-weight: normal;
679  }
680  #plateview .comments
681  {
682    font-style: italic;
683  }
684 
685 
686  </style>
687</head>
688<body onload="init()">
689  <div class="paper <%=view.equals("list") ? "" : "landscape"%>">
690  <div class="noprint fullwidth" style="border-bottom: 1px dashed #A0A0A0; padding-left: 1em; padding-bottom: 1em;">
691    <span class="button" onclick="window.print()" style="float: left; margin-right: 1em;">
692      <img src="../images/print.png">Print&hellip;
693    </span>
694    <b>Note!</b> 
695    <%
696    if (view.equals("list"))
697    {
698      %>
699      For better printing reduce margins to about <i>5mm</i> and set page orientation
700      to <i>portrait</i>. To fit everything on a single page, scale down to <i>60-70%</i>.
701      <%
702    }
703    else
704    {
705      %>
706      For better printing reduce margins to about <i>5mm</i> and set page orientation
707      to <i>landscape</i>. The recommended scale is <i>100%</i>.
708      <%
709    }
710    %>
711    <br clear="all">
712  </div>
713 
714  <h1>Lab protocol for library pooling <span class="reggie">Reggie <%=reggie.getAbout().getVersion() %></span></h1>
715
716  <table style="width: 100%;" class="protocolheader">
717  <tr style="border-bottom: 1px solid #000000;">
718    <th style="width: 15%;">Library plate</th>
719    <td style="width: 30%; border-right: 1px solid #000000;"><%=libPlate == null ? "Multiple" : HTML.encodeTags(libPlate.getName())%></td>
720    <th style="width: 15%;"></th>
721    <th style="width: 20%;">Date</th>
722    <th style="width: 20%;">Operator</th>
723  </tr>
724  <tr>
725    <td rowspan="1" colspan="2" style="width: 50%; border-right: 1px solid #000000;"><%=libPlate != null ? HTML.niceFormat(libPlate.getDescription()) : ""%></td>
726    <td style="border-right: 1px solid #000000;">Pooling</td>
727    <td style="border-right: 1px solid #000000;"></td>
728    <td></td>
729  </tr>
730  </table>
731
732  <%
733  if (view.equals("list"))
734  {
735    for (Integer poolId :pools)
736    {
737      Extract pool = Extract.getById(dc, poolId);
738      %>
739      <div id="pool.<%=poolId%>" style="display: none;" class="pool-section">
740      <table style="width: 100%;" class="poolheader">
741      <tr valign="top">
742        <th style="width: 25%;"><%=HTML.encodeTags(pool.getName())%></th>
743        <th style="width: 75%; border-left: 1px solid #000000;">Comments:</th>
744      </tr>
745      <tr valign="top">
746        <td style="width: 25%;"><span id="molarity.<%=poolId%>"></span></td>
747        <td style="border-left: 1px solid #000000;"><%=HTML.niceFormat(pool.getDescription()) %></td>
748      </tr>
749      </table>
750      <table style="width: 100%;" class="listview" id="listview.<%=poolId%>">
751      <thead>
752        <tr class="toprow">
753          <th class="lib"></th>
754          <th>Remain</th>
755          <th>DNA</th>
756          <th class="workplate">Work</th>
757          <th>Lib</th>
758          <th>EB</th>
759          <th></th>
760        </tr>
761        <tr>
762          <th class="lib">Library</th>
763          <th>(µl)</th>
764          <th>(nM)</th>
765          <th class="workplate">plate</th>
766          <th>(µl)</th>
767          <th>(µl)</th>
768          <th>Remarks</th>
769        </tr>
770      </thead>
771      <tbody id="listview.<%=poolId%>.body">
772      </tbody>
773      <tbody>
774        <tr class="summary">
775          <td colspan="5" style="text-align: right; font-weight: bold; padding-right: 0.5em; font-size: 120%;">EB volume to add</td>
776          <td id="eb-volume.<%=poolId%>" class="eb">eb</td>
777          <td></td>
778        </tr>
779      </tbody>
780      </table>
781      </div>
782      <%
783    }
784  }
785  %>
786
787  <div class="loading" id="loading" style="display: none;"><table><tr><td><img src="../images/loading.gif"></td><td id="loading.msg">Please wait...</td></tr></table></div>
788  <div class="messagecontainer error" id="errorMessage" style="display: none;"></div>
789  <%
790
791  if (view.equals("plate"))
792  {
793    %>
794    <table class="plate" style="margin: 0em 0 0 0; width: 100%; display: none;" id="plateview">
795    <tr id="pool-row">
796      <th colspan="13">&nbsp;</th>
797    </tr>
798    <%
799    WellCoordinateFormatter rowF = new WellCoordinateFormatter(true);
800    WellCoordinateFormatter colF = new WellCoordinateFormatter(false);
801    %>
802    <tr class="header">
803      <th></th>
804      <%
805      for (int c = 0; c < libPlate.getColumns(); ++c)
806      {
807        %>
808        <th id="col.<%=c%>"><%=colF.format(c)%></th>
809        <%
810      }
811      %>
812    </tr>
813    <tbody>
814    <%
815    for (int r = 0; r < libPlate.getRows(); ++r)
816    {
817      String row = rowF.format(r);
818      %>
819      <tr class="row-<%=r%>">
820        <th id="row.<%=r%>" class="rowheader"><%=row%></th>
821        <%
822        for (int c = 0; c < libPlate.getColumns(); ++c)
823        {
824          %>
825          <td class="well col-<%=c%>" id="well.<%=r%>.<%=c%>"></td>
826          <%
827        }
828        %>
829      </tr>
830      <%
831    }
832    %>
833    </tbody>
834    </table>
835    <div style="margin: 1em;">
836      For each pool: <i>Number of libraries</i> • <i>Final molarity</i> • <i>Total volume</i> • <i>EB volume (dynamic mixing only)</i>
837    </div>
838    <%
839  }
840  %>
841  </div>
842</body>
843</html>
844<%
845}
846finally
847{
848  if (dc != null) dc.close();
849}
850%>
Note: See TracBrowser for help on using the repository browser.