Loop functionality
This commit is contained in:
parent
ea30ad9494
commit
45c0ded88c
@ -21,7 +21,7 @@
|
||||
captions: {
|
||||
defaultActive: true
|
||||
},
|
||||
controls: ['play', 'speed-up', 'speed-down', 'progress', 'volume', 'captions', 'settings', 'fullscreen', 'fast-forward']
|
||||
controls: ['play', 'progress', 'volume', 'captions', 'settings', 'fullscreen', 'fast-forward']
|
||||
});
|
||||
plyr.loadSprite('dist/demo.svg');
|
||||
|
||||
|
4
dist/plyr.js
vendored
4
dist/plyr.js
vendored
File diff suppressed because one or more lines are too long
@ -257,7 +257,7 @@ Note the single quotes encapsulating the JSON and double quotes on the object ke
|
||||
<tr>
|
||||
<td><code>controls</code></td>
|
||||
<td>Array</td>
|
||||
<td><code>['play-large', 'play', 'speed-up', 'progress', 'current-time', 'mute', 'volume', 'captions', 'fullscreen']</code></td>
|
||||
<td><code>['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'fullscreen']</code></td>
|
||||
<td>Toggle which control elements you would like to display when using the default controls html. If you specify a <code>html</code> option, this is redundant. The default value is to display everything.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -402,6 +402,12 @@ Note the single quotes encapsulating the JSON and double quotes on the object ke
|
||||
<td>[1.0, 1.5, 2.0, 0.5]</td>
|
||||
<td>Playback speed list.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>loops</code></td>
|
||||
<td>Array</td>
|
||||
<td>[Loop All, Loop in, Loop out, No Loop]</td>
|
||||
<td>Playback loop list.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
199
src/js/plyr.js
199
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 + ': ',
|
||||
'<span data-loop__value="loopin"></span>',
|
||||
'</button>',
|
||||
'</li>',
|
||||
'<li>',
|
||||
'<button type="button" class="plyr__control" data-plyr="loopout">',
|
||||
config.i18n.loopout + ': ',
|
||||
'<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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user