Skip to content

Commit

Permalink
fix #972 Text of selected option in a Select can be manipulated/overl…
Browse files Browse the repository at this point in the history
…ayed by just typing when navigating with the tab key
  • Loading branch information
vegegoku committed Nov 11, 2024
1 parent a54572b commit a18875e
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public AbstractSelect() {
.appendChild(
typingElement =
input("text")
.addEventListener("input", evt -> onTypingStart())
.addCss(dui_auto_type_input, dui_hidden)
.setTabIndex(-1)
.onKeyPress(keyEvents -> keyEvents.alphanumeric(Event::stopPropagation)));
Expand All @@ -115,6 +116,7 @@ public AbstractSelect() {
optionsMenu.focusFirstMatch(typingElement.getValue());
typingElement.setValue(null).addCss(dui_hidden);
focus();
onTypingEnd();
})
.setOnEnterAction(
() -> {
Expand Down Expand Up @@ -212,6 +214,10 @@ public AbstractSelect() {
})));
}

protected abstract void onTypingStart();

protected abstract void onTypingEnd();

private int getTypeAheadDelay() {
return typeAheadDelay > 0
? typeAheadDelay
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.Set;
import java.util.stream.Collectors;
import org.dominokit.domino.ui.elements.DivElement;
import org.dominokit.domino.ui.utils.BaseDominoElement;

/**
* Represents a multi-selection dropdown menu UI component, allowing users to select multiple
Expand Down Expand Up @@ -157,6 +158,7 @@ protected void onOptionSelected(SelectOption<V> option, boolean silent) {
}
withOption(option, silent);
updateTextValue();
option.addCss(() -> "dui-selected-option");
fieldInput.appendChild(option);
selectedOptions.add(option);
getInputElement().element().focus();
Expand Down Expand Up @@ -225,4 +227,14 @@ protected void doSetOption(SelectOption<V> option) {
public List<V> getValue() {
return this.selectedOptions.stream().map(Option::getValue).collect(Collectors.toList());
}

@Override
protected void onTypingStart() {
this.selectedOptions.forEach(BaseDominoElement::hide);
}

@Override
protected void onTypingEnd() {
this.selectedOptions.forEach(BaseDominoElement::show);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;

import elemental2.dom.DomGlobal;
import java.util.Objects;
import java.util.Optional;
import org.dominokit.domino.ui.elements.DivElement;
import org.dominokit.domino.ui.utils.BaseDominoElement;

/**
* Represents a dropdown select control allowing the user to choose a single option from a list.
Expand Down Expand Up @@ -84,6 +86,22 @@ protected void doSetValue(V value, boolean silent) {
}
}

@Override
protected void onTypingStart() {
DomGlobal.console.info("Typing typing typing -----");
Optional.ofNullable(selectedOption)
.ifPresent(
vSelectOption -> {
DomGlobal.console.info("Hide Hide Hide -----");
vSelectOption.hide();
});
}

@Override
protected void onTypingEnd() {
Optional.ofNullable(selectedOption).ifPresent(BaseDominoElement::show);
}

@Override
protected Select<V> clearValue(boolean silent) {
Select<V> thisSelect = super.clearValue(silent);
Expand Down Expand Up @@ -125,6 +143,7 @@ public Select<V> withOption(SelectOption<V> option, boolean silent) {

updateTextValue();
this.selectedOption = option;
option.addCss(() -> "dui-selected-option");
fieldInput.appendChild(option);

if (!silent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,21 @@ public interface HasKeyboardEvents<T> {
*/
T stopOnKeyPress();

/**
* Registers an event listener to be called when an input is applied.
*
* @param onInput The {@link KeyEventsConsumer} to call when an input is applied.
* @return The instance of type {@code T} for method chaining.
*/
T onInput(KeyEventsConsumer onInput);

/**
* Stops listening for input events.
*
* @return The instance of type {@code T} for method chaining.
*/
T stopOnInput();

/**
* Gets the keyboard event options associated with this instance.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
*/
package org.dominokit.domino.ui.keyboard;

import static org.dominokit.domino.ui.utils.Domino.*;

import elemental2.dom.Node;
import org.dominokit.domino.ui.events.HasDefaultEventOptions;
import org.dominokit.domino.ui.utils.LazyInitializer;
Expand Down Expand Up @@ -44,16 +42,20 @@ public class KeyboardEvents<T extends Node>
/** The constant representing the "keypress" event type. */
public static final String KEYPRESS = "keypress";

public static final String INPUT = "input";

private KeyboardEventOptions defaultOptions = KeyboardEventOptions.create();
private final T element;

private KeyboardKeyListener keyUpListener = new KeyboardKeyListener(this);
private KeyboardKeyListener keyDownListener = new KeyboardKeyListener(this);
private KeyboardKeyListener keyPressListener = new KeyboardKeyListener(this);
private KeyboardKeyListener inputListener = new KeyboardKeyListener(this);

private LazyInitializer keyUpListenerInitializer;
private LazyInitializer keyDownListenerInitializer;
private LazyInitializer keyPressListenerInitializer;
private LazyInitializer InputListenerInitializer;

/**
* Creates a new instance of {@code KeyboardEvents} for the specified DOM element.
Expand All @@ -68,6 +70,8 @@ public KeyboardEvents(T element) {
new LazyInitializer(() -> element.addEventListener(KEYDOWN, keyDownListener));
keyPressListenerInitializer =
new LazyInitializer(() -> element.addEventListener(KEYPRESS, keyPressListener));
InputListenerInitializer =
new LazyInitializer(() -> element.addEventListener(INPUT, inputListener));
}

/**
Expand Down Expand Up @@ -142,6 +146,30 @@ public KeyboardEvents<T> stopListenOnKeyPress() {
return this;
}

/**
* Adds a keypress event listener to the element and associates it with the provided {@code
* onInput} consumer.
*
* @param onInput The consumer that will receive keypress events.
* @return This {@code KeyboardEvents} instance for method chaining.
*/
public KeyboardEvents<T> listenOnInput(KeyEventsConsumer onInput) {
InputListenerInitializer.apply();
onInput.accept(inputListener);
return this;
}

/**
* Removes the keypress event listener from the element.
*
* @return This {@code KeyboardEvents} instance for method chaining.
*/
public KeyboardEvents<T> stopListenOnInput() {
element.removeEventListener(INPUT, inputListener);
InputListenerInitializer.reset();
return this;
}

/** {@inheritDoc} */
@Override
public KeyboardEventOptions getOptions() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4144,6 +4144,31 @@ public T stopOnKeyPress() {
return (T) this;
}

/**
* Registers an event handler to be executed when a key is pressed and released.
*
* @param onInput The event handler for key press events.
* @return The modified DOM element.
*/
@Override
public T onInput(KeyEventsConsumer onInput) {
keyEventsInitializer.apply();
keyboardEvents.listenOnInput(onInput);
return (T) this;
}

/**
* Stops listening to key press events.
*
* @return The modified DOM element.
*/
@Override
public T stopOnInput() {
keyEventsInitializer.apply();
keyboardEvents.stopListenOnInput();
return (T) this;
}

/**
* Retrieves the options for keyboard events.
*
Expand Down

0 comments on commit a18875e

Please sign in to comment.