Work on controls
This commit is contained in:
parent
599883e684
commit
ffd864ed39
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
249
dist/plyr.js
vendored
249
dist/plyr.js
vendored
@ -382,12 +382,19 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Inaert an element after another
|
// Inaert an element after another
|
||||||
function insertAfter(element, target) {
|
function insertAfter(element, target) {
|
||||||
|
if (!is.element(element) || !is.element(target)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
target.parentNode.insertBefore(element, target.nextSibling);
|
target.parentNode.insertBefore(element, target.nextSibling);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert a DocumentFragment
|
// Insert a DocumentFragment
|
||||||
function insertElement(type, parent, attributes, text) {
|
function insertElement(type, parent, attributes, text) {
|
||||||
// Inject the new <element>
|
if (!is.element(parent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
parent.appendChild(createElement(type, attributes, text));
|
parent.appendChild(createElement(type, attributes, text));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,6 +414,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Remove all child elements
|
// Remove all child elements
|
||||||
function emptyElement(element) {
|
function emptyElement(element) {
|
||||||
|
if (!is.element(element)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var length = element.childNodes.length;
|
var length = element.childNodes.length;
|
||||||
|
|
||||||
|
|
||||||
@ -1590,31 +1601,16 @@ 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('li');
|
var item = createElement('button', extend(getAttributesFromSelector(this.config.selectors.inputs[type]), {
|
||||||
|
type: 'button',
|
||||||
var label = createElement('label', {
|
|
||||||
class: this.config.classNames.control
|
|
||||||
});
|
|
||||||
|
|
||||||
var radio = createElement('input', extend(getAttributesFromSelector(this.config.selectors.inputs[type]), {
|
|
||||||
type: 'radio',
|
|
||||||
name: 'plyr-' + type,
|
|
||||||
value: value,
|
value: value,
|
||||||
checked: checked,
|
'aria-checked': checked
|
||||||
class: 'plyr__sr-only'
|
}), title);
|
||||||
}));
|
|
||||||
|
|
||||||
var faux = createElement('span', { hidden: '' });
|
|
||||||
|
|
||||||
label.appendChild(radio);
|
|
||||||
label.appendChild(faux);
|
|
||||||
label.insertAdjacentHTML('beforeend', title);
|
|
||||||
|
|
||||||
if (is.element(badge)) {
|
if (is.element(badge)) {
|
||||||
label.appendChild(badge);
|
item.appendChild(badge);
|
||||||
}
|
}
|
||||||
|
|
||||||
item.appendChild(label);
|
|
||||||
list.appendChild(item);
|
list.appendChild(item);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1879,8 +1875,8 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
|
|
||||||
// Hide/show a tab
|
// Hide/show a tab
|
||||||
toggleTab: function toggleTab(setting, toggle) {
|
toggleMenuButton: function toggleMenuButton(setting, toggle) {
|
||||||
toggleHidden(this.elements.settings.tabs[setting], !toggle);
|
toggleHidden(this.elements.settings.buttons[setting], !toggle);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -1889,12 +1885,12 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
var _this3 = this;
|
var _this3 = this;
|
||||||
|
|
||||||
// Menu required
|
// Menu required
|
||||||
if (!is.element(this.elements.settings.panes.quality)) {
|
if (!is.element(this.elements.settings.menus.quality)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var type = 'quality';
|
var type = 'quality';
|
||||||
var list = this.elements.settings.panes.quality.querySelector('ul');
|
var list = this.elements.settings.menus.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)) {
|
||||||
@ -1905,7 +1901,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Toggle the pane and tab
|
// Toggle the pane and tab
|
||||||
var toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;
|
var toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;
|
||||||
controls.toggleTab.call(this, type, toggle);
|
controls.toggleMenuButton.call(this, type, toggle);
|
||||||
|
|
||||||
// Check if we need to toggle the parent
|
// Check if we need to toggle the parent
|
||||||
controls.checkMenu.call(this);
|
controls.checkMenu.call(this);
|
||||||
@ -1977,7 +1973,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.panes[setting];
|
var pane = this.elements.settings.menus[setting];
|
||||||
var value = null;
|
var value = null;
|
||||||
var list = container;
|
var list = container;
|
||||||
|
|
||||||
@ -2006,7 +2002,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Get the list if we need to
|
// Get the list if we need to
|
||||||
if (!is.element(list)) {
|
if (!is.element(list)) {
|
||||||
list = pane && pane.querySelector('ul');
|
list = pane && pane.querySelector('[role="menu"]');
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's no list it means it's not been rendered...
|
// If there's no list it means it's not been rendered...
|
||||||
@ -2015,14 +2011,14 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the label
|
// Update the label
|
||||||
var label = this.elements.settings.tabs[setting].querySelector('.' + this.config.classNames.menu.value);
|
var label = this.elements.settings.buttons[setting].querySelector('.' + this.config.classNames.menu.value);
|
||||||
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('input[value="' + value + '"]');
|
var target = list && list.querySelector('button[value="' + value + '"]');
|
||||||
|
|
||||||
if (is.element(target)) {
|
if (is.element(target)) {
|
||||||
target.checked = true;
|
target.setAttribute('aria-checked', true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -2030,17 +2026,17 @@ 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.panes.loop)) {
|
if (!is.element(this.elements.settings.menus.loop)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const options = ['start', 'end', 'all', 'reset'];
|
const options = ['start', 'end', 'all', 'reset'];
|
||||||
const list = this.elements.settings.panes.loop.querySelector('ul');
|
const list = this.elements.settings.menus.loop.querySelector('[role="menu"]');
|
||||||
// Show the pane and tab
|
// Show the pane and tab
|
||||||
toggleHidden(this.elements.settings.tabs.loop, false);
|
toggleHidden(this.elements.settings.buttons.loop, false);
|
||||||
toggleHidden(this.elements.settings.panes.loop, false);
|
toggleHidden(this.elements.settings.menus.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.toggleTab.call(this, 'loop', toggle);
|
controls.toggleMenuButton.call(this, 'loop', toggle);
|
||||||
// Empty the menu
|
// Empty the menu
|
||||||
emptyElement(list);
|
emptyElement(list);
|
||||||
options.forEach(option => {
|
options.forEach(option => {
|
||||||
@ -2072,11 +2068,11 @@ 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.panes.captions.querySelector('ul');
|
var list = this.elements.settings.menus.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
|
||||||
controls.toggleTab.call(this, type, tracks.length);
|
controls.toggleMenuButton.call(this, type, tracks.length);
|
||||||
|
|
||||||
// Empty the menu
|
// Empty the menu
|
||||||
emptyElement(list);
|
emptyElement(list);
|
||||||
@ -2127,7 +2123,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Menu required
|
// Menu required
|
||||||
if (!is.element(this.elements.settings.panes.speed)) {
|
if (!is.element(this.elements.settings.menus.speed)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2147,7 +2143,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Toggle the pane and tab
|
// Toggle the pane and tab
|
||||||
var toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;
|
var toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;
|
||||||
controls.toggleTab.call(this, type, toggle);
|
controls.toggleMenuButton.call(this, type, toggle);
|
||||||
|
|
||||||
// Check if we need to toggle the parent
|
// Check if we need to toggle the parent
|
||||||
controls.checkMenu.call(this);
|
controls.checkMenu.call(this);
|
||||||
@ -2158,7 +2154,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the list to populate
|
// Get the list to populate
|
||||||
var list = this.elements.settings.panes.speed.querySelector('ul');
|
var list = this.elements.settings.menus.speed.querySelector('[role="menu"]');
|
||||||
|
|
||||||
// Empty the menu
|
// Empty the menu
|
||||||
emptyElement(list);
|
emptyElement(list);
|
||||||
@ -2179,10 +2175,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Check if we need to hide/show the settings menu
|
// Check if we need to hide/show the settings menu
|
||||||
checkMenu: function checkMenu() {
|
checkMenu: function checkMenu() {
|
||||||
var tabs = this.elements.settings.tabs;
|
var buttons = this.elements.settings.buttons;
|
||||||
|
|
||||||
var visible = !is.empty(tabs) && Object.values(tabs).some(function (tab) {
|
var visible = !is.empty(buttons) && Object.values(buttons).some(function (button) {
|
||||||
return !tab.hidden;
|
return !button.hidden;
|
||||||
});
|
});
|
||||||
|
|
||||||
toggleHidden(this.elements.settings.menu, !visible);
|
toggleHidden(this.elements.settings.menu, !visible);
|
||||||
@ -2191,19 +2187,19 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Show/hide menu
|
// Show/hide menu
|
||||||
toggleMenu: function toggleMenu(event) {
|
toggleMenu: function toggleMenu(event) {
|
||||||
var form = this.elements.settings.form;
|
var popup = this.elements.settings.popup;
|
||||||
|
|
||||||
var button = this.elements.buttons.settings;
|
var button = this.elements.buttons.settings;
|
||||||
|
|
||||||
// Menu and button are required
|
// Menu and button are required
|
||||||
if (!is.element(form) || !is.element(button)) {
|
if (!is.element(popup) || !is.element(button)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var show = is.boolean(event) ? event : is.element(form) && form.hasAttribute('hidden');
|
var show = is.boolean(event) ? event : is.element(popup) && popup.hasAttribute('hidden');
|
||||||
|
|
||||||
if (is.event(event)) {
|
if (is.event(event)) {
|
||||||
var isMenuItem = is.element(form) && form.contains(event.target);
|
var isMenuItem = is.element(popup) && popup.contains(event.target);
|
||||||
var isButton = event.target === this.elements.buttons.settings;
|
var isButton = event.target === this.elements.buttons.settings;
|
||||||
|
|
||||||
// If the click was inside the form or if the click
|
// If the click was inside the form or if the click
|
||||||
@ -2224,14 +2220,14 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
button.setAttribute('aria-expanded', show);
|
button.setAttribute('aria-expanded', show);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is.element(form)) {
|
if (is.element(popup)) {
|
||||||
toggleHidden(form, !show);
|
toggleHidden(popup, !show);
|
||||||
toggleClass(this.elements.container, this.config.classNames.menu.open, show);
|
toggleClass(this.elements.container, this.config.classNames.menu.open, show);
|
||||||
|
|
||||||
if (show) {
|
if (show) {
|
||||||
form.removeAttribute('tabindex');
|
popup.removeAttribute('tabindex');
|
||||||
} else {
|
} else {
|
||||||
form.setAttribute('tabindex', -1);
|
popup.setAttribute('tabindex', -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2245,10 +2241,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
clone.removeAttribute('hidden');
|
clone.removeAttribute('hidden');
|
||||||
|
|
||||||
// Prevent input's being unchecked due to the name being identical
|
// Prevent input's being unchecked due to the name being identical
|
||||||
Array.from(clone.querySelectorAll('input[name]')).forEach(function (input) {
|
/* Array.from(clone.querySelectorAll('input[name]')).forEach(input => {
|
||||||
var name = input.getAttribute('name');
|
const name = input.getAttribute('name');
|
||||||
input.setAttribute('name', name + '-clone');
|
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);
|
||||||
@ -2268,34 +2264,37 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
|
|
||||||
// Toggle Menu
|
// Toggle Menu
|
||||||
showTab: function showTab() {
|
showMenu: function showMenu() {
|
||||||
var _this6 = this;
|
var _this6 = this;
|
||||||
|
|
||||||
var target = 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 menu = this.elements.settings.menu;
|
||||||
|
|
||||||
var pane = document.getElementById(target);
|
var 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(pane)) {
|
||||||
|
console.warn('No pane found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we targeting a tab? If not, bail
|
// Are we targeting a tab? If not, bail
|
||||||
var isTab = pane.getAttribute('role') === 'tabpanel';
|
/* const isTab = pane.getAttribute('role') === 'tabpanel';
|
||||||
if (!isTab) {
|
if (!isTab) {
|
||||||
return;
|
return;
|
||||||
}
|
} */
|
||||||
|
|
||||||
// Hide all other tabs
|
// Hide all other tabs
|
||||||
// Get other tabs
|
// Get other tabs
|
||||||
var current = menu.querySelector('[role="tabpanel"]:not([hidden])');
|
var current = menu.querySelector('[id^=plyr-settings-' + this.id + ']:not([hidden])');
|
||||||
var container = current.parentNode;
|
var container = current.parentNode;
|
||||||
|
|
||||||
// Set other toggles to be expanded false
|
// Set other toggles to be expanded false
|
||||||
Array.from(menu.querySelectorAll('[aria-controls="' + current.getAttribute('id') + '"]')).forEach(function (toggle) {
|
/* Array.from(menu.querySelectorAll(`[aria-controls="${current.getAttribute('id')}"]`)).forEach(toggle => {
|
||||||
toggle.setAttribute('aria-expanded', false);
|
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) {
|
||||||
@ -2331,16 +2330,16 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Set attributes on current tab
|
// Set attributes on current tab
|
||||||
toggleHidden(current, true);
|
toggleHidden(current, true);
|
||||||
current.setAttribute('tabindex', -1);
|
// current.setAttribute('tabindex', -1);
|
||||||
|
|
||||||
// Set attributes on target
|
// Set attributes on target
|
||||||
toggleHidden(pane, false);
|
toggleHidden(pane, false);
|
||||||
|
|
||||||
var tabs = getElements.call(this, '[aria-controls="' + target + '"]');
|
/* const tabs = getElements.call(this, `[aria-controls="${target}"]`);
|
||||||
Array.from(tabs).forEach(function (tab) {
|
Array.from(tabs).forEach(tab => {
|
||||||
tab.setAttribute('aria-expanded', true);
|
tab.setAttribute('aria-expanded', true);
|
||||||
});
|
});
|
||||||
pane.removeAttribute('tabindex');
|
pane.removeAttribute('tabindex'); */
|
||||||
|
|
||||||
// Focus the first item
|
// Focus the first item
|
||||||
pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus();
|
pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus();
|
||||||
@ -2453,55 +2452,46 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Settings button / menu
|
// Settings button / menu
|
||||||
if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) {
|
if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) {
|
||||||
var menu = createElement('div', {
|
var control = createElement('div', {
|
||||||
class: 'plyr__menu',
|
class: 'plyr__menu',
|
||||||
hidden: ''
|
hidden: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
menu.appendChild(controls.createButton.call(this, 'settings', {
|
control.appendChild(controls.createButton.call(this, 'settings', {
|
||||||
id: 'plyr-settings-toggle-' + data.id,
|
id: 'plyr-settings-toggle-' + data.id,
|
||||||
'aria-haspopup': true,
|
'aria-haspopup': true,
|
||||||
'aria-controls': 'plyr-settings-' + data.id,
|
'aria-controls': 'plyr-settings-' + data.id,
|
||||||
'aria-expanded': false
|
'aria-expanded': false
|
||||||
}));
|
}));
|
||||||
|
|
||||||
var form = createElement('form', {
|
var popup = createElement('div', {
|
||||||
class: 'plyr__menu__container',
|
class: 'plyr__menu__container',
|
||||||
id: 'plyr-settings-' + data.id,
|
id: 'plyr-settings-' + data.id,
|
||||||
hidden: '',
|
hidden: '',
|
||||||
'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
|
'aria-labelled-by': 'plyr-settings-toggle-' + data.id
|
||||||
role: 'tablist',
|
|
||||||
tabindex: -1
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var inner = createElement('div');
|
var inner = createElement('div');
|
||||||
|
|
||||||
var home = createElement('div', {
|
var home = createElement('div', {
|
||||||
id: 'plyr-settings-' + data.id + '-home',
|
id: 'plyr-settings-' + data.id + '-home'
|
||||||
'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
|
|
||||||
role: 'tabpanel'
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create the tab list
|
// Create the menu
|
||||||
var tabs = createElement('ul', {
|
var menu = createElement('div', {
|
||||||
role: 'tablist'
|
role: 'menu'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Build the tabs
|
// Build the menu items
|
||||||
this.config.settings.forEach(function (type) {
|
this.config.settings.forEach(function (type) {
|
||||||
var tab = createElement('li', {
|
var menuItem = createElement('button', extend(getAttributesFromSelector(_this7.config.selectors.buttons.settings), {
|
||||||
role: 'tab',
|
|
||||||
hidden: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
var button = 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',
|
||||||
id: 'plyr-settings-' + data.id + '-' + type + '-tab',
|
'role': 'menuitem',
|
||||||
'aria-haspopup': true,
|
'aria-haspopup': true
|
||||||
'aria-controls': 'plyr-settings-' + data.id + '-' + type,
|
}));
|
||||||
'aria-expanded': false
|
|
||||||
}), i18n.get(type, _this7.config));
|
var flex = createElement('span', null, i18n.get(type, _this7.config));
|
||||||
|
|
||||||
var value = createElement('span', {
|
var value = createElement('span', {
|
||||||
class: _this7.config.classNames.menu.value
|
class: _this7.config.classNames.menu.value
|
||||||
@ -2510,50 +2500,46 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Speed contains HTML entities
|
// Speed contains HTML entities
|
||||||
value.innerHTML = data[type];
|
value.innerHTML = data[type];
|
||||||
|
|
||||||
button.appendChild(value);
|
flex.appendChild(value);
|
||||||
tab.appendChild(button);
|
menuItem.appendChild(flex);
|
||||||
tabs.appendChild(tab);
|
menu.appendChild(menuItem);
|
||||||
|
|
||||||
_this7.elements.settings.tabs[type] = tab;
|
// Build the panes
|
||||||
});
|
|
||||||
|
|
||||||
home.appendChild(tabs);
|
|
||||||
inner.appendChild(home);
|
|
||||||
|
|
||||||
// Build the panes
|
|
||||||
this.config.settings.forEach(function (type) {
|
|
||||||
var pane = createElement('div', {
|
var pane = createElement('div', {
|
||||||
id: 'plyr-settings-' + data.id + '-' + type,
|
id: 'plyr-settings-' + data.id + '-' + type,
|
||||||
hidden: '',
|
hidden: ''
|
||||||
'aria-labelled-by': 'plyr-settings-' + data.id + '-' + type + '-tab',
|
|
||||||
role: 'tabpanel',
|
|
||||||
tabindex: -1
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var back = createElement('button', {
|
// Back button
|
||||||
|
pane.appendChild(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'
|
||||||
'aria-haspopup': true,
|
}, i18n.get(type, _this7.config)));
|
||||||
'aria-controls': 'plyr-settings-' + data.id + '-home',
|
|
||||||
'aria-expanded': false
|
|
||||||
}, i18n.get(type, _this7.config));
|
|
||||||
|
|
||||||
pane.appendChild(back);
|
// Menu
|
||||||
|
pane.appendChild(createElement('div', {
|
||||||
|
role: 'menu'
|
||||||
|
}));
|
||||||
|
|
||||||
var options = createElement('ul');
|
|
||||||
|
|
||||||
pane.appendChild(options);
|
|
||||||
inner.appendChild(pane);
|
inner.appendChild(pane);
|
||||||
|
|
||||||
_this7.elements.settings.panes[type] = pane;
|
menuItem.addEventListener('click', function () {
|
||||||
|
controls.showMenu.call(_this7, type);
|
||||||
|
});
|
||||||
|
|
||||||
|
_this7.elements.settings.buttons[type] = menuItem;
|
||||||
|
_this7.elements.settings.menus[type] = pane;
|
||||||
});
|
});
|
||||||
|
|
||||||
form.appendChild(inner);
|
home.appendChild(menu);
|
||||||
menu.appendChild(form);
|
inner.appendChild(home);
|
||||||
container.appendChild(menu);
|
|
||||||
|
|
||||||
this.elements.settings.form = form;
|
popup.appendChild(inner);
|
||||||
this.elements.settings.menu = menu;
|
control.appendChild(popup);
|
||||||
|
container.appendChild(control);
|
||||||
|
|
||||||
|
this.elements.settings.popup = popup;
|
||||||
|
this.elements.settings.menu = control;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Picture in picture button
|
// Picture in picture button
|
||||||
@ -4617,13 +4603,12 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Settings menu
|
// Settings menu
|
||||||
bind(this.player.elements.settings.form, 'click', function (event) {
|
bind(this.player.elements.settings.popup, 'click', function (event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
// Go back to home tab on click
|
// Go back to home tab on click
|
||||||
var showHomeTab = function showHomeTab() {
|
var showHomeTab = function showHomeTab() {
|
||||||
var id = 'plyr-settings-' + _this4.player.id + '-home';
|
controls.showMenu.call(_this4.player, 'home');
|
||||||
controls.showTab.call(_this4.player, id);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Settings menu items - use event delegation as items are added/removed
|
// Settings menu items - use event delegation as items are added/removed
|
||||||
@ -4642,9 +4627,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
_this4.player.speed = parseFloat(event.target.value);
|
_this4.player.speed = parseFloat(event.target.value);
|
||||||
showHomeTab();
|
showHomeTab();
|
||||||
}, 'speed');
|
}, 'speed');
|
||||||
} else {
|
|
||||||
var tab = event.target;
|
|
||||||
controls.showTab.call(_this4.player, tab.getAttribute('aria-controls'));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -6952,16 +6934,17 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Elements cache
|
// Elements cache
|
||||||
this.elements = {
|
this.elements = {
|
||||||
container: null,
|
container: null,
|
||||||
|
captions: null,
|
||||||
buttons: {},
|
buttons: {},
|
||||||
display: {},
|
display: {},
|
||||||
progress: {},
|
progress: {},
|
||||||
inputs: {},
|
inputs: {},
|
||||||
settings: {
|
settings: {
|
||||||
|
popup: null,
|
||||||
menu: null,
|
menu: null,
|
||||||
panes: {},
|
menus: {},
|
||||||
tabs: {}
|
buttons: {}
|
||||||
},
|
}
|
||||||
captions: null
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Captions
|
// Captions
|
||||||
|
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
198
src/js/controls.js
vendored
198
src/js/controls.js
vendored
@ -374,34 +374,20 @@ 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 item = createElement('li');
|
const item = createElement(
|
||||||
|
'button',
|
||||||
const label = createElement('label', {
|
|
||||||
class: this.config.classNames.control,
|
|
||||||
});
|
|
||||||
|
|
||||||
const radio = createElement(
|
|
||||||
'input',
|
|
||||||
extend(getAttributesFromSelector(this.config.selectors.inputs[type]), {
|
extend(getAttributesFromSelector(this.config.selectors.inputs[type]), {
|
||||||
type: 'radio',
|
type: 'button',
|
||||||
name: `plyr-${type}`,
|
|
||||||
value,
|
value,
|
||||||
checked,
|
'aria-checked': checked,
|
||||||
class: 'plyr__sr-only',
|
|
||||||
}),
|
}),
|
||||||
|
title,
|
||||||
);
|
);
|
||||||
|
|
||||||
const faux = createElement('span', { hidden: '' });
|
|
||||||
|
|
||||||
label.appendChild(radio);
|
|
||||||
label.appendChild(faux);
|
|
||||||
label.insertAdjacentHTML('beforeend', title);
|
|
||||||
|
|
||||||
if (is.element(badge)) {
|
if (is.element(badge)) {
|
||||||
label.appendChild(badge);
|
item.appendChild(badge);
|
||||||
}
|
}
|
||||||
|
|
||||||
item.appendChild(label);
|
|
||||||
list.appendChild(item);
|
list.appendChild(item);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -656,19 +642,19 @@ const controls = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Hide/show a tab
|
// Hide/show a tab
|
||||||
toggleTab(setting, toggle) {
|
toggleMenuButton(setting, toggle) {
|
||||||
toggleHidden(this.elements.settings.tabs[setting], !toggle);
|
toggleHidden(this.elements.settings.buttons[setting], !toggle);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set the quality menu
|
// Set the quality menu
|
||||||
setQualityMenu(options) {
|
setQualityMenu(options) {
|
||||||
// Menu required
|
// Menu required
|
||||||
if (!is.element(this.elements.settings.panes.quality)) {
|
if (!is.element(this.elements.settings.menus.quality)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const type = 'quality';
|
const type = 'quality';
|
||||||
const list = this.elements.settings.panes.quality.querySelector('ul');
|
const list = this.elements.settings.menus.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)) {
|
||||||
@ -677,7 +663,7 @@ const controls = {
|
|||||||
|
|
||||||
// Toggle the pane and tab
|
// Toggle the pane and tab
|
||||||
const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;
|
const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;
|
||||||
controls.toggleTab.call(this, type, toggle);
|
controls.toggleMenuButton.call(this, type, toggle);
|
||||||
|
|
||||||
// Check if we need to toggle the parent
|
// Check if we need to toggle the parent
|
||||||
controls.checkMenu.call(this);
|
controls.checkMenu.call(this);
|
||||||
@ -749,7 +735,7 @@ const controls = {
|
|||||||
|
|
||||||
// Update the selected setting
|
// Update the selected setting
|
||||||
updateSetting(setting, container, input) {
|
updateSetting(setting, container, input) {
|
||||||
const pane = this.elements.settings.panes[setting];
|
const pane = this.elements.settings.menus[setting];
|
||||||
let value = null;
|
let value = null;
|
||||||
let list = container;
|
let list = container;
|
||||||
|
|
||||||
@ -778,7 +764,7 @@ const controls = {
|
|||||||
|
|
||||||
// Get the list if we need to
|
// Get the list if we need to
|
||||||
if (!is.element(list)) {
|
if (!is.element(list)) {
|
||||||
list = pane && pane.querySelector('ul');
|
list = pane && pane.querySelector('[role="menu"]');
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's no list it means it's not been rendered...
|
// If there's no list it means it's not been rendered...
|
||||||
@ -787,34 +773,34 @@ const controls = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the label
|
// Update the label
|
||||||
const label = this.elements.settings.tabs[setting].querySelector(`.${this.config.classNames.menu.value}`);
|
const label = this.elements.settings.buttons[setting].querySelector(`.${this.config.classNames.menu.value}`);
|
||||||
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(`input[value="${value}"]`);
|
const target = list && list.querySelector(`button[value="${value}"]`);
|
||||||
|
|
||||||
if (is.element(target)) {
|
if (is.element(target)) {
|
||||||
target.checked = true;
|
target.setAttribute('aria-checked', true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set the looping options
|
// Set the looping options
|
||||||
/* setLoopMenu() {
|
/* setLoopMenu() {
|
||||||
// Menu required
|
// Menu required
|
||||||
if (!is.element(this.elements.settings.panes.loop)) {
|
if (!is.element(this.elements.settings.menus.loop)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = ['start', 'end', 'all', 'reset'];
|
const options = ['start', 'end', 'all', 'reset'];
|
||||||
const list = this.elements.settings.panes.loop.querySelector('ul');
|
const list = this.elements.settings.menus.loop.querySelector('[role="menu"]');
|
||||||
|
|
||||||
// Show the pane and tab
|
// Show the pane and tab
|
||||||
toggleHidden(this.elements.settings.tabs.loop, false);
|
toggleHidden(this.elements.settings.buttons.loop, false);
|
||||||
toggleHidden(this.elements.settings.panes.loop, false);
|
toggleHidden(this.elements.settings.menus.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.toggleTab.call(this, 'loop', toggle);
|
controls.toggleMenuButton.call(this, 'loop', toggle);
|
||||||
|
|
||||||
// Empty the menu
|
// Empty the menu
|
||||||
emptyElement(list);
|
emptyElement(list);
|
||||||
@ -849,11 +835,11 @@ 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.panes.captions.querySelector('ul');
|
const list = this.elements.settings.menus.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
|
||||||
controls.toggleTab.call(this, type, tracks.length);
|
controls.toggleMenuButton.call(this, type, tracks.length);
|
||||||
|
|
||||||
// Empty the menu
|
// Empty the menu
|
||||||
emptyElement(list);
|
emptyElement(list);
|
||||||
@ -899,7 +885,7 @@ const controls = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Menu required
|
// Menu required
|
||||||
if (!is.element(this.elements.settings.panes.speed)) {
|
if (!is.element(this.elements.settings.menus.speed)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -917,7 +903,7 @@ const controls = {
|
|||||||
|
|
||||||
// Toggle the pane and tab
|
// Toggle the pane and tab
|
||||||
const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;
|
const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;
|
||||||
controls.toggleTab.call(this, type, toggle);
|
controls.toggleMenuButton.call(this, type, toggle);
|
||||||
|
|
||||||
// Check if we need to toggle the parent
|
// Check if we need to toggle the parent
|
||||||
controls.checkMenu.call(this);
|
controls.checkMenu.call(this);
|
||||||
@ -928,7 +914,7 @@ const controls = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the list to populate
|
// Get the list to populate
|
||||||
const list = this.elements.settings.panes.speed.querySelector('ul');
|
const list = this.elements.settings.menus.speed.querySelector('[role="menu"]');
|
||||||
|
|
||||||
// Empty the menu
|
// Empty the menu
|
||||||
emptyElement(list);
|
emptyElement(list);
|
||||||
@ -948,26 +934,26 @@ const controls = {
|
|||||||
|
|
||||||
// Check if we need to hide/show the settings menu
|
// Check if we need to hide/show the settings menu
|
||||||
checkMenu() {
|
checkMenu() {
|
||||||
const { tabs } = this.elements.settings;
|
const { buttons } = this.elements.settings;
|
||||||
const visible = !is.empty(tabs) && Object.values(tabs).some(tab => !tab.hidden);
|
const visible = !is.empty(buttons) && Object.values(buttons).some(button => !button.hidden);
|
||||||
|
|
||||||
toggleHidden(this.elements.settings.menu, !visible);
|
toggleHidden(this.elements.settings.menu, !visible);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Show/hide menu
|
// Show/hide menu
|
||||||
toggleMenu(event) {
|
toggleMenu(event) {
|
||||||
const { form } = this.elements.settings;
|
const { popup } = this.elements.settings;
|
||||||
const button = this.elements.buttons.settings;
|
const button = this.elements.buttons.settings;
|
||||||
|
|
||||||
// Menu and button are required
|
// Menu and button are required
|
||||||
if (!is.element(form) || !is.element(button)) {
|
if (!is.element(popup) || !is.element(button)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const show = is.boolean(event) ? event : is.element(form) && form.hasAttribute('hidden');
|
const show = is.boolean(event) ? event : is.element(popup) && popup.hasAttribute('hidden');
|
||||||
|
|
||||||
if (is.event(event)) {
|
if (is.event(event)) {
|
||||||
const isMenuItem = is.element(form) && form.contains(event.target);
|
const isMenuItem = is.element(popup) && popup.contains(event.target);
|
||||||
const isButton = event.target === this.elements.buttons.settings;
|
const isButton = event.target === this.elements.buttons.settings;
|
||||||
|
|
||||||
// If the click was inside the form or if the click
|
// If the click was inside the form or if the click
|
||||||
@ -988,14 +974,14 @@ const controls = {
|
|||||||
button.setAttribute('aria-expanded', show);
|
button.setAttribute('aria-expanded', show);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is.element(form)) {
|
if (is.element(popup)) {
|
||||||
toggleHidden(form, !show);
|
toggleHidden(popup, !show);
|
||||||
toggleClass(this.elements.container, this.config.classNames.menu.open, show);
|
toggleClass(this.elements.container, this.config.classNames.menu.open, show);
|
||||||
|
|
||||||
if (show) {
|
if (show) {
|
||||||
form.removeAttribute('tabindex');
|
popup.removeAttribute('tabindex');
|
||||||
} else {
|
} else {
|
||||||
form.setAttribute('tabindex', -1);
|
popup.setAttribute('tabindex', -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1008,10 +994,10 @@ const controls = {
|
|||||||
clone.removeAttribute('hidden');
|
clone.removeAttribute('hidden');
|
||||||
|
|
||||||
// Prevent input's being unchecked due to the name being identical
|
// Prevent input's being unchecked due to the name being identical
|
||||||
Array.from(clone.querySelectorAll('input[name]')).forEach(input => {
|
/* Array.from(clone.querySelectorAll('input[name]')).forEach(input => {
|
||||||
const name = input.getAttribute('name');
|
const name = input.getAttribute('name');
|
||||||
input.setAttribute('name', `${name}-clone`);
|
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);
|
||||||
@ -1030,30 +1016,33 @@ const controls = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Toggle Menu
|
// Toggle Menu
|
||||||
showTab(target = '') {
|
showMenu(type = '') {
|
||||||
const { menu } = this.elements.settings;
|
const { menu } = this.elements.settings;
|
||||||
const pane = document.getElementById(target);
|
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(pane)) {
|
||||||
|
console.warn('No pane found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we targeting a tab? If not, bail
|
// Are we targeting a tab? If not, bail
|
||||||
const isTab = pane.getAttribute('role') === 'tabpanel';
|
/* const isTab = pane.getAttribute('role') === 'tabpanel';
|
||||||
if (!isTab) {
|
if (!isTab) {
|
||||||
return;
|
return;
|
||||||
}
|
} */
|
||||||
|
|
||||||
// Hide all other tabs
|
// Hide all other tabs
|
||||||
// Get other tabs
|
// Get other tabs
|
||||||
const current = menu.querySelector('[role="tabpanel"]:not([hidden])');
|
const current = menu.querySelector(`[id^=plyr-settings-${this.id}]:not([hidden])`);
|
||||||
const container = current.parentNode;
|
const container = current.parentNode;
|
||||||
|
|
||||||
// Set other toggles to be expanded false
|
// Set other toggles to be expanded false
|
||||||
Array.from(menu.querySelectorAll(`[aria-controls="${current.getAttribute('id')}"]`)).forEach(toggle => {
|
/* Array.from(menu.querySelectorAll(`[aria-controls="${current.getAttribute('id')}"]`)).forEach(toggle => {
|
||||||
toggle.setAttribute('aria-expanded', false);
|
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) {
|
||||||
@ -1089,16 +1078,16 @@ const controls = {
|
|||||||
|
|
||||||
// Set attributes on current tab
|
// Set attributes on current tab
|
||||||
toggleHidden(current, true);
|
toggleHidden(current, true);
|
||||||
current.setAttribute('tabindex', -1);
|
// current.setAttribute('tabindex', -1);
|
||||||
|
|
||||||
// Set attributes on target
|
// Set attributes on target
|
||||||
toggleHidden(pane, false);
|
toggleHidden(pane, false);
|
||||||
|
|
||||||
const tabs = getElements.call(this, `[aria-controls="${target}"]`);
|
/* const tabs = getElements.call(this, `[aria-controls="${target}"]`);
|
||||||
Array.from(tabs).forEach(tab => {
|
Array.from(tabs).forEach(tab => {
|
||||||
tab.setAttribute('aria-expanded', true);
|
tab.setAttribute('aria-expanded', true);
|
||||||
});
|
});
|
||||||
pane.removeAttribute('tabindex');
|
pane.removeAttribute('tabindex'); */
|
||||||
|
|
||||||
// Focus the first item
|
// Focus the first item
|
||||||
pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus();
|
pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus();
|
||||||
@ -1220,12 +1209,12 @@ const controls = {
|
|||||||
|
|
||||||
// Settings button / menu
|
// Settings button / menu
|
||||||
if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) {
|
if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) {
|
||||||
const menu = createElement('div', {
|
const control = createElement('div', {
|
||||||
class: 'plyr__menu',
|
class: 'plyr__menu',
|
||||||
hidden: '',
|
hidden: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
menu.appendChild(
|
control.appendChild(
|
||||||
controls.createButton.call(this, 'settings', {
|
controls.createButton.call(this, 'settings', {
|
||||||
id: `plyr-settings-toggle-${data.id}`,
|
id: `plyr-settings-toggle-${data.id}`,
|
||||||
'aria-haspopup': true,
|
'aria-haspopup': true,
|
||||||
@ -1234,48 +1223,38 @@ const controls = {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const form = createElement('form', {
|
const popup = createElement('div', {
|
||||||
class: 'plyr__menu__container',
|
class: 'plyr__menu__container',
|
||||||
id: `plyr-settings-${data.id}`,
|
id: `plyr-settings-${data.id}`,
|
||||||
hidden: '',
|
hidden: '',
|
||||||
'aria-labelled-by': `plyr-settings-toggle-${data.id}`,
|
'aria-labelled-by': `plyr-settings-toggle-${data.id}`,
|
||||||
role: 'tablist',
|
|
||||||
tabindex: -1,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const inner = createElement('div');
|
const inner = createElement('div');
|
||||||
|
|
||||||
const home = createElement('div', {
|
const home = createElement('div', {
|
||||||
id: `plyr-settings-${data.id}-home`,
|
id: `plyr-settings-${data.id}-home`,
|
||||||
'aria-labelled-by': `plyr-settings-toggle-${data.id}`,
|
|
||||||
role: 'tabpanel',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create the tab list
|
// Create the menu
|
||||||
const tabs = createElement('ul', {
|
const menu = createElement('div', {
|
||||||
role: 'tablist',
|
role: 'menu',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Build the tabs
|
// Build the menu items
|
||||||
this.config.settings.forEach(type => {
|
this.config.settings.forEach(type => {
|
||||||
const tab = createElement('li', {
|
const menuItem = createElement(
|
||||||
role: 'tab',
|
|
||||||
hidden: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const button = createElement(
|
|
||||||
'button',
|
'button',
|
||||||
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`,
|
||||||
id: `plyr-settings-${data.id}-${type}-tab`,
|
'role': 'menuitem',
|
||||||
'aria-haspopup': true,
|
'aria-haspopup': true,
|
||||||
'aria-controls': `plyr-settings-${data.id}-${type}`,
|
|
||||||
'aria-expanded': false,
|
|
||||||
}),
|
}),
|
||||||
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,
|
||||||
});
|
});
|
||||||
@ -1283,54 +1262,51 @@ const controls = {
|
|||||||
// Speed contains HTML entities
|
// Speed contains HTML entities
|
||||||
value.innerHTML = data[type];
|
value.innerHTML = data[type];
|
||||||
|
|
||||||
button.appendChild(value);
|
flex.appendChild(value);
|
||||||
tab.appendChild(button);
|
menuItem.appendChild(flex);
|
||||||
tabs.appendChild(tab);
|
menu.appendChild(menuItem);
|
||||||
|
|
||||||
this.elements.settings.tabs[type] = tab;
|
|
||||||
});
|
|
||||||
|
|
||||||
home.appendChild(tabs);
|
// Build the panes
|
||||||
inner.appendChild(home);
|
|
||||||
|
|
||||||
// Build the panes
|
|
||||||
this.config.settings.forEach(type => {
|
|
||||||
const pane = createElement('div', {
|
const pane = createElement('div', {
|
||||||
id: `plyr-settings-${data.id}-${type}`,
|
id: `plyr-settings-${data.id}-${type}`,
|
||||||
hidden: '',
|
hidden: '',
|
||||||
'aria-labelled-by': `plyr-settings-${data.id}-${type}-tab`,
|
|
||||||
role: 'tabpanel',
|
|
||||||
tabindex: -1,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const back = createElement(
|
// Back button
|
||||||
|
pane.appendChild(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`,
|
||||||
'aria-haspopup': true,
|
|
||||||
'aria-controls': `plyr-settings-${data.id}-home`,
|
|
||||||
'aria-expanded': false,
|
|
||||||
},
|
},
|
||||||
i18n.get(type, this.config),
|
i18n.get(type, this.config),
|
||||||
);
|
));
|
||||||
|
|
||||||
pane.appendChild(back);
|
// Menu
|
||||||
|
pane.appendChild(createElement('div', {
|
||||||
|
role: 'menu',
|
||||||
|
}));
|
||||||
|
|
||||||
const options = createElement('ul');
|
|
||||||
|
|
||||||
pane.appendChild(options);
|
|
||||||
inner.appendChild(pane);
|
inner.appendChild(pane);
|
||||||
|
|
||||||
this.elements.settings.panes[type] = pane;
|
menuItem.addEventListener('click', () => {
|
||||||
|
controls.showMenu.call(this, type);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.elements.settings.buttons[type] = menuItem;
|
||||||
|
this.elements.settings.menus[type] = pane;
|
||||||
});
|
});
|
||||||
|
|
||||||
form.appendChild(inner);
|
home.appendChild(menu);
|
||||||
menu.appendChild(form);
|
inner.appendChild(home);
|
||||||
container.appendChild(menu);
|
|
||||||
|
|
||||||
this.elements.settings.form = form;
|
popup.appendChild(inner);
|
||||||
this.elements.settings.menu = menu;
|
control.appendChild(popup);
|
||||||
|
container.appendChild(control);
|
||||||
|
|
||||||
|
this.elements.settings.popup = popup;
|
||||||
|
this.elements.settings.menu = control;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Picture in picture button
|
// Picture in picture button
|
||||||
|
@ -486,13 +486,12 @@ class Listeners {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Settings menu
|
// Settings menu
|
||||||
bind(this.player.elements.settings.form, 'click', event => {
|
bind(this.player.elements.settings.popup, 'click', event => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
// Go back to home tab on click
|
// Go back to home tab on click
|
||||||
const showHomeTab = () => {
|
const showHomeTab = () => {
|
||||||
const id = `plyr-settings-${this.player.id}-home`;
|
controls.showMenu.call(this.player, 'home');
|
||||||
controls.showTab.call(this.player, id);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Settings menu items - use event delegation as items are added/removed
|
// Settings menu items - use event delegation as items are added/removed
|
||||||
@ -523,9 +522,6 @@ class Listeners {
|
|||||||
},
|
},
|
||||||
'speed',
|
'speed',
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
const tab = event.target;
|
|
||||||
controls.showTab.call(this.player, tab.getAttribute('aria-controls'));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -75,16 +75,17 @@ class Plyr {
|
|||||||
// Elements cache
|
// Elements cache
|
||||||
this.elements = {
|
this.elements = {
|
||||||
container: null,
|
container: null,
|
||||||
|
captions: null,
|
||||||
buttons: {},
|
buttons: {},
|
||||||
display: {},
|
display: {},
|
||||||
progress: {},
|
progress: {},
|
||||||
inputs: {},
|
inputs: {},
|
||||||
settings: {
|
settings: {
|
||||||
|
popup: null,
|
||||||
menu: null,
|
menu: null,
|
||||||
panes: {},
|
menus: {},
|
||||||
tabs: {},
|
buttons: {},
|
||||||
},
|
},
|
||||||
captions: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Captions
|
// Captions
|
||||||
|
@ -70,12 +70,19 @@ export function createElement(type, attributes, text) {
|
|||||||
|
|
||||||
// Inaert an element after another
|
// Inaert an element after another
|
||||||
export function insertAfter(element, target) {
|
export function insertAfter(element, target) {
|
||||||
|
if (!is.element(element) || !is.element(target)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
target.parentNode.insertBefore(element, target.nextSibling);
|
target.parentNode.insertBefore(element, target.nextSibling);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert a DocumentFragment
|
// Insert a DocumentFragment
|
||||||
export function insertElement(type, parent, attributes, text) {
|
export function insertElement(type, parent, attributes, text) {
|
||||||
// Inject the new <element>
|
if (!is.element(parent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
parent.appendChild(createElement(type, attributes, text));
|
parent.appendChild(createElement(type, attributes, text));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,6 +102,10 @@ export function removeElement(element) {
|
|||||||
|
|
||||||
// Remove all child elements
|
// Remove all child elements
|
||||||
export function emptyElement(element) {
|
export function emptyElement(element) {
|
||||||
|
if (!is.element(element)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let { length } = element.childNodes;
|
let { length } = element.childNodes;
|
||||||
|
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
|
@ -54,18 +54,16 @@
|
|||||||
width: 0;
|
width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
[role='menu'] {
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
padding: $plyr-control-padding;
|
padding: $plyr-control-padding;
|
||||||
|
}
|
||||||
|
|
||||||
li {
|
[role='menuitem'],
|
||||||
margin-top: 2px;
|
[role='menuitemradio'] {
|
||||||
|
margin-top: 2px;
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,10 +73,16 @@
|
|||||||
color: $plyr-menu-color;
|
color: $plyr-menu-color;
|
||||||
display: flex;
|
display: flex;
|
||||||
font-size: $plyr-font-size-menu;
|
font-size: $plyr-font-size-menu;
|
||||||
padding: ceil($plyr-control-padding / 2) ($plyr-control-padding * 2);
|
padding: ceil($plyr-control-padding / 2) ceil($plyr-control-padding * 1.5);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
> span {
|
||||||
|
align-items: inherit;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
border: 4px solid transparent;
|
border: 4px solid transparent;
|
||||||
content: '';
|
content: '';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user