Skip to content

Commit

Permalink
Fix plotly#2612: unexpected behaviour of the cursor
Browse files Browse the repository at this point in the history
When inserting a non valid character in the middle of a pattern,
the cursor instantly jumps to the end of the word,
instead of staying in that position.
Added also some case tests.
  • Loading branch information
rodasarede committed Jul 22, 2024
1 parent c847882 commit 85a45bd
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 9 deletions.
25 changes: 16 additions & 9 deletions components/dash-core-components/src/components/Input.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,16 +184,23 @@ export default class Input extends PureComponent {

onChange() {
const {debounce} = this.props;
if (debounce) {
if (Number.isFinite(debounce)) {
this.debounceEvent(debounce);
}
if (this.props.type !== 'number') {
this.setState({value: this.input.current.value});
const input = this.input.current;
const cursorPosition = input.selectionStart;
const currentValue = input.value;
this.setState({value: currentValue}, () => {
if (debounce) {
if (Number.isFinite(debounce)) {
this.debounceEvent(debounce);
}
if (this.props.type !== 'number') {
setTimeout(() => {
input.setSelectionRange(cursorPosition, cursorPosition);
}, 0);
}
} else {
this.onEvent();
}
} else {
this.onEvent();
}
});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,72 @@ def test_inbs003_styles_are_scoped(dash_dcc):
dash_outline_css = dash_input.value_of_css_property("outline")

assert external_outline_css != dash_outline_css

@pytest.mark.parametrize(
"initial_text, invalid_char, cursor_position_before, expected_text, expected_cursor_position",
[
("abcdddef", "/", 2, "ab/cdddef", 3),
("abcdef", "$", 2, "ab$cdef", 3),
("abcdef", "$", 3, "abc$def", 4),
("abcdef", "A", 4, "abcdAef", 5), # valid character
],
)
def test_inbs004_cursor_position_on_invalid_input(
dash_dcc,
initial_text,
invalid_char,
cursor_position_before,
expected_text,
expected_cursor_position,
):
app = Dash(__name__)

app.layout = html.Div(
[
dcc.Input(
id="test-input",
type="text",
placeholder="File name",
className="create_file_input",
pattern="[a-zA-Z_][a-zA-Z0-9_]*",
),
html.Div(id="output"),
]
)

dash_dcc.start_server(app)
input_elem = dash_dcc.find_element("#test-input")

input_elem.send_keys(initial_text)
assert (
input_elem.get_attribute("value") == initial_text
), "Initial text should match"

dash_dcc.driver.execute_script(
f"""
var elem = arguments[0];
elem.setSelectionRange({cursor_position_before}, {cursor_position_before});
elem.focus();
""",
input_elem,
)

input_elem.send_keys(invalid_char)

assert (
input_elem.get_attribute("value") == expected_text
), f"Input should be {expected_text}"

cursor_position = dash_dcc.driver.execute_script(
"""
var elem = arguments[0];
return elem.selectionStart;
""",
input_elem,
)

assert (
cursor_position == expected_cursor_position
), f"Cursor should be at position {expected_cursor_position}"

assert dash_dcc.get_logs() == []

0 comments on commit 85a45bd

Please sign in to comment.