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.
Files changed (217) hide show
  1. package/.eslintrc.js +93 -162
  2. package/.github/workflows/test.yml +9 -10
  3. package/.github/workflows/update-gh-pages.yml +33 -0
  4. package/LICENSE.TXT +2 -2
  5. package/README.md +174 -3
  6. package/{i → assets}/sort_handle.png +0 -0
  7. package/babel.config.js +19 -0
  8. package/dist/129.css +334 -0
  9. package/dist/129.css.map +1 -0
  10. package/dist/129.genoverse.js +2 -0
  11. package/dist/129.genoverse.js.map +1 -0
  12. package/dist/15d98c18221c8bcb2334.ttf +0 -0
  13. package/dist/166.css +2 -0
  14. package/dist/166.genoverse.js +1 -0
  15. package/dist/216.css +20 -0
  16. package/dist/216.css.map +1 -0
  17. package/dist/232.css +114 -0
  18. package/dist/232.css.map +1 -0
  19. package/dist/232.genoverse.js +2 -0
  20. package/dist/232.genoverse.js.map +1 -0
  21. package/dist/2e659e443f3e98569e9f.png +0 -0
  22. package/dist/394.css +114 -0
  23. package/dist/394.css.map +1 -0
  24. package/dist/394.genoverse.js +2 -0
  25. package/dist/394.genoverse.js.map +1 -0
  26. package/dist/469.css +24 -0
  27. package/dist/469.css.map +1 -0
  28. package/dist/469.genoverse.js +2 -0
  29. package/dist/469.genoverse.js.map +1 -0
  30. package/dist/4896d4b04430cc3dfb06.woff2 +0 -0
  31. package/dist/530.css +39 -0
  32. package/dist/530.css.map +1 -0
  33. package/dist/530.genoverse.js +2 -0
  34. package/dist/530.genoverse.js.map +1 -0
  35. package/dist/547.css +469 -0
  36. package/dist/547.css.map +1 -0
  37. package/dist/547.genoverse.js +1 -0
  38. package/dist/729.css +315 -0
  39. package/dist/729.css.map +1 -0
  40. package/dist/79da213423ac0def2058.ttf +0 -0
  41. package/dist/804.genoverse.js +2 -0
  42. package/dist/804.genoverse.js.map +1 -0
  43. package/dist/842.genoverse.js +2 -0
  44. package/dist/842.genoverse.js.map +1 -0
  45. package/dist/893.genoverse.js +2 -0
  46. package/dist/893.genoverse.js.map +1 -0
  47. package/dist/949.css +315 -0
  48. package/dist/949.css.map +1 -0
  49. package/dist/949.genoverse.js +2 -0
  50. package/dist/949.genoverse.js.map +1 -0
  51. package/dist/952.css +315 -0
  52. package/dist/952.css.map +1 -0
  53. package/dist/952.genoverse.js +2 -0
  54. package/dist/952.genoverse.js.map +1 -0
  55. package/dist/d79c2ec96ab9ff1161a2.woff2 +0 -0
  56. package/dist/genoverse.js +2 -0
  57. package/dist/genoverse.js.map +1 -0
  58. package/index.html +13 -14
  59. package/jest.config.js +5 -0
  60. package/jest.setup.js +13 -0
  61. package/package.json +29 -12
  62. package/{css → src/css}/controlPanel.css +0 -0
  63. package/{css → src/css}/fileDrop.css +0 -0
  64. package/src/css/fontawesome.css +3 -0
  65. package/{css → src/css}/fullscreen.css +0 -0
  66. package/{css → src/css}/genoverse.css +1 -1
  67. package/{css → src/css}/karyotype.css +2 -0
  68. package/{css → src/css}/resizer.css +0 -0
  69. package/{css → src/css}/tooltips.css +0 -0
  70. package/{css → src/css}/trackControls.css +0 -0
  71. package/src/js/Genoverse.js +1747 -0
  72. package/{js → src/js}/Track/Controller/Sequence.js +6 -4
  73. package/src/js/Track/Controller/Stranded.js +83 -0
  74. package/{js → src/js}/Track/Controller.js +201 -160
  75. package/src/js/Track/Model/File/BAM.js +47 -0
  76. package/src/js/Track/Model/File/BED.js +122 -0
  77. package/src/js/Track/Model/File/GFF.js +42 -0
  78. package/src/js/Track/Model/File/VCF.js +109 -0
  79. package/src/js/Track/Model/File/WIG.js +82 -0
  80. package/src/js/Track/Model/File.js +36 -0
  81. package/src/js/Track/Model/Gene/Ensembl.js +24 -0
  82. package/{js → src/js}/Track/Model/Gene.js +3 -1
  83. package/src/js/Track/Model/Sequence/Ensembl.js +6 -0
  84. package/{js → src/js}/Track/Model/Sequence/Fasta.js +24 -17
  85. package/{js → src/js}/Track/Model/Sequence.js +10 -7
  86. package/{js → src/js}/Track/Model/SequenceVariation.js +17 -11
  87. package/{js → src/js}/Track/Model/Stranded.js +11 -8
  88. package/src/js/Track/Model/Transcript/Ensembl.js +73 -0
  89. package/{js → src/js}/Track/Model/Transcript.js +3 -1
  90. package/{js → src/js}/Track/Model.js +125 -93
  91. package/{js → src/js}/Track/View/Gene/Ensembl.js +6 -4
  92. package/src/js/Track/View/Gene.js +8 -0
  93. package/{js → src/js}/Track/View/Sequence.js +18 -22
  94. package/src/js/Track/View/SequenceVariation.js +117 -0
  95. package/src/js/Track/View/Transcript/Ensembl.js +17 -0
  96. package/src/js/Track/View/Transcript.js +32 -0
  97. package/{js → src/js}/Track/View.js +200 -159
  98. package/{js → src/js}/Track/library/Chromosome.js +18 -13
  99. package/src/js/Track/library/File/BAM.js +34 -0
  100. package/src/js/Track/library/File/BED.js +27 -0
  101. package/src/js/Track/library/File/BIGBED.js +51 -0
  102. package/src/js/Track/library/File/BIGWIG.js +54 -0
  103. package/src/js/Track/library/File/GFF.js +10 -0
  104. package/{js → src/js}/Track/library/File/VCF.js +29 -22
  105. package/src/js/Track/library/File/WIG.js +8 -0
  106. package/{js → src/js}/Track/library/File.js +4 -2
  107. package/src/js/Track/library/Gene.js +44 -0
  108. package/src/js/Track/library/Graph/Bar.js +263 -0
  109. package/src/js/Track/library/Graph/Line.js +335 -0
  110. package/{js → src/js}/Track/library/Graph.js +137 -114
  111. package/{js → src/js}/Track/library/HighlightRegion.js +118 -93
  112. package/src/js/Track/library/Legend.js +258 -0
  113. package/{js → src/js}/Track/library/Scalebar.js +69 -49
  114. package/{js → src/js}/Track/library/Scaleline.js +29 -27
  115. package/src/js/Track/library/Static.js +82 -0
  116. package/{js → src/js}/Track/library/dbSNP.js +47 -50
  117. package/src/js/Track.js +651 -0
  118. package/{js → src/js}/genomes/grch37.js +52 -52
  119. package/{js → src/js}/genomes/grch38.js +52 -52
  120. package/src/js/lib/BWReader.js +562 -0
  121. package/src/js/lib/VCFReader.js +296 -0
  122. package/src/js/lib/dalliance/bam.js +517 -0
  123. package/src/js/lib/dalliance/bin.js +317 -0
  124. package/src/js/lib/dalliance/jszlib-inflate.js +2159 -0
  125. package/src/js/lib/dalliance/lh3utils.js +105 -0
  126. package/src/js/lib/dalliance/sha1.js +334 -0
  127. package/src/js/lib/import-tracks.js +42 -0
  128. package/{js/lib → src/js/lib/jquery-plugins}/jquery.mousehold.js +0 -0
  129. package/{js/lib → src/js/lib/jquery-plugins}/jquery.mousewheel.js +0 -0
  130. package/{js/lib → src/js/lib/jquery-plugins}/jquery.tipsy.js +0 -0
  131. package/src/js/lib/jquery.js +26 -0
  132. package/src/js/lib/polyfills.js +11 -0
  133. package/src/js/lib/wrap-functions.js +88 -0
  134. package/src/js/plugins/controlPanel.js +388 -0
  135. package/src/js/plugins/fileDrop.js +81 -0
  136. package/src/js/plugins/focusRegion.js +13 -0
  137. package/{js → src/js}/plugins/fullscreen.js +18 -14
  138. package/{js → src/js}/plugins/karyotype.js +51 -45
  139. package/src/js/plugins/resizer.js +52 -0
  140. package/{js → src/js}/plugins/tooltips.js +31 -29
  141. package/src/js/plugins/trackControls.js +159 -0
  142. package/test/View/render-legends.test.js +1 -1
  143. package/test/change-width.test.js +71 -0
  144. package/test/create-and-destroy.test.js +2 -2
  145. package/test/track-ordering.test.js +3 -2
  146. package/test/track_config/config-settings.test.js +1 -1
  147. package/test/utils.js +4 -2
  148. package/webpack.config.js +103 -34
  149. package/css/font-awesome.css +0 -3
  150. package/expanded.html +0 -120
  151. package/fontawesome/css/fontawesome.min.css +0 -5
  152. package/fontawesome/css/regular.min.css +0 -5
  153. package/fontawesome/css/solid.min.css +0 -5
  154. package/fontawesome/webfonts/fa-brands-400.ttf +0 -0
  155. package/fontawesome/webfonts/fa-brands-400.woff +0 -0
  156. package/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
  157. package/fontawesome/webfonts/fa-regular-400.ttf +0 -0
  158. package/fontawesome/webfonts/fa-regular-400.woff +0 -0
  159. package/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
  160. package/fontawesome/webfonts/fa-solid-900.ttf +0 -0
  161. package/fontawesome/webfonts/fa-solid-900.woff +0 -0
  162. package/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
  163. package/help.pdf +0 -0
  164. package/index.js +0 -83
  165. package/js/Genoverse.js +0 -1681
  166. package/js/Track/Controller/Stranded.js +0 -73
  167. package/js/Track/Model/File/BAM.js +0 -44
  168. package/js/Track/Model/File/BED.js +0 -116
  169. package/js/Track/Model/File/GFF.js +0 -40
  170. package/js/Track/Model/File/VCF.js +0 -101
  171. package/js/Track/Model/File/WIG.js +0 -67
  172. package/js/Track/Model/File.js +0 -36
  173. package/js/Track/Model/Gene/Ensembl.js +0 -22
  174. package/js/Track/Model/Sequence/Ensembl.js +0 -4
  175. package/js/Track/Model/Transcript/Ensembl.js +0 -67
  176. package/js/Track/View/Gene.js +0 -6
  177. package/js/Track/View/Sequence/Variation.js +0 -115
  178. package/js/Track/View/Transcript/Ensembl.js +0 -12
  179. package/js/Track/View/Transcript.js +0 -28
  180. package/js/Track/library/File/BAM.js +0 -30
  181. package/js/Track/library/File/BED.js +0 -24
  182. package/js/Track/library/File/BIGBED.js +0 -47
  183. package/js/Track/library/File/BIGWIG.js +0 -52
  184. package/js/Track/library/File/GFF.js +0 -9
  185. package/js/Track/library/File/WIG.js +0 -5
  186. package/js/Track/library/Gene.js +0 -37
  187. package/js/Track/library/Graph/Bar.js +0 -235
  188. package/js/Track/library/Graph/Line.js +0 -296
  189. package/js/Track/library/Legend.js +0 -224
  190. package/js/Track/library/Static.js +0 -78
  191. package/js/Track.js +0 -632
  192. package/js/genoverse.min.js +0 -2
  193. package/js/genoverse.min.js.map +0 -1
  194. package/js/lib/BWReader.js +0 -578
  195. package/js/lib/Base.js +0 -145
  196. package/js/lib/VCFReader.js +0 -286
  197. package/js/lib/dalliance/js/bam.js +0 -494
  198. package/js/lib/dalliance/js/bin.js +0 -185
  199. package/js/lib/dalliance/js/das.js +0 -749
  200. package/js/lib/dalliance/js/utils.js +0 -370
  201. package/js/lib/dalliance-lib.js +0 -3594
  202. package/js/lib/dalliance-lib.min.js +0 -68
  203. package/js/lib/jDataView.js +0 -2
  204. package/js/lib/jParser.js +0 -192
  205. package/js/lib/jquery-ui.js +0 -8
  206. package/js/lib/jquery.js +0 -2
  207. package/js/lib/rtree.js +0 -1
  208. package/js/plugins/controlPanel.js +0 -395
  209. package/js/plugins/fileDrop.js +0 -62
  210. package/js/plugins/focusRegion.js +0 -12
  211. package/js/plugins/resizer.js +0 -45
  212. package/js/plugins/trackControls.js +0 -143
  213. package/utils/expandedTemplate.html +0 -46
  214. package/utils/git-hooks/post-commit +0 -9
  215. package/utils/git-hooks/pre-commit +0 -7
  216. package/utils/git-hooks/setup +0 -6
  217. package/utils/makeExpanded.js +0 -19
@@ -1,4 +1,8 @@
1
- Genoverse.Track.View = Base.extend({
1
+ import Base from 'basejs';
2
+ import RTree from 'rtree';
3
+ import wrapFunctions from '../lib/wrap-functions';
4
+
5
+ export default Base.extend({
2
6
  fontHeight : 10,
3
7
  fontFamily : 'sans-serif',
4
8
  fontWeight : 'normal',
@@ -19,8 +23,15 @@ Genoverse.Track.View = Base.extend({
19
23
  subFeatureJoinLineWidth : 0.5,
20
24
 
21
25
  constructor: function (properties) {
22
- $.extend(this, properties);
23
- Genoverse.wrapFunctions(this);
26
+ Object.entries(properties).forEach(
27
+ ([ key, val ]) => {
28
+ if (typeof val !== 'undefined') {
29
+ this[key] = val;
30
+ }
31
+ }
32
+ );
33
+
34
+ wrapFunctions(this, 'View');
24
35
  this.init();
25
36
  },
26
37
 
@@ -33,17 +44,17 @@ Genoverse.Track.View = Base.extend({
33
44
  setDefaults: function () {
34
45
  this.featureMargin = this.featureMargin || { top: 3, right: 1, bottom: 1, left: 0 };
35
46
 
36
- var margin = [ 'top', 'right', 'bottom', 'left' ];
37
-
38
- for (var i = 0; i < margin.length; i++) {
39
- if (typeof this.featureMargin[margin[i]] !== 'number') {
40
- this.featureMargin[margin[i]] = 0;
47
+ [ 'top', 'right', 'bottom', 'left' ].forEach(
48
+ (margin) => {
49
+ if (typeof this.featureMargin[margin] !== 'number') {
50
+ this.featureMargin[margin] = 0;
51
+ }
41
52
  }
42
- }
53
+ );
43
54
 
44
- this.context = $('<canvas>')[0].getContext('2d');
55
+ this.context = this.browser.jQuery('<canvas>')[0].getContext('2d');
45
56
  this.featureHeight = typeof this.featureHeight !== 'undefined' ? this.featureHeight : this.prop('defaultHeight');
46
- this.font = this.fontWeight + ' ' + this.fontHeight + 'px ' + this.fontFamily;
57
+ this.font = `${this.fontWeight} ${this.fontHeight}px ${this.fontFamily}`;
47
58
  this.labelUnits = [ 'bp', 'kb', 'Mb', 'Gb', 'Tb' ];
48
59
 
49
60
  this.context.font = this.font;
@@ -54,19 +65,19 @@ Genoverse.Track.View = Base.extend({
54
65
  },
55
66
 
56
67
  setScaleSettings: function (scale) {
57
- var chr = this.browser.chr;
68
+ const chr = this.browser.chr;
58
69
 
59
70
  if (!this.scaleSettings[chr]) {
60
71
  this.scaleSettings[chr] = {};
61
72
  }
62
73
 
63
74
  if (!this.scaleSettings[chr][scale]) {
64
- var featurePositions = new RTree();
75
+ const featurePositions = new RTree();
65
76
 
66
77
  this.scaleSettings[chr][scale] = {
67
- imgContainers : $(),
78
+ imgContainers : this.browser.jQuery(),
68
79
  featurePositions : featurePositions,
69
- labelPositions : this.labels === 'separate' ? new RTree() : featurePositions
80
+ labelPositions : this.labels === 'separate' ? new RTree() : featurePositions,
70
81
  };
71
82
  }
72
83
 
@@ -82,34 +93,35 @@ Genoverse.Track.View = Base.extend({
82
93
  },
83
94
 
84
95
  scaleFeatures: function (features, scale) {
85
- var add = this.roundPixelValue(Math.max(scale, this.widthCorrection));
86
- var feature, j;
96
+ const add = this.roundPixelValue(Math.max(scale, this.widthCorrection));
87
97
 
88
- for (var i = 0; i < features.length; i++) {
89
- feature = features[i];
98
+ features.forEach(
99
+ (feature) => {
100
+ if (!feature.position) {
101
+ feature.position = {};
102
+ }
90
103
 
91
- if (!feature.position) {
92
- feature.position = {};
93
- }
104
+ if (!feature.position[scale]) {
105
+ feature.position[scale] = {
106
+ start : this.roundPixelValue(feature.start * scale),
107
+ width : Math.max(this.roundPixelValue((feature.end - feature.start) * scale + add), this.minScaledWidth),
108
+ height : feature.height || this.featureHeight,
109
+ };
110
+ }
94
111
 
95
- if (!feature.position[scale]) {
96
- feature.position[scale] = {
97
- start : this.roundPixelValue(feature.start * scale),
98
- width : Math.max(this.roundPixelValue((feature.end - feature.start) * scale + add), this.minScaledWidth),
99
- height : feature.height || this.featureHeight
100
- };
101
- }
112
+ if (feature.subFeatures) {
113
+ feature.subFeatures.forEach(
114
+ (subFeature) => {
115
+ if (typeof subFeature.height === 'undefined') {
116
+ subFeature.height = feature.position[scale].height;
117
+ }
118
+ }
119
+ );
102
120
 
103
- if (feature.subFeatures) {
104
- for (j = 0; j < feature.subFeatures.length; j++) {
105
- if (typeof feature.subFeatures[j].height === 'undefined') {
106
- feature.subFeatures[j].height = feature.position[scale].height;
107
- }
121
+ this.scaleFeatures(feature.subFeatures, scale);
108
122
  }
109
-
110
- this.scaleFeatures(feature.subFeatures, scale);
111
123
  }
112
- }
124
+ );
113
125
 
114
126
  return features;
115
127
  },
@@ -117,9 +129,9 @@ Genoverse.Track.View = Base.extend({
117
129
  positionFeatures: function (features, params) {
118
130
  params.margin = this.prop('margin');
119
131
 
120
- for (var i = 0; i < features.length; i++) {
121
- this.positionFeature(features[i], params);
122
- }
132
+ features.forEach(
133
+ feature => this.positionFeature(feature, params)
134
+ );
123
135
 
124
136
  params.width = Math.ceil(params.width);
125
137
  params.height = Math.ceil(params.height);
@@ -130,33 +142,34 @@ Genoverse.Track.View = Base.extend({
130
142
  },
131
143
 
132
144
  positionFeature: function (feature, params) {
133
- var scale = params.scale;
134
- var scaleSettings = this.scaleSettings[feature.chr][scale];
145
+ const scale = params.scale;
146
+ const scaleSettings = this.scaleSettings[feature.chr][scale];
135
147
 
136
148
  if (!scaleSettings) {
137
149
  return;
138
150
  }
139
151
 
140
- var subFeatures = feature.subFeatures || [];
141
- var i;
152
+ const subFeatures = feature.subFeatures || [];
142
153
 
143
154
  feature.position[scale].X = feature.position[scale].start - params.scaledStart; // FIXME: always have to reposition for X, in case a feature appears in 2 images. Pass scaledStart around instead?
144
155
 
145
- for (i = 0; i < subFeatures.length; i++) {
146
- subFeatures[i].position[scale].x = subFeatures[i].position[scale].start - params.scaledStart;
156
+ subFeatures.forEach(
157
+ (subFeature) => {
158
+ subFeature.position[scale].x = subFeature.position[scale].start - params.scaledStart;
147
159
 
148
- if (this.subFeatureJoinStyle) {
149
- subFeatures[i].position[scale].join = subFeatures[i].position[scale].join || {};
150
- subFeatures[i].position[scale].join.x = subFeatures[i].position[scale].start + subFeatures[i].position[scale].width - params.scaledStart;
160
+ if (this.subFeatureJoinStyle) {
161
+ subFeature.position[scale].join = subFeature.position[scale].join || {};
162
+ subFeature.position[scale].join.x = subFeature.position[scale].start + subFeature.position[scale].width - params.scaledStart;
163
+ }
151
164
  }
152
- }
165
+ );
153
166
 
154
167
  if (this.alwaysReposition || !feature.position[scale].positioned) {
155
168
  feature.position[scale].H = feature.position[scale].height + this.featureMargin.bottom;
156
169
  feature.position[scale].W = feature.position[scale].width + (feature.marginRight || this.featureMargin.right);
157
170
  feature.position[scale].Y = (
158
171
  typeof feature.position[scale].y === 'number' ? feature.position[scale].y :
159
- typeof feature.y === 'number' ? feature.y * feature.position[scale].H : 0
172
+ typeof feature.y === 'number' ? feature.y * feature.position[scale].H : 0
160
173
  ) + (feature.marginTop || this.featureMargin.top);
161
174
 
162
175
  if (feature.label) {
@@ -164,10 +177,10 @@ Genoverse.Track.View = Base.extend({
164
177
  feature.label = feature.label.split('\n');
165
178
  }
166
179
 
167
- var context = this.context;
180
+ const context = this.context;
168
181
 
169
182
  feature.labelHeight = feature.labelHeight || (this.fontHeight + 2) * feature.label.length;
170
- feature.labelWidth = feature.labelWidth || Math.max.apply(Math, $.map(feature.label, function (l) { return Math.ceil(context.measureText(l).width); })) + 1;
183
+ feature.labelWidth = feature.labelWidth || Math.max(...feature.label.map(l => Math.ceil(context.measureText(l).width))) + 1;
171
184
 
172
185
  if (this.labels === true) {
173
186
  feature.position[scale].H += feature.labelHeight;
@@ -177,16 +190,16 @@ Genoverse.Track.View = Base.extend({
177
190
  x : feature.position[scale].start,
178
191
  y : feature.position[scale].Y,
179
192
  w : feature.labelWidth,
180
- h : feature.labelHeight
193
+ h : feature.labelHeight,
181
194
  };
182
195
  }
183
196
  }
184
197
 
185
- var bounds = {
198
+ const bounds = {
186
199
  x : feature.position[scale].start,
187
200
  y : feature.position[scale].Y,
188
201
  w : feature.position[scale].W,
189
- h : feature.position[scale].H + (feature.marginTop || this.featureMargin.top)
202
+ h : feature.position[scale].H + (feature.marginTop || this.featureMargin.top),
190
203
  };
191
204
 
192
205
  feature.position[scale].bounds = bounds;
@@ -201,18 +214,24 @@ Genoverse.Track.View = Base.extend({
201
214
  feature.position[scale].positioned = true;
202
215
  }
203
216
 
204
- var join = this.subFeatureJoinStyle && subFeatures.length ? {
205
- height : (Math.max.apply(Math, subFeatures.map(function (c) { return c.fake ? 0 : c.position[scale].height; })) / 2) * (feature.strand > 0 ? -1 : 1),
206
- y : feature.position[scale].Y + feature.position[scale].height / 2
207
- } : false;
217
+ const join = (
218
+ this.subFeatureJoinStyle && subFeatures.length
219
+ ? {
220
+ height : (Math.max(...subFeatures.map(c => (c.fake ? 0 : c.position[scale].height))) / 2) * (feature.strand > 0 ? -1 : 1),
221
+ y : feature.position[scale].Y + feature.position[scale].height / 2,
222
+ }
223
+ : false
224
+ );
208
225
 
209
- for (i = 0; i < subFeatures.length; i++) {
210
- subFeatures[i].position[scale].y = feature.position[scale].Y + (feature.position[scale].height - subFeatures[i].position[scale].height) / 2;
226
+ subFeatures.forEach(
227
+ (subFeature, i) => {
228
+ subFeature.position[scale].y = feature.position[scale].Y + (feature.position[scale].height - subFeature.position[scale].height) / 2;
211
229
 
212
- if (join && subFeatures[i + 1]) {
213
- $.extend(subFeatures[i].position[scale].join, { width: subFeatures[i + 1].position[scale].x - subFeatures[i].position[scale].join.x }, join);
230
+ if (join && subFeatures[i + 1]) {
231
+ Object.assign(subFeature.position[scale].join, { width: subFeatures[i + 1].position[scale].x - subFeature.position[scale].join.x, ...join });
232
+ }
214
233
  }
215
- }
234
+ );
216
235
 
217
236
  if (this.labels === 'separate' && feature.position[scale].label) {
218
237
  if (this.alwaysReposition || !feature.position[scale].label.positioned) {
@@ -233,20 +252,23 @@ Genoverse.Track.View = Base.extend({
233
252
 
234
253
  // FIXME: should label bumping bounds be distinct from feature bumping bounds when label is smaller than feature?
235
254
  bumpFeature: function (bounds, feature, scale, tree) {
236
- var depth = 0;
237
- var scaleSettings = this.scaleSettings[feature.chr][scale];
238
- var labels = tree === scaleSettings.labelPositions && tree !== scaleSettings.featurePositions;
239
- var bump, clash, searchResults, i;
255
+ const scaleSettings = this.scaleSettings[feature.chr][scale];
256
+ const labels = tree === scaleSettings.labelPositions && tree !== scaleSettings.featurePositions;
257
+
258
+ let bump = true;
259
+ let depth = 0;
240
260
 
241
- do {
261
+ while (bump) {
242
262
  if (this.depth && ++depth >= this.depth) {
243
263
  if (!labels) {
244
- searchResults = scaleSettings.featurePositions.search(bounds);
245
- i = searchResults.length;
264
+ const searchResults = scaleSettings.featurePositions.search(bounds);
265
+
266
+ let i = searchResults.length;
246
267
 
247
268
  while (i--) {
248
269
  if (searchResults[i].position[scale].visible !== false) {
249
270
  feature.position[scale].visible = false;
271
+
250
272
  break;
251
273
  }
252
274
  }
@@ -255,14 +277,14 @@ Genoverse.Track.View = Base.extend({
255
277
  break;
256
278
  }
257
279
 
258
- bump = false;
259
- clash = tree.search(bounds)[0];
280
+ const clash = tree.search(bounds)[0];
260
281
 
261
282
  if (clash && clash.id !== feature.id) {
262
283
  bounds.y = clash.position[scale][labels ? 'label' : 'bounds'].y + clash.position[scale][labels ? 'label' : 'bounds'].h;
263
- bump = true;
284
+ } else {
285
+ bump = false;
264
286
  }
265
- } while (bump);
287
+ }
266
288
 
267
289
  if (!labels) {
268
290
  feature.position[scale].Y = bounds.y;
@@ -270,29 +292,28 @@ Genoverse.Track.View = Base.extend({
270
292
  },
271
293
 
272
294
  draw: function (features, featureContext, labelContext, scale) {
273
- var feature, f;
274
-
275
- for (var i = 0; i < features.length; i++) {
276
- feature = features[i];
277
-
278
- if (feature.position[scale].visible !== false) {
279
- // TODO: extend with feature.position[scale], rationalize keys
280
- f = $.extend({}, feature, {
281
- x : feature.position[scale].X,
282
- y : feature.position[scale].Y,
283
- width : feature.position[scale].width,
284
- height : feature.position[scale].height,
285
- labelPosition : feature.position[scale].label
286
- });
287
-
288
- this.drawFeature(f, featureContext, labelContext, scale);
289
-
290
- if (f.legend !== feature.legend) {
291
- feature.legend = f.legend;
292
- feature.legendColor = f.color;
295
+ features.forEach(
296
+ (feature) => {
297
+ if (feature.position[scale].visible !== false) {
298
+ // TODO: extend with feature.position[scale], rationalize keys
299
+ const f = {
300
+ ...feature,
301
+ x : feature.position[scale].X,
302
+ y : feature.position[scale].Y,
303
+ width : feature.position[scale].width,
304
+ height : feature.position[scale].height,
305
+ labelPosition : feature.position[scale].label,
306
+ };
307
+
308
+ this.drawFeature(f, featureContext, labelContext, scale);
309
+
310
+ if (f.legend !== feature.legend) {
311
+ feature.legend = f.legend;
312
+ feature.legendColor = f.color;
313
+ }
293
314
  }
294
315
  }
295
- }
316
+ );
296
317
  },
297
318
 
298
319
  drawFeature: function (feature, featureContext, labelContext, scale) {
@@ -332,24 +353,26 @@ Genoverse.Track.View = Base.extend({
332
353
  },
333
354
 
334
355
  drawSubFeatures: function (feature, featureContext, labelContext, scale) {
335
- var clonedFeature = $.extend(true, {}, feature, { subFeatures: false, label: false });
336
- var subFeatures = $.extend(true, [], feature.subFeatures);
337
- var joinColor = feature.joinColor || feature.color;
338
-
339
- for (var i = 0; i < subFeatures.length; i++) {
340
- if (!subFeatures[i].fake) {
341
- this.drawFeature($.extend({}, clonedFeature, subFeatures[i].position[scale], subFeatures[i]), featureContext, labelContext, scale);
342
- }
356
+ const clonedFeature = this.browser.jQuery.extend(true, {}, feature, { subFeatures: false, label: false });
357
+ const subFeatures = this.browser.jQuery.extend(true, [], feature.subFeatures);
358
+ const joinColor = feature.joinColor || feature.color;
359
+
360
+ subFeatures.forEach(
361
+ (subFeature) => {
362
+ if (!subFeature.fake) {
363
+ this.drawFeature({ ...clonedFeature, ...subFeature.position[scale], ...subFeature }, featureContext, labelContext, scale);
364
+ }
343
365
 
344
- if (subFeatures[i].position[scale].join && subFeatures[i].position[scale].join.width > 0) {
345
- this.drawSubFeatureJoin($.extend({ color: joinColor }, subFeatures[i].position[scale].join), featureContext);
366
+ if (subFeature.position[scale].join && subFeature.position[scale].join.width > 0) {
367
+ this.drawSubFeatureJoin({ color: joinColor, ...subFeature.position[scale].join }, featureContext);
368
+ }
346
369
  }
347
- }
370
+ );
348
371
  },
349
372
 
350
373
  drawLabel: function (feature, context, scale) {
351
- var original = feature.untruncated;
352
- var width = (original || feature).width;
374
+ const original = feature.untruncated;
375
+ const width = (original || feature).width;
353
376
 
354
377
  if (this.labels === 'overlay' && feature.labelWidth >= Math.floor(width)) {
355
378
  return;
@@ -363,14 +386,17 @@ Genoverse.Track.View = Base.extend({
363
386
  feature.label = [ feature.label ];
364
387
  }
365
388
 
366
- var x = (original || feature).x;
367
- var n = this.repeatLabels ? Math.ceil((width - Math.max(scale, 1) - (this.labels === 'overlay' ? feature.labelWidth : 0)) / this.width) || 1 : 1;
368
- var spacing = width / n;
369
- var label, start, j, y, currentY, h;
389
+ const x = (original || feature).x;
390
+
391
+ let n = this.repeatLabels ? Math.ceil((width - Math.max(scale, 1) - (this.labels === 'overlay' ? feature.labelWidth : 0)) / this.width) || 1 : 1;
392
+ let spacing = width / n;
393
+ let label;
394
+ let y;
395
+ let h;
370
396
 
371
397
  if (this.repeatLabels && (scale > 1 || this.labels !== 'overlay')) { // Ensure there's always a label in each image
372
398
  spacing = this.browser.length * scale;
373
- n = Math.ceil(width / spacing);
399
+ n = Math.ceil(width / spacing);
374
400
  }
375
401
 
376
402
  if (!feature.labelColor) {
@@ -389,35 +415,39 @@ Genoverse.Track.View = Base.extend({
389
415
  h = this.fontHeight + 2;
390
416
  }
391
417
 
392
- var i = context.textAlign === 'center' ? 0.5 : 0;
393
- var offset = feature.labelWidth * i;
418
+ let i = context.textAlign === 'center' ? 0.5 : 0;
419
+
420
+ const offset = feature.labelWidth * i;
394
421
 
395
422
  if (n > 1) {
396
423
  i += Math.max(Math.floor(-(feature.labelWidth + x) / spacing), 0);
397
424
  }
398
425
 
399
426
  for (; i < n; i++) {
400
- start = x + (i * spacing);
427
+ const start = x + (i * spacing);
401
428
 
402
429
  if (start + feature.labelWidth >= 0) {
403
430
  if ((start - offset > this.width) || (i >= 1 && start + feature.labelWidth > feature.position[scale].X + feature.position[scale].width)) {
404
431
  break;
405
432
  }
406
433
 
407
- for (j = 0; j < label.length; j++) {
408
- currentY = y + (j * h);
434
+ label.forEach(
435
+ (line, j) => {
436
+ const currentY = y + (j * h);
409
437
 
410
- if (context.labelPositions && context.labelPositions.search({ x: start, y: currentY, w: feature.labelWidth, h: h }).length) {
411
- feature.position[scale].label.visible = false;
412
- continue;
413
- }
438
+ if (context.labelPositions && context.labelPositions.search({ x: start, y: currentY, w: feature.labelWidth, h: h }).length) {
439
+ feature.position[scale].label.visible = false;
414
440
 
415
- context.fillText(label[j], start, currentY);
441
+ return;
442
+ }
443
+
444
+ context.fillText(line, start, currentY);
416
445
 
417
- if (context.labelPositions) {
418
- context.labelPositions.insert({ x: start, y: currentY, w: feature.labelWidth, h: h }, label[j]);
446
+ if (context.labelPositions) {
447
+ context.labelPositions.insert({ x: start, y: currentY, w: feature.labelWidth, h: h }, line);
448
+ }
419
449
  }
420
- }
450
+ );
421
451
  }
422
452
  }
423
453
  },
@@ -432,23 +462,24 @@ Genoverse.Track.View = Base.extend({
432
462
 
433
463
  // Method to lighten a color by an amount, adapted from https://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color-or-rgb-and-blend-colors
434
464
  shadeColor: function (color, percent) {
435
- var f = parseInt(color.slice(1), 16);
436
- var R = f >> 16;
437
- var G = (f >> 8) & 0x00FF;
438
- var B = f & 0x0000FF;
465
+ const f = parseInt(color.slice(1), 16);
466
+ const R = f >> 16;
467
+ const G = (f >> 8) & 0x00FF;
468
+ const B = f & 0x0000FF;
439
469
 
440
- return '#' + (
470
+ return `#${(
441
471
  0x1000000 +
442
472
  (Math.round((255 - R) * percent) + R) * 0x10000 +
443
473
  (Math.round((255 - G) * percent) + G) * 0x100 +
444
474
  (Math.round((255 - B) * percent) + B)
445
- ).toString(16).slice(1);
475
+ ).toString(16).slice(1)}`;
446
476
  },
447
477
 
448
478
  // truncate features - make the features start at 1px outside the canvas to ensure no lines are drawn at the borders incorrectly
449
479
  truncateForDrawing: function (feature) {
450
- var start = Math.min(Math.max(feature.x, -1), this.width + 1);
451
- var width = feature.x - start + feature.width;
480
+ const start = Math.min(Math.max(feature.x, -1), this.width + 1);
481
+
482
+ let width = feature.x - start + feature.width;
452
483
 
453
484
  if (width + start > this.width) {
454
485
  width = this.width - start + 1;
@@ -460,13 +491,13 @@ Genoverse.Track.View = Base.extend({
460
491
  },
461
492
 
462
493
  drawSubFeatureJoin: function (join, context) {
463
- var coords = this.truncateSubFeatureJoinForDrawing(join);
494
+ const coords = this.truncateSubFeatureJoinForDrawing(join);
464
495
 
465
496
  if (!coords) {
466
497
  return;
467
498
  }
468
499
 
469
- var lineWidth = context.lineWidth;
500
+ const lineWidth = context.lineWidth;
470
501
 
471
502
  context.strokeStyle = join.color;
472
503
  context.lineWidth = this.subFeatureJoinLineWidth;
@@ -477,13 +508,16 @@ Genoverse.Track.View = Base.extend({
477
508
  switch (this.subFeatureJoinStyle) {
478
509
  case 'line':
479
510
  context.lineTo(coords.x3, coords.y1);
511
+
480
512
  break;
481
513
  case 'peak':
482
514
  context.lineTo(coords.x2, coords.y2);
483
515
  context.lineTo(coords.x3, coords.y3);
516
+
484
517
  break;
485
518
  case 'curve':
486
519
  context.quadraticCurveTo(coords.x2, coords.y2, coords.x3, coords.y3);
520
+
487
521
  break;
488
522
  default: break;
489
523
  }
@@ -494,30 +528,33 @@ Genoverse.Track.View = Base.extend({
494
528
  },
495
529
 
496
530
  truncateSubFeatureJoinForDrawing: function (coords) {
497
- var y1 = coords.y; // y coord of the ends of the line (half way down the exon box)
498
- var y3 = y1;
531
+ let y1 = coords.y; // y coord of the ends of the line (half way down the exon box)
532
+ let y3 = y1;
499
533
 
500
534
  if (this.subFeatureJoinStyle === 'line') {
501
535
  this.truncateForDrawing(coords);
502
536
  y1 += 0.5; // Sharpen line
503
537
  }
504
538
 
505
- var x1 = coords.x; // x coord of the right edge of the first exon
506
- var x3 = coords.x + coords.width; // x coord of the left edge of the second exon
539
+ let x1 = coords.x; // x coord of the right edge of the first exon
540
+ let x3 = coords.x + coords.width; // x coord of the left edge of the second exon
507
541
 
508
542
  // Skip if completely outside the image's region
509
543
  if (x3 < 0 || x1 > this.width) {
510
544
  return false;
511
545
  }
512
546
 
513
- var x2, y2, xMid, yScale;
547
+ let x2;
548
+ let y2;
514
549
 
515
550
  // Truncate the coordinates of the line being drawn, so it is inside the image's region
516
551
  if (this.subFeatureJoinStyle === 'peak') {
517
- xMid = (x1 + x3) / 2;
518
- x2 = xMid; // x coord of the peak of the peak/curve
519
- y2 = coords.y + coords.height; // y coord of the peak of the peak/curve (level with the top (forward strand) or bottom (reverse strand) of the exon box)
520
- yScale = (y2 - y1) / (xMid - x1); // Scale factor for recalculating coords if points lie outside the image region
552
+ const xMid = (x1 + x3) / 2;
553
+
554
+ x2 = xMid; // x coord of the peak of the peak/curve
555
+ y2 = coords.y + coords.height; // y coord of the peak of the peak/curve (level with the top (forward strand) or bottom (reverse strand) of the exon box)
556
+
557
+ const yScale = (y2 - y1) / (xMid - x1); // Scale factor for recalculating coords if points lie outside the image region
521
558
 
522
559
  if (xMid < 0) {
523
560
  y2 = coords.y + (yScale * x3);
@@ -543,24 +580,28 @@ Genoverse.Track.View = Base.extend({
543
580
  }
544
581
 
545
582
  return {
546
- x1 : x1,
547
- y1 : y1,
548
- x2 : x2,
549
- y2 : y2,
550
- x3 : x3,
551
- y3 : y3
583
+ x1,
584
+ y1,
585
+ x2,
586
+ y2,
587
+ x3,
588
+ y3,
552
589
  };
553
590
  },
554
591
 
555
592
  formatLabel: function (label) {
556
- var power = Math.floor((label.toString().length - 1) / 3);
557
- var unit = this.labelUnits[power];
593
+ const power = Math.floor((label.toString().length - 1) / 3);
594
+ const unit = this.labelUnits[power];
558
595
 
559
- label /= Math.pow(10, power * 3);
596
+ label /= 10 ** (power * 3);
560
597
 
561
- return Math.floor(label) + (unit === 'bp' ? '' : '.' + (label.toString().split('.')[1] || '').concat('00').substring(0, 2)) + ' ' + unit;
598
+ return `${Math.floor(label)}${(unit === 'bp' ? '' : `.${(label.toString().split('.')[1] || '').concat('00').substring(0, 2)}`)} ${unit}`;
562
599
  },
563
600
 
564
- drawBackground : $.noop,
565
- decorateFeature : $.noop // decoration for the features
601
+ drawBackground : () => {},
602
+ decorateFeature : () => {}, // decoration for the features
603
+
604
+ destroy: function () {
605
+ delete this.scaleSettings;
606
+ },
566
607
  });