javascript onclick() 和 onblur() 排序问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17769005/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
onclick() and onblur() ordering issue
提问by 1''
I have an input field that brings up a custom drop-down menu. I would like the following functionality:
我有一个可以显示自定义下拉菜单的输入字段。我想要以下功能:
- When the user clicks anywhere outside the input field, the menu should be removed.
- If, more specifically, the user clicks on a div inside the menu, the menu should be removed, andspecial processing should occur based on which div was clicked.
- 当用户点击输入字段外的任何地方时,菜单应该被删除。
- 更具体地说,如果用户单击菜单内的 div,则应删除该菜单,并应根据单击的 div 进行特殊处理。
Here is my implementation:
这是我的实现:
The input field has an onblur()
event which deletes the menu (by setting its parent's innerHTML
to an empty string) whenever the user clicks outside the input field. The divs inside the menu also have onclick()
events which execute the special processing.
输入字段有一个onblur()
事件,它会innerHTML
在用户在输入字段外单击时删除菜单(通过将其父级设置为空字符串)。菜单内的 div 也有onclick()
执行特殊处理的事件。
The problem is that the onclick()
events never fire when the menu is clicked, because the input field's onblur()
fires first and deletes the menu, including the onclick()
s!
问题是onclick()
单击菜单时事件永远不会触发,因为输入字段onblur()
首先触发并删除菜单,包括onclick()
s!
I solved the problem by splitting the menu divs' onclick()
into onmousedown()
and onmouseup()
events and setting a global flag on mouse down which is cleared on mouse up, similar to what was suggested in this answer. Because onmousedown()
fires before onblur()
, the flag will be set in onblur()
if one of the menu divs was clicked, but not if somewhere else on the screen was. If the menu was clicked, I immediately return from onblur()
without deleting the menu, then wait for the onclick()
to fire, at which point I can safely delete the menu.
我通过将菜单 div 拆分onclick()
为onmousedown()
和onmouseup()
事件并在鼠标按下时设置全局标志来解决该问题,该标志在鼠标抬起时清除,类似于此答案中的建议。因为onmousedown()
触发 before onblur()
,onblur()
如果单击菜单 div 之一,则标志将被设置,但如果屏幕上的其他地方被单击,则不会。如果单击菜单,我立即返回onblur()
而不删除菜单,然后等待onclick()
触发,此时我可以安全地删除菜单。
Is there a more elegant solution?
有没有更优雅的解决方案?
The code looks something like this:
代码如下所示:
<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;
...
}
回答by johnbakers
I was having the exact same issue as you, my UI is designed exactly as you describe. I solved the problem by simply replacing the onClick
for the menu items with an onMouseDown
. I did nothing else; no onMouseUp
, no flags. This resolved the problem by letting the browser automatically re-order based on the priority of these event handlers, without any additional work from me.
我遇到了与您完全相同的问题,我的 UI 设计完全按照您的描述进行。我通过简单地将onClick
菜单项替换为onMouseDown
. 我什么也没做;不onMouseUp
,没有标志。这通过让浏览器根据这些事件处理程序的优先级自动重新排序解决了这个问题,而无需我做任何额外的工作。
Is there any reason why this wouldn't have also worked for you?
有什么理由说明这对您不起作用吗?
回答by Ian MacFarlane
onClick
should not be replaced with onMouseDown
.
onClick
不应替换为onMouseDown
.
While this approach somewhat works, the two are fundamentally different events that have different expectations in the eyes of the user. Using onMouseDown
instead of onClick
will ruin the predictability of your software in this case. Thus, the two events are noninterchangeable.
虽然这种方法有点奏效,但两者是根本不同的事件,在用户眼中有着不同的期望。在这种情况下,使用onMouseDown
而不是onClick
会破坏软件的可预测性。因此,这两个事件是不可互换的。
To illustrate: when accidentally clicking on a button, users expect to be able to hold down the mouse click, drag the cursor outside of the element, and release the mouse button, ultimately resulting in no action. onClick
does this. onMouseDown
doesn't allow the user to hold the mouse down, and instead will immediately trigger an action, without any recourse for the user. onClick
is the standard by which we expect to trigger actions on a computer.
举例说明:当不小心点击一个按钮时,用户希望能够按住鼠标单击,将光标拖到元素外,然后松开鼠标按钮,最终导致没有任何动作。onClick
做这个。onMouseDown
不允许用户按住鼠标,而是立即触发一个动作,对用户没有任何追索权。onClick
是我们期望在计算机上触发操作的标准。
In this situation, call event.preventDefault()
on the onMouseDown
event. onMouseDown
will cause a blur event by default, and will not do so when preventDefault
is called. Then, onClick
will have a chance to be called. A blur event will still happen, only after onClick
.
在这种情况下,调用event.preventDefault()
的onMouseDown
事件。onMouseDown
默认情况下会导致模糊事件,并且在preventDefault
调用时不会这样做。那么,onClick
就有机会被召唤。模糊事件仍然会发生,只有在 之后onClick
。
After all, the onClick
event is a combination of onMouseDown
and onMouseUp
, if and only if they both occur within the same element.
毕竟,onClick
事件的组合onMouseDown
和onMouseUp
,当且仅当它们都发生在同一单元内。
回答by HIRA THAKUR
Replace on onmousedown
with onfocus
. So this event will be triggered when the focus is inside the textbox.
替换onmousedown
为onfocus
. 所以当焦点在文本框内时会触发此事件。
Replace on onmouseup
with onblur
. The moment you take out your focus out of textbox, onblur will execute.
替换onmouseup
为onblur
. 当您将焦点移出文本框时,onblur 将执行。
I guess this is what you might need.
我想这就是你可能需要的。
UPDATE:
更新:
when you execute your function onfocus-->remove the classes that you will apply in onblur and add the classes that you want to be executed onfocus
当你执行你的函数 onfocus--> 删除你将在 onblur 中应用的类并添加你想要在 onfocus 中执行的类
and
和
when you execute your function onblur-->remove the classes that you will apply in onfocus and add the classes that you want to be executed onblur
当你执行你的函数 onblur--> 删除你将在 onfocus 中应用的类并添加你想要在 onblur 中执行的类
I don't see any need of flag variables.
我认为不需要标志变量。
UPDATE 2:
更新 2:
You can use the events onmouseout and onmouseover
您可以使用 onmouseout 和 onmouseover 事件
onmouseover-Detects when the cursor is over it.
onmouseover -检测光标何时位于其上方。
onmouseout-Detects when the cursor leaves.
onmouseout -检测光标何时离开。
回答by 1''
A more elegant (but likely less performant) solution:
一个更优雅(但性能可能更低)的解决方案:
Instead of using the input's onblur to remove the menu, use document.onclick
, which fires after onblur
.
不是使用输入的 onblur 来移除菜单,而是使用document.onclick
,它在 之后触发onblur
。
However, this also means that the menu is removed when the input itself is clicked on, which is undesired behaviour. Set an input.onclick
with event.stopPropagation()
to avoid propagating clicks to the document click event.
然而,这也意味着当点击输入本身时菜单被删除,这是不受欢迎的行为。设置input.onclick
withevent.stopPropagation()
以避免将点击传播到文档点击事件。
回答by Brasil
change onclick by onfocus
通过 onfocus 更改 onclick
even if the onblur and onclick do not get along very well, but obviously onfocus and yes onblur. since even after the menu is closed the onfocus is still valid for the element clicked inside.
即使 onblur 和 onclick 相处得不是很好,但很明显 onfocus 和是 onblur。因为即使在菜单关闭后,onfocus 对于在内部单击的元素仍然有效。
I did and it worked.
我做到了,它奏效了。
回答by user5271069
You can use a setInterval
function inside your onBlur
handler, like this:
您可以setInterval
在onBlur
处理程序中使用一个函数,如下所示:
<input id="input" onblur="removeMenu()" ... />
function removeMenu() {
setInterval(function(){
if (!mouseflag) {
document.getElementById('menu').innerHTML = '';
}
}, 0);
}
the setInterval
function will remove your onBlur
function out from the call stack, add because you set time to 0, this function will be called immediately after other event handler finished
该setInterval
函数将从onBlur
调用堆栈中删除您的函数,添加因为您将时间设置为 0,该函数将在其他事件处理程序完成后立即调用