У мене є поле введення, яке відображає користувацьке спадне меню. Я хотів би наступної функціональності:
- Коли користувач натискає будь-яке місце поза полем введення, меню слід видалити.
- Якщо, більш конкретно, користувач натискає на div всередині меню, меню слід видалити, і повинна відбутися спеціальна обробка, на основі якої було натиснуто div.
Ось моя реалізація:
У полі введення є onblur()
подія, яка видаляє меню (шляхом встановлення батьківського innerHTML
поля на порожній рядок) кожного разу, коли користувач клацне за межами поля введення. У дівах всередині меню також є onclick()
події, які виконують спеціальну обробку.
Проблема полягає в тому, що onclick()
події ніколи не спрацьовують при натисканні на меню, оскільки onblur()
спочатку вводиться поле введення та видаляє меню, включаючи onclick()
s!
Я вирішив цю проблему, розділивши меню divs ' onclick()
на onmousedown()
і onmouseup()
події та встановивши глобальний прапор на миші вниз, який очищається на миші вгору, подібно до того, що було запропоновано у цій відповіді . Оскільки onmousedown()
запускається раніше onblur()
, прапор буде встановлено, 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;
...
}