cinera_player_pre.js: Add Vimeo support

Fixes

• Fix fullscreen
• Pause whenever / however following a reference or credit URL
This commit is contained in:
Matt Mascarenhas 2021-06-23 15:13:41 +01:00
parent e39a09c0ad
commit dd33bb49b3
3 changed files with 364 additions and 123 deletions

View File

@ -22,8 +22,8 @@ typedef struct
version CINERA_APP_VERSION = { version CINERA_APP_VERSION = {
.Major = 0, .Major = 0,
.Minor = 8, .Minor = 9,
.Patch = 23 .Patch = 0
}; };
#include <stdarg.h> // NOTE(matt): varargs #include <stdarg.h> // NOTE(matt): varargs
@ -2413,12 +2413,14 @@ GetIconTypeFromString(string *Filename, token *T)
char *VODPlatformStrings[] = char *VODPlatformStrings[] =
{ {
0, 0,
"vimeo",
"youtube", "youtube",
}; };
typedef enum typedef enum
{ {
VP_DEFAULT_UNSET, VP_DEFAULT_UNSET,
VP_VIMEO,
VP_YOUTUBE, VP_YOUTUBE,
VP_COUNT, VP_COUNT,
} vod_platform; } vod_platform;
@ -10604,10 +10606,25 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
CopyStringToBufferHTMLSafe(&PlayerBuffers.Menus, Wrap0(HMML.metadata.title)); CopyStringToBufferHTMLSafe(&PlayerBuffers.Menus, Wrap0(HMML.metadata.title));
CopyStringToBuffer(&PlayerBuffers.Menus, "</span>\n"); CopyStringToBuffer(&PlayerBuffers.Menus, "</span>\n");
switch(CollationBuffers->VODPlatform)
{
case VP_VIMEO:
{
CopyStringToBuffer(&PlayerBuffers.Main, "<script src=\"https://player.vimeo.com/api/player.js\"></script>\n"
" ");
} break;
case VP_YOUTUBE:
{
CopyStringToBuffer(&PlayerBuffers.Main, "<script src=\"https://www.youtube.com/iframe_api\"></script>\n"
" ");
} break;
default: break;
}
CopyStringToBuffer(&PlayerBuffers.Main, CopyStringToBuffer(&PlayerBuffers.Main,
"<div class=\"cineraPlayerContainer\">\n" "<div class=\"cineraPlayerContainer\">\n"
" <div class=\"video_container\" data-videoId=\"%s\"></div>\n" " <div class=\"video_container\" data-platform=\"%s\" data-videoId=\"%s\"></div>\n"
" <div class=\"markers_container %.*s\">\n", HMML.metadata.id, (int)CurrentProject->Theme.Length, CurrentProject->Theme.Base); " <div class=\"markers_container %.*s\">\n", VODPlatformStrings[CollationBuffers->VODPlatform], HMML.metadata.id, (int)CurrentProject->Theme.Length, CurrentProject->Theme.Base);
if(N) if(N)
{ {

View File

@ -53,6 +53,7 @@ var CineraProps = {
IsMobile: IsMobile(), IsMobile: IsMobile(),
ScrollX: null, ScrollX: null,
ScrollY: null, ScrollY: null,
VODPlatform: null,
}; };
CineraProps.O = GetRealOrientation(orientations.LANDSCAPE_LEFT, CineraProps.IsMobile); CineraProps.O = GetRealOrientation(orientations.LANDSCAPE_LEFT, CineraProps.IsMobile);
@ -252,7 +253,16 @@ if(titleBar)
setSpriteLightness(focusedElement.firstChild); setSpriteLightness(focusedElement.firstChild);
} }
} }
}) });
if(creditItems[i].tagName == "A")
{
creditItems[i].addEventListener("click", function(ev) {
if(player)
{
player.pause();
}
});
}
} }
} }
@ -379,5 +389,5 @@ if(location.hash) {
} }
else if(lastAnnotation = localStorage.getItem(lastAnnotationStorageItem)) else if(lastAnnotation = localStorage.getItem(lastAnnotationStorageItem))
{ {
player.setTime(lastAnnotation); player.setTimeThenPlay(lastAnnotation);
} }

View File

@ -1,15 +1,33 @@
// refsCallback: (optional) // refsCallback: (optional)
// Will be called when the player enters a marker that has a `data-ref` attribute. The value of `data-ref` will be passed to the function. // Will be called when the player enters a marker that has a `data-ref` attribute. The value of `data-ref` will be passed to the function.
// When leaving a marker that a `data-ref` attribute, and entering a marker without one (or not entering a new marker at all), the function will be called with `null`. // When leaving a marker that a `data-ref` attribute, and entering a marker without one (or not entering a new marker at all), the function will be called with `null`.
var vod_platform = {
VIMEO: 0,
YOUTUBE: 1,
};
function
GetVODPlatformFromString(VODPlatformString)
{
var Result = null;
switch(VODPlatformString)
{
case "vimeo": Result = vod_platform.VIMEO; break;
case "youtube": Result = vod_platform.YOUTUBE; break;
default: break;
}
return Result;
}
function Player(htmlContainer, refsCallback) { function Player(htmlContainer, refsCallback) {
this.container = htmlContainer; this.container = htmlContainer;
this.markersContainer = this.container.querySelector(".markers_container"); this.markersContainer = this.container.querySelector(".markers_container");
this.videoContainer = this.container.querySelector(".video_container"); this.videoContainer = this.container.querySelector(".video_container");
this.refsCallback = refsCallback || function() {}; this.refsCallback = refsCallback || function() {};
if (!this.videoContainer.getAttribute("data-videoId")) { if (!(this.videoContainer.getAttribute("data-platform") || this.videoContainer.getAttribute("data-videoId"))) {
console.error("Expected to find data-videoId attribute on", this.videoContainer, "for player initialized on", this.container); console.error("Expected to find data-platform and data-videoId attribute on", this.videoContainer, "for player initialized on", this.container);
throw new Error("Missing data-videoId attribute."); throw new Error("Missing data-platform or data-videoId attribute.");
} }
this.markers = []; this.markers = [];
var markerEls = this.markersContainer.querySelectorAll(".marker"); var markerEls = this.markersContainer.querySelectorAll(".marker");
@ -33,10 +51,13 @@ function Player(htmlContainer, refsCallback) {
this.markers.push(marker); this.markers.push(marker);
} }
this.vod_platform = GetVODPlatformFromString(this.videoContainer.getAttribute("data-platform"));
this.currentMarker = null; this.currentMarker = null;
this.currentMarkerIdx = null; this.currentMarkerIdx = null;
this.youtubePlayer = null;
this.youtubePlayerReady = false; this.platformPlayer = null;
this.platformPlayerReady = false;
this.playing = false; this.playing = false;
this.shouldPlay = false; this.shouldPlay = false;
this.buffering = false; this.buffering = false;
@ -53,7 +74,8 @@ function Player(htmlContainer, refsCallback) {
this.scrollTo = -1; this.scrollTo = -1;
}.bind(this)); }.bind(this));
Player.initializeYoutube(this.onYoutubeReady.bind(this)); Player.initializePlatform(this.vod_platform, this.onPlatformReady.bind(this));
var PendingMobileStyleInitialisation = true; var PendingMobileStyleInitialisation = true;
this.updateSize(PendingMobileStyleInitialisation); this.updateSize(PendingMobileStyleInitialisation);
this.resume(); this.resume();
@ -62,22 +84,42 @@ function Player(htmlContainer, refsCallback) {
// Start playing the video from the current position. // Start playing the video from the current position.
// If the player hasn't loaded yet, it will autoplay when ready. // If the player hasn't loaded yet, it will autoplay when ready.
Player.prototype.play = function() { Player.prototype.play = function() {
if (this.youtubePlayerReady) { if (this.platformPlayerReady) {
if (!this.playing) { if (!this.playing) {
this.youtubePlayer.playVideo(); switch(this.vod_platform)
{
case vod_platform.VIMEO:
{
this.platformPlayer.play();
} break;
case vod_platform.YOUTUBE:
{
this.platformPlayer.playVideo();
} break;
} }
this.pauseAfterBuffer = false; this.pauseAfterBuffer = false;
} else { } else {
this.shouldPlay = true; this.shouldPlay = true;
} }
}
}; };
// Pause the video at the current position. // Pause the video at the current position.
// If the player hasn't loaded yet, it will not autoplay when ready. (This is the default) // If the player hasn't loaded yet, it will not autoplay when ready. (This is the default)
Player.prototype.pause = function() { Player.prototype.pause = function() {
if (this.youtubePlayerReady) { if (this.platformPlayerReady) {
if (this.playing) { if (this.playing) {
this.youtubePlayer.pauseVideo(); switch(this.vod_platform)
{
case vod_platform.VIMEO:
{
this.platformPlayer.pause();
} break;
case vod_platform.YOUTUBE:
{
this.platformPlayer.pauseVideo();
} break;
}
} else if (this.buffering) { } else if (this.buffering) {
this.pauseAfterBuffer = true; this.pauseAfterBuffer = true;
} }
@ -86,15 +128,34 @@ Player.prototype.pause = function() {
} }
}; };
// Sets the current time. Does not affect play status. // Sets the current time then plays.
// If the player hasn't loaded yet, it will seek to this time when ready. // If the player hasn't loaded yet, it will seek to this time when ready.
Player.prototype.setTime = function(time) { Player.prototype.setTimeThenPlay = function(time) {
this.currentTime = time; this.currentTime = time;
if (this.youtubePlayerReady) { switch(this.vod_platform)
this.currentTime = Math.max(0, Math.min(this.currentTime, this.youtubePlayer.getDuration())); {
this.youtubePlayer.seekTo(this.currentTime); case vod_platform.VIMEO:
{
if (this.platformPlayerReady) {
this.currentTime = Math.max(0, Math.min(this.currentTime, this.duration));
var Parent = this;
this.platformPlayer.setCurrentTime(this.currentTime)
.then(function() {
Parent.updateProgress();
Parent.play();
});
} }
} break;
case vod_platform.YOUTUBE:
{
if (this.platformPlayerReady) {
this.currentTime = Math.max(0, Math.min(this.currentTime, this.duration));
this.platformPlayer.seekTo(this.currentTime);
this.updateProgress(); this.updateProgress();
this.play();
}
} break;
}
}; };
Player.prototype.jumpToNextMarker = function() { Player.prototype.jumpToNextMarker = function() {
@ -105,8 +166,7 @@ Player.prototype.jumpToNextMarker = function() {
++targetMarkerIdx; ++targetMarkerIdx;
targetTime = this.markers[targetMarkerIdx].timestamp; targetTime = this.markers[targetMarkerIdx].timestamp;
} }
this.setTime(targetTime); this.setTimeThenPlay(targetTime);
this.play();
}; };
Player.prototype.jumpToPrevMarker = function() { Player.prototype.jumpToPrevMarker = function() {
@ -117,8 +177,7 @@ Player.prototype.jumpToPrevMarker = function() {
--targetMarkerIdx; --targetMarkerIdx;
targetTime = this.markers[targetMarkerIdx].timestamp; targetTime = this.markers[targetMarkerIdx].timestamp;
} }
this.setTime(targetTime); this.setTimeThenPlay(targetTime);
this.play();
}; };
function function
@ -508,8 +567,16 @@ Player.prototype.updateSize = function() {
height = this.videoContainer.offsetHeight; height = this.videoContainer.offsetHeight;
} }
if (this.youtubePlayerReady) { switch(this.vod_platform)
this.youtubePlayer.setSize(Math.floor(width), Math.floor(height)); {
case vod_platform.VIMEO: /* NOTE(matt): It responds automatically */ break;
case vod_platform.YOUTUBE:
{
if (this.platformPlayerReady) {
this.platformPlayer.setSize(Math.floor(width), Math.floor(height));
}
} break;
default: break;
} }
} }
@ -531,7 +598,15 @@ Player.prototype.resume = function() {
} }
} }
Player.initializeYoutube = function(callback) { Player.initializePlatform = function(platform_id, callback) {
switch(platform_id)
{
case vod_platform.VIMEO:
{
callback();
} break;
case vod_platform.YOUTUBE:
{
if (window.APYoutubeAPIReady === undefined) { if (window.APYoutubeAPIReady === undefined) {
window.APYoutubeAPIReady = false; window.APYoutubeAPIReady = false;
window.APCallbacks = (callback ? [callback] : []); window.APCallbacks = (callback ? [callback] : []);
@ -541,15 +616,13 @@ Player.initializeYoutube = function(callback) {
APCallbacks[i](); APCallbacks[i]();
} }
}; };
var scriptTag = document.createElement("SCRIPT");
scriptTag.setAttribute("type", "text/javascript");
scriptTag.setAttribute("src", "https://www.youtube.com/iframe_api");
document.body.appendChild(scriptTag);
} else if (window.APYoutubeAPIReady === false) { } else if (window.APYoutubeAPIReady === false) {
window.APCallbacks.push(callback); window.APCallbacks.push(callback);
} else if (window.APYoutubeAPIReady === true) { } else if (window.APYoutubeAPIReady === true) {
callback(); callback();
} }
} break;
}
} }
// END PUBLIC INTERFACE // END PUBLIC INTERFACE
@ -559,8 +632,7 @@ Player.prototype.onMarkerClick = function(marker, ev) {
if (this.currentMarker == marker && marker.hoverx !== null) { if (this.currentMarker == marker && marker.hoverx !== null) {
time += (marker.endTime - marker.timestamp) * marker.hoverx; time += (marker.endTime - marker.timestamp) * marker.hoverx;
} }
this.setTime(time); this.setTimeThenPlay(time);
this.play();
}; };
Player.prototype.onMarkerMouseMove = function(marker, ev) { Player.prototype.onMarkerMouseMove = function(marker, ev) {
@ -634,9 +706,24 @@ Player.prototype.updateProgress = function() {
Player.prototype.doFrame = function() { Player.prototype.doFrame = function() {
if (this.playing) { if (this.playing) {
this.currentTime = this.youtubePlayer.getCurrentTime(); switch(this.vod_platform)
} {
case vod_platform.VIMEO:
{
var Parent = this;
this.platformPlayer.getCurrentTime()
.then(function(Result) {
Parent.currentTime = Result;
Parent.updateProgress();
});
} break;
case vod_platform.YOUTUBE:
{
this.currentTime = this.platformPlayer.getCurrentTime();
this.updateProgress(); this.updateProgress();
} break;
}
}
if (this.scrollTo >= 0) { if (this.scrollTo >= 0) {
var targetPosition = this.scrollTo - this.markersContainer.offsetHeight/2.0; var targetPosition = this.scrollTo - this.markersContainer.offsetHeight/2.0;
@ -654,68 +741,182 @@ Player.prototype.doFrame = function() {
updateLink(); updateLink();
}; };
Player.prototype.onYoutubePlayerReady = function() { Player.prototype.setStyleAndQuality = function() {
this.youtubePlayerReady = true; switch(this.vod_platform)
this.markers[this.markers.length-1].endTime = this.youtubePlayer.getDuration(); {
case vod_platform.VIMEO:
{
this.platformPlayer.setQuality("1080p");
var frame = this.videoContainer.querySelector("iframe");
frame.style.width = "100%";
frame.style.height = "100%";
frame.style.position = "absolute"
frame.style.top = 0;
frame.style.left = 0;
} break;
case vod_platform.YOUTUBE:
{
this.platformPlayer.setPlaybackQuality("hd1080");
} break;
}
this.updateSize(); this.updateSize();
this.youtubePlayer.setPlaybackQuality("hd1080"); }
Player.prototype.setDurationThenAutoplay = function(Duration) {
this.duration = Duration;
this.markers[this.markers.length-1].endTime = this.duration;
if (this.currentTime > 0) { if (this.currentTime > 0) {
this.currentTime = Math.max(0, Math.min(this.currentTime, this.youtubePlayer.getDuration())); this.currentTime = Math.max(0, Math.min(this.currentTime, this.duration));
this.youtubePlayer.seekTo(this.currentTime, true); this.setTimeThenPlay(this.currentTime);
} }
if (this.shouldPlay) { if (this.shouldPlay) {
this.youtubePlayer.playVideo(); this.play();
} }
}
Player.prototype.acquireDurationThenAutoplay = function() {
switch(this.vod_platform)
{
case vod_platform.VIMEO:
{
var Parent = this;
this.platformPlayer.getDuration()
.then(function(Response)
{
Parent.setDurationThenAutoplay(Response);
});
} break;
case vod_platform.YOUTUBE:
{
this.setDurationThenAutoplay(this.platformPlayer.getDuration());
} break;
}
}
Player.prototype.onPlatformPlayerReady = function() {
this.platformPlayerReady = true;
this.setStyleAndQuality();
this.acquireDurationThenAutoplay();
}; };
Player.prototype.onYoutubePlayerStateChange = function(ev) { Player.prototype.onPlaybackRateChange = function(Rate)
if (ev.data == YT.PlayerState.PLAYING) { {
this.playing = true; this.speed = Rate;
this.currentTime = this.youtubePlayer.getCurrentTime(); }
} else {
Player.prototype.onVimeoPlayerPlaybackRateChange = function(ev) {
this.onPlaybackRateChange(ev.playbackRate);
};
Player.prototype.onYouTubePlayerPlaybackRateChange = function(ev) {
this.onPlaybackRateChange(ev.data);
};
Player.prototype.onStateBufferStart = function()
{
this.buffering = true;
this.playing = false; this.playing = false;
if (ev.data == YT.PlayerState.PAUSED || ev.data == YT.PlayerState.BUFFERING) {
this.currentTime = this.youtubePlayer.getCurrentTime();
this.updateProgress(); this.updateProgress();
} else if (ev.data == YT.PlayerState.ENDED) { }
Player.prototype.onStateBufferEnd = function()
{
this.buffering = false;
this.updateProgress();
}
Player.prototype.onStateEnded = function()
{
this.buffering = false;
this.playing = false;
localStorage.removeItem(lastAnnotationStorageItem); localStorage.removeItem(lastAnnotationStorageItem);
this.currentTime = null; this.currentTime = null;
this.updateProgress(); this.updateProgress();
} }
Player.prototype.onStatePaused = function(CurrentTime)
{
this.buffering = false;
this.playing = false;
this.currentTime = CurrentTime;
this.updateProgress();
} }
this.buffering = ev.data == YT.PlayerState.BUFFERING; Player.prototype.onStatePlaying = function(CurrentTime)
if (this.playing && this.pauseAfterBuffer) { {
this.pauseAfterBuffering = false; this.buffering = false;
this.playing = true;
this.currentTime = CurrentTime;
if(this.pauseAfterBuffer)
{
this.pauseAfterBuffer = false;
this.pause(); this.pause();
} }
}
Player.prototype.onVimeoPlayerStateChange_Paused = function(ev)
{
this.onStatePaused(ev.seconds);
}
Player.prototype.onVimeoPlayerStateChange_Playing = function(ev)
{
this.onStatePlaying(ev.seconds);
}
Player.prototype.onYouTubePlayerStateChange = function(ev) {
switch(ev.data)
{
case YT.PlayerState.BUFFERING: { this.onStateBufferStart(); }; break;
case YT.PlayerState.ENDED: { this.onStateEnded(); }; break;
case YT.PlayerState.PAUSED: { this.onStatePaused(this.platformPlayer.getCurrentTime()); }; break;
case YT.PlayerState.PLAYING: { this.onStatePlaying(this.platformPlayer.getCurrentTime()); }; break;
default: break;
}
}; };
Player.prototype.onYoutubePlayerPlaybackRateChange = function(ev) { Player.prototype.onPlatformReady = function() {
this.speed = ev.data; var platformPlayerDiv = document.createElement("DIV");
}; platformPlayerDiv.id = "platform_player_" + Player.platformPlayerCount++;
this.videoContainer.appendChild(platformPlayerDiv);
Player.prototype.onYoutubeReady = function() { switch(this.vod_platform)
var youtubePlayerDiv = document.createElement("DIV"); {
youtubePlayerDiv.id = "youtube_player_" + Player.youtubePlayerCount++; case vod_platform.VIMEO:
this.videoContainer.appendChild(youtubePlayerDiv); {
this.youtubePlayer = new YT.Player(youtubePlayerDiv.id, { this.videoContainer.style.position = "relative";
this.videoContainer.style.alignSelf = "unset";
this.platformPlayer = new Vimeo.Player(platformPlayerDiv.id, {
id: this.videoContainer.getAttribute("data-videoId"),
title: false,
});
this.platformPlayer.ready()
.then(this.onPlatformPlayerReady.bind(this));
this.platformPlayer.on("playbackratechange", this.onVimeoPlayerPlaybackRateChange.bind(this));
this.platformPlayer.on("play", this.onVimeoPlayerStateChange_Playing.bind(this));
this.platformPlayer.on("pause", this.onVimeoPlayerStateChange_Paused.bind(this));
this.platformPlayer.on("bufferstart", this.onStateBufferStart.bind());
this.platformPlayer.on("bufferend", this.onStateBufferEnd.bind());
this.platformPlayer.on("ended", this.onStateEnded.bind());
} break;
case vod_platform.YOUTUBE:
{
this.platformPlayer = new YT.Player(platformPlayerDiv.id, {
videoId: this.videoContainer.getAttribute("data-videoId"), videoId: this.videoContainer.getAttribute("data-videoId"),
width: this.videoContainer.offsetWidth, width: this.videoContainer.offsetWidth,
height: this.videoContainer.offsetWidth / 16 * 9, height: this.videoContainer.offsetWidth / 16 * 9,
playerVars: { 'playsinline': 1 }, playerVars: { 'playsinline': 1 },
//playerVars: { disablekb: 1 },
events: { events: {
"onReady": this.onYoutubePlayerReady.bind(this), "onReady": this.onPlatformPlayerReady.bind(this),
"onStateChange": this.onYoutubePlayerStateChange.bind(this), "onStateChange": this.onYouTubePlayerStateChange.bind(this),
"onPlaybackRateChange": this.onYoutubePlayerPlaybackRateChange.bind(this) "onPlaybackRateChange": this.onYouTubePlayerPlaybackRateChange.bind(this)
} }
}); });
} break;
}
}; };
Player.youtubePlayerCount = 0; Player.platformPlayerCount = 0;
// NOTE(matt): Hereafter is my stuff. Beware!
function toggleFilterMode() { function toggleFilterMode() {
if(filterMode == "inclusive") if(filterMode == "inclusive")
@ -750,7 +951,21 @@ function updateLink()
} }
else else
{ {
link.value = baseURL + "#" + Math.round(player.youtubePlayer.getCurrentTime()); switch(player.vod_platform)
{
case vod_platform.VIMEO:
{
player.platformPlayer.getCurrentTime()
.then(function(Response)
{
link.value = baseURL + "#" + Math.round(Response);
});
} break;
case vod_platform.YOUTUBE:
{
link.value = baseURL + "#" + Math.round(player.platformPlayer.getCurrentTime());
} break;
}
} }
} }
} }
@ -891,30 +1106,30 @@ function handleMouseOverViewsMenu()
} }
} }
function IsFullScreen()
{
return (document.fullscreen || document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement || document.fullscreenElement);
}
function enterFullScreen_() function enterFullScreen_()
{ {
if(!document.mozFullScreen && !document.webkitFullScreen) if(!IsFullScreen())
{ {
if(document.mozRequestFullScreen) if(document.body.requestFullscreen) { document.body.requestFullscreen(); }
{ else if(document.body.mozRequestFullScreen) { document.body.mozRequestFullScreen(); }
document.mozRequestFullScreen(); else if(document.body.webkitRequestFullScreen) { document.body.webkitRequestFullScreen(); }
} else if(document.body.msRequestFullscreen) { document.body.msRequestFullscreen(); }
else
{
document.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
}
} }
} }
function leaveFullScreen_() function leaveFullScreen_()
{ {
if(document.mozCancelFullScreen) if(IsFullScreen())
{ {
document.mozCancelFullScreen(); if(document.exitFullscreen) { document.exitFullscreen(); }
} else if(document.mozCancelFullScreen) { document.mozCancelFullScreen(); }
else else if(document.webkitCancelFullScreen) { document.webkitCancelFullScreen(); }
{ else if(document.msExitFullscreen) { document.msExitFullscreen(); }
document.webkitExitFullscreen();
} }
} }
@ -1083,14 +1298,12 @@ function handleKey(key) {
if(focusedElement.parentNode.classList.contains("quotes_container")) if(focusedElement.parentNode.classList.contains("quotes_container"))
{ {
var time = focusedElement.querySelector(".timecode").getAttribute("data-timestamp"); var time = focusedElement.querySelector(".timecode").getAttribute("data-timestamp");
player.setTime(parseInt(time, 10)); player.setTimeThenPlay(parseInt(time));
player.play();
} }
else if(focusedElement.parentNode.classList.contains("references_container")) else if(focusedElement.parentNode.classList.contains("references_container"))
{ {
var time = focusedIdentifier.getAttribute("data-timestamp"); var time = focusedIdentifier.getAttribute("data-timestamp");
player.setTime(parseInt(time, 10)); player.setTimeThenPlay(parseInt(time));
player.play();
} }
else if(focusedElement.parentNode.classList.contains("credit")) else if(focusedElement.parentNode.classList.contains("credit"))
{ {
@ -1113,6 +1326,7 @@ function handleKey(key) {
if(focusedElement.parentNode.classList.contains("references_container") || if(focusedElement.parentNode.classList.contains("references_container") ||
focusedElement.parentNode.classList.contains("quotes_container")) focusedElement.parentNode.classList.contains("quotes_container"))
{ {
if(player) { player.pause(); }
var url = focusedElement.getAttribute("href"); var url = focusedElement.getAttribute("href");
window.open(url, "_blank"); window.open(url, "_blank");
} }
@ -1120,6 +1334,7 @@ function handleKey(key) {
{ {
if(focusedElement.hasAttribute("href")) if(focusedElement.hasAttribute("href"))
{ {
if(player) { player.pause(); }
var url = focusedElement.getAttribute("href"); var url = focusedElement.getAttribute("href");
window.open(url, "_blank"); window.open(url, "_blank");
} }
@ -1880,8 +2095,7 @@ function mouseOverReferences(reference) {
function mouseSkipToTimecode(player, time, ev) function mouseSkipToTimecode(player, time, ev)
{ {
player.setTime(parseInt(time, 10)); player.setTimeThenPlay(parseInt(time, 10));
player.play();
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
return false; return false;