Eu tenho um campo de entrada que abre um menu suspenso personalizado. Eu gostaria da seguinte funcionalidade:
- Quando o usuário clica em qualquer lugar fora do campo de entrada, o menu deve ser removido.
- Se, mais especificamente, o usuário clicar em um div dentro do menu, o menu deve ser removido e um processamento especial deve ocorrer com base em qual div foi clicado.
Aqui está minha implementação:
O campo de entrada tem um onblur()
evento que exclui o menu (definindo o do pai innerHTML
como uma string vazia) sempre que o usuário clica fora do campo de entrada. Os divs dentro do menu também possuem onclick()
eventos que executam o processamento especial.
O problema é que os onclick()
eventos nunca disparam quando o menu é clicado, porque o campo de entrada onblur()
dispara primeiro e exclui o menu, incluindo o onclick()
s!
Eu resolvi o problema dividindo os divs Menu onclick()
em onmousedown()
e onmouseup()
eventos e definir um sinalizador global no mouse para baixo, que é cancelado no mouse para cima, semelhante ao que foi sugerido em esta resposta . Como onmousedown()
dispara antes onblur()
, o sinalizador será definido onblur()
se um dos divs do menu for clicado, mas não se em algum outro lugar da tela for clicado. Se o menu foi clicado, eu retorno imediatamente onblur()
sem excluí-lo e, em seguida, aguardo o onclick()
disparo, momento em que posso excluir o menu com segurança.
Existe uma solução mais elegante?
O código é parecido com este:
<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;
...
}