source: extensions/net.sf.basedb.reggie/trunk/resources/consentform.jsp @ 1521

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

References #349: Copy consent information to multiple cases

The consent registration wizard will now load and check existing consent for all cases and blood samples linked with the given patient. It allows the user to select exactly which cases and blood samples to register. The wizard can be repeated at a later time to register consent for more cases/blood samples.

File size: 16.4 KB
Line 
1<%@ page
2  pageEncoding="UTF-8"
3  session="false"
4  import="net.sf.basedb.core.Application"
5  import="net.sf.basedb.core.User"
6  import="net.sf.basedb.core.DbControl"
7  import="net.sf.basedb.core.SessionControl"
8  import="net.sf.basedb.clients.web.Base"
9  import="net.sf.basedb.clients.web.util.HTML"
10  import="net.sf.basedb.util.Values"
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);
18DbControl dc = null;
19try
20{
21  dc = sc.newDbControl();
22  final User user = User.getById(dc, sc.getLoggedInUserId());
23%>
24<base:page type="default" >
25<base:head scripts="ajax.js" styles="path.css">
26  <link rel="stylesheet" type="text/css" href="reggie.css">
27  <script language="JavaScript" src="reggie.js" type="text/javascript" charset="UTF-8"></script>
28
29<script language="JavaScript">
30
31var debug = true;
32var currentStep = 1;
33var caseIsValid = false;
34var consentDateIsValid = false;
35
36var consentToId = { "Yes": "consent.yes", "No" : "consent.no", "Not asked": "consent.notAsked" };
37var patientInfo;
38
39function init()
40{
41  var frm = document.forms['reggie'];
42  frm.caseName.focus();
43}
44
45function step1IsValid()
46{
47  var frm = document.forms['reggie'];
48  var caseName = frm.caseName.value;
49  caseIsValid = false;
50  if (caseName == '')
51  {
52    setInputStatus('case', 'Missing', 'invalid');
53    frm.caseName.focus();
54  }
55  else if (!isValidCaseName(caseName))
56  {
57    setInputStatus('case', 'Only 7-digits name is allowed .', 'invalid');
58    frm.caseName.focus();
59  }
60  else
61  {
62    setInputStatus('case', '', 'valid');
63    caseIsValid = true;
64  }
65 
66  return caseIsValid;
67}
68
69function step2IsValid()
70{
71  return consentDateIsValid;
72}
73
74function goNext(manual)
75{
76  setInnerHTML('gonext.message', '');
77  if (currentStep == 1)
78  {
79    if (step1IsValid()) gotoStep2();
80  }
81  else if (currentStep == 2)
82  {
83    if (step2IsValid()) gotoStep3();
84  }
85}
86
87
88function gotoStep2()
89{
90  // Check entered case and pnr with AJAX
91  var frm = document.forms['reggie'];
92 
93  frm.caseName.disabled = true;
94  currentStep = 2;
95 
96  var caseName = frm.caseName.value;
97  var request = Ajax.getXmlHttpRequest();
98  var url = 'ConsentForm.servlet?ID=<%=ID%>&cmd=GetCaseInfo';
99  url += '&caseName=' + caseName;
100  request.open("GET", url, false);
101  request.send(null);
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  Main.hide('gonext');
112  Main.show('consentSection');
113 
114  // Get case information from the AJAX response
115  patientInfo = response.patientInfo;
116  var caseInfo = response.caseInfo;
117  var specimenInfo = response.specimenInfo;
118 
119
120  if (caseInfo && caseInfo.consentDate)
121  {
122    frm.consentDate.value = caseInfo.consentDate;
123  }
124  frm.consentDate.focus();
125 
126  if (patientInfo)
127  {
128    var html = '';
129    var numEnabled = 0;
130    if (patientInfo.allCases)
131    {
132      for (var i = 0; i < patientInfo.allCases.length; i++)
133      {
134        var c = patientInfo.allCases[i];
135        var laterality = c.laterality ? ' ('+c.laterality+')' : '';
136        var disabled = '';
137        if (c.consent)
138        {
139          disabled = 'disabled';
140        }
141        else
142        {
143          numEnabled++;
144        }
145        html += '<input type="checkbox" name="case.'+c.id+'" id="case.'+c.id+'" checked ' + disabled +'>';
146        html += '<label for="case.'+c.id+'">Case: ' + c.name + laterality + '</label><br>';
147      }
148    }
149   
150    if (patientInfo.allBlood)
151    {
152      for (var i = 0; i < patientInfo.allBlood.length; i++)
153      {
154        var c = patientInfo.allBlood[i];
155        var disabled = '';
156        if (c.consent)
157        {
158          disabled = 'disabled';
159        }
160        else
161        {
162          numEnabled++;
163        }
164        html += '<input type="checkbox" name="blood.'+ c.id + '" id="blood.'+c.id+'" checked ' + disabled +'>';
165        html += '<label for="blood.'+c.id+'">Blood: ' + c.name + '</label><br>';
166      }
167    }
168   
169    document.getElementById('moreCases').innerHTML = html;
170   
171    if (numEnabled > 0)
172    {
173      enableConsentOption('consent.yes', true);
174      setInputStatus('consent', 'This patient already exists and has at least one case or blood sample with missing consent.', 'valid');
175      Main.showInline('morehelp.multiple');
176      Main.showInline('morehelp.yesonly');
177      Main.show('gocancel');
178      Main.show('goregister');
179    }
180    else
181    {
182      enableConsentOption('consent.yes', true);
183      setInputStatus('consent', '"Yes" has already been registered for all case and blood samples for this patient. It is not possible to change with this wizard.', '');
184      Main.show('gorestart');
185      frm.consentDate.disabled = true;
186    }
187    Main.show('moreCasesSection');
188  }
189  else if (caseInfo)
190  {
191    // A consent has already been registered for this case
192    // We do not support updating this
193    enableConsentOption(consentToId[caseInfo.consent], true);
194    setInputStatus('consent', '"' + caseInfo.consent + '" has already been registered for this case. It is not possible to change with this wizard.', '');
195    Main.show('gorestart');
196    frm.consentDate.disabled = true;
197  }
198  else if (specimenInfo)
199  {
200    // There is no existing case but there are specimen related to it
201    // This wizard will only allow 'Yes' option on the consent form
202    enableConsentOption('consent.yes', true);
203    setInputStatus('consent', 'Specimen tubes for this case already exists.', 'valid');
204    Main.showInline('morehelp.yesonly');
205    Main.show('gocancel');
206    Main.show('goregister');
207  }
208  else
209  {
210    // We have no information about this case -- but allow a consent to be registered in any case
211    enableConsentOption('consent.no', true);
212    enableConsentOption('consent.notAsked');
213    enableConsentOption('consent.yes');
214    Main.showInline('morehelp.any');
215    Main.show('gocancel');
216    Main.show('goregister');
217  }
218
219}
220
221function goRegister()
222{
223  if (!step2IsValid()) return;
224 
225  var frm = document.forms['reggie'];
226  frm.otherReasonIfNotAsked.disabled = true;
227  frm.consentDate.disabled = true;
228  for (var i = 0; i < frm.consent.length; i++)
229  {
230    frm.consent[i].disabled = true;
231  }
232  for (var i = 0; i < frm.reasonIfNotAsked.length; i++)
233  {
234    frm.reasonIfNotAsked[i].disabled = true;
235  }
236 
237  Main.hide('goregister');
238  Main.hide('gocancel');
239
240  var consentInfo = new Object();
241  consentInfo.caseName = frm.caseName.value;
242  consentInfo.consentDate = frm.consentDate.value;
243  consentInfo.consent = Forms.getCheckedRadio(frm.consent).value;
244  if (consentInfo.consent == 'Not asked')
245  {
246    var reasonIfNotAsked = '';
247    for (var i = 0; i < frm.reasonIfNotAsked.length; i++)
248    {
249      var option = frm.reasonIfNotAsked[i];
250      if (option.checked)
251      {
252        if (option.id == 'notAsked.other')
253        {
254          reasonIfNotAsked += frm.otherReasonIfNotAsked.value;
255        }
256        else
257        {
258          var label = document.getElementById(option.id + '.label');
259          reasonIfNotAsked += label.innerHTML + '\n';
260        }
261      }
262    }
263    consentInfo.reasonIfNotAsked = reasonIfNotAsked;
264  }
265 
266  if (patientInfo)
267  {
268    var selectedSamples = new Array();
269    if (patientInfo.allCases)
270    {
271      for (var i = 0; i < patientInfo.allCases.length; i++)
272      {
273        var c = patientInfo.allCases[i];
274        var chk = frm['case.'+c.id];
275        if (chk.checked && !chk.disabled) selectedSamples[selectedSamples.length] = c.id;
276      }
277    }
278   
279    if (patientInfo.allBlood)
280    {
281      for (var i = 0; i < patientInfo.allBlood.length; i++)
282      {
283        var c = patientInfo.allBlood[i];
284        var chk = frm['blood.'+c.id];
285        if (chk.checked && !chk.disabled) selectedSamples[selectedSamples.length] = c.id;
286      }
287    }
288    consentInfo.selectedSamples = selectedSamples;
289  }
290
291  var submitInfo = new Object();
292  submitInfo.consentInfo = consentInfo;
293 
294  if (debug) Main.debug(JSON.stringify(submitInfo));
295  var request = Ajax.getXmlHttpRequest();
296  var url = 'ConsentForm.servlet?ID=<%=ID%>&cmd=RegisterConsent';
297  request.open("POST", url, false);
298  request.setRequestHeader("Content-Type", "application/json");
299  request.send(JSON.stringify(submitInfo));
300
301  if (debug) Main.debug(request.responseText);
302 
303  var response = JSON.parse(request.responseText);
304  if (response.status != 'ok')
305  {
306    setFatalError(response.message);
307    return false;
308  }
309 
310  var msg = '<ul>';
311  for (var i = 0; i < response.messages.length; i++)
312  {
313    msg += '<li>' + response.messages[i];
314  }
315  msg += '</ul>';
316  setInnerHTML('done', msg);
317  Main.show('done');
318  Main.show('gorestart');
319}
320
321function enableConsentOption(optionId, checkIt)
322{
323  var option = document.getElementById(optionId); // The radio button
324  option.disabled = false;
325  if (checkIt) option.checked = true;
326  var label = document.getElementById(optionId + '.label'); // The label
327  Main.removeClass(label, 'disabled');
328}
329
330function consentDateOnChange()
331{
332  var frm = document.forms['reggie'];
333  consentDateIsValid = false;
334  setInputStatus('consentDate', '', '');
335 
336  var consentDate = frm.consentDate.value;
337 
338  if (consentDate == '')
339  {
340    setInputStatus('consentDate', 'Missing', 'warning');
341  }
342  else
343  {
344    // Auto-fill the date if it's only given with 4(MMdd) or 6(yyMMdd) digits.   
345    consentDate = autoFillDate(consentDate);
346    frm.consentDate.value = consentDate;
347 
348    if (!Dates.isDate(consentDate, 'yyyyMMdd'))
349    {
350      setInputStatus('consentDate', 'Not a valid date', 'invalid');
351      return;
352    }
353    setInputStatus('consentDate', '', 'valid');
354  }
355 
356  consentDateIsValid = true;
357}
358
359
360function consentOnChange()
361{
362  // If "Not asked" is selected we must enable the second question
363  var isAsked = !document.getElementById('consent.notAsked').checked;
364 
365  var frm = document.forms['reggie'];
366  var reasonIfNotAsked = frm.reasonIfNotAsked;
367  for (var i = 0; i < reasonIfNotAsked.length; i++)
368  {
369    reasonIfNotAsked[i].disabled = isAsked;
370    var label = document.getElementById(reasonIfNotAsked[i].id + '.label');
371    Main.addOrRemoveClass(label, 'disabled', isAsked);
372  }
373  frm.otherReasonIfNotAsked.disabled = isAsked;
374 
375}
376
377</script>
378<style>
379.disabled
380{
381  color: #999999;
382  font-style: italic;
383}
384</style>
385</base:head>
386<base:body onload="init()">
387
388  <p:path style="margin-top: 20px; margin-bottom: 10px;">
389    <p:pathelement title="Reggie" href="<%="index.jsp?ID="+ID%>" />
390    <p:pathelement title="Consent form registration" />
391  </p:path>
392
393  <%
394  if (sc.getActiveProjectId() == 0)
395  {
396    %>
397    <base:note type="warning" style="width: 800px; margin-left: 20px; margin-bottom: 20px; margin-right: 0px; font-weight: bold; color: #cc0000;">
398      No project has been selected. You may proceed with the registration but
399      created items will not be shared.
400    </base:note>
401    <%
402  }
403  %>
404
405  <form name="reggie" onsubmit="return false;">
406 
407  <!-- 1. Case + Personal number -->
408  <table border="0" cellspacing="0" cellpadding="0" class="stepform">
409  <tr>
410    <td rowspan="3" class="stepno">1</td>
411    <td class="steptitle">Enter Case Name</td>
412  </tr>
413  <tr>
414    <td class="stepfields">
415      <table border="0" cellspacing="0" cellpadding="0" width="100%">
416      <tr>
417        <td class="prompt">Case name</td>
418        <td class="input"><input type="text" name="caseName" 
419          size="18" maxlength="12" onkeypress="doOnTabOrEnter(event, goNext)"></td>
420        <td class="status" id="case.status"></td>
421        <td class="help"><span id="case.message" class="message" style="display: none;"></span>The 7-digit case (barcode) associated with the case.</td>
422      </tr>
423      </table>
424    </td>
425  </tr>
426  </table>
427
428  <!-- 2. Consent section -->
429  <div id="consentSection" style="display: none;">
430  <p>
431  <table border="0" cellspacing="0" cellpadding="0" class="stepform">
432  <tr>
433    <td rowspan="2" class="stepno">2</td>
434    <td class="steptitle">Consent form</td>
435  </tr>
436  <tr>
437    <td class="stepfields">
438      <table border="0" cellspacing="0" cellpadding="0" width="100%">
439      <tr valign="top">
440        <td class="prompt">Date</td>
441        <td class="input" style="padding-left: 0px;">
442          <input type="text" name="consentDate" value="" size="12" maxlength="10"
443            onblur="consentDateOnChange()">
444        </td>
445        <td class="status" id="consentDate.status"></td>
446        <td class="help">
447          <span id="consentDate.message" class="message" style="display: none;"></span>(YYYYMMDD or MMDD)
448        </td>
449      </tr>
450      <tr valign="top">
451        <td class="prompt">Consent</td>
452        <td class="input" style="padding-left: 0px;">
453          <input id="consent.no" type="radio" name="consent" value="No" disabled onchange="consentOnChange()">
454            <label id="consent.no.label" for="consent.no" class="disabled">No</label><br>
455          <input id="consent.yes" type="radio" name="consent" value="Yes" disabled onchange="consentOnChange()">
456            <label id="consent.yes.label" for="consent.yes" class="disabled">Yes</label><br>
457          <div id="moreCasesSection" style="display: none;">
458            <table border="0" cellpadding="0" cellspacing="0">
459            <tr valign="baseline">
460              <td><img src="../../images/joust/joinbottom.gif"></td>
461              <td id="moreCases"></td>
462            </tr>
463            </table>
464          </div>
465          <input id="consent.notAsked" type="radio" name="consent" value="Not asked" disabled onchange="consentOnChange()">
466            <label id="consent.notAsked.label" for="consent.notAsked" class="disabled">Not asked</label>
467        </td>
468        <td class="status" id="consent.status"></td>
469        <td class="help" rowspan="2">
470          <span id="consent.message" class="message" style="display: none;"></span>
471          <span id="morehelp.multiple" style="display:none;">
472            Select the cases and blood samples to register. Cases with
473            already existing consent can't be deselected.
474          </span>
475          <span id="morehelp.yesonly" style="display: none;">
476            <b>Yes</b> is the only option supported by this wizard. The other alternatives
477            may require manual deletion of already registered information.
478          </span>
479          <span id="morehelp.any" style="display: none;">
480            There is currently no information about this case.
481          </span>
482        </td>
483      </tr>
484      <tr valign="top">
485        <td class="subprompt">Reason if not asked</td>
486        <td class="input">
487          <table border="0" cellpadding="0" cellspacing="0">
488          <tr valign="baseline">
489            <td><img src="../../images/joust/joinbottom.gif"></td>
490            <td><input id="notAsked.forgot" type="checkbox" name="reasonIfNotAsked" disabled></td>
491            <td><label id="notAsked.forgot.label" for="notAsked.forgot" class="disabled">Forgot to ask the patient</label></td>
492          </tr>
493         
494          <tr valign="baseline">
495            <td></td>
496            <td><input id="notAsked.language" type="checkbox" name="reasonIfNotAsked" disabled></td>
497            <td><label id="notAsked.language.label" for="notAsked.language" class="disabled">Language problems</label></td>
498          </tr>
499
500          <tr valign="baseline">
501            <td></td>
502            <td><input id="notAsked.condition" type="checkbox" name="reasonIfNotAsked" disabled></td>
503            <td><label id="notAsked.condition.label" for="notAsked.condition" class="disabled">Patient can't decide due to physical and/or mental condition</label></td>
504          </tr>
505
506          <tr valign="baseline">
507            <td></td>
508            <td><input id="notAsked.other" type="checkbox" name="reasonIfNotAsked" disabled></td>
509            <td><label id="notAsked.other.label" for="notAsked.other" class="disabled">Other:</label></td>
510          </tr>
511
512          <tr valign="baseline">
513            <td></td>
514            <td colspan="2">
515            <textarea name="otherReasonIfNotAsked" rows="3" cols="30" disabled
516              onfocus="document.forms['reggie'].reasonIfNotAsked[3].checked = true"></textarea>
517            </td>
518          </tr>
519          </table>
520
521        </td>
522        <td class="status" id="notAsked.status"></td>
523      </tr>
524      </table>
525    </td>
526  </tr>
527  </table>
528  </div>
529 
530  <div class="error" id="errorMessage" style="display: none; width: 800px; margin-left: 20px; margin-bottom: 0px;"></div>
531
532  <div id="done" class="success" style="display: none; width: 800px; margin-left: 20px; margin-top: 20px;"></div>
533
534  <table style="margin-left: 20px; margin-top: 10px;" class="navigation">
535  <tr>
536    <td><base:button id="gocancel" title="Cancel" onclick="goRestart(false)" style="display: none;"/></td>
537    <td><base:button id="gonext" title="Next" image="gonext.gif" onclick="goNext(true)"/></td>
538    <td><base:button id="goregister" title="Register" image="gonext.gif" onclick="goRegister()" style="display: none;"/></td>
539    <td><base:button id="gorestart" title="Restart" image="goback.gif" onclick="goRestart(true)" style="display: none;"/></td>
540    <td id="gonext.message" class="message"></td>
541  </tr>
542  </table>
543  </form>
544 
545</base:body>
546</base:page>
547<%
548}
549finally
550{
551  if (dc != null) dc.close();
552}
553%>
Note: See TracBrowser for help on using the repository browser.