genoverse 3.2.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.
- package/.eslintrc.js +197 -0
- package/.github/workflows/test.yml +24 -0
- package/LICENSE.TXT +24 -0
- package/README.md +11 -0
- package/css/controlPanel.css +200 -0
- package/css/fileDrop.css +22 -0
- package/css/font-awesome.css +3 -0
- package/css/fullscreen.css +19 -0
- package/css/genoverse.css +466 -0
- package/css/karyotype.css +85 -0
- package/css/resizer.css +36 -0
- package/css/tooltips.css +26 -0
- package/css/trackControls.css +111 -0
- package/expanded.html +120 -0
- package/fontawesome/css/fontawesome.min.css +5 -0
- package/fontawesome/css/regular.min.css +5 -0
- package/fontawesome/css/solid.min.css +5 -0
- 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/i/sort_handle.png +0 -0
- package/index.html +68 -0
- package/index.js +83 -0
- package/jest.config.js +4 -0
- package/js/Genoverse.js +1681 -0
- package/js/Track/Controller/Sequence.js +17 -0
- package/js/Track/Controller/Stranded.js +73 -0
- package/js/Track/Controller.js +620 -0
- package/js/Track/Model/File/BAM.js +44 -0
- package/js/Track/Model/File/BED.js +116 -0
- package/js/Track/Model/File/GFF.js +40 -0
- package/js/Track/Model/File/VCF.js +101 -0
- package/js/Track/Model/File/WIG.js +67 -0
- package/js/Track/Model/File.js +36 -0
- package/js/Track/Model/Gene/Ensembl.js +22 -0
- package/js/Track/Model/Gene.js +5 -0
- package/js/Track/Model/Sequence/Ensembl.js +4 -0
- package/js/Track/Model/Sequence/Fasta.js +60 -0
- package/js/Track/Model/Sequence.js +50 -0
- package/js/Track/Model/SequenceVariation.js +41 -0
- package/js/Track/Model/Stranded.js +28 -0
- package/js/Track/Model/Transcript/Ensembl.js +67 -0
- package/js/Track/Model/Transcript.js +5 -0
- package/js/Track/Model.js +303 -0
- package/js/Track/View/Gene/Ensembl.js +46 -0
- package/js/Track/View/Gene.js +6 -0
- package/js/Track/View/Sequence/Variation.js +115 -0
- package/js/Track/View/Sequence.js +63 -0
- package/js/Track/View/Transcript/Ensembl.js +12 -0
- package/js/Track/View/Transcript.js +28 -0
- package/js/Track/View.js +566 -0
- package/js/Track/library/Chromosome.js +145 -0
- package/js/Track/library/File/BAM.js +30 -0
- package/js/Track/library/File/BED.js +24 -0
- package/js/Track/library/File/BIGBED.js +47 -0
- package/js/Track/library/File/BIGWIG.js +52 -0
- package/js/Track/library/File/GFF.js +9 -0
- package/js/Track/library/File/VCF.js +71 -0
- package/js/Track/library/File/WIG.js +5 -0
- package/js/Track/library/File.js +10 -0
- package/js/Track/library/Gene.js +37 -0
- package/js/Track/library/Graph/Bar.js +235 -0
- package/js/Track/library/Graph/Line.js +296 -0
- package/js/Track/library/Graph.js +355 -0
- package/js/Track/library/HighlightRegion.js +292 -0
- package/js/Track/library/Legend.js +224 -0
- package/js/Track/library/Scalebar.js +227 -0
- package/js/Track/library/Scaleline.js +91 -0
- package/js/Track/library/Static.js +78 -0
- package/js/Track/library/dbSNP.js +142 -0
- package/js/Track.js +632 -0
- package/js/genomes/grch37.js +990 -0
- package/js/genomes/grch38.js +990 -0
- package/js/genoverse.min.js +2 -0
- package/js/genoverse.min.js.map +1 -0
- package/js/lib/BWReader.js +578 -0
- package/js/lib/Base.js +145 -0
- package/js/lib/VCFReader.js +286 -0
- package/js/lib/dalliance/js/bam.js +494 -0
- package/js/lib/dalliance/js/bin.js +185 -0
- package/js/lib/dalliance/js/das.js +749 -0
- package/js/lib/dalliance/js/utils.js +370 -0
- package/js/lib/dalliance-lib.js +3594 -0
- package/js/lib/dalliance-lib.min.js +68 -0
- package/js/lib/jDataView.js +2 -0
- package/js/lib/jParser.js +192 -0
- package/js/lib/jquery-ui.js +8 -0
- package/js/lib/jquery.js +2 -0
- package/js/lib/jquery.mousehold.js +53 -0
- package/js/lib/jquery.mousewheel.js +84 -0
- package/js/lib/jquery.tipsy.js +258 -0
- package/js/lib/rtree.js +1 -0
- package/js/plugins/controlPanel.js +395 -0
- package/js/plugins/fileDrop.js +62 -0
- package/js/plugins/focusRegion.js +12 -0
- package/js/plugins/fullscreen.js +77 -0
- package/js/plugins/karyotype.js +210 -0
- package/js/plugins/resizer.js +45 -0
- package/js/plugins/tooltips.js +94 -0
- package/js/plugins/trackControls.js +143 -0
- package/package.json +43 -0
- package/test/View/__snapshots__/render-bar-graph.test.js.snap +111 -0
- package/test/View/__snapshots__/render-blocks.test.js.snap +105 -0
- package/test/View/__snapshots__/render-chromosome.test.js.snap +5 -0
- package/test/View/__snapshots__/render-highlights.test.js.snap +73 -0
- package/test/View/__snapshots__/render-insert-variants.test.js.snap +9 -0
- package/test/View/__snapshots__/render-labels.test.js.snap +241 -0
- package/test/View/__snapshots__/render-legends.test.js.snap +13 -0
- package/test/View/__snapshots__/render-line-graph.test.js.snap +349 -0
- package/test/View/__snapshots__/render-scalebar.test.js.snap +49 -0
- package/test/View/__snapshots__/render-scaleline.test.js.snap +31 -0
- package/test/View/__snapshots__/render-sequence.test.js.snap +23 -0
- package/test/View/__snapshots__/render-stranded.test.js.snap +5 -0
- package/test/View/__snapshots__/render-transcripts.test.js.snap +193 -0
- package/test/View/render-bar-graph.test.js +87 -0
- package/test/View/render-blocks.test.js +171 -0
- package/test/View/render-chromosome.test.js +40 -0
- package/test/View/render-highlights.test.js +67 -0
- package/test/View/render-insert-variants.test.js +11 -0
- package/test/View/render-labels.test.js +266 -0
- package/test/View/render-legends.test.js +31 -0
- package/test/View/render-line-graph.test.js +169 -0
- package/test/View/render-scalebar.test.js +36 -0
- package/test/View/render-scaleline.test.js +28 -0
- package/test/View/render-sequence.test.js +49 -0
- package/test/View/render-stranded.test.js +10 -0
- package/test/View/render-transcripts.test.js +165 -0
- package/test/create-and-destroy.test.js +63 -0
- package/test/track-ordering.test.js +514 -0
- package/test/track_config/__snapshots__/config-settings.test.js.snap +23 -0
- package/test/track_config/config-settings.test.js +321 -0
- package/test/track_config/zoom-level-settings.test.js +98 -0
- package/test/utils.js +80 -0
- package/utils/createGenome.js +52 -0
- package/utils/devServer.js +36 -0
- package/utils/expandedTemplate.html +46 -0
- package/utils/git-hooks/post-commit +9 -0
- package/utils/git-hooks/pre-commit +7 -0
- package/utils/git-hooks/setup +6 -0
- package/utils/makeExpanded.js +19 -0
- package/webpack.config.js +39 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
Genoverse.Plugins.karyotype = function (pluginConf) {
|
|
2
|
+
function createKaryotype() {
|
|
3
|
+
var chromosome = $('<div class="gv-chromosome">');
|
|
4
|
+
var container = $('<div class="gv-karyotype-container">').html(chromosome).insertBefore(this.wrapper);
|
|
5
|
+
var assemblyName = this.assembly || this.genomeName;
|
|
6
|
+
var name = (pluginConf.showAssembly && assemblyName ? assemblyName + ': ' : '') + 'Chr ' + this.chr;
|
|
7
|
+
|
|
8
|
+
if (pluginConf.showAssembly && assemblyName) {
|
|
9
|
+
container.addClass('gv-show-assembly');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
var measureWidth = $('<div class="gv-chromosome"><ul class="gv-label-container"><li><span class="gv-name">' + name + '</span></li></ul></div>').appendTo(container);
|
|
13
|
+
var labelWidth = pluginConf.karyotypeLabel === false ? 0 : measureWidth.find('.gv-name').outerWidth(true) + 10;
|
|
14
|
+
|
|
15
|
+
measureWidth.remove();
|
|
16
|
+
|
|
17
|
+
this.karyotype = new Genoverse({
|
|
18
|
+
parent : this,
|
|
19
|
+
container : chromosome,
|
|
20
|
+
width : chromosome.width(),
|
|
21
|
+
genome : this.genome,
|
|
22
|
+
chr : this.chr,
|
|
23
|
+
start : 1,
|
|
24
|
+
end : this.chromosomeSize,
|
|
25
|
+
isStatic : true,
|
|
26
|
+
tracks : [
|
|
27
|
+
Genoverse.Track.Chromosome.extend({
|
|
28
|
+
name : name,
|
|
29
|
+
height : 20,
|
|
30
|
+
featureHeight : 20,
|
|
31
|
+
border : false,
|
|
32
|
+
legend : false,
|
|
33
|
+
unsortable : true,
|
|
34
|
+
|
|
35
|
+
click: function (e) {
|
|
36
|
+
var offset = this.container.parent().offset().left;
|
|
37
|
+
var x = e.pageX - offset;
|
|
38
|
+
var f = this.featurePositions.search({ x: x, y: 1, w: 1, h: 1 })[0];
|
|
39
|
+
|
|
40
|
+
if (f) {
|
|
41
|
+
if (e.type === 'mouseup') {
|
|
42
|
+
if (!this.browser.parent.isStatic) {
|
|
43
|
+
this.browser.parent.moveTo(f.chr, f.start, f.end, true);
|
|
44
|
+
}
|
|
45
|
+
} else if (this.hoverFeature !== f && !this.browser.hideTooltip) {
|
|
46
|
+
this.container.tipsy('hide');
|
|
47
|
+
|
|
48
|
+
if (f.label) {
|
|
49
|
+
var left = offset + f.position[this.scale].start + f.position[this.scale].width / 2;
|
|
50
|
+
this.container.attr('title', f.label[0]).tipsy({ trigger: 'manual', container: 'body' }).tipsy('show').data('tipsy').$tip.css('left', function () { return left - $(this).width() / 2; });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
this.hoverFeature = f;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
addUserEventHandlers: function () {
|
|
59
|
+
var track = this;
|
|
60
|
+
|
|
61
|
+
this.base();
|
|
62
|
+
|
|
63
|
+
this.container.on({
|
|
64
|
+
mousemove : function (e) { track.click(e); },
|
|
65
|
+
mouseout : function (e) {
|
|
66
|
+
if (track.browser.viewPoint.is(e.relatedTarget) || track.browser.viewPoint.find(e.relatedTarget).length) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
track.container.tipsy('hide');
|
|
71
|
+
track.hoverFeature = false;
|
|
72
|
+
}
|
|
73
|
+
}, '.gv-image-container');
|
|
74
|
+
|
|
75
|
+
// Don't allow zooming in and out on the karyotype image
|
|
76
|
+
this.container.on('mousewheel', '.gv-image-container, .gv-selector', function (e) {
|
|
77
|
+
e.stopPropagation();
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
afterSetName: function () {
|
|
82
|
+
this.label.css('lineHeight', this.label.height() + 'px');
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
],
|
|
86
|
+
|
|
87
|
+
addUserEventHandlers: $.noop,
|
|
88
|
+
|
|
89
|
+
afterInit: function () {
|
|
90
|
+
this.updatePosition();
|
|
91
|
+
this.viewPoint.fadeIn();
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
afterAddTracks: function () {
|
|
95
|
+
this.track = this.tracks[0];
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
afterAddDomElements: function () {
|
|
99
|
+
var karyotype = this;
|
|
100
|
+
var parent = this.parent;
|
|
101
|
+
|
|
102
|
+
function hideTooltip() {
|
|
103
|
+
karyotype.hideTooltip = true;
|
|
104
|
+
karyotype.track.prop('container').tipsy('hide');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function updateLocation(e, ui) {
|
|
108
|
+
karyotype.hideTooltip = false;
|
|
109
|
+
|
|
110
|
+
var scale = karyotype.chromosomeSize / karyotype.width;
|
|
111
|
+
var axis = e.type === 'resizestop' ? $(this).data('ui-resizable').axis : undefined;
|
|
112
|
+
var start = axis === 'e' ? parent.start : Math.max(Math.floor(ui.position.left * scale), 1);
|
|
113
|
+
var end = axis === 'w' ? parent.end : e.type === 'dragstop' ? start + parent.length - 1 : Math.floor(ui.helper.outerWidth(true) * scale) + start;
|
|
114
|
+
|
|
115
|
+
if (start !== parent.start || end !== parent.end) {
|
|
116
|
+
parent.moveTo(karyotype.chr, start, end, true, e.type === 'dragstop');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (pluginConf.karyotypeLabel === false) {
|
|
121
|
+
this.labelContainer.remove();
|
|
122
|
+
this.labelContainer = $();
|
|
123
|
+
container.addClass('gv-no-label');
|
|
124
|
+
} else {
|
|
125
|
+
this.labelContainer.width(labelWidth);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
this.viewPoint = $('<div class="gv-karyotype-viewpoint-wrapper"><div class="gv-karyotype-viewpoint"></div></div>').appendTo(container).css({
|
|
129
|
+
left : labelWidth,
|
|
130
|
+
width : this.width - labelWidth
|
|
131
|
+
}).children().on({
|
|
132
|
+
mousemove : function (e) { karyotype.track.controller.click(e); },
|
|
133
|
+
mouseout : function (e) {
|
|
134
|
+
var el = $(e.relatedTarget);
|
|
135
|
+
|
|
136
|
+
if (karyotype.viewPoint.is(el) || karyotype.viewPoint.find(el).length || (el.prop('nodeName') === 'IMG' && el.parent().is(karyotype.track.prop('imgContainers')[0]))) {
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
karyotype.track.prop('container').tipsy('hide');
|
|
141
|
+
karyotype.track.prop('hoverFeature', false);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
if (!parent.isStatic) {
|
|
146
|
+
this.viewPoint.draggable({
|
|
147
|
+
axis : 'x',
|
|
148
|
+
containment : this.wrapper,
|
|
149
|
+
start : hideTooltip,
|
|
150
|
+
stop : updateLocation
|
|
151
|
+
}).resizable({
|
|
152
|
+
handles : 'e, w',
|
|
153
|
+
containment : 'parent',
|
|
154
|
+
start : hideTooltip,
|
|
155
|
+
stop : updateLocation,
|
|
156
|
+
resize : function (e, ui) {
|
|
157
|
+
ui.element.css('left', Math.max(0, ui.position.left));
|
|
158
|
+
|
|
159
|
+
if (ui.position.left > 0) {
|
|
160
|
+
ui.element.width(Math.min(ui.size.width, ui.element.parent().width() - ui.position.left));
|
|
161
|
+
} else {
|
|
162
|
+
ui.element.width(ui.size.width + ui.position.left);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
updatePosition: function () {
|
|
170
|
+
var left = this.parent.start * this.scale;
|
|
171
|
+
var width = (this.parent.end * this.scale) - left;
|
|
172
|
+
|
|
173
|
+
this.viewPoint.css({ left: left, width: width });
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (this.loadedPlugins.controlPanel !== true) {
|
|
178
|
+
$('<li class="gv-unsortable">').height(function (i, h) {
|
|
179
|
+
return h + container.height();
|
|
180
|
+
}).prependTo(this.labelContainer);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function recreateKaryotype() {
|
|
185
|
+
var container = this.karyotype.container.parent();
|
|
186
|
+
|
|
187
|
+
this.karyotype.destroy();
|
|
188
|
+
container.remove();
|
|
189
|
+
|
|
190
|
+
createKaryotype.call(this);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
this.on({
|
|
194
|
+
afterInit: createKaryotype,
|
|
195
|
+
|
|
196
|
+
afterSetRange: function () {
|
|
197
|
+
if (this.karyotype) {
|
|
198
|
+
this.karyotype.updatePosition();
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
afterSetWidth: recreateKaryotype,
|
|
203
|
+
|
|
204
|
+
afterMoveTo: function (chr) {
|
|
205
|
+
if (this.karyotype && this.karyotype.chr !== chr) {
|
|
206
|
+
recreateKaryotype.call(this);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Genoverse.Plugins.resizer = function () {
|
|
2
|
+
this.on('afterSetMVC', 'tracks', function () {
|
|
3
|
+
if (this.prop('resizable') !== true) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
var track = this;
|
|
8
|
+
var controller = this.controller;
|
|
9
|
+
var resizer = this.prop('resizer');
|
|
10
|
+
var height = this.prop('height');
|
|
11
|
+
|
|
12
|
+
if (!resizer) {
|
|
13
|
+
resizer = this.prop('resizer', $('<div class="gv-resizer gv-static"><div class="gv-handle"></div></div>').appendTo(track.prop('container')).draggable({
|
|
14
|
+
axis : 'y',
|
|
15
|
+
start : function () { $('body').addClass('gv-dragging'); },
|
|
16
|
+
stop : function (e, ui) {
|
|
17
|
+
$('body').removeClass('gv-dragging');
|
|
18
|
+
controller.resize(track.prop('height') + ui.position.top - ui.originalPosition.top, true);
|
|
19
|
+
$(this).css({ top: 'auto', bottom: 0 }); // returns the resizer to the bottom of the container - needed when the track is resized to 0
|
|
20
|
+
}
|
|
21
|
+
}).on('click', function () {
|
|
22
|
+
var h = track.prop('fullVisibleHeight');
|
|
23
|
+
|
|
24
|
+
if (h) {
|
|
25
|
+
controller.resize(h, true);
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
resizer.css({ width: this.width, left: 0 })[this.prop('autoHeight') ? 'hide' : 'show']();
|
|
31
|
+
|
|
32
|
+
if (!this.prop('autoHeight') && height - this.prop('margin') === this.prop('featureHeight')) {
|
|
33
|
+
controller.resize(height + resizer.height());
|
|
34
|
+
this.prop('initialHeight', this.prop('height'));
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
this.on('afterToggleExpander', 'tracks', function () {
|
|
39
|
+
var resizer = this.prop('resizer');
|
|
40
|
+
|
|
41
|
+
if (resizer) {
|
|
42
|
+
resizer[this.expander && this.expander.is(':visible') ? 'addClass' : 'removeClass']('gv-resizer-expander');
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// tipsy, facebook style tooltips for jquery
|
|
2
|
+
// version 1.0.0a
|
|
3
|
+
// (c) 2008-2010 jason frame [jason@onehackoranother.com]
|
|
4
|
+
// released under the MIT license
|
|
5
|
+
|
|
6
|
+
Genoverse.Plugins.tooltips = function () {
|
|
7
|
+
var genoverse = this;
|
|
8
|
+
|
|
9
|
+
function toggleTooltips(browser, tooltips, action) {
|
|
10
|
+
var offset = browser.superContainer.offset();
|
|
11
|
+
|
|
12
|
+
tooltips = tooltips || browser.superContainer.find('.gv-tooltip');
|
|
13
|
+
action = action || $(this).toggleClass('gv-active').hasClass('gv-active') ? 'show' : 'hide';
|
|
14
|
+
|
|
15
|
+
tooltips.each(function () {
|
|
16
|
+
var el = $(this);
|
|
17
|
+
|
|
18
|
+
if (el.is(':visible')) {
|
|
19
|
+
el.tipsy(action).data('tipsy').$tip.data({ parent: el }).appendTo(browser.superContainer).css({
|
|
20
|
+
marginTop : -offset.top,
|
|
21
|
+
marginLeft : -offset.left
|
|
22
|
+
});
|
|
23
|
+
} else if (el.data('tipsy').$tip) {
|
|
24
|
+
el.tipsy('hide');
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function updateTooltips() {
|
|
30
|
+
var tooltips = $();
|
|
31
|
+
|
|
32
|
+
$.each([
|
|
33
|
+
[ genoverse.labelContainer.find('.gv-handle'), { gravity: 'w', fade: true, trigger: 'manual', fallback: 'Reorder tracks by dragging this handle' }],
|
|
34
|
+
[ genoverse.container.find('.gv-resizer'), { gravity: 'n', fade: true, trigger: 'manual', fallback: 'Resize track by dragging this handle' }]
|
|
35
|
+
], function () {
|
|
36
|
+
var el = this[0].filter(':visible').first();
|
|
37
|
+
|
|
38
|
+
if (!el.hasClass('gv-tooltip')) {
|
|
39
|
+
this[0].filter('.gv-tooltip').removeClass('gv-tooltip').tipsy('hide').removeData('tipsy');
|
|
40
|
+
el.tipsy(this[1]).addClass('gv-tooltip');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
tooltips = tooltips.add(el);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Remove any tooltips orphaned by the removal of a track
|
|
47
|
+
genoverse.superContainer.find('.tipsy').not(function () {
|
|
48
|
+
var parent = $(this).data('parent');
|
|
49
|
+
return parent && genoverse.superContainer.find(parent).length;
|
|
50
|
+
}).remove();
|
|
51
|
+
|
|
52
|
+
if (genoverse.controlPanel.find('.gv-tooltips').hasClass('gv-active')) {
|
|
53
|
+
toggleTooltips(genoverse, tooltips, 'show');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return tooltips;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
this.controls.push({
|
|
60
|
+
icon : '<i class="fas fa-question-circle"></i>',
|
|
61
|
+
class : 'gv-tooltips',
|
|
62
|
+
name : 'Tooltips',
|
|
63
|
+
action : toggleTooltips
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
this.on('afterInit', function () {
|
|
67
|
+
this.superContainer.find('.gv-panel-left .gv-button-set[title]').tipsy({ gravity: 'w', fade: true, trigger: 'manual' }).addClass('gv-tooltip');
|
|
68
|
+
this.superContainer.find('.gv-panel-right .gv-button-set[title]').tipsy({ gravity: 'e', fade: true, trigger: 'manual' }).addClass('gv-tooltip');
|
|
69
|
+
|
|
70
|
+
// In order to force placement of this tooltip to be inside the superContainer boundaries, and just below the karyotype, create a hidden element, positioned where we want the tooltip to appear
|
|
71
|
+
$('<i class="gv-wrapper-tooltip">').prependTo(this.wrapper).tipsy({
|
|
72
|
+
gravity : 's',
|
|
73
|
+
fade : true,
|
|
74
|
+
trigger : 'manual',
|
|
75
|
+
fallback : 'Scroll left and right by dragging with your mouse, click on any feature in any track for more info'
|
|
76
|
+
}).addClass('gv-tooltip');
|
|
77
|
+
|
|
78
|
+
updateTooltips();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
this.on('beforeSetWidth', function () {
|
|
82
|
+
this.controlPanel.find('.gv-tooltips.gv-active').trigger('click');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
this.on('afterSortTracks', function () {
|
|
86
|
+
updateTooltips();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
this.on('afterResize', 'tracks', function () {
|
|
90
|
+
updateTooltips();
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
Genoverse.Plugins.tooltips.requires = 'controlPanel';
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
Genoverse.Plugins.trackControls = function () {
|
|
2
|
+
var defaultControls = [
|
|
3
|
+
$('<a title="More info" class="fas fa-question-circle">').on('click', function () {
|
|
4
|
+
var track = $(this).data('track');
|
|
5
|
+
var menu = track.prop('menus').filter('.gv-track-info');
|
|
6
|
+
|
|
7
|
+
if (!menu.length) {
|
|
8
|
+
var info = track.prop('info');
|
|
9
|
+
|
|
10
|
+
menu = { title: track.name };
|
|
11
|
+
menu[typeof info === 'function' ? info.call(track) : info || ''] = '';
|
|
12
|
+
|
|
13
|
+
menu = track.prop('menus', track.prop('menus').add(track.browser.makeMenu(menu).addClass('gv-track-info')));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
menu.show().position({ of: track.prop('container'), at: 'center top', my: 'center top', collision: 'none' });
|
|
17
|
+
}),
|
|
18
|
+
|
|
19
|
+
$(
|
|
20
|
+
'<a class="gv-height-toggle">' +
|
|
21
|
+
'<i class="fas fa-sort"></i>' +
|
|
22
|
+
'<i class="fas fa-sort-down"></i>' +
|
|
23
|
+
'<i class="fas fa-sort-up"></i>' +
|
|
24
|
+
'</a>'
|
|
25
|
+
).on({
|
|
26
|
+
click: function () {
|
|
27
|
+
var track = $(this).data('track');
|
|
28
|
+
var height;
|
|
29
|
+
|
|
30
|
+
if (track.prop('autoHeight', !track.prop('autoHeight'))) {
|
|
31
|
+
track.prop('heightBeforeToggle', track.prop('height'));
|
|
32
|
+
height = track.prop('fullVisibleHeight');
|
|
33
|
+
} else {
|
|
34
|
+
height = track.prop('heightBeforeToggle') || track.prop('initialHeight');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
$(this).trigger('toggleState');
|
|
38
|
+
|
|
39
|
+
track.controller.resize(height, true);
|
|
40
|
+
},
|
|
41
|
+
toggleState: function () { // custom event to set title and change the icon
|
|
42
|
+
var track = $(this).data('track');
|
|
43
|
+
var autoHeight = track.prop('autoHeight');
|
|
44
|
+
var resizer = track.prop('resizer');
|
|
45
|
+
|
|
46
|
+
this.title = autoHeight ? 'Set track to fixed height' : 'Set track to auto-adjust height';
|
|
47
|
+
$(this)[autoHeight ? 'addClass' : 'removeClass']('gv-auto-height');
|
|
48
|
+
|
|
49
|
+
if (resizer) {
|
|
50
|
+
resizer[autoHeight ? 'hide' : 'show']();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
var remove = $('<a title="Remove track" class="far fa-trash-alt">').on('click', function () {
|
|
57
|
+
$(this).data('track').remove();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
var toggle = $(
|
|
61
|
+
'<a class="gv-track-controls-toggle">' +
|
|
62
|
+
'<span><i class="fas fa-angle-double-left"></i><i class="fas fa-cog"></i></span>' +
|
|
63
|
+
'<span><i class="fas fa-angle-double-right"></i></span>' +
|
|
64
|
+
'</a>'
|
|
65
|
+
).on('click', function () {
|
|
66
|
+
$(this).parent().toggleClass('gv-maximized');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
this.on({
|
|
70
|
+
afterAddDomElements: function () {
|
|
71
|
+
var controls = this.prop('controls');
|
|
72
|
+
|
|
73
|
+
if (controls === 'off') {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
var defaultConfig = this.prop('defaultConfig');
|
|
78
|
+
var savedConfig = this.browser.savedConfig ? this.browser.savedConfig[this.prop('id')] || {} : {};
|
|
79
|
+
var prop, el, j;
|
|
80
|
+
|
|
81
|
+
controls = (controls || []).concat(defaultControls, this.prop('removable') === false ? [] : remove);
|
|
82
|
+
|
|
83
|
+
this.trackControls = $('<div class="gv-track-controls">').prependTo(this.container);
|
|
84
|
+
|
|
85
|
+
var controlsContainer = $('<div class="gv-track-controls-container">').appendTo(this.trackControls);
|
|
86
|
+
|
|
87
|
+
for (var i = 0; i < controls.length; i++) {
|
|
88
|
+
if ($.isPlainObject(controls[i]) && controls[i].type) {
|
|
89
|
+
el = $('<' + controls[i].type + '>').data('control', controls[i].name);
|
|
90
|
+
|
|
91
|
+
if (controls[i].options) {
|
|
92
|
+
for (j = 0; j < controls[i].options.length; j++) {
|
|
93
|
+
el.append('<option value="' + controls[i].options[j].value + '">' + controls[i].options[j].text + '</option>');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
} else if (typeof controls[i] === 'string') {
|
|
97
|
+
el = $(controls[i]);
|
|
98
|
+
} else if (typeof controls[i] === 'object' && controls[i].constructor && controls[i] instanceof $) {
|
|
99
|
+
el = controls[i].clone(true);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
el.data('track', this.track).appendTo(controlsContainer);
|
|
103
|
+
|
|
104
|
+
// TODO: other control types
|
|
105
|
+
if (el.is('select')) {
|
|
106
|
+
prop = el.data('control');
|
|
107
|
+
|
|
108
|
+
el.find('option[value=' + (savedConfig[prop] || defaultConfig[prop] || 'all') + ']').attr('selected', true).end().change(function () {
|
|
109
|
+
$(this).data('track').setConfig($(this).data('control'), this.value);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
this.prop('heightToggler', controlsContainer.children('.gv-height-toggle').trigger('toggleState'));
|
|
115
|
+
|
|
116
|
+
var toggler = toggle.clone(true).data('track', this.track).appendTo(this.trackControls);
|
|
117
|
+
|
|
118
|
+
toggler.trigger('click');
|
|
119
|
+
this.minLabelHeight = Math.max(this.minLabelHeight, this.trackControls.outerHeight(true) + this.prop('margin'));
|
|
120
|
+
toggler.trigger('click');
|
|
121
|
+
},
|
|
122
|
+
afterResize: function () {
|
|
123
|
+
if (this.trackControls) {
|
|
124
|
+
this.trackControls[this.prop('height') < this.trackControls.outerHeight(true) ? 'hide' : 'show']();
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
afterResetHeight: function () {
|
|
128
|
+
var heightToggler = this.prop('heightToggler');
|
|
129
|
+
|
|
130
|
+
if (this.prop('resizable') === true && heightToggler) {
|
|
131
|
+
heightToggler[this.prop('autoHeight') ? 'addClass' : 'removeClass']('gv-auto-height');
|
|
132
|
+
heightToggler.trigger('toggleState');
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
afterSetMVC: function () {
|
|
136
|
+
var heightToggler = this.prop('heightToggler');
|
|
137
|
+
|
|
138
|
+
if (heightToggler) {
|
|
139
|
+
heightToggler.trigger('toggleState')[this.prop('resizable') === true ? 'removeClass' : 'addClass']('gv-hide');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}, 'tracks');
|
|
143
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "genoverse",
|
|
3
|
+
"version": "3.2.0",
|
|
4
|
+
"description": "Genoverse is a portable, customizable, back-end independent JavaScript and HTML5 based genome browser which allows the user to explore data in a dynamic and interactive manner.",
|
|
5
|
+
"main": "js/Genoverse.js",
|
|
6
|
+
"directories": {
|
|
7
|
+
"lib": "js",
|
|
8
|
+
"test": "test"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "jest",
|
|
12
|
+
"build": "yarn lint && node utils/makeExpanded.js && webpack",
|
|
13
|
+
"lint": "eslint '**/*.js'",
|
|
14
|
+
"server": "node utils/devServer.js"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/wtsi-web/Genoverse.git"
|
|
19
|
+
},
|
|
20
|
+
"author": "Simon Brent",
|
|
21
|
+
"license": "BSD-3-Clause",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/wtsi-web/Genoverse/issues"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://wtsi-web.github.io/Genoverse/",
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@babel/core": "^7.16.7",
|
|
28
|
+
"@babel/eslint-parser": "^7.16.5",
|
|
29
|
+
"@babel/runtime-corejs3": "^7.16.7",
|
|
30
|
+
"canvas": "^2.8.0",
|
|
31
|
+
"core-js": "^3.20.2",
|
|
32
|
+
"eslint": "^8.6.0",
|
|
33
|
+
"eslint-config-airbnb-base": "^15.0.0",
|
|
34
|
+
"eslint-plugin-align-assignments": "^1.1.2",
|
|
35
|
+
"eslint-plugin-es": "^4.1.0",
|
|
36
|
+
"eslint-plugin-import": "^2.25.4",
|
|
37
|
+
"jest": "^27.4.7",
|
|
38
|
+
"terser-webpack-plugin": "^5.3.0",
|
|
39
|
+
"webpack": "^5.65.0",
|
|
40
|
+
"webpack-cli": "^4.9.1"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {}
|
|
43
|
+
}
|