bitmovin-player-ui
Version:
Bitmovin Player UI Framework
130 lines (110 loc) • 3.74 kB
text/typescript
import { Component, ComponentConfig } from './Component';
import { ExternalRecommendationLink, RecommendationConfig } from '../UIConfig';
import { EventDispatcher, NoArgs, Event } from '../EventDispatcher';
import { PlayerAPI, SourceConfig } from 'bitmovin-player';
import { UIInstanceManager } from '../UIManager';
import { DOM } from '../DOM';
import { Label } from './labels/Label';
import { StringUtils } from '../utils/StringUtils';
/**
* Configuration interface for the {@link RecommendationItem}
*/
export interface RecommendationItemConfig extends ComponentConfig {
/**
* The recommendation configuration for this item.
*/
recommendationConfig: RecommendationConfig;
}
/**
* An item of the {@link RecommendationOverlay}.
*/
export class RecommendationItem extends Component<RecommendationItemConfig> {
private events = {
onClick: new EventDispatcher<RecommendationItem, NoArgs>(),
};
constructor(config: RecommendationItemConfig) {
super(config);
this.config = this.mergeConfig(
config,
{
cssClass: 'ui-recommendation-item',
recommendationConfig: null, // this must be passed in from outside
tabIndex: 0,
},
this.config,
);
}
configure(player: PlayerAPI, uimanager: UIInstanceManager) {
super.configure(player, uimanager);
if (isExternalRecommendationLink(this.config.recommendationConfig.resource)) {
return;
}
this.onClick.subscribe(() => {
player.load(this.config.recommendationConfig.resource as SourceConfig);
player.play();
});
}
protected toDomElement(): DOM {
const recommendationConfig = this.config.recommendationConfig;
const recommendationResource = recommendationConfig.resource;
let tagName: string;
let additionalAttributes: { [name: string]: string } = {};
let posterUrl: string | null;
if (isExternalRecommendationLink(recommendationResource)) {
tagName = 'a';
additionalAttributes = { href: recommendationResource.url };
posterUrl = recommendationResource.thumbnail;
} else {
tagName = 'button';
posterUrl = recommendationResource.poster;
}
const itemElement = new DOM(
tagName,
{
id: this.config.id,
class: this.getCssClasses(),
...additionalAttributes,
tabindex: this.config.tabIndex.toString(),
},
this,
);
if (posterUrl) {
itemElement.css({ 'background-image': `url("${posterUrl}")` });
}
const titleElement = new DOM(
'div',
{
class: this.prefixCss('title-container'),
},
this,
);
const innerTitleElement = new Label({ text: recommendationConfig.title, cssClass: 'title' });
titleElement.append(innerTitleElement.getDomElement());
itemElement.append(titleElement);
if (recommendationConfig.duration != null) {
const timeElement = new Label({
text: recommendationConfig.duration ? StringUtils.secondsToTime(recommendationConfig.duration) : '',
cssClass: 'duration',
});
itemElement.append(timeElement.getDomElement());
}
if (!isExternalRecommendationLink(recommendationResource)) {
// Only add click handler if it's not a link already and we need to load a new source
itemElement.on('click', e => {
e.preventDefault();
e.stopPropagation();
this.onClickEvent();
});
}
return itemElement;
}
protected onClickEvent() {
this.events.onClick.dispatch(this);
}
get onClick(): Event<RecommendationItem, NoArgs> {
return this.events.onClick.getEvent();
}
}
function isExternalRecommendationLink(obj: any): obj is ExternalRecommendationLink {
return 'url' in obj;
}