diff options
author | Sam <me@sampotts.me> | 2016-09-06 23:48:09 +1000 |
---|---|---|
committer | Sam <me@sampotts.me> | 2016-09-06 23:48:09 +1000 |
commit | 37840c384414401a914eb43aa7a93eb0e17ee68e (patch) | |
tree | 85d92b234e422276fffb9658d582508772e4980f /src | |
parent | 28335ef3d8c8aaef959989bacd7d8af026898a53 (diff) | |
download | plyr-37840c384414401a914eb43aa7a93eb0e17ee68e.tar.lz plyr-37840c384414401a914eb43aa7a93eb0e17ee68e.tar.xz plyr-37840c384414401a914eb43aa7a93eb0e17ee68e.zip |
Working on settings menu
Diffstat (limited to 'src')
-rw-r--r-- | src/js/plyr.js | 153 | ||||
-rw-r--r-- | src/less/plyr.less | 109 | ||||
-rw-r--r-- | src/less/variables.less | 10 | ||||
-rw-r--r-- | src/sprite/plyr-settings.svg | 12 |
4 files changed, 193 insertions, 91 deletions
diff --git a/src/js/plyr.js b/src/js/plyr.js index 9a437383..53af4cda 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -41,12 +41,7 @@ volumeStep: 1, defaultSpeed: 1.0, currentSpeed: 1.0, - speeds: [ - 0.5, - 1.0, - 1.5, - 2.0 - ], + speeds: [ 0.5, 1.0, 1.5, 2.0 ], duration: null, displayDuration: true, loadSprite: true, @@ -84,7 +79,7 @@ mute: '[data-plyr="mute"]', captions: '[data-plyr="captions"]', fullscreen: '[data-plyr="fullscreen"]', - speedup: '[data-plyr="speed-up"]' + settings: '[data-plyr="settings"]' }, volume: { input: '[data-plyr="volume"]', @@ -137,7 +132,7 @@ enabled: true, key: 'plyr' }, - controls: ['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'fullscreen'], + controls: ['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'settings', 'fullscreen'], i18n: { restart: 'Restart', rewind: 'Rewind {seektime} secs', @@ -153,7 +148,9 @@ toggleCaptions: 'Toggle Captions', toggleFullscreen: 'Toggle Fullscreen', frameTitle: 'Player for {title}', - speedup: 'Speed x{speed}' + captions: 'Captions', + settings: 'Settings', + speed: 'Speed' }, types: { embed: ['youtube', 'vimeo', 'soundcloud'], @@ -183,7 +180,7 @@ volume: null, captions: null, fullscreen: null, - speedup: null + speed: 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', 'emptied'], @@ -354,21 +351,6 @@ } } - // Unwrap an element - // http://plainjs.com/javascript/manipulation/unwrap-a-dom-element-35/ - /*function _unwrap(wrapper) { - // Get the element's parent node - var parent = wrapper.parentNode; - - // Move all children out of the element - while (wrapper.firstChild) { - parent.insertBefore(wrapper.firstChild, wrapper); - } - - // Remove the empty element - parent.removeChild(wrapper); - }*/ - // Remove an element function _remove(element) { if (!element) { @@ -452,7 +434,7 @@ } // Toggle event listener - function _toggleListener(element, events, callback, toggle, useCapture) { + function _toggleListener(elements, events, callback, toggle, useCapture) { var eventList = events.split(' '); // Whether the listener is a capturing listener or not @@ -462,10 +444,10 @@ } // If a nodelist is passed, call itself on each node - if (element instanceof NodeList) { - for (var x = 0; x < element.length; x++) { - if (element[x] instanceof Node) { - _toggleListener(element[x], arguments[1], arguments[2], arguments[3]); + if (elements instanceof NodeList) { + for (var x = 0; x < elements.length; x++) { + if (elements[x] instanceof Node) { + _toggleListener(elements[x], arguments[1], arguments[2], arguments[3]); } } return; @@ -473,7 +455,7 @@ // If a single node is passed, bind the event listener for (var i = 0; i < eventList.length; i++) { - element[toggle ? 'addEventListener' : 'removeEventListener'](eventList[i], callback, useCapture); + elements[toggle ? 'addEventListener' : 'removeEventListener'](eventList[i], callback, useCapture); } } @@ -484,13 +466,6 @@ } } - // Unbind event - /*function _off(element, events, callback, useCapture) { - if (element) { - _toggleListener(element, events, callback, false, useCapture); - } - }*/ - // Trigger event function _event(element, type, bubbles, properties) { // Bail if no element @@ -604,6 +579,9 @@ }, undefined: function(input) { return input !== null && typeof input === 'undefined'; + }, + empty: function(input) { + return input === null || this.undefined(input) || ((this.string(input) || this.array(input) || this.nodeList(input)) && input.length === 0) || (this.object(input) && Object.keys(input).length === 0); } }; @@ -813,22 +791,12 @@ ); } - // Speed-up button - if (_inArray(config.controls, 'speed-up')) { - html.push( - '<button type="button" data-plyr="speed-up">', - '<svg><use xlink:href="' + iconPath + '-fast-forward" /></svg>', - '<span class="plyr__sr-only">' + config.i18n.speedup + '</span>', - '</button>' - ); - } - // Progress if (_inArray(config.controls, 'progress')) { // Create progress html.push('<span class="plyr__progress">', - '<label for="seek{id}" class="plyr__sr-only">Seek</label>', - '<input id="seek{id}" class="plyr__progress--seek" type="range" min="0" max="100" step="0.1" value="0" data-plyr="seek">', + '<label for="seek-{id}" class="plyr__sr-only">Seek</label>', + '<input id="seek-{id}" class="plyr__progress--seek" type="range" min="0" max="100" step="0.1" value="0" data-plyr="seek">', '<progress class="plyr__progress--played" max="100" value="0" role="presentation"></progress>', '<progress class="plyr__progress--buffer" max="100" value="0">', '<span>0</span>% ' + config.i18n.buffered, @@ -878,8 +846,8 @@ if (_inArray(config.controls, 'volume')) { html.push( '<span class="plyr__volume">', - '<label for="volume{id}" class="plyr__sr-only">' + config.i18n.volume + '</label>', - '<input id="volume{id}" class="plyr__volume--input" type="range" min="' + config.volumeMin + '" max="' + config.volumeMax + '" value="' + config.volume + '" data-plyr="volume">', + '<label for="volume-{id}" class="plyr__sr-only">' + config.i18n.volume + '</label>', + '<input id="volume-{id}" class="plyr__volume--input" type="range" min="' + config.volumeMin + '" max="' + config.volumeMax + '" value="' + config.volume + '" data-plyr="volume">', '<progress class="plyr__volume--display" max="' + config.volumeMax + '" value="' + config.volumeMin + '" role="presentation"></progress>', '</span>' ); @@ -896,6 +864,34 @@ ); } + // Settings button + if (_inArray(config.controls, 'settings')) { + + + html.push( + '<div class="plyr__menu">', + '<button type="button" id="plyr-settings-toggle-{id}" data-plyr="settings" aria-haspopup="true" aria-controls="plyr-settings-{id}" aria-expanded="false">', + '<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}">', + '<ul>', + '<li>', + '<button type="button" data-plyr="slide-captions">', + config.i18n.captions + ' <span class="plyr__menu__value">{lang}</span>', + '</button>', + '</li>', + '<li>', + '<button type="button" data-plyr="slide-speed">', + config.i18n.speed + ' <span class="plyr__menu__value">{speed}</span>', + '</button>', + '</li>', + '</ul>', + '</div>', + '</div>' + ); + } + // Toggle fullscreen button if (_inArray(config.controls, 'fullscreen')) { html.push( @@ -1292,7 +1288,10 @@ html = _replaceAll(html, '{seektime}', config.seekTime); // Replace seek time instances - html = _replaceAll(html, '{speed}', config.currentSpeed); + html = _replaceAll(html, '{speed}', config.currentSpeed === 1 ? 'Normal' : config.currentSpeed.toFixed(1) + 'x'); + + // Replace current captions language + html = _replaceAll(html, '{lang}', 'English'); // Replace all id references with random numbers html = _replaceAll(html, '{id}', Math.floor(Math.random() * (10000))); @@ -1340,7 +1339,7 @@ plyr.buttons.rewind = _getElement(config.selectors.buttons.rewind); plyr.buttons.forward = _getElement(config.selectors.buttons.forward); plyr.buttons.fullscreen = _getElement(config.selectors.buttons.fullscreen); - plyr.buttons.speedup = _getElement(config.selectors.buttons.speedup); + plyr.buttons.settings = _getElement(config.selectors.buttons.settings); // Inputs plyr.buttons.mute = _getElement(config.selectors.buttons.mute); @@ -1982,13 +1981,14 @@ } // Speed-up - function _speedup(speed) { + function _speed(speed) { if (!_is.array(config.speeds)) { _warn('Invalid speeds format'); return; } if (!_is.number(speed)) { var index = config.speeds.indexOf(config.currentSpeed); + if (index !== -1) { var nextIndex = index + 1; if (nextIndex >= config.speeds.length) { @@ -2000,12 +2000,12 @@ } } + // Store current speed config.currentSpeed = speed; + // Set HTML5 speed plyr.media.playbackRate = speed; - _updateSpeedupTooltip(speed); - // Save speed to localStorage _updateStorage({speed: speed}); } @@ -2578,31 +2578,13 @@ } // Set playback speed - function _setSpeedup(speed) { + function _setSpeed(speed) { // Load speed from storage or default value if (_is.undefined(speed)) { speed = plyr.storage.speed || config.defaultSpeed; } - _speedup(speed); - } - - // Update hover tooltip for playback speed changed - function _updateSpeedupTooltip(speed) { - if (!isNaN(speed)) { - speed = config.currentSpeed; - } - - var button = plyr.buttons.speedup; - var template = config.i18n.speedup; - - var elements= button.getElementsByClassName(config.classes.tooltip); - if (elements.length === 0){ - return; - } - - var tooltip = elements[0]; - tooltip.innerHTML = _replaceAll(template, '{speed}', speed); + _speed(speed); } // Show the player controls in fullscreen mode @@ -3068,7 +3050,7 @@ _proxyListener(plyr.buttons.forward, 'click', config.listeners.forward, _forward); // Speed-up - _proxyListener(plyr.buttons.speedup, 'click', config.listeners.speedup, _speedup); + _proxyListener(plyr.buttons.speed, 'click', config.listeners.speed, _speed); // Seek _proxyListener(plyr.buttons.seek, inputEvent, config.listeners.seek, _seek); @@ -3092,6 +3074,18 @@ // Captions _on(plyr.buttons.captions, 'click', _toggleCaptions); + // Menus + _on(plyr.controls.querySelectorAll('[aria-haspopup="true"]'), 'click', function() { + var toggle = this, + target = document.querySelector('#' + toggle.getAttribute('aria-controls')), + show = (toggle.getAttribute('aria-expanded') === 'false'); + + console.log(target, toggle); + + toggle.setAttribute('aria-expanded', show); + target.setAttribute('aria-hidden', !show); + }); + // Seek tooltip _on(plyr.progress.container, 'mouseenter mouseleave mousemove', _updateSeekTooltip); @@ -3456,7 +3450,7 @@ _updateVolume(); // Set playback speed - _setSpeedup(); + _setSpeed(); // Reset time display _timeUpdate(); @@ -3488,6 +3482,7 @@ source: _source, poster: _updatePoster, setVolume: _setVolume, + setSpeed: _setSpeed, togglePlay: _togglePlay, toggleMute: _toggleMute, toggleCaptions: _toggleCaptions, diff --git a/src/less/plyr.less b/src/less/plyr.less index f70d135c..a3dd8e83 100644 --- a/src/less/plyr.less +++ b/src/less/plyr.less @@ -11,6 +11,16 @@ @keyframes plyr-progress { to { background-position: @plyr-progress-loading-size 0; } } +@keyframes plyr-popup { + from { + transform: translateY(10px); + opacity: .5; + } + to { + transform: translateY(0); + opacity: 1; + } +} // Styles // ------------------------------- @@ -40,6 +50,11 @@ } } + // ARIA + [aria-hidden='true'] { + display: none; + } + // Focus &:focus { outline: 0; @@ -268,7 +283,8 @@ // Spacing > button, .plyr__progress, - .plyr__time { + .plyr__time, + .plyr__menu { margin-left: (@plyr-control-spacing / 2); &:first-child { @@ -320,9 +336,16 @@ @media (min-width: @plyr-bp-screen-sm) { > button, .plyr__progress, - .plyr__time { + .plyr__time, + .plyr__menu { margin-left: @plyr-control-spacing; } + + > button + button, + .plyr__menu + button, + > button + .plyr__menu { + margin-left: (@plyr-control-spacing / 2); + } } } // Hide controls @@ -338,7 +361,7 @@ right: 0; bottom: 0; padding: (@plyr-control-spacing * 5) @plyr-control-spacing @plyr-control-spacing; - background: linear-gradient(fade(@plyr-video-controls-bg, 0%), fade(@plyr-video-controls-bg, 50%)); + background: linear-gradient(fade(@plyr-video-controls-bg, 0%), fade(@plyr-video-controls-bg, 70%)); border-bottom-left-radius: inherit; border-bottom-right-radius: inherit; color: @plyr-video-control-color; @@ -442,6 +465,78 @@ display: inline-block; } +// Menus +// -------------------------------------------------------------- +.plyr__menu { + position: relative; + + // Hide tooltip + button[aria-expanded='true'] .plyr__tooltip { + display: none; + } + + // The actual menu container + &__container { + position: absolute; + bottom: 100%; + right: -5px; + margin-bottom: 10px; + animation: plyr-popup .2s ease; + background: fade(@plyr-video-controls-bg, 90%); + box-shadow: 0 1px 0 fade(#000, 20%); + border-radius: 4px; + white-space: nowrap; + text-align: left; + color: @plyr-video-control-color; + font-size: @plyr-font-size-small; + + ul { + margin: 0; + padding: 5px; + list-style: none; + } + + button { + display: flex; + width: 100%; + padding: 10px 30px 10px 12px; + color: @plyr-video-control-color; + font-weight: 600; + + // Arrow + &::after { + content: ""; + position: absolute; + top: 50%; + transform: translateY(-50%); + right: 5px; + border: 5px solid transparent; + border-left-color: fade(@plyr-video-control-color, 80%); + } + } + + // Option value + .plyr__menu__value { + margin-left: auto; + padding-left: 25px; + font-weight: 400; + color: fade(@plyr-video-control-color, 80%); + } + + // Arrow + &::after { + content: ""; + position: absolute; + top: 100%; + right: 15px; + height: 0; + width: 0; + border: 6px solid transparent; + border-top-color: fade(@plyr-video-controls-bg, 90%); + } + } +} + // Tooltips // -------------------------------------------------------------- .plyr__tooltip { @@ -492,7 +587,7 @@ } // First tooltip -.plyr__controls button:first-child .plyr__tooltip { +.plyr__controls > button:first-child .plyr__tooltip { left: 0; transform: translate(0, 10px) scale(.8); transform-origin: 0 100%; @@ -503,7 +598,7 @@ } // Last tooltip -.plyr__controls button:last-child .plyr__tooltip { +.plyr__controls > button:last-child .plyr__tooltip { right: 0; transform: translate(0, 10px) scale(.8); transform-origin: 100% 100%; @@ -515,8 +610,8 @@ } } -.plyr__controls button:first-child, -.plyr__controls button:last-child { +.plyr__controls > button:first-child, +.plyr__controls > button:last-child { &:hover .plyr__tooltip, &.tab-focus:focus .plyr__tooltip, .plyr__tooltip--visible { diff --git a/src/less/variables.less b/src/less/variables.less index fc9e895a..8a601571 100644 --- a/src/less/variables.less +++ b/src/less/variables.less @@ -17,7 +17,7 @@ @plyr-font-size-base: 16px; // Captions -@plyr-captions-bg: fade(#000, 70%); +@plyr-captions-bg: fade(#343f4a, 85%); @plyr-captions-color: #fff; @plyr-font-size-captions-base: @plyr-font-size-base; @plyr-font-size-captions-medium: ceil(@plyr-font-size-base * 1.5); @@ -27,7 +27,7 @@ @plyr-control-icon-size: 18px; @plyr-control-spacing: 10px; @plyr-control-padding: (@plyr-control-spacing * .7); -@plyr-video-controls-bg: #000; +@plyr-video-controls-bg: #343f4a; @plyr-video-control-color: #fff; @plyr-video-control-color-hover: #fff; @plyr-video-control-bg-hover: @plyr-color-main; @@ -38,7 +38,7 @@ @plyr-audio-control-bg-hover: @plyr-color-main; // Tooltips -@plyr-tooltip-bg: fade(#000, 70%); +@plyr-tooltip-bg: fade(#343f4a, 85%); @plyr-tooltip-color: #fff; @plyr-tooltip-padding: (@plyr-control-spacing / 2); @plyr-tooltip-arrow-size: 4px; @@ -46,7 +46,7 @@ // Progress @plyr-progress-loading-size: 25px; -@plyr-progress-loading-bg: fade(#000, 15%); +@plyr-progress-loading-bg: fade(#343f4a, 20%); @plyr-video-progress-bg: fade(#fff, 25%); @plyr-video-progress-buffered-bg: @plyr-video-progress-bg; @plyr-audio-progress-bg: fade(#C6D6DB, 66%); @@ -58,7 +58,7 @@ @plyr-range-thumb-width: floor(@plyr-range-track-height * 2); @plyr-range-thumb-bg: #fff; @plyr-range-thumb-border: 2px solid transparent; -@plyr-range-thumb-shadow: 0 1px 1px fade(@plyr-video-controls-bg, 15%), 0 0 0 1px fade(#000, 15%); +@plyr-range-thumb-shadow: 0 1px 1px fade(@plyr-video-controls-bg, 15%), 0 0 0 1px fade(#343f4a, 20%); @plyr-range-thumb-active-border-color: #fff; @plyr-range-thumb-active-bg: @plyr-video-control-bg-hover; @plyr-range-thumb-active-scale: 1.25; diff --git a/src/sprite/plyr-settings.svg b/src/sprite/plyr-settings.svg new file mode 100644 index 00000000..e6fd0f75 --- /dev/null +++ b/src/sprite/plyr-settings.svg @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg version="1.1" width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"> +<path d="M15.135,6.784c-1.303-0.326-1.921-1.818-1.23-2.969c0.322-0.536,0.225-0.998-0.094-1.316l-0.31-0.31 + c-0.318-0.318-0.78-0.415-1.316-0.094c-1.152,0.691-2.644,0.073-2.969-1.23C9.065,0.258,8.669,0,8.219,0H7.781 + c-0.45,0-0.845,0.258-0.997,0.865c-0.326,1.303-1.818,1.921-2.969,1.23C3.279,1.773,2.816,1.87,2.498,2.188l-0.31,0.31 + C1.87,2.816,1.773,3.279,2.095,3.815c0.691,1.152,0.073,2.644-1.23,2.969C0.26,6.935,0,7.33,0,7.781v0.438 + c0,0.45,0.258,0.845,0.865,0.997c1.303,0.326,1.921,1.818,1.23,2.969c-0.322,0.536-0.225,0.998,0.094,1.316l0.31,0.31 + c0.319,0.319,0.782,0.415,1.316,0.094c1.152-0.691,2.644-0.073,2.969,1.23C6.935,15.742,7.331,16,7.781,16h0.438 + c0.45,0,0.845-0.258,0.997-0.865c0.326-1.303,1.818-1.921,2.969-1.23c0.535,0.321,0.997,0.225,1.316-0.094l0.31-0.31 + c0.318-0.318,0.415-0.781,0.094-1.316c-0.691-1.152-0.073-2.644,1.23-2.969C15.742,9.065,16,8.669,16,8.219V7.781 + C16,7.33,15.74,6.935,15.135,6.784z M8,11c-1.657,0-3-1.343-3-3s1.343-3,3-3s3,1.343,3,3S9.657,11,8,11z"/> +</svg> |