Некорректный перехват нажатия клавиши в JS
в своей программе я хочу, чтобы когда пользователь ввел необходимый текст вызвать функцию alert. Все происходит правильно, только я вынужден набрать на 1 символ больше. Например, вместо того, чтобы просто набрать ЗДОРОВА, я должен дополнительно нажать еще на 1 клавишу (любую). Вот код:
let textBlock = document.getElementById("textBlock");
let textPlace = document.getElementById("textPlace");
function keyHandler(e) {
let len = textPlace.value.length;
if (textPlace.value === textBlock.textContent) {
alert("Ты победил!");
}
else if (textPlace.value != textBlock.textContent.slice(0, len)){
e.target.style.backgroundColor = "red";
}
else {
e.target.style.backgroundColor = "white";
}
}
textPlace.addEventListener("keydown", keyHandler);
Ответы (3 шт):
Сделайте вместо keydown обработку на отпускание клавиши keyup.
Потому что в ином случае событие срабатывает, но на момент его срабатывания в текстовом поле ещё ничего нет. Просто отработка события, ничего более.
Когда происходит событее 'keydown', содержимое поля ещё не изменилось, новый символ ещё не вставлен. Попробуйте использовать событие 'keyup', а ещё лучше событие 'input' (тогда будет работать, например, и при вставке из буфера без участия клавиатуры).
Если вы хотите использовать keydown, знайте, он срабатывает до того, как <input> успеет обработать нажатие клавиши (кстати, это нажатие можно еще и отменить так, что до <input> вообще не дойдет никакой информации).
Но вы можете приплюсовать букву последней клавиши к результату сами.
И ещё я бы рекомендовал заменить работающий везде alert() на что-то более современное (глючащее во многих браузерах) типа <dialog>.
let textBlock = document.getElementById("textBlock");
let textPlace = document.getElementById("textPlace");
function keyHandler(e) {
console.clear();
console.log(`Была нажата клавиша "${e.key}", каретка в позиции ${e.target.selectionStart}`);
const value = textPlace.value;
const caret = e.target.selectionStart;
// новоеЗначение = значениеДоКаретки + буква + значениеПослеКаретки
const newValue = value.substr(0,caret)+e.key+value.substr(caret);
let len = value.length;
if (newValue.trim() === textBlock.textContent.trim()) {
window.requestAnimationFrame(() => {
// А вот тут, мои дорогие, значение <input> будет уже с буквой
// И если сделать проверку здесь, то можно не заморачиваться
// ручной вставкой буквы в значение <input>
console.log('значение в input :', textPlace.value);
if(textPlace.value.trim() === textBlock.textContent.trim()){
openDialog();
}
});
} else if (textPlace.value != textBlock.textContent.slice(0, len)) {
e.target.style.backgroundColor = "red";
} else {
e.target.style.backgroundColor = "white";
}
}
function openDialog() {
let dialog = document.querySelector('#win-dialog');
if (dialog.showModal) {
dialog.showModal();
} else {
dialog.show();
}
}
textPlace.addEventListener("keydown", keyHandler);
* {
box-sizing: border-box;
}
#textBlock {
border: 2px dashed #800;
margin: .5rem;
padding: 1rem;
font-size: 2.5rem;
}
#textPlace {
border: 2px dashed #800;
margin: .5rem;
padding: 1rem;
font-size: 2.5rem;
width: calc(100% - 1rem);
}
dialog { text-align: center; }
dialog button { padding: 0.5rem 2rem 0.5rem 2rem };
<p id=textBlock>Привет</p>
<p><input id=textPlace type=text value="" /></p>
<dialog id="win-dialog">
<h3>Ты победил</h3>
<button onclick="this.closest('dialog').close()">OK</button>
</dialog>