genoverse 3.2.0 → 4.0.0-beta1
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.
- package/.eslintrc.js +93 -162
- package/.github/workflows/test.yml +9 -10
- package/.github/workflows/update-gh-pages.yml +33 -0
- package/LICENSE.TXT +2 -2
- package/README.md +176 -3
- package/{i → assets}/sort_handle.png +0 -0
- package/babel.config.js +19 -0
- package/dist/129.css +334 -0
- package/dist/129.css.map +1 -0
- package/dist/129.genoverse.js +2 -0
- package/dist/129.genoverse.js.map +1 -0
- package/dist/15d98c18221c8bcb2334.ttf +0 -0
- package/dist/166.css +2 -0
- package/dist/166.genoverse.js +1 -0
- package/dist/216.css +20 -0
- package/dist/216.css.map +1 -0
- package/dist/232.css +114 -0
- package/dist/232.css.map +1 -0
- package/dist/232.genoverse.js +2 -0
- package/dist/232.genoverse.js.map +1 -0
- package/dist/2e659e443f3e98569e9f.png +0 -0
- package/dist/394.css +114 -0
- package/dist/394.css.map +1 -0
- package/dist/394.genoverse.js +2 -0
- package/dist/394.genoverse.js.map +1 -0
- package/dist/469.css +24 -0
- package/dist/469.css.map +1 -0
- package/dist/469.genoverse.js +2 -0
- package/dist/469.genoverse.js.map +1 -0
- package/dist/4896d4b04430cc3dfb06.woff2 +0 -0
- package/dist/530.css +39 -0
- package/dist/530.css.map +1 -0
- package/dist/530.genoverse.js +2 -0
- package/dist/530.genoverse.js.map +1 -0
- package/dist/547.css +469 -0
- package/dist/547.css.map +1 -0
- package/dist/547.genoverse.js +1 -0
- package/dist/729.css +315 -0
- package/dist/729.css.map +1 -0
- package/dist/79da213423ac0def2058.ttf +0 -0
- package/dist/804.genoverse.js +2 -0
- package/dist/804.genoverse.js.map +1 -0
- package/dist/842.genoverse.js +2 -0
- package/dist/842.genoverse.js.map +1 -0
- package/dist/893.genoverse.js +2 -0
- package/dist/893.genoverse.js.map +1 -0
- package/dist/949.css +315 -0
- package/dist/949.css.map +1 -0
- package/dist/949.genoverse.js +2 -0
- package/dist/949.genoverse.js.map +1 -0
- package/dist/952.css +315 -0
- package/dist/952.css.map +1 -0
- package/dist/952.genoverse.js +2 -0
- package/dist/952.genoverse.js.map +1 -0
- package/dist/d79c2ec96ab9ff1161a2.woff2 +0 -0
- package/dist/genoverse.js +2 -0
- package/dist/genoverse.js.map +1 -0
- package/index.html +13 -14
- package/jest.config.js +5 -0
- package/jest.setup.js +13 -0
- package/package.json +29 -12
- package/{css → src/css}/controlPanel.css +0 -0
- package/{css → src/css}/fileDrop.css +0 -0
- package/src/css/fontawesome.css +3 -0
- package/{css → src/css}/fullscreen.css +0 -0
- package/{css → src/css}/genoverse.css +1 -1
- package/{css → src/css}/karyotype.css +2 -0
- package/{css → src/css}/resizer.css +0 -0
- package/{css → src/css}/tooltips.css +0 -0
- package/{css → src/css}/trackControls.css +0 -0
- package/src/js/Genoverse.js +1747 -0
- package/{js → src/js}/Track/Controller/Sequence.js +6 -4
- package/src/js/Track/Controller/Stranded.js +83 -0
- package/{js → src/js}/Track/Controller.js +201 -160
- package/src/js/Track/Model/File/BAM.js +47 -0
- package/src/js/Track/Model/File/BED.js +122 -0
- package/src/js/Track/Model/File/GFF.js +42 -0
- package/src/js/Track/Model/File/VCF.js +109 -0
- package/src/js/Track/Model/File/WIG.js +82 -0
- package/src/js/Track/Model/File.js +36 -0
- package/src/js/Track/Model/Gene/Ensembl.js +24 -0
- package/{js → src/js}/Track/Model/Gene.js +3 -1
- package/src/js/Track/Model/Sequence/Ensembl.js +6 -0
- package/{js → src/js}/Track/Model/Sequence/Fasta.js +24 -17
- package/{js → src/js}/Track/Model/Sequence.js +10 -7
- package/{js → src/js}/Track/Model/SequenceVariation.js +17 -11
- package/{js → src/js}/Track/Model/Stranded.js +11 -8
- package/src/js/Track/Model/Transcript/Ensembl.js +73 -0
- package/{js → src/js}/Track/Model/Transcript.js +3 -1
- package/{js → src/js}/Track/Model.js +128 -97
- package/{js → src/js}/Track/View/Gene/Ensembl.js +6 -4
- package/src/js/Track/View/Gene.js +8 -0
- package/{js → src/js}/Track/View/Sequence.js +18 -22
- package/src/js/Track/View/SequenceVariation.js +117 -0
- package/src/js/Track/View/Transcript/Ensembl.js +17 -0
- package/src/js/Track/View/Transcript.js +32 -0
- package/{js → src/js}/Track/View.js +200 -159
- package/{js → src/js}/Track/library/Chromosome.js +18 -13
- package/src/js/Track/library/File/BAM.js +34 -0
- package/src/js/Track/library/File/BED.js +27 -0
- package/src/js/Track/library/File/BIGBED.js +51 -0
- package/src/js/Track/library/File/BIGWIG.js +54 -0
- package/src/js/Track/library/File/GFF.js +10 -0
- package/{js → src/js}/Track/library/File/VCF.js +29 -22
- package/src/js/Track/library/File/WIG.js +8 -0
- package/{js → src/js}/Track/library/File.js +4 -2
- package/src/js/Track/library/Gene.js +44 -0
- package/src/js/Track/library/Graph/Bar.js +263 -0
- package/src/js/Track/library/Graph/Line.js +335 -0
- package/{js → src/js}/Track/library/Graph.js +137 -114
- package/{js → src/js}/Track/library/HighlightRegion.js +118 -93
- package/src/js/Track/library/Legend.js +258 -0
- package/{js → src/js}/Track/library/Scalebar.js +69 -49
- package/{js → src/js}/Track/library/Scaleline.js +29 -27
- package/src/js/Track/library/Static.js +82 -0
- package/{js → src/js}/Track/library/dbSNP.js +47 -50
- package/src/js/Track.js +649 -0
- package/{js → src/js}/genomes/grch37.js +52 -52
- package/{js → src/js}/genomes/grch38.js +52 -52
- package/src/js/lib/BWReader.js +562 -0
- package/src/js/lib/VCFReader.js +296 -0
- package/src/js/lib/dalliance/bam.js +517 -0
- package/src/js/lib/dalliance/bin.js +317 -0
- package/src/js/lib/dalliance/jszlib-inflate.js +2159 -0
- package/src/js/lib/dalliance/lh3utils.js +105 -0
- package/src/js/lib/dalliance/sha1.js +334 -0
- package/src/js/lib/import-tracks.js +42 -0
- package/{js/lib → src/js/lib/jquery-plugins}/jquery.mousehold.js +0 -0
- package/{js/lib → src/js/lib/jquery-plugins}/jquery.mousewheel.js +0 -0
- package/{js/lib → src/js/lib/jquery-plugins}/jquery.tipsy.js +0 -0
- package/src/js/lib/jquery.js +26 -0
- package/src/js/lib/polyfills.js +11 -0
- package/src/js/lib/wrap-functions.js +88 -0
- package/src/js/plugins/controlPanel.js +388 -0
- package/src/js/plugins/fileDrop.js +81 -0
- package/src/js/plugins/focusRegion.js +13 -0
- package/{js → src/js}/plugins/fullscreen.js +18 -14
- package/{js → src/js}/plugins/karyotype.js +51 -45
- package/src/js/plugins/resizer.js +52 -0
- package/{js → src/js}/plugins/tooltips.js +31 -29
- package/src/js/plugins/trackControls.js +159 -0
- package/test/View/render-legends.test.js +1 -1
- package/test/create-and-destroy.test.js +2 -2
- package/test/track-ordering.test.js +3 -2
- package/test/track_config/config-settings.test.js +1 -1
- package/test/utils.js +4 -2
- package/webpack.config.js +103 -34
- package/css/font-awesome.css +0 -3
- package/expanded.html +0 -120
- package/fontawesome/css/fontawesome.min.css +0 -5
- package/fontawesome/css/regular.min.css +0 -5
- package/fontawesome/css/solid.min.css +0 -5
- package/fontawesome/webfonts/fa-brands-400.ttf +0 -0
- package/fontawesome/webfonts/fa-brands-400.woff +0 -0
- package/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
- package/fontawesome/webfonts/fa-regular-400.ttf +0 -0
- package/fontawesome/webfonts/fa-regular-400.woff +0 -0
- package/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
- package/fontawesome/webfonts/fa-solid-900.ttf +0 -0
- package/fontawesome/webfonts/fa-solid-900.woff +0 -0
- package/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
- package/help.pdf +0 -0
- package/index.js +0 -83
- package/js/Genoverse.js +0 -1681
- package/js/Track/Controller/Stranded.js +0 -73
- package/js/Track/Model/File/BAM.js +0 -44
- package/js/Track/Model/File/BED.js +0 -116
- package/js/Track/Model/File/GFF.js +0 -40
- package/js/Track/Model/File/VCF.js +0 -101
- package/js/Track/Model/File/WIG.js +0 -67
- package/js/Track/Model/File.js +0 -36
- package/js/Track/Model/Gene/Ensembl.js +0 -22
- package/js/Track/Model/Sequence/Ensembl.js +0 -4
- package/js/Track/Model/Transcript/Ensembl.js +0 -67
- package/js/Track/View/Gene.js +0 -6
- package/js/Track/View/Sequence/Variation.js +0 -115
- package/js/Track/View/Transcript/Ensembl.js +0 -12
- package/js/Track/View/Transcript.js +0 -28
- package/js/Track/library/File/BAM.js +0 -30
- package/js/Track/library/File/BED.js +0 -24
- package/js/Track/library/File/BIGBED.js +0 -47
- package/js/Track/library/File/BIGWIG.js +0 -52
- package/js/Track/library/File/GFF.js +0 -9
- package/js/Track/library/File/WIG.js +0 -5
- package/js/Track/library/Gene.js +0 -37
- package/js/Track/library/Graph/Bar.js +0 -235
- package/js/Track/library/Graph/Line.js +0 -296
- package/js/Track/library/Legend.js +0 -224
- package/js/Track/library/Static.js +0 -78
- package/js/Track.js +0 -632
- package/js/genoverse.min.js +0 -2
- package/js/genoverse.min.js.map +0 -1
- package/js/lib/BWReader.js +0 -578
- package/js/lib/Base.js +0 -145
- package/js/lib/VCFReader.js +0 -286
- package/js/lib/dalliance/js/bam.js +0 -494
- package/js/lib/dalliance/js/bin.js +0 -185
- package/js/lib/dalliance/js/das.js +0 -749
- package/js/lib/dalliance/js/utils.js +0 -370
- package/js/lib/dalliance-lib.js +0 -3594
- package/js/lib/dalliance-lib.min.js +0 -68
- package/js/lib/jDataView.js +0 -2
- package/js/lib/jParser.js +0 -192
- package/js/lib/jquery-ui.js +0 -8
- package/js/lib/jquery.js +0 -2
- package/js/lib/rtree.js +0 -1
- package/js/plugins/controlPanel.js +0 -395
- package/js/plugins/fileDrop.js +0 -62
- package/js/plugins/focusRegion.js +0 -12
- package/js/plugins/resizer.js +0 -45
- package/js/plugins/trackControls.js +0 -143
- package/utils/expandedTemplate.html +0 -46
- package/utils/git-hooks/post-commit +0 -9
- package/utils/git-hooks/pre-commit +0 -7
- package/utils/git-hooks/setup +0 -6
- package/utils/makeExpanded.js +0 -19
|
@@ -1,12 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
import Base from 'basejs';
|
|
2
|
+
import wrapFunctions from '../lib/wrap-functions';
|
|
3
|
+
|
|
4
|
+
export default Base.extend({
|
|
2
5
|
scrollBuffer : 1.2, // Number of widths, if left or right closer to the edges of viewpoint than the buffer, start making more images
|
|
3
6
|
threshold : Infinity, // Length above which the track is not drawn
|
|
4
7
|
clickTolerance : 0, // pixels of tolerance added to a click position when finding features for popup menus, when scale < 1
|
|
5
8
|
messages : undefined,
|
|
6
9
|
|
|
7
10
|
constructor: function (properties) {
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
Object.entries(properties).forEach(
|
|
12
|
+
([ key, val ]) => {
|
|
13
|
+
if (typeof val !== 'undefined') {
|
|
14
|
+
this[key] = val;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
wrapFunctions(this, 'Controller');
|
|
10
20
|
this.init();
|
|
11
21
|
},
|
|
12
22
|
|
|
@@ -24,17 +34,17 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
24
34
|
this.messages = this.messages || {
|
|
25
35
|
error : 'ERROR: ',
|
|
26
36
|
threshold : 'Data for this track is not displayed in regions greater than ',
|
|
27
|
-
resize : 'Some features are currently hidden, <a class="gv-resize">resize to see all</a>'
|
|
37
|
+
resize : 'Some features are currently hidden, <a class="gv-resize">resize to see all</a>',
|
|
28
38
|
};
|
|
29
39
|
},
|
|
30
40
|
|
|
31
|
-
reset: function () {
|
|
41
|
+
reset: function (arg) {
|
|
32
42
|
this.abort();
|
|
33
43
|
this.setDefaults();
|
|
34
44
|
this.resetImages();
|
|
35
45
|
this.browser.closeMenus(this);
|
|
36
46
|
|
|
37
|
-
if (
|
|
47
|
+
if (arg !== 'resizing') {
|
|
38
48
|
this.setScale();
|
|
39
49
|
this.makeFirstImage();
|
|
40
50
|
}
|
|
@@ -46,7 +56,7 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
46
56
|
},
|
|
47
57
|
|
|
48
58
|
resetImageRanges: function () {
|
|
49
|
-
|
|
59
|
+
const browser = this.browser;
|
|
50
60
|
|
|
51
61
|
this.left = 0;
|
|
52
62
|
this.scrollStart = [ 'ss', browser.chr, browser.start, browser.end ].join('-');
|
|
@@ -57,11 +67,11 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
57
67
|
|
|
58
68
|
setName: function (name, configName) {
|
|
59
69
|
this.track.name = name;
|
|
60
|
-
this.labelName = this.labelName ||
|
|
70
|
+
this.labelName = this.labelName || this.browser.jQuery('<span class="gv-name">').appendTo(this.label);
|
|
61
71
|
|
|
62
72
|
this.labelName.attr('title', name).html(
|
|
63
73
|
configName && configName.length
|
|
64
|
-
? configName.map(
|
|
74
|
+
? configName.map(part => `<span class="gv-name-part">${part}</span>`)
|
|
65
75
|
: name
|
|
66
76
|
);
|
|
67
77
|
|
|
@@ -75,28 +85,35 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
75
85
|
},
|
|
76
86
|
|
|
77
87
|
addDomElements: function () {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
this.
|
|
82
|
-
this.
|
|
83
|
-
this.
|
|
84
|
-
this.
|
|
85
|
-
this.label =
|
|
86
|
-
this.context =
|
|
88
|
+
const name = this.track.name || '';
|
|
89
|
+
const jQuery = this.browser.jQuery;
|
|
90
|
+
|
|
91
|
+
this.menus = jQuery();
|
|
92
|
+
this.container = jQuery('<div class="gv-track-container">').appendTo(this.browser.wrapper);
|
|
93
|
+
this.scrollContainer = jQuery('<div class="gv-scroll-container">').appendTo(this.container);
|
|
94
|
+
this.imgContainer = jQuery('<div class="gv-image-container">').width(this.width).addClass(this.prop('invert') ? 'gv-invert' : '');
|
|
95
|
+
this.label = jQuery('<li>').appendTo(this.browser.labelContainer).height(this.prop('height')).data('track', this.track);
|
|
96
|
+
this.context = jQuery('<canvas>')[0].getContext('2d');
|
|
97
|
+
this.messageContainer = jQuery(`
|
|
98
|
+
<div class="gv-message-container">
|
|
99
|
+
<div class="gv-messages"></div>
|
|
100
|
+
<i class="gv-control gv-collapse fas fa-angle-double-left"></i>
|
|
101
|
+
<i class="gv-control gv-expand fas fa-angle-double-right"></i>
|
|
102
|
+
</div>
|
|
103
|
+
`).appendTo(this.container);
|
|
87
104
|
|
|
88
105
|
if (this.prop('border')) {
|
|
89
|
-
|
|
106
|
+
jQuery('<div class="gv-track-border">').appendTo(this.container);
|
|
90
107
|
}
|
|
91
108
|
|
|
92
109
|
if (this.prop('unsortable')) {
|
|
93
110
|
this.label.addClass('gv-unsortable');
|
|
94
111
|
} else {
|
|
95
|
-
|
|
112
|
+
jQuery('<div class="gv-handle">').appendTo(this.label);
|
|
96
113
|
}
|
|
97
114
|
|
|
98
115
|
if (this.prop('children')) {
|
|
99
|
-
this.superContainer =
|
|
116
|
+
this.superContainer = jQuery('<div class="gv-track-container gv-track-super-container">').insertAfter(this.container);
|
|
100
117
|
this.container.appendTo(this.superContainer);
|
|
101
118
|
} else if (this.prop('parentTrack')) {
|
|
102
119
|
this.superContainer = this.prop('parentTrack').prop('superContainer');
|
|
@@ -113,10 +130,10 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
113
130
|
},
|
|
114
131
|
|
|
115
132
|
addUserEventHandlers: function () {
|
|
116
|
-
|
|
117
|
-
|
|
133
|
+
const controller = this;
|
|
134
|
+
const browser = this.browser;
|
|
118
135
|
|
|
119
|
-
this.container.on('mouseup', '.gv-image-container',
|
|
136
|
+
this.container.on('mouseup', '.gv-image-container', (e) => {
|
|
120
137
|
if ((e.which && e.which !== 1) || (typeof browser.dragStart === 'number' && browser.start !== browser.dragStart) || (browser.dragAction === 'select' && browser.selector.outerWidth(true) > 2)) {
|
|
121
138
|
return; // Only show menus on left click when not dragging and not selecting
|
|
122
139
|
}
|
|
@@ -124,23 +141,24 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
124
141
|
controller.click(e);
|
|
125
142
|
});
|
|
126
143
|
|
|
127
|
-
this.messageContainer.children().on('click',
|
|
128
|
-
|
|
129
|
-
|
|
144
|
+
this.messageContainer.children().on('click', () => {
|
|
145
|
+
const collapsed = controller.messageContainer.children('.gv-messages').is(':visible') ? ' gv-collapsed' : '';
|
|
146
|
+
const code = controller.messageContainer.find('.gv-msg').data('code');
|
|
130
147
|
|
|
131
|
-
controller.messageContainer.attr('class',
|
|
148
|
+
controller.messageContainer.attr('class', `gv-message-container${collapsed}`);
|
|
132
149
|
controller.checkHeight();
|
|
133
150
|
|
|
134
151
|
if (code !== 'error') {
|
|
135
|
-
document.cookie =
|
|
152
|
+
document.cookie = `gv_msg_${code}_${controller.prop('id')}=1; expires=${collapsed ? 'Tue, 19 Jan 2038' : 'Thu, 01 Jan 1970'} 00:00:00 GMT; path=/`;
|
|
136
153
|
}
|
|
137
154
|
});
|
|
138
155
|
},
|
|
139
156
|
|
|
140
157
|
click: function (e) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
158
|
+
const target = this.browser.jQuery(e.target);
|
|
159
|
+
const x = e.pageX - this.container.parent().offset().left + this.browser.scaledStart;
|
|
160
|
+
|
|
161
|
+
let y = e.pageY - target.offset().top;
|
|
144
162
|
|
|
145
163
|
if (this.imgContainer.hasClass('gv-invert')) {
|
|
146
164
|
y = target.height() - y;
|
|
@@ -150,28 +168,30 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
150
168
|
},
|
|
151
169
|
|
|
152
170
|
getClickedFeatures: function (x, y, target) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
171
|
+
const bounds = { x: x, y: y, w: 1, h: 1 };
|
|
172
|
+
const scale = this.scale;
|
|
173
|
+
const tolerance = scale < 1 ? this.clickTolerance : 0;
|
|
156
174
|
|
|
157
175
|
if (tolerance) {
|
|
158
176
|
bounds.x -= tolerance / 2;
|
|
159
177
|
bounds.w += tolerance;
|
|
160
178
|
}
|
|
161
179
|
|
|
162
|
-
|
|
180
|
+
const features = this[target && target.hasClass('gv-labels') ? 'labelPositions' : 'featurePositions'].search(bounds);
|
|
163
181
|
|
|
164
182
|
if (tolerance) {
|
|
165
|
-
return features.filter(
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
183
|
+
return features.filter(
|
|
184
|
+
(f) => {
|
|
185
|
+
const featureBounds = f.position[scale].bounds;
|
|
186
|
+
const center = featureBounds.x + (featureBounds.w / 2);
|
|
187
|
+
const minX = Math.min(featureBounds.x, center - (tolerance / 2));
|
|
188
|
+
const maxX = Math.max(featureBounds.x + featureBounds.w, center + (tolerance / 2));
|
|
189
|
+
|
|
190
|
+
return x >= minX && x <= maxX;
|
|
191
|
+
}
|
|
192
|
+
).sort(
|
|
193
|
+
(a, b) => Math.abs(a.position[scale].start - x) - Math.abs(b.position[scale].start - x)
|
|
194
|
+
);
|
|
175
195
|
}
|
|
176
196
|
|
|
177
197
|
return this.model.sortFeatures(features);
|
|
@@ -179,21 +199,23 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
179
199
|
|
|
180
200
|
// FIXME: messages are now hidden/shown instead of removed/added. This will cause a problem if a new message arrives with the same code as one that already exists.
|
|
181
201
|
showMessage: function (code, additionalText) {
|
|
182
|
-
|
|
202
|
+
let messages = this.messageContainer.children('.gv-messages');
|
|
183
203
|
|
|
184
|
-
if (!messages.children(
|
|
185
|
-
|
|
204
|
+
if (!messages.children(`.gv-${code}`).show().length) {
|
|
205
|
+
const msg = this.browser.jQuery(`<div class="gv-msg gv-${code}">${this.messages[code]}${additionalText || ''}</div>`).data('code', code).prependTo(messages);
|
|
186
206
|
|
|
187
207
|
if (code === 'resize') {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
208
|
+
const controller = this;
|
|
209
|
+
|
|
210
|
+
msg.children('a.gv-resize').on('click', () => {
|
|
211
|
+
controller.resize(controller.fullVisibleHeight);
|
|
212
|
+
});
|
|
191
213
|
}
|
|
192
214
|
|
|
193
|
-
this.messageContainer[document.cookie.match([ 'gv_msg', code, this.prop('id') ].join('_')
|
|
215
|
+
this.messageContainer[document.cookie.match(`${[ 'gv_msg', code, this.prop('id') ].join('_')}=1`) ? 'addClass' : 'removeClass']('gv-collapsed');
|
|
194
216
|
}
|
|
195
217
|
|
|
196
|
-
|
|
218
|
+
const height = this.messageContainer.show().outerHeight(true);
|
|
197
219
|
|
|
198
220
|
if (height > this.prop('height')) {
|
|
199
221
|
this.resize(height, undefined, false);
|
|
@@ -203,10 +225,10 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
203
225
|
},
|
|
204
226
|
|
|
205
227
|
hideMessage: function (code) {
|
|
206
|
-
|
|
228
|
+
let messages = this.messageContainer.find('.gv-msg');
|
|
207
229
|
|
|
208
230
|
if (code) {
|
|
209
|
-
messages = messages.filter(
|
|
231
|
+
messages = messages.filter(`.gv-${code}`).hide();
|
|
210
232
|
|
|
211
233
|
if (messages.length && !messages.siblings().filter(function () { return this.style.display !== 'none'; }).length) {
|
|
212
234
|
this.messageContainer.hide();
|
|
@@ -239,7 +261,7 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
239
261
|
return;
|
|
240
262
|
}
|
|
241
263
|
|
|
242
|
-
|
|
264
|
+
let autoHeight;
|
|
243
265
|
|
|
244
266
|
if (this.browser.length > this.threshold) {
|
|
245
267
|
autoHeight = this.prop('autoHeight');
|
|
@@ -256,22 +278,23 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
256
278
|
},
|
|
257
279
|
|
|
258
280
|
visibleFeatureHeight: function () {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
281
|
+
const bounds = { x: this.browser.scaledStart, w: this.width, y: 0, h: 9e99 };
|
|
282
|
+
const scale = this.scale;
|
|
283
|
+
const features = this.featurePositions.search(bounds);
|
|
284
|
+
const minHeight = this.prop('hideEmpty') ? 0 : this.minLabelHeight;
|
|
285
|
+
|
|
286
|
+
let height = Math.max(...features.map(feature => feature.position[scale].bottom).concat(minHeight));
|
|
264
287
|
|
|
265
288
|
if (this.prop('labels') === 'separate') {
|
|
266
289
|
this.labelTop = height;
|
|
267
|
-
height
|
|
290
|
+
height += Math.max(...this.labelPositions.search(bounds).concat(this.prop('repeatLabels') ? features : []).map(feature => feature.position[scale].label.bottom).concat(minHeight));
|
|
268
291
|
}
|
|
269
292
|
|
|
270
293
|
return height;
|
|
271
294
|
},
|
|
272
295
|
|
|
273
296
|
autoResize: function () {
|
|
274
|
-
|
|
297
|
+
const autoHeight = this.prop('autoHeight');
|
|
275
298
|
|
|
276
299
|
if (autoHeight || this.prop('labels') === 'separate') {
|
|
277
300
|
this.resize(autoHeight ? this.fullVisibleHeight : this.prop('height'), this.labelTop, false);
|
|
@@ -301,8 +324,8 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
301
324
|
return;
|
|
302
325
|
}
|
|
303
326
|
|
|
304
|
-
|
|
305
|
-
|
|
327
|
+
const featureMargin = this.prop('featureMargin');
|
|
328
|
+
const height = this.prop('height');
|
|
306
329
|
|
|
307
330
|
// Note: fullVisibleHeight - featureMargin.top - featureMargin.bottom is not actually the correct value to test against, but it's the easiest best guess to obtain.
|
|
308
331
|
// fullVisibleHeight is the maximum bottom position of the track's features in the region, which includes margin at the bottom of each feature and label
|
|
@@ -312,14 +335,14 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
312
335
|
if (this.fullVisibleHeight - featureMargin.top - featureMargin.bottom > height && !this.prop('disabled')) {
|
|
313
336
|
this.showMessage('resize');
|
|
314
337
|
|
|
315
|
-
|
|
316
|
-
|
|
338
|
+
const controller = this;
|
|
339
|
+
const h = this.messageContainer.outerHeight(true);
|
|
317
340
|
|
|
318
341
|
if (h > height) {
|
|
319
342
|
this.resize(h, undefined, saveConfig);
|
|
320
343
|
}
|
|
321
344
|
|
|
322
|
-
this.expander = (this.expander ||
|
|
345
|
+
this.expander = (this.expander || this.browser.jQuery('<div class="gv-expander gv-static">').width(this.width).appendTo(this.container).on('click', () => {
|
|
323
346
|
controller.resize(controller.fullVisibleHeight);
|
|
324
347
|
}))[this.prop('height') === 0 ? 'hide' : 'show']();
|
|
325
348
|
} else if (this.expander) {
|
|
@@ -329,22 +352,24 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
329
352
|
},
|
|
330
353
|
|
|
331
354
|
setLabelHeight: function (enforceMinHeight) {
|
|
332
|
-
|
|
355
|
+
const parent = this.prop('parentTrack');
|
|
333
356
|
|
|
334
357
|
if (parent) {
|
|
335
|
-
|
|
358
|
+
parent.controller.setLabelHeight();
|
|
359
|
+
|
|
360
|
+
return;
|
|
336
361
|
}
|
|
337
362
|
|
|
338
|
-
|
|
339
|
-
|
|
363
|
+
const tracks = [ this ].concat(this.prop('childTracks') || []);
|
|
364
|
+
const height = tracks.reduce((h, track) => h + (track.prop('disabled') ? 0 : track.prop('height')), 0);
|
|
340
365
|
|
|
341
366
|
this.label.height(this.prop('disabled') ? 0 : enforceMinHeight && this.minLabelHeight ? Math.max(height, this.minLabelHeight) : height);
|
|
342
367
|
|
|
343
368
|
if (tracks.length > 1) {
|
|
344
|
-
|
|
369
|
+
let top = tracks[0].prop('height');
|
|
345
370
|
|
|
346
|
-
tracks.slice(1).forEach(
|
|
347
|
-
|
|
371
|
+
tracks.slice(1).forEach((track) => {
|
|
372
|
+
const h = track.prop('height');
|
|
348
373
|
|
|
349
374
|
track.prop('labelName').css('top', top)[h ? 'removeClass' : 'addClass']('gv-hide');
|
|
350
375
|
top += h;
|
|
@@ -353,24 +378,22 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
353
378
|
},
|
|
354
379
|
|
|
355
380
|
setWidth: function (width) {
|
|
356
|
-
|
|
381
|
+
const track = this.track;
|
|
357
382
|
|
|
358
|
-
|
|
359
|
-
this.width = width;
|
|
360
|
-
});
|
|
383
|
+
[ this, track, track.model, track.view ].forEach((obj) => { obj.width = width; });
|
|
361
384
|
|
|
362
385
|
this.imgContainer.add(this.expander).width(width);
|
|
363
386
|
},
|
|
364
387
|
|
|
365
388
|
setScale: function () {
|
|
366
|
-
|
|
389
|
+
const controller = this;
|
|
367
390
|
|
|
368
391
|
this.scale = this.browser.scale;
|
|
369
392
|
|
|
370
393
|
this.track.setMVC();
|
|
371
394
|
this.resetImageRanges();
|
|
372
395
|
|
|
373
|
-
|
|
396
|
+
const labels = this.prop('labels');
|
|
374
397
|
|
|
375
398
|
if (labels && labels !== 'overlay') {
|
|
376
399
|
this.model.setLabelBuffer(this.browser.labelBuffer);
|
|
@@ -380,7 +403,9 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
380
403
|
this.thresholdMessage = this.view.formatLabel(this.threshold);
|
|
381
404
|
}
|
|
382
405
|
|
|
383
|
-
|
|
406
|
+
Object.entries(this.view.setScaleSettings(this.scale)).forEach(
|
|
407
|
+
([ key, value ]) => { controller[key] = value; }
|
|
408
|
+
);
|
|
384
409
|
|
|
385
410
|
this.hideMessage();
|
|
386
411
|
},
|
|
@@ -389,10 +414,10 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
389
414
|
this.left += delta;
|
|
390
415
|
this.scrollContainer.css('left', this.left);
|
|
391
416
|
|
|
392
|
-
|
|
417
|
+
const scrollStart = this.scrollStart;
|
|
393
418
|
|
|
394
419
|
if (this.imgRange[scrollStart] && this.imgRange[scrollStart].left + this.left > -this.scrollBuffer * this.width) {
|
|
395
|
-
|
|
420
|
+
const end = this.scrollRange[scrollStart].start - 1;
|
|
396
421
|
|
|
397
422
|
this.makeImage({
|
|
398
423
|
scale : this.scale,
|
|
@@ -400,7 +425,7 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
400
425
|
start : end - this.browser.length + 1,
|
|
401
426
|
end : end,
|
|
402
427
|
left : this.imgRange[scrollStart].left,
|
|
403
|
-
cls : scrollStart
|
|
428
|
+
cls : scrollStart,
|
|
404
429
|
});
|
|
405
430
|
|
|
406
431
|
(this.imgRange[scrollStart] || {}).left -= this.width;
|
|
@@ -408,7 +433,7 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
408
433
|
}
|
|
409
434
|
|
|
410
435
|
if (this.imgRange[scrollStart] && this.imgRange[scrollStart].right + this.left < this.scrollBuffer * this.width) {
|
|
411
|
-
|
|
436
|
+
const start = this.scrollRange[scrollStart].end + 1;
|
|
412
437
|
|
|
413
438
|
this.makeImage({
|
|
414
439
|
scale : this.scale,
|
|
@@ -416,7 +441,7 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
416
441
|
start : start,
|
|
417
442
|
end : start + this.browser.length - 1,
|
|
418
443
|
left : this.imgRange[scrollStart].right,
|
|
419
|
-
cls : scrollStart
|
|
444
|
+
cls : scrollStart,
|
|
420
445
|
});
|
|
421
446
|
|
|
422
447
|
(this.imgRange[scrollStart] || {}).right += this.width;
|
|
@@ -425,8 +450,8 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
425
450
|
},
|
|
426
451
|
|
|
427
452
|
moveTo: function (chr, start, end, delta) {
|
|
428
|
-
|
|
429
|
-
|
|
453
|
+
const scrollRange = this.scrollRange[this.scrollStart];
|
|
454
|
+
const scrollStart = [ 'ss', chr, start, end ].join('-');
|
|
430
455
|
|
|
431
456
|
if (this.scrollRange[scrollStart] || start > scrollRange.end || end < scrollRange.start) {
|
|
432
457
|
this.resetImageRanges();
|
|
@@ -444,23 +469,25 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
444
469
|
params.featureHeight = params.featureHeight || 0;
|
|
445
470
|
params.labelHeight = params.labelHeight || 0;
|
|
446
471
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
472
|
+
const controller = this;
|
|
473
|
+
const jQuery = this.browser.jQuery;
|
|
474
|
+
const tooLarge = this.browser.length > this.threshold;
|
|
475
|
+
const div = this.imgContainer.clone().addClass((`${params.cls} gv-loading`).replace('.', '_')).css({ left: params.left, display: params.cls === this.scrollStart ? 'block' : 'none' });
|
|
476
|
+
const bgImage = params.background ? jQuery('<img class="gv-bg">').hide().addClass(params.background).data(params).prependTo(div) : false;
|
|
477
|
+
const image = this.browser.jQuery('<img class="gv-data">').hide().data(params).appendTo(div).on('load', function () {
|
|
478
|
+
jQuery(this).fadeIn('fast').parent().removeClass('gv-loading');
|
|
479
|
+
jQuery(this).siblings('.gv-bg').show();
|
|
455
480
|
});
|
|
456
481
|
|
|
482
|
+
let deferred;
|
|
483
|
+
|
|
457
484
|
params.container = div;
|
|
458
485
|
|
|
459
486
|
this.imgContainers.push(div[0]);
|
|
460
487
|
this.scrollContainer.append(this.imgContainers);
|
|
461
488
|
|
|
462
489
|
if (!tooLarge && !this.model.checkDataRange(params.chr, params.start, params.end)) {
|
|
463
|
-
|
|
490
|
+
const buffer = this.prop('dataBuffer');
|
|
464
491
|
|
|
465
492
|
params.start -= buffer.start;
|
|
466
493
|
params.end += buffer.end;
|
|
@@ -468,44 +495,49 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
468
495
|
}
|
|
469
496
|
|
|
470
497
|
if (!deferred) {
|
|
471
|
-
deferred =
|
|
472
|
-
setTimeout(
|
|
498
|
+
deferred = jQuery.Deferred();
|
|
499
|
+
setTimeout(deferred.resolve, 1); // This defer makes scrolling A LOT smoother, pushing render call to the end of the exec queue
|
|
473
500
|
}
|
|
474
501
|
|
|
475
502
|
this.deferreds.push(deferred);
|
|
476
503
|
|
|
477
|
-
return deferred.done(
|
|
478
|
-
|
|
479
|
-
|
|
504
|
+
return deferred.done(
|
|
505
|
+
() => {
|
|
506
|
+
const features = tooLarge ? [] : controller.model.findFeatures(params.chr, params.start, params.end);
|
|
507
|
+
|
|
508
|
+
controller.render(features, image);
|
|
480
509
|
|
|
481
|
-
|
|
482
|
-
|
|
510
|
+
if (bgImage) {
|
|
511
|
+
controller.renderBackground(features, bgImage);
|
|
512
|
+
}
|
|
483
513
|
}
|
|
484
|
-
|
|
485
|
-
controller.showError(e);
|
|
486
|
-
|
|
514
|
+
).fail(
|
|
515
|
+
(e) => { controller.showError(e); }
|
|
516
|
+
);
|
|
487
517
|
},
|
|
488
518
|
|
|
489
519
|
makeFirstImage: function (moveTo) {
|
|
490
|
-
|
|
520
|
+
const jQuery = this.browser.jQuery;
|
|
521
|
+
const deferred = jQuery.Deferred();
|
|
491
522
|
|
|
492
|
-
if (this.scrollContainer.children().hide().filter(
|
|
523
|
+
if (this.scrollContainer.children().hide().filter(`.${moveTo || this.scrollStart}`).show().length) {
|
|
493
524
|
this.scrollContainer.css('left', 0);
|
|
494
525
|
this.checkHeight();
|
|
495
526
|
|
|
496
527
|
return deferred.resolve();
|
|
497
528
|
}
|
|
498
529
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
530
|
+
const controller = this;
|
|
531
|
+
const chr = this.browser.chr;
|
|
532
|
+
const start = this.browser.start;
|
|
533
|
+
const end = this.browser.end;
|
|
534
|
+
const length = this.browser.length;
|
|
535
|
+
const scale = this.scale;
|
|
536
|
+
const cls = this.scrollStart;
|
|
537
|
+
const images = [{ chr: chr, start: start, end: end, scale: scale, cls: cls, left: 0 }];
|
|
538
|
+
|
|
539
|
+
let left = 0;
|
|
540
|
+
let width = this.width;
|
|
509
541
|
|
|
510
542
|
if (!this.browser.isStatic) {
|
|
511
543
|
if (start > 1) {
|
|
@@ -520,12 +552,10 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
520
552
|
}
|
|
521
553
|
}
|
|
522
554
|
|
|
523
|
-
|
|
555
|
+
const loading = this.imgContainer.clone().addClass('gv-loading').css({ left: left, width: width }).prependTo(this.scrollContainer.css('left', 0));
|
|
524
556
|
|
|
525
557
|
function makeImages() {
|
|
526
|
-
|
|
527
|
-
return controller.makeImage(image);
|
|
528
|
-
})).done(deferred.resolve);
|
|
558
|
+
jQuery.when(...images.map(image => controller.makeImage(image))).done(deferred.resolve);
|
|
529
559
|
|
|
530
560
|
loading.remove();
|
|
531
561
|
}
|
|
@@ -533,9 +563,9 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
533
563
|
if (length > this.threshold || this.model.checkDataRange(chr, start, end)) {
|
|
534
564
|
makeImages();
|
|
535
565
|
} else {
|
|
536
|
-
|
|
566
|
+
const buffer = this.prop('dataBuffer');
|
|
537
567
|
|
|
538
|
-
this.model.getData(chr, start - buffer.start - length, end + buffer.end + length).done(makeImages).fail(
|
|
568
|
+
this.model.getData(chr, start - buffer.start - length, end + buffer.end + length).done(makeImages).fail((e) => {
|
|
539
569
|
controller.showError(e);
|
|
540
570
|
});
|
|
541
571
|
}
|
|
@@ -544,22 +574,31 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
544
574
|
},
|
|
545
575
|
|
|
546
576
|
render: function (features, img) {
|
|
547
|
-
|
|
577
|
+
const params = img.data();
|
|
548
578
|
|
|
549
579
|
// positionFeatures alters params.featureHeight, so this must happen before the canvases are created
|
|
550
580
|
features = this.view.positionFeatures(this.view.scaleFeatures(features, params.scale), params);
|
|
551
581
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
582
|
+
const featureCanvas = this.browser.jQuery('<canvas>').attr({ width: params.width, height: params.featureHeight || 1 });
|
|
583
|
+
const labelCanvas = this.prop('labels') === 'separate' && params.labelHeight ? featureCanvas.clone().attr('height', params.labelHeight) : featureCanvas;
|
|
584
|
+
|
|
585
|
+
const featureContext = featureCanvas[0].getContext('2d');
|
|
586
|
+
const labelContext = labelCanvas[0].getContext('2d');
|
|
556
587
|
|
|
557
588
|
featureContext.font = labelContext.font = this.prop('font');
|
|
558
589
|
|
|
559
590
|
switch (this.prop('labels')) {
|
|
560
|
-
case false
|
|
561
|
-
case 'overlay'
|
|
562
|
-
|
|
591
|
+
case false: break;
|
|
592
|
+
case 'overlay':
|
|
593
|
+
labelContext.textAlign = 'center';
|
|
594
|
+
labelContext.textBaseline = 'middle';
|
|
595
|
+
|
|
596
|
+
break;
|
|
597
|
+
default:
|
|
598
|
+
labelContext.textAlign = 'left';
|
|
599
|
+
labelContext.textBaseline = 'top';
|
|
600
|
+
|
|
601
|
+
break;
|
|
563
602
|
}
|
|
564
603
|
|
|
565
604
|
this.view.draw(features, featureContext, labelContext, params.scale);
|
|
@@ -571,44 +610,46 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
571
610
|
}
|
|
572
611
|
|
|
573
612
|
this.checkHeight();
|
|
574
|
-
|
|
575
|
-
featureCanvas = labelCanvas = img = null;
|
|
576
613
|
},
|
|
577
614
|
|
|
578
615
|
renderBackground: function (features, img, height) {
|
|
579
|
-
|
|
616
|
+
const canvas = this.browser.jQuery('<canvas>').attr({ width: this.width, height: height || 1 })[0];
|
|
617
|
+
|
|
580
618
|
this.view.drawBackground(features, canvas.getContext('2d'), img.data());
|
|
581
619
|
img.attr('src', canvas.toDataURL());
|
|
582
|
-
canvas = img = null;
|
|
583
620
|
},
|
|
584
621
|
|
|
585
622
|
populateMenu: function (feature) {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
623
|
+
const title = feature.label ? feature.label[0] : feature.id;
|
|
624
|
+
|
|
625
|
+
return {
|
|
626
|
+
title : title,
|
|
627
|
+
Location : `${feature.chr}:${feature.start}-${feature.end}`,
|
|
628
|
+
...Object.entries(feature).reduce(
|
|
629
|
+
(acc, [ key, value ]) => {
|
|
630
|
+
if (typeof value === 'object' || value === title || [ 'chr', 'start', 'end', 'sort' ].includes(key)) {
|
|
631
|
+
return acc;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
return Object.assign(acc, { [key]: value });
|
|
635
|
+
},
|
|
636
|
+
{}
|
|
637
|
+
),
|
|
590
638
|
};
|
|
639
|
+
},
|
|
591
640
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
delete f.end;
|
|
595
|
-
delete f.sort;
|
|
596
|
-
|
|
597
|
-
for (var i in f) {
|
|
598
|
-
if (typeof f[i] === 'object' || menu.title === f[i]) {
|
|
599
|
-
delete f[i];
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
return $.extend(menu, f);
|
|
641
|
+
insertPropertiesIntoMenu: function (menuProperties, menuEl, contentEl, feature) {
|
|
642
|
+
return this.browser.insertPropertiesIntoMenu(menuProperties, menuEl, contentEl, feature, this.track);
|
|
604
643
|
},
|
|
605
644
|
|
|
606
645
|
abort: function () {
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
646
|
+
this.deferreds.forEach(
|
|
647
|
+
(deferred) => {
|
|
648
|
+
if (deferred.state() === 'pending') {
|
|
649
|
+
deferred.reject();
|
|
650
|
+
}
|
|
610
651
|
}
|
|
611
|
-
|
|
652
|
+
);
|
|
612
653
|
|
|
613
654
|
this.deferreds = [];
|
|
614
655
|
},
|
|
@@ -616,5 +657,5 @@ Genoverse.Track.Controller = Base.extend({
|
|
|
616
657
|
destroy: function () {
|
|
617
658
|
this.abort();
|
|
618
659
|
this.container.add(this.label).add(this.menus).remove();
|
|
619
|
-
}
|
|
660
|
+
},
|
|
620
661
|
});
|