· 5 years ago · Feb 11, 2021, 06:42 PM
1
2(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}(g.bitmovin || (g.bitmovin = {})).playerui = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
3"use strict";
4Object.defineProperty(exports, "__esModule", { value: true });
5var ArrayUtils;
6(function (ArrayUtils) {
7 /**
8 * Removes an item from an array.
9 * @param array the array that may contain the item to remove
10 * @param item the item to remove from the array
11 * @returns {any} the removed item or null if it wasn't part of the array
12 */
13 function remove(array, item) {
14 var index = array.indexOf(item);
15 if (index > -1) {
16 return array.splice(index, 1)[0];
17 }
18 else {
19 return null;
20 }
21 }
22 ArrayUtils.remove = remove;
23})(ArrayUtils = exports.ArrayUtils || (exports.ArrayUtils = {}));
24
25},{}],2:[function(require,module,exports){
26"use strict";
27Object.defineProperty(exports, "__esModule", { value: true });
28var BrowserUtils;
29(function (BrowserUtils) {
30 // isMobile only needs to be evaluated once (it cannot change during a browser session)
31 // Mobile detection according to Mozilla recommendation: "In summary, we recommend looking for the string “Mobiâ€
32 // anywhere in the User Agent to detect a mobile device."
33 // https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent
34 BrowserUtils.isMobile = navigator && navigator.userAgent && /Mobi/.test(navigator.userAgent);
35 BrowserUtils.isChrome = navigator && navigator.userAgent && /Chrome/.test(navigator.userAgent);
36 BrowserUtils.isAndroid = navigator && navigator.userAgent && /Android/.test(navigator.userAgent);
37})(BrowserUtils = exports.BrowserUtils || (exports.BrowserUtils = {}));
38
39},{}],3:[function(require,module,exports){
40"use strict";
41var __extends = (this && this.__extends) || (function () {
42 var extendStatics = Object.setPrototypeOf ||
43 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
44 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
45 return function (d, b) {
46 extendStatics(d, b);
47 function __() { this.constructor = d; }
48 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
49 };
50})();
51Object.defineProperty(exports, "__esModule", { value: true });
52var clickoverlay_1 = require("./clickoverlay");
53/**
54 * A simple click capture overlay for clickThroughUrls of ads.
55 */
56var AdClickOverlay = /** @class */ (function (_super) {
57 __extends(AdClickOverlay, _super);
58 function AdClickOverlay() {
59 return _super !== null && _super.apply(this, arguments) || this;
60 }
61 AdClickOverlay.prototype.configure = function (player, uimanager) {
62 var _this = this;
63 _super.prototype.configure.call(this, player, uimanager);
64 var clickThroughUrl = null;
65 var clickThroughEnabled = !player.getConfig().advertising
66 || !player.getConfig().advertising.hasOwnProperty('clickThroughEnabled')
67 || player.getConfig().advertising.clickThroughEnabled;
68 player.addEventHandler(player.EVENT.ON_AD_STARTED, function (event) {
69 clickThroughUrl = event.clickThroughUrl;
70 if (clickThroughEnabled) {
71 _this.setUrl(clickThroughUrl);
72 }
73 else {
74 // If click-through is disabled, we set the url to null to avoid it open
75 _this.setUrl(null);
76 }
77 });
78 // Clear click-through URL when ad has finished
79 var adFinishedHandler = function () {
80 _this.setUrl(null);
81 };
82 player.addEventHandler(player.EVENT.ON_AD_FINISHED, adFinishedHandler);
83 player.addEventHandler(player.EVENT.ON_AD_SKIPPED, adFinishedHandler);
84 player.addEventHandler(player.EVENT.ON_AD_ERROR, adFinishedHandler);
85 this.onClick.subscribe(function () {
86 // Pause the ad when overlay is clicked
87 player.pause('ui-content-click');
88 // Notify the player of the clicked ad
89 player.fireEvent(player.EVENT.ON_AD_CLICKED, {
90 clickThroughUrl: clickThroughUrl,
91 });
92 });
93 };
94 return AdClickOverlay;
95}(clickoverlay_1.ClickOverlay));
96exports.AdClickOverlay = AdClickOverlay;
97
98},{"./clickoverlay":14}],4:[function(require,module,exports){
99"use strict";
100var __extends = (this && this.__extends) || (function () {
101 var extendStatics = Object.setPrototypeOf ||
102 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
103 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
104 return function (d, b) {
105 extendStatics(d, b);
106 function __() { this.constructor = d; }
107 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
108 };
109})();
110Object.defineProperty(exports, "__esModule", { value: true });
111var label_1 = require("./label");
112var stringutils_1 = require("../stringutils");
113/**
114 * A label that displays a message about a running ad, optionally with a countdown.
115 */
116var AdMessageLabel = /** @class */ (function (_super) {
117 __extends(AdMessageLabel, _super);
118 function AdMessageLabel(config) {
119 if (config === void 0) { config = {}; }
120 var _this = _super.call(this, config) || this;
121 _this.config = _this.mergeConfig(config, {
122 cssClass: 'ui-label-ad-message',
123 text: 'This ad will end in {remainingTime} seconds.',
124 }, _this.config);
125 return _this;
126 }
127 AdMessageLabel.prototype.configure = function (player, uimanager) {
128 var _this = this;
129 _super.prototype.configure.call(this, player, uimanager);
130 var text = this.getConfig().text;
131 var updateMessageHandler = function () {
132 _this.setText(stringutils_1.StringUtils.replaceAdMessagePlaceholders(text, null, player));
133 };
134 var adStartHandler = function (event) {
135 text = event.adMessage || text;
136 updateMessageHandler();
137 player.addEventHandler(player.EVENT.ON_TIME_CHANGED, updateMessageHandler);
138 player.addEventHandler(player.EVENT.ON_CAST_TIME_UPDATED, updateMessageHandler);
139 };
140 var adEndHandler = function () {
141 player.removeEventHandler(player.EVENT.ON_TIME_CHANGED, updateMessageHandler);
142 player.removeEventHandler(player.EVENT.ON_CAST_TIME_UPDATED, updateMessageHandler);
143 };
144 player.addEventHandler(player.EVENT.ON_AD_STARTED, adStartHandler);
145 player.addEventHandler(player.EVENT.ON_AD_SKIPPED, adEndHandler);
146 player.addEventHandler(player.EVENT.ON_AD_ERROR, adEndHandler);
147 player.addEventHandler(player.EVENT.ON_AD_FINISHED, adEndHandler);
148 };
149 return AdMessageLabel;
150}(label_1.Label));
151exports.AdMessageLabel = AdMessageLabel;
152
153},{"../stringutils":88,"./label":24}],5:[function(require,module,exports){
154"use strict";
155var __extends = (this && this.__extends) || (function () {
156 var extendStatics = Object.setPrototypeOf ||
157 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
158 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
159 return function (d, b) {
160 extendStatics(d, b);
161 function __() { this.constructor = d; }
162 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
163 };
164})();
165Object.defineProperty(exports, "__esModule", { value: true });
166var button_1 = require("./button");
167var stringutils_1 = require("../stringutils");
168/**
169 * A button that is displayed during ads and can be used to skip the ad.
170 */
171var AdSkipButton = /** @class */ (function (_super) {
172 __extends(AdSkipButton, _super);
173 function AdSkipButton(config) {
174 if (config === void 0) { config = {}; }
175 var _this = _super.call(this, config) || this;
176 _this.config = _this.mergeConfig(config, {
177 cssClass: 'ui-button-ad-skip',
178 skipMessage: {
179 countdown: 'Skip ad in {remainingTime}',
180 skip: 'Skip ad',
181 },
182 }, _this.config);
183 return _this;
184 }
185 AdSkipButton.prototype.configure = function (player, uimanager) {
186 var _this = this;
187 _super.prototype.configure.call(this, player, uimanager);
188 var config = this.getConfig(); // TODO get rid of generic cast
189 var skipMessage = config.skipMessage;
190 var adEvent = null;
191 var updateSkipMessageHandler = function () {
192 // Display this button only if ad is skippable
193 if (adEvent.skipOffset) {
194 _this.show();
195 }
196 else {
197 _this.hide();
198 }
199 // Update the skip message on the button
200 if (player.getCurrentTime() < adEvent.skipOffset) {
201 _this.setText(stringutils_1.StringUtils.replaceAdMessagePlaceholders(config.skipMessage.countdown, adEvent.skipOffset, player));
202 }
203 else {
204 _this.setText(config.skipMessage.skip);
205 }
206 };
207 var adStartHandler = function (event) {
208 adEvent = event;
209 skipMessage = adEvent.skipMessage || skipMessage;
210 updateSkipMessageHandler();
211 player.addEventHandler(player.EVENT.ON_TIME_CHANGED, updateSkipMessageHandler);
212 player.addEventHandler(player.EVENT.ON_CAST_TIME_UPDATED, updateSkipMessageHandler);
213 };
214 var adEndHandler = function () {
215 player.removeEventHandler(player.EVENT.ON_TIME_CHANGED, updateSkipMessageHandler);
216 player.removeEventHandler(player.EVENT.ON_CAST_TIME_UPDATED, updateSkipMessageHandler);
217 };
218 player.addEventHandler(player.EVENT.ON_AD_STARTED, adStartHandler);
219 player.addEventHandler(player.EVENT.ON_AD_SKIPPED, adEndHandler);
220 player.addEventHandler(player.EVENT.ON_AD_ERROR, adEndHandler);
221 player.addEventHandler(player.EVENT.ON_AD_FINISHED, adEndHandler);
222 this.onClick.subscribe(function () {
223 // Try to skip the ad (this only works if it is skippable so we don't need to take extra care of that here)
224 player.skipAd();
225 });
226 };
227 return AdSkipButton;
228}(button_1.Button));
229exports.AdSkipButton = AdSkipButton;
230
231},{"../stringutils":88,"./button":10}],6:[function(require,module,exports){
232"use strict";
233var __extends = (this && this.__extends) || (function () {
234 var extendStatics = Object.setPrototypeOf ||
235 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
236 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
237 return function (d, b) {
238 extendStatics(d, b);
239 function __() { this.constructor = d; }
240 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
241 };
242})();
243Object.defineProperty(exports, "__esModule", { value: true });
244var togglebutton_1 = require("./togglebutton");
245/**
246 * A button that toggles Apple AirPlay.
247 */
248var AirPlayToggleButton = /** @class */ (function (_super) {
249 __extends(AirPlayToggleButton, _super);
250 function AirPlayToggleButton(config) {
251 if (config === void 0) { config = {}; }
252 var _this = _super.call(this, config) || this;
253 _this.config = _this.mergeConfig(config, {
254 cssClass: 'ui-airplaytogglebutton',
255 text: 'Apple AirPlay',
256 }, _this.config);
257 return _this;
258 }
259 AirPlayToggleButton.prototype.configure = function (player, uimanager) {
260 var _this = this;
261 _super.prototype.configure.call(this, player, uimanager);
262 if (!player.isAirplayAvailable) {
263 // If the player does not support Airplay (player 7.0), we just hide this component and skip configuration
264 this.hide();
265 return;
266 }
267 this.onClick.subscribe(function () {
268 if (player.isAirplayAvailable()) {
269 player.showAirplayTargetPicker();
270 }
271 else {
272 if (console) {
273 console.log('AirPlay unavailable');
274 }
275 }
276 });
277 var airPlayAvailableHandler = function () {
278 if (player.isAirplayAvailable()) {
279 _this.show();
280 }
281 else {
282 _this.hide();
283 }
284 };
285 player.addEventHandler(player.EVENT.ON_AIRPLAY_AVAILABLE, airPlayAvailableHandler);
286 // Startup init
287 airPlayAvailableHandler(); // Hide button if AirPlay is not available
288 };
289 return AirPlayToggleButton;
290}(togglebutton_1.ToggleButton));
291exports.AirPlayToggleButton = AirPlayToggleButton;
292
293},{"./togglebutton":59}],7:[function(require,module,exports){
294"use strict";
295var __extends = (this && this.__extends) || (function () {
296 var extendStatics = Object.setPrototypeOf ||
297 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
298 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
299 return function (d, b) {
300 extendStatics(d, b);
301 function __() { this.constructor = d; }
302 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
303 };
304})();
305Object.defineProperty(exports, "__esModule", { value: true });
306var selectbox_1 = require("./selectbox");
307/**
308 * A select box providing a selection between 'auto' and the available audio qualities.
309 */
310var AudioQualitySelectBox = /** @class */ (function (_super) {
311 __extends(AudioQualitySelectBox, _super);
312 function AudioQualitySelectBox(config) {
313 if (config === void 0) { config = {}; }
314 return _super.call(this, config) || this;
315 }
316 AudioQualitySelectBox.prototype.configure = function (player, uimanager) {
317 var _this = this;
318 _super.prototype.configure.call(this, player, uimanager);
319 var selectCurrentAudioQuality = function () {
320 if (player.getAudioQuality) {
321 // Since player 7.3.1
322 _this.selectItem(player.getAudioQuality().id);
323 }
324 else {
325 // Backwards compatibility for players <= 7.3.0
326 // TODO remove in next major release
327 var data = player.getDownloadedAudioData();
328 _this.selectItem(data.isAuto ? 'auto' : data.id);
329 }
330 };
331 var updateAudioQualities = function () {
332 var audioQualities = player.getAvailableAudioQualities();
333 _this.clearItems();
334 // Add entry for automatic quality switching (default setting)
335 _this.addItem('auto', 'auto');
336 // Add audio qualities
337 for (var _i = 0, audioQualities_1 = audioQualities; _i < audioQualities_1.length; _i++) {
338 var audioQuality = audioQualities_1[_i];
339 _this.addItem(audioQuality.id, audioQuality.label);
340 }
341 // Select initial quality
342 selectCurrentAudioQuality();
343 };
344 this.onItemSelected.subscribe(function (sender, value) {
345 player.setAudioQuality(value);
346 });
347 // Update qualities when audio track has changed
348 player.addEventHandler(player.EVENT.ON_AUDIO_CHANGED, updateAudioQualities);
349 // Update qualities when source goes away
350 player.addEventHandler(player.EVENT.ON_SOURCE_UNLOADED, updateAudioQualities);
351 // Update qualities when a new source is loaded
352 player.addEventHandler(player.EVENT.ON_READY, updateAudioQualities);
353 // Update qualities when the period within a source changes
354 player.addEventHandler(player.EVENT.ON_PERIOD_SWITCHED, updateAudioQualities);
355 // Update quality selection when quality is changed (from outside)
356 if (player.EVENT.ON_AUDIO_QUALITY_CHANGED) {
357 // Since player 7.3.1
358 player.addEventHandler(player.EVENT.ON_AUDIO_QUALITY_CHANGED, selectCurrentAudioQuality);
359 }
360 else {
361 // Backwards compatibility for players <= 7.3.0
362 // TODO remove in next major release
363 player.addEventHandler(player.EVENT.ON_AUDIO_DOWNLOAD_QUALITY_CHANGE, selectCurrentAudioQuality);
364 }
365 };
366 return AudioQualitySelectBox;
367}(selectbox_1.SelectBox));
368exports.AudioQualitySelectBox = AudioQualitySelectBox;
369
370},{"./selectbox":35}],8:[function(require,module,exports){
371"use strict";
372var __extends = (this && this.__extends) || (function () {
373 var extendStatics = Object.setPrototypeOf ||
374 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
375 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
376 return function (d, b) {
377 extendStatics(d, b);
378 function __() { this.constructor = d; }
379 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
380 };
381})();
382Object.defineProperty(exports, "__esModule", { value: true });
383var selectbox_1 = require("./selectbox");
384/**
385 * A select box providing a selection between available audio tracks (e.g. different languages).
386 */
387var AudioTrackSelectBox = /** @class */ (function (_super) {
388 __extends(AudioTrackSelectBox, _super);
389 function AudioTrackSelectBox(config) {
390 if (config === void 0) { config = {}; }
391 return _super.call(this, config) || this;
392 }
393 AudioTrackSelectBox.prototype.configure = function (player, uimanager) {
394 var _this = this;
395 _super.prototype.configure.call(this, player, uimanager);
396 var selectCurrentAudioTrack = function () {
397 var currentAudioTrack = player.getAudio();
398 // HLS streams don't always provide this, so we have to check
399 if (currentAudioTrack) {
400 _this.selectItem(currentAudioTrack.id);
401 }
402 };
403 var updateAudioTracks = function () {
404 var audioTracks = player.getAvailableAudio();
405 _this.clearItems();
406 // Add audio tracks
407 for (var _i = 0, audioTracks_1 = audioTracks; _i < audioTracks_1.length; _i++) {
408 var audioTrack = audioTracks_1[_i];
409 _this.addItem(audioTrack.id, audioTrack.label);
410 }
411 // Select the correct audio track after the tracks have been added
412 // This is also important in case we missed the `ON_AUDIO_CHANGED` event, e.g. when `playback.audioLanguage`
413 // is configured but the event is fired before the UI is created.
414 selectCurrentAudioTrack();
415 };
416 this.onItemSelected.subscribe(function (sender, value) {
417 player.setAudio(value);
418 });
419 // Update selection when selected track has changed
420 player.addEventHandler(player.EVENT.ON_AUDIO_CHANGED, selectCurrentAudioTrack);
421 // Update tracks when source goes away
422 player.addEventHandler(player.EVENT.ON_SOURCE_UNLOADED, updateAudioTracks);
423 // Update tracks when a new source is loaded
424 player.addEventHandler(player.EVENT.ON_READY, updateAudioTracks);
425 // Update tracks when the period within a source changes
426 player.addEventHandler(player.EVENT.ON_PERIOD_SWITCHED, updateAudioTracks);
427 // Update tracks when a track is added or removed (since player 7.1.4)
428 if (player.EVENT.ON_AUDIO_ADDED && player.EVENT.ON_AUDIO_REMOVED) {
429 player.addEventHandler(player.EVENT.ON_AUDIO_ADDED, updateAudioTracks);
430 player.addEventHandler(player.EVENT.ON_AUDIO_REMOVED, updateAudioTracks);
431 }
432 // Populate tracks at startup
433 updateAudioTracks();
434 };
435 return AudioTrackSelectBox;
436}(selectbox_1.SelectBox));
437exports.AudioTrackSelectBox = AudioTrackSelectBox;
438
439},{"./selectbox":35}],9:[function(require,module,exports){
440"use strict";
441var __extends = (this && this.__extends) || (function () {
442 var extendStatics = Object.setPrototypeOf ||
443 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
444 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
445 return function (d, b) {
446 extendStatics(d, b);
447 function __() { this.constructor = d; }
448 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
449 };
450})();
451Object.defineProperty(exports, "__esModule", { value: true });
452var container_1 = require("./container");
453var component_1 = require("./component");
454var timeout_1 = require("../timeout");
455/**
456 * Overlays the player and displays a buffering indicator.
457 */
458var BufferingOverlay = /** @class */ (function (_super) {
459 __extends(BufferingOverlay, _super);
460 function BufferingOverlay(config) {
461 if (config === void 0) { config = {}; }
462 var _this = _super.call(this, config) || this;
463 _this.indicators = [
464 new component_1.Component({ tag: 'div', cssClass: 'ui-buffering-overlay-indicator' }),
465 new component_1.Component({ tag: 'div', cssClass: 'ui-buffering-overlay-indicator' }),
466 new component_1.Component({ tag: 'div', cssClass: 'ui-buffering-overlay-indicator' }),
467 ];
468 _this.config = _this.mergeConfig(config, {
469 cssClass: 'ui-buffering-overlay',
470 hidden: true,
471 components: _this.indicators,
472 showDelayMs: 1000,
473 }, _this.config);
474 return _this;
475 }
476 BufferingOverlay.prototype.configure = function (player, uimanager) {
477 var _this = this;
478 _super.prototype.configure.call(this, player, uimanager);
479 var config = this.getConfig();
480 var overlayShowTimeout = new timeout_1.Timeout(config.showDelayMs, function () {
481 _this.show();
482 });
483 var showOverlay = function () {
484 overlayShowTimeout.start();
485 };
486 var hideOverlay = function () {
487 overlayShowTimeout.clear();
488 _this.hide();
489 };
490 player.addEventHandler(player.EVENT.ON_STALL_STARTED, showOverlay);
491 player.addEventHandler(player.EVENT.ON_STALL_ENDED, hideOverlay);
492 player.addEventHandler(player.EVENT.ON_SOURCE_UNLOADED, hideOverlay);
493 // Show overlay if player is already stalled at init
494 if (player.isStalled()) {
495 this.show();
496 }
497 };
498 return BufferingOverlay;
499}(container_1.Container));
500exports.BufferingOverlay = BufferingOverlay;
501
502},{"../timeout":89,"./component":16,"./container":17}],10:[function(require,module,exports){
503"use strict";
504var __extends = (this && this.__extends) || (function () {
505 var extendStatics = Object.setPrototypeOf ||
506 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
507 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
508 return function (d, b) {
509 extendStatics(d, b);
510 function __() { this.constructor = d; }
511 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
512 };
513})();
514Object.defineProperty(exports, "__esModule", { value: true });
515var component_1 = require("./component");
516var dom_1 = require("../dom");
517var eventdispatcher_1 = require("../eventdispatcher");
518/**
519 * A simple clickable button.
520 */
521var Button = /** @class */ (function (_super) {
522 __extends(Button, _super);
523 function Button(config) {
524 var _this = _super.call(this, config) || this;
525 _this.buttonEvents = {
526 onClick: new eventdispatcher_1.EventDispatcher(),
527 };
528 _this.config = _this.mergeConfig(config, {
529 cssClass: 'ui-button',
530 }, _this.config);
531 return _this;
532 }
533 Button.prototype.toDomElement = function () {
534 var _this = this;
535 // Create the button element with the text label
536 var buttonElement = new dom_1.DOM('button', {
537 'type': 'button',
538 'id': this.config.id,
539 'class': this.getCssClasses(),
540 }).append(new dom_1.DOM('span', {
541 'class': this.prefixCss('label'),
542 }).html(this.config.text));
543 // Listen for the click event on the button element and trigger the corresponding event on the button component
544 buttonElement.on('click', function () {
545 _this.onClickEvent();
546 });
547 return buttonElement;
548 };
549 /**
550 * Sets text on the label of the button.
551 * @param text the text to put into the label of the button
552 */
553 Button.prototype.setText = function (text) {
554 this.getDomElement().find('.' + this.prefixCss('label')).html(text);
555 };
556 Button.prototype.onClickEvent = function () {
557 this.buttonEvents.onClick.dispatch(this);
558 };
559 Object.defineProperty(Button.prototype, "onClick", {
560 /**
561 * Gets the event that is fired when the button is clicked.
562 * @returns {Event<Button<Config>, NoArgs>}
563 */
564 get: function () {
565 return this.buttonEvents.onClick.getEvent();
566 },
567 enumerable: true,
568 configurable: true
569 });
570 return Button;
571}(component_1.Component));
572exports.Button = Button;
573
574},{"../dom":68,"../eventdispatcher":82,"./component":16}],11:[function(require,module,exports){
575"use strict";
576var __extends = (this && this.__extends) || (function () {
577 var extendStatics = Object.setPrototypeOf ||
578 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
579 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
580 return function (d, b) {
581 extendStatics(d, b);
582 function __() { this.constructor = d; }
583 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
584 };
585})();
586Object.defineProperty(exports, "__esModule", { value: true });
587var container_1 = require("./container");
588var label_1 = require("./label");
589/**
590 * Overlays the player and displays the status of a Cast session.
591 */
592var CastStatusOverlay = /** @class */ (function (_super) {
593 __extends(CastStatusOverlay, _super);
594 function CastStatusOverlay(config) {
595 if (config === void 0) { config = {}; }
596 var _this = _super.call(this, config) || this;
597 _this.statusLabel = new label_1.Label({ cssClass: 'ui-cast-status-label' });
598 _this.config = _this.mergeConfig(config, {
599 cssClass: 'ui-cast-status-overlay',
600 components: [_this.statusLabel],
601 hidden: true,
602 }, _this.config);
603 return _this;
604 }
605 CastStatusOverlay.prototype.configure = function (player, uimanager) {
606 var _this = this;
607 _super.prototype.configure.call(this, player, uimanager);
608 player.addEventHandler(player.EVENT.ON_CAST_WAITING_FOR_DEVICE, function (event) {
609 _this.show();
610 // Get device name and update status text while connecting
611 var castDeviceName = event.castPayload.deviceName;
612 _this.statusLabel.setText("Connecting to <strong>" + castDeviceName + "</strong>...");
613 });
614 player.addEventHandler(player.EVENT.ON_CAST_STARTED, function (event) {
615 // Session is started or resumed
616 // For cases when a session is resumed, we do not receive the previous events and therefore show the status panel
617 // here too
618 _this.show();
619 var castDeviceName = event.deviceName;
620 _this.statusLabel.setText("Playing on <strong>" + castDeviceName + "</strong>");
621 });
622 player.addEventHandler(player.EVENT.ON_CAST_STOPPED, function (event) {
623 // Cast session gone, hide the status panel
624 _this.hide();
625 });
626 };
627 return CastStatusOverlay;
628}(container_1.Container));
629exports.CastStatusOverlay = CastStatusOverlay;
630
631},{"./container":17,"./label":24}],12:[function(require,module,exports){
632"use strict";
633var __extends = (this && this.__extends) || (function () {
634 var extendStatics = Object.setPrototypeOf ||
635 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
636 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
637 return function (d, b) {
638 extendStatics(d, b);
639 function __() { this.constructor = d; }
640 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
641 };
642})();
643Object.defineProperty(exports, "__esModule", { value: true });
644var togglebutton_1 = require("./togglebutton");
645/**
646 * A button that toggles casting to a Cast receiver.
647 */
648var CastToggleButton = /** @class */ (function (_super) {
649 __extends(CastToggleButton, _super);
650 function CastToggleButton(config) {
651 if (config === void 0) { config = {}; }
652 var _this = _super.call(this, config) || this;
653 _this.config = _this.mergeConfig(config, {
654 cssClass: 'ui-casttogglebutton',
655 text: 'Google Cast',
656 }, _this.config);
657 return _this;
658 }
659 CastToggleButton.prototype.configure = function (player, uimanager) {
660 var _this = this;
661 _super.prototype.configure.call(this, player, uimanager);
662 this.onClick.subscribe(function () {
663 if (player.isCastAvailable()) {
664 if (player.isCasting()) {
665 player.castStop();
666 }
667 else {
668 player.castVideo();
669 }
670 }
671 else {
672 if (console) {
673 console.log('Cast unavailable');
674 }
675 }
676 });
677 var castAvailableHander = function () {
678 if (player.isCastAvailable()) {
679 _this.show();
680 }
681 else {
682 _this.hide();
683 }
684 };
685 player.addEventHandler(player.EVENT.ON_CAST_AVAILABLE, castAvailableHander);
686 // Toggle button 'on' state
687 player.addEventHandler(player.EVENT.ON_CAST_WAITING_FOR_DEVICE, function () {
688 _this.on();
689 });
690 player.addEventHandler(player.EVENT.ON_CAST_STARTED, function () {
691 // When a session is resumed, there is no ON_CAST_START event, so we also need to toggle here for such cases
692 _this.on();
693 });
694 player.addEventHandler(player.EVENT.ON_CAST_STOPPED, function () {
695 _this.off();
696 });
697 // Startup init
698 castAvailableHander(); // Hide button if Cast not available
699 if (player.isCasting()) {
700 this.on();
701 }
702 };
703 return CastToggleButton;
704}(togglebutton_1.ToggleButton));
705exports.CastToggleButton = CastToggleButton;
706
707},{"./togglebutton":59}],13:[function(require,module,exports){
708"use strict";
709var __extends = (this && this.__extends) || (function () {
710 var extendStatics = Object.setPrototypeOf ||
711 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
712 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
713 return function (d, b) {
714 extendStatics(d, b);
715 function __() { this.constructor = d; }
716 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
717 };
718})();
719Object.defineProperty(exports, "__esModule", { value: true });
720var uicontainer_1 = require("./uicontainer");
721var timeout_1 = require("../timeout");
722/**
723 * The base container for Cast receivers that contains all of the UI and takes care that the UI is shown on
724 * certain playback events.
725 */
726var CastUIContainer = /** @class */ (function (_super) {
727 __extends(CastUIContainer, _super);
728 function CastUIContainer(config) {
729 return _super.call(this, config) || this;
730 }
731 CastUIContainer.prototype.configure = function (player, uimanager) {
732 var _this = this;
733 _super.prototype.configure.call(this, player, uimanager);
734 var config = this.getConfig();
735 /*
736 * Show UI on Cast devices at certain playback events
737 *
738 * Since a Cast receiver does not have a direct HCI, we show the UI on certain playback events to give the user
739 * a chance to see on the screen what's going on, e.g. on play/pause or a seek the UI is shown and the user can
740 * see the current time and position on the seek bar.
741 * The UI is shown permanently while playback is paused, otherwise hides automatically after the configured
742 * hide delay time.
743 */
744 var isUiShown = false;
745 var hideUi = function () {
746 uimanager.onControlsHide.dispatch(_this);
747 isUiShown = false;
748 };
749 this.castUiHideTimeout = new timeout_1.Timeout(config.hideDelay, hideUi);
750 var showUi = function () {
751 if (!isUiShown) {
752 uimanager.onControlsShow.dispatch(_this);
753 isUiShown = true;
754 }
755 };
756 var showUiPermanently = function () {
757 showUi();
758 _this.castUiHideTimeout.clear();
759 };
760 var showUiWithTimeout = function () {
761 showUi();
762 _this.castUiHideTimeout.start();
763 };
764 var showUiAfterSeek = function () {
765 if (player.isPlaying()) {
766 showUiWithTimeout();
767 }
768 else {
769 showUiPermanently();
770 }
771 };
772 player.addEventHandler(player.EVENT.ON_READY, showUiWithTimeout);
773 player.addEventHandler(player.EVENT.ON_SOURCE_LOADED, showUiWithTimeout);
774 player.addEventHandler(player.EVENT.ON_PLAY, showUiWithTimeout);
775 player.addEventHandler(player.EVENT.ON_PAUSED, showUiPermanently);
776 player.addEventHandler(player.EVENT.ON_SEEK, showUiPermanently);
777 player.addEventHandler(player.EVENT.ON_SEEKED, showUiAfterSeek);
778 };
779 CastUIContainer.prototype.release = function () {
780 _super.prototype.release.call(this);
781 this.castUiHideTimeout.clear();
782 };
783 return CastUIContainer;
784}(uicontainer_1.UIContainer));
785exports.CastUIContainer = CastUIContainer;
786
787},{"../timeout":89,"./uicontainer":61}],14:[function(require,module,exports){
788"use strict";
789var __extends = (this && this.__extends) || (function () {
790 var extendStatics = Object.setPrototypeOf ||
791 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
792 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
793 return function (d, b) {
794 extendStatics(d, b);
795 function __() { this.constructor = d; }
796 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
797 };
798})();
799Object.defineProperty(exports, "__esModule", { value: true });
800var button_1 = require("./button");
801/**
802 * A click overlay that opens an url in a new tab if clicked.
803 */
804var ClickOverlay = /** @class */ (function (_super) {
805 __extends(ClickOverlay, _super);
806 function ClickOverlay(config) {
807 if (config === void 0) { config = {}; }
808 var _this = _super.call(this, config) || this;
809 _this.config = _this.mergeConfig(config, {
810 cssClass: 'ui-clickoverlay',
811 }, _this.config);
812 return _this;
813 }
814 ClickOverlay.prototype.initialize = function () {
815 _super.prototype.initialize.call(this);
816 this.setUrl(this.config.url);
817 var element = this.getDomElement();
818 element.on('click', function () {
819 if (element.data('url')) {
820 window.open(element.data('url'), '_blank');
821 }
822 });
823 };
824 /**
825 * Gets the URL that should be followed when the watermark is clicked.
826 * @returns {string} the watermark URL
827 */
828 ClickOverlay.prototype.getUrl = function () {
829 return this.getDomElement().data('url');
830 };
831 ClickOverlay.prototype.setUrl = function (url) {
832 if (url === undefined || url == null) {
833 url = '';
834 }
835 this.getDomElement().data('url', url);
836 };
837 return ClickOverlay;
838}(button_1.Button));
839exports.ClickOverlay = ClickOverlay;
840
841},{"./button":10}],15:[function(require,module,exports){
842"use strict";
843var __extends = (this && this.__extends) || (function () {
844 var extendStatics = Object.setPrototypeOf ||
845 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
846 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
847 return function (d, b) {
848 extendStatics(d, b);
849 function __() { this.constructor = d; }
850 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
851 };
852})();
853Object.defineProperty(exports, "__esModule", { value: true });
854var button_1 = require("./button");
855/**
856 * A button that closes (hides) a configured component.
857 */
858var CloseButton = /** @class */ (function (_super) {
859 __extends(CloseButton, _super);
860 function CloseButton(config) {
861 var _this = _super.call(this, config) || this;
862 _this.config = _this.mergeConfig(config, {
863 cssClass: 'ui-closebutton',
864 text: 'Close',
865 }, _this.config);
866 return _this;
867 }
868 CloseButton.prototype.configure = function (player, uimanager) {
869 _super.prototype.configure.call(this, player, uimanager);
870 var config = this.getConfig();
871 this.onClick.subscribe(function () {
872 config.target.hide();
873 });
874 };
875 return CloseButton;
876}(button_1.Button));
877exports.CloseButton = CloseButton;
878
879},{"./button":10}],16:[function(require,module,exports){
880"use strict";
881Object.defineProperty(exports, "__esModule", { value: true });
882var guid_1 = require("../guid");
883var dom_1 = require("../dom");
884var eventdispatcher_1 = require("../eventdispatcher");
885/**
886 * The base class of the UI framework.
887 * Each component must extend this class and optionally the config interface.
888 */
889var Component = /** @class */ (function () {
890 /**
891 * Constructs a component with an optionally supplied config. All subclasses must call the constructor of their
892 * superclass and then merge their configuration into the component's configuration.
893 * @param config the configuration for the component
894 */
895 function Component(config) {
896 if (config === void 0) { config = {}; }
897 /**
898 * The list of events that this component offers. These events should always be private and only directly
899 * accessed from within the implementing component.
900 *
901 * Because TypeScript does not support private properties with the same name on different class hierarchy levels
902 * (i.e. superclass and subclass cannot contain a private property with the same name), the default naming
903 * convention for the event list of a component that should be followed by subclasses is the concatenation of the
904 * camel-cased class name + 'Events' (e.g. SubClass extends Component => subClassEvents).
905 * See {@link #componentEvents} for an example.
906 *
907 * Event properties should be named in camel case with an 'on' prefix and in the present tense. Async events may
908 * have a start event (when the operation starts) in the present tense, and must have an end event (when the
909 * operation ends) in the past tense (or present tense in special cases (e.g. onStart/onStarted or onPlay/onPlaying).
910 * See {@link #componentEvents#onShow} for an example.
911 *
912 * Each event should be accompanied with a protected method named by the convention eventName + 'Event'
913 * (e.g. onStartEvent), that actually triggers the event by calling {@link EventDispatcher#dispatch dispatch} and
914 * passing a reference to the component as first parameter. Components should always trigger their events with these
915 * methods. Implementing this pattern gives subclasses means to directly listen to the events by overriding the
916 * method (and saving the overhead of passing a handler to the event dispatcher) and more importantly to trigger
917 * these events without having access to the private event list.
918 * See {@link #onShow} for an example.
919 *
920 * To provide external code the possibility to listen to this component's events (subscribe, unsubscribe, etc.),
921 * each event should also be accompanied by a public getter function with the same name as the event's property,
922 * that returns the {@link Event} obtained from the event dispatcher by calling {@link EventDispatcher#getEvent}.
923 * See {@link #onShow} for an example.
924 *
925 * Full example for an event representing an example action in a example component:
926 *
927 * <code>
928 * // Define an example component class with an example event
929 * class ExampleComponent extends Component<ComponentConfig> {
930 *
931 * private exampleComponentEvents = {
932 * onExampleAction: new EventDispatcher<ExampleComponent, NoArgs>()
933 * }
934 *
935 * // constructor and other stuff...
936 *
937 * protected onExampleActionEvent() {
938 * this.exampleComponentEvents.onExampleAction.dispatch(this);
939 * }
940 *
941 * get onExampleAction(): Event<ExampleComponent, NoArgs> {
942 * return this.exampleComponentEvents.onExampleAction.getEvent();
943 * }
944 * }
945 *
946 * // Create an instance of the component somewhere
947 * var exampleComponentInstance = new ExampleComponent();
948 *
949 * // Subscribe to the example event on the component
950 * exampleComponentInstance.onExampleAction.subscribe(function (sender: ExampleComponent) {
951 * console.log('onExampleAction of ' + sender + ' has fired!');
952 * });
953 * </code>
954 */
955 this.componentEvents = {
956 onShow: new eventdispatcher_1.EventDispatcher(),
957 onHide: new eventdispatcher_1.EventDispatcher(),
958 onHoverChanged: new eventdispatcher_1.EventDispatcher(),
959 };
960 // Create the configuration for this component
961 this.config = this.mergeConfig(config, {
962 tag: 'div',
963 id: 'bmpui-id-' + guid_1.Guid.next(),
964 cssPrefix: 'bmpui',
965 cssClass: 'ui-component',
966 cssClasses: [],
967 hidden: false,
968 }, {});
969 }
970 /**
971 * Initializes the component, e.g. by applying config settings.
972 * This method must not be called from outside the UI framework.
973 *
974 * This method is automatically called by the {@link UIInstanceManager}. If the component is an inner component of
975 * some component, and thus encapsulated abd managed internally and never directly exposed to the UIManager,
976 * this method must be called from the managing component's {@link #initialize} method.
977 */
978 Component.prototype.initialize = function () {
979 this.hidden = this.config.hidden;
980 // Hide the component at initialization if it is configured to be hidden
981 if (this.isHidden()) {
982 this.hidden = false; // Set flag to false for the following hide() call to work (hide() checks the flag)
983 this.hide();
984 }
985 };
986 /**
987 * Configures the component for the supplied Player and UIInstanceManager. This is the place where all the magic
988 * happens, where components typically subscribe and react to events (on their DOM element, the Player, or the
989 * UIInstanceManager), and basically everything that makes them interactive.
990 * This method is called only once, when the UIManager initializes the UI.
991 *
992 * Subclasses usually overwrite this method to add their own functionality.
993 *
994 * @param player the player which this component controls
995 * @param uimanager the UIInstanceManager that manages this component
996 */
997 Component.prototype.configure = function (player, uimanager) {
998 var _this = this;
999 this.onShow.subscribe(function () {
1000 uimanager.onComponentShow.dispatch(_this);
1001 });
1002 this.onHide.subscribe(function () {
1003 uimanager.onComponentHide.dispatch(_this);
1004 });
1005 // Track the hovered state of the element
1006 this.getDomElement().on('mouseenter', function () {
1007 _this.onHoverChangedEvent(true);
1008 });
1009 this.getDomElement().on('mouseleave', function () {
1010 _this.onHoverChangedEvent(false);
1011 });
1012 };
1013 /**
1014 * Releases all resources and dependencies that the component holds. Player, DOM, and UIManager events are
1015 * automatically removed during release and do not explicitly need to be removed here.
1016 * This method is called by the UIManager when it releases the UI.
1017 *
1018 * Subclasses that need to release resources should override this method and call super.release().
1019 */
1020 Component.prototype.release = function () {
1021 // Nothing to do here, override where necessary
1022 };
1023 /**
1024 * Generate the DOM element for this component.
1025 *
1026 * Subclasses usually overwrite this method to extend or replace the DOM element with their own design.
1027 */
1028 Component.prototype.toDomElement = function () {
1029 var element = new dom_1.DOM(this.config.tag, {
1030 'id': this.config.id,
1031 'class': this.getCssClasses(),
1032 });
1033 return element;
1034 };
1035 /**
1036 * Returns the DOM element of this component. Creates the DOM element if it does not yet exist.
1037 *
1038 * Should not be overwritten by subclasses.
1039 *
1040 * @returns {DOM}
1041 */
1042 Component.prototype.getDomElement = function () {
1043 if (!this.element) {
1044 this.element = this.toDomElement();
1045 }
1046 return this.element;
1047 };
1048 /**
1049 * Merges a configuration with a default configuration and a base configuration from the superclass.
1050 *
1051 * @param config the configuration settings for the components, as usually passed to the constructor
1052 * @param defaults a default configuration for settings that are not passed with the configuration
1053 * @param base configuration inherited from a superclass
1054 * @returns {Config}
1055 */
1056 Component.prototype.mergeConfig = function (config, defaults, base) {
1057 // Extend default config with supplied config
1058 var merged = Object.assign({}, base, defaults, config);
1059 // Return the extended config
1060 return merged;
1061 };
1062 /**
1063 * Helper method that returns a string of all CSS classes of the component.
1064 *
1065 * @returns {string}
1066 */
1067 Component.prototype.getCssClasses = function () {
1068 var _this = this;
1069 // Merge all CSS classes into single array
1070 var flattenedArray = [this.config.cssClass].concat(this.config.cssClasses);
1071 // Prefix classes
1072 flattenedArray = flattenedArray.map(function (css) {
1073 return _this.prefixCss(css);
1074 });
1075 // Join array values into a string
1076 var flattenedString = flattenedArray.join(' ');
1077 // Return trimmed string to prevent whitespace at the end from the join operation
1078 return flattenedString.trim();
1079 };
1080 Component.prototype.prefixCss = function (cssClassOrId) {
1081 return this.config.cssPrefix + '-' + cssClassOrId;
1082 };
1083 /**
1084 * Returns the configuration object of the component.
1085 * @returns {Config}
1086 */
1087 Component.prototype.getConfig = function () {
1088 return this.config;
1089 };
1090 /**
1091 * Hides the component if shown.
1092 * This method basically transfers the component into the hidden state. Actual hiding is done via CSS.
1093 */
1094 Component.prototype.hide = function () {
1095 if (!this.hidden) {
1096 this.hidden = true;
1097 this.getDomElement().addClass(this.prefixCss(Component.CLASS_HIDDEN));
1098 this.onHideEvent();
1099 }
1100 };
1101 /**
1102 * Shows the component if hidden.
1103 */
1104 Component.prototype.show = function () {
1105 if (this.hidden) {
1106 this.getDomElement().removeClass(this.prefixCss(Component.CLASS_HIDDEN));
1107 this.hidden = false;
1108 this.onShowEvent();
1109 }
1110 };
1111 /**
1112 * Determines if the component is hidden.
1113 * @returns {boolean} true if the component is hidden, else false
1114 */
1115 Component.prototype.isHidden = function () {
1116 return this.hidden;
1117 };
1118 /**
1119 * Determines if the component is shown.
1120 * @returns {boolean} true if the component is visible, else false
1121 */
1122 Component.prototype.isShown = function () {
1123 return !this.isHidden();
1124 };
1125 /**
1126 * Toggles the hidden state by hiding the component if it is shown, or showing it if hidden.
1127 */
1128 Component.prototype.toggleHidden = function () {
1129 if (this.isHidden()) {
1130 this.show();
1131 }
1132 else {
1133 this.hide();
1134 }
1135 };
1136 /**
1137 * Determines if the component is currently hovered.
1138 * @returns {boolean} true if the component is hovered, else false
1139 */
1140 Component.prototype.isHovered = function () {
1141 return this.hovered;
1142 };
1143 /**
1144 * Fires the onShow event.
1145 * See the detailed explanation on event architecture on the {@link #componentEvents events list}.
1146 */
1147 Component.prototype.onShowEvent = function () {
1148 this.componentEvents.onShow.dispatch(this);
1149 };
1150 /**
1151 * Fires the onHide event.
1152 * See the detailed explanation on event architecture on the {@link #componentEvents events list}.
1153 */
1154 Component.prototype.onHideEvent = function () {
1155 this.componentEvents.onHide.dispatch(this);
1156 };
1157 /**
1158 * Fires the onHoverChanged event.
1159 * See the detailed explanation on event architecture on the {@link #componentEvents events list}.
1160 */
1161 Component.prototype.onHoverChangedEvent = function (hovered) {
1162 this.hovered = hovered;
1163 this.componentEvents.onHoverChanged.dispatch(this, { hovered: hovered });
1164 };
1165 Object.defineProperty(Component.prototype, "onShow", {
1166 /**
1167 * Gets the event that is fired when the component is showing.
1168 * See the detailed explanation on event architecture on the {@link #componentEvents events list}.
1169 * @returns {Event<Component<Config>, NoArgs>}
1170 */
1171 get: function () {
1172 return this.componentEvents.onShow.getEvent();
1173 },
1174 enumerable: true,
1175 configurable: true
1176 });
1177 Object.defineProperty(Component.prototype, "onHide", {
1178 /**
1179 * Gets the event that is fired when the component is hiding.
1180 * See the detailed explanation on event architecture on the {@link #componentEvents events list}.
1181 * @returns {Event<Component<Config>, NoArgs>}
1182 */
1183 get: function () {
1184 return this.componentEvents.onHide.getEvent();
1185 },
1186 enumerable: true,
1187 configurable: true
1188 });
1189 Object.defineProperty(Component.prototype, "onHoverChanged", {
1190 /**
1191 * Gets the event that is fired when the component's hover-state is changing.
1192 * @returns {Event<Component<Config>, ComponentHoverChangedEventArgs>}
1193 */
1194 get: function () {
1195 return this.componentEvents.onHoverChanged.getEvent();
1196 },
1197 enumerable: true,
1198 configurable: true
1199 });
1200 /**
1201 * The classname that is attached to the element when it is in the hidden state.
1202 * @type {string}
1203 */
1204 Component.CLASS_HIDDEN = 'hidden';
1205 return Component;
1206}());
1207exports.Component = Component;
1208
1209},{"../dom":68,"../eventdispatcher":82,"../guid":83}],17:[function(require,module,exports){
1210"use strict";
1211var __extends = (this && this.__extends) || (function () {
1212 var extendStatics = Object.setPrototypeOf ||
1213 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
1214 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
1215 return function (d, b) {
1216 extendStatics(d, b);
1217 function __() { this.constructor = d; }
1218 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1219 };
1220})();
1221Object.defineProperty(exports, "__esModule", { value: true });
1222var component_1 = require("./component");
1223var dom_1 = require("../dom");
1224var arrayutils_1 = require("../arrayutils");
1225/**
1226 * A container component that can contain a collection of child components.
1227 * Components can be added at construction time through the {@link ContainerConfig#components} setting, or later
1228 * through the {@link Container#addComponent} method. The UIManager automatically takes care of all components, i.e. it
1229 * initializes and configures them automatically.
1230 *
1231 * In the DOM, the container consists of an outer <div> (that can be configured by the config) and an inner wrapper
1232 * <div> that contains the components. This double-<div>-structure is often required to achieve many advanced effects
1233 * in CSS and/or JS, e.g. animations and certain formatting with absolute positioning.
1234 *
1235 * DOM example:
1236 * <code>
1237 * <div class='ui-container'>
1238 * <div class='container-wrapper'>
1239 * ... child components ...
1240 * </div>
1241 * </div>
1242 * </code>
1243 */
1244var Container = /** @class */ (function (_super) {
1245 __extends(Container, _super);
1246 function Container(config) {
1247 var _this = _super.call(this, config) || this;
1248 _this.config = _this.mergeConfig(config, {
1249 cssClass: 'ui-container',
1250 components: [],
1251 }, _this.config);
1252 _this.componentsToAdd = [];
1253 _this.componentsToRemove = [];
1254 return _this;
1255 }
1256 /**
1257 * Adds a child component to the container.
1258 * @param component the component to add
1259 */
1260 Container.prototype.addComponent = function (component) {
1261 this.config.components.push(component);
1262 this.componentsToAdd.push(component);
1263 };
1264 /**
1265 * Removes a child component from the container.
1266 * @param component the component to remove
1267 * @returns {boolean} true if the component has been removed, false if it is not contained in this container
1268 */
1269 Container.prototype.removeComponent = function (component) {
1270 if (arrayutils_1.ArrayUtils.remove(this.config.components, component) != null) {
1271 this.componentsToRemove.push(component);
1272 return true;
1273 }
1274 else {
1275 return false;
1276 }
1277 };
1278 /**
1279 * Gets an array of all child components in this container.
1280 * @returns {Component<ComponentConfig>[]}
1281 */
1282 Container.prototype.getComponents = function () {
1283 return this.config.components;
1284 };
1285 /**
1286 * Removes all child components from the container.
1287 */
1288 Container.prototype.removeComponents = function () {
1289 for (var _i = 0, _a = this.getComponents().slice(); _i < _a.length; _i++) {
1290 var component = _a[_i];
1291 this.removeComponent(component);
1292 }
1293 };
1294 /**
1295 * Updates the DOM of the container with the current components.
1296 */
1297 Container.prototype.updateComponents = function () {
1298 /* We cannot just clear the container to remove all elements and then re-add those that should stay, because
1299 * IE looses the innerHTML of unattached elements, leading to empty elements within the container (e.g. missing
1300 * subtitle text in SubtitleLabel).
1301 * Instead, we keep a list of elements to add and remove, leaving remaining elements alone. By keeping them in
1302 * the DOM, their content gets preserved in all browsers.
1303 */
1304 var component;
1305 while (component = this.componentsToRemove.shift()) {
1306 component.getDomElement().remove();
1307 }
1308 while (component = this.componentsToAdd.shift()) {
1309 this.innerContainerElement.append(component.getDomElement());
1310 }
1311 };
1312 Container.prototype.toDomElement = function () {
1313 // Create the container element (the outer <div>)
1314 var containerElement = new dom_1.DOM(this.config.tag, {
1315 'id': this.config.id,
1316 'class': this.getCssClasses(),
1317 });
1318 // Create the inner container element (the inner <div>) that will contain the components
1319 var innerContainer = new dom_1.DOM(this.config.tag, {
1320 'class': this.prefixCss('container-wrapper'),
1321 });
1322 this.innerContainerElement = innerContainer;
1323 for (var _i = 0, _a = this.config.components; _i < _a.length; _i++) {
1324 var initialComponent = _a[_i];
1325 this.componentsToAdd.push(initialComponent);
1326 }
1327 this.updateComponents();
1328 containerElement.append(innerContainer);
1329 return containerElement;
1330 };
1331 return Container;
1332}(component_1.Component));
1333exports.Container = Container;
1334
1335},{"../arrayutils":1,"../dom":68,"./component":16}],18:[function(require,module,exports){
1336"use strict";
1337var __extends = (this && this.__extends) || (function () {
1338 var extendStatics = Object.setPrototypeOf ||
1339 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
1340 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
1341 return function (d, b) {
1342 extendStatics(d, b);
1343 function __() { this.constructor = d; }
1344 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1345 };
1346})();
1347Object.defineProperty(exports, "__esModule", { value: true });
1348var container_1 = require("./container");
1349var uiutils_1 = require("../uiutils");
1350var spacer_1 = require("./spacer");
1351/**
1352 * A container for main player control components, e.g. play toggle button, seek bar, volume control, fullscreen toggle
1353 * button.
1354 */
1355var ControlBar = /** @class */ (function (_super) {
1356 __extends(ControlBar, _super);
1357 function ControlBar(config) {
1358 var _this = _super.call(this, config) || this;
1359 _this.config = _this.mergeConfig(config, {
1360 cssClass: 'ui-controlbar',
1361 hidden: true,
1362 }, _this.config);
1363 return _this;
1364 }
1365 ControlBar.prototype.configure = function (player, uimanager) {
1366 var _this = this;
1367 _super.prototype.configure.call(this, player, uimanager);
1368 // Counts how many components are hovered and block hiding of the control bar
1369 var hoverStackCount = 0;
1370 // Track hover status of child components
1371 uiutils_1.UIUtils.traverseTree(this, function (component) {
1372 // Do not track hover status of child containers or spacers, only of 'real' controls
1373 if (component instanceof container_1.Container || component instanceof spacer_1.Spacer) {
1374 return;
1375 }
1376 // Subscribe hover event and keep a count of the number of hovered children
1377 component.onHoverChanged.subscribe(function (sender, args) {
1378 if (args.hovered) {
1379 hoverStackCount++;
1380 }
1381 else {
1382 hoverStackCount--;
1383 }
1384 });
1385 });
1386 uimanager.onControlsShow.subscribe(function () {
1387 player.fireEvent('hideControls', {});
1388 _this.show();
1389 });
1390 uimanager.onPreviewControlsHide.subscribe(function (sender, args) {
1391 // Cancel the hide event if hovered child components block hiding
1392 args.cancel = (hoverStackCount > 0);
1393 });
1394 uimanager.onControlsHide.subscribe(function () {
1395 player.fireEvent('showControls', {});
1396 _this.hide();
1397 });
1398 };
1399 return ControlBar;
1400}(container_1.Container));
1401exports.ControlBar = ControlBar;
1402
1403},{"../uiutils":91,"./container":17,"./spacer":38}],19:[function(require,module,exports){
1404"use strict";
1405var __extends = (this && this.__extends) || (function () {
1406 var extendStatics = Object.setPrototypeOf ||
1407 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
1408 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
1409 return function (d, b) {
1410 extendStatics(d, b);
1411 function __() { this.constructor = d; }
1412 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1413 };
1414})();
1415Object.defineProperty(exports, "__esModule", { value: true });
1416var container_1 = require("./container");
1417var label_1 = require("./label");
1418var tvnoisecanvas_1 = require("./tvnoisecanvas");
1419/**
1420 * Overlays the player and displays error messages.
1421 */
1422var ErrorMessageOverlay = /** @class */ (function (_super) {
1423 __extends(ErrorMessageOverlay, _super);
1424 function ErrorMessageOverlay(config) {
1425 if (config === void 0) { config = {}; }
1426 var _this = _super.call(this, config) || this;
1427 _this.errorLabel = new label_1.Label({ cssClass: 'ui-errormessage-label' });
1428 _this.tvNoiseBackground = new tvnoisecanvas_1.TvNoiseCanvas();
1429 _this.config = _this.mergeConfig(config, {
1430 cssClass: 'ui-errormessage-overlay',
1431 components: [_this.tvNoiseBackground, _this.errorLabel],
1432 hidden: true,
1433 }, _this.config);
1434 return _this;
1435 }
1436 ErrorMessageOverlay.prototype.configure = function (player, uimanager) {
1437 var _this = this;
1438 _super.prototype.configure.call(this, player, uimanager);
1439 var config = this.getConfig();
1440 player.addEventHandler(player.EVENT.ON_ERROR, function (event) {
1441 var message = event.message;
1442 // Process message translations
1443 if (config.messages) {
1444 if (typeof config.messages === 'function') {
1445 // Translation function for all errors
1446 message = config.messages(event);
1447 }
1448 else if (config.messages[event.code]) {
1449 // It's not a translation function, so it must be a map of strings or translation functions
1450 var customMessage = config.messages[event.code];
1451 if (typeof customMessage === 'string') {
1452 message = customMessage;
1453 }
1454 else {
1455 // The message is a translation function, so we call it
1456 message = customMessage(event);
1457 }
1458 }
1459 }
1460 _this.errorLabel.setText(message);
1461 _this.tvNoiseBackground.start();
1462 _this.show();
1463 });
1464 player.addEventHandler(player.EVENT.ON_SOURCE_LOADED, function (event) {
1465 if (_this.isShown()) {
1466 _this.tvNoiseBackground.stop();
1467 _this.hide();
1468 }
1469 });
1470 };
1471 ErrorMessageOverlay.prototype.release = function () {
1472 _super.prototype.release.call(this);
1473 // Canvas rendering must be explicitly stopped, else it just continues forever and hogs resources
1474 this.tvNoiseBackground.stop();
1475 };
1476 return ErrorMessageOverlay;
1477}(container_1.Container));
1478exports.ErrorMessageOverlay = ErrorMessageOverlay;
1479
1480},{"./container":17,"./label":24,"./tvnoisecanvas":60}],20:[function(require,module,exports){
1481"use strict";
1482var __extends = (this && this.__extends) || (function () {
1483 var extendStatics = Object.setPrototypeOf ||
1484 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
1485 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
1486 return function (d, b) {
1487 extendStatics(d, b);
1488 function __() { this.constructor = d; }
1489 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1490 };
1491})();
1492Object.defineProperty(exports, "__esModule", { value: true });
1493var togglebutton_1 = require("./togglebutton");
1494/**
1495 * A button that toggles the player between windowed and fullscreen view.
1496 */
1497var FullscreenToggleButton = /** @class */ (function (_super) {
1498 __extends(FullscreenToggleButton, _super);
1499 function FullscreenToggleButton(config) {
1500 if (config === void 0) { config = {}; }
1501 var _this = _super.call(this, config) || this;
1502 _this.config = _this.mergeConfig(config, {
1503 cssClass: 'ui-fullscreentogglebutton',
1504 text: 'Fullscreen',
1505 }, _this.config);
1506 return _this;
1507 }
1508 FullscreenToggleButton.prototype.configure = function (player, uimanager) {
1509 var _this = this;
1510 _super.prototype.configure.call(this, player, uimanager);
1511 var fullscreenStateHandler = function () {
1512 if (player.isFullscreen()) {
1513 _this.on();
1514 }
1515 else {
1516 _this.off();
1517 }
1518 };
1519 player.addEventHandler(player.EVENT.ON_FULLSCREEN_ENTER, fullscreenStateHandler);
1520 player.addEventHandler(player.EVENT.ON_FULLSCREEN_EXIT, fullscreenStateHandler);
1521 this.onClick.subscribe(function () {
1522 if (player.isFullscreen()) {
1523 player.exitFullscreen();
1524 }
1525 else {
1526 player.enterFullscreen();
1527 }
1528 });
1529 // Startup init
1530 fullscreenStateHandler();
1531 };
1532 return FullscreenToggleButton;
1533}(togglebutton_1.ToggleButton));
1534exports.FullscreenToggleButton = FullscreenToggleButton;
1535
1536},{"./togglebutton":59}],21:[function(require,module,exports){
1537"use strict";
1538var __extends = (this && this.__extends) || (function () {
1539 var extendStatics = Object.setPrototypeOf ||
1540 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
1541 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
1542 return function (d, b) {
1543 extendStatics(d, b);
1544 function __() { this.constructor = d; }
1545 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1546 };
1547})();
1548Object.defineProperty(exports, "__esModule", { value: true });
1549var playbacktogglebutton_1 = require("./playbacktogglebutton");
1550var dom_1 = require("../dom");
1551/**
1552 * A button that overlays the video and toggles between playback and pause.
1553 */
1554var HugePlaybackToggleButton = /** @class */ (function (_super) {
1555 __extends(HugePlaybackToggleButton, _super);
1556 function HugePlaybackToggleButton(config) {
1557 if (config === void 0) { config = {}; }
1558 var _this = _super.call(this, config) || this;
1559 _this.config = _this.mergeConfig(config, {
1560 cssClass: 'ui-hugeplaybacktogglebutton',
1561 text: 'Play/Pause',
1562 }, _this.config);
1563 return _this;
1564 }
1565 HugePlaybackToggleButton.prototype.configure = function (player, uimanager) {
1566 var _this = this;
1567 // Update button state through API events
1568 _super.prototype.configure.call(this, player, uimanager, false);
1569 var togglePlayback = function () {
1570 if (player.isPlaying()) {
1571 player.pause('ui');
1572 }
1573 else {
1574 player.play('ui');
1575 }
1576 };
1577 var toggleFullscreen = function () {
1578 if (player.isFullscreen()) {
1579 player.exitFullscreen();
1580 }
1581 else {
1582 player.enterFullscreen();
1583 }
1584 };
1585 var firstPlay = true;
1586 var clickTime = 0;
1587 var doubleClickTime = 0;
1588 /*
1589 * YouTube-style toggle button handling
1590 *
1591 * The goal is to prevent a short pause or playback interval between a click, that toggles playback, and a
1592 * double click, that toggles fullscreen. In this naive approach, the first click would e.g. start playback,
1593 * the second click would be detected as double click and toggle to fullscreen, and as second normal click stop
1594 * playback, which results is a short playback interval with max length of the double click detection
1595 * period (usually 500ms).
1596 *
1597 * To solve this issue, we defer handling of the first click for 200ms, which is almost unnoticeable to the user,
1598 * and just toggle playback if no second click (double click) has been registered during this period. If a double
1599 * click is registered, we just toggle the fullscreen. In the first 200ms, undesired playback changes thus cannot
1600 * happen. If a double click is registered within 500ms, we undo the playback change and switch fullscreen mode.
1601 * In the end, this method basically introduces a 200ms observing interval in which playback changes are prevented
1602 * if a double click happens.
1603 */
1604 this.onClick.subscribe(function () {
1605 // Directly start playback on first click of the button.
1606 // This is a required workaround for mobile browsers where video playback needs to be triggered directly
1607 // by the user. A deferred playback start through the timeout below is not considered as user action and
1608 // therefore ignored by mobile browsers.
1609 if (firstPlay) {
1610 // Try to start playback. Then we wait for ON_PLAY and only when it arrives, we disable the firstPlay flag.
1611 // If we disable the flag here, onClick was triggered programmatically instead of by a user interaction, and
1612 // playback is blocked (e.g. on mobile devices due to the programmatic play() call), we loose the chance to
1613 // ever start playback through a user interaction again with this button.
1614 togglePlayback();
1615 return;
1616 }
1617 var now = Date.now();
1618 if (now - clickTime < 200) {
1619 // We have a double click inside the 200ms interval, just toggle fullscreen mode
1620 toggleFullscreen();
1621 doubleClickTime = now;
1622 return;
1623 }
1624 else if (now - clickTime < 500) {
1625 // We have a double click inside the 500ms interval, undo playback toggle and toggle fullscreen mode
1626 toggleFullscreen();
1627 togglePlayback();
1628 doubleClickTime = now;
1629 return;
1630 }
1631 clickTime = now;
1632 setTimeout(function () {
1633 if (Date.now() - doubleClickTime > 200) {
1634 // No double click detected, so we toggle playback and wait what happens next
1635 togglePlayback();
1636 }
1637 }, 200);
1638 });
1639 player.addEventHandler(player.EVENT.ON_PLAY, function () {
1640 // Playback has really started, we can disable the flag to switch to normal toggle button handling
1641 firstPlay = false;
1642 });
1643 player.addEventHandler(player.EVENT.ON_WARNING, function (event) {
1644 // 5008 == Playback could not be started
1645 if (event.code === 5008) {
1646 // if playback could not be started, reset the first play flag as we need the user interaction to start
1647 firstPlay = true;
1648 }
1649 });
1650 // Hide button while initializing a Cast session
1651 var castInitializationHandler = function (event) {
1652 if (event.type === player.EVENT.ON_CAST_START) {
1653 // Hide button when session is being initialized
1654 _this.hide();
1655 }
1656 else {
1657 // Show button when session is established or initialization was aborted
1658 _this.show();
1659 }
1660 };
1661 player.addEventHandler(player.EVENT.ON_CAST_START, castInitializationHandler);
1662 player.addEventHandler(player.EVENT.ON_CAST_STARTED, castInitializationHandler);
1663 player.addEventHandler(player.EVENT.ON_CAST_STOPPED, castInitializationHandler);
1664 var suppressPlayButtonTransitionAnimation = function () {
1665 // Disable the current animation
1666 _this.setTransitionAnimationsEnabled(false);
1667 // Enable the transition animations for the next state change
1668 _this.onToggle.subscribeOnce(function () {
1669 _this.setTransitionAnimationsEnabled(true);
1670 });
1671 };
1672 // Hide the play button animation when the UI is loaded (it should only be animated on state changes)
1673 suppressPlayButtonTransitionAnimation();
1674 var isAutoplayEnabled = player.getConfig().playback && Boolean(player.getConfig().playback.autoplay);
1675 // We only know if an autoplay attempt is upcoming if the player is not yet ready. It the player is already ready,
1676 // the attempt might be upcoming or might have already happened, but we don't have to handle that because we can
1677 // simply rely on isPlaying and the play state events.
1678 var isAutoplayUpcoming = !player.isReady() && isAutoplayEnabled;
1679 // Hide the play button when the player is already playing or autoplay is upcoming
1680 if (player.isPlaying() || isAutoplayUpcoming) {
1681 // Hide the play button (switch to playing state)
1682 this.on();
1683 // Disable the animation of the playing state switch
1684 suppressPlayButtonTransitionAnimation();
1685 // Show the play button without an animation if a play attempt is blocked
1686 player.addEventHandler(player.EVENT.ON_WARNING, function (event) {
1687 if (event.code === 5008) {
1688 suppressPlayButtonTransitionAnimation();
1689 }
1690 });
1691 }
1692 };
1693 HugePlaybackToggleButton.prototype.toDomElement = function () {
1694 var buttonElement = _super.prototype.toDomElement.call(this);
1695 // Add child that contains the play button image
1696 // Setting the image directly on the button does not work together with scaling animations, because the button
1697 // can cover the whole video player are and scaling would extend it beyond. By adding an inner element, confined
1698 // to the size if the image, it can scale inside the player without overshooting.
1699 buttonElement.append(new dom_1.DOM('div', {
1700 'class': this.prefixCss('image'),
1701 }));
1702 return buttonElement;
1703 };
1704 /**
1705 * Enables or disables the play state transition animations of the play button image. Can be used to suppress
1706 * animations.
1707 * @param {boolean} enabled true to enable the animations (default), false to disable them
1708 */
1709 HugePlaybackToggleButton.prototype.setTransitionAnimationsEnabled = function (enabled) {
1710 var noTransitionAnimationsClass = this.prefixCss('no-transition-animations');
1711 if (enabled) {
1712 this.getDomElement().removeClass(noTransitionAnimationsClass);
1713 }
1714 else if (!this.getDomElement().hasClass(noTransitionAnimationsClass)) {
1715 this.getDomElement().addClass(noTransitionAnimationsClass);
1716 }
1717 };
1718 return HugePlaybackToggleButton;
1719}(playbacktogglebutton_1.PlaybackToggleButton));
1720exports.HugePlaybackToggleButton = HugePlaybackToggleButton;
1721
1722},{"../dom":68,"./playbacktogglebutton":30}],22:[function(require,module,exports){
1723"use strict";
1724var __extends = (this && this.__extends) || (function () {
1725 var extendStatics = Object.setPrototypeOf ||
1726 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
1727 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
1728 return function (d, b) {
1729 extendStatics(d, b);
1730 function __() { this.constructor = d; }
1731 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1732 };
1733})();
1734Object.defineProperty(exports, "__esModule", { value: true });
1735var button_1 = require("./button");
1736var dom_1 = require("../dom");
1737/**
1738 * A button to play/replay a video.
1739 */
1740var HugeReplayButton = /** @class */ (function (_super) {
1741 __extends(HugeReplayButton, _super);
1742 function HugeReplayButton(config) {
1743 if (config === void 0) { config = {}; }
1744 var _this = _super.call(this, config) || this;
1745 _this.config = _this.mergeConfig(config, {
1746 cssClass: 'ui-hugereplaybutton',
1747 text: 'Replay',
1748 }, _this.config);
1749 return _this;
1750 }
1751 HugeReplayButton.prototype.configure = function (player, uimanager) {
1752 _super.prototype.configure.call(this, player, uimanager);
1753 this.onClick.subscribe(function () {
1754 player.play('ui');
1755 });
1756 };
1757 HugeReplayButton.prototype.toDomElement = function () {
1758 var buttonElement = _super.prototype.toDomElement.call(this);
1759 // Add child that contains the play button image
1760 // Setting the image directly on the button does not work together with scaling animations, because the button
1761 // can cover the whole video player are and scaling would extend it beyond. By adding an inner element, confined
1762 // to the size if the image, it can scale inside the player without overshooting.
1763 buttonElement.append(new dom_1.DOM('div', {
1764 'class': this.prefixCss('image'),
1765 }));
1766 return buttonElement;
1767 };
1768 return HugeReplayButton;
1769}(button_1.Button));
1770exports.HugeReplayButton = HugeReplayButton;
1771
1772},{"../dom":68,"./button":10}],23:[function(require,module,exports){
1773"use strict";
1774var __extends = (this && this.__extends) || (function () {
1775 var extendStatics = Object.setPrototypeOf ||
1776 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
1777 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
1778 return function (d, b) {
1779 extendStatics(d, b);
1780 function __() { this.constructor = d; }
1781 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1782 };
1783})();
1784Object.defineProperty(exports, "__esModule", { value: true });
1785var listselector_1 = require("./listselector");
1786var dom_1 = require("../dom");
1787var ItemSelectionList = /** @class */ (function (_super) {
1788 __extends(ItemSelectionList, _super);
1789 function ItemSelectionList(config) {
1790 if (config === void 0) { config = {}; }
1791 var _this = _super.call(this, config) || this;
1792 _this.config = _this.mergeConfig(config, {
1793 tag: 'ul',
1794 cssClass: 'ui-itemselectionlist',
1795 }, _this.config);
1796 return _this;
1797 }
1798 ItemSelectionList.prototype.isActive = function () {
1799 return this.items.length > 1;
1800 };
1801 ItemSelectionList.prototype.toDomElement = function () {
1802 var listElement = new dom_1.DOM('ul', {
1803 'id': this.config.id,
1804 'class': this.getCssClasses(),
1805 });
1806 this.listElement = listElement;
1807 this.updateDomItems();
1808 return listElement;
1809 };
1810 ItemSelectionList.prototype.updateDomItems = function (selectedValue) {
1811 var _this = this;
1812 if (selectedValue === void 0) { selectedValue = null; }
1813 // Delete all children
1814 this.listElement.empty();
1815 var selectedListItem = null;
1816 var selectItem = function (listItem) {
1817 listItem.addClass(_this.prefixCss(ItemSelectionList.CLASS_SELECTED));
1818 };
1819 var deselectItem = function (listItem) {
1820 listItem.removeClass(_this.prefixCss(ItemSelectionList.CLASS_SELECTED));
1821 };
1822 var _loop_1 = function (item) {
1823 var listItem = new dom_1.DOM('li', {
1824 'type': 'li',
1825 'class': this_1.prefixCss('ui-selectionlistitem'),
1826 }).append(new dom_1.DOM('a', {}).html(item.label));
1827 if (!selectedListItem) {
1828 if (selectedValue == null) { // If there is no pre-selected value, select the first one
1829 selectedListItem = listItem;
1830 }
1831 else if (String(selectedValue) === item.key) { // convert selectedValue to string to catch 'null'/null case
1832 selectedListItem = listItem;
1833 }
1834 }
1835 // Handle list item selections
1836 listItem.on('click', function () {
1837 // Deselect the previous item (if there was a selected item)
1838 if (selectedListItem) {
1839 deselectItem(selectedListItem);
1840 }
1841 // Select the clicked item
1842 selectedListItem = listItem;
1843 selectItem(listItem);
1844 // Fire the event
1845 _this.onItemSelectedEvent(item.key, false);
1846 });
1847 // Select default item
1848 if (selectedListItem) {
1849 selectItem(selectedListItem);
1850 }
1851 this_1.listElement.append(listItem);
1852 };
1853 var this_1 = this;
1854 for (var _i = 0, _a = this.items; _i < _a.length; _i++) {
1855 var item = _a[_i];
1856 _loop_1(item);
1857 }
1858 };
1859 ItemSelectionList.prototype.onItemAddedEvent = function (value) {
1860 _super.prototype.onItemAddedEvent.call(this, value);
1861 this.updateDomItems(this.selectedItem);
1862 };
1863 ItemSelectionList.prototype.onItemRemovedEvent = function (value) {
1864 _super.prototype.onItemRemovedEvent.call(this, value);
1865 this.updateDomItems(this.selectedItem);
1866 };
1867 ItemSelectionList.prototype.onItemSelectedEvent = function (value, updateDomItems) {
1868 if (updateDomItems === void 0) { updateDomItems = true; }
1869 _super.prototype.onItemSelectedEvent.call(this, value);
1870 if (updateDomItems) {
1871 this.updateDomItems(value);
1872 }
1873 };
1874 ItemSelectionList.CLASS_SELECTED = 'selected';
1875 return ItemSelectionList;
1876}(listselector_1.ListSelector));
1877exports.ItemSelectionList = ItemSelectionList;
1878
1879},{"../dom":68,"./listselector":25}],24:[function(require,module,exports){
1880"use strict";
1881var __extends = (this && this.__extends) || (function () {
1882 var extendStatics = Object.setPrototypeOf ||
1883 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
1884 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
1885 return function (d, b) {
1886 extendStatics(d, b);
1887 function __() { this.constructor = d; }
1888 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1889 };
1890})();
1891Object.defineProperty(exports, "__esModule", { value: true });
1892var component_1 = require("./component");
1893var dom_1 = require("../dom");
1894var eventdispatcher_1 = require("../eventdispatcher");
1895/**
1896 * A simple text label.
1897 *
1898 * DOM example:
1899 * <code>
1900 * <span class='ui-label'>...some text...</span>
1901 * </code>
1902 */
1903var Label = /** @class */ (function (_super) {
1904 __extends(Label, _super);
1905 function Label(config) {
1906 if (config === void 0) { config = {}; }
1907 var _this = _super.call(this, config) || this;
1908 _this.labelEvents = {
1909 onClick: new eventdispatcher_1.EventDispatcher(),
1910 onTextChanged: new eventdispatcher_1.EventDispatcher(),
1911 };
1912 _this.config = _this.mergeConfig(config, {
1913 cssClass: 'ui-label',
1914 }, _this.config);
1915 _this.text = _this.config.text;
1916 return _this;
1917 }
1918 Label.prototype.toDomElement = function () {
1919 var _this = this;
1920 var labelElement = new dom_1.DOM('span', {
1921 'id': this.config.id,
1922 'class': this.getCssClasses(),
1923 }).html(this.text);
1924 labelElement.on('click', function () {
1925 _this.onClickEvent();
1926 });
1927 return labelElement;
1928 };
1929 /**
1930 * Set the text on this label.
1931 * @param text
1932 */
1933 Label.prototype.setText = function (text) {
1934 this.text = text;
1935 this.getDomElement().html(text);
1936 this.onTextChangedEvent(text);
1937 };
1938 /**
1939 * Gets the text on this label.
1940 * @return {string} The text on the label
1941 */
1942 Label.prototype.getText = function () {
1943 return this.text;
1944 };
1945 /**
1946 * Clears the text on this label.
1947 */
1948 Label.prototype.clearText = function () {
1949 this.getDomElement().html('');
1950 this.onTextChangedEvent(null);
1951 };
1952 /**
1953 * Tests if the label is empty and does not contain any text.
1954 * @return {boolean} True if the label is empty, else false
1955 */
1956 Label.prototype.isEmpty = function () {
1957 return !this.text;
1958 };
1959 /**
1960 * Fires the {@link #onClick} event.
1961 * Can be used by subclasses to listen to this event without subscribing an event listener by overwriting the method
1962 * and calling the super method.
1963 */
1964 Label.prototype.onClickEvent = function () {
1965 this.labelEvents.onClick.dispatch(this);
1966 };
1967 /**
1968 * Fires the {@link #onClick} event.
1969 * Can be used by subclasses to listen to this event without subscribing an event listener by overwriting the method
1970 * and calling the super method.
1971 */
1972 Label.prototype.onTextChangedEvent = function (text) {
1973 this.labelEvents.onTextChanged.dispatch(this, text);
1974 };
1975 Object.defineProperty(Label.prototype, "onClick", {
1976 /**
1977 * Gets the event that is fired when the label is clicked.
1978 * @returns {Event<Label<LabelConfig>, NoArgs>}
1979 */
1980 get: function () {
1981 return this.labelEvents.onClick.getEvent();
1982 },
1983 enumerable: true,
1984 configurable: true
1985 });
1986 Object.defineProperty(Label.prototype, "onTextChanged", {
1987 /**
1988 * Gets the event that is fired when the text on the label is changed.
1989 * @returns {Event<Label<LabelConfig>, string>}
1990 */
1991 get: function () {
1992 return this.labelEvents.onTextChanged.getEvent();
1993 },
1994 enumerable: true,
1995 configurable: true
1996 });
1997 return Label;
1998}(component_1.Component));
1999exports.Label = Label;
2000
2001},{"../dom":68,"../eventdispatcher":82,"./component":16}],25:[function(require,module,exports){
2002"use strict";
2003var __extends = (this && this.__extends) || (function () {
2004 var extendStatics = Object.setPrototypeOf ||
2005 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2006 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
2007 return function (d, b) {
2008 extendStatics(d, b);
2009 function __() { this.constructor = d; }
2010 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2011 };
2012})();
2013Object.defineProperty(exports, "__esModule", { value: true });
2014var component_1 = require("./component");
2015var eventdispatcher_1 = require("../eventdispatcher");
2016var arrayutils_1 = require("../arrayutils");
2017var ListSelector = /** @class */ (function (_super) {
2018 __extends(ListSelector, _super);
2019 function ListSelector(config) {
2020 if (config === void 0) { config = {}; }
2021 var _this = _super.call(this, config) || this;
2022 _this.listSelectorEvents = {
2023 onItemAdded: new eventdispatcher_1.EventDispatcher(),
2024 onItemRemoved: new eventdispatcher_1.EventDispatcher(),
2025 onItemSelected: new eventdispatcher_1.EventDispatcher(),
2026 };
2027 _this.config = _this.mergeConfig(config, {
2028 items: [],
2029 cssClass: 'ui-listselector',
2030 }, _this.config);
2031 _this.items = _this.config.items;
2032 return _this;
2033 }
2034 ListSelector.prototype.getItemIndex = function (key) {
2035 for (var index in this.items) {
2036 if (key === this.items[index].key) {
2037 return parseInt(index);
2038 }
2039 }
2040 return -1;
2041 };
2042 /**
2043 * Checks if the specified item is part of this selector.
2044 * @param key the key of the item to check
2045 * @returns {boolean} true if the item is part of this selector, else false
2046 */
2047 ListSelector.prototype.hasItem = function (key) {
2048 return this.getItemIndex(key) > -1;
2049 };
2050 /**
2051 * Adds an item to this selector by appending it to the end of the list of items. If an item with the specified
2052 * key already exists, it is replaced.
2053 * @param key the key of the item to add
2054 * @param label the (human-readable) label of the item to add
2055 */
2056 ListSelector.prototype.addItem = function (key, label) {
2057 var listItem = { key: key, label: label };
2058 // Apply filter function
2059 if (this.config.filter && !this.config.filter(listItem)) {
2060 return;
2061 }
2062 // Apply translator function
2063 if (this.config.translator) {
2064 listItem.label = this.config.translator(listItem);
2065 }
2066 this.removeItem(key); // Try to remove key first to get overwrite behavior and avoid duplicate keys
2067 this.items.push(listItem);
2068 this.onItemAddedEvent(key);
2069 };
2070 /**
2071 * Removes an item from this selector.
2072 * @param key the key of the item to remove
2073 * @returns {boolean} true if removal was successful, false if the item is not part of this selector
2074 */
2075 ListSelector.prototype.removeItem = function (key) {
2076 var index = this.getItemIndex(key);
2077 if (index > -1) {
2078 arrayutils_1.ArrayUtils.remove(this.items, this.items[index]);
2079 this.onItemRemovedEvent(key);
2080 return true;
2081 }
2082 return false;
2083 };
2084 /**
2085 * Selects an item from the items in this selector.
2086 * @param key the key of the item to select
2087 * @returns {boolean} true is the selection was successful, false if the selected item is not part of the selector
2088 */
2089 ListSelector.prototype.selectItem = function (key) {
2090 if (key === this.selectedItem) {
2091 // itemConfig is already selected, suppress any further action
2092 return true;
2093 }
2094 var index = this.getItemIndex(key);
2095 if (index > -1) {
2096 this.selectedItem = key;
2097 this.onItemSelectedEvent(key);
2098 return true;
2099 }
2100 return false;
2101 };
2102 /**
2103 * Returns the key of the selected item.
2104 * @returns {string} the key of the selected item or null if no item is selected
2105 */
2106 ListSelector.prototype.getSelectedItem = function () {
2107 return this.selectedItem;
2108 };
2109 /**
2110 * Removes all items from this selector.
2111 */
2112 ListSelector.prototype.clearItems = function () {
2113 // local copy for iteration after clear
2114 var items = this.items;
2115 // clear items
2116 this.items = [];
2117 // clear the selection as the selected item is also removed
2118 this.selectedItem = null;
2119 // fire events
2120 for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
2121 var item = items_1[_i];
2122 this.onItemRemovedEvent(item.key);
2123 }
2124 };
2125 /**
2126 * Returns the number of items in this selector.
2127 * @returns {number}
2128 */
2129 ListSelector.prototype.itemCount = function () {
2130 return Object.keys(this.items).length;
2131 };
2132 ListSelector.prototype.onItemAddedEvent = function (key) {
2133 this.listSelectorEvents.onItemAdded.dispatch(this, key);
2134 };
2135 ListSelector.prototype.onItemRemovedEvent = function (key) {
2136 this.listSelectorEvents.onItemRemoved.dispatch(this, key);
2137 };
2138 ListSelector.prototype.onItemSelectedEvent = function (key) {
2139 this.listSelectorEvents.onItemSelected.dispatch(this, key);
2140 };
2141 Object.defineProperty(ListSelector.prototype, "onItemAdded", {
2142 /**
2143 * Gets the event that is fired when an item is added to the list of items.
2144 * @returns {Event<ListSelector<Config>, string>}
2145 */
2146 get: function () {
2147 return this.listSelectorEvents.onItemAdded.getEvent();
2148 },
2149 enumerable: true,
2150 configurable: true
2151 });
2152 Object.defineProperty(ListSelector.prototype, "onItemRemoved", {
2153 /**
2154 * Gets the event that is fired when an item is removed from the list of items.
2155 * @returns {Event<ListSelector<Config>, string>}
2156 */
2157 get: function () {
2158 return this.listSelectorEvents.onItemRemoved.getEvent();
2159 },
2160 enumerable: true,
2161 configurable: true
2162 });
2163 Object.defineProperty(ListSelector.prototype, "onItemSelected", {
2164 /**
2165 * Gets the event that is fired when an item is selected from the list of items.
2166 * @returns {Event<ListSelector<Config>, string>}
2167 */
2168 get: function () {
2169 return this.listSelectorEvents.onItemSelected.getEvent();
2170 },
2171 enumerable: true,
2172 configurable: true
2173 });
2174 return ListSelector;
2175}(component_1.Component));
2176exports.ListSelector = ListSelector;
2177
2178},{"../arrayutils":1,"../eventdispatcher":82,"./component":16}],26:[function(require,module,exports){
2179"use strict";
2180var __extends = (this && this.__extends) || (function () {
2181 var extendStatics = Object.setPrototypeOf ||
2182 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2183 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
2184 return function (d, b) {
2185 extendStatics(d, b);
2186 function __() { this.constructor = d; }
2187 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2188 };
2189})();
2190Object.defineProperty(exports, "__esModule", { value: true });
2191var label_1 = require("./label");
2192/**
2193 * Enumerates the types of content that the {@link MetadataLabel} can display.
2194 */
2195var MetadataLabelContent;
2196(function (MetadataLabelContent) {
2197 /**
2198 * Title of the data source.
2199 */
2200 MetadataLabelContent[MetadataLabelContent["Title"] = 0] = "Title";
2201 /**
2202 * Description fo the data source.
2203 */
2204 MetadataLabelContent[MetadataLabelContent["Description"] = 1] = "Description";
2205})(MetadataLabelContent = exports.MetadataLabelContent || (exports.MetadataLabelContent = {}));
2206/**
2207 * A label that can be configured to display certain metadata.
2208 */
2209var MetadataLabel = /** @class */ (function (_super) {
2210 __extends(MetadataLabel, _super);
2211 function MetadataLabel(config) {
2212 var _this = _super.call(this, config) || this;
2213 _this.config = _this.mergeConfig(config, {
2214 cssClasses: ['label-metadata', 'label-metadata-' + MetadataLabelContent[config.content].toLowerCase()],
2215 }, _this.config);
2216 return _this;
2217 }
2218 MetadataLabel.prototype.configure = function (player, uimanager) {
2219 var _this = this;
2220 _super.prototype.configure.call(this, player, uimanager);
2221 var config = this.getConfig();
2222 var uiconfig = uimanager.getConfig();
2223 var init = function () {
2224 switch (config.content) {
2225 case MetadataLabelContent.Title:
2226 _this.setText(uiconfig.metadata.title);
2227 break;
2228 case MetadataLabelContent.Description:
2229 _this.setText(uiconfig.metadata.description);
2230 break;
2231 }
2232 };
2233 var unload = function () {
2234 _this.setText(null);
2235 };
2236 // Init label
2237 init();
2238 // Reinit label when a new source is loaded
2239 player.addEventHandler(player.EVENT.ON_SOURCE_LOADED, init);
2240 // Clear labels when source is unloaded
2241 player.addEventHandler(player.EVENT.ON_SOURCE_UNLOADED, unload);
2242 };
2243 return MetadataLabel;
2244}(label_1.Label));
2245exports.MetadataLabel = MetadataLabel;
2246
2247},{"./label":24}],27:[function(require,module,exports){
2248"use strict";
2249var __extends = (this && this.__extends) || (function () {
2250 var extendStatics = Object.setPrototypeOf ||
2251 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2252 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
2253 return function (d, b) {
2254 extendStatics(d, b);
2255 function __() { this.constructor = d; }
2256 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2257 };
2258})();
2259Object.defineProperty(exports, "__esModule", { value: true });
2260var togglebutton_1 = require("./togglebutton");
2261/**
2262 * A button that toggles Apple macOS picture-in-picture mode.
2263 */
2264var PictureInPictureToggleButton = /** @class */ (function (_super) {
2265 __extends(PictureInPictureToggleButton, _super);
2266 function PictureInPictureToggleButton(config) {
2267 if (config === void 0) { config = {}; }
2268 var _this = _super.call(this, config) || this;
2269 _this.config = _this.mergeConfig(config, {
2270 cssClass: 'ui-piptogglebutton',
2271 text: 'Picture-in-Picture',
2272 }, _this.config);
2273 return _this;
2274 }
2275 PictureInPictureToggleButton.prototype.configure = function (player, uimanager) {
2276 var _this = this;
2277 _super.prototype.configure.call(this, player, uimanager);
2278 console.log('chrome pip: ' + document.pictureInPictureEnabled);
2279 if (!player.isPictureInPictureAvailable || !document.pictureInPictureEnabled) {
2280 // If the player does not support PIP (player 7.0), we just hide this component and skip configuration
2281 this.hide();
2282 return;
2283 }
2284 this.onClick.subscribe(function () {
2285 if (player.isPictureInPictureAvailable() || document.pictureInPictureEnabled) {
2286
2287 if (player.isPictureInPicture() || document.pictureInPictureElement) {
2288 player.exitPictureInPicture();
2289 document.exitPictureInPicture();
2290 }
2291 else {
2292 player.enterPictureInPicture();
2293 document.getElementById('bitmovinplayer-video-player').requestPictureInPicture();
2294 }
2295 }
2296 else {
2297 if (console) {
2298 console.log('PIP unavailable');
2299 }
2300 }
2301 });
2302 var pipAvailableHander = function () {
2303 if (player.isPictureInPictureAvailable() || document.pictureInPictureEnabled) {
2304 _this.show();
2305 }
2306 else {
2307 _this.hide();
2308 }
2309 };
2310 player.addEventHandler(player.EVENT.ON_READY, pipAvailableHander);
2311 // Toggle button 'on' state
2312 player.addEventHandler(player.EVENT.ON_PICTURE_IN_PICTURE_ENTER, function () {
2313 _this.on();
2314 });
2315 player.addEventHandler(player.EVENT.ON_PICTURE_IN_PICTURE_EXIT, function () {
2316 _this.off();
2317 });
2318 // Startup init
2319 pipAvailableHander(); // Hide button if PIP not available
2320 if (player.isPictureInPicture()) {
2321 this.on();
2322 }
2323 };
2324 return PictureInPictureToggleButton;
2325}(togglebutton_1.ToggleButton));
2326exports.PictureInPictureToggleButton = PictureInPictureToggleButton;
2327
2328},{"./togglebutton":59}],28:[function(require,module,exports){
2329"use strict";
2330var __extends = (this && this.__extends) || (function () {
2331 var extendStatics = Object.setPrototypeOf ||
2332 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2333 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
2334 return function (d, b) {
2335 extendStatics(d, b);
2336 function __() { this.constructor = d; }
2337 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2338 };
2339})();
2340Object.defineProperty(exports, "__esModule", { value: true });
2341var selectbox_1 = require("./selectbox");
2342/**
2343 * A select box providing a selection of different playback speeds.
2344 */
2345var PlaybackSpeedSelectBox = /** @class */ (function (_super) {
2346 __extends(PlaybackSpeedSelectBox, _super);
2347 function PlaybackSpeedSelectBox(config) {
2348 if (config === void 0) { config = {}; }
2349 var _this = _super.call(this, config) || this;
2350 _this.defaultPlaybackSpeeds = [0.25, 0.5, 1, 1.5, 2];
2351 return _this;
2352 }
2353 PlaybackSpeedSelectBox.prototype.configure = function (player, uimanager) {
2354 var _this = this;
2355 _super.prototype.configure.call(this, player, uimanager);
2356 this.addDefaultItems();
2357 this.onItemSelected.subscribe(function (sender, value) {
2358 player.setPlaybackSpeed(parseFloat(value));
2359 _this.selectItem(value);
2360 });
2361 var setDefaultValue = function () {
2362 var playbackSpeed = player.getPlaybackSpeed();
2363 _this.setSpeed(playbackSpeed);
2364 };
2365 // when the player hits onReady again, adjust the playback speed selection
2366 player.addEventHandler(player.EVENT.ON_READY, setDefaultValue);
2367 if (player.EVENT.ON_PLAYBACK_SPEED_CHANGED) {
2368 // Since player 7.8.0
2369 player.addEventHandler(player.EVENT.ON_PLAYBACK_SPEED_CHANGED, setDefaultValue);
2370 }
2371 };
2372 PlaybackSpeedSelectBox.prototype.setSpeed = function (speed) {
2373 if (!this.selectItem(String(speed))) {
2374 // a playback speed was set which is not in the list, add it to the list to show it to the user
2375 this.clearItems();
2376 this.addDefaultItems([speed]);
2377 this.selectItem(String(speed));
2378 }
2379 };
2380 PlaybackSpeedSelectBox.prototype.addDefaultItems = function (customItems) {
2381 var _this = this;
2382 if (customItems === void 0) { customItems = []; }
2383 var sortedSpeeds = this.defaultPlaybackSpeeds.concat(customItems).sort();
2384 sortedSpeeds.forEach(function (element) {
2385 if (element !== 1) {
2386 _this.addItem(String(element), element + "x");
2387 }
2388 else {
2389 _this.addItem(String(element), 'Normal');
2390 }
2391 });
2392 };
2393 PlaybackSpeedSelectBox.prototype.clearItems = function () {
2394 this.items = [];
2395 this.selectedItem = null;
2396 };
2397 return PlaybackSpeedSelectBox;
2398}(selectbox_1.SelectBox));
2399exports.PlaybackSpeedSelectBox = PlaybackSpeedSelectBox;
2400
2401},{"./selectbox":35}],29:[function(require,module,exports){
2402"use strict";
2403var __extends = (this && this.__extends) || (function () {
2404 var extendStatics = Object.setPrototypeOf ||
2405 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2406 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
2407 return function (d, b) {
2408 extendStatics(d, b);
2409 function __() { this.constructor = d; }
2410 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2411 };
2412})();
2413Object.defineProperty(exports, "__esModule", { value: true });
2414var label_1 = require("./label");
2415var playerutils_1 = require("../playerutils");
2416var stringutils_1 = require("../stringutils");
2417var PlaybackTimeLabelMode;
2418(function (PlaybackTimeLabelMode) {
2419 PlaybackTimeLabelMode[PlaybackTimeLabelMode["CurrentTime"] = 0] = "CurrentTime";
2420 PlaybackTimeLabelMode[PlaybackTimeLabelMode["TotalTime"] = 1] = "TotalTime";
2421 PlaybackTimeLabelMode[PlaybackTimeLabelMode["CurrentAndTotalTime"] = 2] = "CurrentAndTotalTime";
2422})(PlaybackTimeLabelMode = exports.PlaybackTimeLabelMode || (exports.PlaybackTimeLabelMode = {}));
2423/**
2424 * A label that display the current playback time and the total time through {@link PlaybackTimeLabel#setTime setTime}
2425 * or any string through {@link PlaybackTimeLabel#setText setText}.
2426 */
2427var PlaybackTimeLabel = /** @class */ (function (_super) {
2428 __extends(PlaybackTimeLabel, _super);
2429 function PlaybackTimeLabel(config) {
2430 if (config === void 0) { config = {}; }
2431 var _this = _super.call(this, config) || this;
2432 _this.config = _this.mergeConfig(config, {
2433 cssClass: 'ui-playbacktimelabel',
2434 timeLabelMode: PlaybackTimeLabelMode.CurrentAndTotalTime,
2435 hideInLivePlayback: false,
2436 }, _this.config);
2437 return _this;
2438 }
2439 PlaybackTimeLabel.prototype.configure = function (player, uimanager) {
2440 var _this = this;
2441 _super.prototype.configure.call(this, player, uimanager);
2442 var config = this.getConfig();
2443 var live = false;
2444 var liveCssClass = this.prefixCss('ui-playbacktimelabel-live');
2445 var liveEdgeCssClass = this.prefixCss('ui-playbacktimelabel-live-edge');
2446 var minWidth = 0;
2447 var liveClickHandler = function () {
2448 player.timeShift(0);
2449 };
2450 var updateLiveState = function () {
2451 // Player is playing a live stream when the duration is infinite
2452 live = player.isLive();
2453 // Attach/detach live marker class
2454 if (live) {
2455 _this.getDomElement().addClass(liveCssClass);
2456 _this.setText('Live');
2457 if (config.hideInLivePlayback) {
2458 _this.hide();
2459 }
2460 _this.onClick.subscribe(liveClickHandler);
2461 updateLiveTimeshiftState();
2462 }
2463 else {
2464 _this.getDomElement().removeClass(liveCssClass);
2465 _this.getDomElement().removeClass(liveEdgeCssClass);
2466 _this.show();
2467 _this.onClick.unsubscribe(liveClickHandler);
2468 }
2469 };
2470 var updateLiveTimeshiftState = function () {
2471 if (!live) {
2472 return;
2473 }
2474 // The player is only at the live edge iff the stream is not shifted and it is actually playing or playback has
2475 // never been started (meaning it isn't paused). A player that is paused is always behind the live edge.
2476 // An exception is made for live streams without a timeshift window, because here we "stop" playback instead
2477 // of pausing it (from a UI perspective), so we keep the live edge indicator on because a play would always
2478 // resume at the live edge.
2479 var isTimeshifted = player.getTimeShift() < 0;
2480 var isTimeshiftAvailable = player.getMaxTimeShift() < 0;
2481 if (!isTimeshifted && (!player.isPaused() || !isTimeshiftAvailable)) {
2482 _this.getDomElement().addClass(liveEdgeCssClass);
2483 }
2484 else {
2485 _this.getDomElement().removeClass(liveEdgeCssClass);
2486 }
2487 };
2488 var liveStreamDetector = new playerutils_1.PlayerUtils.LiveStreamDetector(player);
2489 liveStreamDetector.onLiveChanged.subscribe(function (sender, args) {
2490 live = args.live;
2491 updateLiveState();
2492 });
2493 liveStreamDetector.detect(); // Initial detection
2494 var playbackTimeHandler = function () {
2495 if (!live && player.getDuration() !== Infinity) {
2496 _this.setTime(player.getCurrentTime(), player.getDuration());
2497 }
2498 // To avoid 'jumping' in the UI by varying label sizes due to non-monospaced fonts,
2499 // we gradually increase the min-width with the content to reach a stable size.
2500 var width = _this.getDomElement().width();
2501 if (width > minWidth) {
2502 minWidth = width;
2503 _this.getDomElement().css({
2504 'min-width': minWidth + 'px',
2505 });
2506 }
2507 };
2508 player.addEventHandler(player.EVENT.ON_TIME_CHANGED, playbackTimeHandler);
2509 player.addEventHandler(player.EVENT.ON_SEEKED, playbackTimeHandler);
2510 player.addEventHandler(player.EVENT.ON_CAST_TIME_UPDATED, playbackTimeHandler);
2511 player.addEventHandler(player.EVENT.ON_TIME_SHIFT, updateLiveTimeshiftState);
2512 player.addEventHandler(player.EVENT.ON_TIME_SHIFTED, updateLiveTimeshiftState);
2513 player.addEventHandler(player.EVENT.ON_PLAY, updateLiveTimeshiftState);
2514 player.addEventHandler(player.EVENT.ON_PAUSED, updateLiveTimeshiftState);
2515 var init = function () {
2516 // Reset min-width when a new source is ready (especially for switching VOD/Live modes where the label content
2517 // changes)
2518 minWidth = 0;
2519 _this.getDomElement().css({
2520 'min-width': null,
2521 });
2522 // Set time format depending on source duration
2523 _this.timeFormat = Math.abs(player.isLive() ? player.getMaxTimeShift() : player.getDuration()) >= 3600 ?
2524 stringutils_1.StringUtils.FORMAT_HHMMSS : stringutils_1.StringUtils.FORMAT_MMSS;
2525 // Update time after the format has been set
2526 playbackTimeHandler();
2527 };
2528 player.addEventHandler(player.EVENT.ON_READY, init);
2529 init();
2530 };
2531 /**
2532 * Sets the current playback time and total duration.
2533 * @param playbackSeconds the current playback time in seconds
2534 * @param durationSeconds the total duration in seconds
2535 */
2536 PlaybackTimeLabel.prototype.setTime = function (playbackSeconds, durationSeconds) {
2537 var currentTime = stringutils_1.StringUtils.secondsToTime(playbackSeconds, this.timeFormat);
2538 var totalTime = stringutils_1.StringUtils.secondsToTime(durationSeconds, this.timeFormat);
2539 switch (this.config.timeLabelMode) {
2540 case PlaybackTimeLabelMode.CurrentTime:
2541 this.setText("" + currentTime);
2542 break;
2543 case PlaybackTimeLabelMode.TotalTime:
2544 this.setText("" + totalTime);
2545 break;
2546 case PlaybackTimeLabelMode.CurrentAndTotalTime:
2547 this.setText(currentTime + " / " + totalTime);
2548 break;
2549 }
2550 };
2551 /**
2552 * Sets the current time format
2553 * @param timeFormat the time format
2554 */
2555 PlaybackTimeLabel.prototype.setTimeFormat = function (timeFormat) {
2556 this.timeFormat = timeFormat;
2557 };
2558 return PlaybackTimeLabel;
2559}(label_1.Label));
2560exports.PlaybackTimeLabel = PlaybackTimeLabel;
2561
2562},{"../playerutils":86,"../stringutils":88,"./label":24}],30:[function(require,module,exports){
2563"use strict";
2564var __extends = (this && this.__extends) || (function () {
2565 var extendStatics = Object.setPrototypeOf ||
2566 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2567 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
2568 return function (d, b) {
2569 extendStatics(d, b);
2570 function __() { this.constructor = d; }
2571 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2572 };
2573})();
2574Object.defineProperty(exports, "__esModule", { value: true });
2575var togglebutton_1 = require("./togglebutton");
2576var playerutils_1 = require("../playerutils");
2577/**
2578 * A button that toggles between playback and pause.
2579 */
2580var PlaybackToggleButton = /** @class */ (function (_super) {
2581 __extends(PlaybackToggleButton, _super);
2582 function PlaybackToggleButton(config) {
2583 if (config === void 0) { config = {}; }
2584 var _this = _super.call(this, config) || this;
2585 _this.config = _this.mergeConfig(config, {
2586 cssClass: 'ui-playbacktogglebutton',
2587 text: 'Play/Pause',
2588 }, _this.config);
2589 return _this;
2590 }
2591 PlaybackToggleButton.prototype.configure = function (player, uimanager, handleClickEvent) {
2592 var _this = this;
2593 if (handleClickEvent === void 0) { handleClickEvent = true; }
2594 _super.prototype.configure.call(this, player, uimanager);
2595 var isSeeking = false;
2596 // Handler to update button state based on player state
2597 var playbackStateHandler = function (event) {
2598 // If the UI is currently seeking, playback is temporarily stopped but the buttons should
2599 // not reflect that and stay as-is (e.g indicate playback while seeking).
2600 if (isSeeking) {
2601 return;
2602 }
2603 if (player.isPlaying()) {
2604 if (!player.isAd()) {
2605 const $adEl = document.getElementById('bitmovin-ima-container');
2606 if ($adEl) $adEl.remove();
2607 }
2608 _this.on();
2609 }
2610 else {
2611 _this.off();
2612 }
2613 };
2614 // Call handler upon these events
2615 player.addEventHandler(player.EVENT.ON_PLAY, playbackStateHandler);
2616 player.addEventHandler(player.EVENT.ON_PAUSED, playbackStateHandler);
2617 if (player.EVENT.ON_PLAYING) {
2618 // Since player 7.3. Not really necessary but just in case we ever miss the ON_PLAY event.
2619 player.addEventHandler(player.EVENT.ON_PLAYING, playbackStateHandler);
2620 }
2621 // after unloading + loading a new source, the player might be in a different playing state (from playing into stopped)
2622 player.addEventHandler(player.EVENT.ON_SOURCE_LOADED, playbackStateHandler);
2623 player.addEventHandler(player.EVENT.ON_SOURCE_UNLOADED, playbackStateHandler);
2624 // when playback finishes, player turns to paused mode
2625 player.addEventHandler(player.EVENT.ON_PLAYBACK_FINISHED, playbackStateHandler);
2626 player.addEventHandler(player.EVENT.ON_CAST_STARTED, playbackStateHandler);
2627 player.addEventHandler(player.EVENT.ON_CAST_PLAYING, playbackStateHandler);
2628 player.addEventHandler(player.EVENT.ON_CAST_PAUSED, playbackStateHandler);
2629 player.addEventHandler(player.EVENT.ON_CAST_PLAYBACK_FINISHED, playbackStateHandler);
2630 // When a playback attempt is rejected with warning 5008, we switch the button state back to off
2631 // This is required for blocked autoplay, because there is no ON_PAUSED event in such case
2632 player.addEventHandler(player.EVENT.ON_WARNING, function (event) {
2633 if (event.code === 5008) {
2634 _this.off();
2635 }
2636 });
2637 // Detect absence of timeshifting on live streams and add tagging class to convert button icons to play/stop
2638 var timeShiftDetector = new playerutils_1.PlayerUtils.TimeShiftAvailabilityDetector(player);
2639 timeShiftDetector.onTimeShiftAvailabilityChanged.subscribe(function (sender, args) {
2640 if (!args.timeShiftAvailable) {
2641 _this.getDomElement().addClass(_this.prefixCss(PlaybackToggleButton.CLASS_STOPTOGGLE));
2642 }
2643 else {
2644 _this.getDomElement().removeClass(_this.prefixCss(PlaybackToggleButton.CLASS_STOPTOGGLE));
2645 }
2646 });
2647 timeShiftDetector.detect(); // Initial detection
2648 if (handleClickEvent) {
2649 // Control player by button events
2650 // When a button event triggers a player API call, events are fired which in turn call the event handler
2651 // above that updated the button state.
2652 this.onClick.subscribe(function () {
2653 if (player.isPlaying()) {
2654 player.pause('ui');
2655 }
2656 else {
2657 player.play('ui');
2658 }
2659 });
2660 }
2661 // Track UI seeking status
2662 uimanager.onSeek.subscribe(function () {
2663 isSeeking = true;
2664 });
2665 uimanager.onSeeked.subscribe(function () {
2666 isSeeking = false;
2667 });
2668 // Startup init
2669 playbackStateHandler(null);
2670 };
2671 PlaybackToggleButton.CLASS_STOPTOGGLE = 'stoptoggle';
2672 return PlaybackToggleButton;
2673}(togglebutton_1.ToggleButton));
2674exports.PlaybackToggleButton = PlaybackToggleButton;
2675
2676},{"../playerutils":86,"./togglebutton":59}],31:[function(require,module,exports){
2677"use strict";
2678var __extends = (this && this.__extends) || (function () {
2679 var extendStatics = Object.setPrototypeOf ||
2680 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2681 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
2682 return function (d, b) {
2683 extendStatics(d, b);
2684 function __() { this.constructor = d; }
2685 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2686 };
2687})();
2688Object.defineProperty(exports, "__esModule", { value: true });
2689var container_1 = require("./container");
2690var hugeplaybacktogglebutton_1 = require("./hugeplaybacktogglebutton");
2691/**
2692 * Overlays the player and displays error messages.
2693 */
2694var PlaybackToggleOverlay = /** @class */ (function (_super) {
2695 __extends(PlaybackToggleOverlay, _super);
2696 function PlaybackToggleOverlay(config) {
2697 if (config === void 0) { config = {}; }
2698 var _this = _super.call(this, config) || this;
2699 _this.playbackToggleButton = new hugeplaybacktogglebutton_1.HugePlaybackToggleButton();
2700 _this.config = _this.mergeConfig(config, {
2701 cssClass: 'ui-playbacktoggle-overlay',
2702 components: [_this.playbackToggleButton],
2703 }, _this.config);
2704 return _this;
2705 }
2706 return PlaybackToggleOverlay;
2707}(container_1.Container));
2708exports.PlaybackToggleOverlay = PlaybackToggleOverlay;
2709
2710},{"./container":17,"./hugeplaybacktogglebutton":21}],32:[function(require,module,exports){
2711"use strict";
2712var __extends = (this && this.__extends) || (function () {
2713 var extendStatics = Object.setPrototypeOf ||
2714 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2715 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
2716 return function (d, b) {
2717 extendStatics(d, b);
2718 function __() { this.constructor = d; }
2719 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2720 };
2721})();
2722Object.defineProperty(exports, "__esModule", { value: true });
2723var container_1 = require("./container");
2724var component_1 = require("./component");
2725var dom_1 = require("../dom");
2726var stringutils_1 = require("../stringutils");
2727var hugereplaybutton_1 = require("./hugereplaybutton");
2728/**
2729 * Overlays the player and displays recommended videos.
2730 */
2731var RecommendationOverlay = /** @class */ (function (_super) {
2732 __extends(RecommendationOverlay, _super);
2733 function RecommendationOverlay(config) {
2734 if (config === void 0) { config = {}; }
2735 var _this = _super.call(this, config) || this;
2736 _this.replayButton = new hugereplaybutton_1.HugeReplayButton();
2737 _this.config = _this.mergeConfig(config, {
2738 cssClass: 'ui-recommendation-overlay',
2739 hidden: true,
2740 components: [_this.replayButton],
2741 }, _this.config);
2742 return _this;
2743 }
2744 RecommendationOverlay.prototype.configure = function (player, uimanager) {
2745 var _this = this;
2746 _super.prototype.configure.call(this, player, uimanager);
2747 var clearRecommendations = function () {
2748 for (var _i = 0, _a = _this.getComponents().slice(); _i < _a.length; _i++) {
2749 var component = _a[_i];
2750 if (component instanceof RecommendationItem) {
2751 _this.removeComponent(component);
2752 }
2753 }
2754 _this.updateComponents();
2755 _this.getDomElement().removeClass(_this.prefixCss('recommendations'));
2756 };
2757 var setupRecommendations = function () {
2758 clearRecommendations();
2759 var recommendations = uimanager.getConfig().recommendations;
2760 if (recommendations.length > 0) {
2761 var index = 1;
2762 for (var _i = 0, recommendations_1 = recommendations; _i < recommendations_1.length; _i++) {
2763 var item = recommendations_1[_i];
2764 _this.addComponent(new RecommendationItem({
2765 itemConfig: item,
2766 cssClasses: ['recommendation-item-' + (index++)],
2767 }));
2768 }
2769 _this.updateComponents(); // create container DOM elements
2770 _this.getDomElement().addClass(_this.prefixCss('recommendations'));
2771 }
2772 };
2773 // Add recommendation when a source is loaded
2774 player.addEventHandler(player.EVENT.ON_READY, setupRecommendations);
2775 // Remove recommendations and hide overlay when source is unloaded
2776 player.addEventHandler(player.EVENT.ON_SOURCE_UNLOADED, function () {
2777 clearRecommendations();
2778 _this.hide();
2779 });
2780 // Display recommendations when playback has finished
2781 player.addEventHandler(player.EVENT.ON_PLAYBACK_FINISHED, function () {
2782 // Dismiss ON_PLAYBACK_FINISHED events at the end of ads
2783 // TODO remove this workaround once issue #1278 is solved
2784 if (player.isAd()) {
2785 return;
2786 }
2787 _this.show();
2788 });
2789 // Hide recommendations when playback starts, e.g. a restart
2790 player.addEventHandler(player.EVENT.ON_PLAY, function () {
2791 _this.hide();
2792 });
2793 // Init on startup
2794 setupRecommendations();
2795 };
2796 return RecommendationOverlay;
2797}(container_1.Container));
2798exports.RecommendationOverlay = RecommendationOverlay;
2799/**
2800 * An item of the {@link RecommendationOverlay}. Used only internally in {@link RecommendationOverlay}.
2801 */
2802var RecommendationItem = /** @class */ (function (_super) {
2803 __extends(RecommendationItem, _super);
2804 function RecommendationItem(config) {
2805 var _this = _super.call(this, config) || this;
2806 _this.config = _this.mergeConfig(config, {
2807 cssClass: 'ui-recommendation-item',
2808 itemConfig: null,
2809 }, _this.config);
2810 return _this;
2811 }
2812 RecommendationItem.prototype.toDomElement = function () {
2813 var config = this.config.itemConfig; // TODO fix generics and get rid of cast
2814 var itemElement = new dom_1.DOM('a', {
2815 'id': this.config.id,
2816 'class': this.getCssClasses(),
2817 'href': config.url,
2818 }).css({ 'background-image': "url(" + config.thumbnail + ")" });
2819 var bgElement = new dom_1.DOM('div', {
2820 'class': this.prefixCss('background'),
2821 });
2822 itemElement.append(bgElement);
2823 var titleElement = new dom_1.DOM('span', {
2824 'class': this.prefixCss('title'),
2825 }).append(new dom_1.DOM('span', {
2826 'class': this.prefixCss('innertitle'),
2827 }).html(config.title));
2828 itemElement.append(titleElement);
2829 var timeElement = new dom_1.DOM('span', {
2830 'class': this.prefixCss('duration'),
2831 }).append(new dom_1.DOM('span', {
2832 'class': this.prefixCss('innerduration'),
2833 }).html(config.duration ? stringutils_1.StringUtils.secondsToTime(config.duration) : ''));
2834 itemElement.append(timeElement);
2835 return itemElement;
2836 };
2837 return RecommendationItem;
2838}(component_1.Component));
2839
2840},{"../dom":68,"../stringutils":88,"./component":16,"./container":17,"./hugereplaybutton":22}],33:[function(require,module,exports){
2841"use strict";
2842var __extends = (this && this.__extends) || (function () {
2843 var extendStatics = Object.setPrototypeOf ||
2844 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
2845 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
2846 return function (d, b) {
2847 extendStatics(d, b);
2848 function __() { this.constructor = d; }
2849 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2850 };
2851})();
2852Object.defineProperty(exports, "__esModule", { value: true });
2853var component_1 = require("./component");
2854var dom_1 = require("../dom");
2855var eventdispatcher_1 = require("../eventdispatcher");
2856var timeout_1 = require("../timeout");
2857var playerutils_1 = require("../playerutils");
2858/**
2859 * A seek bar to seek within the player's media. It displays the current playback position, amount of buffed data, seek
2860 * target, and keeps status about an ongoing seek.
2861 *
2862 * The seek bar displays different 'bars':
2863 * - the playback position, i.e. the position in the media at which the player current playback pointer is positioned
2864 * - the buffer position, which usually is the playback position plus the time span that is already buffered ahead
2865 * - the seek position, used to preview to where in the timeline a seek will jump to
2866 */
2867var SeekBar = /** @class */ (function (_super) {
2868 __extends(SeekBar, _super);
2869 function SeekBar(config) {
2870 if (config === void 0) { config = {}; }
2871 var _this = _super.call(this, config) || this;
2872 /**
2873 * Buffer of the the current playback position. The position must be buffered in case the element
2874 * needs to be refreshed with {@link #refreshPlaybackPosition}.
2875 * @type {number}
2876 */
2877 _this.playbackPositionPercentage = 0;
2878 // https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how/
2879 _this.touchSupported = ('ontouchstart' in window);
2880 _this.seekBarEvents = {
2881 /**
2882 * Fired when a scrubbing seek operation is started.
2883 */
2884 onSeek: new eventdispatcher_1.EventDispatcher(),
2885 /**
2886 * Fired during a scrubbing seek to indicate that the seek preview (i.e. the video frame) should be updated.
2887 */
2888 onSeekPreview: new eventdispatcher_1.EventDispatcher(),
2889 /**
2890 * Fired when a scrubbing seek has finished or when a direct seek is issued.
2891 */
2892 onSeeked: new eventdispatcher_1.EventDispatcher(),
2893 };
2894 _this.config = _this.mergeConfig(config, {
2895 cssClass: 'ui-seekbar',
2896 vertical: false,
2897 smoothPlaybackPositionUpdateIntervalMs: 50,
2898 }, _this.config);
2899 _this.label = _this.config.label;
2900 _this.timelineMarkers = [];
2901 return _this;
2902 }
2903 SeekBar.prototype.initialize = function () {
2904 _super.prototype.initialize.call(this);
2905 if (this.hasLabel()) {
2906 this.getLabel().initialize();
2907 }
2908 };
2909 SeekBar.prototype.configure = function (player, uimanager, configureSeek) {
2910 var _this = this;
2911 if (configureSeek === void 0) { configureSeek = true; }
2912 _super.prototype.configure.call(this, player, uimanager);
2913 // Apply scaling transform to the backdrop bar to have all bars rendered similarly
2914 // (the call must be up here to be executed for the volume slider as well)
2915 this.setPosition(this.seekBarBackdrop, 100);
2916 if (!configureSeek) {
2917 // The configureSeek flag can be used by subclasses to disable configuration as seek bar. E.g. the volume
2918 // slider is reusing this component but adds its own functionality, and does not need the seek functionality.
2919 // This is actually a hack, the proper solution would be for both seek bar and volume sliders to extend
2920 // a common base slider component and implement their functionality there.
2921 return;
2922 }
2923 var isPlaying = false;
2924 var isSeeking = false;
2925 // Update playback and buffer positions
2926 var playbackPositionHandler = function (event, forceUpdate) {
2927 if (event === void 0) { event = null; }
2928 if (forceUpdate === void 0) { forceUpdate = false; }
2929 if (isSeeking) {
2930 // We caught a seek preview seek, do not update the seekbar
2931 return;
2932 }
2933 if (player.isLive()) {
2934 if (player.getMaxTimeShift() === 0) {
2935 // This case must be explicitly handled to avoid division by zero
2936 _this.setPlaybackPosition(100);
2937 }
2938 else {
2939 var playbackPositionPercentage = 100 - (100 / player.getMaxTimeShift() * player.getTimeShift());
2940 _this.setPlaybackPosition(playbackPositionPercentage);
2941 }
2942 // Always show full buffer for live streams
2943 _this.setBufferPosition(100);
2944 }
2945 else {
2946 var playbackPositionPercentage = 100 / player.getDuration() * player.getCurrentTime();
2947 var videoBufferLength = player.getVideoBufferLength();
2948 var audioBufferLength = player.getAudioBufferLength();
2949 // Calculate the buffer length which is the smaller length of the audio and video buffers. If one of these
2950 // buffers is not available, we set it's value to MAX_VALUE to make sure that the other real value is taken
2951 // as the buffer length.
2952 var bufferLength = Math.min(videoBufferLength != null ? videoBufferLength : Number.MAX_VALUE, audioBufferLength != null ? audioBufferLength : Number.MAX_VALUE);
2953 // If both buffer lengths are missing, we set the buffer length to zero
2954 if (bufferLength === Number.MAX_VALUE) {
2955 bufferLength = 0;
2956 }
2957 var bufferPercentage = 100 / player.getDuration() * bufferLength;
2958 // Update playback position only in paused state or in the initial startup state where player is neither
2959 // paused nor playing. Playback updates are handled in the Timeout below.
2960 if (_this.config.smoothPlaybackPositionUpdateIntervalMs === SeekBar.SMOOTH_PLAYBACK_POSITION_UPDATE_DISABLED
2961 || forceUpdate || player.isPaused() || (player.isPaused() === player.isPlaying())) {
2962 _this.setPlaybackPosition(playbackPositionPercentage);
2963 }
2964 _this.setBufferPosition(playbackPositionPercentage + bufferPercentage);
2965 }
2966 };
2967 // Update seekbar upon these events
2968 // init playback position when the player is ready
2969 player.addEventHandler(player.EVENT.ON_READY, playbackPositionHandler);
2970 // update playback position when it changes
2971 player.addEventHandler(player.EVENT.ON_TIME_CHANGED, playbackPositionHandler);
2972 // update bufferlevel when buffering is complete
2973 player.addEventHandler(player.EVENT.ON_STALL_ENDED, playbackPositionHandler);
2974 // update playback position when a seek has finished
2975 player.addEventHandler(player.EVENT.ON_SEEKED, playbackPositionHandler);
2976 // update playback position when a timeshift has finished
2977 player.addEventHandler(player.EVENT.ON_TIME_SHIFTED, playbackPositionHandler);
2978 // update bufferlevel when a segment has been downloaded
2979 player.addEventHandler(player.EVENT.ON_SEGMENT_REQUEST_FINISHED, playbackPositionHandler);
2980 // update playback position of Cast playback
2981 player.addEventHandler(player.EVENT.ON_CAST_TIME_UPDATED, playbackPositionHandler);
2982 this.configureLivePausedTimeshiftUpdater(player, uimanager, playbackPositionHandler);
2983 // Seek handling
2984 player.addEventHandler(player.EVENT.ON_SEEK, function () {
2985 _this.setSeeking(true);
2986 });
2987 player.addEventHandler(player.EVENT.ON_SEEKED, function () {
2988 _this.setSeeking(false);
2989 });
2990 player.addEventHandler(player.EVENT.ON_TIME_SHIFT, function () {
2991 _this.setSeeking(true);
2992 });
2993 player.addEventHandler(player.EVENT.ON_TIME_SHIFTED, function () {
2994 _this.setSeeking(false);
2995 });
2996 var seek = function (percentage) {
2997 if (player.isLive()) {
2998 player.timeShift(player.getMaxTimeShift() - (player.getMaxTimeShift() * (percentage / 100)), 'ui');
2999 }
3000 else {
3001 player.seek(player.getDuration() * (percentage / 100), 'ui');
3002 }
3003 };
3004 this.onSeek.subscribe(function (sender) {
3005 isSeeking = true; // track seeking status so we can catch events from seek preview seeks
3006 // Notify UI manager of started seek
3007 uimanager.onSeek.dispatch(sender);
3008 // Save current playback state
3009 isPlaying = player.isPlaying();
3010 // Pause playback while seeking
3011 if (isPlaying) {
3012 player.pause('ui');
3013 }
3014 });
3015 this.onSeekPreview.subscribe(function (sender, args) {
3016 // Notify UI manager of seek preview
3017 uimanager.onSeekPreview.dispatch(sender, args);
3018 });
3019 this.onSeekPreview.subscribeRateLimited(function (sender, args) {
3020 // Rate-limited scrubbing seek
3021 if (args.scrubbing) {
3022 seek(args.position);
3023 }
3024 }, 200);
3025 this.onSeeked.subscribe(function (sender, percentage) {
3026 isSeeking = false;
3027 // Do the seek
3028 seek(percentage);
3029 // Continue playback after seek if player was playing when seek started
3030 if (isPlaying) {
3031 player.play('ui');
3032 }
3033 // Notify UI manager of finished seek
3034 uimanager.onSeeked.dispatch(sender);
3035 });
3036 if (this.hasLabel()) {
3037 // Configure a seekbar label that is internal to the seekbar)
3038 this.getLabel().configure(player, uimanager);
3039 }
3040 // Hide seekbar for live sources without timeshift
3041 var isLive = false;
3042 var hasTimeShift = false;
3043 var switchVisibility = function (isLive, hasTimeShift) {
3044 if (isLive && !hasTimeShift) {
3045 _this.hide();
3046 }
3047 else {
3048 _this.show();
3049 }
3050 playbackPositionHandler(null, true);
3051 _this.refreshPlaybackPosition();
3052 };
3053 var liveStreamDetector = new playerutils_1.PlayerUtils.LiveStreamDetector(player);
3054 liveStreamDetector.onLiveChanged.subscribe(function (sender, args) {
3055 isLive = args.live;
3056 switchVisibility(isLive, hasTimeShift);
3057 });
3058 var timeShiftDetector = new playerutils_1.PlayerUtils.TimeShiftAvailabilityDetector(player);
3059 timeShiftDetector.onTimeShiftAvailabilityChanged.subscribe(function (sender, args) {
3060 hasTimeShift = args.timeShiftAvailable;
3061 switchVisibility(isLive, hasTimeShift);
3062 });
3063 // Initial detection
3064 liveStreamDetector.detect();
3065 timeShiftDetector.detect();
3066 // Refresh the playback position when the player resized or the UI is configured. The playback position marker
3067 // is positioned absolutely and must therefore be updated when the size of the seekbar changes.
3068 player.addEventHandler(player.EVENT.ON_PLAYER_RESIZE, function () {
3069 _this.refreshPlaybackPosition();
3070 });
3071 // Additionally, when this code is called, the seekbar is not part of the UI yet and therefore does not have a size,
3072 // resulting in a wrong initial position of the marker. Refreshing it once the UI is configured solved this issue.
3073 uimanager.onConfigured.subscribe(function () {
3074 _this.refreshPlaybackPosition();
3075 });
3076 // It can also happen that the value changes once the player is ready, or when a new source is loaded, so we need
3077 // to update on ON_READY too
3078 player.addEventHandler(player.EVENT.ON_READY, function () {
3079 _this.refreshPlaybackPosition();
3080 });
3081 // Initialize seekbar
3082 playbackPositionHandler(); // Set the playback position
3083 this.setBufferPosition(0);
3084 this.setSeekPosition(0);
3085 if (this.config.smoothPlaybackPositionUpdateIntervalMs !== SeekBar.SMOOTH_PLAYBACK_POSITION_UPDATE_DISABLED) {
3086 this.configureSmoothPlaybackPositionUpdater(player, uimanager);
3087 }
3088 this.configureMarkers(player, uimanager);
3089 };
3090 /**
3091 * Update seekbar while a live stream with DVR window is paused.
3092 * The playback position stays still and the position indicator visually moves towards the back.
3093 */
3094 SeekBar.prototype.configureLivePausedTimeshiftUpdater = function (player, uimanager, playbackPositionHandler) {
3095 // Regularly update the playback position while the timeout is active
3096 var pausedTimeshiftUpdater = new timeout_1.Timeout(1000, playbackPositionHandler, true);
3097 // Start updater when a live stream with timeshift window is paused
3098 player.addEventHandler(player.EVENT.ON_PAUSED, function () {
3099 if (player.isLive() && player.getMaxTimeShift() < 0) {
3100 pausedTimeshiftUpdater.start();
3101 }
3102 });
3103 // Stop updater when playback continues (no matter if the updater was started before)
3104 player.addEventHandler(player.EVENT.ON_PLAY, function () { return pausedTimeshiftUpdater.clear(); });
3105 };
3106 SeekBar.prototype.configureSmoothPlaybackPositionUpdater = function (player, uimanager) {
3107 var _this = this;
3108 /*
3109 * Playback position update
3110 *
3111 * We do not update the position directly from the ON_TIME_CHANGED event, because it arrives very jittery and
3112 * results in a jittery position indicator since the CSS transition time is statically set.
3113 * To work around this issue, we maintain a local playback position that is updated in a stable regular interval
3114 * and kept in sync with the player.
3115 */
3116 var currentTimeSeekBar = 0;
3117 var currentTimePlayer = 0;
3118 var updateIntervalMs = 50;
3119 var currentTimeUpdateDeltaSecs = updateIntervalMs / 1000;
3120 this.smoothPlaybackPositionUpdater = new timeout_1.Timeout(updateIntervalMs, function () {
3121 currentTimeSeekBar += currentTimeUpdateDeltaSecs;
3122 currentTimePlayer = player.getCurrentTime();
3123 // Sync currentTime of seekbar to player
3124 var currentTimeDelta = currentTimeSeekBar - currentTimePlayer;
3125 // If the delta is larger that 2 secs, directly jump the seekbar to the
3126 // player time instead of smoothly fast forwarding/rewinding.
3127 if (Math.abs(currentTimeDelta) > 2) {
3128 currentTimeSeekBar = currentTimePlayer;
3129 }
3130 // If currentTimeDelta is negative and below the adjustment threshold,
3131 // the player is ahead of the seekbar and we 'fast forward' the seekbar
3132 else if (currentTimeDelta <= -currentTimeUpdateDeltaSecs) {
3133 currentTimeSeekBar += currentTimeUpdateDeltaSecs;
3134 }
3135 // If currentTimeDelta is positive and above the adjustment threshold,
3136 // the player is behind the seekbar and we 'rewind' the seekbar
3137 else if (currentTimeDelta >= currentTimeUpdateDeltaSecs) {
3138 currentTimeSeekBar -= currentTimeUpdateDeltaSecs;
3139 }
3140 var playbackPositionPercentage = 100 / player.getDuration() * currentTimeSeekBar;
3141 _this.setPlaybackPosition(playbackPositionPercentage);
3142 }, true);
3143 var startSmoothPlaybackPositionUpdater = function () {
3144 if (!player.isLive()) {
3145 currentTimeSeekBar = player.getCurrentTime();
3146 _this.smoothPlaybackPositionUpdater.start();
3147 }
3148 };
3149 var stopSmoothPlaybackPositionUpdater = function () {
3150 _this.smoothPlaybackPositionUpdater.clear();
3151 };
3152 player.addEventHandler(player.EVENT.ON_PLAY, startSmoothPlaybackPositionUpdater);
3153 player.addEventHandler(player.EVENT.ON_CAST_PLAYING, startSmoothPlaybackPositionUpdater);
3154 player.addEventHandler(player.EVENT.ON_PAUSED, stopSmoothPlaybackPositionUpdater);
3155 player.addEventHandler(player.EVENT.ON_CAST_PAUSED, stopSmoothPlaybackPositionUpdater);
3156 player.addEventHandler(player.EVENT.ON_PLAYBACK_FINISHED, stopSmoothPlaybackPositionUpdater);
3157 player.addEventHandler(player.EVENT.ON_SEEKED, function () {
3158 currentTimeSeekBar = player.getCurrentTime();
3159 });
3160 if (player.isPlaying()) {
3161 startSmoothPlaybackPositionUpdater();
3162 }
3163 };
3164 SeekBar.prototype.configureMarkers = function (player, uimanager) {
3165 var _this = this;
3166 var clearMarkers = function () {
3167 _this.timelineMarkers = [];
3168 _this.updateMarkers();
3169 };
3170 var setupMarkers = function () {
3171 clearMarkers();
3172 var duration = player.getDuration();
3173 if (duration === Infinity) {
3174 // Don't generate timeline markers if we don't yet have a duration
3175 // The duration check is for buggy platforms where the duration is not available instantly (Chrome on Android 4.3)
3176 return;
3177 }
3178 for (var _i = 0, _a = uimanager.getConfig().metadata.markers; _i < _a.length; _i++) {
3179 var marker = _a[_i];
3180 var markerPosition = 100 / duration * marker.time; // convert absolute time to percentage
3181 var markerDuration = 100 / duration * marker.duration;
3182 _this.timelineMarkers.push({ marker: marker, position: markerPosition, duration: markerDuration });
3183 }
3184 // Populate the timeline with the markers
3185 _this.updateMarkers();
3186 };
3187 // Add markers when a source is loaded
3188 player.addEventHandler(player.EVENT.ON_READY, setupMarkers);
3189 // Remove markers when unloaded
3190 player.addEventHandler(player.EVENT.ON_SOURCE_UNLOADED, clearMarkers);
3191 // Update markers when the size of the seekbar changes
3192 player.addEventHandler(player.EVENT.ON_PLAYER_RESIZE, function () { return _this.updateMarkers(); });
3193 // Update markers when a marker is added or removed
3194 uimanager.getConfig().events.onUpdated.subscribe(setupMarkers);
3195 uimanager.onRelease.subscribe(function () { return uimanager.getConfig().events.onUpdated.unsubscribe(setupMarkers); });
3196 // Init markers at startup
3197 setupMarkers();
3198 };
3199 SeekBar.prototype.release = function () {
3200 _super.prototype.release.call(this);
3201 if (this.smoothPlaybackPositionUpdater) { // object must not necessarily exist, e.g. in volume slider subclass
3202 this.smoothPlaybackPositionUpdater.clear();
3203 }
3204 };
3205 SeekBar.prototype.toDomElement = function () {
3206 var _this = this;
3207 if (this.config.vertical) {
3208 this.config.cssClasses.push('vertical');
3209 }
3210 var seekBarContainer = new dom_1.DOM('div', {
3211 'id': this.config.id,
3212 'class': this.getCssClasses(),
3213 });
3214 var seekBar = new dom_1.DOM('div', {
3215 'class': this.prefixCss('seekbar'),
3216 });
3217 this.seekBar = seekBar;
3218 // Indicator that shows the buffer fill level
3219 var seekBarBufferLevel = new dom_1.DOM('div', {
3220 'class': this.prefixCss('seekbar-bufferlevel'),
3221 });
3222 this.seekBarBufferPosition = seekBarBufferLevel;
3223 // Indicator that shows the current playback position
3224 var seekBarPlaybackPosition = new dom_1.DOM('div', {
3225 'class': this.prefixCss('seekbar-playbackposition'),
3226 });
3227 this.seekBarPlaybackPosition = seekBarPlaybackPosition;
3228 // A marker of the current playback position, e.g. a dot or line
3229 var seekBarPlaybackPositionMarker = new dom_1.DOM('div', {
3230 'class': this.prefixCss('seekbar-playbackposition-marker'),
3231 });
3232 this.seekBarPlaybackPositionMarker = seekBarPlaybackPositionMarker;
3233 // Indicator that show where a seek will go to
3234 var seekBarSeekPosition = new dom_1.DOM('div', {
3235 'class': this.prefixCss('seekbar-seekposition'),
3236 });
3237 this.seekBarSeekPosition = seekBarSeekPosition;
3238 // Indicator that shows the full seekbar
3239 var seekBarBackdrop = new dom_1.DOM('div', {
3240 'class': this.prefixCss('seekbar-backdrop'),
3241 });
3242 this.seekBarBackdrop = seekBarBackdrop;
3243 var seekBarChapterMarkersContainer = new dom_1.DOM('div', {
3244 'class': this.prefixCss('seekbar-markers'),
3245 });
3246 this.seekBarMarkersContainer = seekBarChapterMarkersContainer;
3247 seekBar.append(this.seekBarBackdrop, this.seekBarBufferPosition, this.seekBarSeekPosition, this.seekBarPlaybackPosition, this.seekBarMarkersContainer, this.seekBarPlaybackPositionMarker);
3248 var seeking = false;
3249 // Define handler functions so we can attach/remove them later
3250 var mouseTouchMoveHandler = function (e) {
3251 e.preventDefault();
3252 // Avoid propagation to VR handler
3253 e.stopPropagation();
3254 var targetPercentage = 100 * _this.getOffset(e);
3255 _this.setSeekPosition(targetPercentage);
3256 _this.setPlaybackPosition(targetPercentage);
3257 _this.onSeekPreviewEvent(targetPercentage, true);
3258 };
3259 var mouseTouchUpHandler = function (e) {
3260 e.preventDefault();
3261 // Remove handlers, seek operation is finished
3262 new dom_1.DOM(document).off('touchmove mousemove', mouseTouchMoveHandler);
3263 new dom_1.DOM(document).off('touchend mouseup', mouseTouchUpHandler);
3264 var targetPercentage = 100 * _this.getOffset(e);
3265 var snappedChapter = _this.getMarkerAtPosition(targetPercentage);
3266 _this.setSeeking(false);
3267 seeking = false;
3268 // Fire seeked event
3269 _this.onSeekedEvent(snappedChapter ? snappedChapter.position : targetPercentage);
3270 };
3271 // A seek always start with a touchstart or mousedown directly on the seekbar.
3272 // To track a mouse seek also outside the seekbar (for touch events this works automatically),
3273 // so the user does not need to take care that the mouse always stays on the seekbar, we attach the mousemove
3274 // and mouseup handlers to the whole document. A seek is triggered when the user lifts the mouse key.
3275 // A seek mouse gesture is thus basically a click with a long time frame between down and up events.
3276 seekBar.on('touchstart mousedown', function (e) {
3277 var isTouchEvent = _this.touchSupported && e instanceof TouchEvent;
3278 // Prevent selection of DOM elements (also prevents mousedown if current event is touchstart)
3279 e.preventDefault();
3280 // Avoid propagation to VR handler
3281 e.stopPropagation();
3282 _this.setSeeking(true); // Set seeking class on DOM element
3283 seeking = true; // Set seek tracking flag
3284 // Fire seeked event
3285 _this.onSeekEvent();
3286 // Add handler to track the seek operation over the whole document
3287 new dom_1.DOM(document).on(isTouchEvent ? 'touchmove' : 'mousemove', mouseTouchMoveHandler);
3288 new dom_1.DOM(document).on(isTouchEvent ? 'touchend' : 'mouseup', mouseTouchUpHandler);
3289 });
3290 // Display seek target indicator when mouse hovers or finger slides over seekbar
3291 seekBar.on('touchmove mousemove', function (e) {
3292 e.preventDefault();
3293 if (seeking) {
3294 // During a seek (when mouse is down or touch move active), we need to stop propagation to avoid
3295 // the VR viewport reacting to the moves.
3296 e.stopPropagation();
3297 // Because the stopped propagation inhibits the event on the document, we need to call it from here
3298 mouseTouchMoveHandler(e);
3299 }
3300 var position = 100 * _this.getOffset(e);
3301 _this.setSeekPosition(position);
3302 _this.onSeekPreviewEvent(position, false);
3303 if (_this.hasLabel() && _this.getLabel().isHidden()) {
3304 _this.getLabel().show();
3305 }
3306 });
3307 // Hide seek target indicator when mouse or finger leaves seekbar
3308 seekBar.on('touchend mouseleave', function (e) {
3309 e.preventDefault();
3310 _this.setSeekPosition(0);
3311 if (_this.hasLabel()) {
3312 _this.getLabel().hide();
3313 }
3314 });
3315 seekBarContainer.append(seekBar);
3316 if (this.label) {
3317 seekBarContainer.append(this.label.getDomElement());
3318 }
3319 return seekBarContainer;
3320 };
3321 SeekBar.prototype.updateMarkers = function () {
3322 var _this = this;
3323 this.seekBarMarkersContainer.empty();
3324 var seekBarWidthPx = this.seekBar.width();
3325 for (var _i = 0, _a = this.timelineMarkers; _i < _a.length; _i++) {
3326 var marker = _a[_i];
3327 var markerClasses = ['seekbar-marker'].concat(marker.marker.cssClasses || [])
3328 .map(function (cssClass) { return _this.prefixCss(cssClass); });
3329 var cssProperties = {
3330 'width': marker.position + '%',
3331 };
3332 if (marker.duration > 0) {
3333 var markerWidthPx = Math.round(seekBarWidthPx / 100 * marker.duration);
3334 cssProperties['border-right-width'] = markerWidthPx + 'px';
3335 cssProperties['margin-left'] = '0';
3336 }
3337 this.seekBarMarkersContainer.append(new dom_1.DOM('div', {
3338 'class': markerClasses.join(' '),
3339 'data-marker-time': String(marker.marker.time),
3340 'data-marker-title': String(marker.marker.title),
3341 }).css(cssProperties));
3342 }
3343 };
3344 SeekBar.prototype.getMarkerAtPosition = function (percentage) {
3345 var snappingRange = 1;
3346 if (this.timelineMarkers.length > 0) {
3347 for (var _i = 0, _a = this.timelineMarkers; _i < _a.length; _i++) {
3348 var marker = _a[_i];
3349 // Handle interval markers
3350 if (marker.duration > 0
3351 && percentage >= marker.position - snappingRange
3352 && percentage <= marker.position + marker.duration + snappingRange) {
3353 return marker;
3354 }
3355 // Handle position markers
3356 else if (percentage >= marker.position - snappingRange
3357 && percentage <= marker.position + snappingRange) {
3358 return marker;
3359 }
3360 }
3361 }
3362 return null;
3363 };
3364 /**
3365 * Gets the horizontal offset of a mouse/touch event point from the left edge of the seek bar.
3366 * @param eventPageX the pageX coordinate of an event to calculate the offset from
3367 * @returns {number} a number in the range of [0, 1], where 0 is the left edge and 1 is the right edge
3368 */
3369 SeekBar.prototype.getHorizontalOffset = function (eventPageX) {
3370 var elementOffsetPx = this.seekBar.offset().left;
3371 var widthPx = this.seekBar.width();
3372 var offsetPx = eventPageX - elementOffsetPx;
3373 var offset = 1 / widthPx * offsetPx;
3374 return this.sanitizeOffset(offset);
3375 };
3376 /**
3377 * Gets the vertical offset of a mouse/touch event point from the bottom edge of the seek bar.
3378 * @param eventPageY the pageX coordinate of an event to calculate the offset from
3379 * @returns {number} a number in the range of [0, 1], where 0 is the bottom edge and 1 is the top edge
3380 */
3381 SeekBar.prototype.getVerticalOffset = function (eventPageY) {
3382 var elementOffsetPx = this.seekBar.offset().top;
3383 var widthPx = this.seekBar.height();
3384 var offsetPx = eventPageY - elementOffsetPx;
3385 var offset = 1 / widthPx * offsetPx;
3386 return 1 - this.sanitizeOffset(offset);
3387 };
3388 /**
3389 * Gets the mouse or touch event offset for the current configuration (horizontal or vertical).
3390 * @param e the event to calculate the offset from
3391 * @returns {number} a number in the range of [0, 1]
3392 * @see #getHorizontalOffset
3393 * @see #getVerticalOffset
3394 */
3395 SeekBar.prototype.getOffset = function (e) {
3396 if (this.touchSupported && e instanceof TouchEvent) {
3397 if (this.config.vertical) {
3398 return this.getVerticalOffset(e.type === 'touchend' ? e.changedTouches[0].pageY : e.touches[0].pageY);
3399 }
3400 else {
3401 return this.getHorizontalOffset(e.type === 'touchend' ? e.changedTouches[0].pageX : e.touches[0].pageX);
3402 }
3403 }
3404 else if (e instanceof MouseEvent) {
3405 if (this.config.vertical) {
3406 return this.getVerticalOffset(e.pageY);
3407 }
3408 else {
3409 return this.getHorizontalOffset(e.pageX);
3410 }
3411 }
3412 else {
3413 if (console) {
3414 console.warn('invalid event');
3415 }
3416 return 0;
3417 }
3418 };
3419 /**
3420 * Sanitizes the mouse offset to the range of [0, 1].
3421 *
3422 * When tracking the mouse outside the seek bar, the offset can be outside the desired range and this method
3423 * limits it to the desired range. E.g. a mouse event left of the left edge of a seek bar yields an offset below
3424 * zero, but to display the seek target on the seek bar, we need to limit it to zero.
3425 *
3426 * @param offset the offset to sanitize
3427 * @returns {number} the sanitized offset.
3428 */
3429 SeekBar.prototype.sanitizeOffset = function (offset) {
3430 // Since we track mouse moves over the whole document, the target can be outside the seek range,
3431 // and we need to limit it to the [0, 1] range.
3432 if (offset < 0) {
3433 offset = 0;
3434 }
3435 else if (offset > 1) {
3436 offset = 1;
3437 }
3438 return offset;
3439 };
3440 /**
3441 * Sets the position of the playback position indicator.
3442 * @param percent a number between 0 and 100 as returned by the player
3443 */
3444 SeekBar.prototype.setPlaybackPosition = function (percent) {
3445 this.playbackPositionPercentage = percent;
3446 // Set position of the bar
3447 this.setPosition(this.seekBarPlaybackPosition, percent);
3448 // Set position of the marker
3449 var totalSize = (this.config.vertical ? (this.seekBar.height() - this.seekBarPlaybackPositionMarker.height()) : this.seekBar.width());
3450 var px = (totalSize) / 100 * percent;
3451 if (this.config.vertical) {
3452 px = this.seekBar.height() - px - this.seekBarPlaybackPositionMarker.height();
3453 }
3454 var style = this.config.vertical ?
3455 // -ms-transform required for IE9
3456 // -webkit-transform required for Android 4.4 WebView
3457 {
3458 'transform': 'translateY(' + px + 'px)',
3459 '-ms-transform': 'translateY(' + px + 'px)',
3460 '-webkit-transform': 'translateY(' + px + 'px)',
3461 } :
3462 {
3463 'transform': 'translateX(' + px + 'px)',
3464 '-ms-transform': 'translateX(' + px + 'px)',
3465 '-webkit-transform': 'translateX(' + px + 'px)',
3466 };
3467 this.seekBarPlaybackPositionMarker.css(style);
3468 };
3469 /**
3470 * Refreshes the playback position. Can be used by subclasses to refresh the position when
3471 * the size of the component changes.
3472 */
3473 SeekBar.prototype.refreshPlaybackPosition = function () {
3474 this.setPlaybackPosition(this.playbackPositionPercentage);
3475 };
3476 /**
3477 * Sets the position until which media is buffered.
3478 * @param percent a number between 0 and 100
3479 */
3480 SeekBar.prototype.setBufferPosition = function (percent) {
3481 this.setPosition(this.seekBarBufferPosition, percent);
3482 };
3483 /**
3484 * Sets the position where a seek, if executed, would jump to.
3485 * @param percent a number between 0 and 100
3486 */
3487 SeekBar.prototype.setSeekPosition = function (percent) {
3488 this.setPosition(this.seekBarSeekPosition, percent);
3489 };
3490 /**
3491 * Set the actual position (width or height) of a DOM element that represent a bar in the seek bar.
3492 * @param element the element to set the position for
3493 * @param percent a number between 0 and 100
3494 */
3495 SeekBar.prototype.setPosition = function (element, percent) {
3496 var scale = percent / 100;
3497 // When the scale is exactly 1 or very near 1 (and the browser internally rounds it to 1), browsers seem to render
3498 // the elements differently and the height gets slightly off, leading to mismatching heights when e.g. the buffer
3499 // level bar has a width of 1 and the playback position bar has a width < 1. A jittering buffer level around 1
3500 // leads to an even worse flickering effect.
3501 // Various changes in CSS styling and DOM hierarchy did not solve the issue so the workaround is to avoid a scale
3502 // of exactly 1.
3503 if (scale >= 0.99999 && scale <= 1.00001) {
3504 scale = 0.99999;
3505 }
3506 var style = this.config.vertical ?
3507 // -ms-transform required for IE9
3508 // -webkit-transform required for Android 4.4 WebView
3509 {
3510 'transform': 'scaleY(' + scale + ')',
3511 '-ms-transform': 'scaleY(' + scale + ')',
3512 '-webkit-transform': 'scaleY(' + scale + ')',
3513 } :
3514 {
3515 'transform': 'scaleX(' + scale + ')',
3516 '-ms-transform': 'scaleX(' + scale + ')',
3517 '-webkit-transform': 'scaleX(' + scale + ')',
3518 };
3519 element.css(style);
3520 };
3521 /**
3522 * Puts the seek bar into or out of seeking state by adding/removing a class to the DOM element. This can be used
3523 * to adjust the styling while seeking.
3524 *
3525 * @param seeking should be true when entering seek state, false when exiting the seek state
3526 */
3527 SeekBar.prototype.setSeeking = function (seeking) {
3528 if (seeking) {
3529 this.getDomElement().addClass(this.prefixCss(SeekBar.CLASS_SEEKING));
3530 }
3531 else {
3532 this.getDomElement().removeClass(this.prefixCss(SeekBar.CLASS_SEEKING));
3533 }
3534 };
3535 /**
3536 * Checks if the seek bar is currently in the seek state.
3537 * @returns {boolean} true if in seek state, else false
3538 */
3539 SeekBar.prototype.isSeeking = function () {
3540 return this.getDomElement().hasClass(this.prefixCss(SeekBar.CLASS_SEEKING));
3541 };
3542 /**
3543 * Checks if the seek bar has a {@link SeekBarLabel}.
3544 * @returns {boolean} true if the seek bar has a label, else false
3545 */
3546 SeekBar.prototype.hasLabel = function () {
3547 return this.label != null;
3548 };
3549 /**
3550 * Gets the label of this seek bar.
3551 * @returns {SeekBarLabel} the label if this seek bar has a label, else null
3552 */
3553 SeekBar.prototype.getLabel = function () {
3554 return this.label;
3555 };
3556 SeekBar.prototype.onSeekEvent = function () {
3557 this.seekBarEvents.onSeek.dispatch(this);
3558 };
3559 SeekBar.prototype.onSeekPreviewEvent = function (percentage, scrubbing) {
3560 var snappedMarker = this.getMarkerAtPosition(percentage);
3561 var seekPositionPercentage = percentage;
3562 if (snappedMarker) {
3563 if (snappedMarker.duration > 0) {
3564 if (percentage < snappedMarker.position) {
3565 // Snap the position to the start of the interval if the seek is within the left snap margin
3566 // We know that we are within a snap margin when we are outside the marker interval but still
3567 // have a snappedMarker
3568 seekPositionPercentage = snappedMarker.position;
3569 }
3570 else if (percentage > snappedMarker.position + snappedMarker.duration) {
3571 // Snap the position to the end of the interval if the seek is within the right snap margin
3572 seekPositionPercentage = snappedMarker.position + snappedMarker.duration;
3573 }
3574 }
3575 else {
3576 // Position markers always snap to their marker position
3577 seekPositionPercentage = snappedMarker.position;
3578 }
3579 }
3580 if (this.label) {
3581 this.label.getDomElement().css({
3582 'left': seekPositionPercentage + '%',
3583 });
3584 }
3585 this.seekBarEvents.onSeekPreview.dispatch(this, {
3586 scrubbing: scrubbing,
3587 position: seekPositionPercentage,
3588 marker: snappedMarker,
3589 });
3590 };
3591 SeekBar.prototype.onSeekedEvent = function (percentage) {
3592 this.seekBarEvents.onSeeked.dispatch(this, percentage);
3593 };
3594 Object.defineProperty(SeekBar.prototype, "onSeek", {
3595 /**
3596 * Gets the event that is fired when a scrubbing seek operation is started.
3597 * @returns {Event<SeekBar, NoArgs>}
3598 */
3599 get: function () {
3600 return this.seekBarEvents.onSeek.getEvent();
3601 },
3602 enumerable: true,
3603 configurable: true
3604 });
3605 Object.defineProperty(SeekBar.prototype, "onSeekPreview", {
3606 /**
3607 * Gets the event that is fired during a scrubbing seek (to indicate that the seek preview, i.e. the video frame,
3608 * should be updated), or during a normal seek preview when the seek bar is hovered (and the seek target,
3609 * i.e. the seek bar label, should be updated).
3610 * @returns {Event<SeekBar, SeekPreviewEventArgs>}
3611 */
3612 get: function () {
3613 return this.seekBarEvents.onSeekPreview.getEvent();
3614 },
3615 enumerable: true,
3616 configurable: true
3617 });
3618 Object.defineProperty(SeekBar.prototype, "onSeeked", {
3619 /**
3620 * Gets the event that is fired when a scrubbing seek has finished or when a direct seek is issued.
3621 * @returns {Event<SeekBar, number>}
3622 */
3623 get: function () {
3624 return this.seekBarEvents.onSeeked.getEvent();
3625 },
3626 enumerable: true,
3627 configurable: true
3628 });
3629 SeekBar.prototype.onShowEvent = function () {
3630 _super.prototype.onShowEvent.call(this);
3631 // Refresh the position of the playback position when the seek bar becomes visible. To correctly set the position,
3632 // the DOM element must be fully initialized an have its size calculated, because the position is set as an absolute
3633 // value calculated from the size. This required size is not known when it is hidden.
3634 // For such cases, we refresh the position here in onShow because here it is guaranteed that the component knows
3635 // its size and can set the position correctly.
3636 this.refreshPlaybackPosition();
3637 };
3638 SeekBar.SMOOTH_PLAYBACK_POSITION_UPDATE_DISABLED = -1;
3639 /**
3640 * The CSS class that is added to the DOM element while the seek bar is in 'seeking' state.
3641 */
3642 SeekBar.CLASS_SEEKING = 'seeking';
3643 return SeekBar;
3644}(component_1.Component));
3645exports.SeekBar = SeekBar;
3646
3647},{"../dom":68,"../eventdispatcher":82,"../playerutils":86,"../timeout":89,"./component":16}],34:[function(require,module,exports){
3648"use strict";
3649var __extends = (this && this.__extends) || (function () {
3650 var extendStatics = Object.setPrototypeOf ||
3651 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
3652 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
3653 return function (d, b) {
3654 extendStatics(d, b);
3655 function __() { this.constructor = d; }
3656 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
3657 };
3658})();
3659Object.defineProperty(exports, "__esModule", { value: true });
3660var container_1 = require("./container");
3661var label_1 = require("./label");
3662var component_1 = require("./component");
3663var stringutils_1 = require("../stringutils");
3664var imageloader_1 = require("../imageloader");
3665/**
3666 * A label for a {@link SeekBar} that can display the seek target time, a thumbnail, and title (e.g. chapter title).
3667 */
3668var SeekBarLabel = /** @class */ (function (_super) {
3669 __extends(SeekBarLabel, _super);
3670 function SeekBarLabel(config) {
3671 if (config === void 0) { config = {}; }
3672 var _this = _super.call(this, config) || this;
3673 _this.timeLabel = new label_1.Label({ cssClasses: ['seekbar-label-time'] });
3674 _this.titleLabel = new label_1.Label({ cssClasses: ['seekbar-label-title'] });
3675 _this.thumbnail = new component_1.Component({ cssClasses: ['seekbar-thumbnail'] });
3676 _this.thumbnailImageLoader = new imageloader_1.ImageLoader();
3677 _this.config = _this.mergeConfig(config, {
3678 cssClass: 'ui-seekbar-label',
3679 components: [new container_1.Container({
3680 components: [
3681 _this.thumbnail,
3682 new container_1.Container({
3683 components: [_this.titleLabel, _this.timeLabel],
3684 cssClass: 'seekbar-label-metadata',
3685 })
3686 ],
3687 cssClass: 'seekbar-label-inner',
3688 })],
3689 hidden: true,
3690 }, _this.config);
3691 return _this;
3692 }
3693 SeekBarLabel.prototype.configure = function (player, uimanager) {
3694 var _this = this;
3695 _super.prototype.configure.call(this, player, uimanager);
3696 var appliedMarkerCssClasses = [];
3697 uimanager.onSeekPreview.subscribeRateLimited(function (sender, args) {
3698 if (player.isLive()) {
3699 var maxTimeShift = player.getMaxTimeShift();
3700 var time = maxTimeShift - maxTimeShift * (args.position / 100);
3701 _this.setTime(time);
3702 }
3703 else {
3704 if (args.marker) {
3705 _this.setTitleText(args.marker.marker.title);
3706 }
3707 else {
3708 _this.setTitleText(null);
3709 }
3710 var time = player.getDuration() * (args.position / 100);
3711 _this.setTime(time);
3712 _this.setThumbnail(player.getThumb(time));
3713 }
3714 // Remove CSS classes from previous marker
3715 if (appliedMarkerCssClasses.length > 0) {
3716 _this.getDomElement().removeClass(appliedMarkerCssClasses.join(' '));
3717 appliedMarkerCssClasses = [];
3718 }
3719 // Add CSS classes of current marker
3720 if (args.marker) {
3721 var cssClasses = (args.marker.marker.cssClasses || []).map(function (cssClass) { return _this.prefixCss(cssClass); });
3722 _this.getDomElement().addClass(cssClasses.join(' '));
3723 appliedMarkerCssClasses = cssClasses;
3724 }
3725 }, 100);
3726 var init = function () {
3727 // Set time format depending on source duration
3728 _this.timeFormat = Math.abs(player.isLive() ? player.getMaxTimeShift() : player.getDuration()) >= 3600 ?
3729 stringutils_1.StringUtils.FORMAT_HHMMSS : stringutils_1.StringUtils.FORMAT_MMSS;
3730 };
3731 player.addEventHandler(player.EVENT.ON_READY, init);
3732 init();
3733 };
3734 /**
3735 * Sets arbitrary text on the label.
3736 * @param text the text to show on the label
3737 */
3738 SeekBarLabel.prototype.setText = function (text) {
3739 this.timeLabel.setText(text);
3740 };
3741 /**
3742 * Sets a time to be displayed on the label.
3743 * @param seconds the time in seconds to display on the label
3744 */
3745 SeekBarLabel.prototype.setTime = function (seconds) {
3746 this.setText(stringutils_1.StringUtils.secondsToTime(seconds, this.timeFormat));
3747 };
3748 /**
3749 * Sets the text on the title label.
3750 * @param text the text to show on the label
3751 */
3752 SeekBarLabel.prototype.setTitleText = function (text) {
3753 this.titleLabel.setText(text);
3754 };
3755 /**
3756 * Sets or removes a thumbnail on the label.
3757 * @param thumbnail the thumbnail to display on the label or null to remove a displayed thumbnail
3758 */
3759 SeekBarLabel.prototype.setThumbnail = function (thumbnail) {
3760 if (thumbnail === void 0) { thumbnail = null; }
3761 var thumbnailElement = this.thumbnail.getDomElement();
3762 if (thumbnail == null) {
3763 thumbnailElement.css({
3764 'background-image': null,
3765 'display': null,
3766 'width': null,
3767 'height': null,
3768 });
3769 }
3770 else {
3771 // We use the thumbnail image loader to make sure the thumbnail is loaded and it's size is known before be can
3772 // calculate the CSS properties and set them on the element.
3773 this.thumbnailImageLoader.load(thumbnail.url, function (url, width, height) {
3774 var thumbnailCountX = width / thumbnail.w;
3775 var thumbnailCountY = height / thumbnail.h;
3776 var thumbnailIndexX = thumbnail.x / thumbnail.w;
3777 var thumbnailIndexY = thumbnail.y / thumbnail.h;
3778 var sizeX = 100 * thumbnailCountX;
3779 var sizeY = 100 * thumbnailCountY;
3780 var offsetX = 100 * thumbnailIndexX;
3781 var offsetY = 100 * thumbnailIndexY;
3782 var aspectRatio = 1 / thumbnail.w * thumbnail.h;
3783 // The thumbnail size is set by setting the CSS 'width' and 'padding-bottom' properties. 'padding-bottom' is
3784 // used because it is relative to the width and can be used to set the aspect ratio of the thumbnail.
3785 // A default value for width is set in the stylesheet and can be overwritten from there or anywhere else.
3786 thumbnailElement.css({
3787 'display': 'inherit',
3788 'background-image': "url(" + thumbnail.url + ")",
3789 'padding-bottom': 100 * aspectRatio + "%",
3790 'background-size': sizeX + "% " + sizeY + "%",
3791 'background-position': "-" + offsetX + "% -" + offsetY + "%",
3792 });
3793 });
3794 }
3795 };
3796 return SeekBarLabel;
3797}(container_1.Container));
3798exports.SeekBarLabel = SeekBarLabel;
3799
3800},{"../imageloader":84,"../stringutils":88,"./component":16,"./container":17,"./label":24}],35:[function(require,module,exports){
3801"use strict";
3802var __extends = (this && this.__extends) || (function () {
3803 var extendStatics = Object.setPrototypeOf ||
3804 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
3805 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
3806 return function (d, b) {
3807 extendStatics(d, b);
3808 function __() { this.constructor = d; }
3809 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
3810 };
3811})();
3812Object.defineProperty(exports, "__esModule", { value: true });
3813var listselector_1 = require("./listselector");
3814var dom_1 = require("../dom");
3815/**
3816 * A simple select box providing the possibility to select a single item out of a list of available items.
3817 *
3818 * DOM example:
3819 * <code>
3820 * <select class='ui-selectbox'>
3821 * <option value='key'>label</option>
3822 * ...
3823 * </select>
3824 * </code>
3825 */
3826var SelectBox = /** @class */ (function (_super) {
3827 __extends(SelectBox, _super);
3828 function SelectBox(config) {
3829 if (config === void 0) { config = {}; }
3830 var _this = _super.call(this, config) || this;
3831 _this.config = _this.mergeConfig(config, {
3832 cssClass: 'ui-selectbox',
3833 }, _this.config);
3834 return _this;
3835 }
3836 SelectBox.prototype.toDomElement = function () {
3837 var _this = this;
3838 var selectElement = new dom_1.DOM('select', {
3839 'id': this.config.id,
3840 'class': this.getCssClasses(),
3841 });
3842 this.selectElement = selectElement;
3843 this.updateDomItems();
3844 selectElement.on('change', function () {
3845 var value = selectElement.val();
3846 _this.onItemSelectedEvent(value, false);
3847 });
3848 return selectElement;
3849 };
3850 SelectBox.prototype.updateDomItems = function (selectedValue) {
3851 if (selectedValue === void 0) { selectedValue = null; }
3852 // Delete all children
3853 this.selectElement.empty();
3854 // Add updated children
3855 for (var _i = 0, _a = this.items; _i < _a.length; _i++) {
3856 var item = _a[_i];
3857 var optionElement = new dom_1.DOM('option', {
3858 'value': item.key,
3859 }).html(item.label);
3860 if (item.key === String(selectedValue)) { // convert selectedValue to string to catch 'null'/null case
3861 optionElement.attr('selected', 'selected');
3862 }
3863 this.selectElement.append(optionElement);
3864 }
3865 };
3866 SelectBox.prototype.onItemAddedEvent = function (value) {
3867 _super.prototype.onItemAddedEvent.call(this, value);
3868 this.updateDomItems(this.selectedItem);
3869 };
3870 SelectBox.prototype.onItemRemovedEvent = function (value) {
3871 _super.prototype.onItemRemovedEvent.call(this, value);
3872 this.updateDomItems(this.selectedItem);
3873 };
3874 SelectBox.prototype.onItemSelectedEvent = function (value, updateDomItems) {
3875 if (updateDomItems === void 0) { updateDomItems = true; }
3876 _super.prototype.onItemSelectedEvent.call(this, value);
3877 if (updateDomItems) {
3878 this.updateDomItems(value);
3879 }
3880 };
3881 return SelectBox;
3882}(listselector_1.ListSelector));
3883exports.SelectBox = SelectBox;
3884
3885},{"../dom":68,"./listselector":25}],36:[function(require,module,exports){
3886"use strict";
3887var __extends = (this && this.__extends) || (function () {
3888 var extendStatics = Object.setPrototypeOf ||
3889 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
3890 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
3891 return function (d, b) {
3892 extendStatics(d, b);
3893 function __() { this.constructor = d; }
3894 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
3895 };
3896})();
3897Object.defineProperty(exports, "__esModule", { value: true });
3898var container_1 = require("./container");
3899var component_1 = require("./component");
3900var selectbox_1 = require("./selectbox");
3901var label_1 = require("./label");
3902var videoqualityselectbox_1 = require("./videoqualityselectbox");
3903var audioqualityselectbox_1 = require("./audioqualityselectbox");
3904var timeout_1 = require("../timeout");
3905var eventdispatcher_1 = require("../eventdispatcher");
3906/**
3907 * A panel containing a list of {@link SettingsPanelItem items} that represent labelled settings.
3908 */
3909var SettingsPanel = /** @class */ (function (_super) {
3910 __extends(SettingsPanel, _super);
3911 function SettingsPanel(config) {
3912 var _this = _super.call(this, config) || this;
3913 _this.settingsPanelEvents = {
3914 onSettingsStateChanged: new eventdispatcher_1.EventDispatcher(),
3915 };
3916 _this.config = _this.mergeConfig(config, {
3917 cssClass: 'ui-settings-panel',
3918 hideDelay: 3000,
3919 }, _this.config);
3920 return _this;
3921 }
3922 SettingsPanel.prototype.configure = function (player, uimanager) {
3923 var _this = this;
3924 _super.prototype.configure.call(this, player, uimanager);
3925 var config = this.getConfig(); // TODO fix generics type inference
3926 if (config.hideDelay > -1) {
3927 this.hideTimeout = new timeout_1.Timeout(config.hideDelay, function () {
3928 _this.hide();
3929 _this.hideHoveredSelectBoxes();
3930 });
3931 this.onShow.subscribe(function () {
3932 // Activate timeout when shown
3933 _this.hideTimeout.start();
3934 });
3935 this.getDomElement().on('mouseenter', function () {
3936 // On mouse enter clear the timeout
3937 _this.hideTimeout.clear();
3938 });
3939 this.getDomElement().on('mouseleave', function () {
3940 // On mouse leave activate the timeout
3941 _this.hideTimeout.reset();
3942 });
3943 this.onHide.subscribe(function () {
3944 // Clear timeout when hidden from outside
3945 _this.hideTimeout.clear();
3946 });
3947 }
3948 // Fire event when the state of a settings-item has changed
3949 var settingsStateChangedHandler = function () {
3950 _this.onSettingsStateChangedEvent();
3951 // Attach marker class to last visible item
3952 var lastShownItem = null;
3953 for (var _i = 0, _a = _this.getItems(); _i < _a.length; _i++) {
3954 var component = _a[_i];
3955 component.getDomElement().removeClass(_this.prefixCss(SettingsPanel.CLASS_LAST));
3956 if (component.isShown()) {
3957 lastShownItem = component;
3958 }
3959 }
3960 if (lastShownItem) {
3961 lastShownItem.getDomElement().addClass(_this.prefixCss(SettingsPanel.CLASS_LAST));
3962 }
3963 };
3964 for (var _i = 0, _a = this.getItems(); _i < _a.length; _i++) {
3965 var component = _a[_i];
3966 component.onActiveChanged.subscribe(settingsStateChangedHandler);
3967 }
3968 };
3969 /**
3970 * Hack for IE + Firefox
3971 * when the settings panel fades out while an item of a select box is still hovered, the select box will not fade out
3972 * while the settings panel does. This would leave a floating select box, which is just weird
3973 */
3974 SettingsPanel.prototype.hideHoveredSelectBoxes = function () {
3975 this.getItems().forEach(function (item) {
3976 if (item.isActive() && item.setting instanceof selectbox_1.SelectBox) {
3977 var selectBox_1 = item.setting;
3978 var oldDisplay_1 = selectBox_1.getDomElement().css('display');
3979 // updating the display to none marks the select-box as inactive, so it will be hidden with the rest
3980 // we just have to make sure to reset this as soon as possible
3981 selectBox_1.getDomElement().css('display', 'none');
3982 if (window.requestAnimationFrame) {
3983 requestAnimationFrame(function () { selectBox_1.getDomElement().css('display', oldDisplay_1); });
3984 }
3985 else {
3986 // IE9 has no requestAnimationFrame, set the value directly. It has no optimization about ignoring DOM-changes
3987 // between animationFrames
3988 selectBox_1.getDomElement().css('display', oldDisplay_1);
3989 }
3990 }
3991 });
3992 };
3993 SettingsPanel.prototype.release = function () {
3994 _super.prototype.release.call(this);
3995 if (this.hideTimeout) {
3996 this.hideTimeout.clear();
3997 }
3998 };
3999 /**
4000 * Checks if there are active settings within this settings panel. An active setting is a setting that is visible
4001 * and enabled, which the user can interact with.
4002 * @returns {boolean} true if there are active settings, false if the panel is functionally empty to a user
4003 */
4004 SettingsPanel.prototype.hasActiveSettings = function () {
4005 for (var _i = 0, _a = this.getItems(); _i < _a.length; _i++) {
4006 var component = _a[_i];
4007 if (component.isActive()) {
4008 return true;
4009 }
4010 }
4011 return false;
4012 };
4013 SettingsPanel.prototype.getItems = function () {
4014 return this.config.components.filter(function (component) { return component instanceof SettingsPanelItem; });
4015 };
4016 SettingsPanel.prototype.onSettingsStateChangedEvent = function () {
4017 this.settingsPanelEvents.onSettingsStateChanged.dispatch(this);
4018 };
4019 Object.defineProperty(SettingsPanel.prototype, "onSettingsStateChanged", {
4020 /**
4021 * Gets the event that is fired when one or more {@link SettingsPanelItem items} have changed state.
4022 * @returns {Event<SettingsPanel, NoArgs>}
4023 */
4024 get: function () {
4025 return this.settingsPanelEvents.onSettingsStateChanged.getEvent();
4026 },
4027 enumerable: true,
4028 configurable: true
4029 });
4030 SettingsPanel.CLASS_LAST = 'last';
4031 return SettingsPanel;
4032}(container_1.Container));
4033exports.SettingsPanel = SettingsPanel;
4034/**
4035 * An item for a {@link SettingsPanel},
4036 * Containing an optionnal {@link Label} and a component that configures a setting.
4037 * If the components is a {@link SelectBox} it will handle the logic of displaying it or not
4038 */
4039var SettingsPanelItem = /** @class */ (function (_super) {
4040 __extends(SettingsPanelItem, _super);
4041 function SettingsPanelItem(label, setting, config) {
4042 if (config === void 0) { config = {}; }
4043 var _this = _super.call(this, config) || this;
4044 _this.settingsPanelItemEvents = {
4045 onActiveChanged: new eventdispatcher_1.EventDispatcher(),
4046 };
4047 _this.setting = setting;
4048 _this.config = _this.mergeConfig(config, {
4049 cssClass: 'ui-settings-panel-item',
4050 }, _this.config);
4051 if (label !== null) {
4052 if (label instanceof component_1.Component) {
4053 _this.label = label;
4054 }
4055 else {
4056 _this.label = new label_1.Label({ text: label });
4057 }
4058 _this.addComponent(_this.label);
4059 }
4060 _this.addComponent(_this.setting);
4061 return _this;
4062 }
4063 SettingsPanelItem.prototype.configure = function (player, uimanager) {
4064 var _this = this;
4065 if (this.setting instanceof selectbox_1.SelectBox) {
4066 var handleConfigItemChanged = function () {
4067 if (!(_this.setting instanceof selectbox_1.SelectBox)) {
4068 return;
4069 }
4070 // The minimum number of items that must be available for the setting to be displayed
4071 // By default, at least two items must be available, else a selection is not possible
4072 var minItemsToDisplay = 2;
4073 // Audio/video quality select boxes contain an additional 'auto' mode, which in combination with a single
4074 // available quality also does not make sense
4075 if ((_this.setting instanceof videoqualityselectbox_1.VideoQualitySelectBox && _this.setting.hasAutoItem())
4076 || _this.setting instanceof audioqualityselectbox_1.AudioQualitySelectBox) {
4077 minItemsToDisplay = 3;
4078 }
4079 // Hide the setting if no meaningful choice is available
4080 if (_this.setting.itemCount() < minItemsToDisplay) {
4081 _this.hide();
4082 }
4083 else {
4084 _this.show();
4085 }
4086 // Visibility might have changed and therefore the active state might have changed so we fire the event
4087 // TODO fire only when state has really changed (e.g. check if visibility has really changed)
4088 _this.onActiveChangedEvent();
4089 };
4090 this.setting.onItemAdded.subscribe(handleConfigItemChanged);
4091 this.setting.onItemRemoved.subscribe(handleConfigItemChanged);
4092 // Initialize hidden state
4093 handleConfigItemChanged();
4094 }
4095 };
4096 /**
4097 * Checks if this settings panel item is active, i.e. visible and enabled and a user can interact with it.
4098 * @returns {boolean} true if the panel is active, else false
4099 */
4100 SettingsPanelItem.prototype.isActive = function () {
4101 return this.isShown();
4102 };
4103 SettingsPanelItem.prototype.onActiveChangedEvent = function () {
4104 this.settingsPanelItemEvents.onActiveChanged.dispatch(this);
4105 };
4106 Object.defineProperty(SettingsPanelItem.prototype, "onActiveChanged", {
4107 /**
4108 * Gets the event that is fired when the 'active' state of this item changes.
4109 * @see #isActive
4110 * @returns {Event<SettingsPanelItem, NoArgs>}
4111 */
4112 get: function () {
4113 return this.settingsPanelItemEvents.onActiveChanged.getEvent();
4114 },
4115 enumerable: true,
4116 configurable: true
4117 });
4118 return SettingsPanelItem;
4119}(container_1.Container));
4120exports.SettingsPanelItem = SettingsPanelItem;
4121
4122},{"../eventdispatcher":82,"../timeout":89,"./audioqualityselectbox":7,"./component":16,"./container":17,"./label":24,"./selectbox":35,"./videoqualityselectbox":62}],37:[function(require,module,exports){
4123"use strict";
4124var __extends = (this && this.__extends) || (function () {
4125 var extendStatics = Object.setPrototypeOf ||
4126 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4127 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4128 return function (d, b) {
4129 extendStatics(d, b);
4130 function __() { this.constructor = d; }
4131 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4132 };
4133})();
4134Object.defineProperty(exports, "__esModule", { value: true });
4135var togglebutton_1 = require("./togglebutton");
4136/**
4137 * A button that toggles visibility of a settings panel.
4138 */
4139var SettingsToggleButton = /** @class */ (function (_super) {
4140 __extends(SettingsToggleButton, _super);
4141 function SettingsToggleButton(config) {
4142 var _this = _super.call(this, config) || this;
4143 if (!config.settingsPanel) {
4144 throw new Error('Required SettingsPanel is missing');
4145 }
4146 _this.config = _this.mergeConfig(config, {
4147 cssClass: 'ui-settingstogglebutton',
4148 text: 'Settings',
4149 settingsPanel: null,
4150 autoHideWhenNoActiveSettings: true,
4151 }, _this.config);
4152 return _this;
4153 }
4154 SettingsToggleButton.prototype.configure = function (player, uimanager) {
4155 var _this = this;
4156 _super.prototype.configure.call(this, player, uimanager);
4157 var config = this.getConfig(); // TODO fix generics type inference
4158 var settingsPanel = config.settingsPanel;
4159 this.onClick.subscribe(function () {
4160 settingsPanel.toggleHidden();
4161 });
4162 settingsPanel.onShow.subscribe(function () {
4163 // Set toggle status to on when the settings panel shows
4164 _this.on();
4165 });
4166 settingsPanel.onHide.subscribe(function () {
4167 // Set toggle status to off when the settings panel hides
4168 _this.off();
4169 });
4170 // Handle automatic hiding of the button if there are no settings for the user to interact with
4171 if (config.autoHideWhenNoActiveSettings) {
4172 // Setup handler to show/hide button when the settings change
4173 var settingsPanelItemsChangedHandler = function () {
4174 if (settingsPanel.hasActiveSettings()) {
4175 if (_this.isHidden()) {
4176 _this.show();
4177 }
4178 }
4179 else {
4180 if (_this.isShown()) {
4181 _this.hide();
4182 }
4183 }
4184 };
4185 // Wire the handler to the event
4186 settingsPanel.onSettingsStateChanged.subscribe(settingsPanelItemsChangedHandler);
4187 // Call handler for first init at startup
4188 settingsPanelItemsChangedHandler();
4189 }
4190 };
4191 return SettingsToggleButton;
4192}(togglebutton_1.ToggleButton));
4193exports.SettingsToggleButton = SettingsToggleButton;
4194
4195},{"./togglebutton":59}],38:[function(require,module,exports){
4196"use strict";
4197var __extends = (this && this.__extends) || (function () {
4198 var extendStatics = Object.setPrototypeOf ||
4199 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4200 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4201 return function (d, b) {
4202 extendStatics(d, b);
4203 function __() { this.constructor = d; }
4204 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4205 };
4206})();
4207Object.defineProperty(exports, "__esModule", { value: true });
4208var component_1 = require("./component");
4209/**
4210 * A dummy component that just reserves some space and does nothing else.
4211 */
4212var Spacer = /** @class */ (function (_super) {
4213 __extends(Spacer, _super);
4214 function Spacer(config) {
4215 if (config === void 0) { config = {}; }
4216 var _this = _super.call(this, config) || this;
4217 _this.config = _this.mergeConfig(config, {
4218 cssClass: 'ui-spacer',
4219 }, _this.config);
4220 return _this;
4221 }
4222 Spacer.prototype.onShowEvent = function () {
4223 // disable event firing by overwriting and not calling super
4224 };
4225 Spacer.prototype.onHideEvent = function () {
4226 // disable event firing by overwriting and not calling super
4227 };
4228 Spacer.prototype.onHoverChangedEvent = function (hovered) {
4229 // disable event firing by overwriting and not calling super
4230 };
4231 return Spacer;
4232}(component_1.Component));
4233exports.Spacer = Spacer;
4234
4235},{"./component":16}],39:[function(require,module,exports){
4236"use strict";
4237var __extends = (this && this.__extends) || (function () {
4238 var extendStatics = Object.setPrototypeOf ||
4239 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4240 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4241 return function (d, b) {
4242 extendStatics(d, b);
4243 function __() { this.constructor = d; }
4244 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4245 };
4246})();
4247Object.defineProperty(exports, "__esModule", { value: true });
4248var container_1 = require("./container");
4249var label_1 = require("./label");
4250var controlbar_1 = require("./controlbar");
4251var eventdispatcher_1 = require("../eventdispatcher");
4252/**
4253 * Overlays the player to display subtitles.
4254 */
4255var SubtitleOverlay = /** @class */ (function (_super) {
4256 __extends(SubtitleOverlay, _super);
4257 function SubtitleOverlay(config) {
4258 if (config === void 0) { config = {}; }
4259 var _this = _super.call(this, config) || this;
4260 _this.preprocessLabelEventCallback = new eventdispatcher_1.EventDispatcher();
4261 _this.previewSubtitleActive = false;
4262 _this.previewSubtitle = new SubtitleLabel({ text: 'example subtitle' });
4263 _this.config = _this.mergeConfig(config, {
4264 cssClass: 'ui-subtitle-overlay',
4265 }, _this.config);
4266 return _this;
4267 }
4268 SubtitleOverlay.prototype.configure = function (player, uimanager) {
4269 var _this = this;
4270 _super.prototype.configure.call(this, player, uimanager);
4271 var subtitleManager = new ActiveSubtitleManager();
4272 this.subtitleManager = subtitleManager;
4273 player.addEventHandler(player.EVENT.ON_CUE_ENTER, function (event) {
4274 // Sanitize cue data (must be done before the cue ID is generated in subtitleManager.cueEnter)
4275 if (event.position) {
4276 // Sometimes the positions are undefined, we assume them to be zero
4277 event.position.row = event.position.row || 0;
4278 event.position.column = event.position.column || 0;
4279 }
4280 var labelToAdd = subtitleManager.cueEnter(event);
4281 _this.preprocessLabelEventCallback.dispatch(event, labelToAdd);
4282 if (_this.previewSubtitleActive) {
4283 _this.removeComponent(_this.previewSubtitle);
4284 }
4285 _this.addComponent(labelToAdd);
4286 _this.updateComponents();
4287 _this.show();
4288 });
4289 player.addEventHandler(player.EVENT.ON_CUE_EXIT, function (event) {
4290 var labelToRemove = subtitleManager.cueExit(event);
4291 if (labelToRemove) {
4292 _this.removeComponent(labelToRemove);
4293 _this.updateComponents();
4294 }
4295 if (!subtitleManager.hasCues) {
4296 if (!_this.previewSubtitleActive) {
4297 _this.hide();
4298 }
4299 else {
4300 _this.addComponent(_this.previewSubtitle);
4301 _this.updateComponents();
4302 }
4303 }
4304 });
4305 var subtitleClearHandler = function () {
4306 _this.hide();
4307 subtitleManager.clear();
4308 _this.removeComponents();
4309 _this.updateComponents();
4310 };
4311 player.addEventHandler(player.EVENT.ON_AUDIO_CHANGED, subtitleClearHandler);
4312 player.addEventHandler(player.EVENT.ON_SUBTITLE_CHANGED, subtitleClearHandler);
4313 player.addEventHandler(player.EVENT.ON_SEEK, subtitleClearHandler);
4314 player.addEventHandler(player.EVENT.ON_TIME_SHIFT, subtitleClearHandler);
4315 player.addEventHandler(player.EVENT.ON_PLAYBACK_FINISHED, subtitleClearHandler);
4316 player.addEventHandler(player.EVENT.ON_SOURCE_UNLOADED, subtitleClearHandler);
4317 uimanager.onComponentShow.subscribe(function (component) {
4318 if (component instanceof controlbar_1.ControlBar) {
4319 _this.getDomElement().addClass(_this.prefixCss(SubtitleOverlay.CLASS_CONTROLBAR_VISIBLE));
4320 }
4321 });
4322 uimanager.onComponentHide.subscribe(function (component) {
4323 if (component instanceof controlbar_1.ControlBar) {
4324 _this.getDomElement().removeClass(_this.prefixCss(SubtitleOverlay.CLASS_CONTROLBAR_VISIBLE));
4325 }
4326 });
4327 this.configureCea608Captions(player, uimanager);
4328 // Init
4329 subtitleClearHandler();
4330 };
4331 SubtitleOverlay.prototype.configureCea608Captions = function (player, uimanager) {
4332 var _this = this;
4333 // The calculated font size
4334 var fontSize = 0;
4335 // The required letter spacing spread the text characters evenly across the grid
4336 var fontLetterSpacing = 0;
4337 // Flag telling if a font size calculation is required of if the current values are valid
4338 var fontSizeCalculationRequired = true;
4339 // Flag telling if the CEA-608 mode is enabled
4340 var enabled = false;
4341 var updateCEA608FontSize = function () {
4342 var dummyLabel = new SubtitleLabel({ text: 'X' });
4343 dummyLabel.getDomElement().css({
4344 // By using a large font size we do not need to use multiple letters and can get still an
4345 // accurate measurement even though the returned size is an integer value
4346 'font-size': '200px',
4347 'line-height': '200px',
4348 'visibility': 'hidden',
4349 });
4350 _this.addComponent(dummyLabel);
4351 _this.updateComponents();
4352 _this.show();
4353 var dummyLabelCharWidth = dummyLabel.getDomElement().width();
4354 var dummyLabelCharHeight = dummyLabel.getDomElement().height();
4355 var fontSizeRatio = dummyLabelCharWidth / dummyLabelCharHeight;
4356 _this.removeComponent(dummyLabel);
4357 _this.updateComponents();
4358 if (!_this.subtitleManager.hasCues) {
4359 _this.hide();
4360 }
4361 // We subtract 1px here to avoid line breaks at the right border of the subtitle overlay that can happen
4362 // when texts contain whitespaces. It's probably some kind of pixel rounding issue in the browser's
4363 // layouting, but the actual reason could not be determined. Aiming for a target width - 1px would work in
4364 // most browsers, but Safari has a "quantized" font size rendering with huge steps in between so we need
4365 // to subtract some more pixels to avoid line breaks there as well.
4366 var subtitleOverlayWidth = _this.getDomElement().width() - 10;
4367 var subtitleOverlayHeight = _this.getDomElement().height();
4368 // The size ratio of the letter grid
4369 var fontGridSizeRatio = (dummyLabelCharWidth * SubtitleOverlay.CEA608_NUM_COLUMNS) /
4370 (dummyLabelCharHeight * SubtitleOverlay.CEA608_NUM_ROWS);
4371 // The size ratio of the available space for the grid
4372 var subtitleOverlaySizeRatio = subtitleOverlayWidth / subtitleOverlayHeight;
4373 if (subtitleOverlaySizeRatio > fontGridSizeRatio) {
4374 // When the available space is wider than the text grid, the font size is simply
4375 // determined by the height of the available space.
4376 fontSize = subtitleOverlayHeight / SubtitleOverlay.CEA608_NUM_ROWS;
4377 // Calculate the additional letter spacing required to evenly spread the text across the grid's width
4378 var gridSlotWidth = subtitleOverlayWidth / SubtitleOverlay.CEA608_NUM_COLUMNS;
4379 var fontCharWidth = fontSize * fontSizeRatio;
4380 fontLetterSpacing = gridSlotWidth - fontCharWidth;
4381 }
4382 else {
4383 // When the available space is not wide enough, texts would vertically overlap if we take
4384 // the height as a base for the font size, so we need to limit the height. We do that
4385 // by determining the font size by the width of the available space.
4386 fontSize = subtitleOverlayWidth / SubtitleOverlay.CEA608_NUM_COLUMNS / fontSizeRatio;
4387 fontLetterSpacing = 0;
4388 }
4389 // Update font-size of all active subtitle labels
4390 for (var _i = 0, _a = _this.getComponents(); _i < _a.length; _i++) {
4391 var label = _a[_i];
4392 if (label instanceof SubtitleLabel) {
4393 label.getDomElement().css({
4394 'font-size': fontSize + "px",
4395 'letter-spacing': fontLetterSpacing + "px",
4396 });
4397 }
4398 }
4399 };
4400 player.addEventHandler(player.EVENT.ON_PLAYER_RESIZE, function () {
4401 if (enabled) {
4402 updateCEA608FontSize();
4403 }
4404 else {
4405 fontSizeCalculationRequired = true;
4406 }
4407 });
4408 this.preprocessLabelEventCallback.subscribe(function (event, label) {
4409 var isCEA608 = event.position != null;
4410 if (!isCEA608) {
4411 // Skip all non-CEA608 cues
4412 return;
4413 }
4414 if (!enabled) {
4415 enabled = true;
4416 _this.getDomElement().addClass(_this.prefixCss(SubtitleOverlay.CLASS_CEA_608));
4417 // We conditionally update the font size by this flag here to avoid updating every time a subtitle
4418 // is added into an empty overlay. Because we reset the overlay when all subtitles are gone, this
4419 // would trigger an unnecessary update every time, but it's only required under certain conditions,
4420 // e.g. after the player size has changed.
4421 if (fontSizeCalculationRequired) {
4422 updateCEA608FontSize();
4423 fontSizeCalculationRequired = false;
4424 }
4425 }
4426 label.getDomElement().css({
4427 'left': event.position.column * SubtitleOverlay.CEA608_COLUMN_OFFSET + "%",
4428 'top': event.position.row * SubtitleOverlay.CEA608_ROW_OFFSET + "%",
4429 'font-size': fontSize + "px",
4430 'letter-spacing': fontLetterSpacing + "px",
4431 });
4432 });
4433 var reset = function () {
4434 _this.getDomElement().removeClass(_this.prefixCss(SubtitleOverlay.CLASS_CEA_608));
4435 enabled = false;
4436 };
4437 player.addEventHandler(player.EVENT.ON_CUE_EXIT, function () {
4438 if (!_this.subtitleManager.hasCues) {
4439 // Disable CEA-608 mode when all subtitles are gone (to allow correct formatting and
4440 // display of other types of subtitles, e.g. the formatting preview subtitle)
4441 reset();
4442 }
4443 });
4444 player.addEventHandler(player.EVENT.ON_SOURCE_UNLOADED, reset);
4445 player.addEventHandler(player.EVENT.ON_SUBTITLE_CHANGED, reset);
4446 };
4447 SubtitleOverlay.prototype.enablePreviewSubtitleLabel = function () {
4448 this.previewSubtitleActive = true;
4449 if (!this.subtitleManager.hasCues) {
4450 this.addComponent(this.previewSubtitle);
4451 this.updateComponents();
4452 this.show();
4453 }
4454 };
4455 SubtitleOverlay.prototype.removePreviewSubtitleLabel = function () {
4456 this.previewSubtitleActive = false;
4457 this.removeComponent(this.previewSubtitle);
4458 this.updateComponents();
4459 };
4460 SubtitleOverlay.CLASS_CONTROLBAR_VISIBLE = 'controlbar-visible';
4461 SubtitleOverlay.CLASS_CEA_608 = 'cea608';
4462 // The number of rows in a cea608 grid
4463 SubtitleOverlay.CEA608_NUM_ROWS = 15;
4464 // The number of columns in a cea608 grid
4465 SubtitleOverlay.CEA608_NUM_COLUMNS = 32;
4466 // The offset in percent for one row (which is also the height of a row)
4467 SubtitleOverlay.CEA608_ROW_OFFSET = 100 / SubtitleOverlay.CEA608_NUM_ROWS;
4468 // The offset in percent for one column (which is also the width of a column)
4469 SubtitleOverlay.CEA608_COLUMN_OFFSET = 100 / SubtitleOverlay.CEA608_NUM_COLUMNS;
4470 return SubtitleOverlay;
4471}(container_1.Container));
4472exports.SubtitleOverlay = SubtitleOverlay;
4473var SubtitleLabel = /** @class */ (function (_super) {
4474 __extends(SubtitleLabel, _super);
4475 function SubtitleLabel(config) {
4476 if (config === void 0) { config = {}; }
4477 var _this = _super.call(this, config) || this;
4478 _this.config = _this.mergeConfig(config, {
4479 cssClass: 'ui-subtitle-label',
4480 }, _this.config);
4481 return _this;
4482 }
4483 return SubtitleLabel;
4484}(label_1.Label));
4485var ActiveSubtitleManager = /** @class */ (function () {
4486 function ActiveSubtitleManager() {
4487 this.activeSubtitleCueMap = {};
4488 this.activeSubtitleCueCount = 0;
4489 }
4490 /**
4491 * Calculates a unique ID for a subtitle cue, which is needed to associate an ON_CUE_ENTER with its ON_CUE_EXIT
4492 * event so we can remove the correct subtitle in ON_CUE_EXIT when multiple subtitles are active at the same time.
4493 * The start time plus the text should make a unique identifier, and in the only case where a collision
4494 * can happen, two similar texts will be displayed at a similar time and a similar position (or without position).
4495 * The start time should always be known, because it is required to schedule the ON_CUE_ENTER event. The end time
4496 * must not necessarily be known and therefore cannot be used for the ID.
4497 * @param event
4498 * @return {string}
4499 */
4500 ActiveSubtitleManager.calculateId = function (event) {
4501 var id = event.start + '-' + event.text;
4502 if (event.position) {
4503 id += '-' + event.position.row + '-' + event.position.column;
4504 }
4505 return id;
4506 };
4507 /**
4508 * Adds a subtitle cue to the manager and returns the label that should be added to the subtitle overlay.
4509 * @param event
4510 * @return {SubtitleLabel}
4511 */
4512 ActiveSubtitleManager.prototype.cueEnter = function (event) {
4513 var id = ActiveSubtitleManager.calculateId(event);
4514 var label = new SubtitleLabel({
4515 // Prefer the HTML subtitle text if set, else use the plain text
4516 text: event.html || event.text,
4517 });
4518 // Create array for id if it does not exist
4519 this.activeSubtitleCueMap[id] = this.activeSubtitleCueMap[id] || [];
4520 // Add cue
4521 this.activeSubtitleCueMap[id].push({ event: event, label: label });
4522 this.activeSubtitleCueCount++;
4523 return label;
4524 };
4525 /**
4526 * Returns the label associated with an already added cue.
4527 * @param event
4528 * @return {SubtitleLabel}
4529 */
4530 ActiveSubtitleManager.prototype.getCues = function (event) {
4531 var id = ActiveSubtitleManager.calculateId(event);
4532 var activeSubtitleCues = this.activeSubtitleCueMap[id];
4533 if (activeSubtitleCues && activeSubtitleCues.length > 0) {
4534 return activeSubtitleCues.map(function (cue) { return cue.label; });
4535 }
4536 else {
4537 return null;
4538 }
4539 };
4540 /**
4541 * Removes the subtitle cue from the manager and returns the label that should be removed from the subtitle overlay,
4542 * or null if there is no associated label existing (e.g. because all labels have been {@link #clear cleared}.
4543 * @param event
4544 * @return {SubtitleLabel|null}
4545 */
4546 ActiveSubtitleManager.prototype.cueExit = function (event) {
4547 var id = ActiveSubtitleManager.calculateId(event);
4548 var activeSubtitleCues = this.activeSubtitleCueMap[id];
4549 if (activeSubtitleCues && activeSubtitleCues.length > 0) {
4550 // Remove cue
4551 /* We apply the FIFO approach here and remove the oldest cue from the associated id. When there are multiple cues
4552 * with the same id, there is no way to know which one of the cues is to be deleted, so we just hope that FIFO
4553 * works fine. Theoretically it can happen that two cues with colliding ids are removed at different times, in
4554 * the wrong order. This rare case has yet to be observed. If it ever gets an issue, we can take the unstable
4555 * cue end time (which can change between ON_CUE_ENTER and ON_CUE_EXIT IN ON_CUE_UPDATE) and use it as an
4556 * additional hint to try and remove the correct one of the colliding cues.
4557 */
4558 var activeSubtitleCue = activeSubtitleCues.shift();
4559 this.activeSubtitleCueCount--;
4560 return activeSubtitleCue.label;
4561 }
4562 else {
4563 return null;
4564 }
4565 };
4566 Object.defineProperty(ActiveSubtitleManager.prototype, "cueCount", {
4567 /**
4568 * Returns the number of active subtitle cues.
4569 * @return {number}
4570 */
4571 get: function () {
4572 // We explicitly count the cues to save an Array.reduce on every cueCount call (which can happen frequently)
4573 return this.activeSubtitleCueCount;
4574 },
4575 enumerable: true,
4576 configurable: true
4577 });
4578 Object.defineProperty(ActiveSubtitleManager.prototype, "hasCues", {
4579 /**
4580 * Returns true if there are active subtitle cues, else false.
4581 * @return {boolean}
4582 */
4583 get: function () {
4584 return this.cueCount > 0;
4585 },
4586 enumerable: true,
4587 configurable: true
4588 });
4589 /**
4590 * Removes all subtitle cues from the manager.
4591 */
4592 ActiveSubtitleManager.prototype.clear = function () {
4593 this.activeSubtitleCueMap = {};
4594 this.activeSubtitleCueCount = 0;
4595 };
4596 return ActiveSubtitleManager;
4597}());
4598
4599},{"../eventdispatcher":82,"./container":17,"./controlbar":18,"./label":24}],40:[function(require,module,exports){
4600"use strict";
4601var __extends = (this && this.__extends) || (function () {
4602 var extendStatics = Object.setPrototypeOf ||
4603 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4604 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4605 return function (d, b) {
4606 extendStatics(d, b);
4607 function __() { this.constructor = d; }
4608 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4609 };
4610})();
4611Object.defineProperty(exports, "__esModule", { value: true });
4612var selectbox_1 = require("./selectbox");
4613/**
4614 * A select box providing a selection between available subtitle and caption tracks.
4615 */
4616var SubtitleSelectBox = /** @class */ (function (_super) {
4617 __extends(SubtitleSelectBox, _super);
4618 function SubtitleSelectBox(config) {
4619 if (config === void 0) { config = {}; }
4620 return _super.call(this, config) || this;
4621 }
4622 SubtitleSelectBox.prototype.configure = function (player, uimanager) {
4623 var _this = this;
4624 _super.prototype.configure.call(this, player, uimanager);
4625 var selectCurrentSubtitle = function () {
4626 var currentSubtitle = player.getSubtitle();
4627 if (currentSubtitle) {
4628 _this.selectItem(currentSubtitle.id);
4629 }
4630 };
4631 var updateSubtitles = function () {
4632 _this.clearItems();
4633 for (var _i = 0, _a = player.getAvailableSubtitles(); _i < _a.length; _i++) {
4634 var subtitle = _a[_i];
4635 _this.addItem(subtitle.id, subtitle.label);
4636 }
4637 // Select the correct subtitle after the subtitles have been added
4638 selectCurrentSubtitle();
4639 };
4640 this.onItemSelected.subscribe(function (sender, value) {
4641 player.setSubtitle(value === 'null' ? null : value);
4642 });
4643 // React to API events
4644 player.addEventHandler(player.EVENT.ON_SUBTITLE_ADDED, updateSubtitles);
4645 player.addEventHandler(player.EVENT.ON_SUBTITLE_CHANGED, selectCurrentSubtitle);
4646 player.addEventHandler(player.EVENT.ON_SUBTITLE_REMOVED, updateSubtitles);
4647 // Update subtitles when source goes away
4648 player.addEventHandler(player.EVENT.ON_SOURCE_UNLOADED, updateSubtitles);
4649 // Update subtitles when a new source is loaded
4650 player.addEventHandler(player.EVENT.ON_READY, updateSubtitles);
4651 // Update subtitles when the period within a source changes
4652 player.addEventHandler(player.EVENT.ON_PERIOD_SWITCHED, updateSubtitles);
4653 // Populate subtitles at startup
4654 updateSubtitles();
4655 };
4656 return SubtitleSelectBox;
4657}(selectbox_1.SelectBox));
4658exports.SubtitleSelectBox = SubtitleSelectBox;
4659
4660},{"./selectbox":35}],41:[function(require,module,exports){
4661"use strict";
4662var __extends = (this && this.__extends) || (function () {
4663 var extendStatics = Object.setPrototypeOf ||
4664 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4665 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4666 return function (d, b) {
4667 extendStatics(d, b);
4668 function __() { this.constructor = d; }
4669 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4670 };
4671})();
4672Object.defineProperty(exports, "__esModule", { value: true });
4673var subtitlesettingselectbox_1 = require("./subtitlesettingselectbox");
4674/**
4675 * A select box providing a selection of different background colors.
4676 */
4677var BackgroundColorSelectBox = /** @class */ (function (_super) {
4678 __extends(BackgroundColorSelectBox, _super);
4679 function BackgroundColorSelectBox() {
4680 return _super !== null && _super.apply(this, arguments) || this;
4681 }
4682 BackgroundColorSelectBox.prototype.configure = function (player, uimanager) {
4683 var _this = this;
4684 _super.prototype.configure.call(this, player, uimanager);
4685 this.addItem(null, 'default');
4686 this.addItem('white', 'white');
4687 this.addItem('black', 'black');
4688 this.addItem('red', 'red');
4689 this.addItem('green', 'green');
4690 this.addItem('blue', 'blue');
4691 this.addItem('cyan', 'cyan');
4692 this.addItem('yellow', 'yellow');
4693 this.addItem('magenta', 'magenta');
4694 var setColorAndOpacity = function () {
4695 if (_this.settingsManager.backgroundColor.isSet() && _this.settingsManager.backgroundOpacity.isSet()) {
4696 _this.toggleOverlayClass('bgcolor-' + _this.settingsManager.backgroundColor.value + _this.settingsManager.backgroundOpacity.value);
4697 }
4698 else {
4699 _this.toggleOverlayClass(null);
4700 }
4701 };
4702 this.onItemSelected.subscribe(function (sender, key) {
4703 _this.settingsManager.backgroundColor.value = key;
4704 });
4705 this.settingsManager.backgroundColor.onChanged.subscribe(function (sender, property) {
4706 // Color and opacity go together, so we need to...
4707 if (!_this.settingsManager.backgroundColor.isSet()) {
4708 // ... clear the opacity when the color is not set
4709 _this.settingsManager.backgroundOpacity.clear();
4710 }
4711 else if (!_this.settingsManager.backgroundOpacity.isSet()) {
4712 // ... set an opacity when the color is set
4713 _this.settingsManager.backgroundOpacity.value = '100';
4714 }
4715 _this.selectItem(property.value);
4716 setColorAndOpacity();
4717 });
4718 this.settingsManager.backgroundOpacity.onChanged.subscribe(function () {
4719 setColorAndOpacity();
4720 });
4721 // Load initial value
4722 if (this.settingsManager.backgroundColor.isSet()) {
4723 this.selectItem(this.settingsManager.backgroundColor.value);
4724 }
4725 };
4726 return BackgroundColorSelectBox;
4727}(subtitlesettingselectbox_1.SubtitleSettingSelectBox));
4728exports.BackgroundColorSelectBox = BackgroundColorSelectBox;
4729
4730},{"./subtitlesettingselectbox":50}],42:[function(require,module,exports){
4731"use strict";
4732var __extends = (this && this.__extends) || (function () {
4733 var extendStatics = Object.setPrototypeOf ||
4734 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4735 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4736 return function (d, b) {
4737 extendStatics(d, b);
4738 function __() { this.constructor = d; }
4739 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4740 };
4741})();
4742Object.defineProperty(exports, "__esModule", { value: true });
4743var subtitlesettingselectbox_1 = require("./subtitlesettingselectbox");
4744/**
4745 * A select box providing a selection of different background opacity.
4746 */
4747var BackgroundOpacitySelectBox = /** @class */ (function (_super) {
4748 __extends(BackgroundOpacitySelectBox, _super);
4749 function BackgroundOpacitySelectBox() {
4750 return _super !== null && _super.apply(this, arguments) || this;
4751 }
4752 BackgroundOpacitySelectBox.prototype.configure = function (player, uimanager) {
4753 var _this = this;
4754 _super.prototype.configure.call(this, player, uimanager);
4755 this.addItem(null, 'default');
4756 this.addItem('100', '100%');
4757 this.addItem('75', '75%');
4758 this.addItem('50', '50%');
4759 this.addItem('25', '25%');
4760 this.addItem('0', '0%');
4761 this.onItemSelected.subscribe(function (sender, key) {
4762 _this.settingsManager.backgroundOpacity.value = key;
4763 // Color and opacity go together, so we need to...
4764 if (!_this.settingsManager.backgroundOpacity.isSet()) {
4765 // ... clear the color when the opacity is not set
4766 _this.settingsManager.backgroundColor.clear();
4767 }
4768 else if (!_this.settingsManager.backgroundColor.isSet()) {
4769 // ... set a color when the opacity is set
4770 _this.settingsManager.backgroundColor.value = 'black';
4771 }
4772 });
4773 // Update selected item when value is set from somewhere else
4774 this.settingsManager.backgroundOpacity.onChanged.subscribe(function (sender, property) {
4775 _this.selectItem(property.value);
4776 });
4777 // Load initial value
4778 if (this.settingsManager.backgroundOpacity.isSet()) {
4779 this.selectItem(this.settingsManager.backgroundOpacity.value);
4780 }
4781 };
4782 return BackgroundOpacitySelectBox;
4783}(subtitlesettingselectbox_1.SubtitleSettingSelectBox));
4784exports.BackgroundOpacitySelectBox = BackgroundOpacitySelectBox;
4785
4786},{"./subtitlesettingselectbox":50}],43:[function(require,module,exports){
4787"use strict";
4788var __extends = (this && this.__extends) || (function () {
4789 var extendStatics = Object.setPrototypeOf ||
4790 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4791 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4792 return function (d, b) {
4793 extendStatics(d, b);
4794 function __() { this.constructor = d; }
4795 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4796 };
4797})();
4798Object.defineProperty(exports, "__esModule", { value: true });
4799var subtitlesettingselectbox_1 = require("./subtitlesettingselectbox");
4800/**
4801 * A select box providing a selection of different character edge.
4802 */
4803var CharacterEdgeSelectBox = /** @class */ (function (_super) {
4804 __extends(CharacterEdgeSelectBox, _super);
4805 function CharacterEdgeSelectBox() {
4806 return _super !== null && _super.apply(this, arguments) || this;
4807 }
4808 CharacterEdgeSelectBox.prototype.configure = function (player, uimanager) {
4809 var _this = this;
4810 _super.prototype.configure.call(this, player, uimanager);
4811 this.addItem(null, 'default');
4812 this.addItem('raised', 'raised');
4813 this.addItem('depressed', 'depressed');
4814 this.addItem('uniform', 'uniform');
4815 this.addItem('dropshadowed', 'drop shadowed');
4816 this.settingsManager.characterEdge.onChanged.subscribe(function (sender, property) {
4817 if (property.isSet()) {
4818 _this.toggleOverlayClass('characteredge-' + property.value);
4819 }
4820 else {
4821 _this.toggleOverlayClass(null);
4822 }
4823 // Select the item in case the property was set from outside
4824 _this.selectItem(property.value);
4825 });
4826 this.onItemSelected.subscribe(function (sender, key) {
4827 _this.settingsManager.characterEdge.value = key;
4828 });
4829 // Load initial value
4830 if (this.settingsManager.characterEdge.isSet()) {
4831 this.selectItem(this.settingsManager.characterEdge.value);
4832 }
4833 };
4834 return CharacterEdgeSelectBox;
4835}(subtitlesettingselectbox_1.SubtitleSettingSelectBox));
4836exports.CharacterEdgeSelectBox = CharacterEdgeSelectBox;
4837
4838},{"./subtitlesettingselectbox":50}],44:[function(require,module,exports){
4839"use strict";
4840var __extends = (this && this.__extends) || (function () {
4841 var extendStatics = Object.setPrototypeOf ||
4842 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4843 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4844 return function (d, b) {
4845 extendStatics(d, b);
4846 function __() { this.constructor = d; }
4847 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4848 };
4849})();
4850Object.defineProperty(exports, "__esModule", { value: true });
4851var subtitlesettingselectbox_1 = require("./subtitlesettingselectbox");
4852/**
4853 * A select box providing a selection of different font colors.
4854 */
4855var FontColorSelectBox = /** @class */ (function (_super) {
4856 __extends(FontColorSelectBox, _super);
4857 function FontColorSelectBox() {
4858 return _super !== null && _super.apply(this, arguments) || this;
4859 }
4860 FontColorSelectBox.prototype.configure = function (player, uimanager) {
4861 var _this = this;
4862 _super.prototype.configure.call(this, player, uimanager);
4863 this.addItem(null, 'default');
4864 this.addItem('white', 'white');
4865 this.addItem('black', 'black');
4866 this.addItem('red', 'red');
4867 this.addItem('green', 'green');
4868 this.addItem('blue', 'blue');
4869 this.addItem('cyan', 'cyan');
4870 this.addItem('yellow', 'yellow');
4871 this.addItem('magenta', 'magenta');
4872 var setColorAndOpacity = function () {
4873 if (_this.settingsManager.fontColor.isSet() && _this.settingsManager.fontOpacity.isSet()) {
4874 _this.toggleOverlayClass('fontcolor-' + _this.settingsManager.fontColor.value + _this.settingsManager.fontOpacity.value);
4875 }
4876 else {
4877 _this.toggleOverlayClass(null);
4878 }
4879 };
4880 this.onItemSelected.subscribe(function (sender, key) {
4881 _this.settingsManager.fontColor.value = key;
4882 });
4883 this.settingsManager.fontColor.onChanged.subscribe(function (sender, property) {
4884 // Color and opacity go together, so we need to...
4885 if (!_this.settingsManager.fontColor.isSet()) {
4886 // ... clear the opacity when the color is not set
4887 _this.settingsManager.fontOpacity.clear();
4888 }
4889 else if (!_this.settingsManager.fontOpacity.isSet()) {
4890 // ... set an opacity when the color is set
4891 _this.settingsManager.fontOpacity.value = '100';
4892 }
4893 _this.selectItem(property.value);
4894 setColorAndOpacity();
4895 });
4896 this.settingsManager.fontOpacity.onChanged.subscribe(function () {
4897 setColorAndOpacity();
4898 });
4899 // Load initial value
4900 if (this.settingsManager.fontColor.isSet()) {
4901 this.selectItem(this.settingsManager.fontColor.value);
4902 }
4903 };
4904 return FontColorSelectBox;
4905}(subtitlesettingselectbox_1.SubtitleSettingSelectBox));
4906exports.FontColorSelectBox = FontColorSelectBox;
4907
4908},{"./subtitlesettingselectbox":50}],45:[function(require,module,exports){
4909"use strict";
4910var __extends = (this && this.__extends) || (function () {
4911 var extendStatics = Object.setPrototypeOf ||
4912 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4913 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4914 return function (d, b) {
4915 extendStatics(d, b);
4916 function __() { this.constructor = d; }
4917 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4918 };
4919})();
4920Object.defineProperty(exports, "__esModule", { value: true });
4921var subtitlesettingselectbox_1 = require("./subtitlesettingselectbox");
4922/**
4923 * A select box providing a selection of different font family.
4924 */
4925var FontFamilySelectBox = /** @class */ (function (_super) {
4926 __extends(FontFamilySelectBox, _super);
4927 function FontFamilySelectBox() {
4928 return _super !== null && _super.apply(this, arguments) || this;
4929 }
4930 FontFamilySelectBox.prototype.configure = function (player, uimanager) {
4931 var _this = this;
4932 _super.prototype.configure.call(this, player, uimanager);
4933 this.addItem(null, 'default');
4934 this.addItem('monospacedserif', 'monospaced serif');
4935 this.addItem('proportionalserif', 'proportional serif');
4936 this.addItem('monospacedsansserif', 'monospaced sans serif');
4937 this.addItem('proportionalsansserif', 'proportional sans serif');
4938 this.addItem('casual', 'casual');
4939 this.addItem('cursive', 'cursive');
4940 this.addItem('smallcapital', 'small capital');
4941 this.settingsManager.fontFamily.onChanged.subscribe(function (sender, property) {
4942 if (property.isSet()) {
4943 _this.toggleOverlayClass('fontfamily-' + property.value);
4944 }
4945 else {
4946 _this.toggleOverlayClass(null);
4947 }
4948 // Select the item in case the property was set from outside
4949 _this.selectItem(property.value);
4950 });
4951 this.onItemSelected.subscribe(function (sender, key) {
4952 _this.settingsManager.fontFamily.value = key;
4953 });
4954 // Load initial value
4955 if (this.settingsManager.fontFamily.isSet()) {
4956 this.selectItem(this.settingsManager.fontFamily.value);
4957 }
4958 };
4959 return FontFamilySelectBox;
4960}(subtitlesettingselectbox_1.SubtitleSettingSelectBox));
4961exports.FontFamilySelectBox = FontFamilySelectBox;
4962
4963},{"./subtitlesettingselectbox":50}],46:[function(require,module,exports){
4964"use strict";
4965var __extends = (this && this.__extends) || (function () {
4966 var extendStatics = Object.setPrototypeOf ||
4967 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4968 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
4969 return function (d, b) {
4970 extendStatics(d, b);
4971 function __() { this.constructor = d; }
4972 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4973 };
4974})();
4975Object.defineProperty(exports, "__esModule", { value: true });
4976var subtitlesettingselectbox_1 = require("./subtitlesettingselectbox");
4977/**
4978 * A select box providing a selection of different font colors.
4979 */
4980var FontOpacitySelectBox = /** @class */ (function (_super) {
4981 __extends(FontOpacitySelectBox, _super);
4982 function FontOpacitySelectBox() {
4983 return _super !== null && _super.apply(this, arguments) || this;
4984 }
4985 FontOpacitySelectBox.prototype.configure = function (player, uimanager) {
4986 var _this = this;
4987 _super.prototype.configure.call(this, player, uimanager);
4988 this.addItem(null, 'default');
4989 this.addItem('100', '100%');
4990 this.addItem('75', '75%');
4991 this.addItem('50', '50%');
4992 this.addItem('25', '25%');
4993 this.onItemSelected.subscribe(function (sender, key) {
4994 _this.settingsManager.fontOpacity.value = key;
4995 // Color and opacity go together, so we need to...
4996 if (!_this.settingsManager.fontOpacity.isSet()) {
4997 // ... clear the color when the opacity is not set
4998 _this.settingsManager.fontColor.clear();
4999 }
5000 else if (!_this.settingsManager.fontColor.isSet()) {
5001 // ... set a color when the opacity is set
5002 _this.settingsManager.fontColor.value = 'white';
5003 }
5004 });
5005 // Update selected item when value is set from somewhere else
5006 this.settingsManager.fontOpacity.onChanged.subscribe(function (sender, property) {
5007 _this.selectItem(property.value);
5008 });
5009 // Load initial value
5010 if (this.settingsManager.fontOpacity.isSet()) {
5011 this.selectItem(this.settingsManager.fontOpacity.value);
5012 }
5013 };
5014 return FontOpacitySelectBox;
5015}(subtitlesettingselectbox_1.SubtitleSettingSelectBox));
5016exports.FontOpacitySelectBox = FontOpacitySelectBox;
5017
5018},{"./subtitlesettingselectbox":50}],47:[function(require,module,exports){
5019"use strict";
5020var __extends = (this && this.__extends) || (function () {
5021 var extendStatics = Object.setPrototypeOf ||
5022 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5023 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5024 return function (d, b) {
5025 extendStatics(d, b);
5026 function __() { this.constructor = d; }
5027 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5028 };
5029})();
5030Object.defineProperty(exports, "__esModule", { value: true });
5031var subtitlesettingselectbox_1 = require("./subtitlesettingselectbox");
5032/**
5033 * A select box providing a selection of different font colors.
5034 */
5035var FontSizeSelectBox = /** @class */ (function (_super) {
5036 __extends(FontSizeSelectBox, _super);
5037 function FontSizeSelectBox() {
5038 return _super !== null && _super.apply(this, arguments) || this;
5039 }
5040 FontSizeSelectBox.prototype.configure = function (player, uimanager) {
5041 var _this = this;
5042 _super.prototype.configure.call(this, player, uimanager);
5043 this.addItem(null, 'default');
5044 this.addItem('50', '50%');
5045 this.addItem('75', '75%');
5046 this.addItem('100', '100%');
5047 this.addItem('150', '150%');
5048 this.addItem('200', '200%');
5049 this.addItem('300', '300%');
5050 this.addItem('400', '400%');
5051 this.settingsManager.fontSize.onChanged.subscribe(function (sender, property) {
5052 if (property.isSet()) {
5053 _this.toggleOverlayClass('fontsize-' + property.value);
5054 }
5055 else {
5056 _this.toggleOverlayClass(null);
5057 }
5058 // Select the item in case the property was set from outside
5059 _this.selectItem(property.value);
5060 });
5061 this.onItemSelected.subscribe(function (sender, key) {
5062 _this.settingsManager.fontSize.value = key;
5063 });
5064 // Load initial value
5065 if (this.settingsManager.fontSize.isSet()) {
5066 this.selectItem(this.settingsManager.fontSize.value);
5067 }
5068 };
5069 return FontSizeSelectBox;
5070}(subtitlesettingselectbox_1.SubtitleSettingSelectBox));
5071exports.FontSizeSelectBox = FontSizeSelectBox;
5072
5073},{"./subtitlesettingselectbox":50}],48:[function(require,module,exports){
5074"use strict";
5075var __extends = (this && this.__extends) || (function () {
5076 var extendStatics = Object.setPrototypeOf ||
5077 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5078 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5079 return function (d, b) {
5080 extendStatics(d, b);
5081 function __() { this.constructor = d; }
5082 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5083 };
5084})();
5085Object.defineProperty(exports, "__esModule", { value: true });
5086var button_1 = require("../button");
5087var SubtitleSettingsButton = /** @class */ (function (_super) {
5088 __extends(SubtitleSettingsButton, _super);
5089 function SubtitleSettingsButton(config) {
5090 var _this = _super.call(this, config) || this;
5091 _this.subtitleSettingsPanel = config.subtitleSettingsPanel;
5092 _this.settingsPanel = config.settingsPanel;
5093 return _this;
5094 }
5095 return SubtitleSettingsButton;
5096}(button_1.Button));
5097exports.SubtitleSettingsButton = SubtitleSettingsButton;
5098
5099},{"../button":10}],49:[function(require,module,exports){
5100"use strict";
5101var __extends = (this && this.__extends) || (function () {
5102 var extendStatics = Object.setPrototypeOf ||
5103 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5104 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5105 return function (d, b) {
5106 extendStatics(d, b);
5107 function __() { this.constructor = d; }
5108 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5109 };
5110})();
5111Object.defineProperty(exports, "__esModule", { value: true });
5112var subtitlesettingsbutton_1 = require("./subtitlesettingsbutton");
5113/**
5114 * A button that toggles the option menu for subtitles
5115 */
5116var SubtitleSettingsCloseButton = /** @class */ (function (_super) {
5117 __extends(SubtitleSettingsCloseButton, _super);
5118 function SubtitleSettingsCloseButton(config) {
5119 var _this = _super.call(this, config) || this;
5120 _this.config = _this.mergeConfig(config, {
5121 cssClass: 'ui-subtitlesettingsclosebutton',
5122 text: 'Back',
5123 }, _this.config);
5124 return _this;
5125 }
5126 SubtitleSettingsCloseButton.prototype.configure = function (player, uimanager) {
5127 var _this = this;
5128 _super.prototype.configure.call(this, player, uimanager);
5129 this.onClick.subscribe(function () {
5130 _this.subtitleSettingsPanel.hide();
5131 _this.settingsPanel.show();
5132 });
5133 };
5134 return SubtitleSettingsCloseButton;
5135}(subtitlesettingsbutton_1.SubtitleSettingsButton));
5136exports.SubtitleSettingsCloseButton = SubtitleSettingsCloseButton;
5137
5138},{"./subtitlesettingsbutton":48}],50:[function(require,module,exports){
5139"use strict";
5140var __extends = (this && this.__extends) || (function () {
5141 var extendStatics = Object.setPrototypeOf ||
5142 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5143 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5144 return function (d, b) {
5145 extendStatics(d, b);
5146 function __() { this.constructor = d; }
5147 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5148 };
5149})();
5150Object.defineProperty(exports, "__esModule", { value: true });
5151var selectbox_1 = require("../selectbox");
5152/**
5153 * Base class for all subtitles settings select box
5154 **/
5155var SubtitleSettingSelectBox = /** @class */ (function (_super) {
5156 __extends(SubtitleSettingSelectBox, _super);
5157 function SubtitleSettingSelectBox(config) {
5158 var _this = _super.call(this, config) || this;
5159 _this.settingsManager = config.settingsManager;
5160 _this.overlay = config.overlay;
5161 return _this;
5162 }
5163 /**
5164 * Removes a previously set class and adds the passed in class.
5165 * @param cssClass The new class to replace the previous class with or null to just remove the previous class
5166 */
5167 SubtitleSettingSelectBox.prototype.toggleOverlayClass = function (cssClass) {
5168 // Remove previous class if existing
5169 if (this.currentCssClass) {
5170 this.overlay.getDomElement().removeClass(this.currentCssClass);
5171 this.currentCssClass = null;
5172 }
5173 // Add new class if specified. If the new class is null, we don't add anything.
5174 if (cssClass) {
5175 this.currentCssClass = this.prefixCss(cssClass);
5176 this.overlay.getDomElement().addClass(this.currentCssClass);
5177 }
5178 };
5179 return SubtitleSettingSelectBox;
5180}(selectbox_1.SelectBox));
5181exports.SubtitleSettingSelectBox = SubtitleSettingSelectBox;
5182
5183},{"../selectbox":35}],51:[function(require,module,exports){
5184"use strict";
5185var __extends = (this && this.__extends) || (function () {
5186 var extendStatics = Object.setPrototypeOf ||
5187 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5188 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5189 return function (d, b) {
5190 extendStatics(d, b);
5191 function __() { this.constructor = d; }
5192 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5193 };
5194})();
5195Object.defineProperty(exports, "__esModule", { value: true });
5196var container_1 = require("../container");
5197var dom_1 = require("../../dom");
5198var SubtitleSettingsLabel = /** @class */ (function (_super) {
5199 __extends(SubtitleSettingsLabel, _super);
5200 function SubtitleSettingsLabel(config) {
5201 var _this = _super.call(this, config) || this;
5202 _this.opener = config.opener;
5203 _this.text = config.text;
5204 _this.config = _this.mergeConfig(config, {
5205 cssClass: 'ui-label',
5206 components: [
5207 _this.opener,
5208 ],
5209 }, _this.config);
5210 return _this;
5211 }
5212 SubtitleSettingsLabel.prototype.toDomElement = function () {
5213 var labelElement = new dom_1.DOM('span', {
5214 'id': this.config.id,
5215 'class': this.getCssClasses(),
5216 }).append(new dom_1.DOM('span', {}).html(this.text), this.opener.getDomElement());
5217 return labelElement;
5218 };
5219 return SubtitleSettingsLabel;
5220}(container_1.Container));
5221exports.SubtitleSettingsLabel = SubtitleSettingsLabel;
5222
5223},{"../../dom":68,"../container":17}],52:[function(require,module,exports){
5224"use strict";
5225var __extends = (this && this.__extends) || (function () {
5226 var extendStatics = Object.setPrototypeOf ||
5227 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5228 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5229 return function (d, b) {
5230 extendStatics(d, b);
5231 function __() { this.constructor = d; }
5232 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5233 };
5234})();
5235Object.defineProperty(exports, "__esModule", { value: true });
5236var storageutils_1 = require("../../storageutils");
5237var component_1 = require("../component");
5238var eventdispatcher_1 = require("../../eventdispatcher");
5239var SubtitleSettingsManager = /** @class */ (function () {
5240 function SubtitleSettingsManager() {
5241 var _this = this;
5242 this._properties = {
5243 fontColor: new SubtitleSettingsProperty(this),
5244 fontOpacity: new SubtitleSettingsProperty(this),
5245 fontFamily: new SubtitleSettingsProperty(this),
5246 fontSize: new SubtitleSettingsProperty(this),
5247 characterEdge: new SubtitleSettingsProperty(this),
5248 backgroundColor: new SubtitleSettingsProperty(this),
5249 backgroundOpacity: new SubtitleSettingsProperty(this),
5250 windowColor: new SubtitleSettingsProperty(this),
5251 windowOpacity: new SubtitleSettingsProperty(this),
5252 };
5253 this.userSettings = {};
5254 this.localStorageKey = DummyComponent.instance().prefixCss('subtitlesettings');
5255 var _loop_1 = function (propertyName) {
5256 this_1._properties[propertyName].onChanged.subscribe(function (sender, property) {
5257 if (property.isSet()) {
5258 _this.userSettings[propertyName] = property.value;
5259 }
5260 else {
5261 // Delete the property from the settings object if unset to avoid serialization of null values
5262 delete _this.userSettings[propertyName];
5263 }
5264 // Save the settings object when a property has changed
5265 _this.save();
5266 });
5267 };
5268 var this_1 = this;
5269 for (var propertyName in this._properties) {
5270 _loop_1(propertyName);
5271 }
5272 this.load();
5273 }
5274 SubtitleSettingsManager.prototype.reset = function () {
5275 for (var propertyName in this._properties) {
5276 this._properties[propertyName].clear();
5277 }
5278 };
5279 Object.defineProperty(SubtitleSettingsManager.prototype, "fontColor", {
5280 get: function () {
5281 return this._properties.fontColor;
5282 },
5283 enumerable: true,
5284 configurable: true
5285 });
5286 Object.defineProperty(SubtitleSettingsManager.prototype, "fontOpacity", {
5287 get: function () {
5288 return this._properties.fontOpacity;
5289 },
5290 enumerable: true,
5291 configurable: true
5292 });
5293 Object.defineProperty(SubtitleSettingsManager.prototype, "fontFamily", {
5294 get: function () {
5295 return this._properties.fontFamily;
5296 },
5297 enumerable: true,
5298 configurable: true
5299 });
5300 Object.defineProperty(SubtitleSettingsManager.prototype, "fontSize", {
5301 get: function () {
5302 return this._properties.fontSize;
5303 },
5304 enumerable: true,
5305 configurable: true
5306 });
5307 Object.defineProperty(SubtitleSettingsManager.prototype, "characterEdge", {
5308 get: function () {
5309 return this._properties.characterEdge;
5310 },
5311 enumerable: true,
5312 configurable: true
5313 });
5314 Object.defineProperty(SubtitleSettingsManager.prototype, "backgroundColor", {
5315 get: function () {
5316 return this._properties.backgroundColor;
5317 },
5318 enumerable: true,
5319 configurable: true
5320 });
5321 Object.defineProperty(SubtitleSettingsManager.prototype, "backgroundOpacity", {
5322 get: function () {
5323 return this._properties.backgroundOpacity;
5324 },
5325 enumerable: true,
5326 configurable: true
5327 });
5328 Object.defineProperty(SubtitleSettingsManager.prototype, "windowColor", {
5329 get: function () {
5330 return this._properties.windowColor;
5331 },
5332 enumerable: true,
5333 configurable: true
5334 });
5335 Object.defineProperty(SubtitleSettingsManager.prototype, "windowOpacity", {
5336 get: function () {
5337 return this._properties.windowOpacity;
5338 },
5339 enumerable: true,
5340 configurable: true
5341 });
5342 /**
5343 * Saves the settings to local storage.
5344 */
5345 SubtitleSettingsManager.prototype.save = function () {
5346 storageutils_1.StorageUtils.setObject(this.localStorageKey, this.userSettings);
5347 };
5348 /**
5349 * Loads the settings from local storage
5350 */
5351 SubtitleSettingsManager.prototype.load = function () {
5352 this.userSettings = storageutils_1.StorageUtils.getObject(this.localStorageKey) || {};
5353 // Apply the loaded settings
5354 for (var property in this.userSettings) {
5355 this._properties[property].value = this.userSettings[property];
5356 }
5357 };
5358 return SubtitleSettingsManager;
5359}());
5360exports.SubtitleSettingsManager = SubtitleSettingsManager;
5361/**
5362 * A dummy component whose sole purpose is to expose the {@link #prefixCss} method to the
5363 * {@link SubtitleSettingsManager}.
5364 */
5365var DummyComponent = /** @class */ (function (_super) {
5366 __extends(DummyComponent, _super);
5367 function DummyComponent() {
5368 return _super !== null && _super.apply(this, arguments) || this;
5369 }
5370 DummyComponent.instance = function () {
5371 if (!DummyComponent._instance) {
5372 DummyComponent._instance = new DummyComponent();
5373 }
5374 return DummyComponent._instance;
5375 };
5376 DummyComponent.prototype.prefixCss = function (cssClassOrId) {
5377 return _super.prototype.prefixCss.call(this, cssClassOrId);
5378 };
5379 return DummyComponent;
5380}(component_1.Component));
5381var SubtitleSettingsProperty = /** @class */ (function () {
5382 function SubtitleSettingsProperty(manager) {
5383 this._manager = manager;
5384 this._onChanged = new eventdispatcher_1.EventDispatcher();
5385 }
5386 SubtitleSettingsProperty.prototype.isSet = function () {
5387 return this._value != null;
5388 };
5389 SubtitleSettingsProperty.prototype.clear = function () {
5390 this._value = null;
5391 this.onChangedEvent(null);
5392 };
5393 Object.defineProperty(SubtitleSettingsProperty.prototype, "value", {
5394 get: function () {
5395 return this._value;
5396 },
5397 set: function (value) {
5398 if (typeof value === 'string' && value === 'null') {
5399 value = null;
5400 }
5401 this._value = value;
5402 this.onChangedEvent(value);
5403 },
5404 enumerable: true,
5405 configurable: true
5406 });
5407 SubtitleSettingsProperty.prototype.onChangedEvent = function (value) {
5408 this._onChanged.dispatch(this._manager, this);
5409 };
5410 Object.defineProperty(SubtitleSettingsProperty.prototype, "onChanged", {
5411 get: function () {
5412 return this._onChanged.getEvent();
5413 },
5414 enumerable: true,
5415 configurable: true
5416 });
5417 return SubtitleSettingsProperty;
5418}());
5419exports.SubtitleSettingsProperty = SubtitleSettingsProperty;
5420
5421},{"../../eventdispatcher":82,"../../storageutils":87,"../component":16}],53:[function(require,module,exports){
5422"use strict";
5423var __extends = (this && this.__extends) || (function () {
5424 var extendStatics = Object.setPrototypeOf ||
5425 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5426 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5427 return function (d, b) {
5428 extendStatics(d, b);
5429 function __() { this.constructor = d; }
5430 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5431 };
5432})();
5433Object.defineProperty(exports, "__esModule", { value: true });
5434var subtitlesettingsbutton_1 = require("./subtitlesettingsbutton");
5435/**
5436 * A button that toggles the option menu for subtitles
5437 */
5438var SubtitleSettingsOpenButton = /** @class */ (function (_super) {
5439 __extends(SubtitleSettingsOpenButton, _super);
5440 function SubtitleSettingsOpenButton(config) {
5441 var _this = _super.call(this, config) || this;
5442 _this.config = _this.mergeConfig(config, {
5443 cssClass: 'ui-subtitlesettingsopenbutton',
5444 text: 'Subtitles settings',
5445 }, _this.config);
5446 return _this;
5447 }
5448 SubtitleSettingsOpenButton.prototype.configure = function (player, uimanager) {
5449 var _this = this;
5450 _super.prototype.configure.call(this, player, uimanager);
5451 this.onClick.subscribe(function () {
5452 _this.subtitleSettingsPanel.show();
5453 _this.settingsPanel.hide();
5454 });
5455 };
5456 return SubtitleSettingsOpenButton;
5457}(subtitlesettingsbutton_1.SubtitleSettingsButton));
5458exports.SubtitleSettingsOpenButton = SubtitleSettingsOpenButton;
5459
5460},{"./subtitlesettingsbutton":48}],54:[function(require,module,exports){
5461"use strict";
5462var __extends = (this && this.__extends) || (function () {
5463 var extendStatics = Object.setPrototypeOf ||
5464 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5465 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5466 return function (d, b) {
5467 extendStatics(d, b);
5468 function __() { this.constructor = d; }
5469 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5470 };
5471})();
5472Object.defineProperty(exports, "__esModule", { value: true });
5473var settingspanel_1 = require("../settingspanel");
5474var fontcolorselectbox_1 = require("./fontcolorselectbox");
5475var fontopacityselectbox_1 = require("./fontopacityselectbox");
5476var fontfamilyselectbox_1 = require("./fontfamilyselectbox");
5477var fontsizeselectbox_1 = require("./fontsizeselectbox");
5478var backgroundcolorselectbox_1 = require("./backgroundcolorselectbox");
5479var backgroundopacityselectbox_1 = require("./backgroundopacityselectbox");
5480var windowcolorselectbox_1 = require("./windowcolorselectbox");
5481var windowopacityselectbox_1 = require("./windowopacityselectbox");
5482var characteredgeselectbox_1 = require("./characteredgeselectbox");
5483var subtitlesettingsmanager_1 = require("./subtitlesettingsmanager");
5484var subtitlesettingsclosebutton_1 = require("./subtitlesettingsclosebutton");
5485var subtitlesettingsresetbutton_1 = require("./subtitlesettingsresetbutton");
5486/**
5487 * SubtitleSettingsPanel is a settings panel specific to subtitles settings
5488 **/
5489var SubtitleSettingsPanel = /** @class */ (function (_super) {
5490 __extends(SubtitleSettingsPanel, _super);
5491 function SubtitleSettingsPanel(config) {
5492 var _this = _super.call(this, config) || this;
5493 _this.overlay = config.overlay;
5494 var manager = new subtitlesettingsmanager_1.SubtitleSettingsManager();
5495 _this.config = _this.mergeConfig(config, {
5496 components: [
5497 new settingspanel_1.SettingsPanelItem('Font size', new fontsizeselectbox_1.FontSizeSelectBox({
5498 overlay: _this.overlay, settingsManager: manager,
5499 })),
5500 new settingspanel_1.SettingsPanelItem('Font family', new fontfamilyselectbox_1.FontFamilySelectBox({
5501 overlay: _this.overlay, settingsManager: manager,
5502 })),
5503 new settingspanel_1.SettingsPanelItem('Font color', new fontcolorselectbox_1.FontColorSelectBox({
5504 overlay: _this.overlay, settingsManager: manager,
5505 })),
5506 new settingspanel_1.SettingsPanelItem('Font opacity', new fontopacityselectbox_1.FontOpacitySelectBox({
5507 overlay: _this.overlay, settingsManager: manager,
5508 })),
5509 new settingspanel_1.SettingsPanelItem('Character edge', new characteredgeselectbox_1.CharacterEdgeSelectBox({
5510 overlay: _this.overlay, settingsManager: manager,
5511 })),
5512 new settingspanel_1.SettingsPanelItem('Background color', new backgroundcolorselectbox_1.BackgroundColorSelectBox({
5513 overlay: _this.overlay, settingsManager: manager,
5514 })),
5515 new settingspanel_1.SettingsPanelItem('Background opacity', new backgroundopacityselectbox_1.BackgroundOpacitySelectBox({
5516 overlay: _this.overlay, settingsManager: manager,
5517 })),
5518 new settingspanel_1.SettingsPanelItem('Window color', new windowcolorselectbox_1.WindowColorSelectBox({
5519 overlay: _this.overlay, settingsManager: manager,
5520 })),
5521 new settingspanel_1.SettingsPanelItem('Window opacity', new windowopacityselectbox_1.WindowOpacitySelectBox({
5522 overlay: _this.overlay, settingsManager: manager,
5523 })),
5524 new settingspanel_1.SettingsPanelItem(new subtitlesettingsclosebutton_1.SubtitleSettingsCloseButton({
5525 subtitleSettingsPanel: _this, settingsPanel: config.settingsPanel,
5526 }), new subtitlesettingsresetbutton_1.SubtitleSettingsResetButton({
5527 settingsManager: manager,
5528 })),
5529 ],
5530 }, _this.config);
5531 return _this;
5532 }
5533 SubtitleSettingsPanel.prototype.configure = function (player, uimanager) {
5534 var _this = this;
5535 _super.prototype.configure.call(this, player, uimanager);
5536 this.onShow.subscribe(function () {
5537 _this.overlay.enablePreviewSubtitleLabel();
5538 });
5539 this.onHide.subscribe(function () {
5540 _this.overlay.removePreviewSubtitleLabel();
5541 });
5542 };
5543 return SubtitleSettingsPanel;
5544}(settingspanel_1.SettingsPanel));
5545exports.SubtitleSettingsPanel = SubtitleSettingsPanel;
5546
5547},{"../settingspanel":36,"./backgroundcolorselectbox":41,"./backgroundopacityselectbox":42,"./characteredgeselectbox":43,"./fontcolorselectbox":44,"./fontfamilyselectbox":45,"./fontopacityselectbox":46,"./fontsizeselectbox":47,"./subtitlesettingsclosebutton":49,"./subtitlesettingsmanager":52,"./subtitlesettingsresetbutton":55,"./windowcolorselectbox":56,"./windowopacityselectbox":57}],55:[function(require,module,exports){
5548"use strict";
5549var __extends = (this && this.__extends) || (function () {
5550 var extendStatics = Object.setPrototypeOf ||
5551 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5552 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5553 return function (d, b) {
5554 extendStatics(d, b);
5555 function __() { this.constructor = d; }
5556 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5557 };
5558})();
5559Object.defineProperty(exports, "__esModule", { value: true });
5560var button_1 = require("../button");
5561/**
5562 * A button that resets all subtitle settings to their defaults.
5563 */
5564var SubtitleSettingsResetButton = /** @class */ (function (_super) {
5565 __extends(SubtitleSettingsResetButton, _super);
5566 function SubtitleSettingsResetButton(config) {
5567 var _this = _super.call(this, config) || this;
5568 _this.config = _this.mergeConfig(config, {
5569 cssClass: 'ui-subtitlesettingsresetbutton',
5570 text: 'Reset',
5571 }, _this.config);
5572 return _this;
5573 }
5574 SubtitleSettingsResetButton.prototype.configure = function (player, uimanager) {
5575 var _this = this;
5576 _super.prototype.configure.call(this, player, uimanager);
5577 this.onClick.subscribe(function () {
5578 _this.config.settingsManager.reset();
5579 });
5580 };
5581 return SubtitleSettingsResetButton;
5582}(button_1.Button));
5583exports.SubtitleSettingsResetButton = SubtitleSettingsResetButton;
5584
5585},{"../button":10}],56:[function(require,module,exports){
5586"use strict";
5587var __extends = (this && this.__extends) || (function () {
5588 var extendStatics = Object.setPrototypeOf ||
5589 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5590 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5591 return function (d, b) {
5592 extendStatics(d, b);
5593 function __() { this.constructor = d; }
5594 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5595 };
5596})();
5597Object.defineProperty(exports, "__esModule", { value: true });
5598var subtitlesettingselectbox_1 = require("./subtitlesettingselectbox");
5599/**
5600 * A select box providing a selection of different background colors.
5601 */
5602var WindowColorSelectBox = /** @class */ (function (_super) {
5603 __extends(WindowColorSelectBox, _super);
5604 function WindowColorSelectBox() {
5605 return _super !== null && _super.apply(this, arguments) || this;
5606 }
5607 WindowColorSelectBox.prototype.configure = function (player, uimanager) {
5608 var _this = this;
5609 _super.prototype.configure.call(this, player, uimanager);
5610 this.addItem(null, 'default');
5611 this.addItem('white', 'white');
5612 this.addItem('black', 'black');
5613 this.addItem('red', 'red');
5614 this.addItem('green', 'green');
5615 this.addItem('blue', 'blue');
5616 this.addItem('cyan', 'cyan');
5617 this.addItem('yellow', 'yellow');
5618 this.addItem('magenta', 'magenta');
5619 var setColorAndOpacity = function () {
5620 if (_this.settingsManager.windowColor.isSet() && _this.settingsManager.windowOpacity.isSet()) {
5621 _this.toggleOverlayClass('windowcolor-' + _this.settingsManager.windowColor.value + _this.settingsManager.windowOpacity.value);
5622 }
5623 else {
5624 _this.toggleOverlayClass(null);
5625 }
5626 };
5627 this.onItemSelected.subscribe(function (sender, key) {
5628 _this.settingsManager.windowColor.value = key;
5629 });
5630 this.settingsManager.windowColor.onChanged.subscribe(function (sender, property) {
5631 // Color and opacity go together, so we need to...
5632 if (!_this.settingsManager.windowColor.isSet()) {
5633 // ... clear the opacity when the color is not set
5634 _this.settingsManager.windowOpacity.clear();
5635 }
5636 else if (!_this.settingsManager.windowOpacity.isSet()) {
5637 // ... set an opacity when the color is set
5638 _this.settingsManager.windowOpacity.value = '100';
5639 }
5640 _this.selectItem(property.value);
5641 setColorAndOpacity();
5642 });
5643 this.settingsManager.windowOpacity.onChanged.subscribe(function () {
5644 setColorAndOpacity();
5645 });
5646 // Load initial value
5647 if (this.settingsManager.windowColor.isSet()) {
5648 this.selectItem(this.settingsManager.windowColor.value);
5649 }
5650 };
5651 return WindowColorSelectBox;
5652}(subtitlesettingselectbox_1.SubtitleSettingSelectBox));
5653exports.WindowColorSelectBox = WindowColorSelectBox;
5654
5655},{"./subtitlesettingselectbox":50}],57:[function(require,module,exports){
5656"use strict";
5657var __extends = (this && this.__extends) || (function () {
5658 var extendStatics = Object.setPrototypeOf ||
5659 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5660 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5661 return function (d, b) {
5662 extendStatics(d, b);
5663 function __() { this.constructor = d; }
5664 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5665 };
5666})();
5667Object.defineProperty(exports, "__esModule", { value: true });
5668var subtitlesettingselectbox_1 = require("./subtitlesettingselectbox");
5669/**
5670 * A select box providing a selection of different background opacity.
5671 */
5672var WindowOpacitySelectBox = /** @class */ (function (_super) {
5673 __extends(WindowOpacitySelectBox, _super);
5674 function WindowOpacitySelectBox() {
5675 return _super !== null && _super.apply(this, arguments) || this;
5676 }
5677 WindowOpacitySelectBox.prototype.configure = function (player, uimanager) {
5678 var _this = this;
5679 _super.prototype.configure.call(this, player, uimanager);
5680 this.addItem(null, 'default');
5681 this.addItem('100', '100%');
5682 this.addItem('75', '75%');
5683 this.addItem('50', '50%');
5684 this.addItem('25', '25%');
5685 this.addItem('0', '0%');
5686 this.onItemSelected.subscribe(function (sender, key) {
5687 _this.settingsManager.windowOpacity.value = key;
5688 // Color and opacity go together, so we need to...
5689 if (!_this.settingsManager.windowOpacity.isSet()) {
5690 // ... clear the color when the opacity is not set
5691 _this.settingsManager.windowColor.clear();
5692 }
5693 else if (!_this.settingsManager.windowColor.isSet()) {
5694 // ... set a color when the opacity is set
5695 _this.settingsManager.windowColor.value = 'black';
5696 }
5697 });
5698 // Update selected item when value is set from somewhere else
5699 this.settingsManager.windowOpacity.onChanged.subscribe(function (sender, property) {
5700 _this.selectItem(property.value);
5701 });
5702 // Load initial value
5703 if (this.settingsManager.windowOpacity.isSet()) {
5704 this.selectItem(this.settingsManager.windowOpacity.value);
5705 }
5706 };
5707 return WindowOpacitySelectBox;
5708}(subtitlesettingselectbox_1.SubtitleSettingSelectBox));
5709exports.WindowOpacitySelectBox = WindowOpacitySelectBox;
5710
5711},{"./subtitlesettingselectbox":50}],58:[function(require,module,exports){
5712"use strict";
5713var __extends = (this && this.__extends) || (function () {
5714 var extendStatics = Object.setPrototypeOf ||
5715 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5716 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5717 return function (d, b) {
5718 extendStatics(d, b);
5719 function __() { this.constructor = d; }
5720 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5721 };
5722})();
5723Object.defineProperty(exports, "__esModule", { value: true });
5724var container_1 = require("./container");
5725var metadatalabel_1 = require("./metadatalabel");
5726/**
5727 * Displays a title bar containing a label with the title of the video.
5728 */
5729var TitleBar = /** @class */ (function (_super) {
5730 __extends(TitleBar, _super);
5731 function TitleBar(config) {
5732 if (config === void 0) { config = {}; }
5733 var _this = _super.call(this, config) || this;
5734 _this.config = _this.mergeConfig(config, {
5735 cssClass: 'ui-titlebar',
5736 hidden: true,
5737 components: [
5738 new metadatalabel_1.MetadataLabel({ content: metadatalabel_1.MetadataLabelContent.Title }),
5739 new metadatalabel_1.MetadataLabel({ content: metadatalabel_1.MetadataLabelContent.Description }),
5740 ],
5741 keepHiddenWithoutMetadata: false,
5742 }, _this.config);
5743 return _this;
5744 }
5745 TitleBar.prototype.configure = function (player, uimanager) {
5746 var _this = this;
5747 _super.prototype.configure.call(this, player, uimanager);
5748 var config = this.getConfig();
5749 var shouldBeShown = !this.isHidden();
5750 var hasMetadataText = true; // Flag to track if any metadata label contains text
5751 var checkMetadataTextAndUpdateVisibility = function () {
5752 hasMetadataText = false;
5753 // Iterate through metadata labels and check if at least one of them contains text
5754 for (var _i = 0, _a = _this.getComponents(); _i < _a.length; _i++) {
5755 var component = _a[_i];
5756 if (component instanceof metadatalabel_1.MetadataLabel) {
5757 if (!component.isEmpty()) {
5758 hasMetadataText = true;
5759 break;
5760 }
5761 }
5762 }
5763 if (_this.isShown()) {
5764 // Hide a visible titlebar if it does not contain any text and the hidden flag is set
5765 if (config.keepHiddenWithoutMetadata && !hasMetadataText) {
5766 _this.hide();
5767 }
5768 }
5769 else if (shouldBeShown) {
5770 // Show a hidden titlebar if it should actually be shown
5771 _this.show();
5772 }
5773 };
5774 // Listen to text change events to update the hasMetadataText flag when the metadata dynamically changes
5775 for (var _i = 0, _a = this.getComponents(); _i < _a.length; _i++) {
5776 var component = _a[_i];
5777 if (component instanceof metadatalabel_1.MetadataLabel) {
5778 component.onTextChanged.subscribe(checkMetadataTextAndUpdateVisibility);
5779 }
5780 }
5781 uimanager.onControlsShow.subscribe(function () {
5782 shouldBeShown = true;
5783 if (!(config.keepHiddenWithoutMetadata && !hasMetadataText)) {
5784 _this.show();
5785 }
5786 });
5787 uimanager.onControlsHide.subscribe(function () {
5788 shouldBeShown = false;
5789 _this.hide();
5790 });
5791 // init
5792 checkMetadataTextAndUpdateVisibility();
5793 };
5794 return TitleBar;
5795}(container_1.Container));
5796exports.TitleBar = TitleBar;
5797
5798},{"./container":17,"./metadatalabel":26}],59:[function(require,module,exports){
5799"use strict";
5800var __extends = (this && this.__extends) || (function () {
5801 var extendStatics = Object.setPrototypeOf ||
5802 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5803 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5804 return function (d, b) {
5805 extendStatics(d, b);
5806 function __() { this.constructor = d; }
5807 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5808 };
5809})();
5810Object.defineProperty(exports, "__esModule", { value: true });
5811var button_1 = require("./button");
5812var eventdispatcher_1 = require("../eventdispatcher");
5813/**
5814 * A button that can be toggled between 'on' and 'off' states.
5815 */
5816var ToggleButton = /** @class */ (function (_super) {
5817 __extends(ToggleButton, _super);
5818 function ToggleButton(config) {
5819 var _this = _super.call(this, config) || this;
5820 _this.toggleButtonEvents = {
5821 onToggle: new eventdispatcher_1.EventDispatcher(),
5822 onToggleOn: new eventdispatcher_1.EventDispatcher(),
5823 onToggleOff: new eventdispatcher_1.EventDispatcher(),
5824 };
5825 var defaultConfig = {
5826 cssClass: 'ui-togglebutton',
5827 onClass: 'on',
5828 offClass: 'off',
5829 };
5830 _this.config = _this.mergeConfig(config, defaultConfig, _this.config);
5831 return _this;
5832 }
5833 ToggleButton.prototype.configure = function (player, uimanager) {
5834 var config = this.getConfig();
5835 this.getDomElement().addClass(this.prefixCss(config.offClass));
5836 };
5837 /**
5838 * Toggles the button to the 'on' state.
5839 */
5840 ToggleButton.prototype.on = function () {
5841 if (this.isOff()) {
5842 var config = this.getConfig();
5843 this.onState = true;
5844 this.getDomElement().removeClass(this.prefixCss(config.offClass));
5845 this.getDomElement().addClass(this.prefixCss(config.onClass));
5846 this.onToggleEvent();
5847 this.onToggleOnEvent();
5848 }
5849 };
5850 /**
5851 * Toggles the button to the 'off' state.
5852 */
5853 ToggleButton.prototype.off = function () {
5854 if (this.isOn()) {
5855 var config = this.getConfig();
5856 this.onState = false;
5857 this.getDomElement().removeClass(this.prefixCss(config.onClass));
5858 this.getDomElement().addClass(this.prefixCss(config.offClass));
5859 this.onToggleEvent();
5860 this.onToggleOffEvent();
5861 }
5862 };
5863 /**
5864 * Toggle the button 'on' if it is 'off', or 'off' if it is 'on'.
5865 */
5866 ToggleButton.prototype.toggle = function () {
5867 if (this.isOn()) {
5868 this.off();
5869 }
5870 else {
5871 this.on();
5872 }
5873 };
5874 /**
5875 * Checks if the toggle button is in the 'on' state.
5876 * @returns {boolean} true if button is 'on', false if 'off'
5877 */
5878 ToggleButton.prototype.isOn = function () {
5879 return this.onState;
5880 };
5881 /**
5882 * Checks if the toggle button is in the 'off' state.
5883 * @returns {boolean} true if button is 'off', false if 'on'
5884 */
5885 ToggleButton.prototype.isOff = function () {
5886 return !this.isOn();
5887 };
5888 ToggleButton.prototype.onClickEvent = function () {
5889 _super.prototype.onClickEvent.call(this);
5890 // Fire the toggle event together with the click event
5891 // (they are technically the same, only the semantics are different)
5892 this.onToggleEvent();
5893 };
5894 ToggleButton.prototype.onToggleEvent = function () {
5895 this.toggleButtonEvents.onToggle.dispatch(this);
5896 };
5897 ToggleButton.prototype.onToggleOnEvent = function () {
5898 this.toggleButtonEvents.onToggleOn.dispatch(this);
5899 };
5900 ToggleButton.prototype.onToggleOffEvent = function () {
5901 this.toggleButtonEvents.onToggleOff.dispatch(this);
5902 };
5903 Object.defineProperty(ToggleButton.prototype, "onToggle", {
5904 /**
5905 * Gets the event that is fired when the button is toggled.
5906 * @returns {Event<ToggleButton<Config>, NoArgs>}
5907 */
5908 get: function () {
5909 return this.toggleButtonEvents.onToggle.getEvent();
5910 },
5911 enumerable: true,
5912 configurable: true
5913 });
5914 Object.defineProperty(ToggleButton.prototype, "onToggleOn", {
5915 /**
5916 * Gets the event that is fired when the button is toggled 'on'.
5917 * @returns {Event<ToggleButton<Config>, NoArgs>}
5918 */
5919 get: function () {
5920 return this.toggleButtonEvents.onToggleOn.getEvent();
5921 },
5922 enumerable: true,
5923 configurable: true
5924 });
5925 Object.defineProperty(ToggleButton.prototype, "onToggleOff", {
5926 /**
5927 * Gets the event that is fired when the button is toggled 'off'.
5928 * @returns {Event<ToggleButton<Config>, NoArgs>}
5929 */
5930 get: function () {
5931 return this.toggleButtonEvents.onToggleOff.getEvent();
5932 },
5933 enumerable: true,
5934 configurable: true
5935 });
5936 return ToggleButton;
5937}(button_1.Button));
5938exports.ToggleButton = ToggleButton;
5939
5940},{"../eventdispatcher":82,"./button":10}],60:[function(require,module,exports){
5941"use strict";
5942var __extends = (this && this.__extends) || (function () {
5943 var extendStatics = Object.setPrototypeOf ||
5944 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5945 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5946 return function (d, b) {
5947 extendStatics(d, b);
5948 function __() { this.constructor = d; }
5949 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
5950 };
5951})();
5952Object.defineProperty(exports, "__esModule", { value: true });
5953var component_1 = require("./component");
5954var dom_1 = require("../dom");
5955/**
5956 * Animated analog TV static noise.
5957 */
5958var TvNoiseCanvas = /** @class */ (function (_super) {
5959 __extends(TvNoiseCanvas, _super);
5960 function TvNoiseCanvas(config) {
5961 if (config === void 0) { config = {}; }
5962 var _this = _super.call(this, config) || this;
5963 _this.canvasWidth = 160;
5964 _this.canvasHeight = 90;
5965 _this.interferenceHeight = 50;
5966 _this.lastFrameUpdate = 0;
5967 _this.frameInterval = 60;
5968 _this.useAnimationFrame = !!window.requestAnimationFrame;
5969 _this.config = _this.mergeConfig(config, {
5970 cssClass: 'ui-tvnoisecanvas',
5971 }, _this.config);
5972 return _this;
5973 }
5974 TvNoiseCanvas.prototype.toDomElement = function () {
5975 return this.canvas = new dom_1.DOM('canvas', { 'class': this.getCssClasses() });
5976 };
5977 TvNoiseCanvas.prototype.start = function () {
5978 this.canvasElement = this.canvas.get(0);
5979 this.canvasContext = this.canvasElement.getContext('2d');
5980 this.noiseAnimationWindowPos = -this.canvasHeight;
5981 this.lastFrameUpdate = 0;
5982 this.canvasElement.width = this.canvasWidth;
5983 this.canvasElement.height = this.canvasHeight;
5984 this.renderFrame();
5985 };
5986 TvNoiseCanvas.prototype.stop = function () {
5987 if (this.useAnimationFrame) {
5988 cancelAnimationFrame(this.frameUpdateHandlerId);
5989 }
5990 else {
5991 clearTimeout(this.frameUpdateHandlerId);
5992 }
5993 };
5994 TvNoiseCanvas.prototype.renderFrame = function () {
5995 // This code has been copied from the player controls.js and simplified
5996 if (this.lastFrameUpdate + this.frameInterval > new Date().getTime()) {
5997 // It's too early to render the next frame
5998 this.scheduleNextRender();
5999 return;
6000 }
6001 var currentPixelOffset;
6002 var canvasWidth = this.canvasWidth;
6003 var canvasHeight = this.canvasHeight;
6004 // Create texture
6005 var noiseImage = this.canvasContext.createImageData(canvasWidth, canvasHeight);
6006 // Fill texture with noise
6007 for (var y = 0; y < canvasHeight; y++) {
6008 for (var x = 0; x < canvasWidth; x++) {
6009 currentPixelOffset = (canvasWidth * y * 4) + x * 4;
6010 noiseImage.data[currentPixelOffset] = Math.random() * 255;
6011 if (y < this.noiseAnimationWindowPos || y > this.noiseAnimationWindowPos + this.interferenceHeight) {
6012 noiseImage.data[currentPixelOffset] *= 0.85;
6013 }
6014 noiseImage.data[currentPixelOffset + 1] = noiseImage.data[currentPixelOffset];
6015 noiseImage.data[currentPixelOffset + 2] = noiseImage.data[currentPixelOffset];
6016 noiseImage.data[currentPixelOffset + 3] = 50;
6017 }
6018 }
6019 // Put texture onto canvas
6020 this.canvasContext.putImageData(noiseImage, 0, 0);
6021 this.lastFrameUpdate = new Date().getTime();
6022 this.noiseAnimationWindowPos += 7;
6023 if (this.noiseAnimationWindowPos > canvasHeight) {
6024 this.noiseAnimationWindowPos = -canvasHeight;
6025 }
6026 this.scheduleNextRender();
6027 };
6028 TvNoiseCanvas.prototype.scheduleNextRender = function () {
6029 if (this.useAnimationFrame) {
6030 this.frameUpdateHandlerId = window.requestAnimationFrame(this.renderFrame.bind(this));
6031 }
6032 else {
6033 this.frameUpdateHandlerId = setTimeout(this.renderFrame.bind(this), this.frameInterval);
6034 }
6035 };
6036 return TvNoiseCanvas;
6037}(component_1.Component));
6038exports.TvNoiseCanvas = TvNoiseCanvas;
6039
6040},{"../dom":68,"./component":16}],61:[function(require,module,exports){
6041"use strict";
6042var __extends = (this && this.__extends) || (function () {
6043 var extendStatics = Object.setPrototypeOf ||
6044 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6045 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
6046 return function (d, b) {
6047 extendStatics(d, b);
6048 function __() { this.constructor = d; }
6049 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6050 };
6051})();
6052Object.defineProperty(exports, "__esModule", { value: true });
6053var container_1 = require("./container");
6054var dom_1 = require("../dom");
6055var timeout_1 = require("../timeout");
6056var playerutils_1 = require("../playerutils");
6057/**
6058 * The base container that contains all of the UI. The UIContainer is passed to the {@link UIManager} to build and
6059 * setup the UI.
6060 */
6061var UIContainer = /** @class */ (function (_super) {
6062 __extends(UIContainer, _super);
6063 function UIContainer(config) {
6064 var _this = _super.call(this, config) || this;
6065 _this.config = _this.mergeConfig(config, {
6066 cssClass: 'ui-uicontainer',
6067 hideDelay: 5000,
6068 }, _this.config);
6069 return _this;
6070 }
6071 UIContainer.prototype.configure = function (player, uimanager) {
6072 _super.prototype.configure.call(this, player, uimanager);
6073 this.configureUIShowHide(player, uimanager);
6074 this.configurePlayerStates(player, uimanager);
6075 };
6076 UIContainer.prototype.configureUIShowHide = function (player, uimanager) {
6077 var _this = this;
6078 var container = this.getDomElement();
6079 var config = this.getConfig();
6080 if (config.hideDelay === -1) {
6081 uimanager.onConfigured.subscribe(function () { return uimanager.onControlsShow.dispatch(_this); });
6082 return;
6083 }
6084 var isUiShown = false;
6085 var isSeeking = false;
6086 var isFirstTouch = true;
6087 var showUi = function () {
6088 if (!isUiShown) {
6089 // Let subscribers know that they should reveal themselves
6090 uimanager.onControlsShow.dispatch(_this);
6091 isUiShown = true;
6092 }
6093 // Don't trigger timeout while seeking (it will be triggered once the seek is finished) or casting
6094 if (!isSeeking && !player.isCasting()) {
6095 _this.uiHideTimeout.start();
6096 }
6097 };
6098 var hideUi = function () {
6099 // Hide the UI only if it is shown, and if not casting
6100 if (isUiShown && !player.isCasting()) {
6101 // Issue a preview event to check if we are good to hide the controls
6102 var previewHideEventArgs = {};
6103 uimanager.onPreviewControlsHide.dispatch(_this, previewHideEventArgs);
6104 if (!previewHideEventArgs.cancel) {
6105 // If the preview wasn't canceled, let subscribers know that they should now hide themselves
6106 uimanager.onControlsHide.dispatch(_this);
6107 isUiShown = false;
6108 }
6109 else {
6110 // If the hide preview was canceled, continue to show UI
6111 showUi();
6112 }
6113 }
6114 };
6115 // Timeout to defer UI hiding by the configured delay time
6116 this.uiHideTimeout = new timeout_1.Timeout(config.hideDelay, hideUi);
6117 // On touch displays, the first touch reveals the UI
6118 container.on('touchend', function (e) {
6119 if (!isUiShown) {
6120 // Only if the UI is hidden, we prevent other actions (except for the first touch) and reveal the UI instead.
6121 // The first touch is not prevented to let other listeners receive the event and trigger an initial action, e.g.
6122 // the huge playback button can directly start playback instead of requiring a double tap which 1. reveals
6123 // the UI and 2. starts playback.
6124 if (isFirstTouch) {
6125 isFirstTouch = false;
6126 }
6127 else {
6128 e.preventDefault();
6129 }
6130 showUi();
6131 }
6132 });
6133 // When the mouse enters, we show the UI
6134 container.on('mouseenter', function () {
6135 showUi();
6136 });
6137 // When the mouse moves within, we show the UI
6138 container.on('mousemove', function () {
6139 showUi();
6140 });
6141 // When the mouse leaves, we can prepare to hide the UI, except a seek is going on
6142 container.on('mouseleave', function () {
6143 // When a seek is going on, the seek scrub pointer may exit the UI area while still seeking, and we do not hide
6144 // the UI in such cases
6145 if (!isSeeking) {
6146 _this.uiHideTimeout.start();
6147 }
6148 });
6149 uimanager.onSeek.subscribe(function () {
6150 _this.uiHideTimeout.clear(); // Don't hide UI while a seek is in progress
6151 isSeeking = true;
6152 });
6153 uimanager.onSeeked.subscribe(function () {
6154 isSeeking = false;
6155 _this.uiHideTimeout.start(); // Re-enable UI hide timeout after a seek
6156 });
6157 player.addEventHandler(player.EVENT.ON_CAST_STARTED, function () {
6158 showUi(); // Show UI when a Cast session has started (UI will then stay permanently on during the session)
6159 });
6160 };
6161 UIContainer.prototype.configurePlayerStates = function (player, uimanager) {
6162 var _this = this;
6163 var container = this.getDomElement();
6164 // Convert player states into CSS class names
6165 var stateClassNames = [];
6166 for (var state in playerutils_1.PlayerUtils.PlayerState) {
6167 if (isNaN(Number(state))) {
6168 var enumName = playerutils_1.PlayerUtils.PlayerState[playerutils_1.PlayerUtils.PlayerState[state]];
6169 stateClassNames[playerutils_1.PlayerUtils.PlayerState[state]] =
6170 this.prefixCss(UIContainer.STATE_PREFIX + enumName.toLowerCase());
6171 }
6172 }
6173 var removeStates = function () {
6174 container.removeClass(stateClassNames[playerutils_1.PlayerUtils.PlayerState.IDLE]);
6175 container.removeClass(stateClassNames[playerutils_1.PlayerUtils.PlayerState.PREPARED]);
6176 container.removeClass(stateClassNames[playerutils_1.PlayerUtils.PlayerState.PLAYING]);
6177 container.removeClass(stateClassNames[playerutils_1.PlayerUtils.PlayerState.PAUSED]);
6178 container.removeClass(stateClassNames[playerutils_1.PlayerUtils.PlayerState.FINISHED]);
6179 };
6180 player.addEventHandler(player.EVENT.ON_READY, function () {
6181 removeStates();
6182 container.addClass(stateClassNames[playerutils_1.PlayerUtils.PlayerState.PREPARED]);
6183 });
6184 player.addEventHandler(player.EVENT.ON_PLAY, function () {
6185 removeStates();
6186 container.addClass(stateClassNames[playerutils_1.PlayerUtils.PlayerState.PLAYING]);
6187 });
6188 player.addEventHandler(player.EVENT.ON_PAUSED, function () {
6189 removeStates();
6190 container.addClass(stateClassNames[playerutils_1.PlayerUtils.PlayerState.PAUSED]);
6191 });
6192 player.addEventHandler(player.EVENT.ON_PLAYBACK_FINISHED, function () {
6193 removeStates();
6194 container.addClass(stateClassNames[playerutils_1.PlayerUtils.PlayerState.FINISHED]);
6195 });
6196 player.addEventHandler(player.EVENT.ON_SOURCE_UNLOADED, function () {
6197 removeStates();
6198 container.addClass(stateClassNames[playerutils_1.PlayerUtils.PlayerState.IDLE]);
6199 });
6200 // Init in current player state
6201 container.addClass(stateClassNames[playerutils_1.PlayerUtils.getState(player)]);
6202 // Fullscreen marker class
6203 player.addEventHandler(player.EVENT.ON_FULLSCREEN_ENTER, function () {
6204 container.addClass(_this.prefixCss(UIContainer.FULLSCREEN));
6205 });
6206 player.addEventHandler(player.EVENT.ON_FULLSCREEN_EXIT, function () {
6207 container.removeClass(_this.prefixCss(UIContainer.FULLSCREEN));
6208 });
6209 // Init fullscreen state
6210 if (player.isFullscreen()) {
6211 container.addClass(this.prefixCss(UIContainer.FULLSCREEN));
6212 }
6213 // Buffering marker class
6214 player.addEventHandler(player.EVENT.ON_STALL_STARTED, function () {
6215 container.addClass(_this.prefixCss(UIContainer.BUFFERING));
6216 });
6217 player.addEventHandler(player.EVENT.ON_STALL_ENDED, function () {
6218 container.removeClass(_this.prefixCss(UIContainer.BUFFERING));
6219 });
6220 // Init buffering state
6221 if (player.isStalled()) {
6222 container.addClass(this.prefixCss(UIContainer.BUFFERING));
6223 }
6224 // RemoteControl marker class
6225 player.addEventHandler(player.EVENT.ON_CAST_STARTED, function () {
6226 container.addClass(_this.prefixCss(UIContainer.REMOTE_CONTROL));
6227 });
6228 player.addEventHandler(player.EVENT.ON_CAST_STOPPED, function () {
6229 container.removeClass(_this.prefixCss(UIContainer.REMOTE_CONTROL));
6230 });
6231 // Init RemoteControl state
6232 if (player.isCasting()) {
6233 container.addClass(this.prefixCss(UIContainer.REMOTE_CONTROL));
6234 }
6235 // Controls visibility marker class
6236 uimanager.onControlsShow.subscribe(function () {
6237 container.removeClass(_this.prefixCss(UIContainer.CONTROLS_HIDDEN));
6238 container.addClass(_this.prefixCss(UIContainer.CONTROLS_SHOWN));
6239 });
6240 uimanager.onControlsHide.subscribe(function () {
6241 container.removeClass(_this.prefixCss(UIContainer.CONTROLS_SHOWN));
6242 container.addClass(_this.prefixCss(UIContainer.CONTROLS_HIDDEN));
6243 });
6244 // Layout size classes
6245 var updateLayoutSizeClasses = function (width, height) {
6246 container.removeClass(_this.prefixCss('layout-max-width-400'));
6247 container.removeClass(_this.prefixCss('layout-max-width-600'));
6248 container.removeClass(_this.prefixCss('layout-max-width-800'));
6249 container.removeClass(_this.prefixCss('layout-max-width-1200'));
6250 if (width <= 400) {
6251 container.addClass(_this.prefixCss('layout-max-width-400'));
6252 }
6253 else if (width <= 600) {
6254 container.addClass(_this.prefixCss('layout-max-width-600'));
6255 }
6256 else if (width <= 800) {
6257 container.addClass(_this.prefixCss('layout-max-width-800'));
6258 }
6259 else if (width <= 1200) {
6260 container.addClass(_this.prefixCss('layout-max-width-1200'));
6261 }
6262 };
6263 player.addEventHandler(player.EVENT.ON_PLAYER_RESIZE, function (e) {
6264 // Convert strings (with "px" suffix) to ints
6265 var width = Math.round(Number(e.width.substring(0, e.width.length - 2)));
6266 var height = Math.round(Number(e.height.substring(0, e.height.length - 2)));
6267 updateLayoutSizeClasses(width, height);
6268 });
6269 // Init layout state
6270 updateLayoutSizeClasses(new dom_1.DOM(player.getFigure()).width(), new dom_1.DOM(player.getFigure()).height());
6271 };
6272 UIContainer.prototype.release = function () {
6273 _super.prototype.release.call(this);
6274 this.uiHideTimeout.clear();
6275 };
6276 UIContainer.prototype.toDomElement = function () {
6277 var container = _super.prototype.toDomElement.call(this);
6278 // Detect flexbox support (not supported in IE9)
6279 if (document && typeof document.createElement('p').style.flex !== 'undefined') {
6280 container.addClass(this.prefixCss('flexbox'));
6281 }
6282 else {
6283 container.addClass(this.prefixCss('no-flexbox'));
6284 }
6285 return container;
6286 };
6287 UIContainer.STATE_PREFIX = 'player-state-';
6288 UIContainer.FULLSCREEN = 'fullscreen';
6289 UIContainer.BUFFERING = 'buffering';
6290 UIContainer.REMOTE_CONTROL = 'remote-control';
6291 UIContainer.CONTROLS_SHOWN = 'controls-shown';
6292 UIContainer.CONTROLS_HIDDEN = 'controls-hidden';
6293 return UIContainer;
6294}(container_1.Container));
6295exports.UIContainer = UIContainer;
6296
6297},{"../dom":68,"../playerutils":86,"../timeout":89,"./container":17}],62:[function(require,module,exports){
6298"use strict";
6299var __extends = (this && this.__extends) || (function () {
6300 var extendStatics = Object.setPrototypeOf ||
6301 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6302 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
6303 return function (d, b) {
6304 extendStatics(d, b);
6305 function __() { this.constructor = d; }
6306 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6307 };
6308})();
6309Object.defineProperty(exports, "__esModule", { value: true });
6310var selectbox_1 = require("./selectbox");
6311/**
6312 * A select box providing a selection between 'auto' and the available video qualities.
6313 */
6314var VideoQualitySelectBox = /** @class */ (function (_super) {
6315 __extends(VideoQualitySelectBox, _super);
6316 function VideoQualitySelectBox(config) {
6317 if (config === void 0) { config = {}; }
6318 return _super.call(this, config) || this;
6319 }
6320 VideoQualitySelectBox.prototype.configure = function (player, uimanager) {
6321 var _this = this;
6322 _super.prototype.configure.call(this, player, uimanager);
6323 var selectCurrentVideoQuality = function () {
6324 if (player.getVideoQuality) {
6325 // Since player 7.3.1
6326 _this.selectItem(player.getVideoQuality().id);
6327 }
6328 else {
6329 // Backwards compatibility for players <= 7.3.0
6330 // TODO remove in next major release
6331 var data = player.getDownloadedVideoData();
6332 _this.selectItem(data.isAuto ? 'auto' : data.id);
6333 }
6334 };
6335 var updateVideoQualities = function () {
6336 var videoQualities = player.getAvailableVideoQualities();
6337 _this.clearItems();
6338 // Progressive streams do not support automatic quality selection
6339 _this.hasAuto = player.getStreamType() !== 'progressive';
6340 if (_this.hasAuto) {
6341 // Add entry for automatic quality switching (default setting)
6342 _this.addItem('auto', 'auto');
6343 }
6344 // Add video qualities
6345 for (var _i = 0, videoQualities_1 = videoQualities; _i < videoQualities_1.length; _i++) {
6346 var videoQuality = videoQualities_1[_i];
6347 _this.addItem(videoQuality.id, videoQuality.label);
6348 }
6349 // Select initial quality
6350 selectCurrentVideoQuality();
6351 };
6352 this.onItemSelected.subscribe(function (sender, value) {
6353 player.setVideoQuality(value);
6354 });
6355 // Update qualities when source goes away
6356 player.addEventHandler(player.EVENT.ON_SOURCE_UNLOADED, updateVideoQualities);
6357 // Update qualities when a new source is loaded
6358 player.addEventHandler(player.EVENT.ON_READY, updateVideoQualities);
6359 // Update qualities when the period within a source changes
6360 player.addEventHandler(player.EVENT.ON_PERIOD_SWITCHED, updateVideoQualities);
6361 // Update quality selection when quality is changed (from outside)
6362 if (player.EVENT.ON_VIDEO_QUALITY_CHANGED) {
6363 // Since player 7.3.1
6364 player.addEventHandler(player.EVENT.ON_VIDEO_QUALITY_CHANGED, selectCurrentVideoQuality);
6365 }
6366 else {
6367 // Backwards compatibility for players <= 7.3.0
6368 // TODO remove in next major release
6369 player.addEventHandler(player.EVENT.ON_VIDEO_DOWNLOAD_QUALITY_CHANGE, selectCurrentVideoQuality);
6370 }
6371 };
6372 /**
6373 * Returns true if the select box contains an 'auto' item for automatic quality selection mode.
6374 * @return {boolean}
6375 */
6376 VideoQualitySelectBox.prototype.hasAutoItem = function () {
6377 return this.hasAuto;
6378 };
6379 return VideoQualitySelectBox;
6380}(selectbox_1.SelectBox));
6381exports.VideoQualitySelectBox = VideoQualitySelectBox;
6382
6383},{"./selectbox":35}],63:[function(require,module,exports){
6384"use strict";
6385var __extends = (this && this.__extends) || (function () {
6386 var extendStatics = Object.setPrototypeOf ||
6387 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6388 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
6389 return function (d, b) {
6390 extendStatics(d, b);
6391 function __() { this.constructor = d; }
6392 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6393 };
6394})();
6395Object.defineProperty(exports, "__esModule", { value: true });
6396var container_1 = require("./container");
6397var volumeslider_1 = require("./volumeslider");
6398var volumetogglebutton_1 = require("./volumetogglebutton");
6399var timeout_1 = require("../timeout");
6400/**
6401 * A composite volume control that consists of and internally manages a volume control button that can be used
6402 * for muting, and a (depending on the CSS style, e.g. slide-out) volume control bar.
6403 */
6404var VolumeControlButton = /** @class */ (function (_super) {
6405 __extends(VolumeControlButton, _super);
6406 function VolumeControlButton(config) {
6407 if (config === void 0) { config = {}; }
6408 var _this = _super.call(this, config) || this;
6409 _this.volumeToggleButton = new volumetogglebutton_1.VolumeToggleButton();
6410 _this.volumeSlider = new volumeslider_1.VolumeSlider({
6411 vertical: config.vertical != null ? config.vertical : true,
6412 hidden: true,
6413 });
6414 _this.config = _this.mergeConfig(config, {
6415 cssClass: 'ui-volumecontrolbutton',
6416 components: [_this.volumeToggleButton, _this.volumeSlider],
6417 hideDelay: 500,
6418 }, _this.config);
6419 return _this;
6420 }
6421 VolumeControlButton.prototype.configure = function (player, uimanager) {
6422 var _this = this;
6423 _super.prototype.configure.call(this, player, uimanager);
6424 var volumeToggleButton = this.getVolumeToggleButton();
6425 var volumeSlider = this.getVolumeSlider();
6426 this.volumeSliderHideTimeout = new timeout_1.Timeout(this.getConfig().hideDelay, function () {
6427 volumeSlider.hide();
6428 });
6429 /*
6430 * Volume Slider visibility handling
6431 *
6432 * The volume slider shall be visible while the user hovers the mute toggle button, while the user hovers the
6433 * volume slider, and while the user slides the volume slider. If none of these situations are true, the slider
6434 * shall disappear.
6435 */
6436 var volumeSliderHovered = false;
6437 volumeToggleButton.getDomElement().on('mouseenter', function () {
6438 // Show volume slider when mouse enters the button area
6439 if (volumeSlider.isHidden()) {
6440 volumeSlider.show();
6441 }
6442 // Avoid hiding of the slider when button is hovered
6443 _this.volumeSliderHideTimeout.clear();
6444 });
6445 volumeToggleButton.getDomElement().on('mouseleave', function () {
6446 // Hide slider delayed when button is left
6447 _this.volumeSliderHideTimeout.reset();
6448 });
6449 volumeSlider.getDomElement().on('mouseenter', function () {
6450 // When the slider is entered, cancel the hide timeout activated by leaving the button
6451 _this.volumeSliderHideTimeout.clear();
6452 volumeSliderHovered = true;
6453 });
6454 volumeSlider.getDomElement().on('mouseleave', function () {
6455 // When mouse leaves the slider, only hide it if there is no slide operation in progress
6456 if (volumeSlider.isSeeking()) {
6457 _this.volumeSliderHideTimeout.clear();
6458 }
6459 else {
6460 _this.volumeSliderHideTimeout.reset();
6461 }
6462 volumeSliderHovered = false;
6463 });
6464 volumeSlider.onSeeked.subscribe(function () {
6465 // When a slide operation is done and the slider not hovered (mouse outside slider), hide slider delayed
6466 if (!volumeSliderHovered) {
6467 _this.volumeSliderHideTimeout.reset();
6468 }
6469 });
6470 };
6471 VolumeControlButton.prototype.release = function () {
6472 _super.prototype.release.call(this);
6473 this.volumeSliderHideTimeout.clear();
6474 };
6475 /**
6476 * Provides access to the internally managed volume toggle button.
6477 * @returns {VolumeToggleButton}
6478 */
6479 VolumeControlButton.prototype.getVolumeToggleButton = function () {
6480 return this.volumeToggleButton;
6481 };
6482 /**
6483 * Provides access to the internally managed volume silder.
6484 * @returns {VolumeSlider}
6485 */
6486 VolumeControlButton.prototype.getVolumeSlider = function () {
6487 return this.volumeSlider;
6488 };
6489 return VolumeControlButton;
6490}(container_1.Container));
6491exports.VolumeControlButton = VolumeControlButton;
6492
6493},{"../timeout":89,"./container":17,"./volumeslider":64,"./volumetogglebutton":65}],64:[function(require,module,exports){
6494"use strict";
6495var __extends = (this && this.__extends) || (function () {
6496 var extendStatics = Object.setPrototypeOf ||
6497 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6498 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
6499 return function (d, b) {
6500 extendStatics(d, b);
6501 function __() { this.constructor = d; }
6502 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6503 };
6504})();
6505Object.defineProperty(exports, "__esModule", { value: true });
6506var seekbar_1 = require("./seekbar");
6507/**
6508 * A simple volume slider component to adjust the player's volume setting.
6509 */
6510var VolumeSlider = /** @class */ (function (_super) {
6511 __extends(VolumeSlider, _super);
6512 function VolumeSlider(config) {
6513 if (config === void 0) { config = {}; }
6514 var _this = _super.call(this, config) || this;
6515 _this.config = _this.mergeConfig(config, {
6516 cssClass: 'ui-volumeslider',
6517 hideIfVolumeControlProhibited: true,
6518 }, _this.config);
6519 return _this;
6520 }
6521 VolumeSlider.prototype.configure = function (player, uimanager) {
6522 var _this = this;
6523 _super.prototype.configure.call(this, player, uimanager, false);
6524 var config = this.getConfig();
6525 if (config.hideIfVolumeControlProhibited && !this.detectVolumeControlAvailability()) {
6526 this.hide();
6527 // We can just return from here, because the user will never interact with the control and any configured
6528 // functionality would only eat resources for no reason.
6529 return;
6530 }
6531 var volumeChangeHandler = function () {
6532 if (player.isMuted()) {
6533 _this.setPlaybackPosition(0);
6534 }
6535 else {
6536 _this.setPlaybackPosition(player.getVolume());
6537 }
6538 };
6539 player.addEventHandler(player.EVENT.ON_READY, volumeChangeHandler);
6540 player.addEventHandler(player.EVENT.ON_VOLUME_CHANGED, volumeChangeHandler);
6541 player.addEventHandler(player.EVENT.ON_MUTED, volumeChangeHandler);
6542 player.addEventHandler(player.EVENT.ON_UNMUTED, volumeChangeHandler);
6543 this.onSeekPreview.subscribeRateLimited(function (sender, args) {
6544 if (args.scrubbing) {
6545 player.setVolume(args.position, VolumeSlider.issuerName);
6546 }
6547 }, 50);
6548 this.onSeeked.subscribe(function (sender, percentage) {
6549 player.setVolume(percentage, VolumeSlider.issuerName);
6550 });
6551 // Update the volume slider marker when the player resized, a source is loaded and player is ready,
6552 // or the UI is configured. Check the seekbar for a detailed description.
6553 player.addEventHandler(player.EVENT.ON_PLAYER_RESIZE, function () {
6554 _this.refreshPlaybackPosition();
6555 });
6556 player.addEventHandler(player.EVENT.ON_READY, function () {
6557 _this.refreshPlaybackPosition();
6558 });
6559 uimanager.onConfigured.subscribe(function () {
6560 _this.refreshPlaybackPosition();
6561 });
6562 // Init volume bar
6563 volumeChangeHandler();
6564 };
6565 VolumeSlider.prototype.detectVolumeControlAvailability = function () {
6566 /*
6567 * "On iOS devices, the audio level is always under the user’s physical control. The volume property is not
6568 * settable in JavaScript. Reading the volume property always returns 1."
6569 * https://developer.apple.com/library/content/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html
6570 */
6571 // as muted autoplay gets paused as soon as we unmute it, we may not touch the volume of the actual player so we
6572 // probe a dummy audio element
6573 var dummyVideoElement = document.createElement('video');
6574 // try setting the volume to 0.7 and if it's still 1 we are on a volume control restricted device
6575 dummyVideoElement.volume = 0.7;
6576 return dummyVideoElement.volume !== 1;
6577 };
6578 VolumeSlider.issuerName = 'ui';
6579 return VolumeSlider;
6580}(seekbar_1.SeekBar));
6581exports.VolumeSlider = VolumeSlider;
6582
6583},{"./seekbar":33}],65:[function(require,module,exports){
6584"use strict";
6585var __extends = (this && this.__extends) || (function () {
6586 var extendStatics = Object.setPrototypeOf ||
6587 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6588 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
6589 return function (d, b) {
6590 extendStatics(d, b);
6591 function __() { this.constructor = d; }
6592 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6593 };
6594})();
6595Object.defineProperty(exports, "__esModule", { value: true });
6596var togglebutton_1 = require("./togglebutton");
6597/**
6598 * A button that toggles audio muting.
6599 */
6600var VolumeToggleButton = /** @class */ (function (_super) {
6601 __extends(VolumeToggleButton, _super);
6602 function VolumeToggleButton(config) {
6603 if (config === void 0) { config = {}; }
6604 var _this = _super.call(this, config) || this;
6605 var defaultConfig = {
6606 cssClass: 'ui-volumetogglebutton',
6607 text: 'Volume/Mute',
6608 onClass: 'muted',
6609 offClass: 'unmuted',
6610 };
6611 _this.config = _this.mergeConfig(config, defaultConfig, _this.config);
6612 return _this;
6613 }
6614 VolumeToggleButton.prototype.configure = function (player, uimanager) {
6615 var _this = this;
6616 _super.prototype.configure.call(this, player, uimanager);
6617 var muteStateHandler = function () {
6618 if (player.isMuted()) {
6619 _this.on();
6620 // When the volume is unmuted and the volume level is veeeery low, we increase it to 10%. This especially helps
6621 // in the case when the volume is first turned down to 0 and then the player is muted; when the player gets
6622 // unmuted it would switch to volume level 0 which would seem like unmuting did not work, and increasing the
6623 // level a bit helps to overcome this issue.
6624 if (player.getVolume() < 10) {
6625 player.setVolume(10);
6626 }
6627 }
6628 else {
6629 _this.off();
6630 }
6631 };
6632 var volumeLevelHandler = function () {
6633 var volumeLevelTens = Math.ceil(player.getVolume() / 10);
6634 _this.getDomElement().data(_this.prefixCss('volume-level-tens'), String(volumeLevelTens));
6635 // When the volume is turned down to zero, switch into the mute state of the button. This avoids the usability
6636 // issue where the volume is turned down to zero, the button shows the muted icon but is not really unmuted, and
6637 // the next button press would switch it into the mute state, visually staying the same which would seem like
6638 // an expected unmute did not work.
6639 if (volumeLevelTens === 0) {
6640 _this.off();
6641 }
6642 };
6643 player.addEventHandler(player.EVENT.ON_MUTED, muteStateHandler);
6644 player.addEventHandler(player.EVENT.ON_UNMUTED, muteStateHandler);
6645 player.addEventHandler(player.EVENT.ON_VOLUME_CHANGED, volumeLevelHandler);
6646 this.onClick.subscribe(function () {
6647 if (player.isMuted()) {
6648 player.unmute('ui-volumetogglebutton');
6649 }
6650 else {
6651 player.mute('ui-volumetogglebutton');
6652 }
6653 });
6654 // Startup init
6655 muteStateHandler();
6656 volumeLevelHandler();
6657 };
6658 return VolumeToggleButton;
6659}(togglebutton_1.ToggleButton));
6660exports.VolumeToggleButton = VolumeToggleButton;
6661
6662},{"./togglebutton":59}],66:[function(require,module,exports){
6663"use strict";
6664var __extends = (this && this.__extends) || (function () {
6665 var extendStatics = Object.setPrototypeOf ||
6666 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6667 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
6668 return function (d, b) {
6669 extendStatics(d, b);
6670 function __() { this.constructor = d; }
6671 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6672 };
6673})();
6674Object.defineProperty(exports, "__esModule", { value: true });
6675var togglebutton_1 = require("./togglebutton");
6676/**
6677 * A button that toggles the video view between normal/mono and VR/stereo.
6678 */
6679var VRToggleButton = /** @class */ (function (_super) {
6680 __extends(VRToggleButton, _super);
6681 function VRToggleButton(config) {
6682 if (config === void 0) { config = {}; }
6683 var _this = _super.call(this, config) || this;
6684 _this.config = _this.mergeConfig(config, {
6685 cssClass: 'ui-vrtogglebutton',
6686 text: 'VR',
6687 }, _this.config);
6688 return _this;
6689 }
6690 VRToggleButton.prototype.configure = function (player, uimanager) {
6691 var _this = this;
6692 _super.prototype.configure.call(this, player, uimanager);
6693 var isVRConfigured = function () {
6694 // VR availability cannot be checked through getVRStatus() because it is asynchronously populated and not
6695 // available at UI initialization. As an alternative, we check the VR settings in the config.
6696 // TODO use getVRStatus() through isVRStereoAvailable() once the player has been rewritten and the status is
6697 // available in ON_READY
6698 var config = player.getConfig();
6699 return config.source && config.source.vr && config.source.vr.contentType !== 'none';
6700 };
6701 var isVRStereoAvailable = function () {
6702 return player.getVRStatus().contentType !== 'none';
6703 };
6704 var vrStateHandler = function () {
6705 if (isVRConfigured() && isVRStereoAvailable()) {
6706 _this.show(); // show button in case it is hidden
6707 if (player.getVRStatus().isStereo) {
6708 _this.on();
6709 }
6710 else {
6711 _this.off();
6712 }
6713 }
6714 else {
6715 _this.hide(); // hide button if no stereo mode available
6716 }
6717 };
6718 var vrButtonVisibilityHandler = function () {
6719 if (isVRConfigured()) {
6720 _this.show();
6721 }
6722 else {
6723 _this.hide();
6724 }
6725 };
6726 player.addEventHandler(player.EVENT.ON_VR_MODE_CHANGED, vrStateHandler);
6727 player.addEventHandler(player.EVENT.ON_VR_STEREO_CHANGED, vrStateHandler);
6728 player.addEventHandler(player.EVENT.ON_VR_ERROR, vrStateHandler);
6729 // Hide button when VR source goes away
6730 player.addEventHandler(player.EVENT.ON_SOURCE_UNLOADED, vrButtonVisibilityHandler);
6731 // Show button when a new source is loaded and it's VR
6732 player.addEventHandler(player.EVENT.ON_READY, vrButtonVisibilityHandler);
6733 this.onClick.subscribe(function () {
6734 if (!isVRStereoAvailable()) {
6735 if (console) {
6736 console.log('No VR content');
6737 }
6738 }
6739 else {
6740 if (player.getVRStatus().isStereo) {
6741 player.setVRStereo(false);
6742 }
6743 else {
6744 player.setVRStereo(true);
6745 }
6746 }
6747 });
6748 // Set startup visibility
6749 vrButtonVisibilityHandler();
6750 };
6751 return VRToggleButton;
6752}(togglebutton_1.ToggleButton));
6753exports.VRToggleButton = VRToggleButton;
6754
6755},{"./togglebutton":59}],67:[function(require,module,exports){
6756"use strict";
6757var __extends = (this && this.__extends) || (function () {
6758 var extendStatics = Object.setPrototypeOf ||
6759 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6760 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
6761 return function (d, b) {
6762 extendStatics(d, b);
6763 function __() { this.constructor = d; }
6764 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6765 };
6766})();
6767Object.defineProperty(exports, "__esModule", { value: true });
6768var clickoverlay_1 = require("./clickoverlay");
6769/**
6770 * A watermark overlay with a clickable logo.
6771 */
6772var Watermark = /** @class */ (function (_super) {
6773 __extends(Watermark, _super);
6774 function Watermark(config) {
6775 if (config === void 0) { config = {}; }
6776 var _this = _super.call(this, config) || this;
6777 _this.config = _this.mergeConfig(config, {
6778 cssClass: 'ui-watermark',
6779 url: 'http://bitmovin.com',
6780 }, _this.config);
6781 return _this;
6782 }
6783 return Watermark;
6784}(clickoverlay_1.ClickOverlay));
6785exports.Watermark = Watermark;
6786
6787},{"./clickoverlay":14}],68:[function(require,module,exports){
6788"use strict";
6789Object.defineProperty(exports, "__esModule", { value: true });
6790/**
6791 * Simple DOM manipulation and DOM element event handling modeled after jQuery (as replacement for jQuery).
6792 *
6793 * Like jQuery, DOM operates on single elements and lists of elements. For example: creating an element returns a DOM
6794 * instance with a single element, selecting elements returns a DOM instance with zero, one, or many elements. Similar
6795 * to jQuery, setters usually affect all elements, while getters operate on only the first element.
6796 * Also similar to jQuery, most methods (except getters) return the DOM instance facilitating easy chaining of method
6797 * calls.
6798 *
6799 * Built with the help of: http://youmightnotneedjquery.com/
6800 */
6801var DOM = /** @class */ (function () {
6802 function DOM(something, attributes) {
6803 this.document = document; // Set the global document to the local document field
6804 if (something instanceof Array) {
6805 if (something.length > 0 && something[0] instanceof HTMLElement) {
6806 var elements = something;
6807 this.elements = elements;
6808 }
6809 }
6810 else if (something instanceof HTMLElement) {
6811 var element = something;
6812 this.elements = [element];
6813 }
6814 else if (something instanceof Document) {
6815 // When a document is passed in, we do not do anything with it, but by setting this.elements to null
6816 // we give the event handling method a means to detect if the events should be registered on the document
6817 // instead of elements.
6818 this.elements = null;
6819 }
6820 else if (attributes) {
6821 var tagName = something;
6822 var element = document.createElement(tagName);
6823 for (var attributeName in attributes) {
6824 var attributeValue = attributes[attributeName];
6825 element.setAttribute(attributeName, attributeValue);
6826 }
6827 this.elements = [element];
6828 }
6829 else {
6830 var selector = something;
6831 this.elements = this.findChildElements(selector);
6832 }
6833 }
6834 Object.defineProperty(DOM.prototype, "length", {
6835 /**
6836 * Gets the number of elements that this DOM instance currently holds.
6837 * @returns {number} the number of elements
6838 */
6839 get: function () {
6840 return this.elements ? this.elements.length : 0;
6841 },
6842 enumerable: true,
6843 configurable: true
6844 });
6845 /**
6846 * Gets the HTML elements that this DOM instance currently holds.
6847 * @returns {HTMLElement[]} the raw HTML elements
6848 * @deprecated use {@link #get()} instead
6849 */
6850 DOM.prototype.getElements = function () {
6851 return this.get();
6852 };
6853 DOM.prototype.get = function (index) {
6854 if (index === undefined) {
6855 return this.elements;
6856 }
6857 else if (!this.elements || index >= this.elements.length || index < -this.elements.length) {
6858 return undefined;
6859 }
6860 else if (index < 0) {
6861 return this.elements[this.elements.length - index];
6862 }
6863 else {
6864 return this.elements[index];
6865 }
6866 };
6867 /**
6868 * A shortcut method for iterating all elements. Shorts this.elements.forEach(...) to this.forEach(...).
6869 * @param handler the handler to execute an operation on an element
6870 */
6871 DOM.prototype.forEach = function (handler) {
6872 if (!this.elements) {
6873 return;
6874 }
6875 this.elements.forEach(function (element) {
6876 handler(element);
6877 });
6878 };
6879 DOM.prototype.findChildElementsOfElement = function (element, selector) {
6880 var childElements = element.querySelectorAll(selector);
6881 // Convert NodeList to Array
6882 // https://toddmotto.com/a-comprehensive-dive-into-nodelists-arrays-converting-nodelists-and-understanding-the-dom/
6883 return [].slice.call(childElements);
6884 };
6885 DOM.prototype.findChildElements = function (selector) {
6886 var _this = this;
6887 var allChildElements = [];
6888 if (this.elements) {
6889 this.forEach(function (element) {
6890 allChildElements = allChildElements.concat(_this.findChildElementsOfElement(element, selector));
6891 });
6892 }
6893 else {
6894 return this.findChildElementsOfElement(document, selector);
6895 }
6896 return allChildElements;
6897 };
6898 /**
6899 * Finds all child elements of all elements matching the supplied selector.
6900 * @param selector the selector to match with child elements
6901 * @returns {DOM} a new DOM instance representing all matched children
6902 */
6903 DOM.prototype.find = function (selector) {
6904 var allChildElements = this.findChildElements(selector);
6905 return new DOM(allChildElements);
6906 };
6907 DOM.prototype.html = function (content) {
6908 if (arguments.length > 0) {
6909 return this.setHtml(content);
6910 }
6911 else {
6912 return this.getHtml();
6913 }
6914 };
6915 DOM.prototype.getHtml = function () {
6916 return this.elements[0].innerHTML;
6917 };
6918 DOM.prototype.setHtml = function (content) {
6919 if (content === undefined || content == null) {
6920 // Set to empty string to avoid innerHTML getting set to 'undefined' (all browsers) or 'null' (IE9)
6921 content = '';
6922 }
6923 this.forEach(function (element) {
6924 element.innerHTML = content;
6925 });
6926 return this;
6927 };
6928 /**
6929 * Clears the inner HTML of all elements (deletes all children).
6930 * @returns {DOM}
6931 */
6932 DOM.prototype.empty = function () {
6933 this.forEach(function (element) {
6934 element.innerHTML = '';
6935 });
6936 return this;
6937 };
6938 /**
6939 * Returns the current value of the first form element, e.g. the selected value of a select box or the text if an
6940 * input field.
6941 * @returns {string} the value of a form element
6942 */
6943 DOM.prototype.val = function () {
6944 var element = this.elements[0];
6945 if (element instanceof HTMLSelectElement || element instanceof HTMLInputElement) {
6946 return element.value;
6947 }
6948 else {
6949 // TODO add support for missing form elements
6950 throw new Error("val() not supported for " + typeof element);
6951 }
6952 };
6953 DOM.prototype.attr = function (attribute, value) {
6954 if (arguments.length > 1) {
6955 return this.setAttr(attribute, value);
6956 }
6957 else {
6958 return this.getAttr(attribute);
6959 }
6960 };
6961 DOM.prototype.getAttr = function (attribute) {
6962 return this.elements[0].getAttribute(attribute);
6963 };
6964 DOM.prototype.setAttr = function (attribute, value) {
6965 this.forEach(function (element) {
6966 element.setAttribute(attribute, value);
6967 });
6968 return this;
6969 };
6970 DOM.prototype.data = function (dataAttribute, value) {
6971 if (arguments.length > 1) {
6972 return this.setData(dataAttribute, value);
6973 }
6974 else {
6975 return this.getData(dataAttribute);
6976 }
6977 };
6978 DOM.prototype.getData = function (dataAttribute) {
6979 return this.elements[0].getAttribute('data-' + dataAttribute);
6980 };
6981 DOM.prototype.setData = function (dataAttribute, value) {
6982 this.forEach(function (element) {
6983 element.setAttribute('data-' + dataAttribute, value);
6984 });
6985 return this;
6986 };
6987 /**
6988 * Appends one or more DOM elements as children to all elements.
6989 * @param childElements the chrild elements to append
6990 * @returns {DOM}
6991 */
6992 DOM.prototype.append = function () {
6993 var childElements = [];
6994 for (var _i = 0; _i < arguments.length; _i++) {
6995 childElements[_i] = arguments[_i];
6996 }
6997 this.forEach(function (element) {
6998 childElements.forEach(function (childElement) {
6999 childElement.elements.forEach(function (_, index) {
7000 element.appendChild(childElement.elements[index]);
7001 });
7002 });
7003 });
7004 return this;
7005 };
7006 /**
7007 * Removes all elements from the DOM.
7008 */
7009 DOM.prototype.remove = function () {
7010 this.forEach(function (element) {
7011 var parent = element.parentNode;
7012 if (parent) {
7013 parent.removeChild(element);
7014 }
7015 });
7016 };
7017 /**
7018 * Returns the offset of the first element from the document's top left corner.
7019 * @returns {Offset}
7020 */
7021 DOM.prototype.offset = function () {
7022 var element = this.elements[0];
7023 var elementRect = element.getBoundingClientRect();
7024 var htmlRect = document.body.parentElement.getBoundingClientRect();
7025 // Virtual viewport scroll handling (e.g. pinch zoomed viewports in mobile browsers or desktop Chrome/Edge)
7026 // 'normal' zooms and virtual viewport zooms (aka layout viewport) result in different
7027 // element.getBoundingClientRect() results:
7028 // - with normal scrolls, the clientRect decreases with an increase in scroll(Top|Left)/page(X|Y)Offset
7029 // - with pinch zoom scrolls, the clientRect stays the same while scroll/pageOffset changes
7030 // This means, that the combination of clientRect + scroll/pageOffset does not work to calculate the offset
7031 // from the document's upper left origin when pinch zoom is used.
7032 // To work around this issue, we do not use scroll/pageOffset but get the clientRect of the html element and
7033 // subtract it from the element's rect, which always results in the offset from the document origin.
7034 // NOTE: the current way of offset calculation was implemented specifically to track event positions on the
7035 // seek bar, and it might break compatibility with jQuery's offset() method. If this ever turns out to be a
7036 // problem, this method should be reverted to the old version and the offset calculation moved to the seek bar.
7037 return {
7038 top: elementRect.top - htmlRect.top,
7039 left: elementRect.left - htmlRect.left,
7040 };
7041 };
7042 /**
7043 * Returns the width of the first element.
7044 * @returns {number} the width of the first element
7045 */
7046 DOM.prototype.width = function () {
7047 // TODO check if this is the same as jQuery's width() (probably not)
7048 return this.elements[0].offsetWidth;
7049 };
7050 /**
7051 * Returns the height of the first element.
7052 * @returns {number} the height of the first element
7053 */
7054 DOM.prototype.height = function () {
7055 // TODO check if this is the same as jQuery's height() (probably not)
7056 return this.elements[0].offsetHeight;
7057 };
7058 /**
7059 * Attaches an event handler to one or more events on all elements.
7060 * @param eventName the event name (or multiple names separated by space) to listen to
7061 * @param eventHandler the event handler to call when the event fires
7062 * @returns {DOM}
7063 */
7064 DOM.prototype.on = function (eventName, eventHandler) {
7065 var _this = this;
7066 var events = eventName.split(' ');
7067 events.forEach(function (event) {
7068 if (_this.elements == null) {
7069 _this.document.addEventListener(event, eventHandler);
7070 }
7071 else {
7072 _this.forEach(function (element) {
7073 element.addEventListener(event, eventHandler);
7074 });
7075 }
7076 });
7077 return this;
7078 };
7079 /**
7080 * Removes an event handler from one or more events on all elements.
7081 * @param eventName the event name (or multiple names separated by space) to remove the handler from
7082 * @param eventHandler the event handler to remove
7083 * @returns {DOM}
7084 */
7085 DOM.prototype.off = function (eventName, eventHandler) {
7086 var _this = this;
7087 var events = eventName.split(' ');
7088 events.forEach(function (event) {
7089 if (_this.elements == null) {
7090 _this.document.removeEventListener(event, eventHandler);
7091 }
7092 else {
7093 _this.forEach(function (element) {
7094 element.removeEventListener(event, eventHandler);
7095 });
7096 }
7097 });
7098 return this;
7099 };
7100 /**
7101 * Adds the specified class(es) to all elements.
7102 * @param className the class(es) to add, multiple classes separated by space
7103 * @returns {DOM}
7104 */
7105 DOM.prototype.addClass = function (className) {
7106 this.forEach(function (element) {
7107 var _a;
7108 if (element.classList) {
7109 var classNames = className.split(' ')
7110 .filter(function (className) { return className.length > 0; });
7111 if (classNames.length > 0) {
7112 (_a = element.classList).add.apply(_a, classNames);
7113 }
7114 }
7115 else {
7116 element.className += ' ' + className;
7117 }
7118 });
7119 return this;
7120 };
7121 /**
7122 * Removed the specified class(es) from all elements.
7123 * @param className the class(es) to remove, multiple classes separated by space
7124 * @returns {DOM}
7125 */
7126 DOM.prototype.removeClass = function (className) {
7127 this.forEach(function (element) {
7128 var _a;
7129 if (element.classList) {
7130 var classNames = className.split(' ')
7131 .filter(function (className) { return className.length > 0; });
7132 if (classNames.length > 0) {
7133 (_a = element.classList).remove.apply(_a, classNames);
7134 }
7135 }
7136 else {
7137 element.className = element.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
7138 }
7139 });
7140 return this;
7141 };
7142 /**
7143 * Checks if any of the elements has the specified class.
7144 * @param className the class name to check
7145 * @returns {boolean} true if one of the elements has the class attached, else if no element has it attached
7146 */
7147 DOM.prototype.hasClass = function (className) {
7148 var hasClass = false;
7149 this.forEach(function (element) {
7150 if (element.classList) {
7151 if (element.classList.contains(className)) {
7152 // Since we are inside a handler, we can't just 'return true'. Instead, we save it to a variable
7153 // and return it at the end of the function body.
7154 hasClass = true;
7155 }
7156 }
7157 else {
7158 if (new RegExp('(^| )' + className + '( |$)', 'gi').test(element.className)) {
7159 // See comment above
7160 hasClass = true;
7161 }
7162 }
7163 });
7164 return hasClass;
7165 };
7166 DOM.prototype.css = function (propertyNameOrCollection, value) {
7167 if (typeof propertyNameOrCollection === 'string') {
7168 var propertyName = propertyNameOrCollection;
7169 if (arguments.length === 2) {
7170 return this.setCss(propertyName, value);
7171 }
7172 else {
7173 return this.getCss(propertyName);
7174 }
7175 }
7176 else {
7177 var propertyValueCollection = propertyNameOrCollection;
7178 return this.setCssCollection(propertyValueCollection);
7179 }
7180 };
7181 DOM.prototype.getCss = function (propertyName) {
7182 return getComputedStyle(this.elements[0])[propertyName];
7183 };
7184 DOM.prototype.setCss = function (propertyName, value) {
7185 this.forEach(function (element) {
7186 // <any> cast to resolve TS7015: http://stackoverflow.com/a/36627114/370252
7187 element.style[propertyName] = value;
7188 });
7189 return this;
7190 };
7191 DOM.prototype.setCssCollection = function (ruleValueCollection) {
7192 this.forEach(function (element) {
7193 // http://stackoverflow.com/a/34490573/370252
7194 Object.assign(element.style, ruleValueCollection);
7195 });
7196 return this;
7197 };
7198 return DOM;
7199}());
7200exports.DOM = DOM;
7201
7202},{}],69:[function(require,module,exports){
7203"use strict";
7204var __extends = (this && this.__extends) || (function () {
7205 var extendStatics = Object.setPrototypeOf ||
7206 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
7207 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7208 return function (d, b) {
7209 extendStatics(d, b);
7210 function __() { this.constructor = d; }
7211 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
7212 };
7213})();
7214Object.defineProperty(exports, "__esModule", { value: true });
7215var menu_1 = require("../menu/menu");
7216var menucappinglist_1 = require("./menucappinglist");
7217var menulabel_1 = require("../menu/menulabel");
7218var MenuCapping = /** @class */ (function (_super) {
7219 __extends(MenuCapping, _super);
7220 function MenuCapping(config) {
7221 var _this = _super.call(this, config) || this;
7222 _this.title = 'Video Quality';
7223 _this.message = 'Highest quality setting dependent on availability';
7224 _this.mainMenu = config.mainMenu;
7225 _this.config = _this.mergeConfig(config, {
7226 components: [
7227 new menu_1.MenuItem(new menulabel_1.MenuLabel({ text: _this.title, cssClass: 'ui-menu-heading' })),
7228 new menu_1.MenuItem(new menucappinglist_1.MenuCappingList()),
7229 new menu_1.MenuItem(new menulabel_1.MenuLabel({ text: _this.message, cssClass: 'ui-menu-label' })),
7230 ],
7231 }, _this.config);
7232 return _this;
7233 }
7234 return MenuCapping;
7235}(menu_1.Menu));
7236exports.MenuCapping = MenuCapping;
7237
7238},{"../menu/menu":75,"../menu/menulabel":78,"./menucappinglist":70}],70:[function(require,module,exports){
7239"use strict";
7240var __extends = (this && this.__extends) || (function () {
7241 var extendStatics = Object.setPrototypeOf ||
7242 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
7243 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7244 return function (d, b) {
7245 extendStatics(d, b);
7246 function __() { this.constructor = d; }
7247 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
7248 };
7249})();
7250Object.defineProperty(exports, "__esModule", { value: true });
7251var menulistselector_1 = require("../menu/menulistselector");
7252var menucappingutils_1 = require("./menucappingutils");
7253/**
7254 * A select box providing a selection between 'auto' and the available video qualities.
7255 */
7256var MenuCappingList = /** @class */ (function (_super) {
7257 __extends(MenuCappingList, _super);
7258 function MenuCappingList(config) {
7259 if (config === void 0) { config = {}; }
7260 var _this = _super.call(this, config) || this;
7261 _this.config = _this.mergeConfig(config, {
7262 cssClass: 'ui-menu-list',
7263 }, _this.config);
7264 return _this;
7265 }
7266 function isEmptyObj(obj) {
7267 if (typeof obj !== 'object') return false;
7268
7269 for(var key in obj) {
7270 if(obj.hasOwnProperty(key))
7271 return false;
7272 }
7273 return true;
7274 }
7275
7276 var configLoadCount = 0;
7277 MenuCappingList.prototype.configure = function (player, uimanager) {
7278 var _this = this;
7279 _super.prototype.configure.call(this, player, uimanager);
7280 menucappingutils_1.MenuCappingUtils.setCaprates();
7281
7282 var selectCurrentCapping = function () {
7283 var caprate = menucappingutils_1.MenuCappingUtils.getCaprateSelected();
7284 if (isEmptyObj(caprate) && configLoadCount++ === 0) {
7285 var confValues = JSON.parse(sessionStorage.getItem('VIDEO_QUALITY_CONF')) || [];
7286 caprate = confValues.find((el) => el.preferred) || { id: 0 };
7287 _this.selectItem(caprate.id);
7288 } else if (typeof caprate === 'string' || typeof caprate === 'number') {
7289 _this.selectItem(menucappingutils_1.MenuCappingUtils.getCaprateFromCaprates(`${caprate}`));
7290 } else if (caprate.id && caprate.id !== _this.selectedItem || typeof _this.selectedItem === 'undefined') {
7291 _this.selectItem(caprate.id);
7292 }
7293 };
7294 var updateCapping = function () {
7295 var videoQualities = player.getAvailableVideoQualities();
7296 _this.clearItems();
7297
7298 if (videoQualities.length > 1) {
7299 var caprates = menucappingutils_1.MenuCappingUtils.getCaprates();
7300 for (var _i = 0, caprates_1 = caprates; _i < caprates_1.length; _i++) {
7301 var item = caprates_1[_i];
7302 _this.addItem(item.id, item.label, item.message);
7303 }
7304 }
7305 selectCurrentCapping();
7306 };
7307 this.onItemSelected.subscribe(function (sender, id) {
7308 _this.selectedItem = id;
7309 menucappingutils_1.MenuCappingUtils.setCaprateSelected(id);
7310 });
7311 player.addEventHandler(player.EVENT.ON_READY, updateCapping);
7312 player.addEventHandler(player.EVENT.ON_VIDEO_ADAPTATION, selectCurrentCapping);
7313 };
7314 /**
7315 * Returns true if the select box contains an 'auto' item for automatic quality selection mode.
7316 * @return {boolean}
7317 */
7318 MenuCappingList.prototype.hasAutoItem = function () {
7319 return this.hasAuto;
7320 };
7321 return MenuCappingList;
7322}(menulistselector_1.MenuListSelector));
7323exports.MenuCappingList = MenuCappingList;
7324
7325},{"../menu/menulistselector":79,"./menucappingutils":71}],71:[function(require,module,exports){
7326"use strict";
7327Object.defineProperty(exports, "__esModule", { value: true });
7328var storageutils_1 = require("../../storageutils");
7329var MenuCappingUtils;
7330(function (MenuCappingUtils) {
7331 var caprateSelected;
7332 var capratesUpdated = [];
7333 var localStorageCaprateKey = 'bimovinplayer_caprate';
7334 function setCaprates() {
7335 capratesUpdated = JSON.parse(sessionStorage.getItem('VIDEO_QUALITY_CONF'));
7336 }
7337 MenuCappingUtils.setCaprates = setCaprates;
7338 function getCaprates() {
7339 return capratesUpdated;
7340 }
7341 MenuCappingUtils.getCaprates = getCaprates;
7342 function setCaprateSelected(value) {
7343 if (typeof value === 'string') {
7344 caprateSelected = getCaprateFromCaprates(value);
7345 }
7346 else {
7347 caprateSelected = value;
7348 }
7349 saveCaprate();
7350 }
7351 MenuCappingUtils.setCaprateSelected = setCaprateSelected;
7352 function getCaprateSelected() {
7353 var savedCaprate = loadCaprate();
7354 if (!savedCaprate || typeof savedCaprate === 'undefined')
7355 return;
7356 return savedCaprate;
7357 }
7358 MenuCappingUtils.getCaprateSelected = getCaprateSelected;
7359 function getCaprateFromCaprates(id) {
7360 for (var _i = 0, capratesUpdated_1 = capratesUpdated; _i < capratesUpdated_1.length; _i++) {
7361 var item = capratesUpdated_1[_i];
7362 if (id === item.id)
7363 return item;
7364 }
7365 return 'auto';
7366 }
7367 MenuCappingUtils.getCaprateFromCaprates = getCaprateFromCaprates;
7368 /**
7369 * Saves the settings to local storage
7370 */
7371 function saveCaprate() {
7372 if (typeof caprateSelected !== 'undefined') {
7373 storageutils_1.StorageUtils.setObject(localStorageCaprateKey, caprateSelected);
7374 }
7375 }
7376 /**
7377 * Loads the settings from local storage
7378 */
7379 function loadCaprate() {
7380 return storageutils_1.StorageUtils.getObject(localStorageCaprateKey) || {};
7381 }
7382})(MenuCappingUtils = exports.MenuCappingUtils || (exports.MenuCappingUtils = {}));
7383
7384},{"../../storageutils":87}],72:[function(require,module,exports){
7385"use strict";
7386var __extends = (this && this.__extends) || (function () {
7387 var extendStatics = Object.setPrototypeOf ||
7388 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
7389 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7390 return function (d, b) {
7391 extendStatics(d, b);
7392 function __() { this.constructor = d; }
7393 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
7394 };
7395})();
7396Object.defineProperty(exports, "__esModule", { value: true });
7397var playbacktogglebutton_1 = require("../components/playbacktogglebutton");
7398var dom_1 = require("../dom");
7399/**
7400 * A button that overlays the video and toggles between playback and pause.
7401 */
7402var DStvHugePlaybackToggleButton = /** @class */ (function (_super) {
7403 __extends(DStvHugePlaybackToggleButton, _super);
7404 function DStvHugePlaybackToggleButton(config) {
7405 if (config === void 0) { config = {}; }
7406 var _this = _super.call(this, config) || this;
7407 _this.config = _this.mergeConfig(config, {
7408 cssClass: 'ui-hugeplaybacktogglebutton',
7409 text: 'Play/Pause',
7410 }, _this.config);
7411 return _this;
7412 }
7413 DStvHugePlaybackToggleButton.prototype.configure = function (player, uimanager) {
7414 var _this = this;
7415 // Update button state through API events
7416 _super.prototype.configure.call(this, player, uimanager, false);
7417 var togglePlayback = function () {
7418 if (player.isPlaying()) {
7419 player.pause('ui-overlay');
7420 }
7421 else {
7422 player.play('ui-overlay');
7423 }
7424 };
7425 var toggleFullscreen = function () {
7426 if (player.isFullscreen()) {
7427 player.exitFullscreen();
7428 }
7429 else {
7430 player.enterFullscreen();
7431 }
7432 };
7433 var firstPlay = true;
7434 var clickTime = 0;
7435 var doubleClickTime = 0;
7436 /*
7437 * YouTube-style toggle button handling
7438 *
7439 * The goal is to prevent a short pause or playback interval between a click, that toggles playback, and a
7440 * double click, that toggles fullscreen. In this naive approach, the first click would e.g. start playback,
7441 * the second click would be detected as double click and toggle to fullscreen, and as second normal click stop
7442 * playback, which results is a short playback interval with max length of the double click detection
7443 * period (usually 500ms).
7444 *
7445 * To solve this issue, we defer handling of the first click for 200ms, which is almost unnoticeable to the user,
7446 * and just toggle playback if no second click (double click) has been registered during this period. If a double
7447 * click is registered, we just toggle the fullscreen. In the first 200ms, undesired playback changes thus cannot
7448 * happen. If a double click is registered within 500ms, we undo the playback change and switch fullscreen mode.
7449 * In the end, this method basically introduces a 200ms observing interval in which playback changes are prevented
7450 * if a double click happens.
7451 */
7452 this.onClick.subscribe(function () {
7453 // Directly start playback on first click of the button.
7454 // This is a required workaround for mobile browsers where video playback needs to be triggered directly
7455 // by the user. A deferred playback start through the timeout below is not considered as user action and
7456 // therefore ignored by mobile browsers.
7457 if (firstPlay) {
7458 // Try to start playback. Then we wait for ON_PLAY and only when it arrives, we disable the firstPlay flag.
7459 // If we disable the flag here, onClick was triggered programmatically instead of by a user interaction, and
7460 // playback is blocked (e.g. on mobile devices due to the programmatic play() call), we loose the chance to
7461 // ever start playback through a user interaction again with this button.
7462 togglePlayback();
7463 return;
7464 }
7465 var now = Date.now();
7466 if (now - clickTime < 200) {
7467 // We have a double click inside the 200ms interval, just toggle fullscreen mode
7468 toggleFullscreen();
7469 doubleClickTime = now;
7470 return;
7471 }
7472 else if (now - clickTime < 500) {
7473 // We have a double click inside the 500ms interval, undo playback toggle and toggle fullscreen mode
7474 toggleFullscreen();
7475 togglePlayback();
7476 doubleClickTime = now;
7477 return;
7478 }
7479 clickTime = now;
7480 setTimeout(function () {
7481 if (Date.now() - doubleClickTime > 200) {
7482 // No double click detected, so we toggle playback and wait what happens next
7483 togglePlayback();
7484 }
7485 }, 200);
7486 });
7487 player.addEventHandler(player.EVENT.ON_PLAY, function () {
7488 // Playback has really started, we can disable the flag to switch to normal toggle button handling
7489 firstPlay = false;
7490 });
7491 // Hide button while initializing a Cast session
7492 var castInitializationHandler = function (event) {
7493 if (event.type === player.EVENT.ON_CAST_START) {
7494 // Hide button when session is being initialized
7495 _this.hide();
7496 }
7497 else {
7498 // Show button when session is established or initialization was aborted
7499 _this.show();
7500 }
7501 };
7502 player.addEventHandler(player.EVENT.ON_CAST_START, castInitializationHandler);
7503 player.addEventHandler(player.EVENT.ON_CAST_STARTED, castInitializationHandler);
7504 player.addEventHandler(player.EVENT.ON_CAST_STOPPED, castInitializationHandler);
7505 };
7506 DStvHugePlaybackToggleButton.prototype.toDomElement = function () {
7507 var buttonElement = _super.prototype.toDomElement.call(this);
7508 var playCircleElement = new dom_1.DOM('div', {
7509 'class': this.prefixCss('play-circle'),
7510 });
7511 var playIconOverElement = new dom_1.DOM('div', {
7512 'class': this.prefixCss('play-icon-over'),
7513 });
7514 buttonElement.append(playCircleElement);
7515 buttonElement.append(playIconOverElement);
7516 return buttonElement;
7517 };
7518 return DStvHugePlaybackToggleButton;
7519}(playbacktogglebutton_1.PlaybackToggleButton));
7520exports.DStvHugePlaybackToggleButton = DStvHugePlaybackToggleButton;
7521
7522},{"../components/playbacktogglebutton":30,"../dom":68}],73:[function(require,module,exports){
7523"use strict";
7524var __extends = (this && this.__extends) || (function () {
7525 var extendStatics = Object.setPrototypeOf ||
7526 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
7527 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7528 return function (d, b) {
7529 extendStatics(d, b);
7530 function __() { this.constructor = d; }
7531 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
7532 };
7533})();
7534Object.defineProperty(exports, "__esModule", { value: true });
7535var component_1 = require("../components/component");
7536var eventdispatcher_1 = require("../eventdispatcher");
7537var arrayutils_1 = require("../arrayutils");
7538var DStvListSelector = /** @class */ (function (_super) {
7539 __extends(DStvListSelector, _super);
7540 function DStvListSelector(config) {
7541 if (config === void 0) { config = {}; }
7542 var _this = _super.call(this, config) || this;
7543 _this.listSelectorEvents = {
7544 onItemAdded: new eventdispatcher_1.EventDispatcher(),
7545 onItemRemoved: new eventdispatcher_1.EventDispatcher(),
7546 onItemSelected: new eventdispatcher_1.EventDispatcher(),
7547 };
7548 _this.config = _this.mergeConfig(config, {
7549 items: [],
7550 cssClass: 'ui-listselector',
7551 }, _this.config);
7552 _this.items = _this.config.items;
7553 return _this;
7554 }
7555 DStvListSelector.prototype.getItemIndex = function (key) {
7556 for (var index in this.items) {
7557 if (key === this.items[index].key) {
7558 return parseInt(index);
7559 }
7560 }
7561 return -1;
7562 };
7563 /**
7564 * Checks if the specified item is part of this selector.
7565 * @param key the key of the item to check
7566 * @returns {boolean} true if the item is part of this selector, else false
7567 */
7568 DStvListSelector.prototype.hasItem = function (key) {
7569 return this.getItemIndex(key) > -1;
7570 };
7571 /**
7572 * Adds an item to this selector by appending it to the end of the list of items. If an item with the specified
7573 * key already exists, it is replaced.
7574 * @param key the key of the item to add
7575 * @param label the (human-readable) label of the item to add
7576 */
7577 DStvListSelector.prototype.addItem = function (key, label, msg) {
7578 this.removeItem(key); // Try to remove key first to get overwrite behavior and avoid duplicate keys
7579 this.items.push({ key: key, label: label, msg: msg });
7580 this.onItemAddedEvent(key);
7581 };
7582 /**
7583 * Removes an item from this selector.
7584 * @param key the key of the item to remove
7585 * @returns {boolean} true if removal was successful, false if the item is not part of this selector
7586 */
7587 DStvListSelector.prototype.removeItem = function (key) {
7588 var index = this.getItemIndex(key);
7589 if (index > -1) {
7590 arrayutils_1.ArrayUtils.remove(this.items, this.items[index]);
7591 this.onItemRemovedEvent(key);
7592 return true;
7593 }
7594 return false;
7595 };
7596 /**
7597 * Selects an item from the items in this selector.
7598 * @param key the key of the item to select
7599 * @returns {boolean} true is the selection was successful, false if the selected item is not part of the selector
7600 */
7601 DStvListSelector.prototype.selectItem = function (key) {
7602 if (key === this.selectedItem) {
7603 // itemConfig is already selected, suppress any further action
7604 return true;
7605 }
7606 var index = this.getItemIndex(key);
7607 if (index > -1) {
7608 this.selectedItem = key;
7609 this.onItemSelectedEvent(key);
7610 return true;
7611 }
7612 return false;
7613 };
7614 /**
7615 * Returns the key of the selected item.
7616 * @returns {string} the key of the selected item or null if no item is selected
7617 */
7618 DStvListSelector.prototype.getSelectedItem = function () {
7619 return this.selectedItem;
7620 };
7621 /**
7622 * Removes all items from this selector.
7623 */
7624 DStvListSelector.prototype.clearItems = function () {
7625 // local copy for iteration after clear
7626 var items = this.items;
7627 // clear items
7628 this.items = [];
7629 // clear the selection as the selected item is also removed
7630 this.selectedItem = null;
7631 // fire events
7632 for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
7633 var item = items_1[_i];
7634 this.onItemRemovedEvent(item.key);
7635 }
7636 };
7637 /**
7638 * Returns the number of items in this selector.
7639 * @returns {number}
7640 */
7641 DStvListSelector.prototype.itemCount = function () {
7642 return Object.keys(this.items).length;
7643 };
7644 DStvListSelector.prototype.onItemAddedEvent = function (key) {
7645 this.listSelectorEvents.onItemAdded.dispatch(this, key);
7646 };
7647 DStvListSelector.prototype.onItemRemovedEvent = function (key) {
7648 this.listSelectorEvents.onItemRemoved.dispatch(this, key);
7649 };
7650 DStvListSelector.prototype.onItemSelectedEvent = function (key) {
7651 this.listSelectorEvents.onItemSelected.dispatch(this, key);
7652 };
7653 Object.defineProperty(DStvListSelector.prototype, "onItemAdded", {
7654 /**
7655 * Gets the event that is fired when an item is added to the list of items.
7656 * @returns {Event<DStvListSelector<Config>, string>}
7657 */
7658 get: function () {
7659 return this.listSelectorEvents.onItemAdded.getEvent();
7660 },
7661 enumerable: true,
7662 configurable: true
7663 });
7664 Object.defineProperty(DStvListSelector.prototype, "onItemRemoved", {
7665 /**
7666 * Gets the event that is fired when an item is removed from the list of items.
7667 * @returns {Event<DStvListSelector<Config>, string>}
7668 */
7669 get: function () {
7670 return this.listSelectorEvents.onItemRemoved.getEvent();
7671 },
7672 enumerable: true,
7673 configurable: true
7674 });
7675 Object.defineProperty(DStvListSelector.prototype, "onItemSelected", {
7676 /**
7677 * Gets the event that is fired when an item is selected from the list of items.
7678 * @returns {Event<DStvListSelector<Config>, string>}
7679 */
7680 get: function () {
7681 return this.listSelectorEvents.onItemSelected.getEvent();
7682 },
7683 enumerable: true,
7684 configurable: true
7685 });
7686 return DStvListSelector;
7687}(component_1.Component));
7688exports.DStvListSelector = DStvListSelector;
7689
7690},{"../arrayutils":1,"../components/component":16,"../eventdispatcher":82}],74:[function(require,module,exports){
7691"use strict";
7692var __extends = (this && this.__extends) || (function () {
7693 var extendStatics = Object.setPrototypeOf ||
7694 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
7695 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7696 return function (d, b) {
7697 extendStatics(d, b);
7698 function __() { this.constructor = d; }
7699 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
7700 };
7701})();
7702Object.defineProperty(exports, "__esModule", { value: true });
7703var container_1 = require("../components/container");
7704var dstvhugeplaybacktogglebutton_1 = require("./dstvhugeplaybacktogglebutton");
7705/**
7706 * Overlays the player and displays error messages.
7707 */
7708var DStvPlaybackToggleOverlay = /** @class */ (function (_super) {
7709 __extends(DStvPlaybackToggleOverlay, _super);
7710 function DStvPlaybackToggleOverlay(config) {
7711 if (config === void 0) { config = {}; }
7712 var _this = _super.call(this, config) || this;
7713 _this.playbackToggleButton = new dstvhugeplaybacktogglebutton_1.DStvHugePlaybackToggleButton();
7714 _this.config = _this.mergeConfig(config, {
7715 cssClass: 'ui-playbacktoggle-overlay',
7716 components: [_this.playbackToggleButton],
7717 }, _this.config);
7718 return _this;
7719 }
7720 return DStvPlaybackToggleOverlay;
7721}(container_1.Container));
7722exports.DStvPlaybackToggleOverlay = DStvPlaybackToggleOverlay;
7723
7724},{"../components/container":17,"./dstvhugeplaybacktogglebutton":72}],75:[function(require,module,exports){
7725"use strict";
7726var __extends = (this && this.__extends) || (function () {
7727 var extendStatics = Object.setPrototypeOf ||
7728 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
7729 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7730 return function (d, b) {
7731 extendStatics(d, b);
7732 function __() { this.constructor = d; }
7733 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
7734 };
7735})();
7736Object.defineProperty(exports, "__esModule", { value: true });
7737var container_1 = require("../../components/container");
7738var timeout_1 = require("../../timeout");
7739var eventdispatcher_1 = require("../../eventdispatcher");
7740var menuitembutton_1 = require("./menuitembutton");
7741var menulistselector_1 = require("./menulistselector");
7742/**
7743 * A panel containing a list of {@link SettingsPanelItem items} that represent labelled settings.
7744 */
7745var Menu = /** @class */ (function (_super) {
7746 __extends(Menu, _super);
7747 function Menu(config) {
7748 var _this = _super.call(this, config) || this;
7749 _this.settingsPanelEvents = {
7750 onSettingsStateChanged: new eventdispatcher_1.EventDispatcher(),
7751 };
7752 _this.config = _this.mergeConfig(config, {
7753 cssClass: 'ui-menu',
7754 }, _this.config);
7755 return _this;
7756 }
7757 Menu.prototype.configure = function (player, uimanager) {
7758 var _this = this;
7759 _super.prototype.configure.call(this, player, uimanager);
7760 var config = this.getConfig(); // TODO fix generics type inference
7761 if (config.hideDelay > -1) {
7762 this.hideTimeout = new timeout_1.Timeout(config.hideDelay, function () {
7763 _this.hide();
7764 });
7765 this.onShow.subscribe(function () {
7766 // Activate timeout when shown
7767 _this.hideTimeout.start();
7768 });
7769 this.getDomElement().on('mouseenter', function () {
7770 // On mouse enter clear the timeout
7771 _this.hideTimeout.clear();
7772 });
7773 this.getDomElement().on('mouseleave', function () {
7774 // On mouse leave activate the timeout
7775 _this.hideTimeout.reset();
7776 });
7777 this.onHide.subscribe(function () {
7778 // Clear timeout when hidden from outside
7779 _this.hideTimeout.clear();
7780 });
7781 }
7782 // Fire event when the state of a settings-item has changed
7783 var settingsStateChangedHandler = function () {
7784 _this.onSettingsStateChangedEvent();
7785 };
7786 // Attach marker class to last visible item
7787 var lastShownItem = null;
7788 var componentCount = 0;
7789 for (var _i = 0, _a = this.getItems(); _i < _a.length; _i++) {
7790 var component = _a[_i];
7791 if (component instanceof MenuItem) {
7792 var components = component.getConfig().components;
7793 if (components.length > 0 && components[0] instanceof menuitembutton_1.MenuItemButton) {
7794 if (componentCount >= 1) {
7795 lastShownItem = component;
7796 }
7797 componentCount++;
7798 }
7799 }
7800 if (component instanceof MenuItem) {
7801 component.onActiveChanged.subscribe(settingsStateChangedHandler);
7802 }
7803 }
7804 if (lastShownItem) {
7805 lastShownItem.getDomElement().addClass(this.prefixCss(Menu.CLASS_LAST));
7806 }
7807 };
7808 Menu.prototype.release = function () {
7809 _super.prototype.release.call(this);
7810 if (this.hideTimeout) {
7811 this.hideTimeout.clear();
7812 }
7813 };
7814 /**
7815 * Checks if there are active settings within this settings panel. An active setting is a setting that is visible
7816 * and enabled, which the user can interact with.
7817 * @returns {boolean} true if there are active settings, false if the panel is functionally empty to a user
7818 */
7819 Menu.prototype.hasActiveSettings = function () {
7820 for (var _i = 0, _a = this.getItems(); _i < _a.length; _i++) {
7821 var component = _a[_i];
7822 var subcomponent = component.getConfig().components[0];
7823 if (subcomponent instanceof menulistselector_1.MenuListSelector) {
7824 if (subcomponent.isActive()) {
7825 return true;
7826 }
7827 }
7828 }
7829 return false;
7830 };
7831 Menu.prototype.getItems = function () {
7832 return this.config.components;
7833 };
7834 Menu.prototype.onSettingsStateChangedEvent = function () {
7835 this.settingsPanelEvents.onSettingsStateChanged.dispatch(this);
7836 };
7837 Object.defineProperty(Menu.prototype, "onSettingsStateChanged", {
7838 /**
7839 * Gets the event that is fired when one or more {@link SettingsPanelItem items} have changed state.
7840 * @returns {Event<SettingsPanel, NoArgs>}
7841 */
7842 get: function () {
7843 return this.settingsPanelEvents.onSettingsStateChanged.getEvent();
7844 },
7845 enumerable: true,
7846 configurable: true
7847 });
7848 Menu.CLASS_LAST = 'last';
7849 return Menu;
7850}(container_1.Container));
7851exports.Menu = Menu;
7852/**
7853 * An item for a {@link SettingsPanel},
7854 * Containing an optionnal {@link component} and a component that configures a setting.
7855 * If the components is a {@link setting} it will handle the logic of displaying it or not
7856 */
7857var MenuItem = /** @class */ (function (_super) {
7858 __extends(MenuItem, _super);
7859 function MenuItem(setting, config) {
7860 if (setting === void 0) { setting = null; }
7861 if (config === void 0) { config = {}; }
7862 var _this = _super.call(this, config) || this;
7863 _this.settingsPanelItemEvents = {
7864 onActiveChanged: new eventdispatcher_1.EventDispatcher(),
7865 };
7866 _this.setting = setting;
7867 _this.config = _this.mergeConfig(config, {
7868 cssClass: 'ui-menu-item',
7869 }, _this.config);
7870 if (setting !== null)
7871 _this.addComponent(_this.setting);
7872 return _this;
7873 }
7874 MenuItem.prototype.configure = function (player, uimanager) {
7875 var _this = this;
7876 _super.prototype.configure.call(this, player, uimanager);
7877 if (this.setting instanceof menulistselector_1.MenuListSelector) {
7878 var handleConfigItemChanged = function () {
7879 // Visibility might have changed and therefore the active state might have changed so we fire the event
7880 // TODO fire only when state has really changed (e.g. check if visibility has really changed)
7881 _this.onActiveChangedEvent();
7882 };
7883 this.setting.onItemAdded.subscribe(handleConfigItemChanged);
7884 this.setting.onItemRemoved.subscribe(handleConfigItemChanged);
7885 // Initialize hidden state
7886 handleConfigItemChanged();
7887 }
7888 };
7889 /**
7890 * Checks if this settings panel item is active, i.e. visible and enabled and a user can interact with it.
7891 * @returns {boolean} true if the panel is active, else false
7892 */
7893 MenuItem.prototype.isActive = function () {
7894 return this.isShown();
7895 };
7896 MenuItem.prototype.onActiveChangedEvent = function () {
7897 this.settingsPanelItemEvents.onActiveChanged.dispatch(this);
7898 };
7899 Object.defineProperty(MenuItem.prototype, "onActiveChanged", {
7900 /**
7901 * Gets the event that is fired when the 'active' state of this item changes.
7902 * @see #isActive
7903 * @returns {Event<SettingsPanelItem, NoArgs>}
7904 */
7905 get: function () {
7906 return this.settingsPanelItemEvents.onActiveChanged.getEvent();
7907 },
7908 enumerable: true,
7909 configurable: true
7910 });
7911 return MenuItem;
7912}(container_1.Container));
7913exports.MenuItem = MenuItem;
7914
7915},{"../../components/container":17,"../../eventdispatcher":82,"../../timeout":89,"./menuitembutton":76,"./menulistselector":79}],76:[function(require,module,exports){
7916"use strict";
7917var __extends = (this && this.__extends) || (function () {
7918 var extendStatics = Object.setPrototypeOf ||
7919 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
7920 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7921 return function (d, b) {
7922 extendStatics(d, b);
7923 function __() { this.constructor = d; }
7924 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
7925 };
7926})();
7927Object.defineProperty(exports, "__esModule", { value: true });
7928var container_1 = require("../../components/container");
7929var dom_1 = require("../../dom");
7930var menuitemlabel_1 = require("./menuitemlabel");
7931var MenuItemButton = /** @class */ (function (_super) {
7932 __extends(MenuItemButton, _super);
7933 function MenuItemButton(config) {
7934 var _this = _super.call(this, config) || this;
7935 _this.label = new menuitemlabel_1.MenuItemLabel();
7936 _this.button = config.buttonController;
7937 _this.config = _this.mergeConfig(config, {
7938 components: [
7939 _this.button,
7940 _this.label,
7941 ],
7942 }, _this.config);
7943 return _this;
7944 }
7945 MenuItemButton.prototype.toDomElement = function () {
7946 var menuElement = new dom_1.DOM('div', {
7947 'id': this.config.id,
7948 'class': this.getCssClasses(),
7949 });
7950 var labelElement = this.label.getDomElement();
7951 var buttonElement = this.button.getDomElement();
7952 buttonElement.append(labelElement);
7953 menuElement.append(buttonElement);
7954 this.menuElement = menuElement;
7955 return menuElement;
7956 };
7957 MenuItemButton.prototype.setLabel = function (value) {
7958 this.label.setText(value);
7959 };
7960 return MenuItemButton;
7961}(container_1.Container));
7962exports.MenuItemButton = MenuItemButton;
7963
7964},{"../../components/container":17,"../../dom":68,"./menuitemlabel":77}],77:[function(require,module,exports){
7965"use strict";
7966var __extends = (this && this.__extends) || (function () {
7967 var extendStatics = Object.setPrototypeOf ||
7968 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
7969 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7970 return function (d, b) {
7971 extendStatics(d, b);
7972 function __() { this.constructor = d; }
7973 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
7974 };
7975})();
7976Object.defineProperty(exports, "__esModule", { value: true });
7977var label_1 = require("../../components/label");
7978var MenuItemLabel = /** @class */ (function (_super) {
7979 __extends(MenuItemLabel, _super);
7980 function MenuItemLabel(config) {
7981 if (config === void 0) { config = {}; }
7982 var _this = _super.call(this, config) || this;
7983 _this.config = _this.mergeConfig(config, {
7984 cssClass: 'label-info',
7985 }, _this.config);
7986 return _this;
7987 }
7988 MenuItemLabel.prototype.setLabel = function (value) {
7989 this.setText(value);
7990 };
7991 return MenuItemLabel;
7992}(label_1.Label));
7993exports.MenuItemLabel = MenuItemLabel;
7994
7995},{"../../components/label":24}],78:[function(require,module,exports){
7996"use strict";
7997var __extends = (this && this.__extends) || (function () {
7998 var extendStatics = Object.setPrototypeOf ||
7999 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
8000 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
8001 return function (d, b) {
8002 extendStatics(d, b);
8003 function __() { this.constructor = d; }
8004 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
8005 };
8006})();
8007Object.defineProperty(exports, "__esModule", { value: true });
8008var component_1 = require("../../components/component");
8009var dom_1 = require("../../dom");
8010var MenuLabel = /** @class */ (function (_super) {
8011 __extends(MenuLabel, _super);
8012 function MenuLabel(config) {
8013 var _this = _super.call(this, config) || this;
8014 _this.config = _this.mergeConfig(config, {
8015 cssClass: config.cssClass,
8016 }, _this.config);
8017 return _this;
8018 }
8019 MenuLabel.prototype.toDomElement = function () {
8020 var infoElement = new dom_1.DOM('div', {
8021 'id': this.config.id,
8022 'class': this.getCssClasses(),
8023 }).append(new dom_1.DOM('span', {
8024 'class': this.prefixCss('label'),
8025 }).html(this.config.text));
8026 return infoElement;
8027 };
8028 return MenuLabel;
8029}(component_1.Component));
8030exports.MenuLabel = MenuLabel;
8031
8032},{"../../components/component":16,"../../dom":68}],79:[function(require,module,exports){
8033"use strict";
8034var __extends = (this && this.__extends) || (function () {
8035 var extendStatics = Object.setPrototypeOf ||
8036 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
8037 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
8038 return function (d, b) {
8039 extendStatics(d, b);
8040 function __() { this.constructor = d; }
8041 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
8042 };
8043})();
8044Object.defineProperty(exports, "__esModule", { value: true });
8045var dstvlistselector_1 = require("../dstvlistselector");
8046var dom_1 = require("../../dom");
8047var MenuListSelector = /** @class */ (function (_super) {
8048 __extends(MenuListSelector, _super);
8049 function MenuListSelector(config) {
8050 if (config === void 0) { config = {}; }
8051 return _super.call(this, config) || this;
8052 }
8053 MenuListSelector.prototype.isActive = function () {
8054 return this.items.length > 1;
8055 };
8056 MenuListSelector.prototype.toDomElement = function () {
8057 var listElement = new dom_1.DOM('div', {
8058 'id': this.config.id,
8059 'class': this.getCssClasses(),
8060 });
8061 this.listElement = listElement;
8062 this.updateDomItems();
8063 return listElement;
8064 };
8065 MenuListSelector.prototype.updateDomItems = function (selectedValue) {
8066 var _this = this;
8067 if (selectedValue === void 0) { selectedValue = null; }
8068 // Delete all children
8069 this.listElement.empty();
8070 var selectedListItem = null;
8071 var selectItem = function (listItem) {
8072 listItem.addClass(_this.prefixCss(MenuListSelector.CLASS_SELECTED));
8073 };
8074 var deselectItem = function (listItem) {
8075 listItem.removeClass(_this.prefixCss(MenuListSelector.CLASS_SELECTED));
8076 };
8077 var _loop_1 = function (item) {
8078 var listItem = new dom_1.DOM('button', {
8079 'type': 'button',
8080 'value': item.key,
8081 'class': this_1.prefixCss('ui-menu-list-item'),
8082 }).append(new dom_1.DOM('span', {
8083 'class': this_1.prefixCss('label'),
8084 }).html(item.label));
8085 if (item.msg) {
8086 var infoItem = new dom_1.DOM('span', {
8087 'class': this_1.prefixCss('info'),
8088 }).html(item.msg);
8089 listItem.append(infoItem);
8090 }
8091 if (!selectedListItem) {
8092 if (selectedValue == null) { // If there is no pre-selected value, select the first one
8093 selectedListItem = listItem;
8094 }
8095 else if (String(selectedValue) === item.key) { // convert selectedValue to string to catch 'null'/null case
8096 selectedListItem = listItem;
8097 }
8098 }
8099 // Handle list item selections
8100 listItem.on('click', function () {
8101 // Deselect the previous item (if there was a selected item)
8102 if (selectedListItem) {
8103 deselectItem(selectedListItem);
8104 }
8105 // Select the clicked item
8106 selectedListItem = listItem;
8107 selectItem(listItem);
8108 // Fire the event
8109 _this.onItemSelectedEvent(item.key, false);
8110 });
8111 // Select default item
8112 if (selectedListItem) {
8113 selectItem(selectedListItem);
8114 }
8115 this_1.listElement.append(listItem);
8116 };
8117 var this_1 = this;
8118 for (var _i = 0, _a = this.items; _i < _a.length; _i++) {
8119 var item = _a[_i];
8120 _loop_1(item);
8121 }
8122 };
8123 MenuListSelector.prototype.onItemAddedEvent = function (value) {
8124 _super.prototype.onItemAddedEvent.call(this, value);
8125 this.updateDomItems(this.selectedItem);
8126 };
8127 MenuListSelector.prototype.onItemRemovedEvent = function (value) {
8128 _super.prototype.onItemRemovedEvent.call(this, value);
8129 this.updateDomItems(this.selectedItem);
8130 };
8131 MenuListSelector.prototype.onItemSelectedEvent = function (value, updateDomItems) {
8132 if (updateDomItems === void 0) { updateDomItems = true; }
8133 _super.prototype.onItemSelectedEvent.call(this, value);
8134 if (updateDomItems) {
8135 this.updateDomItems(value);
8136 }
8137 };
8138 MenuListSelector.CLASS_SELECTED = 'selected';
8139 return MenuListSelector;
8140}(dstvlistselector_1.DStvListSelector));
8141exports.MenuListSelector = MenuListSelector;
8142
8143},{"../../dom":68,"../dstvlistselector":73}],80:[function(require,module,exports){
8144"use strict";
8145var __extends = (this && this.__extends) || (function () {
8146 var extendStatics = Object.setPrototypeOf ||
8147 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
8148 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
8149 return function (d, b) {
8150 extendStatics(d, b);
8151 function __() { this.constructor = d; }
8152 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
8153 };
8154})();
8155Object.defineProperty(exports, "__esModule", { value: true });
8156var togglebutton_1 = require("../../components/togglebutton");
8157/**
8158 * A button that toggles visibility of a settings panel.
8159 */
8160var MenuToggleButton = /** @class */ (function (_super) {
8161 __extends(MenuToggleButton, _super);
8162 function MenuToggleButton(config) {
8163 var _this = _super.call(this, config) || this;
8164 if (!config.mainMenu) {
8165 throw new Error('Required Menu is missing');
8166 }
8167 _this.config = _this.mergeConfig(config, {
8168 cssClass: 'ui-settingstogglebutton',
8169 text: 'Settings',
8170 mainMenu: null,
8171 autoHideWhenNoActiveSettings: true,
8172 }, _this.config);
8173 return _this;
8174 }
8175 MenuToggleButton.prototype.configure = function (player, uimanager) {
8176 var _this = this;
8177 _super.prototype.configure.call(this, player, uimanager);
8178 var config = this.getConfig(); // TODO fix generics type inference
8179 var menu = config.mainMenu;
8180 this.onClick.subscribe(function () {
8181 menu.toggleHidden();
8182 });
8183 menu.onShow.subscribe(function () {
8184 // Set toggle status to on when the settings panel shows
8185 _this.on();
8186 });
8187 menu.onHide.subscribe(function () {
8188 // Set toggle status to off when the settings panel hides
8189 _this.off();
8190 });
8191 // Handle automatic hiding of the button if there are no settings for the user to interact with
8192 if (config.autoHideWhenNoActiveSettings) {
8193 // Setup handler to show/hide button when the settings change
8194 var settingsPanelItemsChangedHandler = function () {
8195 if (menu.hasActiveSettings()) {
8196 if (_this.isHidden()) {
8197 _this.show();
8198 }
8199 }
8200 else {
8201 if (_this.isShown()) {
8202 _this.hide();
8203 }
8204 }
8205 };
8206 // Wire the handler to the event
8207 menu.onSettingsStateChanged.subscribe(settingsPanelItemsChangedHandler);
8208 // Call handler for first init at startup
8209 settingsPanelItemsChangedHandler();
8210 }
8211 };
8212 return MenuToggleButton;
8213}(togglebutton_1.ToggleButton));
8214exports.MenuToggleButton = MenuToggleButton;
8215
8216},{"../../components/togglebutton":59}],81:[function(require,module,exports){
8217"use strict";
8218Object.defineProperty(exports, "__esModule", { value: true });
8219var uimanager_1 = require("../uimanager");
8220var dstvplaybacktoggleoverlay_1 = require("./dstvplaybacktoggleoverlay");
8221var menutogglebutton_1 = require("./menu/menutogglebutton");
8222var menucapping_1 = require("./capping/menucapping");
8223var uicontainer_1 = require("../components/uicontainer");
8224var component_1 = require("../components/component");
8225var container_1 = require("../components/container");
8226var playbacktogglebutton_1 = require("../components/playbacktogglebutton");
8227var fullscreentogglebutton_1 = require("../components/fullscreentogglebutton");
8228var vrtogglebutton_1 = require("../components/vrtogglebutton");
8229var volumetogglebutton_1 = require("../components/volumetogglebutton");
8230var seekbar_1 = require("../components/seekbar");
8231var playbacktimelabel_1 = require("../components/playbacktimelabel");
8232var controlbar_1 = require("../components/controlbar");
8233var seekbarlabel_1 = require("../components/seekbarlabel");
8234var volumeslider_1 = require("../components/volumeslider");
8235var subtitleoverlay_1 = require("../components/subtitleoverlay");
8236var casttogglebutton_1 = require("../components/casttogglebutton");
8237var caststatusoverlay_1 = require("../components/caststatusoverlay");
8238var errormessageoverlay_1 = require("../components/errormessageoverlay");
8239var pictureinpicturetogglebutton_1 = require("../components/pictureinpicturetogglebutton");
8240var titlebar_1 = require("../components/titlebar");
8241var recommendationoverlay_1 = require("../components/recommendationoverlay");
8242var bufferingoverlay_1 = require("../components/bufferingoverlay");
8243var metadatalabel_1 = require("../components/metadatalabel");
8244var airplaytogglebutton_1 = require("../components/airplaytogglebutton");
8245var Factory;
8246(function (Factory) {
8247 function buildDstvNowUI(player, config) {
8248 if (config === void 0) { config = {}; }
8249 // show smallScreen UI only on mobile/handheld devices
8250 return new uimanager_1.UIManager(player, [{
8251 ui: dstvNowUI(),
8252 }], config);
8253 }
8254 Factory.buildDstvNowUI = buildDstvNowUI;
8255 function dstvNowUI() {
8256 var cappingMenu = new menucapping_1.MenuCapping({
8257 hidden: true,
8258 hideDelay: 6000,
8259 });
8260 var controlBar = new controlbar_1.ControlBar({
8261 components: [
8262 cappingMenu,
8263 new container_1.Container({
8264 components: [
8265 new seekbar_1.SeekBar({ label: new seekbarlabel_1.SeekBarLabel() }),
8266 ],
8267 cssClasses: ['controlbar-top'],
8268 }),
8269 new container_1.Container({
8270 components: [
8271 new playbacktogglebutton_1.PlaybackToggleButton(),
8272 new volumetogglebutton_1.VolumeToggleButton(),
8273 new volumeslider_1.VolumeSlider(),
8274 new component_1.Component({ cssClass: 'spacer' }),
8275 new playbacktimelabel_1.PlaybackTimeLabel(),
8276 new airplaytogglebutton_1.AirPlayToggleButton(),
8277 new casttogglebutton_1.CastToggleButton(),
8278 new vrtogglebutton_1.VRToggleButton(),
8279 new pictureinpicturetogglebutton_1.PictureInPictureToggleButton(),
8280 new menutogglebutton_1.MenuToggleButton({ mainMenu: cappingMenu }),
8281 new fullscreentogglebutton_1.FullscreenToggleButton(),
8282 ],
8283 cssClasses: ['controlbar-bottom'],
8284 }),
8285 ],
8286 hidden: false,
8287 });
8288 return new uicontainer_1.UIContainer({
8289 components: [
8290 new subtitleoverlay_1.SubtitleOverlay(),
8291 new bufferingoverlay_1.BufferingOverlay(),
8292 new dstvplaybacktoggleoverlay_1.DStvPlaybackToggleOverlay(),
8293 new caststatusoverlay_1.CastStatusOverlay(),
8294 controlBar,
8295 new titlebar_1.TitleBar({
8296 components: [
8297 new metadatalabel_1.MetadataLabel({ content: metadatalabel_1.MetadataLabelContent.Title }),
8298 ],
8299 }),
8300 new recommendationoverlay_1.RecommendationOverlay(),
8301 new errormessageoverlay_1.ErrorMessageOverlay(),
8302 ], cssClasses: ['ui-player-dstv'],
8303 });
8304 }
8305})(Factory = exports.Factory || (exports.Factory = {}));
8306
8307},{"../components/airplaytogglebutton":6,"../components/bufferingoverlay":9,"../components/caststatusoverlay":11,"../components/casttogglebutton":12,"../components/component":16,"../components/container":17,"../components/controlbar":18,"../components/errormessageoverlay":19,"../components/fullscreentogglebutton":20,"../components/metadatalabel":26,"../components/pictureinpicturetogglebutton":27,"../components/playbacktimelabel":29,"../components/playbacktogglebutton":30,"../components/recommendationoverlay":32,"../components/seekbar":33,"../components/seekbarlabel":34,"../components/subtitleoverlay":39,"../components/titlebar":58,"../components/uicontainer":61,"../components/volumeslider":64,"../components/volumetogglebutton":65,"../components/vrtogglebutton":66,"../uimanager":90,"./capping/menucapping":69,"./dstvplaybacktoggleoverlay":74,"./menu/menutogglebutton":80}],82:[function(require,module,exports){
8308"use strict";
8309var __extends = (this && this.__extends) || (function () {
8310 var extendStatics = Object.setPrototypeOf ||
8311 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
8312 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
8313 return function (d, b) {
8314 extendStatics(d, b);
8315 function __() { this.constructor = d; }
8316 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
8317 };
8318})();
8319Object.defineProperty(exports, "__esModule", { value: true });
8320var arrayutils_1 = require("./arrayutils");
8321/**
8322 * Event dispatcher to subscribe and trigger events. Each event should have its own dispatcher.
8323 */
8324var EventDispatcher = /** @class */ (function () {
8325 function EventDispatcher() {
8326 this.listeners = [];
8327 }
8328 /**
8329 * {@inheritDoc}
8330 */
8331 EventDispatcher.prototype.subscribe = function (listener) {
8332 this.listeners.push(new EventListenerWrapper(listener));
8333 };
8334 /**
8335 * {@inheritDoc}
8336 */
8337 EventDispatcher.prototype.subscribeOnce = function (listener) {
8338 this.listeners.push(new EventListenerWrapper(listener, true));
8339 };
8340 /**
8341 * {@inheritDoc}
8342 */
8343 EventDispatcher.prototype.subscribeRateLimited = function (listener, rateMs) {
8344 this.listeners.push(new RateLimitedEventListenerWrapper(listener, rateMs));
8345 };
8346 /**
8347 * {@inheritDoc}
8348 */
8349 EventDispatcher.prototype.unsubscribe = function (listener) {
8350 // Iterate through listeners, compare with parameter, and remove if found
8351 // NOTE: In case we ever remove all matching listeners instead of just the first, we need to reverse-iterate here
8352 for (var i = 0; i < this.listeners.length; i++) {
8353 var subscribedListener = this.listeners[i];
8354 if (subscribedListener.listener === listener) {
8355 arrayutils_1.ArrayUtils.remove(this.listeners, subscribedListener);
8356 return true;
8357 }
8358 }
8359 return false;
8360 };
8361 /**
8362 * Removes all listeners from this dispatcher.
8363 */
8364 EventDispatcher.prototype.unsubscribeAll = function () {
8365 this.listeners = [];
8366 };
8367 /**
8368 * Dispatches an event to all subscribed listeners.
8369 * @param sender the source of the event
8370 * @param args the arguments for the event
8371 */
8372 EventDispatcher.prototype.dispatch = function (sender, args) {
8373 if (args === void 0) { args = null; }
8374 var listenersToRemove = [];
8375 // Call every listener
8376 // We iterate over a copy of the array of listeners to avoid the case where events are not fired on listeners when
8377 // listeners are unsubscribed from within the event handlers during a dispatch (because the indices change and
8378 // listeners are shifted within the array).
8379 // This means that listener x+1 will still be called if unsubscribed from within the handler of listener x, as well
8380 // as listener y+1 will not be called when subscribed from within the handler of listener y.
8381 // Array.slice(0) is the fastest array copy method according to: https://stackoverflow.com/a/21514254/370252
8382 var listeners = this.listeners.slice(0);
8383 for (var _i = 0, listeners_1 = listeners; _i < listeners_1.length; _i++) {
8384 var listener = listeners_1[_i];
8385 listener.fire(sender, args);
8386 if (listener.isOnce()) {
8387 listenersToRemove.push(listener);
8388 }
8389 }
8390 // Remove one-time listener
8391 for (var _a = 0, listenersToRemove_1 = listenersToRemove; _a < listenersToRemove_1.length; _a++) {
8392 var listenerToRemove = listenersToRemove_1[_a];
8393 arrayutils_1.ArrayUtils.remove(this.listeners, listenerToRemove);
8394 }
8395 };
8396 /**
8397 * Returns the event that this dispatcher manages and on which listeners can subscribe and unsubscribe event handlers.
8398 * @returns {Event}
8399 */
8400 EventDispatcher.prototype.getEvent = function () {
8401 // For now, just cast the event dispatcher to the event interface. At some point in the future when the
8402 // codebase grows, it might make sense to split the dispatcher into separate dispatcher and event classes.
8403 return this;
8404 };
8405 return EventDispatcher;
8406}());
8407exports.EventDispatcher = EventDispatcher;
8408/**
8409 * A basic event listener wrapper to manage listeners within the {@link EventDispatcher}. This is a 'private' class
8410 * for internal dispatcher use and it is therefore not exported.
8411 */
8412var EventListenerWrapper = /** @class */ (function () {
8413 function EventListenerWrapper(listener, once) {
8414 if (once === void 0) { once = false; }
8415 this.eventListener = listener;
8416 this.once = once;
8417 }
8418 Object.defineProperty(EventListenerWrapper.prototype, "listener", {
8419 /**
8420 * Returns the wrapped event listener.
8421 * @returns {EventListener<Sender, Args>}
8422 */
8423 get: function () {
8424 return this.eventListener;
8425 },
8426 enumerable: true,
8427 configurable: true
8428 });
8429 /**
8430 * Fires the wrapped event listener with the given arguments.
8431 * @param sender
8432 * @param args
8433 */
8434 EventListenerWrapper.prototype.fire = function (sender, args) {
8435 this.eventListener(sender, args);
8436 };
8437 /**
8438 * Checks if this listener is scheduled to be called only once.
8439 * @returns {boolean} once if true
8440 */
8441 EventListenerWrapper.prototype.isOnce = function () {
8442 return this.once;
8443 };
8444 return EventListenerWrapper;
8445}());
8446/**
8447 * Extends the basic {@link EventListenerWrapper} with rate-limiting functionality.
8448 */
8449var RateLimitedEventListenerWrapper = /** @class */ (function (_super) {
8450 __extends(RateLimitedEventListenerWrapper, _super);
8451 function RateLimitedEventListenerWrapper(listener, rateMs) {
8452 var _this = _super.call(this, listener) || this;
8453 _this.rateMs = rateMs;
8454 _this.lastFireTime = 0;
8455 // Wrap the event listener with an event listener that does the rate-limiting
8456 _this.rateLimitingEventListener = function (sender, args) {
8457 if (Date.now() - _this.lastFireTime > _this.rateMs) {
8458 // Only if enough time since the previous call has passed, call the
8459 // actual event listener and record the current time
8460 _this.fireSuper(sender, args);
8461 _this.lastFireTime = Date.now();
8462 }
8463 };
8464 return _this;
8465 }
8466 RateLimitedEventListenerWrapper.prototype.fireSuper = function (sender, args) {
8467 // Fire the actual external event listener
8468 _super.prototype.fire.call(this, sender, args);
8469 };
8470 RateLimitedEventListenerWrapper.prototype.fire = function (sender, args) {
8471 // Fire the internal rate-limiting listener instead of the external event listener
8472 this.rateLimitingEventListener(sender, args);
8473 };
8474 return RateLimitedEventListenerWrapper;
8475}(EventListenerWrapper));
8476
8477},{"./arrayutils":1}],83:[function(require,module,exports){
8478"use strict";
8479Object.defineProperty(exports, "__esModule", { value: true });
8480var Guid;
8481(function (Guid) {
8482 var guid = 1;
8483 function next() {
8484 return guid++;
8485 }
8486 Guid.next = next;
8487})(Guid = exports.Guid || (exports.Guid = {}));
8488
8489},{}],84:[function(require,module,exports){
8490"use strict";
8491Object.defineProperty(exports, "__esModule", { value: true });
8492var dom_1 = require("./dom");
8493/**
8494 * Tracks the loading state of images.
8495 */
8496var ImageLoader = /** @class */ (function () {
8497 function ImageLoader() {
8498 this.state = {};
8499 }
8500 /**
8501 * Loads an image and call the callback once the image is loaded. If the image is already loaded, the callback
8502 * is called immediately, else it is called once loading has finished. Calling this method multiple times for the
8503 * same image while it is loading calls only let callback passed into the last call.
8504 * @param url The url to the image to load
8505 * @param loadedCallback The callback that is called when the image is loaded
8506 */
8507 ImageLoader.prototype.load = function (url, loadedCallback) {
8508 var _this = this;
8509 if (!this.state[url]) {
8510 // When the image was never attempted to be loaded before, we create a state and store it in the state map
8511 // for later use when the same image is requested to be loaded again.
8512 var state_1 = {
8513 url: url,
8514 image: new dom_1.DOM('img', {}),
8515 loadedCallback: loadedCallback,
8516 loaded: false,
8517 width: 0,
8518 height: 0,
8519 };
8520 this.state[url] = state_1;
8521 // Listen to the load event, update the state and call the callback once the image is loaded
8522 state_1.image.on('load', function (e) {
8523 state_1.loaded = true;
8524 state_1.width = state_1.image.get(0).width;
8525 state_1.height = state_1.image.get(0).height;
8526 _this.callLoadedCallback(state_1);
8527 });
8528 // Set the image URL to start the loading
8529 state_1.image.attr('src', state_1.url);
8530 }
8531 else {
8532 // We have a state for the requested image, so it is either already loaded or currently loading
8533 var state = this.state[url];
8534 // We overwrite the callback to make sure that only the callback of the latest call gets executed.
8535 // Earlier callbacks become invalid once a new load call arrives, and they are not called as long as the image
8536 // is not loaded.
8537 state.loadedCallback = loadedCallback;
8538 // When the image is already loaded, we directly execute the callback instead of waiting for the load event
8539 if (state.loaded) {
8540 this.callLoadedCallback(state);
8541 }
8542 }
8543 };
8544 ImageLoader.prototype.callLoadedCallback = function (state) {
8545 state.loadedCallback(state.url, state.width, state.height);
8546 };
8547 return ImageLoader;
8548}());
8549exports.ImageLoader = ImageLoader;
8550
8551},{"./dom":68}],85:[function(require,module,exports){
8552"use strict";
8553Object.defineProperty(exports, "__esModule", { value: true });
8554/// <reference path='player.d.ts' />
8555var DStv = require("./dstv/uimanager");
8556var uimanager_1 = require("./uimanager");
8557var button_1 = require("./components/button");
8558var controlbar_1 = require("./components/controlbar");
8559var fullscreentogglebutton_1 = require("./components/fullscreentogglebutton");
8560var hugeplaybacktogglebutton_1 = require("./components/hugeplaybacktogglebutton");
8561var playbacktimelabel_1 = require("./components/playbacktimelabel");
8562var playbacktogglebutton_1 = require("./components/playbacktogglebutton");
8563var seekbar_1 = require("./components/seekbar");
8564var selectbox_1 = require("./components/selectbox");
8565var itemselectionlist_1 = require("./components/itemselectionlist");
8566var settingspanel_1 = require("./components/settingspanel");
8567var settingstogglebutton_1 = require("./components/settingstogglebutton");
8568var togglebutton_1 = require("./components/togglebutton");
8569var videoqualityselectbox_1 = require("./components/videoqualityselectbox");
8570var volumetogglebutton_1 = require("./components/volumetogglebutton");
8571var vrtogglebutton_1 = require("./components/vrtogglebutton");
8572var watermark_1 = require("./components/watermark");
8573var uicontainer_1 = require("./components/uicontainer");
8574var container_1 = require("./components/container");
8575var label_1 = require("./components/label");
8576var audioqualityselectbox_1 = require("./components/audioqualityselectbox");
8577var audiotrackselectbox_1 = require("./components/audiotrackselectbox");
8578var caststatusoverlay_1 = require("./components/caststatusoverlay");
8579var casttogglebutton_1 = require("./components/casttogglebutton");
8580var component_1 = require("./components/component");
8581var errormessageoverlay_1 = require("./components/errormessageoverlay");
8582var recommendationoverlay_1 = require("./components/recommendationoverlay");
8583var seekbarlabel_1 = require("./components/seekbarlabel");
8584var subtitleoverlay_1 = require("./components/subtitleoverlay");
8585var subtitleselectbox_1 = require("./components/subtitleselectbox");
8586var titlebar_1 = require("./components/titlebar");
8587var volumecontrolbutton_1 = require("./components/volumecontrolbutton");
8588var clickoverlay_1 = require("./components/clickoverlay");
8589var adskipbutton_1 = require("./components/adskipbutton");
8590var admessagelabel_1 = require("./components/admessagelabel");
8591var adclickoverlay_1 = require("./components/adclickoverlay");
8592var playbackspeedselectbox_1 = require("./components/playbackspeedselectbox");
8593var hugereplaybutton_1 = require("./components/hugereplaybutton");
8594var bufferingoverlay_1 = require("./components/bufferingoverlay");
8595var castuicontainer_1 = require("./components/castuicontainer");
8596var playbacktoggleoverlay_1 = require("./components/playbacktoggleoverlay");
8597var closebutton_1 = require("./components/closebutton");
8598var metadatalabel_1 = require("./components/metadatalabel");
8599var airplaytogglebutton_1 = require("./components/airplaytogglebutton");
8600var volumeslider_1 = require("./components/volumeslider");
8601var pictureinpicturetogglebutton_1 = require("./components/pictureinpicturetogglebutton");
8602var spacer_1 = require("./components/spacer");
8603var backgroundcolorselectbox_1 = require("./components/subtitlesettings/backgroundcolorselectbox");
8604var backgroundopacityselectbox_1 = require("./components/subtitlesettings/backgroundopacityselectbox");
8605var characteredgeselectbox_1 = require("./components/subtitlesettings/characteredgeselectbox");
8606var fontcolorselectbox_1 = require("./components/subtitlesettings/fontcolorselectbox");
8607var fontfamilyselectbox_1 = require("./components/subtitlesettings/fontfamilyselectbox");
8608var fontopacityselectbox_1 = require("./components/subtitlesettings/fontopacityselectbox");
8609var fontsizeselectbox_1 = require("./components/subtitlesettings/fontsizeselectbox");
8610var subtitlesettingsbutton_1 = require("./components/subtitlesettings/subtitlesettingsbutton");
8611var subtitlesettingsclosebutton_1 = require("./components/subtitlesettings/subtitlesettingsclosebutton");
8612var subtitlesettingselectbox_1 = require("./components/subtitlesettings/subtitlesettingselectbox");
8613var subtitlesettingslabel_1 = require("./components/subtitlesettings/subtitlesettingslabel");
8614var subtitlesettingsopenbutton_1 = require("./components/subtitlesettings/subtitlesettingsopenbutton");
8615var subtitlesettingspanel_1 = require("./components/subtitlesettings/subtitlesettingspanel");
8616var windowcolorselectbox_1 = require("./components/subtitlesettings/windowcolorselectbox");
8617var windowopacityselectbox_1 = require("./components/subtitlesettings/windowopacityselectbox");
8618var arrayutils_1 = require("./arrayutils");
8619var stringutils_1 = require("./stringutils");
8620var playerutils_1 = require("./playerutils");
8621var uiutils_1 = require("./uiutils");
8622var browserutils_1 = require("./browserutils");
8623var storageutils_1 = require("./storageutils");
8624var subtitlesettingsresetbutton_1 = require("./components/subtitlesettings/subtitlesettingsresetbutton");
8625// Object.assign polyfill for ES5/IE9
8626// https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
8627if (typeof Object.assign !== 'function') {
8628 Object.assign = function (target) {
8629 'use strict';
8630 if (target == null) {
8631 throw new TypeError('Cannot convert undefined or null to object');
8632 }
8633 target = Object(target);
8634 for (var index = 1; index < arguments.length; index++) {
8635 var source = arguments[index];
8636 if (source != null) {
8637 for (var key in source) {
8638 if (Object.prototype.hasOwnProperty.call(source, key)) {
8639 target[key] = source[key];
8640 }
8641 }
8642 }
8643 }
8644 return target;
8645 };
8646}
8647var playerui = {
8648 version: '2.16.0',
8649 // Management
8650 DStv: DStv,
8651 UIManager: uimanager_1.UIManager,
8652 UIInstanceManager: uimanager_1.UIInstanceManager,
8653 // Utils
8654 ArrayUtils: arrayutils_1.ArrayUtils,
8655 StringUtils: stringutils_1.StringUtils,
8656 PlayerUtils: playerutils_1.PlayerUtils,
8657 UIUtils: uiutils_1.UIUtils,
8658 BrowserUtils: browserutils_1.BrowserUtils,
8659 StorageUtils: storageutils_1.StorageUtils,
8660 // Components
8661 AdClickOverlay: adclickoverlay_1.AdClickOverlay,
8662 AdMessageLabel: admessagelabel_1.AdMessageLabel,
8663 AdSkipButton: adskipbutton_1.AdSkipButton,
8664 AirPlayToggleButton: airplaytogglebutton_1.AirPlayToggleButton,
8665 AudioQualitySelectBox: audioqualityselectbox_1.AudioQualitySelectBox,
8666 AudioTrackSelectBox: audiotrackselectbox_1.AudioTrackSelectBox,
8667 BufferingOverlay: bufferingoverlay_1.BufferingOverlay,
8668 Button: button_1.Button,
8669 CastStatusOverlay: caststatusoverlay_1.CastStatusOverlay,
8670 CastToggleButton: casttogglebutton_1.CastToggleButton,
8671 CastUIContainer: castuicontainer_1.CastUIContainer,
8672 ClickOverlay: clickoverlay_1.ClickOverlay,
8673 CloseButton: closebutton_1.CloseButton,
8674 Component: component_1.Component,
8675 Container: container_1.Container,
8676 ControlBar: controlbar_1.ControlBar,
8677 ErrorMessageOverlay: errormessageoverlay_1.ErrorMessageOverlay,
8678 FullscreenToggleButton: fullscreentogglebutton_1.FullscreenToggleButton,
8679 HugePlaybackToggleButton: hugeplaybacktogglebutton_1.HugePlaybackToggleButton,
8680 HugeReplayButton: hugereplaybutton_1.HugeReplayButton,
8681 Label: label_1.Label,
8682 MetadataLabel: metadatalabel_1.MetadataLabel,
8683 MetadataLabelContent: metadatalabel_1.MetadataLabelContent,
8684 PictureInPictureToggleButton: pictureinpicturetogglebutton_1.PictureInPictureToggleButton,
8685 PlaybackSpeedSelectBox: playbackspeedselectbox_1.PlaybackSpeedSelectBox,
8686 PlaybackTimeLabel: playbacktimelabel_1.PlaybackTimeLabel,
8687 PlaybackTimeLabelMode: playbacktimelabel_1.PlaybackTimeLabelMode,
8688 PlaybackToggleButton: playbacktogglebutton_1.PlaybackToggleButton,
8689 PlaybackToggleOverlay: playbacktoggleoverlay_1.PlaybackToggleOverlay,
8690 RecommendationOverlay: recommendationoverlay_1.RecommendationOverlay,
8691 SeekBar: seekbar_1.SeekBar,
8692 SeekBarLabel: seekbarlabel_1.SeekBarLabel,
8693 SelectBox: selectbox_1.SelectBox,
8694 ItemSelectionList: itemselectionlist_1.ItemSelectionList,
8695 SettingsPanel: settingspanel_1.SettingsPanel,
8696 SettingsPanelItem: settingspanel_1.SettingsPanelItem,
8697 SettingsToggleButton: settingstogglebutton_1.SettingsToggleButton,
8698 Spacer: spacer_1.Spacer,
8699 SubtitleOverlay: subtitleoverlay_1.SubtitleOverlay,
8700 SubtitleSelectBox: subtitleselectbox_1.SubtitleSelectBox,
8701 TitleBar: titlebar_1.TitleBar,
8702 ToggleButton: togglebutton_1.ToggleButton,
8703 UIContainer: uicontainer_1.UIContainer,
8704 VideoQualitySelectBox: videoqualityselectbox_1.VideoQualitySelectBox,
8705 VolumeControlButton: volumecontrolbutton_1.VolumeControlButton,
8706 VolumeSlider: volumeslider_1.VolumeSlider,
8707 VolumeToggleButton: volumetogglebutton_1.VolumeToggleButton,
8708 VRToggleButton: vrtogglebutton_1.VRToggleButton,
8709 Watermark: watermark_1.Watermark,
8710 // Subtitle related components
8711 subtitlesettings: {
8712 BackgroundColorSelectBox: backgroundcolorselectbox_1.BackgroundColorSelectBox,
8713 BackgroundOpacitySelectBox: backgroundopacityselectbox_1.BackgroundOpacitySelectBox,
8714 CharacterEdgeSelectBox: characteredgeselectbox_1.CharacterEdgeSelectBox,
8715 FontColorSelectBox: fontcolorselectbox_1.FontColorSelectBox,
8716 FontFamilySelectBox: fontfamilyselectbox_1.FontFamilySelectBox,
8717 FontOpacitySelectBox: fontopacityselectbox_1.FontOpacitySelectBox,
8718 FontSizeSelectBox: fontsizeselectbox_1.FontSizeSelectBox,
8719 SubtitleSettingsButton: subtitlesettingsbutton_1.SubtitleSettingsButton,
8720 SubtitleSettingsCloseButton: subtitlesettingsclosebutton_1.SubtitleSettingsCloseButton,
8721 SubtitleSettingSelectBox: subtitlesettingselectbox_1.SubtitleSettingSelectBox,
8722 SubtitleSettingsLabel: subtitlesettingslabel_1.SubtitleSettingsLabel,
8723 SubtitleSettingsOpenButton: subtitlesettingsopenbutton_1.SubtitleSettingsOpenButton,
8724 SubtitleSettingsPanel: subtitlesettingspanel_1.SubtitleSettingsPanel,
8725 WindowColorSelectBox: windowcolorselectbox_1.WindowColorSelectBox,
8726 WindowOpacitySelectBox: windowopacityselectbox_1.WindowOpacitySelectBox,
8727 SubtitleSettingsResetButton: subtitlesettingsresetbutton_1.SubtitleSettingsResetButton,
8728 },
8729};
8730module.exports = playerui;
8731
8732},{"./arrayutils":1,"./browserutils":2,"./components/adclickoverlay":3,"./components/admessagelabel":4,"./components/adskipbutton":5,"./components/airplaytogglebutton":6,"./components/audioqualityselectbox":7,"./components/audiotrackselectbox":8,"./components/bufferingoverlay":9,"./components/button":10,"./components/caststatusoverlay":11,"./components/casttogglebutton":12,"./components/castuicontainer":13,"./components/clickoverlay":14,"./components/closebutton":15,"./components/component":16,"./components/container":17,"./components/controlbar":18,"./components/errormessageoverlay":19,"./components/fullscreentogglebutton":20,"./components/hugeplaybacktogglebutton":21,"./components/hugereplaybutton":22,"./components/itemselectionlist":23,"./components/label":24,"./components/metadatalabel":26,"./components/pictureinpicturetogglebutton":27,"./components/playbackspeedselectbox":28,"./components/playbacktimelabel":29,"./components/playbacktogglebutton":30,"./components/playbacktoggleoverlay":31,"./components/recommendationoverlay":32,"./components/seekbar":33,"./components/seekbarlabel":34,"./components/selectbox":35,"./components/settingspanel":36,"./components/settingstogglebutton":37,"./components/spacer":38,"./components/subtitleoverlay":39,"./components/subtitleselectbox":40,"./components/subtitlesettings/backgroundcolorselectbox":41,"./components/subtitlesettings/backgroundopacityselectbox":42,"./components/subtitlesettings/characteredgeselectbox":43,"./components/subtitlesettings/fontcolorselectbox":44,"./components/subtitlesettings/fontfamilyselectbox":45,"./components/subtitlesettings/fontopacityselectbox":46,"./components/subtitlesettings/fontsizeselectbox":47,"./components/subtitlesettings/subtitlesettingsbutton":48,"./components/subtitlesettings/subtitlesettingsclosebutton":49,"./components/subtitlesettings/subtitlesettingselectbox":50,"./components/subtitlesettings/subtitlesettingslabel":51,"./components/subtitlesettings/subtitlesettingsopenbutton":53,"./components/subtitlesettings/subtitlesettingspanel":54,"./components/subtitlesettings/subtitlesettingsresetbutton":55,"./components/subtitlesettings/windowcolorselectbox":56,"./components/subtitlesettings/windowopacityselectbox":57,"./components/titlebar":58,"./components/togglebutton":59,"./components/uicontainer":61,"./components/videoqualityselectbox":62,"./components/volumecontrolbutton":63,"./components/volumeslider":64,"./components/volumetogglebutton":65,"./components/vrtogglebutton":66,"./components/watermark":67,"./dstv/uimanager":81,"./playerutils":86,"./storageutils":87,"./stringutils":88,"./uimanager":90,"./uiutils":91}],86:[function(require,module,exports){
8733"use strict";
8734Object.defineProperty(exports, "__esModule", { value: true });
8735var eventdispatcher_1 = require("./eventdispatcher");
8736var browserutils_1 = require("./browserutils");
8737var PlayerUtils;
8738(function (PlayerUtils) {
8739 var PlayerState;
8740 (function (PlayerState) {
8741 PlayerState[PlayerState["IDLE"] = 0] = "IDLE";
8742 PlayerState[PlayerState["PREPARED"] = 1] = "PREPARED";
8743 PlayerState[PlayerState["PLAYING"] = 2] = "PLAYING";
8744 PlayerState[PlayerState["PAUSED"] = 3] = "PAUSED";
8745 PlayerState[PlayerState["FINISHED"] = 4] = "FINISHED";
8746 })(PlayerState = PlayerUtils.PlayerState || (PlayerUtils.PlayerState = {}));
8747 function isTimeShiftAvailable(player) {
8748 return player.isLive() && player.getMaxTimeShift() !== 0;
8749 }
8750 PlayerUtils.isTimeShiftAvailable = isTimeShiftAvailable;
8751 function getState(player) {
8752 if (player.hasEnded()) {
8753 return PlayerState.FINISHED;
8754 }
8755 else if (player.isPlaying()) {
8756 return PlayerState.PLAYING;
8757 }
8758 else if (player.isPaused()) {
8759 return PlayerState.PAUSED;
8760 }
8761 else if (player.isReady()) {
8762 return PlayerState.PREPARED;
8763 }
8764 else {
8765 return PlayerState.IDLE;
8766 }
8767 }
8768 PlayerUtils.getState = getState;
8769 var TimeShiftAvailabilityDetector = /** @class */ (function () {
8770 function TimeShiftAvailabilityDetector(player) {
8771 var _this = this;
8772 this.timeShiftAvailabilityChangedEvent = new eventdispatcher_1.EventDispatcher();
8773 this.player = player;
8774 this.timeShiftAvailable = undefined;
8775 var timeShiftDetector = function () {
8776 _this.detect();
8777 };
8778 // Try to detect timeshift availability in ON_READY, which works for DASH streams
8779 player.addEventHandler(player.EVENT.ON_READY, timeShiftDetector);
8780 // With HLS/NativePlayer streams, getMaxTimeShift can be 0 before the buffer fills, so we need to additionally
8781 // check timeshift availability in ON_TIME_CHANGED
8782 player.addEventHandler(player.EVENT.ON_TIME_CHANGED, timeShiftDetector);
8783 }
8784 TimeShiftAvailabilityDetector.prototype.detect = function () {
8785 if (this.player.isLive()) {
8786 var timeShiftAvailableNow = PlayerUtils.isTimeShiftAvailable(this.player);
8787 // When the availability changes, we fire the event
8788 if (timeShiftAvailableNow !== this.timeShiftAvailable) {
8789 this.timeShiftAvailabilityChangedEvent.dispatch(this.player, { timeShiftAvailable: timeShiftAvailableNow });
8790 this.timeShiftAvailable = timeShiftAvailableNow;
8791 }
8792 }
8793 };
8794 Object.defineProperty(TimeShiftAvailabilityDetector.prototype, "onTimeShiftAvailabilityChanged", {
8795 get: function () {
8796 return this.timeShiftAvailabilityChangedEvent.getEvent();
8797 },
8798 enumerable: true,
8799 configurable: true
8800 });
8801 return TimeShiftAvailabilityDetector;
8802 }());
8803 PlayerUtils.TimeShiftAvailabilityDetector = TimeShiftAvailabilityDetector;
8804 /**
8805 * Detects changes of the stream type, i.e. changes of the return value of the player#isLive method.
8806 * Normally, a stream cannot change its type during playback, it's either VOD or live. Due to bugs on some
8807 * platforms or browsers, it can still change. It is therefore unreliable to just check #isLive and this detector
8808 * should be used as a workaround instead.
8809 *
8810 * Known cases:
8811 *
8812 * - HLS VOD on Android 4.3
8813 * Video duration is initially 'Infinity' and only gets available after playback starts, so streams are wrongly
8814 * reported as 'live' before playback (the live-check in the player checks for infinite duration).
8815 */
8816 var LiveStreamDetector = /** @class */ (function () {
8817 function LiveStreamDetector(player) {
8818 var _this = this;
8819 this.liveChangedEvent = new eventdispatcher_1.EventDispatcher();
8820 this.player = player;
8821 this.live = undefined;
8822 var liveDetector = function () {
8823 _this.detect();
8824 };
8825 // Initialize when player is ready
8826 player.addEventHandler(player.EVENT.ON_READY, liveDetector);
8827 // Re-evaluate when playback starts
8828 player.addEventHandler(player.EVENT.ON_PLAY, liveDetector);
8829 // HLS live detection workaround for Android:
8830 // Also re-evaluate during playback, because that is when the live flag might change.
8831 // (Doing it only in Android Chrome saves unnecessary overhead on other plattforms)
8832 if (browserutils_1.BrowserUtils.isAndroid && browserutils_1.BrowserUtils.isChrome) {
8833 player.addEventHandler(player.EVENT.ON_TIME_CHANGED, liveDetector);
8834 }
8835 }
8836 LiveStreamDetector.prototype.detect = function () {
8837 var liveNow = this.player.isLive();
8838 // Compare current to previous live state flag and fire event when it changes. Since we initialize the flag
8839 // with undefined, there is always at least an initial event fired that tells listeners the live state.
8840 if (liveNow !== this.live) {
8841 this.liveChangedEvent.dispatch(this.player, { live: liveNow });
8842 this.live = liveNow;
8843 }
8844 };
8845 Object.defineProperty(LiveStreamDetector.prototype, "onLiveChanged", {
8846 get: function () {
8847 return this.liveChangedEvent.getEvent();
8848 },
8849 enumerable: true,
8850 configurable: true
8851 });
8852 return LiveStreamDetector;
8853 }());
8854 PlayerUtils.LiveStreamDetector = LiveStreamDetector;
8855})(PlayerUtils = exports.PlayerUtils || (exports.PlayerUtils = {}));
8856
8857},{"./browserutils":2,"./eventdispatcher":82}],87:[function(require,module,exports){
8858"use strict";
8859Object.defineProperty(exports, "__esModule", { value: true });
8860var StorageUtils;
8861(function (StorageUtils) {
8862 var hasLocalStorageCache;
8863 function hasLocalStorage() {
8864 if (hasLocalStorageCache) {
8865 return hasLocalStorageCache;
8866 }
8867 // hasLocalStorage is used to safely ensure we can use localStorage
8868 // taken from https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#Feature-detecting_localStorage
8869 var storage = window['localStorage'];
8870 try {
8871 var x = '__storage_test__';
8872 storage.setItem(x, x);
8873 storage.removeItem(x);
8874 hasLocalStorageCache = true;
8875 }
8876 catch (e) {
8877 hasLocalStorageCache = e instanceof DOMException && (
8878 // everything except Firefox
8879 e.code === 22 ||
8880 // Firefox
8881 e.code === 1014 ||
8882 // test name field too, because code might not be present
8883 // everything except Firefox
8884 e.name === 'QuotaExceededError' ||
8885 // Firefox
8886 e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
8887 // acknowledge QuotaExceededError only if there's something already stored
8888 storage.length !== 0;
8889 }
8890 return hasLocalStorageCache;
8891 }
8892 StorageUtils.hasLocalStorage = hasLocalStorage;
8893 /**
8894 * Stores a string item into localStorage.
8895 * @param key the item's key
8896 * @param data the item's data
8897 */
8898 function setItem(key, data) {
8899 if (StorageUtils.hasLocalStorage()) {
8900 window.localStorage.setItem(key, data);
8901 }
8902 }
8903 StorageUtils.setItem = setItem;
8904 /**
8905 * Gets an item's string value from the localStorage.
8906 * @param key the key to look up its associated value
8907 * @return {string | null} Returns the string if found, null if there is no data stored for the key
8908 */
8909 function getItem(key) {
8910 if (StorageUtils.hasLocalStorage()) {
8911 return window.localStorage.getItem(key);
8912 }
8913 else {
8914 return null;
8915 }
8916 }
8917 StorageUtils.getItem = getItem;
8918 /**
8919 * Stores an object into localStorage. The object will be serialized to JSON. The following types are supported
8920 * in addition to the default types:
8921 * - ColorUtils.Color
8922 *
8923 * @param key the key to store the data to
8924 * @param data the object to store
8925 */
8926 function setObject(key, data) {
8927 if (StorageUtils.hasLocalStorage()) {
8928 var json = JSON.stringify(data);
8929 setItem(key, json);
8930 }
8931 }
8932 StorageUtils.setObject = setObject;
8933 /**
8934 * Gets an object for the given key from localStorage. The object will be deserialized from JSON. Beside the
8935 * default types, the following types are supported:
8936 * - ColorUtils.Color
8937 *
8938 * @param key the key to look up its associated object
8939 * @return {any} Returns the object if found, null otherwise
8940 */
8941 function getObject(key) {
8942 if (StorageUtils.hasLocalStorage()) {
8943 var json = getItem(key);
8944 if (key) {
8945 var object = JSON.parse(json);
8946 return object;
8947 }
8948 }
8949 return null;
8950 }
8951 StorageUtils.getObject = getObject;
8952})(StorageUtils = exports.StorageUtils || (exports.StorageUtils = {}));
8953
8954},{}],88:[function(require,module,exports){
8955"use strict";
8956Object.defineProperty(exports, "__esModule", { value: true });
8957var StringUtils;
8958(function (StringUtils) {
8959 StringUtils.FORMAT_HHMMSS = 'hh:mm:ss';
8960 StringUtils.FORMAT_MMSS = 'mm:ss';
8961 /**
8962 * Formats a number of seconds into a time string with the pattern hh:mm:ss.
8963 *
8964 * @param totalSeconds the total number of seconds to format to string
8965 * @param format the time format to output (default: hh:mm:ss)
8966 * @returns {string} the formatted time string
8967 */
8968 function secondsToTime(totalSeconds, format) {
8969 if (format === void 0) { format = StringUtils.FORMAT_HHMMSS; }
8970 var isNegative = totalSeconds < 0;
8971 if (isNegative) {
8972 // If the time is negative, we make it positive for the calculation below
8973 // (else we'd get all negative numbers) and reattach the negative sign later.
8974 totalSeconds = -totalSeconds;
8975 }
8976 // Split into separate time parts
8977 var hours = Math.floor(totalSeconds / 3600);
8978 var minutes = Math.floor(totalSeconds / 60) - hours * 60;
8979 var seconds = Math.floor(totalSeconds) % 60;
8980 return (isNegative ? '-' : '') + format
8981 .replace('hh', leftPadWithZeros(hours, 2))
8982 .replace('mm', leftPadWithZeros(minutes, 2))
8983 .replace('ss', leftPadWithZeros(seconds, 2));
8984 }
8985 StringUtils.secondsToTime = secondsToTime;
8986 /**
8987 * Converts a number to a string and left-pads it with zeros to the specified length.
8988 * Example: leftPadWithZeros(123, 5) => '00123'
8989 *
8990 * @param num the number to convert to string and pad with zeros
8991 * @param length the desired length of the padded string
8992 * @returns {string} the padded number as string
8993 */
8994 function leftPadWithZeros(num, length) {
8995 var text = num + '';
8996 var padding = '0000000000'.substr(0, length - text.length);
8997 return padding + text;
8998 }
8999 /**
9000 * Fills out placeholders in an ad message.
9001 *
9002 * Has the placeholders '{remainingTime[formatString]}', '{playedTime[formatString]}' and
9003 * '{adDuration[formatString]}', which are replaced by the remaining time until the ad can be skipped, the current
9004 * time or the ad duration. The format string is optional. If not specified, the placeholder is replaced by the time
9005 * in seconds. If specified, it must be of the following format:
9006 * - %d - Inserts the time as an integer.
9007 * - %0Nd - Inserts the time as an integer with leading zeroes, if the length of the time string is smaller than N.
9008 * - %f - Inserts the time as a float.
9009 * - %0Nf - Inserts the time as a float with leading zeroes.
9010 * - %.Mf - Inserts the time as a float with M decimal places. Can be combined with %0Nf, e.g. %04.2f (the time
9011 * 10.123
9012 * would be printed as 0010.12).
9013 * - %hh:mm:ss
9014 * - %mm:ss
9015 *
9016 * @param adMessage an ad message with optional placeholders to fill
9017 * @param skipOffset if specified, {remainingTime} will be filled with the remaining time until the ad can be skipped
9018 * @param player the player to get the time data from
9019 * @returns {string} the ad message with filled placeholders
9020 */
9021 function replaceAdMessagePlaceholders(adMessage, skipOffset, player) {
9022 var adMessagePlaceholderRegex = new RegExp('\\{(remainingTime|playedTime|adDuration)(}|%((0[1-9]\\d*(\\.\\d+(d|f)|d|f)|\\.\\d+f|d|f)|hh:mm:ss|mm:ss)})', 'g');
9023 return adMessage.replace(adMessagePlaceholderRegex, function (formatString) {
9024 var time = 0;
9025 if (formatString.indexOf('remainingTime') > -1) {
9026 if (skipOffset) {
9027 time = Math.ceil(skipOffset - player.getCurrentTime());
9028 }
9029 else {
9030 time = player.getDuration() - player.getCurrentTime();
9031 }
9032 }
9033 else if (formatString.indexOf('playedTime') > -1) {
9034 time = player.getCurrentTime();
9035 }
9036 else if (formatString.indexOf('adDuration') > -1) {
9037 time = player.getDuration();
9038 }
9039 return formatNumber(time, formatString);
9040 });
9041 }
9042 StringUtils.replaceAdMessagePlaceholders = replaceAdMessagePlaceholders;
9043 function formatNumber(time, format) {
9044 var formatStringValidationRegex = /%((0[1-9]\d*(\.\d+(d|f)|d|f)|\.\d+f|d|f)|hh:mm:ss|mm:ss)/;
9045 var leadingZeroesRegex = /(%0[1-9]\d*)(?=(\.\d+f|f|d))/;
9046 var decimalPlacesRegex = /\.\d*(?=f)/;
9047 if (!formatStringValidationRegex.test(format)) {
9048 // If the format is invalid, we set a default fallback format
9049 format = '%d';
9050 }
9051 // Determine the number of leading zeros
9052 var leadingZeroes = 0;
9053 var leadingZeroesMatches = format.match(leadingZeroesRegex);
9054 if (leadingZeroesMatches) {
9055 leadingZeroes = parseInt(leadingZeroesMatches[0].substring(2));
9056 }
9057 // Determine the number of decimal places
9058 var numDecimalPlaces = null;
9059 var decimalPlacesMatches = format.match(decimalPlacesRegex);
9060 if (decimalPlacesMatches && !isNaN(parseInt(decimalPlacesMatches[0].substring(1)))) {
9061 numDecimalPlaces = parseInt(decimalPlacesMatches[0].substring(1));
9062 if (numDecimalPlaces > 20) {
9063 numDecimalPlaces = 20;
9064 }
9065 }
9066 // Float format
9067 if (format.indexOf('f') > -1) {
9068 var timeString = '';
9069 if (numDecimalPlaces !== null) {
9070 // Apply fixed number of decimal places
9071 timeString = time.toFixed(numDecimalPlaces);
9072 }
9073 else {
9074 timeString = '' + time;
9075 }
9076 // Apply leading zeros
9077 if (timeString.indexOf('.') > -1) {
9078 return leftPadWithZeros(timeString, timeString.length + (leadingZeroes - timeString.indexOf('.')));
9079 }
9080 else {
9081 return leftPadWithZeros(timeString, leadingZeroes);
9082 }
9083 }
9084 // Time format
9085 else if (format.indexOf(':') > -1) {
9086 var totalSeconds = Math.ceil(time);
9087 // hh:mm:ss format
9088 if (format.indexOf('hh') > -1) {
9089 return secondsToTime(totalSeconds);
9090 }
9091 // mm:ss format
9092 else {
9093 var minutes = Math.floor(totalSeconds / 60);
9094 var seconds = totalSeconds % 60;
9095 return leftPadWithZeros(minutes, 2) + ':' + leftPadWithZeros(seconds, 2);
9096 }
9097 }
9098 // Integer format
9099 else {
9100 return leftPadWithZeros(Math.ceil(time), leadingZeroes);
9101 }
9102 }
9103})(StringUtils = exports.StringUtils || (exports.StringUtils = {}));
9104
9105},{}],89:[function(require,module,exports){
9106"use strict";
9107Object.defineProperty(exports, "__esModule", { value: true });
9108// TODO change to internal (not exported) class, how to use in other files?
9109/**
9110 * Executes a callback after a specified amount of time, optionally repeatedly until stopped.
9111 */
9112var Timeout = /** @class */ (function () {
9113 /**
9114 * Creates a new timeout callback handler.
9115 * @param delay the delay in milliseconds after which the callback should be executed
9116 * @param callback the callback to execute after the delay time
9117 * @param repeat if true, call the callback repeatedly in delay intervals
9118 */
9119 function Timeout(delay, callback, repeat) {
9120 if (repeat === void 0) { repeat = false; }
9121 this.delay = delay;
9122 this.callback = callback;
9123 this.repeat = repeat;
9124 this.timeoutHandle = 0;
9125 }
9126 /**
9127 * Starts the timeout and calls the callback when the timeout delay has passed.
9128 * @returns {Timeout} the current timeout (so the start call can be chained to the constructor)
9129 */
9130 Timeout.prototype.start = function () {
9131 this.reset();
9132 return this;
9133 };
9134 /**
9135 * Clears the timeout. The callback will not be called if clear is called during the timeout.
9136 */
9137 Timeout.prototype.clear = function () {
9138 this.clearInternal();
9139 };
9140 /**
9141 * Resets the passed timeout delay to zero. Can be used to defer the calling of the callback.
9142 */
9143 Timeout.prototype.reset = function () {
9144 var _this = this;
9145 var lastScheduleTime = 0;
9146 var delayAdjust = 0;
9147 this.clearInternal();
9148 var internalCallback = function () {
9149 _this.callback();
9150 if (_this.repeat) {
9151 var now = Date.now();
9152 // The time of one iteration from scheduling to executing the callback (usually a bit longer than the delay
9153 // time)
9154 var delta = now - lastScheduleTime;
9155 // Calculate the delay adjustment for the next schedule to keep a steady delay interval over time
9156 delayAdjust = _this.delay - delta + delayAdjust;
9157 lastScheduleTime = now;
9158 // Schedule next execution by the adjusted delay
9159 _this.timeoutHandle = setTimeout(internalCallback, _this.delay + delayAdjust);
9160 }
9161 };
9162 lastScheduleTime = Date.now();
9163 this.timeoutHandle = setTimeout(internalCallback, this.delay);
9164 };
9165 Timeout.prototype.clearInternal = function () {
9166 clearTimeout(this.timeoutHandle);
9167 };
9168 return Timeout;
9169}());
9170exports.Timeout = Timeout;
9171
9172},{}],90:[function(require,module,exports){
9173"use strict";
9174var __extends = (this && this.__extends) || (function () {
9175 var extendStatics = Object.setPrototypeOf ||
9176 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
9177 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
9178 return function (d, b) {
9179 extendStatics(d, b);
9180 function __() { this.constructor = d; }
9181 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
9182 };
9183})();
9184var __assign = (this && this.__assign) || Object.assign || function(t) {
9185 for (var s, i = 1, n = arguments.length; i < n; i++) {
9186 s = arguments[i];
9187 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
9188 t[p] = s[p];
9189 }
9190 return t;
9191};
9192Object.defineProperty(exports, "__esModule", { value: true });
9193var uicontainer_1 = require("./components/uicontainer");
9194var dom_1 = require("./dom");
9195var container_1 = require("./components/container");
9196var playbacktogglebutton_1 = require("./components/playbacktogglebutton");
9197var fullscreentogglebutton_1 = require("./components/fullscreentogglebutton");
9198var vrtogglebutton_1 = require("./components/vrtogglebutton");
9199var volumetogglebutton_1 = require("./components/volumetogglebutton");
9200var seekbar_1 = require("./components/seekbar");
9201var playbacktimelabel_1 = require("./components/playbacktimelabel");
9202var controlbar_1 = require("./components/controlbar");
9203var eventdispatcher_1 = require("./eventdispatcher");
9204var settingstogglebutton_1 = require("./components/settingstogglebutton");
9205var settingspanel_1 = require("./components/settingspanel");
9206var subtitlesettingspanel_1 = require("./components/subtitlesettings/subtitlesettingspanel");
9207var subtitlesettingslabel_1 = require("./components/subtitlesettings/subtitlesettingslabel");
9208var subtitlesettingsopenbutton_1 = require("./components/subtitlesettings/subtitlesettingsopenbutton");
9209var videoqualityselectbox_1 = require("./components/videoqualityselectbox");
9210var watermark_1 = require("./components/watermark");
9211var audioqualityselectbox_1 = require("./components/audioqualityselectbox");
9212var audiotrackselectbox_1 = require("./components/audiotrackselectbox");
9213var seekbarlabel_1 = require("./components/seekbarlabel");
9214var volumeslider_1 = require("./components/volumeslider");
9215var subtitleselectbox_1 = require("./components/subtitleselectbox");
9216var subtitleoverlay_1 = require("./components/subtitleoverlay");
9217var volumecontrolbutton_1 = require("./components/volumecontrolbutton");
9218var casttogglebutton_1 = require("./components/casttogglebutton");
9219var caststatusoverlay_1 = require("./components/caststatusoverlay");
9220var errormessageoverlay_1 = require("./components/errormessageoverlay");
9221var titlebar_1 = require("./components/titlebar");
9222var recommendationoverlay_1 = require("./components/recommendationoverlay");
9223var admessagelabel_1 = require("./components/admessagelabel");
9224var adskipbutton_1 = require("./components/adskipbutton");
9225var adclickoverlay_1 = require("./components/adclickoverlay");
9226var playbackspeedselectbox_1 = require("./components/playbackspeedselectbox");
9227var bufferingoverlay_1 = require("./components/bufferingoverlay");
9228var castuicontainer_1 = require("./components/castuicontainer");
9229var playbacktoggleoverlay_1 = require("./components/playbacktoggleoverlay");
9230var closebutton_1 = require("./components/closebutton");
9231var metadatalabel_1 = require("./components/metadatalabel");
9232var label_1 = require("./components/label");
9233var airplaytogglebutton_1 = require("./components/airplaytogglebutton");
9234var pictureinpicturetogglebutton_1 = require("./components/pictureinpicturetogglebutton");
9235var spacer_1 = require("./components/spacer");
9236var uiutils_1 = require("./uiutils");
9237var arrayutils_1 = require("./arrayutils");
9238var browserutils_1 = require("./browserutils");
9239var UIManager = /** @class */ (function () {
9240 function UIManager(player, playerUiOrUiVariants, config) {
9241 if (config === void 0) { config = {}; }
9242 var _this = this;
9243 this.events = {
9244 onUiVariantResolve: new eventdispatcher_1.EventDispatcher(),
9245 };
9246 if (playerUiOrUiVariants instanceof uicontainer_1.UIContainer) {
9247 // Single-UI constructor has been called, transform arguments to UIVariant[] signature
9248 var playerUi = playerUiOrUiVariants;
9249 var uiVariants = [];
9250 // Add the default player UI
9251 uiVariants.push({ ui: playerUi });
9252 this.uiVariants = uiVariants;
9253 }
9254 else {
9255 // Default constructor (UIVariant[]) has been called
9256 this.uiVariants = playerUiOrUiVariants;
9257 }
9258 this.player = player;
9259 this.config = __assign({}, config, { events: {
9260 onUpdated: new eventdispatcher_1.EventDispatcher(),
9261 } });
9262 this.managerPlayerWrapper = new PlayerWrapper(player);
9263 /**
9264 * Gathers configuration data from the UI config and player source config and creates a merged UI config
9265 * that is used throughout the UI instance.
9266 */
9267 var updateConfig = function () {
9268 var playerSourceConfig = player.getConfig().source || {};
9269 var uiConfig = __assign({}, config);
9270 uiConfig.metadata = uiConfig.metadata || {};
9271 // Extract the UI-related config properties from the source config
9272 var playerSourceUiConfig = {
9273 metadata: {
9274 // TODO move metadata into source.metadata namespace in player v8
9275 title: playerSourceConfig.title,
9276 description: playerSourceConfig.description,
9277 markers: playerSourceConfig.markers,
9278 },
9279 recommendations: playerSourceConfig.recommendations,
9280 };
9281 // Player source config takes precedence over the UI config, because the config in the source is attached
9282 // to a source which changes with every player.load, whereas the UI config stays the same for the whole
9283 // lifetime of the player instance.
9284 _this.config.metadata = _this.config.metadata || {};
9285 _this.config.metadata.title = playerSourceUiConfig.metadata.title || uiConfig.metadata.title;
9286 _this.config.metadata.description = playerSourceUiConfig.metadata.description || uiConfig.metadata.description;
9287 _this.config.metadata.markers = playerSourceUiConfig.metadata.markers || uiConfig.metadata.markers || [];
9288 _this.config.recommendations = playerSourceUiConfig.recommendations || uiConfig.recommendations || [];
9289 };
9290 updateConfig();
9291 // Update the configuration when a new source is loaded
9292 this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_SOURCE_LOADED, function () {
9293 updateConfig();
9294 _this.config.events.onUpdated.dispatch(_this);
9295 });
9296 if (config.container) {
9297 // Unfortunately "uiContainerElement = new DOM(config.container)" will not accept the container with
9298 // string|HTMLElement type directly, although it accepts both types, so we need to spit these two cases up here.
9299 // TODO check in upcoming TS versions if the container can be passed in directly, or fix the constructor
9300 this.uiContainerElement = config.container instanceof HTMLElement ?
9301 new dom_1.DOM(config.container) : new dom_1.DOM(config.container);
9302 }
9303 else {
9304 this.uiContainerElement = new dom_1.DOM(player.getFigure());
9305 }
9306 // Create UI instance managers for the UI variants
9307 // The instance managers map to the corresponding UI variants by their array index
9308 this.uiInstanceManagers = [];
9309 var uiVariantsWithoutCondition = [];
9310 for (var _i = 0, _a = this.uiVariants; _i < _a.length; _i++) {
9311 var uiVariant = _a[_i];
9312 if (uiVariant.condition == null) {
9313 // Collect variants without conditions for error checking
9314 uiVariantsWithoutCondition.push(uiVariant);
9315 }
9316 // Create the instance manager for a UI variant
9317 this.uiInstanceManagers.push(new InternalUIInstanceManager(player, uiVariant.ui, this.config));
9318 }
9319 // Make sure that there is only one UI variant without a condition
9320 // It does not make sense to have multiple variants without condition, because only the first one in the list
9321 // (the one with the lowest index) will ever be selected.
9322 if (uiVariantsWithoutCondition.length > 1) {
9323 throw Error('Too many UIs without a condition: You cannot have more than one default UI');
9324 }
9325 // Make sure that the default UI variant, if defined, is at the end of the list (last index)
9326 // If it comes earlier, the variants with conditions that come afterwards will never be selected because the
9327 // default variant without a condition always evaluates to 'true'
9328 if (uiVariantsWithoutCondition.length > 0
9329 && uiVariantsWithoutCondition[0] !== this.uiVariants[this.uiVariants.length - 1]) {
9330 throw Error('Invalid UI variant order: the default UI (without condition) must be at the end of the list');
9331 }
9332 // Switch on auto UI resolving by default
9333 if (config.autoUiVariantResolve === undefined) {
9334 config.autoUiVariantResolve = true;
9335 }
9336 var adStartedEvent = null; // keep the event stored here during ad playback
9337 // Dynamically select a UI variant that matches the current UI condition.
9338 var resolveUiVariant = function (event) {
9339 // Make sure that the ON_AD_STARTED event data is persisted through ad playback in case other events happen
9340 // in the meantime, e.g. player resize. We need to store this data because there is no other way to find out
9341 // ad details (e.g. the ad client) while an ad is playing.
9342 // Existing event data signals that an ad is currently active. We cannot use player.isAd() because it returns
9343 // true on ad start and also on ad end events, which is problematic.
9344 if (event != null) {
9345 switch (event.type) {
9346 // When the ad starts, we store the event data
9347 case player.EVENT.ON_AD_STARTED:
9348 adStartedEvent = event;
9349 break;
9350 // When the ad ends, we delete the event data
9351 case player.EVENT.ON_AD_FINISHED:
9352 case player.EVENT.ON_AD_SKIPPED:
9353 case player.EVENT.ON_AD_ERROR:
9354 adStartedEvent = null;
9355 break;
9356 // When a new source is loaded during ad playback, there will be no ad end event so we detect the end
9357 // of the ad playback by checking isAd() in ON_READY, because ON_READY always arrives when the source
9358 // changes.
9359 case player.EVENT.ON_READY:
9360 if (adStartedEvent && !player.isAd()) {
9361 adStartedEvent = null;
9362 }
9363 }
9364 }
9365 // Detect if an ad has started
9366 var ad = adStartedEvent != null;
9367 var adWithUI = ad && adStartedEvent.clientType === 'vast';
9368 _this.resolveUiVariant({
9369 isAd: ad,
9370 isAdWithUI: adWithUI,
9371 adClientType: ad ? adStartedEvent.clientType : null,
9372 }, function (context) {
9373 // If this is an ad UI, we need to relay the saved ON_AD_STARTED event data so ad components can configure
9374 // themselves for the current ad.
9375 if (context.isAd) {
9376 /* Relay the ON_AD_STARTED event to the ads UI
9377 *
9378 * Because the ads UI is initialized in the ON_AD_STARTED handler, i.e. when the ON_AD_STARTED event has
9379 * already been fired, components in the ads UI that listen for the ON_AD_STARTED event never receive it.
9380 * Since this can break functionality of components that rely on this event, we relay the event to the
9381 * ads UI components with the following call.
9382 */
9383 _this.currentUi.getWrappedPlayer().fireEventInUI(_this.player.EVENT.ON_AD_STARTED, adStartedEvent);
9384 }
9385 });
9386 };
9387 // Listen to the following events to trigger UI variant resolution
9388 if (config.autoUiVariantResolve) {
9389 this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_READY, resolveUiVariant);
9390 this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_PLAY, resolveUiVariant);
9391 this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_PAUSED, resolveUiVariant);
9392 this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_AD_STARTED, resolveUiVariant);
9393 this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_AD_FINISHED, resolveUiVariant);
9394 this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_AD_SKIPPED, resolveUiVariant);
9395 this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_AD_ERROR, resolveUiVariant);
9396 this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_PLAYER_RESIZE, resolveUiVariant);
9397 this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_FULLSCREEN_ENTER, resolveUiVariant);
9398 this.managerPlayerWrapper.getPlayer().addEventHandler(this.player.EVENT.ON_FULLSCREEN_EXIT, resolveUiVariant);
9399 }
9400 // Initialize the UI
9401 resolveUiVariant(null);
9402 }
9403 UIManager.prototype.getConfig = function () {
9404 return this.config;
9405 };
9406 /**
9407 * Returns the list of UI variants as passed into the constructor of {@link UIManager}.
9408 * @returns {UIVariant[]} the list of available UI variants
9409 */
9410 UIManager.prototype.getUiVariants = function () {
9411 return this.uiVariants;
9412 };
9413 /**
9414 * Switches to a UI variant from the list returned by {@link getUiVariants}.
9415 * @param {UIVariant} uiVariant the UI variant to switch to
9416 * @param {() => void} onShow a callback that is executed just before the new UI variant is shown
9417 */
9418 UIManager.prototype.switchToUiVariant = function (uiVariant, onShow) {
9419 var uiVariantIndex = this.uiVariants.indexOf(uiVariant);
9420 var nextUi = this.uiInstanceManagers[uiVariantIndex];
9421 var uiVariantChanged = false;
9422 // Determine if the UI variant is changing
9423 if (nextUi !== this.currentUi) {
9424 uiVariantChanged = true;
9425 // console.log('switched from ', this.currentUi ? this.currentUi.getUI() : 'none',
9426 // ' to ', nextUi ? nextUi.getUI() : 'none');
9427 }
9428 // Only if the UI variant is changing, we need to do some stuff. Else we just leave everything as-is.
9429 if (uiVariantChanged) {
9430 // Hide the currently active UI variant
9431 if (this.currentUi) {
9432 this.currentUi.getUI().hide();
9433 }
9434 // Assign the new UI variant as current UI
9435 this.currentUi = nextUi;
9436 // When we switch to a different UI instance, there's some additional stuff to manage. If we do not switch
9437 // to an instance, we're done here.
9438 if (this.currentUi != null) {
9439 // Add the UI to the DOM (and configure it) the first time it is selected
9440 if (!this.currentUi.isConfigured()) {
9441 this.addUi(this.currentUi);
9442 }
9443 if (onShow) {
9444 onShow();
9445 }
9446 this.currentUi.getUI().show();
9447 }
9448 }
9449 };
9450 /**
9451 * Triggers a UI variant switch as triggered by events when automatic switching is enabled. It allows to overwrite
9452 * properties of the {@link UIConditionContext}.
9453 * @param {Partial<UIConditionContext>} context an optional set of properties that overwrite properties of the
9454 * automatically determined context
9455 * @param {(context: UIConditionContext) => void} onShow a callback that is executed just before the new UI variant
9456 * is shown (if a switch is happening)
9457 */
9458 UIManager.prototype.resolveUiVariant = function (context, onShow) {
9459 if (context === void 0) { context = {}; }
9460 // Determine the current context for which the UI variant will be resolved
9461 var defaultContext = {
9462 isAd: false,
9463 isAdWithUI: false,
9464 adClientType: null,
9465 isFullscreen: this.player.isFullscreen(),
9466 isMobile: browserutils_1.BrowserUtils.isMobile,
9467 isPlaying: this.player.isPlaying(),
9468 width: this.uiContainerElement.width(),
9469 documentWidth: document.body.clientWidth,
9470 };
9471 // Overwrite properties of the default context with passed in context properties
9472 var switchingContext = __assign({}, defaultContext, context);
9473 // Fire the event and allow modification of the context before it is used to resolve the UI variant
9474 this.events.onUiVariantResolve.dispatch(this, switchingContext);
9475 var nextUiVariant = null;
9476 // Select new UI variant
9477 // If no variant condition is fulfilled, we switch to *no* UI
9478 for (var _i = 0, _a = this.uiVariants; _i < _a.length; _i++) {
9479 var uiVariant = _a[_i];
9480 if (uiVariant.condition == null || uiVariant.condition(switchingContext) === true) {
9481 nextUiVariant = uiVariant;
9482 break;
9483 }
9484 }
9485 this.switchToUiVariant(nextUiVariant, function () {
9486 if (onShow) {
9487 onShow(switchingContext);
9488 }
9489 });
9490 };
9491 UIManager.prototype.addUi = function (ui) {
9492 var dom = ui.getUI().getDomElement();
9493 var player = ui.getWrappedPlayer();
9494 ui.configureControls();
9495 /* Append the UI DOM after configuration to avoid CSS transitions at initialization
9496 * Example: Components are hidden during configuration and these hides may trigger CSS transitions that are
9497 * undesirable at this time. */
9498 this.uiContainerElement.append(dom);
9499 // Some components initialize their state on ON_READY. When the UI is loaded after the player is already ready,
9500 // they will never receive the event so we fire it from here in such cases.
9501 if (player.isReady()) {
9502 player.fireEventInUI(player.EVENT.ON_READY, {});
9503 }
9504 // Fire onConfigured after UI DOM elements are successfully added. When fired immediately, the DOM elements
9505 // might not be fully configured and e.g. do not have a size.
9506 // https://swizec.com/blog/how-to-properly-wait-for-dom-elements-to-show-up-in-modern-browsers/swizec/6663
9507 if (window.requestAnimationFrame) {
9508 requestAnimationFrame(function () { ui.onConfigured.dispatch(ui.getUI()); });
9509 }
9510 else {
9511 // IE9 fallback
9512 setTimeout(function () { ui.onConfigured.dispatch(ui.getUI()); }, 0);
9513 }
9514 };
9515 UIManager.prototype.releaseUi = function (ui) {
9516 ui.releaseControls();
9517 ui.getUI().getDomElement().remove();
9518 ui.clearEventHandlers();
9519 };
9520 UIManager.prototype.release = function () {
9521 for (var _i = 0, _a = this.uiInstanceManagers; _i < _a.length; _i++) {
9522 var uiInstanceManager = _a[_i];
9523 this.releaseUi(uiInstanceManager);
9524 }
9525 this.managerPlayerWrapper.clearEventHandlers();
9526 };
9527 Object.defineProperty(UIManager.prototype, "onUiVariantResolve", {
9528 /**
9529 * Fires just before UI variants are about to be resolved and the UI variant is possibly switched. It is fired when
9530 * the switch is triggered from an automatic switch and when calling {@link resolveUiVariant}.
9531 * Can be used to modify the {@link UIConditionContext} before resolving is done.
9532 * @returns {EventDispatcher<UIManager, UIConditionContext>}
9533 */
9534 get: function () {
9535 return this.events.onUiVariantResolve;
9536 },
9537 enumerable: true,
9538 configurable: true
9539 });
9540 /**
9541 * Returns the list of all added markers in undefined order.
9542 */
9543 UIManager.prototype.getTimelineMarkers = function () {
9544 return this.config.metadata.markers;
9545 };
9546 /**
9547 * Adds a marker to the timeline. Does not check for duplicates/overlaps at the `time`.
9548 */
9549 UIManager.prototype.addTimelineMarker = function (timelineMarker) {
9550 this.config.metadata.markers.push(timelineMarker);
9551 this.config.events.onUpdated.dispatch(this);
9552 };
9553 /**
9554 * Removes a marker from the timeline (by reference) and returns `true` if the marker has
9555 * been part of the timeline and successfully removed, or `false` if the marker could not
9556 * be found and thus not removed.
9557 */
9558 UIManager.prototype.removeTimelineMarker = function (timelineMarker) {
9559 if (arrayutils_1.ArrayUtils.remove(this.config.metadata.markers, timelineMarker) === timelineMarker) {
9560 this.config.events.onUpdated.dispatch(this);
9561 return true;
9562 }
9563 return false;
9564 };
9565 return UIManager;
9566}());
9567exports.UIManager = UIManager;
9568(function (UIManager) {
9569 var Factory;
9570 (function (Factory) {
9571 function buildDefaultUI(player, config) {
9572 if (config === void 0) { config = {}; }
9573 return UIManager.Factory.buildModernUI(player, config);
9574 }
9575 Factory.buildDefaultUI = buildDefaultUI;
9576 function buildDefaultSmallScreenUI(player, config) {
9577 if (config === void 0) { config = {}; }
9578 return UIManager.Factory.buildModernSmallScreenUI(player, config);
9579 }
9580 Factory.buildDefaultSmallScreenUI = buildDefaultSmallScreenUI;
9581 function buildDefaultCastReceiverUI(player, config) {
9582 if (config === void 0) { config = {}; }
9583 return UIManager.Factory.buildModernCastReceiverUI(player, config);
9584 }
9585 Factory.buildDefaultCastReceiverUI = buildDefaultCastReceiverUI;
9586 function modernUI() {
9587 var subtitleOverlay = new subtitleoverlay_1.SubtitleOverlay();
9588 var settingsPanel = new settingspanel_1.SettingsPanel({
9589 components: [
9590 new settingspanel_1.SettingsPanelItem('Video Quality', new videoqualityselectbox_1.VideoQualitySelectBox()),
9591 new settingspanel_1.SettingsPanelItem('Speed', new playbackspeedselectbox_1.PlaybackSpeedSelectBox()),
9592 new settingspanel_1.SettingsPanelItem('Audio Track', new audiotrackselectbox_1.AudioTrackSelectBox()),
9593 new settingspanel_1.SettingsPanelItem('Audio Quality', new audioqualityselectbox_1.AudioQualitySelectBox()),
9594 ],
9595 hidden: true,
9596 });
9597 var subtitleSettingsPanel = new subtitlesettingspanel_1.SubtitleSettingsPanel({
9598 hidden: true,
9599 overlay: subtitleOverlay,
9600 settingsPanel: settingsPanel,
9601 });
9602 var subtitleSettingsOpenButton = new subtitlesettingsopenbutton_1.SubtitleSettingsOpenButton({
9603 subtitleSettingsPanel: subtitleSettingsPanel,
9604 settingsPanel: settingsPanel,
9605 });
9606 settingsPanel.addComponent(new settingspanel_1.SettingsPanelItem(new subtitlesettingslabel_1.SubtitleSettingsLabel({ text: 'Subtitles', opener: subtitleSettingsOpenButton }), new subtitleselectbox_1.SubtitleSelectBox()));
9607 var controlBar = new controlbar_1.ControlBar({
9608 components: [
9609 settingsPanel,
9610 subtitleSettingsPanel,
9611 new container_1.Container({
9612 components: [
9613 new playbacktimelabel_1.PlaybackTimeLabel({ timeLabelMode: playbacktimelabel_1.PlaybackTimeLabelMode.CurrentTime, hideInLivePlayback: true }),
9614 new seekbar_1.SeekBar({ label: new seekbarlabel_1.SeekBarLabel() }),
9615 new playbacktimelabel_1.PlaybackTimeLabel({ timeLabelMode: playbacktimelabel_1.PlaybackTimeLabelMode.TotalTime, cssClasses: ['text-right'] }),
9616 ],
9617 cssClasses: ['controlbar-top'],
9618 }),
9619 new container_1.Container({
9620 components: [
9621 new playbacktogglebutton_1.PlaybackToggleButton(),
9622 new volumetogglebutton_1.VolumeToggleButton(),
9623 new volumeslider_1.VolumeSlider(),
9624 new spacer_1.Spacer(),
9625 new pictureinpicturetogglebutton_1.PictureInPictureToggleButton(),
9626 new airplaytogglebutton_1.AirPlayToggleButton(),
9627 new casttogglebutton_1.CastToggleButton(),
9628 new vrtogglebutton_1.VRToggleButton(),
9629 new settingstogglebutton_1.SettingsToggleButton({ settingsPanel: settingsPanel }),
9630 new fullscreentogglebutton_1.FullscreenToggleButton(),
9631 ],
9632 cssClasses: ['controlbar-bottom'],
9633 }),
9634 ],
9635 });
9636 return new uicontainer_1.UIContainer({
9637 components: [
9638 subtitleOverlay,
9639 new bufferingoverlay_1.BufferingOverlay(),
9640 new playbacktoggleoverlay_1.PlaybackToggleOverlay(),
9641 new caststatusoverlay_1.CastStatusOverlay(),
9642 controlBar,
9643 new titlebar_1.TitleBar(),
9644 new recommendationoverlay_1.RecommendationOverlay(),
9645 new watermark_1.Watermark(),
9646 new errormessageoverlay_1.ErrorMessageOverlay(),
9647 ],
9648 cssClasses: ['ui-skin-modern'],
9649 });
9650 }
9651 function modernAdsUI() {
9652 return new uicontainer_1.UIContainer({
9653 components: [
9654 new bufferingoverlay_1.BufferingOverlay(),
9655 new adclickoverlay_1.AdClickOverlay(),
9656 new playbacktoggleoverlay_1.PlaybackToggleOverlay(),
9657 new container_1.Container({
9658 components: [
9659 new admessagelabel_1.AdMessageLabel({ text: 'Ad: {remainingTime} secs' }),
9660 new adskipbutton_1.AdSkipButton(),
9661 ],
9662 cssClass: 'ui-ads-status',
9663 }),
9664 new controlbar_1.ControlBar({
9665 components: [
9666 new container_1.Container({
9667 components: [
9668 new playbacktogglebutton_1.PlaybackToggleButton(),
9669 new volumetogglebutton_1.VolumeToggleButton(),
9670 new volumeslider_1.VolumeSlider(),
9671 new spacer_1.Spacer(),
9672 new fullscreentogglebutton_1.FullscreenToggleButton(),
9673 ],
9674 cssClasses: ['controlbar-bottom'],
9675 }),
9676 ],
9677 }),
9678 ],
9679 cssClasses: ['ui-skin-modern', 'ui-skin-ads'],
9680 });
9681 }
9682 function modernSmallScreenUI() {
9683 var subtitleOverlay = new subtitleoverlay_1.SubtitleOverlay();
9684 var settingsPanel = new settingspanel_1.SettingsPanel({
9685 components: [
9686 new settingspanel_1.SettingsPanelItem('Video Quality', new videoqualityselectbox_1.VideoQualitySelectBox()),
9687 new settingspanel_1.SettingsPanelItem('Speed', new playbackspeedselectbox_1.PlaybackSpeedSelectBox()),
9688 new settingspanel_1.SettingsPanelItem('Audio Track', new audiotrackselectbox_1.AudioTrackSelectBox()),
9689 new settingspanel_1.SettingsPanelItem('Audio Quality', new audioqualityselectbox_1.AudioQualitySelectBox()),
9690 ],
9691 hidden: true,
9692 hideDelay: -1,
9693 });
9694 var subtitleSettingsPanel = new subtitlesettingspanel_1.SubtitleSettingsPanel({
9695 hidden: true,
9696 hideDelay: -1,
9697 overlay: subtitleOverlay,
9698 settingsPanel: settingsPanel,
9699 });
9700 var subtitleSettingsOpenButton = new subtitlesettingsopenbutton_1.SubtitleSettingsOpenButton({
9701 subtitleSettingsPanel: subtitleSettingsPanel,
9702 settingsPanel: settingsPanel,
9703 });
9704 settingsPanel.addComponent(new settingspanel_1.SettingsPanelItem(new subtitlesettingslabel_1.SubtitleSettingsLabel({ text: 'Subtitles', opener: subtitleSettingsOpenButton }), new subtitleselectbox_1.SubtitleSelectBox()));
9705 settingsPanel.addComponent(new closebutton_1.CloseButton({ target: settingsPanel }));
9706 subtitleSettingsPanel.addComponent(new closebutton_1.CloseButton({ target: subtitleSettingsPanel }));
9707 var controlBar = new controlbar_1.ControlBar({
9708 components: [
9709 new container_1.Container({
9710 components: [
9711 new playbacktimelabel_1.PlaybackTimeLabel({ timeLabelMode: playbacktimelabel_1.PlaybackTimeLabelMode.CurrentTime, hideInLivePlayback: true }),
9712 new seekbar_1.SeekBar({ label: new seekbarlabel_1.SeekBarLabel() }),
9713 new playbacktimelabel_1.PlaybackTimeLabel({ timeLabelMode: playbacktimelabel_1.PlaybackTimeLabelMode.TotalTime, cssClasses: ['text-right'] }),
9714 ],
9715 cssClasses: ['controlbar-top'],
9716 }),
9717 ],
9718 });
9719 return new uicontainer_1.UIContainer({
9720 components: [
9721 subtitleOverlay,
9722 new bufferingoverlay_1.BufferingOverlay(),
9723 new caststatusoverlay_1.CastStatusOverlay(),
9724 new playbacktoggleoverlay_1.PlaybackToggleOverlay(),
9725 controlBar,
9726 new titlebar_1.TitleBar({
9727 components: [
9728 new metadatalabel_1.MetadataLabel({ content: metadatalabel_1.MetadataLabelContent.Title }),
9729 new casttogglebutton_1.CastToggleButton(),
9730 new vrtogglebutton_1.VRToggleButton(),
9731 new volumetogglebutton_1.VolumeToggleButton(),
9732 new settingstogglebutton_1.SettingsToggleButton({ settingsPanel: settingsPanel }),
9733 new fullscreentogglebutton_1.FullscreenToggleButton(),
9734 ],
9735 }),
9736 settingsPanel,
9737 subtitleSettingsPanel,
9738 new recommendationoverlay_1.RecommendationOverlay(),
9739 new watermark_1.Watermark(),
9740 new errormessageoverlay_1.ErrorMessageOverlay(),
9741 ],
9742 cssClasses: ['ui-skin-modern', 'ui-skin-smallscreen'],
9743 });
9744 }
9745 function modernSmallScreenAdsUI() {
9746 return new uicontainer_1.UIContainer({
9747 components: [
9748 new bufferingoverlay_1.BufferingOverlay(),
9749 new adclickoverlay_1.AdClickOverlay(),
9750 new playbacktoggleoverlay_1.PlaybackToggleOverlay(),
9751 new titlebar_1.TitleBar({
9752 components: [
9753 // dummy label with no content to move buttons to the right
9754 new label_1.Label({ cssClass: 'label-metadata-title' }),
9755 new fullscreentogglebutton_1.FullscreenToggleButton(),
9756 ],
9757 }),
9758 new container_1.Container({
9759 components: [
9760 new admessagelabel_1.AdMessageLabel({ text: 'Ad: {remainingTime} secs' }),
9761 new adskipbutton_1.AdSkipButton(),
9762 ],
9763 cssClass: 'ui-ads-status',
9764 }),
9765 ],
9766 cssClasses: ['ui-skin-modern', 'ui-skin-ads', 'ui-skin-smallscreen'],
9767 });
9768 }
9769 function modernCastReceiverUI() {
9770 var controlBar = new controlbar_1.ControlBar({
9771 components: [
9772 new container_1.Container({
9773 components: [
9774 new playbacktimelabel_1.PlaybackTimeLabel({ timeLabelMode: playbacktimelabel_1.PlaybackTimeLabelMode.CurrentTime, hideInLivePlayback: true }),
9775 new seekbar_1.SeekBar({ smoothPlaybackPositionUpdateIntervalMs: -1 }),
9776 new playbacktimelabel_1.PlaybackTimeLabel({ timeLabelMode: playbacktimelabel_1.PlaybackTimeLabelMode.TotalTime, cssClasses: ['text-right'] }),
9777 ],
9778 cssClasses: ['controlbar-top'],
9779 }),
9780 ],
9781 });
9782 return new castuicontainer_1.CastUIContainer({
9783 components: [
9784 new subtitleoverlay_1.SubtitleOverlay(),
9785 new bufferingoverlay_1.BufferingOverlay(),
9786 new playbacktoggleoverlay_1.PlaybackToggleOverlay(),
9787 new watermark_1.Watermark(),
9788 controlBar,
9789 new titlebar_1.TitleBar({ keepHiddenWithoutMetadata: true }),
9790 new errormessageoverlay_1.ErrorMessageOverlay(),
9791 ],
9792 cssClasses: ['ui-skin-modern', 'ui-skin-cast-receiver'],
9793 });
9794 }
9795 function buildModernUI(player, config) {
9796 if (config === void 0) { config = {}; }
9797 // show smallScreen UI only on mobile/handheld devices
9798 var smallScreenSwitchWidth = 600;
9799 return new UIManager(player, [{
9800 ui: modernSmallScreenAdsUI(),
9801 condition: function (context) {
9802 return context.isMobile && context.documentWidth < smallScreenSwitchWidth && context.isAdWithUI;
9803 },
9804 }, {
9805 ui: modernAdsUI(),
9806 condition: function (context) {
9807 return context.isAdWithUI;
9808 },
9809 }, {
9810 ui: modernSmallScreenUI(),
9811 condition: function (context) {
9812 return context.isMobile && context.documentWidth < smallScreenSwitchWidth;
9813 },
9814 }, {
9815 ui: modernUI(),
9816 }], config);
9817 }
9818 Factory.buildModernUI = buildModernUI;
9819 function buildModernSmallScreenUI(player, config) {
9820 if (config === void 0) { config = {}; }
9821 return new UIManager(player, [{
9822 ui: modernSmallScreenAdsUI(),
9823 condition: function (context) {
9824 return context.isAdWithUI;
9825 },
9826 }, {
9827 ui: modernSmallScreenUI(),
9828 }], config);
9829 }
9830 Factory.buildModernSmallScreenUI = buildModernSmallScreenUI;
9831 function buildModernCastReceiverUI(player, config) {
9832 if (config === void 0) { config = {}; }
9833 return new UIManager(player, modernCastReceiverUI(), config);
9834 }
9835 Factory.buildModernCastReceiverUI = buildModernCastReceiverUI;
9836 function legacyUI() {
9837 var settingsPanel = new settingspanel_1.SettingsPanel({
9838 components: [
9839 new settingspanel_1.SettingsPanelItem('Video Quality', new videoqualityselectbox_1.VideoQualitySelectBox()),
9840 new settingspanel_1.SettingsPanelItem('Audio Track', new audiotrackselectbox_1.AudioTrackSelectBox()),
9841 new settingspanel_1.SettingsPanelItem('Audio Quality', new audioqualityselectbox_1.AudioQualitySelectBox()),
9842 new settingspanel_1.SettingsPanelItem('Subtitles', new subtitleselectbox_1.SubtitleSelectBox()),
9843 ],
9844 hidden: true,
9845 });
9846 var controlBar = new controlbar_1.ControlBar({
9847 components: [
9848 settingsPanel,
9849 new playbacktogglebutton_1.PlaybackToggleButton(),
9850 new seekbar_1.SeekBar({ label: new seekbarlabel_1.SeekBarLabel() }),
9851 new playbacktimelabel_1.PlaybackTimeLabel(),
9852 new vrtogglebutton_1.VRToggleButton(),
9853 new volumecontrolbutton_1.VolumeControlButton(),
9854 new settingstogglebutton_1.SettingsToggleButton({ settingsPanel: settingsPanel }),
9855 new casttogglebutton_1.CastToggleButton(),
9856 new fullscreentogglebutton_1.FullscreenToggleButton(),
9857 ],
9858 });
9859 return new uicontainer_1.UIContainer({
9860 components: [
9861 new subtitleoverlay_1.SubtitleOverlay(),
9862 new caststatusoverlay_1.CastStatusOverlay(),
9863 new playbacktoggleoverlay_1.PlaybackToggleOverlay(),
9864 new watermark_1.Watermark(),
9865 new recommendationoverlay_1.RecommendationOverlay(),
9866 controlBar,
9867 new titlebar_1.TitleBar(),
9868 new errormessageoverlay_1.ErrorMessageOverlay(),
9869 ],
9870 cssClasses: ['ui-skin-legacy'],
9871 });
9872 }
9873 function legacyAdsUI() {
9874 return new uicontainer_1.UIContainer({
9875 components: [
9876 new adclickoverlay_1.AdClickOverlay(),
9877 new controlbar_1.ControlBar({
9878 components: [
9879 new playbacktogglebutton_1.PlaybackToggleButton(),
9880 new admessagelabel_1.AdMessageLabel(),
9881 new volumecontrolbutton_1.VolumeControlButton(),
9882 new fullscreentogglebutton_1.FullscreenToggleButton(),
9883 ],
9884 }),
9885 new adskipbutton_1.AdSkipButton(),
9886 ],
9887 cssClasses: ['ui-skin-legacy', 'ui-skin-ads'],
9888 });
9889 }
9890 function legacyCastReceiverUI() {
9891 var controlBar = new controlbar_1.ControlBar({
9892 components: [
9893 new seekbar_1.SeekBar(),
9894 new playbacktimelabel_1.PlaybackTimeLabel(),
9895 ],
9896 });
9897 return new uicontainer_1.UIContainer({
9898 components: [
9899 new subtitleoverlay_1.SubtitleOverlay(),
9900 new playbacktoggleoverlay_1.PlaybackToggleOverlay(),
9901 new watermark_1.Watermark(),
9902 controlBar,
9903 new titlebar_1.TitleBar(),
9904 new errormessageoverlay_1.ErrorMessageOverlay(),
9905 ],
9906 cssClasses: ['ui-skin-legacy', 'ui-skin-cast-receiver'],
9907 });
9908 }
9909 function legacyTestUI() {
9910 var settingsPanel = new settingspanel_1.SettingsPanel({
9911 components: [
9912 new settingspanel_1.SettingsPanelItem('Video Quality', new videoqualityselectbox_1.VideoQualitySelectBox()),
9913 new settingspanel_1.SettingsPanelItem('Audio Track', new audiotrackselectbox_1.AudioTrackSelectBox()),
9914 new settingspanel_1.SettingsPanelItem('Audio Quality', new audioqualityselectbox_1.AudioQualitySelectBox()),
9915 new settingspanel_1.SettingsPanelItem('Subtitles', new subtitleselectbox_1.SubtitleSelectBox()),
9916 ],
9917 hidden: true,
9918 });
9919 var controlBar = new controlbar_1.ControlBar({
9920 components: [settingsPanel,
9921 new playbacktogglebutton_1.PlaybackToggleButton(),
9922 new seekbar_1.SeekBar({ label: new seekbarlabel_1.SeekBarLabel() }),
9923 new playbacktimelabel_1.PlaybackTimeLabel(),
9924 new vrtogglebutton_1.VRToggleButton(),
9925 new volumetogglebutton_1.VolumeToggleButton(),
9926 new volumeslider_1.VolumeSlider(),
9927 new volumecontrolbutton_1.VolumeControlButton(),
9928 new volumecontrolbutton_1.VolumeControlButton({ vertical: false }),
9929 new settingstogglebutton_1.SettingsToggleButton({ settingsPanel: settingsPanel }),
9930 new casttogglebutton_1.CastToggleButton(),
9931 new fullscreentogglebutton_1.FullscreenToggleButton(),
9932 ],
9933 });
9934 return new uicontainer_1.UIContainer({
9935 components: [
9936 new subtitleoverlay_1.SubtitleOverlay(),
9937 new caststatusoverlay_1.CastStatusOverlay(),
9938 new playbacktoggleoverlay_1.PlaybackToggleOverlay(),
9939 new watermark_1.Watermark(),
9940 new recommendationoverlay_1.RecommendationOverlay(),
9941 controlBar,
9942 new titlebar_1.TitleBar(),
9943 new errormessageoverlay_1.ErrorMessageOverlay(),
9944 ],
9945 cssClasses: ['ui-skin-legacy'],
9946 });
9947 }
9948 function buildLegacyUI(player, config) {
9949 if (config === void 0) { config = {}; }
9950 return new UIManager(player, [{
9951 ui: legacyAdsUI(),
9952 condition: function (context) {
9953 return context.isAdWithUI;
9954 },
9955 }, {
9956 ui: legacyUI(),
9957 }], config);
9958 }
9959 Factory.buildLegacyUI = buildLegacyUI;
9960 function buildLegacyCastReceiverUI(player, config) {
9961 if (config === void 0) { config = {}; }
9962 return new UIManager(player, legacyCastReceiverUI(), config);
9963 }
9964 Factory.buildLegacyCastReceiverUI = buildLegacyCastReceiverUI;
9965 function buildLegacyTestUI(player, config) {
9966 if (config === void 0) { config = {}; }
9967 return new UIManager(player, legacyTestUI(), config);
9968 }
9969 Factory.buildLegacyTestUI = buildLegacyTestUI;
9970 })(Factory = UIManager.Factory || (UIManager.Factory = {}));
9971})(UIManager = exports.UIManager || (exports.UIManager = {}));
9972exports.UIManager = UIManager;
9973/**
9974 * Encapsulates functionality to manage a UI instance. Used by the {@link UIManager} to manage multiple UI instances.
9975 */
9976var UIInstanceManager = /** @class */ (function () {
9977 function UIInstanceManager(player, ui, config) {
9978 this.events = {
9979 onConfigured: new eventdispatcher_1.EventDispatcher(),
9980 onSeek: new eventdispatcher_1.EventDispatcher(),
9981 onSeekPreview: new eventdispatcher_1.EventDispatcher(),
9982 onSeeked: new eventdispatcher_1.EventDispatcher(),
9983 onComponentShow: new eventdispatcher_1.EventDispatcher(),
9984 onComponentHide: new eventdispatcher_1.EventDispatcher(),
9985 onControlsShow: new eventdispatcher_1.EventDispatcher(),
9986 onPreviewControlsHide: new eventdispatcher_1.EventDispatcher(),
9987 onControlsHide: new eventdispatcher_1.EventDispatcher(),
9988 onRelease: new eventdispatcher_1.EventDispatcher(),
9989 };
9990 this.playerWrapper = new PlayerWrapper(player);
9991 this.ui = ui;
9992 this.config = config;
9993 }
9994 UIInstanceManager.prototype.getConfig = function () {
9995 return this.config;
9996 };
9997 UIInstanceManager.prototype.getUI = function () {
9998 return this.ui;
9999 };
10000 UIInstanceManager.prototype.getPlayer = function () {
10001 return this.playerWrapper.getPlayer();
10002 };
10003 Object.defineProperty(UIInstanceManager.prototype, "onConfigured", {
10004 /**
10005 * Fires when the UI is fully configured and added to the DOM.
10006 * @returns {EventDispatcher}
10007 */
10008 get: function () {
10009 return this.events.onConfigured;
10010 },
10011 enumerable: true,
10012 configurable: true
10013 });
10014 Object.defineProperty(UIInstanceManager.prototype, "onSeek", {
10015 /**
10016 * Fires when a seek starts.
10017 * @returns {EventDispatcher}
10018 */
10019 get: function () {
10020 return this.events.onSeek;
10021 },
10022 enumerable: true,
10023 configurable: true
10024 });
10025 Object.defineProperty(UIInstanceManager.prototype, "onSeekPreview", {
10026 /**
10027 * Fires when the seek timeline is scrubbed.
10028 * @returns {EventDispatcher}
10029 */
10030 get: function () {
10031 return this.events.onSeekPreview;
10032 },
10033 enumerable: true,
10034 configurable: true
10035 });
10036 Object.defineProperty(UIInstanceManager.prototype, "onSeeked", {
10037 /**
10038 * Fires when a seek is finished.
10039 * @returns {EventDispatcher}
10040 */
10041 get: function () {
10042 return this.events.onSeeked;
10043 },
10044 enumerable: true,
10045 configurable: true
10046 });
10047 Object.defineProperty(UIInstanceManager.prototype, "onComponentShow", {
10048 /**
10049 * Fires when a component is showing.
10050 * @returns {EventDispatcher}
10051 */
10052 get: function () {
10053 return this.events.onComponentShow;
10054 },
10055 enumerable: true,
10056 configurable: true
10057 });
10058 Object.defineProperty(UIInstanceManager.prototype, "onComponentHide", {
10059 /**
10060 * Fires when a component is hiding.
10061 * @returns {EventDispatcher}
10062 */
10063 get: function () {
10064 return this.events.onComponentHide;
10065 },
10066 enumerable: true,
10067 configurable: true
10068 });
10069 Object.defineProperty(UIInstanceManager.prototype, "onControlsShow", {
10070 /**
10071 * Fires when the UI controls are showing.
10072 * @returns {EventDispatcher}
10073 */
10074 get: function () {
10075 return this.events.onControlsShow;
10076 },
10077 enumerable: true,
10078 configurable: true
10079 });
10080 Object.defineProperty(UIInstanceManager.prototype, "onPreviewControlsHide", {
10081 /**
10082 * Fires before the UI controls are hiding to check if they are allowed to hide.
10083 * @returns {EventDispatcher}
10084 */
10085 get: function () {
10086 return this.events.onPreviewControlsHide;
10087 },
10088 enumerable: true,
10089 configurable: true
10090 });
10091 Object.defineProperty(UIInstanceManager.prototype, "onControlsHide", {
10092 /**
10093 * Fires when the UI controls are hiding.
10094 * @returns {EventDispatcher}
10095 */
10096 get: function () {
10097 return this.events.onControlsHide;
10098 },
10099 enumerable: true,
10100 configurable: true
10101 });
10102 Object.defineProperty(UIInstanceManager.prototype, "onRelease", {
10103 /**
10104 * Fires when the UI controls are released.
10105 * @returns {EventDispatcher}
10106 */
10107 get: function () {
10108 return this.events.onRelease;
10109 },
10110 enumerable: true,
10111 configurable: true
10112 });
10113 UIInstanceManager.prototype.clearEventHandlers = function () {
10114 this.playerWrapper.clearEventHandlers();
10115 var events = this.events; // avoid TS7017
10116 for (var event_1 in events) {
10117 var dispatcher = events[event_1];
10118 dispatcher.unsubscribeAll();
10119 }
10120 };
10121 return UIInstanceManager;
10122}());
10123exports.UIInstanceManager = UIInstanceManager;
10124/**
10125 * Extends the {@link UIInstanceManager} for internal use in the {@link UIManager} and provides access to functionality
10126 * that components receiving a reference to the {@link UIInstanceManager} should not have access to.
10127 */
10128var InternalUIInstanceManager = /** @class */ (function (_super) {
10129 __extends(InternalUIInstanceManager, _super);
10130 function InternalUIInstanceManager() {
10131 return _super !== null && _super.apply(this, arguments) || this;
10132 }
10133 InternalUIInstanceManager.prototype.getWrappedPlayer = function () {
10134 // TODO find a non-hacky way to provide the WrappedPlayer to the UIManager without exporting it
10135 // getPlayer() actually returns the WrappedPlayer but its return type is set to Player so the WrappedPlayer does
10136 // not need to be exported
10137 return this.getPlayer();
10138 };
10139 InternalUIInstanceManager.prototype.configureControls = function () {
10140 this.configureControlsTree(this.getUI());
10141 this.configured = true;
10142 };
10143 InternalUIInstanceManager.prototype.isConfigured = function () {
10144 return this.configured;
10145 };
10146 InternalUIInstanceManager.prototype.configureControlsTree = function (component) {
10147 var _this = this;
10148 var configuredComponents = [];
10149 uiutils_1.UIUtils.traverseTree(component, function (component) {
10150 // First, check if we have already configured a component, and throw an error if we did. Multiple configuration
10151 // of the same component leads to unexpected UI behavior. Also, a component that is in the UI tree multiple
10152 // times hints at a wrong UI structure.
10153 // We could just skip configuration in such a case and not throw an exception, but enforcing a clean UI tree
10154 // seems like the better choice.
10155 for (var _i = 0, configuredComponents_1 = configuredComponents; _i < configuredComponents_1.length; _i++) {
10156 var configuredComponent = configuredComponents_1[_i];
10157 if (configuredComponent === component) {
10158 // Write the component to the console to simplify identification of the culprit
10159 // (e.g. by inspecting the config)
10160 if (console) {
10161 console.error('Circular reference in UI tree', component);
10162 }
10163 // Additionally throw an error, because this case must not happen and leads to unexpected UI behavior.
10164 throw Error('Circular reference in UI tree: ' + component.constructor.name);
10165 }
10166 }
10167 component.initialize();
10168 component.configure(_this.getPlayer(), _this);
10169 configuredComponents.push(component);
10170 });
10171 };
10172 InternalUIInstanceManager.prototype.releaseControls = function () {
10173 // Do not call release methods if the components have never been configured; this can result in exceptions
10174 if (this.configured) {
10175 this.onRelease.dispatch(this.getUI());
10176 this.releaseControlsTree(this.getUI());
10177 this.configured = false;
10178 }
10179 this.released = true;
10180 };
10181 InternalUIInstanceManager.prototype.isReleased = function () {
10182 return this.released;
10183 };
10184 InternalUIInstanceManager.prototype.releaseControlsTree = function (component) {
10185 component.release();
10186 if (component instanceof container_1.Container) {
10187 for (var _i = 0, _a = component.getComponents(); _i < _a.length; _i++) {
10188 var childComponent = _a[_i];
10189 this.releaseControlsTree(childComponent);
10190 }
10191 }
10192 };
10193 InternalUIInstanceManager.prototype.clearEventHandlers = function () {
10194 _super.prototype.clearEventHandlers.call(this);
10195 };
10196 return InternalUIInstanceManager;
10197}(UIInstanceManager));
10198/**
10199 * Wraps the player to track event handlers and provide a simple method to remove all registered event
10200 * handlers from the player.
10201 */
10202var PlayerWrapper = /** @class */ (function () {
10203 function PlayerWrapper(player) {
10204 var _this = this;
10205 this.eventHandlers = {};
10206 this.player = player;
10207 // Collect all members of the player (public API methods and properties of the player)
10208 // (Object.getOwnPropertyNames(player) does not work with the player TypeScript class starting in 7.2)
10209 var members = [];
10210 for (var member in player) {
10211 members.push(member);
10212 }
10213 // Split the members into methods and properties
10214 var methods = [];
10215 var properties = [];
10216 for (var _i = 0, members_1 = members; _i < members_1.length; _i++) {
10217 var member = members_1[_i];
10218 if (typeof player[member] === 'function') {
10219 methods.push(member);
10220 }
10221 else {
10222 properties.push(member);
10223 }
10224 }
10225 // Create wrapper object
10226 var wrapper = {};
10227 var _loop_1 = function (method) {
10228 wrapper[method] = function () {
10229 // console.log('called ' + member); // track method calls on the player
10230 return player[method].apply(player, arguments);
10231 };
10232 };
10233 // Add function wrappers for all API methods that do nothing but calling the base method on the player
10234 for (var _a = 0, methods_1 = methods; _a < methods_1.length; _a++) {
10235 var method = methods_1[_a];
10236 _loop_1(method);
10237 }
10238 var _loop_2 = function (property) {
10239 // Get an eventually existing property descriptor to differentiate between plain properties and properties with
10240 // getters/setters.
10241 var propertyDescriptor = Object.getOwnPropertyDescriptor(player, property) ||
10242 Object.getOwnPropertyDescriptor(Object.getPrototypeOf(player), property);
10243 // If the property has getters/setters, wrap them accordingly...
10244 if (propertyDescriptor && (propertyDescriptor.get || propertyDescriptor.set)) {
10245 Object.defineProperty(wrapper, property, {
10246 get: function () { return propertyDescriptor.get.call(player); },
10247 set: function (value) { return propertyDescriptor.set.call(player, value); },
10248 });
10249 }
10250 // ... else just transfer the property to the wrapper
10251 else {
10252 wrapper[property] = player[property];
10253 }
10254 };
10255 // Add all public properties of the player to the wrapper
10256 for (var _b = 0, properties_1 = properties; _b < properties_1.length; _b++) {
10257 var property = properties_1[_b];
10258 _loop_2(property);
10259 }
10260 // Explicitly add a wrapper method for 'addEventHandler' that adds added event handlers to the event list
10261 wrapper.addEventHandler = function (eventType, callback) {
10262 // in player V8 addEventHandler was replaced by on
10263 if (player.on) {
10264 player.on(eventType, callback);
10265 }
10266 else {
10267 // keep backward compatibility for versions <7.7
10268 player.addEventHandler(eventType, callback);
10269 }
10270 if (!_this.eventHandlers[eventType]) {
10271 _this.eventHandlers[eventType] = [];
10272 }
10273 _this.eventHandlers[eventType].push(callback);
10274 return wrapper;
10275 };
10276 // Explicitly add a wrapper method for 'removeEventHandler' that removes removed event handlers from the event list
10277 wrapper.removeEventHandler = function (eventType, callback) {
10278 if (player.off) {
10279 player.off(eventType, callback);
10280 }
10281 else {
10282 // keep backward compatibility for versions <7.7
10283 player.removeEventHandler(eventType, callback);
10284 }
10285 if (_this.eventHandlers[eventType]) {
10286 arrayutils_1.ArrayUtils.remove(_this.eventHandlers[eventType], callback);
10287 }
10288 return wrapper;
10289 };
10290 wrapper.fireEventInUI = function (event, data) {
10291 if (_this.eventHandlers[event]) { // check if there are handlers for this event registered
10292 // Extend the data object with default values to convert it to a {@link PlayerEvent} object.
10293 var playerEventData = Object.assign({}, {
10294 timestamp: Date.now(),
10295 type: event,
10296 // Add a marker property so the UI can detect UI-internal player events
10297 uiSourced: true,
10298 }, data);
10299 // Execute the registered callbacks
10300 for (var _i = 0, _a = _this.eventHandlers[event]; _i < _a.length; _i++) {
10301 var callback = _a[_i];
10302 callback(playerEventData);
10303 }
10304 }
10305 };
10306 this.wrapper = wrapper;
10307 }
10308 /**
10309 * Returns a wrapped player object that can be used on place of the normal player object.
10310 * @returns {WrappedPlayer} a wrapped player
10311 */
10312 PlayerWrapper.prototype.getPlayer = function () {
10313 return this.wrapper;
10314 };
10315 /**
10316 * Clears all registered event handlers from the player that were added through the wrapped player.
10317 */
10318 PlayerWrapper.prototype.clearEventHandlers = function () {
10319 for (var eventType in this.eventHandlers) {
10320 for (var _i = 0, _a = this.eventHandlers[eventType]; _i < _a.length; _i++) {
10321 var callback = _a[_i];
10322 this.player.removeEventHandler(eventType, callback);
10323 }
10324 }
10325 };
10326 return PlayerWrapper;
10327}());
10328
10329},{"./arrayutils":1,"./browserutils":2,"./components/adclickoverlay":3,"./components/admessagelabel":4,"./components/adskipbutton":5,"./components/airplaytogglebutton":6,"./components/audioqualityselectbox":7,"./components/audiotrackselectbox":8,"./components/bufferingoverlay":9,"./components/caststatusoverlay":11,"./components/casttogglebutton":12,"./components/castuicontainer":13,"./components/closebutton":15,"./components/container":17,"./components/controlbar":18,"./components/errormessageoverlay":19,"./components/fullscreentogglebutton":20,"./components/label":24,"./components/metadatalabel":26,"./components/pictureinpicturetogglebutton":27,"./components/playbackspeedselectbox":28,"./components/playbacktimelabel":29,"./components/playbacktogglebutton":30,"./components/playbacktoggleoverlay":31,"./components/recommendationoverlay":32,"./components/seekbar":33,"./components/seekbarlabel":34,"./components/settingspanel":36,"./components/settingstogglebutton":37,"./components/spacer":38,"./components/subtitleoverlay":39,"./components/subtitleselectbox":40,"./components/subtitlesettings/subtitlesettingslabel":51,"./components/subtitlesettings/subtitlesettingsopenbutton":53,"./components/subtitlesettings/subtitlesettingspanel":54,"./components/titlebar":58,"./components/uicontainer":61,"./components/videoqualityselectbox":62,"./components/volumecontrolbutton":63,"./components/volumeslider":64,"./components/volumetogglebutton":65,"./components/vrtogglebutton":66,"./components/watermark":67,"./dom":68,"./eventdispatcher":82,"./uiutils":91}],91:[function(require,module,exports){
10330"use strict";
10331Object.defineProperty(exports, "__esModule", { value: true });
10332var container_1 = require("./components/container");
10333var UIUtils;
10334(function (UIUtils) {
10335 function traverseTree(component, visit) {
10336 var recursiveTreeWalker = function (component, parent) {
10337 visit(component, parent);
10338 // If the current component is a container, visit it's children
10339 if (component instanceof container_1.Container) {
10340 for (var _i = 0, _a = component.getComponents(); _i < _a.length; _i++) {
10341 var childComponent = _a[_i];
10342 recursiveTreeWalker(childComponent, component);
10343 }
10344 }
10345 };
10346 // Walk and configure the component tree
10347 recursiveTreeWalker(component);
10348 }
10349 UIUtils.traverseTree = traverseTree;
10350})(UIUtils = exports.UIUtils || (exports.UIUtils = {}));
10351
10352},{"./components/container":17}]},{},[85])(85)
10353});