extensions/net.sf.basedb.meludi/trunk/resources/libprep/select_dna.js

Code
Comments
Other
Rev Date Author Line
3520 01 Oct 15 olle 1 var SelectDnaRefCode = function()
3449 28 Jul 15 olle 2 {
3449 28 Jul 15 olle 3   var selectdna = {};
3449 28 Jul 15 olle 4   var barcodesByName = [];
3449 28 Jul 15 olle 5   
3449 28 Jul 15 olle 6   var EXTERNAL_DNA_NAME = 'External.d';
3449 28 Jul 15 olle 7   var debug = 0;
4200 01 Nov 16 olle 8   var startPlatePrefix;
3449 28 Jul 15 olle 9   
3449 28 Jul 15 olle 10   var graphics;
3449 28 Jul 15 olle 11   var pen;
3449 28 Jul 15 olle 12   
3449 28 Jul 15 olle 13   var quantitiesAreValid = false;
3449 28 Jul 15 olle 14   var subtypeDna;
3449 28 Jul 15 olle 15   var subtypeDnaNormalized
3449 28 Jul 15 olle 16
3449 28 Jul 15 olle 17   // Page initialization
3449 28 Jul 15 olle 18   selectdna.initPage = function()
3449 28 Jul 15 olle 19   {
3449 28 Jul 15 olle 20     // Step 1
3449 28 Jul 15 olle 21     Events.addEventHandler('step-1', 'wizard-validate', selectdna.validateStep1);
3449 28 Jul 15 olle 22
3449 28 Jul 15 olle 23     Events.addEventHandler('pool_schema', 'change', selectdna.poolSchemaOnChange);
3449 28 Jul 15 olle 24     Events.addEventHandler('barcode_variant', 'change', selectdna.barcodeVariantOnChange);
3449 28 Jul 15 olle 25     Events.addEventHandler('quantity_regular', 'change', selectdna.quantityOnChange);
3449 28 Jul 15 olle 26     Events.addEventHandler('quantity_qc', 'change', selectdna.quantityOnChange);
3449 28 Jul 15 olle 27     Events.addEventHandler('quantity_regular', 'keypress', Events.numberOnly);
3449 28 Jul 15 olle 28     Events.addEventHandler('quantity_qc', 'keypress', Events.numberOnly);
3449 28 Jul 15 olle 29     
3449 28 Jul 15 olle 30     Events.addEventHandler('warning_quantity', 'change', selectdna.warningLevelOnChange);
3449 28 Jul 15 olle 31     Events.addEventHandler('warning_quality_score', 'change', selectdna.warningLevelOnChange);
3449 28 Jul 15 olle 32     Events.addEventHandler('warning_quantity', 'keypress', Events.numberOnly);
3449 28 Jul 15 olle 33     Events.addEventHandler('warning_quality_score', 'keypress', Events.numberOnly);
3449 28 Jul 15 olle 34     
3449 28 Jul 15 olle 35     Events.addEventHandler('location', 'click', selectdna.toggleInfo);
3449 28 Jul 15 olle 36     Events.addEventHandler('quantity', 'click', selectdna.toggleInfo);
3449 28 Jul 15 olle 37     Events.addEventHandler('quality-score', 'click', selectdna.toggleInfo);
3449 28 Jul 15 olle 38     Events.addEventHandler('qubitconc', 'click', selectdna.toggleInfo);
3449 28 Jul 15 olle 39     Events.addEventHandler('volumes', 'click', selectdna.toggleInfo);
3449 28 Jul 15 olle 40     Events.addEventHandler('qiacube-date', 'click', selectdna.toggleInfo);
3449 28 Jul 15 olle 41     
3449 28 Jul 15 olle 42     Events.addEventHandler('pool-row', 'click', selectdna.togglePool);
3449 28 Jul 15 olle 43     Events.addEventHandler('pool-row', 'mouseover', selectdna.highlightPool);
3449 28 Jul 15 olle 44     Events.addEventHandler('pool-row', 'mouseout', selectdna.highlightPool);
3449 28 Jul 15 olle 45     
3449 28 Jul 15 olle 46     Buttons.addClickHandler('btnLoadFromFile', selectdna.selectFile);
3449 28 Jul 15 olle 47     Buttons.addClickHandler('btnAutoSelect', selectdna.autoSelect);
3449 28 Jul 15 olle 48     Buttons.addClickHandler('btnManualSelect', selectdna.manualSelect);
3449 28 Jul 15 olle 49     Events.addEventHandler('plate', 'base-selected', selectdna.manuallySelected);
3449 28 Jul 15 olle 50     Buttons.addClickHandler('btnStratagene', selectdna.setToStratagene);
3449 28 Jul 15 olle 51     Buttons.addClickHandler('btnExternal', selectdna.setToExternal);
3449 28 Jul 15 olle 52     Buttons.addClickHandler('btnToggleQc', selectdna.toggleQc);
3449 28 Jul 15 olle 53     Buttons.addClickHandler('btnComment', selectdna.commentSelected);
3449 28 Jul 15 olle 54     Buttons.addClickHandler('btnCutSelected', selectdna.cutSelected);
3449 28 Jul 15 olle 55     Buttons.addClickHandler('btnCopySelected', selectdna.copySelected);
3449 28 Jul 15 olle 56     Buttons.addClickHandler('btnPasteToSelected', selectdna.pasteToSelected);
3449 28 Jul 15 olle 57     Buttons.addClickHandler('btnSwitch', selectdna.switchSelected);
3449 28 Jul 15 olle 58     
3449 28 Jul 15 olle 59     Events.addEventHandler('iconSpecialSelect', 'click', selectdna.toggleSpecialSelect);
3449 28 Jul 15 olle 60     Events.addEventHandler('plate', 'mouseup', selectdna.contextEvent);
3449 28 Jul 15 olle 61     Events.addEventHandler('plate', 'contextmenu', selectdna.contextEvent);
3449 28 Jul 15 olle 62     Events.addEventHandler('mnuComment', 'click', selectdna.commentSelected);
3449 28 Jul 15 olle 63     Events.addEventHandler('mnuToggleQc', 'click', selectdna.toggleQc);
3449 28 Jul 15 olle 64     Events.addEventHandler('mnuCutSelected', 'click', selectdna.cutSelected);
3449 28 Jul 15 olle 65     Events.addEventHandler('mnuCopySelected', 'click', selectdna.copySelected);
3449 28 Jul 15 olle 66     Events.addEventHandler('mnuPasteToSelected', 'click', selectdna.pasteToSelected);
3449 28 Jul 15 olle 67     Events.addEventHandler('mnuSwitch', 'click', selectdna.switchSelected);
3449 28 Jul 15 olle 68     Events.addEventHandler('mnuCaseSummary', 'click', selectdna.showCaseSummary);
3449 28 Jul 15 olle 69     Events.addEventHandler('mnuFlagLowQualityScore', 'click', selectdna.flagSelected);
3449 28 Jul 15 olle 70     Events.addEventHandler('mnuFlagNotEnoughRemainingQuantity', 'click', selectdna.flagSelected);
3449 28 Jul 15 olle 71     Events.addEventHandler('mnuFlagOther', 'click', selectdna.flagSelected);
3449 28 Jul 15 olle 72
3449 28 Jul 15 olle 73     Events.addEventHandler('flaggedDna', 'click', selectdna.showFlaggedDna);
3449 28 Jul 15 olle 74     
3449 28 Jul 15 olle 75     // Barcode wells
3449 28 Jul 15 olle 76     var wells = document.getElementsByClassName('barcode-well');
3449 28 Jul 15 olle 77     for (var wellNo = 0; wellNo < wells.length; wellNo++)
3449 28 Jul 15 olle 78     {
3449 28 Jul 15 olle 79       Events.addEventHandler(wells[wellNo], 'click', selectdna.selectBarcode);
3449 28 Jul 15 olle 80     }
3449 28 Jul 15 olle 81     Events.addEventHandler('select-barcode', 'click', selectdna.barcodeSelected);
3449 28 Jul 15 olle 82     Events.addEventHandler('wizard', 'click', selectdna.hideBarcodeSelection);
3449 28 Jul 15 olle 83
3449 28 Jul 15 olle 84     // Navigation
3449 28 Jul 15 olle 85     Buttons.addClickHandler('gocancel', Wizard.cancelWizard);
3449 28 Jul 15 olle 86     Buttons.addClickHandler('gorestart', Wizard.restartWizard);
3449 28 Jul 15 olle 87     Buttons.addClickHandler('gonext', Wizard.goNextOnClick);
3449 28 Jul 15 olle 88     Buttons.addClickHandler('goregister', Wizard.goRegister);
3449 28 Jul 15 olle 89     
3449 28 Jul 15 olle 90     // Final registration
3449 28 Jul 15 olle 91     Events.addEventHandler('wizard', 'wizard-submit', selectdna.submit);
3449 28 Jul 15 olle 92     
3449 28 Jul 15 olle 93     var isNeoPrep = Data.int('page-data', 'is-neoprep');
3449 28 Jul 15 olle 94 /*
3449 28 Jul 15 olle 95     TOTAL_VOLUME = isNeoPrep ? 45 : 50; // µl
3449 28 Jul 15 olle 96 */
3449 28 Jul 15 olle 97     TOTAL_VOLUME = isNeoPrep ? 45 : 10; // µl
3449 28 Jul 15 olle 98     MINIMAL_DNA_VOLUME = 1.0; // µl
4200 01 Nov 16 olle 99
4200 01 Nov 16 olle 100     // Load configuration
4200 01 Nov 16 olle 101     selectdna.loadConfiguration();
4200 01 Nov 16 olle 102   }
4200 01 Nov 16 olle 103
4200 01 Nov 16 olle 104   selectdna.loadConfiguration = function()
4200 01 Nov 16 olle 105   {
4200 01 Nov 16 olle 106     var url = '../Session.servlet?ID='+App.getSessionId();
4200 01 Nov 16 olle 107     url += '&cmd=GetConfiguration';
4200 01 Nov 16 olle 108     var request = Ajax.getXmlHttpRequest();
4200 01 Nov 16 olle 109     request.open("GET", url, true);
4200 01 Nov 16 olle 110     Ajax.setReadyStateHandler(request, selectdna.onConfiguration, selectdna.onConfiguration);
4200 01 Nov 16 olle 111     request.send(null);
4200 01 Nov 16 olle 112   }
4200 01 Nov 16 olle 113
4200 01 Nov 16 olle 114   selectdna.onConfiguration = function(request)
4200 01 Nov 16 olle 115   {
4200 01 Nov 16 olle 116     if (debug)
4200 01 Nov 16 olle 117     {
4200 01 Nov 16 olle 118       App.debug(Strings.encodeTags(request.responseText));
4200 01 Nov 16 olle 119     }
4200 01 Nov 16 olle 120
4200 01 Nov 16 olle 121     var response;
4200 01 Nov 16 olle 122     var error = false;
4200 01 Nov 16 olle 123     try
4200 01 Nov 16 olle 124     {
4200 01 Nov 16 olle 125       response = JSON.parse(request.responseText);
4200 01 Nov 16 olle 126       if (response.status != 'ok')
4200 01 Nov 16 olle 127       {
4200 01 Nov 16 olle 128         error = response.message || response.stacktrace || 'Unexpected error';
4200 01 Nov 16 olle 129       }
4200 01 Nov 16 olle 130     }
4200 01 Nov 16 olle 131     catch (ex)
4200 01 Nov 16 olle 132     {
4200 01 Nov 16 olle 133       error = ex;
4200 01 Nov 16 olle 134     }
4200 01 Nov 16 olle 135     if (error) App.debug(error);
4200 01 Nov 16 olle 136
4200 01 Nov 16 olle 137     // Get configuration result
4200 01 Nov 16 olle 138     var conf = response.configuration;
4200 01 Nov 16 olle 139     // Check for start plate prefix
4200 01 Nov 16 olle 140     startPlatePrefix = conf.startPlateItemPrefix;
4200 01 Nov 16 olle 141
4200 01 Nov 16 olle 142     // Continue with initializing info
3449 28 Jul 15 olle 143     var url = '../Dna.servlet?ID='+App.getSessionId();
3449 28 Jul 15 olle 144     url += '&cmd=GetStratagene';
3449 28 Jul 15 olle 145     Wizard.asyncJsonRequest(url, selectdna.stratageneLoaded);
3449 28 Jul 15 olle 146
3449 28 Jul 15 olle 147     var url = '../Dna.servlet?ID='+App.getSessionId();
3449 28 Jul 15 olle 148     url += '&cmd=GetNextAutoGeneratedPlateName';
3449 28 Jul 15 olle 149     url += '&bioPlateType=' + (isNeoPrep ? 'NEOPREP' : 'DNA');
4200 01 Nov 16 olle 150     url += '&bioPlatePrefix=' + startPlatePrefix;
3449 28 Jul 15 olle 151     Wizard.showLoadingAnimation('Loading next '+(isNeoPrep ? 'NeoPrep' : 'DNA') + ' plate');
3449 28 Jul 15 olle 152     Wizard.asyncJsonRequest(url, selectdna.nextPlateNameLoaded);
3449 28 Jul 15 olle 153     
3449 28 Jul 15 olle 154     var url = '../LibPrep.servlet?ID='+App.getSessionId();
3449 28 Jul 15 olle 155     url += '&cmd=GetAllBarcodeInfo';
3449 28 Jul 15 olle 156     Wizard.asyncJsonRequest(url, selectdna.barcodesLoaded);
3449 28 Jul 15 olle 157   }
3449 28 Jul 15 olle 158
3449 28 Jul 15 olle 159   selectdna.barcodesLoaded = function(response)
3449 28 Jul 15 olle 160   {
3449 28 Jul 15 olle 161     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 162     var isNeoPrep = Data.int('page-data', 'is-neoprep');
3449 28 Jul 15 olle 163
3449 28 Jul 15 olle 164     var barcodes = response.barcodes;
3449 28 Jul 15 olle 165     var selectBarcodeHtml = '';
3449 28 Jul 15 olle 166     for (var i = 0; i < barcodes.length; i++)
3449 28 Jul 15 olle 167     {
3449 28 Jul 15 olle 168       if (i % 8 == 0 && i > 0)
3449 28 Jul 15 olle 169       {
3449 28 Jul 15 olle 170         selectBarcodeHtml += '<div class="menuseparator"></div>';
3449 28 Jul 15 olle 171       }
3449 28 Jul 15 olle 172       var barcode = barcodes[i];
3449 28 Jul 15 olle 173       barcodesByName[barcode.name] = barcode;
3449 28 Jul 15 olle 174       selectBarcodeHtml += '<div class="menuitem interactable enabled" id="bc-'+barcode.id+'" data-barcode-name="'+Strings.encodeTags(barcode.name)+'">';
3449 28 Jul 15 olle 175       selectBarcodeHtml += Strings.encodeTags(barcode.name)+'</div>';
3449 28 Jul 15 olle 176     }
3449 28 Jul 15 olle 177     Doc.element('select-barcode-all').innerHTML = selectBarcodeHtml;
3449 28 Jul 15 olle 178     
3449 28 Jul 15 olle 179     selectdna.quantityOnChange();
3449 28 Jul 15 olle 180     selectdna.warningLevelOnChange();    
3449 28 Jul 15 olle 181     
3449 28 Jul 15 olle 182     // Init plate, pool schema and barcode variants
3449 28 Jul 15 olle 183     graphics = new jsGraphics(Doc.element('canvas'));
3449 28 Jul 15 olle 184     pen = new jsPen(new jsColor('#2288AA'), 2);
3449 28 Jul 15 olle 185     var columns = isNeoPrep ? 2 : 12;
3449 28 Jul 15 olle 186     var rows = 8;
3449 28 Jul 15 olle 187     var schema = PoolSchema.initList(frm.pool_schema, null, isNeoPrep ? 'neoprep' : 'manual');
3449 28 Jul 15 olle 188     Plate.init(rows, columns, schema, WellPainter);
3449 28 Jul 15 olle 189     Events.sendChangeEvent(frm.pool_schema);
3449 28 Jul 15 olle 190     // Set default for showing info for plate well
3449 28 Jul 15 olle 191     selectdna.setDefaultInfo('location');
3449 28 Jul 15 olle 192     selectdna.setDefaultInfo('quantity');
3449 28 Jul 15 olle 193     selectdna.setDefaultInfo('quality-score');
3449 28 Jul 15 olle 194     selectdna.setDefaultInfo('qubitconc');
3449 28 Jul 15 olle 195     selectdna.setDefaultInfo('volumes');
3449 28 Jul 15 olle 196     selectdna.setDefaultInfo('qiacube-date');
3449 28 Jul 15 olle 197     //
3449 28 Jul 15 olle 198     Doc.show('step-1');
3449 28 Jul 15 olle 199     Doc.show('gocancel');
3449 28 Jul 15 olle 200     Doc.show('goregister');
3449 28 Jul 15 olle 201     Wizard.setNoConfirmOnFirstStep(false);
3449 28 Jul 15 olle 202     Wizard.keepSessionAlive();
3449 28 Jul 15 olle 203   }
3449 28 Jul 15 olle 204   
3449 28 Jul 15 olle 205   selectdna.stratageneLoaded = function(response)
3449 28 Jul 15 olle 206   {
3449 28 Jul 15 olle 207     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 208     var stratagene = response.stratagene;
3449 28 Jul 15 olle 209
3449 28 Jul 15 olle 210     for (var i = 0; i < stratagene.length; i++)
3449 28 Jul 15 olle 211     {
3449 28 Jul 15 olle 212       var s = stratagene[i];
3449 28 Jul 15 olle 213       var name = s.name;
3449 28 Jul 15 olle 214       if (s.bioWell)
3449 28 Jul 15 olle 215       {
3449 28 Jul 15 olle 216         name += ' -- ' + s.bioWell.bioPlate.name + ' ('+s.bioWell.location + ')';
3449 28 Jul 15 olle 217       }
3449 28 Jul 15 olle 218       frm.stratagene[frm.stratagene.length] = new Option(name, s.name);
3449 28 Jul 15 olle 219     }
3449 28 Jul 15 olle 220   }
3449 28 Jul 15 olle 221
3449 28 Jul 15 olle 222   selectdna.nextPlateNameLoaded = function(response)
3449 28 Jul 15 olle 223   {
3449 28 Jul 15 olle 224     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 225     Plate.name = response.name;
3449 28 Jul 15 olle 226     Doc.element('plateName').innerHTML = Strings.encodeTags(Plate.name);
3449 28 Jul 15 olle 227   }
3449 28 Jul 15 olle 228   
3449 28 Jul 15 olle 229   selectdna.quantityOnChange = function(event)
3449 28 Jul 15 olle 230   {
3449 28 Jul 15 olle 231     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 232     quantitiesAreValid = false;
3449 28 Jul 15 olle 233     
3449 28 Jul 15 olle 234     var qRegular = parseFloat(frm.quantity_regular.value);
3449 28 Jul 15 olle 235     if (!(qRegular > 0))
3449 28 Jul 15 olle 236     {
3449 28 Jul 15 olle 237       Wizard.setInputStatus('quantities', 'invalid', 'Amount must be ≥ 0.');
3449 28 Jul 15 olle 238       return;
3449 28 Jul 15 olle 239     }
3449 28 Jul 15 olle 240     var qQc = parseFloat(frm.quantity_qc.value);
3449 28 Jul 15 olle 241     if (!(qQc > qRegular))
3449 28 Jul 15 olle 242     {
3449 28 Jul 15 olle 243       Wizard.setInputStatus('quantities', 'invalid', 'Amount QC must be &gt; ' + qRegular + '.');
3449 28 Jul 15 olle 244       return;
3449 28 Jul 15 olle 245     }
3449 28 Jul 15 olle 246     
3449 28 Jul 15 olle 247     quantitiesAreValid = true;
3449 28 Jul 15 olle 248     QUANTITY_REGULAR = qRegular;
3449 28 Jul 15 olle 249     QUANTITY_QC = qQc;
3449 28 Jul 15 olle 250     
3449 28 Jul 15 olle 251     Wizard.setInputStatus('quantities', 'valid');
3449 28 Jul 15 olle 252     if (event) Plate.paint(Plate.getWells());
3449 28 Jul 15 olle 253   }
3449 28 Jul 15 olle 254
3449 28 Jul 15 olle 255   selectdna.warningLevelOnChange = function(event)
3449 28 Jul 15 olle 256   {
3449 28 Jul 15 olle 257     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 258
3449 28 Jul 15 olle 259     var wQuantity = parseFloat(frm.warning_quantity.value);
3449 28 Jul 15 olle 260     if (!(wQuantity > 0))
3449 28 Jul 15 olle 261     {
3449 28 Jul 15 olle 262       Wizard.setInputStatus('warnings', 'invalid', 'Remaining quantity must be ≥ 0.');
3449 28 Jul 15 olle 263       return;
3449 28 Jul 15 olle 264     }
3449 28 Jul 15 olle 265     var wQualityScore = parseFloat(frm.warning_quality_score.value);
3449 28 Jul 15 olle 266 /*
3449 28 Jul 15 olle 267     if (!(wQualityScore > 0))
3449 28 Jul 15 olle 268     {
3449 28 Jul 15 olle 269       Wizard.setInputStatus('warnings', 'invalid', 'RQS/RIN must be ≥ 0.');
3449 28 Jul 15 olle 270       return;
3449 28 Jul 15 olle 271     }
3449 28 Jul 15 olle 272 */
3449 28 Jul 15 olle 273     
3449 28 Jul 15 olle 274     LOW_QUANTITY_WARNING_LIMIT = wQuantity;
3449 28 Jul 15 olle 275     QUALITY_SCORE_WARNING_LIMIT = wQualityScore;
3449 28 Jul 15 olle 276     
3449 28 Jul 15 olle 277     Wizard.setInputStatus('warnings', 'valid');
3449 28 Jul 15 olle 278     if (event) Plate.paint(Plate.getWells());
3449 28 Jul 15 olle 279   }
3449 28 Jul 15 olle 280   
3449 28 Jul 15 olle 281   selectdna.poolSchemaOnChange = function()
3449 28 Jul 15 olle 282   {
3449 28 Jul 15 olle 283     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 284     var schema = PoolSchema.getById(frm.pool_schema.value);
3449 28 Jul 15 olle 285     Plate.setPoolSchema(schema);
3449 28 Jul 15 olle 286     
3449 28 Jul 15 olle 287     var isNeoPrep = Data.int('page-data', 'is-neoprep');
3449 28 Jul 15 olle 288     if (isNeoPrep)
3449 28 Jul 15 olle 289     {
3449 28 Jul 15 olle 290       PoolSchema.buildPoolTableRow(schema, Plate.columns, true, '<td class="barcode-fill barcode-left"></td>', '<th></th><td class="barcode-fill barcode-right"></td>');
3449 28 Jul 15 olle 291       PoolSchema.initVariantList(frm.barcode_variant, schema);
3449 28 Jul 15 olle 292       Events.sendChangeEvent(frm.barcode_variant);
3449 28 Jul 15 olle 293     }
3449 28 Jul 15 olle 294     else
3449 28 Jul 15 olle 295     {
3449 28 Jul 15 olle 296       PoolSchema.buildPoolTableRow(schema, Plate.columns, true);
3449 28 Jul 15 olle 297       Plate.paint(Plate.getWells());
3449 28 Jul 15 olle 298     }
3449 28 Jul 15 olle 299   }
3449 28 Jul 15 olle 300   
3449 28 Jul 15 olle 301   selectdna.barcodeVariantOnChange = function()
3449 28 Jul 15 olle 302   {
3449 28 Jul 15 olle 303     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 304     var schema = PoolSchema.getById(frm.pool_schema.value);
3449 28 Jul 15 olle 305     var barcodeVariant = PoolSchema.getBarcodeVariantByName(schema, frm.barcode_variant.value);
3449 28 Jul 15 olle 306     
3449 28 Jul 15 olle 307     selectdna.assignSchemaDefinedBarcodeVariant(schema, barcodeVariant);
3449 28 Jul 15 olle 308     WellPainter.barcodeVariant = barcodeVariant;
3449 28 Jul 15 olle 309     Plate.paint(Plate.getWells());
3449 28 Jul 15 olle 310   }
3449 28 Jul 15 olle 311
3449 28 Jul 15 olle 312   selectdna.assignSchemaDefinedBarcodeVariant = function(schema, barcodeVariant)
3449 28 Jul 15 olle 313   {
3449 28 Jul 15 olle 314     var wells = Plate.getWells();
3449 28 Jul 15 olle 315     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 316     {
3449 28 Jul 15 olle 317       var well = wells[i];
3449 28 Jul 15 olle 318
3449 28 Jul 15 olle 319       var indexSet = barcodeVariant ? barcodeVariant.indexSets[well.column] : null;
3449 28 Jul 15 olle 320       var barcode = null;
3449 28 Jul 15 olle 321       if (indexSet)
3449 28 Jul 15 olle 322       {
3449 28 Jul 15 olle 323         var barcodeName = indexSet.barcodes[well.row];
3449 28 Jul 15 olle 324         barcode = barcodesByName[barcodeName];
3449 28 Jul 15 olle 325       }
3449 28 Jul 15 olle 326       well.barcode = barcode;
3449 28 Jul 15 olle 327       well.defaultBarcode = barcode;
3449 28 Jul 15 olle 328       well.duplicate = false;
3449 28 Jul 15 olle 329     }
3449 28 Jul 15 olle 330   }
3449 28 Jul 15 olle 331
3449 28 Jul 15 olle 332   var currentWell;
3449 28 Jul 15 olle 333   var lastSelectedBarcode;
3449 28 Jul 15 olle 334   selectdna.selectBarcode = function(event)
3449 28 Jul 15 olle 335   {
3449 28 Jul 15 olle 336     var row = Data.int(event.currentTarget, 'row');
3449 28 Jul 15 olle 337     var column = Data.int(event.currentTarget, 'col');
3449 28 Jul 15 olle 338
3449 28 Jul 15 olle 339     // Locate the barcode selection div so that the current
3449 28 Jul 15 olle 340     // barcode is positioned next to the current mouse position
3449 28 Jul 15 olle 341     // Initially set it to the right of the mouse so that the
3449 28 Jul 15 olle 342     // center is vertically aligned
3449 28 Jul 15 olle 343     currentWell = Plate.getWell(row, column);
3449 28 Jul 15 olle 344     var scroll = 0;
3449 28 Jul 15 olle 345
3449 28 Jul 15 olle 346     // Reset 'current' selection
3449 28 Jul 15 olle 347     var menu = Doc.element('select-barcode');
3449 28 Jul 15 olle 348     var selectAll = Doc.element('select-barcode-all');
3449 28 Jul 15 olle 349     for (var i = 0; i <  selectAll.childNodes.length; i++)
3449 28 Jul 15 olle 350     {
3449 28 Jul 15 olle 351       Doc.removeClass(selectAll.childNodes[i], 'current');
3449 28 Jul 15 olle 352     }
3449 28 Jul 15 olle 353     menu.style.display = 'block';
3449 28 Jul 15 olle 354
3449 28 Jul 15 olle 355     var x = event.clientX+1;
3449 28 Jul 15 olle 356     var halfHeight = Math.floor(selectAll.offsetHeight/2)
3449 28 Jul 15 olle 357     var y = event.clientY-halfHeight;
3449 28 Jul 15 olle 358     var scroll = 0;
3449 28 Jul 15 olle 359     var barcodeDiv;
3449 28 Jul 15 olle 360     
3449 28 Jul 15 olle 361     var useBarcode = currentWell.barcode || lastSelectedBarcode;
3449 28 Jul 15 olle 362     if (useBarcode)
3449 28 Jul 15 olle 363     {
3449 28 Jul 15 olle 364       var barcodeDiv = Doc.element('bc-'+useBarcode.id);
3449 28 Jul 15 olle 365       if (!currentWell.barcode && barcodeDiv.nextSibling) barcodeDiv = barcodeDiv.nextSibling;
3449 28 Jul 15 olle 366       // Try to scroll the current barcode so that it's baseline is at the center of the div
3449 28 Jul 15 olle 367       scroll = barcodeDiv.offsetTop + barcodeDiv.offsetHeight - halfHeight;
3449 28 Jul 15 olle 368       if (scroll < 0) 
3449 28 Jul 15 olle 369       {
3449 28 Jul 15 olle 370         // We get a negative scroll for the first few elements, shift the
3449 28 Jul 15 olle 371         // entire selection div down instead
3449 28 Jul 15 olle 372         y -= scroll;
3449 28 Jul 15 olle 373         scroll = 0;
3449 28 Jul 15 olle 374       }
3449 28 Jul 15 olle 375       else if (scroll > selectAll.scrollHeight - selectAll.offsetHeight)
3449 28 Jul 15 olle 376       {
3449 28 Jul 15 olle 377         // We get a too large scroll value for the last few elements, shift
3449 28 Jul 15 olle 378         // the entire selection div up instead
3449 28 Jul 15 olle 379         y -= scroll - (selectAll.scrollHeight - selectAll.offsetHeight);
3449 28 Jul 15 olle 380         scroll = selectAll.scrollHeight - selectAll.offsetHeight;
3449 28 Jul 15 olle 381       }
3449 28 Jul 15 olle 382       if (currentWell.barcode)
3449 28 Jul 15 olle 383       {
3449 28 Jul 15 olle 384         Doc.addClass(barcodeDiv, 'current');
3449 28 Jul 15 olle 385       }
3449 28 Jul 15 olle 386     }
3449 28 Jul 15 olle 387     
3449 28 Jul 15 olle 388     // Default barcode
3449 28 Jul 15 olle 389     if (currentWell.defaultBarcode && currentWell.defaultBarcode != currentWell.barcode)
3449 28 Jul 15 olle 390     {
3449 28 Jul 15 olle 391       var selectDefault = Doc.element('select-barcode-default');
3449 28 Jul 15 olle 392       Data.set(selectDefault, 'barcode-name', currentWell.defaultBarcode.name);
3449 28 Jul 15 olle 393       selectDefault.innerHTML = 'Default: ' + Strings.encodeTags(currentWell.defaultBarcode.name);
3449 28 Jul 15 olle 394       Doc.show('select-barcode-default');
3449 28 Jul 15 olle 395       Doc.show('select-barcode-default-separator');
3449 28 Jul 15 olle 396     }
3449 28 Jul 15 olle 397     else
3449 28 Jul 15 olle 398     {
3449 28 Jul 15 olle 399       Doc.hide('select-barcode-default');
3449 28 Jul 15 olle 400       Doc.hide('select-barcode-default-separator');
3449 28 Jul 15 olle 401     }
3449 28 Jul 15 olle 402     
3449 28 Jul 15 olle 403     // Position the selection div
3449 28 Jul 15 olle 404     selectAll.scrollTop = scroll;
3449 28 Jul 15 olle 405     menu.style.left = (x)+'px';
3449 28 Jul 15 olle 406     menu.style.top = (y)+'px';
3449 28 Jul 15 olle 407     event.stopPropagation();
3449 28 Jul 15 olle 408   }
3449 28 Jul 15 olle 409
3449 28 Jul 15 olle 410   selectdna.barcodeSelected = function(event)
3449 28 Jul 15 olle 411   {
3449 28 Jul 15 olle 412     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 413     var schema = PoolSchema.getById(frm.pool_schema.value);
3449 28 Jul 15 olle 414     var target = event.target;
3449 28 Jul 15 olle 415     if (currentWell)
3449 28 Jul 15 olle 416     {
3449 28 Jul 15 olle 417       lastSelectedBarcode = barcodesByName[Data.get(target, 'barcode-name')];
3449 28 Jul 15 olle 418       currentWell.barcode = lastSelectedBarcode;
3449 28 Jul 15 olle 419       var poolNum = schema.getPoolNumForColumn(currentWell.column);
3449 28 Jul 15 olle 420       selectdna.checkDuplicateBarcode(poolNum);
3449 28 Jul 15 olle 421       Plate.paint(Plate.getWells());
3449 28 Jul 15 olle 422     }
3449 28 Jul 15 olle 423     selectdna.hideBarcodeSelection();
3449 28 Jul 15 olle 424   }
3449 28 Jul 15 olle 425
3449 28 Jul 15 olle 426   selectdna.checkDuplicateBarcode = function(poolNum)
3449 28 Jul 15 olle 427   {
3449 28 Jul 15 olle 428     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 429     var schema = PoolSchema.getById(frm.pool_schema.value);
3449 28 Jul 15 olle 430
3449 28 Jul 15 olle 431     var wells = schema.getWellsInPool(Plate, poolNum);
3449 28 Jul 15 olle 432     var wellByBarcodeName = [];
3449 28 Jul 15 olle 433     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 434     {
3449 28 Jul 15 olle 435       var well = wells[i];
3449 28 Jul 15 olle 436       if (well.barcode)
3449 28 Jul 15 olle 437       {
3449 28 Jul 15 olle 438         if (wellByBarcodeName[well.barcode.name])
3449 28 Jul 15 olle 439         {
3449 28 Jul 15 olle 440           well.duplicate = true;
3449 28 Jul 15 olle 441           wellByBarcodeName[well.barcode.name].duplicate = true;
3449 28 Jul 15 olle 442         }
3449 28 Jul 15 olle 443         else
3449 28 Jul 15 olle 444         {
3449 28 Jul 15 olle 445           wellByBarcodeName[well.barcode.name] = well;
3449 28 Jul 15 olle 446           well.duplicate = false;
3449 28 Jul 15 olle 447         }
3449 28 Jul 15 olle 448       }
3449 28 Jul 15 olle 449     }
3449 28 Jul 15 olle 450   }
3449 28 Jul 15 olle 451
3449 28 Jul 15 olle 452   
3449 28 Jul 15 olle 453   selectdna.hideBarcodeSelection = function()
3449 28 Jul 15 olle 454   {
3449 28 Jul 15 olle 455     Doc.hide('select-barcode');
3449 28 Jul 15 olle 456   }
3449 28 Jul 15 olle 457
3449 28 Jul 15 olle 458   
3449 28 Jul 15 olle 459   /**
3449 28 Jul 15 olle 460     Sets default display of info data for plate wells,
3449 28 Jul 15 olle 461     based on check box values. Assumes the id of the
3449 28 Jul 15 olle 462     check box in question as input.
3449 28 Jul 15 olle 463   */
3449 28 Jul 15 olle 464   selectdna.setDefaultInfo = function(chkbox)
3449 28 Jul 15 olle 465   {
3449 28 Jul 15 olle 466     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 467     var show = frm[chkbox].checked;
3449 28 Jul 15 olle 468     Doc.addOrRemoveClass('plate', 'hide-'+chkbox, !show);
3449 28 Jul 15 olle 469   }
3449 28 Jul 15 olle 470
3449 28 Jul 15 olle 471   selectdna.toggleInfo = function(event)
3449 28 Jul 15 olle 472   {
3449 28 Jul 15 olle 473     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 474     var show = event.currentTarget.checked;
3449 28 Jul 15 olle 475     Doc.addOrRemoveClass('plate', 'hide-'+event.currentTarget.id, !show);
3449 28 Jul 15 olle 476   }
3449 28 Jul 15 olle 477
3449 28 Jul 15 olle 478   /**
3449 28 Jul 15 olle 479     Open a popup dialog for selecting a data files.
3449 28 Jul 15 olle 480   */
3449 28 Jul 15 olle 481   selectdna.selectFile = function()
3449 28 Jul 15 olle 482   {
3449 28 Jul 15 olle 483     Dialogs.openPopup('select_file.jsp?ID='+App.getSessionId(), 'SelectFile', 600, 400);  
3449 28 Jul 15 olle 484   }
3449 28 Jul 15 olle 485
3449 28 Jul 15 olle 486   /**
3449 28 Jul 15 olle 487     Parse a tab-separated data file. The columns must be in the following order:
3449 28 Jul 15 olle 488     0: DNA name
3449 28 Jul 15 olle 489     1: Row letter (A-H)
3449 28 Jul 15 olle 490     2: Column number (1-12)
3449 28 Jul 15 olle 491     3: QC flag (can be empty)
3449 28 Jul 15 olle 492   */
3449 28 Jul 15 olle 493   selectdna.parseDnaFile = function(data)
3449 28 Jul 15 olle 494   {
3449 28 Jul 15 olle 495     var lines = data.split(/[\n\r]+/);
3449 28 Jul 15 olle 496   
3449 28 Jul 15 olle 497     // Load information about all DNA items in a batch (will improve performance)
3449 28 Jul 15 olle 498     var names = [];
3449 28 Jul 15 olle 499     for (var i = 0; i < lines.length; i++)
3449 28 Jul 15 olle 500     {
3449 28 Jul 15 olle 501       var line = lines[i];
3449 28 Jul 15 olle 502       if (line)
3449 28 Jul 15 olle 503       {
3449 28 Jul 15 olle 504         var cols = lines[i].split(/\t/);
3449 28 Jul 15 olle 505         if (cols.length < 3) throw 'On line '+(i+1)+': Too few columns (' + cols.length + ')';
3449 28 Jul 15 olle 506         names[names.length] = cols[0];
3449 28 Jul 15 olle 507       }
3449 28 Jul 15 olle 508     }
3449 28 Jul 15 olle 509     Dna.loadInfoByNames(names);
3449 28 Jul 15 olle 510     
3449 28 Jul 15 olle 511     // Place DNA on the plate
3449 28 Jul 15 olle 512     var duplicates = [];
3449 28 Jul 15 olle 513     for (var i = 0; i < lines.length; i++)
3449 28 Jul 15 olle 514     {
3449 28 Jul 15 olle 515       var line = lines[i];
3449 28 Jul 15 olle 516       if (line)
3449 28 Jul 15 olle 517       {
3449 28 Jul 15 olle 518         var cols = lines[i].split(/\t/);
3449 28 Jul 15 olle 519   
3449 28 Jul 15 olle 520         var dna = Dna.createByName(cols[0]);
3449 28 Jul 15 olle 521         var row =  Meludi.alphaToWell(cols[1].toUpperCase());
3449 28 Jul 15 olle 522         var col =  parseInt(cols[2], 10)-1;
3449 28 Jul 15 olle 523         
3449 28 Jul 15 olle 524         var well = Plate.getWell(row, col);
3449 28 Jul 15 olle 525         if (!well) throw 'On line '+(i+1)+': Invalid plate coordinate ['+cols[1]+','+cols[2]+']';
3449 28 Jul 15 olle 526   
3449 28 Jul 15 olle 527         dna.qc = cols.length >= 4 && cols[3];
3449 28 Jul 15 olle 528         Dna.unflag(dna);
3449 28 Jul 15 olle 529         
3449 28 Jul 15 olle 530         // Check for duplicate DNA on same position (which is an error)
3449 28 Jul 15 olle 531         var pos = 'c'+col+'r'+row;
3449 28 Jul 15 olle 532         if (duplicates[pos])
3449 28 Jul 15 olle 533         {
3449 28 Jul 15 olle 534           well.addDuplicate(dna);
3449 28 Jul 15 olle 535         }
3449 28 Jul 15 olle 536         else
3449 28 Jul 15 olle 537         {
3449 28 Jul 15 olle 538           duplicates[pos] = dna.name;
3449 28 Jul 15 olle 539           well.setExtract(dna);
3449 28 Jul 15 olle 540         }
3449 28 Jul 15 olle 541       }
3449 28 Jul 15 olle 542     }
3449 28 Jul 15 olle 543     
3449 28 Jul 15 olle 544     selectdna.updateNumFlaggedDna();
3449 28 Jul 15 olle 545     
3449 28 Jul 15 olle 546     // Check for replicates on the whole plate and repaint it
3449 28 Jul 15 olle 547     Plate.checkReplicates(null, true);
3449 28 Jul 15 olle 548     Plate.paint(Plate.getWells());
3449 28 Jul 15 olle 549   }
3449 28 Jul 15 olle 550   
3449 28 Jul 15 olle 551   var currentSelected;
3449 28 Jul 15 olle 552   var names = [];
3449 28 Jul 15 olle 553
3449 28 Jul 15 olle 554   /**
3449 28 Jul 15 olle 555     Open a popup dialog for manual selection of DNA.
3449 28 Jul 15 olle 556   */
3449 28 Jul 15 olle 557   selectdna.manualSelect = function(event)
3449 28 Jul 15 olle 558   {
3449 28 Jul 15 olle 559     currentSelected = Plate.getSelected();
3449 28 Jul 15 olle 560     if (currentSelected.length == 0)
3449 28 Jul 15 olle 561     {
3449 28 Jul 15 olle 562       Forms.showNotification(event.currentTarget, 'Please select one or more wells were DNA should be placed.');
3449 28 Jul 15 olle 563       return;
3449 28 Jul 15 olle 564     }
3449 28 Jul 15 olle 565     
3449 28 Jul 15 olle 566     if (subtypeDna == null) subtypeDna = Meludi.getSubtypeInfo('DNA');
3449 28 Jul 15 olle 567 /*
3449 28 Jul 15 olle 568     if (subtypeDnaNormalized == null) subtypeDnaNormalized = Meludi.getSubtypeInfo('DNA_NORMALIZED_ALIQUOT');
3449 28 Jul 15 olle 569 */
3449 28 Jul 15 olle 570   
3449 28 Jul 15 olle 571     var url = '&resetTemporary=1';
3449 28 Jul 15 olle 572 /*
3449 28 Jul 15 olle 573     url += '&tmpfilter:INT:itemSubtype='+subtypeDna.id+'|'+subtypeDnaNormalized.id;
3449 28 Jul 15 olle 574 */
3449 28 Jul 15 olle 575     url += '&tmpfilter:INT:itemSubtype='+subtypeDna.id;
3449 28 Jul 15 olle 576     url += '&tmpfilter:DATE:creationEvent.eventDate='+encodeURIComponent('<>');
3449 28 Jul 15 olle 577     url += '&tmpfilter:FLOAT:remainingQuantity='+encodeURIComponent('>=1');
3449 28 Jul 15 olle 578     url += '&'+encodeURIComponent('tmpfilter:STRING:&childCreationEvents(event.bioMaterial.name)')+'='+encodeURIComponent('<>%.m');
3449 28 Jul 15 olle 579
3449 28 Jul 15 olle 580     Dialogs.selectItem('EXTRACT', 'plate', 1, url);
3449 28 Jul 15 olle 581   }
3449 28 Jul 15 olle 582
3449 28 Jul 15 olle 583   /**
3449 28 Jul 15 olle 584     Callback method for manual selection.
3449 28 Jul 15 olle 585   */
3449 28 Jul 15 olle 586   selectdna.manuallySelected = function(event)
3449 28 Jul 15 olle 587   {
3449 28 Jul 15 olle 588     names[names.length] = event.detail.name;
3449 28 Jul 15 olle 589     
3449 28 Jul 15 olle 590     if (event.detail.remaining == 0 && names.length > 0)
3449 28 Jul 15 olle 591     {
3449 28 Jul 15 olle 592       Dna.loadInfoByNames(names);
3449 28 Jul 15 olle 593       
3449 28 Jul 15 olle 594       for (var i = 0; i < names.length && i < currentSelected.length; i++)
3449 28 Jul 15 olle 595       {
3449 28 Jul 15 olle 596         var well = currentSelected[i];
3449 28 Jul 15 olle 597         var name = names[i];
3449 28 Jul 15 olle 598         
3449 28 Jul 15 olle 599         // Create a new DNA object
3449 28 Jul 15 olle 600         var dna = Dna.createByName(name);
3449 28 Jul 15 olle 601         Dna.unflag(dna);
3449 28 Jul 15 olle 602         well.setExtract(dna);
3449 28 Jul 15 olle 603         well.selected = false;
3449 28 Jul 15 olle 604       }
3449 28 Jul 15 olle 605       
3449 28 Jul 15 olle 606       Plate.checkReplicates();
3449 28 Jul 15 olle 607       Plate.paint(currentSelected);
3449 28 Jul 15 olle 608       selectdna.updateNumFlaggedDna();
3449 28 Jul 15 olle 609       names = [];
3449 28 Jul 15 olle 610     }
3449 28 Jul 15 olle 611   }
3449 28 Jul 15 olle 612
3449 28 Jul 15 olle 613   
3449 28 Jul 15 olle 614   /**
3449 28 Jul 15 olle 615     Let the wizard automatically select among unprocessed DNA items.
3449 28 Jul 15 olle 616   */  
3449 28 Jul 15 olle 617   selectdna.autoSelect = function(event)
3449 28 Jul 15 olle 618   {
3449 28 Jul 15 olle 619     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 620     var wells = Plate.getWells();
3449 28 Jul 15 olle 621     var selected = [];
3449 28 Jul 15 olle 622     var ignore = [];
3449 28 Jul 15 olle 623     var notEmpty = 0;
3449 28 Jul 15 olle 624     
3449 28 Jul 15 olle 625     // Count selected and non-empty wells and keep track of DNA that is already present
3449 28 Jul 15 olle 626     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 627     {
3449 28 Jul 15 olle 628       var well = wells[i];
3449 28 Jul 15 olle 629       if (well.selected) 
3449 28 Jul 15 olle 630       {
3449 28 Jul 15 olle 631         selected[selected.length] = well;
3449 28 Jul 15 olle 632         if (well.extract && !well.hasError()) notEmpty++;
3449 28 Jul 15 olle 633       }
3449 28 Jul 15 olle 634       if (well.extract && well.extract.id)
3449 28 Jul 15 olle 635       {
3449 28 Jul 15 olle 636         ignore[ignore.length] = well.extract.id;
3449 28 Jul 15 olle 637       }
3449 28 Jul 15 olle 638     }
3449 28 Jul 15 olle 639     // Ignore DNA already flagged
3449 28 Jul 15 olle 640     var flagged = Dna.getFlagged();
3449 28 Jul 15 olle 641     for (var i = 0; i < flagged.length; i++)
3449 28 Jul 15 olle 642     {
3449 28 Jul 15 olle 643       var dna = flagged[i];
3449 28 Jul 15 olle 644       if (dna.id) ignore[ignore.length] = dna.id;
3449 28 Jul 15 olle 645     }
3449 28 Jul 15 olle 646     
3449 28 Jul 15 olle 647     if (selected.length == 0)
3449 28 Jul 15 olle 648     {
3449 28 Jul 15 olle 649       Forms.showNotification(event.currentTarget, 'Please select one or more wells were DNA should be placed.');
3449 28 Jul 15 olle 650       return;
3449 28 Jul 15 olle 651     }
3449 28 Jul 15 olle 652       
3449 28 Jul 15 olle 653     if (notEmpty > 0)
3449 28 Jul 15 olle 654     {
3449 28 Jul 15 olle 655       if (!confirm('Replace DNA in ' + notEmpty + ' wells?'))
3449 28 Jul 15 olle 656       {
3449 28 Jul 15 olle 657         return;
3449 28 Jul 15 olle 658       }
3449 28 Jul 15 olle 659     }
3449 28 Jul 15 olle 660       
3449 28 Jul 15 olle 661     var url = 'auto_select_dna.jsp?ID='+App.getSessionId();
3449 28 Jul 15 olle 662     url += '&numToSelect='+selected.length;
3449 28 Jul 15 olle 663     url += '&quantity='+encodeURIComponent(frm.quantity_regular.value);
3449 28 Jul 15 olle 664     url += '&ignore='+ignore.join(',');
3449 28 Jul 15 olle 665     Dialogs.openPopup(url, 'AutoSelectDNA', 750, 500);
3449 28 Jul 15 olle 666   }
3449 28 Jul 15 olle 667
3449 28 Jul 15 olle 668   /**
3449 28 Jul 15 olle 669     Callback function for auto-select.
3449 28 Jul 15 olle 670   */  
3449 28 Jul 15 olle 671   selectdna.dnaSelected = function(response)
3449 28 Jul 15 olle 672   {
3449 28 Jul 15 olle 673     // Cache DNA information
3449 28 Jul 15 olle 674     Dna.cacheInfo(response.dna);
3449 28 Jul 15 olle 675     Dna.cacheInfo(response.flagged);
3449 28 Jul 15 olle 676     
3449 28 Jul 15 olle 677     selectdna.updateNumFlaggedDna();
3449 28 Jul 15 olle 678     var selected = Plate.getSelected();
3449 28 Jul 15 olle 679
3449 28 Jul 15 olle 680 /*
3449 28 Jul 15 olle 681     // Get selected DNA names
3449 28 Jul 15 olle 682     for (var i = 0; i < response.dna.length; i++)
3449 28 Jul 15 olle 683     {
3449 28 Jul 15 olle 684       if (i < selected.length)
3449 28 Jul 15 olle 685       {
3449 28 Jul 15 olle 686         names[i] = response.dna[i].name;
3449 28 Jul 15 olle 687       }
3449 28 Jul 15 olle 688     }
3449 28 Jul 15 olle 689     if (names.length > 0)
3449 28 Jul 15 olle 690     {
3449 28 Jul 15 olle 691       Dna.loadInfoByNames(names);
3449 28 Jul 15 olle 692
3449 28 Jul 15 olle 693       for (var i = 0; i < names.length && i < selected.length; i++)
3449 28 Jul 15 olle 694       {
3449 28 Jul 15 olle 695         var well = selected[i];
3449 28 Jul 15 olle 696         var name = names[i];
3449 28 Jul 15 olle 697         
3449 28 Jul 15 olle 698         // Create a new DNA object
3449 28 Jul 15 olle 699         var dna = Dna.createByName(name);
3449 28 Jul 15 olle 700         Dna.unflag(dna);
3449 28 Jul 15 olle 701         well.setExtract(dna);
3449 28 Jul 15 olle 702         well.selected = false;
3449 28 Jul 15 olle 703       }
3449 28 Jul 15 olle 704       
3449 28 Jul 15 olle 705       Plate.checkReplicates();
3449 28 Jul 15 olle 706       Plate.paint(selected);
3449 28 Jul 15 olle 707       selectdna.updateNumFlaggedDna();
3449 28 Jul 15 olle 708       names = [];
3449 28 Jul 15 olle 709     }
3449 28 Jul 15 olle 710 */
3449 28 Jul 15 olle 711
3449 28 Jul 15 olle 712     for (var i = 0; i < response.dna.length; i++)
3449 28 Jul 15 olle 713     {
3449 28 Jul 15 olle 714       if (i < selected.length)
3449 28 Jul 15 olle 715       {
3449 28 Jul 15 olle 716         var well = selected[i];
3449 28 Jul 15 olle 717         // Create a new DNA object
3449 28 Jul 15 olle 718         var dna = Dna.createByName(response.dna[i].name);
3449 28 Jul 15 olle 719         well.setExtract(dna);
3449 28 Jul 15 olle 720         well.selected = false;
3449 28 Jul 15 olle 721       }
3449 28 Jul 15 olle 722     }
3449 28 Jul 15 olle 723     
3449 28 Jul 15 olle 724     // Check for replicates on the whole plate and repaint it
3449 28 Jul 15 olle 725     Plate.checkReplicates(null, true);
3449 28 Jul 15 olle 726     Plate.paint(Plate.getWells());
3449 28 Jul 15 olle 727   }
3449 28 Jul 15 olle 728   
3449 28 Jul 15 olle 729   // Update the 'Flagged DNA' information
3449 28 Jul 15 olle 730   selectdna.updateNumFlaggedDna = function()
3449 28 Jul 15 olle 731   {
3449 28 Jul 15 olle 732     var numFlagged = Dna.getFlagged().length;
3449 28 Jul 15 olle 733     if (numFlagged > 0)
3449 28 Jul 15 olle 734     {
3449 28 Jul 15 olle 735       Doc.element('flaggedDna').innerHTML = numFlagged + ' flagged DNA items.';
3449 28 Jul 15 olle 736       Doc.show('flaggedDna');
3449 28 Jul 15 olle 737     }
3449 28 Jul 15 olle 738     else
3449 28 Jul 15 olle 739     {
3449 28 Jul 15 olle 740       Doc.hide('flaggedDna');
3449 28 Jul 15 olle 741     }
3449 28 Jul 15 olle 742   }
3449 28 Jul 15 olle 743
3449 28 Jul 15 olle 744   /**
3449 28 Jul 15 olle 745     Add 'Stratagene' to the selected wells.
3449 28 Jul 15 olle 746   */
3449 28 Jul 15 olle 747   selectdna.setToStratagene = function(event)
3449 28 Jul 15 olle 748   {
3449 28 Jul 15 olle 749     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 750     selectdna.setToSpecial(event, frm.stratagene.value, true);
3449 28 Jul 15 olle 751   }
3449 28 Jul 15 olle 752
3449 28 Jul 15 olle 753
3449 28 Jul 15 olle 754   /**
3449 28 Jul 15 olle 755     Add 'External DNA' to the selected wells.
3449 28 Jul 15 olle 756   */
3449 28 Jul 15 olle 757   selectdna.setToExternal = function(event)
3449 28 Jul 15 olle 758   {
3449 28 Jul 15 olle 759     selectdna.setToSpecial(event, EXTERNAL_DNA_NAME, false);  
3449 28 Jul 15 olle 760   }
3449 28 Jul 15 olle 761   
3449 28 Jul 15 olle 762   /**
3449 28 Jul 15 olle 763     Add special DNA to the selected wells.
3449 28 Jul 15 olle 764   */
3449 28 Jul 15 olle 765   selectdna.setToSpecial = function(event, specialName, qc)
3449 28 Jul 15 olle 766   {
3449 28 Jul 15 olle 767     var wells = Plate.getSelected();
3449 28 Jul 15 olle 768     
3449 28 Jul 15 olle 769     if (wells.length == 0)
3449 28 Jul 15 olle 770     {
3449 28 Jul 15 olle 771       Forms.showNotification(event.currentTarget, 'No wells have been selected');
3449 28 Jul 15 olle 772       return;
3449 28 Jul 15 olle 773     }
3449 28 Jul 15 olle 774     
3449 28 Jul 15 olle 775     // Count non-empty wells
3449 28 Jul 15 olle 776     var count = 0;
3449 28 Jul 15 olle 777     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 778     {
3449 28 Jul 15 olle 779       var well = wells[i];
3449 28 Jul 15 olle 780       if (well.extract && !well.hasError()) count++;
3449 28 Jul 15 olle 781     }
3449 28 Jul 15 olle 782     
3449 28 Jul 15 olle 783     if (count > 0)
3449 28 Jul 15 olle 784     {
3449 28 Jul 15 olle 785       if (!confirm('Replace DNA in ' + count + ' wells with '+specialName+'?'))
3449 28 Jul 15 olle 786       {
3449 28 Jul 15 olle 787         return;
3449 28 Jul 15 olle 788       }
3449 28 Jul 15 olle 789     }
3449 28 Jul 15 olle 790     
3449 28 Jul 15 olle 791     var info = Dna.infoByName(specialName);
3449 28 Jul 15 olle 792     if (!info.id)
3449 28 Jul 15 olle 793     {
3449 28 Jul 15 olle 794       alert('Could not find any DNA with name=\''+specialName+'\'. Please check that it exists on the server.');
3449 28 Jul 15 olle 795       return;
3449 28 Jul 15 olle 796     }
3449 28 Jul 15 olle 797     
3449 28 Jul 15 olle 798     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 799     {
3449 28 Jul 15 olle 800       var well = wells[i];
3449 28 Jul 15 olle 801       var dna = Dna.createByInfo(info);
3449 28 Jul 15 olle 802       dna.qc = qc;
3449 28 Jul 15 olle 803       well.setExtract(dna);
3449 28 Jul 15 olle 804       well.selected = false;
3449 28 Jul 15 olle 805     }
3449 28 Jul 15 olle 806     
3449 28 Jul 15 olle 807     Plate.paint(wells);
3449 28 Jul 15 olle 808     
3449 28 Jul 15 olle 809     // Check for replicated DNA if some have been replaced with Stratagene
3449 28 Jul 15 olle 810     if (count > 0) Plate.checkReplicates();
3449 28 Jul 15 olle 811   }
3449 28 Jul 15 olle 812   
3449 28 Jul 15 olle 813   /**
3449 28 Jul 15 olle 814     Toggle the QC flag for the selected wells. The first non-empty
3449 28 Jul 15 olle 815     well is toggled and the rest of the wells will use the same new QC
3449 28 Jul 15 olle 816     value.
3449 28 Jul 15 olle 817   */
3449 28 Jul 15 olle 818   selectdna.toggleQc = function(event)
3449 28 Jul 15 olle 819   {
3449 28 Jul 15 olle 820     var wells = Plate.getSelected();
3449 28 Jul 15 olle 821   
3449 28 Jul 15 olle 822     if (wells.length == 0) 
3449 28 Jul 15 olle 823     {
3449 28 Jul 15 olle 824       Forms.showNotification(event.currentTarget, 'No wells have been selected');
3449 28 Jul 15 olle 825       return;
3449 28 Jul 15 olle 826     }
3449 28 Jul 15 olle 827     
3449 28 Jul 15 olle 828     var gotQc = false;
3449 28 Jul 15 olle 829     var newQc;
3449 28 Jul 15 olle 830     var count = 0;
3449 28 Jul 15 olle 831     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 832     {
3449 28 Jul 15 olle 833       var well = wells[i];
3449 28 Jul 15 olle 834       if (well.extract)
3449 28 Jul 15 olle 835       {
3449 28 Jul 15 olle 836         // Toggle QC flag for the first well with DNA, then use the same flag for the rest
3449 28 Jul 15 olle 837         if (!gotQc)
3449 28 Jul 15 olle 838         {
3449 28 Jul 15 olle 839           gotQc = true;
3449 28 Jul 15 olle 840           newQc = !well.extract.qc;
3449 28 Jul 15 olle 841         }
3449 28 Jul 15 olle 842         well.extract.qc = newQc;
3449 28 Jul 15 olle 843         count++;
3449 28 Jul 15 olle 844       }
3449 28 Jul 15 olle 845     }
3449 28 Jul 15 olle 846     
3449 28 Jul 15 olle 847     if (count == 0)
3449 28 Jul 15 olle 848     {
3449 28 Jul 15 olle 849       Forms.showNotification(event.currentTarget, 'None of the selected wells contain any DNA');
3449 28 Jul 15 olle 850     }
3449 28 Jul 15 olle 851     else
3449 28 Jul 15 olle 852     {
3449 28 Jul 15 olle 853       Plate.paint(wells);
3449 28 Jul 15 olle 854     }
3449 28 Jul 15 olle 855   }
3449 28 Jul 15 olle 856
3449 28 Jul 15 olle 857   // Set a comment on the selected wells
3449 28 Jul 15 olle 858   selectdna.commentSelected = function(event)
3449 28 Jul 15 olle 859   {
3449 28 Jul 15 olle 860     var wells = Plate.getSelected();
3449 28 Jul 15 olle 861     
3449 28 Jul 15 olle 862     if (wells.length == 0)
3449 28 Jul 15 olle 863     {
3449 28 Jul 15 olle 864       Forms.showNotification(event.currentTarget, 'No wells have been selected');
3449 28 Jul 15 olle 865       return;
3449 28 Jul 15 olle 866     }
3449 28 Jul 15 olle 867     
3449 28 Jul 15 olle 868     var count = 0;
3449 28 Jul 15 olle 869     var comment = '';
3449 28 Jul 15 olle 870     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 871     {
3449 28 Jul 15 olle 872       var well = wells[i];
3449 28 Jul 15 olle 873       if (well.extract) 
3449 28 Jul 15 olle 874       {
3449 28 Jul 15 olle 875         count++;
3449 28 Jul 15 olle 876         if (well.extract.comment) comment = well.extract.comment;
3449 28 Jul 15 olle 877       }
3449 28 Jul 15 olle 878     }
3449 28 Jul 15 olle 879       
3449 28 Jul 15 olle 880     if (count == 0)
3449 28 Jul 15 olle 881     {
3449 28 Jul 15 olle 882       Forms.showNotification(event.currentTarget, 'None of the selected wells contain any DNA');
3449 28 Jul 15 olle 883       return;
3449 28 Jul 15 olle 884     }
3449 28 Jul 15 olle 885
3449 28 Jul 15 olle 886     comment = prompt('Comment', comment || '');
3449 28 Jul 15 olle 887     if (comment == null) return;
3449 28 Jul 15 olle 888     
3449 28 Jul 15 olle 889     if (comment == '') comment = null;
3449 28 Jul 15 olle 890     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 891     {
3449 28 Jul 15 olle 892       var well = wells[i];
3449 28 Jul 15 olle 893       if (well.extract) well.extract.comment = comment;
3449 28 Jul 15 olle 894     }
3449 28 Jul 15 olle 895     Plate.paint(wells);
3449 28 Jul 15 olle 896   }
3449 28 Jul 15 olle 897
3449 28 Jul 15 olle 898   /**
3449 28 Jul 15 olle 899     Empty the selected wells from DNA. They can later be pasted again.
3449 28 Jul 15 olle 900   */
3449 28 Jul 15 olle 901   selectdna.cutSelected = function(event)
3449 28 Jul 15 olle 902   {
3449 28 Jul 15 olle 903     var wells = Plate.getSelected();
3449 28 Jul 15 olle 904     
3449 28 Jul 15 olle 905     if (wells.length == 0)
3449 28 Jul 15 olle 906     {
3449 28 Jul 15 olle 907       Forms.showNotification(event.currentTarget, 'No wells have been selected');
3449 28 Jul 15 olle 908       return;
3449 28 Jul 15 olle 909     }
3449 28 Jul 15 olle 910     
3449 28 Jul 15 olle 911     var count = 0;
3449 28 Jul 15 olle 912     var valid = 0;
3449 28 Jul 15 olle 913     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 914     {
3449 28 Jul 15 olle 915       var well = wells[i];
3449 28 Jul 15 olle 916       if (well.extract) 
3449 28 Jul 15 olle 917       {
3449 28 Jul 15 olle 918         count++;
3449 28 Jul 15 olle 919         if (!well.hasError()) valid++;
3449 28 Jul 15 olle 920       }
3449 28 Jul 15 olle 921     }
3449 28 Jul 15 olle 922     
3449 28 Jul 15 olle 923     if (count == 0)
3449 28 Jul 15 olle 924     {
3449 28 Jul 15 olle 925       Forms.showNotification(event.currentTarget, 'None of the selected wells contain any DNA');
3449 28 Jul 15 olle 926       return;
3449 28 Jul 15 olle 927     }
3449 28 Jul 15 olle 928     
3449 28 Jul 15 olle 929     // Ask for confirmation before deleting from valid wells
3449 28 Jul 15 olle 930     if (valid > 0)
3449 28 Jul 15 olle 931     {
3449 28 Jul 15 olle 932       if (!confirm('Clear DNA from ' + count + ' of ' + wells.length + ' selected wells?'))
3449 28 Jul 15 olle 933       {
3449 28 Jul 15 olle 934         return;
3449 28 Jul 15 olle 935       }
3449 28 Jul 15 olle 936     }
3449 28 Jul 15 olle 937   
3449 28 Jul 15 olle 938     selectdna.copySelected();
3449 28 Jul 15 olle 939     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 940     {
3449 28 Jul 15 olle 941       var well = wells[i];
3449 28 Jul 15 olle 942       well.setExtract(null);
3449 28 Jul 15 olle 943       well.selected = false;
3449 28 Jul 15 olle 944     }
3449 28 Jul 15 olle 945     Plate.paint(wells);
3449 28 Jul 15 olle 946     Plate.checkReplicates();
3449 28 Jul 15 olle 947   }
3449 28 Jul 15 olle 948   
3449 28 Jul 15 olle 949   var copy;
3449 28 Jul 15 olle 950   /**
3449 28 Jul 15 olle 951     Copy information about the selected wells. 
3449 28 Jul 15 olle 952   */
3449 28 Jul 15 olle 953   selectdna.copySelected = function(event)
3449 28 Jul 15 olle 954   {
3449 28 Jul 15 olle 955     // Clear existing wells in the copy
3449 28 Jul 15 olle 956     var repaint = [];
3449 28 Jul 15 olle 957     if (copy && copy.length > 0)
3449 28 Jul 15 olle 958     {
3449 28 Jul 15 olle 959       for (var i = 0; i < copy.length; i++)
3449 28 Jul 15 olle 960       {
3449 28 Jul 15 olle 961         var cp = copy[i];
3449 28 Jul 15 olle 962         cp.well.doneWithCopy();
3449 28 Jul 15 olle 963         repaint[repaint.length] = cp.well;
3449 28 Jul 15 olle 964       }
3449 28 Jul 15 olle 965     }
3449 28 Jul 15 olle 966     Plate.paint(repaint);
3449 28 Jul 15 olle 967     
3449 28 Jul 15 olle 968     // Place selected wells in the copy
3449 28 Jul 15 olle 969     var wells = Plate.getSelected();
3449 28 Jul 15 olle 970     copy = [];
3449 28 Jul 15 olle 971     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 972     {
3449 28 Jul 15 olle 973       var well = wells[i];
3449 28 Jul 15 olle 974       copy[copy.length] = well.makeCopy();
3449 28 Jul 15 olle 975       well.selected = false;
3449 28 Jul 15 olle 976     }
3449 28 Jul 15 olle 977     Plate.paint(wells);
3449 28 Jul 15 olle 978   }
3449 28 Jul 15 olle 979   
3449 28 Jul 15 olle 980   /**
3449 28 Jul 15 olle 981     Paste information into the selected wells.
3449 28 Jul 15 olle 982   */
3449 28 Jul 15 olle 983   selectdna.pasteToSelected = function(event)
3449 28 Jul 15 olle 984   {
3449 28 Jul 15 olle 985     if (!copy || copy.length == 0) 
3449 28 Jul 15 olle 986     {
3449 28 Jul 15 olle 987       Forms.showNotification(event.currentTarget, 'Nothing to paste. Please cut or copy wells first.');
3449 28 Jul 15 olle 988       return;
3449 28 Jul 15 olle 989     }
3449 28 Jul 15 olle 990     
3449 28 Jul 15 olle 991     var wells = Plate.getSelected();
3449 28 Jul 15 olle 992     // Count non-empty and valid wells
3449 28 Jul 15 olle 993     var count = 0;
3449 28 Jul 15 olle 994     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 995     {
3449 28 Jul 15 olle 996       var well = wells[i];
3449 28 Jul 15 olle 997       if (well.extract && !well.hasError()) count++;
3449 28 Jul 15 olle 998     }
3449 28 Jul 15 olle 999     
3449 28 Jul 15 olle 1000     if (count > 0)
3449 28 Jul 15 olle 1001     {
3449 28 Jul 15 olle 1002       if (!confirm('Replace DNA in ' + count + ' wells with copy?'))
3449 28 Jul 15 olle 1003       {
3449 28 Jul 15 olle 1004         return;
3449 28 Jul 15 olle 1005       }
3449 28 Jul 15 olle 1006     }
3449 28 Jul 15 olle 1007     
3449 28 Jul 15 olle 1008     var wi = 0;
3449 28 Jul 15 olle 1009     var ci = 0;
3449 28 Jul 15 olle 1010     var copyEmpty;
3449 28 Jul 15 olle 1011     var askIfEmpty = true;
3449 28 Jul 15 olle 1012     var repaint = [];
3449 28 Jul 15 olle 1013     
3449 28 Jul 15 olle 1014     while (wi < wells.length && ci < copy.length)
3449 28 Jul 15 olle 1015     {
3449 28 Jul 15 olle 1016       var well = wells[wi];
3449 28 Jul 15 olle 1017       var cp = copy[ci];
3449 28 Jul 15 olle 1018       var dna = null;
3449 28 Jul 15 olle 1019       cp.well.doneWithCopy();
3449 28 Jul 15 olle 1020       repaint[repaint.length] = cp.well;
3449 28 Jul 15 olle 1021       if (cp.name)
3449 28 Jul 15 olle 1022       {
3449 28 Jul 15 olle 1023         dna = Dna.createByName(cp.name);
3449 28 Jul 15 olle 1024         dna.comment = cp.comment;
3449 28 Jul 15 olle 1025       }
3449 28 Jul 15 olle 1026       else
3449 28 Jul 15 olle 1027       {
3449 28 Jul 15 olle 1028         // The copy is from an empty well
3449 28 Jul 15 olle 1029         if (askIfEmpty)
3449 28 Jul 15 olle 1030         {
3449 28 Jul 15 olle 1031           askIfEmpty = false;
3449 28 Jul 15 olle 1032           copyEmpty = confirm('Do you want to copy empty wells? If not, only non-empty well are copied.');
3449 28 Jul 15 olle 1033         }
3449 28 Jul 15 olle 1034       }
3449 28 Jul 15 olle 1035       if (dna != null || copyEmpty)
3449 28 Jul 15 olle 1036       {
3449 28 Jul 15 olle 1037         well.setExtract(dna);
3449 28 Jul 15 olle 1038         well.selected = false;
3449 28 Jul 15 olle 1039         repaint[repaint.length] = well;
3449 28 Jul 15 olle 1040         wi++;
3449 28 Jul 15 olle 1041       }
3449 28 Jul 15 olle 1042       ci++;
3449 28 Jul 15 olle 1043     }
3449 28 Jul 15 olle 1044     Plate.paint(repaint);
3449 28 Jul 15 olle 1045     copy.splice(0, ci);
3449 28 Jul 15 olle 1046     Plate.checkReplicates();
3449 28 Jul 15 olle 1047   }
3449 28 Jul 15 olle 1048
3449 28 Jul 15 olle 1049   /*
3449 28 Jul 15 olle 1050     If exactly two wells have been selected, switch the DNA in them.
3449 28 Jul 15 olle 1051   */
3449 28 Jul 15 olle 1052   selectdna.switchSelected = function(event)
3449 28 Jul 15 olle 1053   {
3449 28 Jul 15 olle 1054     var wells = Plate.getSelected();
3449 28 Jul 15 olle 1055   
3449 28 Jul 15 olle 1056     if (wells.length != 2)
3449 28 Jul 15 olle 1057     {
3449 28 Jul 15 olle 1058       Forms.showNotification(event.currentTarget, 'Exactly 2 wells must be selected.');
3449 28 Jul 15 olle 1059       return;
3449 28 Jul 15 olle 1060     }
3449 28 Jul 15 olle 1061   
3449 28 Jul 15 olle 1062     var dna0 = wells[0].extract;
3449 28 Jul 15 olle 1063     var dna1 = wells[1].extract;
3449 28 Jul 15 olle 1064     
3449 28 Jul 15 olle 1065     wells[0].setExtract(dna1);
3449 28 Jul 15 olle 1066     wells[1].setExtract(dna0);
3449 28 Jul 15 olle 1067     Plate.paint(wells);
3449 28 Jul 15 olle 1068   }
3449 28 Jul 15 olle 1069
3449 28 Jul 15 olle 1070   // Toggle the 'special select' menu on and off
3449 28 Jul 15 olle 1071   selectdna.toggleSpecialSelect = function(event)
3449 28 Jul 15 olle 1072   {
3449 28 Jul 15 olle 1073     var pos = Doc.getElementPosition('iconSpecialSelect');
3449 28 Jul 15 olle 1074     Menu.toggleTopMenu('menuSpecialSelect', pos.left+pos.width/4, pos.top+pos.height); 
3449 28 Jul 15 olle 1075     event.stopPropagation();
3449 28 Jul 15 olle 1076   }
3449 28 Jul 15 olle 1077   
3449 28 Jul 15 olle 1078   var contextDNA = null;
3449 28 Jul 15 olle 1079   var contextX;
3449 28 Jul 15 olle 1080   var contextY;
3449 28 Jul 15 olle 1081   /**
3449 28 Jul 15 olle 1082     Reacts to 'mouseup' and 'contextmenu' events for the bioplate. 
3449 28 Jul 15 olle 1083     This should bring up the cut/copy/paste context menu depending on which
3449 28 Jul 15 olle 1084     mouse button that was clicked.
3449 28 Jul 15 olle 1085   */
3449 28 Jul 15 olle 1086   selectdna.contextEvent = function(event)
3449 28 Jul 15 olle 1087   {
3449 28 Jul 15 olle 1088     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 1089     // Context menu on 'right' mouse button
3449 28 Jul 15 olle 1090     // Can't just check the button since two events are sent ('mouseup' and 'contextmenu')
3449 28 Jul 15 olle 1091     var showContext = event.type == 'contextmenu' && event.button == 2;
3449 28 Jul 15 olle 1092       
3449 28 Jul 15 olle 1093     if (showContext)
3449 28 Jul 15 olle 1094     {
3449 28 Jul 15 olle 1095       event.preventDefault(); // Prevents the default right-click menu from appearing
3449 28 Jul 15 olle 1096       
3449 28 Jul 15 olle 1097       // Get the well that is right-clicked and the DNA that is in it
3449 28 Jul 15 olle 1098       contextDNA = null;
3449 28 Jul 15 olle 1099       var well = event.target;
3449 28 Jul 15 olle 1100       while (well && (!well.id || well.id.indexOf('well') != 0))
3449 28 Jul 15 olle 1101       {
3449 28 Jul 15 olle 1102         well = well.parentNode;
3449 28 Jul 15 olle 1103       }
3449 28 Jul 15 olle 1104       if (well)
3449 28 Jul 15 olle 1105       {
3449 28 Jul 15 olle 1106         var c = well.id.split(/\./);
3449 28 Jul 15 olle 1107         contextDNA = Plate.getWell(parseInt(c[1]), parseInt(c[2])).extract;
3449 28 Jul 15 olle 1108       }
3449 28 Jul 15 olle 1109       // Update the context meny
3449 28 Jul 15 olle 1110       var caseSummaryMenu = Doc.element('mnuCaseSummary');
3449 28 Jul 15 olle 1111       if (contextDNA)
3449 28 Jul 15 olle 1112       {
3449 28 Jul 15 olle 1113         caseSummaryMenu.title = 'Show case summary for ' + Strings.encodeTags(contextDNA.name);
3449 28 Jul 15 olle 1114         Doc.show('sepCaseSummary');
3449 28 Jul 15 olle 1115         Doc.show('mnuCaseSummary');
3449 28 Jul 15 olle 1116       }
3449 28 Jul 15 olle 1117       else
3449 28 Jul 15 olle 1118       {
3449 28 Jul 15 olle 1119         Doc.hide('sepCaseSummary');
3449 28 Jul 15 olle 1120         Doc.hide('mnuCaseSummary');
3449 28 Jul 15 olle 1121       }
3449 28 Jul 15 olle 1122       
3449 28 Jul 15 olle 1123       var menu = Doc.element('menuContext');
3449 28 Jul 15 olle 1124       // 1 pixel offset to avoid losing well focus outline
3449 28 Jul 15 olle 1125       contextX = event.clientX+1;
3449 28 Jul 15 olle 1126       contextY = event.clientY+1;
3449 28 Jul 15 olle 1127       // Need short delay since 'mouseup' are also sent as 'click' events
3449 28 Jul 15 olle 1128       // to the 'document' object which BASE already have a Menu.hideAll()
3449 28 Jul 15 olle 1129       // call which would hide the menu immediately
3449 28 Jul 15 olle 1130       setTimeout(selectdna.showContextMenu, 100);
3449 28 Jul 15 olle 1131     }
3449 28 Jul 15 olle 1132   }
3449 28 Jul 15 olle 1133   
3449 28 Jul 15 olle 1134   selectdna.showContextMenu = function()
3449 28 Jul 15 olle 1135   {
3449 28 Jul 15 olle 1136     Menu.showTopMenu('menuContext', contextX, contextY);
3449 28 Jul 15 olle 1137   }
3449 28 Jul 15 olle 1138
3449 28 Jul 15 olle 1139   selectdna.showCaseSummary = function()
3449 28 Jul 15 olle 1140   {
3449 28 Jul 15 olle 1141     if (!contextDNA) return;
3449 28 Jul 15 olle 1142     var caseName = contextDNA.name;
3449 28 Jul 15 olle 1143     // Remove suffix starting with dot "."
3449 28 Jul 15 olle 1144     var firstDotIndex = caseName.indexOf(".");
3449 28 Jul 15 olle 1145     if (firstDotIndex >= 0)
3449 28 Jul 15 olle 1146     {
3449 28 Jul 15 olle 1147       caseName = caseName.substring(0, firstDotIndex);
3449 28 Jul 15 olle 1148     }
3449 28 Jul 15 olle 1149     var url = '../reports/case_summary.jsp?ID='+App.getSessionId();
3449 28 Jul 15 olle 1150     url += '&caseName='+encodeURIComponent(caseName);
3449 28 Jul 15 olle 1151     url += '&pageType=popup';
3449 28 Jul 15 olle 1152     Dialogs.openPopup(url, 'CaseSummary'+caseName, 1000, 700);
3449 28 Jul 15 olle 1153   }
3449 28 Jul 15 olle 1154   
3449 28 Jul 15 olle 1155   selectdna.showFlaggedDna = function()
3449 28 Jul 15 olle 1156   {
3449 28 Jul 15 olle 1157     currentSelected = Plate.getSelected();
3449 28 Jul 15 olle 1158     currentIndex = 0;
3449 28 Jul 15 olle 1159
3449 28 Jul 15 olle 1160     var flagged = Dna.getFlagged();
3449 28 Jul 15 olle 1161     var url = 'show_flagged_dna.jsp?ID='+App.getSessionId();
3449 28 Jul 15 olle 1162     url += '&numFlagged='+flagged.length;
3449 28 Jul 15 olle 1163     url += '&numSelected='+currentSelected.length;
3449 28 Jul 15 olle 1164     Dialogs.openPopup(url, 'FlaggedDna', 800, 500);
3449 28 Jul 15 olle 1165   }
3449 28 Jul 15 olle 1166
3449 28 Jul 15 olle 1167   
3449 28 Jul 15 olle 1168   //Flag the selected DNA
3449 28 Jul 15 olle 1169   selectdna.flagSelected = function(event)
3449 28 Jul 15 olle 1170   {
3449 28 Jul 15 olle 1171     var flag = Data.get(event.currentTarget, 'flag');
3449 28 Jul 15 olle 1172     var wells = Plate.getSelected();
3449 28 Jul 15 olle 1173     
3449 28 Jul 15 olle 1174     if (wells.length == 0)
3449 28 Jul 15 olle 1175     {
3449 28 Jul 15 olle 1176       Forms.showNotification(event.currentTarget, 'No wells have been selected.');
3449 28 Jul 15 olle 1177       return;
3449 28 Jul 15 olle 1178     }
3449 28 Jul 15 olle 1179     
3449 28 Jul 15 olle 1180     var comment = null;
3449 28 Jul 15 olle 1181     if (flag == 'ManualFlag')
3449 28 Jul 15 olle 1182     {
3449 28 Jul 15 olle 1183       // Check if a comment has been set on any of the DNA
3449 28 Jul 15 olle 1184       for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 1185       {
3449 28 Jul 15 olle 1186         var well = wells[i];
3449 28 Jul 15 olle 1187         if (well.extract && well.extract.info) 
3449 28 Jul 15 olle 1188         {
3449 28 Jul 15 olle 1189           if (well.extract.info.comment) comment = well.extract.info.comment;
3449 28 Jul 15 olle 1190         }
3449 28 Jul 15 olle 1191       }
3449 28 Jul 15 olle 1192       comment = prompt('Comment', comment || '');
3449 28 Jul 15 olle 1193       if (!comment) return;
3449 28 Jul 15 olle 1194     }
3449 28 Jul 15 olle 1195     
3449 28 Jul 15 olle 1196     var count = 0;
3449 28 Jul 15 olle 1197     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 1198     {
3449 28 Jul 15 olle 1199       var well = wells[i];
3449 28 Jul 15 olle 1200       var dna = well.extract;
3449 28 Jul 15 olle 1201       if (dna && !dna.stratagene && !dna.external)
3449 28 Jul 15 olle 1202       {
3449 28 Jul 15 olle 1203         Dna.flag(dna, flag);
3449 28 Jul 15 olle 1204         dna.info.comment = comment;
3449 28 Jul 15 olle 1205         well.setExtract(null);
3449 28 Jul 15 olle 1206         count++;
3449 28 Jul 15 olle 1207       }
3449 28 Jul 15 olle 1208       well.selected = false;
3449 28 Jul 15 olle 1209     }
3449 28 Jul 15 olle 1210     
3449 28 Jul 15 olle 1211     selectdna.updateNumFlaggedDna();
3449 28 Jul 15 olle 1212     Plate.paint(wells);
3449 28 Jul 15 olle 1213   }
3449 28 Jul 15 olle 1214
3449 28 Jul 15 olle 1215
3449 28 Jul 15 olle 1216   selectdna.validateStep1 = function(event)
3449 28 Jul 15 olle 1217   {
3449 28 Jul 15 olle 1218     if (!quantitiesAreValid) 
3449 28 Jul 15 olle 1219     {
3449 28 Jul 15 olle 1220       event.preventDefault();
3449 28 Jul 15 olle 1221       return;
3449 28 Jul 15 olle 1222     }
3449 28 Jul 15 olle 1223
3449 28 Jul 15 olle 1224     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 1225     var numErrors = 0;
3449 28 Jul 15 olle 1226     var numWarnings = 0;
3449 28 Jul 15 olle 1227     var numDna = 0;
3449 28 Jul 15 olle 1228     var numStratagene = 0;
3449 28 Jul 15 olle 1229     var numExternal = 0;
3449 28 Jul 15 olle 1230     var wells = Plate.getWells();
3449 28 Jul 15 olle 1231     var schema = PoolSchema.getById(frm.pool_schema.value);
3449 28 Jul 15 olle 1232     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 1233     {
3449 28 Jul 15 olle 1234       var well = wells[i];
3449 28 Jul 15 olle 1235       var dna = well.extract;
3449 28 Jul 15 olle 1236       if (well.hasWarning())
3449 28 Jul 15 olle 1237       {
3449 28 Jul 15 olle 1238         numWarnings++;
3449 28 Jul 15 olle 1239       }
3449 28 Jul 15 olle 1240       if (well.hasError())
3449 28 Jul 15 olle 1241       {
3449 28 Jul 15 olle 1242         numErrors++;
3449 28 Jul 15 olle 1243       }
3449 28 Jul 15 olle 1244       else
3449 28 Jul 15 olle 1245       {
3449 28 Jul 15 olle 1246         if (dna && dna.id) 
3449 28 Jul 15 olle 1247         {
3449 28 Jul 15 olle 1248           numDna++;
3449 28 Jul 15 olle 1249           if (dna.stratagene) numStratagene++;
3449 28 Jul 15 olle 1250           if (dna.external) numExternal++;
3449 28 Jul 15 olle 1251         }
3449 28 Jul 15 olle 1252       }
3449 28 Jul 15 olle 1253     }
3449 28 Jul 15 olle 1254
3449 28 Jul 15 olle 1255     if (numErrors > 0)
3449 28 Jul 15 olle 1256     {
3449 28 Jul 15 olle 1257       event.preventDefault();
3449 28 Jul 15 olle 1258       return;
3449 28 Jul 15 olle 1259     }
3449 28 Jul 15 olle 1260     
3449 28 Jul 15 olle 1261     if (numDna == 0)
3449 28 Jul 15 olle 1262     {
3449 28 Jul 15 olle 1263       alert('There is no DNA in any wells');
3449 28 Jul 15 olle 1264       event.preventDefault();
3449 28 Jul 15 olle 1265       return;
3449 28 Jul 15 olle 1266     }
3449 28 Jul 15 olle 1267     
3449 28 Jul 15 olle 1268     if (numWarnings > 0)
3449 28 Jul 15 olle 1269     {
3449 28 Jul 15 olle 1270       if (!confirm('There are ' + numWarnings + ' wells with a warning. Continue anyway?'))
3449 28 Jul 15 olle 1271       {
3449 28 Jul 15 olle 1272         event.preventDefault();
3449 28 Jul 15 olle 1273         return;
3449 28 Jul 15 olle 1274       }
3449 28 Jul 15 olle 1275     }
3449 28 Jul 15 olle 1276     
3449 28 Jul 15 olle 1277     if (schema)
3449 28 Jul 15 olle 1278     {
3449 28 Jul 15 olle 1279       var numPrimary = schema.numPools * schema.numWellsPerPool;
3449 28 Jul 15 olle 1280       if (numDna < numPrimary)
3449 28 Jul 15 olle 1281       {
3449 28 Jul 15 olle 1282         if (!confirm((numPrimary-numDna)+ ' primary wells are missing DNA. Continue anyway?'))
3449 28 Jul 15 olle 1283         {
3449 28 Jul 15 olle 1284           event.preventDefault();
3449 28 Jul 15 olle 1285           return;
3449 28 Jul 15 olle 1286         }
3449 28 Jul 15 olle 1287       }
3449 28 Jul 15 olle 1288     }
3449 28 Jul 15 olle 1289     
3449 28 Jul 15 olle 1290     if (numDna == numStratagene+numExternal)
3449 28 Jul 15 olle 1291     {
3449 28 Jul 15 olle 1292       if (!confirm('There are only wells with Stratagene or external DNA on this plate. Continue anyway?'))
3449 28 Jul 15 olle 1293       {
3449 28 Jul 15 olle 1294         event.preventDefault();
3449 28 Jul 15 olle 1295         return;
3449 28 Jul 15 olle 1296       }
3449 28 Jul 15 olle 1297     }
3449 28 Jul 15 olle 1298     
3449 28 Jul 15 olle 1299   }
3449 28 Jul 15 olle 1300   
3449 28 Jul 15 olle 1301   selectdna.submit = function()
3449 28 Jul 15 olle 1302   {
3449 28 Jul 15 olle 1303     var frm = document.forms['meludi'];
3449 28 Jul 15 olle 1304     var isNeoPrep = Data.int('page-data', 'is-neoprep');
3449 28 Jul 15 olle 1305
3449 28 Jul 15 olle 1306     var submitInfo = {};
3449 28 Jul 15 olle 1307     var plateInfo = {};
3449 28 Jul 15 olle 1308     var flaggedDnaInfo = [];
3449 28 Jul 15 olle 1309     
3449 28 Jul 15 olle 1310     submitInfo.bioplate = plateInfo;
3449 28 Jul 15 olle 1311     submitInfo.flagged = flaggedDnaInfo;
3449 28 Jul 15 olle 1312     var schema = PoolSchema.getById(frm.pool_schema.value);
3449 28 Jul 15 olle 1313     
3449 28 Jul 15 olle 1314     plateInfo.name = Plate.name;
3449 28 Jul 15 olle 1315     plateInfo.comments = frm.comments.value;
3449 28 Jul 15 olle 1316 /*
3449 28 Jul 15 olle 1317     plateInfo.plateType = isNeoPrep ? 'NEOPREP' : 'MDNA';
3449 28 Jul 15 olle 1318 */
3449 28 Jul 15 olle 1319     plateInfo.plateType = isNeoPrep ? 'NEOPREP' : 'DNA';
3449 28 Jul 15 olle 1320     plateInfo.poolSchema = schema ? schema.id : null;
3449 28 Jul 15 olle 1321     if (isNeoPrep)
3449 28 Jul 15 olle 1322     {
3449 28 Jul 15 olle 1323       plateInfo.barcodeVariant = frm.barcode_variant.value;
3449 28 Jul 15 olle 1324     }
3449 28 Jul 15 olle 1325     plateInfo.wells = [];
3449 28 Jul 15 olle 1326
3449 28 Jul 15 olle 1327     var wells = Plate.getWells();
3449 28 Jul 15 olle 1328     for (var i = 0; i < wells.length; i++)
3449 28 Jul 15 olle 1329     {
3449 28 Jul 15 olle 1330       var well = wells[i];
3449 28 Jul 15 olle 1331       var dna = well.extract;
3449 28 Jul 15 olle 1332       if (dna && dna.id)
3449 28 Jul 15 olle 1333       {
3449 28 Jul 15 olle 1334         var tmp = {};
3449 28 Jul 15 olle 1335         tmp.row = well.row;
3449 28 Jul 15 olle 1336         tmp.column = well.column;
3449 28 Jul 15 olle 1337         tmp.dna = {};
3449 28 Jul 15 olle 1338         tmp.dna.id = dna.id;
3449 28 Jul 15 olle 1339         tmp.dna.usedQuantity = dna.usedQuantity;
3449 28 Jul 15 olle 1340         tmp.dna.dilutionConc = dna.dilutionConc;
3449 28 Jul 15 olle 1341         tmp.dna.qc = dna.qc;
3449 28 Jul 15 olle 1342         tmp.dna.comment = dna.comment;
3449 28 Jul 15 olle 1343         if (well.barcode)
3449 28 Jul 15 olle 1344         {
3449 28 Jul 15 olle 1345           tmp.dna.barcode = well.barcode;
3449 28 Jul 15 olle 1346         }
3449 28 Jul 15 olle 1347         plateInfo.wells[plateInfo.wells.length] = tmp;
3449 28 Jul 15 olle 1348       }
3449 28 Jul 15 olle 1349     }
3449 28 Jul 15 olle 1350
3449 28 Jul 15 olle 1351     var flagged = Dna.getFlagged();
3449 28 Jul 15 olle 1352     for (var i = 0; i < flagged.length; i++)
3449 28 Jul 15 olle 1353     {
3449 28 Jul 15 olle 1354       var dna = flagged[i];
3449 28 Jul 15 olle 1355       var tmp = {};
3449 28 Jul 15 olle 1356       tmp.id = dna.id;
3449 28 Jul 15 olle 1357       tmp.flag = dna.flag;
3449 28 Jul 15 olle 1358       tmp.comment = dna.comment;
3449 28 Jul 15 olle 1359       flaggedDnaInfo[flaggedDnaInfo.length] = tmp;
3449 28 Jul 15 olle 1360     }
3449 28 Jul 15 olle 1361
3449 28 Jul 15 olle 1362     var url = '../Dna.servlet?ID='+App.getSessionId();
3449 28 Jul 15 olle 1363     url += '&cmd=CreateDnaOrLibPlate';
3449 28 Jul 15 olle 1364     Wizard.showLoadingAnimation('Performing registration...');
3449 28 Jul 15 olle 1365     Wizard.asyncJsonRequest(url, selectdna.submissionResults, 'POST', JSON.stringify(submitInfo));
3449 28 Jul 15 olle 1366   }
3449 28 Jul 15 olle 1367   
3449 28 Jul 15 olle 1368   selectdna.submissionResults = function(response)
3449 28 Jul 15 olle 1369   {
3449 28 Jul 15 olle 1370     Wizard.showFinalMessage(response.messages);
3449 28 Jul 15 olle 1371     Doc.show('gorestart');
3449 28 Jul 15 olle 1372   }
3449 28 Jul 15 olle 1373   
3449 28 Jul 15 olle 1374   selectdna.initElements = function(element, autoInit)
3449 28 Jul 15 olle 1375   {
3449 28 Jul 15 olle 1376     if (autoInit == 'plate-col')
3449 28 Jul 15 olle 1377     {
3449 28 Jul 15 olle 1378       Events.addEventHandler(element, 'click', selectdna.toggleColumn);
3449 28 Jul 15 olle 1379       Events.addEventHandler(element, 'mouseover', selectdna.highlightColumn);
3449 28 Jul 15 olle 1380       Events.addEventHandler(element, 'mouseout', selectdna.highlightColumn);
3449 28 Jul 15 olle 1381     }
3449 28 Jul 15 olle 1382     else if (autoInit == 'plate-row')
3449 28 Jul 15 olle 1383     {
3449 28 Jul 15 olle 1384       Events.addEventHandler(element, 'click', selectdna.toggleRow);
3449 28 Jul 15 olle 1385       Events.addEventHandler(element, 'mouseover', selectdna.highlightRow);
3449 28 Jul 15 olle 1386       Events.addEventHandler(element, 'mouseout', selectdna.highlightRow);
3449 28 Jul 15 olle 1387     }
3449 28 Jul 15 olle 1388     else if (autoInit == 'plate-well')
3449 28 Jul 15 olle 1389     {
3449 28 Jul 15 olle 1390       Events.addEventHandler(element, 'click', selectdna.toggleWell);
3449 28 Jul 15 olle 1391       Events.addEventHandler(element, 'mouseover', selectdna.highlightReplicated);
3449 28 Jul 15 olle 1392       Events.addEventHandler(element, 'mouseout', selectdna.highlightReplicated);
3449 28 Jul 15 olle 1393     }
3449 28 Jul 15 olle 1394     else if (autoInit == 'special-select')
3449 28 Jul 15 olle 1395     {
3449 28 Jul 15 olle 1396       Events.addEventHandler(element, 'click', selectdna.specialToggle)
3449 28 Jul 15 olle 1397     }
3449 28 Jul 15 olle 1398   }
3449 28 Jul 15 olle 1399
3449 28 Jul 15 olle 1400   // Toggle the selected status of a single well
3449 28 Jul 15 olle 1401   selectdna.toggleWell = function(event)
3449 28 Jul 15 olle 1402   {
3449 28 Jul 15 olle 1403     var row = Data.int(event.currentTarget, 'row');
3449 28 Jul 15 olle 1404     var column = Data.int(event.currentTarget, 'col');
3449 28 Jul 15 olle 1405     var well = Plate.getWell(row, column);
3449 28 Jul 15 olle 1406     Plate.toggleSelected([well]);
3449 28 Jul 15 olle 1407   }
3449 28 Jul 15 olle 1408
3449 28 Jul 15 olle 1409   // Toggle the selected status of a complete row
3449 28 Jul 15 olle 1410   selectdna.toggleRow = function(event)
3449 28 Jul 15 olle 1411   {
3449 28 Jul 15 olle 1412     var row = Data.int(event.currentTarget, 'row');
3449 28 Jul 15 olle 1413     Plate.toggleSelected(Plate.getRow(row));
3449 28 Jul 15 olle 1414   }
3449 28 Jul 15 olle 1415
3449 28 Jul 15 olle 1416   // Toggle the selected status of a complete column
3449 28 Jul 15 olle 1417   selectdna.toggleColumn = function(event)
3449 28 Jul 15 olle 1418   {
3449 28 Jul 15 olle 1419     var column = Data.int(event.currentTarget, 'col');
3449 28 Jul 15 olle 1420     Plate.toggleSelected(Plate.getColumn(column));
3449 28 Jul 15 olle 1421   }
3449 28 Jul 15 olle 1422   
3449 28 Jul 15 olle 1423   // Toggle the selected status of a pool
3449 28 Jul 15 olle 1424   selectdna.togglePool = function(event)
3449 28 Jul 15 olle 1425   {
3449 28 Jul 15 olle 1426     var pool = Data.int(event.target, 'pool-num');
3449 28 Jul 15 olle 1427     if (!isNaN(pool)) Plate.toggleSelected(Plate.getPool(pool));
3449 28 Jul 15 olle 1428   }
3449 28 Jul 15 olle 1429   
3449 28 Jul 15 olle 1430   // Highlight enable/disable all wells in a column
3449 28 Jul 15 olle 1431   selectdna.highlightColumn = function(event)
3449 28 Jul 15 olle 1432   {
3449 28 Jul 15 olle 1433     var column = Data.int(event.currentTarget, 'col');
3449 28 Jul 15 olle 1434     var on = event.type == 'mouseover';
3449 28 Jul 15 olle 1435     
3449 28 Jul 15 olle 1436     Doc.addOrRemoveClass(event.currentTarget, 'highlight-column', on);
3449 28 Jul 15 olle 1437     var wells = Plate.getColumn(column);
3449 28 Jul 15 olle 1438     Plate.setHighlight(wells, 'highlight-column', on);
3449 28 Jul 15 olle 1439   }
3449 28 Jul 15 olle 1440
3449 28 Jul 15 olle 1441   // Highlight enable/disable all wells in a row
3449 28 Jul 15 olle 1442   selectdna.highlightRow = function(event)
3449 28 Jul 15 olle 1443   {
3449 28 Jul 15 olle 1444     var row = Data.int(event.currentTarget, 'row');
3449 28 Jul 15 olle 1445     var on = event.type == 'mouseover';
3449 28 Jul 15 olle 1446     
3449 28 Jul 15 olle 1447     Doc.addOrRemoveClass(event.currentTarget, 'highlight-row', on);
3449 28 Jul 15 olle 1448     var wells = Plate.getRow(row);
3449 28 Jul 15 olle 1449     Plate.setHighlight(wells, 'highlight-row', on);
3449 28 Jul 15 olle 1450   }
3449 28 Jul 15 olle 1451   
3449 28 Jul 15 olle 1452   // Highligt enable/disable all wells in a pool
3449 28 Jul 15 olle 1453   selectdna.highlightPool = function(event)
3449 28 Jul 15 olle 1454   {
3449 28 Jul 15 olle 1455     var pool = Data.int(event.target, 'pool-num');
3449 28 Jul 15 olle 1456     var on = event.type == 'mouseover';
3449 28 Jul 15 olle 1457     if (!isNaN(pool))
3449 28 Jul 15 olle 1458     {
3449 28 Jul 15 olle 1459       Doc.addOrRemoveClass(event.target, 'highlight-pool', on);
3449 28 Jul 15 olle 1460       var wells = Plate.getPool(pool);
3449 28 Jul 15 olle 1461       Plate.setHighlight(wells, 'highlight-pool', on);
3449 28 Jul 15 olle 1462     }
3449 28 Jul 15 olle 1463   }
3449 28 Jul 15 olle 1464
3449 28 Jul 15 olle 1465   /**
3449 28 Jul 15 olle 1466     Highlight all replicated wells with the same DNA as the given well.
3449 28 Jul 15 olle 1467   */
3449 28 Jul 15 olle 1468   selectdna.highlightReplicated = function(event)
3449 28 Jul 15 olle 1469   {
3449 28 Jul 15 olle 1470     var column = Data.int(event.currentTarget, 'col');
3449 28 Jul 15 olle 1471     var row = Data.int(event.currentTarget, 'row');
3449 28 Jul 15 olle 1472     var on = event.type == 'mouseover';
3449 28 Jul 15 olle 1473     
3449 28 Jul 15 olle 1474     var well = Plate.getWell(row, column);
3449 28 Jul 15 olle 1475     if (well.extract && well.replicate)
3449 28 Jul 15 olle 1476     {
3449 28 Jul 15 olle 1477       // Get center coordinates for the current well
3449 28 Jul 15 olle 1478       var pos = Doc.getElementPosition(well.tag);
3449 28 Jul 15 olle 1479       var jsPos = new jsPoint(pos.left+pos.width/2, pos.top+pos.height/2);
3449 28 Jul 15 olle 1480   
3449 28 Jul 15 olle 1481       var replicated = Plate.getWellsByName(well.extract.name);
3449 28 Jul 15 olle 1482       for (var i = 0; i < replicated.length; i++)
3449 28 Jul 15 olle 1483       {
3449 28 Jul 15 olle 1484         var rep = replicated[i];
3449 28 Jul 15 olle 1485         if (rep != well)
3449 28 Jul 15 olle 1486         {
3449 28 Jul 15 olle 1487           Doc.addOrRemoveClass(rep.tag, 'highlight-replicated', on);
3449 28 Jul 15 olle 1488           if (rep.line)
3449 28 Jul 15 olle 1489           {
3449 28 Jul 15 olle 1490             // Clear any recent lines
3449 28 Jul 15 olle 1491             graphics.clearDrawing(rep.line);
3449 28 Jul 15 olle 1492             rep.line = null;
3449 28 Jul 15 olle 1493           }
3449 28 Jul 15 olle 1494           if (on)
3449 28 Jul 15 olle 1495           {
3449 28 Jul 15 olle 1496             // We draw a line between the current and replicated well
3449 28 Jul 15 olle 1497             var rPos = Doc.getElementPosition(rep.tag);
3449 28 Jul 15 olle 1498             rep.line = graphics.drawLine(pen, jsPos, new jsPoint(rPos.left+rPos.width/2, rPos.top+rPos.height/2));
3449 28 Jul 15 olle 1499           }
3449 28 Jul 15 olle 1500         }
3449 28 Jul 15 olle 1501       }
3449 28 Jul 15 olle 1502     }
3449 28 Jul 15 olle 1503   }
3449 28 Jul 15 olle 1504
3449 28 Jul 15 olle 1505   // Some special toogle operations
3449 28 Jul 15 olle 1506   selectdna.specialToggle = function(event)
3449 28 Jul 15 olle 1507   {
3449 28 Jul 15 olle 1508     var what = Data.get(event.currentTarget, 'special');
3449 28 Jul 15 olle 1509     var wells = [];
3449 28 Jul 15 olle 1510     if (what == 'all' || what == 'empty' || what == 'none')
3449 28 Jul 15 olle 1511     {
3449 28 Jul 15 olle 1512       // All wells or all empty (will be filtered later)
3449 28 Jul 15 olle 1513       wells = Plate.getWells();
3449 28 Jul 15 olle 1514     }
3449 28 Jul 15 olle 1515     else if (what == 'pools' || what == 'empty-pools')
3449 28 Jul 15 olle 1516     {
3449 28 Jul 15 olle 1517       // All primary pools or all empty in the primary pools (will be filtered later)
3449 28 Jul 15 olle 1518       for (var i = 0; i < Plate.poolSchema.numPools; i++)
3449 28 Jul 15 olle 1519       {
3449 28 Jul 15 olle 1520         wells = wells.concat(Plate.getPool(i));
3449 28 Jul 15 olle 1521       }
3449 28 Jul 15 olle 1522     }
3449 28 Jul 15 olle 1523     else if (what == 'stratagene')
3449 28 Jul 15 olle 1524     {
3449 28 Jul 15 olle 1525       // All wells with 'Stratagene'
3449 28 Jul 15 olle 1526       var tmp = Plate.getWells();
3449 28 Jul 15 olle 1527       for (var i = 0; i < tmp.length; i++)
3449 28 Jul 15 olle 1528       {
3449 28 Jul 15 olle 1529         var well = tmp[i];
3449 28 Jul 15 olle 1530         if (well.extract && well.extract.stratagene) wells[wells.length] = well;
3449 28 Jul 15 olle 1531       }
3449 28 Jul 15 olle 1532     }
3449 28 Jul 15 olle 1533     else if (what == 'external')
3449 28 Jul 15 olle 1534     {
3449 28 Jul 15 olle 1535       // All wells with 'External DNA'
3449 28 Jul 15 olle 1536       var tmp = Plate.getWells();
3449 28 Jul 15 olle 1537       for (var i = 0; i < tmp.length; i++)
3449 28 Jul 15 olle 1538       {
3449 28 Jul 15 olle 1539         var well = tmp[i];
3449 28 Jul 15 olle 1540         if (well.extract && well.extract.external) wells[wells.length] = well;
3449 28 Jul 15 olle 1541       }
3449 28 Jul 15 olle 1542     }
3449 28 Jul 15 olle 1543     else if (what == 'replicates')
3449 28 Jul 15 olle 1544     {
3449 28 Jul 15 olle 1545       // All wells with replicated DNA
3449 28 Jul 15 olle 1546       var tmp = Plate.getWells();
3449 28 Jul 15 olle 1547       for (var i = 0; i < tmp.length; i++)
3449 28 Jul 15 olle 1548       {
3449 28 Jul 15 olle 1549         var well = tmp[i];
3449 28 Jul 15 olle 1550         if (well.extract && well.replicate) wells[wells.length] = well;
3449 28 Jul 15 olle 1551       }
3449 28 Jul 15 olle 1552     }
3449 28 Jul 15 olle 1553     else if (what == 'error')
3449 28 Jul 15 olle 1554     {
3449 28 Jul 15 olle 1555       // All wells with an error
3449 28 Jul 15 olle 1556       var tmp = Plate.getWells();
3449 28 Jul 15 olle 1557       for (var i = 0; i < tmp.length; i++)
3449 28 Jul 15 olle 1558       {
3449 28 Jul 15 olle 1559         var well = tmp[i];
3449 28 Jul 15 olle 1560         if (well.hasError()) wells[wells.length] = well;
3449 28 Jul 15 olle 1561       }
3449 28 Jul 15 olle 1562     }
3449 28 Jul 15 olle 1563     else if (what == 'warning')
3449 28 Jul 15 olle 1564     {
3449 28 Jul 15 olle 1565       // All wells with a warning
3449 28 Jul 15 olle 1566       var tmp = Plate.getWells();
3449 28 Jul 15 olle 1567       for (var i = 0; i < tmp.length; i++)
3449 28 Jul 15 olle 1568       {
3449 28 Jul 15 olle 1569         var well = tmp[i];
3449 28 Jul 15 olle 1570         if (well.warning) wells[wells.length] = well;
3449 28 Jul 15 olle 1571       }
3449 28 Jul 15 olle 1572     }
3449 28 Jul 15 olle 1573     
3449 28 Jul 15 olle 1574     // Extra filter for empty wells only
3449 28 Jul 15 olle 1575     if (what.indexOf('empty') != -1)
3449 28 Jul 15 olle 1576     {
3449 28 Jul 15 olle 1577       var tmp = wells;
3449 28 Jul 15 olle 1578       wells = [];
3449 28 Jul 15 olle 1579       for (var i = 0; i < tmp.length; i++)
3449 28 Jul 15 olle 1580       {
3449 28 Jul 15 olle 1581         if (!tmp[i].extract) wells[wells.length] = tmp[i];
3449 28 Jul 15 olle 1582       }
3449 28 Jul 15 olle 1583     }
3449 28 Jul 15 olle 1584     
3449 28 Jul 15 olle 1585     if (what == 'none')
3449 28 Jul 15 olle 1586     {
3449 28 Jul 15 olle 1587       Plate.setSelected(wells, false);
3449 28 Jul 15 olle 1588     }
3449 28 Jul 15 olle 1589     else
3449 28 Jul 15 olle 1590     {
3449 28 Jul 15 olle 1591       Plate.toggleSelected(wells);
3449 28 Jul 15 olle 1592     }
3449 28 Jul 15 olle 1593   }
3449 28 Jul 15 olle 1594
3449 28 Jul 15 olle 1595
3449 28 Jul 15 olle 1596   return selectdna;
3449 28 Jul 15 olle 1597 }();
3449 28 Jul 15 olle 1598
3520 01 Oct 15 olle 1599 Doc.onLoad(SelectDnaRefCode.initPage);
3520 01 Oct 15 olle 1600 Doc.addElementInitializer(SelectDnaRefCode.initElements);
3449 28 Jul 15 olle 1601
3449 28 Jul 15 olle 1602
3449 28 Jul 15 olle 1603 var Dna = function()
3449 28 Jul 15 olle 1604 {
3449 28 Jul 15 olle 1605   var dna = {};
3449 28 Jul 15 olle 1606   var flagged = [];
3449 28 Jul 15 olle 1607   var info = [];
3449 28 Jul 15 olle 1608   
3449 28 Jul 15 olle 1609   /**
3449 28 Jul 15 olle 1610     Create a new DNA object by name. More information
3449 28 Jul 15 olle 1611     about the DNA is automatically loaded from the database.
3449 28 Jul 15 olle 1612   */
3449 28 Jul 15 olle 1613   dna.createByName = function(name)
3449 28 Jul 15 olle 1614   {
3449 28 Jul 15 olle 1615     var tmp = {};
3449 28 Jul 15 olle 1616     tmp.name = name;
3449 28 Jul 15 olle 1617     tmp.stratagene = Meludi.isStratagene(name)
3449 28 Jul 15 olle 1618     tmp.external = Meludi.isExternal(name);
3449 28 Jul 15 olle 1619     tmp.info = dna.infoByName(name);
3449 28 Jul 15 olle 1620 //alert("select_dna.js::dna.createByName(name): name = " + name + " info = " + JSON.stringify(tmp.info));
3449 28 Jul 15 olle 1621     tmp.id = tmp.info.id;
3449 28 Jul 15 olle 1622     return tmp;
3449 28 Jul 15 olle 1623   }
3449 28 Jul 15 olle 1624   
3449 28 Jul 15 olle 1625   /**
3449 28 Jul 15 olle 1626     Create a new DNA object by info object.
3449 28 Jul 15 olle 1627   */
3449 28 Jul 15 olle 1628   dna.createByInfo = function(info)
3449 28 Jul 15 olle 1629   {
3449 28 Jul 15 olle 1630     var tmp = {};
3449 28 Jul 15 olle 1631     tmp.name = info.name;
3449 28 Jul 15 olle 1632     tmp.stratagene = Meludi.isStratagene(tmp.name);
3449 28 Jul 15 olle 1633     tmp.external = Meludi.isExternal(tmp.name);
3449 28 Jul 15 olle 1634     tmp.id = info.id;
3449 28 Jul 15 olle 1635     tmp.info = info;
3449 28 Jul 15 olle 1636     return tmp;
3449 28 Jul 15 olle 1637   }
3449 28 Jul 15 olle 1638   
3449 28 Jul 15 olle 1639   /**
3449 28 Jul 15 olle 1640     Get information about a DNA item with a given name.
3449 28 Jul 15 olle 1641   */
3449 28 Jul 15 olle 1642   dna.infoByName = function(name)
3449 28 Jul 15 olle 1643   {
3449 28 Jul 15 olle 1644     var key = 'N'+name;
3449 28 Jul 15 olle 1645     if (!info[key])
3449 28 Jul 15 olle 1646     {
3449 28 Jul 15 olle 1647       dna.loadInfoByNames([name]);
3449 28 Jul 15 olle 1648       if (!info[key]) info[key] = {};
3449 28 Jul 15 olle 1649     }
3449 28 Jul 15 olle 1650     return info[key];
3449 28 Jul 15 olle 1651   }
3449 28 Jul 15 olle 1652
3449 28 Jul 15 olle 1653   /**
3449 28 Jul 15 olle 1654     Load and cache DNA information for all DNA items with a name in the
3449 28 Jul 15 olle 1655     given list.
3449 28 Jul 15 olle 1656   */
3449 28 Jul 15 olle 1657   dna.loadInfoByNames = function(names)
3449 28 Jul 15 olle 1658   {
3449 28 Jul 15 olle 1659     var newNames = [];
3449 28 Jul 15 olle 1660     for (var i = 0; i < names.length; i++)
3449 28 Jul 15 olle 1661     {
3449 28 Jul 15 olle 1662       if (!info['N'+names[i]]) newNames[newNames.length] = names[i];
3449 28 Jul 15 olle 1663     }
3449 28 Jul 15 olle 1664     
3449 28 Jul 15 olle 1665     var submitInfo = {};
3449 28 Jul 15 olle 1666     submitInfo.names = newNames;
3449 28 Jul 15 olle 1667     
3449 28 Jul 15 olle 1668     if (newNames.length > 0)
3449 28 Jul 15 olle 1669     {
3449 28 Jul 15 olle 1670       var url = '../Dna.servlet?ID='+App.getSessionId();
3449 28 Jul 15 olle 1671       url += '&cmd=GetDnaInfoFromNames';  
3449 28 Jul 15 olle 1672       var response = Wizard.syncJsonRequest(url, 'POST', JSON.stringify(submitInfo));
3449 28 Jul 15 olle 1673       dna.cacheInfo(response.dna);
3449 28 Jul 15 olle 1674     }
3449 28 Jul 15 olle 1675   }
3449 28 Jul 15 olle 1676   
3449 28 Jul 15 olle 1677   dna.cacheInfo = function(dnaList)
3449 28 Jul 15 olle 1678   {
3449 28 Jul 15 olle 1679     for (var i = 0; i < dnaList.length; i++)
3449 28 Jul 15 olle 1680     {
3449 28 Jul 15 olle 1681       var r = dnaList[i];
3449 28 Jul 15 olle 1682       info['N'+r.name] = r;
3449 28 Jul 15 olle 1683       info['I'+r.id] = r;
3449 28 Jul 15 olle 1684       if (r.flag) flagged[flagged.length] = r;
3449 28 Jul 15 olle 1685     }
3449 28 Jul 15 olle 1686   }
3449 28 Jul 15 olle 1687
3449 28 Jul 15 olle 1688   dna.unflag = function(r)
3449 28 Jul 15 olle 1689   {
3449 28 Jul 15 olle 1690     if (!r.info || !r.info.flag) return false;
3449 28 Jul 15 olle 1691
3449 28 Jul 15 olle 1692     r.info.flag = null;
3449 28 Jul 15 olle 1693     for (var i = 0; i < flagged.length; i++)
3449 28 Jul 15 olle 1694     {
3449 28 Jul 15 olle 1695       if (r.id == flagged[i].id)
3449 28 Jul 15 olle 1696       {
3449 28 Jul 15 olle 1697         flagged.splice(i, 1);
3449 28 Jul 15 olle 1698         break;
3449 28 Jul 15 olle 1699       }
3449 28 Jul 15 olle 1700     }
3449 28 Jul 15 olle 1701     return true;
3449 28 Jul 15 olle 1702   }
3449 28 Jul 15 olle 1703   
3449 28 Jul 15 olle 1704   dna.flag = function(r, flag)
3449 28 Jul 15 olle 1705   {
3449 28 Jul 15 olle 1706     if (!r.info || r.info.flag) return false;
3449 28 Jul 15 olle 1707     r.info.flag = flag;
3449 28 Jul 15 olle 1708     flagged[flagged.length] = r.info;
3449 28 Jul 15 olle 1709   }
3449 28 Jul 15 olle 1710   
3449 28 Jul 15 olle 1711   dna.getFlagged = function()
3449 28 Jul 15 olle 1712   {
3449 28 Jul 15 olle 1713     return flagged;
3449 28 Jul 15 olle 1714   }
3449 28 Jul 15 olle 1715   
3449 28 Jul 15 olle 1716   return dna;
3449 28 Jul 15 olle 1717 }();
3449 28 Jul 15 olle 1718
3449 28 Jul 15 olle 1719
3449 28 Jul 15 olle 1720
3449 28 Jul 15 olle 1721 var WellPainter = function()
3449 28 Jul 15 olle 1722 {
3449 28 Jul 15 olle 1723   var painter = {};
3449 28 Jul 15 olle 1724   
3449 28 Jul 15 olle 1725   // Add class indicators for replicates and QC assigned wells
3449 28 Jul 15 olle 1726   painter.getClassNameForWell = function(well)
3449 28 Jul 15 olle 1727   {
3449 28 Jul 15 olle 1728     var cls = '';
3449 28 Jul 15 olle 1729     if (well.extract)
3449 28 Jul 15 olle 1730     {
3449 28 Jul 15 olle 1731       if (well.replicate) cls += ' replicate';
3449 28 Jul 15 olle 1732       if (well.extract.qc) cls += ' qc';
3449 28 Jul 15 olle 1733     }
3449 28 Jul 15 olle 1734     if (well.column == Plate.columns-1) cls += ' last-child';
3449 28 Jul 15 olle 1735     
3449 28 Jul 15 olle 1736     return cls;
3449 28 Jul 15 olle 1737   }
3449 28 Jul 15 olle 1738   
3449 28 Jul 15 olle 1739   painter.getWellText = function(well)
3449 28 Jul 15 olle 1740   {
3449 28 Jul 15 olle 1741     var text = '';
3449 28 Jul 15 olle 1742     if (well.duplicates)
3449 28 Jul 15 olle 1743     {
3449 28 Jul 15 olle 1744       well.setError('Duplicate DNA in this location');
3449 28 Jul 15 olle 1745       text += '<div class="name">'+Strings.encodeTags(well.duplicates.join(', '))+'</div>';
3449 28 Jul 15 olle 1746     }
3449 28 Jul 15 olle 1747     else if (well.extract)
3449 28 Jul 15 olle 1748     {
3449 28 Jul 15 olle 1749       // The well contains DNA
3449 28 Jul 15 olle 1750       var dna = well.extract;
3449 28 Jul 15 olle 1751       var info = dna.info;
3449 28 Jul 15 olle 1752       text += '<div class="name">'+Strings.encodeTags(dna.name)+'</div>';
3449 28 Jul 15 olle 1753 //alert("select_dna.js::getWellText(): info = " + JSON.stringify(info));
3449 28 Jul 15 olle 1754       
3449 28 Jul 15 olle 1755       var warningMsg = [];
3449 28 Jul 15 olle 1756       if (info.bioWell)
3449 28 Jul 15 olle 1757       {
3449 28 Jul 15 olle 1758         var dnaWell = info.bioWell;
3449 28 Jul 15 olle 1759         text += '<div class="location">'+Strings.encodeTags(dnaWell.bioPlate.name+'['+dnaWell.location)+']</div>';
3449 28 Jul 15 olle 1760       }
3449 28 Jul 15 olle 1761       else if (info.preNormalized)
3449 28 Jul 15 olle 1762       {
3449 28 Jul 15 olle 1763         text += '<div class="location">PreNormalized</div>';
3449 28 Jul 15 olle 1764       }
3449 28 Jul 15 olle 1765       else if (!dna.stratagene && !dna.external)
3449 28 Jul 15 olle 1766       {
3449 28 Jul 15 olle 1767         warningMsg[warningMsg.length] = 'No location';
3449 28 Jul 15 olle 1768       }
3449 28 Jul 15 olle 1769
3449 28 Jul 15 olle 1770       if (info && info.id && !dna.stratagene && !dna.external)
3449 28 Jul 15 olle 1771       {
3449 28 Jul 15 olle 1772         var USED_VOL_PER_ALIQUOT = 10.0; // µl
3449 28 Jul 15 olle 1773         var VOL_ALIQUOT = 10.0; // µl
3449 28 Jul 15 olle 1774         var removedVolume = 2 * USED_VOL_PER_ALIQUOT; // µl
3449 28 Jul 15 olle 1775         var deltaCt = info.deltaCt;
3449 28 Jul 15 olle 1776         var dilutionFactor = painter.fetchDilutionFactor(deltaCt);
3449 28 Jul 15 olle 1777         var origConc = info.QubitConc; // ng/µl
3449 28 Jul 15 olle 1778         //var usedQuantityPerAliquout = Math.ceil(VOL_ALIQUOT*origConc/dilutionFactor/1000); // µg
3449 28 Jul 15 olle 1779         //var usedQuantityPerAliquout = VOL_ALIQUOT*origConc/dilutionFactor/1000; // µg
3449 28 Jul 15 olle 1780         var usedQuantityPerAliquout = VOL_ALIQUOT*origConc/dilutionFactor; // ng
3449 28 Jul 15 olle 1781 alert("select_dna.js::painter.getWellText(): name = " + dna.name + " removedVolume = " + removedVolume + " deltaCt = " + deltaCt + " dilutionFactor = " + dilutionFactor + " origConc = " + origConc + " usedQuantityPerAliquout = " + usedQuantityPerAliquout + " ng");
3449 28 Jul 15 olle 1782
3449 28 Jul 15 olle 1783 /*        
3449 28 Jul 15 olle 1784         dna.usedQuantity = dna.qc ? QUANTITY_QC : QUANTITY_REGULAR; // µg
3449 28 Jul 15 olle 1785         dna.dilutionConc = 1000 * dna.usedQuantity / TOTAL_VOLUME; // ng/µl
3449 28 Jul 15 olle 1786
3449 28 Jul 15 olle 1787         var volDNA = Math.ceil(10000*dna.usedQuantity/info.QubitConc) / 10; // µl, rounded to 1 decimal
3449 28 Jul 15 olle 1788         var water = TOTAL_VOLUME - volDNA;
3449 28 Jul 15 olle 1789 */        
3449 28 Jul 15 olle 1790         var volDNA = USED_VOL_PER_ALIQUOT; // µl
3449 28 Jul 15 olle 1791
3449 28 Jul 15 olle 1792         if (removedVolume < MINIMAL_DNA_VOLUME)
3449 28 Jul 15 olle 1793         {
3449 28 Jul 15 olle 1794 /*
3449 28 Jul 15 olle 1795           // Large mix since we do not want to take less than 1µl
3449 28 Jul 15 olle 1796           volDNA = MINIMAL_DNA_VOLUME;
3449 28 Jul 15 olle 1797           dna.usedQuantity = volDNA * info.QubitConc / 1000; // µg
3449 28 Jul 15 olle 1798           var totalVolume = 1000 * dna.usedQuantity / dna.dilutionConc; // µl
3449 28 Jul 15 olle 1799           water = totalVolume - volDNA;
3449 28 Jul 15 olle 1800           warningMsg[warningMsg.length] = 'Large mix';
3449 28 Jul 15 olle 1801 */
3449 28 Jul 15 olle 1802           warningMsg[warningMsg.length] = 'Vol < MINIMAL_DNA_VOLUME = ' + MINIMAL_DNA_VOLUME;
3449 28 Jul 15 olle 1803         }
3449 28 Jul 15 olle 1804         
3449 28 Jul 15 olle 1805         if (info.remainingQuantity)
3449 28 Jul 15 olle 1806         {
3449 28 Jul 15 olle 1807 /*
3449 28 Jul 15 olle 1808           text += '<div class="quantity">'+Numbers.formatNumber(info.remainingQuantity, 2) + 'µg</div>';
3449 28 Jul 15 olle 1809 */
3449 28 Jul 15 olle 1810           var quantityLeft = 1000.0*info.remainingQuantity - 2*usedQuantityPerAliquout; // ng
3449 28 Jul 15 olle 1811 alert("select_dna.js::painter.getWellText(): name = " + dna.name + " info.remainingQuantity = " + info.remainingQuantity + " µg usedQuantityPerAliquout = " + usedQuantityPerAliquout + " ng quantityLeft = " + quantityLeft + " ng");
3449 28 Jul 15 olle 1812 /*
3449 28 Jul 15 olle 1813           text += '<div class="quantity">'+Numbers.formatNumber(quantityLeft, 2) + 'µg '+Numbers.formatNumber(volDNA, 1)+'µl</div>';
3449 28 Jul 15 olle 1814 */
3449 28 Jul 15 olle 1815           text += '<div class="quantity">'+Numbers.formatNumber(usedQuantityPerAliquout, 2) + 'ng '+Numbers.formatNumber(volDNA, 1)+'µl</div>';
3449 28 Jul 15 olle 1816           // Must have at least 1.1µg or 1.22µg (if default values are used)
3449 28 Jul 15 olle 1817           var remainLimit = dna.qc ? QUANTITY_QC : QUANTITY_REGULAR;
3449 28 Jul 15 olle 1818 /*
3449 28 Jul 15 olle 1819           if (info.remainingQuantity < remainLimit)
3449 28 Jul 15 olle 1820           {
3449 28 Jul 15 olle 1821             well.setError('Not enough DNA');
3449 28 Jul 15 olle 1822           }
3449 28 Jul 15 olle 1823           // Warning if near the limit
3449 28 Jul 15 olle 1824           if (info.remainingQuantity < LOW_QUANTITY_WARNING_LIMIT && !info.preNormalized)
3449 28 Jul 15 olle 1825           {
3449 28 Jul 15 olle 1826             warningMsg[warningMsg.length] = 'Low quantity';
3449 28 Jul 15 olle 1827           }
3449 28 Jul 15 olle 1828 */
3449 28 Jul 15 olle 1829           if (quantityLeft < 1000.0*remainLimit)
3449 28 Jul 15 olle 1830           {
3449 28 Jul 15 olle 1831             well.setError('Not enough DNA');
3449 28 Jul 15 olle 1832           }
3449 28 Jul 15 olle 1833           // Warning if near the limit
3449 28 Jul 15 olle 1834           if (quantityLeft < 1000.0*LOW_QUANTITY_WARNING_LIMIT && !info.preNormalized)
3449 28 Jul 15 olle 1835           {
3449 28 Jul 15 olle 1836             warningMsg[warningMsg.length] = 'Low quantity';
3449 28 Jul 15 olle 1837           }
3449 28 Jul 15 olle 1838         }
3449 28 Jul 15 olle 1839         else
3449 28 Jul 15 olle 1840         {
3449 28 Jul 15 olle 1841           warningMsg[warningMsg.length] = 'No quantity';
3449 28 Jul 15 olle 1842         }
3449 28 Jul 15 olle 1843         if (info.deltaCt)
3449 28 Jul 15 olle 1844         {
3449 28 Jul 15 olle 1845           text += '<div class="quality-score">ΔCt='+Numbers.formatNumber(info.deltaCt, 1) + '</div>';
3449 28 Jul 15 olle 1846           if (info.deltaCt > QUALITY_SCORE_WARNING_LIMIT) warningMsg[warningMsg.length] = 'High ΔCt value';
3449 28 Jul 15 olle 1847         }
3449 28 Jul 15 olle 1848         else
3449 28 Jul 15 olle 1849         {
3449 28 Jul 15 olle 1850           warningMsg[warningMsg.length] = 'No ΔCt value';
3449 28 Jul 15 olle 1851         }
3449 28 Jul 15 olle 1852 /*
3449 28 Jul 15 olle 1853         if (info.QubitConc)
3449 28 Jul 15 olle 1854         {
3449 28 Jul 15 olle 1855           text += '<div class="qubitconc">'+Numbers.formatNumber(info.QubitConc, 2) + 'ng/µl</div>';
3449 28 Jul 15 olle 1856           text += '<div class="volumes"><span class="volume">'+Numbers.formatNumber(volDNA, 1)+'</span> + <span class="water">'+Numbers.formatNumber(water, 1)+'µl</span></div>';
3449 28 Jul 15 olle 1857         }
3449 28 Jul 15 olle 1858         else
3449 28 Jul 15 olle 1859         {
3449 28 Jul 15 olle 1860           warningMsg[warningMsg.length] = 'No QubitConc value';
3449 28 Jul 15 olle 1861         }
3449 28 Jul 15 olle 1862 */
3449 28 Jul 15 olle 1863         if (info.QiacubeDate)
3449 28 Jul 15 olle 1864         {
3449 28 Jul 15 olle 1865           text += '<div class="qiacube-date">'+info.QiacubeDate+'</div>';
3449 28 Jul 15 olle 1866         }
3449 28 Jul 15 olle 1867         else if (info.DilutionDate)
3449 28 Jul 15 olle 1868         {
3449 28 Jul 15 olle 1869           text += '<div class="dilution-date">'+info.DilutionDate+'</div>';
3449 28 Jul 15 olle 1870         }
3449 28 Jul 15 olle 1871         else
3449 28 Jul 15 olle 1872         {
3449 28 Jul 15 olle 1873           warningMsg[warningMsg.length] = info.preNormalized ? 'No DilutionDate value' : 'No QiacubeDate value';
3449 28 Jul 15 olle 1874         }
3449 28 Jul 15 olle 1875         if (info.AutoProcessing)
3449 28 Jul 15 olle 1876         {
3449 28 Jul 15 olle 1877           warningMsg[warningMsg.length] = info.AutoProcessing;
3449 28 Jul 15 olle 1878         }
3449 28 Jul 15 olle 1879 /*
3449 28 Jul 15 olle 1880         dna.usedQuantity = dna.qc ? QUANTITY_QC : QUANTITY_REGULAR; // µg
3449 28 Jul 15 olle 1881         dna.dilutionConc = 1000 * dna.usedQuantity / TOTAL_VOLUME; // ng/µl
3449 28 Jul 15 olle 1882
3449 28 Jul 15 olle 1883         var volDNA = Math.ceil(10000*dna.usedQuantity/info.QubitConc) / 10; // µl, rounded to 1 decimal
3449 28 Jul 15 olle 1884         var water = TOTAL_VOLUME - volDNA;
3449 28 Jul 15 olle 1885         
3449 28 Jul 15 olle 1886         if (volDNA < MINIMAL_DNA_VOLUME)
3449 28 Jul 15 olle 1887         {
3449 28 Jul 15 olle 1888           // Large mix since we do not want to take less than 1µl
3449 28 Jul 15 olle 1889           volDNA = MINIMAL_DNA_VOLUME;
3449 28 Jul 15 olle 1890           dna.usedQuantity = volDNA * info.QubitConc / 1000; // µg
3449 28 Jul 15 olle 1891           var totalVolume = 1000 * dna.usedQuantity / dna.dilutionConc; // µl
3449 28 Jul 15 olle 1892           water = totalVolume - volDNA;
3449 28 Jul 15 olle 1893           warningMsg[warningMsg.length] = 'Large mix';
3449 28 Jul 15 olle 1894         }
3449 28 Jul 15 olle 1895         
3449 28 Jul 15 olle 1896         if (info.remainingQuantity)
3449 28 Jul 15 olle 1897         {
3449 28 Jul 15 olle 1898           //text += '<div class="quantity">'+Numbers.formatNumber(info.remainingQuantity, 2) + 'µg</div>';
3449 28 Jul 15 olle 1899           text += '<div class="quantity">'+Numbers.formatNumber(info.remainingQuantity, 2) + 'µg '+Numbers.formatNumber(volDNA, 1)+'µl</div>';
3449 28 Jul 15 olle 1900           // Must have at least 1.1µg or 1.22µg (if default values are used)
3449 28 Jul 15 olle 1901           var remainLimit = dna.qc ? QUANTITY_QC : QUANTITY_REGULAR;
3449 28 Jul 15 olle 1902           if (info.remainingQuantity < remainLimit)
3449 28 Jul 15 olle 1903           {
3449 28 Jul 15 olle 1904             well.setError('Not enough DNA');
3449 28 Jul 15 olle 1905           }
3449 28 Jul 15 olle 1906           // Warning if near the limit
3449 28 Jul 15 olle 1907           if (info.remainingQuantity < LOW_QUANTITY_WARNING_LIMIT && !info.preNormalized)
3449 28 Jul 15 olle 1908           {
3449 28 Jul 15 olle 1909             warningMsg[warningMsg.length] = 'Low quantity';
3449 28 Jul 15 olle 1910           }
3449 28 Jul 15 olle 1911         }
3449 28 Jul 15 olle 1912         else
3449 28 Jul 15 olle 1913         {
3449 28 Jul 15 olle 1914           warningMsg[warningMsg.length] = 'No quantity';
3449 28 Jul 15 olle 1915         }
3449 28 Jul 15 olle 1916         if (info.deltaCt)
3449 28 Jul 15 olle 1917         {
3449 28 Jul 15 olle 1918           text += '<div class="quality-score">ΔCt='+Numbers.formatNumber(info.deltaCt, 1) + '</div>';
3449 28 Jul 15 olle 1919           if (info.deltaCt > QUALITY_SCORE_WARNING_LIMIT) warningMsg[warningMsg.length] = 'High ΔCt value';
3449 28 Jul 15 olle 1920         }
3449 28 Jul 15 olle 1921         else
3449 28 Jul 15 olle 1922         {
3449 28 Jul 15 olle 1923           warningMsg[warningMsg.length] = 'No ΔCt value';
3449 28 Jul 15 olle 1924         }
3449 28 Jul 15 olle 1925         if (info.QubitConc)
3449 28 Jul 15 olle 1926         {
3449 28 Jul 15 olle 1927           text += '<div class="qubitconc">'+Numbers.formatNumber(info.QubitConc, 2) + 'ng/µl</div>';
3449 28 Jul 15 olle 1928           text += '<div class="volumes"><span class="volume">'+Numbers.formatNumber(volDNA, 1)+'</span> + <span class="water">'+Numbers.formatNumber(water, 1)+'µl</span></div>';
3449 28 Jul 15 olle 1929         }
3449 28 Jul 15 olle 1930         else
3449 28 Jul 15 olle 1931         {
3449 28 Jul 15 olle 1932           warningMsg[warningMsg.length] = 'No QubitConc value';
3449 28 Jul 15 olle 1933         }
3449 28 Jul 15 olle 1934         if (info.QiacubeDate)
3449 28 Jul 15 olle 1935         {
3449 28 Jul 15 olle 1936           text += '<div class="qiacube-date">'+info.QiacubeDate+'</div>';
3449 28 Jul 15 olle 1937         }
3449 28 Jul 15 olle 1938         else if (info.DilutionDate)
3449 28 Jul 15 olle 1939         {
3449 28 Jul 15 olle 1940           text += '<div class="dilution-date">'+info.DilutionDate+'</div>';
3449 28 Jul 15 olle 1941         }
3449 28 Jul 15 olle 1942         else
3449 28 Jul 15 olle 1943         {
3449 28 Jul 15 olle 1944           warningMsg[warningMsg.length] = info.preNormalized ? 'No DilutionDate value' : 'No QiacubeDate value';
3449 28 Jul 15 olle 1945         }
3449 28 Jul 15 olle 1946         if (info.AutoProcessing)
3449 28 Jul 15 olle 1947         {
3449 28 Jul 15 olle 1948           warningMsg[warningMsg.length] = info.AutoProcessing;
3449 28 Jul 15 olle 1949         }
3449 28 Jul 15 olle 1950 */
3449 28 Jul 15 olle 1951       }
3449 28 Jul 15 olle 1952       else if (!dna.id)
3449 28 Jul 15 olle 1953       {
3449 28 Jul 15 olle 1954         well.setError('DNA not found');
3449 28 Jul 15 olle 1955       }
3449 28 Jul 15 olle 1956       if (dna.comment)
3449 28 Jul 15 olle 1957       {
3449 28 Jul 15 olle 1958         text += '<div class="comment">'+Strings.encodeTags(dna.comment)+'</div>';
3449 28 Jul 15 olle 1959       }
3449 28 Jul 15 olle 1960       if (info && info.comment)
3449 28 Jul 15 olle 1961       {
3449 28 Jul 15 olle 1962         text += '<div class="comment">'+Strings.encodeTags(info.comment)+'</div>';
3449 28 Jul 15 olle 1963       }
3449 28 Jul 15 olle 1964       if (warningMsg.length > 0)
3449 28 Jul 15 olle 1965       {
3449 28 Jul 15 olle 1966         well.setWarning(warningMsg.join('; '));
3449 28 Jul 15 olle 1967       }
3449 28 Jul 15 olle 1968     }
3449 28 Jul 15 olle 1969     else if (well.copyText)
3449 28 Jul 15 olle 1970     {
3449 28 Jul 15 olle 1971       text = '<div class="copy-text">'+well.copyText+'</div>';
3449 28 Jul 15 olle 1972     }
3449 28 Jul 15 olle 1973     else
3449 28 Jul 15 olle 1974     {
3449 28 Jul 15 olle 1975       text = 'empty';
3449 28 Jul 15 olle 1976     }
3449 28 Jul 15 olle 1977     if (well.duplicate)
3449 28 Jul 15 olle 1978     {
3449 28 Jul 15 olle 1979       well.setError('Duplicate barcode');
3449 28 Jul 15 olle 1980     }
3449 28 Jul 15 olle 1981
3449 28 Jul 15 olle 1982     var bc = Doc.element('barcode.'+well.row+'.'+well.column);
3449 28 Jul 15 olle 1983     if (bc)
3449 28 Jul 15 olle 1984     {
3449 28 Jul 15 olle 1985       var cls = 'barcode-well'
3449 28 Jul 15 olle 1986       cls += well.column == 0 ? ' barcode-left' : ' barcode-right';
3449 28 Jul 15 olle 1987
3449 28 Jul 15 olle 1988       if (well.barcode)
3449 28 Jul 15 olle 1989       {
3449 28 Jul 15 olle 1990         bc.innerHTML = well.barcode.name;
3449 28 Jul 15 olle 1991         var indexSet = painter.barcodeVariant ? painter.barcodeVariant.indexSets[well.column] : null;
3449 28 Jul 15 olle 1992         if (indexSet)
3449 28 Jul 15 olle 1993         {
3449 28 Jul 15 olle 1994           cls += ' ' + indexSet.color;
3449 28 Jul 15 olle 1995         }
3449 28 Jul 15 olle 1996         if (well.defaultBarcode && well.barcode != well.defaultBarcode)
3449 28 Jul 15 olle 1997         {
3449 28 Jul 15 olle 1998           cls += ' bg-modified';
3449 28 Jul 15 olle 1999         }
3449 28 Jul 15 olle 2000         if (well.duplicate)
3449 28 Jul 15 olle 2001         {
3449 28 Jul 15 olle 2002           cls += ' duplicate';
3449 28 Jul 15 olle 2003         }
3449 28 Jul 15 olle 2004       }
3449 28 Jul 15 olle 2005       bc.className = cls;
3449 28 Jul 15 olle 2006     }
3449 28 Jul 15 olle 2007     return text;
3449 28 Jul 15 olle 2008   }
3449 28 Jul 15 olle 2009
3449 28 Jul 15 olle 2010   painter.fetchDilutionFactor = function(deltaCt)
3449 28 Jul 15 olle 2011   {
3449 28 Jul 15 olle 2012     var dilutionFactor = 1.0;
3449 28 Jul 15 olle 2013     if (deltaCt > 0.5 && deltaCt <= 1.5)
3449 28 Jul 15 olle 2014     {
3449 28 Jul 15 olle 2015       dilutionFactor = 2.0;
3449 28 Jul 15 olle 2016     }
3449 28 Jul 15 olle 2017     if (deltaCt > -0.5 && deltaCt <= 0.5)
3449 28 Jul 15 olle 2018     {
3449 28 Jul 15 olle 2019       dilutionFactor = 4.0;
3449 28 Jul 15 olle 2020     }
3449 28 Jul 15 olle 2021     if (deltaCt > -1.5 && deltaCt <= -0.5)
3449 28 Jul 15 olle 2022     {
3449 28 Jul 15 olle 2023       dilutionFactor = 8.0;
3449 28 Jul 15 olle 2024     }
3449 28 Jul 15 olle 2025     if (deltaCt <=- 1.5)
3449 28 Jul 15 olle 2026     {
3449 28 Jul 15 olle 2027       dilutionFactor = 16.0;
3449 28 Jul 15 olle 2028     }
3449 28 Jul 15 olle 2029     return dilutionFactor;
3449 28 Jul 15 olle 2030   }
3449 28 Jul 15 olle 2031   
3449 28 Jul 15 olle 2032   return painter;
3449 28 Jul 15 olle 2033 }();