@ebay/ebayui-core
Version:
Collection of core eBay components; considered to be the building blocks for all composite structures, pages & apps.
399 lines (398 loc) • 14.8 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getElements = getElements;
/**
* Builds a time string, e.g., 01:04:23, from |displayTime|.
*
* @param {number} displayTime (in seconds)
* @param {boolean} showHour
* @return {string}
*/
function buildTimeString(displayTime, showHour) {
const h = Math.floor(displayTime / 3600);
const m = Math.floor((displayTime / 60) % 60);
let s = Math.floor(displayTime % 60);
if (s < 10) {
s = "0" + s;
}
let text = m + ":" + s;
if (showHour) {
if (m < 10) {
text = "0" + text;
}
text = h + ":" + text;
}
return text;
}
/**
* Depending on the value of display, sets/removes the css class of element to
* either display it or hide it.
*
* @param {Element} element
* @param {boolean} display
*/
function setDisplay(element, display) {
if (!element) {
return;
}
if (display) {
// Removing a non-existent class doesn't throw, so, even if
// the element is not hidden, this should be fine.
element.classList.remove("shaka-hidden");
}
else {
element.classList.add("shaka-hidden");
}
}
/* eslint-disable no-undef,new-cap */
// Have to contain in order to not execute until shaka is downloaded
function getElements(self) {
self.shaka.ui.Utils = self.shaka.ui.Utils || {
setDisplay,
buildTimeString,
};
const Report = class extends self.shaka.ui.Element {
constructor(parent, controls) {
super(parent, controls);
if (!self.input.reportText || !self.input.a11yReportText) {
return;
}
// The actual button that will be displayed
this.button_ = document.createElement("button");
this.button_.classList.add("video-player__report-button");
const flagIcon = self
.getComponent("flag-icon")
.el.cloneNode(true);
this.button_.prepend(flagIcon);
this.parent.appendChild(this.button_);
this.eventManager.listen(this.button_, "click", () => {
self.emit("report");
});
}
};
Report.Factory = class {
create(rootElement, controls) {
return new Report(rootElement, controls);
}
};
const TextSelection = self.shaka.ui.TextSelection;
TextSelection.Factory = class {
/** @override */
create(rootElement, controls) {
return new self.shaka.ui.TextSelection(rootElement, controls);
}
};
/**
* @extends {shaka.ui.Element}
* @final
* @export
*/
const CurrentTime = class extends self.shaka.ui.Element {
/**
* @param {!HTMLElement} parent
* @param {!shaka.ui.Controls} controls
*/
constructor(parent, controls) {
super(parent, controls);
/** @type {!HTMLButtonElement} */
this.currentTime_ = document.createElement("button");
this.currentTime_.classList.add("shaka-current-time");
this.currentTime_.disabled = true;
this.setValue_("0:00");
this.parent.appendChild(this.currentTime_);
this.eventManager.listen(this.currentTime_, "click", () => {
// Jump to LIVE if the user clicks on the current time.
if (this.player.isLive()) {
this.video.currentTime = this.player.seekRange().end;
}
});
this.eventManager.listen(this.controls, "timeandseekrangeupdated", () => {
this.updateTime_();
});
this.eventManager.listen(this.player, "trackschanged", () => {
this.onTracksChanged_();
});
}
/**
* @param {string} value
* @private
*/
setValue_(value) {
// To avoid constant updates to the DOM, which makes debugging more
// difficult, only set the value if it has changed. If we don't do this
// check, the DOM updates constantly, this element flashes in the debugger
// in Chrome, and you can't make changes in the CSS panel.
if (value != this.currentTime_.textContent) {
this.currentTime_.textContent = value;
}
}
/** @private */
updateTime_() {
const isSeeking = this.controls.isSeeking();
let displayTime = this.controls.getDisplayTime();
const seekRange = this.player.seekRange();
const seekRangeSize = seekRange.end - seekRange.start;
if (!isFinite(seekRangeSize)) {
this.setValue_(this.localization.resolve(self.shaka.ui.Locales.Ids.LIVE));
}
else if (this.player.isLive()) {
// The amount of time we are behind the live edge.
const behindLive = Math.floor(seekRange.end - displayTime);
displayTime = Math.max(0, behindLive);
const showHour = seekRangeSize >= 3600;
// Consider "LIVE" when less than 1 second behind the live-edge. Always
// show the full time string when seeking, including the leading '-';
// otherwise, the time string "flickers" near the live-edge.
// The button should only be clickable when it's live stream content, and
// the current play time is behind live edge.
if (displayTime >= 1 || isSeeking) {
this.setValue_("- " + buildTimeString(displayTime, showHour));
}
else {
this.setValue_(this.localization.resolve(self.shaka.ui.Locales.Ids.LIVE));
}
}
else {
const showHour = seekRangeSize >= 3600;
const currentTime = Math.max(0, displayTime - seekRange.start);
let value = buildTimeString(currentTime, showHour);
this.setValue_(value);
}
}
/**
* Set the aria label to be 'Live' when the content is live stream.
* @private
*/
onTracksChanged_() {
if (this.player.isLive()) {
const ariaLabel = self.shaka.ui.Locales.Ids.SKIP_TO_LIVE;
this.currentTime_.ariaLabel =
this.localization.resolve(ariaLabel);
}
}
};
/**
* @implements {shaka.extern.IUIElement.Factory}
* @final
*/
CurrentTime.Factory = class {
/** @override */
create(rootElement, controls) {
return new CurrentTime(rootElement, controls);
}
};
/**
* @extends {shaka.ui.Element}
* @final
* @export
*/
const TotalTime = class extends self.shaka.ui.Element {
/**
* @param {!HTMLElement} parent
* @param {!shaka.ui.Controls} controls
*/
constructor(parent, controls) {
super(parent, controls);
/** @type {!HTMLButtonElement} */
this.currentTime_ = document.createElement("button");
this.currentTime_.classList.add("shaka-current-time");
this.currentTime_.disabled = true;
this.parent.appendChild(this.currentTime_);
this.eventManager.listen(this.controls, "timeandseekrangeupdated", () => {
this.updateTime_();
});
this.eventManager.listen(this.player, "trackschanged", () => {
this.onTracksChanged_();
});
}
/**
* @param {string} value
* @private
*/
setValue_(value) {
// To avoid constant updates to the DOM, which makes debugging more
// difficult, only set the value if it has changed. If we don't do this
// check, the DOM updates constantly, this element flashes in the debugger
// in Chrome, and you can't make changes in the CSS panel.
if (value != this.currentTime_.textContent) {
this.currentTime_.textContent = value;
}
}
/** @private */
updateTime_() {
const seekRange = this.player.seekRange();
const seekRangeSize = seekRange.end - seekRange.start;
if (isFinite(seekRangeSize) && seekRangeSize) {
const showHour = seekRangeSize >= 3600;
this.setValue_(buildTimeString(seekRangeSize, showHour));
}
}
/**
* Set the aria label to be 'Live' when the content is live stream.
* @private
*/
onTracksChanged_() {
if (this.player.isLive()) {
const ariaLabel = self.shaka.ui.Locales.Ids.SKIP_TO_LIVE;
this.currentTime_.ariaLabel =
this.localization.resolve(ariaLabel);
}
}
};
/**
* @implements {shaka.extern.IUIElement.Factory}
* @final
*/
TotalTime.Factory = class {
/** @override */
create(rootElement, controls) {
return new TotalTime(rootElement, controls);
}
};
const MuteButton = class extends self.shaka.ui.Element {
/**
* @param {!HTMLElement} parent
* @param {!shaka.ui.Controls} controls
*/
constructor(parent, controls) {
super(parent, controls);
/** @private {!HTMLButtonElement} */
this.button_ = document.createElement("button");
this.button_.classList.add("shaka-mute-button");
this.button_.classList.add("shaka-tooltip");
this.audioOff = self
.getComponent("audio-off-icon")
.el.cloneNode(true);
this.audioHigh = self
.getComponent("audio-high-icon")
.el.cloneNode(true);
/** @private {!HTMLElement} */
this.icon_ = this.audioOff.cloneNode(true);
this.button_.appendChild(this.icon_);
/** @private {!HTMLElement} */
this.currentState_ = document.createElement("span");
this.currentState_.classList.add("shaka-current-selection-span");
this.parent.appendChild(this.button_);
this.updateIcon_();
this.eventManager.listen(this.button_, "click", () => {
if (!this.video.muted && this.video.volume == 0) {
this.video.volume = 1;
}
else {
this.video.muted = !this.video.muted;
}
});
this.eventManager.listen(this.video, "volumechange", () => {
this.updateIcon_();
});
}
/**
* @private
*/
updateIcon_() {
const icon = this.video.muted || this.video.volume == 0
? this.audioOff
: this.audioHigh;
this.button_.childNodes[0].replaceWith(icon);
}
};
/**
* @implements {shaka.extern.IUIElement.Factory}
* @final
*/
MuteButton.Factory = class {
/** @override */
create(rootElement, controls) {
return new MuteButton(rootElement, controls);
}
};
/**
* @extends {shaka.ui.Element}
* @final
* @export
*/
const FullscreenButton = class extends self.shaka.ui.Element {
/**
* @param {!HTMLElement} parent
* @param {!shaka.ui.Controls} controls
*/
constructor(parent, controls) {
super(parent, controls);
/** @private {HTMLMediaElement} */
this.localVideo_ = this.controls.getLocalVideo();
this.fullscreenIcon = self
.getComponent("expand-icon")
.el.cloneNode(true);
this.exitFullscreenIcon = self
.getComponent("contract-icon")
.el.cloneNode(true);
/** @private {!HTMLButtonElement} */
this.button_ = document.createElement("button");
this.button_.classList.add("shaka-fullscreen-button");
this.button_.classList.add("shaka-tooltip");
this.checkSupport_();
this.button_.appendChild(this.fullscreenIcon);
this.parent.appendChild(this.button_);
this.eventManager.listen(this.button_, "click", () => __awaiter(this, void 0, void 0, function* () {
yield this.controls.toggleFullScreen();
}));
this.eventManager.listen(document, "fullscreenchange", () => {
this.updateIcon_();
});
this.eventManager.listen(this.localVideo_, "loadedmetadata", () => {
this.checkSupport_();
});
this.eventManager.listen(this.localVideo_, "loadeddata", () => {
this.checkSupport_();
});
}
/**
* @private
*/
checkSupport_() {
// Don't show the button if fullscreen is not supported
if (!this.controls.isFullScreenSupported()) {
this.button_.classList.add("shaka-hidden");
}
else {
this.button_.classList.remove("shaka-hidden");
}
}
/**
* @private
*/
updateIcon_() {
const icon = this.controls.isFullScreenEnabled()
? this.exitFullscreenIcon
: this.fullscreenIcon;
this.button_.childNodes[0].replaceWith(icon);
}
};
/**
* @implements {shaka.extern.IUIElement.Factory}
* @final
*/
FullscreenButton.Factory = class {
/** @override */
create(rootElement, controls) {
return new FullscreenButton(rootElement, controls);
}
};
return {
Report,
MuteButton,
CurrentTime,
TotalTime,
FullscreenButton,
TextSelection,
};
}