/**
* Vimeo website support module.
* @author Moez Bouhlel <bmoez.j@gmail.com>
* @license MPL-2.0
* @copyright 2014-2017 Moez Bouhlel
*/
import Module from './Module.js';
import VP from './video-player.js';
import {
asyncGet,
} from './common.js';
/**
* Vimeo website support.
* Vimeo does embed its video player directly into the web page.
*
* URLs support:
* - [x] `http[s]?://vimeo.com/<VIDEO_ID>`
* - [x] `http[s]?://vimeo.com/<USER>`
* - [x] `http[s]?://vimeo.com/channels/<CHANNEL_NAME>`
* - [x] `http[s]?://player.vimeo.com/video/<VIDEO_ID>`
* - [ ] `http[s]?://vimeo.com/couchmode/user<USER_ID>/videos/sort:<SORT_TYPE>/<VIDEO_ID>`
*
* Other:
* - [Milestone](https://github.com/lejenome/html5-video-everywhere/milestones/Vimeo%20Support)
*
* @external
*/
class Vimeo extends Module {
constructor() {
super("vimeo");
}
onInteractive() {
this.getConfig().then((conf) => this.getVideoInfo(conf));
}
injectPlayer(conf) {
try {
let playerContainer;
let stl;
if (conf.isEmbed) {
playerContainer = document.body;
} else if (conf.isWatch) {
playerContainer =
document.getElementsByClassName("player_area")[0];
/*
if ((stl = playerContainer.children[0]) && (stl = stl.sheet) &&
(stl.cssRules.length > 0)) {
stl = stl.cssRules[0].cssText;
}
*/
} else {
playerContainer = document.getElementById("clip_" + conf.id);
}
if (!playerContainer) return;
let vp = new VP(playerContainer, this.options);
vp.srcs(conf.fmts);
vp.props({
className: conf.className,
autoplay: this.options.isAutoPlay(),
preload: this.options.getPreload(),
loop: this.options.isLoop(),
controls: true,
poster: conf.poster,
volume: this.options.getVolume(),
});
vp.tracksList(conf.tracks.map((l) => l.lang), (lang, resolve, reject) => {
let l = conf.tracks.find((l) => l.lang === lang);
if (l === undefined) {
reject();
} else {
resolve(l.direct_url || l.url);
}
});
if (stl) vp.addCSSRule(stl);
vp.setup();
if (conf.isWatch) this.brozarEvents();
} catch (e) {
this.log("Exception on changePlayer()", e.lineNumber, e.columnNumber, e.message, e.stack);
}
}
getConfig() {
return new Promise((resolve, reject) => {
let isWatch =
/https?:\/\/vimeo.com\/[\d]+/.test(location.href) || this.ogType().indexOf("video") > -1;
let isEmbed = /https?:\/\/player.vimeo.com\/video/.test(location.href);
let isChannel = !isWatch && (/https?:\/\/vimeo.com\/(channels\/|)\w+/.test(location.href) ||
this.ogType().match(/channel|profile/) !== null);
if (!isWatch && !isChannel && !isEmbed) reject();
let playerId;
let playerClass;
if (isWatch) {
playerId = location.pathname.match(/\/([\d]+)/)[1];
playerClass = "player";
} else if (isEmbed) {
playerId = location.pathname.match(/video\/([\d]+)/)[1];
playerClass = "fallback";
} else if (isChannel) {
playerClass = "player";
}
if (!playerId && !isChannel) reject();
resolve({
isWatch: isWatch,
isEmbed: isEmbed,
isChannel: isChannel,
id: playerId,
className: playerClass,
});
});
}
getVideoInfo(conf) {
const INFO_URL = "https://player.vimeo.com/video/";
if (conf.isChannel) {
return Array.map(document.getElementsByClassName("player_container"), (el) => {
let _conf = {};
for (const k of Object.keys(conf)) {
_conf[k] = conf[k];
}
_conf.id = el.id.replace("clip_", "");
return asyncGet(INFO_URL + _conf.id + "/config")
.then(this.processData(_conf))
.then((conf) => this.injectPlayer(conf));
});
} else {
return asyncGet(INFO_URL + conf.id + "/config")
.then(this.processData(conf))
.then((conf) => this.injectPlayer(conf));
}
}
processData(conf) {
return (data) => {
data = JSON.parse(data);
conf.fmts = this.getSrcs(data.request.files.progressive);
conf.poster = data.video.thumbs.base;
conf.tracks = data.request.text_tracks || [];
return Promise.resolve(conf);
};
}
getSrcs(progressive) {
let fmts = {};
let srcs = {};
Array.forEach(progressive, (v) => {
srcs[v.quality] = v.url;
});
for (const [q, fmt] of [
["270p", "low/mp4"],
["360p", "medium/mp4"],
["720p", "high/mp4"],
["1028p", "higher/mp4"],
]) {
if (srcs[q]) fmts[fmt] = srcs[q];
}
return fmts;
}
brozarEvents() {
// change Vimeo default click events of items on brozar element
let clips = document.getElementById("clips");
if (clips) {
clips.onclick = function(e) {
if (e.target === e.currentTarget) return;
let li = e.target;
while (li.tagName !== "LI") {
li = li.parentElement;
}
window.location = "/" + li.id.replace("clip_", "");
};
}
let promos = document.getElementsByClassName("js-promo_link");
let promoClick = function(e) {
window.location = "/" + e.currentTarget.dataset.clipId;
};
for (let i = 0; promos && i < promos.length; i++) {
promos[i].onclick = promoClick;
}
}
ogType() {
let t = document.head.querySelector("meta[property=\"og:type\"]");
return (t) ? t.content : "";
}
}
new Vimeo().start();