source: extensions/net.sf.basedb.reggie/trunk/resources/libprep/lib_registration.jsp @ 1961

Last change on this file since 1961 was 1961, checked in by Nicklas Nordborg, 9 years ago

References #473: Register library processing results

The library registration now uses 'local storage' to temporarily save the form. In case the registration fails for any reason (common: data files are not correctly formatted), the saved data is used to re-populate all input fields so that the user doesn't have to enter all values again.

File size: 22.3 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.clients.web.Base" 
9  import="net.sf.basedb.clients.web.util.HTML" 
10  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
11%>
12<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
13<%@ taglib prefix="p" uri="/WEB-INF/path.tld" %>
14<%
15final SessionControl sc = Base.getExistingSessionControl(request, true);
16final String ID = sc.getId();
17final float scale = Base.getScale(sc);
18final String home = ExtensionsControl.getHomeUrl("net.sf.basedb.reggie");
19DbControl dc = null;
20try
21{
22  dc = sc.newDbControl();
23  final User user = User.getById(dc, sc.getLoggedInUserId());
24%>
25<base:page type="default" >
26<base:head scripts="ajax.js" styles="path.css">
27  <link rel="stylesheet" type="text/css" href="../css/reggie.css">
28  <script language="JavaScript" src="../reggie.js" type="text/javascript" charset="UTF-8"></script>
29
30<script language="JavaScript">
31var debug = false;
32var currentStep = 1;
33
34var libDateIsValid = false;
35var wellTableIsValid = false;
36var qubitCsvIsValid = false;
37var libCommentsIsValid = false;
38
39function init()
40{
41  var frm = document.forms['reggie'];
42  var bioplates = getLibraryBioPlates();
43 
44  // Load existing Library plates not yet registered
45  var plates = frm.bioplate;
46  if (bioplates != null && bioplates.length > 0)
47  {
48    for (var i=0; i < bioplates.length; i++)
49    {
50      var bioplate = bioplates[i];
51      var option = new Option(bioplate.name, bioplate.id);
52      option.comments = bioplate.comments;
53      plates.options[plates.length] = option;
54    }
55    bioplateIsValid = true;
56    setInputStatus('bioplate', '', 'valid');
57    bioPlateOnChange();
58    outcomeOnChange();
59  }
60  else
61  {
62    var msg = 'No Library bioplates available for processing.';
63    setFatalError(msg);
64    return;
65  }
66
67  // All is ok
68  frm.bioplate.focus();
69}
70
71
72function goNextAuto()
73{
74  goNext(false);
75}
76
77function goNext(manual)
78{
79  setInnerHTML('gonext.message', '');
80  if (currentStep == 1)
81  {   
82    gotoStep2();
83  }
84  setCurrentStep(currentStep);
85}
86
87
88
89function getLibraryBioPlates()
90{
91  var frm = document.forms['reggie']; 
92 
93  var request = Ajax.getXmlHttpRequest();
94  try
95  {
96    showLoadingAnimation('Loading Library bioplates...');
97    var url = '../LibPrep.servlet?ID=<%=ID%>&cmd=GetLibraryPlatesForLibPrep';   
98    request.open("GET", url, false); 
99    request.send(null);
100  }
101  finally
102  {
103    hideLoadingAnimation();
104  }
105 
106  if (debug) Main.debug(request.responseText);
107  var response = JSON.parse(request.responseText); 
108  if (response.status != 'ok')
109  {
110    setFatalError(response.message);
111    return false;
112  }
113  return response.bioplates;
114}
115
116function gotoStep2()
117{
118  var frm = document.forms['reggie']; 
119  frm.bioplate.disabled = true;
120  frm.outcome[0].disabled = true;
121  frm.outcome[1].disabled = true;
122 
123  currentStep = 2;
124  Main.addClass(document.getElementById('step.1.section'), 'disabled');
125  Main.hide('gonext');
126  Main.show('gocancel');
127  Main.show('goregister');
128 
129  var libInfo = getStoredInfo(frm.bioplate.value);
130  if (libInfo)
131  {
132    if (debug) Main.debug(JSON.stringify(libInfo));
133    var failed = document.getElementById('outcomeFailed').checked
134   
135    if (libInfo.libDate) 
136    {
137      frm.libDate.value = libInfo.libDate;
138      libDateOnChange();
139    }
140    if (!failed)
141    {
142      if (libInfo.wellTable.id && libInfo.wellTable.path)
143      {
144        lastPrefix = 'welltable';
145        setFileCallback(libInfo.wellTable.id, libInfo.wellTable.path);
146      }
147      if (libInfo.caliperGxd.id && libInfo.caliperGxd.path)
148      {
149        lastPrefix = 'calipergxd';
150        setFileCallback(libInfo.caliperGxd.id, libInfo.caliperGxd.path);
151      }
152      if (libInfo.caliperPdf.id && libInfo.caliperPdf.path)
153      {
154        lastPrefix = 'caliperpdf';
155        setFileCallback(libInfo.caliperPdf.id, libInfo.caliperPdf.path);
156      }
157      if (libInfo.qubitCsv.id && libInfo.qubitCsv.path)
158      {
159        lastPrefix = 'qubitcsv';
160        setFileCallback(libInfo.qubitCsv.id, libInfo.qubitCsv.path);
161      }
162    }
163    if (libInfo.libOperator) frm.libOperator.value = libInfo.libOperator;
164    if (libInfo.libComments) 
165    {
166      frm.libComments.value = libInfo.libComments;
167      libDateOnChange();
168    }
169  }
170 
171  Main.show('step.2.section');
172  frm.libDate.focus();
173
174  // Load Library protocols
175  var libProtocols = getProtocols('LIBRARY_PROTOCOL');
176  for (var i = 0; i < libProtocols.length; i++)
177  {
178    var protocol = libProtocols[i];
179    frm.libProtocol[frm.libProtocol.length] = new Option(protocol.name, protocol.id, protocol.isDefault);
180    setInputStatus('libProtocol', '', 'valid');
181  }
182  if (frm.libProtocol.length == 0)
183  {
184    frm.libProtocol[0] = new Option('- none -', '');
185  }
186}
187
188function getProtocols(subtype)
189{
190  var request = Ajax.getXmlHttpRequest();
191  try
192  {
193    showLoadingAnimation('Loading ' + subtype + ' protocols...');
194    var url = '../Protocol.servlet?ID=<%=ID%>&cmd=GetProtocols&subtype='+subtype;   
195    request.open("GET", url, false); 
196    request.send(null);
197  }
198  finally
199  {
200    hideLoadingAnimation();
201  }
202
203  if (debug) Main.debug(request.responseText);
204  var response = JSON.parse(request.responseText); 
205  if (response.status != 'ok')
206  {
207    setFatalError(response.message);
208    return false;
209  }
210  return response.protocols;
211}
212
213function bioPlateOnChange()
214{
215  var frm = document.forms['reggie'];
216}
217
218function outcomeOnChange()
219{
220  var frm = document.forms['reggie'];
221  var failed = document.getElementById('outcomeFailed').checked
222
223  if (failed)
224  {
225    Main.addClass(frm.libComments, 'required');
226    Main.hide('filesSection');
227  }
228  else
229  {
230    Main.removeClass(frm.libComments, 'required');
231    Main.show('filesSection');
232  }
233}
234
235var lastPrefix;
236function browseOnClick(prefix, extension)
237{
238  var frm = document.forms['reggie'];
239  if (frm[prefix+'.path'].disabled) return;
240 
241  var url = getRoot() + 'filemanager/index.jsp?ID=<%=ID%>&cmd=SelectOne&callback=setFileCallback';
242  url += '&resetTemporary=1&tmpfilter:STRING:name='+escape('%.' + extension);
243  lastPrefix = prefix;
244  Main.openPopup(url, 'SelectFile', 1000, 700);
245}
246
247function setFileCallback(id, path)
248{
249  var frm = document.forms['reggie'];
250  frm[lastPrefix+'.id'].value = id;
251  frm[lastPrefix+'.path'].value = path;
252 
253  if (lastPrefix == 'welltable')
254  {
255    preValidateCsvFile();
256  }
257  else if (lastPrefix == 'qubitcsv')
258  {
259    qubitCsvFileOnChange();
260    frm.libProtocol.focus();
261  }
262  else
263  {
264    setInputStatus(lastPrefix, '', 'valid');
265  }
266}
267
268function libDateOnChange()
269{
270  var frm = document.forms['reggie'];
271  libDateIsValid = false;
272  setInputStatus('libDate', '', '');
273 
274  var libDate = frm.libDate.value;
275  if (libDate == '')
276  {
277    setInputStatus('libDate', 'Missing', 'invalid');
278    return;
279  }
280
281  // Auto-fill the date if it's only given with 4(MMdd) or 6(yyMMdd) digits.   
282  libDate = autoFillDate(libDate);
283  frm.libDate.value = libDate;
284 
285  if (!Dates.isDate(libDate, 'yyyyMMdd'))
286  {
287    setInputStatus('libDate', 'Not a valid date', 'invalid');
288    return;
289  }
290 
291  setInputStatus('libDate', '', 'valid');
292  libDateIsValid = true;
293}
294
295
296function preValidateCsvFile()
297{
298  var frm = document.forms['reggie'];
299  var csvId = frm['welltable.id'].value;
300  var csvPath = frm['welltable.path'].value;
301 
302  wellTableIsValid = false;
303 
304  if (!csvId) 
305  {
306    setInputStatus('welltable', 'Missing', 'invalid');
307    return;
308  }
309 
310  var url = '../LibPrep.servlet?ID=<%=ID%>&cmd=PreValidateCaliperWellTable&csv='+csvId;
311 
312  var request = Ajax.getXmlHttpRequest();
313  request.open("POST", url, false); 
314  request.send('');
315 
316  if (debug) Main.debug(request.responseText);
317  var response = JSON.parse(request.responseText); 
318 
319  if (response.messages && response.messages.length > 0)
320  {
321    var messages = '<ul>';
322    for (var i = 0; i < response.messages.length; i++)
323    {
324      messages += '<li>' + response.messages[i];
325    }
326    messages += '</ul>';
327    setInnerHTML('messages', messages);
328    Main.show('messages');
329  }
330  else
331  {
332    Main.hide('messages'); 
333  }
334 
335  if (response.status != 'ok')
336  {
337    setInputStatus('welltable', response.message, 'invalid');
338    Main.addClass(document.getElementById('messages'), 'failure');
339    return;
340  }
341
342  setInputStatus('welltable', '', 'valid');
343  wellTableIsValid = true;
344}
345
346
347function qubitCsvFileOnChange()
348{
349  var frm = document.forms['reggie'];
350  qubitCsvIsValid = false;
351  if (!frm['qubitcsv.id'].value)
352  {
353    // A PDF is reuired for successful registration, optional after a failure
354    var msg = frm['qubitcsv.path'].value ? 'Use the Browse button to select a file' : 'Missing';
355    setInputStatus('qubitcsv', msg, 'invalid');
356    return;
357  }
358  qubitCsvIsValid = true;
359  setInputStatus('qubitcsv', '', 'valid');
360}
361
362function libCommentsOnChange()
363{
364  var failed = document.getElementById('outcomeFailed').checked;
365  if (!failed) return;
366
367  var frm = document.forms['reggie'];
368  libCommentsIsValid = false;
369  setInputStatus('libComments', '', '');
370 
371  var comments = frm.libComments.value;
372  if (comments == '')
373  {
374    setInputStatus('libComments', 'Missing', 'invalid');
375    return;
376  }
377
378  setInputStatus('libComments', '', 'valid');
379  libCommentsIsValid = true;
380}
381
382
383function step2IsValid()
384{
385  var failed = document.getElementById('outcomeFailed').checked;
386  if (failed)
387  {
388    return libDateIsValid && libCommentsIsValid;
389  }
390  else
391  {
392    return libDateIsValid && wellTableIsValid && qubitCsvIsValid;
393  }
394}
395
396function goRegister()
397{
398  if (!step2IsValid()) return;
399 
400  Main.hide('goregister');
401  Main.hide('gocancel');
402
403  var frm = document.forms['reggie'];
404  var libPlateId = parseInt(frm.bioplate.value, 10);
405  var submitInfo = {};
406  submitInfo.bioplate = libPlateId;
407
408  Main.addClass(document.getElementById('step.2.section'), 'disabled');
409  var url = '../LibPrep.servlet?ID=<%=ID%>&cmd=ImportLibPrepResults';
410  var failed = document.getElementById('outcomeFailed').checked;
411  submitInfo.failed = failed;
412   
413  if (!failed)
414  {
415    saveToLocalStorage(libPlateId);
416    submitInfo.wellTableCsv = parseInt(frm['welltable.id'].value, 10);
417    submitInfo.caliperGxd = parseInt(frm['calipergxd.id'].value, 10);
418    submitInfo.caliperPdf = parseInt(frm['caliperpdf.id'].value, 10);
419    submitInfo.qubitCsv = parseInt(frm['qubitcsv.id'].value, 10);
420  }
421   
422  submitInfo.libDate = frm.libDate.value;
423  submitInfo.libProtocol = parseInt(frm.libProtocol.value, 10);
424  submitInfo.libOperator = frm.libOperator.value;
425  submitInfo.libComments = frm.libComments.value;
426 
427  if (debug) Main.debug(JSON.stringify(submitInfo));
428 
429  var request = Ajax.getXmlHttpRequest();
430  try
431  {
432    showLoadingAnimation('Performing registration...');
433    request.open("POST", url, false);
434    request.send(JSON.stringify(submitInfo));
435  }
436  finally
437  {
438    hideLoadingAnimation();
439  }
440 
441  if (debug) Main.debug(request.responseText);
442  var response = JSON.parse(request.responseText);
443 
444  if (response.messages && response.messages.length > 0)
445  {
446    var msg = '<ul>';
447    for (var i = 0; i < response.messages.length; i++)
448    {
449      var msgLine = response.messages[i];
450      if (msgLine.indexOf('[Warning]') >= 0)
451      {
452        msg += '<li class="warning">' + msgLine.replace('[Warning]', '');
453      }
454      else
455      {
456        msg += '<li>' + msgLine;
457      }
458    }
459    msg += '</ul>';
460    setInnerHTML('messages', msg);
461    Main.show('messages');
462  }
463 
464  if (response.status != 'ok')
465  {
466    Main.addClass(document.getElementById('messages'), 'failure');
467    setFatalError(response.message);
468    return false;
469  }
470  else
471  {
472    removeFromLocalStorage(libPlateId);
473  }
474
475  Main.show('gorestart');
476}
477
478
479/**
480  Save as much information as possible about the library registration.
481  The information is stored in the localStorage()
482  under the key 'reggie.libplate.<id>.info' where
483  <id> is the ID of the library plate.
484*/
485function saveToLocalStorage(libPlateId)
486{
487  if (window.localStorage)
488  {
489    var frm = document.forms['reggie'];
490    var libInfo = new Object();
491    libInfo.id = libPlateId;
492    libInfo.libDate = frm.libDate.value;
493    libInfo.wellTable = { id: frm['welltable.id'].value, path: frm['welltable.path'].value };
494    libInfo.caliperGxd = { id: frm['calipergxd.id'].value, path: frm['calipergxd.path'].value };
495    libInfo.caliperPdf = { id: frm['caliperpdf.id'].value, path: frm['caliperpdf.path'].value };
496    libInfo.qubitCsv = { id: frm['qubitcsv.id'].value, path: frm['qubitcsv.path'].value };
497    libInfo.libProtocol = frm.libProtocol.value;
498    libInfo.libOperator = frm.libOperator.value;
499    libInfo.libComments = frm.libComments.value;
500   
501    window.localStorage.setItem('reggie.libplate.' + libPlateId + '.info', JSON.stringify(libInfo));
502    if (debug)
503    {
504      Main.debug(libPlateId + ': ' + window.localStorage.getItem('reggie.libplate.' + libPlateId + '.info'));
505    }
506  }
507}
508
509function removeFromLocalStorage(libPlateId)
510{
511  if (!window.localStorage) return;
512  if (debug) Main.debug('removeFromLocalStorage:' + libPlateId);
513  window.localStorage.removeItem('reggie.libplate.' + libPlateId + '.info');
514}
515
516function getStoredInfo(libPlateId)
517{
518  if (!window.localStorage) return null;
519  try
520  {
521    var stored = window.localStorage.getItem('reggie.libplate.' + libPlateId + '.info');
522    if (debug) Main.debug(stored);
523    return stored ? JSON.parse(stored) : null;
524  }
525  catch (e)
526  {
527    Main.debug('Could not load stored information for tube ' + tubeId + ': ' + e);
528  }
529}
530
531
532</script>
533
534</base:head>
535<base:body onload="init()">
536
537  <p:path><p:pathelement 
538    title="Reggie" href="<%="../index.jsp?ID="+ID%>" 
539    /><p:pathelement title="Library registration" 
540    /></p:path>
541
542  <div class="content">
543  <%
544  if (sc.getActiveProjectId() == 0)
545  {
546    %>
547    <div class="messagecontainer note" style="width: 950px; margin-left: 20px; margin-bottom: 20px; margin-right: 0px; font-weight: bold; color: #cc0000;">
548      No project has been selected. You may proceed with the registration but
549      created items will not be shared.
550    </div>
551    <%
552  }
553  %>
554
555  <form name="reggie" onsubmit="return false;">
556    <input type="hidden" name="pdf.id" value="">
557 
558  <div id="step.1.section">
559  <table class="stepform">
560  <tr>
561    <td rowspan="3" class="stepno">1</td>
562    <td class="steptitle">Select Library bioplate</td>
563  </tr>
564  <tr>
565    <td class="stepfields">
566      <table>
567      <tr valign="top">
568        <td class="prompt">Library bioplate</td>
569        <td class="input"><select class="required" style="width:90%;" 
570            name="bioplate" id="bioplate" onchange="bioPlateOnChange()"></select>
571        </td>
572        <td class="status" id="bioplate.status"></td>
573        <td class="help"><span id="bioplate.message" class="message" style="display: none;"></span>
574          Select an existing Library bioplate. The list contain all Library bioplates that
575          has not yet been processed (determined by the absence of a 'creation' date).
576        </td>
577      </tr>
578      <tr valign="top" id="outcomeSection">
579        <td class="prompt">Outcome</td>
580        <td class="input">
581          <input type="radio" name="outcome" id="outcomeSuccess" 
582            onchange="outcomeOnChange()" checked><label for="outcomeSuccess">Success</label> - continue processing<br>
583          <input type="radio" name="outcome" id="outcomeFailed" 
584            onchange="outcomeOnChange()"><label for="outcomeFailed">Failure</label> - no further processing
585        </td>
586        <td class="status"></td>
587        <td class="help">
588          Select the <b>Failure</b> option if further processing to pooled libraries is not possible.
589          Existing RNA will be flagged and added to the <b>Flagged RNA</b> list.
590        </td>
591      </tr>
592      </table>
593    </td>
594  </tr>
595  </table>
596  </div>
597 
598 
599  <div id="step.2.section" style="display: none;">
600  <table class="stepform">
601  <tr>
602    <td rowspan="3" class="stepno">2</td>
603    <td class="steptitle">Full plate registration</td>
604  </tr>
605  <tr>
606    <td class="stepfields">
607      <table>
608      <tr valign="top">
609        <td class="prompt">Date</td>
610        <td class="input">
611          <input type="text" class="required" name="libDate" value="" size="12" maxlength="10"
612            onblur="libDateOnChange()" onkeypress="focusOnEnter(event, 'welltable.path')">
613        </td>
614        <td class="status" id="libDate.status"></td>
615        <td class="help">
616          <span id="libDate.message" class="message" style="display: none;"></span>(YYYYMMDD or MMDD)
617        </td>
618      </tr>
619      <tbody id="filesSection">
620      <tr>
621        <td class="prompt">Caliper files</td>
622        <td class="input"></td>
623        <td class="status"></td>
624        <td class="help"></td>
625      </tr>
626      <tr valign="top">
627        <td class="subprompt">Well table CSV</td>
628        <td class="input">
629          <input type="hidden" name="welltable.id" value="">
630          <table>
631          <tr>
632          <td><input class="text required" type="text" 
633            name="welltable.path" value=""
634            size="50" onkeypress="doOnEnter(event, function(){document.getElementById('btnWellTable').click()})"
635            onblur="csvFileOnChange()"
636            ></td>
637          <td style="padding-left: 4px;"><base:button 
638              title="Browse&hellip;"
639              onclick="browseOnClick('welltable', 'csv')"
640              id="btnWellTable"
641              />
642          </td>
643          </tr>
644          </table>
645        </td>
646        <td class="status" id="welltable.status"></td>
647        <td class="help"><span id="welltable.message" class="message" style="display: none;"></span>
648           Select the <b>Well Table CSV</b> file that contains the exported analysis
649           result from the Caliper software.
650        </td>
651      </tr>
652      <tr valign="top">
653        <td class="subprompt">GXD raw data</td>
654        <td class="input">
655          <input type="hidden" name="calipergxd.id" value="">
656          <table>
657          <tr>
658          <td><input class="text" type="text" 
659            name="calipergxd.path" value=""
660            size="50" onkeypress="doOnEnter(event, function(){document.getElementById('btnCaliperGxd').click()})"
661            ></td>
662          <td style="padding-left: 4px;"><base:button 
663              title="Browse&hellip;"
664              onclick="browseOnClick('calipergxd', 'gxd')"
665              id="btnCaliperGxd"
666              />
667          </td>
668          </tr>
669          </table>
670        </td>
671        <td class="status" id="calipergxd.status"></td>
672        <td class="help"><span id="calipergxd.message" class="message" style="display: none;"></span>
673          Select the <b>GXD raw data file</b> from Caliper.
674        </td>
675      </tr>
676      <tr valign="top">
677        <td class="subprompt">PDF file</td>
678        <td class="input">
679          <input type="hidden" name="caliperpdf.id" value="">
680          <table>
681          <tr>
682          <td><input class="text" type="text" 
683            name="caliperpdf.path" value=""
684            size="50" onkeypress="doOnEnter(event, function(){document.getElementById('btnCaliperPdf').click()})"
685            ></td>
686          <td style="padding-left: 4px;"><base:button 
687              title="Browse&hellip;"
688              onclick="browseOnClick('caliperpdf', 'pdf')"
689              id="btnCaliperPdf"
690              />
691          </td>
692          </tr>
693          </table>
694        </td>
695        <td class="status" id="caliperpdf.status"></td>
696        <td class="help"><span id="caliperpdf.message" class="message" style="display: none;"></span>
697          Select the <b>PDF file</b> that contains a printout with diagrams and other
698          useful documentation.
699        </td>
700      </tr>
701      <tr>
702        <td class="prompt">Qubit files</td>
703        <td class="input"></td>
704        <td class="status"></td>
705        <td class="help"></td>
706      </tr>
707      <tr valign="top">
708        <td class="subprompt">Conc. CSV</td>
709        <td class="input">
710          <input type="hidden" name="qubitcsv.id" value="">
711          <table>
712          <tr>
713          <td><input class="text required" type="text" 
714            name="qubitcsv.path" value=""
715            size="50" onkeypress="doOnEnter(event, function(){document.getElementById('btnQubitCsv').click()})"
716            onblur="qubitCsvFileOnChange()"
717            ></td>
718          <td style="padding-left: 4px;"><base:button 
719              title="Browse&hellip;"
720              onclick="browseOnClick('qubitcsv', 'csv')"
721              id="btnQubitCsv"
722              />
723          </td>
724          </tr>
725          </table>
726        </td>
727        <td class="status" id="qubitcsv.status"></td>
728        <td class="help"><span id="qubitcsv.message" class="message" style="display: none;"></span>
729          Select the <b>Qubit CSV</b> file that contains the table with concentration
730          measurements.
731        </td>
732      </tr>
733      </tbody>
734      <tr valign="top">
735        <td class="prompt">Protocol</td>
736        <td class="input"><select style="width:90%" name="libProtocol" id="libProtocol" 
737          onkeypress="focusOnEnter(event, 'libOperator')"></select></td>
738        <td class="status" id="libProtocol.status"></td>
739        <td class="help"><span id="libProtocol.message" class="message" style="display: none;"></span>
740          Select the protocol used for library preparation.
741        </td>
742      </tr>
743      <tr valign="top">
744        <td class="prompt">Operator</td>
745        <td class="input">
746          <input type="text" name="libOperator" value="<%=HTML.encodeTags(user.getName()) %>" 
747            style="width: 90%;" maxlength="255" onkeypress="focusOnEnter(event, 'libComments')">
748        </td>
749        <td class="status" id="libOperator.status"></td>
750        <td class="help">
751          <span id="libOperator.message" class="message" style="display: none;"></span>
752        </td>
753      </tr>
754      <tr valign="top">
755        <td class="prompt">Comments</td>
756        <td class="input"><textarea rows="4" cols="50" style="width: 90%;" name="libComments" value="" onblur="libCommentsOnChange()"></textarea></td>
757        <td class="status" id="libComments.status"></td>
758        <td class="help"><span id="libComments.message" class="message" style="display: none;"></span>Comments about the library preparation.</td>
759      </tr>
760      </table>
761    </td>
762  </tr>
763  </table>
764  </div>
765 
766 
767  <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>
768 
769  <div class="messagecontainer error" id="errorMessage" style="display: none; width: 950px; margin-left: 20px; margin-bottom: 0px;"></div>
770 
771  <div id="messages" class="success" style="display: none; width: 950px; margin-left: 20px; margin-top: 20px;"></div>
772 
773  <table style="margin-left: 20px; margin-top: 10px;" class="navigation">
774    <tr>
775      <td><base:button id="gocancel" title="Cancel" onclick="goRestart(false)" style="display: none;"/></td>
776      <td><base:button id="gonext" title="Next" image="<%=home+"/images/gonext.png"%>" onclick="goNext(true)"/></td>
777      <td><base:button id="goregister" title="Register" image="<%=home+"/images/import.png"%>" onclick="goRegister()" style="display: none;"/></td>
778      <td><base:button id="gorestart" title="Restart" image="<%=home+"/images/goback.png"%>" onclick="goRestart(true)" style="display: none;"/></td>
779      <td id="gonext.message" class="message"></td>
780    </tr>
781  </table>
782 
783  </form>
784  </div>
785 
786</base:body>
787</base:page>
788<%
789}
790finally
791{
792  if (dc != null) dc.close();
793}
794%>
Note: See TracBrowser for help on using the repository browser.