higlass 1.13.0 → 1.13.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.
@@ -1,3 +1,4 @@
1
+ // @ts-check
1
2
  import { formatPrefix, precisionPrefix } from 'd3-format';
2
3
  import slugid from 'slugid';
3
4
 
@@ -7,14 +8,18 @@ import { colorToHex } from './utils';
7
8
 
8
9
  // Configs
9
10
  import { GLOBALS } from './configs';
11
+ import {
12
+ isResolutionsTilesetInfo,
13
+ isLegacyTilesetInfo,
14
+ } from './utils/type-guards';
10
15
 
11
16
  /**
12
17
  * Format a resolution relative to the highest possible resolution.
13
18
  *
14
19
  * The highest possible resolution determines the granularity of the
15
20
  * formatting (e.g. 20K vs 20000)
16
- * @param {int} resolution The resolution to format (e.g. 30000)
17
- * @param {int} maxResolutionSize The maximum possible resolution (e.g. 1000)
21
+ * @param {number} resolution The resolution to format (e.g. 30000)
22
+ * @param {number} maxResolutionSize The maximum possible resolution (e.g. 1000)
18
23
  *
19
24
  * @returns {string} A formatted resolution string (e.g. "30K")
20
25
  */
@@ -30,11 +35,10 @@ function formatResolutionText(resolution, maxResolutionSize) {
30
35
  * Get a text description of a resolution based on a zoom level
31
36
  * and a list of resolutions
32
37
  *
33
- * @param {list} resolutions: A list of resolutions (e.g. [1000,2000,3000])
34
- * @param {int} zoomLevel: The current zoom level (e.g. 4)
38
+ * @param {Array<number>} resolutions: A list of resolutions (e.g. [1000,2000,3000])
39
+ * @param {number} zoomLevel: The current zoom level (e.g. 4)
35
40
  *
36
- * @returns {string} A formatted string representation of the zoom level
37
- * (e.g. "30K")
41
+ * @returns {string} A formatted string representation of the zoom level (e.g. "30K")
38
42
  */
39
43
  function getResolutionBasedResolutionText(resolutions, zoomLevel) {
40
44
  const sortedResolutions = resolutions.map((x) => +x).sort((a, b) => b - a);
@@ -46,18 +50,14 @@ function getResolutionBasedResolutionText(resolutions, zoomLevel) {
46
50
 
47
51
  /**
48
52
  * Get a text description of the resolution based on the zoom level
49
- * max width of the dataset, the bins per dimension and the maximum
50
- * zoom.
53
+ * max width of the dataset, the bins per dimension and the maximum zoom.
51
54
  *
52
- * @param {int} zoomLevel The current zoomLevel (e.g. 0)
53
- * @param {int} max_width The max width
54
- * (e.g. 2 ** maxZoom * highestResolution * binsPerDimension)
55
- * @param {int} bins_per_dimension The number of bins per tile dimension
56
- * (e.g. 256)
57
- * @param {int} maxZoom The maximum zoom level for this tileset
55
+ * @param {number} zoomLevel - The current zoomLevel (e.g. 0)
56
+ * @param {number} maxWidth - The max width (e.g. 2 ** maxZoom * highestResolution * binsPerDimension)
57
+ * @param {number} binsPerDimension - The number of bins per tile dimension (e.g. 256)
58
+ * @param {number} maxZoom - The maximum zoom level for this tileset
58
59
  *
59
- * @returns {string} A formatted string representation of the zoom level
60
- * (e.g. "30K")
60
+ * @returns {string} A formatted string representation of the zoom level (e.g. "30K")
61
61
  */
62
62
  function getWidthBasedResolutionText(
63
63
  zoomLevel,
@@ -84,14 +84,35 @@ function getWidthBasedResolutionText(
84
84
  return '';
85
85
  }
86
86
 
87
+ /**
88
+ * @typedef PixiTrackOptions
89
+ * @property {string} labelPosition - If the label is to be drawn, where should it be drawn?
90
+ * @property {string} labelText - What should be drawn in the label.
91
+ * If either labelPosition or labelText are false, no label will be drawn.
92
+ * @property {number=} trackBorderWidth
93
+ * @property {string=} trackBorderColor
94
+ * @property {string=} backgroundColor
95
+ * @property {string=} labelColor
96
+ * @property {string=} lineStrokeColor
97
+ * @property {string=} barFillColor
98
+ * @property {string=} name
99
+ * @property {number=} labelTextOpacity
100
+ * @property {string=} labelBackgroundColor
101
+ * @property {number=} labelLeftMargin
102
+ * @property {number=} labelRightMargin
103
+ * @property {number=} labelTopMargin
104
+ * @property {number=} labelBottomMargin
105
+ * @property {number=} labelBackgroundOpacity
106
+ * @property {boolean=} labelShowAssembly
107
+ * @property {boolean=} labelShowResolution
108
+ * @property {string=} dataTransform
109
+ */
110
+
111
+ /** @extends {Track<PixiTrackOptions>} */
87
112
  class PixiTrack extends Track {
88
113
  /**
89
- * @param scene: A PIXI.js scene to draw everything to.
90
- * @param options: A set of options that describe how this track is rendered.
91
- this.pMain.position.x = this.position[0];
92
- * - labelPosition: If the label is to be drawn, where should it be drawn?
93
- * - labelText: What should be drawn in the label. If either labelPosition
94
- * or labelText are false, no label will be drawn.
114
+ * @param {import('./Track').ExtendedTrackContext<{ scene: import('pixi.js').Container}>} context - Includes the PIXI.js scene to draw to.
115
+ * @param {PixiTrackOptions} options - The options for this track.
95
116
  */
96
117
  constructor(context, options) {
97
118
  super(context, options);
@@ -99,27 +120,39 @@ class PixiTrack extends Track {
99
120
 
100
121
  // the PIXI drawing areas
101
122
  // pMain will have transforms applied to it as users scroll to and fro
123
+ /** @type {import('pixi.js').Container} */
102
124
  this.scene = scene;
103
125
 
104
126
  // this option is used to temporarily prevent drawing so that
105
127
  // updates can be batched (e.g. zoomed and options changed)
128
+ /** @type {boolean} */
106
129
  this.delayDrawing = false;
107
130
 
131
+ /** @type {import('pixi.js').Graphics} */
108
132
  this.pBase = new GLOBALS.PIXI.Graphics();
109
-
133
+ /** @type {import('pixi.js').Graphics} */
110
134
  this.pMasked = new GLOBALS.PIXI.Graphics();
135
+ /** @type {import('pixi.js').Graphics} */
111
136
  this.pMask = new GLOBALS.PIXI.Graphics();
137
+ /** @type {import('pixi.js').Graphics} */
112
138
  this.pMain = new GLOBALS.PIXI.Graphics();
113
139
 
114
140
  // for drawing the track label (often its name)
141
+ /** @type {import('pixi.js').Graphics} */
115
142
  this.pBorder = new GLOBALS.PIXI.Graphics();
143
+ /** @type {import('pixi.js').Graphics} */
116
144
  this.pBackground = new GLOBALS.PIXI.Graphics();
145
+ /** @type {import('pixi.js').Graphics} */
117
146
  this.pForeground = new GLOBALS.PIXI.Graphics();
147
+ /** @type {import('pixi.js').Graphics} */
118
148
  this.pLabel = new GLOBALS.PIXI.Graphics();
149
+ /** @type {import('pixi.js').Graphics} */
119
150
  this.pMobile = new GLOBALS.PIXI.Graphics();
151
+ /** @type {import('pixi.js').Graphics} */
120
152
  this.pAxis = new GLOBALS.PIXI.Graphics();
121
153
 
122
154
  // for drawing information on mouseover events
155
+ /** @type {import('pixi.js').Graphics} */
123
156
  this.pMouseOver = new GLOBALS.PIXI.Graphics();
124
157
 
125
158
  this.scene.addChild(this.pBase);
@@ -138,20 +171,28 @@ class PixiTrack extends Track {
138
171
 
139
172
  this.pMasked.mask = this.pMask;
140
173
 
174
+ /** @type {string} */
141
175
  this.prevOptions = '';
142
176
 
143
177
  // pMobile will be a graphics object that is moved around
144
178
  // tracks that wish to use it will replace this.pMain with it
145
179
 
180
+ /** @type {PixiTrackOptions} */
146
181
  this.options = Object.assign(this.options, options);
147
182
 
183
+ /** @type {string} */
148
184
  const labelTextText = this.getName();
149
-
185
+ /** @type {string} */
150
186
  this.labelTextFontFamily = 'Arial';
187
+ /** @type {number} */
151
188
  this.labelTextFontSize = 12;
152
- // Used to avoid label/colormap clashes
189
+ /**
190
+ * Used to avoid label/colormap clashes
191
+ * @type {number}
192
+ */
153
193
  this.labelXOffset = 0;
154
194
 
195
+ /** @type {import('pixi.js').Text} */
155
196
  this.labelText = new GLOBALS.PIXI.Text(labelTextText, {
156
197
  fontSize: `${this.labelTextFontSize}px`,
157
198
  fontFamily: this.labelTextFontFamily,
@@ -159,6 +200,7 @@ class PixiTrack extends Track {
159
200
  });
160
201
  this.pLabel.addChild(this.labelText);
161
202
 
203
+ /** @type {import('pixi.js').Text} */
162
204
  this.errorText = new GLOBALS.PIXI.Text('', {
163
205
  fontSize: '12px',
164
206
  fontFamily: 'Arial',
@@ -167,12 +209,19 @@ class PixiTrack extends Track {
167
209
  this.errorText.anchor.x = 0.5;
168
210
  this.errorText.anchor.y = 0.5;
169
211
  this.pLabel.addChild(this.errorText);
212
+ /** @type {string} */
213
+ this.errorTextText = '';
214
+ /** @type {boolean} */
215
+ this.flipText = false;
216
+ /** @type {import('./types').TilesetInfo | undefined} */
217
+ this.tilesetInfo = undefined;
170
218
  }
171
219
 
172
220
  setLabelText() {
173
221
  // will be drawn in draw() anyway
174
222
  }
175
223
 
224
+ /** @param {[number, number]} newPosition */
176
225
  setPosition(newPosition) {
177
226
  this.position = newPosition;
178
227
 
@@ -183,6 +232,7 @@ class PixiTrack extends Track {
183
232
  this.setForeground();
184
233
  }
185
234
 
235
+ /** @param {[number, number]} newDimensions */
186
236
  setDimensions(newDimensions) {
187
237
  super.setDimensions(newDimensions);
188
238
 
@@ -193,6 +243,10 @@ class PixiTrack extends Track {
193
243
  this.setForeground();
194
244
  }
195
245
 
246
+ /**
247
+ * @param {[number, number]} position
248
+ * @param {[number, number]} dimensions
249
+ */
196
250
  setMask(position, dimensions) {
197
251
  this.pMask.clear();
198
252
  this.pMask.beginFill();
@@ -320,6 +374,8 @@ class PixiTrack extends Track {
320
374
 
321
375
  graphics.clear();
322
376
 
377
+ // TODO(Trevor): I don't think this can ever be true. Options are always defined,
378
+ // and options.labelPosition can't be defined if this.options is undefined.
323
379
  if (
324
380
  !this.options ||
325
381
  !this.options.labelPosition ||
@@ -330,11 +386,11 @@ class PixiTrack extends Track {
330
386
  return;
331
387
  }
332
388
 
389
+ const { labelBackgroundColor = 'white', labelBackgroundOpacity = 0.5 } =
390
+ this.options;
333
391
  graphics.beginFill(
334
- colorToHex(this.options.labelBackgroundColor || 'white'),
335
- +this.options.labelBackgroundOpacity >= 0
336
- ? +this.options.labelBackgroundOpacity
337
- : 0.5,
392
+ colorToHex(labelBackgroundColor),
393
+ +labelBackgroundOpacity,
338
394
  );
339
395
 
340
396
  const fontColor = colorToHex(this.getLabelColor());
@@ -356,8 +412,7 @@ class PixiTrack extends Track {
356
412
 
357
413
  if (
358
414
  this.options.labelShowResolution &&
359
- this.tilesetInfo &&
360
- this.tilesetInfo.max_width &&
415
+ isLegacyTilesetInfo(this.tilesetInfo) &&
361
416
  this.tilesetInfo.bins_per_dimension
362
417
  ) {
363
418
  const formattedResolution = getWidthBasedResolutionText(
@@ -370,8 +425,7 @@ class PixiTrack extends Track {
370
425
  labelTextText += `\n[Current data resolution: ${formattedResolution}]`;
371
426
  } else if (
372
427
  this.options.labelShowResolution &&
373
- this.tilesetInfo &&
374
- this.tilesetInfo.resolutions
428
+ isResolutionsTilesetInfo(this.tilesetInfo)
375
429
  ) {
376
430
  const formattedResolution = getResolutionBasedResolutionText(
377
431
  this.tilesetInfo.resolutions,
@@ -418,10 +472,12 @@ class PixiTrack extends Track {
418
472
  this.labelText.scale.x = -1;
419
473
  }
420
474
 
421
- const labelLeftMargin = +this.options.labelLeftMargin || 0;
422
- const labelRightMargin = +this.options.labelRightMargin || 0;
423
- const labelTopMargin = +this.options.labelTopMargin || 0;
424
- const labelBottomMargin = +this.options.labelBottomMargin || 0;
475
+ const {
476
+ labelLeftMargin = 0,
477
+ labelRightMargin = 0,
478
+ labelTopMargin = 0,
479
+ labelBottomMargin = 0,
480
+ } = this.options;
425
481
 
426
482
  if (this.options.labelPosition === 'topLeft') {
427
483
  this.labelText.x = this.position[0] + labelLeftMargin + this.labelXOffset;
@@ -575,6 +631,7 @@ class PixiTrack extends Track {
575
631
  }
576
632
  }
577
633
 
634
+ /** @param {PixiTrackOptions} options */
578
635
  rerender(options) {
579
636
  this.options = options;
580
637
 
@@ -598,8 +655,8 @@ class PixiTrack extends Track {
598
655
  /**
599
656
  * Export an SVG representation of this track
600
657
  *
601
- * @returns {Array} The two returned DOM nodes are both SVG
602
- * elements [base,track]. Base is a parent which contains track as a
658
+ * @returns {[HTMLElement, HTMLElement]} The two returned DOM nodes are both SVG
659
+ * elements [base, track]. Base is a parent which contains track as a
603
660
  * child. Track is clipped with a clipping rectangle contained in base.
604
661
  *
605
662
  */
@@ -693,15 +750,15 @@ class PixiTrack extends Track {
693
750
  this.options.labelPosition === 'topRight'
694
751
  ) {
695
752
  const dy = ddy + (i + 1) * (this.labelTextFontSize + 2);
696
- text.setAttribute('dy', dy);
753
+ text.setAttribute('dy', String(dy));
697
754
  } else if (
698
755
  this.options.labelPosition === 'bottomLeft' ||
699
756
  this.options.labelPosition === 'bottomRight'
700
757
  ) {
701
- text.setAttribute('dy', ddy + i * (this.labelTextFontSize + 2));
758
+ text.setAttribute('dy', String(ddy + i * (this.labelTextFontSize + 2)));
702
759
  }
703
760
 
704
- text.setAttribute('fill', this.options.labelColor);
761
+ text.setAttribute('fill', this.options.labelColor ?? '');
705
762
 
706
763
  if (this.labelText.anchor.x === 0.5) {
707
764
  text.setAttribute('text-anchor', 'middle');
@@ -721,6 +778,13 @@ class PixiTrack extends Track {
721
778
  // contents
722
779
  return [gBase, gTrack];
723
780
  }
781
+
782
+ /**
783
+ * @returns {number}
784
+ */
785
+ calculateZoomLevel() {
786
+ throw new Error('Must be implemented by subclass');
787
+ }
724
788
  }
725
789
 
726
790
  export default PixiTrack;
@@ -1,41 +1,62 @@
1
+ // @ts-check
1
2
  import { scaleLinear } from 'd3-scale';
2
3
  import { fake as fakePubSub } from './hocs/with-pub-sub';
3
4
 
4
5
  // Services
5
6
  import { isWithin } from './utils';
6
7
 
8
+ /**
9
+ * @typedef TrackContext
10
+ * @property {string} id - The track ID.
11
+ * @property {import('pub-sub-es').PubSub & { __fake__?: boolean }} [pubSub] - The pub-sub channel.
12
+ * @property {() => import('./types').Theme} [getTheme] - A function that returns the current theme.
13
+ */
14
+
15
+ /**
16
+ * @template T
17
+ * @typedef {T & TrackContext} ExtendedTrackContext
18
+ */
19
+
20
+ /** @template Options */
7
21
  class Track {
8
- constructor(context) {
22
+ /**
23
+ * @param {TrackContext} context
24
+ * @param {Options} options
25
+ */
26
+ constructor(context, options) {
9
27
  this.context = context;
10
28
 
11
29
  const { id, pubSub, getTheme } = context;
12
- if (pubSub) {
13
- this.pubSub = pubSub;
14
- } else {
15
- this.pubSub = fakePubSub;
16
- }
30
+ /** @type {import('pub-sub-es').PubSub} */
31
+ this.pubSub = pubSub ?? fakePubSub;
17
32
 
33
+ /** @type {string} */
18
34
  this.id = id;
35
+ /** @type {import('./types').Scale} */
19
36
  this._xScale = scaleLinear();
37
+ /** @type {import('./types').Scale} */
20
38
  this._yScale = scaleLinear();
21
39
 
22
40
  // reference scales used for tracks that can translate and scale
23
41
  // their graphics
24
42
  // They will draw their graphics on the reference scales and then translate
25
43
  // and pan them as needed
44
+ /** @type {import('./types').Scale} */
26
45
  this._refXScale = scaleLinear();
46
+ /** @type {import('./types').Scale} */
27
47
  this._refYScale = scaleLinear();
28
48
 
49
+ /** @type {[number, number]} */
29
50
  this.position = [0, 0];
51
+ /** @type {[number, number]} */
30
52
  this.dimensions = [1, 1];
31
- this.options = {};
53
+ /** @type {Options} */
54
+ this.options = options;
55
+ /** @type {Array<import('pub-sub-es').Subscription>} */
32
56
  this.pubSubs = [];
33
57
 
34
- if (getTheme) {
35
- this.getTheme = getTheme;
36
- } else {
37
- this.getTheme = () => {};
38
- }
58
+ /** @type {() => (import('./types').Theme | undefined)} */
59
+ this.getTheme = getTheme ?? (() => undefined);
39
60
 
40
61
  this.pubSubs.push(
41
62
  this.pubSub.subscribe(
@@ -43,14 +64,16 @@ class Track {
43
64
  this.defaultMouseMoveHandler.bind(this),
44
65
  ),
45
66
  );
67
+
68
+ this.isLeftModified = false;
46
69
  }
47
70
 
48
71
  /**
49
72
  * Check if a 2d location (x, y) is within the bounds of this track.
50
73
  *
51
- * @param {Number} x X position to be tested.
52
- * @param {Number} y Y position to be tested.
53
- * @return {Boolean} If `true` location is within the track.
74
+ * @param {number} x - X position to be tested.
75
+ * @param {number} y - Y position to be tested.
76
+ * @return {boolean} If `true` location is within the track.
54
77
  */
55
78
  isWithin(x, y) {
56
79
  let xx = x;
@@ -75,14 +98,26 @@ class Track {
75
98
  );
76
99
  }
77
100
 
101
+ /**
102
+ * Get a property from the track.
103
+ * @template {keyof this} T
104
+ * @param {T} prop - The property to get.
105
+ * @return {() => this[T]}
106
+ */
78
107
  getProp(prop) {
79
108
  return () => this[prop];
80
109
  }
81
110
 
82
111
  getData() {}
83
112
 
84
- /** Capture click events. x and y are relative to the track
85
- * position */
113
+ /**
114
+ * Capture click events. x and y are relative to the track position
115
+ * @template T
116
+ * @param {number} x - X position of the click event.
117
+ * @param {number} y - Y position of the click event.
118
+ * @param {T} evt - The event.
119
+ * @return {{ type: 'generic', event: T, payload: null }}
120
+ */
86
121
  click(x, y, evt) {
87
122
  return {
88
123
  type: 'generic',
@@ -94,10 +129,12 @@ class Track {
94
129
  /** There was a click event outside the track * */
95
130
  clickOutside() {}
96
131
 
132
+ /** @returns {[number, number]} */
97
133
  getDimensions() {
98
134
  return this.dimensions;
99
135
  }
100
136
 
137
+ /** @param {[number, number]} newDimensions */
101
138
  setDimensions(newDimensions) {
102
139
  this.dimensions = newDimensions;
103
140
 
@@ -105,82 +142,136 @@ class Track {
105
142
  this._yScale.range([0, this.dimensions[1]]);
106
143
  }
107
144
 
145
+ /**
146
+ * @overload
147
+ * @return {import('./types').Scale}
148
+ */
149
+ /**
150
+ * @overload
151
+ * @param {import('./types').Scale} scale
152
+ * @return {this}
153
+ */
108
154
  /**
109
155
  * Either get or set the reference xScale
156
+ *
157
+ * @param {import('./types').Scale=} scale
158
+ * @return {import('./types').Scale | this}
110
159
  */
111
- refXScale(_) {
112
- if (!arguments.length) return this._refXScale;
113
-
114
- this._refXScale = _;
115
-
160
+ refXScale(scale) {
161
+ if (!scale) return this._refXScale;
162
+ this._refXScale = scale;
116
163
  return this;
117
164
  }
118
165
 
166
+ /**
167
+ * @overload
168
+ * @return {import('./types').Scale}
169
+ */
170
+ /**
171
+ * @overload
172
+ * @param {import('./types').Scale} scale
173
+ * @return {this}
174
+ */
119
175
  /**
120
176
  * Either get or set the reference yScale
177
+ *
178
+ * @param {import('./types').Scale=} scale
179
+ * @return {import('./types').Scale | this}
121
180
  */
122
- refYScale(_) {
123
- if (!arguments.length) return this._refYScale;
124
-
125
- this._refYScale = _;
126
-
181
+ refYScale(scale) {
182
+ if (!scale) return this._refYScale;
183
+ this._refYScale = scale;
127
184
  return this;
128
185
  }
129
186
 
187
+ /**
188
+ * @overload
189
+ * @return {import('./types').Scale}
190
+ */
191
+ /**
192
+ * @overload
193
+ * @param {import('./types').Scale} scale
194
+ * @return {this}
195
+ */
130
196
  /**
131
197
  * Either get or set the xScale
198
+ *
199
+ * @param {import('./types').Scale=} scale
200
+ * @return {import('./types').Scale | this}
132
201
  */
133
- xScale(_) {
134
- if (!arguments.length) return this._xScale;
135
-
136
- this._xScale = _;
137
-
202
+ xScale(scale) {
203
+ if (!scale) return this._xScale;
204
+ this._xScale = scale;
138
205
  return this;
139
206
  }
140
207
 
208
+ /**
209
+ * @overload
210
+ * @return {import('./types').Scale}
211
+ */
212
+ /**
213
+ * @overload
214
+ * @param {import('./types').Scale} scale
215
+ * @return {this}
216
+ */
141
217
  /**
142
218
  * Either get or set the yScale
219
+ *
220
+ * @param {import('./types').Scale=} scale
221
+ * @return {import('./types').Scale | this}
143
222
  */
144
- yScale(_) {
145
- if (!arguments.length) {
146
- return this._yScale;
147
- }
148
-
149
- this._yScale = _;
150
-
223
+ yScale(scale) {
224
+ if (!scale) return this._yScale;
225
+ this._yScale = scale;
151
226
  return this;
152
227
  }
153
228
 
229
+ /**
230
+ * @param {import('./types').Scale} newXScale
231
+ * @param {import('./types').Scale} newYScale
232
+ * @returns {void}
233
+ */
154
234
  zoomed(newXScale, newYScale) {
155
235
  this.xScale(newXScale);
156
236
  this.yScale(newYScale);
157
237
  }
158
238
 
239
+ /**
240
+ * @param {import('./types').Scale} refXScale
241
+ * @param {import('./types').Scale} refYScale
242
+ * @returns {void}
243
+ */
159
244
  refScalesChanged(refXScale, refYScale) {
160
245
  this._refXScale = refXScale;
161
246
  this._refYScale = refYScale;
162
247
  }
163
248
 
249
+ /** @returns {void} */
164
250
  draw() {}
165
251
 
252
+ /** @returns {[number, number]} */
166
253
  getPosition() {
167
254
  return this.position;
168
255
  }
169
256
 
257
+ /**
258
+ * @param {[number, number]} newPosition
259
+ * @returns {void}
260
+ */
170
261
  setPosition(newPosition) {
171
262
  this.position = newPosition;
172
263
  }
173
264
 
174
- /*
265
+ /**
175
266
  * A blank handler for MouseMove / Zoom events. Should be overriden
176
267
  * by individual tracks to provide
177
268
  *
178
- * @param {obj} evt:
179
- *
180
- * @returns nothing
269
+ * @param {{}} evt
270
+ * @returns {void}
181
271
  */
182
272
  defaultMouseMoveHandler(evt) {}
183
273
 
274
+ /** @returns {void} */
184
275
  remove() {
185
276
  // Clear all pubSub subscriptions
186
277
  this.pubSubs.forEach((subscription) =>
@@ -189,19 +280,36 @@ class Track {
189
280
  this.pubSubs = [];
190
281
  }
191
282
 
192
- rerender() {}
283
+ /**
284
+ * @param {Options} options
285
+ * @returns {void}
286
+ */
287
+ rerender(options) {}
193
288
 
194
- /*
289
+ /**
195
290
  * This function is for seeing whether this track should respond
196
291
  * to events at this mouse position. The difference to `isWithin()` is that it
197
292
  * can be overwritten if a track is inactive for example.
293
+ *
294
+ * @param {number} x - X position to be tested.
295
+ * @param {number} y - Y position to be tested.
296
+ * @returns {boolean}
198
297
  */
199
298
  respondsToPosition(x, y) {
200
299
  return this.isWithin(x, y);
201
300
  }
202
301
 
302
+ /**
303
+ * @param {number} trackY
304
+ * @param {number} kMultiplier
305
+ * @returns {void}
306
+ */
203
307
  zoomedY(trackY, kMultiplier) {}
204
308
 
309
+ /**
310
+ * @param {number} dY
311
+ * @returns {void}
312
+ */
205
313
  movedY(dY) {}
206
314
  }
207
315