aboutsummaryrefslogtreecommitdiffstats
path: root/src/js/plyr.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/plyr.js')
-rw-r--r--src/js/plyr.js296
1 files changed, 210 insertions, 86 deletions
diff --git a/src/js/plyr.js b/src/js/plyr.js
index c2b78d6b..8b995303 100644
--- a/src/js/plyr.js
+++ b/src/js/plyr.js
@@ -1,6 +1,6 @@
// ==========================================================================
// Plyr
-// plyr.js v1.0.31
+// plyr.js v1.1.0
// https://github.com/selz/plyr
// License: The MIT License (MIT)
// ==========================================================================
@@ -44,6 +44,7 @@
played: ".player-progress-played"
},
captions: ".player-captions",
+ currentTime: ".player-current-time",
duration: ".player-duration"
},
classes: {
@@ -79,71 +80,148 @@
enabled: true,
key: "plyr_volume"
},
- html: (function() {
- return [
- "<div class='player-controls'>",
- "<div class='player-progress'>",
- "<label for='seek{id}' class='sr-only'>Seek</label>",
- "<input id='seek{id}' class='player-progress-seek' type='range' min='0' max='100' step='0.5' value='0' data-player='seek'>",
- "<progress class='player-progress-played' max='100' value='0'>",
- "<span>0</span>% played",
- "</progress>",
- "<progress class='player-progress-buffer' max='100' value='0'>",
- "<span>0</span>% buffered",
- "</progress>",
- "</div>",
- "<span class='player-controls-left'>",
- "<button type='button' data-player='restart'>",
- "<svg><use xlink:href='#icon-restart'></use></svg>",
- "<span class='sr-only'>Restart</span>",
- "</button>",
- "<button type='button' data-player='rewind'>",
- "<svg><use xlink:href='#icon-rewind'></use></svg>",
- "<span class='sr-only'>Rewind {seektime} secs</span>",
- "</button>",
- "<button type='button' data-player='play'>",
- "<svg><use xlink:href='#icon-play'></use></svg>",
- "<span class='sr-only'>Play</span>",
- "</button>",
- "<button type='button' data-player='pause'>",
- "<svg><use xlink:href='#icon-pause'></use></svg>",
- "<span class='sr-only'>Pause</span>",
- "</button>",
- "<button type='button' data-player='fast-forward'>",
- "<svg><use xlink:href='#icon-fast-forward'></use></svg>",
- "<span class='sr-only'>Forward {seektime} secs</span>",
- "</button>",
- "<span class='player-time'>",
- "<span class='sr-only'>Time</span>",
- "<span class='player-duration'>00:00</span>",
- "</span>",
- "</span>",
- "<span class='player-controls-right'>",
- "<input class='inverted sr-only' id='mute{id}' type='checkbox' data-player='mute'>",
- "<label id='mute{id}' for='mute{id}'>",
- "<svg class='icon-muted'><use xlink:href='#icon-muted'></use></svg>",
- "<svg><use xlink:href='#icon-volume'></use></svg>",
- "<span class='sr-only'>Toggle Mute</span>",
- "</label>",
- "<label for='volume{id}' class='sr-only'>Volume</label>",
- "<input id='volume{id}' class='player-volume' type='range' min='0' max='10' value='5' data-player='volume'>",
- "<input class='sr-only' id='captions{id}' type='checkbox' data-player='captions'>",
- "<label for='captions{id}'>",
- "<svg class='icon-captions-on'><use xlink:href='#icon-captions-on'></use></svg>",
- "<svg><use xlink:href='#icon-captions-off'></use></svg>",
- "<span class='sr-only'>Toggle Captions</span>",
- "</label>",
- "<button type='button' data-player='fullscreen'>",
- "<svg class='icon-exit-fullscreen'><use xlink:href='#icon-exit-fullscreen'></use></svg>",
- "<svg><use xlink:href='#icon-enter-fullscreen'></use></svg>",
- "<span class='sr-only'>Toggle Fullscreen</span>",
- "</button>",
- "</span>",
- "</div>"
- ].join("\n");
- })()
+ controls: ["restart", "rewind", "play", "fast-forward", "current-time", "duration", "mute", "volume", "captions", "fullscreen"]
};
+ // Build the default HTML
+ defaults.html = (function() {
+ // Open and add the progress and seek elements
+ var html = [
+ "<div class='player-controls'>",
+ "<div class='player-progress'>",
+ "<label for='seek{id}' class='sr-only'>Seek</label>",
+ "<input id='seek{id}' class='player-progress-seek' type='range' min='0' max='100' step='0.5' value='0' data-player='seek'>",
+ "<progress class='player-progress-played' max='100' value='0'>",
+ "<span>0</span>% played",
+ "</progress>",
+ "<progress class='player-progress-buffer' max='100' value='0'>",
+ "<span>0</span>% buffered",
+ "</progress>",
+ "</div>",
+ "<span class='player-controls-left'>"];
+
+ // Restart button
+ if(_inArray(defaults.controls, "restart")) {
+ html.push(
+ "<button type='button' data-player='restart'>",
+ "<svg><use xlink:href='#icon-restart'></use></svg>",
+ "<span class='sr-only'>Restart</span>",
+ "</button>"
+ );
+ }
+
+ // Rewind button
+ if(_inArray(defaults.controls, "rewind")) {
+ html.push(
+ "<button type='button' data-player='rewind'>",
+ "<svg><use xlink:href='#icon-rewind'></use></svg>",
+ "<span class='sr-only'>Rewind {seektime} secs</span>",
+ "</button>"
+ );
+ }
+
+ // Play/pause button
+ if(_inArray(defaults.controls, "play")) {
+ html.push(
+ "<button type='button' data-player='play'>",
+ "<svg><use xlink:href='#icon-play'></use></svg>",
+ "<span class='sr-only'>Play</span>",
+ "</button>",
+ "<button type='button' data-player='pause'>",
+ "<svg><use xlink:href='#icon-pause'></use></svg>",
+ "<span class='sr-only'>Pause</span>",
+ "</button>"
+ );
+ }
+
+ // Fast forward button
+ if(_inArray(defaults.controls, "fast-forward")) {
+ html.push(
+ "<button type='button' data-player='fast-forward'>",
+ "<svg><use xlink:href='#icon-fast-forward'></use></svg>",
+ "<span class='sr-only'>Forward {seektime} secs</span>",
+ "</button>"
+ );
+ }
+
+ // Media current time display
+ if(_inArray(defaults.controls, "current-time")) {
+ html.push(
+ "<span class='player-time'>",
+ "<span class='sr-only'>Current time</span>",
+ "<span class='player-current-time'>00:00</span>",
+ "</span>"
+ );
+ }
+
+ // Media duration display
+ if(_inArray(defaults.controls, "duration")) {
+ html.push(
+ "<span class='player-time'>",
+ "<span class='sr-only'>Duration</span>",
+ "<span class='player-duration'>00:00</span>",
+ "</span>"
+ );
+ }
+
+ // Close left controls
+ html.push(
+ "</span>",
+ "<span class='player-controls-right'>"
+ );
+
+ // Toggle mute button
+ if(_inArray(defaults.controls, "mute")) {
+ html.push(
+ "<input class='inverted sr-only' id='mute{id}' type='checkbox' data-player='mute'>",
+ "<label id='mute{id}' for='mute{id}'>",
+ "<svg class='icon-muted'><use xlink:href='#icon-muted'></use></svg>",
+ "<svg><use xlink:href='#icon-volume'></use></svg>",
+ "<span class='sr-only'>Toggle Mute</span>",
+ "</label>"
+ );
+ }
+
+ // Volume range control
+ if(_inArray(defaults.controls, "volume")) {
+ html.push(
+ "<label for='volume{id}' class='sr-only'>Volume</label>",
+ "<input id='volume{id}' class='player-volume' type='range' min='0' max='10' value='5' data-player='volume'>"
+ );
+ }
+
+ // Toggle captions button
+ if(_inArray(defaults.controls, "captions")) {
+ html.push(
+ "<input class='sr-only' id='captions{id}' type='checkbox' data-player='captions'>",
+ "<label for='captions{id}'>",
+ "<svg class='icon-captions-on'><use xlink:href='#icon-captions-on'></use></svg>",
+ "<svg><use xlink:href='#icon-captions-off'></use></svg>",
+ "<span class='sr-only'>Toggle Captions</span>",
+ "</label>"
+ );
+ }
+
+ // Toggle fullscreen button
+ if(_inArray(defaults.controls, "fullscreen")) {
+ html.push(
+ "<button type='button' data-player='fullscreen'>",
+ "<svg class='icon-exit-fullscreen'><use xlink:href='#icon-exit-fullscreen'></use></svg>",
+ "<svg><use xlink:href='#icon-enter-fullscreen'></use></svg>",
+ "<span class='sr-only'>Toggle Fullscreen</span>",
+ "</button>"
+ );
+ }
+
+ // Close everything
+ html.push(
+ "</span>",
+ "</div>"
+ );
+
+ return html.join("");
+ })();
+
// Debugging
function _log(text, error) {
if(config.debug && window.console) {
@@ -249,6 +327,11 @@
// If we got this far, we're stuffed
return false;
}
+
+ // Element exists in an array
+ function _inArray(haystack, needle) {
+ return (haystack.indexOf(needle) != -1);
+ }
// Replace all
function _replaceAll(string, find, replace) {
@@ -339,12 +422,16 @@
// Bind event
function _on(element, events, callback) {
- _toggleHandler(element, events, callback, true);
+ if(element) {
+ _toggleHandler(element, events, callback, true);
+ }
}
// Unbind event
function _off(element, events, callback) {
- _toggleHandler(element, events, callback, false);
+ if(element) {
+ _toggleHandler(element, events, callback, false);
+ }
}
// Trigger event
@@ -533,6 +620,11 @@
// Display captions container and button (for initialization)
function _showCaptions() {
+ // If there's no caption toggle, bail
+ if(!player.buttons.captions) {
+ return;
+ }
+
_toggleClass(player.container, config.classes.captions.enabled, true);
if (config.captions.defaultActive) {
@@ -592,18 +684,19 @@
// Insert custom video controls
_log("Injecting custom controls.");
- // Use specified html
- // Need to do a default?
- var html = config.html;
+ // If no controls are specified, bail
+ if(!config.html) {
+ return;
+ }
// Replace seek time instances
- html = _replaceAll(html, "{seektime}", config.seekTime);
+ config.html = _replaceAll(config.html, "{seektime}", config.seekTime);
// Replace all id references
- html = _replaceAll(html, "{id}", player.random);
+ config.html = _replaceAll(config.html, "{id}", player.random);
// Inject into the container
- player.container.insertAdjacentHTML("beforeend", html);
+ player.container.insertAdjacentHTML("beforeend", config.html);
// Setup tooltips
if(config.tooltips) {
@@ -645,18 +738,19 @@
// Progress - Buffering
player.progress.buffer = {};
player.progress.buffer.bar = _getElement(config.selectors.progress.buffer);
- player.progress.buffer.text = player.progress.buffer.bar.getElementsByTagName("span")[0];
+ player.progress.buffer.text = player.progress.buffer.bar && player.progress.buffer.bar.getElementsByTagName("span")[0];
// Progress - Played
player.progress.played = {};
player.progress.played.bar = _getElement(config.selectors.progress.played);
- player.progress.played.text = player.progress.played.bar.getElementsByTagName("span")[0];
+ player.progress.played.text = player.progress.played.bar && player.progress.played.bar.getElementsByTagName("span")[0];
// Volume
player.volume = _getElement(config.selectors.buttons.volume);
// Timing
player.duration = _getElement(config.selectors.duration);
+ player.currentTime = _getElement(config.selectors.currentTime);
player.seekTime = _getElements(config.selectors.seekTime);
return true;
@@ -664,12 +758,21 @@
catch(e) {
_log("It looks like there's a problem with your controls html. Bailing.", true);
+ // Restore native video controls
+ player.media.setAttribute("controls", "");
+
return false;
}
}
// Setup aria attributes
function _setupAria() {
+ // If there's no play button, bail
+ if(!player.buttons.play) {
+ return;
+ }
+
+ // Find the current text
var label = player.buttons.play.innerText || "Play";
// If there's a media title set, use that for the label
@@ -1018,6 +1121,11 @@
// Set volume
function _setVolume(volume) {
+ // Bail if there's no volume element
+ if(!player.volume) {
+ return;
+ }
+
// Use default if needed
if(typeof volume === "undefined") {
if(config.storage.enabled && _storage().supported) {
@@ -1070,7 +1178,8 @@
// Toggle captions
function _toggleCaptions(show) {
- if(!player.supported.full) {
+ // If there's no full support, or there's no caption toggle
+ if(!player.supported.full || !player.buttons.captions) {
return;
}
@@ -1115,7 +1224,7 @@
value = _getPercentage(player.media.currentTime, player.media.duration);
// Set seek range value only if it's a "natural" time event
- if(event.type == "timeupdate") {
+ if(event.type == "timeupdate" && player.buttons.seek) {
player.buttons.seek.value = value;
}
@@ -1147,12 +1256,21 @@
}
// Set values
- progress.value = value;
- text.innerHTML = value;
+ if(progress) {
+ progress.value = value;
+ }
+ if(text) {
+ text.innerHTML = value;
+ }
}
// Update the displayed time
- function _updateTimeDisplay(time) {
+ function _updateTimeDisplay(time, element) {
+ // Bail if there's no duration display
+ if(!element) {
+ return;
+ }
+
player.secs = parseInt(time % 60);
player.mins = parseInt((time / 60) % 60);
player.hours = parseInt(((time / 60) / 60) % 60);
@@ -1165,20 +1283,28 @@
player.mins = ("0" + player.mins).slice(-2);
// Render
- player.duration.innerHTML = (displayHours ? player.hours + ":" : "") + player.mins + ":" + player.secs;
+ element.innerHTML = (displayHours ? player.hours + ":" : "") + player.mins + ":" + player.secs;
}
// Show the duration on metadataloaded
function _displayDuration() {
- if(player.media.paused) {
- _updateTimeDisplay(player.media.duration || 0);
+ var duration = player.media.duration || 0;
+
+ // If there's only one time display, display duration there
+ if(!player.duration && config.displayDuration && player.media.paused) {
+ _updateTimeDisplay(duration, player.currentTime);
+ }
+
+ // If there's a duration element, update content
+ if(player.duration) {
+ _updateTimeDisplay(duration, player.duration);
}
}
// Handle time change event
function _timeUpdate(event) {
// Duration
- _updateTimeDisplay(player.media.currentTime);
+ _updateTimeDisplay(player.media.currentTime, player.currentTime);
// Playing progress
_updateProgress(event);
@@ -1312,9 +1438,7 @@
_on(player.media, "timeupdate", _seekManualCaptions);
// Display duration
- if(config.displayDuration) {
- _on(player.media, "loadedmetadata", _displayDuration);
- }
+ _on(player.media, "loadedmetadata", _displayDuration);
// Seek
_on(player.buttons.seek, "change input", _seek);