shaka-player 2.5.1 → 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 (166) hide show
  1. package/.csslintrc +13 -0
  2. package/AUTHORS +3 -0
  3. package/CHANGELOG.md +156 -0
  4. package/CONTRIBUTORS +3 -0
  5. package/README.md +3 -0
  6. package/build/README.md +5 -5
  7. package/build/apps.py +3 -1
  8. package/build/build.py +5 -2
  9. package/build/check.py +17 -0
  10. package/build/compiler.py +49 -0
  11. package/build/conformance.textproto +1 -0
  12. package/build/docs.py +0 -6
  13. package/build/generateExterns.js +72 -20
  14. package/build/install-linux-prereqs.sh +4 -4
  15. package/build/shakaBuildHelpers.py +7 -8
  16. package/build/test.py +21 -9
  17. package/build/types/core +1 -0
  18. package/build/types/ui +6 -1
  19. package/demo/asset_card.js +129 -41
  20. package/demo/cast_receiver/receiver_app.css +27 -13
  21. package/demo/close_button.js +10 -15
  22. package/demo/common/asset.js +6 -6
  23. package/demo/common/assets.js +72 -14
  24. package/demo/config.js +28 -25
  25. package/demo/custom.js +20 -16
  26. package/demo/demo.less +107 -16
  27. package/demo/demo_uncompiled.js +33 -0
  28. package/demo/demo_utils.js +4 -3
  29. package/demo/front.js +12 -8
  30. package/demo/index.html +14 -17
  31. package/demo/input.js +30 -23
  32. package/demo/input_container.js +15 -11
  33. package/demo/load.js +5 -7
  34. package/demo/main.js +138 -49
  35. package/demo/search.js +40 -36
  36. package/demo/service_worker.js +1 -1
  37. package/demo/tooltip.js +16 -24
  38. package/dist/.csslintstamp +0 -0
  39. package/dist/controls.css +1 -1
  40. package/dist/controls.css.map +1 -1
  41. package/dist/demo.compiled.debug.js +165 -152
  42. package/dist/demo.compiled.debug.map +4 -4
  43. package/dist/demo.compiled.js +165 -152
  44. package/dist/demo.compiled.map +4 -4
  45. package/dist/demo.css +1 -1
  46. package/dist/demo.css.map +1 -1
  47. package/dist/deps.js +28 -11
  48. package/dist/receiver.compiled.debug.js +11 -11
  49. package/dist/receiver.compiled.debug.map +3 -3
  50. package/dist/receiver.compiled.js +11 -11
  51. package/dist/receiver.compiled.map +3 -3
  52. package/dist/shaka-player.compiled.debug.externs.js +232 -102
  53. package/dist/shaka-player.compiled.debug.js +189 -165
  54. package/dist/shaka-player.compiled.debug.map +4 -4
  55. package/dist/shaka-player.compiled.externs.js +232 -102
  56. package/dist/shaka-player.compiled.js +567 -553
  57. package/dist/shaka-player.compiled.map +4 -4
  58. package/dist/shaka-player.ui.debug.externs.js +338 -113
  59. package/dist/shaka-player.ui.debug.js +296 -276
  60. package/dist/shaka-player.ui.debug.map +4 -4
  61. package/dist/shaka-player.ui.externs.js +338 -113
  62. package/dist/shaka-player.ui.js +685 -671
  63. package/dist/shaka-player.ui.map +4 -4
  64. package/docs/tutorials/drm-config.md +1 -0
  65. package/docs/tutorials/fairplay.md +77 -0
  66. package/docs/tutorials/index.json +1 -0
  67. package/docs/tutorials/manifest-parser.md +1 -1
  68. package/docs/tutorials/ui-customization.md +5 -2
  69. package/docs/tutorials/ui.md +10 -4
  70. package/docs/tutorials/welcome.md +2 -2
  71. package/externs/mediasession.js +16 -1
  72. package/externs/shaka/net.js +14 -4
  73. package/externs/shaka/player.js +136 -90
  74. package/externs/tippy.js +30 -0
  75. package/externs/webkitmediakeys.js +4 -0
  76. package/karma.conf.js +30 -24
  77. package/lib/cast/cast_proxy.js +94 -23
  78. package/lib/cast/cast_receiver.js +8 -1
  79. package/lib/dash/content_protection.js +33 -1
  80. package/lib/dash/dash_parser.js +13 -5
  81. package/lib/hls/hls_parser.js +20 -4
  82. package/lib/media/drm_engine.js +29 -2
  83. package/lib/media/media_source_engine.js +9 -6
  84. package/lib/media/play_rate_controller.js +14 -3
  85. package/lib/media/playhead.js +8 -3
  86. package/lib/media/streaming_engine.js +68 -20
  87. package/lib/media/transmuxer.js +2 -2
  88. package/lib/media/video_wrapper.js +8 -3
  89. package/lib/net/data_uri_plugin.js +5 -2
  90. package/lib/net/http_fetch_plugin.js +3 -3
  91. package/lib/net/http_plugin_utils.js +2 -4
  92. package/lib/net/http_xhr_plugin.js +2 -2
  93. package/lib/net/networking_engine.js +1 -0
  94. package/lib/offline/offline_scheme.js +7 -2
  95. package/lib/player.js +18 -8
  96. package/lib/polyfill/input_event.js +7 -11
  97. package/lib/polyfill/mediasource.js +1 -1
  98. package/lib/polyfill/patchedmediakeys_apple.js +2 -72
  99. package/lib/text/cue.js +1 -1
  100. package/lib/text/ttml_text_parser.js +1 -1
  101. package/lib/util/config_utils.js +1 -0
  102. package/lib/util/error.js +45 -11
  103. package/lib/util/event_manager.js +211 -100
  104. package/lib/util/fairplay_utils.js +122 -0
  105. package/lib/util/i_releasable.js +1 -0
  106. package/lib/util/player_configuration.js +7 -0
  107. package/lib/util/pssh.js +41 -0
  108. package/lib/util/string_utils.js +42 -6
  109. package/lib/util/timer.js +1 -1
  110. package/package.json +33 -33
  111. package/roadmap.md +96 -0
  112. package/shaka-player.uncompiled.js +5 -1
  113. package/test/dash/dash_parser_content_protection_unit.js +35 -1
  114. package/test/dash/dash_parser_manifest_unit.js +60 -0
  115. package/test/hls/hls_live_unit.js +7 -1
  116. package/test/hls/hls_parser_unit.js +50 -0
  117. package/test/media/drm_engine_unit.js +10 -4
  118. package/test/media/media_source_engine_integration.js +12 -0
  119. package/test/media/media_source_engine_unit.js +3 -1
  120. package/test/media/playhead_unit.js +7 -5
  121. package/test/media/streaming_engine_unit.js +46 -1
  122. package/test/media/transmuxer_integration.js +13 -0
  123. package/test/net/data_uri_plugin_unit.js +13 -2
  124. package/test/net/http_plugin_unit.js +17 -12
  125. package/test/net/networking_engine_unit.js +17 -8
  126. package/test/offline/offline_scheme_unit.js +18 -8
  127. package/test/player_external.js +3 -2
  128. package/test/player_integration.js +94 -3
  129. package/test/player_src_equals_integration.js +2 -2
  130. package/test/player_unit.js +21 -8
  131. package/test/test/boot.js +20 -5
  132. package/test/test/externs/jasmine.js +48 -0
  133. package/test/test/util/expect_async_polyfill.js +145 -0
  134. package/test/test/util/fake_networking_engine.js +1 -0
  135. package/test/test/util/manifest_generator.js +2 -1
  136. package/test/test/util/test_scheme.js +34 -2
  137. package/test/test/util/ui_utils.js +41 -0
  138. package/test/test/util/util.js +16 -8
  139. package/test/ui/ui_unit.js +130 -4
  140. package/ui/audio_language_selection.js +17 -96
  141. package/ui/big_play_button.js +61 -0
  142. package/ui/controls.js +226 -335
  143. package/ui/controls.less +3 -5
  144. package/ui/element.js +24 -6
  145. package/ui/externs/ui.js +62 -9
  146. package/ui/fullscreen_button.js +2 -52
  147. package/ui/less/buttons.less +10 -16
  148. package/ui/less/containers.less +75 -20
  149. package/ui/less/general.less +18 -2
  150. package/ui/less/other_elements.less +2 -1
  151. package/ui/less/overflow_menu.less +11 -10
  152. package/ui/less/range_elements.less +12 -10
  153. package/ui/less/spinner.less +2 -0
  154. package/ui/overflow_menu.js +1 -1
  155. package/ui/pip_button.js +1 -1
  156. package/ui/{play_pause_button.js → play_button.js} +17 -47
  157. package/ui/presentation_time.js +17 -12
  158. package/ui/range_element.js +176 -0
  159. package/ui/resolution_selection.js +43 -106
  160. package/ui/seek_bar.js +204 -0
  161. package/ui/settings_menu.js +113 -0
  162. package/ui/small_play_button.js +73 -0
  163. package/ui/text_displayer.js +17 -14
  164. package/ui/text_selection.js +42 -107
  165. package/ui/ui.js +17 -40
  166. package/ui/volume_bar.js +40 -68
@@ -198,8 +198,8 @@ shaka.ui.TextDisplayer = class {
198
198
  const captionsStyle = captions.style;
199
199
  const panelStyle = this.textContainer_.style;
200
200
 
201
- // Set white-space to 'pre' to enable showing line breaks in the text.
202
- captionsStyle.whiteSpace = 'pre';
201
+ // Set white-space to 'pre-line' to enable showing line breaks in the text.
202
+ captionsStyle.whiteSpace = 'pre-line';
203
203
  captions.textContent = cue.payload;
204
204
  captionsStyle.backgroundColor = cue.backgroundColor;
205
205
  captionsStyle.color = cue.color;
@@ -210,6 +210,9 @@ shaka.ui.TextDisplayer = class {
210
210
  captionsStyle.backgroundRepeat = 'no-repeat';
211
211
  captionsStyle.backgroundSize = 'contain';
212
212
  captionsStyle.backgroundPosition = 'center';
213
+ if (cue.backgroundColor == '') {
214
+ captionsStyle.backgroundColor = 'transparent';
215
+ }
213
216
  }
214
217
  if (cue.backgroundImage && cue.region) {
215
218
  const percentageUnit = shaka.text.CueRegion.units.PERCENTAGE;
@@ -256,21 +259,21 @@ shaka.ui.TextDisplayer = class {
256
259
  if (cue.lineInterpretation == Cue.lineInterpretation.PERCENTAGE) {
257
260
  if (cue.writingMode == Cue.writingMode.HORIZONTAL_TOP_TO_BOTTOM) {
258
261
  if (cue.lineAlign == Cue.lineAlign.START) {
259
- this.textContainer_.top = cue.line + '%';
262
+ panelStyle.top = cue.line + '%';
260
263
  } else if (cue.lineAlign == Cue.lineAlign.END) {
261
- this.textContainer_.bottom = cue.line + '%';
264
+ panelStyle.bottom = cue.line + '%';
262
265
  }
263
266
  } else if (cue.writingMode == Cue.writingMode.VERTICAL_LEFT_TO_RIGHT) {
264
267
  if (cue.lineAlign == Cue.lineAlign.START) {
265
- this.textContainer_.left = cue.line + '%';
268
+ panelStyle.left = cue.line + '%';
266
269
  } else if (cue.lineAlign == Cue.lineAlign.END) {
267
- this.textContainer_.right = cue.line + '%';
270
+ panelStyle.right = cue.line + '%';
268
271
  }
269
272
  } else {
270
273
  if (cue.lineAlign == Cue.lineAlign.START) {
271
- this.textContainer_.right = cue.line + '%';
274
+ panelStyle.right = cue.line + '%';
272
275
  } else if (cue.lineAlign == Cue.lineAlign.END) {
273
- this.textContainer_.left = cue.line + '%';
276
+ panelStyle.left = cue.line + '%';
274
277
  }
275
278
  }
276
279
  }
@@ -282,18 +285,18 @@ shaka.ui.TextDisplayer = class {
282
285
  // direction defined by the writing direction.
283
286
  if (cue.position) {
284
287
  if (cue.writingMode == Cue.writingMode.HORIZONTAL_TOP_TO_BOTTOM) {
285
- this.textContainer_.paddingLeft = cue.position;
288
+ panelStyle.paddingLeft = cue.position;
286
289
  } else {
287
- this.textContainer_.paddingTop = cue.position;
290
+ panelStyle.paddingTop = cue.position;
288
291
  }
289
292
  }
290
293
 
291
294
  // The positionAlign attribute is an alignment for the text container in
292
295
  // the dimension of the writing direction.
293
296
  if (cue.positionAlign == Cue.positionAlign.LEFT) {
294
- panelStyle.float = 'left';
297
+ panelStyle.cssFloat = 'left';
295
298
  } else if (cue.positionAlign == Cue.positionAlign.RIGHT) {
296
- panelStyle.float = 'right';
299
+ panelStyle.cssFloat = 'right';
297
300
  } else {
298
301
  panelStyle.margin = 'auto';
299
302
  }
@@ -306,9 +309,9 @@ shaka.ui.TextDisplayer = class {
306
309
  // interpreted as a percentage of the video, as defined by the writing
307
310
  // direction.
308
311
  if (cue.writingMode == Cue.writingMode.HORIZONTAL_TOP_TO_BOTTOM) {
309
- this.textContainer_.width = cue.size + '%';
312
+ panelStyle.width = cue.size + '%';
310
313
  } else {
311
- this.textContainer_.height = cue.size + '%';
314
+ panelStyle.height = cue.size + '%';
312
315
  }
313
316
  }
314
317
  };
@@ -18,31 +18,39 @@
18
18
 
19
19
  goog.provide('shaka.ui.TextSelection');
20
20
 
21
- goog.require('shaka.ui.Element');
22
21
  goog.require('shaka.ui.Enums');
23
22
  goog.require('shaka.ui.LanguageUtils');
24
23
  goog.require('shaka.ui.Locales');
25
24
  goog.require('shaka.ui.Localization');
26
25
  goog.require('shaka.ui.OverflowMenu');
26
+ goog.require('shaka.ui.SettingsMenu');
27
27
  goog.require('shaka.util.Dom');
28
28
 
29
29
 
30
30
  /**
31
- * @extends {shaka.ui.Element}
31
+ * @extends {shaka.ui.SettingsMenu}
32
32
  * @final
33
33
  * @export
34
34
  */
35
- shaka.ui.TextSelection = class extends shaka.ui.Element {
35
+ shaka.ui.TextSelection = class extends shaka.ui.SettingsMenu {
36
36
  /**
37
37
  * @param {!HTMLElement} parent
38
38
  * @param {!shaka.ui.Controls} controls
39
39
  */
40
40
  constructor(parent, controls) {
41
- super(parent, controls);
41
+ super(parent,
42
+ controls, shaka.ui.Enums.MaterialDesignIcons.CLOSED_CAPTIONS);
42
43
 
43
- this.addCaptionButton_();
44
+ this.button.classList.add('shaka-caption-button');
45
+ this.menu.classList.add('shaka-text-languages');
44
46
 
45
- this.addTextLangMenu_();
47
+ if (this.player && this.player.isTextTrackVisible()) {
48
+ this.button.setAttribute('aria-pressed', 'true');
49
+ } else {
50
+ this.button.setAttribute('aria-pressed', 'false');
51
+ }
52
+
53
+ this.addOffOption_();
46
54
 
47
55
  this.eventManager.listen(
48
56
  this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
@@ -66,10 +74,6 @@ shaka.ui.TextSelection = class extends shaka.ui.Element {
66
74
  this.onCaptionStateChange_();
67
75
  });
68
76
 
69
- this.eventManager.listen(this.captionButton_, 'click', () => {
70
- this.onCaptionClick_();
71
- });
72
-
73
77
  this.eventManager.listen(this.player, 'textchanged', () => {
74
78
  this.updateTextLanguages_();
75
79
  });
@@ -91,70 +95,10 @@ shaka.ui.TextSelection = class extends shaka.ui.Element {
91
95
  /**
92
96
  * @private
93
97
  */
94
- addCaptionButton_() {
95
- /** @private {!HTMLElement} */
96
- this.captionButton_ = shaka.util.Dom.createHTMLElement('button');
97
- this.captionButton_.classList.add('shaka-caption-button');
98
-
99
- /** @private {!HTMLElement} */
100
- this.captionIcon_ = shaka.util.Dom.createHTMLElement('i');
101
- this.captionIcon_.classList.add('material-icons');
102
- this.captionIcon_.textContent =
103
- shaka.ui.Enums.MaterialDesignIcons.CLOSED_CAPTIONS;
104
-
105
- if (this.player && this.player.isTextTrackVisible()) {
106
- this.captionButton_.setAttribute('aria-pressed', 'true');
107
- } else {
108
- this.captionButton_.setAttribute('aria-pressed', 'false');
109
- }
110
- this.captionButton_.appendChild(this.captionIcon_);
111
-
112
- const label = shaka.util.Dom.createHTMLElement('label');
113
- label.classList.add('shaka-overflow-button-label');
114
-
115
- /** @private {!HTMLElement} */
116
- this.captionsNameSpan_ = shaka.util.Dom.createHTMLElement('span');
117
-
118
- label.appendChild(this.captionsNameSpan_);
119
-
120
- /** @private {!HTMLElement} */
121
- this.currentCaptions_ = shaka.util.Dom.createHTMLElement('span');
122
- this.currentCaptions_.classList.add('shaka-current-selection-span');
123
- label.appendChild(this.currentCaptions_);
124
- this.captionButton_.appendChild(label);
125
- this.parent.appendChild(this.captionButton_);
126
- }
127
-
128
-
129
- /**
130
- * @private
131
- */
132
- addTextLangMenu_() {
133
- /** @private {!HTMLElement} */
134
- this.textLangMenu_ = shaka.util.Dom.createHTMLElement('div');
135
- this.textLangMenu_.classList.add('shaka-text-languages');
136
- this.textLangMenu_.classList.add('shaka-no-propagation');
137
- this.textLangMenu_.classList.add('shaka-show-controls-on-mouse-over');
138
- this.textLangMenu_.classList.add('shaka-settings-menu');
139
-
140
- /** @private {!HTMLElement} */
141
- this.backFromCaptionsButton_ = shaka.util.Dom.createHTMLElement('button');
142
- this.backFromCaptionsButton_.classList.add('shaka-back-to-overflow-button');
143
- this.textLangMenu_.appendChild(this.backFromCaptionsButton_);
144
-
145
- const backIcon = shaka.util.Dom.createHTMLElement('i');
146
- backIcon.classList.add('material-icons');
147
- backIcon.textContent = shaka.ui.Enums.MaterialDesignIcons.BACK;
148
- this.backFromCaptionsButton_.appendChild(backIcon);
149
-
150
- /** @private {!HTMLElement} */
151
- this.backFromCaptionsSpan_ = shaka.util.Dom.createHTMLElement('span');
152
- this.backFromCaptionsButton_.appendChild(this.backFromCaptionsSpan_);
153
-
154
- // Add the off option
98
+ addOffOption_() {
155
99
  const off = shaka.util.Dom.createHTMLElement('button');
156
100
  off.setAttribute('aria-selected', 'true');
157
- this.textLangMenu_.appendChild(off);
101
+ this.menu.appendChild(off);
158
102
 
159
103
  off.appendChild(shaka.ui.Utils.checkmarkIcon());
160
104
 
@@ -163,31 +107,19 @@ shaka.ui.TextSelection = class extends shaka.ui.Element {
163
107
 
164
108
  this.captionsOffSpan_.classList.add('shaka-auto-span');
165
109
  off.appendChild(this.captionsOffSpan_);
166
-
167
- const controlsContainer = this.controls.getControlsContainer();
168
- controlsContainer.appendChild(this.textLangMenu_);
169
- }
170
-
171
-
172
- /** @private */
173
- onCaptionClick_() {
174
- this.controls.dispatchEvent(new shaka.util.FakeEvent('submenuopen'));
175
- shaka.ui.Utils.setDisplay(this.textLangMenu_, true);
176
- // Focus on the currently selected language button.
177
- shaka.ui.Utils.focusOnTheChosenItem(this.textLangMenu_);
178
110
  }
179
111
 
180
112
 
181
113
  /** @private */
182
114
  onCaptionStateChange_() {
183
115
  if (this.player.isTextTrackVisible()) {
184
- this.captionIcon_.classList.add('shaka-captions-on');
185
- this.captionIcon_.classList.remove('shaka-captions-off');
186
- this.captionButton_.setAttribute('aria-pressed', 'true');
116
+ this.icon.classList.add('shaka-captions-on');
117
+ this.icon.classList.remove('shaka-captions-off');
118
+ this.button.setAttribute('aria-pressed', 'true');
187
119
  } else {
188
- this.captionIcon_.classList.add('shaka-captions-off');
189
- this.captionIcon_.classList.remove('shaka-captions-on');
190
- this.captionButton_.setAttribute('aria-pressed', 'false');
120
+ this.icon.classList.add('shaka-captions-off');
121
+ this.icon.classList.remove('shaka-captions-on');
122
+ this.button.setAttribute('aria-pressed', 'false');
191
123
  }
192
124
 
193
125
  // TODO: document this event
@@ -204,35 +136,38 @@ shaka.ui.TextSelection = class extends shaka.ui.Element {
204
136
  return langAndRole.language;
205
137
  });
206
138
 
207
- shaka.ui.LanguageUtils.updateLanguages(tracks, this.textLangMenu_,
208
- languages,
209
- this.onTextLanguageSelected_.bind(this),
210
- // Don't mark current text language as chosen unless captions are enabled
211
- this.player.isTextTrackVisible(),
212
- this.currentCaptions_,
213
- this.localization);
139
+ shaka.ui.LanguageUtils.updateLanguages(tracks, this.menu,
140
+ languages,
141
+ (lang) => this.onTextLanguageSelected_(lang),
142
+
143
+ // Don't mark current text language as chosen unless captions are
144
+ // enabled
145
+ this.player.isTextTrackVisible(),
146
+ this.currentSelection,
147
+ this.localization);
214
148
 
215
149
  // Add the Off button
216
150
  const offButton = shaka.util.Dom.createHTMLElement('button');
217
151
  offButton.classList.add('shaka-turn-captions-off-button');
218
- offButton.addEventListener('click', () => {
219
- this.player.setTextTrackVisibility(false);
152
+ this.eventManager.listen(offButton, 'click', () => {
153
+ const p = this.player.setTextTrackVisibility(false);
154
+ p.catch(() => {}); // TODO(#1993): Handle possible errors.
220
155
  this.updateTextLanguages_();
221
156
  });
222
157
 
223
158
  offButton.appendChild(this.captionsOffSpan_);
224
159
 
225
- this.textLangMenu_.appendChild(offButton);
160
+ this.menu.appendChild(offButton);
226
161
 
227
162
  if (!this.player.isTextTrackVisible()) {
228
163
  offButton.setAttribute('aria-selected', 'true');
229
164
  offButton.appendChild(shaka.ui.Utils.checkmarkIcon());
230
165
  this.captionsOffSpan_.classList.add('shaka-chosen-item');
231
- this.currentCaptions_.textContent =
166
+ this.currentSelection.textContent =
232
167
  this.localization.resolve(shaka.ui.Locales.Ids.OFF);
233
168
  }
234
169
 
235
- shaka.ui.Utils.focusOnTheChosenItem(this.textLangMenu_);
170
+ shaka.ui.Utils.focusOnTheChosenItem(this.menu);
236
171
 
237
172
  // TODO: document this event
238
173
  this.controls.dispatchEvent(
@@ -259,13 +194,13 @@ shaka.ui.TextSelection = class extends shaka.ui.Element {
259
194
  updateLocalizedStrings_() {
260
195
  const LocIds = shaka.ui.Locales.Ids;
261
196
 
262
- this.captionButton_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
197
+ this.button.setAttribute(shaka.ui.Constants.ARIA_LABEL,
263
198
  this.localization.resolve(LocIds.CAPTIONS));
264
- this.backFromCaptionsButton_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
199
+ this.backButton.setAttribute(shaka.ui.Constants.ARIA_LABEL,
265
200
  this.localization.resolve(LocIds.BACK));
266
- this.captionsNameSpan_.textContent =
201
+ this.nameSpan.textContent =
267
202
  this.localization.resolve(LocIds.CAPTIONS);
268
- this.backFromCaptionsSpan_.textContent =
203
+ this.backSpan.textContent =
269
204
  this.localization.resolve(LocIds.CAPTIONS);
270
205
  this.captionsOffSpan_.textContent =
271
206
  this.localization.resolve(LocIds.OFF);
@@ -275,7 +210,7 @@ shaka.ui.TextSelection = class extends shaka.ui.Element {
275
210
  /** @private */
276
211
  onTracksChanged_() {
277
212
  const hasText = this.player.getTextTracks().length > 0;
278
- shaka.ui.Utils.setDisplay(this.captionButton_, hasText);
213
+ shaka.ui.Utils.setDisplay(this.button, hasText);
279
214
  this.updateTextLanguages_();
280
215
  }
281
216
  };
package/ui/ui.js CHANGED
@@ -38,12 +38,6 @@ shaka.ui.Overlay = function(player, videoContainer, video) {
38
38
  /** @private {shaka.Player} */
39
39
  this.player_ = player;
40
40
 
41
- /** @private {!HTMLElement} */
42
- this.videoContainer_ = videoContainer;
43
-
44
- /** @private {!HTMLMediaElement} */
45
- this.video_ = video;
46
-
47
41
  /** @private {!shaka.extern.UIConfiguration} */
48
42
  this.config_ = this.defaultConfig_();
49
43
 
@@ -57,6 +51,10 @@ shaka.ui.Overlay = function(player, videoContainer, video) {
57
51
  videoContainer.classList.add('shaka-mobile');
58
52
  }
59
53
 
54
+ /** @private {shaka.ui.Controls} */
55
+ this.controls_ = new shaka.ui.Controls(
56
+ player, videoContainer, video, this.config_);
57
+
60
58
  // Run the initial setup so that no configure() call is required for default
61
59
  // settings.
62
60
  this.configure({});
@@ -120,28 +118,6 @@ shaka.ui.Overlay.prototype.configure = function(config, value) {
120
118
 
121
119
  goog.asserts.assert(typeof(config) == 'object', 'Should be an object!');
122
120
 
123
- const DomUtils = shaka.util.Dom;
124
- // Deconstruct the old layout.
125
-
126
- // Save the text container, so subtitles can be displayed with
127
- // the new layout.
128
- const textContainer =
129
- this.videoContainer_.querySelector('.shaka-text-container');
130
-
131
- // Remember whether the controls were shown
132
- let shown = false;
133
- let controlsContainer =
134
- this.videoContainer_.querySelector('.shaka-controls-container');
135
- if (controlsContainer != null) {
136
- shown = controlsContainer.getAttribute('shown');
137
- }
138
-
139
- // Destroy the old layout.
140
- shaka.util.Dom.removeAllChildren(this.videoContainer_);
141
-
142
- // Add the video back in
143
- this.videoContainer_.appendChild(this.video_);
144
-
145
121
  shaka.util.ConfigUtils.mergeConfigObjects(
146
122
  this.config_, config, this.defaultConfig_(),
147
123
  /* overrides (only used for player config)*/ {}, /* path */ '');
@@ -154,18 +130,7 @@ shaka.ui.Overlay.prototype.configure = function(config, value) {
154
130
 
155
131
  goog.asserts.assert(this.player_ != null, 'Should have a player!');
156
132
 
157
- /** @private {shaka.ui.Controls} */
158
- this.controls_ = new shaka.ui.Controls(
159
- this.player_, this.videoContainer_, this.video_, this.config_);
160
-
161
- controlsContainer = DomUtils.getElementByClassName(
162
- 'shaka-controls-container', this.videoContainer_);
163
- controlsContainer.setAttribute('shown', shown);
164
-
165
- // Add the text container back.
166
- if (textContainer) {
167
- this.videoContainer_.appendChild(textContainer);
168
- }
133
+ this.controls_.configure(this.config_);
169
134
 
170
135
  this.controls_.dispatchEvent(new shaka.util.FakeEvent('uiupdated'));
171
136
  };
@@ -228,7 +193,9 @@ shaka.ui.Overlay.prototype.defaultConfig_ = function() {
228
193
  'cast',
229
194
  ],
230
195
  addSeekBar: true,
196
+ addBigPlayButton: true,
231
197
  castReceiverAppId: '',
198
+ clearBufferOnQualityChange: true,
232
199
  };
233
200
  };
234
201
 
@@ -269,6 +236,11 @@ shaka.ui.Overlay.scanPageForShakaElements_ = function() {
269
236
  // Just the video elements were provided.
270
237
  for (let i = 0; i < videos.length; i++) {
271
238
  const video = videos[i];
239
+ // If the app has already manually created a UI for this element,
240
+ // don't create another one.
241
+ if (video['ui']) {
242
+ continue;
243
+ }
272
244
  goog.asserts.assert(video.tagName.toLowerCase() == 'video',
273
245
  'Should be a video element!');
274
246
 
@@ -298,6 +270,11 @@ shaka.ui.Overlay.scanPageForShakaElements_ = function() {
298
270
  } else {
299
271
  for (let i = 0; i < containers.length; i++) {
300
272
  const container = containers[i];
273
+ // If the app has already manually created a UI for this element,
274
+ // don't create another one.
275
+ if (container['ui']) {
276
+ continue;
277
+ }
301
278
  goog.asserts.assert(container.tagName.toLowerCase() == 'div',
302
279
  'Container should be a div!');
303
280
 
package/ui/volume_bar.js CHANGED
@@ -18,108 +18,80 @@
18
18
 
19
19
  goog.provide('shaka.ui.VolumeBar');
20
20
 
21
- goog.require('shaka.ui.Element');
21
+ goog.require('shaka.ui.Constants');
22
22
  goog.require('shaka.ui.Locales');
23
23
  goog.require('shaka.ui.Localization');
24
+ goog.require('shaka.ui.RangeElement');
24
25
 
25
26
 
26
27
  /**
27
- * @extends {shaka.ui.Element}
28
+ * @extends {shaka.ui.RangeElement}
28
29
  * @final
29
30
  * @export
30
31
  */
31
- shaka.ui.VolumeBar = class extends shaka.ui.Element {
32
+ shaka.ui.VolumeBar = class extends shaka.ui.RangeElement {
32
33
  /**
33
34
  * @param {!HTMLElement} parent
34
35
  * @param {!shaka.ui.Controls} controls
35
36
  */
36
37
  constructor(parent, controls) {
37
- super(parent, controls);
38
-
39
- // This container is to support IE 11. See detailed notes in
40
- // less/range_elements.less for a complete explanation.
41
- // TODO: Factor this into a range-element component.
42
- /** @private {!HTMLElement} */
43
- this.container_ = shaka.util.Dom.createHTMLElement('div');
44
- this.container_.classList.add('shaka-volume-bar-container');
45
-
46
- this.bar_ =
47
- /** @type {!HTMLInputElement} */ (document.createElement('input'));
48
- this.bar_.classList.add('shaka-volume-bar');
49
- this.bar_.setAttribute('type', 'range');
50
- // NOTE: step=any causes keyboard nav problems on IE 11.
51
- this.bar_.setAttribute('step', 'any');
52
- this.bar_.setAttribute('min', '0');
53
- this.bar_.setAttribute('max', '1');
54
- this.bar_.setAttribute('value', '0');
55
-
56
- this.container_.appendChild(this.bar_);
57
- this.parent.appendChild(this.container_);
58
- this.updateAriaLabel_();
59
-
60
- this.eventManager.listen(this.video, 'volumechange', () => {
61
- this.onVolumeStateChange_();
62
- });
38
+ super(parent, controls,
39
+ ['shaka-volume-bar-container'], ['shaka-volume-bar']);
63
40
 
64
- this.eventManager.listen(this.bar_, 'input', () => {
65
- this.onVolumeInput_();
66
- });
41
+ this.eventManager.listen(this.video,
42
+ 'volumechange',
43
+ () => this.onVolumeStateChange_());
67
44
 
68
- this.eventManager.listen(
69
- this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
70
- this.updateAriaLabel_();
71
- });
45
+ this.eventManager.listen(this.localization,
46
+ shaka.ui.Localization.LOCALE_UPDATED,
47
+ () => this.updateAriaLabel_());
72
48
 
73
- this.eventManager.listen(
74
- this.localization, shaka.ui.Localization.LOCALE_CHANGED, () => {
75
- this.updateAriaLabel_();
76
- });
49
+ this.eventManager.listen(this.localization,
50
+ shaka.ui.Localization.LOCALE_CHANGED,
51
+ () => this.updateAriaLabel_());
77
52
 
78
- // Initialize volume display with a fake event.
53
+ // Initialize volume display and label.
79
54
  this.onVolumeStateChange_();
55
+ this.updateAriaLabel_();
80
56
  }
81
57
 
82
-
83
58
  /**
84
- * @private
59
+ * Update the video element's state to match the input element's state.
60
+ * Called by the base class when the input element changes.
61
+ *
62
+ * @override
85
63
  */
64
+ onChange() {
65
+ this.video.volume = this.getValue();
66
+ if (this.video.volume == 0) {
67
+ this.video.muted = true;
68
+ } else {
69
+ this.video.muted = false;
70
+ }
71
+ }
72
+
73
+ /** @private */
86
74
  onVolumeStateChange_() {
87
75
  if (this.video.muted) {
88
- this.bar_.value = 0;
76
+ this.setValue(0);
89
77
  } else {
90
- this.bar_.value = this.video.volume;
78
+ this.setValue(this.video.volume);
91
79
  }
92
80
 
93
- // TODO: Can we do this with LESS?
94
- let gradient = ['to right'];
81
+ const gradient = ['to right'];
95
82
  gradient.push(shaka.ui.Constants.VOLUME_BAR_VOLUME_LEVEL_COLOR +
96
- (this.bar_.value * 100) + '%');
83
+ (this.getValue() * 100) + '%');
97
84
  gradient.push(shaka.ui.Constants.VOLUME_BAR_BASE_COLOR +
98
- (this.bar_.value * 100) + '%');
85
+ (this.getValue() * 100) + '%');
99
86
  gradient.push(shaka.ui.Constants.VOLUME_BAR_BASE_COLOR + '100%');
100
- this.container_.style.background =
101
- 'linear-gradient(' + gradient.join(',') + ')';
102
- }
103
87
 
104
-
105
- /**
106
- * @private
107
- */
108
- onVolumeInput_() {
109
- this.video.volume = parseFloat(this.bar_.value);
110
- if (this.video.volume == 0) {
111
- this.video.muted = true;
112
- } else {
113
- this.video.muted = false;
114
- }
88
+ this.container.style.background =
89
+ 'linear-gradient(' + gradient.join(',') + ')';
115
90
  }
116
91
 
117
-
118
- /**
119
- * @private
120
- */
92
+ /** @private */
121
93
  updateAriaLabel_() {
122
- this.bar_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
94
+ this.bar.setAttribute(shaka.ui.Constants.ARIA_LABEL,
123
95
  this.localization.resolve(shaka.ui.Locales.Ids.VOLUME));
124
96
  }
125
97
  };