quorum 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/Gemfile.lock +35 -28
  2. data/HISTORY.md +4 -0
  3. data/app/assets/javascripts/quorum/application.js +1 -0
  4. data/app/assets/javascripts/quorum/jobs.js +5 -345
  5. data/app/assets/javascripts/quorum/quorum.js +275 -0
  6. data/app/assets/javascripts/quorum/template_settings.js +8 -0
  7. data/app/assets/javascripts/quorum/utilities.js +12 -0
  8. data/app/assets/stylesheets/quorum/application.css +0 -4
  9. data/app/assets/stylesheets/quorum/autohint.css +4 -0
  10. data/app/controllers/quorum/jobs_controller.rb +9 -9
  11. data/app/views/quorum/jobs/form/_blastn_form.html.erb +62 -62
  12. data/app/views/quorum/jobs/form/_blastp_form.html.erb +62 -62
  13. data/app/views/quorum/jobs/form/_blastx_form.html.erb +62 -62
  14. data/app/views/quorum/jobs/form/_tblastn_form.html.erb +62 -62
  15. data/app/views/quorum/jobs/show.html.erb +1 -1
  16. data/app/views/quorum/jobs/templates/_blast_detailed_report_template.html.erb +22 -22
  17. data/app/views/quorum/jobs/templates/_blast_template.html.erb +29 -29
  18. data/app/views/shared/_error_messages.html.erb +8 -8
  19. data/lib/quorum/version.rb +1 -1
  20. data/lib/tasks/jasmine.rake +8 -0
  21. data/quorum.gemspec +1 -0
  22. data/spec/data/seqs_not_fa.txt +16 -16
  23. data/spec/javascripts/fixtures/formatted_sequence.html +6 -0
  24. data/spec/javascripts/fixtures/quorum_search_form.html +461 -0
  25. data/spec/javascripts/fixtures/quorum_tabs.html +10 -0
  26. data/spec/javascripts/helpers/jasmine-jquery.js +288 -0
  27. data/spec/javascripts/jobs_spec.js +99 -0
  28. data/spec/javascripts/jquery/jquery-ui.min.js +791 -0
  29. data/spec/javascripts/jquery/jquery.min.js +4 -0
  30. data/spec/javascripts/jquery/jquery_ujs.js +373 -0
  31. data/spec/javascripts/quorum_spec.js +106 -0
  32. data/spec/javascripts/string_spec.js +18 -0
  33. data/spec/javascripts/support/jasmine.yml +84 -0
  34. data/spec/javascripts/support/jasmine_config.rb +23 -0
  35. data/spec/javascripts/support/jasmine_runner.rb +33 -0
  36. data/spec/requests/jobs_spec.rb +34 -33
  37. data/vendor/assets/javascripts/jquery.autohint.js +87 -0
  38. metadata +62 -26
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- quorum (0.2.0)
4
+ quorum (0.3.0)
5
5
  bio-blastxmlparser (~> 1.0.1)
6
6
  jquery-rails
7
7
  net-ssh (~> 2.3.0)
@@ -12,31 +12,31 @@ PATH
12
12
  GEM
13
13
  remote: http://rubygems.org/
14
14
  specs:
15
- actionmailer (3.2.0)
16
- actionpack (= 3.2.0)
15
+ actionmailer (3.2.1)
16
+ actionpack (= 3.2.1)
17
17
  mail (~> 2.4.0)
18
- actionpack (3.2.0)
19
- activemodel (= 3.2.0)
20
- activesupport (= 3.2.0)
18
+ actionpack (3.2.1)
19
+ activemodel (= 3.2.1)
20
+ activesupport (= 3.2.1)
21
21
  builder (~> 3.0.0)
22
22
  erubis (~> 2.7.0)
23
- journey (~> 1.0.0)
23
+ journey (~> 1.0.1)
24
24
  rack (~> 1.4.0)
25
25
  rack-cache (~> 1.1)
26
26
  rack-test (~> 0.6.1)
27
27
  sprockets (~> 2.1.2)
28
- activemodel (3.2.0)
29
- activesupport (= 3.2.0)
28
+ activemodel (3.2.1)
29
+ activesupport (= 3.2.1)
30
30
  builder (~> 3.0.0)
31
- activerecord (3.2.0)
32
- activemodel (= 3.2.0)
33
- activesupport (= 3.2.0)
31
+ activerecord (3.2.1)
32
+ activemodel (= 3.2.1)
33
+ activesupport (= 3.2.1)
34
34
  arel (~> 3.0.0)
35
35
  tzinfo (~> 0.3.29)
36
- activeresource (3.2.0)
37
- activemodel (= 3.2.0)
38
- activesupport (= 3.2.0)
39
- activesupport (3.2.0)
36
+ activeresource (3.2.1)
37
+ activemodel (= 3.2.1)
38
+ activesupport (= 3.2.1)
39
+ activesupport (3.2.1)
40
40
  i18n (~> 0.6)
41
41
  multi_json (~> 1.0)
42
42
  arel (3.0.0)
@@ -66,7 +66,13 @@ GEM
66
66
  ffi (1.0.11)
67
67
  hike (1.2.1)
68
68
  i18n (0.6.0)
69
- journey (1.0.0)
69
+ jasmine (1.1.2)
70
+ jasmine-core (>= 1.1.0)
71
+ rack (>= 1.1)
72
+ rspec (>= 1.3.1)
73
+ selenium-webdriver (>= 0.1.3)
74
+ jasmine-core (1.1.0)
75
+ journey (1.0.1)
70
76
  jquery-rails (2.0.0)
71
77
  railties (>= 3.2.0.beta, < 5.0)
72
78
  thor (~> 0.14)
@@ -91,17 +97,17 @@ GEM
91
97
  rack
92
98
  rack-test (0.6.1)
93
99
  rack (>= 1.0)
94
- rails (3.2.0)
95
- actionmailer (= 3.2.0)
96
- actionpack (= 3.2.0)
97
- activerecord (= 3.2.0)
98
- activeresource (= 3.2.0)
99
- activesupport (= 3.2.0)
100
+ rails (3.2.1)
101
+ actionmailer (= 3.2.1)
102
+ actionpack (= 3.2.1)
103
+ activerecord (= 3.2.1)
104
+ activeresource (= 3.2.1)
105
+ activesupport (= 3.2.1)
100
106
  bundler (~> 1.0)
101
- railties (= 3.2.0)
102
- railties (3.2.0)
103
- actionpack (= 3.2.0)
104
- activesupport (= 3.2.0)
107
+ railties (= 3.2.1)
108
+ railties (3.2.1)
109
+ actionpack (= 3.2.1)
110
+ activesupport (= 3.2.1)
105
111
  rack-ssl (~> 1.3.2)
106
112
  rake (>= 0.8.7)
107
113
  rdoc (~> 3.4)
@@ -139,7 +145,7 @@ GEM
139
145
  railties (>= 3.0)
140
146
  rspec (~> 2.8.0)
141
147
  rubyzip (0.9.5)
142
- selenium-webdriver (2.17.0)
148
+ selenium-webdriver (2.18.0)
143
149
  childprocess (>= 0.2.5)
144
150
  ffi (~> 1.0.9)
145
151
  multi_json (~> 1.0.4)
@@ -170,6 +176,7 @@ DEPENDENCIES
170
176
  capybara (~> 1.1)
171
177
  database_cleaner (~> 0.6)
172
178
  factory_girl_rails (~> 1.2)
179
+ jasmine (~> 1.1)
173
180
  mysql2 (~> 0.3.11)
174
181
  quorum!
175
182
  resque_spec (~> 0.8)
data/HISTORY.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.3.0 (2012-01-31)
2
+
3
+ * Created QUORUM JS object and added properties.
4
+
1
5
  ## 0.2.1 (2012-01-24)
2
6
 
3
7
  * Rails 3.2 compatible.
@@ -9,5 +9,6 @@
9
9
  //= require jquery-ui
10
10
  //= require underscore-min
11
11
  //= require jquery.tipsy
12
+ //= require jquery.autohint
12
13
  //= require_tree .
13
14
 
@@ -1,72 +1,9 @@
1
- //
2
- // Mustache style Underscore.js templating.
3
- //
4
- _.templateSettings = {
5
- evaluate: /\{\{(.+?)\}\}/g,
6
- interpolate: /\{\{\=(.+?)\}\}/g
7
- };
8
-
9
1
  //
10
2
  // jQuery
11
3
  //---------------------------------------------------------------------------//
12
4
 
13
5
  $(function() {
14
6
 
15
- // jQuery Functions //
16
-
17
- $.fn.extend({
18
- // Add hints to the form elements.
19
- addHints: function() {
20
- $(this).each(function() {
21
- if ($(this).attr('title') === '') {
22
- return;
23
- }
24
-
25
- if ($(this).val() === '') {
26
- $(this).val($(this).attr('title'));
27
-
28
- if (!$(this).hasClass('auto-hint')) {
29
- $(this).addClass('auto-hint');
30
- }
31
- } else {
32
- $(this).removeClass('auto-hint');
33
- }
34
- });
35
- },
36
-
37
- // Remove hints on submit.
38
- removeHintsOnSubmit: function() {
39
- $(this).each(function() {
40
- if ($(this).val() === $(this).attr('title')) {
41
- $(this).val('');
42
- }
43
- });
44
- },
45
-
46
- // Remove hint and class on focus.
47
- focusHint: function() {
48
- $(this).focus(function() {
49
- if ($(this).val() === $(this).attr('title')) {
50
- $(this).val('');
51
- $(this).removeClass('auto-hint');
52
- }
53
- });
54
- },
55
-
56
- // Retain value or add hint.
57
- blurHint: function() {
58
- $(this).blur(function() {
59
- if ($(this).val() === '' && $(this).attr('title') !== '') {
60
- $(this).val($(this).attr('title'));
61
- $(this).addClass('auto-hint');
62
- }
63
- });
64
- }
65
- });
66
-
67
- // End jQuery Functions //
68
-
69
-
70
7
  // Hide Elements //
71
8
 
72
9
  if (!$('#job_blastn_job_attributes_queue').is(':checked')) {
@@ -91,9 +28,7 @@ $(function() {
91
28
  // Form //
92
29
 
93
30
  var form = $('form :input.auto-hint');
94
- form.focusHint();
95
- form.blurHint();
96
- form.addHints();
31
+ form.autoHint();
97
32
 
98
33
  // Toggle Algorithms //
99
34
 
@@ -121,21 +56,22 @@ $(function() {
121
56
  'disabled', 'disabled'
122
57
  );
123
58
 
124
- form.removeHintsOnSubmit();
59
+ form.autoHint('removeHints');
125
60
  });
126
61
 
127
62
  // Reset form.
128
63
  $('#quorum_job_reset').click(function() {
64
+ $('textarea').val('');
129
65
  $('input:text').val('');
130
66
  $('input:file').val('');
131
- $('input:checkbox').attr('checked', false);
67
+ $('input:checkbox').prop('checked', false);
132
68
  $('select').val('');
133
69
 
134
70
  $('.toggle').each(function() {
135
71
  $(this).hide();
136
72
  });
137
73
 
138
- form.addHints();
74
+ form.autoHint('addHints');
139
75
  });
140
76
 
141
77
  // End Form //
@@ -150,279 +86,3 @@ $(function() {
150
86
 
151
87
  });
152
88
 
153
-
154
- //
155
- // JavaScript Functions
156
- //---------------------------------------------------------------------------//
157
-
158
- //
159
- // Poll quorum search results asynchronously and insert them into
160
- // the DOM via #blast_template.
161
- //
162
- var pollResults = function(id, interval, algos) {
163
-
164
- // Set the default poll interval to 5 seconds.
165
- interval = interval || 5000;
166
-
167
- // Algorithms
168
- algos = algos || ["blastn", "blastx", "tblastn", "blastp"];
169
-
170
- _.each(algos, function(a) {
171
- $.getJSON(
172
- '/quorum/jobs/' + id + '/get_quorum_search_results.json?algo=' + a,
173
- function(data) {
174
- if (data.length === 0) {
175
- setTimeout(function() { pollResults(id, interval, [a]); }, interval);
176
- } else {
177
- $('#' + a + '-results').empty();
178
- var temp = _.template(
179
- $('#blast_template').html(), {
180
- data: data,
181
- algo: a
182
- }
183
- );
184
- $('#' + a + '-results').html(temp);
185
- return;
186
- }
187
- }
188
- );
189
- });
190
- }
191
-
192
- //
193
- // Display jQuery UI modal box containing detailed report of all hits
194
- // to the same query. After the modal box is inserted into the DOM,
195
- // automatically scroll to the highlighted hit.
196
- //
197
- var viewDetailedReport = function(id, focus_id, query, algo) {
198
- // Create the modal box.
199
- $('#detailed_report_dialog').html(
200
- "<p class='center'>" +
201
- "Loading... <img src='/assets/quorum/loading.gif' alt='Loading'>" +
202
- "</p>"
203
- ).dialog({
204
- modal: true,
205
- width: 850,
206
- position: 'top'
207
- });
208
-
209
- $.getJSON(
210
- '/quorum/jobs/' + id + '/get_quorum_search_results.json?algo=' + algo +
211
- '&query=' + query,
212
- function(data) {
213
- var temp = _.template(
214
- $('#detailed_report_template').html(), {
215
- data: data,
216
- query: query,
217
- algo: algo
218
- }
219
- );
220
-
221
- // Insert the detailed report data.
222
- $('#detailed_report_dialog').empty().html(temp);
223
-
224
- // Add tipsy to the sequence data.
225
- $('a[rel=quorum-tipsy]').tipsy({ gravity: 's' });
226
-
227
- // Highlight the selected id.
228
- $('#' + focus_id).addClass("ui-state-highlight");
229
-
230
- // Automatically scroll to the selected id.
231
- autoScroll(focus_id, false);
232
- }
233
- );
234
- }
235
-
236
- //
237
- // Helper to add title sequence position attribute for tipsy.
238
- //
239
- // If from > to decrement index; otherwise increment.
240
- // If the algo is tblastn and type is hit OR algo is blastx and type is query,
241
- // increment / decrement by 3; otherwise increment / decrement by 1.
242
- //
243
- var addBaseTitleIndex = function(bases, from, to, algo, type) {
244
- var forward = true;
245
- var value = 1;
246
- var index = from;
247
-
248
- if (from > to) {
249
- forward = false;
250
- }
251
-
252
- // Set value to 3 for the below.
253
- if ((type === "hit" && algo === "tblastn") ||
254
- (type === "query" && algo === "blastx")) {
255
- value = 3;
256
- }
257
-
258
- // Add tipsy to each base.
259
- return _.map(bases.split(''), function(c) {
260
- var str = "<a rel='quorum-tipsy' title=" + index + ">" + c + "</a>";
261
- forward ? index += value : index -= value;
262
- return str;
263
- }).join('');
264
- }
265
-
266
- //
267
- // Format sequence data for detailed report.
268
- //
269
- // If q_from > q_to or h_from > h_to, subtract by increment; otherwise add
270
- // by increment.
271
- //
272
- // If algo is tblastn or blastx, multiple increment by 3.
273
- //
274
- var formatSequenceReport = function(qseq, midline, hseq, q_from, q_to, h_from, h_to, algo) {
275
- var max = qseq.length; // max length
276
- var increment = 60; // increment value
277
- var s = 0; // start position
278
- var e = increment; // end position
279
- var seq = "\n"; // seq string to return
280
-
281
- while(true) {
282
- seq += "qseq " + addBaseTitleIndex(qseq.slice(s, e), q_from, q_to, algo, 'query') + "\n";
283
- seq += " " + midline.slice(s, e) + "\n";
284
- seq += "hseq " + addBaseTitleIndex(hseq.slice(s, e), h_from, h_to, algo, 'hit') + "\n\n";
285
-
286
- if (e >= max) {
287
- break;
288
- }
289
-
290
- s += increment;
291
- e += increment;
292
-
293
- // If the algorithm is blastx, increment * 3 only for qseq.
294
- if (algo === "blastx") {
295
- q_from < q_to ? q_from += (increment * 3) : q_from -= (increment * 3);
296
- } else {
297
- q_from < q_to ? q_from += increment : q_from -= increment;
298
- }
299
-
300
- // If the algorithm is tblastn, increment * 3 only for hseq.
301
- if (algo === "tblastn") {
302
- h_from < h_to ? h_from += (increment * 3) : h_from -= (increment * 3);
303
- } else {
304
- h_from < h_to ? h_from += increment : h_from -= increment;
305
- }
306
- }
307
- return "<p class='small'>Alignment (Mouse over for positions):</p>" +
308
- "<span class='small'><pre>" + seq + "</pre></span>";
309
- }
310
-
311
- //
312
- // Format Query and Hit Strand.
313
- //
314
- // If query_frame or hit_frame < 0, print 'reverse'; print 'forward' otherwise.
315
- //
316
- var formatStrand = function(qstrand, hstrand) {
317
- var q = "";
318
- var h = "";
319
-
320
- qstrand < 0 ? q = "reverse" : q = "forward";
321
- hstrand < 0 ? h = "reverse" : h = "forward";
322
-
323
- return q + " / " + h;
324
- }
325
-
326
- //
327
- // Display links to Hsps in the same group.
328
- //
329
- var displayHspLinks = function(focus, group, data) {
330
- if (group !== null) {
331
- var str = "Related <a onclick=\"(openWindow(" +
332
- "'http://www.ncbi.nlm.nih.gov/books/NBK62051/def-item/blast_glossary.HSP'," +
333
- "'HSP', 800, 300))\">HSPs</a>: ";
334
-
335
- var ids = _.map(group.split(","), function(i) { return parseInt(i); });
336
-
337
- var selected = _(data).chain()
338
- .reject(function(d) { return !_.include(ids, d.id); })
339
- .sortBy(function(d) { return d.id; })
340
- .value();
341
-
342
- _.each(selected, function(e) {
343
- if (e.id !== focus) {
344
- str += "<a onclick='(autoScroll(" + e.id + ", true))'>" + e.hsp_num + "</a> ";
345
- } else {
346
- str += e.hsp_num + " ";
347
- }
348
- });
349
- return str;
350
- }
351
- }
352
-
353
- //
354
- // Download Blast hit sequence.
355
- //
356
- var downloadSequence = function(id, algo_id, algo, el) {
357
- $(el).html('Fetching sequence...');
358
-
359
- $.getJSON(
360
- "/quorum/jobs/" + id + "/get_quorum_blast_hit_sequence.json?algo_id=" +
361
- algo_id + "&algo=" + algo,
362
- function(data) {
363
- getSequenceFile(id, data[0].meta_id, el);
364
- }
365
- );
366
- }
367
-
368
- //
369
- // Poll application for Blast hit sequence.
370
- //
371
- var getSequenceFile = function(id, meta_id, el) {
372
- var url = "/quorum/jobs/" + id +
373
- "/send_quorum_blast_hit_sequence?meta_id=" + meta_id;
374
- $.get(
375
- url,
376
- function(data) {
377
- if (data.length === 0) {
378
- setTimeout(function() { getSequenceFile(id, meta_id, el) }, 2500);
379
- } else {
380
- if (data.indexOf("error") !== -1) {
381
- // Print error message.
382
- $(el).addClass('ui-state-error').html(data);
383
- } else {
384
- // Force browser to download file via iframe.
385
- $(el).addClass('ui-state-highlight').html('Sequence Downloaded Successfully');
386
- $('.quorum_sequence_download').remove();
387
- $('body').append('<iframe class="quorum_sequence_download"></iframe>');
388
- $('.quorum_sequence_download').attr('src', url).hide();
389
- }
390
- }
391
- }
392
- );
393
- }
394
-
395
- //
396
- // Autoscroll to given div id.
397
- //
398
- var autoScroll = function(id, highlight) {
399
- $('html, body').animate({
400
- scrollTop: $('#' + id).offset().top
401
- }, 1000);
402
-
403
- if (highlight) {
404
- $('#' + id).effect("highlight", {}, 4000);
405
- }
406
- }
407
-
408
- //
409
- // Truncate string to length n using word boundary.
410
- //
411
- String.prototype.trunc = function(n) {
412
- var longStr = this.length > n;
413
- var str = longStr ? this.substr(0, n-1) : this;
414
-
415
- longStr ? str.substr(0, str.lastIndexOf(' ')) : str;
416
- return longStr ? str + '...' : str;
417
- }
418
-
419
- //
420
- // Open URL in new window.
421
- //
422
- var openWindow = function(url, name, width, height) {
423
-
424
- var windowSize = "width=" + width + ",height=" + height + ",scrollbars=yes";
425
-
426
- window.open(url, name, windowSize);
427
- }
428
-