1 | <%@ page |
---|
2 | pageEncoding="UTF-8" |
---|
3 | session="false" |
---|
4 | import="net.sf.basedb.core.Application" |
---|
5 | import="net.sf.basedb.core.User" |
---|
6 | import="net.sf.basedb.core.DbControl" |
---|
7 | import="net.sf.basedb.core.SessionControl" |
---|
8 | import="net.sf.basedb.clients.web.Base" |
---|
9 | import="net.sf.basedb.clients.web.util.HTML" |
---|
10 | import="net.sf.basedb.clients.web.extensions.ExtensionsControl" |
---|
11 | import="net.sf.basedb.util.Values" |
---|
12 | import="net.sf.basedb.util.formatter.WellCoordinateFormatter" |
---|
13 | %> |
---|
14 | <%@ taglib prefix="base" uri="/WEB-INF/base.tld" %> |
---|
15 | <%@ taglib prefix="p" uri="/WEB-INF/path.tld" %> |
---|
16 | <%@ taglib prefix="tbl" uri="/WEB-INF/table.tld" %> |
---|
17 | <% |
---|
18 | final SessionControl sc = Base.getExistingSessionControl(request, true); |
---|
19 | final String ID = sc.getId(); |
---|
20 | final float scale = Base.getScale(sc); |
---|
21 | final String home = ExtensionsControl.getHomeUrl("net.sf.basedb.reggie"); |
---|
22 | DbControl dc = null; |
---|
23 | try |
---|
24 | { |
---|
25 | dc = sc.newDbControl(); |
---|
26 | final User user = User.getById(dc, sc.getLoggedInUserId()); |
---|
27 | %> |
---|
28 | <base:page type="default" > |
---|
29 | <base:head scripts="ajax.js,js-draw.js" styles="path.css,toolbar.css"> |
---|
30 | <link rel="stylesheet" type="text/css" href="../css/reggie.css"> |
---|
31 | <link rel="stylesheet" type="text/css" href="../css/plate.css"> |
---|
32 | <script language="JavaScript" src="../reggie.js" type="text/javascript" charset="UTF-8"></script> |
---|
33 | |
---|
34 | <script language="JavaScript"> |
---|
35 | var debug = 1; |
---|
36 | |
---|
37 | var QUANTITY_REGULAR = 1.1; |
---|
38 | var QUANTITY_QC = 1.22; |
---|
39 | |
---|
40 | var Plate = function() |
---|
41 | { |
---|
42 | var plate = {}; |
---|
43 | plate.rows = 8; |
---|
44 | plate.columns = 12; |
---|
45 | plate.wells = []; |
---|
46 | |
---|
47 | plate.init = function() |
---|
48 | { |
---|
49 | for (var c = 0; c < plate.columns; c++) |
---|
50 | { |
---|
51 | for (var r = 0; r < plate.rows; r++) |
---|
52 | { |
---|
53 | plate.wells[plate.wells.length] = new Well(r, c); |
---|
54 | } |
---|
55 | } |
---|
56 | } |
---|
57 | |
---|
58 | /** |
---|
59 | Get all wells on the plate. |
---|
60 | */ |
---|
61 | plate.getWells = function() |
---|
62 | { |
---|
63 | return plate.wells; |
---|
64 | } |
---|
65 | |
---|
66 | /** |
---|
67 | Get all wells in the given row. First row is 0. |
---|
68 | */ |
---|
69 | plate.getRow = function(row) |
---|
70 | { |
---|
71 | var result = []; |
---|
72 | for (var i = row; result.length < plate.columns; i += plate.rows) |
---|
73 | { |
---|
74 | result[result.length] = plate.wells[i]; |
---|
75 | } |
---|
76 | return result; |
---|
77 | } |
---|
78 | |
---|
79 | /** |
---|
80 | Get all wells in the given column. First column is 0. |
---|
81 | */ |
---|
82 | plate.getColumn = function(column) |
---|
83 | { |
---|
84 | var result = []; |
---|
85 | for (var i = column*plate.rows; result.length < plate.rows; i++) |
---|
86 | { |
---|
87 | result[result.length] = plate.wells[i]; |
---|
88 | } |
---|
89 | return result; |
---|
90 | } |
---|
91 | |
---|
92 | /** |
---|
93 | Get all wells in the given pool number. First pool is 0. |
---|
94 | */ |
---|
95 | plate.getPool = function(pool) |
---|
96 | { |
---|
97 | var result = []; |
---|
98 | for (var i = pool*2*plate.rows; result.length < plate.rows*2; i++) |
---|
99 | { |
---|
100 | result[result.length] = plate.wells[i]; |
---|
101 | } |
---|
102 | return result; |
---|
103 | } |
---|
104 | |
---|
105 | /** |
---|
106 | Get the well at the given coordinate. |
---|
107 | */ |
---|
108 | plate.getWell = function(row, column) |
---|
109 | { |
---|
110 | return plate.wells[row + column * plate.rows]; |
---|
111 | } |
---|
112 | |
---|
113 | /** |
---|
114 | Get all wells that contains RNA with a given name. |
---|
115 | */ |
---|
116 | plate.getWellsByName = function(name) |
---|
117 | { |
---|
118 | var result = []; |
---|
119 | for (var i = 0; i < plate.wells.length; i++) |
---|
120 | { |
---|
121 | var well = plate.wells[i]; |
---|
122 | if (well.rna && well.rna.name == name) |
---|
123 | { |
---|
124 | result[result.length] = plate.wells[i]; |
---|
125 | } |
---|
126 | } |
---|
127 | return result; |
---|
128 | } |
---|
129 | |
---|
130 | /** |
---|
131 | Get all wells that are selected. |
---|
132 | */ |
---|
133 | plate.getSelected = function() |
---|
134 | { |
---|
135 | var selected = []; |
---|
136 | for (var i = 0; i < plate.wells.length; i++) |
---|
137 | { |
---|
138 | var well = plate.wells[i]; |
---|
139 | if (well.selected) |
---|
140 | { |
---|
141 | selected[selected.length] = well; |
---|
142 | } |
---|
143 | } |
---|
144 | return selected; |
---|
145 | } |
---|
146 | |
---|
147 | /** |
---|
148 | Set the selected status for all wells in the array. |
---|
149 | The wells are automatically repainted. |
---|
150 | */ |
---|
151 | plate.setSelected = function(wells, select) |
---|
152 | { |
---|
153 | for (var i = 0; i < wells.length; i++) |
---|
154 | { |
---|
155 | var well = wells[i]; |
---|
156 | well.selected = select; |
---|
157 | well.paint(); |
---|
158 | } |
---|
159 | } |
---|
160 | |
---|
161 | /** |
---|
162 | Toggle the selected status for all wells in the array. |
---|
163 | The next status is determined by the current status of |
---|
164 | the first well in the array. |
---|
165 | */ |
---|
166 | plate.toggleSelected = function(wells) |
---|
167 | { |
---|
168 | if (wells.length == 0) return; |
---|
169 | plate.setSelected(wells, !wells[0].selected); |
---|
170 | } |
---|
171 | |
---|
172 | /** |
---|
173 | Enable or disable highlight of the given wells. |
---|
174 | */ |
---|
175 | plate.setHighlight = function(wells, highlightClass, on) |
---|
176 | { |
---|
177 | var tmpClass = on ? highlightClass : null; |
---|
178 | for (var i = 0; i < wells.length; i++) |
---|
179 | { |
---|
180 | var well = wells[i]; |
---|
181 | well.highlightClass = tmpClass; |
---|
182 | Main.addOrRemoveClass(well.tag, highlightClass, on); |
---|
183 | } |
---|
184 | } |
---|
185 | |
---|
186 | /** |
---|
187 | Paint the given wells. |
---|
188 | */ |
---|
189 | plate.paint = function(wells) |
---|
190 | { |
---|
191 | for (var i = 0; i < wells.length; i++) |
---|
192 | { |
---|
193 | wells[i].paint(); |
---|
194 | } |
---|
195 | } |
---|
196 | |
---|
197 | /** |
---|
198 | Check if the plate have any replicated RNA. Eg. RNA that is found |
---|
199 | in more than one well. If a name is given, only RNA for that name |
---|
200 | is checked, otherwise the complete plate is checked. |
---|
201 | */ |
---|
202 | plate.checkReplicates = function(name, noRepaint) |
---|
203 | { |
---|
204 | if (name) |
---|
205 | { |
---|
206 | // If a name has been given, it is relatively easy |
---|
207 | var wells = plate.getWellsByName(name); |
---|
208 | var isReplicate = wells.length > 1; |
---|
209 | for (var i = 0; i < wells.length; i++) |
---|
210 | { |
---|
211 | var well = wells[i]; |
---|
212 | if (well.rna.replicate != isReplicate) |
---|
213 | { |
---|
214 | well.rna.replicate = isReplicate; |
---|
215 | if (!noRepaint) well.paint(); |
---|
216 | } |
---|
217 | } |
---|
218 | } |
---|
219 | else |
---|
220 | { |
---|
221 | // No name, we begin by counting the number of times we find any given name |
---|
222 | var nameCount = []; |
---|
223 | for (var i = 0; i < plate.wells.length; i++) |
---|
224 | { |
---|
225 | var well = plate.wells[i]; |
---|
226 | // Ignore empty wells and wells with 'Stratagene' |
---|
227 | if (well.rna && !well.rna.stratagene) |
---|
228 | { |
---|
229 | nameCount[well.rna.name] = 1 + (nameCount[well.rna.name] || 0); |
---|
230 | } |
---|
231 | } |
---|
232 | // Then, we update the status for all wells |
---|
233 | for (var i = 0; i < plate.wells.length; i++) |
---|
234 | { |
---|
235 | var well = plate.wells[i]; |
---|
236 | if (well.rna) |
---|
237 | { |
---|
238 | var isReplicate = nameCount[well.rna.name] > 1; |
---|
239 | if (well.rna.replicate != isReplicate) |
---|
240 | { |
---|
241 | well.rna.replicate = isReplicate; |
---|
242 | if (!noRepaint) well.paint(); |
---|
243 | } |
---|
244 | } |
---|
245 | } |
---|
246 | } |
---|
247 | } |
---|
248 | |
---|
249 | plate.findNextMRnaPlateName = function() |
---|
250 | { |
---|
251 | var request = Ajax.getXmlHttpRequest(); |
---|
252 | var url = '../MRna.servlet?ID=<%=ID%>&cmd=GetNextAutoGeneratedPlateName&bioPlateType=MRNA'; |
---|
253 | if (debug) Main.debug(url); |
---|
254 | request.open("GET", url, false); |
---|
255 | request.send(null); |
---|
256 | |
---|
257 | if (debug) Main.debug(request.responseText); |
---|
258 | var response = JSON.parse(request.responseText); |
---|
259 | if (response.status != 'ok') |
---|
260 | { |
---|
261 | setFatalError(response.message); |
---|
262 | return false; |
---|
263 | } |
---|
264 | plate.name = response.name; |
---|
265 | return plate.name; |
---|
266 | } |
---|
267 | |
---|
268 | return plate; |
---|
269 | }(); |
---|
270 | |
---|
271 | |
---|
272 | var Rna = function() |
---|
273 | { |
---|
274 | var rna = {}; |
---|
275 | var info = []; |
---|
276 | |
---|
277 | /** |
---|
278 | Create a new RNA object by name. More information |
---|
279 | about the RNA is automatically loaded from the database. |
---|
280 | */ |
---|
281 | rna.createByName = function(name) |
---|
282 | { |
---|
283 | var tmp = {}; |
---|
284 | tmp.name = name; |
---|
285 | tmp.stratagene = name == 'Stratagene'; |
---|
286 | tmp.replicate = false; |
---|
287 | tmp.info = rna.infoByName(name); |
---|
288 | tmp.id = tmp.info.id; |
---|
289 | return tmp; |
---|
290 | } |
---|
291 | |
---|
292 | /** |
---|
293 | Create a new RNA object by info object. |
---|
294 | */ |
---|
295 | rna.createByInfo = function(info) |
---|
296 | { |
---|
297 | var tmp = {}; |
---|
298 | tmp.name = info.name; |
---|
299 | tmp.stratagene = tmp.name == 'Stratagene'; |
---|
300 | tmp.replicate = false; |
---|
301 | tmp.id = info.id; |
---|
302 | tmp.info = info; |
---|
303 | return tmp; |
---|
304 | } |
---|
305 | |
---|
306 | /** |
---|
307 | Get information about a RNA item with a given name. |
---|
308 | */ |
---|
309 | rna.infoByName = function(name) |
---|
310 | { |
---|
311 | var key = 'N'+name; |
---|
312 | if (!info[key]) |
---|
313 | { |
---|
314 | rna.loadInfoByNames([name]); |
---|
315 | if (!info[key]) info[key] = {}; |
---|
316 | } |
---|
317 | return info[key]; |
---|
318 | } |
---|
319 | |
---|
320 | /** |
---|
321 | Load and cache RNA information for all RNA items with a name in the |
---|
322 | given list. |
---|
323 | */ |
---|
324 | rna.loadInfoByNames = function(names) |
---|
325 | { |
---|
326 | var submitInfo = {}; |
---|
327 | submitInfo.names = names; |
---|
328 | if (debug) Main.debug(JSON.stringify(submitInfo)); |
---|
329 | |
---|
330 | var request = Ajax.getXmlHttpRequest(); |
---|
331 | var url = '../MRna.servlet?ID=<%=ID%>&cmd=GetRnaInfoFromNames'; |
---|
332 | request.open("POST", url, false); |
---|
333 | request.setRequestHeader("Content-Type", "application/json"); |
---|
334 | request.send(JSON.stringify(submitInfo)); |
---|
335 | |
---|
336 | if (debug) Main.debug(request.responseText); |
---|
337 | var response = JSON.parse(request.responseText); |
---|
338 | if (response.status != 'ok') |
---|
339 | { |
---|
340 | setFatalError(response.message); |
---|
341 | return false; |
---|
342 | } |
---|
343 | |
---|
344 | for (var i = 0; i < response.rna.length; i++) |
---|
345 | { |
---|
346 | var rna = response.rna[i]; |
---|
347 | info['N'+rna.name] = rna; |
---|
348 | info['I'+rna.id] = rna; |
---|
349 | } |
---|
350 | } |
---|
351 | |
---|
352 | return rna; |
---|
353 | }(); |
---|
354 | |
---|
355 | // Represents a well on the plate |
---|
356 | // Each well is created when the page is loaded |
---|
357 | function Well(row, column) |
---|
358 | { |
---|
359 | this.row = row; |
---|
360 | this.column = column; |
---|
361 | this.selected = false; |
---|
362 | this.highlighClass = null; |
---|
363 | this.rna = null; |
---|
364 | this.duplicates = null; |
---|
365 | this.tag = document.getElementById('well.'+row+'.'+column); |
---|
366 | } |
---|
367 | |
---|
368 | /** |
---|
369 | Set the RNA item that is put into this well. Use |
---|
370 | 'null' to clear the well. |
---|
371 | */ |
---|
372 | Well.prototype.setRna = function(rna) |
---|
373 | { |
---|
374 | this.rna = rna; |
---|
375 | this.duplicates = null; |
---|
376 | if (rna && this.clipboard) this.doneWithCopy(); |
---|
377 | } |
---|
378 | |
---|
379 | /** |
---|
380 | Set a duplicate RNA item in this well. This can |
---|
381 | happen when using a file import if the same location |
---|
382 | is specified twice and is an error condition which |
---|
383 | must be resolved. |
---|
384 | */ |
---|
385 | Well.prototype.addDuplicate = function(rna) |
---|
386 | { |
---|
387 | if (!this.duplicates) |
---|
388 | { |
---|
389 | this.duplicates = []; |
---|
390 | this.duplicates[0] = this.rna.name; |
---|
391 | } |
---|
392 | this.duplicates[this.duplicates.length] = rna.name; |
---|
393 | } |
---|
394 | |
---|
395 | Well.prototype.makeCopy = function() |
---|
396 | { |
---|
397 | var cp = {}; |
---|
398 | cp.well = this; |
---|
399 | cp.name = this.rna ? this.rna.name : null; |
---|
400 | this.clipboard = true; |
---|
401 | this.copyText = cp.name; |
---|
402 | return cp; |
---|
403 | } |
---|
404 | |
---|
405 | Well.prototype.doneWithCopy = function() |
---|
406 | { |
---|
407 | this.clipboard = false; |
---|
408 | this.copyText = null; |
---|
409 | } |
---|
410 | |
---|
411 | Well.prototype.hasError = function() |
---|
412 | { |
---|
413 | return this.duplicates || (this.rna && !this.rna.id); |
---|
414 | } |
---|
415 | |
---|
416 | Well.prototype.getClassName = function() |
---|
417 | { |
---|
418 | var c = this.column; |
---|
419 | var cls = 'well col-'+c; |
---|
420 | cls += (c >= 2 && c <= 9) ? ' primary' : ' secondary'; |
---|
421 | cls += c % 2 == 0 ? ' pool-left' : ' pool-right'; |
---|
422 | if (this.selected) cls += ' selected'; |
---|
423 | if (this.clipboard) cls += ' clipboard'; |
---|
424 | if (this.rna) |
---|
425 | { |
---|
426 | if (this.rna.replicate) cls += ' replicate'; |
---|
427 | if (this.rna.qc) cls += ' qc'; |
---|
428 | } |
---|
429 | if (this.hasError()) cls += ' err'; |
---|
430 | if (this.warning) cls += ' warning'; |
---|
431 | if (this.highlightClass) cls += ' ' + this.highlightClass; |
---|
432 | return cls; |
---|
433 | } |
---|
434 | |
---|
435 | Well.prototype.getText = function() |
---|
436 | { |
---|
437 | var text = ''; |
---|
438 | if (this.duplicates) |
---|
439 | { |
---|
440 | text = '<div class="name">'+this.duplicates.join(', ')+'</div>'; |
---|
441 | text += '<div class="err-msg">Duplicate RNA in this location</div>'; |
---|
442 | } |
---|
443 | else if (this.rna) |
---|
444 | { |
---|
445 | text = '<div class="name">'+this.rna.name+'</div>'; |
---|
446 | var info = this.rna.info; |
---|
447 | var warningMsg = null; |
---|
448 | if (info && info.id && !this.rna.stratagene) |
---|
449 | { |
---|
450 | var quantity = 10000 * (this.rna.qc ? QUANTITY_QC : QUANTITY_REGULAR); |
---|
451 | var use = Math.ceil(quantity/info.NDConc); |
---|
452 | var water = Math.round(500-use); |
---|
453 | if (info.bioWell) |
---|
454 | { |
---|
455 | var well = info.bioWell; |
---|
456 | text += '<div class="location">'+well.bioPlate.name+'['+WELL_ALPHA[well.row]+(well.column+1)+']</div>'; |
---|
457 | } |
---|
458 | else |
---|
459 | { |
---|
460 | if (!warningMsg) warningMsg = 'No location'; |
---|
461 | } |
---|
462 | if (info.remainingQuantity) |
---|
463 | { |
---|
464 | text += '<div class="quantity">'+Numbers.formatNumber(info.remainingQuantity, 2, 'µg')+'</div>'; |
---|
465 | if (info.remainingQuantity < (this.rna.qc ? QUANTITY_QC : QUANTITY_REGULAR)) |
---|
466 | { |
---|
467 | if (!warningMsg) warningMsg = 'Low quantity'; |
---|
468 | } |
---|
469 | } |
---|
470 | else |
---|
471 | { |
---|
472 | if (!warningMsg) warningMsg = 'No quantity'; |
---|
473 | } |
---|
474 | if (info.NDConc) |
---|
475 | { |
---|
476 | text += '<div class="ndconc">'+Numbers.formatNumber(info.NDConc, 2, 'ng/µl') + '</div>'; |
---|
477 | text += '<div class="volume">'+Numbers.formatNumber(use/10, 1)+' + '+Numbers.formatNumber(water/10, 1)+'µl</div>'; |
---|
478 | } |
---|
479 | else |
---|
480 | { |
---|
481 | if (!warningMsg) warningMsg = 'No NDConc value'; |
---|
482 | } |
---|
483 | if (warningMsg) |
---|
484 | { |
---|
485 | this.warning = true; |
---|
486 | text += '<div class="warn-msg">'+ warningMsg + '</div>'; |
---|
487 | } |
---|
488 | } |
---|
489 | else if (!this.rna.id) |
---|
490 | { |
---|
491 | text += '<div class="err-msg">RNA not found</div>' |
---|
492 | } |
---|
493 | } |
---|
494 | else if (this.copyText) |
---|
495 | { |
---|
496 | text = '<div class="copy-text">'+this.copyText+'</div>'; |
---|
497 | } |
---|
498 | return text; |
---|
499 | } |
---|
500 | |
---|
501 | Well.prototype.getTooltip = function() |
---|
502 | { |
---|
503 | var tooltip = 'Select/deselect this well'; |
---|
504 | return tooltip; |
---|
505 | } |
---|
506 | |
---|
507 | Well.prototype.paint = function() |
---|
508 | { |
---|
509 | this.warning = false; |
---|
510 | this.tag.innerHTML = this.getText(); |
---|
511 | this.tag.className = this.getClassName(); |
---|
512 | this.tag.title = this.getTooltip(); |
---|
513 | } |
---|
514 | |
---|
515 | var graphics; |
---|
516 | var pen; |
---|
517 | |
---|
518 | function init() |
---|
519 | { |
---|
520 | Plate.init(); |
---|
521 | Plate.paint(Plate.getWells()); |
---|
522 | |
---|
523 | graphics = new jsGraphics(document.getElementById('canvas')); |
---|
524 | pen = new jsPen(new jsColor('#2288AA'), 2); |
---|
525 | |
---|
526 | var plateName = Plate.findNextMRnaPlateName(); |
---|
527 | setInnerHTML('plateName', plateName); |
---|
528 | } |
---|
529 | |
---|
530 | |
---|
531 | /** |
---|
532 | Parse a tab-separated data file. The columns must be in the following order: |
---|
533 | 0: RNA name |
---|
534 | 1: Row letter (A-H) |
---|
535 | 2: Column number (1-12) |
---|
536 | 3: QC flag (can be empty) |
---|
537 | */ |
---|
538 | function parseRnaFile(data) |
---|
539 | { |
---|
540 | var lines = data.split(/[\n\r]+/); |
---|
541 | |
---|
542 | // Load information about all RNA items in a batch (will improve performance) |
---|
543 | var names = []; |
---|
544 | for (var i = 0; i < lines.length; i++) |
---|
545 | { |
---|
546 | var line = lines[i]; |
---|
547 | if (line) |
---|
548 | { |
---|
549 | var cols = lines[i].split(/\t/); |
---|
550 | if (cols.length < 3) throw 'On line '+(i+1)+': Too few columns (' + cols.length + ')'; |
---|
551 | names[names.length] = cols[0]; |
---|
552 | } |
---|
553 | } |
---|
554 | Rna.loadInfoByNames(names); |
---|
555 | |
---|
556 | // Place RNA on the plate |
---|
557 | var duplicates = []; |
---|
558 | for (var i = 0; i < lines.length; i++) |
---|
559 | { |
---|
560 | var line = lines[i]; |
---|
561 | if (line) |
---|
562 | { |
---|
563 | var cols = lines[i].split(/\t/); |
---|
564 | |
---|
565 | var rna = Rna.createByName(cols[0]); |
---|
566 | var row = WELL_ALPHA.indexOf(cols[1].toUpperCase()); |
---|
567 | var col = parseInt(cols[2], 10)-1; |
---|
568 | |
---|
569 | var well = Plate.getWell(row, col); |
---|
570 | if (!well) throw 'On line '+(i+1)+': Invalid plate coordinate ['+cols[1]+','+cols[2]+']'; |
---|
571 | |
---|
572 | rna.qc = cols.length >= 4 && cols[3]; |
---|
573 | |
---|
574 | // Check for duplicate RNA on same position (which is an error) |
---|
575 | var pos = 'c'+col+'r'+row; |
---|
576 | if (duplicates[pos]) |
---|
577 | { |
---|
578 | well.addDuplicate(rna); |
---|
579 | } |
---|
580 | else |
---|
581 | { |
---|
582 | duplicates[pos] = rna.name; |
---|
583 | well.setRna(rna); |
---|
584 | } |
---|
585 | } |
---|
586 | } |
---|
587 | |
---|
588 | // Check for replicates on the whole plate and repaint it |
---|
589 | Plate.checkReplicates(null, true); |
---|
590 | Plate.paint(Plate.getWells()); |
---|
591 | } |
---|
592 | |
---|
593 | /** |
---|
594 | Add 'Stratagene' to the selected wells. |
---|
595 | */ |
---|
596 | function setToStratagene() |
---|
597 | { |
---|
598 | var wells = Plate.getSelected(); |
---|
599 | |
---|
600 | if (wells.length == 0) |
---|
601 | { |
---|
602 | alert('No wells have been selected'); |
---|
603 | return; |
---|
604 | } |
---|
605 | |
---|
606 | // Count non-empty wells |
---|
607 | var count = 0; |
---|
608 | for (var i = 0; i < wells.length; i++) |
---|
609 | { |
---|
610 | var well = wells[i]; |
---|
611 | if (well.rna && !well.hasError()) count++; |
---|
612 | } |
---|
613 | |
---|
614 | if (count > 0) |
---|
615 | { |
---|
616 | if (!confirm('Replace RNA in ' + count + ' wells with Stratagene?')) |
---|
617 | { |
---|
618 | return; |
---|
619 | } |
---|
620 | } |
---|
621 | |
---|
622 | var info = Rna.infoByName('Stratagene'); |
---|
623 | if (!info.id) |
---|
624 | { |
---|
625 | alert('Could not find any RNA with name=Stratagene. Please check that it exists on the server.'); |
---|
626 | return; |
---|
627 | } |
---|
628 | |
---|
629 | for (var i = 0; i < wells.length; i++) |
---|
630 | { |
---|
631 | var well = wells[i]; |
---|
632 | var rna = Rna.createByInfo(info); |
---|
633 | rna.qc = true; |
---|
634 | well.setRna(rna); |
---|
635 | well.selected = false; |
---|
636 | well.paint(); |
---|
637 | } |
---|
638 | |
---|
639 | // Check for replicated RNA if some have been replaced with Stratagene |
---|
640 | if (count > 0) Plate.checkReplicates(); |
---|
641 | } |
---|
642 | |
---|
643 | /** |
---|
644 | Toggle the QC flag for the selected wells. The first non-empty |
---|
645 | well is toggled and the rest of the wells will use the same new QC |
---|
646 | value. |
---|
647 | */ |
---|
648 | function toggleQc() |
---|
649 | { |
---|
650 | var wells = Plate.getSelected(); |
---|
651 | |
---|
652 | if (wells.length == 0) |
---|
653 | { |
---|
654 | alert('No wells have been selected'); |
---|
655 | return; |
---|
656 | } |
---|
657 | |
---|
658 | var gotQc = false; |
---|
659 | var newQc; |
---|
660 | var count = 0; |
---|
661 | for (var i = 0; i < wells.length; i++) |
---|
662 | { |
---|
663 | var well = wells[i]; |
---|
664 | if (well.rna) |
---|
665 | { |
---|
666 | // Toggle QC flag for the first well with RNA, then use the same flag for the rest |
---|
667 | if (!gotQc) |
---|
668 | { |
---|
669 | gotQc = true; |
---|
670 | newQc = !well.rna.qc; |
---|
671 | } |
---|
672 | well.rna.qc = newQc; |
---|
673 | well.paint(); |
---|
674 | count++; |
---|
675 | } |
---|
676 | } |
---|
677 | |
---|
678 | if (count == 0) |
---|
679 | { |
---|
680 | alert('None of the selected wells contain any RNA'); |
---|
681 | } |
---|
682 | } |
---|
683 | |
---|
684 | /** |
---|
685 | Empty the selected wells from RNA. They can later be pasted again. |
---|
686 | */ |
---|
687 | function cutSelected() |
---|
688 | { |
---|
689 | var wells = Plate.getSelected(); |
---|
690 | |
---|
691 | if (wells.length == 0) |
---|
692 | { |
---|
693 | alert('No wells have been selected'); |
---|
694 | return; |
---|
695 | } |
---|
696 | |
---|
697 | var count = 0; |
---|
698 | var valid = 0; |
---|
699 | for (var i = 0; i < wells.length; i++) |
---|
700 | { |
---|
701 | var well = wells[i]; |
---|
702 | if (well.rna) |
---|
703 | { |
---|
704 | count++; |
---|
705 | if (!well.hasError()) valid++; |
---|
706 | } |
---|
707 | } |
---|
708 | |
---|
709 | if (count == 0) |
---|
710 | { |
---|
711 | alert('None of the selected wells contain any RNA'); |
---|
712 | return; |
---|
713 | } |
---|
714 | |
---|
715 | // Ask for confirmation before deleting from valid wells |
---|
716 | if (valid > 0) |
---|
717 | { |
---|
718 | if (!confirm('Clear RNA from ' + count + ' of ' + wells.length + ' selected wells?')) |
---|
719 | { |
---|
720 | return; |
---|
721 | } |
---|
722 | } |
---|
723 | |
---|
724 | copySelected(); |
---|
725 | for (var i = 0; i < wells.length; i++) |
---|
726 | { |
---|
727 | var well = wells[i]; |
---|
728 | well.setRna(null); |
---|
729 | well.selected = false; |
---|
730 | well.paint(); |
---|
731 | } |
---|
732 | Plate.checkReplicates(); |
---|
733 | } |
---|
734 | |
---|
735 | var copy; |
---|
736 | /** |
---|
737 | Copy information about the selected wells. |
---|
738 | */ |
---|
739 | function copySelected() |
---|
740 | { |
---|
741 | // Clear existing wells in the copy |
---|
742 | if (copy && copy.length > 0) |
---|
743 | { |
---|
744 | for (var i = 0; i < copy.length; i++) |
---|
745 | { |
---|
746 | var cp = copy[i]; |
---|
747 | cp.well.doneWithCopy(); |
---|
748 | cp.well.paint(); |
---|
749 | } |
---|
750 | } |
---|
751 | |
---|
752 | // Place selected wells in the copy |
---|
753 | var wells = Plate.getSelected(); |
---|
754 | copy = []; |
---|
755 | for (var i = 0; i < wells.length; i++) |
---|
756 | { |
---|
757 | var well = wells[i]; |
---|
758 | copy[copy.length] = well.makeCopy(); |
---|
759 | well.selected = false; |
---|
760 | well.paint(); |
---|
761 | } |
---|
762 | } |
---|
763 | |
---|
764 | /** |
---|
765 | Paste information into the selected wells. |
---|
766 | */ |
---|
767 | function pasteToSelected() |
---|
768 | { |
---|
769 | if (!copy || copy.length == 0) |
---|
770 | { |
---|
771 | alert('Nothing to paste. Please cut or copy wells first.'); |
---|
772 | return; |
---|
773 | } |
---|
774 | |
---|
775 | var wells = Plate.getSelected(); |
---|
776 | // Count non-empty and valid wells |
---|
777 | var count = 0; |
---|
778 | for (var i = 0; i < wells.length; i++) |
---|
779 | { |
---|
780 | var well = wells[i]; |
---|
781 | if (well.rna && !well.hasError()) count++; |
---|
782 | } |
---|
783 | |
---|
784 | if (count > 0) |
---|
785 | { |
---|
786 | if (!confirm('Replace RNA in ' + count + ' wells with copy?')) |
---|
787 | { |
---|
788 | return; |
---|
789 | } |
---|
790 | } |
---|
791 | |
---|
792 | var wi = 0; |
---|
793 | var ci = 0; |
---|
794 | var copyEmpty; |
---|
795 | var askIfEmpty = true; |
---|
796 | |
---|
797 | while (wi < wells.length && ci < copy.length) |
---|
798 | { |
---|
799 | var well = wells[wi]; |
---|
800 | var cp = copy[ci]; |
---|
801 | var rna = null; |
---|
802 | cp.well.doneWithCopy(); |
---|
803 | cp.well.paint(); |
---|
804 | if (cp.name) |
---|
805 | { |
---|
806 | rna = Rna.createByName(cp.name); |
---|
807 | } |
---|
808 | else |
---|
809 | { |
---|
810 | // The copy is from an empty well |
---|
811 | if (askIfEmpty) |
---|
812 | { |
---|
813 | askIfEmpty = false; |
---|
814 | copyEmpty = confirm('Do you want to copy empty wells? If not, only non-empty well are copied.'); |
---|
815 | } |
---|
816 | } |
---|
817 | if (rna != null || copyEmpty) |
---|
818 | { |
---|
819 | well.setRna(rna); |
---|
820 | well.selected = false; |
---|
821 | well.paint(); |
---|
822 | wi++; |
---|
823 | } |
---|
824 | ci++; |
---|
825 | } |
---|
826 | copy.splice(0, ci); |
---|
827 | Plate.checkReplicates(); |
---|
828 | } |
---|
829 | |
---|
830 | |
---|
831 | /** |
---|
832 | Open a popup dialog for selecting a data files. |
---|
833 | */ |
---|
834 | function selectFile() |
---|
835 | { |
---|
836 | Main.openPopup('select_file.jsp?ID=<%=ID%>', 'SelectFile', 600, 400); |
---|
837 | } |
---|
838 | |
---|
839 | |
---|
840 | var currentSelected; |
---|
841 | var currentIndex = 0; |
---|
842 | var subtypeRna = null; |
---|
843 | |
---|
844 | /** |
---|
845 | Open a popup dialog for manual selection of RNA. |
---|
846 | */ |
---|
847 | function manualSelect() |
---|
848 | { |
---|
849 | currentSelected = Plate.getSelected(); |
---|
850 | currentIndex = 0; |
---|
851 | |
---|
852 | if (currentSelected.length == 0) |
---|
853 | { |
---|
854 | alert('Please select one or more wells were RNA should be placed.'); |
---|
855 | return; |
---|
856 | } |
---|
857 | |
---|
858 | if (subtypeRna == null) |
---|
859 | { |
---|
860 | var request = Ajax.getXmlHttpRequest(); |
---|
861 | var url = '../Subtype.servlet?ID=<%=ID%>&cmd=GetSubtypeInfo&name=RNA'; |
---|
862 | request.open("GET", url, false); |
---|
863 | request.send(null); |
---|
864 | |
---|
865 | if (debug) Main.debug(request.responseText); |
---|
866 | var response = JSON.parse(request.responseText); |
---|
867 | if (response.status != 'ok') |
---|
868 | { |
---|
869 | setFatalError(response.message); |
---|
870 | return false; |
---|
871 | } |
---|
872 | subtypeRna = response.subtype; |
---|
873 | } |
---|
874 | |
---|
875 | var url = getRoot() + 'biomaterials/extracts/index.jsp?ID=<%=ID%>'; |
---|
876 | url += '&cmd=UpdateContext&mode=selectmultiple&callback=setRnaCallback&resetTemporary=1'; |
---|
877 | url += '&tmpfilter:INT:itemSubtype='+subtypeRna.id; |
---|
878 | url += '&tmpfilter:DATE:creationEvent.eventDate='+encodeURIComponent('<>'); |
---|
879 | url += '&tmpfilter:FLOAT:remainingQuantity='+encodeURIComponent('>=1'); |
---|
880 | Main.openPopup(url, 'SelectRNA', 1000, 700); |
---|
881 | } |
---|
882 | |
---|
883 | /** |
---|
884 | Callback method for manual selection. |
---|
885 | */ |
---|
886 | function setRnaCallback(id, name) |
---|
887 | { |
---|
888 | if (currentIndex >= currentSelected.length) |
---|
889 | { |
---|
890 | return; |
---|
891 | } |
---|
892 | var well = currentSelected[currentIndex]; |
---|
893 | |
---|
894 | // Keep a reference to the old rna in the well |
---|
895 | var oldRna = well.rna; |
---|
896 | |
---|
897 | // Create a new RNA object |
---|
898 | var rna = Rna.createByName(name); |
---|
899 | well.setRna(rna); |
---|
900 | well.selected = false; |
---|
901 | well.paint(); |
---|
902 | |
---|
903 | // Update replicate information |
---|
904 | Plate.checkReplicates(name); |
---|
905 | if (oldRna) Plate.checkReplicates(oldRna.name); |
---|
906 | |
---|
907 | // Move to the next item |
---|
908 | currentIndex++; |
---|
909 | } |
---|
910 | |
---|
911 | // Toggle the selected status of a single well |
---|
912 | function toggleWell(row, column) |
---|
913 | { |
---|
914 | var well = Plate.getWell(row, column); |
---|
915 | Plate.toggleSelected([well]); |
---|
916 | } |
---|
917 | |
---|
918 | // Toggle the selected status of a complete row |
---|
919 | function toggleRow(row) |
---|
920 | { |
---|
921 | Plate.toggleSelected(Plate.getRow(row)); |
---|
922 | } |
---|
923 | |
---|
924 | // Toggle the selected status of a complete column |
---|
925 | function toggleColumn(column) |
---|
926 | { |
---|
927 | Plate.toggleSelected(Plate.getColumn(column)); |
---|
928 | } |
---|
929 | |
---|
930 | // Toggle the selected status of all wells |
---|
931 | function toggleAll() |
---|
932 | { |
---|
933 | Plate.toggleSelected(Plate.getWells()); |
---|
934 | } |
---|
935 | |
---|
936 | // Toggle the selected status of a complete pool (=two columns) |
---|
937 | function togglePool(pool) |
---|
938 | { |
---|
939 | Plate.toggleSelected(Plate.getPool(pool)); |
---|
940 | } |
---|
941 | |
---|
942 | // Highlight enable/disable all wells in a column |
---|
943 | function highlightColumn(column, on) |
---|
944 | { |
---|
945 | Main.addOrRemoveClass(document.getElementById('col.'+column), 'highlight-column', on); |
---|
946 | var wells = Plate.getColumn(column); |
---|
947 | Plate.setHighlight(wells, 'highlight-column', on); |
---|
948 | } |
---|
949 | |
---|
950 | // Highlight enable/disable all wells in a row |
---|
951 | function highlightRow(row, on) |
---|
952 | { |
---|
953 | Main.addOrRemoveClass(document.getElementById('row.'+row), 'highlight-row', on); |
---|
954 | var wells = Plate.getRow(row); |
---|
955 | Plate.setHighlight(wells, 'highlight-row', on); |
---|
956 | } |
---|
957 | |
---|
958 | // Highlight enable/disable all wells in a pool |
---|
959 | function highlightPool(pool, on) |
---|
960 | { |
---|
961 | Main.addOrRemoveClass(document.getElementById('pool.'+pool), 'highlight-pool', on); |
---|
962 | var wells = Plate.getPool(pool); |
---|
963 | Plate.setHighlight(wells, 'highlight-pool', on); |
---|
964 | } |
---|
965 | |
---|
966 | /** |
---|
967 | Highlight all replicated wells with the same RNA as the given well. |
---|
968 | */ |
---|
969 | function highlightReplicated(row, column, on) |
---|
970 | { |
---|
971 | var well = Plate.getWell(row, column); |
---|
972 | if (well.rna && well.rna.replicate) |
---|
973 | { |
---|
974 | // Get center coordinates for the current well |
---|
975 | var pos = Main.getElementPosition(well.tag); |
---|
976 | var jsPos = new jsPoint(pos.left+pos.width/2, pos.top+pos.height/2); |
---|
977 | |
---|
978 | var replicated = Plate.getWellsByName(well.rna.name); |
---|
979 | for (var i = 0; i < replicated.length; i++) |
---|
980 | { |
---|
981 | var rep = replicated[i]; |
---|
982 | if (rep != well) |
---|
983 | { |
---|
984 | Main.addOrRemoveClass(rep.tag, 'highlight-replicated', on); |
---|
985 | if (rep.line) |
---|
986 | { |
---|
987 | // Clear any recent lines |
---|
988 | graphics.clearDrawing(rep.line); |
---|
989 | rep.line = null; |
---|
990 | } |
---|
991 | if (on) |
---|
992 | { |
---|
993 | // We draw a line between the current and replicated well |
---|
994 | var rPos = Main.getElementPosition(rep.tag); |
---|
995 | rep.line = graphics.drawLine(pen, jsPos, new jsPoint(rPos.left+rPos.width/2, rPos.top+rPos.height/2)); |
---|
996 | } |
---|
997 | } |
---|
998 | } |
---|
999 | } |
---|
1000 | } |
---|
1001 | |
---|
1002 | |
---|
1003 | function goCreate() |
---|
1004 | { |
---|
1005 | var submitInfo = {}; |
---|
1006 | var plateInfo = {}; |
---|
1007 | submitInfo.bioplate = plateInfo; |
---|
1008 | |
---|
1009 | plateInfo.name = Plate.name; |
---|
1010 | plateInfo.wells = []; |
---|
1011 | |
---|
1012 | var wells = Plate.getWells(); |
---|
1013 | var numErrors = 0; |
---|
1014 | var numWarnings = 0; |
---|
1015 | var numRna = 0; |
---|
1016 | var numStratagene = 0; |
---|
1017 | for (var i = 0; i < wells.length; i++) |
---|
1018 | { |
---|
1019 | var well = wells[i]; |
---|
1020 | if (well.warning) numWarnings++; |
---|
1021 | if (well.hasError()) |
---|
1022 | { |
---|
1023 | numErrors++; |
---|
1024 | } |
---|
1025 | else |
---|
1026 | { |
---|
1027 | if (well.rna && well.rna.id) |
---|
1028 | { |
---|
1029 | var tmp = {}; |
---|
1030 | tmp.row = well.row; |
---|
1031 | tmp.column = well.column; |
---|
1032 | tmp.rna = {}; |
---|
1033 | tmp.rna.id = well.rna.id; |
---|
1034 | tmp.rna.usedQuantity = well.rna.qc ? QUANTITY_QC : QUANTITY_REGULAR; |
---|
1035 | plateInfo.wells[plateInfo.wells.length] = tmp; |
---|
1036 | numRna++; |
---|
1037 | if (well.rna.stratagene) numStratagene++; |
---|
1038 | } |
---|
1039 | } |
---|
1040 | } |
---|
1041 | |
---|
1042 | if (numErrors > 0) |
---|
1043 | { |
---|
1044 | alert('There are ' + numErrors + ' wells with errors. Please fix them before creating the mRNA plate.'); |
---|
1045 | return; |
---|
1046 | } |
---|
1047 | |
---|
1048 | if (numRna == 0) |
---|
1049 | { |
---|
1050 | alert('There is no RNA in any wells'); |
---|
1051 | return; |
---|
1052 | } |
---|
1053 | |
---|
1054 | if (numWarnings > 0) |
---|
1055 | { |
---|
1056 | if (!confirm('There are ' + numWarnings + ' wells with a warning. Continue anyway?')) return; |
---|
1057 | } |
---|
1058 | |
---|
1059 | if (numRna < 64) |
---|
1060 | { |
---|
1061 | if (!confirm('Less than 64 wells have RNA in them. Continue anyway?')) return; |
---|
1062 | } |
---|
1063 | |
---|
1064 | if (numRna == numStratagene) |
---|
1065 | { |
---|
1066 | if (!confirm('There are only wells with Stratagene on this plate. Continue anyway?')) return; |
---|
1067 | } |
---|
1068 | |
---|
1069 | Main.addClass(document.getElementById('step.1.section'), 'disabled'); |
---|
1070 | Main.hide('gocancel'); |
---|
1071 | Main.hide('gocreate'); |
---|
1072 | |
---|
1073 | if (debug) Main.debug(JSON.stringify(submitInfo)); |
---|
1074 | |
---|
1075 | var request = Ajax.getXmlHttpRequest(); |
---|
1076 | var url = '../MRna.servlet?ID=<%=ID%>'; |
---|
1077 | url += '&cmd=CreateMRnaPlate'; |
---|
1078 | request.open("POST", url, false); |
---|
1079 | request.setRequestHeader("Content-Type", "application/json"); |
---|
1080 | request.send(JSON.stringify(submitInfo)); |
---|
1081 | |
---|
1082 | if (debug) Main.debug(request.responseText); |
---|
1083 | |
---|
1084 | var response = JSON.parse(request.responseText); |
---|
1085 | if (response.status != 'ok') |
---|
1086 | { |
---|
1087 | setFatalError(response.message); |
---|
1088 | return false; |
---|
1089 | } |
---|
1090 | |
---|
1091 | var msg = '<ul>'; |
---|
1092 | for (var i = 0; i < response.messages.length; i++) |
---|
1093 | { |
---|
1094 | msg += '<li>' + response.messages[i]; |
---|
1095 | } |
---|
1096 | msg += '</ul>'; |
---|
1097 | setInnerHTML('done', msg); |
---|
1098 | Main.show('done'); |
---|
1099 | Main.show('gorestart'); |
---|
1100 | } |
---|
1101 | |
---|
1102 | function toggleInfo(what) |
---|
1103 | { |
---|
1104 | var frm = document.forms['reggie']; |
---|
1105 | var show = frm[what].checked; |
---|
1106 | Main.addOrRemoveClass(document.getElementById('plate'), 'hide-'+what, !show); |
---|
1107 | } |
---|
1108 | |
---|
1109 | </script> |
---|
1110 | <style> |
---|
1111 | |
---|
1112 | /* A well assigned for QC include a background icon as indicator */ |
---|
1113 | .well.qc |
---|
1114 | { |
---|
1115 | background-image: url('../images/mrnaqc.png'); |
---|
1116 | background-position: 95% 5%; |
---|
1117 | background-repeat: no-repeat; |
---|
1118 | } |
---|
1119 | |
---|
1120 | /* A well which contain replicate RNA is also marked with an icon */ |
---|
1121 | .well.replicate |
---|
1122 | { |
---|
1123 | background-image: url('../images/copy.png'); |
---|
1124 | background-position: 95% 5%; |
---|
1125 | background-repeat: no-repeat; |
---|
1126 | } |
---|
1127 | |
---|
1128 | /* A well that is both a replicate and QC need to re-arrange the icons a bit */ |
---|
1129 | .well.qc.replicate |
---|
1130 | { |
---|
1131 | background-image: url('../images/mrnaqc.png'), url('../images/copy.png'); |
---|
1132 | background-position: 95% 5%, 95% 55%; |
---|
1133 | background-repeat: no-repeat; |
---|
1134 | } |
---|
1135 | |
---|
1136 | .well .name |
---|
1137 | { |
---|
1138 | font-weight: bold; |
---|
1139 | } |
---|
1140 | |
---|
1141 | .well .err-msg, .well .warn-msg |
---|
1142 | { |
---|
1143 | color: #C80000; |
---|
1144 | font-style: italic; |
---|
1145 | } |
---|
1146 | |
---|
1147 | .well .missing |
---|
1148 | { |
---|
1149 | font-style: italic; |
---|
1150 | } |
---|
1151 | |
---|
1152 | .plate.hide-location .location |
---|
1153 | { |
---|
1154 | display: none; |
---|
1155 | } |
---|
1156 | .plate.hide-quantity .quantity |
---|
1157 | { |
---|
1158 | display: none; |
---|
1159 | } |
---|
1160 | .plate.hide-volume .volume |
---|
1161 | { |
---|
1162 | display: none; |
---|
1163 | } |
---|
1164 | .plate.hide-ndconc .ndconc |
---|
1165 | { |
---|
1166 | display: none; |
---|
1167 | } |
---|
1168 | |
---|
1169 | </style> |
---|
1170 | </base:head> |
---|
1171 | <base:body onload="init()"> |
---|
1172 | <p:path><p:pathelement |
---|
1173 | title="Reggie" href="<%="../index.jsp?ID="+ID%>" |
---|
1174 | /><p:pathelement title="Create new mRNA plate" |
---|
1175 | /></p:path> |
---|
1176 | <div id="canvas" class="absolutefull" style="z-index: -1;"> |
---|
1177 | <div class="content"> |
---|
1178 | <% |
---|
1179 | if (sc.getActiveProjectId() == 0) |
---|
1180 | { |
---|
1181 | %> |
---|
1182 | <div class="messagecontainer note" style="width: 950px; margin-left: 20px; margin-bottom: 20px; margin-right: 0px; font-weight: bold; color: #cc0000;"> |
---|
1183 | No project has been selected. You may proceed with the wizard but |
---|
1184 | created items will not be shared. |
---|
1185 | </div> |
---|
1186 | <% |
---|
1187 | } |
---|
1188 | %> |
---|
1189 | <form name="reggie" onsubmit="return false;"> |
---|
1190 | |
---|
1191 | <table class="stepform" id="step.1.section" style="width: auto;"> |
---|
1192 | <tr> |
---|
1193 | <td rowspan="3" class="stepno">1</td> |
---|
1194 | <td class="steptitle">Fragmented mRNA plate</td> |
---|
1195 | </tr> |
---|
1196 | <tr> |
---|
1197 | <td class="stepfields"> |
---|
1198 | <table class="bottomborder" style="width: 100%;"> |
---|
1199 | <tr> |
---|
1200 | <td class="prompt">Name</td> |
---|
1201 | <td class="input" id="plateName"></td> |
---|
1202 | <td class="help">Select RNA items to use for the new mRNA plate.</td> |
---|
1203 | </tr> |
---|
1204 | <tr style="vertical-align: top;"> |
---|
1205 | <td class="prompt">Show</td> |
---|
1206 | <td class="input"> |
---|
1207 | <table> |
---|
1208 | <tr> |
---|
1209 | <td> |
---|
1210 | <input type="checkbox" name="location" id="location" onclick="toggleInfo('location')" checked><label for="location">Bioplate location</label><br> |
---|
1211 | <input type="checkbox" name="quantity" id="quantity" onclick="toggleInfo('quantity')" checked><label for="quantity">Remaining quantity</label><br> |
---|
1212 | </td> |
---|
1213 | <td> |
---|
1214 | <input type="checkbox" name="ndconc" id="ndconc" onclick="toggleInfo('ndconc')"><label for="ndconc">NDConc</label><br> |
---|
1215 | <input type="checkbox" name="volume" id="volume" onclick="toggleInfo('volume')"><label for="volume">Used volume+water</label><br> |
---|
1216 | </td> |
---|
1217 | </tr> |
---|
1218 | </table> |
---|
1219 | <br> |
---|
1220 | </td> |
---|
1221 | <td class="help"></td> |
---|
1222 | </tr> |
---|
1223 | </table> |
---|
1224 | </td> |
---|
1225 | </tr> |
---|
1226 | |
---|
1227 | <tr> |
---|
1228 | <td> |
---|
1229 | <tbl:toolbar subclass="bottomborder"> |
---|
1230 | <tbl:button |
---|
1231 | title="Load from file…" |
---|
1232 | image="<%=home+"/images/file.png"%>" |
---|
1233 | onclick="selectFile()" |
---|
1234 | tooltip="Load plate design from file" |
---|
1235 | /> |
---|
1236 | |
---|
1237 | <tbl:button |
---|
1238 | title="Auto-select…" |
---|
1239 | image="<%=home+"/images/wizard.png"%>" |
---|
1240 | onclick="autoSelect()" |
---|
1241 | tooltip="Let the wizard auto-select RNA" |
---|
1242 | /> |
---|
1243 | <tbl:button |
---|
1244 | title="Manual select…" |
---|
1245 | image="<%=home+"/images/manual_rna.png"%>" |
---|
1246 | onclick="manualSelect()" |
---|
1247 | tooltip="Manually select RNA items" |
---|
1248 | /> |
---|
1249 | <tbl:button |
---|
1250 | title="Stratagene" |
---|
1251 | image="<%=home+"/images/stratagene.png"%>" |
---|
1252 | onclick="setToStratagene()" |
---|
1253 | tooltip="Place stratagene in the selected wells" |
---|
1254 | /> |
---|
1255 | <tbl:button |
---|
1256 | title="Toggle QC" |
---|
1257 | image="<%=home+"/images/mrnaqc.png"%>" |
---|
1258 | onclick="toggleQc()" |
---|
1259 | tooltip="Select/deselect RNA for QC" |
---|
1260 | /> |
---|
1261 | <tbl:button |
---|
1262 | title="Cut…" |
---|
1263 | image="<%=home+"/images/cut.png"%>" |
---|
1264 | onclick="cutSelected()" |
---|
1265 | tooltip="Clear the selected wells" |
---|
1266 | /> |
---|
1267 | <tbl:button |
---|
1268 | title="Copy" |
---|
1269 | image="<%=home+"/images/copy.png"%>" |
---|
1270 | onclick="copySelected()" |
---|
1271 | tooltip="Make a copy of the selected RNA" |
---|
1272 | /> |
---|
1273 | <tbl:button |
---|
1274 | title="Paste" |
---|
1275 | image="<%=home+"/images/paste.png"%>" |
---|
1276 | onclick="pasteToSelected()" |
---|
1277 | tooltip="Paste RNA into selected wells" |
---|
1278 | /> |
---|
1279 | </tbl:toolbar> |
---|
1280 | <table class="plate hide-volume hide-ndconc" style="margin: 1em 1em 0 1em;" id="plate"> |
---|
1281 | <% |
---|
1282 | int columns = 12; |
---|
1283 | int rows = 8; |
---|
1284 | WellCoordinateFormatter rowF = new WellCoordinateFormatter(true); |
---|
1285 | WellCoordinateFormatter colF = new WellCoordinateFormatter(false); |
---|
1286 | %> |
---|
1287 | <tr class="header"> |
---|
1288 | <th> |
---|
1289 | <base:icon image="<%=home+"/images/select_all.png"%>" |
---|
1290 | onclick="toggleAll()" |
---|
1291 | tooltip="Select/deselect all wells on the plate" |
---|
1292 | /> |
---|
1293 | </th> |
---|
1294 | <% |
---|
1295 | for (int c = 0; c < columns; ++c) |
---|
1296 | { |
---|
1297 | %> |
---|
1298 | <th class="link" id="col.<%=c%>" |
---|
1299 | onclick="toggleColumn(<%=c%>)" |
---|
1300 | onmouseover="highlightColumn(<%=c%>, true)" |
---|
1301 | onmouseout="highlightColumn(<%=c%>, false)" |
---|
1302 | title="Select/deselect all wells in this column"><%=colF.format(c)%></td> |
---|
1303 | <% |
---|
1304 | } |
---|
1305 | %> |
---|
1306 | </tr> |
---|
1307 | <tbody> |
---|
1308 | <% |
---|
1309 | for (int r = 0; r < rows; ++r) |
---|
1310 | { |
---|
1311 | String row = rowF.format(r); |
---|
1312 | %> |
---|
1313 | <tr class="row-<%=r%>"> |
---|
1314 | <th class="link" id="row.<%=r%>" |
---|
1315 | onclick="toggleRow(<%=r%>)" |
---|
1316 | onmouseover="highlightRow(<%=r%>, true)" |
---|
1317 | onmouseout="highlightRow(<%=r%>, false)" |
---|
1318 | title="Select/deselect all wells in this row"><%=row%></th> |
---|
1319 | <% |
---|
1320 | for (int c = 0; c < columns; ++c) |
---|
1321 | { |
---|
1322 | %> |
---|
1323 | <td id="well.<%=r%>.<%=c%>" |
---|
1324 | onclick="toggleWell(<%=r%>,<%=c%>)" |
---|
1325 | onmouseenter="highlightReplicated(<%=r%>, <%=c%>, true)" |
---|
1326 | onmouseleave="highlightReplicated(<%=r%>, <%=c%>, false)" |
---|
1327 | title="Select/deselect this well"></td> |
---|
1328 | <% |
---|
1329 | } |
---|
1330 | %> |
---|
1331 | </tr> |
---|
1332 | <% |
---|
1333 | } |
---|
1334 | %> |
---|
1335 | </tbody> |
---|
1336 | <tr> |
---|
1337 | <th></th> |
---|
1338 | <% |
---|
1339 | for (int i = 0; i < columns / 2; ++i) |
---|
1340 | { |
---|
1341 | %> |
---|
1342 | <th colspan="2" class="link" id="pool.<%=i %>" |
---|
1343 | onclick="togglePool(<%=i%>)" |
---|
1344 | onmouseover="highlightPool(<%=i%>, true)" |
---|
1345 | onmouseout="highlightPool(<%=i%>, false)" |
---|
1346 | title="Select/deselect all wells in this pool" |
---|
1347 | ><%=i==0 || i == (columns / 2 - 1) ? "Extra" : "Pool #" + i %></td> |
---|
1348 | <% |
---|
1349 | } |
---|
1350 | %> |
---|
1351 | </tr> |
---|
1352 | </table> |
---|
1353 | <div style="padding-left: 1em; padding-bottom: 0.5em; padding-top: 2px;"> |
---|
1354 | <base:icon image="<%=home+"/images/mrnaqc.png"%>" />=Selected for QC |
---|
1355 | <base:icon image="<%=home+"/images/copy.png"%>" style="padding-left: 1em;" />=Replicated RNA |
---|
1356 | <base:icon image="<%=home+"/images/error.png"%>" style="padding-left: 1em;" />=Error that prevent plate creation |
---|
1357 | <base:icon image="<%=home+"/images/warning.png"%>" style="padding-left: 1em;" />=Warning but plate can be created |
---|
1358 | </div> |
---|
1359 | </td> |
---|
1360 | </tr> |
---|
1361 | </table> |
---|
1362 | |
---|
1363 | |
---|
1364 | <div class="messagecontainer error" id="errorMessage" style="display: none; width: 950px; margin-left: 20px; margin-bottom: 0px;"></div> |
---|
1365 | |
---|
1366 | <div id="done" class="success" style="display: none; width: 950px; margin-left: 20px; margin-top: 20px;"></div> |
---|
1367 | |
---|
1368 | <table style="margin-left: 20px; margin-top: 10px;" class="navigation"> |
---|
1369 | <tr> |
---|
1370 | <td><base:button id="gocancel" title="Cancel" onclick="goRestart(false)" /></td> |
---|
1371 | <td><base:button id="gocreate" title="Create" image="<%=home+"/images/gonext.png"%>" onclick="goCreate()" /></td> |
---|
1372 | <td><base:button id="gorestart" title="Restart" image="<%=home+"/images/goback.png"%>" onclick="goRestart(true)" style="display: none;"/></td> |
---|
1373 | </tr> |
---|
1374 | </table> |
---|
1375 | </form> |
---|
1376 | |
---|
1377 | <div class="loading" id="loading" style="display: none;"><table><tr><td><img src="images/loading.gif"></td><td id="loading.msg">Please wait...</td></tr></table></div> |
---|
1378 | |
---|
1379 | </div> |
---|
1380 | </div> |
---|
1381 | </base:body> |
---|
1382 | </base:page> |
---|
1383 | <% |
---|
1384 | } |
---|
1385 | finally |
---|
1386 | { |
---|
1387 | if (dc != null) dc.close(); |
---|
1388 | } |
---|
1389 | %> |
---|