@vidispine/vdt-videojs 23.1.0 → 23.2.0-pre.2

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/src/seekBar.js DELETED
@@ -1,904 +0,0 @@
1
- /* eslint-disable max-len */
2
- /* eslint-disable no-multi-assign */
3
- /* eslint-disable no-unused-expressions */
4
- /* eslint-disable no-param-reassign */
5
- /* eslint-disable max-classes-per-file */
6
-
7
- import mousetrap from 'mousetrap';
8
-
9
- import { classNames, colors } from './constants';
10
- import { truncate, sanitize, reactiveSetters } from './helpers';
11
-
12
- const constants = Object.freeze({
13
- className: 'vdt-seekbar',
14
- defaults: {
15
- bgColor: '#fafafa',
16
- fillColor: '#f00',
17
- regionColor: '#f6e58d', // yellow
18
- markerWidth: 16,
19
- regionAccentColor: '#00a8ff',
20
- transitionTime: 300, // ms
21
- },
22
- markerTypes: {
23
- in: 'in',
24
- out: 'out',
25
- },
26
- });
27
-
28
- const CSS = (bgColor, fillColor) => `
29
- .${constants.className}{
30
- user-select: none;
31
- background: ${colors.light};
32
- height: 6px;
33
- width: 100%;
34
- position: relative;
35
- cursor: pointer;
36
- z-index: 5;
37
- }
38
-
39
- .${classNames.onDark}.${constants.className}{
40
- background: ${colors.gray};
41
- }
42
-
43
- .fill, .load-indicator{
44
- height: 100%;
45
- display: inline-block;
46
- position: absolute;
47
- left: 0px;
48
- top: 0px;
49
- background: ${fillColor};
50
- transition: width ${constants.defaults.transitionTime}ms linear;
51
- z-index: 2;
52
- }
53
-
54
- .load-indicator{
55
- background: #e1e1e1;
56
- z-index: 1;
57
- opacity: .2;
58
- transition: none;
59
- }
60
-
61
- .${classNames.onDark}.${constants.className} .load-indicator{
62
- background: white;
63
- }
64
-
65
- .${constants.className}.dragging .fill{
66
- transition: none;
67
- }
68
-
69
-
70
- .marker, .region{
71
- position: absolute;
72
- top: 0px;
73
- height: 100%;
74
- background: cyan;
75
- width: 1px;
76
- display: inline-block;
77
- z-index: 4;
78
- }
79
-
80
- .marker{
81
- transition: opacity ${constants.defaults.transitionTime}ms linear;
82
- }
83
-
84
- .marker{ display: none; }
85
- .marker.active{ display: initial; }
86
-
87
- .marker .handle{
88
- position: absolute;
89
- bottom: 10px; right: 0px;
90
- width: ${constants.defaults.markerWidth}px;
91
- height: 28px;
92
- background: #999;
93
- border-radius: 3px;
94
- cursor: col-resize;
95
- z-index: 3;
96
- box-sizing: border-box;
97
- }
98
-
99
- .marker.regional .handle{
100
- background: ${constants.defaults.regionAccentColor};
101
- box-shadow: -2px 1px 1px rgba(0,0,0,.1);
102
- }
103
-
104
- .marker.regional.in .handle{
105
- box-shadow: 2px 1px 1px rgba(0,0,0,.1);
106
- }
107
-
108
- .marker.in .handle{
109
- border-bottom-left-radius: 40px;
110
- }
111
-
112
- .marker.out .handle{
113
- left: 1px;
114
- right: initial;
115
- border-bottom-right-radius: 20px;
116
- }
117
-
118
- .handle:active{
119
- background: ${constants.defaults.regionColor};
120
- }
121
-
122
- .region{
123
- position: absolute;
124
- width: auto;
125
- background: ${constants.defaults.regionColor};
126
- opacity: .7;
127
- }
128
-
129
- .region.nav{
130
- background: transparent;
131
- opacity: 1;
132
- border-left: 1px solid cyan;
133
- }
134
-
135
- .region.nav .bubble,
136
- .region.nav:after{
137
- content: " ";
138
- height: 16px;
139
- bottom: 10px;
140
- width: 16px;
141
- border-radius: 16px;
142
- background: ${constants.defaults.regionAccentColor};
143
- position: absolute;
144
- margin-left: -8px;
145
- transition: transform 200ms ease-out;
146
- transform: translate3d(0px, 0px, 0px);
147
- transform-origin: bottom center;
148
- }
149
-
150
- .region.nav .popout{
151
- width: 160px;
152
- z-index: 4;
153
- background: rgba(28, 28, 28, .7);
154
- color: white;
155
- font-size: 14px;
156
- min-height: 100px;
157
- bottom: 16px;
158
- left: -80px;
159
- position: absolute;
160
- border-radius: 8px;
161
- -webkit-backdrop-filter: blur(10px);
162
- font-family: Arial, Helvetica, sans-serif;
163
- overflow: hidden;
164
- opacity: 0;
165
- visibility: hidden;
166
- }
167
-
168
- .region.nav.right-aligned .popout{
169
- right: 0px;
170
- left: initial;
171
- }
172
-
173
- .region.nav.left-aligned .popout{
174
- left: -32px;
175
- }
176
-
177
- .region.nav .popout .title{
178
- padding: 4px 14px;
179
- text-align: center;
180
- color: black;
181
- background: white;
182
- }
183
-
184
- .region.nav .popout .annotation{
185
- padding: 8px 12px;
186
- font-weight: light;
187
- color: rgba(255,255,255,.9);
188
- }
189
-
190
- .region.nav:after{
191
- width: 1px;
192
- left: 8px;
193
- height: 10px;
194
- bottom: 0px;
195
- background: #00a8ff;
196
- }
197
-
198
- .region.nav:hover{
199
- background: rgba(28, 28, 28, .5);
200
- }
201
-
202
- .region.nav.has-popout:hover .bubble{
203
- background: rgba(28, 28, 28, .8);
204
- opacity: 1;
205
- z-index: 3;
206
- }
207
-
208
- .region.nav:hover:after,
209
- .region.nav:hover:before{
210
- background: rgba(28, 28, 28, .8);
211
- }
212
-
213
- .region.nav:hover .popout{
214
- opacity: 1;
215
- visibility: visible;
216
- }
217
-
218
- .${constants.className}.dragging .bubble{
219
- transform: scale3d(.75,.75,.75);
220
- }
221
-
222
- .${constants.className}.hide-markers .marker{
223
- opacity: 0;
224
- }
225
-
226
- `;
227
-
228
- export class Region {
229
- constructor(props) {
230
- const regionDefaultProps = {
231
- in: null,
232
- out: null,
233
- title: '',
234
- annotation: '',
235
- el: null, // can store a
236
- };
237
-
238
- Object.assign(this, regionDefaultProps, props); // apply props
239
- }
240
- }
241
-
242
- export default class SeekBar {
243
- constructor(props) {
244
- this.props = props;
245
- reactiveSetters.apply(this); // ability to handle new props via setters
246
-
247
- this.container = document.createElement('div');
248
- this.container.className = `${constants.className}-wrapper`;
249
-
250
- this.state = {
251
- in: null, // in seconds from 0
252
- out: null,
253
- markersEnabled: this.props.markersEnabled === undefined ? true : this.props.markersEnabled,
254
- regions: [], // array with regions providing {in: 0, out: 12} and possibly more
255
- dragging: false,
256
- };
257
-
258
- this.markers = {};
259
-
260
- if (this.props.target) {
261
- this.shadow = this.container.attachShadow({ mode: 'open' });
262
- this.props.target.appendChild(this.container);
263
- // attach styles
264
- this.style = document.createElement('style');
265
- this.style.type = 'text/css';
266
-
267
- // colors from props
268
- const bgColor = this.props.bgColor ? this.props.bgColor : constants.defaults.bgColor;
269
- const fillColor = this.props.fillColor ? this.props.fillColor : constants.defaults.fillColor;
270
-
271
- this.style.innerHTML = CSS(sanitize(bgColor), sanitize(fillColor));
272
- this.shadow.appendChild(this.style);
273
- }
274
-
275
- this.bindEvents();
276
- this.draw();
277
- this.bindHotkeys();
278
-
279
- /*
280
- run this for "in" and "out" points set in constructor
281
- when the player metadata is ready (duration data is there)
282
- */
283
- const { player } = this.props;
284
- if (player) {
285
- player.videojs.on('loadedmetadata', () => {
286
- this.handleNewProps(this.props);
287
- });
288
- }
289
- }
290
-
291
- /*
292
- Video.js seekbar works a bit differently - it
293
- sets an interval and checks the playback position
294
- very frequently, could do it that way -
295
- then could use requestAnimationFrame and
296
- get a smoother animation at more expense
297
- */
298
- bindEvents() {
299
- // bind to vdt player instance
300
- if (this.props.player) {
301
- const { player } = this.props;
302
- player.videojs.on('timeupdate', () => {
303
- const progressFraction = player.videojs.currentTime() / player.videojs.duration();
304
- this.fill.style.width = `${100 * progressFraction}%`;
305
- });
306
-
307
- player.videojs.on('progress', () => {
308
- this.percentLoaded = player.percentLoaded;
309
- });
310
- }
311
- }
312
-
313
- bindHotkeys() {
314
- this.bindings = [];
315
-
316
- // bindings related to player
317
- if (this.props.player) {
318
- const { player } = this.props;
319
- this.bindings = [
320
- {
321
- key: ['i'],
322
- method: () => {
323
- if (this.markersEnabled) this.in = player.videojs.currentTime();
324
- },
325
- },
326
- {
327
- key: ['o'],
328
- method: () => {
329
- if (this.markersEnabled) this.out = player.videojs.currentTime();
330
- },
331
- },
332
- {
333
- key: ['shift+i'],
334
- method: () => {
335
- if (this.markersEnabled) this.navigateToIn();
336
- },
337
- },
338
- {
339
- key: ['shift+o'],
340
- method: () => {
341
- if (this.markersEnabled) this.navigateToOut();
342
- },
343
- },
344
- ];
345
- }
346
-
347
- if (this.props.player) {
348
- const { player } = this.props;
349
- mousetrap.bind('i', () => {
350
- if (this.markersEnabled) this.in = player.videojs.currentTime();
351
- });
352
-
353
- mousetrap.bind('o', () => {
354
- if (this.markersEnabled) this.out = player.videojs.currentTime();
355
- });
356
-
357
- mousetrap.bind('shift+i', () => {
358
- if (this.markersEnabled) this.navigateToIn();
359
- });
360
-
361
- mousetrap.bind('shift+o', () => {
362
- if (this.markersEnabled) this.navigateToOut();
363
- });
364
- }
365
-
366
- // bind
367
- this.bindings.forEach((binding) => {
368
- mousetrap.bind(binding.key, (e) => {
369
- binding.method(e);
370
- });
371
- });
372
- }
373
-
374
- unbindHotKeys() {
375
- this.bindings &&
376
- this.bindings.forEach((binding) => {
377
- mousetrap.unbind(binding.key);
378
- });
379
- }
380
-
381
- handleSeek(event) {
382
- // check if target is a region
383
- if (this.props.player) {
384
- const { player } = this.props;
385
- if (this.state.regions) {
386
- let clickedOnRegion = false;
387
- let preventSeek = false; // prevent seek from happening
388
- this.state.regions.forEach((region) => {
389
- if (region.el.contains(event.target)) {
390
- // player.seekTo(region.in);
391
-
392
- // callback for clicking on a region, if callback returns false, no seek happens
393
- // TODO - make a convention of returning true / false to break from seek
394
- if (this.props.onRegionClick) {
395
- preventSeek = this.props.onRegionClick(region);
396
- if (!preventSeek) {
397
- player.seekTo(region.in);
398
- }
399
- } else {
400
- player.seekTo(region.in);
401
- }
402
-
403
- clickedOnRegion = true;
404
- }
405
- });
406
-
407
- /*
408
- exit from method, TODO - implement foreach
409
- for breaking more efficiently
410
- */
411
-
412
- if (clickedOnRegion) return;
413
- }
414
-
415
- const seekFractionX =
416
- (event.clientX - this.bar.getBoundingClientRect().left) / this.bar.offsetWidth;
417
- // -> 0.34732
418
-
419
- const timeToSeek = seekFractionX * player.videojs.duration();
420
- // -> something like 32.2323 (in seconds)
421
- player.seekTo(timeToSeek);
422
- } // TODO - make a callback for more generic use case (non-vdt player)
423
- }
424
-
425
- handleSeekDrag(mouseDownEvent) {
426
- const barOffset = this.bar.getBoundingClientRect().left; // px from page left side
427
- const barWidth = this.bar.getBoundingClientRect().width; // seek bar width
428
- const duration = this.props.player.videojs.duration(); // in secondsā
429
- let left;
430
-
431
- const drag = (e) => {
432
- left = e.clientX - barOffset;
433
- const pxDragged = Math.abs(mouseDownEvent.clientX - e.clientX);
434
-
435
- if (left >= 0 && left < barWidth && pxDragged > 1) {
436
- // prevent out-of-bounds
437
- this.dragging = true;
438
- const fractionFromStart = parseFloat(left) / barWidth;
439
- const seconds = fractionFromStart * duration;
440
- this.props.player.videojs.currentTime(seconds);
441
- }
442
-
443
- e.preventDefault();
444
- };
445
-
446
- const stopDrag = (e) => {
447
- this.dragging = false;
448
-
449
- // remove listeners
450
- document.removeEventListener('mousemove', drag, false);
451
- document.removeEventListener('mouseup', stopDrag, false);
452
-
453
- const fractionFromStart = parseFloat(left) / barWidth;
454
- const seconds = fractionFromStart * duration;
455
- this.props.player.videojs.currentTime(seconds);
456
-
457
- e.stopPropagation();
458
- };
459
-
460
- // add listeners
461
- document.addEventListener('mousemove', drag, false);
462
- document.addEventListener('mouseup', stopDrag, false);
463
- }
464
-
465
- draw() {
466
- this.bar = document.createElement('div');
467
- this.bar.className = constants.className;
468
- this.bar.onclick = (e) => {
469
- if (!e.target.classList.contains('marker') && !e.target.classList.contains('handle')) {
470
- this.handleSeek(e);
471
- }
472
- };
473
-
474
- // handle drag
475
-
476
- this.bar.addEventListener(
477
- 'mousedown',
478
- (e) => {
479
- e.preventDefault(); // prevents selection cursor
480
-
481
- if (!this.dragging) {
482
- // don't attach listeners if something is already dragging
483
- this.handleSeekDrag(e);
484
- }
485
- },
486
- false,
487
- );
488
-
489
- this.fill = document.createElement('div');
490
- this.fill.className = 'fill';
491
-
492
- this.loadIndicator = document.createElement('div');
493
- this.loadIndicator.className = 'load-indicator';
494
-
495
- this.region = document.createElement('div');
496
- this.region.className = 'region';
497
-
498
- this.bar.appendChild(this.fill);
499
- this.bar.appendChild(this.loadIndicator);
500
- this.bar.appendChild(this.region);
501
- this.shadow.appendChild(this.bar);
502
-
503
- this.drawMarkers();
504
- }
505
-
506
- drawMarkers() {
507
- // TODO - add touch events
508
- if (this.markersEnabled) {
509
- const markerIn = (this.markers[constants.markerTypes.in] = document.createElement('div'));
510
- const markerOut = (this.markers[constants.markerTypes.out] = document.createElement('div'));
511
- markerIn.className = `marker ${constants.markerTypes.in}`;
512
- markerOut.className = `marker ${constants.markerTypes.out}`;
513
-
514
- const handleIn = document.createElement('div');
515
- const handleOut = document.createElement('div');
516
- handleIn.className = handleOut.className = 'handle';
517
-
518
- handleIn.addEventListener(
519
- 'mousedown',
520
- (e) => {
521
- e.preventDefault(); // prevents selection cursor
522
- e.stopPropagation(); // prevent triggering seek bar drag
523
-
524
- this.handleMarkerDrag(markerIn, constants.markerTypes.in, e);
525
- },
526
- false,
527
- );
528
-
529
- handleOut.addEventListener(
530
- 'mousedown',
531
- (e) => {
532
- e.preventDefault(); // prevents selection cursor
533
- e.stopPropagation(); // prevent triggering seek bar drag
534
-
535
- this.handleMarkerDrag(markerOut, constants.markerTypes.out, e);
536
- },
537
- false,
538
- );
539
-
540
- markerIn.appendChild(handleIn);
541
- markerOut.appendChild(handleOut);
542
-
543
- this.bar.appendChild(markerIn);
544
- this.bar.appendChild(markerOut);
545
- }
546
- }
547
-
548
- updateMarkers(marker) {
549
- this.markers[marker.type].style.left = `${marker.value * 100}%`;
550
- this.markers[marker.type].classList.add('active');
551
-
552
- // check if marker mathes a region and add a classname to it
553
- if (this.state.regions) {
554
- // check if any region contains in / out matching value
555
- const matchingRegions = [];
556
- const isRegional = matchingRegions.length > 0;
557
- if (isRegional) {
558
- this.markers[marker.type].classList.add('regional');
559
- } else {
560
- this.markers[marker.type].classList.remove('regional');
561
- }
562
- }
563
-
564
- this.drawInAndOutRegion();
565
- }
566
-
567
- drawInAndOutRegion() {
568
- // triggered after drawMarkers if in + out is set
569
- if (this.state.in !== null && this.state.out !== null) {
570
- this.region.style.left = this.markers[constants.markerTypes.in].style.left;
571
- this.region.style.right = `${
572
- 100 - parseFloat(this.markers[constants.markerTypes.out].style.left.replace('%', ''))
573
- }%`;
574
- } else {
575
- // remove region div or hide it
576
- }
577
- }
578
-
579
- /*
580
- TODO - handle touch events,
581
- but find out if there is a mobile use
582
- case before that
583
- */
584
- handleMarkerDrag(markerNode, type, mouseDownEvent) {
585
- // marker node, marker type (constants.markerTypes)
586
- const barOffset = this.bar.getBoundingClientRect().left; // px from page left side
587
- const barWidth = this.bar.getBoundingClientRect().width; // seek bar width
588
- const duration = this.props.player.videojs.duration(); // in secondsā
589
- let dragHappened = false;
590
-
591
- const drag = (e) => {
592
- const pxDragged = Math.abs(mouseDownEvent.clientX - e.clientX);
593
- const markerOffset =
594
- type === constants.markerTypes.in
595
- ? constants.defaults.markerWidth / 2
596
- : -(constants.defaults.markerWidth / 2);
597
- const left = e.clientX - barOffset + markerOffset;
598
-
599
- if (left >= 0 && left < barWidth && pxDragged > 1) {
600
- // prevent out-of-bounds
601
- dragHappened = this.dragging = true;
602
- markerNode.style.left = `${left}px`;
603
- markerNode.classList.add('active');
604
-
605
- const fractionFromStart =
606
- parseFloat(markerNode.getBoundingClientRect().left - barOffset) / barWidth;
607
- const seconds = fractionFromStart * duration;
608
- this.props.player.videojs.currentTime(seconds);
609
- }
610
-
611
- e.preventDefault();
612
- };
613
-
614
- const stopDrag = (e) => {
615
- this.dragging = false;
616
-
617
- // remove listeners
618
- document.removeEventListener('mousemove', drag, false);
619
- document.removeEventListener('mouseup', stopDrag, false);
620
-
621
- const fractionFromStart =
622
- parseFloat(markerNode.getBoundingClientRect().left - barOffset) / barWidth;
623
- const seconds = fractionFromStart * duration;
624
- this[type] = seconds;
625
- this.props.player.videojs.currentTime(seconds);
626
-
627
- /*
628
- if drag did not take place,
629
- user just clicked the marker -
630
- jump to the time of marker in player
631
- */
632
- if (!dragHappened) {
633
- if (type === constants.markerTypes.in) {
634
- this.navigateToIn();
635
- } else {
636
- this.navigateToOut();
637
- }
638
- }
639
-
640
- this.props.onDragFinish && this.props.onDragFinish({ type, seconds });
641
- e.stopPropagation();
642
- };
643
-
644
- // add listeners
645
- document.addEventListener('mousemove', drag, false);
646
- document.addEventListener('mouseup', stopDrag, false);
647
- }
648
-
649
- /*
650
- hide dead markers (for state parity) or ones that
651
- make no sense (like out point before in point)
652
- */
653
- cleanupMarkers() {
654
- let removedMarker = false;
655
- if (this.state.in === null) {
656
- this.markers[constants.markerTypes.in].classList.remove('active');
657
- removedMarker = true;
658
- }
659
-
660
- if (this.state.out === null) {
661
- this.markers[constants.markerTypes.out].classList.remove('active');
662
- removedMarker = true;
663
- }
664
-
665
- if (removedMarker) {
666
- // if a marker was removed, region no longer is valid
667
- this.region.style.left = 'initial';
668
- this.region.style.right = 'initial';
669
- }
670
- }
671
-
672
- clearMarkers() {
673
- this.in = null;
674
- this.out = null;
675
- }
676
-
677
- // utilizes player instance from props
678
- setInFromCurrent() {
679
- this.in = this.props.player.videojs.currentTime();
680
- }
681
-
682
- setOutFromCurrent() {
683
- this.out = this.props.player.videojs.currentTime();
684
- }
685
-
686
- navigateToIn() {
687
- const { player } = this.props;
688
- player.seekTo(this.in);
689
- }
690
-
691
- navigateToOut() {
692
- const { player } = this.props;
693
- player.seekTo(this.out);
694
- }
695
-
696
- // setters and getters
697
- set in(val) {
698
- if (!this.state.markersEnabled) return;
699
-
700
- this.state.in = val;
701
-
702
- if (val !== null && val !== undefined) {
703
- const { player } = this.props;
704
- this.updateMarkers({
705
- type: constants.markerTypes.in,
706
- value: val / player.videojs.duration(),
707
- });
708
-
709
- // make sure in point is not set after out point
710
- if (this.state.out !== null && val > this.state.out) {
711
- this.out = null;
712
- }
713
-
714
- this.props.onIn && this.props.onIn(this.state.in);
715
- } else {
716
- this.cleanupMarkers();
717
- }
718
- }
719
-
720
- get in() {
721
- return this.state.in;
722
- }
723
-
724
- set out(val) {
725
- if (!this.state.markersEnabled) return;
726
-
727
- this.state.out = val;
728
-
729
- if (val !== null && val !== undefined) {
730
- const { player } = this.props;
731
- this.updateMarkers({
732
- type: constants.markerTypes.out,
733
- value: val / player.videojs.duration(),
734
- });
735
-
736
- // make sure out point is not set before in point
737
- if (this.state.in != null && val < this.state.in) {
738
- this.in = null;
739
- }
740
-
741
- this.props.onOut && this.props.onOut(this.state.out);
742
- } else {
743
- this.cleanupMarkers();
744
- }
745
- }
746
-
747
- get out() {
748
- return this.state.out;
749
- }
750
-
751
- get markersEnabled() {
752
- return this.state.markersEnabled;
753
- }
754
-
755
- set markersEnabled(bool) {
756
- if (typeof bool === 'boolean') {
757
- if (!bool) {
758
- this.clearMarkers();
759
- this.state.markersEnabled = false;
760
- } else {
761
- !this.markersEnabled && this.drawMarkers();
762
- this.state.markersEnabled = true;
763
- }
764
- }
765
- }
766
-
767
- set regions(regionArray) {
768
- // different than i / o markers
769
- if (this.state.regions.length < 1) {
770
- // first time add
771
- regionArray &&
772
- regionArray.forEach((region) => {
773
- this.addRegion(region);
774
- });
775
- } else {
776
- // state redraw
777
- this.state.regions.forEach((region, index) => {
778
- this.removeRegion(index);
779
- });
780
-
781
- this.state.regions = [];
782
- this.regions = regionArray; // run again
783
- }
784
- }
785
-
786
- get regions() {
787
- return this.state.regions;
788
- }
789
-
790
- set dragging(bool) {
791
- // update only if worth updating
792
- if (bool && !this.state.dragging) {
793
- this.state.dragging = true;
794
- this.bar.classList.add('dragging');
795
- } else if (!bool && this.state.dragging) {
796
- this.state.dragging = false;
797
- this.bar.classList.remove('dragging');
798
- }
799
- }
800
-
801
- get dragging() {
802
- return this.state.dragging;
803
- }
804
-
805
- addRegion(regionObj) {
806
- if (regionObj.constructor.name === Region.name) {
807
- this.state.regions.push(regionObj);
808
- this.drawRegion(regionObj);
809
- } else {
810
- // try to construct region if has accepted properties
811
- this.addRegion(new Region(regionObj));
812
- }
813
- }
814
-
815
- removeRegion(param) {
816
- if (typeof param === typeof Region) {
817
- // TODO - implement this - find by region obj
818
- // find said matching region
819
- } else {
820
- // it's an index
821
- this.state.regions[param].el.remove();
822
- this.state.regions[param] = null;
823
- delete this.state.regions[param];
824
- }
825
- }
826
-
827
- drawRegion(region) {
828
- const duration = this.props.player.videojs.duration(); // seconds
829
- const inPoint = region.in;
830
-
831
- const leftPercentage = (inPoint / duration) * 100;
832
- const rightPercentage = ((duration - region.out) / duration) * 100;
833
-
834
- const regionEl = document.createElement('div');
835
- regionEl.className = 'region nav ';
836
- regionEl.innerHTML = '<div class="bubble"></div>';
837
-
838
- if (region.title && region.annotation) {
839
- let alignmentClassName = '';
840
- if (leftPercentage > 70) alignmentClassName = 'right-aligned';
841
- if (leftPercentage < 30) alignmentClassName = 'left-aligned';
842
- regionEl.className += ` has-popout ${alignmentClassName}`;
843
-
844
- const popout = document.createElement('div');
845
-
846
- popout.className = 'popout';
847
- popout.innerHTML = `
848
- <div class="title">
849
- ${sanitize(region.title)}
850
- </div>
851
- <div class="annotation">
852
- ${truncate(sanitize(region.annotation), 72)}
853
- </div>
854
- `;
855
-
856
- regionEl.appendChild(popout);
857
- }
858
-
859
- regionEl.style.left = `${leftPercentage}%`;
860
- regionEl.style.right = `${rightPercentage}%`;
861
-
862
- region.el = regionEl;
863
-
864
- this.bar.appendChild(regionEl);
865
- }
866
-
867
- set onDark(bool) {
868
- if (bool) {
869
- this.bar.classList.add(classNames.onDark);
870
- } else {
871
- this.bar.classList.remove(classNames.onDark);
872
- }
873
- }
874
-
875
- get onDark() {
876
- return this.container.classList.contains(classNames.onDark);
877
- }
878
-
879
- set percentLoaded(val) {
880
- this.loadIndicator.style.width = `${val}%`;
881
- }
882
-
883
- destroy() {
884
- this.unbindHotKeys();
885
- }
886
-
887
- toggleMarkers() {
888
- if (this.bar.classList.contains('hide-markers')) {
889
- this.showMarkers();
890
- } else {
891
- this.hideMarkers();
892
- }
893
- }
894
-
895
- hideMarkers() {
896
- this.bar.classList.add('hide-markers');
897
- }
898
-
899
- showMarkers() {
900
- this.bar.classList.remove('hide-markers');
901
- }
902
- }
903
-
904
- SeekBar.Region = Region;