diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/js/plyr.js | 171 |
1 files changed, 153 insertions, 18 deletions
diff --git a/src/js/plyr.js b/src/js/plyr.js index 7a4f19e0..490c2626 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -38,13 +38,15 @@ debug: false, autoplay: false, loop: false, + loopin: 0, + loopout: null, seekTime: 10, volume: 10, volumeMin: 0, volumeMax: 10, volumeStep: 1, defaultSpeed: 1.0, - currentSpeed: 1.0, + currentSpeed: 1, speeds: [0.5, 1.0, 1.5, 2.0], duration: null, displayDuration: true, @@ -85,7 +87,9 @@ fullscreen: '[data-plyr="fullscreen"]', settings: '[data-plyr="settings"]', pip: '[data-plyr="pip"]', - airplay: '[data-plyr="airplay"]' + airplay: '[data-plyr="airplay"]', + speed: '[data-plyr="speed"]', + loop: '[data-plyr="loop"]' }, volume: { input: '[data-plyr="volume"]', @@ -165,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'], @@ -195,7 +204,8 @@ volume: null, captions: null, fullscreen: null, - speed: null + speed: null, + loop: 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'], @@ -977,7 +987,7 @@ '<svg><use xlink:href="' + iconPath + '-settings" /></svg>', '<span class="plyr__sr-only">' + config.i18n.settings + '</span>', '</button>', - '<div class="plyr__menu__container" id="plyr-settings-{id}" aria-hidden="true" aria-labelled-by="plyr-settings-toggle-{id}" role="tablist" tabindex="-1">', + '<form class="plyr__menu__container" id="plyr-settings-{id}" aria-hidden="true" aria-labelled-by="plyr-settings-toggle-{id}" role="tablist" tabindex="-1">', '<div>', '<div id="plyr-settings-{id}-primary" aria-hidden="false" aria-labelled-by="plyr-settings-toggle-{id}" role="tabpanel" tabindex="-1">', '<ul>', @@ -990,7 +1000,7 @@ '<li role="tab">', '<button type="button" class="plyr__control plyr__control--forward" id="plyr-settings-{id}-speed-toggle" aria-haspopup="true" aria-controls="plyr-settings-{id}-speed" aria-expanded="false">', config.i18n.speed + - '<span class="plyr__menu__value">{speed}</span>', + '<span class="plyr__menu__value" data-menu="speed">{speed}</span>', '</button>', '</li>', '<li role="tab">', @@ -999,6 +1009,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 id="plyr-settings-{id}-captions" aria-hidden="true" aria-labelled-by="plyr-settings-{id}-captions-toggle" role="tabpanel" tabindex="-1">', @@ -1024,21 +1040,33 @@ '</button>', '</li>', '<li>', - '<button type="button" class="plyr__control">2×</button>', + '<label class="plyr__control">', + '<input type="radio" name="speed" data-plyr="speed" value="2.0" '+ (config.currentSpeed === 2 ? 'checked' : '') +'>', + '2.0×', + '</label>', '</li>', '<li>', - '<button type="button" class="plyr__control">1.5×</button>', + '<label class="plyr__control">', + '<input type="radio" name="speed" data-plyr="speed" value="1.5" '+ (config.currentSpeed === 1.5 ? 'checked' : '') +'>', + '1.5×', + '</label>', '</li>', '<li>', - '<button type="button" class="plyr__control">1×</button>', + '<label class="plyr__control">', + '<input type="radio" name="speed" data-plyr="speed" value="1.0" '+ (config.currentSpeed === 1 ? 'checked' : '') +'>', + '1.0×', + '</label>', '</li>', '<li>', - '<button type="button" class="plyr__control">0.5×</button>', + '<label class="plyr__control">', + '<input type="radio" name="speed" data-plyr="speed" value="0.5" '+ (config.currentSpeed === 0.5 ? 'checked' : '') +'>', + '0.5×', + '</label>', '</li>', '</ul>', '</div>', '<div id="plyr-settings-{id}-quality" aria-hidden="true" aria-labelled-by="plyr-settings-{id}-quality-toggle" role="tabpanel" tabindex="-1">', - '<ul class="js-plyr__menu__list--quality">', + '<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.quality, @@ -1094,8 +1122,40 @@ '</li>', '</ul>', '</div>', + '<div 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="loop" data-loop__type="loopall">', + config.i18n.loopall, + '<span data-loop__value="loopall"></span>', + '</button>', + '</li>', + '<li>', + '<button type="button" class="plyr__control" data-plyr="loop" data-loop__type="loopin">', + config.i18n.loopin + ': ', + '<span data-loop__value="loopin"></span>', + '</button>', + '</li>', + '<li>', + '<button type="button" class="plyr__control" data-plyr="loop" data-loop__type="loopout">', + config.i18n.loopout + ': ', + '<span data-loop__value="loopout"></span>', + '</button>', + '</li>', + '<li>', + '<button type="button" class="plyr__control" data-plyr="loop" data-loop__type="loopclear">', + config.i18n.loopclear, + '</button>', + '</li>', + '</ul>', + '</div>', '</div>', - '</div>', + '</form>', '</div>' ); /* beautify ignore:end */ @@ -1646,8 +1706,8 @@ // Replace seek time instances html = replaceAll(html, '{seektime}', config.seekTime); - // Replace seek time instances - html = replaceAll(html, '{speed}', config.currentSpeed.toFixed(1).toString().replace('.0', '') + '×'); + // Replace speed time instances + html = replaceAll(html, '{speed}', getSpeedDisplayValue()); // Replace current captions language html = replaceAll(html, '{lang}', 'English'); @@ -1685,6 +1745,10 @@ } } + function getSpeedDisplayValue() { + return config.currentSpeed.toFixed(1).toString().replace('.0', '') + '×' + } + // Find the UI controls and store references function findElements() { try { @@ -1700,7 +1764,9 @@ forward: getElement(config.selectors.buttons.forward), fullscreen: getElement(config.selectors.buttons.fullscreen), 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), + loop: document.querySelectorAll(config.selectors.buttons.loop) }; // Inputs @@ -2395,6 +2461,49 @@ 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 + 2, document.querySelector('[data-loop__value="loopout"]')) : document.querySelector('[data-loop__value="loopout"]').innerHTML = ''; + 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 @@ -2430,6 +2539,9 @@ updateStorage({ speed: speed }); + + //Update current value of menu + document.querySelector('[data-menu="speed"]').innerHTML = getSpeedDisplayValue(); } // Rewind @@ -2867,7 +2979,10 @@ } } - // Set values + if (is.number(config.loopin) && is.number(config.loopout) && plyr.media.currentTime >= config.loopout) { + seek(config.loopin); + } + setProgress(progress, value); } @@ -2927,8 +3042,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 @@ -3540,7 +3657,10 @@ proxy(plyr.buttons.forward, 'click', config.listeners.forward, forward); // Speed-up - proxy(plyr.buttons.speed, 'click', config.listeners.speed, setSpeed); + proxy(plyr.buttons.speed, 'click', config.listeners.speed, function() { + var speedValue = document.querySelector('[data-plyr="speed"]:checked').value; + setSpeed(Number(speedValue)); + }); // Seek proxy(plyr.buttons.seek, inputEvent, config.listeners.seek, seek); @@ -3556,6 +3676,14 @@ // Fullscreen proxy(plyr.buttons.fullscreen, 'click', config.listeners.fullscreen, toggleFullscreen); + // Loop + proxy(plyr.buttons.loop, 'click', config.listeners.loop, function(event) { + var loopValue = event.target.getAttribute('data-loop__value') || event.target.getAttribute('data-loop__type'); + if (['loopin', 'loopout', 'loopall', 'loopclear'].indexOf(loopValue) > -1) { + toggleLoop(loopValue); + } + }); + // Handle user exiting fullscreen by escaping etc if (support.fullscreen) { on(document, fullscreen.eventType, toggleFullscreen); @@ -3998,6 +4126,9 @@ // Set playback speed setSpeed(); + // Set loop + toggleLoop(); + // Reset time display timeUpdate(); @@ -4040,12 +4171,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(); |