shaka-player 2.5.4 → 2.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/.csslintrc +13 -0
  2. package/CHANGELOG.md +56 -0
  3. package/build/build.py +4 -1
  4. package/build/check.py +17 -0
  5. package/build/compiler.py +40 -0
  6. package/build/types/core +1 -0
  7. package/build/types/ui +4 -1
  8. package/demo/asset_card.js +41 -11
  9. package/demo/cast_receiver/receiver_app.css +19 -13
  10. package/demo/close_button.js +0 -6
  11. package/demo/common/asset.js +6 -1
  12. package/demo/common/assets.js +72 -14
  13. package/demo/demo.less +105 -16
  14. package/demo/index.html +8 -5
  15. package/demo/load.js +5 -7
  16. package/demo/main.js +81 -16
  17. package/dist/.csslintstamp +0 -0
  18. package/dist/controls.css +1 -1
  19. package/dist/controls.css.map +1 -1
  20. package/dist/demo.compiled.debug.js +46 -39
  21. package/dist/demo.compiled.debug.map +3 -3
  22. package/dist/demo.compiled.js +46 -39
  23. package/dist/demo.compiled.map +3 -3
  24. package/dist/demo.css +1 -1
  25. package/dist/demo.css.map +1 -1
  26. package/dist/deps.js +11 -7
  27. package/dist/receiver.compiled.debug.js +10 -6
  28. package/dist/receiver.compiled.debug.map +3 -3
  29. package/dist/receiver.compiled.js +10 -6
  30. package/dist/receiver.compiled.map +3 -3
  31. package/dist/shaka-player.compiled.debug.externs.js +123 -92
  32. package/dist/shaka-player.compiled.debug.js +113 -105
  33. package/dist/shaka-player.compiled.debug.map +4 -4
  34. package/dist/shaka-player.compiled.externs.js +123 -92
  35. package/dist/shaka-player.compiled.js +551 -548
  36. package/dist/shaka-player.compiled.map +4 -4
  37. package/dist/shaka-player.ui.debug.externs.js +170 -101
  38. package/dist/shaka-player.ui.debug.js +187 -188
  39. package/dist/shaka-player.ui.debug.map +4 -4
  40. package/dist/shaka-player.ui.externs.js +170 -101
  41. package/dist/shaka-player.ui.js +651 -651
  42. package/dist/shaka-player.ui.map +3 -3
  43. package/docs/tutorials/drm-config.md +1 -0
  44. package/docs/tutorials/fairplay.md +77 -0
  45. package/docs/tutorials/index.json +1 -0
  46. package/docs/tutorials/ui-customization.md +3 -0
  47. package/docs/tutorials/ui.md +3 -1
  48. package/externs/mediasession.js +16 -1
  49. package/externs/shaka/net.js +5 -1
  50. package/externs/shaka/player.js +136 -90
  51. package/externs/webkitmediakeys.js +4 -0
  52. package/lib/dash/content_protection.js +33 -1
  53. package/lib/dash/dash_parser.js +12 -4
  54. package/lib/hls/hls_parser.js +20 -4
  55. package/lib/media/drm_engine.js +29 -2
  56. package/lib/media/media_source_engine.js +7 -3
  57. package/lib/media/playhead.js +8 -3
  58. package/lib/media/streaming_engine.js +24 -8
  59. package/lib/media/video_wrapper.js +8 -3
  60. package/lib/net/networking_engine.js +1 -0
  61. package/lib/player.js +3 -2
  62. package/lib/polyfill/patchedmediakeys_apple.js +2 -72
  63. package/lib/util/error.js +12 -0
  64. package/lib/util/fairplay_utils.js +122 -0
  65. package/lib/util/player_configuration.js +5 -0
  66. package/lib/util/pssh.js +41 -0
  67. package/package.json +4 -3
  68. package/shaka-player.uncompiled.js +5 -1
  69. package/test/dash/dash_parser_content_protection_unit.js +35 -1
  70. package/test/dash/dash_parser_manifest_unit.js +31 -0
  71. package/test/hls/hls_live_unit.js +7 -1
  72. package/test/hls/hls_parser_unit.js +50 -0
  73. package/test/media/media_source_engine_integration.js +12 -0
  74. package/test/media/playhead_unit.js +2 -0
  75. package/test/player_external.js +3 -2
  76. package/test/player_integration.js +75 -0
  77. package/test/test/externs/jasmine.js +6 -0
  78. package/test/test/util/test_scheme.js +32 -1
  79. package/test/test/util/ui_utils.js +41 -0
  80. package/test/ui/ui_unit.js +129 -3
  81. package/ui/audio_language_selection.js +17 -96
  82. package/ui/big_play_button.js +61 -0
  83. package/ui/controls.js +111 -86
  84. package/ui/controls.less +3 -5
  85. package/ui/externs/ui.js +14 -2
  86. package/ui/fullscreen_button.js +2 -52
  87. package/ui/less/buttons.less +8 -8
  88. package/ui/less/containers.less +21 -21
  89. package/ui/less/general.less +11 -0
  90. package/ui/less/other_elements.less +2 -1
  91. package/ui/less/overflow_menu.less +11 -10
  92. package/ui/less/range_elements.less +6 -0
  93. package/ui/less/spinner.less +2 -0
  94. package/ui/pip_button.js +1 -1
  95. package/ui/{play_pause_button.js → play_button.js} +17 -47
  96. package/ui/resolution_selection.js +41 -104
  97. package/ui/seek_bar.js +15 -17
  98. package/ui/settings_menu.js +113 -0
  99. package/ui/small_play_button.js +73 -0
  100. package/ui/text_displayer.js +2 -2
  101. package/ui/text_selection.js +39 -105
  102. package/ui/ui.js +12 -0
package/ui/controls.js CHANGED
@@ -149,8 +149,6 @@ shaka.ui.Controls = function(player, videoContainer, video, config) {
149
149
  // Configure and create the layout of the controls
150
150
  this.configure(this.config_);
151
151
 
152
- this.updateLocalizedStrings_();
153
-
154
152
  this.addEventListeners_();
155
153
 
156
154
  /**
@@ -358,8 +356,18 @@ shaka.ui.Controls.prototype.configure = function(config) {
358
356
 
359
357
  this.castProxy_.changeReceiverId(config.castReceiverAppId);
360
358
 
359
+ // Deconstruct the old layout if applicable
360
+ if (this.seekBar_) {
361
+ this.seekBar_.destroy();
362
+ this.seekBar_ = null;
363
+ }
364
+
365
+ if (this.playButton_) {
366
+ this.playButton_.destroy();
367
+ this.playButton_ = null;
368
+ }
369
+
361
370
  if (this.controlsContainer_) {
362
- // Deconstruct the old layout if applicable
363
371
  shaka.util.Dom.removeAllChildren(this.controlsContainer_);
364
372
  this.videoContainer_.removeChild(this.spinnerContainer_);
365
373
  } else {
@@ -369,9 +377,31 @@ shaka.ui.Controls.prototype.configure = function(config) {
369
377
  // Create the new layout
370
378
  this.createDOM_();
371
379
 
372
- this.addEventListeners_();
373
- };
380
+ // Init the play state
381
+ this.onPlayStateChange_();
374
382
 
383
+ // Elements that should not propagate clicks (controls panel, menus)
384
+ const noPropagationElements = this.videoContainer_.getElementsByClassName(
385
+ 'shaka-no-propagation');
386
+ for (const element of noPropagationElements) {
387
+ const cb = (event) => event.stopPropagation();
388
+ this.eventManager_.listen(element, 'click', cb);
389
+ this.eventManager_.listen(element, 'dblclick', cb);
390
+ }
391
+
392
+ // Keep showing controls if one of those elements is hovered
393
+ const showControlsElements = this.videoContainer_.getElementsByClassName(
394
+ 'shaka-show-controls-on-mouse-over');
395
+ for (const element of showControlsElements) {
396
+ this.eventManager_.listen(element, 'mouseover', () => {
397
+ this.overrideCssShowControls_ = true;
398
+ });
399
+
400
+ this.eventManager_.listen(element, 'mouseleave', () => {
401
+ this.overrideCssShowControls_ = false;
402
+ });
403
+ }
404
+ };
375
405
 
376
406
  /**
377
407
  * Enable or disable the custom controls. Enabling disables native
@@ -405,6 +435,15 @@ shaka.ui.Controls.prototype.setEnabledShakaControls = function(enabled) {
405
435
  };
406
436
 
407
437
 
438
+ /**
439
+ * @param {boolean} seeking
440
+ * @export
441
+ */
442
+ shaka.ui.Controls.prototype.setSeeking = function(seeking) {
443
+ this.isSeeking_ = seeking;
444
+ };
445
+
446
+
408
447
  /**
409
448
  * Enable or disable native browser controls. Enabling disables shaka
410
449
  * controls.
@@ -443,6 +482,24 @@ shaka.ui.Controls.prototype.getLocalization = function() {
443
482
  return this.localization_;
444
483
  };
445
484
 
485
+ /** @export */
486
+ shaka.ui.Controls.prototype.toggleFullScreen = async function() {
487
+ if (document.fullscreenElement) {
488
+ document.exitFullscreen();
489
+ } else {
490
+ // If we are in PiP mode, leave PiP mode first.
491
+ try {
492
+ if (document.pictureInPictureElement) {
493
+ await document.exitPictureInPicture();
494
+ }
495
+ } catch (error) {
496
+ this.dispatchEvent(new shaka.util.FakeEvent('error', {
497
+ detail: error,
498
+ }));
499
+ }
500
+ await this.videoContainer_.requestFullscreen();
501
+ }
502
+ };
446
503
 
447
504
  /**
448
505
  * @return {!HTMLElement}
@@ -576,33 +633,16 @@ shaka.ui.Controls.prototype.hideSettingsMenus = function() {
576
633
  };
577
634
 
578
635
 
579
- /**
580
- * @private
581
- */
582
- shaka.ui.Controls.prototype.updateLocalizedStrings_ = function() {
583
- const LocIds = shaka.ui.Locales.Ids;
584
-
585
- // Localize state-dependant labels
586
- const makePlayNotPause = this.video_.paused && !this.isSeeking_;
587
- const playButtonAriaLabelId = makePlayNotPause ? LocIds.PLAY : LocIds.PAUSE;
588
- this.playButton_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
589
- this.localization_.resolve(playButtonAriaLabelId));
590
- };
591
-
592
-
593
636
  /**
594
637
  * @private
595
638
  */
596
639
  shaka.ui.Controls.prototype.createDOM_ = function() {
597
- if (this.seekBar_) {
598
- this.seekBar_.destroy();
599
- this.seekBar_ = null;
600
- }
601
-
602
640
  this.videoContainer_.classList.add('shaka-video-container');
603
641
  this.video_.classList.add('shaka-video');
604
642
 
605
- this.addPlayButton_();
643
+ if (this.config_.addBigPlayButton) {
644
+ this.addPlayButton_();
645
+ }
606
646
 
607
647
  this.addBufferingSpinner_();
608
648
 
@@ -645,16 +685,13 @@ shaka.ui.Controls.prototype.addControlsContainer_ = function() {
645
685
  * @private
646
686
  */
647
687
  shaka.ui.Controls.prototype.addPlayButton_ = function() {
648
- /** @private {!HTMLElement} */
649
- this.playButtonContainer_ = shaka.util.Dom.createHTMLElement('div');
650
- this.playButtonContainer_.classList.add('shaka-play-button-container');
651
- this.controlsContainer_.appendChild(this.playButtonContainer_);
688
+ const playButtonContainer = shaka.util.Dom.createHTMLElement('div');
689
+ playButtonContainer.classList.add('shaka-play-button-container');
690
+ this.controlsContainer_.appendChild(playButtonContainer);
652
691
 
653
- /** @private {!HTMLElement} */
654
- this.playButton_ = shaka.util.Dom.createHTMLElement('button');
655
- this.playButton_.classList.add('shaka-play-button');
656
- this.playButtonContainer_.appendChild(this.playButton_);
657
- this.onPlayStateChange_();
692
+ /** @private {shaka.ui.BigPlayButton} */
693
+ this.playButton_ =
694
+ new shaka.ui.BigPlayButton(playButtonContainer, this);
658
695
  };
659
696
 
660
697
 
@@ -712,6 +749,14 @@ shaka.ui.Controls.prototype.addControlsButtonPanel_ = function() {
712
749
  this.controlsButtonPanel_.classList.add('shaka-show-controls-on-mouse-over');
713
750
  this.bottomControls_.appendChild(this.controlsButtonPanel_);
714
751
 
752
+ // Overflow menus are supposed to hide once you click elsewhere
753
+ // on the video element. The code in onContainerClick_ ensures that.
754
+ // However, clicks on controls panel don't propagate to the container,
755
+ // so we have to explicitly hide the menus onclick here.
756
+ this.eventManager_.listen(this.controlsButtonPanel_, 'click', () => {
757
+ this.hideSettingsMenus();
758
+ });
759
+
715
760
  // Create the elements specified by controlPanelElements
716
761
  for (let i = 0; i < this.config_.controlPanelElements.length; i++) {
717
762
  const name = this.config_.controlPanelElements[i];
@@ -727,6 +772,30 @@ shaka.ui.Controls.prototype.addControlsButtonPanel_ = function() {
727
772
 
728
773
 
729
774
  /**
775
+ * When a mobile device is rotated to landscape layout, and the video is
776
+ * loaded, make the demo app go into fullscreen.
777
+ * Similarly, exit fullscreen when the device is rotated to portrait layout.
778
+ * @private
779
+ */
780
+ shaka.ui.Controls.prototype.onScreenRotation_ = function() {
781
+ if (!this.video_ ||
782
+ this.video_.readyState == 0 ||
783
+ this.castProxy_.isCasting()) { return; }
784
+
785
+ if (screen.orientation.type.includes('landscape') &&
786
+ !document.fullscreenElement) {
787
+ this.videoContainer_.requestFullscreen();
788
+ } else if (screen.orientation.type.includes('portrait') &&
789
+ document.fullscreenElement) {
790
+ document.exitFullscreen();
791
+ }
792
+ };
793
+
794
+
795
+ /**
796
+ * Adds static event listeners. This should only add event listeners to
797
+ * things that don't change (e.g. Player). Dynamic elements (e.g. controls)
798
+ * should have their event listeners added when they are created.
730
799
  * @private
731
800
  */
732
801
  shaka.ui.Controls.prototype.addEventListeners_ = function() {
@@ -742,6 +811,9 @@ shaka.ui.Controls.prototype.addEventListeners_ = function() {
742
811
  // for focused elements.
743
812
  this.eventManager_.listen(window, 'keydown', this.onKeyDown_.bind(this));
744
813
 
814
+ this.eventManager_.listen(
815
+ this.controlsContainer_, 'dblclick', () => this.toggleFullScreen());
816
+
745
817
  this.eventManager_.listen(this.video_,
746
818
  'play', this.onPlayStateChange_.bind(this));
747
819
  this.eventManager_.listen(this.video_,
@@ -752,32 +824,6 @@ shaka.ui.Controls.prototype.addEventListeners_ = function() {
752
824
  this.eventManager_.listen(this.video_,
753
825
  'ended', this.onPlayStateChange_.bind(this));
754
826
 
755
-
756
- // Elements that should not propagate clicks (controls panel, menus)
757
- const noPropagationElements = this.videoContainer_.getElementsByClassName(
758
- 'shaka-no-propagation');
759
- for (let i = 0; i < noPropagationElements.length; i++) {
760
- let element = noPropagationElements[i];
761
- this.eventManager_.listen(element,
762
- 'click', function(event) { event.stopPropagation(); });
763
- }
764
-
765
- // Keep showing controls if one of those elements is hovered
766
- let showControlsElements = this.videoContainer_.getElementsByClassName(
767
- 'shaka-show-controls-on-mouse-over');
768
- for (let i = 0; i < showControlsElements.length; i++) {
769
- let element = showControlsElements[i];
770
- this.eventManager_.listen(element,
771
- 'mouseover', () => {
772
- this.overrideCssShowControls_ = true;
773
- });
774
-
775
- this.eventManager_.listen(element,
776
- 'mouseleave', () => {
777
- this.overrideCssShowControls_ = false;
778
- });
779
- }
780
-
781
827
  this.eventManager_.listen(this.videoContainer_,
782
828
  'mousemove', this.onMouseMove_.bind(this));
783
829
  this.eventManager_.listen(this.videoContainer_,
@@ -787,14 +833,6 @@ shaka.ui.Controls.prototype.addEventListeners_ = function() {
787
833
  this.eventManager_.listen(this.videoContainer_,
788
834
  'mouseleave', this.onMouseLeave_.bind(this));
789
835
 
790
- // Overflow menus are supposed to hide once you click elsewhere
791
- // on the video element. The code in onContainerClick_ ensures that.
792
- // However, clicks on controls panel don't propagate to the container,
793
- // so we have to explicitly hide the menus onclick here.
794
- this.eventManager_.listen(this.controlsButtonPanel_, 'click', () => {
795
- this.hideSettingsMenusTimer_.tickNow();
796
- });
797
-
798
836
  this.eventManager_.listen(this.castProxy_,
799
837
  'caststatuschanged', (e) => {
800
838
  this.onCastStatusChange_(e);
@@ -803,13 +841,11 @@ shaka.ui.Controls.prototype.addEventListeners_ = function() {
803
841
  this.eventManager_.listen(this.videoContainer_,
804
842
  'keyup', this.onKeyUp_.bind(this));
805
843
 
806
- this.eventManager_.listen(this.localization_,
807
- shaka.ui.Localization.LOCALE_UPDATED,
808
- (e) => this.updateLocalizedStrings_());
809
-
810
- this.eventManager_.listen(this.localization_,
811
- shaka.ui.Localization.LOCALE_CHANGED,
812
- (e) => this.updateLocalizedStrings_());
844
+ if (screen.orientation) {
845
+ this.eventManager_.listen(screen.orientation, 'change', () => {
846
+ this.onScreenRotation_();
847
+ });
848
+ }
813
849
  };
814
850
 
815
851
 
@@ -988,17 +1024,6 @@ shaka.ui.Controls.prototype.onPlayStateChange_ = function() {
988
1024
  if (this.video_.ended && !this.video_.paused) {
989
1025
  this.video_.pause();
990
1026
  }
991
-
992
- // Video is paused during seek, so don't show the play arrow while seeking:
993
- if (this.enabled_ && this.video_.paused && !this.isSeeking_) {
994
- this.playButton_.setAttribute('icon', 'play');
995
- this.playButton_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
996
- this.localization_.resolve(shaka.ui.Locales.Ids.PLAY));
997
- } else {
998
- this.playButton_.setAttribute('icon', 'pause');
999
- this.playButton_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
1000
- this.localization_.resolve(shaka.ui.Locales.Ids.PAUSE));
1001
- }
1002
1027
  };
1003
1028
 
1004
1029
 
package/ui/controls.less CHANGED
@@ -22,7 +22,6 @@
22
22
  @import "less/spinner.less";
23
23
  @import "less/other_elements.less";
24
24
  @import "less/overflow_menu.less";
25
-
26
25
  @import (css, inline) "https://fonts.googleapis.com/css?family=Roboto";
27
26
  @import (css, inline) "https://fonts.googleapis.com/icon?family=Material+Icons";
28
27
 
@@ -35,6 +34,7 @@
35
34
  font-size: 150%;
36
35
  padding: 5px;
37
36
 
37
+ /* dimensions */
38
38
  bottom: 50px;
39
39
  left: 0;
40
40
  right: 0;
@@ -53,12 +53,10 @@ to make them override display setting previously set in
53
53
  .overflowMenu button.
54
54
  See https://goo.gl/egXAJY for explanation of
55
55
  how CSS cascade rules work. */
56
- button.shaka-hidden,
57
- .shaka-hidden {
56
+ button.shaka-hidden, .shaka-hidden {
58
57
  .hidden();
59
58
  }
60
59
 
61
- button.shaka-displayed,
62
- .shaka-displayed {
60
+ button.shaka-displayed, .shaka-displayed {
63
61
  display: flex;
64
62
  }
package/ui/externs/ui.js CHANGED
@@ -34,7 +34,9 @@ shaka.extern = {};
34
34
  * controlPanelElements: !Array.<string>,
35
35
  * overflowMenuButtons: !Array.<string>,
36
36
  * addSeekBar: boolean,
37
- * castReceiverAppId: string
37
+ * addBigPlayButton: boolean,
38
+ * castReceiverAppId: string,
39
+ * clearBufferOnQualityChange: boolean
38
40
  * }}
39
41
  *
40
42
  * @property {!Array.<string>} controlPanelElements
@@ -43,9 +45,19 @@ shaka.extern = {};
43
45
  * The ordered list of the overflow menu buttons.
44
46
  * @property {boolean} addSeekBar
45
47
  * Whether or not a seek bar should be part of the UI.
48
+ * @property {boolean} addBigPlayButton
49
+ * Whether or not a big play button in the center of the video
50
+ * should be part of the UI.
46
51
  * @property {string} castReceiverAppId
47
52
  * Receiver app id to use for the Chromecast support.
48
- * @exportDoc
53
+ * @property {boolean} clearBufferOnQualityChange
54
+ * Only applicable if the resolution selection is part of the UI.
55
+ * Whether buffer should be cleared when changing resolution
56
+ * via UI. Clearing buffer would result in immidiate change of quality,
57
+ * but playback may flicker/stall for a sec as the content in new
58
+ * resolution is being buffered. Not clearing the buffer will mean
59
+ * we play the content in the previously selected resolution that we
60
+ * already have buffered before switching to the new resolution.
49
61
  */
50
62
  shaka.extern.UIConfiguration;
51
63
 
@@ -51,9 +51,6 @@ shaka.ui.FullscreenButton = class extends shaka.ui.Element {
51
51
  this.parent.appendChild(this.button_);
52
52
  this.updateAriaLabel_();
53
53
 
54
- /** @private {!HTMLElement} */
55
- this.videoContainer_ = this.controls.getVideoContainer();
56
-
57
54
  this.eventManager.listen(
58
55
  this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
59
56
  this.updateAriaLabel_();
@@ -65,14 +62,8 @@ shaka.ui.FullscreenButton = class extends shaka.ui.Element {
65
62
  });
66
63
 
67
64
  this.eventManager.listen(this.button_, 'click', () => {
68
- this.toggleFullScreen_();
69
- });
70
-
71
- if (screen.orientation) {
72
- this.eventManager.listen(screen.orientation, 'change', () => {
73
- this.onScreenRotation_();
74
- });
75
- }
65
+ this.controls.toggleFullScreen();
66
+ });
76
67
 
77
68
  this.eventManager.listen(document, 'fullscreenchange', () => {
78
69
  this.updateIcon_();
@@ -101,47 +92,6 @@ shaka.ui.FullscreenButton = class extends shaka.ui.Element {
101
92
  shaka.ui.Enums.MaterialDesignIcons.EXIT_FULLSCREEN :
102
93
  shaka.ui.Enums.MaterialDesignIcons.FULLSCREEN;
103
94
  }
104
-
105
- /**
106
- * @private
107
- */
108
- async toggleFullScreen_() {
109
- if (document.fullscreenElement) {
110
- document.exitFullscreen();
111
- } else {
112
- // If you are in PiP mode, leave PiP mode first.
113
- try {
114
- if (document.pictureInPictureElement) {
115
- await document.exitPictureInPicture();
116
- }
117
- } catch (error) {
118
- this.controls.dispatchEvent(new shaka.util.FakeEvent('error', {
119
- detail: error,
120
- }));
121
- }
122
- await this.videoContainer_.requestFullscreen();
123
- }
124
- }
125
-
126
- /**
127
- * When a mobile device is rotated to landscape layout, and the video is
128
- * loaded, make the demo app go into fullscreen.
129
- * Similarly, exit fullscreen when the device is rotated to portrait layout.
130
- * @private
131
- */
132
- onScreenRotation_() {
133
- if (!this.video ||
134
- this.video.readyState == 0 ||
135
- this.controls.getCastProxy().isCasting()) return;
136
-
137
- if (screen.orientation.type.includes('landscape') &&
138
- !document.fullscreenElement) {
139
- this.videoContainer_.requestFullscreen();
140
- } else if (screen.orientation.type.includes('portrait') &&
141
- document.fullscreenElement) {
142
- document.exitFullscreen();
143
- }
144
- }
145
95
  };
146
96
 
147
97
 
@@ -41,7 +41,7 @@
41
41
  border-radius: 50%;
42
42
 
43
43
  /* A small drop shadow below the button. */
44
- box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 20px 0px;
44
+ box-shadow: rgba(0, 0, 0, 0.1) 0 0 20px 0;
45
45
 
46
46
  /* No border. */
47
47
  border: none;
@@ -52,8 +52,9 @@
52
52
  background-size: 50%;
53
53
  background-repeat: no-repeat;
54
54
  background-position: center center;
55
+
55
56
  /* A background color behind the play arrow. */
56
- background-color: rgba(255, 255, 255, .9);
57
+ background-color: rgba(255, 255, 255, 0.9);
57
58
 
58
59
  /* Actual icon images for the two states this could be in.
59
60
  * These will be inlined as data URIs when compiled, and so do not need to be
@@ -62,6 +63,7 @@
62
63
  &[icon="play"] {
63
64
  background-image: data-uri('images/play_arrow.svg');
64
65
  }
66
+
65
67
  &[icon="pause"] {
66
68
  background-image: data-uri('images/pause.svg');
67
69
  }
@@ -91,11 +93,11 @@
91
93
 
92
94
  /* Use a consistent outline focus style across browsers. */
93
95
  .shaka-controls-container {
94
- button:focus,
95
- input:focus {
96
+ button:focus, input:focus {
96
97
  /* Most browsers will fall back to "Highlight" (system setting) color for
97
98
  * the focus outline. */
98
99
  outline: 1px solid Highlight;
100
+
99
101
  /* WebKit-based and Blink-based browsers have this as their default outline
100
102
  * color. */
101
103
  outline: 1px solid -webkit-focus-ring-color;
@@ -103,8 +105,7 @@
103
105
 
104
106
  /* Disable this Mozilla-specific focus ring, since we have an outline defined
105
107
  * for focus. */
106
- button::-moz-focus-inner,
107
- input::-moz-focus-outer {
108
+ button:-moz-focus-inner, input:-moz-focus-outer {
108
109
  outline: none;
109
110
  border: 0;
110
111
  }
@@ -114,8 +115,7 @@
114
115
  * it doesn't look great. This removes the outline for
115
116
  * mouse users while leaving it for keyboard users. */
116
117
  .shaka-controls-container:not(.shaka-keyboard-navigation) {
117
- button:focus,
118
- input:focus {
118
+ button:focus, input:focus {
119
119
  outline: none;
120
120
  border: 0;
121
121
  }
@@ -17,6 +17,8 @@
17
17
 
18
18
  /* All of the top-level containers into which various visible features go. */
19
19
 
20
+ @transparent: rgba(0, 0, 0, 0);
21
+
20
22
  /* A container for the entire video + controls combo. This is the auto-setup
21
23
  * div which we populate. */
22
24
  .shaka-video-container {
@@ -31,6 +33,7 @@
31
33
  .material-icons {
32
34
  font-family: 'Material Icons';
33
35
  }
36
+
34
37
  * {
35
38
  font-family: Roboto-Regular, Roboto, sans-serif;
36
39
  }
@@ -44,12 +47,14 @@
44
47
  * pseudo-class they don't support. */
45
48
  .fullscreen-container() {
46
49
  .fill-container();
50
+
47
51
  background-color: black;
48
52
 
49
53
  .shaka-text-container {
50
54
  /* In fullscreen mode, the text displayer's font size should be relative to
51
- * the window height instead of a fixed size. */
52
- font-size: 4.4vh;
55
+ * the either window height or width (whichever is smaller), instead of a
56
+ * fixed size. */
57
+ font-size: 4.4vmin;
53
58
  }
54
59
  }
55
60
  .shaka-video-container:fullscreen { .fullscreen-container(); }
@@ -77,18 +82,18 @@
77
82
 
78
83
  /* A flex container, to make layout of children easier to reason about. */
79
84
  display: flex;
85
+
80
86
  /* Defines in which direction the children should flow. */
81
87
  flex-direction: column;
88
+
82
89
  /* Pushes the children toward the bottom of the container. */
83
90
  justify-content: flex-end;
91
+
84
92
  /* Centers children horizontally. */
85
93
  align-items: center;
86
94
 
87
95
  /* A black gradient at the bottom, behind the controls, but only so high. */
88
- background: linear-gradient(
89
- to top,
90
- rgba(0, 0, 0, 1) 0,
91
- rgba(0, 0, 0, 0) 92px);
96
+ background: linear-gradient(to top, rgba(0, 0, 0, 1) 0, @transparent 92px);
92
97
 
93
98
  /* By default, do not allow any of our controls to shrink.
94
99
  * Specific controls can use .shrinkable() to override. */
@@ -98,7 +103,7 @@
98
103
  opacity: 0;
99
104
 
100
105
  /* When we show/hide this, do it gradually using cubic-bezier timing. */
101
- transition: opacity cubic-bezier(0.4, 0.0, 0.6, 1) 600ms;
106
+ transition: opacity cubic-bezier(0.4, 0, 0.6, 1) 600ms;
102
107
 
103
108
  /* Position the controls container in front of the text container, so that
104
109
  * the text container doesn't interfere with the control buttons. */
@@ -119,7 +124,6 @@
119
124
  }
120
125
  }
121
126
 
122
-
123
127
  /* Container for controls positioned at the bottom of the video container:
124
128
  * controls button panel and the seek bar. */
125
129
  .shaka-bottom-controls {
@@ -148,8 +152,10 @@
148
152
  /* This is itself a flex container, with children layed out horizontally. */
149
153
  display: flex;
150
154
  flex-direction: row;
155
+
151
156
  /* Push children to the right. */
152
157
  justify-content: flex-end;
158
+
153
159
  /* Center children vertically. */
154
160
  align-items: center;
155
161
 
@@ -196,24 +202,21 @@
196
202
  margin: 0;
197
203
  .fill-container();
198
204
  .shrinkable();
205
+ .absolute-position();
199
206
 
200
207
  /* Keep the play button in the middle of this container. */
201
208
  display: flex;
202
209
  justify-content: center;
203
210
  align-items: center;
204
- position: absolute;
205
- /* Specify left and top for IE's sake. Otherwise, the container ends up below
206
- * and to the right of where it should be. */
207
- top: 0;
208
- left: 0;
209
211
  }
210
212
 
211
213
  .shaka-text-container {
214
+ .absolute-position();
215
+
212
216
  bottom: 15%;
213
- top: 0;
214
- left: 0;
215
217
  width: 100%;
216
218
  min-width: 48px;
219
+ text-align: center;
217
220
 
218
221
  /* Set the captions in the middle horizontally by default. */
219
222
  display: flex;
@@ -226,9 +229,6 @@
226
229
  * overflow content. */
227
230
  overflow: hidden;
228
231
 
229
- text-align: center;
230
- position: absolute;
231
-
232
232
  /* These are defaults which are overridden by JS or cue styles. */
233
233
  font-size: 20px;
234
234
  line-height: 1.4; // relative to font size.
@@ -242,10 +242,9 @@
242
242
  }
243
243
  }
244
244
 
245
-
246
245
  /* The buffering spinner. */
247
246
  .shaka-spinner-container {
248
- position: absolute;
247
+ .absolute-position();
249
248
  .fill-container();
250
249
 
251
250
  flex-shrink: 1;
@@ -262,8 +261,9 @@
262
261
  for the detailed explanation. */
263
262
 
264
263
  /* For the padding thing to work, spinner div needs to be an
265
- overlay-parent and spinner svg - an overlay child.*/
264
+ overlay-parent and spinner svg - an overlay child. */
266
265
  .overlay-parent();
266
+
267
267
  margin: 0;
268
268
  box-sizing: border-box;
269
269
  padding: @spinner-size-percentage / 2;
@@ -77,6 +77,17 @@
77
77
  .fill-container();
78
78
  }
79
79
 
80
+ .absolute-position() {
81
+ /* When setting "position: absolute" it uses the left,right,top,bottom
82
+ * properties to determine the positioning. We should set all these
83
+ * properties to ensure it is positioned properly on all platforms. */
84
+ position: absolute;
85
+ left: 0;
86
+ right: 0;
87
+ top: 0;
88
+ bottom: 0;
89
+ }
90
+
80
91
  /* For things that should not shrink inside a flex container.
81
92
  * This will be used for all controls by default. */
82
93
  .unshrinkable() {
@@ -29,6 +29,7 @@
29
29
  /* Make the element grow to take up the remaining space. */
30
30
  flex-grow: 1;
31
31
 
32
- /* Margins don't shrink. Remove margins in order to be more flexible when shrinking. */
32
+ /* Margins don't shrink. Remove margins in order to be more flexible when
33
+ * shrinking. */
33
34
  margin: 0;
34
35
  }