简体   繁体   English

触发点击事件需要多长时间?

[英]How long does it take until click event is triggered?

I try to make a select box whose entries are opened after clicking into the input box. 我尝试创建一个选择框,单击输入框后,其输入将打开。 After selecting one of the items, the dropdown should be closed again. 选择其中一项后,下拉菜单应再次关闭。 I want to achieve the open/close part of the dropdown without the use of javascript. 我想在不使用javascript的情况下实现下拉菜单的打开/关闭部分。

The html looks like this: html看起来像这样:

<div id="outer">
  <input type="text" id="input">
  <div id="results">
    <div>Test 1 </div>
    <div>Test 2 </div>
    <div>Test 3 </div>
    <div>Test 4 </div>    
  </div>
</div>
<div id="label">
</div>

After clicking onto an item, the selected value should appear below the #outer div (just for demonstration purposes). 单击项目后,所选值应显示在#outer div下方(仅用于演示目的)。 The Javascript for assigning click events to the dropdown values: 用于将点击事件分配给下拉值的Javascript:

document.querySelectorAll("#results div").forEach(setClick);
function setClick(node) {
     node.addEventListener("click", setText.bind(null, node.innerHTML))
}
function setText(t) {
    document.getElementById("label").innerHTML = t;
}

Now I will show you my first draft of css code: 现在,我将向您展示我的CSS代码初稿:

#outer {
  width: 200px;
  position: relative;
}
#input {
  width: 100%;
}
#results {
    position: absolute;
    width: 100%;
    display: block;
    visibility: hidden;
    background-color: white;
}
#results > div:hover {
  background-color: lightblue;
  cursor: pointer;
}
#outer:focus-within #results, #results:hover {
  visibility: visible;
}

This works like a charm but fails in one point: After clicking an item, the dropdown is not closed. 这就像一个超级按钮,但有一点失败:单击一个项目后,下拉列表没有关闭。 This is because of the #results:hover selector which is needed to keep the dropdown open after clicking onto an item. 这是因为需要使用#results:hover选择器,以在单击某个项目后保持下拉菜单处于打开状态。 The click takes the focus out of the input field, thus the focus-within selector is not applied anymore. 单击将焦点移出输入字段,因此不再应用focus-within选择器。 As the focus is removed from the input before the click occurs, the dropdown is hidden when the final click arrives in the document (this is my understanding of the problem). 由于在单击发生之前从输入中移出了焦点,因此当最终单击到达文档时,下拉菜单将隐藏(这是我对问题的理解)。 Thus I use the hover selector which forces the div to keep open as long as the mouse is above the div. 因此,我使用hover选择器,只要鼠标在div上方,它就会强制div保持打开状态。

You can test this here: https://jsfiddle.net/hcetz1og/3/ 您可以在这里测试: https : //jsfiddle.net/hcetz1og/3/

My solution for this was a transition that hides the dropdown after the focus has been taken away: 我对此的解决方案是一个过渡,在焦点移开后隐藏了下拉菜单:

#outer:not(:focus-within) #results:hover {
  visibility: hidden;
  transition-property: visibility;
  /*use 10 ms and the clicked value in the drop down won't be shown */
  transition-delay: 100ms;
  transition-timing-function: step-end;
}

This works on my machine when I use 100ms as a delay. 当我使用100ms作为延迟时,这在我的机器上有效。 If I use 10ms, I have the same problem again. 如果使用10毫秒,我将再次遇到相同的问题。 It seems that the click event is triggered "very" late. 看来,点击事件是“非常”晚才触发的。

Feel free to test it here: https://jsfiddle.net/hcetz1og/2 随时在这里进行测试: https//jsfiddle.net/hcetz1og/2

Question: How long will it take until the click event arrives at the document? 问:单击事件到达文档要花多长时间? Is there a fixed time span I have to wait or can the delay depend on every machine? 我必须等待一个固定的时间范围,还是延迟取决于每台计算机? If so, I am forced to not use plain CSS but must use javascript for this I think. 如果是这样,我被迫不使用纯CSS,而必须使用javascript。

Edit : Feel free to post an alternative solution using plain css. 编辑 :随意发布使用纯CSS的替代解决方案。 But please be aware that I mainly want to focus on getting an answer to this question, not alternative solutions. 但是请注意,我主要想集中精力获得该问题的答案,而不是替代解决方案。

As @Mark Baijens said in the comments, using timeouts is a bad practice, so here is a pretty clean solution. 正如@Mark Ba​​ijens在评论中所说,使用超时是一种不好的做法,因此这是一个非常干净的解决方案。 I used JavaScript to render the dropdown, not the CSS, because the CSS is where Your issue is coming from. 我使用JavaScript而不是CSS来呈现下拉列表,因为CSS是您问题的出处。

I don't know why would You want to set the innerHTML , but not some other property, like style.visibility for example. 我不知道您为什么要设置innerHTML ,而不要设置其他属性,例如style.visibility It just doesn't make sense to me, so with that in mind, let's get our hands on this :) 这对我来说没有任何意义,因此请记住这一点:

Working demo >> HERE << . 工作演示>>在这里<<

Step 1 - remove the #outer...:hover parts of CSS 第1步-删除CSS的#outer...:hover部分

So, You are left with this: 所以,剩下的就是:

#outer {
  width: 200px;
  position: relative;
}
#input {
  width: 100%;
}
#results {
    position: absolute;
    width: 100%;
    display: block;
    visibility: hidden;
    background-color: white;
}
#results > div:hover {
  background-color: lightblue;
  cursor: pointer;
}

Step 2 - add the onfocus event to the input field 第2步-将onfocus事件添加到input字段

Just assign a function call to the onfocus attribute of the input. 只需将函数调用分配给输入的onfocus属性即可。 Everything else in the HTML stays the same. HTML中的所有其他内容保持不变。

<div id="outer">
  <input type="text" id="input" onfocus="showElements()">
  <div id="results">
    <div>Test 1 </div>
    <div>Test 2 </div>
    <div>Test 3 </div>
    <div>Test 4 </div>    
  </div>
</div>
<div id="label">
</div>

Step 3 - create the showElements and hideElements function: 第3步-创建showElementshideElements函数:

function showElements() {
  document.getElementById("results").style.visibility = 'visible';
}
function hideElements() {
  document.getElementById("results").style.visibility = 'hidden';
}

Step 4 - call the hideElements() when clicked outside the input element 第4步-在input元素之外单击时调用hideElements()

There are two cases for the click outside the input element: input元素外单击有两种情况:

  • Case 1 - we clicked on one of the div s inside the #results wrapper 情况1-我们在#results包装器中单击了div之一
  • Case 2 - clicking outside the input field, but not on one of the div s inside the #results wrapper 情况2-在输入字段外部单击,但不在#results包装器内的div之一上单击

In the first case , we will modify the assignment of the onclick handler like this: 在第一种情况下 ,我们将像这样修改onclick处理程序的分配:

document.querySelectorAll("#results div").forEach(setClick);
function setClick(node) {
  node.addEventListener("click", setTextAndHideElements.bind(null, node.innerHTML));
}

So, the setText function now becomes setTextAndHideElements and looks like this: 因此, setText函数现在变为setTextAndHideElements ,如下所示:

function setTextAndHideElements(t) {
  document.getElementById("label").innerHTML = t;
  hideElements();
}

For the second case (clicking outside the input field, but not on one of the div s inside the #results wrapper), we must watch for the click on the whole page ( document element), and respond to the action like this: 对于第二种情况 (在输入字段之外单击,而不是在#results包装器内的div上单击),我们必须注意整个页面( document元素)上的单击,并响应如下操作:

document.onclick = function(e) {
  if (e.target.id !== 'input'){
    hideElements();
  }
}

Note: this will override any previously assigned onclick events assigned to the document element. 注意:这将覆盖先前分配给document元素的所有先前分配的onclick事件。

As mentioned in the beginning, working demo is >> HERE (codepen.io) << . 如开头所述,工作示例为>> HERE(codepen.io)<<

I tried another solution which requires no setting of additional JS events. 我尝试了另一种无需设置其他JS事件的解决方案。 See: https://jsfiddle.net/hcetz1og/4/ 参见: https : //jsfiddle.net/hcetz1og/4/

I gave every result item a tabindex of "0" to ensure, those items can be focusable. 我给每个result item的tabindex都设置为“ 0”,以确保这些项可以聚焦。 Then i removed the #outer:not() part from the css and replaced the hover selector with this: #results:focus-within . 然后,我从CSS中删除了#outer:not()部分,并将hover选择器替换为: #results:focus-within Additional I called node.blur() on the node after clicking onto them. 单击它们后,我在节点上还调用了node.blur()

Summary: Change in HTML: 摘要:HTML的更改:

<div tabindex="0">Test 1 </div>

Change in JS: 更改JS:

function setText(t, node) {
    document.getElementById("label").innerHTML = t;
  node.blur();
}

Change in CSS: CSS变更:

#outer:focus-within #results, #results:focus-within {
  visibility: visible;
}

What do you think about this one? 您如何看待这个? Should be stable I think because the focus onto the #results div is set before the click event is triggered onto the result item. 我认为应该稳定,因为在将click事件触发到结果项之前#results焦点放在#results div上。 Event order should be (based on my observation): 活动顺序应为(根据我的观察):

input focus -> input blur -> item focus -> item click

Not sure if the step between blur and focus can lead to a visible problem. 不确定模糊和聚焦之间的距离是否会导致可见的问题。 Theoretically, the results div must be hidden and shown again in a very small amount of time. 从理论上讲,必须隐藏结果div并在非常短的时间内再次显示。 But I investigated this with chrome's performance timeline and did not recognize a new render between both events. 但是我用chrome的性能时间表对此进行了调查,但没有发现两个事件之间都有新的渲染。 One can see, that the result item is focused (outline is set onto it) and then it disappears as expected. 可以看到,结果项已聚焦(轮廓已设置在其上),然后按预期消失。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM