Onclick() и onblur()
У меня есть поле ввода, в котором отображается настраиваемое раскрывающееся меню. Я хотел бы использовать следующие функции:
- Когда пользователь нажимает нигде вне поля ввода, меню следует удалить.
- Если, более конкретно, пользователь нажимает на div внутри меню, меню должно быть удалено, и специальная обработка должна произойти, на основании которого был нажат div.
Вот моя реализация:
В поле ввода есть событие onblur()
, которое удаляет меню (путем установки родительского элемента innerHTML
в пустую строку) всякий раз, когда пользователь щелкает за пределами поля ввода. Внутри div также есть onclick()
события, которые выполняют специальную обработку.
Проблема в том, что события onclick()
никогда не срабатывают при щелчке по меню, потому что поле ввода onblur()
срабатывает первым и удаляет меню, включая onclick()
s!
Я решил проблему, разделив события div div < > t22 > на onmousedown()
и onmouseup()
событиями и установив глобальный флаг мыши, который очищается с помощью мыши вверх, подобно тому, что было предложено в этот ответ. Поскольку перед тем, как onblur()
срабатывает onmousedown()
, флаг будет установлен в onblur()
, если было нажато одно из разделов меню, но не было, если в другом месте на экране было. Если щелкнуть меню, я сразу же вернусь из onblur()
, не удаляя меню, а затем дождитесь onclick()
, и в этот момент я могу безопасно удалить меню.
Есть ли более элегантное решение?
Код выглядит примерно так:
<div class="menu" onmousedown="setFlag()" onmouseup="doProcessing()">...</div>
<input id="input" onblur="removeMenu()" ... />
var mouseflag;
function setFlag() {
mouseflag = true;
}
function removeMenu() {
if (!mouseflag) {
document.getElementById('menu').innerHTML = '';
}
}
function doProcessing(id, name) {
mouseflag = false;
...
}
Ответы
Ответ 1
У меня была та же проблема, что и у вас, мой интерфейс разработан именно так, как вы описываете. Я решил проблему, просто заменив onClick
для пунктов меню на onMouseDown
. Я больше ничего не делал; нет onMouseUp
, нет флагов. Это решило проблему, позволив браузеру автоматически переупорядочивать в зависимости от приоритета этих обработчиков событий, без дополнительной работы с моей стороны.
Есть ли причина, по которой это не сработало бы и для вас?
Ответ 2
Заменить на onmousedown
с onfocus
, Таким образом, это событие будет срабатывать, когда фокус находится внутри текстового поля.
Замените на onmouseup
с onblur
, Когда вы выберете фокус из текстового поля, будет выполняться onblur.
Я думаю, это то, что вам может понадобиться.
UPDATE
при выполнении вашей функции onfocus → удалить классы, которые будут применяться в onblur, и добавить классы, которые вы хотите выполнить в фокусе
и
когда вы выполняете свою функцию onblur → удалите классы, которые будут применяться в onfocus
и добавьте классы, которые вы хотите выполнить onblur
Я не вижу необходимости в переменных флага.
ОБНОВЛЕНИЕ 2:
Вы можете использовать события onmouseout и onmouseover
onmouseover - определяет, когда курсор над ним.
onmouseout - определяет, когда курсор покидает.
Ответ 3
Более элегантное (но скорее менее эффективное) решение:
Вместо того, чтобы использовать ввод onblur для удаления меню, используйте document.onclick
, который запускается после onblur
.
Однако это также означает, что меню удаляется при нажатии на вход, что является нежелательным поведением. Установите input.onclick
с помощью event.stopPropagation()
, чтобы избежать распространения кликов на событие щелчка документа.
Ответ 4
onClick
не следует заменять на onMouseDown
.
Хотя этот подход в некоторой степени работает, это два принципиально разных события, которые имеют разные ожидания в глазах пользователя. Использование onMouseDown
вместо onClick
нарушит предсказуемость вашего программного обеспечения в этом случае. Таким образом, эти два события не являются взаимозаменяемыми.
Для иллюстрации: при случайном нажатии на кнопку пользователи ожидают, что смогут удерживать нажатой кнопку мыши, перетащить курсор за пределы элемента и отпустить кнопку мыши, что в конечном итоге не приведет к каким-либо действиям. onClick
делает это. onMouseDown
не позволяет пользователю удерживать мышь нажатой, а вместо этого немедленно запускает действие, без какой-либо помощи для пользователя. onClick
- это стандарт, по которому мы ожидаем запуска действий на компьютере.
В этой ситуации вызовите event.preventDefault()
для события onMouseDown
. По умолчанию onMouseDown
вызывает событие размытия по умолчанию и не будет делать это при вызове preventDefault
. Тогда у onClick
будет шанс позвонить. Событие размытия все равно произойдет, только после onClick
.
В конце концов, событие onClick
является комбинацией onMouseDown
и onMouseUp
, если и только если они оба происходят в одном и том же элементе.
Ответ 5
изменить onclick с помощью onfocus
даже если onblur и onclick не очень хорошо ладят друг с другом, но очевидно onfocus и yes onblur. поскольку даже после закрытия меню онфокус по-прежнему действует для элемента, щелкнувшего внутри.
Я сделал, и это сработало.
Ответ 6
Вы можете использовать функцию setInterval
внутри вашего обработчика onBlur
, например:
<input id="input" onblur="removeMenu()" ... />
function removeMenu() {
setInterval(function(){
if (!mouseflag) {
document.getElementById('menu').innerHTML = '';
}
}, 0);
}
функция setInterval
удалит вашу функцию onBlur
из стека вызовов, добавит, потому что вы установите время на 0, эта функция вызывается сразу после завершения обработчика других событий