More work on menus
This commit is contained in:
2
demo/dist/demo.css
vendored
2
demo/dist/demo.css
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.css
vendored
2
dist/plyr.css
vendored
File diff suppressed because one or more lines are too long
133
dist/plyr.js
vendored
133
dist/plyr.js
vendored
@ -1624,7 +1624,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
var attributes = getAttributesFromSelector(this.config.selectors.display[type]);
|
var attributes = getAttributesFromSelector(this.config.selectors.display[type]);
|
||||||
|
|
||||||
var container = createElement('div', extend(attributes, {
|
var container = createElement('div', extend(attributes, {
|
||||||
class: 'plyr__time ' + attributes.class,
|
class: (this.config.classNames.display.time + ' ' + (attributes.class ? attributes.class : '')).trim(),
|
||||||
'aria-label': i18n.get(type, this.config)
|
'aria-label': i18n.get(type, this.config)
|
||||||
}), '00:00');
|
}), '00:00');
|
||||||
|
|
||||||
@ -1646,16 +1646,42 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
_ref$checked = _ref.checked,
|
_ref$checked = _ref.checked,
|
||||||
checked = _ref$checked === undefined ? false : _ref$checked;
|
checked = _ref$checked === undefined ? false : _ref$checked;
|
||||||
|
|
||||||
var item = createElement('button', extend(getAttributesFromSelector(this.config.selectors.inputs[type]), {
|
var attributes = getAttributesFromSelector(this.config.selectors.inputs[type]);
|
||||||
|
|
||||||
|
var item = createElement('button', extend(attributes, {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
|
role: 'menuitemradio',
|
||||||
|
class: (this.config.classNames.control + ' ' + (attributes.class ? attributes.class : '')).trim(),
|
||||||
value: value,
|
value: value,
|
||||||
'aria-checked': checked
|
'aria-checked': checked
|
||||||
}), title);
|
}));
|
||||||
|
|
||||||
|
// We have to set as HTML incase of special characters
|
||||||
|
item.innerHTML = title;
|
||||||
|
|
||||||
if (is.element(badge)) {
|
if (is.element(badge)) {
|
||||||
item.appendChild(badge);
|
item.appendChild(badge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(item, 'checked', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function get$$1() {
|
||||||
|
return item.getAttribute('aria-checked') === 'true';
|
||||||
|
},
|
||||||
|
set: function set$$1(checked) {
|
||||||
|
// Ensure exclusivity
|
||||||
|
if (checked) {
|
||||||
|
Array.from(item.parentNode.children).filter(function (node) {
|
||||||
|
return matches(node, '[role="menuitemradio"]');
|
||||||
|
}).forEach(function (node) {
|
||||||
|
return node.setAttribute('aria-checked', 'false');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
item.setAttribute('aria-checked', checked ? 'true' : 'false');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
list.appendChild(item);
|
list.appendChild(item);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1930,12 +1956,12 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
var _this3 = this;
|
var _this3 = this;
|
||||||
|
|
||||||
// Menu required
|
// Menu required
|
||||||
if (!is.element(this.elements.settings.menus.quality)) {
|
if (!is.element(this.elements.settings.panels.quality)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var type = 'quality';
|
var type = 'quality';
|
||||||
var list = this.elements.settings.menus.quality.querySelector('[role="menu"]');
|
var list = this.elements.settings.panels.quality.querySelector('[role="menu"]');
|
||||||
|
|
||||||
// Set options if passed and filter based on uniqueness and config
|
// Set options if passed and filter based on uniqueness and config
|
||||||
if (is.array(options)) {
|
if (is.array(options)) {
|
||||||
@ -2018,7 +2044,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Update the selected setting
|
// Update the selected setting
|
||||||
updateSetting: function updateSetting(setting, container, input) {
|
updateSetting: function updateSetting(setting, container, input) {
|
||||||
var pane = this.elements.settings.menus[setting];
|
var pane = this.elements.settings.panels[setting];
|
||||||
var value = null;
|
var value = null;
|
||||||
var list = container;
|
var list = container;
|
||||||
|
|
||||||
@ -2060,10 +2086,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
label.innerHTML = controls.getLabel.call(this, setting, value);
|
label.innerHTML = controls.getLabel.call(this, setting, value);
|
||||||
|
|
||||||
// Find the radio option and check it
|
// Find the radio option and check it
|
||||||
var target = list && list.querySelector('button[value="' + value + '"]');
|
var target = list && list.querySelector('[value="' + value + '"]');
|
||||||
|
|
||||||
if (is.element(target)) {
|
if (is.element(target)) {
|
||||||
target.setAttribute('aria-checked', true);
|
target.checked = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -2071,14 +2097,14 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Set the looping options
|
// Set the looping options
|
||||||
/* setLoopMenu() {
|
/* setLoopMenu() {
|
||||||
// Menu required
|
// Menu required
|
||||||
if (!is.element(this.elements.settings.menus.loop)) {
|
if (!is.element(this.elements.settings.panels.loop)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const options = ['start', 'end', 'all', 'reset'];
|
const options = ['start', 'end', 'all', 'reset'];
|
||||||
const list = this.elements.settings.menus.loop.querySelector('[role="menu"]');
|
const list = this.elements.settings.panels.loop.querySelector('[role="menu"]');
|
||||||
// Show the pane and tab
|
// Show the pane and tab
|
||||||
toggleHidden(this.elements.settings.buttons.loop, false);
|
toggleHidden(this.elements.settings.buttons.loop, false);
|
||||||
toggleHidden(this.elements.settings.menus.loop, false);
|
toggleHidden(this.elements.settings.panels.loop, false);
|
||||||
// Toggle the pane and tab
|
// Toggle the pane and tab
|
||||||
const toggle = !is.empty(this.loop.options);
|
const toggle = !is.empty(this.loop.options);
|
||||||
controls.toggleMenuButton.call(this, 'loop', toggle);
|
controls.toggleMenuButton.call(this, 'loop', toggle);
|
||||||
@ -2113,7 +2139,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// TODO: Captions or language? Currently it's mixed
|
// TODO: Captions or language? Currently it's mixed
|
||||||
var type = 'captions';
|
var type = 'captions';
|
||||||
var list = this.elements.settings.menus.captions.querySelector('[role="menu"]');
|
var list = this.elements.settings.panels.captions.querySelector('[role="menu"]');
|
||||||
var tracks = captions.getTracks.call(this);
|
var tracks = captions.getTracks.call(this);
|
||||||
|
|
||||||
// Toggle the pane and tab
|
// Toggle the pane and tab
|
||||||
@ -2168,7 +2194,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Menu required
|
// Menu required
|
||||||
if (!is.element(this.elements.settings.menus.speed)) {
|
if (!is.element(this.elements.settings.panels.speed)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2199,7 +2225,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the list to populate
|
// Get the list to populate
|
||||||
var list = this.elements.settings.menus.speed.querySelector('[role="menu"]');
|
var list = this.elements.settings.panels.speed.querySelector('[role="menu"]');
|
||||||
|
|
||||||
// Empty the menu
|
// Empty the menu
|
||||||
emptyElement(list);
|
emptyElement(list);
|
||||||
@ -2278,19 +2304,13 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
// Get the natural size of a tab
|
// Get the natural size of a menu panel
|
||||||
getTabSize: function getTabSize(tab) {
|
getMenuSize: function getMenuSize(tab) {
|
||||||
var clone = tab.cloneNode(true);
|
var clone = tab.cloneNode(true);
|
||||||
clone.style.position = 'absolute';
|
clone.style.position = 'absolute';
|
||||||
clone.style.opacity = 0;
|
clone.style.opacity = 0;
|
||||||
clone.removeAttribute('hidden');
|
clone.removeAttribute('hidden');
|
||||||
|
|
||||||
// Prevent input's being unchecked due to the name being identical
|
|
||||||
/* Array.from(clone.querySelectorAll('input[name]')).forEach(input => {
|
|
||||||
const name = input.getAttribute('name');
|
|
||||||
input.setAttribute('name', `${name}-clone`);
|
|
||||||
}); */
|
|
||||||
|
|
||||||
// Append to parent so we get the "real" size
|
// Append to parent so we get the "real" size
|
||||||
tab.parentNode.appendChild(clone);
|
tab.parentNode.appendChild(clone);
|
||||||
|
|
||||||
@ -2308,38 +2328,24 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
// Toggle Menu
|
// Show a panel in the menu
|
||||||
showMenu: function showMenu() {
|
showMenuPanel: function showMenuPanel() {
|
||||||
var _this6 = this;
|
var _this6 = this;
|
||||||
|
|
||||||
var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
||||||
var menu = this.elements.settings.menu;
|
|
||||||
|
|
||||||
var pane = document.getElementById('plyr-settings-' + this.id + '-' + type);
|
var target = document.getElementById('plyr-settings-' + this.id + '-' + type);
|
||||||
|
|
||||||
console.warn('plyr-settings-' + this.id + '-' + type);
|
|
||||||
|
|
||||||
// Nothing to show, bail
|
// Nothing to show, bail
|
||||||
if (!is.element(pane)) {
|
if (!is.element(target)) {
|
||||||
console.warn('No pane found');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we targeting a tab? If not, bail
|
// Hide all other panels
|
||||||
/* const isTab = pane.getAttribute('role') === 'tabpanel';
|
var container = target.parentNode;
|
||||||
if (!isTab) {
|
var current = Array.from(container.children).find(function (node) {
|
||||||
return;
|
return !node.hidden;
|
||||||
} */
|
});
|
||||||
|
|
||||||
// Hide all other tabs
|
|
||||||
// Get other tabs
|
|
||||||
var current = menu.querySelector('[id^=plyr-settings-' + this.id + ']:not([hidden])');
|
|
||||||
var container = current.parentNode;
|
|
||||||
|
|
||||||
// Set other toggles to be expanded false
|
|
||||||
/* Array.from(menu.querySelectorAll(`[aria-controls="${current.getAttribute('id')}"]`)).forEach(toggle => {
|
|
||||||
toggle.setAttribute('aria-expanded', false);
|
|
||||||
}); */
|
|
||||||
|
|
||||||
// If we can do fancy animations, we'll animate the height/width
|
// If we can do fancy animations, we'll animate the height/width
|
||||||
if (support.transitions && !support.reducedMotion) {
|
if (support.transitions && !support.reducedMotion) {
|
||||||
@ -2348,12 +2354,12 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
container.style.height = current.scrollHeight + 'px';
|
container.style.height = current.scrollHeight + 'px';
|
||||||
|
|
||||||
// Get potential sizes
|
// Get potential sizes
|
||||||
var size = controls.getTabSize.call(this, pane);
|
var size = controls.getMenuSize.call(this, target);
|
||||||
|
|
||||||
// Restore auto height/width
|
// Restore auto height/width
|
||||||
var restore = function restore(e) {
|
var restore = function restore(event) {
|
||||||
// We're only bothered about height and width on the container
|
// We're only bothered about height and width on the container
|
||||||
if (e.target !== container || !['width', 'height'].includes(e.propertyName)) {
|
if (event.target !== container || !['width', 'height'].includes(event.propertyName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2378,16 +2384,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// current.setAttribute('tabindex', -1);
|
// current.setAttribute('tabindex', -1);
|
||||||
|
|
||||||
// Set attributes on target
|
// Set attributes on target
|
||||||
toggleHidden(pane, false);
|
toggleHidden(target, false);
|
||||||
|
|
||||||
/* const tabs = getElements.call(this, `[aria-controls="${target}"]`);
|
|
||||||
Array.from(tabs).forEach(tab => {
|
|
||||||
tab.setAttribute('aria-expanded', true);
|
|
||||||
});
|
|
||||||
pane.removeAttribute('tabindex'); */
|
|
||||||
|
|
||||||
// Focus the first item
|
// Focus the first item
|
||||||
pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus();
|
target.querySelectorAll('[role^="menuitem"]')[0].focus();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -2532,7 +2532,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
var menuItem = createElement('button', extend(getAttributesFromSelector(_this7.config.selectors.buttons.settings), {
|
var menuItem = createElement('button', extend(getAttributesFromSelector(_this7.config.selectors.buttons.settings), {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
class: _this7.config.classNames.control + ' ' + _this7.config.classNames.control + '--forward',
|
class: _this7.config.classNames.control + ' ' + _this7.config.classNames.control + '--forward',
|
||||||
'role': 'menuitem',
|
role: 'menuitem',
|
||||||
'aria-haspopup': true
|
'aria-haspopup': true
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -2556,10 +2556,14 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Back button
|
// Back button
|
||||||
pane.appendChild(createElement('button', {
|
var back = createElement('button', {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
class: _this7.config.classNames.control + ' ' + _this7.config.classNames.control + '--back'
|
class: _this7.config.classNames.control + ' ' + _this7.config.classNames.control + '--back'
|
||||||
}, i18n.get(type, _this7.config)));
|
}, i18n.get(type, _this7.config));
|
||||||
|
back.addEventListener('click', function () {
|
||||||
|
controls.showMenuPanel.call(_this7, 'home');
|
||||||
|
});
|
||||||
|
pane.appendChild(back);
|
||||||
|
|
||||||
// Menu
|
// Menu
|
||||||
pane.appendChild(createElement('div', {
|
pane.appendChild(createElement('div', {
|
||||||
@ -2569,11 +2573,11 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
inner.appendChild(pane);
|
inner.appendChild(pane);
|
||||||
|
|
||||||
menuItem.addEventListener('click', function () {
|
menuItem.addEventListener('click', function () {
|
||||||
controls.showMenu.call(_this7, type);
|
controls.showMenuPanel.call(_this7, type);
|
||||||
});
|
});
|
||||||
|
|
||||||
_this7.elements.settings.buttons[type] = menuItem;
|
_this7.elements.settings.buttons[type] = menuItem;
|
||||||
_this7.elements.settings.menus[type] = pane;
|
_this7.elements.settings.panels[type] = pane;
|
||||||
});
|
});
|
||||||
|
|
||||||
home.appendChild(menu);
|
home.appendChild(menu);
|
||||||
@ -3482,6 +3486,9 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
isTouch: 'plyr--is-touch',
|
isTouch: 'plyr--is-touch',
|
||||||
uiSupported: 'plyr--full-ui',
|
uiSupported: 'plyr--full-ui',
|
||||||
noTransition: 'plyr--no-transition',
|
noTransition: 'plyr--no-transition',
|
||||||
|
display: {
|
||||||
|
time: 'plyr__time'
|
||||||
|
},
|
||||||
menu: {
|
menu: {
|
||||||
value: 'plyr__menu__value',
|
value: 'plyr__menu__value',
|
||||||
badge: 'plyr__badge',
|
badge: 'plyr__badge',
|
||||||
@ -4608,7 +4615,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Go back to home tab on click
|
// Go back to home tab on click
|
||||||
var showHomeTab = function showHomeTab() {
|
var showHomeTab = function showHomeTab() {
|
||||||
controls.showMenu.call(_this4.player, 'home');
|
controls.showMenuPanel.call(_this4.player, 'home');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Settings menu items - use event delegation as items are added/removed
|
// Settings menu items - use event delegation as items are added/removed
|
||||||
@ -6942,7 +6949,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
settings: {
|
settings: {
|
||||||
popup: null,
|
popup: null,
|
||||||
menu: null,
|
menu: null,
|
||||||
menus: {},
|
panels: {},
|
||||||
buttons: {}
|
buttons: {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
2
dist/plyr.js.map
vendored
2
dist/plyr.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.min.js
vendored
2
dist/plyr.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.min.js.map
vendored
2
dist/plyr.min.js.map
vendored
File diff suppressed because one or more lines are too long
@ -354,6 +354,9 @@ const defaults = {
|
|||||||
isTouch: 'plyr--is-touch',
|
isTouch: 'plyr--is-touch',
|
||||||
uiSupported: 'plyr--full-ui',
|
uiSupported: 'plyr--full-ui',
|
||||||
noTransition: 'plyr--no-transition',
|
noTransition: 'plyr--no-transition',
|
||||||
|
display: {
|
||||||
|
time: 'plyr__time',
|
||||||
|
},
|
||||||
menu: {
|
menu: {
|
||||||
value: 'plyr__menu__value',
|
value: 'plyr__menu__value',
|
||||||
badge: 'plyr__badge',
|
badge: 'plyr__badge',
|
||||||
|
146
src/js/controls.js
vendored
146
src/js/controls.js
vendored
@ -9,19 +9,7 @@ import support from './support';
|
|||||||
import { repaint, transitionEndEvent } from './utils/animation';
|
import { repaint, transitionEndEvent } from './utils/animation';
|
||||||
import { dedupe } from './utils/arrays';
|
import { dedupe } from './utils/arrays';
|
||||||
import browser from './utils/browser';
|
import browser from './utils/browser';
|
||||||
import {
|
import { createElement, emptyElement, getAttributesFromSelector, getElement, getElements, hasClass, matches, removeElement, setAttributes, toggleClass, toggleHidden } from './utils/elements';
|
||||||
createElement,
|
|
||||||
emptyElement,
|
|
||||||
getAttributesFromSelector,
|
|
||||||
getElement,
|
|
||||||
getElements,
|
|
||||||
hasClass,
|
|
||||||
removeElement,
|
|
||||||
setAttributes,
|
|
||||||
toggleClass,
|
|
||||||
toggleHidden,
|
|
||||||
matches,
|
|
||||||
} from './utils/elements';
|
|
||||||
import { off, on } from './utils/events';
|
import { off, on } from './utils/events';
|
||||||
import is from './utils/is';
|
import is from './utils/is';
|
||||||
import loadSprite from './utils/loadSprite';
|
import loadSprite from './utils/loadSprite';
|
||||||
@ -360,7 +348,7 @@ const controls = {
|
|||||||
const container = createElement(
|
const container = createElement(
|
||||||
'div',
|
'div',
|
||||||
extend(attributes, {
|
extend(attributes, {
|
||||||
class: `plyr__time ${attributes.class}`,
|
class: `${this.config.classNames.display.time} ${attributes.class ? attributes.class : ''}`.trim(),
|
||||||
'aria-label': i18n.get(type, this.config),
|
'aria-label': i18n.get(type, this.config),
|
||||||
}),
|
}),
|
||||||
'00:00',
|
'00:00',
|
||||||
@ -374,20 +362,43 @@ const controls = {
|
|||||||
|
|
||||||
// Create a settings menu item
|
// Create a settings menu item
|
||||||
createMenuItem({ value, list, type, title, badge = null, checked = false }) {
|
createMenuItem({ value, list, type, title, badge = null, checked = false }) {
|
||||||
|
const attributes = getAttributesFromSelector(this.config.selectors.inputs[type]);
|
||||||
|
|
||||||
const item = createElement(
|
const item = createElement(
|
||||||
'button',
|
'button',
|
||||||
extend(getAttributesFromSelector(this.config.selectors.inputs[type]), {
|
extend(attributes, {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
|
role: 'menuitemradio',
|
||||||
|
class: `${this.config.classNames.control} ${attributes.class ? attributes.class : ''}`.trim(),
|
||||||
value,
|
value,
|
||||||
'aria-checked': checked,
|
'aria-checked': checked,
|
||||||
}),
|
})
|
||||||
title,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// We have to set as HTML incase of special characters
|
||||||
|
item.innerHTML = title;
|
||||||
|
|
||||||
if (is.element(badge)) {
|
if (is.element(badge)) {
|
||||||
item.appendChild(badge);
|
item.appendChild(badge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(item, 'checked', {
|
||||||
|
enumerable: true,
|
||||||
|
get() {
|
||||||
|
return item.getAttribute('aria-checked') === 'true';
|
||||||
|
},
|
||||||
|
set(checked) {
|
||||||
|
// Ensure exclusivity
|
||||||
|
if (checked) {
|
||||||
|
Array.from(item.parentNode.children)
|
||||||
|
.filter(node => matches(node, '[role="menuitemradio"]'))
|
||||||
|
.forEach(node => node.setAttribute('aria-checked', 'false'));
|
||||||
|
}
|
||||||
|
|
||||||
|
item.setAttribute('aria-checked', checked ? 'true' : 'false');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
list.appendChild(item);
|
list.appendChild(item);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -649,12 +660,12 @@ const controls = {
|
|||||||
// Set the quality menu
|
// Set the quality menu
|
||||||
setQualityMenu(options) {
|
setQualityMenu(options) {
|
||||||
// Menu required
|
// Menu required
|
||||||
if (!is.element(this.elements.settings.menus.quality)) {
|
if (!is.element(this.elements.settings.panels.quality)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const type = 'quality';
|
const type = 'quality';
|
||||||
const list = this.elements.settings.menus.quality.querySelector('[role="menu"]');
|
const list = this.elements.settings.panels.quality.querySelector('[role="menu"]');
|
||||||
|
|
||||||
// Set options if passed and filter based on uniqueness and config
|
// Set options if passed and filter based on uniqueness and config
|
||||||
if (is.array(options)) {
|
if (is.array(options)) {
|
||||||
@ -735,7 +746,7 @@ const controls = {
|
|||||||
|
|
||||||
// Update the selected setting
|
// Update the selected setting
|
||||||
updateSetting(setting, container, input) {
|
updateSetting(setting, container, input) {
|
||||||
const pane = this.elements.settings.menus[setting];
|
const pane = this.elements.settings.panels[setting];
|
||||||
let value = null;
|
let value = null;
|
||||||
let list = container;
|
let list = container;
|
||||||
|
|
||||||
@ -777,26 +788,26 @@ const controls = {
|
|||||||
label.innerHTML = controls.getLabel.call(this, setting, value);
|
label.innerHTML = controls.getLabel.call(this, setting, value);
|
||||||
|
|
||||||
// Find the radio option and check it
|
// Find the radio option and check it
|
||||||
const target = list && list.querySelector(`button[value="${value}"]`);
|
const target = list && list.querySelector(`[value="${value}"]`);
|
||||||
|
|
||||||
if (is.element(target)) {
|
if (is.element(target)) {
|
||||||
target.setAttribute('aria-checked', true);
|
target.checked = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set the looping options
|
// Set the looping options
|
||||||
/* setLoopMenu() {
|
/* setLoopMenu() {
|
||||||
// Menu required
|
// Menu required
|
||||||
if (!is.element(this.elements.settings.menus.loop)) {
|
if (!is.element(this.elements.settings.panels.loop)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = ['start', 'end', 'all', 'reset'];
|
const options = ['start', 'end', 'all', 'reset'];
|
||||||
const list = this.elements.settings.menus.loop.querySelector('[role="menu"]');
|
const list = this.elements.settings.panels.loop.querySelector('[role="menu"]');
|
||||||
|
|
||||||
// Show the pane and tab
|
// Show the pane and tab
|
||||||
toggleHidden(this.elements.settings.buttons.loop, false);
|
toggleHidden(this.elements.settings.buttons.loop, false);
|
||||||
toggleHidden(this.elements.settings.menus.loop, false);
|
toggleHidden(this.elements.settings.panels.loop, false);
|
||||||
|
|
||||||
// Toggle the pane and tab
|
// Toggle the pane and tab
|
||||||
const toggle = !is.empty(this.loop.options);
|
const toggle = !is.empty(this.loop.options);
|
||||||
@ -835,7 +846,7 @@ const controls = {
|
|||||||
setCaptionsMenu() {
|
setCaptionsMenu() {
|
||||||
// TODO: Captions or language? Currently it's mixed
|
// TODO: Captions or language? Currently it's mixed
|
||||||
const type = 'captions';
|
const type = 'captions';
|
||||||
const list = this.elements.settings.menus.captions.querySelector('[role="menu"]');
|
const list = this.elements.settings.panels.captions.querySelector('[role="menu"]');
|
||||||
const tracks = captions.getTracks.call(this);
|
const tracks = captions.getTracks.call(this);
|
||||||
|
|
||||||
// Toggle the pane and tab
|
// Toggle the pane and tab
|
||||||
@ -885,7 +896,7 @@ const controls = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Menu required
|
// Menu required
|
||||||
if (!is.element(this.elements.settings.menus.speed)) {
|
if (!is.element(this.elements.settings.panels.speed)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -914,7 +925,7 @@ const controls = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the list to populate
|
// Get the list to populate
|
||||||
const list = this.elements.settings.menus.speed.querySelector('[role="menu"]');
|
const list = this.elements.settings.panels.speed.querySelector('[role="menu"]');
|
||||||
|
|
||||||
// Empty the menu
|
// Empty the menu
|
||||||
emptyElement(list);
|
emptyElement(list);
|
||||||
@ -986,19 +997,13 @@ const controls = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Get the natural size of a tab
|
// Get the natural size of a menu panel
|
||||||
getTabSize(tab) {
|
getMenuSize(tab) {
|
||||||
const clone = tab.cloneNode(true);
|
const clone = tab.cloneNode(true);
|
||||||
clone.style.position = 'absolute';
|
clone.style.position = 'absolute';
|
||||||
clone.style.opacity = 0;
|
clone.style.opacity = 0;
|
||||||
clone.removeAttribute('hidden');
|
clone.removeAttribute('hidden');
|
||||||
|
|
||||||
// Prevent input's being unchecked due to the name being identical
|
|
||||||
/* Array.from(clone.querySelectorAll('input[name]')).forEach(input => {
|
|
||||||
const name = input.getAttribute('name');
|
|
||||||
input.setAttribute('name', `${name}-clone`);
|
|
||||||
}); */
|
|
||||||
|
|
||||||
// Append to parent so we get the "real" size
|
// Append to parent so we get the "real" size
|
||||||
tab.parentNode.appendChild(clone);
|
tab.parentNode.appendChild(clone);
|
||||||
|
|
||||||
@ -1015,34 +1020,18 @@ const controls = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
// Toggle Menu
|
// Show a panel in the menu
|
||||||
showMenu(type = '') {
|
showMenuPanel(type = '') {
|
||||||
const { menu } = this.elements.settings;
|
const target = document.getElementById(`plyr-settings-${this.id}-${type}`);
|
||||||
const pane = document.getElementById(`plyr-settings-${this.id}-${type}`);
|
|
||||||
|
|
||||||
console.warn(`plyr-settings-${this.id}-${type}`);
|
|
||||||
|
|
||||||
// Nothing to show, bail
|
// Nothing to show, bail
|
||||||
if (!is.element(pane)) {
|
if (!is.element(target)) {
|
||||||
console.warn('No pane found');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we targeting a tab? If not, bail
|
// Hide all other panels
|
||||||
/* const isTab = pane.getAttribute('role') === 'tabpanel';
|
const container = target.parentNode;
|
||||||
if (!isTab) {
|
const current = Array.from(container.children).find(node => !node.hidden);
|
||||||
return;
|
|
||||||
} */
|
|
||||||
|
|
||||||
// Hide all other tabs
|
|
||||||
// Get other tabs
|
|
||||||
const current = menu.querySelector(`[id^=plyr-settings-${this.id}]:not([hidden])`);
|
|
||||||
const container = current.parentNode;
|
|
||||||
|
|
||||||
// Set other toggles to be expanded false
|
|
||||||
/* Array.from(menu.querySelectorAll(`[aria-controls="${current.getAttribute('id')}"]`)).forEach(toggle => {
|
|
||||||
toggle.setAttribute('aria-expanded', false);
|
|
||||||
}); */
|
|
||||||
|
|
||||||
// If we can do fancy animations, we'll animate the height/width
|
// If we can do fancy animations, we'll animate the height/width
|
||||||
if (support.transitions && !support.reducedMotion) {
|
if (support.transitions && !support.reducedMotion) {
|
||||||
@ -1051,12 +1040,12 @@ const controls = {
|
|||||||
container.style.height = `${current.scrollHeight}px`;
|
container.style.height = `${current.scrollHeight}px`;
|
||||||
|
|
||||||
// Get potential sizes
|
// Get potential sizes
|
||||||
const size = controls.getTabSize.call(this, pane);
|
const size = controls.getMenuSize.call(this, target);
|
||||||
|
|
||||||
// Restore auto height/width
|
// Restore auto height/width
|
||||||
const restore = e => {
|
const restore = event => {
|
||||||
// We're only bothered about height and width on the container
|
// We're only bothered about height and width on the container
|
||||||
if (e.target !== container || !['width', 'height'].includes(e.propertyName)) {
|
if (event.target !== container || !['width', 'height'].includes(event.propertyName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1081,16 +1070,10 @@ const controls = {
|
|||||||
// current.setAttribute('tabindex', -1);
|
// current.setAttribute('tabindex', -1);
|
||||||
|
|
||||||
// Set attributes on target
|
// Set attributes on target
|
||||||
toggleHidden(pane, false);
|
toggleHidden(target, false);
|
||||||
|
|
||||||
/* const tabs = getElements.call(this, `[aria-controls="${target}"]`);
|
|
||||||
Array.from(tabs).forEach(tab => {
|
|
||||||
tab.setAttribute('aria-expanded', true);
|
|
||||||
});
|
|
||||||
pane.removeAttribute('tabindex'); */
|
|
||||||
|
|
||||||
// Focus the first item
|
// Focus the first item
|
||||||
pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus();
|
target.querySelectorAll('[role^="menuitem"]')[0].focus();
|
||||||
},
|
},
|
||||||
|
|
||||||
// Build the default HTML
|
// Build the default HTML
|
||||||
@ -1248,12 +1231,12 @@ const controls = {
|
|||||||
extend(getAttributesFromSelector(this.config.selectors.buttons.settings), {
|
extend(getAttributesFromSelector(this.config.selectors.buttons.settings), {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,
|
class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,
|
||||||
'role': 'menuitem',
|
role: 'menuitem',
|
||||||
'aria-haspopup': true,
|
'aria-haspopup': true,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const flex = createElement('span', null, i18n.get(type, this.config))
|
const flex = createElement('span', null, i18n.get(type, this.config));
|
||||||
|
|
||||||
const value = createElement('span', {
|
const value = createElement('span', {
|
||||||
class: this.config.classNames.menu.value,
|
class: this.config.classNames.menu.value,
|
||||||
@ -1266,7 +1249,6 @@ const controls = {
|
|||||||
menuItem.appendChild(flex);
|
menuItem.appendChild(flex);
|
||||||
menu.appendChild(menuItem);
|
menu.appendChild(menuItem);
|
||||||
|
|
||||||
|
|
||||||
// Build the panes
|
// Build the panes
|
||||||
const pane = createElement('div', {
|
const pane = createElement('div', {
|
||||||
id: `plyr-settings-${data.id}-${type}`,
|
id: `plyr-settings-${data.id}-${type}`,
|
||||||
@ -1274,28 +1256,34 @@ const controls = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Back button
|
// Back button
|
||||||
pane.appendChild(createElement(
|
const back = createElement(
|
||||||
'button',
|
'button',
|
||||||
{
|
{
|
||||||
type: 'button',
|
type: 'button',
|
||||||
class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,
|
class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,
|
||||||
},
|
},
|
||||||
i18n.get(type, this.config),
|
i18n.get(type, this.config),
|
||||||
));
|
);
|
||||||
|
back.addEventListener('click', () => {
|
||||||
|
controls.showMenuPanel.call(this, 'home');
|
||||||
|
});
|
||||||
|
pane.appendChild(back);
|
||||||
|
|
||||||
// Menu
|
// Menu
|
||||||
pane.appendChild(createElement('div', {
|
pane.appendChild(
|
||||||
|
createElement('div', {
|
||||||
role: 'menu',
|
role: 'menu',
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
inner.appendChild(pane);
|
inner.appendChild(pane);
|
||||||
|
|
||||||
menuItem.addEventListener('click', () => {
|
menuItem.addEventListener('click', () => {
|
||||||
controls.showMenu.call(this, type);
|
controls.showMenuPanel.call(this, type);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.elements.settings.buttons[type] = menuItem;
|
this.elements.settings.buttons[type] = menuItem;
|
||||||
this.elements.settings.menus[type] = pane;
|
this.elements.settings.panels[type] = pane;
|
||||||
});
|
});
|
||||||
|
|
||||||
home.appendChild(menu);
|
home.appendChild(menu);
|
||||||
|
@ -491,7 +491,7 @@ class Listeners {
|
|||||||
|
|
||||||
// Go back to home tab on click
|
// Go back to home tab on click
|
||||||
const showHomeTab = () => {
|
const showHomeTab = () => {
|
||||||
controls.showMenu.call(this.player, 'home');
|
controls.showMenuPanel.call(this.player, 'home');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Settings menu items - use event delegation as items are added/removed
|
// Settings menu items - use event delegation as items are added/removed
|
||||||
|
@ -83,7 +83,7 @@ class Plyr {
|
|||||||
settings: {
|
settings: {
|
||||||
popup: null,
|
popup: null,
|
||||||
menu: null,
|
menu: null,
|
||||||
menus: {},
|
panels: {},
|
||||||
buttons: {},
|
buttons: {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -139,50 +139,49 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
label.plyr__control {
|
.plyr__control[role='menuitemradio'] {
|
||||||
padding-left: $plyr-control-padding;
|
padding-left: $plyr-control-padding;
|
||||||
|
|
||||||
input[type='radio'] + span {
|
&::before,
|
||||||
background: rgba(#000, 0.1);
|
&::after {
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
background: rgba(#000, 0.1);
|
||||||
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
margin-right: $plyr-control-spacing;
|
margin-right: $plyr-control-spacing;
|
||||||
position: relative;
|
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 100%;
|
border: 0;
|
||||||
content: '';
|
|
||||||
height: 6px;
|
height: 6px;
|
||||||
left: 5px;
|
left: 12px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
position: absolute;
|
top: 50%;
|
||||||
top: 5px;
|
transform: translateY(-50%) scale(0);
|
||||||
transform: scale(0);
|
|
||||||
transition: transform 0.3s ease, opacity 0.3s ease;
|
transition: transform 0.3s ease, opacity 0.3s ease;
|
||||||
width: 6px;
|
width: 6px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
input[type='radio']:checked + span {
|
&[aria-checked='true'] {
|
||||||
|
&::before {
|
||||||
background: $plyr-color-main;
|
background: $plyr-color-main;
|
||||||
|
}
|
||||||
&::after {
|
&::after {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scale(1);
|
transform: translateY(-50%) scale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type='radio']:focus + span {
|
&.plyr__tab-focus::before,
|
||||||
@include plyr-tab-focus();
|
&:hover::before {
|
||||||
}
|
|
||||||
|
|
||||||
&.plyr__tab-focus input[type='radio'] + span,
|
|
||||||
&:hover input[type='radio'] + span {
|
|
||||||
background: rgba(#000, 0.1);
|
background: rgba(#000, 0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user