quorum 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
-