extensions/net.sf.basedb.reggie/trunk/resources/sampleproc/dna_normalization.js

Code
Comments
Other
Rev Date Author Line
5359 12 Apr 19 nicklas 1 var DnaNormalize = function()
5359 12 Apr 19 nicklas 2 {
5359 12 Apr 19 nicklas 3   var normalize = {};
5359 12 Apr 19 nicklas 4
5359 12 Apr 19 nicklas 5   // The minial volume of DNA we want to take when normalizing
5359 12 Apr 19 nicklas 6   // For DNA with high concentration we must make a larger mix to reach the target concentation
5359 12 Apr 19 nicklas 7   var MINIMAL_DNA_VOLUME = 1; // µl
5359 12 Apr 19 nicklas 8   var hasInitProtocols = false;
5449 27 May 19 nicklas 9   var protocolIsValid = false;
5359 12 Apr 19 nicklas 10   
5359 12 Apr 19 nicklas 11   var selectedDna;
5359 12 Apr 19 nicklas 12   var subtypeDna = null;
5359 12 Apr 19 nicklas 13   
5359 12 Apr 19 nicklas 14   var newDna = [];
5359 12 Apr 19 nicklas 15   
5359 12 Apr 19 nicklas 16   // Page initialization
5359 12 Apr 19 nicklas 17   normalize.initPage = function()
5359 12 Apr 19 nicklas 18   {
5359 12 Apr 19 nicklas 19     // Step 1
5359 12 Apr 19 nicklas 20     Events.addEventHandler('step-1', 'wizard-validate', normalize.validateStep1);
5359 12 Apr 19 nicklas 21     Buttons.addClickHandler('btnSelectDna', normalize.selectDna);
5359 12 Apr 19 nicklas 22     Events.addEventHandler('dna', 'base-selected', normalize.onDnaSelected);
5359 12 Apr 19 nicklas 23     
5359 12 Apr 19 nicklas 24     // Step 2
5359 12 Apr 19 nicklas 25     Events.addEventHandler('normalizationProtocol', 'change', normalize.protocolOnChange);
5359 12 Apr 19 nicklas 26     Events.addEventHandler('normalizationProtocol', 'keyup', normalize.protocolOnChange);
5361 15 Apr 19 nicklas 27     Events.addEventHandler('normalizedPlate', 'change', normalize.normalizedPlateOnChange);
5361 15 Apr 19 nicklas 28     Events.addEventHandler('normalizedPlate', 'keyup', normalize.normalizedPlateOnChange);
5359 12 Apr 19 nicklas 29     Events.addEventHandler('step-2', 'wizard-initialize', normalize.initializeStep2);
5359 12 Apr 19 nicklas 30     Events.addEventHandler('step-2', 'wizard-validate', normalize.validateStep2);
5359 12 Apr 19 nicklas 31
5359 12 Apr 19 nicklas 32     // Step 3
5359 12 Apr 19 nicklas 33     Events.addEventHandler('step-3', 'wizard-initialize', normalize.initializeStep3);
5359 12 Apr 19 nicklas 34     Events.addEventHandler('normalizationDate', 'blur', Wizard.validateDate);
5359 12 Apr 19 nicklas 35     
5359 12 Apr 19 nicklas 36     // Navigation
5359 12 Apr 19 nicklas 37     Buttons.addClickHandler('gocancel', Wizard.cancelWizard);
5359 12 Apr 19 nicklas 38     Buttons.addClickHandler('gorestart', Wizard.restartWizard);
5359 12 Apr 19 nicklas 39     Buttons.addClickHandler('gonext', Wizard.goNextOnClick);
5359 12 Apr 19 nicklas 40     Buttons.addClickHandler('goprint', normalize.printVersion);
5359 12 Apr 19 nicklas 41     Buttons.addClickHandler('goregister', Wizard.goRegister);
5359 12 Apr 19 nicklas 42
5359 12 Apr 19 nicklas 43     // Final registration
5359 12 Apr 19 nicklas 44     Events.addEventHandler('wizard', 'wizard-submit', normalize.submit);
5359 12 Apr 19 nicklas 45
5359 12 Apr 19 nicklas 46     var url = '../Extraction.servlet?ID='+App.getSessionId();
5359 12 Apr 19 nicklas 47     url += '&cmd=GetDNAToNormalize';
5359 12 Apr 19 nicklas 48     Wizard.showLoadingAnimation('Loading DNA extracts...');
5359 12 Apr 19 nicklas 49     Wizard.asyncJsonRequest(url, normalize.onDnaLoaded);
5359 12 Apr 19 nicklas 50   }
5359 12 Apr 19 nicklas 51   
5359 12 Apr 19 nicklas 52   normalize.onDnaLoaded = function(response)
5359 12 Apr 19 nicklas 53   {
5359 12 Apr 19 nicklas 54     var frm = document.forms['reggie'];
5359 12 Apr 19 nicklas 55     var dnaExtracts = response.dnaExtracts;
5359 12 Apr 19 nicklas 56     
5359 12 Apr 19 nicklas 57     dnaExtracts.sort(normalize.sortByQiacubePosition);
5359 12 Apr 19 nicklas 58     
5359 12 Apr 19 nicklas 59     if (dnaExtracts.length > 0)
5359 12 Apr 19 nicklas 60     {
5359 12 Apr 19 nicklas 61       var qiacubeRun = dnaExtracts[0].QiacubeDate + '#' + dnaExtracts[0].QiacubeRunNo;
5359 12 Apr 19 nicklas 62       for (var i=0; i < dnaExtracts.length; i++)
5359 12 Apr 19 nicklas 63       {
5359 12 Apr 19 nicklas 64         var dna = dnaExtracts[i];
5359 12 Apr 19 nicklas 65         var selected = (dna.QiacubeDate + '#' + dna.QiacubeRunNo) == qiacubeRun;
5359 12 Apr 19 nicklas 66         normalize.addDnaOption(frm.dna, dna, selected);
5359 12 Apr 19 nicklas 67       }
5449 27 May 19 nicklas 68       Wizard.setInputStatus('dna', 'valid');
5359 12 Apr 19 nicklas 69     }
5359 12 Apr 19 nicklas 70     else
5359 12 Apr 19 nicklas 71     {  
5359 12 Apr 19 nicklas 72       Wizard.setInputStatus('dna', 'invalid', 'No DNA available for normalization.');
5359 12 Apr 19 nicklas 73     }
5359 12 Apr 19 nicklas 74     
5359 12 Apr 19 nicklas 75     Doc.show('step-1');
5359 12 Apr 19 nicklas 76     Doc.show('gonext');
5359 12 Apr 19 nicklas 77   }
5359 12 Apr 19 nicklas 78   
5359 12 Apr 19 nicklas 79   /**
5359 12 Apr 19 nicklas 80     Sort by qiacube date, run number and position
5359 12 Apr 19 nicklas 81   */
5359 12 Apr 19 nicklas 82   normalize.sortByQiacubePosition = function(a, b)
5359 12 Apr 19 nicklas 83   {
5359 12 Apr 19 nicklas 84     if (a.QiacubeDate == b.QiacubeDate)
5359 12 Apr 19 nicklas 85     {
5359 12 Apr 19 nicklas 86       if (a.QiacubeRunNo == b.QiacubeRunNo)
5359 12 Apr 19 nicklas 87       {
5359 12 Apr 19 nicklas 88         return a.QiacubePosition-b.QiacubePosition;
5359 12 Apr 19 nicklas 89       }
5359 12 Apr 19 nicklas 90       else
5359 12 Apr 19 nicklas 91       {
5359 12 Apr 19 nicklas 92         return a.QiacubeRunNo - b.QiacubeRunNo;
5359 12 Apr 19 nicklas 93       }
5359 12 Apr 19 nicklas 94     }
5359 12 Apr 19 nicklas 95     else
5359 12 Apr 19 nicklas 96     {
5359 12 Apr 19 nicklas 97       return a.QiacubeDate < b.QiacubeDate ? -1 : 1;
5359 12 Apr 19 nicklas 98     }
5359 12 Apr 19 nicklas 99
5359 12 Apr 19 nicklas 100     return a.id - b.id;
5359 12 Apr 19 nicklas 101   }
5359 12 Apr 19 nicklas 102
5359 12 Apr 19 nicklas 103
5359 12 Apr 19 nicklas 104   /**
5359 12 Apr 19 nicklas 105     Sort by qiacube date, run number and position
5359 12 Apr 19 nicklas 106   */
5359 12 Apr 19 nicklas 107   normalize.sortByStorageLocation = function(a, b)
5359 12 Apr 19 nicklas 108   {
6219 20 Apr 21 nicklas 109     if (a.bioWell && b.bioWell)
5359 12 Apr 19 nicklas 110     {
6219 20 Apr 21 nicklas 111       if (a.bioWell.bioPlate.name == b.bioWell.bioPlate.name)
6219 20 Apr 21 nicklas 112       {
6219 20 Apr 21 nicklas 113         return a.bioWell.location < b.bioWell.location ? -1 : 1;
6219 20 Apr 21 nicklas 114       }
6219 20 Apr 21 nicklas 115       else
6219 20 Apr 21 nicklas 116       {
6219 20 Apr 21 nicklas 117         return a.bioWell.bioPlate.name < b.bioWell.bioPlate.name ? -1 : 1;
6219 20 Apr 21 nicklas 118       }
6219 20 Apr 21 nicklas 119     }  
5359 12 Apr 19 nicklas 120     return a.id - b.id;
5359 12 Apr 19 nicklas 121   }
5359 12 Apr 19 nicklas 122   
5361 15 Apr 19 nicklas 123   /**
5361 15 Apr 19 nicklas 124     Sort wells by column and row
5361 15 Apr 19 nicklas 125    */
5361 15 Apr 19 nicklas 126   normalize.sortWellsByColumnAndRow = function(a, b)
5361 15 Apr 19 nicklas 127   {
5361 15 Apr 19 nicklas 128     if (a.column == b.column)
5361 15 Apr 19 nicklas 129     {
5361 15 Apr 19 nicklas 130       return a.row - b.row;
5361 15 Apr 19 nicklas 131     }
5361 15 Apr 19 nicklas 132     else
5361 15 Apr 19 nicklas 133     {
5361 15 Apr 19 nicklas 134       return a.column - b.column;
5361 15 Apr 19 nicklas 135     }
5361 15 Apr 19 nicklas 136   }
5361 15 Apr 19 nicklas 137   
5359 12 Apr 19 nicklas 138   normalize.selectDna = function()
5359 12 Apr 19 nicklas 139   {
5359 12 Apr 19 nicklas 140     var frm = document.forms['reggie'];
5359 12 Apr 19 nicklas 141     if (frm.dna.disabled) return;
5359 12 Apr 19 nicklas 142     
5359 12 Apr 19 nicklas 143     if (subtypeDna == null)
5359 12 Apr 19 nicklas 144     {
5359 12 Apr 19 nicklas 145       subtypeDna = Reggie.getSubtypeInfo('DNA');
5359 12 Apr 19 nicklas 146     }
5359 12 Apr 19 nicklas 147     
5359 12 Apr 19 nicklas 148     newDna = [];
5359 12 Apr 19 nicklas 149     var url = '&resetTemporary=1';
5359 12 Apr 19 nicklas 150     url += '&tmpfilter:INT:itemSubtype='+subtypeDna.id;
5359 12 Apr 19 nicklas 151     Dialogs.selectItem('EXTRACT', 'dna', 1, url);
5359 12 Apr 19 nicklas 152   }
5359 12 Apr 19 nicklas 153
5359 12 Apr 19 nicklas 154   normalize.onDnaSelected = function(event)
5359 12 Apr 19 nicklas 155   {
5359 12 Apr 19 nicklas 156     var dna = event.detail;
5359 12 Apr 19 nicklas 157     
5359 12 Apr 19 nicklas 158     var frm = document.forms['reggie'];
5359 12 Apr 19 nicklas 159     var dnaList = frm.dna;
5359 12 Apr 19 nicklas 160     var isNew = true;
5359 12 Apr 19 nicklas 161     for (var i = 0; i < dnaList.length; i++)
5359 12 Apr 19 nicklas 162     {
5359 12 Apr 19 nicklas 163       if (dnaList[i].value == dna.id)
5359 12 Apr 19 nicklas 164       {
5359 12 Apr 19 nicklas 165         dnaList[i].selected = true;
5359 12 Apr 19 nicklas 166         isNew = false;
5359 12 Apr 19 nicklas 167       }
5359 12 Apr 19 nicklas 168     }
5359 12 Apr 19 nicklas 169     
5359 12 Apr 19 nicklas 170     if (isNew) newDna[newDna.length] = dna.id;
5359 12 Apr 19 nicklas 171     
5359 12 Apr 19 nicklas 172     if (event.detail.remaining == 0 && newDna.length > 0)
5359 12 Apr 19 nicklas 173     {
5359 12 Apr 19 nicklas 174       // Get more information about the selected dna
5359 12 Apr 19 nicklas 175       var url = '../Extraction.servlet?ID='+App.getSessionId();
5359 12 Apr 19 nicklas 176       url += '&cmd=GetDNAInfoForNormalize&dnaIds=' + newDna.join(',');
5359 12 Apr 19 nicklas 177       Wizard.asyncJsonRequest(url, normalize.onDnaInfoLoaded);
5359 12 Apr 19 nicklas 178     }
5359 12 Apr 19 nicklas 179   }
5359 12 Apr 19 nicklas 180
5359 12 Apr 19 nicklas 181   normalize.onDnaInfoLoaded = function(response)
5359 12 Apr 19 nicklas 182   {
5359 12 Apr 19 nicklas 183     var frm = document.forms['reggie'];
5359 12 Apr 19 nicklas 184     var dnaExtracts = response.dnaExtracts;
5359 12 Apr 19 nicklas 185     dnaExtracts.sort(normalize.sortByQiacubePosition);
5359 12 Apr 19 nicklas 186     
5359 12 Apr 19 nicklas 187     for (var dnaNo = 0; dnaNo < dnaExtracts.length; dnaNo++)
5359 12 Apr 19 nicklas 188     {
5359 12 Apr 19 nicklas 189       var dna = dnaExtracts[dnaNo];
5359 12 Apr 19 nicklas 190       normalize.addDnaOption(frm.dna, dna, true);
5359 12 Apr 19 nicklas 191     }
5449 27 May 19 nicklas 192     Wizard.setInputStatus('dna', 'valid');
5359 12 Apr 19 nicklas 193   }
5359 12 Apr 19 nicklas 194   
5359 12 Apr 19 nicklas 195   normalize.addDnaOption = function(list, dna, selected)
5359 12 Apr 19 nicklas 196   {
5359 12 Apr 19 nicklas 197     var name = dna.name;
6726 04 May 22 nicklas 198     if (dna.QiacubeDate)
5359 12 Apr 19 nicklas 199     {
6726 04 May 22 nicklas 200       name += ' -- ' + Reggie.reformatDate(dna.QiacubeDate);
6726 04 May 22 nicklas 201       if (dna.QiacubeRunNo) name += '; Run ' + dna.QiacubeRunNo;
6726 04 May 22 nicklas 202       if (dna.QiacubePosition) name += '; Pos ' + dna.QiacubePosition;
5359 12 Apr 19 nicklas 203     }
5359 12 Apr 19 nicklas 204
5359 12 Apr 19 nicklas 205     var option = new Option(name, dna.id, selected, selected);
5359 12 Apr 19 nicklas 206     if (dna.specimen && dna.specimen.YellowLabel != null) option.className = 'yellow';
5359 12 Apr 19 nicklas 207     option.dna = dna;
5359 12 Apr 19 nicklas 208     list[list.length] = option;
5359 12 Apr 19 nicklas 209   }
5359 12 Apr 19 nicklas 210   
5359 12 Apr 19 nicklas 211   normalize.validateStep1 = function(event)
5359 12 Apr 19 nicklas 212   {
5359 12 Apr 19 nicklas 213     var frm = document.forms['reggie'];
5359 12 Apr 19 nicklas 214     var dnaList = frm.dna;
5359 12 Apr 19 nicklas 215     
5359 12 Apr 19 nicklas 216     selectedDna = [];
5359 12 Apr 19 nicklas 217     for (var i=0; i < dnaList.length; i++)
5359 12 Apr 19 nicklas 218     {
5359 12 Apr 19 nicklas 219       if (dnaList[i].selected)
5359 12 Apr 19 nicklas 220       {
5359 12 Apr 19 nicklas 221         selectedDna[selectedDna.length] = dnaList[i].dna;
5359 12 Apr 19 nicklas 222       }
5359 12 Apr 19 nicklas 223     }
5359 12 Apr 19 nicklas 224       
5359 12 Apr 19 nicklas 225     if (selectedDna.length == 0)
5359 12 Apr 19 nicklas 226     {
5359 12 Apr 19 nicklas 227       Wizard.setInputStatus('dna', 'invalid', 'Not selected', 'invalid');
5359 12 Apr 19 nicklas 228       event.preventDefault();
5359 12 Apr 19 nicklas 229     }
5359 12 Apr 19 nicklas 230     else
5359 12 Apr 19 nicklas 231     {
5359 12 Apr 19 nicklas 232       Wizard.setInputStatus('dna', 'valid');
5359 12 Apr 19 nicklas 233     }
5359 12 Apr 19 nicklas 234   }
5359 12 Apr 19 nicklas 235
5359 12 Apr 19 nicklas 236
5359 12 Apr 19 nicklas 237   normalize.initializeStep2 = function()
5359 12 Apr 19 nicklas 238   {
5361 15 Apr 19 nicklas 239     normalize.buildProtocol();
5361 15 Apr 19 nicklas 240     
5361 15 Apr 19 nicklas 241     var url = '../Extraction.servlet?ID='+App.getSessionId();
5361 15 Apr 19 nicklas 242     url += '&cmd=GetActivePreNormalizedDNAPlates&numFreeWells=' + selectedDna.length;
5361 15 Apr 19 nicklas 243     Wizard.asyncJsonRequest(url, normalize.onPlateInfoLoaded);
5361 15 Apr 19 nicklas 244   }
5361 15 Apr 19 nicklas 245   
5361 15 Apr 19 nicklas 246   normalize.onPlateInfoLoaded = function(response)
5361 15 Apr 19 nicklas 247   {
5359 12 Apr 19 nicklas 248     var frm = document.forms['reggie'];
5361 15 Apr 19 nicklas 249     var plates = response.plates;
5361 15 Apr 19 nicklas 250     for (var plateNo = 0; plateNo < plates.length; plateNo++)
5361 15 Apr 19 nicklas 251     {
5361 15 Apr 19 nicklas 252       var plate = plates[plateNo];
5361 15 Apr 19 nicklas 253       var title = '';
5361 15 Apr 19 nicklas 254       if (plate.id == 0) 
5361 15 Apr 19 nicklas 255       {
5361 15 Apr 19 nicklas 256         title = 'Create: ' + plate.name;
5361 15 Apr 19 nicklas 257       }
5361 15 Apr 19 nicklas 258       else
5361 15 Apr 19 nicklas 259       {
5361 15 Apr 19 nicklas 260         title = plate.name + ' -- ' + plate.freeWells + ' free wells';
5361 15 Apr 19 nicklas 261       }
5361 15 Apr 19 nicklas 262       var option = new Option(title, plate.id);
5361 15 Apr 19 nicklas 263       plate.bioWells.sort(normalize.sortWellsByColumnAndRow);
5361 15 Apr 19 nicklas 264       option.plate = plate;
5361 15 Apr 19 nicklas 265       frm.normalizedPlate[frm.normalizedPlate.length] = option;
5361 15 Apr 19 nicklas 266     }
5361 15 Apr 19 nicklas 267     Wizard.setInputStatus('normalizedPlate', 'valid');
5361 15 Apr 19 nicklas 268
5361 15 Apr 19 nicklas 269     Wizard.setCurrentStep(2);
5361 15 Apr 19 nicklas 270     Doc.show('gonext');
5361 15 Apr 19 nicklas 271     Doc.show('goprint');
5361 15 Apr 19 nicklas 272     Doc.show('gocancel');
5361 15 Apr 19 nicklas 273     Wizard.keepSessionAlive();
5602 13 Sep 19 nicklas 274     Reggie.loadProtocols('DNA_NORMALIZATION_PROTOCOL', 'normalizationProtocol', 'DNA_TARGET_AMOUNT,DNA_MINIMAL_AMOUNT,DNA_TARGET_VOLUME,MIPS_PANEL');
5361 15 Apr 19 nicklas 275     frm.normalizationProtocol.focus();
5361 15 Apr 19 nicklas 276   }
5361 15 Apr 19 nicklas 277   
5361 15 Apr 19 nicklas 278   normalize.buildProtocol = function()
5361 15 Apr 19 nicklas 279   {
5359 12 Apr 19 nicklas 280     // Check if all DNA from same Qiacube run
5359 12 Apr 19 nicklas 281     var qiacubeRun = selectedDna[0].QiacubeDate + '#' + selectedDna[0].QiacubeRunNo;
5359 12 Apr 19 nicklas 282     var sameQiacubeRun = true;
6726 04 May 22 nicklas 283     var showLabelColumn = false;
6726 04 May 22 nicklas 284     for (var i=0; i < selectedDna.length; i++)
5359 12 Apr 19 nicklas 285     {
5359 12 Apr 19 nicklas 286       var dna = selectedDna[i];
5359 12 Apr 19 nicklas 287       if (qiacubeRun != dna.QiacubeDate+'#'+dna.QiacubeRunNo)
5359 12 Apr 19 nicklas 288       {
5359 12 Apr 19 nicklas 289         sameQiacubeRun = false;
5359 12 Apr 19 nicklas 290       }
6726 04 May 22 nicklas 291       if (dna.label) showLabelColumn = true;
5359 12 Apr 19 nicklas 292     }
5359 12 Apr 19 nicklas 293     
5359 12 Apr 19 nicklas 294     if (sameQiacubeRun)
5359 12 Apr 19 nicklas 295     {
5359 12 Apr 19 nicklas 296       selectedDna.sort(normalize.sortByQiacubePosition);
5359 12 Apr 19 nicklas 297       Doc.show('qiacube-info');
5359 12 Apr 19 nicklas 298       Doc.element('qiacube-date').innerHTML = Reggie.reformatDate(selectedDna[0].QiacubeDate);
5359 12 Apr 19 nicklas 299       Doc.element('qiacube-run').innerHTML = selectedDna[0].QiacubeRunNo;
5359 12 Apr 19 nicklas 300     }
5359 12 Apr 19 nicklas 301     else
5359 12 Apr 19 nicklas 302     {
5359 12 Apr 19 nicklas 303       selectedDna.sort(normalize.sortByStorageLocation);
5359 12 Apr 19 nicklas 304     }
5359 12 Apr 19 nicklas 305     
5359 12 Apr 19 nicklas 306     var html = '<table id="extractTable">';
5359 12 Apr 19 nicklas 307     html += '<thead class="bg-filled-100">';
5359 12 Apr 19 nicklas 308     // First header row
5359 12 Apr 19 nicklas 309     html += '<tr>';
5359 12 Apr 19 nicklas 310     html += '<th>DNA</th>';
6726 04 May 22 nicklas 311     if (showLabelColumn)
6726 04 May 22 nicklas 312     {
6726 04 May 22 nicklas 313       html += '<th>Label¹</th>';
6726 04 May 22 nicklas 314     }
5359 12 Apr 19 nicklas 315     if (sameQiacubeRun)
5359 12 Apr 19 nicklas 316     {
5359 12 Apr 19 nicklas 317       html += '<th>Qiacube</th>';
5359 12 Apr 19 nicklas 318     }
5359 12 Apr 19 nicklas 319     html += '<th>Storage</th>';
6219 20 Apr 21 nicklas 320     html += '<th>Conc.</th>';
5359 12 Apr 19 nicklas 321     html += '<th>Remain</th>';  
5359 12 Apr 19 nicklas 322     html += '<th colspan="2">Volumes</th>';
5361 15 Apr 19 nicklas 323     html += '<th>Normalized</th>';
5359 12 Apr 19 nicklas 324     html += '<th></th>';
5359 12 Apr 19 nicklas 325     html += '</tr>';
5359 12 Apr 19 nicklas 326     // Second header row
5359 12 Apr 19 nicklas 327     html += '<tr>';
5359 12 Apr 19 nicklas 328     html += '<th></th>';
6726 04 May 22 nicklas 329     if (showLabelColumn)
6726 04 May 22 nicklas 330     {
6726 04 May 22 nicklas 331       html += '<th></th>';
6726 04 May 22 nicklas 332     }
5359 12 Apr 19 nicklas 333     if (sameQiacubeRun)
5359 12 Apr 19 nicklas 334     {
5359 12 Apr 19 nicklas 335       html += '<th>position</th>';
5359 12 Apr 19 nicklas 336     }
5359 12 Apr 19 nicklas 337     html += '<th>box</th>';
5359 12 Apr 19 nicklas 338     html += '<th>(ng/µl)</th>';
5359 12 Apr 19 nicklas 339     html += '<th>(µg)</th>';
5359 12 Apr 19 nicklas 340     html += '<th>(µl)</th>';
5359 12 Apr 19 nicklas 341     html += '<th>H<sub>2</sub>O</th>';
5361 15 Apr 19 nicklas 342     html += '<th>plate</th>';
5359 12 Apr 19 nicklas 343     html += '<th>Remarks</th>';
5359 12 Apr 19 nicklas 344     html += '</tr>';
5359 12 Apr 19 nicklas 345     html += '</thead>';
5359 12 Apr 19 nicklas 346     html += '<tbody>';
5359 12 Apr 19 nicklas 347     
5359 12 Apr 19 nicklas 348     var expectedQiacubePosition = 0;
5359 12 Apr 19 nicklas 349     var homeUrl = Data.get('page-data', 'home-url');
5359 12 Apr 19 nicklas 350     var yellowImg = '<img src="'+homeUrl+'/images/yellow-label.png">';
5359 12 Apr 19 nicklas 351     for (var i=0; i < selectedDna.length; i++)
5359 12 Apr 19 nicklas 352     {
5359 12 Apr 19 nicklas 353       var dna = selectedDna[i];
5359 12 Apr 19 nicklas 354       var isYellow = dna.specimen && dna.specimen.YellowLabel != null;
5359 12 Apr 19 nicklas 355       if (sameQiacubeRun)
5359 12 Apr 19 nicklas 356       {
5359 12 Apr 19 nicklas 357         expectedQiacubePosition++;
5359 12 Apr 19 nicklas 358         while (expectedQiacubePosition != dna.QiacubePosition && expectedQiacubePosition <= 12)
5359 12 Apr 19 nicklas 359         {
6726 04 May 22 nicklas 360           html += normalize.insertEmpty(expectedQiacubePosition, showLabelColumn);
5359 12 Apr 19 nicklas 361           expectedQiacubePosition++;
5359 12 Apr 19 nicklas 362         }
5359 12 Apr 19 nicklas 363       }
5359 12 Apr 19 nicklas 364
5359 12 Apr 19 nicklas 365       var img = isYellow ? yellowImg : '';
5361 15 Apr 19 nicklas 366       html += '<tr class="highlight'+(isYellow ? ' yellow-specimen' : '')+'" id="dnaRow.'+dna.id+'">';
5359 12 Apr 19 nicklas 367       html += '<td class="extract if-yellow">'+img+Strings.encodeTags(dna.nextAliquotName)+'</td>';
6726 04 May 22 nicklas 368       if (showLabelColumn)
6726 04 May 22 nicklas 369       {
6726 04 May 22 nicklas 370         html += '<td class="label if-yellow">'+Strings.encodeTags(dna.label)+'</td>';
6726 04 May 22 nicklas 371       }
5359 12 Apr 19 nicklas 372       if (sameQiacubeRun)
5359 12 Apr 19 nicklas 373       {
5359 12 Apr 19 nicklas 374         html += '<td class="qiacubepos">'+dna.QiacubePosition+'</td>';
5359 12 Apr 19 nicklas 375       }
6219 20 Apr 21 nicklas 376       html += '<td class="box">'+(dna.bioWell?Strings.encodeTags(dna.bioWell.bioPlate.name + ' ' + dna.bioWell.location):'unknown')+'</td>';
6219 20 Apr 21 nicklas 377       html += '<td class="conc">'+ Numbers.formatNumber(dna.conc, 1) + '</td>';
5359 12 Apr 19 nicklas 378       html += '<td class="remain">'+ Numbers.formatNumber(dna.remainingQuantity, 2) + '</td>';
5359 12 Apr 19 nicklas 379       html += '<td class="volume" id="dnaVolume.'+dna.id+'"></td>';
5359 12 Apr 19 nicklas 380       html += '<td class="water" id="dnaWater.'+dna.id+'"></td>';
5361 15 Apr 19 nicklas 381       html += '<td class="plate" id="dnaLocation.'+dna.id+'"></td>';
5359 12 Apr 19 nicklas 382       html += '<td class="remarks" id="remarks.'+dna.id+'"></td>';
5359 12 Apr 19 nicklas 383       html += '</tr>'
5359 12 Apr 19 nicklas 384     }
5359 12 Apr 19 nicklas 385     if (sameQiacubeRun)
5359 12 Apr 19 nicklas 386     {
5359 12 Apr 19 nicklas 387       expectedQiacubePosition++;
5359 12 Apr 19 nicklas 388       while (expectedQiacubePosition <= 12)
5359 12 Apr 19 nicklas 389       {
6726 04 May 22 nicklas 390         html += normalize.insertEmpty(expectedQiacubePosition, showLabelColumn);
5359 12 Apr 19 nicklas 391         expectedQiacubePosition++;
5359 12 Apr 19 nicklas 392       }
5359 12 Apr 19 nicklas 393     }
5359 12 Apr 19 nicklas 394     html += '</tbody>';
5359 12 Apr 19 nicklas 395     html += '</table>';
6726 04 May 22 nicklas 396     if (showLabelColumn)
6726 04 May 22 nicklas 397     {
6726 04 May 22 nicklas 398       html += '<div id="protocol-footer">';
6726 04 May 22 nicklas 399       html += '¹ Some SCAN-B tubes have a non-standard label.';
6726 04 May 22 nicklas 400       html += '</div>';
6726 04 May 22 nicklas 401     }
5359 12 Apr 19 nicklas 402     
5359 12 Apr 19 nicklas 403     Doc.element('dnaNormalize').innerHTML = html;
5361 15 Apr 19 nicklas 404   }
5361 15 Apr 19 nicklas 405   
5361 15 Apr 19 nicklas 406   normalize.normalizedPlateOnChange = function()
5361 15 Apr 19 nicklas 407   {
5361 15 Apr 19 nicklas 408     var frm = document.forms['reggie'];
5361 15 Apr 19 nicklas 409     Doc.element('normalized-plate-name').innerHTML =  Strings.encodeTags(frm.normalizedPlate[frm.normalizedPlate.selectedIndex].text);
5359 12 Apr 19 nicklas 410     
5361 15 Apr 19 nicklas 411     Wizard.showGoNextConfirmation(true, 'Print the lab protocol before continuing with the registration!');
5361 15 Apr 19 nicklas 412
5361 15 Apr 19 nicklas 413     var plate = frm.normalizedPlate[frm.normalizedPlate.selectedIndex].plate;
5361 15 Apr 19 nicklas 414     var wells = plate.bioWells;
5361 15 Apr 19 nicklas 415     
5361 15 Apr 19 nicklas 416     var wellNo = 0;
5361 15 Apr 19 nicklas 417     for (var i=0; i < selectedDna.length; i++)
5361 15 Apr 19 nicklas 418     {
5361 15 Apr 19 nicklas 419       var dna = selectedDna[i];
5361 15 Apr 19 nicklas 420       if (!dna.notEnoughQuantity)
5361 15 Apr 19 nicklas 421       {
5361 15 Apr 19 nicklas 422         while (!wells[wellNo].canAdd) wellNo++;
5361 15 Apr 19 nicklas 423         Doc.element('dnaLocation.'+dna.id).innerHTML = wells[wellNo].location;
5361 15 Apr 19 nicklas 424         dna.well = wells[wellNo];
5361 15 Apr 19 nicklas 425         wellNo++;
5361 15 Apr 19 nicklas 426       }
5361 15 Apr 19 nicklas 427       else
5361 15 Apr 19 nicklas 428       {
5361 15 Apr 19 nicklas 429         Doc.element('dnaLocation.'+dna.id).innerHTML = '';
5361 15 Apr 19 nicklas 430         dna.well = null;
5361 15 Apr 19 nicklas 431       }
5361 15 Apr 19 nicklas 432     }
5359 12 Apr 19 nicklas 433   }
5359 12 Apr 19 nicklas 434   
5359 12 Apr 19 nicklas 435   normalize.protocolOnChange = function()
5359 12 Apr 19 nicklas 436   {
5359 12 Apr 19 nicklas 437     var frm = document.forms['reggie'];
5359 12 Apr 19 nicklas 438
5359 12 Apr 19 nicklas 439     if (!hasInitProtocols)
5359 12 Apr 19 nicklas 440     {
5359 12 Apr 19 nicklas 441       hasInitProtocols = true;
5359 12 Apr 19 nicklas 442       if (frm.normalizationProtocol.length == 0)
5359 12 Apr 19 nicklas 443       {
5359 12 Apr 19 nicklas 444         Wizard.setFatalError('No DNA normalization protocols found. Please ask the server administrator to create at least one protocol.');
5359 12 Apr 19 nicklas 445         return;
5359 12 Apr 19 nicklas 446       }
5359 12 Apr 19 nicklas 447       for (var i=0; i < frm.normalizationProtocol.length; i++)
5359 12 Apr 19 nicklas 448       {
5359 12 Apr 19 nicklas 449         var p = frm.normalizationProtocol[i].item;
5359 12 Apr 19 nicklas 450         
5359 12 Apr 19 nicklas 451         var unit = 'µg';
5359 12 Apr 19 nicklas 452         var factor = 1;
5359 12 Apr 19 nicklas 453         if (p.DNATargetAmount <= 0.5)
5359 12 Apr 19 nicklas 454         {
5359 12 Apr 19 nicklas 455           unit = 'ng';
5359 12 Apr 19 nicklas 456           factor = 1000;
5359 12 Apr 19 nicklas 457         }
5359 12 Apr 19 nicklas 458         
5359 12 Apr 19 nicklas 459         var text = p.name + ' (';
5602 13 Sep 19 nicklas 460         text += (p.MIPS_Panel ? Strings.encodeTags(p.MIPS_Panel) : 'NO MIPS_Panel!') + '; ';
5359 12 Apr 19 nicklas 461         if (p.DNAMinimalAmount) text += Reggie.formatNumber(p.DNAMinimalAmount * factor, '', 1) + '-';
5359 12 Apr 19 nicklas 462         text += p.DNATargetAmount ? Reggie.formatNumber(p.DNATargetAmount * factor, '', 1) : '? ';
5359 12 Apr 19 nicklas 463         text += unit;
5359 12 Apr 19 nicklas 464         text += ' in '+(p.DNATargetVolume || '? ')+'µl)';
5359 12 Apr 19 nicklas 465         frm.normalizationProtocol[i].text = text;
5359 12 Apr 19 nicklas 466       }
5359 12 Apr 19 nicklas 467     }
5359 12 Apr 19 nicklas 468
5449 27 May 19 nicklas 469     Wizard.setInputStatus('normalizationProtocol');
5449 27 May 19 nicklas 470     protocolIsValid = true;
5359 12 Apr 19 nicklas 471     Wizard.showGoNextConfirmation(true, 'Print the lab protocol before continuing with the registration!');
5359 12 Apr 19 nicklas 472
5359 12 Apr 19 nicklas 473     var protocol = frm.normalizationProtocol[frm.normalizationProtocol.selectedIndex].item;
5602 13 Sep 19 nicklas 474     if (!protocol.MIPS_Panel)
5359 12 Apr 19 nicklas 475     {
5602 13 Sep 19 nicklas 476       Wizard.setInputStatus('normalizationProtocol', 'invalid',  'No MIPS_Panel!');
5449 27 May 19 nicklas 477       protocolIsValid = false;
5449 27 May 19 nicklas 478     }
5449 27 May 19 nicklas 479     if (!protocol.DNATargetAmount || !protocol.DNATargetVolume)
5449 27 May 19 nicklas 480     {
5359 12 Apr 19 nicklas 481       protocol = {};
5449 27 May 19 nicklas 482       protocol.DNATargetAmount = 0.5;
5449 27 May 19 nicklas 483       protocol.DNATargetVolume = 10;
5449 27 May 19 nicklas 484       protocolIsValid = true;
5359 12 Apr 19 nicklas 485       
5449 27 May 19 nicklas 486       if (protocolIsValid)
5449 27 May 19 nicklas 487       {
5449 27 May 19 nicklas 488         var msg = 'Missing normalization data; assuming ';
5449 27 May 19 nicklas 489         msg += protocol.DNATargetAmount+ 'µg in '+protocol.DNATargetVolume+'µl.';
5449 27 May 19 nicklas 490         Wizard.setInputStatus('normalizationProtocol', 'warning',  msg);
5449 27 May 19 nicklas 491       }
5359 12 Apr 19 nicklas 492     }
5449 27 May 19 nicklas 493     else if (protocolIsValid)
5359 12 Apr 19 nicklas 494     {
5359 12 Apr 19 nicklas 495       Wizard.setInputStatus('normalizationProtocol', 'valid');
5359 12 Apr 19 nicklas 496     }
5359 12 Apr 19 nicklas 497     if (!protocol.DNAMinimalAmount) protocol.DNAMinimalAmount = protocol.DNATargetAmount;
5359 12 Apr 19 nicklas 498     Doc.element('normalization-protocol').innerHTML =  Strings.encodeTags(frm.normalizationProtocol[frm.normalizationProtocol.selectedIndex].text);
5359 12 Apr 19 nicklas 499
5359 12 Apr 19 nicklas 500     // The concentration of the normalized DNA
5359 12 Apr 19 nicklas 501     var normalizedConc = protocol.DNATargetAmount / protocol.DNATargetVolume; // µg/µl
5359 12 Apr 19 nicklas 502     
5359 12 Apr 19 nicklas 503     for (var i=0; i < selectedDna.length; i++)
5359 12 Apr 19 nicklas 504     {
5359 12 Apr 19 nicklas 505       var dna = selectedDna[i];
5359 12 Apr 19 nicklas 506       
5359 12 Apr 19 nicklas 507       // Aim for DNATargetAmount but not more than remiaingQuantity or less than DNAMinimalAmount
5359 12 Apr 19 nicklas 508       dna.usedQuantity = Math.max(Math.min(dna.remainingQuantity, protocol.DNATargetAmount), protocol.DNAMinimalAmount); // µg
6219 20 Apr 21 nicklas 509       dna.volume = Math.ceil(10000*dna.usedQuantity/dna.conc) / 10;
5359 12 Apr 19 nicklas 510       dna.water = protocol.DNATargetVolume-dna.volume; // µl
5359 12 Apr 19 nicklas 511       
5359 12 Apr 19 nicklas 512       var remarks = [];
5359 12 Apr 19 nicklas 513       if (dna.volume < MINIMAL_DNA_VOLUME)
5359 12 Apr 19 nicklas 514       {
5359 12 Apr 19 nicklas 515         // Large mix since we do not want to take less than 1µl
5359 12 Apr 19 nicklas 516         dna.volume = MINIMAL_DNA_VOLUME;
6219 20 Apr 21 nicklas 517         dna.usedQuantity = dna.volume * dna.conc / 1000; // µg
5359 12 Apr 19 nicklas 518         var totalVolume = dna.usedQuantity / normalizedConc; // µl
5359 12 Apr 19 nicklas 519         dna.water = totalVolume - dna.volume;
5359 12 Apr 19 nicklas 520         remarks[remarks.length] = 'Large mix';
5359 12 Apr 19 nicklas 521       }
5359 12 Apr 19 nicklas 522       else if (dna.volume > protocol.DNATargetVolume)
5359 12 Apr 19 nicklas 523       {
5359 12 Apr 19 nicklas 524         // The DNA has too low concentration so we can't reach the target amount
5359 12 Apr 19 nicklas 525         // with the target volume. The protocol may allow us to use a lesser amount
5359 12 Apr 19 nicklas 526         // so we try this
5359 12 Apr 19 nicklas 527         dna.volume = protocol.DNATargetVolume;
5359 12 Apr 19 nicklas 528         dna.water = 0;
6219 20 Apr 21 nicklas 529         dna.usedQuantity = dna.volume * dna.conc / 1000;
5359 12 Apr 19 nicklas 530       }
5359 12 Apr 19 nicklas 531       
5359 12 Apr 19 nicklas 532       dna.notEnoughQuantity = dna.remainingQuantity < dna.usedQuantity || dna.usedQuantity < protocol.DNAMinimalAmount;
5359 12 Apr 19 nicklas 533       if (dna.notEnoughQuantity) 
5359 12 Apr 19 nicklas 534       {
5359 12 Apr 19 nicklas 535         remarks[remarks.length] = '<span class="flag">Not enough quantity</span>';
5359 12 Apr 19 nicklas 536       }
5359 12 Apr 19 nicklas 537       else if (dna.usedQuantity < protocol.DNATargetAmount)
5359 12 Apr 19 nicklas 538       {
5359 12 Apr 19 nicklas 539         remarks[remarks.length] = Numbers.formatNumber(dna.usedQuantity * 1000, 0) + 'ng';
5359 12 Apr 19 nicklas 540       }
5359 12 Apr 19 nicklas 541       
5359 12 Apr 19 nicklas 542       Doc.element('dnaVolume.'+dna.id).innerHTML = dna.notEnoughQuantity ? '' : Numbers.formatNumber(dna.volume, 1);
5359 12 Apr 19 nicklas 543       Doc.element('dnaWater.'+dna.id).innerHTML = dna.notEnoughQuantity ? '' : (dna.water > 0 ? Numbers.formatNumber(dna.water, 1) : '—');
5359 12 Apr 19 nicklas 544       Doc.element('remarks.'+dna.id).innerHTML = remarks.join(', ');
5361 15 Apr 19 nicklas 545       Doc.addOrRemoveClass('dnaRow.'+dna.id, 'not-enough-quantity', dna.notEnoughQuantity);
5359 12 Apr 19 nicklas 546     }
5361 15 Apr 19 nicklas 547     normalize.normalizedPlateOnChange();
5359 12 Apr 19 nicklas 548   }
5359 12 Apr 19 nicklas 549   
6726 04 May 22 nicklas 550   normalize.insertEmpty = function(qiacubePosition, showLabelColumn)
5359 12 Apr 19 nicklas 551   {
5359 12 Apr 19 nicklas 552     var html = '<tr class="highlight empty">';
5359 12 Apr 19 nicklas 553     html += '<td class="extract"></td>';
6726 04 May 22 nicklas 554     if (showLabelColumn) html += '<td class="label"></td>';
5359 12 Apr 19 nicklas 555     html += '<td class="qiacubepos">'+qiacubePosition+'</td>';
5359 12 Apr 19 nicklas 556     html += '<td class="box"></td>';
6219 20 Apr 21 nicklas 557     html += '<td class="conc"></td>';
5359 12 Apr 19 nicklas 558     html += '<td class="remain"></td>';
5359 12 Apr 19 nicklas 559     html += '<td class="volume"></td>';
5359 12 Apr 19 nicklas 560     html += '<td class="water"></td>';
5361 15 Apr 19 nicklas 561     html += '<td class="plate"></td>';
5359 12 Apr 19 nicklas 562     html += '<td class="remarks">Not selected for pre-normalization</td>';
5359 12 Apr 19 nicklas 563     html += '</tr>'
5359 12 Apr 19 nicklas 564     return html;
5359 12 Apr 19 nicklas 565   }
5359 12 Apr 19 nicklas 566   
5359 12 Apr 19 nicklas 567   normalize.printVersion = function()
5359 12 Apr 19 nicklas 568   {
5359 12 Apr 19 nicklas 569     Wizard.hideGoNextConfirmation();
5359 12 Apr 19 nicklas 570     Doc.removeClass('gonext', 'disabled');
5359 12 Apr 19 nicklas 571     var reportName = 'DNA Normalization Protocol';
5359 12 Apr 19 nicklas 572     var printNote = '<b>Note!</b> For better printing set page orientation to <i>portrait</i>.';
5359 12 Apr 19 nicklas 573     Reggie.openPrintWindow('full-protocol', reportName, 'portrait', printNote, '../', 'normalize_extract.css');
5359 12 Apr 19 nicklas 574   }
5359 12 Apr 19 nicklas 575
5359 12 Apr 19 nicklas 576   normalize.validateStep2 = function(event)
5449 27 May 19 nicklas 577   {
5449 27 May 19 nicklas 578     var valid = protocolIsValid;
5449 27 May 19 nicklas 579     if (!valid) event.preventDefault();
5449 27 May 19 nicklas 580   }
5359 12 Apr 19 nicklas 581
5359 12 Apr 19 nicklas 582   normalize.initializeStep3 = function()
5359 12 Apr 19 nicklas 583   {
5359 12 Apr 19 nicklas 584     var frm = document.forms['reggie'];
5359 12 Apr 19 nicklas 585     Wizard.setCurrentStep(3);
5359 12 Apr 19 nicklas 586     Doc.show('goregister');
5359 12 Apr 19 nicklas 587     Doc.show('gocancel');
5359 12 Apr 19 nicklas 588     Events.sendChangeEvent('normalizationDate');
5359 12 Apr 19 nicklas 589     frm.normalizationDate.focus();
5359 12 Apr 19 nicklas 590   }
5359 12 Apr 19 nicklas 591   
5359 12 Apr 19 nicklas 592   normalize.submit = function()
5359 12 Apr 19 nicklas 593   {
5359 12 Apr 19 nicklas 594     var frm = document.forms['reggie'];
5359 12 Apr 19 nicklas 595     
5359 12 Apr 19 nicklas 596     var submitInfo = {};
5359 12 Apr 19 nicklas 597     submitInfo.normalizationProtocol = parseInt(frm.normalizationProtocol.value, 10);
5359 12 Apr 19 nicklas 598     submitInfo.normalizationDate = frm.normalizationDate.value;
5359 12 Apr 19 nicklas 599     submitInfo.normalizationOperator = frm.normalizationOperator.value;
5361 15 Apr 19 nicklas 600     submitInfo.normalizedPlate = parseInt(frm.normalizedPlate.value, 10);
5359 12 Apr 19 nicklas 601     
5359 12 Apr 19 nicklas 602     var dnaAliquots = [];
5359 12 Apr 19 nicklas 603     for (var i=0; i < selectedDna.length; i++)
5359 12 Apr 19 nicklas 604     {
5359 12 Apr 19 nicklas 605       var dna = selectedDna[i];
5359 12 Apr 19 nicklas 606       if (!dna.notEnoughQuantity)
5359 12 Apr 19 nicklas 607       {
5359 12 Apr 19 nicklas 608         var normalizedDna = {};
5359 12 Apr 19 nicklas 609         normalizedDna.parentId = dna.id;
5359 12 Apr 19 nicklas 610         normalizedDna.name = dna.nextAliquotName;
5359 12 Apr 19 nicklas 611
5359 12 Apr 19 nicklas 612         normalizedDna.usedQuantity = dna.usedQuantity; // µg
6219 20 Apr 21 nicklas 613         normalizedDna.conc = 1000 * dna.usedQuantity / (dna.volume+dna.water); // ng/µl
6219 20 Apr 21 nicklas 614         normalizedDna.ConcType = dna.NDConc ? 'ND_CONC' : 'QUBIT_CONC';
5359 12 Apr 19 nicklas 615         
5361 15 Apr 19 nicklas 616         normalizedDna.row = dna.well.row;
5361 15 Apr 19 nicklas 617         normalizedDna.column = dna.well.column;
5361 15 Apr 19 nicklas 618         
5359 12 Apr 19 nicklas 619         dnaAliquots[dnaAliquots.length] = normalizedDna;
5359 12 Apr 19 nicklas 620       }
5359 12 Apr 19 nicklas 621       else
5359 12 Apr 19 nicklas 622       {
5359 12 Apr 19 nicklas 623         var flaggedDna = {};
5359 12 Apr 19 nicklas 624         flaggedDna.id = dna.id;
5359 12 Apr 19 nicklas 625         flaggedDna.flag = 'NotEnoughRemainingQuantity';
5359 12 Apr 19 nicklas 626         dnaAliquots[dnaAliquots.length] = flaggedDna;
5359 12 Apr 19 nicklas 627       }
5359 12 Apr 19 nicklas 628     }
5359 12 Apr 19 nicklas 629     
5359 12 Apr 19 nicklas 630     submitInfo.dnaAliquots = dnaAliquots;
5359 12 Apr 19 nicklas 631
5359 12 Apr 19 nicklas 632     var url = '../Extraction.servlet?ID='+App.getSessionId();
5359 12 Apr 19 nicklas 633     url += '&cmd=RegisterNormalizedDNA';
5359 12 Apr 19 nicklas 634     Wizard.showLoadingAnimation('Performing registration...');
5359 12 Apr 19 nicklas 635     Wizard.asyncJsonRequest(url, normalize.submissionResults, 'POST', JSON.stringify(submitInfo));
5359 12 Apr 19 nicklas 636   }
5359 12 Apr 19 nicklas 637
5359 12 Apr 19 nicklas 638   normalize.submissionResults = function(response)
5359 12 Apr 19 nicklas 639   {
5359 12 Apr 19 nicklas 640     Wizard.showFinalMessage(response.messages);
5359 12 Apr 19 nicklas 641     Doc.show('gorestart');
5359 12 Apr 19 nicklas 642   }
5359 12 Apr 19 nicklas 643
5359 12 Apr 19 nicklas 644   return normalize;
5359 12 Apr 19 nicklas 645 }();
5359 12 Apr 19 nicklas 646
5359 12 Apr 19 nicklas 647 Doc.onLoad(DnaNormalize.initPage);
5359 12 Apr 19 nicklas 648