extensions/net.sf.basedb.reggie/trunk/resources/libprep/create_pools.js

Code
Comments
Other
Rev Date Author Line
2829 17 Oct 14 nicklas 1 var CreatePool = function()
2829 17 Oct 14 nicklas 2 {
2829 17 Oct 14 nicklas 3   var createpool = {};
2853 23 Oct 14 nicklas 4   var debug = 0;
2829 17 Oct 14 nicklas 5   
2829 17 Oct 14 nicklas 6   var targetVolumePerLibIsValid = [];
2829 17 Oct 14 nicklas 7   var POOL_DATA = [];
2837 20 Oct 14 nicklas 8   var USED_POOL_NAMES = [];
2829 17 Oct 14 nicklas 9
2829 17 Oct 14 nicklas 10   // Loaded from servlet when getting Library information
2829 17 Oct 14 nicklas 11   var LIMIT_FOR_AUTO_EXCLUDE = 0.25;
2829 17 Oct 14 nicklas 12   var LIMIT_FOR_EXTRA_LARGE_MIX;
2829 17 Oct 14 nicklas 13   var MAX_TARGET_VOLUME = 20;
2829 17 Oct 14 nicklas 14   var MIN_TARGET_VOLUME = 2;
2829 17 Oct 14 nicklas 15
2829 17 Oct 14 nicklas 16   var LIBRARY_FRAC_ADPT_LIMIT = 10; // percent
2829 17 Oct 14 nicklas 17
2829 17 Oct 14 nicklas 18   
2829 17 Oct 14 nicklas 19   // Page initialization
2829 17 Oct 14 nicklas 20   createpool.initPage = function()
2829 17 Oct 14 nicklas 21   {
2829 17 Oct 14 nicklas 22     // Step 1
2829 17 Oct 14 nicklas 23     Events.addEventHandler('step-1', 'wizard-validate', createpool.validateStep1);
2829 17 Oct 14 nicklas 24     Buttons.addClickHandler('btnCreateManualPool', createpool.createManualPool);
3307 05 May 15 nicklas 25     Buttons.addClickHandler('btnCreateManualPool2', createpool.createManualPool);
2829 17 Oct 14 nicklas 26     
2829 17 Oct 14 nicklas 27     // Step 2
2829 17 Oct 14 nicklas 28     Events.addEventHandler('step-2', 'wizard-initialize', createpool.initializeStep2);
2829 17 Oct 14 nicklas 29     Events.addEventHandler('step-2', 'wizard-validate', createpool.validateStep2);
2829 17 Oct 14 nicklas 30     Buttons.addClickHandler('btnExcludeFromPool', createpool.excludeSelected);
2829 17 Oct 14 nicklas 31     Buttons.addClickHandler('btnIncludeInPool', createpool.includeSelected);
2829 17 Oct 14 nicklas 32     Buttons.addClickHandler('btnSetTargetVolume', createpool.setTargetVolume);
2829 17 Oct 14 nicklas 33     Buttons.addClickHandler('btnFlag', createpool.toggleFlag);
2829 17 Oct 14 nicklas 34     Buttons.addClickHandler('btnComment', createpool.commentSelected);
2931 14 Nov 14 nicklas 35   
2931 14 Nov 14 nicklas 36     // Right-click menu
2931 14 Nov 14 nicklas 37     Events.addEventHandler('plate', 'mouseup', createpool.contextEvent);
2931 14 Nov 14 nicklas 38     Events.addEventHandler('plate', 'contextmenu', createpool.contextEvent);
2931 14 Nov 14 nicklas 39     Events.addEventHandler('mnuExcludeFromPool', 'click', createpool.excludeSelected);
2931 14 Nov 14 nicklas 40     Events.addEventHandler('mnuIncludeInPool', 'click', createpool.includeSelected);
2931 14 Nov 14 nicklas 41     Events.addEventHandler('mnuSetTargetVolume', 'click', createpool.setTargetVolume);
2931 14 Nov 14 nicklas 42     Events.addEventHandler('mnuFlag', 'click', createpool.toggleFlag);
2931 14 Nov 14 nicklas 43     Events.addEventHandler('mnuComment', 'click', createpool.commentSelected);
2931 14 Nov 14 nicklas 44     Events.addEventHandler('mnuCaseSummary', 'click', createpool.showCaseSummary);
2931 14 Nov 14 nicklas 45     Events.addEventHandler(document, 'click', createpool.forgetContext);
2931 14 Nov 14 nicklas 46     
2829 17 Oct 14 nicklas 47     // Navigation
2829 17 Oct 14 nicklas 48     Buttons.addClickHandler('gocancel', Wizard.cancelWizard);
2829 17 Oct 14 nicklas 49     Buttons.addClickHandler('gorestart', Wizard.restartWizard);
2829 17 Oct 14 nicklas 50     Buttons.addClickHandler('gonext', Wizard.goNextOnClick);
2829 17 Oct 14 nicklas 51     Buttons.addClickHandler('goregister', Wizard.goRegister);
2829 17 Oct 14 nicklas 52     
2829 17 Oct 14 nicklas 53     // Final registration
2829 17 Oct 14 nicklas 54     Events.addEventHandler('wizard', 'wizard-submit', createpool.submit);
2829 17 Oct 14 nicklas 55
2829 17 Oct 14 nicklas 56     var url = '../Pool.servlet?ID='+App.getSessionId();
2829 17 Oct 14 nicklas 57     url += '&cmd=GetLibraryPlatesForPooling';
2829 17 Oct 14 nicklas 58     Wizard.showLoadingAnimation('Loading library plates...');
2829 17 Oct 14 nicklas 59     Wizard.asyncJsonRequest(url, createpool.libPlateInfoLoaded);
2829 17 Oct 14 nicklas 60   }
2829 17 Oct 14 nicklas 61   
2829 17 Oct 14 nicklas 62   createpool.libPlateInfoLoaded = function(response)
2829 17 Oct 14 nicklas 63   {
2829 17 Oct 14 nicklas 64     var frm = document.forms['reggie'];
2829 17 Oct 14 nicklas 65
2829 17 Oct 14 nicklas 66     var bioplates = response.bioplates;
2829 17 Oct 14 nicklas 67     var plates = frm.bioplate;
2829 17 Oct 14 nicklas 68     if (bioplates.length > 0)
2829 17 Oct 14 nicklas 69     {
2829 17 Oct 14 nicklas 70       for (var i=0; i < bioplates.length; i++)
2829 17 Oct 14 nicklas 71       {
2829 17 Oct 14 nicklas 72         var bioplate = bioplates[i];
2829 17 Oct 14 nicklas 73         var option = new Option(bioplate.name, bioplate.id);
2829 17 Oct 14 nicklas 74         option.bioplate = bioplate;
2829 17 Oct 14 nicklas 75         plates.options[plates.length] = option;
2829 17 Oct 14 nicklas 76       }
2829 17 Oct 14 nicklas 77       bioplateIsValid = true;
2829 17 Oct 14 nicklas 78       Wizard.setInputStatus('bioplate', 'valid');
2829 17 Oct 14 nicklas 79     }
2829 17 Oct 14 nicklas 80     else
2829 17 Oct 14 nicklas 81     {
2829 17 Oct 14 nicklas 82       Wizard.setFatalError('No Library bioplates available for processing.');
3307 05 May 15 nicklas 83       Doc.show('btnCreateManualPool2');
3307 05 May 15 nicklas 84       Doc.hide('gorestart');
2829 17 Oct 14 nicklas 85       return;
2829 17 Oct 14 nicklas 86     }
2829 17 Oct 14 nicklas 87
2829 17 Oct 14 nicklas 88     Doc.show('step-1');
2829 17 Oct 14 nicklas 89     Doc.show('gonext');
2829 17 Oct 14 nicklas 90   }
2829 17 Oct 14 nicklas 91     
2829 17 Oct 14 nicklas 92   createpool.createManualPool = function()
2829 17 Oct 14 nicklas 93   {
2829 17 Oct 14 nicklas 94     location.replace('create_manual_pool.jsp?ID='+App.getSessionId());
2829 17 Oct 14 nicklas 95   }
2829 17 Oct 14 nicklas 96   
2829 17 Oct 14 nicklas 97   createpool.validateStep1 = function(event)
2829 17 Oct 14 nicklas 98   {}
2829 17 Oct 14 nicklas 99
2829 17 Oct 14 nicklas 100   createpool.initializeStep2 = function()
2829 17 Oct 14 nicklas 101   {
2829 17 Oct 14 nicklas 102     var frm = document.forms['reggie'];
2829 17 Oct 14 nicklas 103     var libPlate = frm.bioplate[frm.bioplate.selectedIndex].bioplate;
2829 17 Oct 14 nicklas 104     var schema = PoolSchema.getById(libPlate.poolSchema);
3310 07 May 15 nicklas 105     var columns = libPlate.columns;
3310 07 May 15 nicklas 106     var rows = libPlate.rows;
2829 17 Oct 14 nicklas 107     
3310 07 May 15 nicklas 108     var html = '<tr id="pool-row"></tr>';
3310 07 May 15 nicklas 109     html += '<tr class="header">';
3310 07 May 15 nicklas 110     html += '<th></th>';
3310 07 May 15 nicklas 111     for (var c = 0; c < columns; c++)
3310 07 May 15 nicklas 112     {
3310 07 May 15 nicklas 113       html += '<th id="col.'+c+'">'+(c+1)+'</th>';
3310 07 May 15 nicklas 114     }
3310 07 May 15 nicklas 115     html += '</tr>';
3310 07 May 15 nicklas 116     html += '<tbody>';
3310 07 May 15 nicklas 117     
3310 07 May 15 nicklas 118     for (var r = 0; r < rows; r++)
3310 07 May 15 nicklas 119     {
3310 07 May 15 nicklas 120       html += '<tr class="row-'+r+'">';
5883 26 Mar 20 nicklas 121       html += '<th id="row.'+r+'" class="rowheader">'+(Reggie.wellToAlpha(r))+'</th>';
3310 07 May 15 nicklas 122
3310 07 May 15 nicklas 123       for (var c = 0; c < columns; c++)
3310 07 May 15 nicklas 124       {
3310 07 May 15 nicklas 125         html += '<td class="well col-'+c+'" id="well.'+r+'.'+c+'"';
3310 07 May 15 nicklas 126         html += ' data-col="'+c+'" data-row="'+r+'"';
3310 07 May 15 nicklas 127         html += ' title="Select/deselect this well"></td>';
3310 07 May 15 nicklas 128       }
3310 07 May 15 nicklas 129       html += '</tr>';
3310 07 May 15 nicklas 130     }
3310 07 May 15 nicklas 131     html += '</tbody>';
3310 07 May 15 nicklas 132     Doc.element('plate').innerHTML = html;
3310 07 May 15 nicklas 133     
3310 07 May 15 nicklas 134     var wells = Doc.element('plate').getElementsByClassName('well');
3310 07 May 15 nicklas 135     for (var i = 0; i < wells.length; i++)
3310 07 May 15 nicklas 136     {
3310 07 May 15 nicklas 137       Events.addEventHandler(wells[i], 'click', createpool.toggleWell);
3310 07 May 15 nicklas 138     }
3310 07 May 15 nicklas 139     
2829 17 Oct 14 nicklas 140     var url = '../Pool.servlet?ID='+App.getSessionId();
2829 17 Oct 14 nicklas 141     url += '&cmd=GetNextAutoGeneratedPoolNames&numNames='+schema.numPools;    
3109 04 Feb 15 nicklas 142     Wizard.showLoadingAnimation('Loading information about pools...');
2829 17 Oct 14 nicklas 143     Wizard.asyncJsonRequest(url, createpool.poolNamesLoaded);
3109 04 Feb 15 nicklas 144   }
2829 17 Oct 14 nicklas 145   
3109 04 Feb 15 nicklas 146   createpool.poolNamesLoaded = function(response)
3109 04 Feb 15 nicklas 147   {
3109 04 Feb 15 nicklas 148     var list = response.names;
3109 04 Feb 15 nicklas 149     for (var i = 0; i < list.length; i++)
3109 04 Feb 15 nicklas 150     {
3109 04 Feb 15 nicklas 151       POOL_NAMES[i] = list[i];
3109 04 Feb 15 nicklas 152     }
3109 04 Feb 15 nicklas 153
3109 04 Feb 15 nicklas 154     var frm = document.forms['reggie'];
3109 04 Feb 15 nicklas 155     var libPlate = frm.bioplate[frm.bioplate.selectedIndex].bioplate;
2829 17 Oct 14 nicklas 156     var url = '../Pool.servlet?ID='+App.getSessionId();
2829 17 Oct 14 nicklas 157     url += '&cmd=GetLibraryInfoForPlate&bioplate='+libPlate.id;    
2829 17 Oct 14 nicklas 158     Wizard.showLoadingAnimation('Loading information about libraries...');
2829 17 Oct 14 nicklas 159     Wizard.asyncJsonRequest(url, createpool.libraryInfoLoaded);
2829 17 Oct 14 nicklas 160   }
2829 17 Oct 14 nicklas 161   
2829 17 Oct 14 nicklas 162   createpool.libraryInfoLoaded = function(response)
2829 17 Oct 14 nicklas 163   {
2829 17 Oct 14 nicklas 164     var frm = document.forms['reggie'];
2829 17 Oct 14 nicklas 165     var libPlate = frm.bioplate[frm.bioplate.selectedIndex].bioplate;
2829 17 Oct 14 nicklas 166
2829 17 Oct 14 nicklas 167     var schema = PoolSchema.getById(libPlate.poolSchema);
2829 17 Oct 14 nicklas 168     var barcodeVariant = PoolSchema.getBarcodeVariantByName(schema, libPlate.barcodeVariant);
2829 17 Oct 14 nicklas 169     Plate.setPoolSchema(schema);
2829 17 Oct 14 nicklas 170     WellPainter.barcodeVariant = barcodeVariant;
3310 07 May 15 nicklas 171     WellPainter.plate = libPlate;
3310 07 May 15 nicklas 172     Plate.init(libPlate.rows, libPlate.columns, schema, WellPainter);
2829 17 Oct 14 nicklas 173
2829 17 Oct 14 nicklas 174     var poolInfo = response.poolInfo;
2829 17 Oct 14 nicklas 175     LIMIT_FOR_EXTRA_LARGE_MIX = poolInfo.limitForExtraLargeMix;
2829 17 Oct 14 nicklas 176     var libs = response.libraries;
3107 27 Jan 15 nicklas 177     var molarityLimit = poolInfo.targetMolarity * LIMIT_FOR_AUTO_EXCLUDE;
2829 17 Oct 14 nicklas 178     for (var i = 0; i < libs.length; i++)
2829 17 Oct 14 nicklas 179     {
2829 17 Oct 14 nicklas 180       var lib = libs[i];
2829 17 Oct 14 nicklas 181       var well = lib.bioWell;
2829 17 Oct 14 nicklas 182       lib.excludeFromPool = false;
3762 19 Feb 16 nicklas 183       lib.isYellow = lib.specimen && lib.specimen.YellowLabel != null;
2829 17 Oct 14 nicklas 184       
2829 17 Oct 14 nicklas 185       if (lib.molarity != null && lib.molarity < molarityLimit)
2829 17 Oct 14 nicklas 186       {
2829 17 Oct 14 nicklas 187         lib.excludeFromPool = true;
2829 17 Oct 14 nicklas 188         lib.flag = 'ExcludedFromPool';
2829 17 Oct 14 nicklas 189         lib.comment = 'Not enough DNA';
2829 17 Oct 14 nicklas 190       }
2829 17 Oct 14 nicklas 191   
2829 17 Oct 14 nicklas 192       Plate.getWell(well.row, well.column).setExtract(lib);
2829 17 Oct 14 nicklas 193     }
2829 17 Oct 14 nicklas 194
2829 17 Oct 14 nicklas 195     Wizard.setCurrentStep(2);
2829 17 Oct 14 nicklas 196     Doc.show('gocancel');
2829 17 Oct 14 nicklas 197     Doc.show('goregister');
2829 17 Oct 14 nicklas 198     
5883 26 Mar 20 nicklas 199     PoolSchema.buildPoolTableRow(schema, libPlate.columns, false, null, null);
2829 17 Oct 14 nicklas 200     createpool.initPoolData(poolInfo.targetVolumePerLib);
2829 17 Oct 14 nicklas 201     createpool.updatePoolData();
2829 17 Oct 14 nicklas 202   }
2829 17 Oct 14 nicklas 203
2829 17 Oct 14 nicklas 204   createpool.initPoolData = function(targetVolumePerLib)
2829 17 Oct 14 nicklas 205   {
2837 20 Oct 14 nicklas 206     var usePoolNo = -1;
2829 17 Oct 14 nicklas 207     for (var poolNo = 0; poolNo < Plate.getPools(); poolNo++)
2829 17 Oct 14 nicklas 208     {
2837 20 Oct 14 nicklas 209       // Count libs
2837 20 Oct 14 nicklas 210       var numLibs = 0;
2837 20 Oct 14 nicklas 211       var wells = Plate.getPool(poolNo);
2837 20 Oct 14 nicklas 212       for (var wellNo = 0; wellNo < wells.length; wellNo++)
2837 20 Oct 14 nicklas 213       {
2837 20 Oct 14 nicklas 214         var well = wells[wellNo];
2837 20 Oct 14 nicklas 215         var lib = well.extract;
2837 20 Oct 14 nicklas 216         if (lib)
2837 20 Oct 14 nicklas 217         {
2837 20 Oct 14 nicklas 218           numLibs++;
2837 20 Oct 14 nicklas 219         }
2837 20 Oct 14 nicklas 220       }
2837 20 Oct 14 nicklas 221       
2829 17 Oct 14 nicklas 222       var poolDiv = Doc.element('pool.'+poolNo);
2837 20 Oct 14 nicklas 223       if (numLibs > 0)
2837 20 Oct 14 nicklas 224       {
2837 20 Oct 14 nicklas 225         usePoolNo++;
2837 20 Oct 14 nicklas 226         USED_POOL_NAMES[poolNo] = POOL_NAMES[usePoolNo];
2837 20 Oct 14 nicklas 227         var html = '';
2837 20 Oct 14 nicklas 228         html += '<div class="pool-name">'+Strings.encodeTags(USED_POOL_NAMES[poolNo])+'</div>';
2837 20 Oct 14 nicklas 229         html += '<div class="pool-data">';
2837 20 Oct 14 nicklas 230         html += '<table class="step-form">';
3107 27 Jan 15 nicklas 231         html += '<tr><td class="prompt">Pool molarity</td>';
3107 27 Jan 15 nicklas 232         html += '<td><select name="target_molarity.'+poolNo+'" id="target_molarity.'+poolNo+'" style="width: 4em;">';
3107 27 Jan 15 nicklas 233         html += '<option value="1">1.0';
3107 27 Jan 15 nicklas 234         html += '<option value="2" selected>2.0';
3107 27 Jan 15 nicklas 235         html += '</select> nM</td>';
3107 27 Jan 15 nicklas 236         html += '<td id="target_molarity.'+poolNo+'.status" class="status">&nbsp;</td></tr>';
2837 20 Oct 14 nicklas 237         html += '<tr><td class="prompt">Volume/lib</td>';
2837 20 Oct 14 nicklas 238         html += '<td><input type="text" name="target_volume.'+poolNo+'" id="target_volume.'+poolNo+'"';
2837 20 Oct 14 nicklas 239         html += ' style="width: 4em;" value="'+targetVolumePerLib+'">';
3107 27 Jan 15 nicklas 240         html += ' µl ('+MIN_TARGET_VOLUME+'--'+MAX_TARGET_VOLUME+')</td>';
2837 20 Oct 14 nicklas 241         html += '<td id="target_volume.'+poolNo+'.status" class="status">&nbsp;</td></tr>';
2837 20 Oct 14 nicklas 242         html += '<tr><td class="prompt">Mixing strategy</td>';
2837 20 Oct 14 nicklas 243         html += '<td colspan="2">';
2837 20 Oct 14 nicklas 244         html += '<label><input type="radio" name="mixing_strategy.'+poolNo+'" id="mixing_strategy.'+poolNo+'.dynamic"';
2837 20 Oct 14 nicklas 245         html += ' value="dynamic" checked>Dynamic</label> ';
2837 20 Oct 14 nicklas 246         html += '<label><input type="radio" name="mixing_strategy.'+poolNo+'" id="mixing_strategy.'+poolNo+'.fixed"';
2837 20 Oct 14 nicklas 247         html += ' value="fixed">Fixed</label>';
2837 20 Oct 14 nicklas 248         html += '</td></tr>';
2837 20 Oct 14 nicklas 249         html += '</table>';
2837 20 Oct 14 nicklas 250         
2837 20 Oct 14 nicklas 251         html += '<textarea name="comment.'+poolNo+'"></textarea>';
2837 20 Oct 14 nicklas 252         html += '</div>';
2837 20 Oct 14 nicklas 253         html += '<div class="pool-summary" id="pool-summary.'+poolNo+'"></div>';
2837 20 Oct 14 nicklas 254         poolDiv.innerHTML = html;
2837 20 Oct 14 nicklas 255         createpool.setTargetVolumePerLib(poolNo, targetVolumePerLib);
2837 20 Oct 14 nicklas 256       }
2837 20 Oct 14 nicklas 257       else
2837 20 Oct 14 nicklas 258       {
2837 20 Oct 14 nicklas 259         poolDiv.innerHTML = '';
2837 20 Oct 14 nicklas 260       }
2829 17 Oct 14 nicklas 261     }
2829 17 Oct 14 nicklas 262     
2829 17 Oct 14 nicklas 263     for (var poolNo = 0; poolNo < Plate.getPools(); poolNo++)
2829 17 Oct 14 nicklas 264     {
3107 27 Jan 15 nicklas 265       Events.addEventHandler('target_molarity.'+poolNo, 'change', createpool.targetMolarityOnChange);
2829 17 Oct 14 nicklas 266       Events.addEventHandler('target_volume.'+poolNo, 'keypress', Events.numberOnly);
2829 17 Oct 14 nicklas 267       Events.addEventHandler('target_volume.'+poolNo, 'change', createpool.targetVolumeOnChange);
2829 17 Oct 14 nicklas 268       Events.doOnEnter('target_volume.'+poolNo, createpool.targetVolumeOnChange);
2829 17 Oct 14 nicklas 269
2829 17 Oct 14 nicklas 270       Events.addEventHandler('mixing_strategy.'+poolNo+'.dynamic', 'click', createpool.mixingStrategyOnChange);
2829 17 Oct 14 nicklas 271       Events.addEventHandler('mixing_strategy.'+poolNo+'.fixed', 'click', createpool.mixingStrategyOnChange);
2829 17 Oct 14 nicklas 272     }
2829 17 Oct 14 nicklas 273   }
2829 17 Oct 14 nicklas 274   
2829 17 Oct 14 nicklas 275   createpool.setTargetVolumePerLib = function(poolNo, targetVolumePerLib)
2829 17 Oct 14 nicklas 276   {
2829 17 Oct 14 nicklas 277     var frm = document.forms['reggie'];
2829 17 Oct 14 nicklas 278     if (targetVolumePerLib)
2829 17 Oct 14 nicklas 279     {
2829 17 Oct 14 nicklas 280       frm['target_volume.'+poolNo].value = targetVolumePerLib;
2829 17 Oct 14 nicklas 281     }
2829 17 Oct 14 nicklas 282     else
2829 17 Oct 14 nicklas 283     {
2829 17 Oct 14 nicklas 284       targetVolumePerLib = parseInt(frm['target_volume.'+poolNo].value);
2829 17 Oct 14 nicklas 285     }
2829 17 Oct 14 nicklas 286     
2829 17 Oct 14 nicklas 287     targetVolumePerLibIsValid[poolNo] = false;
2829 17 Oct 14 nicklas 288     if (targetVolumePerLib < MIN_TARGET_VOLUME || targetVolumePerLib > MAX_TARGET_VOLUME)
2829 17 Oct 14 nicklas 289     {
2829 17 Oct 14 nicklas 290       Wizard.setInputStatus('target_volume.'+poolNo, 'invalid', 'Must be between '+MIN_TARGET_VOLUME+' and '+MAX_TARGET_VOLUME+'µl');
2829 17 Oct 14 nicklas 291       return;
2829 17 Oct 14 nicklas 292     }
2829 17 Oct 14 nicklas 293     
2829 17 Oct 14 nicklas 294     Wizard.setInputStatus('target_volume.'+poolNo, 'valid');
2829 17 Oct 14 nicklas 295     targetVolumePerLibIsValid[poolNo] = true;
2829 17 Oct 14 nicklas 296
2829 17 Oct 14 nicklas 297     // Pre-process the Library items
2829 17 Oct 14 nicklas 298     var mixingStrategy = Forms.getCheckedRadio(frm['mixing_strategy.'+poolNo]).value;
3107 27 Jan 15 nicklas 299     var targetMolarityInPool = parseFloat(frm['target_molarity.'+poolNo].value);
2829 17 Oct 14 nicklas 300     var wells = Plate.getPool(poolNo);
2829 17 Oct 14 nicklas 301     for (var i = 0; i < wells.length; i++)
2829 17 Oct 14 nicklas 302     {
2829 17 Oct 14 nicklas 303       var lib = wells[i].extract;
2829 17 Oct 14 nicklas 304       if (lib)
2829 17 Oct 14 nicklas 305       {
2829 17 Oct 14 nicklas 306         if (lib.remainingQuantity == null)
2829 17 Oct 14 nicklas 307         {
2829 17 Oct 14 nicklas 308           lib.excludeFromPool = true;
2829 17 Oct 14 nicklas 309         }
2829 17 Oct 14 nicklas 310         else
2829 17 Oct 14 nicklas 311         {
3107 27 Jan 15 nicklas 312           PoolMix.calculateLibVolume(lib, targetMolarityInPool, targetVolumePerLib, mixingStrategy);
3107 27 Jan 15 nicklas 313           PoolMix.calculateEbVolume(lib, targetMolarityInPool, targetVolumePerLib, mixingStrategy);
2829 17 Oct 14 nicklas 314         }
2829 17 Oct 14 nicklas 315       }
2829 17 Oct 14 nicklas 316     }
2829 17 Oct 14 nicklas 317   }
2829 17 Oct 14 nicklas 318   
2829 17 Oct 14 nicklas 319   createpool.targetVolumeOnChange = function(event)
2829 17 Oct 14 nicklas 320   {
2829 17 Oct 14 nicklas 321     var poolNo = parseInt(event.target.name.substr(-1));
2829 17 Oct 14 nicklas 322     createpool.setTargetVolumePerLib(poolNo);
2829 17 Oct 14 nicklas 323     createpool.updatePoolData();
2829 17 Oct 14 nicklas 324   }
2829 17 Oct 14 nicklas 325   
2829 17 Oct 14 nicklas 326   createpool.mixingStrategyOnChange = function(event)
2829 17 Oct 14 nicklas 327   {
2829 17 Oct 14 nicklas 328     createpool.targetVolumeOnChange(event);
2829 17 Oct 14 nicklas 329   }
2829 17 Oct 14 nicklas 330   
3107 27 Jan 15 nicklas 331   createpool.targetMolarityOnChange = function(event)
3107 27 Jan 15 nicklas 332   {
3107 27 Jan 15 nicklas 333     createpool.targetVolumeOnChange(event);
3107 27 Jan 15 nicklas 334   }
3107 27 Jan 15 nicklas 335   
3310 07 May 15 nicklas 336   createpool.calculateRemarks = function(plate, lib, schema, barcodeVariant)
2829 17 Oct 14 nicklas 337   {
2829 17 Oct 14 nicklas 338     var well = lib.bioWell;
2829 17 Oct 14 nicklas 339     var remarks = [];
2829 17 Oct 14 nicklas 340
2829 17 Oct 14 nicklas 341     // Check if default barcode has been modified
2829 17 Oct 14 nicklas 342     var indexSet = barcodeVariant.indexSets[well.column];
2829 17 Oct 14 nicklas 343     if (indexSet)
2829 17 Oct 14 nicklas 344     {
2829 17 Oct 14 nicklas 345       var defaultBarcode = indexSet.barcodes[well.row];
2829 17 Oct 14 nicklas 346       if (defaultBarcode && lib.barcode.name != defaultBarcode)
2829 17 Oct 14 nicklas 347       {
2829 17 Oct 14 nicklas 348         remarks[remarks.length] = 'Modified barcode';
2829 17 Oct 14 nicklas 349         lib.barcode.modified = true;
2829 17 Oct 14 nicklas 350       }
2829 17 Oct 14 nicklas 351     }
2829 17 Oct 14 nicklas 352     
2829 17 Oct 14 nicklas 353     if (lib.molarity != null)
2829 17 Oct 14 nicklas 354     {
2829 17 Oct 14 nicklas 355       if (lib.volume != lib.actualVolume)
2829 17 Oct 14 nicklas 356       {
2829 17 Oct 14 nicklas 357         if (lib.volume > lib.remainingVolume)
2829 17 Oct 14 nicklas 358         {
2829 17 Oct 14 nicklas 359           remarks[remarks.length] = 'Low quantity';
2829 17 Oct 14 nicklas 360         }
2829 17 Oct 14 nicklas 361         else 
2829 17 Oct 14 nicklas 362         {
2829 17 Oct 14 nicklas 363           remarks[remarks.length] = 'Low molarity';
2829 17 Oct 14 nicklas 364         }
2829 17 Oct 14 nicklas 365       }
2829 17 Oct 14 nicklas 366
2829 17 Oct 14 nicklas 367       if (lib.speedVacConc != null)
2829 17 Oct 14 nicklas 368       {
2829 17 Oct 14 nicklas 369         remarks[remarks.length] = 'SpeedVac';
2829 17 Oct 14 nicklas 370       }
2829 17 Oct 14 nicklas 371       
2829 17 Oct 14 nicklas 372       if (lib.mixFactor > 1)
2829 17 Oct 14 nicklas 373       {
2829 17 Oct 14 nicklas 374         // Larger mix than default
2829 17 Oct 14 nicklas 375         remarks[remarks.length] = 'Use ' + Numbers.formatNumber(lib.actualVolume+lib.actualEb, 1, 'µl') + ' in pool';
2829 17 Oct 14 nicklas 376       }
2829 17 Oct 14 nicklas 377       
2829 17 Oct 14 nicklas 378     }
2829 17 Oct 14 nicklas 379     
5883 26 Mar 20 nicklas 380     if (lib.libraryFracAdpt == null)
2829 17 Oct 14 nicklas 381     {
5883 26 Mar 20 nicklas 382       remarks[remarks.length] = 'Unknown adapter fraction';
2829 17 Oct 14 nicklas 383     }
5883 26 Mar 20 nicklas 384     else if (lib.libraryFracAdpt > LIBRARY_FRAC_ADPT_LIMIT)
5883 26 Mar 20 nicklas 385     {
5883 26 Mar 20 nicklas 386       remarks[remarks.length] = 'High adapter fraction';
5883 26 Mar 20 nicklas 387     }
2829 17 Oct 14 nicklas 388     
2829 17 Oct 14 nicklas 389     lib.stratagene = Reggie.isStratagene(lib.name);
2829 17 Oct 14 nicklas 390     lib.external = Reggie.isExternal(lib.name);
2829 17 Oct 14 nicklas 391     lib.remarks = remarks;
2829 17 Oct 14 nicklas 392   }
2829 17 Oct 14 nicklas 393
2829 17 Oct 14 nicklas 394   
2829 17 Oct 14 nicklas 395   createpool.updatePoolData = function()
2829 17 Oct 14 nicklas 396   {
2829 17 Oct 14 nicklas 397     var frm = document.forms['reggie'];
2829 17 Oct 14 nicklas 398
2829 17 Oct 14 nicklas 399     var libPlate = frm.bioplate[frm.bioplate.selectedIndex].bioplate;
2829 17 Oct 14 nicklas 400     var schema = PoolSchema.getById(libPlate.poolSchema);
2829 17 Oct 14 nicklas 401     var barcodeVariant = PoolSchema.getBarcodeVariantByName(schema, libPlate.barcodeVariant);
2829 17 Oct 14 nicklas 402
2829 17 Oct 14 nicklas 403     for (var poolNo = 0; poolNo < Plate.getPools(); poolNo++)
2829 17 Oct 14 nicklas 404     {
2829 17 Oct 14 nicklas 405       var numSeparateMix = 0;
2829 17 Oct 14 nicklas 406       var numLowQuantity = 0;
2829 17 Oct 14 nicklas 407       var numExcluded = 0;
2829 17 Oct 14 nicklas 408       
2829 17 Oct 14 nicklas 409       // Get all libs into an array
2829 17 Oct 14 nicklas 410       var libs = [];
2829 17 Oct 14 nicklas 411       var wells = Plate.getPool(poolNo);
2829 17 Oct 14 nicklas 412       for (var wellNo = 0; wellNo < wells.length; wellNo++)
2829 17 Oct 14 nicklas 413       {
2829 17 Oct 14 nicklas 414         var well = wells[wellNo];
2829 17 Oct 14 nicklas 415         var lib = well.extract;
2829 17 Oct 14 nicklas 416         if (lib)
2829 17 Oct 14 nicklas 417         {
2829 17 Oct 14 nicklas 418           if (lib.excludeFromPool)
2829 17 Oct 14 nicklas 419           {
2829 17 Oct 14 nicklas 420             numExcluded++;
2829 17 Oct 14 nicklas 421           }
2829 17 Oct 14 nicklas 422           else
2829 17 Oct 14 nicklas 423           {
2829 17 Oct 14 nicklas 424             libs[libs.length] = lib;
2829 17 Oct 14 nicklas 425           }
2829 17 Oct 14 nicklas 426         }
2829 17 Oct 14 nicklas 427       }
2829 17 Oct 14 nicklas 428       
2837 20 Oct 14 nicklas 429       if (libs.length == 0)
2837 20 Oct 14 nicklas 430       {
2837 20 Oct 14 nicklas 431         // There are no libs in this pool...
2837 20 Oct 14 nicklas 432         Plate.paint(wells);
2837 20 Oct 14 nicklas 433         continue;
2837 20 Oct 14 nicklas 434       }
2837 20 Oct 14 nicklas 435       
2829 17 Oct 14 nicklas 436       // Calculate final pool volumes, molarity, etc.
2829 17 Oct 14 nicklas 437       var targetVolumePerLib = parseFloat(frm['target_volume.'+poolNo].value);
2829 17 Oct 14 nicklas 438       var mixingStrategy = Forms.getCheckedRadio(frm['mixing_strategy.'+poolNo]).value;
3107 27 Jan 15 nicklas 439       var targetMolarityInPool = parseFloat(frm['target_molarity.'+poolNo].value);
3107 27 Jan 15 nicklas 440       var poolInfo = PoolMix.calculateFinalPoolInfo(libs, targetMolarityInPool, targetVolumePerLib, mixingStrategy);
2829 17 Oct 14 nicklas 441       POOL_DATA[poolNo] = poolInfo;
2829 17 Oct 14 nicklas 442       
2829 17 Oct 14 nicklas 443       // Make remarks for each lib
2829 17 Oct 14 nicklas 444       for (var libNo = 0; libNo < libs.length; libNo++)
2829 17 Oct 14 nicklas 445       {
2829 17 Oct 14 nicklas 446         var lib = libs[libNo];
3310 07 May 15 nicklas 447         createpool.calculateRemarks(libPlate, lib, schema, barcodeVariant);
2829 17 Oct 14 nicklas 448         if (lib.eb != 0 || mixingStrategy == 'fixed') numSeparateMix++;
2829 17 Oct 14 nicklas 449         if (lib.volume > lib.actualVolume) numLowQuantity++;
2829 17 Oct 14 nicklas 450       }
2829 17 Oct 14 nicklas 451       
2829 17 Oct 14 nicklas 452       Plate.paint(wells);
2829 17 Oct 14 nicklas 453
2829 17 Oct 14 nicklas 454       var warnMsg = null;
2829 17 Oct 14 nicklas 455       if (poolInfo.ebVolumeExtra < 0) 
2829 17 Oct 14 nicklas 456       {
2829 17 Oct 14 nicklas 457         warnMsg = 'Too many libs with low molarity';
2829 17 Oct 14 nicklas 458       }
2829 17 Oct 14 nicklas 459       
2829 17 Oct 14 nicklas 460       var poolDiv = Doc.element('pool.'+poolNo);
2829 17 Oct 14 nicklas 461       var summaryDiv = Doc.element('pool-summary.'+poolNo);
2829 17 Oct 14 nicklas 462       var poolData = '';
2829 17 Oct 14 nicklas 463       poolData += libs.length + ' libs • ';
2829 17 Oct 14 nicklas 464       poolData += Numbers.formatNumber(poolInfo.molarity, 2, 'nM')+' • ';
2829 17 Oct 14 nicklas 465       poolData += Numbers.formatNumber(poolInfo.totalVolume, 1, 'µl');
2829 17 Oct 14 nicklas 466       if (mixingStrategy == 'dynamic')
2829 17 Oct 14 nicklas 467       {
2829 17 Oct 14 nicklas 468         poolData += ' • <span class="pool-eb">'+Numbers.formatNumber(poolInfo.ebVolumeExtra, 1, 'µl')+'</span>';
2829 17 Oct 14 nicklas 469       }
2829 17 Oct 14 nicklas 470       if (numSeparateMix > 0 || numLowQuantity)
2829 17 Oct 14 nicklas 471       {
2829 17 Oct 14 nicklas 472         poolData += '<br>Separate mix: ' + numSeparateMix;
2829 17 Oct 14 nicklas 473         poolData += ' • Low quantity: ' + numLowQuantity;
2829 17 Oct 14 nicklas 474         poolData += '';
2829 17 Oct 14 nicklas 475       }
2829 17 Oct 14 nicklas 476       
2829 17 Oct 14 nicklas 477       if (warnMsg)
2829 17 Oct 14 nicklas 478       {
2829 17 Oct 14 nicklas 479         Doc.addClass(poolDiv, 'warning');
2829 17 Oct 14 nicklas 480         poolData += '<div class="warning-message">'+warnMsg+'</div>';
2829 17 Oct 14 nicklas 481       }
2829 17 Oct 14 nicklas 482       else
2829 17 Oct 14 nicklas 483       {
2829 17 Oct 14 nicklas 484         Doc.removeClass(poolDiv, 'warning');
2829 17 Oct 14 nicklas 485       }
2829 17 Oct 14 nicklas 486       summaryDiv.innerHTML = poolData;
2829 17 Oct 14 nicklas 487     }
2829 17 Oct 14 nicklas 488   }
2829 17 Oct 14 nicklas 489
2931 14 Nov 14 nicklas 490   var contextWell = null;
2931 14 Nov 14 nicklas 491   var contextX;
2931 14 Nov 14 nicklas 492   var contextY;
2931 14 Nov 14 nicklas 493   createpool.forgetContext = function()
2931 14 Nov 14 nicklas 494   {
2931 14 Nov 14 nicklas 495     contextWell = null;
2931 14 Nov 14 nicklas 496   }
2931 14 Nov 14 nicklas 497
2931 14 Nov 14 nicklas 498   /**
2931 14 Nov 14 nicklas 499     Reacts to 'mouseup' and 'contextmenu' events for the bioplate. 
2931 14 Nov 14 nicklas 500     This should bring up the cut/copy/paste context menu depending on which
2931 14 Nov 14 nicklas 501     mouse button that was clicked.
2931 14 Nov 14 nicklas 502   */
2931 14 Nov 14 nicklas 503   createpool.contextEvent = function(event)
2931 14 Nov 14 nicklas 504   {
2931 14 Nov 14 nicklas 505     // Context menu on 'right' mouse button
2931 14 Nov 14 nicklas 506     // Can't just check the button since two events are sent ('mouseup' and 'contextmenu')
2931 14 Nov 14 nicklas 507     var showContext = event.type == 'contextmenu' && event.button == 2;
2931 14 Nov 14 nicklas 508       
2931 14 Nov 14 nicklas 509     if (showContext)
2931 14 Nov 14 nicklas 510     {
2931 14 Nov 14 nicklas 511       event.preventDefault(); // Prevents the default right-click menu from appearing
2931 14 Nov 14 nicklas 512       
2931 14 Nov 14 nicklas 513       // Get the well that is right-clicked and the Library that is in it
2931 14 Nov 14 nicklas 514       contextWell = null;
2931 14 Nov 14 nicklas 515       var well = event.target;
2931 14 Nov 14 nicklas 516       while (well && (!well.id || well.id.indexOf('well') != 0))
2931 14 Nov 14 nicklas 517       {
2931 14 Nov 14 nicklas 518         well = well.parentNode;
2931 14 Nov 14 nicklas 519       }
2931 14 Nov 14 nicklas 520       if (well)
2931 14 Nov 14 nicklas 521       {
2931 14 Nov 14 nicklas 522         var c = well.id.split(/\./);
2931 14 Nov 14 nicklas 523         var tmp = Plate.getWell(parseInt(c[1]), parseInt(c[2]));
2931 14 Nov 14 nicklas 524         if (tmp.extract) contextWell = tmp;
2931 14 Nov 14 nicklas 525       }
2931 14 Nov 14 nicklas 526       
2931 14 Nov 14 nicklas 527       if (!contextWell) return;
2931 14 Nov 14 nicklas 528       
2931 14 Nov 14 nicklas 529       // Update the context meny
2931 14 Nov 14 nicklas 530       var caseSummaryMenu = Doc.element('mnuCaseSummary');
2931 14 Nov 14 nicklas 531       if (contextWell)
2931 14 Nov 14 nicklas 532       {
2931 14 Nov 14 nicklas 533         caseSummaryMenu.title = 'Show case summary for ' + Strings.encodeTags(contextWell.extract.name);
2931 14 Nov 14 nicklas 534         Doc.show('sepCaseSummary');
2931 14 Nov 14 nicklas 535         Doc.show('mnuCaseSummary');
2931 14 Nov 14 nicklas 536       }
2931 14 Nov 14 nicklas 537       else
2931 14 Nov 14 nicklas 538       {
2931 14 Nov 14 nicklas 539         Doc.hide('sepCaseSummary');
2931 14 Nov 14 nicklas 540         Doc.hide('mnuCaseSummary');
2931 14 Nov 14 nicklas 541       }
2931 14 Nov 14 nicklas 542       
2931 14 Nov 14 nicklas 543       var menu = Doc.element('menuContext');
2931 14 Nov 14 nicklas 544       // 1 pixel offset to avoid losing well focus outline
2931 14 Nov 14 nicklas 545       contextX = event.clientX+1;
2931 14 Nov 14 nicklas 546       contextY = event.clientY+1;
2931 14 Nov 14 nicklas 547       // Need short delay since 'mouseup' are also sent as 'click' events
2931 14 Nov 14 nicklas 548       // to the 'document' object which BASE already have a Menu.hideAll()
2931 14 Nov 14 nicklas 549       // call which would hide the menu immediately
2931 14 Nov 14 nicklas 550       App.debug('show-context:'+contextX+':'+contextY+':'+contextWell);
2931 14 Nov 14 nicklas 551       setTimeout(createpool.showContextMenu, 100);
2931 14 Nov 14 nicklas 552     }
2931 14 Nov 14 nicklas 553   }
2829 17 Oct 14 nicklas 554   
2931 14 Nov 14 nicklas 555   createpool.showContextMenu = function()
2931 14 Nov 14 nicklas 556   {
2931 14 Nov 14 nicklas 557     Menu.showTopMenu('menuContext', contextX, contextY);
2931 14 Nov 14 nicklas 558   }
2931 14 Nov 14 nicklas 559   
2931 14 Nov 14 nicklas 560   createpool.showCaseSummary = function()
2931 14 Nov 14 nicklas 561   {
2931 14 Nov 14 nicklas 562     if (!contextWell) return;
5019 10 Oct 18 nicklas 563     Reggie.openCaseSummaryPopup(contextWell.extract.name);
2931 14 Nov 14 nicklas 564   }
2931 14 Nov 14 nicklas 565   
2829 17 Oct 14 nicklas 566   createpool.validateStep2 = function(event)
2829 17 Oct 14 nicklas 567   {
2829 17 Oct 14 nicklas 568     var numPools = Plate.getPools();
2829 17 Oct 14 nicklas 569     for (var poolNo = 0; poolNo < numPools; poolNo++)
2829 17 Oct 14 nicklas 570     {
2837 20 Oct 14 nicklas 571       if (USED_POOL_NAMES[poolNo] && !targetVolumePerLibIsValid[poolNo]) 
2829 17 Oct 14 nicklas 572       {
2829 17 Oct 14 nicklas 573         event.preventDefault();
2829 17 Oct 14 nicklas 574         return;
2829 17 Oct 14 nicklas 575       }
2829 17 Oct 14 nicklas 576     }
2829 17 Oct 14 nicklas 577   }
2829 17 Oct 14 nicklas 578   
2829 17 Oct 14 nicklas 579   createpool.submit = function()
2829 17 Oct 14 nicklas 580   {
2829 17 Oct 14 nicklas 581     var frm = document.forms['reggie'];
2829 17 Oct 14 nicklas 582
2829 17 Oct 14 nicklas 583     var submitInfo = {};
2829 17 Oct 14 nicklas 584     submitInfo.pools = [];
2829 17 Oct 14 nicklas 585     submitInfo.flagged = [];
2829 17 Oct 14 nicklas 586
2829 17 Oct 14 nicklas 587     var libPlate = frm.bioplate[frm.bioplate.selectedIndex].bioplate;
2829 17 Oct 14 nicklas 588
2829 17 Oct 14 nicklas 589     var numPools = Plate.getPools();
2829 17 Oct 14 nicklas 590     for (var poolNo = 0; poolNo < numPools; poolNo++)
2829 17 Oct 14 nicklas 591     {
2837 20 Oct 14 nicklas 592       if (!USED_POOL_NAMES[poolNo])
2837 20 Oct 14 nicklas 593       {
2837 20 Oct 14 nicklas 594         continue;
2837 20 Oct 14 nicklas 595       }
2829 17 Oct 14 nicklas 596       var wells = Plate.getPool(poolNo);
2837 20 Oct 14 nicklas 597       
2829 17 Oct 14 nicklas 598       var poolInfo = {};
2837 20 Oct 14 nicklas 599       poolInfo.name = USED_POOL_NAMES[poolNo];
3107 27 Jan 15 nicklas 600       poolInfo.targetPoolMolarity = parseFloat(frm['target_molarity.'+poolNo].value);
2829 17 Oct 14 nicklas 601       poolInfo.targetVolumeInPoolPerLib = parseFloat(frm['target_volume.'+poolNo].value);
2829 17 Oct 14 nicklas 602       var mixingStrategy = Forms.getCheckedRadio(frm['mixing_strategy.'+poolNo]).value;
2829 17 Oct 14 nicklas 603       poolInfo.mixingStrategy = mixingStrategy;
2829 17 Oct 14 nicklas 604       poolInfo.comment = frm['comment.'+poolNo].value;
2829 17 Oct 14 nicklas 605       poolInfo.ebVolumeExtra = POOL_DATA[poolNo].ebVolumeExtra;
2829 17 Oct 14 nicklas 606       poolInfo.libPlate = libPlate.id;
2829 17 Oct 14 nicklas 607       poolInfo.libs = [];
2829 17 Oct 14 nicklas 608       poolInfo.excluded = [];
2829 17 Oct 14 nicklas 609         
2829 17 Oct 14 nicklas 610       for (var wellNo = 0; wellNo < wells.length; wellNo++)
2829 17 Oct 14 nicklas 611       {
2829 17 Oct 14 nicklas 612         var lib = wells[wellNo].extract;
2829 17 Oct 14 nicklas 613         if (lib)
2829 17 Oct 14 nicklas 614         {
2829 17 Oct 14 nicklas 615           // We send library id, name and mixin volumes
2829 17 Oct 14 nicklas 616           var tmp = {};
2829 17 Oct 14 nicklas 617           tmp.id = lib.id;
2829 17 Oct 14 nicklas 618           tmp.name = lib.name;
2829 17 Oct 14 nicklas 619           tmp.volume = lib.actualVolume; 
2829 17 Oct 14 nicklas 620           tmp.eb = lib.actualEb;
2829 17 Oct 14 nicklas 621           tmp.mixFactor = lib.mixFactor;
2829 17 Oct 14 nicklas 622           if (lib.mixFactor > 1 && lib.targetVolume && mixingStrategy == 'dynamic') 
2829 17 Oct 14 nicklas 623           {
2829 17 Oct 14 nicklas 624             tmp.targetVolume = lib.targetVolume;
2829 17 Oct 14 nicklas 625           }
2829 17 Oct 14 nicklas 626           tmp.comment = lib.comment;
2829 17 Oct 14 nicklas 627             
2829 17 Oct 14 nicklas 628           if (lib.excludeFromPool)
2829 17 Oct 14 nicklas 629           {
2829 17 Oct 14 nicklas 630             poolInfo.excluded[poolInfo.excluded.length] = tmp;
2829 17 Oct 14 nicklas 631           }
2829 17 Oct 14 nicklas 632           else
2829 17 Oct 14 nicklas 633           {
2829 17 Oct 14 nicklas 634             poolInfo.libs[poolInfo.libs.length] = tmp;
2829 17 Oct 14 nicklas 635           }
2829 17 Oct 14 nicklas 636             
2829 17 Oct 14 nicklas 637           if (lib.flag)
2829 17 Oct 14 nicklas 638           {
2829 17 Oct 14 nicklas 639             tmp.flag = lib.flag;
2829 17 Oct 14 nicklas 640             submitInfo.flagged[submitInfo.flagged.length] = tmp;
2829 17 Oct 14 nicklas 641           }
2829 17 Oct 14 nicklas 642         }
2829 17 Oct 14 nicklas 643       }
2829 17 Oct 14 nicklas 644       
2829 17 Oct 14 nicklas 645       submitInfo.pools[submitInfo.pools.length] = poolInfo;
2829 17 Oct 14 nicklas 646     }
2829 17 Oct 14 nicklas 647
2829 17 Oct 14 nicklas 648     var url = '../Pool.servlet?ID='+App.getSessionId();
2829 17 Oct 14 nicklas 649     url += '&cmd=CreatePools';
2829 17 Oct 14 nicklas 650     Wizard.showLoadingAnimation('Performing registration...');
2829 17 Oct 14 nicklas 651     Wizard.asyncJsonRequest(url, createpool.submissionResults, 'POST', JSON.stringify(submitInfo));
2829 17 Oct 14 nicklas 652   }
2829 17 Oct 14 nicklas 653   
2829 17 Oct 14 nicklas 654   createpool.submissionResults = function(response)
2829 17 Oct 14 nicklas 655   {
2829 17 Oct 14 nicklas 656     Wizard.showFinalMessage(response.messages);
2829 17 Oct 14 nicklas 657     Doc.show('gorestart');
2829 17 Oct 14 nicklas 658   }
2829 17 Oct 14 nicklas 659
2829 17 Oct 14 nicklas 660   createpool.initElements = function(element, autoInit)
2829 17 Oct 14 nicklas 661   {
2829 17 Oct 14 nicklas 662     if (autoInit == 'plate-well')
2829 17 Oct 14 nicklas 663     {
2829 17 Oct 14 nicklas 664       Events.addEventHandler(element, 'click', createpool.toggleWell);
2829 17 Oct 14 nicklas 665     }
2829 17 Oct 14 nicklas 666   }
2829 17 Oct 14 nicklas 667
2829 17 Oct 14 nicklas 668   //Toggle the selected status of a single well
2829 17 Oct 14 nicklas 669   createpool.toggleWell = function(event)
2829 17 Oct 14 nicklas 670   {
2829 17 Oct 14 nicklas 671     var row = Data.int(event.currentTarget, 'row');
2829 17 Oct 14 nicklas 672     var column = Data.int(event.currentTarget, 'col');
2829 17 Oct 14 nicklas 673     var well = Plate.getWell(row, column);
2829 17 Oct 14 nicklas 674     Plate.toggleSelected([well]);
2829 17 Oct 14 nicklas 675   }
2829 17 Oct 14 nicklas 676   
2829 17 Oct 14 nicklas 677   var lastComment = '';
2829 17 Oct 14 nicklas 678   createpool.excludeSelected = function(event)
2829 17 Oct 14 nicklas 679   {
2829 17 Oct 14 nicklas 680     var wells = Plate.getSelected();
2931 14 Nov 14 nicklas 681     if (wells.length == 0 && contextWell) wells = [ contextWell ];
2829 17 Oct 14 nicklas 682     if (wells.length == 0)
2829 17 Oct 14 nicklas 683     {
2829 17 Oct 14 nicklas 684       Forms.showNotification(event.currentTarget, 'No wells have been selected');
2829 17 Oct 14 nicklas 685       return;
2829 17 Oct 14 nicklas 686     }
2829 17 Oct 14 nicklas 687
2829 17 Oct 14 nicklas 688     // See if there is an existing comment
2829 17 Oct 14 nicklas 689     var comment;
2829 17 Oct 14 nicklas 690     for (var i = 0; i < wells.length; i++)
2829 17 Oct 14 nicklas 691     {
2829 17 Oct 14 nicklas 692       var lib = wells[i].extract;
2829 17 Oct 14 nicklas 693       if (lib && lib.comment) 
2829 17 Oct 14 nicklas 694       {
2829 17 Oct 14 nicklas 695         comment = lib.comment;
2829 17 Oct 14 nicklas 696       }
2829 17 Oct 14 nicklas 697     }
2829 17 Oct 14 nicklas 698
2829 17 Oct 14 nicklas 699     comment = prompt('Comment on reason for exclusion', comment || lastComment);
2829 17 Oct 14 nicklas 700     if (comment == null) return;
2829 17 Oct 14 nicklas 701     lastComment = comment;
2829 17 Oct 14 nicklas 702     
2829 17 Oct 14 nicklas 703     if (comment == '') comment = null;
2829 17 Oct 14 nicklas 704     
2829 17 Oct 14 nicklas 705     for (var i = 0; i < wells.length; i++)
2829 17 Oct 14 nicklas 706     {
2829 17 Oct 14 nicklas 707       var well = wells[i];
2829 17 Oct 14 nicklas 708       var lib = well.extract;
2829 17 Oct 14 nicklas 709       if (lib)
2829 17 Oct 14 nicklas 710       {
2829 17 Oct 14 nicklas 711         lib.excludeFromPool = true;
2829 17 Oct 14 nicklas 712         if (!lib.stratagene && !lib.external)
2829 17 Oct 14 nicklas 713         {
2829 17 Oct 14 nicklas 714           lib.flag = 'ExcludedFromPool';
2829 17 Oct 14 nicklas 715           lib.comment = comment;
2829 17 Oct 14 nicklas 716         }
2829 17 Oct 14 nicklas 717       }
2829 17 Oct 14 nicklas 718       well.selected = false;
2829 17 Oct 14 nicklas 719     }
2829 17 Oct 14 nicklas 720     
2829 17 Oct 14 nicklas 721     createpool.updatePoolData();
2829 17 Oct 14 nicklas 722   }
2829 17 Oct 14 nicklas 723
2829 17 Oct 14 nicklas 724   createpool.includeSelected = function(event)
2829 17 Oct 14 nicklas 725   {
2829 17 Oct 14 nicklas 726     var wells = Plate.getSelected();
2931 14 Nov 14 nicklas 727     if (wells.length == 0 && contextWell) wells = [ contextWell ];
2829 17 Oct 14 nicklas 728     if (wells.length == 0)
2829 17 Oct 14 nicklas 729     {
2829 17 Oct 14 nicklas 730       Forms.showNotification(event.currentTarget, 'No wells have been selected');
2829 17 Oct 14 nicklas 731       return;
2829 17 Oct 14 nicklas 732     }
2829 17 Oct 14 nicklas 733
2829 17 Oct 14 nicklas 734     for (var i = 0; i < wells.length; i++)
2829 17 Oct 14 nicklas 735     {
2829 17 Oct 14 nicklas 736       var well = wells[i];
2829 17 Oct 14 nicklas 737       var lib = well.extract;
2829 17 Oct 14 nicklas 738       if (lib)
2829 17 Oct 14 nicklas 739       {
2829 17 Oct 14 nicklas 740         lib.excludeFromPool = false;
2829 17 Oct 14 nicklas 741         lib.flag = null;
2829 17 Oct 14 nicklas 742         lib.oldComment = lib.comment;
2829 17 Oct 14 nicklas 743         lib.comment = null;
2829 17 Oct 14 nicklas 744       }
2829 17 Oct 14 nicklas 745       well.selected = false;
2829 17 Oct 14 nicklas 746     }
2829 17 Oct 14 nicklas 747     createpool.updatePoolData();
2829 17 Oct 14 nicklas 748   }
2829 17 Oct 14 nicklas 749
2829 17 Oct 14 nicklas 750   
2829 17 Oct 14 nicklas 751   //Flag the selected RNA
2829 17 Oct 14 nicklas 752   createpool.toggleFlag = function(event)
2829 17 Oct 14 nicklas 753   {
2829 17 Oct 14 nicklas 754     var wells = Plate.getSelected();
2931 14 Nov 14 nicklas 755     if (wells.length == 0 && contextWell) wells = [ contextWell ];
2829 17 Oct 14 nicklas 756     if (wells.length == 0)
2829 17 Oct 14 nicklas 757     {
2829 17 Oct 14 nicklas 758       Forms.showNotification(event.currentTarget, 'No wells have been selected');
2829 17 Oct 14 nicklas 759       return;
2829 17 Oct 14 nicklas 760     }
2829 17 Oct 14 nicklas 761
2829 17 Oct 14 nicklas 762     var flag = null;
2829 17 Oct 14 nicklas 763     var firstLib = true;
2829 17 Oct 14 nicklas 764     for (var i = 0; i < wells.length; i++)
2829 17 Oct 14 nicklas 765     {
2829 17 Oct 14 nicklas 766       var well = wells[i];
2829 17 Oct 14 nicklas 767       var lib = well.extract;
2829 17 Oct 14 nicklas 768       if (lib)
2829 17 Oct 14 nicklas 769       {
2829 17 Oct 14 nicklas 770         if (firstLib && !lib.excludeFromPool)
2829 17 Oct 14 nicklas 771         {
2829 17 Oct 14 nicklas 772           flag = lib.flag ? null : 'ManualFlag';
2829 17 Oct 14 nicklas 773           firstLib = false;
2829 17 Oct 14 nicklas 774         }
2829 17 Oct 14 nicklas 775         lib.flag = lib.excludeFromPool ? 'ExcludedFromPool' : flag;
2829 17 Oct 14 nicklas 776       }
2829 17 Oct 14 nicklas 777       //well.selected = false;
2829 17 Oct 14 nicklas 778     }
2829 17 Oct 14 nicklas 779     createpool.updatePoolData();
2829 17 Oct 14 nicklas 780   }
2829 17 Oct 14 nicklas 781
2829 17 Oct 14 nicklas 782   //Set a comment on the selected wells
2829 17 Oct 14 nicklas 783   createpool.commentSelected = function(event)
2829 17 Oct 14 nicklas 784   {
2829 17 Oct 14 nicklas 785     var wells = Plate.getSelected();
2931 14 Nov 14 nicklas 786     if (wells.length == 0 && contextWell) wells = [ contextWell ];
2829 17 Oct 14 nicklas 787     if (wells.length == 0)
2829 17 Oct 14 nicklas 788     {
2829 17 Oct 14 nicklas 789       Forms.showNotification(event.currentTarget, 'No wells have been selected');
2829 17 Oct 14 nicklas 790       return;
2829 17 Oct 14 nicklas 791     }
2829 17 Oct 14 nicklas 792       
2829 17 Oct 14 nicklas 793     var count = 0;
2829 17 Oct 14 nicklas 794     var comment;
2829 17 Oct 14 nicklas 795     for (var i = 0; i < wells.length; i++)
2829 17 Oct 14 nicklas 796     {
2829 17 Oct 14 nicklas 797       var well = wells[i];
2829 17 Oct 14 nicklas 798       if (well.extract) 
2829 17 Oct 14 nicklas 799       {
2829 17 Oct 14 nicklas 800         if (well.extract.comment) comment = well.extract.comment;
2829 17 Oct 14 nicklas 801         count++;
2829 17 Oct 14 nicklas 802       }
2829 17 Oct 14 nicklas 803     }
2829 17 Oct 14 nicklas 804       
2829 17 Oct 14 nicklas 805     if (count == 0)
2829 17 Oct 14 nicklas 806     {
2829 17 Oct 14 nicklas 807       Forms.showNotification(event.currentTarget, 'Only empty wells have been selected');
2829 17 Oct 14 nicklas 808       return;
2829 17 Oct 14 nicklas 809     }
2829 17 Oct 14 nicklas 810       
2829 17 Oct 14 nicklas 811     comment = prompt('Comment', comment || lastComment);
2829 17 Oct 14 nicklas 812     if (comment == null) return;
2829 17 Oct 14 nicklas 813       
2829 17 Oct 14 nicklas 814     lastComment = comment;
2829 17 Oct 14 nicklas 815     
2829 17 Oct 14 nicklas 816     if (comment == '') comment = null;
2829 17 Oct 14 nicklas 817     for (var i = 0; i < wells.length; i++)
2829 17 Oct 14 nicklas 818     {
2829 17 Oct 14 nicklas 819       var well = wells[i];
2829 17 Oct 14 nicklas 820       if (well.extract) 
2829 17 Oct 14 nicklas 821       {
2829 17 Oct 14 nicklas 822         well.extract.comment = comment;
2829 17 Oct 14 nicklas 823       }
2829 17 Oct 14 nicklas 824       well.selected = false;
2829 17 Oct 14 nicklas 825     }
2829 17 Oct 14 nicklas 826     
2829 17 Oct 14 nicklas 827     createpool.updatePoolData();
2829 17 Oct 14 nicklas 828   }
2829 17 Oct 14 nicklas 829   
2829 17 Oct 14 nicklas 830   //Set target volume on the selected wells
2829 17 Oct 14 nicklas 831   var lastTargetVolume = null;
2829 17 Oct 14 nicklas 832   createpool.setTargetVolume = function(event)
2829 17 Oct 14 nicklas 833   {
2829 17 Oct 14 nicklas 834     var frm = document.forms['reggie'];
2829 17 Oct 14 nicklas 835
2829 17 Oct 14 nicklas 836     var wells = Plate.getSelected();
2931 14 Nov 14 nicklas 837     if (wells.length == 0 && contextWell) wells = [ contextWell ];
2829 17 Oct 14 nicklas 838     if (wells.length == 0)
2829 17 Oct 14 nicklas 839     {
2829 17 Oct 14 nicklas 840       Forms.showNotification(event.currentTarget, 'No wells have been selected');
2829 17 Oct 14 nicklas 841       return;
2829 17 Oct 14 nicklas 842     }
2829 17 Oct 14 nicklas 843       
2829 17 Oct 14 nicklas 844     var count = 0;
2829 17 Oct 14 nicklas 845     var targetVolume;
2829 17 Oct 14 nicklas 846     for (var i = 0; i < wells.length; i++)
2829 17 Oct 14 nicklas 847     {
2829 17 Oct 14 nicklas 848       var well = wells[i];
2829 17 Oct 14 nicklas 849       if (well.extract && well.extract.mixFactor > 1) 
2829 17 Oct 14 nicklas 850       {
2829 17 Oct 14 nicklas 851         if (well.extract.targetVolume) 
2829 17 Oct 14 nicklas 852         {
2829 17 Oct 14 nicklas 853           targetVolume = well.extract.targetVolume;
2829 17 Oct 14 nicklas 854         }
2829 17 Oct 14 nicklas 855         else
2829 17 Oct 14 nicklas 856         {
2829 17 Oct 14 nicklas 857           var poolNo = Plate.poolSchema.getPoolNumForColumn(well.column);
2829 17 Oct 14 nicklas 858           targetVolume = parseFloat(frm['target_volume.'+poolNo].value);
2829 17 Oct 14 nicklas 859         }
2829 17 Oct 14 nicklas 860         count++;
2829 17 Oct 14 nicklas 861       }
2829 17 Oct 14 nicklas 862     }
2829 17 Oct 14 nicklas 863       
2829 17 Oct 14 nicklas 864     if (count == 0)
2829 17 Oct 14 nicklas 865     {
2829 17 Oct 14 nicklas 866       Forms.showNotification(event.currentTarget, 'Only empty or dynamic-mixed wells have been selected');
2829 17 Oct 14 nicklas 867       return;
2829 17 Oct 14 nicklas 868     }
2829 17 Oct 14 nicklas 869       
2829 17 Oct 14 nicklas 870     targetVolume = parseFloat(prompt('Volume to use in pool ('+LIMIT_FOR_EXTRA_LARGE_MIX+'--'+MAX_TARGET_VOLUME+' µl)', targetVolume || lastTargetVolume || D));
2829 17 Oct 14 nicklas 871     if (isNaN(targetVolume))
2829 17 Oct 14 nicklas 872     {
2829 17 Oct 14 nicklas 873       targetVolume = null;
2829 17 Oct 14 nicklas 874     }
2829 17 Oct 14 nicklas 875     else if (targetVolume > MAX_TARGET_VOLUME)
2829 17 Oct 14 nicklas 876     {
2829 17 Oct 14 nicklas 877       targetVolume = MAX_TARGET_VOLUME;
2829 17 Oct 14 nicklas 878     }
2829 17 Oct 14 nicklas 879     else if (targetVolume < LIMIT_FOR_EXTRA_LARGE_MIX)
2829 17 Oct 14 nicklas 880     {
2829 17 Oct 14 nicklas 881       targetVolume = LIMIT_FOR_EXTRA_LARGE_MIX
2829 17 Oct 14 nicklas 882     }
2829 17 Oct 14 nicklas 883   
2829 17 Oct 14 nicklas 884     
2829 17 Oct 14 nicklas 885     lastTargetVolume = targetVolume;
2829 17 Oct 14 nicklas 886     
2829 17 Oct 14 nicklas 887     if (targetVolume == '') targetVolume = null;
2829 17 Oct 14 nicklas 888     var frm = document.forms['reggie'];
2829 17 Oct 14 nicklas 889     for (var i = 0; i < wells.length; i++)
2829 17 Oct 14 nicklas 890     {
2829 17 Oct 14 nicklas 891       var well = wells[i];
2829 17 Oct 14 nicklas 892       if (well.extract) 
2829 17 Oct 14 nicklas 893       {
2829 17 Oct 14 nicklas 894         var lib = well.extract;
2829 17 Oct 14 nicklas 895         lib.targetVolume = targetVolume;
2829 17 Oct 14 nicklas 896         var poolNo = Plate.poolSchema.getPoolNumForColumn(lib.bioWell.column);
2829 17 Oct 14 nicklas 897         
2829 17 Oct 14 nicklas 898         var targetVolumePerLib = parseFloat(frm['target_volume.'+poolNo].value);
2829 17 Oct 14 nicklas 899         var mixingStrategy = Forms.getCheckedRadio(frm['mixing_strategy.'+poolNo]).value;
3107 27 Jan 15 nicklas 900         var targetMolarityInPool = parseFloat(frm['target_molarity.'+poolNo].value);
3107 27 Jan 15 nicklas 901         PoolMix.calculateEbVolume(lib, targetMolarityInPool, targetVolumePerLib, mixingStrategy);
2829 17 Oct 14 nicklas 902       }
2829 17 Oct 14 nicklas 903       well.selected = false;
2829 17 Oct 14 nicklas 904     }
2829 17 Oct 14 nicklas 905     
2829 17 Oct 14 nicklas 906     createpool.updatePoolData();
2829 17 Oct 14 nicklas 907   }
2829 17 Oct 14 nicklas 908
2829 17 Oct 14 nicklas 909
2829 17 Oct 14 nicklas 910   return createpool;
2829 17 Oct 14 nicklas 911 }();
2829 17 Oct 14 nicklas 912
2829 17 Oct 14 nicklas 913 Doc.onLoad(CreatePool.initPage);
2829 17 Oct 14 nicklas 914 Doc.addElementInitializer(CreatePool.initElements);
2829 17 Oct 14 nicklas 915
2829 17 Oct 14 nicklas 916 var WellPainter = function()
2829 17 Oct 14 nicklas 917 {
2829 17 Oct 14 nicklas 918   var painter = {};
2829 17 Oct 14 nicklas 919   
2829 17 Oct 14 nicklas 920   painter.getClassNameForWell = function(well, schema)
2829 17 Oct 14 nicklas 921   {
2829 17 Oct 14 nicklas 922     var indexSet = painter.barcodeVariant.indexSets[well.column];
2829 17 Oct 14 nicklas 923     var cls = '';
2829 17 Oct 14 nicklas 924     var lib = well.extract;
2829 17 Oct 14 nicklas 925     
2829 17 Oct 14 nicklas 926     if (lib)
2829 17 Oct 14 nicklas 927     {
2829 17 Oct 14 nicklas 928       if (lib.excludeFromPool)
2829 17 Oct 14 nicklas 929       {
2829 17 Oct 14 nicklas 930         cls += ' exclude-from-pool';
2829 17 Oct 14 nicklas 931       }
2829 17 Oct 14 nicklas 932       else if (indexSet)
2829 17 Oct 14 nicklas 933       {
2829 17 Oct 14 nicklas 934         cls += ' ' + (lib && lib.barcode.modified ? 'bg-modified' : indexSet.color);
2829 17 Oct 14 nicklas 935       }
2829 17 Oct 14 nicklas 936       if (lib.flag)
2829 17 Oct 14 nicklas 937       {
2829 17 Oct 14 nicklas 938         cls += ' flagged';
2829 17 Oct 14 nicklas 939       }
2829 17 Oct 14 nicklas 940       if (!lib.flag && lib.actualVolume < lib.volume)
2829 17 Oct 14 nicklas 941       {
2829 17 Oct 14 nicklas 942         cls += ' low-volume';
2829 17 Oct 14 nicklas 943       }
5883 26 Mar 20 nicklas 944       if (lib.libraryFracAdpt == null || lib.libraryFracAdpt > CreatePool.LIBRARY_FRAC_ADPT_LIMIT)
2829 17 Oct 14 nicklas 945       {
2829 17 Oct 14 nicklas 946         cls += ' high-adapter';
2829 17 Oct 14 nicklas 947       }
3762 19 Feb 16 nicklas 948       if (lib.isYellow)
3762 19 Feb 16 nicklas 949       {
3762 19 Feb 16 nicklas 950         cls += ' yellow-specimen';
3762 19 Feb 16 nicklas 951       }
2829 17 Oct 14 nicklas 952
2829 17 Oct 14 nicklas 953     }
2829 17 Oct 14 nicklas 954     else if (indexSet)
2829 17 Oct 14 nicklas 955     {
2829 17 Oct 14 nicklas 956       cls += indexSet.color;
2829 17 Oct 14 nicklas 957     }
2829 17 Oct 14 nicklas 958     return cls;
2829 17 Oct 14 nicklas 959   }
2829 17 Oct 14 nicklas 960   
2829 17 Oct 14 nicklas 961   painter.getWellText = function(well, schema)
2829 17 Oct 14 nicklas 962   {
2829 17 Oct 14 nicklas 963     var text = '';
2829 17 Oct 14 nicklas 964     var lib = well.extract;
2829 17 Oct 14 nicklas 965     if (lib)
2829 17 Oct 14 nicklas 966     {
2829 17 Oct 14 nicklas 967       var name = lib.name;
2829 17 Oct 14 nicklas 968       var i = name.indexOf('.m');
3762 19 Feb 16 nicklas 969       if (i < 0) i = name.indexOf('.lib');
2829 17 Oct 14 nicklas 970       var mixFactor = lib.mixFactor;
3310 07 May 15 nicklas 971       var displayName = i == -1 ? Strings.encodeTags(name) : Strings.encodeTags(name.substring(0, i+1))+'<br>&nbsp;'+Strings.encodeTags(name.substring(i));
3762 19 Feb 16 nicklas 972       text += '<div class="lib if-yellow">'+displayName+'</div>';
2829 17 Oct 14 nicklas 973       text += '<div>';
2829 17 Oct 14 nicklas 974 //      text += '<span class="barcode">'+lib.barcode.name+'</span>';
2829 17 Oct 14 nicklas 975       text += '<span class="adapter">'+(lib.libraryFracAdpt != null ? lib.libraryFracAdpt + '%' : '—') + '</span>';
2829 17 Oct 14 nicklas 976       if (lib.molarity != null)
2829 17 Oct 14 nicklas 977       {
2829 17 Oct 14 nicklas 978         text += '<span class="molarity">'+Numbers.formatNumber(lib.molarity, 2, 'nM')+'</span>';
2829 17 Oct 14 nicklas 979       }
2829 17 Oct 14 nicklas 980       text += '</div>';
2829 17 Oct 14 nicklas 981       if (!lib.excludeFromPool)
2829 17 Oct 14 nicklas 982       {
2829 17 Oct 14 nicklas 983         mark = (lib.volume > lib.actualVolume) ? '*' : '';
2829 17 Oct 14 nicklas 984         text += '<div>';
2829 17 Oct 14 nicklas 985         text += '<span class="volume">'+(isFinite(lib.volume) ? Numbers.formatNumber(lib.volume*mixFactor, 1, 'µl'+mark) : '∞')+'</span>';
2829 17 Oct 14 nicklas 986         if (lib.mixingStrategy == 'fixed' || lib.mixFactor > 1)
2829 17 Oct 14 nicklas 987         {
2829 17 Oct 14 nicklas 988           text += '<span class="eb">'+(isFinite(lib.eb) ? Numbers.formatNumber(lib.eb*mixFactor, 1, 'µl') : '-∞')+'</span>';
2829 17 Oct 14 nicklas 989         }
2829 17 Oct 14 nicklas 990         else
2829 17 Oct 14 nicklas 991         {
2829 17 Oct 14 nicklas 992           text += '<span class="eb">—</span>';
2829 17 Oct 14 nicklas 993         }
2829 17 Oct 14 nicklas 994         text += '</div>';
2829 17 Oct 14 nicklas 995       }
2829 17 Oct 14 nicklas 996       if (lib.remarks) text += '<div class="remarks">'+ lib.remarks.join('; ') + '</div>';
2829 17 Oct 14 nicklas 997       if (lib.comment)
2829 17 Oct 14 nicklas 998       {
2829 17 Oct 14 nicklas 999         text += '<div class="remarks">'+ lib.comment + '</div>';
2829 17 Oct 14 nicklas 1000       }
2829 17 Oct 14 nicklas 1001     }
2829 17 Oct 14 nicklas 1002     return text;
2829 17 Oct 14 nicklas 1003   }
2829 17 Oct 14 nicklas 1004
2829 17 Oct 14 nicklas 1005   return painter;
2829 17 Oct 14 nicklas 1006 }();
2829 17 Oct 14 nicklas 1007