All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dominokit.domino.ui.dropdown.MenuNavigation Maven / Gradle / Ivy

There is a newer version: 1.0.139
Show newest version
package org.dominokit.domino.ui.dropdown;

import elemental2.dom.Event;
import elemental2.dom.EventListener;
import elemental2.dom.HTMLElement;
import elemental2.dom.KeyboardEvent;
import jsinterop.base.Js;
import org.jboss.gwt.elemento.core.IsElement;

import java.util.List;

import static java.util.Objects.isNull;
import static org.dominokit.domino.ui.utils.ElementUtil.*;

public class MenuNavigation implements EventListener {

    private final List items;
    private FocusHandler focusHandler;
    private SelectHandler selectHandler;
    private FocusCondition focusCondition;
    private EscapeHandler escapeHandler;

    public MenuNavigation(List items) {
        this.items = items;
    }

    public static  MenuNavigation create(List items) {
        return new MenuNavigation<>(items);
    }

    public MenuNavigation onFocus(FocusHandler focusHandler) {
        this.focusHandler = focusHandler;
        return this;
    }

    public MenuNavigation onSelect(SelectHandler selectHandler) {
        this.selectHandler = selectHandler;
        return this;
    }

    public MenuNavigation onEscape(EscapeHandler escapeHandler) {
        this.escapeHandler = escapeHandler;
        return this;
    }

    public MenuNavigation focusCondition(FocusCondition focusCondition) {
        this.focusCondition = focusCondition;
        return this;
    }

    @Override
    public void handleEvent(Event evt) {
        KeyboardEvent keyboardEvent = (KeyboardEvent) evt;
        HTMLElement element = Js.uncheckedCast(keyboardEvent.target);
        for (V item : items) {
            if (item.element().contains(element)) {
                if (isArrowUp(keyboardEvent)) {
                    focusPrevious(item);
                } else if (isArrowDown(keyboardEvent)) {
                    focusNext(item);
                } else if (isEscapeKey(keyboardEvent)) {
                    escapeHandler.onEscape();
                }

                if (isEnterKey(keyboardEvent) ||
                        isSpaceKey(keyboardEvent)
                        || isTabKey(keyboardEvent)) {
                    selectHandler.doSelect(item);
                }
                evt.preventDefault();
            }
        }
    }

    private void focusNext(V item) {
        int nextIndex = items.indexOf(item) + 1;
        int size = items.size();
        if (nextIndex >= size) {
            focusTopFocusableItem();
        } else {
            for (int i = nextIndex; i < size; i++) {
                V itemToFocus = items.get(i);
                if (shouldFocus((V) itemToFocus)) {
                    doFocus(itemToFocus);
                    return;
                }
            }
            focusTopFocusableItem();
        }
    }

    private boolean shouldFocus(V itemToFocus) {
        return isNull(focusCondition) || focusCondition.shouldFocus(itemToFocus);
    }

    private void focusTopFocusableItem() {
        for (V item : items) {
            if (shouldFocus(item)) {
                doFocus(item);
                break;
            }
        }
    }

    private void focusBottomFocusableItem() {
        for (int i = items.size() - 1; i >= 0; i--) {
            V itemToFocus = items.get(i);
            if (shouldFocus(itemToFocus)) {
                doFocus(itemToFocus);
                break;
            }
        }
    }

    private void focusPrevious(V item) {
        int nextIndex = items.indexOf(item) - 1;
        if (nextIndex < 0) {
            focusBottomFocusableItem();
        } else {
            for (int i = nextIndex; i >= 0; i--) {
                V itemToFocus = items.get(i);
                if (shouldFocus(itemToFocus)) {
                    doFocus(itemToFocus);
                    return;
                }
            }
            focusBottomFocusableItem();
        }
    }

    private void doFocus(V item) {
        focusHandler.doFocus(item);
    }

    public void focusAt(int index) {
        if (!items.isEmpty()) {
            V item = items.get(index);
            doFocus(item);
        }
    }

    @FunctionalInterface
    public interface FocusHandler {
        void doFocus(V item);
    }

    @FunctionalInterface
    public interface SelectHandler {
        void doSelect(V item);

    }

    @FunctionalInterface
    public interface EscapeHandler {
        void onEscape();
    }

    @FunctionalInterface
    public interface FocusCondition {
        boolean shouldFocus(V item);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy