Work on key bindings for menu
This commit is contained in:
parent
e59fe1aacf
commit
3bf1c59bd6
2
demo/dist/demo.css
vendored
2
demo/dist/demo.css
vendored
File diff suppressed because one or more lines are too long
11
demo/dist/demo.js
vendored
11
demo/dist/demo.js
vendored
@ -1874,7 +1874,7 @@ typeof navigator === "object" && (function () {
|
|||||||
// webpack (using a build step causes webpack #1617). Grunt verifies that
|
// webpack (using a build step causes webpack #1617). Grunt verifies that
|
||||||
// this value matches package.json during build.
|
// this value matches package.json during build.
|
||||||
// See: https://github.com/getsentry/raven-js/issues/465
|
// See: https://github.com/getsentry/raven-js/issues/465
|
||||||
VERSION: '3.26.2',
|
VERSION: '3.26.3',
|
||||||
|
|
||||||
debug: false,
|
debug: false,
|
||||||
|
|
||||||
@ -2351,7 +2351,9 @@ typeof navigator === "object" && (function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._globalOptions.stacktrace || (options && options.stacktrace)) {
|
// Always attempt to get stacktrace if message is empty.
|
||||||
|
// It's the only way to provide any helpful information to the user.
|
||||||
|
if (this._globalOptions.stacktrace || options.stacktrace || data.message === '') {
|
||||||
// fingerprint on msg, not stack trace (legacy behavior, could be revisited)
|
// fingerprint on msg, not stack trace (legacy behavior, could be revisited)
|
||||||
data.fingerprint = data.fingerprint == null ? msg : data.fingerprint;
|
data.fingerprint = data.fingerprint == null ? msg : data.fingerprint;
|
||||||
|
|
||||||
@ -3508,6 +3510,11 @@ typeof navigator === "object" && (function () {
|
|||||||
options
|
options
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var ex = data.exception.values[0];
|
||||||
|
if (ex.type == null && ex.value === '') {
|
||||||
|
ex.value = 'Unrecoverable error caught';
|
||||||
|
}
|
||||||
|
|
||||||
// Move mechanism from options to exception interface
|
// Move mechanism from options to exception interface
|
||||||
// We do this, as requiring user to pass `{exception:{mechanism:{ ... }}}` would be
|
// We do this, as requiring user to pass `{exception:{mechanism:{ ... }}}` would be
|
||||||
// too much
|
// too much
|
||||||
|
2
demo/dist/demo.js.map
vendored
2
demo/dist/demo.js.map
vendored
File diff suppressed because one or more lines are too long
2
demo/dist/demo.min.js
vendored
2
demo/dist/demo.min.js
vendored
File diff suppressed because one or more lines are too long
2
demo/dist/demo.min.js.map
vendored
2
demo/dist/demo.min.js.map
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
118
dist/plyr.js
vendored
118
dist/plyr.js
vendored
@ -638,6 +638,24 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false);
|
toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set focus and tab focus class
|
||||||
|
function setFocus() {
|
||||||
|
var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
||||||
|
var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||||||
|
|
||||||
|
if (!is.element(element)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set regular focus
|
||||||
|
element.focus();
|
||||||
|
|
||||||
|
// If we want to mimic keyboard focus via tab
|
||||||
|
if (tabFocus) {
|
||||||
|
toggleClass(element, this.config.classNames.tabFocus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
var transitionEndEvent = function () {
|
var transitionEndEvent = function () {
|
||||||
@ -2351,12 +2369,22 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
button.setAttribute('aria-expanded', show);
|
button.setAttribute('aria-expanded', show);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show the actual popup
|
||||||
if (is.element(popup)) {
|
if (is.element(popup)) {
|
||||||
toggleHidden(popup, !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) {
|
||||||
popup.removeAttribute('tabindex');
|
popup.removeAttribute('tabindex');
|
||||||
|
|
||||||
|
// Focus the first item if key interaction
|
||||||
|
if (event.type === 'keydown') {
|
||||||
|
var pane = Object.values(this.elements.settings.panels).find(function (pane) {
|
||||||
|
return !pane.hidden;
|
||||||
|
});
|
||||||
|
var firstItem = pane.querySelector('[role^="menuitem"]');
|
||||||
|
setFocus.call(this, firstItem, true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
popup.setAttribute('tabindex', -1);
|
popup.setAttribute('tabindex', -1);
|
||||||
}
|
}
|
||||||
@ -2447,9 +2475,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Focus the first item
|
// Focus the first item
|
||||||
var firstItem = target.querySelector('[role^="menuitem"]');
|
var firstItem = target.querySelector('[role^="menuitem"]');
|
||||||
if (firstItem) {
|
setFocus.call(this, firstItem, true);
|
||||||
firstItem.focus();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -2589,6 +2615,9 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
role: 'menu'
|
role: 'menu'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
home.appendChild(menu);
|
||||||
|
inner.appendChild(home);
|
||||||
|
|
||||||
// Build the menu items
|
// Build the menu items
|
||||||
this.config.settings.forEach(function (type) {
|
this.config.settings.forEach(function (type) {
|
||||||
var menuItem = createElement('button', extend(getAttributesFromSelector(_this8.config.selectors.buttons.settings), {
|
var menuItem = createElement('button', extend(getAttributesFromSelector(_this8.config.selectors.buttons.settings), {
|
||||||
@ -2599,6 +2628,26 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
hidden: ''
|
hidden: ''
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Handle space or -> to open menu
|
||||||
|
on(menuItem, 'keydown', function (event) {
|
||||||
|
// We only care about space and ->
|
||||||
|
if (![32, 39].includes(event.which)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent play / seek
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
// Show the respective menu
|
||||||
|
controls.showMenuPanel.call(_this8, type);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
// Show menu on click
|
||||||
|
on(menuItem, 'click', function () {
|
||||||
|
controls.showMenuPanel.call(_this8, type);
|
||||||
|
});
|
||||||
|
|
||||||
var flex = createElement('span', null, i18n.get(type, _this8.config));
|
var flex = createElement('span', null, i18n.get(type, _this8.config));
|
||||||
|
|
||||||
var value = createElement('span', {
|
var value = createElement('span', {
|
||||||
@ -2619,14 +2668,43 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Back button
|
// Back button
|
||||||
var back = createElement('button', {
|
var backButton = createElement('button', {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
class: _this8.config.classNames.control + ' ' + _this8.config.classNames.control + '--back'
|
class: _this8.config.classNames.control + ' ' + _this8.config.classNames.control + '--back'
|
||||||
}, i18n.get(type, _this8.config));
|
});
|
||||||
back.addEventListener('click', function () {
|
|
||||||
|
// Visible label
|
||||||
|
backButton.appendChild(createElement('span', {
|
||||||
|
'aria-hidden': true
|
||||||
|
}, i18n.get(type, _this8.config)));
|
||||||
|
|
||||||
|
// Screen reader label
|
||||||
|
backButton.appendChild(createElement('span', {
|
||||||
|
class: _this8.config.classNames.hidden
|
||||||
|
}, i18n.get('menuBack', _this8.config)));
|
||||||
|
|
||||||
|
// Handle space or -> to open menu
|
||||||
|
on(backButton, 'keydown', function (event) {
|
||||||
|
// We only care about <-
|
||||||
|
if (event.which !== 37) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent seek
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
// Show the respective menu
|
||||||
|
controls.showMenuPanel.call(_this8, 'home');
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
// Go back
|
||||||
|
on(backButton, 'click', function () {
|
||||||
controls.showMenuPanel.call(_this8, 'home');
|
controls.showMenuPanel.call(_this8, 'home');
|
||||||
});
|
});
|
||||||
pane.appendChild(back);
|
|
||||||
|
// Add to pane
|
||||||
|
pane.appendChild(backButton);
|
||||||
|
|
||||||
// Menu
|
// Menu
|
||||||
pane.appendChild(createElement('div', {
|
pane.appendChild(createElement('div', {
|
||||||
@ -2635,17 +2713,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
inner.appendChild(pane);
|
inner.appendChild(pane);
|
||||||
|
|
||||||
menuItem.addEventListener('click', function () {
|
|
||||||
controls.showMenuPanel.call(_this8, type);
|
|
||||||
});
|
|
||||||
|
|
||||||
_this8.elements.settings.buttons[type] = menuItem;
|
_this8.elements.settings.buttons[type] = menuItem;
|
||||||
_this8.elements.settings.panels[type] = pane;
|
_this8.elements.settings.panels[type] = pane;
|
||||||
});
|
});
|
||||||
|
|
||||||
home.appendChild(menu);
|
|
||||||
inner.appendChild(home);
|
|
||||||
|
|
||||||
popup.appendChild(inner);
|
popup.appendChild(inner);
|
||||||
control.appendChild(popup);
|
control.appendChild(popup);
|
||||||
container.appendChild(control);
|
container.appendChild(control);
|
||||||
@ -4678,11 +4749,28 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Airplay
|
// Airplay
|
||||||
this.bind(this.player.elements.buttons.airplay, 'click', this.player.airplay, 'airplay');
|
this.bind(this.player.elements.buttons.airplay, 'click', this.player.airplay, 'airplay');
|
||||||
|
|
||||||
// Settings menu
|
// Settings menu - click toggle
|
||||||
this.bind(this.player.elements.buttons.settings, 'click', function (event) {
|
this.bind(this.player.elements.buttons.settings, 'click', function (event) {
|
||||||
controls.toggleMenu.call(_this5.player, event);
|
controls.toggleMenu.call(_this5.player, event);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Settings menu - keyboard toggle
|
||||||
|
this.bind(this.player.elements.buttons.settings, 'keydown', function (event) {
|
||||||
|
// We only care about space
|
||||||
|
if (event.which !== 32) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent scroll
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// Prevent playing video
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
// Toggle menu
|
||||||
|
controls.toggleMenu.call(_this5.player, event);
|
||||||
|
}, null, false);
|
||||||
|
|
||||||
// Set range input alternative "value", which matches the tooltip time (#954)
|
// Set range input alternative "value", which matches the tooltip time (#954)
|
||||||
this.bind(this.player.elements.inputs.seek, 'mousedown mousemove', function (event) {
|
this.bind(this.player.elements.inputs.seek, 'mousedown mousemove', function (event) {
|
||||||
var clientRect = _this5.player.elements.progress.getBoundingClientRect();
|
var clientRect = _this5.player.elements.progress.getBoundingClientRect();
|
||||||
|
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
49
dist/plyr.polyfilled.js
vendored
49
dist/plyr.polyfilled.js
vendored
@ -7737,12 +7737,20 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
button.setAttribute('aria-expanded', show);
|
button.setAttribute('aria-expanded', show);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show the actual popup
|
||||||
if (is$1.element(popup)) {
|
if (is$1.element(popup)) {
|
||||||
toggleHidden(popup, !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) {
|
||||||
popup.removeAttribute('tabindex');
|
popup.removeAttribute('tabindex');
|
||||||
|
|
||||||
|
// Focus the first item
|
||||||
|
var firstItem = popup.querySelector('[role^="menuitem"]');
|
||||||
|
console.warn(firstItem);
|
||||||
|
if (firstItem) {
|
||||||
|
firstItem.focus();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
popup.setAttribute('tabindex', -1);
|
popup.setAttribute('tabindex', -1);
|
||||||
}
|
}
|
||||||
@ -8005,14 +8013,28 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Back button
|
// Back button
|
||||||
var back = createElement('button', {
|
var backButton = createElement('button', {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
class: _this8.config.classNames.control + ' ' + _this8.config.classNames.control + '--back'
|
class: _this8.config.classNames.control + ' ' + _this8.config.classNames.control + '--back'
|
||||||
}, i18n.get(type, _this8.config));
|
});
|
||||||
back.addEventListener('click', function () {
|
|
||||||
|
// Visible label
|
||||||
|
backButton.appendChild(createElement('span', {
|
||||||
|
'aria-hidden': true
|
||||||
|
}, i18n.get(type, _this8.config)));
|
||||||
|
|
||||||
|
// Screen reader label
|
||||||
|
backButton.appendChild(createElement('span', {
|
||||||
|
class: _this8.config.classNames.hidden
|
||||||
|
}, i18n.get('menuBack', _this8.config)));
|
||||||
|
|
||||||
|
// Bind listener
|
||||||
|
backButton.addEventListener('click', function () {
|
||||||
controls.showMenuPanel.call(_this8, 'home');
|
controls.showMenuPanel.call(_this8, 'home');
|
||||||
});
|
});
|
||||||
pane.appendChild(back);
|
|
||||||
|
// Add to pane
|
||||||
|
pane.appendChild(backButton);
|
||||||
|
|
||||||
// Menu
|
// Menu
|
||||||
pane.appendChild(createElement('div', {
|
pane.appendChild(createElement('div', {
|
||||||
@ -10064,11 +10086,28 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Airplay
|
// Airplay
|
||||||
this.bind(this.player.elements.buttons.airplay, 'click', this.player.airplay, 'airplay');
|
this.bind(this.player.elements.buttons.airplay, 'click', this.player.airplay, 'airplay');
|
||||||
|
|
||||||
// Settings menu
|
// Settings menu - click toggle
|
||||||
this.bind(this.player.elements.buttons.settings, 'click', function (event) {
|
this.bind(this.player.elements.buttons.settings, 'click', function (event) {
|
||||||
controls.toggleMenu.call(_this5.player, event);
|
controls.toggleMenu.call(_this5.player, event);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Settings menu - keyboard toggle
|
||||||
|
this.bind(this.player.elements.buttons.settings, 'keydown', function (event) {
|
||||||
|
// We only care about space
|
||||||
|
if (event.which !== 32) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent scroll
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// Prevent playing video
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
// Toggle menu
|
||||||
|
controls.toggleMenu.call(_this5.player, event);
|
||||||
|
}, null, false);
|
||||||
|
|
||||||
// Set range input alternative "value", which matches the tooltip time (#954)
|
// Set range input alternative "value", which matches the tooltip time (#954)
|
||||||
this.bind(this.player.elements.inputs.seek, 'mousedown mousemove', function (event) {
|
this.bind(this.player.elements.inputs.seek, 'mousedown mousemove', function (event) {
|
||||||
var clientRect = _this5.player.elements.progress.getBoundingClientRect();
|
var clientRect = _this5.player.elements.progress.getBoundingClientRect();
|
||||||
|
2
dist/plyr.polyfilled.js.map
vendored
2
dist/plyr.polyfilled.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.polyfilled.min.js
vendored
2
dist/plyr.polyfilled.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.polyfilled.min.js.map
vendored
2
dist/plyr.polyfilled.min.js.map
vendored
File diff suppressed because one or more lines are too long
12
package.json
12
package.json
@ -9,14 +9,14 @@
|
|||||||
"style": "./dist/plyr.css",
|
"style": "./dist/plyr.css",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-core": "^6.26.3",
|
"babel-core": "^6.26.3",
|
||||||
"babel-eslint": "^8.2.4",
|
"babel-eslint": "^8.2.5",
|
||||||
"babel-plugin-external-helpers": "^6.22.0",
|
"babel-plugin-external-helpers": "^6.22.0",
|
||||||
"babel-preset-env": "^1.7.0",
|
"babel-preset-env": "^1.7.0",
|
||||||
"del": "^3.0.0",
|
"del": "^3.0.0",
|
||||||
"eslint": "^5.0.0",
|
"eslint": "^5.0.0",
|
||||||
"eslint-config-airbnb-base": "^13.0.0",
|
"eslint-config-airbnb-base": "^13.0.0",
|
||||||
"eslint-config-prettier": "^2.9.0",
|
"eslint-config-prettier": "^2.9.0",
|
||||||
"eslint-plugin-import": "^2.12.0",
|
"eslint-plugin-import": "^2.13.0",
|
||||||
"git-branch": "^2.0.1",
|
"git-branch": "^2.0.1",
|
||||||
"gulp": "^3.9.1",
|
"gulp": "^3.9.1",
|
||||||
"gulp-autoprefixer": "^5.0.0",
|
"gulp-autoprefixer": "^5.0.0",
|
||||||
@ -40,16 +40,16 @@
|
|||||||
"postcss-custom-properties": "^7.0.0",
|
"postcss-custom-properties": "^7.0.0",
|
||||||
"prettier-eslint": "^8.8.2",
|
"prettier-eslint": "^8.8.2",
|
||||||
"prettier-stylelint": "^0.4.2",
|
"prettier-stylelint": "^0.4.2",
|
||||||
"rollup-plugin-babel": "^3.0.4",
|
"rollup-plugin-babel": "^3.0.5",
|
||||||
"rollup-plugin-commonjs": "^9.1.3",
|
"rollup-plugin-commonjs": "^9.1.3",
|
||||||
"rollup-plugin-node-resolve": "^3.3.0",
|
"rollup-plugin-node-resolve": "^3.3.0",
|
||||||
"run-sequence": "^2.2.1",
|
"run-sequence": "^2.2.1",
|
||||||
"stylelint": "^9.3.0",
|
"stylelint": "^9.3.0",
|
||||||
"stylelint-config-prettier": "^3.2.0",
|
"stylelint-config-prettier": "^3.3.0",
|
||||||
"stylelint-config-recommended": "^2.1.0",
|
"stylelint-config-recommended": "^2.1.0",
|
||||||
"stylelint-config-sass-guidelines": "^5.0.0",
|
"stylelint-config-sass-guidelines": "^5.0.0",
|
||||||
"stylelint-order": "^0.8.1",
|
"stylelint-order": "^0.8.1",
|
||||||
"stylelint-scss": "^3.1.2",
|
"stylelint-scss": "^3.1.3",
|
||||||
"stylelint-selector-bem-pattern": "^2.0.0"
|
"stylelint-selector-bem-pattern": "^2.0.0"
|
||||||
},
|
},
|
||||||
"keywords": ["HTML5 Video", "HTML5 Audio", "Media Player", "DASH", "Shaka", "WordPress", "HLS"],
|
"keywords": ["HTML5 Video", "HTML5 Audio", "Media Player", "DASH", "Shaka", "WordPress", "HLS"],
|
||||||
@ -74,7 +74,7 @@
|
|||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"custom-event-polyfill": "^0.3.0",
|
"custom-event-polyfill": "^0.3.0",
|
||||||
"loadjs": "^3.5.4",
|
"loadjs": "^3.5.4",
|
||||||
"raven-js": "^3.26.2",
|
"raven-js": "^3.26.3",
|
||||||
"url-polyfill": "^1.0.13"
|
"url-polyfill": "^1.0.13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
101
src/js/controls.js
vendored
101
src/js/controls.js
vendored
@ -9,7 +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 { createElement, emptyElement, getAttributesFromSelector, getElement, getElements, hasClass, matches, removeElement, setAttributes, toggleClass, toggleHidden } from './utils/elements';
|
import { createElement, emptyElement, getAttributesFromSelector, getElement, getElements, hasClass, matches, removeElement, setAttributes, setFocus, toggleClass, toggleHidden } 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';
|
||||||
@ -175,7 +175,7 @@ const controls = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ('class' in attributes) {
|
if ('class' in attributes) {
|
||||||
if (attributes.class.includes(this.config.classNames.control)) {
|
if (!attributes.class.includes(this.config.classNames.control)) {
|
||||||
attributes.class += ` ${this.config.classNames.control}`;
|
attributes.class += ` ${this.config.classNames.control}`;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1016,12 +1016,20 @@ const controls = {
|
|||||||
button.setAttribute('aria-expanded', show);
|
button.setAttribute('aria-expanded', show);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show the actual popup
|
||||||
if (is.element(popup)) {
|
if (is.element(popup)) {
|
||||||
toggleHidden(popup, !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) {
|
||||||
popup.removeAttribute('tabindex');
|
popup.removeAttribute('tabindex');
|
||||||
|
|
||||||
|
// Focus the first item if key interaction
|
||||||
|
if (event.type === 'keydown') {
|
||||||
|
const pane = Object.values(this.elements.settings.panels).find(pane => !pane.hidden);
|
||||||
|
const firstItem = pane.querySelector('[role^="menuitem"]');
|
||||||
|
setFocus.call(this, firstItem, true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
popup.setAttribute('tabindex', -1);
|
popup.setAttribute('tabindex', -1);
|
||||||
}
|
}
|
||||||
@ -1104,9 +1112,7 @@ const controls = {
|
|||||||
|
|
||||||
// Focus the first item
|
// Focus the first item
|
||||||
const firstItem = target.querySelector('[role^="menuitem"]');
|
const firstItem = target.querySelector('[role^="menuitem"]');
|
||||||
if (firstItem) {
|
setFocus.call(this, firstItem, true);
|
||||||
firstItem.focus();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Build the default HTML
|
// Build the default HTML
|
||||||
@ -1257,6 +1263,9 @@ const controls = {
|
|||||||
role: 'menu',
|
role: 'menu',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
home.appendChild(menu);
|
||||||
|
inner.appendChild(home);
|
||||||
|
|
||||||
// Build the menu items
|
// Build the menu items
|
||||||
this.config.settings.forEach(type => {
|
this.config.settings.forEach(type => {
|
||||||
const menuItem = createElement(
|
const menuItem = createElement(
|
||||||
@ -1270,6 +1279,26 @@ const controls = {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Handle space or -> to open menu
|
||||||
|
on(menuItem, 'keydown', event => {
|
||||||
|
// We only care about space and ->
|
||||||
|
if (![32,39].includes(event.which)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent play / seek
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
// Show the respective menu
|
||||||
|
controls.showMenuPanel.call(this, type);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
// Show menu on click
|
||||||
|
on(menuItem, 'click', () => {
|
||||||
|
controls.showMenuPanel.call(this, type);
|
||||||
|
});
|
||||||
|
|
||||||
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', {
|
||||||
@ -1290,18 +1319,55 @@ const controls = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Back button
|
// Back button
|
||||||
const back = createElement(
|
const backButton = createElement('button', {
|
||||||
'button',
|
type: 'button',
|
||||||
{
|
class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,
|
||||||
type: 'button',
|
});
|
||||||
class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,
|
|
||||||
},
|
// Visible label
|
||||||
i18n.get(type, this.config),
|
backButton.appendChild(
|
||||||
|
createElement(
|
||||||
|
'span',
|
||||||
|
{
|
||||||
|
'aria-hidden': true,
|
||||||
|
},
|
||||||
|
i18n.get(type, this.config),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
back.addEventListener('click', () => {
|
|
||||||
|
// Screen reader label
|
||||||
|
backButton.appendChild(
|
||||||
|
createElement(
|
||||||
|
'span',
|
||||||
|
{
|
||||||
|
class: this.config.classNames.hidden,
|
||||||
|
},
|
||||||
|
i18n.get('menuBack', this.config),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Handle space or -> to open menu
|
||||||
|
on(backButton, 'keydown', event => {
|
||||||
|
// We only care about <-
|
||||||
|
if (event.which !== 37) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent seek
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
// Show the respective menu
|
||||||
|
controls.showMenuPanel.call(this, 'home');
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
// Go back
|
||||||
|
on(backButton, 'click', () => {
|
||||||
controls.showMenuPanel.call(this, 'home');
|
controls.showMenuPanel.call(this, 'home');
|
||||||
});
|
});
|
||||||
pane.appendChild(back);
|
|
||||||
|
// Add to pane
|
||||||
|
pane.appendChild(backButton);
|
||||||
|
|
||||||
// Menu
|
// Menu
|
||||||
pane.appendChild(
|
pane.appendChild(
|
||||||
@ -1312,17 +1378,10 @@ const controls = {
|
|||||||
|
|
||||||
inner.appendChild(pane);
|
inner.appendChild(pane);
|
||||||
|
|
||||||
menuItem.addEventListener('click', () => {
|
|
||||||
controls.showMenuPanel.call(this, type);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.elements.settings.buttons[type] = menuItem;
|
this.elements.settings.buttons[type] = menuItem;
|
||||||
this.elements.settings.panels[type] = pane;
|
this.elements.settings.panels[type] = pane;
|
||||||
});
|
});
|
||||||
|
|
||||||
home.appendChild(menu);
|
|
||||||
inner.appendChild(home);
|
|
||||||
|
|
||||||
popup.appendChild(inner);
|
popup.appendChild(inner);
|
||||||
control.appendChild(popup);
|
control.appendChild(popup);
|
||||||
container.appendChild(control);
|
container.appendChild(control);
|
||||||
|
@ -483,11 +483,34 @@ class Listeners {
|
|||||||
// Airplay
|
// Airplay
|
||||||
this.bind(this.player.elements.buttons.airplay, 'click', this.player.airplay, 'airplay');
|
this.bind(this.player.elements.buttons.airplay, 'click', this.player.airplay, 'airplay');
|
||||||
|
|
||||||
// Settings menu
|
// Settings menu - click toggle
|
||||||
this.bind(this.player.elements.buttons.settings, 'click', event => {
|
this.bind(this.player.elements.buttons.settings, 'click', event => {
|
||||||
controls.toggleMenu.call(this.player, event);
|
controls.toggleMenu.call(this.player, event);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Settings menu - keyboard toggle
|
||||||
|
this.bind(
|
||||||
|
this.player.elements.buttons.settings,
|
||||||
|
'keydown',
|
||||||
|
event => {
|
||||||
|
// We only care about space
|
||||||
|
if (event.which !== 32) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent scroll
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// Prevent playing video
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
// Toggle menu
|
||||||
|
controls.toggleMenu.call(this.player, event);
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
// Set range input alternative "value", which matches the tooltip time (#954)
|
// Set range input alternative "value", which matches the tooltip time (#954)
|
||||||
this.bind(this.player.elements.inputs.seek, 'mousedown mousemove', event => {
|
this.bind(this.player.elements.inputs.seek, 'mousedown mousemove', event => {
|
||||||
const clientRect = this.player.elements.progress.getBoundingClientRect();
|
const clientRect = this.player.elements.progress.getBoundingClientRect();
|
||||||
@ -626,8 +649,7 @@ class Listeners {
|
|||||||
const inverted = event.webkitDirectionInvertedFromDevice;
|
const inverted = event.webkitDirectionInvertedFromDevice;
|
||||||
|
|
||||||
// Get delta from event. Invert if `inverted` is true
|
// Get delta from event. Invert if `inverted` is true
|
||||||
const [x, y] = [event.deltaX, -event.deltaY]
|
const [x, y] = [event.deltaX, -event.deltaY].map(value => (inverted ? -value : value));
|
||||||
.map(value => inverted ? -value : value);
|
|
||||||
|
|
||||||
// Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)
|
// Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)
|
||||||
const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);
|
const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);
|
||||||
|
@ -294,3 +294,18 @@ export function trapFocus(element = null, toggle = false) {
|
|||||||
|
|
||||||
toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false);
|
toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set focus and tab focus class
|
||||||
|
export function setFocus(element = null, tabFocus = false) {
|
||||||
|
if (!is.element(element)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set regular focus
|
||||||
|
element.focus();
|
||||||
|
|
||||||
|
// If we want to mimic keyboard focus via tab
|
||||||
|
if (tabFocus) {
|
||||||
|
toggleClass(element, this.config.classNames.tabFocus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// Nicer focus styles
|
// Nicer focus styles
|
||||||
// ---------------------------------------
|
// ---------------------------------------
|
||||||
@mixin plyr-tab-focus($color: $plyr-tab-focus-default-color) {
|
@mixin plyr-tab-focus($color: $plyr-tab-focus-default-color) {
|
||||||
box-shadow: 0 0 0 3px rgba($color, 0.35);
|
box-shadow: 0 0 0 5px rgba($color, 0.5);
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
yarn.lock
32
yarn.lock
@ -464,7 +464,7 @@ babel-core@^6.26.3:
|
|||||||
slash "^1.0.0"
|
slash "^1.0.0"
|
||||||
source-map "^0.5.7"
|
source-map "^0.5.7"
|
||||||
|
|
||||||
babel-eslint@^8.2.4:
|
babel-eslint@^8.2.5:
|
||||||
version "8.2.5"
|
version "8.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.5.tgz#dc2331c259d36782aa189da510c43dedd5adc7a3"
|
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.5.tgz#dc2331c259d36782aa189da510c43dedd5adc7a3"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1901,9 +1901,9 @@ eslint-module-utils@^2.2.0:
|
|||||||
debug "^2.6.8"
|
debug "^2.6.8"
|
||||||
pkg-dir "^1.0.0"
|
pkg-dir "^1.0.0"
|
||||||
|
|
||||||
eslint-plugin-import@^2.12.0:
|
eslint-plugin-import@^2.13.0:
|
||||||
version "2.12.0"
|
version "2.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.12.0.tgz#dad31781292d6664b25317fd049d2e2b2f02205d"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.13.0.tgz#df24f241175e312d91662dc91ca84064caec14ed"
|
||||||
dependencies:
|
dependencies:
|
||||||
contains-path "^0.1.0"
|
contains-path "^0.1.0"
|
||||||
debug "^2.6.8"
|
debug "^2.6.8"
|
||||||
@ -5178,9 +5178,9 @@ randomatic@^1.1.3:
|
|||||||
is-number "^3.0.0"
|
is-number "^3.0.0"
|
||||||
kind-of "^4.0.0"
|
kind-of "^4.0.0"
|
||||||
|
|
||||||
raven-js@^3.26.2:
|
raven-js@^3.26.3:
|
||||||
version "3.26.2"
|
version "3.26.3"
|
||||||
resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.26.2.tgz#9153af2416e96ccf4e0b9cbc6c90c34dda0d7e88"
|
resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.26.3.tgz#0efb49969b5b11ab965f7b0d6da4ca102b763cb0"
|
||||||
|
|
||||||
rc@^1.0.1, rc@^1.1.6:
|
rc@^1.0.1, rc@^1.1.6:
|
||||||
version "1.2.6"
|
version "1.2.6"
|
||||||
@ -5629,9 +5629,9 @@ rimraf@2, rimraf@^2.2.8:
|
|||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.0.5"
|
glob "^7.0.5"
|
||||||
|
|
||||||
rollup-plugin-babel@^3.0.4:
|
rollup-plugin-babel@^3.0.5:
|
||||||
version "3.0.4"
|
version "3.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-3.0.4.tgz#41b3e762fe64450dd61da3105a2cf7ad76be4edc"
|
resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-3.0.5.tgz#9769a7977098da1dce5b5888fe38dfd8666bf08d"
|
||||||
dependencies:
|
dependencies:
|
||||||
rollup-pluginutils "^1.5.0"
|
rollup-pluginutils "^1.5.0"
|
||||||
|
|
||||||
@ -6103,9 +6103,9 @@ style-search@^0.1.0:
|
|||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902"
|
resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902"
|
||||||
|
|
||||||
stylelint-config-prettier@^3.2.0:
|
stylelint-config-prettier@^3.3.0:
|
||||||
version "3.2.0"
|
version "3.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-3.2.0.tgz#af32b7845adeeddbf0a0bd642ace4ca1e68958e2"
|
resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-3.3.0.tgz#cc22a4b5310c1919cee77131d6e220c60a62a480"
|
||||||
dependencies:
|
dependencies:
|
||||||
stylelint "^9.1.1"
|
stylelint "^9.1.1"
|
||||||
|
|
||||||
@ -6138,9 +6138,9 @@ stylelint-scss@^2.0.0:
|
|||||||
postcss-selector-parser "^3.1.1"
|
postcss-selector-parser "^3.1.1"
|
||||||
postcss-value-parser "^3.3.0"
|
postcss-value-parser "^3.3.0"
|
||||||
|
|
||||||
stylelint-scss@^3.1.2:
|
stylelint-scss@^3.1.3:
|
||||||
version "3.1.2"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-3.1.2.tgz#3257c0600d197fe7642f3698944b47c91567f379"
|
resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-3.1.3.tgz#28f881ae298c3f5db667b10b6cf94a1a219001d6"
|
||||||
dependencies:
|
dependencies:
|
||||||
lodash "^4.17.10"
|
lodash "^4.17.10"
|
||||||
postcss-media-query-parser "^0.2.3"
|
postcss-media-query-parser "^0.2.3"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user