rizzo-next
Version:
The next generation of Lonely Planet's style guide and pattern library.
209 lines (165 loc) • 6.54 kB
JavaScript
import Brightcove from "./brightcove";
import Youtube from "./youtube";
import File from "./file";
require("./_video.scss");
let players = new Map();
players.set("brightcove", Brightcove);
players.set("youtube", Youtube);
players.set("file", File);
/*
Video - an interface for inserting video embeds onto the page and/or
creating a reference to a pre-existing video embed on the page.
example usage:
let player = null;
Video.addPlayer("element-id", {autoplay: true}).then((x) => {
player = x;
player.on("ended", () => alert("video finished playing!")));
});
parameters:
element - The HTML element to create a player in. This can be a string id for
an existing DOM element or can be a reference to a DOM element.
type - (optional) "brightcove", "youtube", or "file". This determines which type of
of embed code to generate and determines how rizzo interacts with the
player
playerName - (optional) "default", "bestintravel", "destinations", or "background". This determines
which player from the respective "type" to insert into the page. ("brightcove" only).
videoId - (optional) The id or URL of the video to play. This can be either an id
pertaining to the platform depicted by the 'type' parameter, or it can
be a URL to a video (which will be parsed internally to get the video id if needed)
autoplay - (optional) Whether the player should autoplay once it's ready/loaded
poster - (optional) URL to poster image to display before video begins
playing ("file" only)
seo - (optional) Whether to render SEO markup for the video ("brightcove" only)
controls - (optional) Whether to include HTML5 video controls on the player or
not ("brightcove" and "file" only)
popout - (optional) Whether the player should follow the user when it scrolls
out of view ("brightcove" only) -- Only works if the video embed does not
exist on the page prior to instantiation.
cover - (optional) Whether to cover the entire parent element with the
video -- acts similar to background-size css. ("file" and "brightcove" only)
muted - (optional) Whether the video should be muted or not ("file" and "brightcove" only).
playsInline - (optional) Whether the video should play inline on mobile devices or popout into
the device's native player ("file" and "brightcove" only)
playWhenInView - (optional) Whether to play the video automatically once the
player enters the viewport. ("brightcove" only)
pauseWhenOutOfView - (optional) Whether to pause the video automatically once the
player leaves the viewport. ("brightcove" only)
outOfViewThreshold - (optional | default: 0.5 | Decimal between 0 and 1)
Determines how much of the player should be outside of the viewport to be considered
"out of view". Use this alongside "playsWhenInView" and/or "pauseWhenOutOfView".
("brightcove" only)
insertPixel - (optional) Whether to fetch a tracking pixel from the video's
"custom fields" and insert the pixel onto the page. ("brightcove" only)
events:
"ready" - Player has finished loading and is ready to be interacted with
"disposed" - Player has been torn down and removed from the page
"loadstart" - Video has finished loading and is ready to play ("brightcove" only)
"started" - Video playback has either started OR Ad playback has started ("brightcove" and "file" only)
"ended" - Player has finished playing the current video ("brightcove" and "file" only)
*/
class Video {
static addPlayer(element, {
type = "brightcove",
playerName = "default",
videoId = null,
autoplay = false,
poster = null,
controls = true,
seo = true,
popout = false,
cover = false,
muted = false,
playsInline = false,
playWhenInView = false,
pauseWhenOutOfView = false,
outOfViewThreshold = 0.5,
insertPixel = true,
} = {}) {
if (typeof element === "string") {
element = document.getElementById(element);
}
if (!element) {
return;
}
type = this.cleanVideoType(type, videoId);
videoId = this.cleanVideoId(videoId);
this.players = this.players || new Map();
let PlayerConstructor = players.get(type),
player = new PlayerConstructor({
el: element,
playerId: this.players.size + 1,
videoId,
autoplay,
poster,
controls,
playerName,
seo,
popout,
cover,
muted,
playsInline,
playWhenInView,
pauseWhenOutOfView,
outOfViewThreshold,
insertPixel,
});
this.players.set(element, player);
player.on("disposed", this.removePlayer.bind(this));
// Take the return value and use .then() on it to ensure the
// player is ready before using it.
return new Promise((resolve) => {
if (player.isReady) {
resolve(player);
return;
}
player.on("ready", () => {
resolve(player);
});
});
}
static removePlayer(player) {
if (this.players) {
this.players.delete(player.el);
}
}
static cleanVideoType(type, videoId) {
if (videoId && videoId.toLowerCase().startsWith("http")) {
const youtubeId = this.getYoutubeId(videoId);
const brightcoveId = this.getBrightcoveId(videoId);
if (youtubeId) {
return "youtube";
}
if (brightcoveId) {
return "brightcove";
}
if (!youtubeId && !brightcoveId) {
return "file";
}
}
return type;
}
static cleanVideoId(videoId) {
if (videoId && videoId.toLowerCase().startsWith("http")) {
const youtubeId = this.getYoutubeId(videoId);
const brightcoveId = this.getBrightcoveId(videoId);
if (youtubeId) {
return youtubeId;
}
if (brightcoveId) {
return brightcoveId;
}
}
return videoId;
}
static getYoutubeId(url) {
const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
const match = url.match(regExp);
return match && match[2].length == 11 ? match[2] : null;
}
static getBrightcoveId(url) {
const regExp = /^.*\.brightcove\..*(\/videos\/|\?videoId=)([0-9]+).*/;
const match = url.match(regExp);
return match ? match[2] : null;
}
}
export default Video;