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.js199
1 files changed, 193 insertions, 6 deletions
diff --git a/src/js/plyr.js b/src/js/plyr.js
index 346bfb7e..3b849d4f 100644
--- a/src/js/plyr.js
+++ b/src/js/plyr.js
@@ -38,6 +38,8 @@
debug: false,
autoplay: false,
loop: false,
+ loopin: 0,
+ loopout: null,
seekTime: 10,
volume: 10,
volumeMin: 0,
@@ -86,7 +88,11 @@
settings: '[data-plyr="settings"]',
pip: '[data-plyr="pip"]',
airplay: '[data-plyr="airplay"]',
- speed: '[data-plyr="speed"]'
+ speed: '[data-plyr="speed"]',
+ loopin: '[data-plyr="loopin"]',
+ loopout: '[data-plyr="loopout"]',
+ loopall: '[data-plyr="loopall"]',
+ loopclear: '[data-plyr="loopclear"]',
},
volume: {
input: '[data-plyr="volume"]',
@@ -163,7 +169,12 @@
captions: 'Captions',
settings: 'Settings',
speed: 'Speed',
- quality: 'Quality'
+ quality: 'Quality',
+ loop: 'Loop',
+ loopin: 'Loop in',
+ loopout: 'Loop out',
+ loopall: 'Loop all',
+ loopclear: 'No Loop',
},
types: {
embed: ['youtube', 'vimeo', 'soundcloud'],
@@ -193,7 +204,11 @@
volume: null,
captions: null,
fullscreen: null,
- speed: null
+ speed: null,
+ loopin: null,
+ loopout: null,
+ loopall: null,
+ loopclear: null
},
// Events to watch on HTML5 media elements
events: ['ready', 'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied'],
@@ -997,6 +1012,12 @@
'<span class="plyr__menu__value">Auto</span>',
'</button>',
'</li>',
+ '<li role="tab">',
+ '<button type="button" class="plyr__control plyr__control--forward" id="plyr-settings-{id}-loop-toggle" aria-haspopup="true" aria-controls="plyr-settings-{id}-loop" aria-expanded="false">',
+ config.i18n.loop +
+ '<span class="plyr__menu__value" data-menu="loop"></span>',
+ '</button>',
+ '</li>',
'</ul>',
'</div>',
'<div class="plyr__menu__secondary" id="plyr-settings-{id}-captions" aria-hidden="true" aria-labelled-by="plyr-settings-{id}-captions-toggle" role="tabpanel" tabindex="-1">',
@@ -1104,6 +1125,38 @@
'</li>',
'</ul>',
'</div>',
+ '<div class="plyr__menu__secondary" id="plyr-settings-{id}-loop" aria-hidden="true" aria-labelled-by="plyr-settings-{id}-loop-toggle" role="tabpanel" tabindex="-1">',
+ '<ul>',
+ '<li role="tab">',
+ '<button type="button" class="plyr__control plyr__control--back" aria-haspopup="true" aria-controls="plyr-settings-{id}-primary" aria-expanded="false">',
+ config.i18n.loop,
+ '</button>',
+ '</li>',
+ '<li>',
+ '<button type="button" class="plyr__control" data-plyr="loopall">',
+ config.i18n.loopall,
+ '<span data-loop__value="loopall"></span>',
+ '</button>',
+ '</li>',
+ '<li>',
+ '<button type="button" class="plyr__control" data-plyr="loopin">',
+ config.i18n.loopin + ':&nbsp;',
+ '<span data-loop__value="loopin"></span>',
+ '</button>',
+ '</li>',
+ '<li>',
+ '<button type="button" class="plyr__control" data-plyr="loopout">',
+ config.i18n.loopout + ':&nbsp;',
+ '<span data-loop__value="loopout"></span>',
+ '</button>',
+ '</li>',
+ '<li>',
+ '<button type="button" class="plyr__control" data-plyr="loopclear">',
+ config.i18n.loopclear,
+ '</button>',
+ '</li>',
+ '</ul>',
+ '</div>',
'</div>',
'</div>',
'</div>'
@@ -1278,6 +1331,35 @@
}
}
+ // Setup Loop
+ function setupLoop() {
+ if (!plyr.supported.full) {
+ return;
+ }
+
+ if ((plyr.type !== 'audio' || config.fullscreen.allowAudio) && config.fullscreen.enabled) {
+ // Check for native support
+ var nativeSupport = support.fullscreen;
+
+ if (nativeSupport || (config.fullscreen.fallback && !inFrame())) {
+ log((nativeSupport ? 'Native' : 'Fallback') + ' fullscreen enabled');
+
+ // Add styling hook
+ toggleClass(plyr.container, config.classes.fullscreen.enabled, true);
+ } else {
+ log('Fullscreen not supported and fallback disabled');
+ }
+
+ // Toggle state
+ if (plyr.buttons && plyr.buttons.fullscreen) {
+ toggleState(plyr.buttons.fullscreen, false);
+ }
+
+ // Setup focus trap
+ focusTrap();
+ }
+ }
+
// Display active caption if it contains text
function setActiveCue(track) {
// Get the track from the event if needed
@@ -1715,7 +1797,11 @@
fullscreen: getElement(config.selectors.buttons.fullscreen),
settings: getElement(config.selectors.buttons.settings),
pip: getElement(config.selectors.buttons.pip),
- speed: document.querySelectorAll(config.selectors.buttons.speed)
+ speed: document.querySelectorAll(config.selectors.buttons.speed),
+ loopin: document.querySelectorAll(config.selectors.buttons.loopin),
+ loopout: document.querySelectorAll(config.selectors.buttons.loopout),
+ loopall: document.querySelectorAll(config.selectors.buttons.loopall),
+ loopclear: document.querySelectorAll(config.selectors.buttons.loopclear)
};
// Inputs
@@ -2410,6 +2496,50 @@
return toggle;
}
+ // Toggle loop
+ function toggleLoop(toggle) {
+ if (['loopin', 'loopout', 'loopall'].indexOf(toggle) === -1) {
+ toggle = 'loopclear';
+ }
+
+ var currentTime = Number(plyr.media.currentTime);
+
+ switch(toggle) {
+ case 'loopin':
+ if (config.loopout && config.loopout <= currentTime) {
+ config.loopout = null;
+ }
+ config.loopin = currentTime;
+ break;
+ case 'loopout':
+ if (config.loopin >= currentTime) {
+ return;
+ }
+ config.loopout = currentTime;
+ break;
+ case 'loopall':
+ config.loopin = 0;
+ config.loopout = plyr.media.duration - 2;
+ break;
+ default:
+ config.loopin = 0;
+ config.loopout = null;
+ break;
+ }
+
+ //check if can loop
+ config.loop = is.number(config.loopin) && is.number(config.loopout);
+
+ var loopin = updateTimeDisplay(config.loopin, document.querySelector('[data-loop__value="loopin"]'));
+ var loopout = is.number(config.loopout) ? updateTimeDisplay(config.loopout, document.querySelector('[data-loop__value="loopout"]')) : null;
+ if (config.loop) {
+ document.querySelector('[data-menu="loop"]').innerHTML = loopin + ' - ' + loopout;
+ } else {
+ document.querySelector('[data-menu="loop"]').innerHTML = config.i18n.loopclear;
+ }
+
+ }
+
// Speed-up
function setSpeed(speed) {
// Load speed from storage or default value
@@ -2776,6 +2906,36 @@
}
}
+
+ // Update volume UI and storage
+ function updateLoop() {
+ // Get the current volume
+ var volume = plyr.media.muted ? 0 : (plyr.media.volume * config.volumeMax);
+
+ // Update the <input type="range"> if present
+ if (plyr.supported.full) {
+ if (plyr.volume.input) {
+ plyr.volume.input.value = volume;
+ }
+ if (plyr.volume.display) {
+ plyr.volume.display.value = volume;
+ }
+ }
+
+ // Update the volume in storage
+ updateStorage({
+ volume: volume
+ });
+
+ // Toggle class if muted
+ toggleClass(plyr.container, config.classes.muted, (volume === 0));
+
+ // Update checkbox for mute state
+ if (plyr.supported.full && plyr.buttons.mute) {
+ toggleState(plyr.buttons.mute, (volume === 0));
+ }
+ }
+
// Toggle captions
function toggleCaptions(show) {
// If there's no full support, or there's no caption toggle
@@ -2885,7 +3045,10 @@
}
}
- // Set values
+ if (is.number(config.loopin) && is.number(config.loopout) && plyr.media.currentTime >= config.loopout) {
+ seek(config.loopin);
+ }
+
setProgress(progress, value);
}
@@ -2945,8 +3108,10 @@
plyr.secs = ('0' + plyr.secs).slice(-2);
plyr.mins = ('0' + plyr.mins).slice(-2);
+ var txt = (displayHours ? plyr.hours + ':' : '') + plyr.mins + ':' + plyr.secs;
// Render
- element.innerHTML = (displayHours ? plyr.hours + ':' : '') + plyr.mins + ':' + plyr.secs;
+ element.innerHTML = txt;
+ return txt;
}
// Show the duration on metadataloaded
@@ -3577,6 +3742,20 @@
// Fullscreen
proxy(plyr.buttons.fullscreen, 'click', config.listeners.fullscreen, toggleFullscreen);
+ // Loop
+ proxy(plyr.buttons.loopall, 'click', config.listeners.loopall, function () {
+ toggleLoop('loopall');
+ });
+ proxy(plyr.buttons.loopin, 'click', config.listeners.loopin, function(){
+ toggleLoop('loopin');
+ });
+ proxy(plyr.buttons.loopout, 'click', config.listeners.loopout, function () {
+ toggleLoop('loopout');
+ });
+ proxy(plyr.buttons.loopclear, 'click', config.listeners.loopclear, function () {
+ toggleLoop('loopclear');
+ });
+
// Handle user exiting fullscreen by escaping etc
if (support.fullscreen) {
on(document, fullscreen.eventType, toggleFullscreen);
@@ -4019,6 +4198,10 @@
// Set playback speed
setSpeed();
+
+ // Set loop
+ toggleLoop();
+
// Reset time display
timeUpdate();
@@ -4061,12 +4244,16 @@
isPaused: function() {
return plyr.media.paused;
},
+ isLooping: function() {
+ return config.loopin && config.loopout;
+ },
on: function(event, callback) {
on(plyr.container, event, callback);
return this;
},
play: play,
pause: pause,
+ loop: toggleLoop,
stop: function() {
pause();
seek();