Loop functionality
This commit is contained in:
parent
ea30ad9494
commit
45c0ded88c
@ -21,7 +21,7 @@
|
|||||||
captions: {
|
captions: {
|
||||||
defaultActive: true
|
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');
|
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>
|
<tr>
|
||||||
<td><code>controls</code></td>
|
<td><code>controls</code></td>
|
||||||
<td>Array</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>
|
<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>
|
||||||
<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>[1.0, 1.5, 2.0, 0.5]</td>
|
||||||
<td>Playback speed list.</td>
|
<td>Playback speed list.</td>
|
||||||
</tr>
|
</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>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
199
src/js/plyr.js
199
src/js/plyr.js
@ -38,6 +38,8 @@
|
|||||||
debug: false,
|
debug: false,
|
||||||
autoplay: false,
|
autoplay: false,
|
||||||
loop: false,
|
loop: false,
|
||||||
|
loopin: 0,
|
||||||
|
loopout: null,
|
||||||
seekTime: 10,
|
seekTime: 10,
|
||||||
volume: 10,
|
volume: 10,
|
||||||
volumeMin: 0,
|
volumeMin: 0,
|
||||||
@ -86,7 +88,11 @@
|
|||||||
settings: '[data-plyr="settings"]',
|
settings: '[data-plyr="settings"]',
|
||||||
pip: '[data-plyr="pip"]',
|
pip: '[data-plyr="pip"]',
|
||||||
airplay: '[data-plyr="airplay"]',
|
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: {
|
volume: {
|
||||||
input: '[data-plyr="volume"]',
|
input: '[data-plyr="volume"]',
|
||||||
@ -163,7 +169,12 @@
|
|||||||
captions: 'Captions',
|
captions: 'Captions',
|
||||||
settings: 'Settings',
|
settings: 'Settings',
|
||||||
speed: 'Speed',
|
speed: 'Speed',
|
||||||
quality: 'Quality'
|
quality: 'Quality',
|
||||||
|
loop: 'Loop',
|
||||||
|
loopin: 'Loop in',
|
||||||
|
loopout: 'Loop out',
|
||||||
|
loopall: 'Loop all',
|
||||||
|
loopclear: 'No Loop',
|
||||||
},
|
},
|
||||||
types: {
|
types: {
|
||||||
embed: ['youtube', 'vimeo', 'soundcloud'],
|
embed: ['youtube', 'vimeo', 'soundcloud'],
|
||||||
@ -193,7 +204,11 @@
|
|||||||
volume: null,
|
volume: null,
|
||||||
captions: null,
|
captions: null,
|
||||||
fullscreen: null,
|
fullscreen: null,
|
||||||
speed: null
|
speed: null,
|
||||||
|
loopin: null,
|
||||||
|
loopout: null,
|
||||||
|
loopall: null,
|
||||||
|
loopclear: null
|
||||||
},
|
},
|
||||||
// Events to watch on HTML5 media elements
|
// 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'],
|
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>',
|
'<span class="plyr__menu__value">Auto</span>',
|
||||||
'</button>',
|
'</button>',
|
||||||
'</li>',
|
'</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>',
|
'</ul>',
|
||||||
'</div>',
|
'</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">',
|
'<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>',
|
'</li>',
|
||||||
'</ul>',
|
'</ul>',
|
||||||
'</div>',
|
'</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>',
|
'</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
|
// Display active caption if it contains text
|
||||||
function setActiveCue(track) {
|
function setActiveCue(track) {
|
||||||
// Get the track from the event if needed
|
// Get the track from the event if needed
|
||||||
@ -1715,7 +1797,11 @@
|
|||||||
fullscreen: getElement(config.selectors.buttons.fullscreen),
|
fullscreen: getElement(config.selectors.buttons.fullscreen),
|
||||||
settings: getElement(config.selectors.buttons.settings),
|
settings: getElement(config.selectors.buttons.settings),
|
||||||
pip: getElement(config.selectors.buttons.pip),
|
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
|
// Inputs
|
||||||
@ -2410,6 +2496,50 @@
|
|||||||
return toggle;
|
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
|
// Speed-up
|
||||||
function setSpeed(speed) {
|
function setSpeed(speed) {
|
||||||
// Load speed from storage or default value
|
// 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
|
// Toggle captions
|
||||||
function toggleCaptions(show) {
|
function toggleCaptions(show) {
|
||||||
// If there's no full support, or there's no caption toggle
|
// 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);
|
setProgress(progress, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2945,8 +3108,10 @@
|
|||||||
plyr.secs = ('0' + plyr.secs).slice(-2);
|
plyr.secs = ('0' + plyr.secs).slice(-2);
|
||||||
plyr.mins = ('0' + plyr.mins).slice(-2);
|
plyr.mins = ('0' + plyr.mins).slice(-2);
|
||||||
|
|
||||||
|
var txt = (displayHours ? plyr.hours + ':' : '') + plyr.mins + ':' + plyr.secs;
|
||||||
// Render
|
// Render
|
||||||
element.innerHTML = (displayHours ? plyr.hours + ':' : '') + plyr.mins + ':' + plyr.secs;
|
element.innerHTML = txt;
|
||||||
|
return txt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show the duration on metadataloaded
|
// Show the duration on metadataloaded
|
||||||
@ -3577,6 +3742,20 @@
|
|||||||
// Fullscreen
|
// Fullscreen
|
||||||
proxy(plyr.buttons.fullscreen, 'click', config.listeners.fullscreen, toggleFullscreen);
|
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
|
// Handle user exiting fullscreen by escaping etc
|
||||||
if (support.fullscreen) {
|
if (support.fullscreen) {
|
||||||
on(document, fullscreen.eventType, toggleFullscreen);
|
on(document, fullscreen.eventType, toggleFullscreen);
|
||||||
@ -4019,6 +4198,10 @@
|
|||||||
// Set playback speed
|
// Set playback speed
|
||||||
setSpeed();
|
setSpeed();
|
||||||
|
|
||||||
|
|
||||||
|
// Set loop
|
||||||
|
toggleLoop();
|
||||||
|
|
||||||
// Reset time display
|
// Reset time display
|
||||||
timeUpdate();
|
timeUpdate();
|
||||||
|
|
||||||
@ -4061,12 +4244,16 @@
|
|||||||
isPaused: function() {
|
isPaused: function() {
|
||||||
return plyr.media.paused;
|
return plyr.media.paused;
|
||||||
},
|
},
|
||||||
|
isLooping: function() {
|
||||||
|
return config.loopin && config.loopout;
|
||||||
|
},
|
||||||
on: function(event, callback) {
|
on: function(event, callback) {
|
||||||
on(plyr.container, event, callback);
|
on(plyr.container, event, callback);
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
play: play,
|
play: play,
|
||||||
pause: pause,
|
pause: pause,
|
||||||
|
loop: toggleLoop,
|
||||||
stop: function() {
|
stop: function() {
|
||||||
pause();
|
pause();
|
||||||
seek();
|
seek();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user