source: extensions/net.sf.basedb.reggie/trunk/resources/reports/samplereportgenerator.jsp @ 2024

Last change on this file since 2024 was 2024, checked in by olle, 8 years ago

Refs #505. Refs #449. Sample source reports updated to support follow-up blood samples.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 102.0 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.extensions.ExtensionsControl"
10%>
11<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
12<%@ taglib prefix="p" uri="/WEB-INF/path.tld" %>
13<%
14final SessionControl sc = Base.getExistingSessionControl(request, true);
15final String ID = sc.getId();
16final float scale = Base.getScale(sc);
17final String home = ExtensionsControl.getHomeUrl("net.sf.basedb.reggie");
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="../css/reggie.css">
27  <script language="JavaScript" src="../reggie.js" type="text/javascript" charset="UTF-8"></script>
28   
29   
30  <script language="JavaScript">
31  var currentStep = 1;
32  var debug = false;
33  var numCols;
34  var unknownSite = 0;
35  var unknownCreation = 0;
36  var numMissing = 0;
37  var numPatientsNoSamples = 0;
38 
39  var month=new Array(12);
40    month[0]="Jan";
41    month[1]="Feb";
42    month[2]="Mar";
43    month[3]="Apr";
44    month[4]="May";
45    month[5]="Jun";
46    month[6]="Jul";
47    month[7]="Aug";
48    month[8]="Sep";
49    month[9]="Oct";
50    month[10]="Nov";
51    month[11]="Dec";
52 
53  var intervalIsValid = true;
54 
55  function goNext()
56  {
57    if (currentStep == 1)
58    {
59      gotoStep2();
60    }
61  }
62 
63  function gotoStep2()
64  {
65    var frm = document.forms['reggie'];
66    frm.reporttype.disabled = true;
67    // Hide report period input fields
68    document.getElementById("reportPeriodSubSection01").style.display = 'none';
69    document.getElementById("reportPeriodSubSection02").style.display = 'none';
70    document.getElementById("reportPeriodSubSection04").style.display = 'none';
71    // Hide view type pop-up menu
72    document.getElementById("viewTypeSubSection01").style.display = 'none';
73    document.getElementById("viewTypeSubSection02").style.display = 'none';
74    document.getElementById("viewTypeSubSection04").style.display = 'none';
75    // Hide sample type pop-up menu
76    document.getElementById("sampleTypeSubSection01").style.display = 'none';
77    document.getElementById("sampleTypeSubSection02").style.display = 'none';
78    document.getElementById("sampleTypeSubSection04").style.display = 'none';
79    // Hide table alternatives pop-up menu
80    document.getElementById("tableAlternativesSubSection01").style.display = 'none';
81    document.getElementById("tableAlternativesSubSection02").style.display = 'none';
82    document.getElementById("tableAlternativesSubSection04").style.display = 'none';
83    // Hide blood sample filter pop-up menu
84    document.getElementById("bloodSampleFilterSubSection01").style.display = 'none';
85    document.getElementById("bloodSampleFilterSubSection02").style.display = 'none';
86    document.getElementById("bloodSampleFilterSubSection04").style.display = 'none';
87    if (frm.reporttype[frm.reporttype.selectedIndex].value == 'samplecount')
88    {
89      // Show report period input fields
90      document.getElementById("reportPeriodSubSection01").style.display = 'block';
91      document.getElementById("reportPeriodSubSection02").style.display = 'block';
92      document.getElementById("reportPeriodSubSection04").style.display = 'block';
93      document.getElementById("reportPeriodSubSection01Header").innerHTML="Report period";
94      document.getElementById("reportPeriodSubSection04HelpText").innerHTML="Define which period the report should cover. Empty fields will include all tubes.";
95      // Set item name for report time step text
96      document.getElementById("items02").innerHTML="samples";
97      document.getElementById("items03").innerHTML="samples";
98      document.getElementById("items04").innerHTML="samples";
99      document.getElementById("items05").innerHTML="samples";
100      // Show view type pop-up menu
101      document.getElementById("viewTypeSubSection01").style.display = 'block';
102      document.getElementById("viewTypeSubSection02").style.display = 'block';
103      document.getElementById("viewTypeSubSection04").style.display = 'block';
104      // Show sample type pop-up menu
105      document.getElementById("sampleTypeSubSection01").style.display = 'block';
106      document.getElementById("sampleTypeSubSection02").style.display = 'block';
107      document.getElementById("sampleTypeSubSection04").style.display = 'block';
108      // Show table alternatives pop-up menu
109      document.getElementById("tableAlternativesSubSection01").style.display = 'block';
110      document.getElementById("tableAlternativesSubSection02").style.display = 'block';
111      document.getElementById("tableAlternativesSubSection04").style.display = 'block';
112      document.getElementById("tableAlternativesSubSection04HelpText").innerHTML="Select table alternative for report (only used if sample type = \'Blood\').";
113      frm.tablealternatives.disabled = true;
114      // Show blood sample filter pop-up menu
115      document.getElementById("bloodSampleFilterSubSection01").style.display = 'block';
116      document.getElementById("bloodSampleFilterSubSection02").style.display = 'block';
117      document.getElementById("bloodSampleFilterSubSection04").style.display = 'block';
118      document.getElementById("bloodSampleFilterSubSection04HelpText").innerHTML="Select blood sample filter for report (only used if sample type = \'Blood\').";
119      frm.bloodsamplefilter.disabled = true;
120    }
121    else if (frm.reporttype[frm.reporttype.selectedIndex].value == 'consentcount')
122    {
123      // Show report period input fields
124      document.getElementById("reportPeriodSubSection01").style.display = 'block';
125      document.getElementById("reportPeriodSubSection02").style.display = 'block';
126      document.getElementById("reportPeriodSubSection04").style.display = 'block';
127      document.getElementById("reportPeriodSubSection01Header").innerHTML="Report period";
128      document.getElementById("reportPeriodSubSection04HelpText").innerHTML="Define which period the report should cover. Empty fields will include all consents.";
129    }
130    else if (frm.reporttype[frm.reporttype.selectedIndex].value == 'patientcount')
131    {
132      // Show report period input fields
133      document.getElementById("reportPeriodSubSection01").style.display = 'block';
134      document.getElementById("reportPeriodSubSection02").style.display = 'block';
135      document.getElementById("reportPeriodSubSection04").style.display = 'block';
136      document.getElementById("reportPeriodSubSection01Header").innerHTML="Report period";
137      document.getElementById("reportPeriodSubSection04HelpText").innerHTML="Define which period the report should cover. Empty fields will include all patients.";
138      // Set item name for report time step text
139      document.getElementById("items02").innerHTML="patients";
140      document.getElementById("items03").innerHTML="patients";
141      document.getElementById("items04").innerHTML="patients";
142      document.getElementById("items05").innerHTML="patients";
143      // Show view type pop-up menu
144      document.getElementById("viewTypeSubSection01").style.display = 'block';
145      document.getElementById("viewTypeSubSection02").style.display = 'block';
146      document.getElementById("viewTypeSubSection04").style.display = 'block';
147    }
148    else if (frm.reporttype[frm.reporttype.selectedIndex].value == 'overviewreport')
149    {
150/*
151      // Set parameters (report period) help text
152      document.getElementById("reportPeriodSubSection01").style.display = 'block';
153      document.getElementById("reportPeriodSubSection04").style.display = 'block';
154      document.getElementById("reportPeriodSubSection01Header").innerHTML="No report parameters";
155      document.getElementById("reportPeriodSubSection04HelpText").innerHTML="Overview report will be generated irrespective of date for items.";
156*/
157      // Show blood sample filter pop-up menu
158      document.getElementById("bloodSampleFilterSubSection01").style.display = 'block';
159      document.getElementById("bloodSampleFilterSubSection02").style.display = 'block';
160      document.getElementById("bloodSampleFilterSubSection04").style.display = 'block';
161      document.getElementById("bloodSampleFilterSubSection04HelpText").innerHTML="Select blood sample filter for report.";
162      // Enable blood sample type filter menu
163      frm.bloodsamplefilter.disabled = false;
164    }
165    else if (frm.reporttype[frm.reporttype.selectedIndex].value == 'missingsampledatareport')
166    {
167      // Show sample type pop-up menu
168      document.getElementById("sampleTypeSubSection01").style.display = 'block';
169      document.getElementById("sampleTypeSubSection02").style.display = 'block';
170      document.getElementById("sampleTypeSubSection04").style.display = 'block';
171      // Show blood sample filter pop-up menu
172      document.getElementById("bloodSampleFilterSubSection01").style.display = 'block';
173      document.getElementById("bloodSampleFilterSubSection02").style.display = 'block';
174      document.getElementById("bloodSampleFilterSubSection04").style.display = 'block';
175      document.getElementById("bloodSampleFilterSubSection04HelpText").innerHTML="Select blood sample filter for report (only used if sample type = \'Blood\').";
176      frm.bloodsamplefilter.disabled = true;
177    }
178    Main.show('itemCountSection');
179       
180    Main.show('gocreate');   
181    Main.hide('gonext');
182    frm.fromdate.focus();
183    currentStep = 2;
184  }
185 
186  function dateOnChange()
187  {
188    var frm = document.forms['reggie'];   
189    var fdate;
190    var tdate;
191   
192    intervalIsValid = false;
193    setInputStatus('displayInterval','','valid');
194    if (frm.fromdate.value != null && frm.fromdate.value != '')
195    {
196      frm.fromdate.value = autoFillDate(frm.fromdate.value);     
197      if (!Dates.isDate(frm.fromdate.value, 'yyyyMMdd'))
198      {
199        setInputStatus('displayInterval','Not a valid from-date', 'invalid');
200        return;
201      }
202      else
203      {
204        fdate = frm.fromdate.value;
205        fdate = new Date(fdate.substr(0,4), parseInt(fdate.substr(4,2), 10)-1, fdate.substr(6,2));
206      }
207    }
208   
209    if (frm.todate.value != null && frm.todate.value != '')
210    {
211      frm.todate.value = autoFillDate(frm.todate.value);
212      if (!Dates.isDate(frm.todate.value, 'yyyyMMdd'))
213      {
214        setInputStatus('displayInterval', 'Not a valid to-date', 'invalid');
215        return;
216      }
217      else
218      {
219        tdate = frm.todate.value;
220        tdate = new Date(tdate.substr(0,4), parseInt(tdate.substr(4,2), 10)-1, tdate.substr(6,2));
221      }
222    }
223   
224    if (tdate != null && fdate != null)
225    {
226      if (fdate > tdate)
227      {
228        setInputStatus('displayInterval', 'Invalid period', 'invalid')
229        return;
230      }     
231    }
232    intervalIsValid = true;
233  }
234 
235  function sampleTypeOnChange()
236  {
237    var frm = document.forms['reggie'];
238    var reportType = frm.reporttype[frm.reporttype.selectedIndex].value;
239    var sampleType = frm.sampletype[frm.sampletype.selectedIndex].value;
240    var tableAlternatives = frm.tablealternatives[frm.tablealternatives.selectedIndex].value;
241    if (sampleType == 'blood')
242    {
243      if (reportType == 'samplecount')
244      {
245        // Enable table alternatives menu
246        frm.tablealternatives.disabled = false;
247        // In principal this case should not exist when sample type has just been changed to 'blood'
248        if (tableAlternatives == 'blood_sample_table_with_filter')
249        {
250          // Enable blood sample type filter menu
251          frm.bloodsamplefilter.disabled = false;
252        }
253      }
254      else
255      {
256        // Enable blood sample type filter menu
257        frm.bloodsamplefilter.disabled = false;
258      }
259    }
260    else
261    {
262      // Disable table alternatives menu and reset option
263      frm.tablealternatives.selectedIndex = 0;
264      frm.tablealternatives.disabled = true;
265      // Disable blood sample type filter menu and reset option
266      frm.bloodsamplefilter.selectedIndex = 0;
267      frm.bloodsamplefilter.disabled = true;
268    }
269  }
270
271  function tableAlternativesOnChange()
272  {
273    var frm = document.forms['reggie'];
274    var sampleType = frm.sampletype[frm.sampletype.selectedIndex].value;
275    var tableAlternatives = frm.tablealternatives[frm.tablealternatives.selectedIndex].value;
276    if (sampleType == 'blood' && tableAlternatives == 'blood_sample_table_with_filter')
277    {
278      // Enable blood sample type filter menu
279      frm.bloodsamplefilter.disabled = false;
280    }
281    else
282    {
283      // Disable blood sample type filter menu and reset option
284      frm.bloodsamplefilter.selectedIndex = 0;
285      frm.bloodsamplefilter.disabled = true;
286    }
287  }
288
289  function goCreate()
290  {
291    if (!intervalIsValid) return;
292    var cellElement = document.getElementById('reportcell');
293    var frm = document.forms['reggie'];   
294    var reportType = frm.reporttype[frm.reporttype.selectedIndex].value;   
295    frm.fromdate.disabled = true;
296    frm.todate.disabled = true;
297    var sampleType = frm.sampletype[frm.sampletype.selectedIndex].value;   
298    if (reportType == 'samplecount')
299    {
300      frm.viewtype.disabled = true;
301      frm.sampletype.disabled = true;
302      frm.tablealternatives.disabled = true;
303      frm.bloodsamplefilter.disabled = true;
304    }
305    else if (reportType == 'patientcount')
306    {
307      frm.viewtype.disabled = true;
308    }
309    else if (reportType == 'overviewreport')
310    {
311      frm.bloodsamplefilter.disabled = true;
312    }
313    else if (reportType == 'missingsampledatareport')
314    {
315      frm.sampletype.disabled = true;
316      frm.bloodsamplefilter.disabled = true;
317    }
318    Main.hide('gocreate');
319    Main.show('reportSection');
320    var url = '../SampleReport.servlet?ID=<%=ID%>&cmd='+reportType;   
321   
322    if (frm.fromdate.value != null) url += '&fdate='+frm.fromdate.value;
323    if (frm.todate.value != null) url += '&tdate='+frm.todate.value;
324    if (reportType == 'samplecount')
325    {     
326      if (frm.viewtype.value != null) url += '&vtype='+frm.viewtype.value;
327      if (frm.sampletype.value != null) url += '&stype='+frm.sampletype.value;
328      if (frm.tablealternatives.value != null) url += '&tablealternatives='+frm.tablealternatives.value;
329      if (frm.bloodsamplefilter.value != null) url += '&bloodsamplefilter='+frm.bloodsamplefilter.value;
330    }
331    else if (reportType == 'patientcount')
332    {     
333      if (frm.viewtype.value != null) url += '&vtype='+frm.viewtype.value;
334    }
335    else if (reportType == 'overviewreport')
336    {     
337      if (frm.bloodsamplefilter.value != null) url += '&bloodsamplefilter='+frm.bloodsamplefilter.value;
338    }
339    else if (reportType == 'missingsampledatareport')
340    {     
341      if (frm.sampletype.value != null) url += '&stype='+frm.sampletype.value;
342      if (frm.bloodsamplefilter.value != null) url += '&bloodsamplefilter='+frm.bloodsamplefilter.value;
343    }
344   
345    var request = Ajax.getXmlHttpRequest();
346    request.open("GET", url, false);
347    request.send(null);
348   
349    if (debug) Main.debug(request.responseText);   
350    var response = JSON.parse(request.responseText); 
351    if (response.status != 'ok')
352    {
353      setFatalError(response.message);
354      return false;
355    }
356    var report = response.report;
357    var permissionDeniedForPatientName = report.permissionDeniedForPatientName;
358    var reportTable;
359   
360    if (report != null)
361    {
362      if ('samplecount' == reportType)
363      {     
364        reportTable = createItemCountReport(report, reportType);
365      }
366      else if ('consentcount' == reportType)
367      {     
368        reportTable = createConsentCountReport(report);
369      }
370      else if ('patientcount' == reportType)
371      {     
372        reportTable = createItemCountReport(report, reportType);
373      }
374      else if ('overviewreport' == reportType)
375      {     
376        reportTable = createOverviewReport(report);
377      }
378      else if ('missingsampledatareport' == reportType)
379      {     
380        reportTable = createMissingSampleDataReport(report);
381      }
382    }
383    else
384    {
385      var messageCell = getTableCellElement('No values could be found during given period', 'reportheader');
386      var messageRow = document.createElement('tr');
387      messageRow.appendChild(messageCell);     
388      var messageTable = getReportTable();
389      messageTable.appendChild(messageRow);
390      reportTable = messageTable;     
391    }
392    setInnerHTML('reportcell', '');
393    cellElement.appendChild(reportTable);
394    //
395    // Optional extra tables
396    if ('samplecount' == reportType)
397    {     
398      if ('blood' == sampleType && report.tableAlternatives == 'full_blood_sample_tables' && report != null)
399      {
400        var spacer0 = document.createElement('text');
401        spacer0.innerHTML = "<BR>";
402        cellElement.appendChild(spacer0);
403        var spacer = document.createElement('text');
404        spacer.innerHTML = "<BR>";
405        cellElement.appendChild(spacer);
406        // Follow-up
407        cellElement.appendChild(spacer);
408        var reportFollowUp = report.reportFollowUp;
409        var reportFollowUpTable = createItemCountReport(reportFollowUp, reportType);
410        cellElement.appendChild(reportFollowUpTable);
411        // Not follow-up
412        cellElement.appendChild(spacer);
413        cellElement.appendChild(spacer);
414        var reportNotFollowUp = report.reportNotFollowUp;
415        var reportNotFollowUpTable = createItemCountReport(reportNotFollowUp, reportType);
416        cellElement.appendChild(reportNotFollowUpTable);
417        // Unknown
418        cellElement.appendChild(spacer);
419        cellElement.appendChild(spacer);
420        var reportUnknown = report.reportUnknown;
421        var reportUnknownTable = createItemCountReport(reportUnknown, reportType);
422        cellElement.appendChild(reportUnknownTable);
423        // PreNeo
424        cellElement.appendChild(spacer);
425        cellElement.appendChild(spacer);
426        var reportPreNeo = report.reportPreNeo;
427        var reportPreNeoTable = createItemCountReport(reportPreNeo, reportType);
428        cellElement.appendChild(reportPreNeoTable);
429        // PreOp
430        cellElement.appendChild(spacer);
431        cellElement.appendChild(spacer);
432        var reportPreOp = report.reportPreOp;
433        var reportPreOpTable = createItemCountReport(reportPreOp, reportType);
434        cellElement.appendChild(reportPreOpTable);
435        // FollowUp06
436        cellElement.appendChild(spacer);
437        cellElement.appendChild(spacer);
438        var reportFollowUp06 = report.reportFollowUp06;
439        var reportFollowUp06Table = createItemCountReport(reportFollowUp06, reportType);
440        cellElement.appendChild(reportFollowUp06Table);
441        // FollowUp12
442        cellElement.appendChild(spacer);
443        cellElement.appendChild(spacer);
444        var reportFollowUp12 = report.reportFollowUp12;
445        var reportFollowUp12Table = createItemCountReport(reportFollowUp12, reportType);
446        cellElement.appendChild(reportFollowUp12Table);
447        // FollowUp36
448        cellElement.appendChild(spacer);
449        cellElement.appendChild(spacer);
450        var reportFollowUp36 = report.reportFollowUp36;
451        var reportFollowUp36Table = createItemCountReport(reportFollowUp36, reportType);
452        cellElement.appendChild(reportFollowUp36Table);
453        //
454        // Reset # of blood samples with unknown site or creation date to that for unfiltered report
455        unknownCreation = report.statistics.noDate;
456        unknownSite = report.statistics.unknownSite;
457      }
458    }
459    else if ('consentcount' == reportType)
460    {
461      var spacer0 = document.createElement('text');
462      spacer0.innerHTML = "<BR>";
463      cellElement.appendChild(spacer0);
464      var spacer = document.createElement('text');
465      spacer.innerHTML = "<BR>";
466      cellElement.appendChild(spacer);
467      // Table with consents in different categories with date, as well as consents with unknown date
468      cellElement.appendChild(spacer);
469      var hasDateTable = createConsentCountHasDateTable(report);
470      cellElement.appendChild(hasDateTable);
471      // Table with consents in different categories with unknown date, as well as missing consents
472      cellElement.appendChild(spacer);
473      var unknownDateTable = createConsentCountUnknownDateTable(report);
474      cellElement.appendChild(unknownDateTable);
475    }
476    else if ('overviewreport' == reportType)
477    {
478      var spacer = document.createElement('text');
479      spacer.innerHTML = "<BR>";
480      cellElement.appendChild(spacer);
481      var patientDetailedTable = createOverviewPatientDetailedTable(report);
482      cellElement.appendChild(patientDetailedTable);
483    }
484    // Summary list
485    var summaryList = document.createElement('ul');
486    if (unknownSite == null) unknownSite = 0;
487    if (unknownCreation == null) unknownCreation = 0;
488    if ('samplecount' == reportType)
489    {
490      var samples = 'specimens';
491      if ('nospecimen' == sampleType)
492      {
493        samples = '"no specimens"';
494      }
495      else if ('blood' == sampleType)
496      {
497        samples = 'blood samples';
498      }
499      summaryList.appendChild(getListElement(unknownSite + ' ' + samples + ' registered to unknown sites.'));
500      summaryList.appendChild(getListElement(unknownCreation + ' ' + samples + ' without creation date. These are included in the \'Total\' column.'));
501    }
502    else if ('consentcount' == reportType)
503    {
504      var numDuplicates = 0;
505      if (report != null)
506      {
507        var statistics = report.statistics;
508        numDuplicates = statistics.duplicateKey;
509      }
510      if (numDuplicates == null)
511      {
512        numDuplicates = 0;
513      }
514      summaryList.appendChild(getListElement(unknownSite + ' consents registered to unknown sites.'));
515      summaryList.appendChild(getListElement(unknownCreation + ' consents without known date. These are included in the \'Total\' column.'));
516      summaryList.appendChild(getListElement(numMissing + ' missing consents for cases and blood samples. These are NOT included in the \'Total\' column.'));
517      summaryList.appendChild(getListElement(numDuplicates + ' duplicates ignored.'));
518
519      var patientsWithMultipleDates = statistics.patientsWithMultipleDatesKey;
520      var counter = 0;
521      for (var key in patientsWithMultipleDates)
522      {
523        counter++;
524      }
525      var patientsWithMultipleDatesText = counter + ' patients with multiple dates.';
526      summaryList.appendChild(getListElement(patientsWithMultipleDatesText));
527    }
528    else if ('patientcount' == reportType)
529    {
530      summaryList.appendChild(getListElement(unknownSite + ' patients registered to unknown sites.'));
531      summaryList.appendChild(getListElement(unknownCreation + ' patients without creation date. These are included in the \'Total\' column.'));
532    }
533    else if ('overviewreport' == reportType)
534    {
535      summaryList.appendChild(getListElement(unknownSite + ' patients registered to unknown sites.'));
536      summaryList.appendChild(getListElement(numPatientsNoSamples + ' patients with no samples.'));
537      summaryList.appendChild(getListElement('Note: Consents of type "Yes" include consents without patient id (PAT#) or date.'));
538      summaryList.appendChild(getListElement('Note: Data in column "Blood samples follow-up" are not affected by blood sample filter.'));
539    }
540    else if ('missingsampledatareport' == reportType)
541    {
542      summaryList.appendChild(getListElement('Note: Patient name is considered missing if either "all first names" or "family name" is missing.'));
543      if ('true' == permissionDeniedForPatientName)
544      {
545        var patientNamePermissionWarningIconWithMessage = document.createElement('img');
546        patientNamePermissionWarningIconWithMessage.innerHTML = '<img src="images/warning.png"> Sorry, logged-in user does not have permission to check patient names.</img>';
547        var patientNamePermissionWarningListElement = document.createElement('li');
548        patientNamePermissionWarningListElement.appendChild(patientNamePermissionWarningIconWithMessage);
549        summaryList.appendChild(patientNamePermissionWarningListElement);
550      }
551    }
552    cellElement.appendChild(summaryList);
553    if ('consentcount' == reportType)
554    {
555      // Add table with patients with consents with multiple dates
556      var multipleDatesTable = createConsentTablePatientsWithMultipleDates(report);
557      cellElement.appendChild(multipleDatesTable);
558    }
559    Main.show('printButton');
560    Main.show('gorestart');
561  }
562 
563  function createItemCountReport(report, reportType)
564  {
565    var reportTable = getReportTable();
566    var sdString = report.beginDate;
567    var edString = report.endDate;
568    var psdString = report.periodBeginDate;
569    var ldString = report.latestDate;
570    var startDate = dateStrToDate(sdString);
571    var endDate = dateStrToDate(edString);
572    var periodStartDate = dateStrToDate(psdString);
573    var latestDate = dateStrToDate(ldString);
574   
575    var viewType = report.viewType;   
576    var sampleType = report.sampleType;
577    var tableAlternatives = report.tableAlternatives;
578    var bloodSampleFilter = report.bloodSampleFilter;
579 
580    var headerRow = document.createElement('tr');   
581    var subHeaderRowYear = document.createElement('tr');
582    var columnHeaderRow = document.createElement('tr');
583   
584    var headerText = '# Items by ';
585    var startDateStr = addHyphensToDateString(sdString);
586    var endDateStr = addHyphensToDateString(edString);
587    var latestDateStr = addHyphensToDateString(ldString);
588    if ('samplecount' == reportType)
589    {
590      headerText = '# Specimens by ';
591      if ('nospecimen' == sampleType)
592      {
593        headerText = '# "No specimens" by ';
594      }
595      else if ('blood' == sampleType)
596      {
597        headerText = '# Blood samples by ';
598        if (bloodSampleFilter != null && bloodSampleFilter != 'none')
599        {
600          bloodSampleFilterDisplayText = getBloodSampleFilterDisplayText(bloodSampleFilter);
601          headerText = '# Blood samples of type \'' + bloodSampleFilterDisplayText + '\' by ';
602        }
603      }
604    }
605    else if ('patientcount' == reportType)
606    {
607      headerText = '# Patients by ';
608    }
609    if (viewType == 'WEEK')
610    {
611      var startWeek = getISOWeekNumber(periodStartDate);
612      var endWeek = getISOWeekNumber(endDate);
613      var tempDate = new Date(periodStartDate.getFullYear(), periodStartDate.getMonth(), periodStartDate.getDate()-periodStartDate.getDay()+1);
614      numCols = 0;
615      while (tempDate < endDate)
616      {
617        numCols++;
618        tempDate.setDate(tempDate.getDate()+7);
619      }
620      headerText += 'week';
621    }
622    else if (viewType == 'MONTH')
623    {
624      numCols = (endDate.getFullYear()-periodStartDate.getFullYear())*12 + endDate.getMonth()-periodStartDate.getMonth()+1;
625      headerText += 'month';
626    }
627    else if (viewType == 'QUARTER')
628    {
629      // First year (from start quarter to end of year)
630      numCols = 4 - Math.floor(periodStartDate.getMonth()/3);
631      // Last year (from start of year to end quarter) 
632      numCols += Math.floor(endDate.getMonth()/3)+1;
633      // If first and last year is the same, subtract 4 quarters
634      if (endDate.getFullYear() - periodStartDate.getFullYear() == 0)
635      {
636        numCols -= 4;
637      }
638      // Full years between start and end dates
639      if((endDate.getFullYear() - periodStartDate.getFullYear()) > 1)
640      {
641        numCols += 4 * (endDate.getFullYear() - periodStartDate.getFullYear()-1);
642      }
643      headerText += 'quarter';
644    }
645    else
646    {
647      numCols = endDate.getFullYear() - periodStartDate.getFullYear() + 1;
648      headerText += 'year';
649    }
650     
651    // Set table header
652    headerText += ' (between ' + startDateStr + ' and ' + endDateStr + ')';
653    if (latestDate != null)
654    {
655      headerText += '\nLast registration ' + latestDateStr;
656    }   
657    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', (numCols+5)));
658   
659    // Sub headers
660    // Only if each datacol is less then a year
661    if (viewType != 'YEAR')
662    {
663      subHeaderRowYear.appendChild(getTableCellElement('', 'reportsubheader', 3));
664      addYearSubHeaders(periodStartDate, endDate, subHeaderRowYear, viewType);     
665      subHeaderRowYear.appendChild(getTableCellElement('', 'reportsubheader', 2));
666    }   
667         
668    // Columnsheader   
669    var siteHeader = getTableCellElement('Site', 'reportsubheader');     
670    var startDateHeader = getTableCellElement('Start date','reportsubheader');
671    var latestDateHeader = getTableCellElement('Latest date','reportsubheader');
672    columnHeaderRow.appendChild(siteHeader);
673    columnHeaderRow.appendChild(startDateHeader);
674    columnHeaderRow.appendChild(latestDateHeader); 
675   
676    if (viewType == 'MONTH') addMonthColumnHeaders(columnHeaderRow, periodStartDate);
677    else if (viewType == 'WEEK') addWeekColumnHeaders(columnHeaderRow, periodStartDate);
678    else if (viewType == 'QUARTER') addQuarterColumnHeaders(columnHeaderRow, periodStartDate);
679    else if (viewType == 'YEAR') addYearSubHeaders(periodStartDate, endDate, columnHeaderRow, viewType);
680   
681   
682    columnHeaderRow.appendChild(getTableCellElement('Sum', 'reportsubheader'));
683    columnHeaderRow.appendChild(getTableCellElement('Total', 'reportsubheader'));
684
685    // Build table     
686    reportTable.appendChild(headerRow);
687    reportTable.appendChild(subHeaderRowYear);
688    reportTable.appendChild(columnHeaderRow);
689         
690    // Data rows     
691    addDataRowsToTable(report, reportTable);
692     
693    // Add a row with the combined numbers for all sites for each period
694    var sitesCombinedRow = document.createElement('tr');
695    sitesCombinedRow.appendChild(getTableCellElement('Sites combined', 'colsummary'));
696    sitesCombinedRow.appendChild(getTableCellElement('', 'colsummary', 2));
697    // Get combined numbers for all sites for each period
698    var statistics = report.statistics;
699    var sitesCombined = statistics.sitesCombinedKey;   
700    var sortedKeyArray = createSortedPeriodArray(report, numCols);
701    var key;
702    for (arrayIndex in sortedKeyArray)
703    {
704      key = sortedKeyArray[arrayIndex];
705      var data = getJSONData(sitesCombined, key, 0);
706      // Add entry with sample sum for site for selected time period
707      sitesCombinedRow.appendChild(getTableCellElement(data,'colsummary'));
708    }
709    // Get total number of samples for site for the selected time period
710    var sum = getJSONData(statistics, 'sumKey', 0);
711    // Add entry with total number of samples for site for the selected time period
712    sitesCombinedRow.appendChild(getTableCellElement(sum, 'colsummary'));
713    // Get total number of samples for all sites, regardless of creation date
714    var total = getJSONData(statistics, 'totalKey', 0);
715    // Add entry with total number of samples for all sites, regardless of creation date
716    sitesCombinedRow.appendChild(getTableCellElement(total, 'colsummary'));
717    reportTable.appendChild(sitesCombinedRow); 
718
719    return reportTable;
720  }
721 
722  function createConsentCountReport(report)
723  {
724    var reportTable = getReportTable();
725    var sdString = report.beginDate;
726    var edString = report.endDate;
727    var ldString = report.latestDate;
728    var startDate = dateStrToDate(sdString);
729    var endDate = dateStrToDate(edString);
730    var latestDate = dateStrToDate(ldString);
731
732    var headerRow = document.createElement('tr');   
733    var subHeaderRow = document.createElement('tr');
734    var columnHeaderRow = document.createElement('tr');
735   
736    var numCols = 5;
737    var numDecimals = 0;
738    var headerText = '# Consent forms of different types for cases and blood samples';
739    var startDateStr = addHyphensToDateString(sdString);
740    var endDateStr = addHyphensToDateString(edString);
741    var latestDateStr = addHyphensToDateString(ldString);
742    headerText += ' (betweeen ' + startDateStr + ' and ' + endDateStr + ')';
743    if (latestDate != null)
744    {
745        headerText += '\nLast registration ' + latestDateStr;
746    }
747    headerText += '\nConsents without date treated as if belonging to selected time period';
748    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', (numCols+3)));
749   
750    // Subheader   
751    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 3));
752   
753    subHeaderRow.appendChild(getTableCellElement('Yes', 'reportsubheader'));
754    subHeaderRow.appendChild(getTableCellElement('No', 'reportsubheader'));
755    subHeaderRow.appendChild(getTableCellElement('Not asked', 'reportsubheader'));
756    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 2));
757
758    // Columnsheader   
759    var siteHeader = getTableCellElement('Site', 'reportsubheader');     
760    var startDateHeader = getTableCellElement('Start date','reportsubheader');
761    var latestDateHeader = getTableCellElement('Latest date','reportsubheader');
762    columnHeaderRow.appendChild(siteHeader);
763    columnHeaderRow.appendChild(startDateHeader);
764    columnHeaderRow.appendChild(latestDateHeader); 
765   
766    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
767    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
768    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
769    columnHeaderRow.appendChild(getTableCellElement('Sum', 'reportsubheader'));
770    columnHeaderRow.appendChild(getTableCellElement('Total', 'reportsubheader'));
771
772    // Build table     
773    reportTable.appendChild(headerRow);
774    reportTable.appendChild(subHeaderRow);
775    reportTable.appendChild(columnHeaderRow);
776         
777    // Data rows     
778    addDataRowsToConsentTable(report, reportTable);
779     
780    // Add a row with the combined numbers for all sites for each period
781    var sitesCombinedRow = document.createElement('tr');
782    sitesCombinedRow.appendChild(getTableCellElement('Sites combined', 'colsummary'));
783    sitesCombinedRow.appendChild(getTableCellElement('', 'colsummary', 2));
784    // Get combined numbers for all sites for each period
785    var noDateKey = 'noDate';
786    var sumDateIgnoredKey = 'sumDateIgnoredKey';
787    var statistics = report.statistics;
788    var sitesCombined = statistics.sitesCombinedKey;
789    if (sitesCombined != null)
790    {
791      data = getJSONDataWithPercent(sitesCombined, 'yes', sumDateIgnoredKey, numDecimals);
792      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
793      data = getJSONDataWithPercent(sitesCombined, 'no', sumDateIgnoredKey, numDecimals);
794      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
795      data = getJSONDataWithPercent(sitesCombined, 'notAsked', sumDateIgnoredKey, numDecimals);
796      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
797    }
798    // Add entry with total number of consents with chosen restrictions
799    data = getJSONData(sitesCombined, sumDateIgnoredKey, 0);
800    sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
801    // Add entry with total number of consents, regardless of restrictions
802    var totalKey = 'totalKey';
803    data = getJSONData(sitesCombined, totalKey, 0);
804    sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
805    reportTable.appendChild(sitesCombinedRow); 
806
807    return reportTable;
808  }
809 
810  function createConsentCountHasDateTable(report)
811  {
812    var reportTable = getReportTable();
813    var sdString = report.beginDate;
814    var edString = report.endDate;
815    var ldString = report.latestDate;
816    var startDate = dateStrToDate(sdString);
817    var endDate = dateStrToDate(edString);
818    var latestDate = dateStrToDate(ldString);
819
820    var headerRow = document.createElement('tr');   
821    var subHeaderRow = document.createElement('tr');
822    var columnHeaderRow = document.createElement('tr');
823   
824    var numCols = 5;
825    var numDecimals = 0;
826    var headerText = '# Consent forms of different types for cases and blood samples';
827    var startDateStr = addHyphensToDateString(sdString);
828    var endDateStr = addHyphensToDateString(edString);
829    var latestDateStr = addHyphensToDateString(ldString);
830    headerText += ' (betweeen ' + startDateStr + ' and ' + endDateStr + ')';
831    if (latestDate != null)
832    {
833        headerText += '\nLast registration ' + latestDateStr;
834    }
835    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', (numCols+5)));
836   
837    // Subheader   
838    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 3));
839   
840    subHeaderRow.appendChild(getTableCellElement('Yes', 'reportsubheader'));
841    subHeaderRow.appendChild(getTableCellElement('Yes', 'reportsubheader'));
842    subHeaderRow.appendChild(getTableCellElement('No', 'reportsubheader'));
843    subHeaderRow.appendChild(getTableCellElement('Not asked', 'reportsubheader'));
844    subHeaderRow.appendChild(getTableCellElement('Unknown date', 'reportsubheader'));
845    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 2));
846
847    // Columnsheader   
848    var siteHeader = getTableCellElement('Site', 'reportsubheader');     
849    var startDateHeader = getTableCellElement('Start date','reportsubheader');
850    var latestDateHeader = getTableCellElement('Latest date','reportsubheader');
851    columnHeaderRow.appendChild(siteHeader);
852    columnHeaderRow.appendChild(startDateHeader);
853    columnHeaderRow.appendChild(latestDateHeader); 
854   
855    columnHeaderRow.appendChild(getTableCellElement('(has PAT#)', 'reportsubheader'));
856    columnHeaderRow.appendChild(getTableCellElement('(no PAT#)', 'reportsubheader'));
857    columnHeaderRow.appendChild(getTableCellElement('(has date)', 'reportsubheader'));
858    columnHeaderRow.appendChild(getTableCellElement('(has date)', 'reportsubheader'));
859    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
860    columnHeaderRow.appendChild(getTableCellElement('Sum', 'reportsubheader'));
861    columnHeaderRow.appendChild(getTableCellElement('Total', 'reportsubheader'));
862
863    // Build table     
864    reportTable.appendChild(headerRow);
865    reportTable.appendChild(subHeaderRow);
866    reportTable.appendChild(columnHeaderRow);
867         
868    // Data rows     
869    addDataRowsToConsentTableHasDate(report, reportTable);
870     
871    // Add a row with the combined numbers for all sites for each period
872    var sitesCombinedRow = document.createElement('tr');
873    sitesCombinedRow.appendChild(getTableCellElement('Sites combined', 'colsummary'));
874    sitesCombinedRow.appendChild(getTableCellElement('', 'colsummary', 2));
875    // Get combined numbers for all sites for each period
876    var noDateKey = 'noDate';
877    var sumKey = 'sumKey';
878    var statistics = report.statistics;
879    var sitesCombined = statistics.sitesCombinedKey;
880    if (sitesCombined != null)
881    {
882      data = getJSONDataWithPercent(sitesCombined, 'yesPatientExistsDateExists', sumKey, numDecimals);
883      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
884      data = getJSONDataWithPercent(sitesCombined, 'yesPatientUnknownDateExists', sumKey, numDecimals);
885      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
886      data = getJSONDataWithPercent(sitesCombined, 'noDateExists', sumKey, numDecimals);
887      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
888      data = getJSONDataWithPercent(sitesCombined, 'notAskedDateExists', sumKey, numDecimals);
889      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
890      data = getJSONDataWithPercent(sitesCombined, noDateKey, sumKey, numDecimals);
891      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
892    }
893    // Add entry with total number of consents with chosen restrictions
894    data = getJSONData(sitesCombined, sumKey, 0);
895    sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
896    // Add entry with total number of consents, regardless of restrictions
897    var totalKey = 'totalKey';
898    data = getJSONData(sitesCombined, totalKey, 0);
899    sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
900    reportTable.appendChild(sitesCombinedRow); 
901
902    return reportTable;
903  }
904 
905  function createConsentCountUnknownDateTable(report)
906  {
907    var reportTable = getReportTable();
908    var headerRow = document.createElement('tr');   
909    var subHeaderRow = document.createElement('tr');
910    var columnHeaderRow = document.createElement('tr');
911   
912    var numCols = 4;
913    var numDecimals = 0;
914    var headerText = '# Consent forms of different types for cases and blood samples with unknown consent date, as well as items with missing consents';
915    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', (numCols+5)));
916   
917    // Subheader   
918    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 3));
919   
920    subHeaderRow.appendChild(getTableCellElement('Yes', 'reportsubheader'));
921    subHeaderRow.appendChild(getTableCellElement('No', 'reportsubheader'));
922    subHeaderRow.appendChild(getTableCellElement('Not asked', 'reportsubheader'));
923    subHeaderRow.appendChild(getTableCellElement('Missing', 'reportsubheader'));
924    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 2));
925
926    // Columnsheader   
927    var siteHeader = getTableCellElement('Site', 'reportsubheader');     
928    var startDateHeader = getTableCellElement('Start date','reportsubheader');
929    var latestDateHeader = getTableCellElement('Latest date','reportsubheader');
930    columnHeaderRow.appendChild(siteHeader);
931    columnHeaderRow.appendChild(startDateHeader);
932    columnHeaderRow.appendChild(latestDateHeader); 
933   
934    columnHeaderRow.appendChild(getTableCellElement('(no date)', 'reportsubheader'));
935    columnHeaderRow.appendChild(getTableCellElement('(no date)', 'reportsubheader'));
936    columnHeaderRow.appendChild(getTableCellElement('(no date)', 'reportsubheader'));
937    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
938    columnHeaderRow.appendChild(getTableCellElement('Sum', 'reportsubheader'));
939    columnHeaderRow.appendChild(getTableCellElement('Total', 'reportsubheader'));
940
941    // Build table     
942    reportTable.appendChild(headerRow);
943    reportTable.appendChild(subHeaderRow);
944    reportTable.appendChild(columnHeaderRow);
945         
946    // Data rows     
947    addDataRowsToConsentTableUnknownDate(report, reportTable);
948     
949    // Add a row with the combined numbers for all sites
950    var sitesCombinedRow = document.createElement('tr');
951    sitesCombinedRow.appendChild(getTableCellElement('Sites combined', 'colsummary'));
952    sitesCombinedRow.appendChild(getTableCellElement('', 'colsummary', 2));
953    // Get combined numbers for all sites
954    var noDateOrMissingKey = 'noDateOrMissing';
955    var sumKey = 'sumKey';
956    var statistics = report.statistics;
957    var sitesCombined = statistics.sitesCombinedKey;
958    if (sitesCombined != null)
959    {
960      data = getJSONDataWithPercent(sitesCombined, 'yesDateUnknown', noDateOrMissingKey, numDecimals);
961      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
962      data = getJSONDataWithPercent(sitesCombined, 'noDateUnknown', noDateOrMissingKey, numDecimals);
963      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
964      data = getJSONDataWithPercent(sitesCombined, 'notAskedDateUnknown', noDateOrMissingKey, numDecimals);
965      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
966      data = getJSONDataWithPercent(sitesCombined, 'missing', noDateOrMissingKey, numDecimals);
967      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
968      // Add entry with total number of consents with chosen restrictions
969      var noDateOrMissingKey = 'noDateOrMissing';
970      data = getJSONData(sitesCombined, noDateOrMissingKey, 0);
971      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
972      // Add entry with total number of consents, regardless of restrictions
973      var totalKey = 'totalKey';
974      data = getJSONData(sitesCombined, totalKey, 0);
975      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
976    }
977    reportTable.appendChild(sitesCombinedRow); 
978
979    return reportTable;
980  }
981 
982  function createOverviewReport(report)
983  {
984    var reportTable = getReportTable();
985    var bloodSampleFilter = report.bloodSampleFilter;
986    var sdString = report.beginDate;
987    var edString = report.endDate;
988    var ldString = report.latestDate;
989    var startDate = dateStrToDate(sdString);
990    var endDate = dateStrToDate(edString);
991    var latestDate = dateStrToDate(ldString);
992 
993    var headerRow = document.createElement('tr');   
994    var subHeaderRow = document.createElement('tr');
995    var subHeader2Row = document.createElement('tr');
996    var columnHeaderRow = document.createElement('tr');
997   
998    var numCols = 7;
999    var numDecimals = 0;
1000    var headerText = 'Number of items of different kinds';
1001    if (bloodSampleFilter != null && bloodSampleFilter != 'none')
1002    {
1003      bloodSampleFilterDisplayText = getBloodSampleFilterDisplayText(bloodSampleFilter);
1004      headerText += ', blood sample type = \'' + bloodSampleFilterDisplayText + '\'';
1005    }
1006    var startDateStr = addHyphensToDateString(sdString);
1007    var endDateStr = addHyphensToDateString(edString);
1008    var latestDateStr = addHyphensToDateString(ldString);
1009    headerText += ' (betweeen ' + startDateStr + ' and ' + endDateStr + ')';
1010    if (latestDate != null)
1011    {
1012        headerText += '\nLast registration ' + latestDateStr;
1013    }
1014    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', (numCols+3)));
1015   
1016    // Subheader
1017    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 3));
1018   
1019    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
1020    subHeaderRow.appendChild(getTableCellElement('Blood', 'reportsubheader'));
1021    subHeaderRow.appendChild(getTableCellElement('Blood', 'reportsubheader'));
1022    subHeaderRow.appendChild(getTableCellElement('Specimens', 'reportsubheader'));
1023    subHeaderRow.appendChild(getTableCellElement('No specimens', 'reportsubheader'));
1024    subHeaderRow.appendChild(getTableCellElement('Consents', 'reportsubheader'));
1025    subHeaderRow.appendChild(getTableCellElement('Consents', 'reportsubheader'));
1026
1027    // Subheader 2
1028    subHeader2Row.appendChild(getTableCellElement('', 'reportsubheader', 3));
1029   
1030    subHeader2Row.appendChild(getTableCellElement('', 'reportsubheader'));
1031    subHeader2Row.appendChild(getTableCellElement('samples', 'reportsubheader'));
1032    subHeader2Row.appendChild(getTableCellElement('samples', 'reportsubheader'));
1033    subHeader2Row.appendChild(getTableCellElement('', 'reportsubheader'));
1034    subHeader2Row.appendChild(getTableCellElement('', 'reportsubheader'));
1035    subHeader2Row.appendChild(getTableCellElement('(Yes)', 'reportsubheader'));
1036    subHeader2Row.appendChild(getTableCellElement('missing', 'reportsubheader'));
1037
1038    // Columnsheader   
1039    var siteHeader = getTableCellElement('Site', 'reportsubheader');     
1040    var startDateHeader = getTableCellElement('Start date','reportsubheader');
1041    var latestDateHeader = getTableCellElement('Latest date','reportsubheader');
1042    columnHeaderRow.appendChild(siteHeader);
1043    columnHeaderRow.appendChild(startDateHeader);
1044    columnHeaderRow.appendChild(latestDateHeader); 
1045   
1046    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
1047    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
1048    columnHeaderRow.appendChild(getTableCellElement('follow-up', 'reportsubheader'));
1049    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
1050    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
1051    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
1052    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
1053
1054    // Build table     
1055    reportTable.appendChild(headerRow);
1056    reportTable.appendChild(subHeaderRow);
1057    reportTable.appendChild(subHeader2Row);
1058    reportTable.appendChild(columnHeaderRow);
1059         
1060    // Data rows     
1061    addDataRowsToOverviewTable(report, reportTable);
1062     
1063    // Add a row with the combined numbers for all sites for each period
1064    var sitesCombinedRow = document.createElement('tr');
1065    sitesCombinedRow.appendChild(getTableCellElement('Sites combined', 'colsummary'));
1066    sitesCombinedRow.appendChild(getTableCellElement('', 'colsummary', 2));
1067    // Get combined numbers for all sites for each period
1068    var noDateKey = 'noDate';
1069    var sumKey = 'sumKey';
1070    var statistics = report.statistics;
1071    // Get values for use in summary section
1072    numPatientsNoSamples = statistics.patientNoSamples;
1073    var sitesCombined = statistics.sitesCombinedKey;
1074    if (sitesCombined != null)
1075    {
1076      data = getJSONData(sitesCombined, 'patient');
1077      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1078      data = getJSONData(sitesCombined, 'bloodSample');
1079      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1080      data = getJSONData(sitesCombined, 'bloodSampleFollowUp');
1081      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1082      data = getJSONData(sitesCombined, 'specimen');
1083      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1084      data = getJSONData(sitesCombined, 'noSpecimen');
1085      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1086      data = getJSONData(sitesCombined, 'consentYes');
1087      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1088      data = getJSONData(sitesCombined, 'consentMissing');
1089      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1090    }
1091    reportTable.appendChild(sitesCombinedRow); 
1092
1093    return reportTable;
1094  }
1095 
1096  function createOverviewPatientDetailedTable(report)
1097  {
1098    var reportTable = getReportTable();
1099    var bloodSampleFilter = report.bloodSampleFilter;
1100    var sdString = report.beginDate;
1101    var edString = report.endDate;
1102    var ldString = report.latestDate;
1103    var startDate = dateStrToDate(sdString);
1104    var endDate = dateStrToDate(edString);
1105 
1106    var headerRow = document.createElement('tr');   
1107    var subHeaderRow = document.createElement('tr');
1108    var subHeader2Row = document.createElement('tr');
1109    var columnHeaderRow = document.createElement('tr');
1110   
1111    var numCols = 8;
1112    var numDecimals = 0;
1113    var headerText = 'Patient records of different kinds';
1114    if (bloodSampleFilter != null && bloodSampleFilter != 'none')
1115    {
1116      bloodSampleFilterDisplayText = getBloodSampleFilterDisplayText(bloodSampleFilter);
1117      headerText += ', blood sample type = \'' + bloodSampleFilterDisplayText + '\'';
1118    }
1119    var startDateStr = addHyphensToDateString(sdString);
1120    var endDateStr = addHyphensToDateString(edString);
1121    var latestDateStr = addHyphensToDateString(ldString);
1122    headerText += ' (betweeen ' + startDateStr + ' and ' + endDateStr + ')';
1123/*
1124    if (latestDate != null)
1125    {
1126        headerText += '\nLast registration ' + latestDateStr;
1127    }
1128*/
1129    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', (numCols+2)));
1130   
1131    // Subheader
1132    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 2));
1133   
1134    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
1135    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
1136    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
1137    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
1138    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
1139    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
1140    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
1141    //subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
1142    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
1143
1144    // Subheader 2
1145    subHeader2Row.appendChild(getTableCellElement('', 'reportsubheader', 2));
1146   
1147    subHeader2Row.appendChild(getTableCellElement('(blood', 'reportsubheader'));
1148    subHeader2Row.appendChild(getTableCellElement('(spec.', 'reportsubheader'));
1149    subHeader2Row.appendChild(getTableCellElement('(no spec.', 'reportsubheader'));
1150    subHeader2Row.appendChild(getTableCellElement('(blood and', 'reportsubheader'));
1151    subHeader2Row.appendChild(getTableCellElement('(blood and', 'reportsubheader'));
1152    subHeader2Row.appendChild(getTableCellElement('(spec. and', 'reportsubheader'));
1153    subHeader2Row.appendChild(getTableCellElement('(blood, spec.,', 'reportsubheader'));
1154    //subHeader2Row.appendChild(getTableCellElement('(no samples)', 'reportsubheader'));
1155    subHeader2Row.appendChild(getTableCellElement('', 'reportsubheader'));
1156
1157    // Columnsheader   
1158    var siteHeader = getTableCellElement('Site', 'reportsubheader');     
1159    var startDateHeader = getTableCellElement('Start date','reportsubheader');
1160    //var latestDateHeader = getTableCellElement('Latest date','reportsubheader');
1161    columnHeaderRow.appendChild(siteHeader);
1162    columnHeaderRow.appendChild(startDateHeader);
1163    //columnHeaderRow.appendChild(latestDateHeader); 
1164   
1165    columnHeaderRow.appendChild(getTableCellElement('only)', 'reportsubheader'));
1166    columnHeaderRow.appendChild(getTableCellElement('only)', 'reportsubheader'));
1167    columnHeaderRow.appendChild(getTableCellElement('only)', 'reportsubheader'));
1168    columnHeaderRow.appendChild(getTableCellElement('specimens)', 'reportsubheader'));
1169    columnHeaderRow.appendChild(getTableCellElement('no spec.)', 'reportsubheader'));
1170    columnHeaderRow.appendChild(getTableCellElement('no spec.)', 'reportsubheader'));
1171    columnHeaderRow.appendChild(getTableCellElement('and no spec.)', 'reportsubheader'));
1172    //columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
1173
1174    columnHeaderRow.appendChild(getTableCellElement('Sum', 'reportsubheader'));
1175
1176    // Build table     
1177    reportTable.appendChild(headerRow);
1178    reportTable.appendChild(subHeaderRow);
1179    reportTable.appendChild(subHeader2Row);
1180    reportTable.appendChild(columnHeaderRow);
1181         
1182    // Data rows     
1183    addDataRowsToOverviewPatientDetailedTable(report, reportTable);
1184     
1185    // Add a row with the combined numbers for all sites
1186    var sitesCombinedRow = document.createElement('tr');
1187    sitesCombinedRow.appendChild(getTableCellElement('Sites combined', 'colsummary'));
1188    sitesCombinedRow.appendChild(getTableCellElement('', 'colsummary'));
1189    // Get combined numbers for all sites
1190    var noDateKey = 'noDate';
1191    var sumKey = 'sumKey';
1192    var statistics = report.statistics;
1193    // Get values for use in summary section
1194    numPatientsNoSamples = statistics.patientNoSamples;
1195    var sitesCombined = statistics.sitesCombinedKey;
1196    if (sitesCombined != null)
1197    {
1198      data = getJSONData(sitesCombined, 'patientBloodSampleOnly');
1199      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1200      data = getJSONData(sitesCombined, 'patientSpecimenOnly');
1201      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1202      data = getJSONData(sitesCombined, 'patientNoSpecimenOnly');
1203      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1204      data = getJSONData(sitesCombined, 'patientBloodSampleAndSpecimen');
1205      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1206      data = getJSONData(sitesCombined, 'patientBloodSampleAndNoSpecimen');
1207      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1208      data = getJSONData(sitesCombined, 'patientSpecimenAndNoSpecimen');
1209      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1210      data = getJSONData(sitesCombined, 'patientBloodSampleAndSpecimenAndNoSpecimen');
1211      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1212      //data = getJSONData(sitesCombined, 'patientNoSamples');
1213      //sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1214      data = getJSONData(sitesCombined, 'sumKey');
1215      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1216    }
1217    reportTable.appendChild(sitesCombinedRow); 
1218
1219    return reportTable;
1220  }
1221 
1222  function createMissingSampleDataReport(report)
1223  {
1224    var reportTable = getReportTable();
1225    var sdString = report.beginDate;
1226    var edString = report.endDate;
1227    var ldString = report.latestDate;
1228    var startDate = dateStrToDate(sdString);
1229    var endDate = dateStrToDate(edString);
1230    var latestDate = dateStrToDate(ldString);
1231
1232    var sampleType = report.sampleType;
1233    var bloodSampleFilter = report.bloodSampleFilter;
1234    var permissionDeniedForPatientName = report.permissionDeniedForPatientName;
1235
1236    var headerRow = document.createElement('tr');   
1237    var subHeaderRow = document.createElement('tr');
1238    var subHeader2Row = document.createElement('tr');
1239    var columnHeaderRow = document.createElement('tr');
1240   
1241    var numCols = 5;
1242    if (sampleType == 'specimen')
1243    {
1244      numCols = 5;
1245    }
1246    else if (sampleType == 'nospecimen')
1247    {
1248      numCols = 4;
1249    }
1250    else if (sampleType == 'blood')
1251    {
1252      numCols = 3;
1253    }
1254    var numDecimals = 0;
1255    var headerText = 'Number of missing specimen items of different kinds';
1256    if ('nospecimen' == sampleType)
1257    {
1258      headerText = 'Number of missing "no specimen" items of different kinds';
1259    }
1260    else if ('blood' == sampleType)
1261    {
1262      headerText = 'Number of missing blood sample items of different kinds';
1263      if (bloodSampleFilter != null && bloodSampleFilter != 'none')
1264      {
1265        bloodSampleFilterDisplayText = getBloodSampleFilterDisplayText(bloodSampleFilter);
1266        headerText += ', blood sample type = \'' + bloodSampleFilterDisplayText + '\'';
1267      }
1268    }
1269    var startDateStr = addHyphensToDateString(sdString);
1270    var endDateStr = addHyphensToDateString(edString);
1271    var latestDateStr = addHyphensToDateString(ldString);
1272    headerText += ' (betweeen ' + startDateStr + ' and ' + endDateStr + ')';
1273    if (latestDate != null)
1274    {
1275        headerText += '\nLast registration ' + latestDateStr;
1276    }
1277    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', (numCols+3)));
1278   
1279    // Subheader
1280    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 3));
1281   
1282    subHeaderRow.appendChild(getTableCellElement('Patient', 'reportsubheader'));
1283    if (sampleType == 'specimen')
1284    {
1285      subHeaderRow.appendChild(getTableCellElement('PAD', 'reportsubheader'));
1286      subHeaderRow.appendChild(getTableCellElement('Laterality', 'reportsubheader'));
1287      subHeaderRow.appendChild(getTableCellElement('Sampling', 'reportsubheader'));
1288      subHeaderRow.appendChild(getTableCellElement('RNALater', 'reportsubheader'));
1289    }
1290    else if (sampleType == 'nospecimen')
1291    {
1292      subHeaderRow.appendChild(getTableCellElement('PAD', 'reportsubheader'));
1293      subHeaderRow.appendChild(getTableCellElement('Laterality', 'reportsubheader'));
1294      subHeaderRow.appendChild(getTableCellElement('Sampling', 'reportsubheader'));
1295    }
1296    else if (sampleType == 'blood')
1297    {
1298      subHeaderRow.appendChild(getTableCellElement('Blood sampling', 'reportsubheader'));
1299      subHeaderRow.appendChild(getTableCellElement('Blood freezer', 'reportsubheader'));
1300    }
1301
1302    // Columnsheader   
1303    var siteHeader = getTableCellElement('Site', 'reportsubheader');     
1304    var startDateHeader = getTableCellElement('Start date','reportsubheader');
1305    var latestDateHeader = getTableCellElement('Latest date','reportsubheader');
1306    columnHeaderRow.appendChild(siteHeader);
1307    columnHeaderRow.appendChild(startDateHeader);
1308    columnHeaderRow.appendChild(latestDateHeader); 
1309   
1310    columnHeaderRow.appendChild(getTableCellElement('name', 'reportsubheader'));
1311    if (sampleType == 'specimen')
1312    {
1313      columnHeaderRow.appendChild(getTableCellElement('reference', 'reportsubheader'));
1314      columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
1315      columnHeaderRow.appendChild(getTableCellElement('date', 'reportsubheader'));
1316      columnHeaderRow.appendChild(getTableCellElement('date', 'reportsubheader'));
1317    }
1318    else if (sampleType == 'nospecimen')
1319    {
1320      columnHeaderRow.appendChild(getTableCellElement('reference', 'reportsubheader'));
1321      columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
1322      columnHeaderRow.appendChild(getTableCellElement('date', 'reportsubheader'));
1323    }
1324    else if (sampleType == 'blood')
1325    {
1326      columnHeaderRow.appendChild(getTableCellElement('date', 'reportsubheader'));
1327      columnHeaderRow.appendChild(getTableCellElement('date', 'reportsubheader'));
1328    }
1329
1330    // Build table     
1331    reportTable.appendChild(headerRow);
1332    reportTable.appendChild(subHeaderRow);
1333    reportTable.appendChild(columnHeaderRow);
1334         
1335    // Data rows     
1336    addDataRowsToMissingSampleDataTable(report, reportTable);
1337     
1338    // Add a row with the combined numbers for all sites for each period
1339    var sitesCombinedRow = document.createElement('tr');
1340    sitesCombinedRow.appendChild(getTableCellElement('Sites combined', 'colsummary'));
1341    sitesCombinedRow.appendChild(getTableCellElement('', 'colsummary', 2));
1342    // Get combined numbers for all sites for each period
1343    var noDateKey = 'noDate';
1344    var sumKey = 'sumKey';
1345    var statistics = report.statistics;
1346    var sitesCombined = statistics.sitesCombinedKey;
1347    if (sitesCombined != null)
1348    {
1349      if ('false' == permissionDeniedForPatientName)
1350      {
1351        data = getJSONData(sitesCombined, 'missingPatientName');
1352        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1353      }
1354      else
1355      {
1356        data = '-';
1357        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1358      }
1359      if (sampleType == 'specimen')
1360      {
1361        data = getJSONData(sitesCombined, 'missingPadReference');
1362        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1363        data = getJSONData(sitesCombined, 'missingLaterality');
1364        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1365        data = getJSONData(sitesCombined, 'missingSamplingDateTime');
1366        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1367        data = getJSONData(sitesCombined, 'missingRnaLaterDateTime');
1368        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1369      }
1370      else if (sampleType == 'nospecimen')
1371      {
1372        data = getJSONData(sitesCombined, 'missingPadReference');
1373        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1374        data = getJSONData(sitesCombined, 'missingLaterality');
1375        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1376        data = getJSONData(sitesCombined, 'missingSamplingDateTime');
1377        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1378      }
1379      else if (sampleType == 'blood')
1380      {
1381        data = getJSONData(sitesCombined, 'missingBloodSamplingDateTime');
1382        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1383        data = getJSONData(sitesCombined, 'missingBloodFreezerDateTime');
1384        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1385      }
1386    }
1387    reportTable.appendChild(sitesCombinedRow); 
1388
1389    return reportTable;
1390  }
1391 
1392  function createConsentTablePatientsWithMultipleDates(report)
1393  {
1394    var multipleDatesTable = getReportTable();
1395    var headerRow = document.createElement('tr');   
1396    var columnHeaderRow = document.createElement('tr');
1397   
1398    // Table header
1399    var numCols = 3;
1400    var headerText = 'Consent forms with multiple dates for same patient';
1401    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', numCols));
1402   
1403    // Columnsheader
1404    columnHeaderRow.appendChild(getTableCellElement('Patient ID', 'reportsubheader'));
1405    columnHeaderRow.appendChild(getTableCellElement('Date 1', 'reportsubheader'));
1406    columnHeaderRow.appendChild(getTableCellElement('Date 2', 'reportsubheader'));
1407
1408    // Build table     
1409    multipleDatesTable.appendChild(headerRow);
1410    multipleDatesTable.appendChild(columnHeaderRow);
1411         
1412    // Data rows
1413    if (report != null)
1414    {
1415      var statistics = report.statistics;
1416      var sessionId = statistics.sessionIdKey;
1417      var patientsWithMultipleDates = statistics.patientsWithMultipleDatesKey;
1418      var patientnamePatientid = statistics.patientnamePatientidKey;
1419      for (var patientName in patientsWithMultipleDates)
1420      {
1421        var tableRow = document.createElement('tr');
1422        // Add patient name to table
1423        var patientIdStr = patientnamePatientid[patientName];
1424        var columnCell = document.createElement('td');
1425        var patientLinkStr = createLinkStr(patientName, patientIdStr, 'BIOSOURCE', 'View this sample', sessionId);
1426        var tableCol = createTableCellElementHtml(patientLinkStr, 'reportdata');
1427        tableRow.appendChild(tableCol);
1428        // Add dates to table in chronological order
1429        var dateSet = patientsWithMultipleDates[patientName];
1430        var dateStr1 = '';
1431        var dateStr2 = '';
1432        for (var key in dateSet)
1433        {
1434          var dateStr = dateSet[key];
1435          if (dateStr1 == '')
1436          {
1437            dateStr1 = dateStr;
1438          }
1439          else if (dateStr > dateStr1)
1440          {
1441            dateStr2 = dateStr;
1442          }
1443          else
1444          {
1445            dateStr2 = dateStr1;
1446            dateStr1 = dateStr;
1447          }
1448        }
1449        var dateCol = '';
1450        dateCol = getTableCellElement(dateStr1, 'reportdata');
1451        tableRow.appendChild(dateCol);
1452        dateCol = getTableCellElement(dateStr2, 'reportdata');
1453        tableRow.appendChild(dateCol);
1454        multipleDatesTable.appendChild(tableRow);
1455      }
1456    }
1457
1458    return multipleDatesTable;
1459  }
1460 
1461  function addDataRowsToConsentTable(report, reportTable, numDecimals)
1462  {
1463    var sites = report.sites;   
1464    var statistics = report.statistics;
1465    unknownCreation = statistics.noDate;
1466    unknownSite = statistics.unknownSite;
1467    var siteOrderList = report.siteOrderListKey;
1468    for (var siteOrderIndex in siteOrderList)
1469    {
1470      var namePrefix = siteOrderList[siteOrderIndex];   
1471      if (!sites.hasOwnProperty(namePrefix)) continue;       
1472      var site = sites[namePrefix];
1473      var siteName = site.name;
1474      var siteStartDate = dateStrToDate(site.startDate);
1475      var siteStartDateStr = addHyphensToDateString(site.startDate);
1476     
1477      var siteData = statistics[namePrefix];     
1478      var siteLatestDate = siteData['latestDateKey'];
1479      var siteLatestDateStr = addHyphensToDateString(siteLatestDate);
1480      var tableRow = document.createElement('tr');
1481      var tableCol = getTableCellElement(siteName, 'rowtitle');
1482      tableRow.appendChild(tableCol);
1483      tableRow.appendChild(getTableCellElement(siteStartDateStr, 'reportdata'));
1484      tableRow.appendChild(getTableCellElement(siteLatestDateStr, 'reportdata'));
1485      var noDateKey = 'noDate';
1486      var sumDateIgnoredKey = 'sumDateIgnoredKey';
1487      var totalKey = 'totalKey';
1488      if (siteData != null)
1489      {
1490        data = getJSONDataWithPercent(siteData, 'yes', sumDateIgnoredKey, numDecimals);
1491        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1492        data = getJSONDataWithPercent(siteData, 'no', sumDateIgnoredKey, numDecimals);
1493        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1494        data = getJSONDataWithPercent(siteData, 'notAsked', sumDateIgnoredKey, numDecimals);
1495        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1496        // Add column with summed values for site
1497        var siteSum = getJSONData(siteData, sumDateIgnoredKey, 0);
1498        tableRow.appendChild(getTableCellElement(siteSum, 'rowsummary'));
1499      }
1500      // Add column with total number of samples for site, regardless of creation date
1501      var siteTotal = getJSONData(siteData, totalKey, 0);
1502      tableRow.appendChild(getTableCellElement(siteTotal, 'rowsummary'));
1503      reportTable.appendChild(tableRow);
1504    }
1505  }
1506
1507  function addDataRowsToConsentTableHasDate(report, reportTable, numDecimals)
1508  {
1509    var sites = report.sites;   
1510    var statistics = report.statistics;
1511    unknownCreation = statistics.noDate;
1512    unknownSite = statistics.unknownSite;
1513    var siteOrderList = report.siteOrderListKey;
1514    for (var siteOrderIndex in siteOrderList)
1515    {
1516      var namePrefix = siteOrderList[siteOrderIndex];   
1517      if (!sites.hasOwnProperty(namePrefix)) continue;       
1518      var site = sites[namePrefix];
1519      var siteName = site.name;
1520      var siteStartDate = dateStrToDate(site.startDate);
1521      var siteStartDateStr = addHyphensToDateString(site.startDate);
1522     
1523      var siteData = statistics[namePrefix];     
1524      var siteLatestDate = siteData['latestDateKey'];
1525      var siteLatestDateStr = addHyphensToDateString(siteLatestDate);
1526      var tableRow = document.createElement('tr');
1527      var tableCol = getTableCellElement(siteName, 'rowtitle');
1528      tableRow.appendChild(tableCol);
1529      tableRow.appendChild(getTableCellElement(siteStartDateStr, 'reportdata'));
1530      tableRow.appendChild(getTableCellElement(siteLatestDateStr, 'reportdata'));
1531      var noDateKey = 'noDate';
1532      var sumKey = 'sumKey';
1533      var totalKey = 'totalKey';
1534      if (siteData != null)
1535      {
1536        data = getJSONDataWithPercent(siteData, 'yesPatientExistsDateExists', sumKey, numDecimals);
1537        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1538        data = getJSONDataWithPercent(siteData, 'yesPatientUnknownDateExists', sumKey, numDecimals);
1539        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1540        data = getJSONDataWithPercent(siteData, 'noDateExists', sumKey, numDecimals);
1541        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1542        data = getJSONDataWithPercent(siteData, 'notAskedDateExists', sumKey, numDecimals);
1543        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1544        data = getJSONDataWithPercent(siteData, noDateKey, sumKey, numDecimals);
1545        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1546        // Add column with summed values for site
1547        var siteSum = getJSONData(siteData, sumKey, 0);
1548        tableRow.appendChild(getTableCellElement(siteSum, 'rowsummary'));
1549      }
1550      // Add column with total number of samples for site, regardless of creation date
1551      var siteTotal = getJSONData(siteData, totalKey, 0);
1552      tableRow.appendChild(getTableCellElement(siteTotal, 'rowsummary'));
1553      reportTable.appendChild(tableRow);
1554    }
1555  }
1556
1557  function addDataRowsToConsentTableUnknownDate(report, reportTable, numDecimals)
1558  {
1559    var sites = report.sites;   
1560    var statistics = report.statistics;
1561    unknownCreation = statistics.noDate;
1562    unknownSite = statistics.unknownSite;
1563    numMissing = statistics.missing;
1564    var siteOrderList = report.siteOrderListKey;
1565    for (var siteOrderIndex in siteOrderList)
1566    {
1567      var namePrefix = siteOrderList[siteOrderIndex];   
1568      if (!sites.hasOwnProperty(namePrefix)) continue;       
1569      var site = sites[namePrefix];
1570      var siteName = site.name;
1571      var siteStartDate = dateStrToDate(site.startDate);
1572      var siteStartDateStr = addHyphensToDateString(site.startDate);
1573     
1574      var siteData = statistics[namePrefix];     
1575      var siteLatestDate = siteData['latestDateKey'];
1576      var siteLatestDateStr = addHyphensToDateString(siteLatestDate);
1577      var tableRow = document.createElement('tr');
1578      var tableCol = getTableCellElement(siteName, 'rowtitle');
1579      tableRow.appendChild(tableCol);
1580      tableRow.appendChild(getTableCellElement(siteStartDateStr, 'reportdata'));
1581      tableRow.appendChild(getTableCellElement(siteLatestDateStr, 'reportdata'));
1582      var noDateOrMissingKey = 'noDateOrMissing';
1583      var sumKey = 'sumKey';
1584      var totalKey = 'totalKey';
1585      if (siteData != null)
1586      {
1587        data = getJSONDataWithPercent(siteData, 'yesDateUnknown', noDateOrMissingKey, numDecimals);
1588        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1589        data = getJSONDataWithPercent(siteData, 'noDateUnknown', noDateOrMissingKey, numDecimals);
1590        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1591        data = getJSONDataWithPercent(siteData, 'notAskedDateUnknown', noDateOrMissingKey, numDecimals);
1592        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1593        data = getJSONDataWithPercent(siteData, 'missing', noDateOrMissingKey, numDecimals);
1594        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1595        // Add column with summed values for site
1596        var siteSum = getJSONData(siteData, noDateOrMissingKey, 0);
1597        tableRow.appendChild(getTableCellElement(siteSum, 'rowsummary'));
1598      }
1599      // Add column with total number of samples for site, regardless of creation date
1600      var siteTotal = getJSONData(siteData, totalKey, 0);
1601      tableRow.appendChild(getTableCellElement(siteTotal, 'rowsummary'));
1602      reportTable.appendChild(tableRow);
1603    }
1604  }
1605
1606  function addDataRowsToOverviewTable(report, reportTable)
1607  {
1608    var sites = report.sites;   
1609    var statistics = report.statistics;
1610    unknownCreation = statistics.noDate;
1611    unknownSite = statistics.unknownSite;
1612    var siteOrderList = report.siteOrderListKey;
1613    for (var siteOrderIndex in siteOrderList)
1614    {
1615      var namePrefix = siteOrderList[siteOrderIndex];   
1616      if (!sites.hasOwnProperty(namePrefix)) continue;       
1617      var site = sites[namePrefix];
1618      var siteName = site.name;       
1619      var siteStartDate = dateStrToDate(site.startDate);
1620      var siteStartDateStr = addHyphensToDateString(site.startDate);
1621     
1622      var siteData = statistics[namePrefix];     
1623      var siteLatestDate = siteData['latestDateKey'];
1624      var siteLatestDateStr = addHyphensToDateString(siteLatestDate);
1625      var tableRow = document.createElement('tr');
1626      var tableCol = getTableCellElement(siteName, 'rowtitle');
1627      tableRow.appendChild(tableCol);
1628      tableRow.appendChild(getTableCellElement(siteStartDateStr, 'reportdata'));
1629      tableRow.appendChild(getTableCellElement(siteLatestDateStr, 'reportdata'));
1630      var noDateKey = 'noDate';
1631      var sumKey = 'sumKey';
1632      var totalKey = 'totalKey';
1633      if (siteData != null)
1634      {
1635        data = getJSONData(siteData, 'patient');
1636        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1637        data = getJSONData(siteData, 'bloodSample');
1638        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1639        data = getJSONData(siteData, 'bloodSampleFollowUp');
1640        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1641        data = getJSONData(siteData, 'specimen');
1642        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1643        data = getJSONData(siteData, 'noSpecimen');
1644        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1645        data = getJSONData(siteData, 'consentYes');
1646        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1647        data = getJSONData(siteData, 'consentMissing');
1648        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1649      }
1650      reportTable.appendChild(tableRow);
1651    }
1652  }
1653
1654  function addDataRowsToOverviewPatientDetailedTable(report, reportTable)
1655  {
1656    var sites = report.sites;   
1657    var statistics = report.statistics;
1658    unknownCreation = statistics.noDate;
1659    unknownSite = statistics.unknownSite;
1660    var siteOrderList = report.siteOrderListKey;
1661    for (var siteOrderIndex in siteOrderList)
1662    {
1663      var namePrefix = siteOrderList[siteOrderIndex];   
1664      if (!sites.hasOwnProperty(namePrefix)) continue;       
1665      var site = sites[namePrefix];
1666      var siteName = site.name;       
1667      var siteStartDate = dateStrToDate(site.startDate);
1668      var siteStartDateStr = addHyphensToDateString(site.startDate);
1669     
1670      var siteData = statistics[namePrefix];
1671/*   
1672      var siteLatestDate = siteData['latestDateKey'];
1673      var siteLatestDateStr = addHyphensToDateString(siteLatestDate);
1674*/
1675      var tableRow = document.createElement('tr');
1676      var tableCol = getTableCellElement(siteName, 'rowtitle');
1677      tableRow.appendChild(tableCol);
1678      tableRow.appendChild(getTableCellElement(siteStartDateStr, 'reportdata'));
1679/*
1680      tableRow.appendChild(getTableCellElement(siteLatestDateStr, 'reportdata'));
1681*/
1682      var noDateKey = 'noDate';
1683      var sumKey = 'sumKey';
1684      var totalKey = 'totalKey';
1685      if (siteData != null)
1686      {
1687        data = getJSONData(siteData, 'patientBloodSampleOnly');
1688        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1689        data = getJSONData(siteData, 'patientSpecimenOnly');
1690        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1691        data = getJSONData(siteData, 'patientNoSpecimenOnly');
1692        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1693        data = getJSONData(siteData, 'patientBloodSampleAndSpecimen');
1694        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1695        data = getJSONData(siteData, 'patientBloodSampleAndNoSpecimen');
1696        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1697        data = getJSONData(siteData, 'patientSpecimenAndNoSpecimen');
1698        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1699        data = getJSONData(siteData, 'patientBloodSampleAndSpecimenAndNoSpecimen');
1700        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1701        //data = getJSONData(siteData, 'patientNoSamples');
1702        //tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1703        data = getJSONData(siteData, 'sumKey');
1704        tableRow.appendChild(getTableCellElement(data, 'rowsummary'));
1705      }
1706      reportTable.appendChild(tableRow);
1707    }
1708  }
1709
1710  function addDataRowsToMissingSampleDataTable(report, reportTable)
1711  {
1712    var sites = report.sites;   
1713    var statistics = report.statistics;
1714    var sampleType = report.sampleType;
1715    var permissionDeniedForPatientName = report.permissionDeniedForPatientName;
1716    var unknownCreation = statistics.noDate;
1717    var unknownSite = statistics.unknownSite;
1718    var siteOrderList = report.siteOrderListKey;
1719    for (var siteOrderIndex in siteOrderList)
1720    {
1721      var namePrefix = siteOrderList[siteOrderIndex];   
1722      if (!sites.hasOwnProperty(namePrefix)) continue;       
1723      var site = sites[namePrefix];
1724      var siteName = site.name;
1725      var siteStartDate = dateStrToDate(site.startDate);
1726      var siteStartDateStr = addHyphensToDateString(site.startDate);
1727     
1728      var siteData = statistics[namePrefix];     
1729      var siteLatestDate = siteData['latestDateKey'];
1730      var siteLatestDateStr = addHyphensToDateString(siteLatestDate);
1731      var tableRow = document.createElement('tr');
1732      var tableCol = getTableCellElement(siteName, 'rowtitle');
1733      tableRow.appendChild(tableCol);
1734      tableRow.appendChild(getTableCellElement(siteStartDateStr, 'reportdata'));
1735      tableRow.appendChild(getTableCellElement(siteLatestDateStr, 'reportdata'));
1736      //var currentDate = new Date(periodStartDate.getFullYear(), periodStartDate.getMonth(), periodStartDate.getDate());     
1737      var noDateKey = 'noDate';
1738      var sumKey = 'sumKey';
1739      var totalKey = 'totalKey';
1740      if (siteData != null)
1741      {
1742        if ('false' == permissionDeniedForPatientName)
1743        {
1744          data = getJSONData(siteData, 'missingPatientName');
1745          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1746        }
1747        else
1748        {
1749          data = '-';
1750          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1751        }
1752        if (sampleType == 'specimen')
1753        {
1754          data = getJSONData(siteData, 'missingPadReference');
1755          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1756          data = getJSONData(siteData, 'missingLaterality');
1757          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1758          data = getJSONData(siteData, 'missingSamplingDateTime');
1759          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1760          data = getJSONData(siteData, 'missingRnaLaterDateTime');
1761          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1762        }
1763        else if (sampleType == 'nospecimen')
1764        {
1765          data = getJSONData(siteData, 'missingPadReference');
1766          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1767          data = getJSONData(siteData, 'missingLaterality');
1768          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1769          data = getJSONData(siteData, 'missingSamplingDateTime');
1770          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1771        }
1772        else if (sampleType == 'blood')
1773        {
1774          data = getJSONData(siteData, 'missingBloodSamplingDateTime');
1775          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1776          data = getJSONData(siteData, 'missingBloodFreezerDateTime');
1777          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1778        }
1779      }
1780      reportTable.appendChild(tableRow);
1781    }
1782  }
1783
1784  function createLinkStr(linkName, idStr, itemTypeStr, titleStr, sessionId)
1785  {
1786    var linkStr = '<span class="link" onclick="Main.itemOnClick(event, \'' + sessionId + '\', \'' + itemTypeStr + '\', ' + idStr + ', false)" title="' + titleStr + '">' + linkName + '</span>';
1787    return linkStr;
1788  }
1789
1790  function createTableCellElementHtml(html, clazz, colspan, rowspan)
1791  {
1792    var htmlStr = new String(html);
1793    var cellElement = document.createElement('td');
1794    cellElement.innerHTML = htmlStr;
1795    cellElement.setAttribute('class', clazz);
1796    if (colspan != null) cellElement.setAttribute('colspan', colspan);
1797    if (rowspan != null) cellElement.setAttribute('rowspan', rowspan);
1798   
1799    return cellElement;
1800  }
1801 
1802  function getJSONDataWithPercent(jsonObject, key, sumKey, numDecimals)
1803  {
1804    var dataNum = getJSONData(jsonObject, key);
1805    var dataSum = getJSONData(jsonObject, sumKey);
1806    var dataPct = '0';
1807    if (dataSum != null && dataSum != 0)
1808    {
1809      dataPct = 100*dataNum/dataSum;
1810      dataPct = dataPct.toFixed(numDecimals);
1811    }
1812    var data = dataNum + ' (' + dataPct + '%)';
1813    return data;
1814  }
1815
1816  function getJSONData(jsonObject, key)
1817  {
1818    var data = getJSONData(jsonObject, key, '');
1819    return data;
1820  }
1821
1822  function getJSONData(jsonObject, key, defaultChoice)
1823  {
1824    var data = defaultChoice;
1825    if (jsonObject != null)
1826    {
1827      if (jsonObject[key] != null)
1828      {
1829        data = jsonObject[key];
1830      }
1831    }
1832    /*
1833    else
1834    {
1835      data = 'jsonObject==null';
1836    }
1837    */
1838    return data;
1839  }
1840
1841  function addQuarterColumnHeaders(columnHeaderRow, startDate)
1842  {
1843    var currentDate = startDate;
1844    for (var i=0;i<numCols;i++)
1845    {
1846      var quarter = Math.floor(currentDate.getMonth()/3)+1;
1847      var columnText = 'Q'+quarter;
1848      var quarterHeader = getTableCellElement(columnText, 'reportsubheader');
1849      columnHeaderRow.appendChild(quarterHeader); 
1850      currentDate.setMonth(currentDate.getMonth()+3);     
1851    }
1852  }
1853 
1854  function addWeekColumnHeaders(columnHeaderRow, startDate)
1855  {
1856    var currentDate = startDate;
1857    var day = currentDate.getDay()-1;
1858    day = day>=0 ? day: day + 7;
1859    currentDate.setDate(currentDate.getDate()-day);
1860    for (var i=0;i<numCols;i++)
1861    {     
1862      var weekNum = getISOWeekNumber(currentDate);
1863      var columnText = weekNum;
1864      if (weekNum < 10) columnText = '0'+columnText;     
1865      columnHeaderRow.appendChild(getTableCellElement(columnText, 'reportsubheader'));
1866      currentDate.setDate(currentDate.getDate()+7);     
1867    }
1868  }
1869 
1870  function addMonthColumnHeaders(columnHeaderRow, startDate)
1871  {   
1872    var currentDate = new Date(startDate.getFullYear(), startDate.getMonth());
1873    for (var i=0;i<numCols;i++)
1874    {             
1875      var monthHeader = getTableCellElement(month[currentDate.getMonth()], 'reportsubheader');
1876      columnHeaderRow.appendChild(monthHeader);       
1877      currentDate.setMonth(currentDate.getMonth() +1);
1878    }   
1879  }
1880 
1881  function addYearSubHeaders(startDate, endDate, subHeaderRowYear, vt)
1882  {   
1883    var currentYear = startDate.getFullYear(); 
1884   
1885    var columnCounter = 0;   
1886    do
1887    {
1888      var colspan;
1889      var headerText = currentYear;
1890      if (vt == "MONTH")
1891      {
1892        if (currentYear == startDate.getFullYear())
1893        {
1894          colspan =  11-startDate.getMonth()+1;
1895          if (endDate.getFullYear() == currentYear)
1896          {
1897            colspan = colspan - (11-endDate.getMonth());
1898          }
1899        }
1900        else if (currentYear == endDate.getFullYear()) 
1901          colspan = endDate.getMonth()+1;
1902        else
1903          colspan = 12;
1904      }
1905      else if (vt == "WEEK")
1906      { 
1907        if (startDate.getFullYear() == endDate.getFullYear())
1908        {
1909          colspan = numCols;
1910        }
1911        else if (currentYear == startDate.getFullYear())
1912        {
1913          var startWeek = getISOWeekNumber(startDate);
1914          var lastDay = new Date(startDate.getFullYear(), 11, 31);
1915          var endWeek = getISOWeekNumber(lastDay);
1916          if (endWeek == 1)
1917          {
1918            lastDay.setDate(lastDay.getDate()-7);
1919            endWeek = getISOWeekNumber(lastDay);
1920          }
1921          colspan = endWeek - startWeek +1;
1922        }
1923        else if (currentYear == endDate.getFullYear())
1924        {
1925          var endWeek = getISOWeekNumber(endDate);
1926          colspan = endWeek;
1927        }
1928        else
1929        {
1930          var dateInLastWeek = new Date(currentYear, 11, 31);
1931          var endWeek = getISOWeekNumber(dateInLastWeek);
1932          if (endWeek == 1)
1933          {
1934            dateInLastWeek.setDate(dateInLastWeek.getDate()-7);
1935            endWeek = getISOWeekNumber(dateInLastWeek);
1936          }
1937          colspan = endWeek;
1938        }               
1939      }
1940      else if (vt == "QUARTER")
1941      {
1942        if (currentYear == startDate.getFullYear())
1943        {
1944          if (startDate.getFullYear() == endDate.getFullYear())
1945          {
1946            colspan = Math.floor((endDate.getMonth()-startDate.getMonth())/3)+1;
1947          }
1948          else
1949          {
1950            colspan = Math.floor((11-startDate.getMonth())/3) +1;
1951          }
1952        }
1953        else if(currentYear == endDate.getFullYear())
1954        {
1955          colspan = Math.floor(endDate.getMonth()/3)+1;
1956        }
1957        else 
1958        {
1959          colspan = 4;
1960        }
1961      }
1962      else if (vt == "YEAR")
1963      {
1964        colspan = 1;       
1965      }
1966      columnCounter += colspan;           
1967      subHeaderRowYear.appendChild(getTableCellElement(headerText, 'reportsubheader', colspan));
1968    }while(!(++currentYear>endDate.getFullYear()));
1969  }
1970 
1971  function addDataRowsToTable(report, reportTable)
1972  {
1973    var fdString = report.beginDate;
1974    var ldString = report.endDate;
1975    var psdString = report.periodBeginDate;
1976    var startDate = new Date();
1977    startDate.setYear(fdString.substr(0,4));
1978    startDate.setMonth(fdString.substr(4,2)-1);
1979    startDate.setDate(fdString.substr(6));
1980    var endDate = new Date();
1981    endDate.setYear(ldString.substr(0,4));
1982    endDate.setMonth(ldString.substr(4,2)-1);
1983    endDate.setDate(ldString.substr(6));
1984    var periodStartDate = new Date();
1985    periodStartDate.setYear(psdString.substr(0,4));
1986    periodStartDate.setMonth(psdString.substr(4,2)-1);
1987    periodStartDate.setDate(psdString.substr(6));
1988    var viewType = report.viewType;   
1989    var sites = report.sites;   
1990    var statistics = report.statistics;
1991    unknownCreation = statistics.noDate;
1992    unknownSite = statistics.unknownSite;
1993    var siteOrderList = report.siteOrderListKey;
1994    for (var siteOrderIndex in siteOrderList)
1995    {
1996      var namePrefix = siteOrderList[siteOrderIndex];   
1997      if (!sites.hasOwnProperty(namePrefix)) continue;
1998      var site = sites[namePrefix];
1999      var siteName = site.name;   
2000      var year = site.startDate.substr(0,4);
2001      var month = site.startDate.substr(5,2);
2002      var date = site.startDate.substr(8,2);     
2003      var siteStartDate = new Date(year, month-1, date);
2004     
2005      var siteData = statistics[namePrefix];
2006      var siteLatestDate = siteData['latestDateKey'];
2007      var siteLatestDateStr = '????-??-??';
2008      if (siteLatestDate != null)
2009      {
2010        var siteLatestDateYear = siteLatestDate.substr(0,4);
2011        var siteLatestDateMonth = siteLatestDate.substr(4,2);
2012        var siteLatestDateDate = siteLatestDate.substr(6,2);
2013        siteLatestDateStr = siteLatestDateYear + '-' + siteLatestDateMonth + '-' + siteLatestDateDate;
2014      }
2015      var tableRow = document.createElement('tr');
2016      var tableCol = getTableCellElement(siteName, 'rowtitle');
2017      tableRow.appendChild(tableCol);
2018      tableRow.appendChild(getTableCellElement(year+'-'+(month)+'-'+date, 'reportdata'));
2019      tableRow.appendChild(getTableCellElement(siteLatestDateStr, 'reportdata'));
2020      var currentDate = new Date(periodStartDate.getFullYear(), periodStartDate.getMonth(), periodStartDate.getDate());     
2021      var columnCounter = 0;
2022      do
2023      {
2024        var data = 0;
2025        var keyIndex;
2026        var yearIndex = currentDate.getFullYear();
2027       
2028        if (viewType == 'YEAR')
2029        {
2030          keyIndex = yearIndex;
2031          if (siteData != null)
2032          {
2033            if (siteData[keyIndex] != null) data = siteData[keyIndex];
2034          }
2035          // Initialize data columns before site start date to empty string
2036          if ( (currentDate.getFullYear() < siteStartDate.getFullYear()))
2037          {
2038            data = '';
2039          }
2040          currentDate.setFullYear(currentDate.getFullYear()+1);
2041        }
2042        else if (viewType == 'QUARTER')
2043        {
2044          var qIndex = Math.floor(currentDate.getMonth()/3) + 1;
2045          var startQuarter = Math.floor(siteStartDate.getMonth()/3)+1;
2046          keyIndex = yearIndex + '' + qIndex;
2047          if (siteData != null)
2048          {
2049            if (siteData[keyIndex] != null) data = siteData[keyIndex];           
2050          }         
2051          // Initialize data columns before site start date to empty string
2052          if ( (currentDate.getFullYear() < siteStartDate.getFullYear()) ||
2053               (currentDate.getFullYear() == siteStartDate.getFullYear() && qIndex < startQuarter))
2054          {
2055            data = '';
2056          }
2057          currentDate.setMonth(currentDate.getMonth()+3);         
2058        }
2059        else if (viewType == 'MONTH')
2060        {
2061          var monthIndex = currentDate.getMonth()+1;
2062          var rowFill = monthIndex < 10 ? '0' : '';
2063          keyIndex = yearIndex + rowFill + monthIndex;
2064          if (siteData != null)
2065          {
2066            if (siteData[keyIndex] != null) data = siteData[keyIndex];
2067          }
2068          // Initialize data columns before site start date to empty string
2069          if ( (currentDate.getFullYear() < siteStartDate.getFullYear()) ||
2070               (currentDate.getFullYear() == siteStartDate.getFullYear() && (monthIndex-1) < siteStartDate.getMonth()))
2071          {
2072            data = '';
2073          }
2074          currentDate.setMonth(currentDate.getMonth()+1);
2075        }
2076        else if (viewType == 'WEEK')
2077        {
2078          var weekIndex = getISOWeekNumber(currentDate);
2079          // Week number in year stored as yyyyww with leading 0 if needed
2080          if (weekIndex < 10)
2081          {
2082            keyIndex = yearIndex + '0' + weekIndex;
2083          }
2084          else
2085          {
2086            keyIndex = yearIndex + '' + weekIndex;
2087          }
2088          if (siteData != null)
2089          {
2090            if (siteData[keyIndex] != null) data = siteData[keyIndex];
2091          }
2092          // Initialize data columns before site start date to empty string
2093          //
2094          // Note: ISO week numbers are tricky in their short form (without being coupled to a year),
2095          // since days in different years may lie in the same week, and days at the start of
2096          // a year may have week number 52 or 53 of the previous year and days at the end of
2097          // a year may have week number 01 of the next year.
2098          // Example: Monday 2012-01-02 has week number 2012-01, Monday 2012-12-31 has week number 2013-01
2099          // If current date is before site start date - 6 days, it is in a previous week
2100          // If current date is within site start date +/- 6 days and not in the same week, check dates
2101          // (just checking week numbers in the last case leads to e.g. 2012-12-30 (w52) > 2012-12-31 (w01))
2102          //
2103          if (currentDate.getTime() < siteStartDate.getTime() - 6*24*3600*1000 ||
2104              currentDate.getTime() < siteStartDate.getTime() + 6*24*3600*1000 &&
2105                 getISOWeekNumber(currentDate) != getISOWeekNumber(siteStartDate) &&
2106                 currentDate < siteStartDate)
2107          {
2108            data = '';
2109          }
2110          currentDate.setDate(currentDate.getDate()+7);
2111        }
2112       
2113        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
2114        columnCounter++;       
2115      } while (columnCounter < numCols)
2116      // Add column with sample sum for site for the selected time period
2117      var siteSum = 0;
2118      if (siteData != null)
2119      {
2120        var sumSiteKey = 'sumSiteKey';
2121        if (siteData[sumSiteKey] != null)
2122        {
2123          siteSum = siteData[sumSiteKey];
2124        }
2125      }
2126      tableRow.appendChild(getTableCellElement(siteSum, 'rowsummary'));
2127      // Add column with total number of samples for site, regardless of creation date
2128      var siteTotal = 0;
2129      if (siteData != null)
2130      {
2131        var totalSiteKey = 'totalSiteKey';
2132        if (siteData[totalSiteKey] != null)
2133        {
2134          siteTotal = siteData[totalSiteKey];
2135        }
2136      }
2137      tableRow.appendChild(getTableCellElement(siteTotal, 'rowsummary'));
2138      reportTable.appendChild(tableRow);
2139    }
2140  }
2141 
2142  function createSortedPeriodArray(report, numberOfColumns)
2143  {
2144    var psdString = report.periodBeginDate;
2145    var periodStartDate = new Date();
2146    periodStartDate.setYear(psdString.substr(0,4));
2147    periodStartDate.setMonth(psdString.substr(4,2)-1);
2148    periodStartDate.setDate(psdString.substr(6));
2149    var viewType = report.viewType;   
2150    var sortedPeriodArray = Array(numberOfColumns);
2151    var currentDate = new Date(periodStartDate.getFullYear(), periodStartDate.getMonth(), periodStartDate.getDate());     
2152    var columnCounter = 0;
2153    do
2154    { 
2155      var keyIndex;
2156      var yearIndex = currentDate.getFullYear();
2157       
2158      if (viewType == 'YEAR')
2159      {
2160        keyIndex = yearIndex;
2161        currentDate.setFullYear(currentDate.getFullYear()+1);
2162      }
2163      else if (viewType == 'QUARTER')
2164      {
2165        var qIndex = Math.floor(currentDate.getMonth()/3) + 1;
2166        keyIndex = yearIndex + '' + qIndex;
2167        currentDate.setMonth(currentDate.getMonth()+3);         
2168      }
2169      else if (viewType == 'MONTH')
2170      {
2171        var monthIndex = currentDate.getMonth()+1;
2172        var rowFill = monthIndex < 10 ? '0' : '';
2173        keyIndex = yearIndex + rowFill + monthIndex;
2174        currentDate.setMonth(currentDate.getMonth()+1);
2175      }
2176      else if (viewType == 'WEEK')
2177      {
2178        var weekIndex = getISOWeekNumber(currentDate);
2179        // Week number in year stored as yyyyww with leading 0 if needed
2180        if (weekIndex < 10)
2181        {
2182          keyIndex = yearIndex + '0' + weekIndex;
2183        }
2184        else
2185        {
2186          keyIndex = yearIndex + '' + weekIndex;
2187        }
2188        currentDate.setDate(currentDate.getDate()+7);
2189      }
2190      sortedPeriodArray[columnCounter] = keyIndex;
2191      columnCounter++;       
2192    } while (columnCounter < numberOfColumns)
2193    return sortedPeriodArray;
2194  }
2195 
2196  function getReportTable()
2197  {
2198      var reportTable = document.createElement('table');
2199      reportTable.setAttribute('class','reporttable');
2200      reportTable.setAttribute('border','1');     
2201      return reportTable;
2202  }
2203 
2204  function getTableCellElement(text, clazz, colspan, rowspan)
2205  {
2206    var cellElement = document.createElement('td');
2207    text = new String(text);   
2208    var textArray = text.split("\n");   
2209    if (textArray.length > 1)
2210    {
2211      for (var i=0;i<textArray.length;i++)
2212      {       
2213        if (i>0)cellElement.appendChild(document.createElement('br'));
2214        cellElement.appendChild(document.createTextNode(textArray[i]));
2215      }     
2216    }
2217    else
2218    {
2219      cellElement.appendChild(document.createTextNode(text));
2220    }
2221    cellElement.setAttribute('class', clazz);
2222    if (colspan != null) cellElement.setAttribute('colspan', colspan);
2223    if (rowspan != null) cellElement.setAttribute('rowspan', rowspan);
2224   
2225    return cellElement;
2226  }
2227 
2228  function getListElement(itemText)
2229  {
2230    var listElement = document.createElement('li');
2231    var textNode = document.createTextNode(itemText);
2232    listElement.appendChild(textNode);
2233    return listElement;
2234  }
2235
2236  /**
2237   *  addHyphensToDateStr()
2238   *
2239   *  Adds hyphens to date string in yyyymmdd format to
2240   *  get yyyy-mm-dd format. If input string already contains
2241   *  hyphen(s), the input string is returned unchanged.
2242   *  If input string is null or empty, '????-??-??' is returned.
2243   *
2244   *  @param dateStr String Input date string in yyyy-mm-dd or yyyymmdd format.
2245   *  @return String Date string in yyyy-mm-dd format.
2246   */
2247  function addHyphensToDateString(dateStr)
2248  {
2249    var dateWithHyphensStr = '????-??-??';
2250    if (dateStr != null && dateStr != '')
2251    {
2252      // Check if input string already contains hyphen
2253      if (dateStr.indexOf("-") >= 0)
2254      {
2255        // Date already has hyphen(s)
2256        dateWithHyphensStr = dateStr;
2257      }
2258      else
2259      {
2260        // Date in yyyymmdd format
2261        var yearStr = dateStr.substr(0,4);
2262        var monthStr = dateStr.substr(4,2);
2263        var dayStr = dateStr.substr(6,2);     
2264        dateWithHyphensStr = yearStr + '-' + monthStr + '-' + dayStr;
2265      }
2266    }
2267    return dateWithHyphensStr;
2268  }
2269
2270  /**
2271   *  dateStrToDate()
2272   *
2273   *  Takes an input date string in yyyy-mm-dd or yyyymmdd format
2274   *  and returns a date corresponding to the date string.
2275   *  If input string is null or empty, null is returned.
2276   *
2277   *  @param dateStr String Input date string in yyyy-mm-dd or yyyymmdd format.
2278   *  @return Date Date corresponding to input date string.
2279   */
2280  function dateStrToDate(dateStr)
2281  {
2282    var date = null;
2283    if (dateStr != null && dateStr != '')
2284    {
2285      // Check if input string already contains hyphen
2286      if (dateStr.indexOf("-") >= 0)
2287      {
2288        // Date in yyyy-mm-dd format
2289        var yearStr = dateStr.substr(0,4);
2290        var monthStr = dateStr.substr(5,2);
2291        var dayStr = dateStr.substr(8,2);     
2292        var date = new Date(parseInt(yearStr, 10), parseInt(monthStr, 10)-1, parseInt(dayStr, 10));
2293      }
2294      else
2295      {
2296        // Date in yyyymmdd format
2297        var yearStr = dateStr.substr(0,4);
2298        var monthStr = dateStr.substr(4,2);
2299        var dayStr = dateStr.substr(6,2);     
2300        var date = new Date(parseInt(yearStr, 10), parseInt(monthStr, 10)-1, parseInt(dayStr, 10));
2301      }
2302    }
2303    return date;
2304  }
2305
2306  /*
2307   *  Get the ISO week number for a given date
2308   *
2309   *  Based on code at http://stackoverflow.com/questions/6117814/get-week-of-year-in-javascript-like-in-php
2310   *
2311   *  @param date String Input date to get ISO week number for.
2312   *  @return int ISO week number for input date.
2313   */
2314  function getISOWeekNumber(date)
2315  {
2316    tmpDate = new Date(date);
2317    tmpDate.setHours(0,0,0);
2318    // Set to nearest Thursday: current date + 4 - current day number
2319    // Make Sunday day number 7
2320    tmpDate.setDate(tmpDate.getDate() + 4 - (tmpDate.getDay() || 7));
2321    // Get first day of year
2322    var yearStart = new Date(tmpDate.getFullYear(), 0, 1);
2323    // Calculate full weeks to nearast Thursday (86400000 = 24*60*60*1000 number of ms in a day)
2324    var weekNo = Math.ceil(( ( (tmpDate - yearStart) / 86400000) + 1)/7);
2325    return weekNo;
2326  }
2327 
2328  function goPrint()
2329  {
2330    var frm = document.forms['reggie'];
2331    var reportName = frm.reporttype[frm.reporttype.selectedIndex].text;
2332    var printNote = '<b>Note!</b> For better printing set page orientation to <i>landscape</i>.';
2333    openPrintWindow('<%=ID%>', 'reportcell', reportName, 'landscape', printNote, '../');
2334  }
2335
2336  function getBloodSampleFilterDisplayText(bloodSampleFilter)
2337  {
2338    var bloodSampleFilterDisplayText = bloodSampleFilter;
2339    if (bloodSampleFilter == 'followup')
2340    {
2341      bloodSampleFilterDisplayText = 'Follow-up';
2342    }
2343    else if (bloodSampleFilter == 'notfollowup')
2344    {
2345      bloodSampleFilterDisplayText = 'Not follow-up';
2346    }
2347    else if (bloodSampleFilter == '')
2348    {
2349      bloodSampleFilterDisplayText = 'unknown';
2350    }
2351    return bloodSampleFilterDisplayText;
2352  }
2353
2354  </script>
2355 
2356 
2357  </base:head>
2358  <base:body onload="init()">
2359    <p:path><p:pathelement 
2360      title="Reggie" href="<%="../index.jsp?ID="+ID%>" 
2361      /><p:pathelement title="Sample source report" 
2362      /></p:path>
2363    <div class="content">
2364    <%
2365    if (sc.getActiveProjectId() == 0)
2366    {
2367      %>
2368      <div class="messagecontainer note" style="width: 950px; margin-left: 20px; margin-bottom: 20px; margin-right: 0px; font-weight: bold; color: #cc0000;">
2369        No project has been selected. You may proceed with the report generation but
2370        only your own items will be included in the report.
2371      </div>
2372      <%
2373    }
2374    %>
2375 
2376    <form name="reggie" onsubmit="return false;">
2377      <!-- 1. Report type-->
2378      <table border="0" cellspacing="0" cellpadding="0" class="stepform">
2379      <tr>
2380        <td rowspan="3" class="stepno">1</td>
2381        <td class="steptitle">Report type</td>
2382      </tr>
2383      <tr>
2384        <td class="stepfields">
2385          <table border="0" cellspacing="0" cellpadding="0" width="100%">
2386          <tr valign="top">
2387            <td class="prompt">Report</td>
2388            <td class="input">
2389              <select name="reporttype">
2390                <option value="samplecount" selected="yes">Sample count report</option>
2391                <option value="consentcount">Consent count report</option>
2392                <option value="patientcount">Patient count report</option>
2393                <option value="overviewreport">Overview report</option>
2394                <option value="missingsampledatareport">Missing sample data report</option>
2395              </select>
2396            </td>
2397            <td class="status" id="report.status"></td>
2398            <td class="help">
2399              <span id="report.message" class="message" style="display: none;"></span>
2400              Select which report to generate.
2401            </td>
2402          </tr>
2403          </table>
2404        </td>
2405      </tr>
2406      </table>
2407     
2408      <div id="itemCountSection" style="display:none;">
2409        <p></p>
2410        <!-- 2. Report parameters-->
2411        <table border="0" cellspacing="0" cellpadding="0" class="stepform">
2412        <tr>
2413          <td rowspan="3" class="stepno">2</td>
2414          <td class="steptitle">Report parameters</td>
2415        </tr>
2416        <tr>
2417          <td class="stepfields">
2418            <table border="0" cellspacing="0" cellpadding="0" width="100%">           
2419            <tr>
2420              <td valign="top" class="prompt">
2421                <div id="reportPeriodSubSection01" style="display:none;">
2422                  <text id="reportPeriodSubSection01Header">Report period</text>
2423                </div>
2424              </td>
2425              <td valign="top" class="input">
2426                <div id="reportPeriodSubSection02" style="display:none;">
2427                  From<input type="text" onChange="dateOnChange()" size=7 name="fromdate"/>&nbsp;
2428                  To<input type="text" onChange="dateOnChange()" size=7 name="todate" />
2429                </div>
2430              </td>
2431              <td valign="top" class="status" id="displayInterval.status"></td>
2432              <td class="help">
2433                <div id="reportPeriodSubSection04" style="display:none;">
2434                  <span id="displayInterval.message" class="message" style="display: none;"></span>
2435                  <!--
2436                  Define which period the report should cover. Empty fields will include all <text id="items01">items</text>.<br>
2437                  -->
2438                  <text id="reportPeriodSubSection04HelpText">Parameter help text</text><br>
2439                </div>
2440              </td>
2441            </tr> 
2442            <tr>
2443              <td valign="top" class="prompt">
2444                <div id="viewTypeSubSection01" style="display:none;">
2445                  View type
2446                </div>
2447              </td>
2448              <td valign="top" class="input">
2449                <div id="viewTypeSubSection02" style="display:none;">
2450                  <select name="viewtype">
2451                    <option value="AUTO" selected="yes">Auto</option>
2452                    <option value="WEEK">Week</option>
2453                    <option value="MONTH">Month</option>
2454                    <option value="QUARTER">Quarter</option>
2455                    <option value="YEAR">Year</option>
2456                  </select>
2457                </div>
2458              </td>
2459              <td valign="top" class="status" id="displayViewType.status"></td>
2460              <td class="help">
2461                <div id="viewTypeSubSection04" style="display:none;">
2462                  <span id="displayViewType.message" class="message" style="display: none;"></span>
2463                  Auto will adjust the report depending on the size of the period.
2464                  <ul>
2465                    <li>Period shorter than 3 months - <text id="items02">items</text> per week</li>
2466                    <li>Period shorter than 13 months - <text id="items03">items</text> per month</li>
2467                    <li>Period shorter than 3 years - <text id="items04">items</text> per quarter</li>
2468                    <li>Period is 3 years or greater - <text id="items05">items</text> per year</li>
2469                  </ul>                 
2470                </div>
2471              </td>
2472            </tr>
2473            <tr>
2474              <td valign="top" class="prompt">
2475                <div id="sampleTypeSubSection01" style="display:none;">
2476                  Sample type
2477                </div>
2478              </td>
2479              <td valign="top" class="input">
2480                <div id="sampleTypeSubSection02" style="display:none;">
2481                  <select name="sampletype" onChange="sampleTypeOnChange()">
2482                    <option value="specimen" selected="yes">Specimen</option>
2483                    <option value="nospecimen">No specimen</option>
2484                    <option value="blood">Blood</option>
2485                  </select>
2486                </div>
2487              </td>
2488              <td valign="top" class="status" id="displaySampleType.status"></td>
2489              <td class="help">
2490                <div id="sampleTypeSubSection04" style="display:none;">
2491                  <span id="displaySampleType.message" class="message" style="display: none;"></span>
2492                  Select sample type for report.
2493                </div>
2494              </td>
2495            </tr>
2496            <tr>
2497              <td valign="top" class="prompt">
2498                <div id="tableAlternativesSubSection01" style="display:none;">
2499                  Table alternatives
2500                </div>
2501              </td>
2502              <td valign="top" class="input">
2503                <div id="tableAlternativesSubSection02" style="display:none;">
2504                  <select name="tablealternatives" onChange="tableAlternativesOnChange()">
2505                    <option value="full_blood_sample_tables" selected="yes">9 tables with different blood sample choices</option>
2506                    <option value="blood_sample_table_with_filter">1 table with optional blood sample filter</option>
2507                  </select>
2508                </div>
2509              </td>
2510              <td valign="top" class="status" id="displayTableAlternatives.status"></td>
2511              <td class="help">
2512                <div id="tableAlternativesSubSection04" style="display:none;">
2513                  <span id="displayTableAlternatives.message" class="message" style="display: none;"></span>
2514                  <!--
2515                  Select table alternative for report (only used if sample type = 'Blood').<br>
2516                  -->
2517                  <text id="tableAlternativesSubSection04HelpText">Parameter help text</text><br>
2518                </div>
2519              </td>
2520            </tr>
2521            <tr>
2522              <td valign="top" class="prompt">
2523                <div id="bloodSampleFilterSubSection01" style="display:none;">
2524                  Blood sample filter
2525                </div>
2526              </td>
2527              <td valign="top" class="input">
2528                <div id="bloodSampleFilterSubSection02" style="display:none;">
2529                  <select name="bloodsamplefilter">
2530                    <option value="none" selected="yes">None</option>
2531                    <option value="followup">Follow-up</option>
2532                    <option value="notfollowup">Not follow-up</option>
2533                    <option value="">unknown</option>
2534                    <option value="PreNeo">PreNeo</option>
2535                    <option value="PreOp">PreOp</option>
2536                    <option value="FollowUp06">FollowUp06</option>
2537                    <option value="FollowUp12">FollowUp12</option>
2538                    <option value="FollowUp36">FollowUp36</option>
2539                  </select>
2540                </div>
2541              </td>
2542              <td valign="top" class="status" id="displayBloodSampleFilter.status"></td>
2543              <td class="help">
2544                <div id="bloodSampleFilterSubSection04" style="display:none;">
2545                  <span id="displayBloodSampleFilter.message" class="message" style="display: none;"></span>
2546                  <!--
2547                  Select optional blood sample filter for report.<br>
2548                  -->
2549                  <text id="bloodSampleFilterSubSection04HelpText">Parameter help text</text><br>
2550                </div>
2551              </td>
2552            </tr>
2553            </table>
2554          </td>
2555        </tr>
2556        </table>
2557      </div>
2558     
2559      <div id="reportSection" style="display:none;">
2560        <p></p>
2561        <table border="0" cellspacing="0" cellpadding="0" class="stepform">
2562        <tr>
2563          <td rowspan="3" class="stepno">3</td>
2564          <td class="steptitle">Generated report
2565            <span id="printButton" class="link" style="float:right; display: none;" onclick="goPrint()"><img src="../images/print.png" style="padding-right: 0.5em;">Print version&hellip;</span>
2566          </td>
2567        </tr>
2568        <tr>
2569          <td id="reportcell" class="stepfields">
2570            <div class="loading" id="loading">
2571              <table>
2572              <tr>
2573                <td><img src="../images/loading.gif"></td>
2574                <td id="loading.msg">Generating report...</td>
2575              </tr>
2576              </table>
2577            </div>
2578          </td>
2579        </tr>
2580        </table>
2581      </div> 
2582     
2583      <div class="messagecontainer error" id="errorMessage" style="display: none; width: 950px; margin-left: 20px; margin-bottom: 0px;"></div>   
2584       
2585      <table style="margin-left: 20px; margin-top: 10px;" class="navigation">
2586        <tr>
2587          <td><base:button id="gocancel" title="Cancel" onclick="goRestart(false)" style="display: none;"/></td>
2588          <td><base:button id="gonext" title="Next" image="<%=home+"/images/gonext.png"%>" onclick="goNext(true)" /></td>
2589          <td><base:button id="gocreate" title="Generate" image="<%=home+"/images/gonext.png"%>" onclick="goCreate()" style="display: none;"/></td>         
2590          <td><base:button id="gorestart" title="Restart" image="<%=home+"/images/goback.png"%>" onclick="goRestart(true)" style="display: none;"/></td>
2591          <td id="gonext.message" class="message"></td>
2592        </tr>
2593      </table>     
2594    </form>
2595    </div>
2596   
2597  </base:body>
2598  </base:page>
2599  <%
2600}
2601finally
2602{
2603  if (dc != null) dc.close();
2604}
2605%>
Note: See TracBrowser for help on using the repository browser.