@eluvio/elv-player-js 1.0.95 → 1.0.97

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": "@eluvio/elv-player-js",
3
- "version": "1.0.95",
3
+ "version": "1.0.97",
4
4
  "description": "![Eluvio Logo](src/static/images/Logo.png \"Eluvio Logo\")",
5
5
  "main": "src/index.js",
6
6
  "license": "MIT",
@@ -4,6 +4,7 @@ import PauseIcon from "./static/icons/media/Pause icon.svg";
4
4
  import FullscreenIcon from "./static/icons/media/Full Screen icon.svg";
5
5
  import ExitFullscreenIcon from "./static/icons/minimize.svg";
6
6
  import SettingsIcon from "./static/icons/media/Settings icon.svg";
7
+ import CloseIcon from "./static/icons/x.svg";
7
8
  import MutedIcon from "./static/icons/media/no volume icon.svg";
8
9
  import VolumeLowIcon from "./static/icons/media/low volume icon.svg";
9
10
  import VolumeHighIcon from "./static/icons/media/Volume icon.svg";
@@ -114,7 +115,6 @@ class PlayerControls {
114
115
  this.playerOptions = playerOptions;
115
116
  this.timeouts = {};
116
117
  this.played = false;
117
- this.controlsHover = false;
118
118
  this.progressHidden = false;
119
119
 
120
120
  if(posterUrl) {
@@ -139,15 +139,17 @@ class PlayerControls {
139
139
  }
140
140
  }
141
141
 
142
- FadeOut(key, elements, delay=250, callback) {
142
+ FadeOut({key, elements, delay=250, unless, callback}) {
143
+ if(unless && unless()) { return; }
144
+
143
145
  clearTimeout(this.timeouts[key]);
144
146
 
145
147
  this.timeouts[key] = setTimeout(() => {
146
148
  elements.forEach(element => {
147
149
  if(!element) { return; }
148
150
 
149
- element.style.pointerEvents = "none";
150
- element.style.opacity = "0";
151
+ element.classList.add("-elv-fade-out");
152
+ element.classList.remove("-elv-fade-in");
151
153
  });
152
154
 
153
155
  if(callback) {
@@ -156,107 +158,86 @@ class PlayerControls {
156
158
  }, delay);
157
159
  }
158
160
 
159
- FadeIn(key, elements) {
161
+ FadeIn({key, elements, callback}) {
160
162
  clearTimeout(this.timeouts[key]);
161
163
 
162
164
  elements.forEach(element => {
163
165
  if(!element) { return; }
164
166
 
165
- element.style.opacity = "1";
166
- element.style.pointerEvents = "unset";
167
+ element.classList.remove("-elv-fade-out");
168
+ element.classList.add("-elv-fade-in");
167
169
  });
168
- }
169
170
 
171
+ if(callback) {
172
+ callback();
173
+ }
174
+ }
170
175
 
171
176
  AutohideControls(controls) {
172
177
  this.video.addEventListener("play", () => {
173
178
  this.played = true;
174
179
  });
175
180
 
176
- const PlayerOut = () => {
177
- if(!this.played && this.video.paused) { return; }
178
-
179
- this.FadeOut("controls", [controls, this.settingsMenu, this.toolTip], 2000);
180
- };
181
+ /*
182
+ Controls should stay visible if:
183
+ - Video hasn't started yet
184
+ - Settings menu is open
185
+ - Currently hovering over controls
186
+ - Currently keyboard-selecting controls
187
+ */
188
+ const ControlsShouldShow = () => (
189
+ (!this.played && this.video.paused) ||
190
+ (this.settingsMenu && this.settingsMenu.dataset.mode !== "hidden") ||
191
+ !!Array.from(document.querySelectorAll(":hover")).find(element => this.controls.contains(element)) ||
192
+ !!this.controls.contains(document.activeElement) && document.activeElement.classList.contains("focus-visible")
193
+ );
181
194
 
182
195
  const PlayerMove = () => {
183
- if(this.controlsHover) { return; }
184
-
185
- this.FadeIn("controls", [controls, this.settingsMenu, this.toolTip]);
186
- this.FadeOut("controls", [controls, this.settingsMenu, this.toolTip], 3000, () => this.target.style.cursor = "none");
196
+ this.FadeIn({
197
+ key: "controls",
198
+ elements: [controls, this.settingsMenu, this.toolTip],
199
+ callback: () => {
200
+ this.target.classList.remove("-elv-no-cursor");
201
+ }
202
+ });
203
+ this.FadeOut({
204
+ key: "controls",
205
+ elements: [controls, this.settingsMenu, this.toolTip],
206
+ delay: 3000,
207
+ unless: () => ControlsShouldShow(),
208
+ callback: () => {
209
+ this.target.classList.add("-elv-no-cursor");
210
+ }
211
+ });
187
212
 
188
213
  this.target.style.cursor = "unset";
189
214
  };
190
215
 
191
- const ControlsIn = () => {
192
- clearTimeout(this.timeouts.controls);
193
- this.controlsHover = true;
194
- };
195
-
196
- const ControlsOut = () => this.controlsHover = false;
197
-
198
216
  // Play / Pause
199
217
  this.video.addEventListener("play", () => PlayerMove);
200
218
  this.video.addEventListener("pause", () => PlayerMove);
201
219
 
202
220
  // Mouse events
203
221
  this.target.addEventListener("mousemove", PlayerMove);
204
- this.target.addEventListener("mouseleave", PlayerOut);
205
- controls.addEventListener("mouseenter", ControlsIn);
206
- controls.addEventListener("mouseleave", ControlsOut);
207
-
208
- if(this.settingsMenu) {
209
- this.settingsMenu.addEventListener("mouseenter", ControlsIn);
210
- this.settingsMenu.addEventListener("mouseleave", ControlsOut);
211
- }
212
222
 
213
- if(this.toolTip) {
214
- this.toolTip.addEventListener("mouseenter", ControlsIn);
215
- this.toolTip.addEventListener("mouseleave", ControlsOut);
216
- }
217
223
 
218
224
  // Touch events
219
225
  this.target.addEventListener("touchmove", PlayerMove);
220
- this.target.addEventListener("touchleave", PlayerOut);
221
- controls.addEventListener("touchmove", ControlsIn);
222
- controls.addEventListener("touchleave", ControlsOut);
223
- controls.addEventListener("touchend", () => { ControlsOut(); PlayerOut(); });
224
-
225
- if(this.settingsMenu) {
226
- this.settingsMenu.addEventListener("touchmove", ControlsIn);
227
- this.settingsMenu.addEventListener("touchleave", ControlsOut);
228
- this.settingsMenu.addEventListener("touchend", () => {
229
- ControlsOut();
230
- PlayerOut();
231
- });
232
- }
233
-
234
- if(this.toolTip) {
235
- this.toolTip.addEventListener("touchmove", ControlsIn);
236
- this.toolTip.addEventListener("touchleave", ControlsOut);
237
- this.toolTip.addEventListener("touchend", () => {
238
- ControlsOut();
239
- PlayerOut();
240
- });
241
- }
242
226
 
243
227
  // Keyboard events
244
228
  this.target.addEventListener("blur", () => setTimeout(() => {
245
229
  if(!this.target.contains(document.activeElement)) {
246
- PlayerOut();
247
- ControlsOut();
230
+ PlayerMove();
248
231
  }
249
232
  }), 2000);
250
233
 
251
- window.addEventListener("blur", () => { PlayerOut(); ControlsOut(); });
234
+ window.addEventListener("blur", () => { PlayerMove(); });
252
235
 
253
236
  Array.from(this.target.querySelectorAll("button, input")).forEach(button => {
254
- button.addEventListener("focus", () => { PlayerMove(); ControlsIn(); });
237
+ button.addEventListener("focus", () => { PlayerMove(); });
255
238
  });
256
239
 
257
- if(!this.controlsHover) {
258
- PlayerOut();
259
- }
240
+ PlayerMove();
260
241
  }
261
242
 
262
243
  InitializeControls(className="") {
@@ -379,12 +360,12 @@ class PlayerControls {
379
360
  });
380
361
 
381
362
  this.video.addEventListener("play", () => {
382
- this.FadeOut("big-play-button", [this.bigPlayButton]);
363
+ this.FadeOut({key: "big-play-button", elements: [this.bigPlayButton]});
383
364
 
384
365
  // Prevent big play button from flashing
385
366
  setTimeout(() => this.target.classList.remove("eluvio-player-restarted"), 1000);
386
367
  });
387
- this.video.addEventListener("pause", () => this.FadeIn("big-play-button", [this.bigPlayButton]));
368
+ this.video.addEventListener("pause", () => this.FadeIn({key: "big-play-button", elements: [this.bigPlayButton]}));
388
369
 
389
370
  this.bigPlayButton.style.display = this.video.paused ? null : "none";
390
371
  this.bigPlayButton.addEventListener("click", () => this.video.play());
@@ -675,6 +656,21 @@ class PlayerControls {
675
656
  }
676
657
  }
677
658
 
659
+ InitializeMenu(mode) {
660
+ this.settingsMenu.innerHTML = "";
661
+ this.settingsMenu.classList.remove("eluvio-player__controls__settings-menu-hidden");
662
+ this.settingsMenu.setAttribute("data-mode", mode);
663
+
664
+ const closeButton = CreateImageButton({
665
+ parent: this.settingsMenu,
666
+ svg: CloseIcon,
667
+ type: "button",
668
+ classes: ["eluvio-player__controls__settings-menu__close"]
669
+ });
670
+
671
+ closeButton.addEventListener("click", () => this.HideSettingsMenu());
672
+ }
673
+
678
674
  AddSetting({Retrieve, Set}) {
679
675
  if(!Retrieve) { return; }
680
676
 
@@ -692,8 +688,7 @@ class PlayerControls {
692
688
 
693
689
  if(Set) {
694
690
  optionSelectionButton.addEventListener("click", () => {
695
- this.settingsMenu.innerHTML = "";
696
- this.settingsMenu.setAttribute("data-mode", "settings-submenu");
691
+ this.InitializeMenu("settings-submenu");
697
692
 
698
693
  const backButton = CreateElement({
699
694
  parent: this.settingsMenu,
@@ -703,11 +698,12 @@ class PlayerControls {
703
698
 
704
699
  CreateElement({
705
700
  parent: backButton,
706
- type: "svg"
701
+ classes: ["eluvio-player__controls__settings-menu__option-back__icon"]
707
702
  }).innerHTML = LeftArrow;
708
703
 
709
704
  CreateElement({
710
705
  parent: backButton,
706
+ classes: ["eluvio-player__controls__settings-menu__option-back__text"]
711
707
  }).innerHTML = label;
712
708
 
713
709
  backButton.addEventListener("click", () => this.ShowSettingsMenu());
@@ -738,9 +734,7 @@ class PlayerControls {
738
734
  }
739
735
 
740
736
  ShowSettingsMenu() {
741
- this.settingsMenu.innerHTML = "";
742
- this.settingsMenu.classList.remove("eluvio-player__controls__settings-menu-hidden");
743
- this.settingsMenu.setAttribute("data-mode", "settings");
737
+ this.InitializeMenu("settings");
744
738
 
745
739
  if(this.GetLevels) {
746
740
  this.AddSetting({Retrieve: this.GetLevels, Set: this.SetLevel});
package/src/index.js CHANGED
@@ -667,7 +667,7 @@ export class EluvioPlayer {
667
667
  }
668
668
 
669
669
  const UpdateAudioTracks = () => {
670
- if(this.video.audioTracks.length <= 1) { return; }
670
+ if(!this.video.audioTracks || this.video.audioTracks.length <= 1) { return; }
671
671
 
672
672
  this.controls.SetAudioTrackControls({
673
673
  GetAudioTracks: () => {
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
@@ -41,6 +41,7 @@ $button-height: 35px;
41
41
  box-sizing: border-box;
42
42
  font-family: "Helvetica Neue", Helvetica, sans-serif;
43
43
  line-height: 1;
44
+ overscroll-behavior-y: contain; // sass-lint:disable-line no-misspelled-properties
44
45
  }
45
46
 
46
47
  // sass-lint:disable force-attribute-nesting no-qualifying-elements
@@ -345,6 +346,7 @@ $button-height: 35px;
345
346
  }
346
347
 
347
348
  &__settings-menu {
349
+ backdrop-filter: blur(5px);
348
350
  background: $menu-color;
349
351
  border-radius: 3px;
350
352
  bottom: 45px;
@@ -363,6 +365,22 @@ $button-height: 35px;
363
365
 
364
366
  button {
365
367
  border: 1px solid transparent;
368
+
369
+ &.eluvio-player__controls__settings-menu__close {
370
+ border: 1.5px solid $button-color;
371
+ border-radius: 100%;
372
+ }
373
+ }
374
+
375
+ &__close {
376
+ display: none;
377
+ position: absolute;
378
+ right: 20px;
379
+ top: 20px;
380
+
381
+ * {
382
+ color: $button-color;
383
+ }
366
384
  }
367
385
 
368
386
  &__option {
@@ -378,28 +396,37 @@ $button-height: 35px;
378
396
  width: 100%;
379
397
 
380
398
  &-back {
399
+ align-items: center;
381
400
  display: flex;
382
- font-weight: 500;
401
+ position: relative;
383
402
  width: 100%;
403
+ }
384
404
 
385
- svg {
386
- height: 15px;
387
- margin-right: 5px;
388
- width: 15px;
389
- }
405
+ &-back__icon {
406
+ height: 15px;
407
+ left: 20px;
408
+ margin-right: 5px;
409
+ position: absolute;
410
+ width: 15px;
390
411
 
391
- div {
412
+ svg {
413
+ height: 100%;
392
414
  width: 100%;
393
415
  }
394
416
  }
395
417
 
418
+ &-back__text {
419
+ padding-inline: 25px;
420
+ width: 100%;
421
+ }
422
+
396
423
  &-selected {
397
- color: $button-color;
424
+ color: $white;
398
425
  }
399
426
 
400
427
  &:hover {
401
428
  background: $menu-active-color;
402
- color: $button-color;
429
+ color: $white;
403
430
  }
404
431
 
405
432
  &.focus-visible {
@@ -434,12 +461,6 @@ $button-height: 35px;
434
461
  }
435
462
  }
436
463
 
437
- &.eluvio-player-autohide {
438
- .eluvio-player__controls {
439
- opacity: 0;
440
- }
441
- }
442
-
443
464
  &:fullscreen {
444
465
  margin: 0;
445
466
  max-height: unset;
@@ -668,11 +689,28 @@ $button-height: 35px;
668
689
  }
669
690
 
670
691
  .eluvio-player__controls__settings-menu {
692
+ align-items: center;
671
693
  height: 100%;
672
- padding: 20px 0;
694
+ max-height: 100%;
695
+ padding: 80px 0 100px;
673
696
  right: 0;
674
697
  top: 0;
675
698
  width: 100%;
699
+
700
+ &__option {
701
+ font-size: 20px;
702
+ margin-bottom: 5px;
703
+ text-align: center;
704
+
705
+ &-back {
706
+ font-size: 24px;
707
+ margin-bottom: 20px;
708
+ }
709
+ }
710
+
711
+ &__close {
712
+ display: unset;
713
+ }
676
714
  }
677
715
 
678
716
  .eluvio-player__hotspot-overlay {
@@ -685,6 +723,29 @@ $button-height: 35px;
685
723
  }
686
724
  }
687
725
 
726
+ // sass-lint:disable no-important
727
+ .-elv-fade-in,
728
+ .-elv-fade-out {
729
+ transition: opacity 0.25s linear;
730
+ }
731
+
732
+ .-elv-fade-out {
733
+ opacity: 0 !important;
734
+ pointer-events: none !important;
735
+ }
736
+
737
+ .-elv-fade-in {
738
+ opacity: 1;
739
+ }
740
+
741
+ .-elv-no-cursor {
742
+ cursor: none !important;
743
+
744
+ * {
745
+ cursor: none !important;
746
+ }
747
+ }
748
+
688
749
  // sass-lint:disable no-color-literals
689
750
  @keyframes hotspot-select {
690
751
  0% {