@checksub_team/peaks_timeline 1.8.2 → 1.9.1-beta.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checksub_team/peaks_timeline",
3
- "version": "1.8.2",
3
+ "version": "1.9.1-beta.1",
4
4
  "description": "JavaScript UI component for displaying audio waveforms",
5
5
  "main": "./peaks.js",
6
6
  "types": "./peaks.js.d.ts",
package/peaks.js CHANGED
@@ -15064,6 +15064,23 @@ module.exports = function (Konva, Utils) {
15064
15064
  }
15065
15065
  return newXs;
15066
15066
  };
15067
+ Line.prototype.getSourcesAfter = function (time) {
15068
+ const sources = [];
15069
+ var currentId = this._firstSourceId;
15070
+ while (currentId) {
15071
+ var lineSource = this._sources[currentId];
15072
+ if (lineSource.source.startTime >= time) {
15073
+ while (currentId) {
15074
+ lineSource = this._sources[currentId];
15075
+ sources.push(lineSource.source);
15076
+ currentId = lineSource.nextSourceId;
15077
+ }
15078
+ break;
15079
+ }
15080
+ currentId = lineSource.nextSourceId;
15081
+ }
15082
+ return sources;
15083
+ };
15067
15084
  Line.prototype.updatePosition = function (pos) {
15068
15085
  for (var sourceId in this._sources) {
15069
15086
  if (Utils.objectHasProperty(this._sources, sourceId)) {
@@ -15210,6 +15227,9 @@ module.exports = function (SegmentsGroup, Line, LineIndicator, Utils) {
15210
15227
  }
15211
15228
  return positions;
15212
15229
  };
15230
+ Lines.prototype.getSourcesOnLineAfter = function (lineId, time) {
15231
+ return this._linesByPosition[lineId].getSourcesAfter(time);
15232
+ };
15213
15233
  Lines.prototype.getSegmentsGroups = function () {
15214
15234
  return this._segmentsGroups;
15215
15235
  };
@@ -15613,8 +15633,11 @@ module.exports = function (Colors, EventEmitter, TimelineSegments, TimelineSourc
15613
15633
  Peaks.prototype.selectSourceById = function (sourceId) {
15614
15634
  return this.view.selectSourceById(sourceId);
15615
15635
  };
15616
- Peaks.prototype.deselectSource = function () {
15617
- return this.view.deselectElement();
15636
+ Peaks.prototype.selectSourcesOnLineAfter = function (lineId, time) {
15637
+ return this.view.selectSourcesOnLineAfter(lineId, time);
15638
+ };
15639
+ Peaks.prototype.deselectAll = function () {
15640
+ return this.view.deselectAll();
15618
15641
  };
15619
15642
  Peaks.prototype._addWindowResizeHandler = function () {
15620
15643
  this._onResize = this._onResize.bind(this);
@@ -15687,7 +15710,7 @@ module.exports = function (DefaultSegmentMarker, Utils, Konva) {
15687
15710
  };
15688
15711
  }(_dereq_('./default-segment-marker'), _dereq_('./utils'), _dereq_('konva'));
15689
15712
  },{"./default-segment-marker":88,"./utils":112,"konva":43}],96:[function(_dereq_,module,exports){
15690
- module.exports = function (Utils, SourceGroup, Konva) {
15713
+ module.exports = function (Utils, Source, SourceGroup, Konva) {
15691
15714
  'use strict';
15692
15715
  var TIME_X_OFFSET = 20;
15693
15716
  var TIME_Y_OFFSET = 10;
@@ -15697,6 +15720,7 @@ module.exports = function (Utils, SourceGroup, Konva) {
15697
15720
  this._view = view;
15698
15721
  this._playheadLayer = playheadLayer;
15699
15722
  this._stage = stage;
15723
+ this._selectedElements = {};
15700
15724
  this._layer = new Konva.Layer({ listening: this._mode !== 'default' });
15701
15725
  this._prepareDefaultMode();
15702
15726
  this._onMouseClickInDefaultMode = this._onMouseClickInDefaultMode.bind(this);
@@ -15711,31 +15735,54 @@ module.exports = function (Utils, SourceGroup, Konva) {
15711
15735
  ModeLayer.prototype.addToStage = function (stage) {
15712
15736
  stage.add(this._layer);
15713
15737
  };
15714
- ModeLayer.prototype.selectElement = function (element, notify) {
15715
- this.deselectElement(notify);
15716
- if (element) {
15717
- this._selectedElement = element;
15718
- this._selectedElement.setSelected(true);
15738
+ ModeLayer.prototype.selectElements = function (elements, notify) {
15739
+ const sources = [];
15740
+ const segments = [];
15741
+ const self = this;
15742
+ elements.forEach(function (element) {
15743
+ self._selectedElements[element.id] = element;
15744
+ element.setSelected(true);
15719
15745
  if (notify) {
15720
- if (element instanceof SourceGroup) {
15721
- this._peaks.emit('source.selected', this._selectedElement.getSource());
15746
+ if (element instanceof Source) {
15747
+ sources.push(element);
15722
15748
  } else {
15723
- this._peaks.emit('segment.selected', this._selectedElement.getSegment());
15749
+ segments.push(element);
15724
15750
  }
15725
15751
  }
15752
+ });
15753
+ if (notify) {
15754
+ if (sources.length) {
15755
+ this._peaks.emit('sources.selected', sources);
15756
+ }
15757
+ if (segments.length) {
15758
+ this._peaks.emit('segments.selected', segments);
15759
+ }
15726
15760
  }
15727
15761
  };
15728
- ModeLayer.prototype.deselectElement = function (notify) {
15729
- if (this._selectedElement) {
15730
- this._selectedElement.setSelected(false);
15731
- if (notify) {
15732
- if (this._selectedElement instanceof SourceGroup) {
15733
- this._peaks.emit('source.deselected', this._selectedElement.getSource());
15734
- } else {
15735
- this._peaks.emit('segment.deselected', this._selectedElement.getSegment());
15762
+ ModeLayer.prototype.deselectAll = function (notify) {
15763
+ const sources = [];
15764
+ const segments = [];
15765
+ for (var id in this._selectedElements) {
15766
+ if (Utils.objectHasProperty(this._selectedElements, id)) {
15767
+ const element = this._selectedElements[id];
15768
+ element.setSelected(false);
15769
+ if (notify) {
15770
+ if (element instanceof Source) {
15771
+ sources.push(element);
15772
+ } else {
15773
+ segments.push(element);
15774
+ }
15736
15775
  }
15776
+ delete this._selectedElements[id];
15777
+ }
15778
+ }
15779
+ if (notify) {
15780
+ if (sources.length) {
15781
+ this._peaks.emit('sources.deselected', sources);
15782
+ }
15783
+ if (segments.length) {
15784
+ this._peaks.emit('segments.deselected', segments);
15737
15785
  }
15738
- this._selectedElement = null;
15739
15786
  }
15740
15787
  };
15741
15788
  ModeLayer.prototype._prepareDefaultMode = function () {
@@ -15787,24 +15834,30 @@ module.exports = function (Utils, SourceGroup, Konva) {
15787
15834
  this._layer.add(this._cutGroup);
15788
15835
  };
15789
15836
  ModeLayer.prototype._onMouseClickInDefaultMode = function () {
15790
- var hoveredElement = this._view.getHoveredElement();
15791
- if (hoveredElement) {
15792
- this.selectElement(hoveredElement, true);
15837
+ const hoveredKonvaElement = this._view.getHoveredElement();
15838
+ if (hoveredKonvaElement) {
15839
+ if (hoveredKonvaElement instanceof SourceGroup) {
15840
+ this.selectElements([hoveredKonvaElement.getSource()], true);
15841
+ } else {
15842
+ this.selectElements([hoveredKonvaElement.getSegment()], true);
15843
+ }
15793
15844
  } else {
15794
- this.deselectElement(true);
15845
+ this.deselectAll(true);
15846
+ this._view.drawSourcesLayer();
15795
15847
  }
15796
15848
  };
15797
15849
  ModeLayer.prototype._onKeyboardDelete = function () {
15798
- if (this._selectedElement) {
15799
- var selectedElement = this._selectedElement;
15800
- this.deselectElement(true);
15801
- if (selectedElement instanceof SourceGroup) {
15850
+ const selectedElements = Object.values(this._selectedElements);
15851
+ if (selectedElements.length) {
15852
+ var selectedElement = selectedElements[0];
15853
+ this.deselectAll(true);
15854
+ if (selectedElement instanceof Source) {
15802
15855
  if (selectedElement.isDeletable()) {
15803
- this._peaks.destroySource(selectedElement.getSource().id);
15856
+ this._peaks.destroySource(selectedElement.id);
15804
15857
  }
15805
15858
  } else {
15806
15859
  if (selectedElement.getSegment().allowDeletion) {
15807
- this._peaks.destroySegment(selectedElement.getSegment().id);
15860
+ this._peaks.destroySegment(selectedElement.id);
15808
15861
  }
15809
15862
  }
15810
15863
  }
@@ -15943,7 +15996,7 @@ module.exports = function (Utils, SourceGroup, Konva) {
15943
15996
  this._peaks.off('keyboard.delete', this._onKeyboardDelete);
15944
15997
  break;
15945
15998
  }
15946
- this.deselectElement(true);
15999
+ this.deselectAll(true);
15947
16000
  switch (mode) {
15948
16001
  case 'cut':
15949
16002
  this._stage.on('mouseover', this._onMouseEnterInCutMode);
@@ -15980,8 +16033,8 @@ module.exports = function (Utils, SourceGroup, Konva) {
15980
16033
  return this._mode;
15981
16034
  };
15982
16035
  return ModeLayer;
15983
- }(_dereq_('./utils'), _dereq_('./source-group'), _dereq_('konva'));
15984
- },{"./source-group":104,"./utils":112,"konva":43}],97:[function(_dereq_,module,exports){
16036
+ }(_dereq_('./utils'), _dereq_('./source'), _dereq_('./source-group'), _dereq_('konva'));
16037
+ },{"./source":105,"./source-group":104,"./utils":112,"konva":43}],97:[function(_dereq_,module,exports){
15985
16038
  module.exports = function (Konva) {
15986
16039
  'use strict';
15987
16040
  function getMarkerObject(obj) {
@@ -16412,7 +16465,6 @@ module.exports = function (Konva, SegmentMarker, Utils) {
16412
16465
  this._endMarker = null;
16413
16466
  this._shapeGroup = null;
16414
16467
  this._rectangle = null;
16415
- this._isSelected = false;
16416
16468
  this._indicators = {};
16417
16469
  var self = this;
16418
16470
  this._segmentWidth = this._view.timeToPixels(this._segment.endTime - this._segment.startTime);
@@ -16709,9 +16761,6 @@ module.exports = function (Konva, SegmentMarker, Utils) {
16709
16761
  var startMarker = segmentMarker.isStartMarker();
16710
16762
  this._peaks.emit('segments.dragend', this._segment, startMarker);
16711
16763
  };
16712
- SegmentShape.prototype.setSelected = function (isSelected) {
16713
- this._isSelected = isSelected;
16714
- };
16715
16764
  SegmentShape.prototype.fitToView = function () {
16716
16765
  if (this._startMarker) {
16717
16766
  this._startMarker.fitToView();
@@ -16845,6 +16894,7 @@ module.exports = function (Utils) {
16845
16894
  this._indicators = opts.indicators;
16846
16895
  this._minSize = peaks.options.minSegmentSize;
16847
16896
  this._relativeId = 0;
16897
+ this._selected = false;
16848
16898
  if (shouldNotifyUpdate) {
16849
16899
  peaks.emit('segments.updated', [this]);
16850
16900
  }
@@ -17024,6 +17074,9 @@ module.exports = function (Utils) {
17024
17074
  this._indicators = opts.indicators;
17025
17075
  this._peaks.emit('segment.updated', this);
17026
17076
  };
17077
+ Segment.prototype.setSelected = function (selected) {
17078
+ this._selected = selected;
17079
+ };
17027
17080
  Segment.prototype.isVisible = function (startTime, endTime) {
17028
17081
  return this.startTime < endTime && startTime < this.endTime;
17029
17082
  };
@@ -17565,11 +17618,15 @@ module.exports = function (WaveformBuilder, WaveformShape, Utils, Konva) {
17565
17618
  var SPACING_BETWEEN_PREVIEW_AND_BORDER_RATIO = 0.15;
17566
17619
  var SPACING_BETWEEN_PREVIEWS = 1.5;
17567
17620
  var CORNER_RADIUS = 8;
17621
+ var INDICATOR_RADIUS = 4;
17622
+ var INDICATORS_MARGIN_LEFT = 8;
17623
+ var INDICATORS_MARGIN_TOP = 12;
17568
17624
  function SourceGroup(source, peaks, layer, view) {
17569
17625
  this._source = source;
17570
17626
  this._peaks = peaks;
17571
17627
  this._layer = layer;
17572
17628
  this._view = view;
17629
+ this._indicators = {};
17573
17630
  var self = this;
17574
17631
  this._x = this._view.timeToPixels(source.startTime);
17575
17632
  this._width = this._view.timeToPixels(source.endTime - source.startTime);
@@ -17615,6 +17672,10 @@ module.exports = function (WaveformBuilder, WaveformShape, Utils, Konva) {
17615
17672
  }
17616
17673
  this._addHandles();
17617
17674
  this.setWrapping(source.wrapped);
17675
+ this._setSelected();
17676
+ this._indicatorsGroup = new Konva.Group();
17677
+ this._group.add(this._indicatorsGroup);
17678
+ this.createIndicators();
17618
17679
  }
17619
17680
  SourceGroup.prototype._onSourceGroupDragStart = function () {
17620
17681
  this._dragged = true;
@@ -18151,9 +18212,9 @@ module.exports = function (WaveformBuilder, WaveformShape, Utils, Konva) {
18151
18212
  return preview.type === 'audio';
18152
18213
  });
18153
18214
  };
18154
- SourceGroup.prototype.setSelected = function (isSelected) {
18215
+ SourceGroup.prototype._setSelected = function () {
18155
18216
  if (this._border) {
18156
- if (isSelected) {
18217
+ if (this._source._selected) {
18157
18218
  this._border.fill(this._source.selectedColor);
18158
18219
  this._borderWidth = this._peaks.options.sourceSelectedBorderWidth;
18159
18220
  } else {
@@ -18166,7 +18227,7 @@ module.exports = function (WaveformBuilder, WaveformShape, Utils, Konva) {
18166
18227
  return node.getClassName() === 'Shape';
18167
18228
  });
18168
18229
  if (unwrap_background) {
18169
- if (isSelected) {
18230
+ if (this._source._selected) {
18170
18231
  unwrap_background.stroke(this._source.selectedColor);
18171
18232
  unwrap_background.strokeWidth(this._peaks.options.sourceSelectedBorderWidth);
18172
18233
  } else {
@@ -18179,7 +18240,7 @@ module.exports = function (WaveformBuilder, WaveformShape, Utils, Konva) {
18179
18240
  return node.getClassName() === 'Shape';
18180
18241
  });
18181
18242
  if (wrap_background) {
18182
- if (isSelected) {
18243
+ if (this._source._selected) {
18183
18244
  wrap_background.stroke(this._source.selectedColor);
18184
18245
  wrap_background.strokeWidth(this._peaks.options.sourceSelectedBorderWidth);
18185
18246
  } else {
@@ -18188,7 +18249,6 @@ module.exports = function (WaveformBuilder, WaveformShape, Utils, Konva) {
18188
18249
  }
18189
18250
  }
18190
18251
  }
18191
- this._view.drawSourcesLayer();
18192
18252
  };
18193
18253
  SourceGroup.prototype.updatePreviews = function () {
18194
18254
  var self = this;
@@ -18298,6 +18358,54 @@ module.exports = function (WaveformBuilder, WaveformShape, Utils, Konva) {
18298
18358
  SourceGroup.prototype.destroy = function () {
18299
18359
  this._group.destroy();
18300
18360
  };
18361
+ SourceGroup.prototype.createIndicators = function () {
18362
+ var newIndicatorsColors = this._source.indicators;
18363
+ var oldIndicators = this._indicators;
18364
+ var newIndicators = {};
18365
+ if (newIndicatorsColors) {
18366
+ newIndicatorsColors.forEach(function (indicatorColor) {
18367
+ var oldIndicator = oldIndicators[indicatorColor];
18368
+ if (oldIndicator) {
18369
+ newIndicators[indicatorColor] = oldIndicator;
18370
+ delete oldIndicators[indicatorColor];
18371
+ } else {
18372
+ newIndicators[indicatorColor] = null;
18373
+ }
18374
+ });
18375
+ for (var color in oldIndicators) {
18376
+ if (Utils.objectHasProperty(oldIndicators, color)) {
18377
+ oldIndicators[color].destroy();
18378
+ }
18379
+ }
18380
+ }
18381
+ this._indicators = Object.keys(newIndicators).sort().reverse().reduce(function (objEntries, key) {
18382
+ objEntries[key] = newIndicators[key];
18383
+ return objEntries;
18384
+ }, {});
18385
+ this._createIndicators();
18386
+ };
18387
+ SourceGroup.prototype._createIndicators = function () {
18388
+ var currentX = 0;
18389
+ var zIndex = 0;
18390
+ for (var color in this._indicators) {
18391
+ if (Utils.objectHasProperty(this._indicators, color)) {
18392
+ if (!this._indicators[color]) {
18393
+ this._indicators[color] = new Konva.Circle({
18394
+ radius: INDICATOR_RADIUS,
18395
+ fill: color,
18396
+ strokeEnabled: false
18397
+ });
18398
+ this._indicatorsGroup.add(this._indicators[color]);
18399
+ }
18400
+ this._indicators[color].x(currentX);
18401
+ this._indicators[color].zIndex(zIndex);
18402
+ currentX -= INDICATOR_RADIUS;
18403
+ zIndex += 1;
18404
+ }
18405
+ }
18406
+ this._indicatorsGroup.offsetX(currentX - INDICATORS_MARGIN_LEFT);
18407
+ this._indicatorsGroup.offsetY(-INDICATORS_MARGIN_TOP);
18408
+ };
18301
18409
  return SourceGroup;
18302
18410
  }(_dereq_('./waveform-builder'), _dereq_('./waveform-shape'), _dereq_('./utils'), _dereq_('konva'));
18303
18411
  },{"./utils":112,"./waveform-builder":113,"./waveform-shape":114,"konva":43}],105:[function(_dereq_,module,exports){
@@ -18468,8 +18576,11 @@ module.exports = function (Utils) {
18468
18576
  } else if (options.wrapping === 'complete') {
18469
18577
  options.wrapped = false;
18470
18578
  }
18579
+ if (Utils.isNullOrUndefined(options.indicators)) {
18580
+ options.indicators = [];
18581
+ }
18471
18582
  }
18472
- function Source(peaks, id, originId, elementId, title, url, previewUrl, binaryUrl, kind, subkind, duration, startTime, endTime, mediaStartTime, mediaEndTime, color, backgroundColor, borderColor, selectedColor, textFont, textFontSize, textColor, textBackgroundColor, textPosition, borderWidth, borderRadius, wrapped, position, draggable, orderable, resizable, cuttable, deletable, wrapping, previewHeight, binaryHeight) {
18583
+ function Source(peaks, id, originId, elementId, title, url, previewUrl, binaryUrl, kind, subkind, duration, startTime, endTime, mediaStartTime, mediaEndTime, color, backgroundColor, borderColor, selectedColor, textFont, textFontSize, textColor, textBackgroundColor, textPosition, borderWidth, borderRadius, wrapped, position, draggable, orderable, resizable, cuttable, deletable, wrapping, previewHeight, binaryHeight, indicators) {
18473
18584
  var opts = {
18474
18585
  title: title,
18475
18586
  url: url,
@@ -18502,7 +18613,8 @@ module.exports = function (Utils) {
18502
18613
  deletable: deletable,
18503
18614
  wrapping: wrapping,
18504
18615
  previewHeight: previewHeight,
18505
- binaryHeight: binaryHeight
18616
+ binaryHeight: binaryHeight,
18617
+ indicators: indicators
18506
18618
  };
18507
18619
  validateSource(peaks, opts, 'add()');
18508
18620
  this._peaks = peaks;
@@ -18541,7 +18653,9 @@ module.exports = function (Utils) {
18541
18653
  this._wrapping = opts.wrapping;
18542
18654
  this._previewHeight = opts.previewHeight;
18543
18655
  this._binaryHeight = opts.binaryHeight;
18656
+ this._indicators = opts.indicators;
18544
18657
  this._minSize = peaks.options.minSourceSize;
18658
+ this._selected = false;
18545
18659
  }
18546
18660
  Object.defineProperties(Source.prototype, {
18547
18661
  id: {
@@ -18823,6 +18937,12 @@ module.exports = function (Utils) {
18823
18937
  this._binaryHeight = binaryHeight;
18824
18938
  }
18825
18939
  },
18940
+ indicators: {
18941
+ enumerable: true,
18942
+ get: function () {
18943
+ return this._indicators;
18944
+ }
18945
+ },
18826
18946
  minSize: {
18827
18947
  enumerable: true,
18828
18948
  get: function () {
@@ -18947,7 +19067,8 @@ module.exports = function (Utils) {
18947
19067
  deletable: this.deletable,
18948
19068
  wrapping: this.wrapping,
18949
19069
  previewHeight: this.previewHeight,
18950
- binaryHeight: this.binaryHeight
19070
+ binaryHeight: this.binaryHeight,
19071
+ indicators: this.indicators
18951
19072
  };
18952
19073
  Utils.extend(opts, options);
18953
19074
  validateSource(this._peaks, opts, 'update()');
@@ -18983,11 +19104,20 @@ module.exports = function (Utils) {
18983
19104
  this._wrapping = opts.wrapping;
18984
19105
  this._previewHeight = opts.previewHeight;
18985
19106
  this._binaryHeight = opts.binaryHeight;
19107
+ this._indicators = opts.indicators;
19108
+ this._peaks.emit('source.update', this);
19109
+ };
19110
+ Source.prototype.setSelected = function (selected) {
19111
+ this._selected = selected;
18986
19112
  this._peaks.emit('source.update', this);
18987
19113
  };
18988
19114
  Source.prototype.isVisible = function (startTime, endTime) {
18989
19115
  return this._startTime < endTime && startTime < this._endTime;
18990
19116
  };
19117
+ Source.prototype.setIndicators = function (newIndicators) {
19118
+ this._indicators = newIndicators;
19119
+ this._peaks.emit('source.setIndicators', this);
19120
+ };
18991
19121
  return Source;
18992
19122
  }(_dereq_('./utils'));
18993
19123
  },{"./utils":112}],106:[function(_dereq_,module,exports){
@@ -19013,6 +19143,7 @@ module.exports = function (SourceGroup, Lines, DataRetriever, Utils, Invoker, Ko
19013
19143
  this._peaks.on('sources.refresh', this._onSourcesRefresh.bind(this));
19014
19144
  this._peaks.on('segments.show', this._onSegmentsShow.bind(this));
19015
19145
  this._peaks.on('options.set.line_height', this._onOptionsLineHeightChange.bind(this));
19146
+ this._peaks.on('source.setIndicators', this.setIndicators.bind(this));
19016
19147
  }
19017
19148
  SourcesLayer.prototype.fitToView = function () {
19018
19149
  this._lines.fitToView();
@@ -19159,6 +19290,13 @@ module.exports = function (SourceGroup, Lines, DataRetriever, Utils, Invoker, Ko
19159
19290
  this._dataRetriever.retrieveData(source);
19160
19291
  return sourceGroup;
19161
19292
  };
19293
+ SourcesLayer.prototype.setIndicators = function (source) {
19294
+ var sourceGroup = this._sourcesGroup[source.id];
19295
+ if (sourceGroup) {
19296
+ sourceGroup.createIndicators();
19297
+ this._layer.draw();
19298
+ }
19299
+ };
19162
19300
  SourcesLayer.prototype.updateSources = function (startTime, endTime) {
19163
19301
  this._lines.updateSegments(startTime, endTime);
19164
19302
  var sources = this.findSources(startTime, endTime);
@@ -19286,6 +19424,9 @@ module.exports = function (SourceGroup, Lines, DataRetriever, Utils, Invoker, Ko
19286
19424
  SourcesLayer.prototype.getSourceGroupById = function (sourceId) {
19287
19425
  return this._sourcesGroup[sourceId];
19288
19426
  };
19427
+ SourcesLayer.prototype.getSourcesOnLineAfter = function (lineId, time) {
19428
+ return this._lines.getSourcesOnLineAfter(lineId, time);
19429
+ };
19289
19430
  SourcesLayer.prototype._sourcesOverlapped = function (source1, source2) {
19290
19431
  var endsLater = source1.startTime < source2.startTime && source1.endTime > source2.startTime;
19291
19432
  var startsEarlier = source1.startTime > source2.startTime && source1.startTime < source2.endTime;
@@ -19330,6 +19471,7 @@ module.exports = function (SourceGroup, Lines, DataRetriever, Utils, Invoker, Ko
19330
19471
  this._peaks.off('data.retrieved', this._onDataRetrieved);
19331
19472
  this._peaks.off('sources.refresh', this._onSourcesRefresh);
19332
19473
  this._peaks.off('segments.show', this._onSegmentsShow);
19474
+ this._peaks.off('source.setIndicators', this.setIndicators);
19333
19475
  };
19334
19476
  SourcesLayer.prototype.getHeight = function () {
19335
19477
  return this._layer.getHeight();
@@ -19745,7 +19887,7 @@ module.exports = function (Source, Utils) {
19745
19887
  if (!Utils.isObject(options)) {
19746
19888
  throw new TypeError('peaks.sources.add(): expected a Source object parameter');
19747
19889
  }
19748
- var source = new Source(this._peaks, options.id || this._getNextSourceId(), options.originId, options.elementId, options.title, options.url, options.previewUrl, options.binaryUrl, options.kind, options.subkind, options.duration, options.startTime, options.endTime, options.mediaStartTime, options.mediaEndTime, options.color, options.backgroundColor, options.borderColor, options.selectedColor, options.textFont, options.textFontSize, options.textColor, options.textBackgroundColor, options.textPosition, options.borderWidth, options.borderRadius, options.wrapped, options.position, options.draggable, options.orderable, options.resizable, options.cuttable, options.deletable, options.wrapping, options.previewHeight, options.binaryHeight);
19890
+ var source = new Source(this._peaks, options.id || this._getNextSourceId(), options.originId, options.elementId, options.title, options.url, options.previewUrl, options.binaryUrl, options.kind, options.subkind, options.duration, options.startTime, options.endTime, options.mediaStartTime, options.mediaEndTime, options.color, options.backgroundColor, options.borderColor, options.selectedColor, options.textFont, options.textFontSize, options.textColor, options.textBackgroundColor, options.textPosition, options.borderWidth, options.borderRadius, options.wrapped, options.position, options.draggable, options.orderable, options.resizable, options.cuttable, options.deletable, options.wrapping, options.previewHeight, options.binaryHeight, options.indicators);
19749
19891
  return source;
19750
19892
  };
19751
19893
  TimelineSources.prototype.getSources = function () {
@@ -20077,13 +20219,19 @@ module.exports = function (MouseDragHandler, PlayheadLayer, SourcesLayer, ModeLa
20077
20219
  this._sourcesLayer.draw();
20078
20220
  };
20079
20221
  TimelineZoomView.prototype.selectSourceById = function (sourceId) {
20080
- var sourceGroup = this._sourcesLayer.getSourceGroupById(sourceId);
20222
+ const sourceGroup = this._sourcesLayer.getSourceGroupById(sourceId);
20081
20223
  if (sourceGroup) {
20082
20224
  this._modeLayer.selectElement(sourceGroup, false);
20083
20225
  }
20084
20226
  };
20085
- TimelineZoomView.prototype.deselectElement = function () {
20086
- this._modeLayer.deselectElement(false);
20227
+ TimelineZoomView.prototype.selectSourcesOnLineAfter = function (lineId, time) {
20228
+ const sources = this._sourcesLayer.getSourcesOnLineAfter(lineId, time);
20229
+ if (sources) {
20230
+ this._modeLayer.selectElements(sources, false);
20231
+ }
20232
+ };
20233
+ TimelineZoomView.prototype.deselectAll = function () {
20234
+ this._modeLayer.deselectAll(false);
20087
20235
  };
20088
20236
  TimelineZoomView.prototype.isListening = function () {
20089
20237
  return this._stage.listening();
package/src/line.js CHANGED
@@ -655,6 +655,28 @@ define([
655
655
  // }
656
656
  // };
657
657
 
658
+ Line.prototype.getSourcesAfter = function(time) {
659
+ const sources = [];
660
+ var currentId = this._firstSourceId;
661
+
662
+ while (currentId) {
663
+ var lineSource = this._sources[currentId];
664
+
665
+ if (lineSource.source.startTime >= time) {
666
+ while (currentId) {
667
+ lineSource = this._sources[currentId];
668
+
669
+ sources.push(lineSource.source);
670
+ currentId = lineSource.nextSourceId;
671
+ }
672
+ break;
673
+ }
674
+ currentId = lineSource.nextSourceId;
675
+ }
676
+
677
+ return sources;
678
+ };
679
+
658
680
  Line.prototype.updatePosition = function(pos) {
659
681
  for (var sourceId in this._sources) {
660
682
  if (Utils.objectHasProperty(this._sources, sourceId)) {
package/src/lines.js CHANGED
@@ -185,6 +185,10 @@ define([
185
185
  return positions;
186
186
  };
187
187
 
188
+ Lines.prototype.getSourcesOnLineAfter = function(lineId, time) {
189
+ return this._linesByPosition[lineId].getSourcesAfter(time);
190
+ };
191
+
188
192
  Lines.prototype.getSegmentsGroups = function() {
189
193
  return this._segmentsGroups;
190
194
  };
package/src/main.js CHANGED
@@ -720,9 +720,14 @@ define([
720
720
  .selectSourceById(sourceId);
721
721
  };
722
722
 
723
- Peaks.prototype.deselectSource = function() {
723
+ Peaks.prototype.selectSourcesOnLineAfter = function(lineId, time) {
724
724
  return this.view
725
- .deselectElement();
725
+ .selectSourcesOnLineAfter(lineId, time);
726
+ };
727
+
728
+ Peaks.prototype.deselectAll = function() {
729
+ return this.view
730
+ .deselectAll();
726
731
  };
727
732
 
728
733
  Peaks.prototype._addWindowResizeHandler = function() {
package/src/mode-layer.js CHANGED
@@ -8,9 +8,10 @@
8
8
 
9
9
  define([
10
10
  './utils',
11
+ './source',
11
12
  './source-group',
12
13
  'konva'
13
- ], function(Utils, SourceGroup, Konva) {
14
+ ], function(Utils, Source, SourceGroup, Konva) {
14
15
  'use strict';
15
16
 
16
17
  var TIME_X_OFFSET = 20;
@@ -34,6 +35,8 @@ define([
34
35
  this._playheadLayer = playheadLayer;
35
36
  this._stage = stage;
36
37
 
38
+ this._selectedElements = {};
39
+
37
40
  this._layer = new Konva.Layer({
38
41
  listening: this._mode !== 'default'
39
42
  });
@@ -63,34 +66,60 @@ define([
63
66
  stage.add(this._layer);
64
67
  };
65
68
 
66
- ModeLayer.prototype.selectElement = function(element, notify) {
67
- this.deselectElement(notify);
68
- if (element) {
69
- this._selectedElement = element;
70
- this._selectedElement.setSelected(true);
69
+ ModeLayer.prototype.selectElements = function(elements, notify) {
70
+ const sources = [];
71
+ const segments = [];
72
+ const self = this;
73
+
74
+ elements.forEach(function(element) {
75
+ self._selectedElements[element.id] = element;
76
+ element.setSelected(true);
71
77
  if (notify) {
72
- if (element instanceof SourceGroup) {
73
- this._peaks.emit('source.selected', this._selectedElement.getSource());
78
+ if (element instanceof Source) {
79
+ sources.push(element);
74
80
  }
75
81
  else {
76
- this._peaks.emit('segment.selected', this._selectedElement.getSegment());
82
+ segments.push(element);
77
83
  }
78
84
  }
85
+ });
86
+ if (notify) {
87
+ if (sources.length) {
88
+ this._peaks.emit('sources.selected', sources);
89
+ }
90
+ if (segments.length) {
91
+ this._peaks.emit('segments.selected', segments);
92
+ }
79
93
  }
80
94
  };
81
95
 
82
- ModeLayer.prototype.deselectElement = function(notify) {
83
- if (this._selectedElement) {
84
- this._selectedElement.setSelected(false);
85
- if (notify) {
86
- if (this._selectedElement instanceof SourceGroup) {
87
- this._peaks.emit('source.deselected', this._selectedElement.getSource());
88
- }
89
- else {
90
- this._peaks.emit('segment.deselected', this._selectedElement.getSegment());
96
+ ModeLayer.prototype.deselectAll = function(notify) {
97
+ const sources = [];
98
+ const segments = [];
99
+
100
+ for (var id in this._selectedElements) {
101
+ if (Utils.objectHasProperty(this._selectedElements, id)) {
102
+ const element = this._selectedElements[id];
103
+
104
+ element.setSelected(false);
105
+ if (notify) {
106
+ if (element instanceof Source) {
107
+ sources.push(element);
108
+ }
109
+ else {
110
+ segments.push(element);
111
+ }
91
112
  }
113
+ delete this._selectedElements[id];
114
+ }
115
+ }
116
+ if (notify) {
117
+ if (sources.length) {
118
+ this._peaks.emit('sources.deselected', sources);
119
+ }
120
+ if (segments.length) {
121
+ this._peaks.emit('segments.deselected', segments);
92
122
  }
93
- this._selectedElement = null;
94
123
  }
95
124
  };
96
125
 
@@ -149,30 +178,39 @@ define([
149
178
  };
150
179
 
151
180
  ModeLayer.prototype._onMouseClickInDefaultMode = function() {
152
- var hoveredElement = this._view.getHoveredElement();
181
+ const hoveredKonvaElement = this._view.getHoveredElement();
153
182
 
154
- if (hoveredElement) {
155
- this.selectElement(hoveredElement, true);
183
+ if (hoveredKonvaElement) {
184
+ if (hoveredKonvaElement instanceof SourceGroup) {
185
+ this.selectElements([hoveredKonvaElement.getSource()], true);
186
+ }
187
+ else {
188
+ this.selectElements([hoveredKonvaElement.getSegment()], true);
189
+ }
156
190
  }
157
191
  else {
158
- this.deselectElement(true);
192
+ this.deselectAll(true);
193
+ this._view.drawSourcesLayer(); // Redraw sources layer to remove selection
159
194
  }
160
195
  };
161
196
 
162
197
  ModeLayer.prototype._onKeyboardDelete = function() {
163
- if (this._selectedElement) {
164
- var selectedElement = this._selectedElement;
198
+ const selectedElements = Object.values(this._selectedElements);
199
+
200
+ // We allow deletion if there is ONLY 1 element selected
201
+ if (selectedElements.length) {
202
+ var selectedElement = selectedElements[0];
165
203
 
166
- this.deselectElement(true);
204
+ this.deselectAll(true);
167
205
 
168
- if (selectedElement instanceof SourceGroup) {
206
+ if (selectedElement instanceof Source) {
169
207
  if (selectedElement.isDeletable()) {
170
- this._peaks.destroySource(selectedElement.getSource().id);
208
+ this._peaks.destroySource(selectedElement.id);
171
209
  }
172
210
  }
173
211
  else {
174
212
  if (selectedElement.getSegment().allowDeletion) {
175
- this._peaks.destroySegment(selectedElement.getSegment().id);
213
+ this._peaks.destroySegment(selectedElement.id);
176
214
  }
177
215
  }
178
216
  }
@@ -379,7 +417,7 @@ define([
379
417
  break;
380
418
  }
381
419
 
382
- this.deselectElement(true);
420
+ this.deselectAll(true);
383
421
 
384
422
  // Set new mode
385
423
  switch (mode) {
@@ -46,7 +46,6 @@ define([
46
46
  this._endMarker = null;
47
47
  this._shapeGroup = null;
48
48
  this._rectangle = null;
49
- this._isSelected = false;
50
49
  this._indicators = {};
51
50
 
52
51
  var self = this;
@@ -452,10 +451,6 @@ define([
452
451
  this._peaks.emit('segments.dragend', this._segment, startMarker);
453
452
  };
454
453
 
455
- SegmentShape.prototype.setSelected = function(isSelected) {
456
- this._isSelected = isSelected;
457
- };
458
-
459
454
  SegmentShape.prototype.fitToView = function() {
460
455
  if (this._startMarker) {
461
456
  this._startMarker.fitToView();
package/src/segment.js CHANGED
@@ -150,6 +150,7 @@ define([
150
150
  this._indicators = opts.indicators;
151
151
  this._minSize = peaks.options.minSegmentSize;
152
152
  this._relativeId = 0;
153
+ this._selected = false;
153
154
 
154
155
  if (shouldNotifyUpdate) {
155
156
  peaks.emit('segments.updated', [this]);
@@ -340,6 +341,11 @@ define([
340
341
  this._peaks.emit('segment.updated', this);
341
342
  };
342
343
 
344
+ Segment.prototype.setSelected = function(selected) {
345
+ this._selected = selected;
346
+ // this._peaks.emit('segment.update', this); // It's currently useless
347
+ };
348
+
343
349
  /**
344
350
  * Returns <code>true</code> if the segment overlaps a given time region.
345
351
  *
@@ -21,6 +21,9 @@ define([
21
21
  var SPACING_BETWEEN_PREVIEW_AND_BORDER_RATIO = 0.15;
22
22
  var SPACING_BETWEEN_PREVIEWS = 1.5;
23
23
  var CORNER_RADIUS = 8;
24
+ var INDICATOR_RADIUS = 4; // px
25
+ var INDICATORS_MARGIN_LEFT = 8; // px
26
+ var INDICATORS_MARGIN_TOP = 12; // px
24
27
 
25
28
  /**
26
29
  * Creates a source group for the given source.
@@ -39,6 +42,7 @@ define([
39
42
  this._peaks = peaks;
40
43
  this._layer = layer;
41
44
  this._view = view;
45
+ this._indicators = {};
42
46
 
43
47
  var self = this;
44
48
 
@@ -94,6 +98,13 @@ define([
94
98
  this._addHandles();
95
99
 
96
100
  this.setWrapping(source.wrapped);
101
+
102
+ this._setSelected();
103
+
104
+ this._indicatorsGroup = new Konva.Group();
105
+ this._group.add(this._indicatorsGroup);
106
+
107
+ this.createIndicators();
97
108
  }
98
109
 
99
110
  // SourceGroup.prototype.rescale = function() {
@@ -842,9 +853,9 @@ define([
842
853
  });
843
854
  };
844
855
 
845
- SourceGroup.prototype.setSelected = function(isSelected) {
856
+ SourceGroup.prototype._setSelected = function() {
846
857
  if (this._border) {
847
- if (isSelected) {
858
+ if (this._source._selected) {
848
859
  this._border.fill(this._source.selectedColor);
849
860
  this._borderWidth = this._peaks.options.sourceSelectedBorderWidth;
850
861
  }
@@ -861,7 +872,7 @@ define([
861
872
  });
862
873
 
863
874
  if (unwrap_background) {
864
- if (isSelected) {
875
+ if (this._source._selected) {
865
876
  unwrap_background.stroke(this._source.selectedColor);
866
877
  unwrap_background.strokeWidth(this._peaks.options.sourceSelectedBorderWidth);
867
878
  }
@@ -878,7 +889,7 @@ define([
878
889
  });
879
890
 
880
891
  if (wrap_background) {
881
- if (isSelected) {
892
+ if (this._source._selected) {
882
893
  wrap_background.stroke(this._source.selectedColor);
883
894
  wrap_background.strokeWidth(this._peaks.options.sourceSelectedBorderWidth);
884
895
  }
@@ -888,8 +899,6 @@ define([
888
899
  }
889
900
  }
890
901
  }
891
-
892
- this._view.drawSourcesLayer();
893
902
  };
894
903
 
895
904
  SourceGroup.prototype.updatePreviews = function() {
@@ -1039,5 +1048,69 @@ define([
1039
1048
  this._group.destroy();
1040
1049
  };
1041
1050
 
1051
+ SourceGroup.prototype.createIndicators = function() {
1052
+ var newIndicatorsColors = this._source.indicators;
1053
+
1054
+ var oldIndicators = this._indicators;
1055
+ var newIndicators = {};
1056
+
1057
+ if (newIndicatorsColors) {
1058
+ newIndicatorsColors.forEach(function(indicatorColor) {
1059
+ var oldIndicator = oldIndicators[indicatorColor];
1060
+
1061
+ if (oldIndicator) {
1062
+ newIndicators[indicatorColor] = oldIndicator;
1063
+ delete oldIndicators[indicatorColor];
1064
+ }
1065
+ else {
1066
+ newIndicators[indicatorColor] = null;
1067
+ }
1068
+ });
1069
+
1070
+ for (var color in oldIndicators) {
1071
+ if (Utils.objectHasProperty(oldIndicators, color)) {
1072
+ oldIndicators[color].destroy();
1073
+ }
1074
+ }
1075
+ }
1076
+
1077
+ this._indicators = Object.keys(newIndicators)
1078
+ .sort()
1079
+ .reverse()
1080
+ .reduce(function(objEntries, key) {
1081
+ objEntries[key] = newIndicators[key];
1082
+ return objEntries;
1083
+ }, {}
1084
+ );
1085
+
1086
+ this._createIndicators();
1087
+ };
1088
+
1089
+ SourceGroup.prototype._createIndicators = function() {
1090
+ var currentX = 0;
1091
+ var zIndex = 0;
1092
+
1093
+ for (var color in this._indicators) {
1094
+ if (Utils.objectHasProperty(this._indicators, color)) {
1095
+ if (!this._indicators[color]) {
1096
+ this._indicators[color] = new Konva.Circle({
1097
+ radius: INDICATOR_RADIUS,
1098
+ fill: color,
1099
+ strokeEnabled: false
1100
+ });
1101
+ this._indicatorsGroup.add(this._indicators[color]);
1102
+ }
1103
+
1104
+ this._indicators[color].x(currentX);
1105
+ this._indicators[color].zIndex(zIndex);
1106
+ currentX -= INDICATOR_RADIUS;
1107
+ zIndex += 1;
1108
+ }
1109
+ }
1110
+
1111
+ this._indicatorsGroup.offsetX(currentX - INDICATORS_MARGIN_LEFT);
1112
+ this._indicatorsGroup.offsetY(-INDICATORS_MARGIN_TOP);
1113
+ };
1114
+
1042
1115
  return SourceGroup;
1043
1116
  });
package/src/source.js CHANGED
@@ -246,6 +246,10 @@ define([
246
246
  else if (options.wrapping === 'complete') {
247
247
  options.wrapped = false;
248
248
  }
249
+
250
+ if (Utils.isNullOrUndefined(options.indicators)) {
251
+ options.indicators = [];
252
+ }
249
253
  }
250
254
 
251
255
  /**
@@ -266,13 +270,14 @@ define([
266
270
  * @param {Number} position Position of the source on the timeline.
267
271
  * Correspond to the index of the line.
268
272
  * @param {Boolean} segments If <code>true</code> this source will integrate the segments.
273
+ * @param {Array<String>} indicators Array containing the colors of all indicators.
269
274
  */
270
275
 
271
276
  function Source(peaks, id, originId, elementId, title, url, previewUrl, binaryUrl, kind,
272
277
  subkind, duration, startTime, endTime, mediaStartTime, mediaEndTime, color, backgroundColor,
273
278
  borderColor, selectedColor, textFont, textFontSize, textColor, textBackgroundColor,
274
279
  textPosition, borderWidth, borderRadius, wrapped, position, draggable, orderable, resizable,
275
- cuttable, deletable, wrapping, previewHeight, binaryHeight) {
280
+ cuttable, deletable, wrapping, previewHeight, binaryHeight, indicators) {
276
281
  var opts = {
277
282
  title: title,
278
283
  url: url,
@@ -305,7 +310,8 @@ define([
305
310
  deletable: deletable,
306
311
  wrapping: wrapping,
307
312
  previewHeight: previewHeight,
308
- binaryHeight: binaryHeight
313
+ binaryHeight: binaryHeight,
314
+ indicators: indicators
309
315
  };
310
316
 
311
317
  validateSource(peaks, opts, 'add()');
@@ -346,7 +352,9 @@ define([
346
352
  this._wrapping = opts.wrapping;
347
353
  this._previewHeight = opts.previewHeight;
348
354
  this._binaryHeight = opts.binaryHeight;
355
+ this._indicators = opts.indicators;
349
356
  this._minSize = peaks.options.minSourceSize;
357
+ this._selected = false;
350
358
  }
351
359
 
352
360
  Object.defineProperties(Source.prototype, {
@@ -650,6 +658,12 @@ define([
650
658
  this._binaryHeight = binaryHeight;
651
659
  }
652
660
  },
661
+ indicators: {
662
+ enumerable: true,
663
+ get: function() {
664
+ return this._indicators;
665
+ }
666
+ },
653
667
  minSize: {
654
668
  enumerable: true,
655
669
  get: function() {
@@ -806,7 +820,8 @@ define([
806
820
  deletable: this.deletable,
807
821
  wrapping: this.wrapping,
808
822
  previewHeight: this.previewHeight,
809
- binaryHeight: this.binaryHeight
823
+ binaryHeight: this.binaryHeight,
824
+ indicators: this.indicators
810
825
  };
811
826
 
812
827
  Utils.extend(opts, options);
@@ -845,10 +860,16 @@ define([
845
860
  this._wrapping = opts.wrapping;
846
861
  this._previewHeight = opts.previewHeight;
847
862
  this._binaryHeight = opts.binaryHeight;
863
+ this._indicators = opts.indicators;
848
864
 
849
865
  this._peaks.emit('source.update', this);
850
866
  };
851
867
 
868
+ Source.prototype.setSelected = function(selected) {
869
+ this._selected = selected;
870
+ this._peaks.emit('source.update', this);
871
+ };
872
+
852
873
  /**
853
874
  * Returns <code>true</code> if the source overlaps a given time region.
854
875
  *
@@ -862,5 +883,16 @@ define([
862
883
  return this._startTime < endTime && startTime < this._endTime;
863
884
  };
864
885
 
886
+ /**
887
+ * Update the indicators of this source.
888
+ *
889
+ * @param {Array<String>} newIndicators The new indicators.
890
+ */
891
+
892
+ Source.prototype.setIndicators = function(newIndicators) {
893
+ this._indicators = newIndicators;
894
+ this._peaks.emit('source.setIndicators', this);
895
+ };
896
+
865
897
  return Source;
866
898
  });
@@ -58,6 +58,7 @@ define([
58
58
  this._peaks.on('sources.refresh', this._onSourcesRefresh.bind(this));
59
59
  this._peaks.on('segments.show', this._onSegmentsShow.bind(this));
60
60
  this._peaks.on('options.set.line_height', this._onOptionsLineHeightChange.bind(this));
61
+ this._peaks.on('source.setIndicators', this.setIndicators.bind(this));
61
62
  }
62
63
 
63
64
  SourcesLayer.prototype.fitToView = function() {
@@ -280,6 +281,15 @@ define([
280
281
  return sourceGroup;
281
282
  };
282
283
 
284
+ SourcesLayer.prototype.setIndicators = function(source) {
285
+ var sourceGroup = this._sourcesGroup[source.id];
286
+
287
+ if (sourceGroup) {
288
+ sourceGroup.createIndicators();
289
+ this._layer.draw();
290
+ }
291
+ };
292
+
283
293
  /**
284
294
  * Updates the positions of all displayed sources in the view.
285
295
  *
@@ -506,6 +516,10 @@ define([
506
516
  return this._sourcesGroup[sourceId];
507
517
  };
508
518
 
519
+ SourcesLayer.prototype.getSourcesOnLineAfter = function(lineId, time) {
520
+ return this._lines.getSourcesOnLineAfter(lineId, time);
521
+ };
522
+
509
523
  SourcesLayer.prototype._sourcesOverlapped = function(source1, source2) {
510
524
  var endsLater = (source1.startTime < source2.startTime)
511
525
  && (source1.endTime > source2.startTime);
@@ -568,6 +582,7 @@ define([
568
582
  this._peaks.off('data.retrieved', this._onDataRetrieved);
569
583
  this._peaks.off('sources.refresh', this._onSourcesRefresh);
570
584
  this._peaks.off('segments.show', this._onSegmentsShow);
585
+ this._peaks.off('source.setIndicators', this.setIndicators);
571
586
  };
572
587
 
573
588
  SourcesLayer.prototype.getHeight = function() {
@@ -179,7 +179,8 @@ define([
179
179
  options.deletable,
180
180
  options.wrapping,
181
181
  options.previewHeight,
182
- options.binaryHeight
182
+ options.binaryHeight,
183
+ options.indicators
183
184
  );
184
185
 
185
186
  return source;
@@ -366,15 +366,23 @@ define([
366
366
  };
367
367
 
368
368
  TimelineZoomView.prototype.selectSourceById = function(sourceId) {
369
- var sourceGroup = this._sourcesLayer.getSourceGroupById(sourceId);
369
+ const sourceGroup = this._sourcesLayer.getSourceGroupById(sourceId);
370
370
 
371
371
  if (sourceGroup) {
372
372
  this._modeLayer.selectElement(sourceGroup, false);
373
373
  }
374
374
  };
375
375
 
376
- TimelineZoomView.prototype.deselectElement = function() {
377
- this._modeLayer.deselectElement(false);
376
+ TimelineZoomView.prototype.selectSourcesOnLineAfter = function(lineId, time) {
377
+ const sources = this._sourcesLayer.getSourcesOnLineAfter(lineId, time);
378
+
379
+ if (sources) {
380
+ this._modeLayer.selectElements(sources, false);
381
+ }
382
+ };
383
+
384
+ TimelineZoomView.prototype.deselectAll = function() {
385
+ this._modeLayer.deselectAll(false);
378
386
  };
379
387
 
380
388
  TimelineZoomView.prototype.isListening = function() {