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 | rna.cacheInfo(response.rna); |
---|
345 | } |
---|
346 | |
---|
347 | rna.cacheInfo = function(rnaList) |
---|
348 | { |
---|
349 | for (var i = 0; i < rnaList.length; i++) |
---|
350 | { |
---|
351 | var rna = rnaList[i]; |
---|
352 | info['N'+rna.name] = rna; |
---|
353 | info['I'+rna.id] = rna; |
---|
354 | } |
---|
355 | } |
---|
356 | |
---|
357 | return rna; |
---|
358 | }(); |
---|
359 | |
---|
360 | // Represents a well on the plate |
---|
361 | // Each well is created when the page is loaded |
---|
362 | function Well(row, column) |
---|
363 | { |
---|
364 | this.row = row; |
---|
365 | this.column = column; |
---|
366 | this.selected = false; |
---|
367 | this.highlighClass = null; |
---|
368 | this.rna = null; |
---|
369 | this.duplicates = null; |
---|
370 | this.tag = document.getElementById('well.'+row+'.'+column); |
---|
371 | } |
---|
372 | |
---|
373 | /** |
---|
374 | Set the RNA item that is put into this well. Use |
---|
375 | 'null' to clear the well. |
---|
376 | */ |
---|
377 | Well.prototype.setRna = function(rna) |
---|
378 | { |
---|
379 | this.rna = rna; |
---|
380 | this.duplicates = null; |
---|
381 | if (rna && this.clipboard) this.doneWithCopy(); |
---|
382 | } |
---|
383 | |
---|
384 | /** |
---|
385 | Set a duplicate RNA item in this well. This can |
---|
386 | happen when using a file import if the same location |
---|
387 | is specified twice and is an error condition which |
---|
388 | must be resolved. |
---|
389 | */ |
---|
390 | Well.prototype.addDuplicate = function(rna) |
---|
391 | { |
---|
392 | if (!this.duplicates) |
---|
393 | { |
---|
394 | this.duplicates = []; |
---|
395 | this.duplicates[0] = this.rna.name; |
---|
396 | } |
---|
397 | this.duplicates[this.duplicates.length] = rna.name; |
---|
398 | } |
---|
399 | |
---|
400 | Well.prototype.makeCopy = function() |
---|
401 | { |
---|
402 | var cp = {}; |
---|
403 | cp.well = this; |
---|
404 | cp.name = this.rna ? this.rna.name : null; |
---|
405 | this.clipboard = true; |
---|
406 | this.copyText = cp.name; |
---|
407 | return cp; |
---|
408 | } |
---|
409 | |
---|
410 | Well.prototype.doneWithCopy = function() |
---|
411 | { |
---|
412 | this.clipboard = false; |
---|
413 | this.copyText = null; |
---|
414 | } |
---|
415 | |
---|
416 | Well.prototype.hasError = function() |
---|
417 | { |
---|
418 | return this.duplicates || (this.rna && !this.rna.id); |
---|
419 | } |
---|
420 | |
---|
421 | Well.prototype.getClassName = function() |
---|
422 | { |
---|
423 | var c = this.column; |
---|
424 | var cls = 'well col-'+c; |
---|
425 | cls += (c >= 2 && c <= 9) ? ' primary' : ' secondary'; |
---|
426 | cls += c % 2 == 0 ? ' pool-left' : ' pool-right'; |
---|
427 | if (this.selected) cls += ' selected'; |
---|
428 | if (this.clipboard) cls += ' clipboard'; |
---|
429 | if (this.rna) |
---|
430 | { |
---|
431 | if (this.rna.replicate) cls += ' replicate'; |
---|
432 | if (this.rna.qc) cls += ' qc'; |
---|
433 | } |
---|
434 | if (this.hasError()) cls += ' err'; |
---|
435 | if (this.warning) cls += ' warning'; |
---|
436 | if (this.highlightClass) cls += ' ' + this.highlightClass; |
---|
437 | return cls; |
---|
438 | } |
---|
439 | |
---|
440 | Well.prototype.getText = function() |
---|
441 | { |
---|
442 | var text = ''; |
---|
443 | if (this.duplicates) |
---|
444 | { |
---|
445 | text = '<div class="name">'+this.duplicates.join(', ')+'</div>'; |
---|
446 | text += '<div class="err-msg">Duplicate RNA in this location</div>'; |
---|
447 | } |
---|
448 | else if (this.rna) |
---|
449 | { |
---|
450 | text = '<div class="name">'+this.rna.name+'</div>'; |
---|
451 | var info = this.rna.info; |
---|
452 | var warningMsg = null; |
---|
453 | if (info && info.id && !this.rna.stratagene) |
---|
454 | { |
---|
455 | var quantity = 10000 * (this.rna.qc ? QUANTITY_QC : QUANTITY_REGULAR); |
---|
456 | var use = Math.ceil(quantity/info.NDConc); |
---|
457 | var water = Math.round(500-use); |
---|
458 | if (info.bioWell) |
---|
459 | { |
---|
460 | var well = info.bioWell; |
---|
461 | text += '<div class="location">'+well.bioPlate.name+'['+WELL_ALPHA[well.row]+(well.column+1)+']</div>'; |
---|
462 | } |
---|
463 | else |
---|
464 | { |
---|
465 | if (!warningMsg) warningMsg = 'No location'; |
---|
466 | } |
---|
467 | if (info.remainingQuantity) |
---|
468 | { |
---|
469 | text += '<div class="quantity">'+Numbers.formatNumber(info.remainingQuantity, 2, 'µg')+'</div>'; |
---|
470 | if (info.remainingQuantity < (this.rna.qc ? QUANTITY_QC : QUANTITY_REGULAR)) |
---|
471 | { |
---|
472 | if (!warningMsg) warningMsg = 'Low quantity'; |
---|
473 | } |
---|
474 | } |
---|
475 | else |
---|
476 | { |
---|
477 | if (!warningMsg) warningMsg = 'No quantity'; |
---|
478 | } |
---|
479 | if (info.NDConc) |
---|
480 | { |
---|
481 | text += '<div class="ndconc">'+Numbers.formatNumber(info.NDConc, 2, 'ng/µl') + '</div>'; |
---|
482 | text += '<div class="volumes"><span class="volume">'+Numbers.formatNumber(use/10, 1)+'</span> + <span class="water">'+Numbers.formatNumber(water/10, 1)+'µl</span></div>'; |
---|
483 | } |
---|
484 | else |
---|
485 | { |
---|
486 | if (!warningMsg) warningMsg = 'No NDConc value'; |
---|
487 | } |
---|
488 | if (warningMsg) |
---|
489 | { |
---|
490 | this.warning = true; |
---|
491 | text += '<div class="warn-msg">'+ warningMsg + '</div>'; |
---|
492 | } |
---|
493 | } |
---|
494 | else if (!this.rna.id) |
---|
495 | { |
---|
496 | text += '<div class="err-msg">RNA not found</div>' |
---|
497 | } |
---|
498 | } |
---|
499 | else if (this.copyText) |
---|
500 | { |
---|
501 | text = '<div class="copy-text">'+this.copyText+'</div>'; |
---|
502 | } |
---|
503 | return text; |
---|
504 | } |
---|
505 | |
---|
506 | Well.prototype.getTooltip = function() |
---|
507 | { |
---|
508 | var tooltip = 'Select/deselect this well'; |
---|
509 | return tooltip; |
---|
510 | } |
---|
511 | |
---|
512 | Well.prototype.paint = function() |
---|
513 | { |
---|
514 | this.warning = false; |
---|
515 | this.tag.innerHTML = this.getText(); |
---|
516 | this.tag.className = this.getClassName(); |
---|
517 | this.tag.title = this.getTooltip(); |
---|
518 | } |
---|
519 | |
---|
520 | var graphics; |
---|
521 | var pen; |
---|
522 | |
---|
523 | function init() |
---|
524 | { |
---|
525 | Plate.init(); |
---|
526 | Plate.paint(Plate.getWells()); |
---|
527 | |
---|
528 | graphics = new jsGraphics(document.getElementById('canvas')); |
---|
529 | pen = new jsPen(new jsColor('#2288AA'), 2); |
---|
530 | |
---|
531 | var plateName = Plate.findNextMRnaPlateName(); |
---|
532 | setInnerHTML('plateName', plateName); |
---|
533 | } |
---|
534 | |
---|
535 | |
---|
536 | /** |
---|
537 | Parse a tab-separated data file. The columns must be in the following order: |
---|
538 | 0: RNA name |
---|
539 | 1: Row letter (A-H) |
---|
540 | 2: Column number (1-12) |
---|
541 | 3: QC flag (can be empty) |
---|
542 | */ |
---|
543 | function parseRnaFile(data) |
---|
544 | { |
---|
545 | var lines = data.split(/[\n\r]+/); |
---|
546 | |
---|
547 | // Load information about all RNA items in a batch (will improve performance) |
---|
548 | var names = []; |
---|
549 | for (var i = 0; i < lines.length; i++) |
---|
550 | { |
---|
551 | var line = lines[i]; |
---|
552 | if (line) |
---|
553 | { |
---|
554 | var cols = lines[i].split(/\t/); |
---|
555 | if (cols.length < 3) throw 'On line '+(i+1)+': Too few columns (' + cols.length + ')'; |
---|
556 | names[names.length] = cols[0]; |
---|
557 | } |
---|
558 | } |
---|
559 | Rna.loadInfoByNames(names); |
---|
560 | |
---|
561 | // Place RNA on the plate |
---|
562 | var duplicates = []; |
---|
563 | for (var i = 0; i < lines.length; i++) |
---|
564 | { |
---|
565 | var line = lines[i]; |
---|
566 | if (line) |
---|
567 | { |
---|
568 | var cols = lines[i].split(/\t/); |
---|
569 | |
---|
570 | var rna = Rna.createByName(cols[0]); |
---|
571 | var row = WELL_ALPHA.indexOf(cols[1].toUpperCase()); |
---|
572 | var col = parseInt(cols[2], 10)-1; |
---|
573 | |
---|
574 | var well = Plate.getWell(row, col); |
---|
575 | if (!well) throw 'On line '+(i+1)+': Invalid plate coordinate ['+cols[1]+','+cols[2]+']'; |
---|
576 | |
---|
577 | rna.qc = cols.length >= 4 && cols[3]; |
---|
578 | |
---|
579 | // Check for duplicate RNA on same position (which is an error) |
---|
580 | var pos = 'c'+col+'r'+row; |
---|
581 | if (duplicates[pos]) |
---|
582 | { |
---|
583 | well.addDuplicate(rna); |
---|
584 | } |
---|
585 | else |
---|
586 | { |
---|
587 | duplicates[pos] = rna.name; |
---|
588 | well.setRna(rna); |
---|
589 | } |
---|
590 | } |
---|
591 | } |
---|
592 | |
---|
593 | // Check for replicates on the whole plate and repaint it |
---|
594 | Plate.checkReplicates(null, true); |
---|
595 | Plate.paint(Plate.getWells()); |
---|
596 | } |
---|
597 | |
---|
598 | /** |
---|
599 | Add 'Stratagene' to the selected wells. |
---|
600 | */ |
---|
601 | function setToStratagene() |
---|
602 | { |
---|
603 | var wells = Plate.getSelected(); |
---|
604 | |
---|
605 | if (wells.length == 0) |
---|
606 | { |
---|
607 | alert('No wells have been selected'); |
---|
608 | return; |
---|
609 | } |
---|
610 | |
---|
611 | // Count non-empty wells |
---|
612 | var count = 0; |
---|
613 | for (var i = 0; i < wells.length; i++) |
---|
614 | { |
---|
615 | var well = wells[i]; |
---|
616 | if (well.rna && !well.hasError()) count++; |
---|
617 | } |
---|
618 | |
---|
619 | if (count > 0) |
---|
620 | { |
---|
621 | if (!confirm('Replace RNA in ' + count + ' wells with Stratagene?')) |
---|
622 | { |
---|
623 | return; |
---|
624 | } |
---|
625 | } |
---|
626 | |
---|
627 | var info = Rna.infoByName('Stratagene'); |
---|
628 | if (!info.id) |
---|
629 | { |
---|
630 | alert('Could not find any RNA with name=Stratagene. Please check that it exists on the server.'); |
---|
631 | return; |
---|
632 | } |
---|
633 | |
---|
634 | for (var i = 0; i < wells.length; i++) |
---|
635 | { |
---|
636 | var well = wells[i]; |
---|
637 | var rna = Rna.createByInfo(info); |
---|
638 | rna.qc = true; |
---|
639 | well.setRna(rna); |
---|
640 | well.selected = false; |
---|
641 | well.paint(); |
---|
642 | } |
---|
643 | |
---|
644 | // Check for replicated RNA if some have been replaced with Stratagene |
---|
645 | if (count > 0) Plate.checkReplicates(); |
---|
646 | } |
---|
647 | |
---|
648 | /** |
---|
649 | Toggle the QC flag for the selected wells. The first non-empty |
---|
650 | well is toggled and the rest of the wells will use the same new QC |
---|
651 | value. |
---|
652 | */ |
---|
653 | function toggleQc() |
---|
654 | { |
---|
655 | var wells = Plate.getSelected(); |
---|
656 | |
---|
657 | if (wells.length == 0) |
---|
658 | { |
---|
659 | alert('No wells have been selected'); |
---|
660 | return; |
---|
661 | } |
---|
662 | |
---|
663 | var gotQc = false; |
---|
664 | var newQc; |
---|
665 | var count = 0; |
---|
666 | for (var i = 0; i < wells.length; i++) |
---|
667 | { |
---|
668 | var well = wells[i]; |
---|
669 | if (well.rna) |
---|
670 | { |
---|
671 | // Toggle QC flag for the first well with RNA, then use the same flag for the rest |
---|
672 | if (!gotQc) |
---|
673 | { |
---|
674 | gotQc = true; |
---|
675 | newQc = !well.rna.qc; |
---|
676 | } |
---|
677 | well.rna.qc = newQc; |
---|
678 | well.paint(); |
---|
679 | count++; |
---|
680 | } |
---|
681 | } |
---|
682 | |
---|
683 | if (count == 0) |
---|
684 | { |
---|
685 | alert('None of the selected wells contain any RNA'); |
---|
686 | } |
---|
687 | } |
---|
688 | |
---|
689 | /** |
---|
690 | Empty the selected wells from RNA. They can later be pasted again. |
---|
691 | */ |
---|
692 | function cutSelected() |
---|
693 | { |
---|
694 | var wells = Plate.getSelected(); |
---|
695 | |
---|
696 | if (wells.length == 0) |
---|
697 | { |
---|
698 | alert('No wells have been selected'); |
---|
699 | return; |
---|
700 | } |
---|
701 | |
---|
702 | var count = 0; |
---|
703 | var valid = 0; |
---|
704 | for (var i = 0; i < wells.length; i++) |
---|
705 | { |
---|
706 | var well = wells[i]; |
---|
707 | if (well.rna) |
---|
708 | { |
---|
709 | count++; |
---|
710 | if (!well.hasError()) valid++; |
---|
711 | } |
---|
712 | } |
---|
713 | |
---|
714 | if (count == 0) |
---|
715 | { |
---|
716 | alert('None of the selected wells contain any RNA'); |
---|
717 | return; |
---|
718 | } |
---|
719 | |
---|
720 | // Ask for confirmation before deleting from valid wells |
---|
721 | if (valid > 0) |
---|
722 | { |
---|
723 | if (!confirm('Clear RNA from ' + count + ' of ' + wells.length + ' selected wells?')) |
---|
724 | { |
---|
725 | return; |
---|
726 | } |
---|
727 | } |
---|
728 | |
---|
729 | copySelected(); |
---|
730 | for (var i = 0; i < wells.length; i++) |
---|
731 | { |
---|
732 | var well = wells[i]; |
---|
733 | well.setRna(null); |
---|
734 | well.selected = false; |
---|
735 | well.paint(); |
---|
736 | } |
---|
737 | Plate.checkReplicates(); |
---|
738 | } |
---|
739 | |
---|
740 | var copy; |
---|
741 | /** |
---|
742 | Copy information about the selected wells. |
---|
743 | */ |
---|
744 | function copySelected() |
---|
745 | { |
---|
746 | // Clear existing wells in the copy |
---|
747 | if (copy && copy.length > 0) |
---|
748 | { |
---|
749 | for (var i = 0; i < copy.length; i++) |
---|
750 | { |
---|
751 | var cp = copy[i]; |
---|
752 | cp.well.doneWithCopy(); |
---|
753 | cp.well.paint(); |
---|
754 | } |
---|
755 | } |
---|
756 | |
---|
757 | // Place selected wells in the copy |
---|
758 | var wells = Plate.getSelected(); |
---|
759 | copy = []; |
---|
760 | for (var i = 0; i < wells.length; i++) |
---|
761 | { |
---|
762 | var well = wells[i]; |
---|
763 | copy[copy.length] = well.makeCopy(); |
---|
764 | well.selected = false; |
---|
765 | well.paint(); |
---|
766 | } |
---|
767 | } |
---|
768 | |
---|
769 | /** |
---|
770 | Paste information into the selected wells. |
---|
771 | */ |
---|
772 | function pasteToSelected() |
---|
773 | { |
---|
774 | if (!copy || copy.length == 0) |
---|
775 | { |
---|
776 | alert('Nothing to paste. Please cut or copy wells first.'); |
---|
777 | return; |
---|
778 | } |
---|
779 | |
---|
780 | var wells = Plate.getSelected(); |
---|
781 | // Count non-empty and valid wells |
---|
782 | var count = 0; |
---|
783 | for (var i = 0; i < wells.length; i++) |
---|
784 | { |
---|
785 | var well = wells[i]; |
---|
786 | if (well.rna && !well.hasError()) count++; |
---|
787 | } |
---|
788 | |
---|
789 | if (count > 0) |
---|
790 | { |
---|
791 | if (!confirm('Replace RNA in ' + count + ' wells with copy?')) |
---|
792 | { |
---|
793 | return; |
---|
794 | } |
---|
795 | } |
---|
796 | |
---|
797 | var wi = 0; |
---|
798 | var ci = 0; |
---|
799 | var copyEmpty; |
---|
800 | var askIfEmpty = true; |
---|
801 | |
---|
802 | while (wi < wells.length && ci < copy.length) |
---|
803 | { |
---|
804 | var well = wells[wi]; |
---|
805 | var cp = copy[ci]; |
---|
806 | var rna = null; |
---|
807 | cp.well.doneWithCopy(); |
---|
808 | cp.well.paint(); |
---|
809 | if (cp.name) |
---|
810 | { |
---|
811 | rna = Rna.createByName(cp.name); |
---|
812 | } |
---|
813 | else |
---|
814 | { |
---|
815 | // The copy is from an empty well |
---|
816 | if (askIfEmpty) |
---|
817 | { |
---|
818 | askIfEmpty = false; |
---|
819 | copyEmpty = confirm('Do you want to copy empty wells? If not, only non-empty well are copied.'); |
---|
820 | } |
---|
821 | } |
---|
822 | if (rna != null || copyEmpty) |
---|
823 | { |
---|
824 | well.setRna(rna); |
---|
825 | well.selected = false; |
---|
826 | well.paint(); |
---|
827 | wi++; |
---|
828 | } |
---|
829 | ci++; |
---|
830 | } |
---|
831 | copy.splice(0, ci); |
---|
832 | Plate.checkReplicates(); |
---|
833 | } |
---|
834 | |
---|
835 | |
---|
836 | /** |
---|
837 | Open a popup dialog for selecting a data files. |
---|
838 | */ |
---|
839 | function selectFile() |
---|
840 | { |
---|
841 | Main.openPopup('select_file.jsp?ID=<%=ID%>', 'SelectFile', 600, 400); |
---|
842 | } |
---|
843 | |
---|
844 | |
---|
845 | /** |
---|
846 | Let the wizard automatically select among unprocessed RNA items. |
---|
847 | */ |
---|
848 | function autoSelect() |
---|
849 | { |
---|
850 | |
---|
851 | var wells = Plate.getWells(); |
---|
852 | var ignore = []; |
---|
853 | var selected = 0; |
---|
854 | var notEmpty = 0; |
---|
855 | |
---|
856 | // Count selected and non-empty wells and keep track of RNA that is already present |
---|
857 | for (var i = 0; i < wells.length; i++) |
---|
858 | { |
---|
859 | var well = wells[i]; |
---|
860 | if (well.selected) |
---|
861 | { |
---|
862 | selected++; |
---|
863 | if (well.rna && !well.hasError()) notEmpty++; |
---|
864 | } |
---|
865 | if (well.rna && well.rna.id) |
---|
866 | { |
---|
867 | ignore[ignore.length] = well.rna.id; |
---|
868 | } |
---|
869 | } |
---|
870 | |
---|
871 | if (selected == 0) |
---|
872 | { |
---|
873 | alert('Please select one or more wells were RNA should be placed.'); |
---|
874 | return; |
---|
875 | } |
---|
876 | |
---|
877 | if (notEmpty > 0) |
---|
878 | { |
---|
879 | if (!confirm('Replace RNA in ' + notEmpty + ' wells?')) |
---|
880 | { |
---|
881 | return; |
---|
882 | } |
---|
883 | } |
---|
884 | |
---|
885 | var request = Ajax.getXmlHttpRequest(); |
---|
886 | var url = '../MRna.servlet?ID=<%=ID%>&cmd=AutoSelectRnaForMRna&numToSelect='+currentSelected; |
---|
887 | url += '&ignore='+ignore.join(','); |
---|
888 | request.open("GET", url, false); |
---|
889 | request.send(null); |
---|
890 | |
---|
891 | if (debug) Main.debug(request.responseText); |
---|
892 | var response = JSON.parse(request.responseText); |
---|
893 | if (response.status != 'ok') |
---|
894 | { |
---|
895 | setFatalError(response.message); |
---|
896 | return false; |
---|
897 | } |
---|
898 | |
---|
899 | // Cache RNA information |
---|
900 | Rna.cacheInfo(response.rna); |
---|
901 | |
---|
902 | if (response.rna.length == 0) |
---|
903 | { |
---|
904 | alert('Could not find any unprocessed RNA at this time.'); |
---|
905 | } |
---|
906 | |
---|
907 | for (var i = 0; i < response.rna.length; i++) |
---|
908 | { |
---|
909 | if (i < selected.length) |
---|
910 | { |
---|
911 | var well = selected[i]; |
---|
912 | // Create a new RNA object |
---|
913 | var rna = Rna.createByName(response.rna[i].name); |
---|
914 | well.setRna(rna); |
---|
915 | well.selected = false; |
---|
916 | } |
---|
917 | } |
---|
918 | |
---|
919 | // Check for replicates on the whole plate and repaint it |
---|
920 | Plate.checkReplicates(null, true); |
---|
921 | Plate.paint(Plate.getWells()); |
---|
922 | } |
---|
923 | |
---|
924 | |
---|
925 | var currentSelected; |
---|
926 | var currentIndex = 0; |
---|
927 | var subtypeRna = null; |
---|
928 | |
---|
929 | /** |
---|
930 | Open a popup dialog for manual selection of RNA. |
---|
931 | */ |
---|
932 | function manualSelect() |
---|
933 | { |
---|
934 | currentSelected = Plate.getSelected(); |
---|
935 | currentIndex = 0; |
---|
936 | |
---|
937 | if (currentSelected.length == 0) |
---|
938 | { |
---|
939 | alert('Please select one or more wells were RNA should be placed.'); |
---|
940 | return; |
---|
941 | } |
---|
942 | |
---|
943 | if (subtypeRna == null) |
---|
944 | { |
---|
945 | var request = Ajax.getXmlHttpRequest(); |
---|
946 | var url = '../Subtype.servlet?ID=<%=ID%>&cmd=GetSubtypeInfo&name=RNA'; |
---|
947 | request.open("GET", url, false); |
---|
948 | request.send(null); |
---|
949 | |
---|
950 | if (debug) Main.debug(request.responseText); |
---|
951 | var response = JSON.parse(request.responseText); |
---|
952 | if (response.status != 'ok') |
---|
953 | { |
---|
954 | setFatalError(response.message); |
---|
955 | return false; |
---|
956 | } |
---|
957 | subtypeRna = response.subtype; |
---|
958 | } |
---|
959 | |
---|
960 | var url = getRoot() + 'biomaterials/extracts/index.jsp?ID=<%=ID%>'; |
---|
961 | url += '&cmd=UpdateContext&mode=selectmultiple&callback=setRnaCallback&resetTemporary=1'; |
---|
962 | url += '&tmpfilter:INT:itemSubtype='+subtypeRna.id; |
---|
963 | url += '&tmpfilter:DATE:creationEvent.eventDate='+encodeURIComponent('<>'); |
---|
964 | url += '&tmpfilter:FLOAT:remainingQuantity='+encodeURIComponent('>=1'); |
---|
965 | Main.openPopup(url, 'SelectRNA', 1000, 700); |
---|
966 | } |
---|
967 | |
---|
968 | /** |
---|
969 | Callback method for manual selection. |
---|
970 | */ |
---|
971 | function setRnaCallback(id, name) |
---|
972 | { |
---|
973 | if (currentIndex >= currentSelected.length) |
---|
974 | { |
---|
975 | return; |
---|
976 | } |
---|
977 | var well = currentSelected[currentIndex]; |
---|
978 | |
---|
979 | // Keep a reference to the old rna in the well |
---|
980 | var oldRna = well.rna; |
---|
981 | |
---|
982 | // Create a new RNA object |
---|
983 | var rna = Rna.createByName(name); |
---|
984 | well.setRna(rna); |
---|
985 | well.selected = false; |
---|
986 | well.paint(); |
---|
987 | |
---|
988 | // Update replicate information |
---|
989 | Plate.checkReplicates(name); |
---|
990 | if (oldRna) Plate.checkReplicates(oldRna.name); |
---|
991 | |
---|
992 | // Move to the next item |
---|
993 | currentIndex++; |
---|
994 | } |
---|
995 | |
---|
996 | // Toggle the selected status of a single well |
---|
997 | function toggleWell(row, column) |
---|
998 | { |
---|
999 | var well = Plate.getWell(row, column); |
---|
1000 | Plate.toggleSelected([well]); |
---|
1001 | } |
---|
1002 | |
---|
1003 | // Toggle the selected status of a complete row |
---|
1004 | function toggleRow(row) |
---|
1005 | { |
---|
1006 | Plate.toggleSelected(Plate.getRow(row)); |
---|
1007 | } |
---|
1008 | |
---|
1009 | // Toggle the selected status of a complete column |
---|
1010 | function toggleColumn(column) |
---|
1011 | { |
---|
1012 | Plate.toggleSelected(Plate.getColumn(column)); |
---|
1013 | } |
---|
1014 | |
---|
1015 | // Toggle the selected status of all wells |
---|
1016 | function toggleAll() |
---|
1017 | { |
---|
1018 | Plate.toggleSelected(Plate.getWells()); |
---|
1019 | } |
---|
1020 | |
---|
1021 | // Toggle the selected status of a complete pool (=two columns) |
---|
1022 | function togglePool(pool) |
---|
1023 | { |
---|
1024 | Plate.toggleSelected(Plate.getPool(pool)); |
---|
1025 | } |
---|
1026 | |
---|
1027 | // Highlight enable/disable all wells in a column |
---|
1028 | function highlightColumn(column, on) |
---|
1029 | { |
---|
1030 | Main.addOrRemoveClass(document.getElementById('col.'+column), 'highlight-column', on); |
---|
1031 | var wells = Plate.getColumn(column); |
---|
1032 | Plate.setHighlight(wells, 'highlight-column', on); |
---|
1033 | } |
---|
1034 | |
---|
1035 | // Highlight enable/disable all wells in a row |
---|
1036 | function highlightRow(row, on) |
---|
1037 | { |
---|
1038 | Main.addOrRemoveClass(document.getElementById('row.'+row), 'highlight-row', on); |
---|
1039 | var wells = Plate.getRow(row); |
---|
1040 | Plate.setHighlight(wells, 'highlight-row', on); |
---|
1041 | } |
---|
1042 | |
---|
1043 | // Highlight enable/disable all wells in a pool |
---|
1044 | function highlightPool(pool, on) |
---|
1045 | { |
---|
1046 | Main.addOrRemoveClass(document.getElementById('pool.'+pool), 'highlight-pool', on); |
---|
1047 | var wells = Plate.getPool(pool); |
---|
1048 | Plate.setHighlight(wells, 'highlight-pool', on); |
---|
1049 | } |
---|
1050 | |
---|
1051 | /** |
---|
1052 | Highlight all replicated wells with the same RNA as the given well. |
---|
1053 | */ |
---|
1054 | function highlightReplicated(row, column, on) |
---|
1055 | { |
---|
1056 | var well = Plate.getWell(row, column); |
---|
1057 | if (well.rna && well.rna.replicate) |
---|
1058 | { |
---|
1059 | // Get center coordinates for the current well |
---|
1060 | var pos = Main.getElementPosition(well.tag); |
---|
1061 | var jsPos = new jsPoint(pos.left+pos.width/2, pos.top+pos.height/2); |
---|
1062 | |
---|
1063 | var replicated = Plate.getWellsByName(well.rna.name); |
---|
1064 | for (var i = 0; i < replicated.length; i++) |
---|
1065 | { |
---|
1066 | var rep = replicated[i]; |
---|
1067 | if (rep != well) |
---|
1068 | { |
---|
1069 | Main.addOrRemoveClass(rep.tag, 'highlight-replicated', on); |
---|
1070 | if (rep.line) |
---|
1071 | { |
---|
1072 | // Clear any recent lines |
---|
1073 | graphics.clearDrawing(rep.line); |
---|
1074 | rep.line = null; |
---|
1075 | } |
---|
1076 | if (on) |
---|
1077 | { |
---|
1078 | // We draw a line between the current and replicated well |
---|
1079 | var rPos = Main.getElementPosition(rep.tag); |
---|
1080 | rep.line = graphics.drawLine(pen, jsPos, new jsPoint(rPos.left+rPos.width/2, rPos.top+rPos.height/2)); |
---|
1081 | } |
---|
1082 | } |
---|
1083 | } |
---|
1084 | } |
---|
1085 | } |
---|
1086 | |
---|
1087 | |
---|
1088 | function goCreate() |
---|
1089 | { |
---|
1090 | var submitInfo = {}; |
---|
1091 | var plateInfo = {}; |
---|
1092 | submitInfo.bioplate = plateInfo; |
---|
1093 | |
---|
1094 | plateInfo.name = Plate.name; |
---|
1095 | plateInfo.wells = []; |
---|
1096 | |
---|
1097 | var wells = Plate.getWells(); |
---|
1098 | var numErrors = 0; |
---|
1099 | var numWarnings = 0; |
---|
1100 | var numRna = 0; |
---|
1101 | var numStratagene = 0; |
---|
1102 | for (var i = 0; i < wells.length; i++) |
---|
1103 | { |
---|
1104 | var well = wells[i]; |
---|
1105 | if (well.warning) numWarnings++; |
---|
1106 | if (well.hasError()) |
---|
1107 | { |
---|
1108 | numErrors++; |
---|
1109 | } |
---|
1110 | else |
---|
1111 | { |
---|
1112 | if (well.rna && well.rna.id) |
---|
1113 | { |
---|
1114 | var tmp = {}; |
---|
1115 | tmp.row = well.row; |
---|
1116 | tmp.column = well.column; |
---|
1117 | tmp.rna = {}; |
---|
1118 | tmp.rna.id = well.rna.id; |
---|
1119 | tmp.rna.usedQuantity = well.rna.qc ? QUANTITY_QC : QUANTITY_REGULAR; |
---|
1120 | plateInfo.wells[plateInfo.wells.length] = tmp; |
---|
1121 | numRna++; |
---|
1122 | if (well.rna.stratagene) numStratagene++; |
---|
1123 | } |
---|
1124 | } |
---|
1125 | } |
---|
1126 | |
---|
1127 | if (numErrors > 0) |
---|
1128 | { |
---|
1129 | alert('There are ' + numErrors + ' wells with errors. Please fix them before creating the mRNA plate.'); |
---|
1130 | return; |
---|
1131 | } |
---|
1132 | |
---|
1133 | if (numRna == 0) |
---|
1134 | { |
---|
1135 | alert('There is no RNA in any wells'); |
---|
1136 | return; |
---|
1137 | } |
---|
1138 | |
---|
1139 | if (numWarnings > 0) |
---|
1140 | { |
---|
1141 | if (!confirm('There are ' + numWarnings + ' wells with a warning. Continue anyway?')) return; |
---|
1142 | } |
---|
1143 | |
---|
1144 | if (numRna < 64) |
---|
1145 | { |
---|
1146 | if (!confirm('Less than 64 wells have RNA in them. Continue anyway?')) return; |
---|
1147 | } |
---|
1148 | |
---|
1149 | if (numRna == numStratagene) |
---|
1150 | { |
---|
1151 | if (!confirm('There are only wells with Stratagene on this plate. Continue anyway?')) return; |
---|
1152 | } |
---|
1153 | |
---|
1154 | Main.addClass(document.getElementById('step.1.section'), 'disabled'); |
---|
1155 | Main.hide('gocancel'); |
---|
1156 | Main.hide('gocreate'); |
---|
1157 | |
---|
1158 | if (debug) Main.debug(JSON.stringify(submitInfo)); |
---|
1159 | |
---|
1160 | var request = Ajax.getXmlHttpRequest(); |
---|
1161 | var url = '../MRna.servlet?ID=<%=ID%>'; |
---|
1162 | url += '&cmd=CreateMRnaPlate'; |
---|
1163 | request.open("POST", url, false); |
---|
1164 | request.setRequestHeader("Content-Type", "application/json"); |
---|
1165 | request.send(JSON.stringify(submitInfo)); |
---|
1166 | |
---|
1167 | if (debug) Main.debug(request.responseText); |
---|
1168 | |
---|
1169 | var response = JSON.parse(request.responseText); |
---|
1170 | if (response.status != 'ok') |
---|
1171 | { |
---|
1172 | setFatalError(response.message); |
---|
1173 | return false; |
---|
1174 | } |
---|
1175 | |
---|
1176 | var msg = '<ul>'; |
---|
1177 | for (var i = 0; i < response.messages.length; i++) |
---|
1178 | { |
---|
1179 | msg += '<li>' + response.messages[i]; |
---|
1180 | } |
---|
1181 | msg += '</ul>'; |
---|
1182 | setInnerHTML('done', msg); |
---|
1183 | Main.show('done'); |
---|
1184 | Main.show('gorestart'); |
---|
1185 | } |
---|
1186 | |
---|
1187 | function toggleInfo(what) |
---|
1188 | { |
---|
1189 | var frm = document.forms['reggie']; |
---|
1190 | var show = frm[what].checked; |
---|
1191 | Main.addOrRemoveClass(document.getElementById('plate'), 'hide-'+what, !show); |
---|
1192 | } |
---|
1193 | |
---|
1194 | </script> |
---|
1195 | <style> |
---|
1196 | |
---|
1197 | /* A well assigned for QC include a background icon as indicator */ |
---|
1198 | .well.qc |
---|
1199 | { |
---|
1200 | background-image: url('../images/mrnaqc.png'); |
---|
1201 | background-position: 95% 5%; |
---|
1202 | background-repeat: no-repeat; |
---|
1203 | } |
---|
1204 | |
---|
1205 | /* A well which contain replicate RNA is also marked with an icon */ |
---|
1206 | .well.replicate |
---|
1207 | { |
---|
1208 | background-image: url('../images/copy.png'); |
---|
1209 | background-position: 95% 5%; |
---|
1210 | background-repeat: no-repeat; |
---|
1211 | } |
---|
1212 | |
---|
1213 | /* A well that is both a replicate and QC need to re-arrange the icons a bit */ |
---|
1214 | .well.qc.replicate |
---|
1215 | { |
---|
1216 | background-image: url('../images/mrnaqc.png'), url('../images/copy.png'); |
---|
1217 | background-position: 95% 5%, 95% 55%; |
---|
1218 | background-repeat: no-repeat; |
---|
1219 | } |
---|
1220 | |
---|
1221 | .well .name |
---|
1222 | { |
---|
1223 | font-weight: bold; |
---|
1224 | } |
---|
1225 | |
---|
1226 | .well .err-msg, .well .warn-msg |
---|
1227 | { |
---|
1228 | color: #C80000; |
---|
1229 | font-style: italic; |
---|
1230 | } |
---|
1231 | |
---|
1232 | .well .missing |
---|
1233 | { |
---|
1234 | font-style: italic; |
---|
1235 | } |
---|
1236 | |
---|
1237 | .plate.hide-location .location |
---|
1238 | { |
---|
1239 | display: none; |
---|
1240 | } |
---|
1241 | .plate.hide-quantity .quantity |
---|
1242 | { |
---|
1243 | display: none; |
---|
1244 | } |
---|
1245 | .plate.hide-volumes .volumes |
---|
1246 | { |
---|
1247 | display: none; |
---|
1248 | } |
---|
1249 | .plate.hide-ndconc .ndconc |
---|
1250 | { |
---|
1251 | display: none; |
---|
1252 | } |
---|
1253 | |
---|
1254 | .volume |
---|
1255 | { |
---|
1256 | color: #C80000; |
---|
1257 | } |
---|
1258 | .water |
---|
1259 | { |
---|
1260 | color: #0000C8; |
---|
1261 | } |
---|
1262 | |
---|
1263 | </style> |
---|
1264 | </base:head> |
---|
1265 | <base:body onload="init()"> |
---|
1266 | <p:path><p:pathelement |
---|
1267 | title="Reggie" href="<%="../index.jsp?ID="+ID%>" |
---|
1268 | /><p:pathelement title="Create new mRNA plate" |
---|
1269 | /></p:path> |
---|
1270 | <div id="canvas" class="absolutefull" style="z-index: -1;"> |
---|
1271 | <div class="content"> |
---|
1272 | <% |
---|
1273 | if (sc.getActiveProjectId() == 0) |
---|
1274 | { |
---|
1275 | %> |
---|
1276 | <div class="messagecontainer note" style="width: 950px; margin-left: 20px; margin-bottom: 20px; margin-right: 0px; font-weight: bold; color: #cc0000;"> |
---|
1277 | No project has been selected. You may proceed with the wizard but |
---|
1278 | created items will not be shared. |
---|
1279 | </div> |
---|
1280 | <% |
---|
1281 | } |
---|
1282 | %> |
---|
1283 | <form name="reggie" onsubmit="return false;"> |
---|
1284 | |
---|
1285 | <table class="stepform" id="step.1.section" style="width: auto;"> |
---|
1286 | <tr> |
---|
1287 | <td rowspan="3" class="stepno">1</td> |
---|
1288 | <td class="steptitle">Fragmented mRNA plate</td> |
---|
1289 | </tr> |
---|
1290 | <tr> |
---|
1291 | <td class="stepfields"> |
---|
1292 | <table class="bottomborder" style="width: 100%;"> |
---|
1293 | <tr> |
---|
1294 | <td class="prompt">Name</td> |
---|
1295 | <td class="input" id="plateName"></td> |
---|
1296 | <td class="help">Select RNA items to use for the new mRNA plate.</td> |
---|
1297 | </tr> |
---|
1298 | <tr style="vertical-align: top;"> |
---|
1299 | <td class="prompt">Show</td> |
---|
1300 | <td class="input"> |
---|
1301 | <table> |
---|
1302 | <tr> |
---|
1303 | <td> |
---|
1304 | <input type="checkbox" name="location" id="location" onclick="toggleInfo('location')" checked><label for="location">Bioplate location</label><br> |
---|
1305 | <input type="checkbox" name="quantity" id="quantity" onclick="toggleInfo('quantity')" checked><label for="quantity">Remaining quantity</label><br> |
---|
1306 | </td> |
---|
1307 | <td> |
---|
1308 | <input type="checkbox" name="ndconc" id="ndconc" onclick="toggleInfo('ndconc')"><label for="ndconc">NDConc</label><br> |
---|
1309 | <input type="checkbox" name="volumes" id="volumes" onclick="toggleInfo('volumes')"><label for="volumes">Used volume+water</label><br> |
---|
1310 | </td> |
---|
1311 | </tr> |
---|
1312 | </table> |
---|
1313 | <br> |
---|
1314 | </td> |
---|
1315 | <td class="help"></td> |
---|
1316 | </tr> |
---|
1317 | </table> |
---|
1318 | </td> |
---|
1319 | </tr> |
---|
1320 | |
---|
1321 | <tr> |
---|
1322 | <td> |
---|
1323 | <tbl:toolbar subclass="bottomborder"> |
---|
1324 | <tbl:button |
---|
1325 | title="Load from file…" |
---|
1326 | image="<%=home+"/images/file.png"%>" |
---|
1327 | onclick="selectFile()" |
---|
1328 | tooltip="Load plate design from file" |
---|
1329 | /> |
---|
1330 | |
---|
1331 | <tbl:button |
---|
1332 | title="Auto-select" |
---|
1333 | image="<%=home+"/images/wizard.png"%>" |
---|
1334 | onclick="autoSelect()" |
---|
1335 | tooltip="Let the wizard auto-select RNA" |
---|
1336 | /> |
---|
1337 | <tbl:button |
---|
1338 | title="Manual select…" |
---|
1339 | image="<%=home+"/images/manual_rna.png"%>" |
---|
1340 | onclick="manualSelect()" |
---|
1341 | tooltip="Manually select RNA items" |
---|
1342 | /> |
---|
1343 | <tbl:button |
---|
1344 | title="Stratagene" |
---|
1345 | image="<%=home+"/images/stratagene.png"%>" |
---|
1346 | onclick="setToStratagene()" |
---|
1347 | tooltip="Place stratagene in the selected wells" |
---|
1348 | /> |
---|
1349 | <tbl:button |
---|
1350 | title="Toggle QC" |
---|
1351 | image="<%=home+"/images/mrnaqc.png"%>" |
---|
1352 | onclick="toggleQc()" |
---|
1353 | tooltip="Select/deselect RNA for QC" |
---|
1354 | /> |
---|
1355 | <tbl:button |
---|
1356 | title="Cut…" |
---|
1357 | image="<%=home+"/images/cut.png"%>" |
---|
1358 | onclick="cutSelected()" |
---|
1359 | tooltip="Clear the selected wells" |
---|
1360 | /> |
---|
1361 | <tbl:button |
---|
1362 | title="Copy" |
---|
1363 | image="<%=home+"/images/copy.png"%>" |
---|
1364 | onclick="copySelected()" |
---|
1365 | tooltip="Make a copy of the selected RNA" |
---|
1366 | /> |
---|
1367 | <tbl:button |
---|
1368 | title="Paste" |
---|
1369 | image="<%=home+"/images/paste.png"%>" |
---|
1370 | onclick="pasteToSelected()" |
---|
1371 | tooltip="Paste RNA into selected wells" |
---|
1372 | /> |
---|
1373 | </tbl:toolbar> |
---|
1374 | <table class="plate hide-volumes hide-ndconc" style="margin: 1em 1em 0 1em;" id="plate"> |
---|
1375 | <% |
---|
1376 | int columns = 12; |
---|
1377 | int rows = 8; |
---|
1378 | WellCoordinateFormatter rowF = new WellCoordinateFormatter(true); |
---|
1379 | WellCoordinateFormatter colF = new WellCoordinateFormatter(false); |
---|
1380 | %> |
---|
1381 | <tr class="header"> |
---|
1382 | <th> |
---|
1383 | <base:icon image="<%=home+"/images/select_all.png"%>" |
---|
1384 | onclick="toggleAll()" |
---|
1385 | tooltip="Select/deselect all wells on the plate" |
---|
1386 | /> |
---|
1387 | </th> |
---|
1388 | <% |
---|
1389 | for (int c = 0; c < columns; ++c) |
---|
1390 | { |
---|
1391 | %> |
---|
1392 | <th class="link" id="col.<%=c%>" |
---|
1393 | onclick="toggleColumn(<%=c%>)" |
---|
1394 | onmouseover="highlightColumn(<%=c%>, true)" |
---|
1395 | onmouseout="highlightColumn(<%=c%>, false)" |
---|
1396 | title="Select/deselect all wells in this column"><%=colF.format(c)%></td> |
---|
1397 | <% |
---|
1398 | } |
---|
1399 | %> |
---|
1400 | </tr> |
---|
1401 | <tbody> |
---|
1402 | <% |
---|
1403 | for (int r = 0; r < rows; ++r) |
---|
1404 | { |
---|
1405 | String row = rowF.format(r); |
---|
1406 | %> |
---|
1407 | <tr class="row-<%=r%>"> |
---|
1408 | <th class="link" id="row.<%=r%>" |
---|
1409 | onclick="toggleRow(<%=r%>)" |
---|
1410 | onmouseover="highlightRow(<%=r%>, true)" |
---|
1411 | onmouseout="highlightRow(<%=r%>, false)" |
---|
1412 | title="Select/deselect all wells in this row"><%=row%></th> |
---|
1413 | <% |
---|
1414 | for (int c = 0; c < columns; ++c) |
---|
1415 | { |
---|
1416 | %> |
---|
1417 | <td id="well.<%=r%>.<%=c%>" |
---|
1418 | onclick="toggleWell(<%=r%>,<%=c%>)" |
---|
1419 | onmouseenter="highlightReplicated(<%=r%>, <%=c%>, true)" |
---|
1420 | onmouseleave="highlightReplicated(<%=r%>, <%=c%>, false)" |
---|
1421 | title="Select/deselect this well"></td> |
---|
1422 | <% |
---|
1423 | } |
---|
1424 | %> |
---|
1425 | </tr> |
---|
1426 | <% |
---|
1427 | } |
---|
1428 | %> |
---|
1429 | </tbody> |
---|
1430 | <tr> |
---|
1431 | <th></th> |
---|
1432 | <% |
---|
1433 | for (int i = 0; i < columns / 2; ++i) |
---|
1434 | { |
---|
1435 | %> |
---|
1436 | <th colspan="2" class="link" id="pool.<%=i %>" |
---|
1437 | onclick="togglePool(<%=i%>)" |
---|
1438 | onmouseover="highlightPool(<%=i%>, true)" |
---|
1439 | onmouseout="highlightPool(<%=i%>, false)" |
---|
1440 | title="Select/deselect all wells in this pool" |
---|
1441 | ><%=i==0 || i == (columns / 2 - 1) ? "Extra" : "Pool #" + i %></td> |
---|
1442 | <% |
---|
1443 | } |
---|
1444 | %> |
---|
1445 | </tr> |
---|
1446 | </table> |
---|
1447 | <div style="padding-left: 1em; padding-bottom: 0.5em; padding-top: 2px;"> |
---|
1448 | <base:icon image="<%=home+"/images/mrnaqc.png"%>" />=Selected for QC |
---|
1449 | <base:icon image="<%=home+"/images/copy.png"%>" style="padding-left: 1em;" />=Replicated RNA |
---|
1450 | <base:icon image="<%=home+"/images/error.png"%>" style="padding-left: 1em;" />=Error that prevent plate creation |
---|
1451 | <base:icon image="<%=home+"/images/warning.png"%>" style="padding-left: 1em;" />=Warning but plate can be created |
---|
1452 | </div> |
---|
1453 | </td> |
---|
1454 | </tr> |
---|
1455 | </table> |
---|
1456 | |
---|
1457 | |
---|
1458 | <div class="messagecontainer error" id="errorMessage" style="display: none; width: 950px; margin-left: 20px; margin-bottom: 0px;"></div> |
---|
1459 | |
---|
1460 | <div id="done" class="success" style="display: none; width: 950px; margin-left: 20px; margin-top: 20px;"></div> |
---|
1461 | |
---|
1462 | <table style="margin-left: 20px; margin-top: 10px;" class="navigation"> |
---|
1463 | <tr> |
---|
1464 | <td><base:button id="gocancel" title="Cancel" onclick="goRestart(false)" /></td> |
---|
1465 | <td><base:button id="gocreate" title="Create" image="<%=home+"/images/gonext.png"%>" onclick="goCreate()" /></td> |
---|
1466 | <td><base:button id="gorestart" title="Restart" image="<%=home+"/images/goback.png"%>" onclick="goRestart(true)" style="display: none;"/></td> |
---|
1467 | </tr> |
---|
1468 | </table> |
---|
1469 | </form> |
---|
1470 | |
---|
1471 | <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> |
---|
1472 | |
---|
1473 | </div> |
---|
1474 | </div> |
---|
1475 | </base:body> |
---|
1476 | </base:page> |
---|
1477 | <% |
---|
1478 | } |
---|
1479 | finally |
---|
1480 | { |
---|
1481 | if (dc != null) dc.close(); |
---|
1482 | } |
---|
1483 | %> |
---|