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

Code
Comments
Other
Rev Date Author Line
2933 14 Nov 14 olle 1
2933 14 Nov 14 olle 2 var Plate = function()
2933 14 Nov 14 olle 3 {
2933 14 Nov 14 olle 4   var plate = {};
2933 14 Nov 14 olle 5   plate.rows = 8;
2933 14 Nov 14 olle 6   plate.columns = 12;
2933 14 Nov 14 olle 7   plate.wells = [];
2933 14 Nov 14 olle 8   plate.poolSchema = null;
2933 14 Nov 14 olle 9   plate.wellPainter = null;
2933 14 Nov 14 olle 10   
2933 14 Nov 14 olle 11   /**
2933 14 Nov 14 olle 12     Initialize a plate with the given number of rows and columns.
2933 14 Nov 14 olle 13   */
2933 14 Nov 14 olle 14   plate.init = function(rows, columns, poolSchema, wellPainter)
2933 14 Nov 14 olle 15   {
2933 14 Nov 14 olle 16     if (rows) plate.rows = rows;
2933 14 Nov 14 olle 17     if (columns) plate.columns = columns;
2933 14 Nov 14 olle 18     if (poolSchema) plate.poolSchema = poolSchema;
2933 14 Nov 14 olle 19     if (wellPainter) plate.wellPainter = wellPainter;
2933 14 Nov 14 olle 20     
2933 14 Nov 14 olle 21     for (var c = 0; c < plate.columns; c++)
2933 14 Nov 14 olle 22     {
2933 14 Nov 14 olle 23       for (var r = 0; r < plate.rows; r++)
2933 14 Nov 14 olle 24       {
2933 14 Nov 14 olle 25         plate.wells[plate.wells.length] = new Well(r, c);
2933 14 Nov 14 olle 26       }
2933 14 Nov 14 olle 27     }
2933 14 Nov 14 olle 28   }
2933 14 Nov 14 olle 29   
2933 14 Nov 14 olle 30   /**
2933 14 Nov 14 olle 31     Change the pool layout schema for the plate.
2933 14 Nov 14 olle 32   */
2933 14 Nov 14 olle 33   plate.setPoolSchema = function(poolSchema)
2933 14 Nov 14 olle 34   {
2933 14 Nov 14 olle 35     plate.poolSchema = poolSchema;
2933 14 Nov 14 olle 36   }
2933 14 Nov 14 olle 37
2933 14 Nov 14 olle 38   /**
2933 14 Nov 14 olle 39     Change the well painter for the plate.
2933 14 Nov 14 olle 40   */
2933 14 Nov 14 olle 41   plate.setWellPainter = function(wellPainter)
2933 14 Nov 14 olle 42   {
2933 14 Nov 14 olle 43     plate.wellPainter = wellPainter;
2933 14 Nov 14 olle 44   }
2933 14 Nov 14 olle 45   
2933 14 Nov 14 olle 46   /**
2933 14 Nov 14 olle 47     Get the number of rows on the plate.
2933 14 Nov 14 olle 48   */
2933 14 Nov 14 olle 49   plate.getRows = function()
2933 14 Nov 14 olle 50   {
2933 14 Nov 14 olle 51     return plate.rows;
2933 14 Nov 14 olle 52   }
2933 14 Nov 14 olle 53
2933 14 Nov 14 olle 54   /**
2933 14 Nov 14 olle 55     Get the number of columns on the plate.
2933 14 Nov 14 olle 56   */
2933 14 Nov 14 olle 57   plate.getColumns = function()
2933 14 Nov 14 olle 58   {
2933 14 Nov 14 olle 59     return plate.columns;
2933 14 Nov 14 olle 60   }
2933 14 Nov 14 olle 61
2933 14 Nov 14 olle 62   /**
2933 14 Nov 14 olle 63     Get the number of pools on the plate.
2933 14 Nov 14 olle 64     If no schema has been set, 0 is returned.
2933 14 Nov 14 olle 65   */
2933 14 Nov 14 olle 66   plate.getPools = function()
2933 14 Nov 14 olle 67   {
2933 14 Nov 14 olle 68     return plate.poolSchema ? plate.poolSchema.numPools : 0;
2933 14 Nov 14 olle 69   }
2933 14 Nov 14 olle 70   
2933 14 Nov 14 olle 71   /**
2933 14 Nov 14 olle 72     Get all wells on the plate.
2933 14 Nov 14 olle 73   */
2933 14 Nov 14 olle 74   plate.getWells = function()
2933 14 Nov 14 olle 75   {
2933 14 Nov 14 olle 76     return plate.wells;
2933 14 Nov 14 olle 77   }
2933 14 Nov 14 olle 78   
2933 14 Nov 14 olle 79   /**
2933 14 Nov 14 olle 80     Get all wells in the given row. First row is 0.
2933 14 Nov 14 olle 81   */
2933 14 Nov 14 olle 82   plate.getRow = function(row)
2933 14 Nov 14 olle 83   {
2933 14 Nov 14 olle 84     var result = [];
2933 14 Nov 14 olle 85     for (var i = row; result.length < plate.columns; i += plate.rows)
2933 14 Nov 14 olle 86     {
2933 14 Nov 14 olle 87       result[result.length] = plate.wells[i];
2933 14 Nov 14 olle 88     }
2933 14 Nov 14 olle 89     return result;
2933 14 Nov 14 olle 90   }
2933 14 Nov 14 olle 91   
2933 14 Nov 14 olle 92   /**
2933 14 Nov 14 olle 93     Get all wells in the given column. First column is 0.
2933 14 Nov 14 olle 94   */
2933 14 Nov 14 olle 95   plate.getColumn = function(column)
2933 14 Nov 14 olle 96   {
2933 14 Nov 14 olle 97     var result = [];
2933 14 Nov 14 olle 98     for (var i = column*plate.rows; result.length < plate.rows; i++)
2933 14 Nov 14 olle 99     {
2933 14 Nov 14 olle 100       result[result.length] = plate.wells[i];
2933 14 Nov 14 olle 101     }
2933 14 Nov 14 olle 102     return result;
2933 14 Nov 14 olle 103   }
2933 14 Nov 14 olle 104
2933 14 Nov 14 olle 105   
2933 14 Nov 14 olle 106   /**
2933 14 Nov 14 olle 107     Get all wells in the given pool number. Which wells are selected,
2933 14 Nov 14 olle 108     depends on the pool schema. First pool number is 0.
2933 14 Nov 14 olle 109   */
2933 14 Nov 14 olle 110   plate.getPool = function(poolNum)
2933 14 Nov 14 olle 111   {
2933 14 Nov 14 olle 112     return plate.poolSchema.getWellsInPool(plate, poolNum);
2933 14 Nov 14 olle 113   }
2933 14 Nov 14 olle 114
2933 14 Nov 14 olle 115   /**
2933 14 Nov 14 olle 116     Get the well at the given coordinate.
2933 14 Nov 14 olle 117   */
2933 14 Nov 14 olle 118   plate.getWell = function(row, column)
2933 14 Nov 14 olle 119   {
2933 14 Nov 14 olle 120     return plate.wells[row + column * plate.rows];
2933 14 Nov 14 olle 121   }
2933 14 Nov 14 olle 122   
2933 14 Nov 14 olle 123   /**
2933 14 Nov 14 olle 124     Get all wells that contains extract with a given name.
2933 14 Nov 14 olle 125   */
2933 14 Nov 14 olle 126   plate.getWellsByName = function(name)
2933 14 Nov 14 olle 127   {
2933 14 Nov 14 olle 128     var result = [];
2933 14 Nov 14 olle 129     for (var i = 0; i < plate.wells.length; i++)
2933 14 Nov 14 olle 130     {
2933 14 Nov 14 olle 131       var well = plate.wells[i];
2933 14 Nov 14 olle 132       if (well.extract && well.extract.name == name)
2933 14 Nov 14 olle 133       {
2933 14 Nov 14 olle 134         result[result.length] = plate.wells[i];
2933 14 Nov 14 olle 135       }
2933 14 Nov 14 olle 136     }
2933 14 Nov 14 olle 137     return result;
2933 14 Nov 14 olle 138   }
2933 14 Nov 14 olle 139   
2933 14 Nov 14 olle 140   /**
2933 14 Nov 14 olle 141     Get all wells that are selected.
2933 14 Nov 14 olle 142   */
2933 14 Nov 14 olle 143   plate.getSelected = function()
2933 14 Nov 14 olle 144   {
2933 14 Nov 14 olle 145     var selected = [];
2933 14 Nov 14 olle 146     for (var i = 0; i < plate.wells.length; i++)
2933 14 Nov 14 olle 147     {
2933 14 Nov 14 olle 148       var well = plate.wells[i];
2933 14 Nov 14 olle 149       if (well.selected)
2933 14 Nov 14 olle 150       {
2933 14 Nov 14 olle 151         selected[selected.length] = well;
2933 14 Nov 14 olle 152       }
2933 14 Nov 14 olle 153     }
2933 14 Nov 14 olle 154     return selected;
2933 14 Nov 14 olle 155   }
2933 14 Nov 14 olle 156
2933 14 Nov 14 olle 157   /**
2933 14 Nov 14 olle 158     Set the selected status for all wells in the array.
2933 14 Nov 14 olle 159     The wells are automatically repainted.
2933 14 Nov 14 olle 160   */
2933 14 Nov 14 olle 161   plate.setSelected = function(wells, select)
2933 14 Nov 14 olle 162   {
2933 14 Nov 14 olle 163     for (var i = 0; i < wells.length; i++)
2933 14 Nov 14 olle 164     {
2933 14 Nov 14 olle 165       var well = wells[i];
2933 14 Nov 14 olle 166       well.selected = select;
2933 14 Nov 14 olle 167       well.paint(plate.wellPainter, plate.poolSchema);
2933 14 Nov 14 olle 168     }
2933 14 Nov 14 olle 169   }
2933 14 Nov 14 olle 170   
2933 14 Nov 14 olle 171   /**
2933 14 Nov 14 olle 172     Toggle the selected status for all wells in the array.
2933 14 Nov 14 olle 173     The next status is determined by the current status of 
2933 14 Nov 14 olle 174     the first well in the array.
2933 14 Nov 14 olle 175   */
2933 14 Nov 14 olle 176   plate.toggleSelected = function(wells)
2933 14 Nov 14 olle 177   {
2933 14 Nov 14 olle 178     if (wells.length == 0) return;
2933 14 Nov 14 olle 179     plate.setSelected(wells, !wells[0].selected);
2933 14 Nov 14 olle 180   }
2933 14 Nov 14 olle 181   
2933 14 Nov 14 olle 182   /**
2933 14 Nov 14 olle 183     Enable or disable highlight of the given wells.
2933 14 Nov 14 olle 184   */
2933 14 Nov 14 olle 185   plate.setHighlight = function(wells, highlightClass, on)
2933 14 Nov 14 olle 186   {
2933 14 Nov 14 olle 187     var tmpClass = on ? highlightClass : null;
2933 14 Nov 14 olle 188     for (var i = 0; i < wells.length; i++)
2933 14 Nov 14 olle 189     {
2933 14 Nov 14 olle 190       var well = wells[i];
2933 14 Nov 14 olle 191       well.highlightClass = tmpClass;
2933 14 Nov 14 olle 192       Doc.addOrRemoveClass(well.tag, highlightClass, on);
2933 14 Nov 14 olle 193     }
2933 14 Nov 14 olle 194   }
2933 14 Nov 14 olle 195   
2933 14 Nov 14 olle 196   /**
2933 14 Nov 14 olle 197     Paint the given wells.
2933 14 Nov 14 olle 198   */
2933 14 Nov 14 olle 199   plate.paint = function(wells)
2933 14 Nov 14 olle 200   {
2933 14 Nov 14 olle 201     for (var i = 0; i < wells.length; i++)
2933 14 Nov 14 olle 202     {
2933 14 Nov 14 olle 203       wells[i].paint(plate.wellPainter, plate.poolSchema);
2933 14 Nov 14 olle 204     }
2933 14 Nov 14 olle 205   }
2933 14 Nov 14 olle 206   
2933 14 Nov 14 olle 207   /**
2933 14 Nov 14 olle 208     Check if the plate have any replicated extracts. Eg. extracts that are
2933 14 Nov 14 olle 209     found in more than one well. If a name is given, only extracts with that
2933 14 Nov 14 olle 210     name is checked, otherwise the complete plate is checked. The
2933 14 Nov 14 olle 211     result of the check is stored in the 'replicate' flag of the well.
2933 14 Nov 14 olle 212   */
2933 14 Nov 14 olle 213   plate.checkReplicates = function(name, noRepaint)
2933 14 Nov 14 olle 214   {
2933 14 Nov 14 olle 215     var result = [];
2933 14 Nov 14 olle 216     if (name)
2933 14 Nov 14 olle 217     {
2933 14 Nov 14 olle 218       // If a name has been given, it is relatively easy
2933 14 Nov 14 olle 219       var wells = plate.getWellsByName(name);
2933 14 Nov 14 olle 220       var isReplicate = wells.length > 1;
2933 14 Nov 14 olle 221       for (var i = 0; i < wells.length; i++)
2933 14 Nov 14 olle 222       {
2933 14 Nov 14 olle 223         var well = wells[i];
2933 14 Nov 14 olle 224         if (well.replicate != isReplicate)
2933 14 Nov 14 olle 225         {
2933 14 Nov 14 olle 226           well.replicate = isReplicate;
2933 14 Nov 14 olle 227           if (!noRepaint) well.paint(plate.wellPainter, plate.poolSchema);
2933 14 Nov 14 olle 228         }
2933 14 Nov 14 olle 229       }
2933 14 Nov 14 olle 230     }
2933 14 Nov 14 olle 231     else
2933 14 Nov 14 olle 232     {
2933 14 Nov 14 olle 233       // No name, we begin by counting the number of times we find any given name
2933 14 Nov 14 olle 234       var nameCount = [];
2933 14 Nov 14 olle 235       for (var i = 0; i < plate.wells.length; i++)
2933 14 Nov 14 olle 236       {
2933 14 Nov 14 olle 237         var well = plate.wells[i];
2933 14 Nov 14 olle 238         // Ignore empty wells and wells with 'Stratagene' or external 
2933 14 Nov 14 olle 239         if (well.extract && !well.extract.stratagene && !well.extract.external)
2933 14 Nov 14 olle 240         {
2933 14 Nov 14 olle 241           nameCount[well.extract.name] = 1 + (nameCount[well.extract.name] || 0);
2933 14 Nov 14 olle 242         }
2933 14 Nov 14 olle 243       }
2933 14 Nov 14 olle 244       // Then, we update the status for all wells 
2933 14 Nov 14 olle 245       for (var i = 0; i < plate.wells.length; i++)
2933 14 Nov 14 olle 246       {
2933 14 Nov 14 olle 247         var well = plate.wells[i];
2933 14 Nov 14 olle 248         if (well.extract)
2933 14 Nov 14 olle 249         {
2933 14 Nov 14 olle 250           var isReplicate = nameCount[well.extract.name] > 1;
2933 14 Nov 14 olle 251           if (well.replicate != isReplicate)
2933 14 Nov 14 olle 252           {
2933 14 Nov 14 olle 253             well.replicate = isReplicate;
2933 14 Nov 14 olle 254             if (!noRepaint) well.paint(plate.wellPainter, plate.poolSchema);
2933 14 Nov 14 olle 255           }
2933 14 Nov 14 olle 256         }
2933 14 Nov 14 olle 257       }
2933 14 Nov 14 olle 258     }
2933 14 Nov 14 olle 259   }
2933 14 Nov 14 olle 260   
2933 14 Nov 14 olle 261   return plate;
2933 14 Nov 14 olle 262 }();
2933 14 Nov 14 olle 263
2933 14 Nov 14 olle 264 /**
2933 14 Nov 14 olle 265   Represents a well on the plate. Each well is created when 
2933 14 Nov 14 olle 266   the page is loaded and is initially empty.
2933 14 Nov 14 olle 267 */
2933 14 Nov 14 olle 268 function Well(row, column)
2933 14 Nov 14 olle 269 {
2933 14 Nov 14 olle 270   this.row = row;
2933 14 Nov 14 olle 271   this.column = column;
2933 14 Nov 14 olle 272   this.selected = false;
2933 14 Nov 14 olle 273   this.highlighClass = null;
2933 14 Nov 14 olle 274   this.extract = null;
2933 14 Nov 14 olle 275   this.duplicates = null;
2933 14 Nov 14 olle 276   this.replicate = false;
2933 14 Nov 14 olle 277   this.warning = null;
2933 14 Nov 14 olle 278   this.error = null;
2933 14 Nov 14 olle 279   
2933 14 Nov 14 olle 280   this.tag = document.getElementById('well.'+row+'.'+column);
2933 14 Nov 14 olle 281 }
2933 14 Nov 14 olle 282
2933 14 Nov 14 olle 283 /**
2933 14 Nov 14 olle 284   Set the extract item that is put into this well. Use
2933 14 Nov 14 olle 285   'null' to clear the well. The extract should always
2933 14 Nov 14 olle 286   have a 'name' property, and an 'id' property if it 
2933 14 Nov 14 olle 287   exists in the database.
2933 14 Nov 14 olle 288 */
2933 14 Nov 14 olle 289 Well.prototype.setExtract = function(extract)
2933 14 Nov 14 olle 290 {
2933 14 Nov 14 olle 291   this.extract = extract;
2933 14 Nov 14 olle 292   this.duplicates = null;
2933 14 Nov 14 olle 293   this.replicate = false;
2933 14 Nov 14 olle 294   if (extract && this.clipboard) this.doneWithCopy();
2933 14 Nov 14 olle 295 }
2933 14 Nov 14 olle 296
2933 14 Nov 14 olle 297 /**
2933 14 Nov 14 olle 298   Set duplicate extract items in this well. This can
2933 14 Nov 14 olle 299   happen when using a file import if the same location
2933 14 Nov 14 olle 300   is specified twice and is an error condition which
2933 14 Nov 14 olle 301   must be resolved.
2933 14 Nov 14 olle 302 */
2933 14 Nov 14 olle 303 Well.prototype.addDuplicate = function(extract)
2933 14 Nov 14 olle 304 {
2933 14 Nov 14 olle 305   if (!this.duplicates)
2933 14 Nov 14 olle 306   {
2933 14 Nov 14 olle 307     this.duplicates = [];
2933 14 Nov 14 olle 308     this.duplicates[0] = this.extract.name;
2933 14 Nov 14 olle 309   }
2933 14 Nov 14 olle 310   this.duplicates[this.duplicates.length] = extract.name;
2933 14 Nov 14 olle 311 }
2933 14 Nov 14 olle 312
2933 14 Nov 14 olle 313 /**
2933 14 Nov 14 olle 314   Create a copy-object holding information about this well.
2933 14 Nov 14 olle 315   The copy has 'well' property pointing to this well and
2933 14 Nov 14 olle 316   'name' property holding the extract name if the well is not
2933 14 Nov 14 olle 317   empty. The 'clipboard' flag of this well is set to true.
2933 14 Nov 14 olle 318 */
2933 14 Nov 14 olle 319 Well.prototype.makeCopy = function()
2933 14 Nov 14 olle 320 {
2933 14 Nov 14 olle 321   var cp = {};
2933 14 Nov 14 olle 322   cp.well = this;
2933 14 Nov 14 olle 323   cp.name = this.extract ? this.extract.name : null;
2933 14 Nov 14 olle 324   cp.comment = this.extract ? this.extract.comment : null;
2933 14 Nov 14 olle 325   this.clipboard = true;
2933 14 Nov 14 olle 326   this.copyText = cp.name;
2933 14 Nov 14 olle 327   return cp;
2933 14 Nov 14 olle 328 }
2933 14 Nov 14 olle 329
2933 14 Nov 14 olle 330 /**
2933 14 Nov 14 olle 331   Unset the 'clipboard' flag for this well.
2933 14 Nov 14 olle 332 */
2933 14 Nov 14 olle 333 Well.prototype.doneWithCopy = function()
2933 14 Nov 14 olle 334 {
2933 14 Nov 14 olle 335   this.clipboard = false;
2933 14 Nov 14 olle 336   this.copyText = null;
2933 14 Nov 14 olle 337 }
2933 14 Nov 14 olle 338
2933 14 Nov 14 olle 339 Well.prototype.setWarning = function(warning)
2933 14 Nov 14 olle 340 {
2933 14 Nov 14 olle 341   this.warning = warning;
2933 14 Nov 14 olle 342 }
2933 14 Nov 14 olle 343
2933 14 Nov 14 olle 344 Well.prototype.hasWarning = function()
2933 14 Nov 14 olle 345 {
2933 14 Nov 14 olle 346   return this.warning != null;
2933 14 Nov 14 olle 347 }
2933 14 Nov 14 olle 348
2933 14 Nov 14 olle 349 Well.prototype.setError = function(error)
2933 14 Nov 14 olle 350 {
2933 14 Nov 14 olle 351   this.error = error;
2933 14 Nov 14 olle 352 }
2933 14 Nov 14 olle 353
2933 14 Nov 14 olle 354 Well.prototype.hasError = function()
2933 14 Nov 14 olle 355 {
2933 14 Nov 14 olle 356   return this.error != null;
2933 14 Nov 14 olle 357 }
2933 14 Nov 14 olle 358
2933 14 Nov 14 olle 359 Well.prototype.getClassName = function(wellPainter, poolSchema)
2933 14 Nov 14 olle 360 {
2933 14 Nov 14 olle 361   var c = this.column;
2933 14 Nov 14 olle 362   var cls = 'well col-'+c;
2933 14 Nov 14 olle 363   if (this.selected) cls += ' selected';
2933 14 Nov 14 olle 364   if (this.clipboard) cls += ' clipboard';
2933 14 Nov 14 olle 365   if (!this.extract) cls += ' empty';
2933 14 Nov 14 olle 366   if (this.hasError()) cls += ' err';
2933 14 Nov 14 olle 367   if (this.hasWarning()) cls += ' warning';
2933 14 Nov 14 olle 368   if (this.highlightClass) cls += ' ' + this.highlightClass;
2933 14 Nov 14 olle 369
2933 14 Nov 14 olle 370   if (poolSchema)
2933 14 Nov 14 olle 371   {
2933 14 Nov 14 olle 372     cls += ' ' + poolSchema.getClassNameForWell(this, wellPainter);
2933 14 Nov 14 olle 373   }
2933 14 Nov 14 olle 374   if (wellPainter)
2933 14 Nov 14 olle 375   {
2933 14 Nov 14 olle 376     cls += ' ' + wellPainter.getClassNameForWell(this, poolSchema);
2933 14 Nov 14 olle 377   }
2933 14 Nov 14 olle 378   return cls;
2933 14 Nov 14 olle 379 }
2933 14 Nov 14 olle 380
2933 14 Nov 14 olle 381 Well.prototype.getText = function(wellPainter, poolSchema)
2933 14 Nov 14 olle 382 {
2933 14 Nov 14 olle 383   var text = '';
2933 14 Nov 14 olle 384   if (wellPainter)
2933 14 Nov 14 olle 385   {
2933 14 Nov 14 olle 386     text = wellPainter.getWellText(this, poolSchema);
2933 14 Nov 14 olle 387   }
2933 14 Nov 14 olle 388   else
2933 14 Nov 14 olle 389   {
2933 14 Nov 14 olle 390     if (this.extract)
2933 14 Nov 14 olle 391     {
2933 14 Nov 14 olle 392       text += '<div class="name">'+this.extract.name+'</div>'
2933 14 Nov 14 olle 393     }
2933 14 Nov 14 olle 394   }
2933 14 Nov 14 olle 395   if (this.hasError())
2933 14 Nov 14 olle 396   {
2933 14 Nov 14 olle 397     text += '<div class="err-msg">'+this.error + '</div>';
2933 14 Nov 14 olle 398   }
2933 14 Nov 14 olle 399   if (this.hasWarning())
2933 14 Nov 14 olle 400   {
2933 14 Nov 14 olle 401     text += '<div class="warn-msg">'+this.warning + '</div>';
2933 14 Nov 14 olle 402   }
2933 14 Nov 14 olle 403   return text;
2933 14 Nov 14 olle 404 }
2933 14 Nov 14 olle 405
2933 14 Nov 14 olle 406 Well.prototype.paint = function(wellPainter, poolSchema)
2933 14 Nov 14 olle 407 {
2933 14 Nov 14 olle 408   this.warning = null;
2933 14 Nov 14 olle 409   this.error = null;
2933 14 Nov 14 olle 410   this.tag.innerHTML = this.getText(wellPainter, poolSchema);
2933 14 Nov 14 olle 411   this.tag.className = this.getClassName(wellPainter, poolSchema);
2933 14 Nov 14 olle 412 }
2933 14 Nov 14 olle 413
2933 14 Nov 14 olle 414