Keyboard and focus improvements
This commit is contained in:
@@ -116,7 +116,11 @@ export function emptyElement(element) {
|
||||
|
||||
// Replace element
|
||||
export function replaceElement(newChild, oldChild) {
|
||||
if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) {
|
||||
if (
|
||||
!is.element(oldChild) ||
|
||||
!is.element(oldChild.parentNode) ||
|
||||
!is.element(newChild)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -203,6 +207,10 @@ export function toggleHidden(element, hidden) {
|
||||
|
||||
// Mirror Element.classList.toggle, with IE compatibility for "force" argument
|
||||
export function toggleClass(element, className, force) {
|
||||
if (is.nodeList(element)) {
|
||||
return Array.from(element).map(e => toggleClass(e, className, force));
|
||||
}
|
||||
|
||||
if (is.element(element)) {
|
||||
let method = 'toggle';
|
||||
if (typeof force !== 'undefined') {
|
||||
@@ -213,7 +221,7 @@ export function toggleClass(element, className, force) {
|
||||
return element.classList.contains(className);
|
||||
}
|
||||
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Has class name
|
||||
@@ -249,26 +257,16 @@ export function getElement(selector) {
|
||||
return this.elements.container.querySelector(selector);
|
||||
}
|
||||
|
||||
// Get the focused element
|
||||
export function getFocusElement() {
|
||||
let focused = document.activeElement;
|
||||
|
||||
if (!focused || focused === document.body) {
|
||||
focused = null;
|
||||
} else {
|
||||
focused = document.querySelector(':focus');
|
||||
}
|
||||
|
||||
return focused;
|
||||
}
|
||||
|
||||
// Trap focus inside container
|
||||
export function trapFocus(element = null, toggle = false) {
|
||||
if (!is.element(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');
|
||||
const focusable = getElements.call(
|
||||
this,
|
||||
'button:not(:disabled), input:not(:disabled), [tabindex]',
|
||||
);
|
||||
const first = focusable[0];
|
||||
const last = focusable[focusable.length - 1];
|
||||
|
||||
@@ -279,7 +277,7 @@ export function trapFocus(element = null, toggle = false) {
|
||||
}
|
||||
|
||||
// Get the current focused element
|
||||
const focused = getFocusElement();
|
||||
const focused = document.activeElement;
|
||||
|
||||
if (focused === last && !event.shiftKey) {
|
||||
// Move focus to first element that can be tabbed if Shift isn't used
|
||||
@@ -292,7 +290,14 @@ 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
|
||||
|
||||
@@ -27,9 +27,21 @@ const supportsPassiveListeners = (() => {
|
||||
})();
|
||||
|
||||
// Toggle event listener
|
||||
export function toggleListener(element, event, callback, toggle = false, passive = true, capture = false) {
|
||||
export function toggleListener(
|
||||
element,
|
||||
event,
|
||||
callback,
|
||||
toggle = false,
|
||||
passive = true,
|
||||
capture = false,
|
||||
) {
|
||||
// Bail if no element, event, or callback
|
||||
if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) {
|
||||
if (
|
||||
!element ||
|
||||
!('addEventListener' in element) ||
|
||||
is.empty(event) ||
|
||||
!is.function(callback)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -57,28 +69,74 @@ export function toggleListener(element, event, callback, toggle = false, passive
|
||||
this.eventListeners.push({ element, type, callback, options });
|
||||
}
|
||||
|
||||
element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);
|
||||
element[toggle ? 'addEventListener' : 'removeEventListener'](
|
||||
type,
|
||||
callback,
|
||||
options,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Bind event handler
|
||||
export function on(element, events = '', callback, passive = true, capture = false) {
|
||||
toggleListener.call(this, element, events, callback, true, passive, capture);
|
||||
export function on(
|
||||
element,
|
||||
events = '',
|
||||
callback,
|
||||
passive = true,
|
||||
capture = false,
|
||||
) {
|
||||
toggleListener.call(
|
||||
this,
|
||||
element,
|
||||
events,
|
||||
callback,
|
||||
true,
|
||||
passive,
|
||||
capture,
|
||||
);
|
||||
}
|
||||
|
||||
// Unbind event handler
|
||||
export function off(element, events = '', callback, passive = true, capture = false) {
|
||||
toggleListener.call(this, element, events, callback, false, passive, capture);
|
||||
export function off(
|
||||
element,
|
||||
events = '',
|
||||
callback,
|
||||
passive = true,
|
||||
capture = false,
|
||||
) {
|
||||
toggleListener.call(
|
||||
this,
|
||||
element,
|
||||
events,
|
||||
callback,
|
||||
false,
|
||||
passive,
|
||||
capture,
|
||||
);
|
||||
}
|
||||
|
||||
// Bind once-only event handler
|
||||
export function once(element, events = '', callback, passive = true, capture = false) {
|
||||
export function once(
|
||||
element,
|
||||
events = '',
|
||||
callback,
|
||||
passive = true,
|
||||
capture = false,
|
||||
) {
|
||||
function onceCallback(...args) {
|
||||
off(element, events, onceCallback, passive, capture);
|
||||
callback.apply(this, args);
|
||||
}
|
||||
|
||||
toggleListener.call(this, element, events, onceCallback, true, passive, capture);
|
||||
toggleListener.call(
|
||||
this,
|
||||
element,
|
||||
events,
|
||||
onceCallback,
|
||||
true,
|
||||
passive,
|
||||
capture,
|
||||
);
|
||||
}
|
||||
|
||||
// Trigger event
|
||||
@@ -115,6 +173,9 @@ export function unbindListeners() {
|
||||
// Run method when / if player is ready
|
||||
export function ready() {
|
||||
return new Promise(
|
||||
resolve => (this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve)),
|
||||
resolve =>
|
||||
this.ready
|
||||
? setTimeout(resolve, 0)
|
||||
: on.call(this, this.elements.container, 'ready', resolve),
|
||||
).then(() => {});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user