/**
* @file poster-image.js
*/
import ClickableComponent from './clickable-component.js';
import Component from './component.js';
import * as Dom from './utils/dom.js';
import {silencePromise} from './utils/promise';
/** @import Player from './player' */
/**
* A `ClickableComponent` that handles showing the poster image for the player.
*
* @extends ClickableComponent
*/
class PosterImage extends ClickableComponent {
/**
* Create an instance of this class.
*
* @param {Player} player
* The `Player` that this class should attach to.
*
* @param {Object} [options]
* The key/value store of player options.
*/
constructor(player, options) {
super(player, options);
this.update();
this.update_ = (e) => this.update(e);
player.on('posterchange', this.update_);
}
/**
* Clean up and dispose of the `PosterImage`.
*/
dispose() {
this.player().off('posterchange', this.update_);
super.dispose();
}
/**
* Create the `PosterImage`s DOM element.
*
* @return {Element}
* The element that gets created.
*/
createEl() {
// The el is an empty div to keep position in the DOM
// A picture and img el will be inserted when a source is set
return Dom.createEl('div', { className: 'vjs-poster'});
}
/**
* Get or set the `PosterImage`'s crossOrigin option.
*
* @param {string|null} [value]
* The value to set the crossOrigin to. If an argument is
* given, must be one of `'anonymous'` or `'use-credentials'`, or 'null'.
*
* @return {string|null}
* - The current crossOrigin value of the `Player` when getting.
* - undefined when setting
*/
crossOrigin(value) {
// `null` can be set to unset a value
if (typeof value === 'undefined') {
if (this.$('img')) {
// If the poster's element exists, give its value
return this.$('img').crossOrigin;
} else if (this.player_.tech_ && this.player_.tech_.isReady_) {
// If not but the tech is ready, query the tech
return this.player_.crossOrigin();
}
// Otherwise check options as the poster is usually set before the state of crossorigin
// can be retrieved by the getter
return this.player_.options_.crossOrigin || this.player_.options_.crossorigin || null;
}
if (value !== null && value !== 'anonymous' && value !== 'use-credentials') {
this.player_.log.warn(`crossOrigin must be null, "anonymous" or "use-credentials", given "${value}"`);
return;
}
if (this.$('img')) {
this.$('img').crossOrigin = value;
}
return;
}
/**
* An {@link EventTarget~EventListener} for {@link Player#posterchange} events.
*
* @listens Player#posterchange
*
* @param {Event} [event]
* The `Player#posterchange` event that triggered this function.
*/
update(event) {
const url = this.player().poster();
this.setSrc(url);
// If there's no poster source we should display:none on this component
// so it's not still clickable or right-clickable
if (url) {
this.show();
} else {
this.hide();
}
}
/**
* Set the source of the `PosterImage` depending on the display method. (Re)creates
* the inner picture and img elementss when needed.
*
* @param {string} [url]
* The URL to the source for the `PosterImage`. If not specified or falsy,
* any source and ant inner picture/img are removed.
*/
setSrc(url) {
if (!url) {
this.el_.textContent = '';
return;
}
if (!this.$('img')) {
this.el_.appendChild(Dom.createEl(
'picture', {
className: 'vjs-poster',
// Don't want poster to be tabbable.
tabIndex: -1
},
{},
Dom.createEl('img', {
loading: 'lazy',
crossOrigin: this.crossOrigin()
}, {
alt: ''
})
));
}
this.$('img').src = url;
}
/**
* An {@link EventTarget~EventListener} for clicks on the `PosterImage`. See
* {@link ClickableComponent#handleClick} for instances where this will be triggered.
*
* @listens tap
* @listens click
* @listens keydown
*
* @param {Event} event
+ The `click`, `tap` or `keydown` event that caused this function to be called.
*/
handleClick(event) {
// We don't want a click to trigger playback when controls are disabled
if (!this.player_.controls()) {
return;
}
if (this.player_.tech(true)) {
this.player_.tech(true).focus();
}
if (this.player_.paused()) {
silencePromise(this.player_.play());
} else {
this.player_.pause();
}
}
}
/**
* Get or set the `PosterImage`'s crossorigin option. For the HTML5 player, this
* sets the `crossOrigin` property on the `<img>` tag to control the CORS
* behavior.
*
* @param {string|null} [value]
* The value to set the `PosterImages`'s crossorigin to. If an argument is
* given, must be one of `anonymous` or `use-credentials`.
*
* @return {string|null|undefined}
* - The current crossorigin value of the `Player` when getting.
* - undefined when setting
*/
PosterImage.prototype.crossorigin = PosterImage.prototype.crossOrigin;
Component.registerComponent('PosterImage', PosterImage);
export default PosterImage;