genoverse 3.2.0 → 4.0.1
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 +174 -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 +125 -93
- 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 +651 -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/change-width.test.js +71 -0
- 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,16 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
import '../../css/karyotype.css';
|
|
2
|
+
import Chromosome from '../Track/library/Chromosome';
|
|
3
|
+
|
|
4
|
+
const plugin = function (pluginConf) {
|
|
5
|
+
const jQuery = this.jQuery;
|
|
6
|
+
|
|
2
7
|
function createKaryotype() {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
const chromosome = jQuery('<div class="gv-chromosome">');
|
|
9
|
+
const container = jQuery('<div class="gv-karyotype-container">').html(chromosome).insertBefore(this.wrapper);
|
|
10
|
+
const assemblyName = this.assembly || this.genomeName;
|
|
11
|
+
const name = `${pluginConf.showAssembly && assemblyName ? `${assemblyName}: ` : ''}Chr ${this.chr}`;
|
|
7
12
|
|
|
8
13
|
if (pluginConf.showAssembly && assemblyName) {
|
|
9
14
|
container.addClass('gv-show-assembly');
|
|
10
15
|
}
|
|
11
16
|
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
const measureWidth = jQuery(`<div class="gv-chromosome"><ul class="gv-label-container"><li><span class="gv-name">${name}</span></li></ul></div>`).appendTo(container);
|
|
18
|
+
const labelWidth = pluginConf.karyotypeLabel === false ? 0 : measureWidth.find('.gv-name').outerWidth(true) + 10;
|
|
14
19
|
|
|
15
20
|
measureWidth.remove();
|
|
16
21
|
|
|
@@ -24,7 +29,7 @@ Genoverse.Plugins.karyotype = function (pluginConf) {
|
|
|
24
29
|
end : this.chromosomeSize,
|
|
25
30
|
isStatic : true,
|
|
26
31
|
tracks : [
|
|
27
|
-
|
|
32
|
+
Chromosome.extend({
|
|
28
33
|
name : name,
|
|
29
34
|
height : 20,
|
|
30
35
|
featureHeight : 20,
|
|
@@ -33,9 +38,9 @@ Genoverse.Plugins.karyotype = function (pluginConf) {
|
|
|
33
38
|
unsortable : true,
|
|
34
39
|
|
|
35
40
|
click: function (e) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
const offset = this.container.parent().offset().left;
|
|
42
|
+
const x = e.pageX - offset;
|
|
43
|
+
const f = this.featurePositions.search({ x: x, y: 1, w: 1, h: 1 })[0];
|
|
39
44
|
|
|
40
45
|
if (f) {
|
|
41
46
|
if (e.type === 'mouseup') {
|
|
@@ -46,8 +51,9 @@ Genoverse.Plugins.karyotype = function (pluginConf) {
|
|
|
46
51
|
this.container.tipsy('hide');
|
|
47
52
|
|
|
48
53
|
if (f.label) {
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
const left = offset + f.position[this.scale].start + f.position[this.scale].width / 2;
|
|
55
|
+
|
|
56
|
+
this.container.attr('title', f.label[0]).tipsy({ trigger: 'manual', container: 'body' }).tipsy('show').data('tipsy').$tip.css('left', function () { return left - jQuery(this).width() / 2; });
|
|
51
57
|
}
|
|
52
58
|
|
|
53
59
|
this.hoverFeature = f;
|
|
@@ -56,35 +62,35 @@ Genoverse.Plugins.karyotype = function (pluginConf) {
|
|
|
56
62
|
},
|
|
57
63
|
|
|
58
64
|
addUserEventHandlers: function () {
|
|
59
|
-
|
|
65
|
+
const track = this;
|
|
60
66
|
|
|
61
67
|
this.base();
|
|
62
68
|
|
|
63
69
|
this.container.on({
|
|
64
|
-
mousemove :
|
|
65
|
-
mouseout :
|
|
70
|
+
mousemove : (e) => { track.click(e); },
|
|
71
|
+
mouseout : (e) => {
|
|
66
72
|
if (track.browser.viewPoint.is(e.relatedTarget) || track.browser.viewPoint.find(e.relatedTarget).length) {
|
|
67
73
|
return true;
|
|
68
74
|
}
|
|
69
75
|
|
|
70
76
|
track.container.tipsy('hide');
|
|
71
77
|
track.hoverFeature = false;
|
|
72
|
-
}
|
|
78
|
+
},
|
|
73
79
|
}, '.gv-image-container');
|
|
74
80
|
|
|
75
81
|
// Don't allow zooming in and out on the karyotype image
|
|
76
|
-
this.container.on('mousewheel', '.gv-image-container, .gv-selector',
|
|
82
|
+
this.container.on('mousewheel', '.gv-image-container, .gv-selector', (e) => {
|
|
77
83
|
e.stopPropagation();
|
|
78
84
|
});
|
|
79
85
|
},
|
|
80
86
|
|
|
81
87
|
afterSetName: function () {
|
|
82
|
-
this.label.css('lineHeight', this.label.height()
|
|
83
|
-
}
|
|
84
|
-
})
|
|
88
|
+
this.label.css('lineHeight', `${this.label.height()}px`);
|
|
89
|
+
},
|
|
90
|
+
}),
|
|
85
91
|
],
|
|
86
92
|
|
|
87
|
-
addUserEventHandlers:
|
|
93
|
+
addUserEventHandlers: () => {},
|
|
88
94
|
|
|
89
95
|
afterInit: function () {
|
|
90
96
|
this.updatePosition();
|
|
@@ -96,8 +102,8 @@ Genoverse.Plugins.karyotype = function (pluginConf) {
|
|
|
96
102
|
},
|
|
97
103
|
|
|
98
104
|
afterAddDomElements: function () {
|
|
99
|
-
|
|
100
|
-
|
|
105
|
+
const karyotype = this;
|
|
106
|
+
const parent = this.parent;
|
|
101
107
|
|
|
102
108
|
function hideTooltip() {
|
|
103
109
|
karyotype.hideTooltip = true;
|
|
@@ -107,10 +113,10 @@ Genoverse.Plugins.karyotype = function (pluginConf) {
|
|
|
107
113
|
function updateLocation(e, ui) {
|
|
108
114
|
karyotype.hideTooltip = false;
|
|
109
115
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
const scale = karyotype.chromosomeSize / karyotype.width;
|
|
117
|
+
const axis = e.type === 'resizestop' ? jQuery(this).data('ui-resizable').axis : undefined;
|
|
118
|
+
const start = axis === 'e' ? parent.start : Math.max(Math.floor(ui.position.left * scale), 1);
|
|
119
|
+
const end = axis === 'w' ? parent.end : e.type === 'dragstop' ? start + parent.length - 1 : Math.floor(ui.helper.outerWidth(true) * scale) + start;
|
|
114
120
|
|
|
115
121
|
if (start !== parent.start || end !== parent.end) {
|
|
116
122
|
parent.moveTo(karyotype.chr, start, end, true, e.type === 'dragstop');
|
|
@@ -119,19 +125,19 @@ Genoverse.Plugins.karyotype = function (pluginConf) {
|
|
|
119
125
|
|
|
120
126
|
if (pluginConf.karyotypeLabel === false) {
|
|
121
127
|
this.labelContainer.remove();
|
|
122
|
-
this.labelContainer =
|
|
128
|
+
this.labelContainer = jQuery();
|
|
123
129
|
container.addClass('gv-no-label');
|
|
124
130
|
} else {
|
|
125
131
|
this.labelContainer.width(labelWidth);
|
|
126
132
|
}
|
|
127
133
|
|
|
128
|
-
this.viewPoint =
|
|
134
|
+
this.viewPoint = jQuery('<div class="gv-karyotype-viewpoint-wrapper"><div class="gv-karyotype-viewpoint"></div></div>').appendTo(container).css({
|
|
129
135
|
left : labelWidth,
|
|
130
|
-
width : this.width - labelWidth
|
|
136
|
+
width : this.width - labelWidth,
|
|
131
137
|
}).children().on({
|
|
132
|
-
mousemove :
|
|
133
|
-
mouseout :
|
|
134
|
-
|
|
138
|
+
mousemove : (e) => { karyotype.track.controller.click(e); },
|
|
139
|
+
mouseout : (e) => {
|
|
140
|
+
const el = jQuery(e.relatedTarget);
|
|
135
141
|
|
|
136
142
|
if (karyotype.viewPoint.is(el) || karyotype.viewPoint.find(el).length || (el.prop('nodeName') === 'IMG' && el.parent().is(karyotype.track.prop('imgContainers')[0]))) {
|
|
137
143
|
return true;
|
|
@@ -139,7 +145,7 @@ Genoverse.Plugins.karyotype = function (pluginConf) {
|
|
|
139
145
|
|
|
140
146
|
karyotype.track.prop('container').tipsy('hide');
|
|
141
147
|
karyotype.track.prop('hoverFeature', false);
|
|
142
|
-
}
|
|
148
|
+
},
|
|
143
149
|
});
|
|
144
150
|
|
|
145
151
|
if (!parent.isStatic) {
|
|
@@ -147,7 +153,7 @@ Genoverse.Plugins.karyotype = function (pluginConf) {
|
|
|
147
153
|
axis : 'x',
|
|
148
154
|
containment : this.wrapper,
|
|
149
155
|
start : hideTooltip,
|
|
150
|
-
stop : updateLocation
|
|
156
|
+
stop : updateLocation,
|
|
151
157
|
}).resizable({
|
|
152
158
|
handles : 'e, w',
|
|
153
159
|
containment : 'parent',
|
|
@@ -161,28 +167,26 @@ Genoverse.Plugins.karyotype = function (pluginConf) {
|
|
|
161
167
|
} else {
|
|
162
168
|
ui.element.width(ui.size.width + ui.position.left);
|
|
163
169
|
}
|
|
164
|
-
}
|
|
170
|
+
},
|
|
165
171
|
});
|
|
166
172
|
}
|
|
167
173
|
},
|
|
168
174
|
|
|
169
175
|
updatePosition: function () {
|
|
170
|
-
|
|
171
|
-
|
|
176
|
+
const left = this.parent.start * this.scale;
|
|
177
|
+
const width = (this.parent.end * this.scale) - left;
|
|
172
178
|
|
|
173
179
|
this.viewPoint.css({ left: left, width: width });
|
|
174
|
-
}
|
|
180
|
+
},
|
|
175
181
|
});
|
|
176
182
|
|
|
177
183
|
if (this.loadedPlugins.controlPanel !== true) {
|
|
178
|
-
|
|
179
|
-
return h + container.height();
|
|
180
|
-
}).prependTo(this.labelContainer);
|
|
184
|
+
jQuery('<li class="gv-unsortable">').height((i, h) => h + container.height()).prependTo(this.labelContainer);
|
|
181
185
|
}
|
|
182
186
|
}
|
|
183
187
|
|
|
184
188
|
function recreateKaryotype() {
|
|
185
|
-
|
|
189
|
+
const container = this.karyotype.container.parent();
|
|
186
190
|
|
|
187
191
|
this.karyotype.destroy();
|
|
188
192
|
container.remove();
|
|
@@ -205,6 +209,8 @@ Genoverse.Plugins.karyotype = function (pluginConf) {
|
|
|
205
209
|
if (this.karyotype && this.karyotype.chr !== chr) {
|
|
206
210
|
recreateKaryotype.call(this);
|
|
207
211
|
}
|
|
208
|
-
}
|
|
212
|
+
},
|
|
209
213
|
});
|
|
210
214
|
};
|
|
215
|
+
|
|
216
|
+
export default { karyotype: plugin };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import '../../css/resizer.css';
|
|
2
|
+
|
|
3
|
+
const plugin = function () {
|
|
4
|
+
const jQuery = this.jQuery;
|
|
5
|
+
|
|
6
|
+
this.on('afterSetMVC', 'tracks', function () {
|
|
7
|
+
if (this.prop('resizable') !== true) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const track = this;
|
|
12
|
+
const controller = this.controller;
|
|
13
|
+
const height = this.prop('height');
|
|
14
|
+
|
|
15
|
+
let resizer = this.prop('resizer');
|
|
16
|
+
|
|
17
|
+
if (!resizer) {
|
|
18
|
+
resizer = this.prop('resizer', jQuery('<div class="gv-resizer gv-static"><div class="gv-handle"></div></div>').appendTo(track.prop('container')).draggable({
|
|
19
|
+
axis : 'y',
|
|
20
|
+
start : () => { jQuery('body').addClass('gv-dragging'); },
|
|
21
|
+
stop : function (e, ui) {
|
|
22
|
+
jQuery('body').removeClass('gv-dragging');
|
|
23
|
+
controller.resize(track.prop('height') + ui.position.top - ui.originalPosition.top, true);
|
|
24
|
+
jQuery(this).css({ top: 'auto', bottom: 0 }); // returns the resizer to the bottom of the container - needed when the track is resized to 0
|
|
25
|
+
},
|
|
26
|
+
}).on('click', () => {
|
|
27
|
+
const h = track.prop('fullVisibleHeight');
|
|
28
|
+
|
|
29
|
+
if (h) {
|
|
30
|
+
controller.resize(h, true);
|
|
31
|
+
}
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
resizer.css({ width: this.width, left: 0 })[this.prop('autoHeight') ? 'hide' : 'show']();
|
|
36
|
+
|
|
37
|
+
if (!this.prop('autoHeight') && height - this.prop('margin') === this.prop('featureHeight')) {
|
|
38
|
+
controller.resize(height + resizer.height());
|
|
39
|
+
this.prop('initialHeight', this.prop('height'));
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
this.on('afterToggleExpander', 'tracks', function () {
|
|
44
|
+
const resizer = this.prop('resizer');
|
|
45
|
+
|
|
46
|
+
if (resizer) {
|
|
47
|
+
resizer[this.expander?.is(':visible') ? 'addClass' : 'removeClass']('gv-resizer-expander');
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default { resizer: plugin };
|
|
@@ -3,22 +3,26 @@
|
|
|
3
3
|
// (c) 2008-2010 jason frame [jason@onehackoranother.com]
|
|
4
4
|
// released under the MIT license
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import '../../css/tooltips.css';
|
|
7
|
+
import controlPanel from './controlPanel';
|
|
8
|
+
|
|
9
|
+
const plugin = function () {
|
|
10
|
+
const genoverse = this;
|
|
11
|
+
const jQuery = this.jQuery;
|
|
8
12
|
|
|
9
13
|
function toggleTooltips(browser, tooltips, action) {
|
|
10
|
-
|
|
14
|
+
const offset = browser.superContainer.offset();
|
|
11
15
|
|
|
12
16
|
tooltips = tooltips || browser.superContainer.find('.gv-tooltip');
|
|
13
|
-
action = action ||
|
|
17
|
+
action = action || jQuery(this).toggleClass('gv-active').hasClass('gv-active') ? 'show' : 'hide';
|
|
14
18
|
|
|
15
19
|
tooltips.each(function () {
|
|
16
|
-
|
|
20
|
+
const el = jQuery(this);
|
|
17
21
|
|
|
18
22
|
if (el.is(':visible')) {
|
|
19
23
|
el.tipsy(action).data('tipsy').$tip.data({ parent: el }).appendTo(browser.superContainer).css({
|
|
20
24
|
marginTop : -offset.top,
|
|
21
|
-
marginLeft : -offset.left
|
|
25
|
+
marginLeft : -offset.left,
|
|
22
26
|
});
|
|
23
27
|
} else if (el.data('tipsy').$tip) {
|
|
24
28
|
el.tipsy('hide');
|
|
@@ -27,25 +31,28 @@ Genoverse.Plugins.tooltips = function () {
|
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
function updateTooltips() {
|
|
30
|
-
|
|
34
|
+
let tooltips = jQuery();
|
|
31
35
|
|
|
32
|
-
|
|
36
|
+
[
|
|
33
37
|
[ 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
|
-
]
|
|
36
|
-
|
|
38
|
+
[ genoverse.container.find('.gv-resizer'), { gravity: 'n', fade: true, trigger: 'manual', fallback: 'Resize track by dragging this handle' }],
|
|
39
|
+
].forEach(
|
|
40
|
+
([ selector, options ]) => {
|
|
41
|
+
const el = selector.filter(':visible').first();
|
|
37
42
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
if (!el.hasClass('gv-tooltip')) {
|
|
44
|
+
selector.filter('.gv-tooltip').removeClass('gv-tooltip').tipsy('hide').removeData('tipsy');
|
|
45
|
+
el.tipsy(options).addClass('gv-tooltip');
|
|
46
|
+
}
|
|
42
47
|
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
tooltips = tooltips.add(el);
|
|
49
|
+
}
|
|
50
|
+
);
|
|
45
51
|
|
|
46
52
|
// Remove any tooltips orphaned by the removal of a track
|
|
47
53
|
genoverse.superContainer.find('.tipsy').not(function () {
|
|
48
|
-
|
|
54
|
+
const parent = jQuery(this).data('parent');
|
|
55
|
+
|
|
49
56
|
return parent && genoverse.superContainer.find(parent).length;
|
|
50
57
|
}).remove();
|
|
51
58
|
|
|
@@ -60,7 +67,7 @@ Genoverse.Plugins.tooltips = function () {
|
|
|
60
67
|
icon : '<i class="fas fa-question-circle"></i>',
|
|
61
68
|
class : 'gv-tooltips',
|
|
62
69
|
name : 'Tooltips',
|
|
63
|
-
action : toggleTooltips
|
|
70
|
+
action : toggleTooltips,
|
|
64
71
|
});
|
|
65
72
|
|
|
66
73
|
this.on('afterInit', function () {
|
|
@@ -68,11 +75,11 @@ Genoverse.Plugins.tooltips = function () {
|
|
|
68
75
|
this.superContainer.find('.gv-panel-right .gv-button-set[title]').tipsy({ gravity: 'e', fade: true, trigger: 'manual' }).addClass('gv-tooltip');
|
|
69
76
|
|
|
70
77
|
// 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
|
-
|
|
78
|
+
jQuery('<i class="gv-wrapper-tooltip">').prependTo(this.wrapper).tipsy({
|
|
72
79
|
gravity : 's',
|
|
73
80
|
fade : true,
|
|
74
81
|
trigger : 'manual',
|
|
75
|
-
fallback : 'Scroll left and right by dragging with your mouse, click on any feature in any track for more info'
|
|
82
|
+
fallback : 'Scroll left and right by dragging with your mouse, click on any feature in any track for more info',
|
|
76
83
|
}).addClass('gv-tooltip');
|
|
77
84
|
|
|
78
85
|
updateTooltips();
|
|
@@ -82,13 +89,8 @@ Genoverse.Plugins.tooltips = function () {
|
|
|
82
89
|
this.controlPanel.find('.gv-tooltips.gv-active').trigger('click');
|
|
83
90
|
});
|
|
84
91
|
|
|
85
|
-
this.on('afterSortTracks',
|
|
86
|
-
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
this.on('afterResize', 'tracks', function () {
|
|
90
|
-
updateTooltips();
|
|
91
|
-
});
|
|
92
|
+
this.on('afterSortTracks', () => { updateTooltips(); });
|
|
93
|
+
this.on('afterResize', 'tracks', () => { updateTooltips(); });
|
|
92
94
|
};
|
|
93
95
|
|
|
94
|
-
|
|
96
|
+
export default { tooltips: plugin, requires: controlPanel };
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import '../../css/trackControls.css';
|
|
2
|
+
|
|
3
|
+
const plugin = function () {
|
|
4
|
+
const jQuery = this.jQuery;
|
|
5
|
+
const defaultControls = [
|
|
6
|
+
jQuery('<a title="More info" class="fas fa-question-circle">').on('click', function () {
|
|
7
|
+
const track = jQuery(this).data('track');
|
|
8
|
+
|
|
9
|
+
let menu = track.prop('menus').filter('.gv-track-info');
|
|
10
|
+
|
|
11
|
+
if (!menu.length) {
|
|
12
|
+
const info = track.prop('info');
|
|
13
|
+
|
|
14
|
+
menu = track.prop(
|
|
15
|
+
'menus',
|
|
16
|
+
track.prop('menus').add(
|
|
17
|
+
track.browser.makeMenu({
|
|
18
|
+
title : track.name,
|
|
19
|
+
[typeof info === 'function' ? info.call(track) : info || ''] : '',
|
|
20
|
+
}).addClass('gv-track-info')
|
|
21
|
+
)
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
menu.show().position({ of: track.prop('container'), at: 'center top', my: 'center top', collision: 'none' });
|
|
26
|
+
}),
|
|
27
|
+
|
|
28
|
+
jQuery(`
|
|
29
|
+
<a class="gv-height-toggle">
|
|
30
|
+
<i class="fas fa-sort"></i>
|
|
31
|
+
<i class="fas fa-sort-down"></i>
|
|
32
|
+
<i class="fas fa-sort-up"></i>
|
|
33
|
+
</a>
|
|
34
|
+
`).on({
|
|
35
|
+
click: function () {
|
|
36
|
+
const track = jQuery(this).data('track');
|
|
37
|
+
|
|
38
|
+
let height;
|
|
39
|
+
|
|
40
|
+
if (track.prop('autoHeight', !track.prop('autoHeight'))) {
|
|
41
|
+
track.prop('heightBeforeToggle', track.prop('height'));
|
|
42
|
+
height = track.prop('fullVisibleHeight');
|
|
43
|
+
} else {
|
|
44
|
+
height = track.prop('heightBeforeToggle') || track.prop('initialHeight');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
jQuery(this).trigger('toggleState');
|
|
48
|
+
|
|
49
|
+
track.controller.resize(height, true);
|
|
50
|
+
},
|
|
51
|
+
toggleState: function () { // custom event to set title and change the icon
|
|
52
|
+
const track = jQuery(this).data('track');
|
|
53
|
+
const autoHeight = track.prop('autoHeight');
|
|
54
|
+
const resizer = track.prop('resizer');
|
|
55
|
+
|
|
56
|
+
this.title = autoHeight ? 'Set track to fixed height' : 'Set track to auto-adjust height';
|
|
57
|
+
|
|
58
|
+
jQuery(this)[autoHeight ? 'addClass' : 'removeClass']('gv-auto-height');
|
|
59
|
+
|
|
60
|
+
if (resizer) {
|
|
61
|
+
resizer[autoHeight ? 'hide' : 'show']();
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
const remove = jQuery('<a title="Remove track" class="far fa-trash-alt">').on('click', function () {
|
|
68
|
+
jQuery(this).data('track').remove();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const toggle = jQuery(`
|
|
72
|
+
<a class="gv-track-controls-toggle">
|
|
73
|
+
<span><i class="fas fa-angle-double-left"></i><i class="fas fa-cog"></i></span>
|
|
74
|
+
<span><i class="fas fa-angle-double-right"></i></span>
|
|
75
|
+
</a>
|
|
76
|
+
`).on('click', function () {
|
|
77
|
+
jQuery(this).parent().toggleClass('gv-maximized');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
this.on({
|
|
81
|
+
afterAddDomElements: function () {
|
|
82
|
+
let controls = this.prop('controls');
|
|
83
|
+
|
|
84
|
+
if (controls === 'off') {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const defaultConfig = this.prop('defaultConfig');
|
|
89
|
+
const savedConfig = this.browser.savedConfig?.[this.prop('id')] || {};
|
|
90
|
+
|
|
91
|
+
controls = (controls || []).concat(defaultControls, this.prop('removable') === false ? [] : remove);
|
|
92
|
+
|
|
93
|
+
this.trackControls = jQuery('<div class="gv-track-controls">').prependTo(this.container);
|
|
94
|
+
|
|
95
|
+
const controlsContainer = jQuery('<div class="gv-track-controls-container">').appendTo(this.trackControls);
|
|
96
|
+
|
|
97
|
+
controls.forEach(
|
|
98
|
+
(control) => {
|
|
99
|
+
let el;
|
|
100
|
+
|
|
101
|
+
if (jQuery.isPlainObject(control) && control.type) {
|
|
102
|
+
el = jQuery(`<${control.type}>`).data('control', control.name);
|
|
103
|
+
|
|
104
|
+
(control.options || []).forEach(
|
|
105
|
+
option => el.append(`<option value="${option.value}">${option.text}</option>`)
|
|
106
|
+
);
|
|
107
|
+
} else if (typeof control === 'string') {
|
|
108
|
+
el = jQuery(control);
|
|
109
|
+
} else if (typeof control === 'object' && control.constructor && control instanceof jQuery) {
|
|
110
|
+
el = control.clone(true);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
el.data('track', this.track).appendTo(controlsContainer);
|
|
114
|
+
|
|
115
|
+
// TODO: other control types
|
|
116
|
+
if (el.is('select')) {
|
|
117
|
+
const prop = el.data('control');
|
|
118
|
+
|
|
119
|
+
el.find(`option[value=${savedConfig[prop] || defaultConfig[prop] || 'all'}]`).attr('selected', true).end().change(function () {
|
|
120
|
+
jQuery(this).data('track').setConfig(jQuery(this).data('control'), this.value);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
this.prop('heightToggler', controlsContainer.children('.gv-height-toggle').trigger('toggleState'));
|
|
127
|
+
|
|
128
|
+
const toggler = toggle.clone(true).data('track', this.track).appendTo(this.trackControls);
|
|
129
|
+
|
|
130
|
+
toggler.trigger('click');
|
|
131
|
+
|
|
132
|
+
this.minLabelHeight = Math.max(this.minLabelHeight, this.trackControls.outerHeight(true) + this.prop('margin'));
|
|
133
|
+
|
|
134
|
+
toggler.trigger('click');
|
|
135
|
+
},
|
|
136
|
+
afterResize: function () {
|
|
137
|
+
if (this.trackControls) {
|
|
138
|
+
this.trackControls[this.prop('height') < this.trackControls.outerHeight(true) ? 'hide' : 'show']();
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
afterResetHeight: function () {
|
|
142
|
+
const heightToggler = this.prop('heightToggler');
|
|
143
|
+
|
|
144
|
+
if (this.prop('resizable') === true && heightToggler) {
|
|
145
|
+
heightToggler[this.prop('autoHeight') ? 'addClass' : 'removeClass']('gv-auto-height');
|
|
146
|
+
heightToggler.trigger('toggleState');
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
afterSetMVC: function () {
|
|
150
|
+
const heightToggler = this.prop('heightToggler');
|
|
151
|
+
|
|
152
|
+
if (heightToggler) {
|
|
153
|
+
heightToggler.trigger('toggleState')[this.prop('resizable') === true ? 'removeClass' : 'addClass']('gv-hide');
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
}, 'tracks');
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export default { trackControls: plugin };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const { afterTest } = require('./utils');
|
|
2
|
+
|
|
3
|
+
describe('Changing width', () => {
|
|
4
|
+
afterEach(afterTest);
|
|
5
|
+
|
|
6
|
+
const genoverse = new Genoverse({
|
|
7
|
+
chr : 1,
|
|
8
|
+
start : 1,
|
|
9
|
+
end : 20,
|
|
10
|
+
chromosomeSize : 9e99,
|
|
11
|
+
width : 100,
|
|
12
|
+
tracks : [ Genoverse.Track.extend({ 10: false, model: Genoverse.Track.Model.extend({ __test: true }) }) ],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const track = genoverse.tracks[0];
|
|
16
|
+
|
|
17
|
+
it('Initial settings are correct', () => {
|
|
18
|
+
expect(track.lengthMap.length).toBe(2);
|
|
19
|
+
expect(track.lengthMap.map(l => l[0])).toEqual([ 10, -1 ]);
|
|
20
|
+
|
|
21
|
+
expect(track.model).toEqual(track.models[10]);
|
|
22
|
+
expect(track.model.__test).toBe(undefined);
|
|
23
|
+
|
|
24
|
+
expect(genoverse.width).toBe(100);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('Settings are correct after width change', (done) => {
|
|
28
|
+
genoverse.setWidth(1000);
|
|
29
|
+
|
|
30
|
+
setTimeout( // setWidth causes tracks to be reset after a 1ms delay, which we need to wait for here
|
|
31
|
+
() => {
|
|
32
|
+
try {
|
|
33
|
+
expect(track.lengthMap.length).toBe(2);
|
|
34
|
+
expect(track.lengthMap.map(l => l[0])).toEqual([ 10, -1 ]);
|
|
35
|
+
|
|
36
|
+
expect(track.model).toEqual(track.models[10]);
|
|
37
|
+
expect(track.model.__test).toBe(undefined);
|
|
38
|
+
|
|
39
|
+
expect(genoverse.width).toBe(1000);
|
|
40
|
+
|
|
41
|
+
done();
|
|
42
|
+
} catch (e) {
|
|
43
|
+
done(e);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
100
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('Model changes correctly after width change + zoom out', (done) => {
|
|
51
|
+
genoverse.setWidth(1000);
|
|
52
|
+
|
|
53
|
+
setTimeout( // setWidth causes tracks to be reset after a 1ms delay, which we need to wait for here
|
|
54
|
+
() => {
|
|
55
|
+
genoverse.moveTo(1, 1, 5);
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
expect(genoverse.width).toBe(1000);
|
|
59
|
+
expect(genoverse.length).toBe(5);
|
|
60
|
+
expect(track.model).toEqual(track.models[-1]);
|
|
61
|
+
expect(track.model.__test).toBe(true);
|
|
62
|
+
|
|
63
|
+
done();
|
|
64
|
+
} catch (e) {
|
|
65
|
+
done(e);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
100
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const css
|
|
2
|
-
const { Genoverse, afterTest } = require('./utils');
|
|
1
|
+
const css = require('fs').readFileSync('src/css/genoverse.css', 'utf8');
|
|
2
|
+
const { $, Genoverse, afterTest } = require('./utils');
|
|
3
3
|
|
|
4
4
|
const html = `<style>${css}</style><div id="genoverse-test-1"></div><div id="genoverse-test-2"></div><div id="genoverse-test-3"></div>`;
|
|
5
5
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { Genoverse, afterTest } = require('./utils');
|
|
1
|
+
const { $, Genoverse, afterTest } = require('./utils');
|
|
2
2
|
|
|
3
3
|
// TODO: unsortable, particularly with unsortable order=9e99, then adding another track
|
|
4
4
|
|
|
@@ -22,6 +22,7 @@ describe('Track ordering', () => {
|
|
|
22
22
|
tracks : tracks.map(t => Genoverse.Track.extend({ url: false, ...t })),
|
|
23
23
|
_initDeferred : $.Deferred(),
|
|
24
24
|
saveConfig : () => {},
|
|
25
|
+
loadCSS : () => {},
|
|
25
26
|
loadGenome : () => {},
|
|
26
27
|
loadPlugins : () => {},
|
|
27
28
|
});
|
|
@@ -107,7 +108,7 @@ describe('Track ordering', () => {
|
|
|
107
108
|
|
|
108
109
|
const legendTrack = (id, legendConf) => ({
|
|
109
110
|
id : id,
|
|
110
|
-
legend : legendConf ? Genoverse.Track.Legend.extend(legendConf) :
|
|
111
|
+
legend : legendConf ? Genoverse.Track.Legend.extend(legendConf) : Genoverse.Track.Legend,
|
|
111
112
|
});
|
|
112
113
|
|
|
113
114
|
describe('Simple tracks', () => {
|