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