How long does it take until click event is triggered?How do I detect a click outside an element?Trigger a button click with JavaScript on the Enter key in a text boxHow does JavaScript .prototype work?How to trigger event in JavaScript?How does the “this” keyword work?How to make Twitter Bootstrap menu dropdown on hover rather than clickHow does data binding work in AngularJS?Jquery UI autocomplete combobox button click eventHow does Facebook disable the browser's integrated Developer Tools?Cannot display HTML string
What are these funnel-looking green things in my yard?
Do I have to cite common CS algorithms?
What is the difference between 王 and 皇?
Why did Saruman lie?
Why aren't rainbows blurred-out into nothing after they are produced?
Using hearing aids on the sabbath?
How do some PhD students get 10+ papers? Is that what I need for landing good faculty position?
How can God warn people of the upcoming rapture without disrupting society?
Website error: "Walmart can’t use this browser"
Regex crossword (sudoku?)
If you know the location of an invisible creature, can you attack it?
Are those flyers about apartment purchase a scam?
What is a "soap"?
Help, I cannot decide when to start the story
Can the IPA represent all languages' tones?
A torrent of foreign terms
Why is the result of ('b'+'a'+ + 'a' + 'a').toLowerCase() 'banana'?
Can sampling rate be a floating point number?
How to derive this identity
Boss asked a co-worker to assault me
Why aren’t there water shutoff valves for each room?
Is there a SQL/English like language that lets you define formulations given some data?
How would timezones work on a planet 100 times the size of our Earth
Why does my purified Pokémon need to be healed?
How long does it take until click event is triggered?
How do I detect a click outside an element?Trigger a button click with JavaScript on the Enter key in a text boxHow does JavaScript .prototype work?How to trigger event in JavaScript?How does the “this” keyword work?How to make Twitter Bootstrap menu dropdown on hover rather than clickHow does data binding work in AngularJS?Jquery UI autocomplete combobox button click eventHow does Facebook disable the browser's integrated Developer Tools?Cannot display HTML string
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
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.
The html looks like this:
<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).
The Javascript for assigning click events to the dropdown values:
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:
#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. The click takes the focus out of the input field, thus the focus-within
selector is not applied anymore. 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.
You can test this here:
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. If I use 10ms, I have the same problem again. It seems that the click event is triggered "very" late.
Feel free to test it here:
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.
Edit:
Feel free to post an alternative solution using plain css. But please be aware that I mainly want to focus on getting an answer to this question, not alternative solutions.
javascript html css css3
add a comment |
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.
The html looks like this:
<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).
The Javascript for assigning click events to the dropdown values:
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:
#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. The click takes the focus out of the input field, thus the focus-within
selector is not applied anymore. 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.
You can test this here:
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. If I use 10ms, I have the same problem again. It seems that the click event is triggered "very" late.
Feel free to test it here:
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.
Edit:
Feel free to post an alternative solution using plain css. But please be aware that I mainly want to focus on getting an answer to this question, not alternative solutions.
javascript html css css3
i don't think it is a delay after the click but rather you need to mouse out after the click??? or so it seems for me
– Paddy Hallihan
Mar 27 at 9:01
@PaddyHallihan Yes, I need to mouse out to force thehover
selector to not be applied anymore. For this I introduced the second solution. By using a transition withstep-end
I am ensuring that the dropdown is "moved" away from the user's mouse position, forcing thehover
to be disabled. But when this happens too early, the click seems not to touch the result items, otherwise the item's value should be rendered below theouter
div. I am not sure about the exact process here. It is only a assumption by me. Maybe someone knows in depth what is happening here.
– Josef Biehler
Mar 27 at 9:10
4
The time for a click event to trigger should be really short. It's impossible to say exactly how short because it depend on the computing power, browser and other factors. Therefore a design that depends on timings like this is bad in my opinion and should be avoided if possible. It is as asking for problems. A javascript solution based on event handlers would be much more reliable and easy to implement. Not sure if it can be accomplished with css.
– Mark Baijens
Mar 27 at 9:22
add a comment |
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.
The html looks like this:
<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).
The Javascript for assigning click events to the dropdown values:
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:
#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. The click takes the focus out of the input field, thus the focus-within
selector is not applied anymore. 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.
You can test this here:
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. If I use 10ms, I have the same problem again. It seems that the click event is triggered "very" late.
Feel free to test it here:
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.
Edit:
Feel free to post an alternative solution using plain css. But please be aware that I mainly want to focus on getting an answer to this question, not alternative solutions.
javascript html css css3
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.
The html looks like this:
<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).
The Javascript for assigning click events to the dropdown values:
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:
#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. The click takes the focus out of the input field, thus the focus-within
selector is not applied anymore. 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.
You can test this here:
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. If I use 10ms, I have the same problem again. It seems that the click event is triggered "very" late.
Feel free to test it here:
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.
Edit:
Feel free to post an alternative solution using plain css. But please be aware that I mainly want to focus on getting an answer to this question, not alternative solutions.
javascript html css css3
javascript html css css3
edited Mar 27 at 8:52
errorau
5711 gold badge3 silver badges20 bronze badges
5711 gold badge3 silver badges20 bronze badges
asked Mar 27 at 8:43
Josef BiehlerJosef Biehler
19412 bronze badges
19412 bronze badges
i don't think it is a delay after the click but rather you need to mouse out after the click??? or so it seems for me
– Paddy Hallihan
Mar 27 at 9:01
@PaddyHallihan Yes, I need to mouse out to force thehover
selector to not be applied anymore. For this I introduced the second solution. By using a transition withstep-end
I am ensuring that the dropdown is "moved" away from the user's mouse position, forcing thehover
to be disabled. But when this happens too early, the click seems not to touch the result items, otherwise the item's value should be rendered below theouter
div. I am not sure about the exact process here. It is only a assumption by me. Maybe someone knows in depth what is happening here.
– Josef Biehler
Mar 27 at 9:10
4
The time for a click event to trigger should be really short. It's impossible to say exactly how short because it depend on the computing power, browser and other factors. Therefore a design that depends on timings like this is bad in my opinion and should be avoided if possible. It is as asking for problems. A javascript solution based on event handlers would be much more reliable and easy to implement. Not sure if it can be accomplished with css.
– Mark Baijens
Mar 27 at 9:22
add a comment |
i don't think it is a delay after the click but rather you need to mouse out after the click??? or so it seems for me
– Paddy Hallihan
Mar 27 at 9:01
@PaddyHallihan Yes, I need to mouse out to force thehover
selector to not be applied anymore. For this I introduced the second solution. By using a transition withstep-end
I am ensuring that the dropdown is "moved" away from the user's mouse position, forcing thehover
to be disabled. But when this happens too early, the click seems not to touch the result items, otherwise the item's value should be rendered below theouter
div. I am not sure about the exact process here. It is only a assumption by me. Maybe someone knows in depth what is happening here.
– Josef Biehler
Mar 27 at 9:10
4
The time for a click event to trigger should be really short. It's impossible to say exactly how short because it depend on the computing power, browser and other factors. Therefore a design that depends on timings like this is bad in my opinion and should be avoided if possible. It is as asking for problems. A javascript solution based on event handlers would be much more reliable and easy to implement. Not sure if it can be accomplished with css.
– Mark Baijens
Mar 27 at 9:22
i don't think it is a delay after the click but rather you need to mouse out after the click??? or so it seems for me
– Paddy Hallihan
Mar 27 at 9:01
i don't think it is a delay after the click but rather you need to mouse out after the click??? or so it seems for me
– Paddy Hallihan
Mar 27 at 9:01
@PaddyHallihan Yes, I need to mouse out to force the
hover
selector to not be applied anymore. For this I introduced the second solution. By using a transition with step-end
I am ensuring that the dropdown is "moved" away from the user's mouse position, forcing the hover
to be disabled. But when this happens too early, the click seems not to touch the result items, otherwise the item's value should be rendered below the outer
div. I am not sure about the exact process here. It is only a assumption by me. Maybe someone knows in depth what is happening here.– Josef Biehler
Mar 27 at 9:10
@PaddyHallihan Yes, I need to mouse out to force the
hover
selector to not be applied anymore. For this I introduced the second solution. By using a transition with step-end
I am ensuring that the dropdown is "moved" away from the user's mouse position, forcing the hover
to be disabled. But when this happens too early, the click seems not to touch the result items, otherwise the item's value should be rendered below the outer
div. I am not sure about the exact process here. It is only a assumption by me. Maybe someone knows in depth what is happening here.– Josef Biehler
Mar 27 at 9:10
4
4
The time for a click event to trigger should be really short. It's impossible to say exactly how short because it depend on the computing power, browser and other factors. Therefore a design that depends on timings like this is bad in my opinion and should be avoided if possible. It is as asking for problems. A javascript solution based on event handlers would be much more reliable and easy to implement. Not sure if it can be accomplished with css.
– Mark Baijens
Mar 27 at 9:22
The time for a click event to trigger should be really short. It's impossible to say exactly how short because it depend on the computing power, browser and other factors. Therefore a design that depends on timings like this is bad in my opinion and should be avoided if possible. It is as asking for problems. A javascript solution based on event handlers would be much more reliable and easy to implement. Not sure if it can be accomplished with css.
– Mark Baijens
Mar 27 at 9:22
add a comment |
2 Answers
2
active
oldest
votes
As @Mark Baijens said in the comments, using timeouts is a bad practice, so here is a pretty clean solution.
I used JavaScript to render the dropdown, not the CSS, because the CSS is where Your issue is coming from.
I don't know why would You want to set the innerHTML
, but not some other property, like style.visibility
for example. 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
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
Just assign a function call to the onfocus
attribute of the input. Everything else in the HTML stays the same.
<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:
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
There are two cases for the click outside the input
element:
- Case 1 - we clicked on one of the
div
s inside the#results
wrapper - Case 2 - clicking outside the input field, but not on one of the
div
s inside the#results
wrapper
In the first case, we will modify the assignment of the onclick
handler like this:
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:
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:
document.onclick = function(e)
if (e.target.id !== 'input')
hideElements();
Note: this will override any previously assigned onclick
events assigned to the document
element.
As mentioned in the beginning, working demo is >> HERE (codepen.io) <<.
As mentioned, this was only a minimal working example. Replace the innerHtml with anything you like more. Thanks for your investigation :-). Of course I know some kind of Javascript solutions (but I did not thought about usingonfocus
event for this. Seems reasonable to prefer this over a pure onclick based solution). The CSS solution would have been cleaner in my opinion. That was the reason for trying this. Unfortunatelly, the event order forces me to use this kind of timeout.
– Josef Biehler
Mar 27 at 10:43
Usingonfocus
or:focus-within
in CSS both deal with thefocus
of an element. The difference is in readability and quality of the solution. If You end up using my code (or most of it), please accept this answer. :)
– Casper
Mar 27 at 11:14
add a comment |
I tried another solution which requires no setting of additional JS events.
See: https://jsfiddle.net/hcetz1og/4/
I gave every result item
a tabindex of "0" to ensure, those items can be focusable.
Then i removed the #outer:not()
part from the css and replaced the hover
selector with this: #results:focus-within
. Additional I called node.blur()
on the node after clicking onto them.
Summary:
Change in HTML:
<div tabindex="0">Test 1 </div>
Change in JS:
function setText(t, node)
document.getElementById("label").innerHTML = t;
node.blur();
Change in 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.
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.
But I investigated this with chrome's performance timeline and did not recognize a new render between both events. One can see, that the result item is focused (outline is set onto it) and then it disappears as expected.
This will work, but it is far more complicated for understanding, I think. You should not write code that is hard to read and understand, that is why I think that JS solution is a better fit. CSS should handle styling of elements, but the logic of how something operates should be handled by JS. That's just my opinion.
– Casper
Mar 27 at 11:10
1
@Casper that is a good point! I think you're right. If another developer looks into my code, it would not be clear how this is working. Thanks for pointing this out.
– Josef Biehler
Mar 27 at 12:53
I am glad I helped :)
– Casper
Mar 27 at 12:57
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55372942%2fhow-long-does-it-take-until-click-event-is-triggered%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
As @Mark Baijens said in the comments, using timeouts is a bad practice, so here is a pretty clean solution.
I used JavaScript to render the dropdown, not the CSS, because the CSS is where Your issue is coming from.
I don't know why would You want to set the innerHTML
, but not some other property, like style.visibility
for example. 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
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
Just assign a function call to the onfocus
attribute of the input. Everything else in the HTML stays the same.
<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:
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
There are two cases for the click outside the input
element:
- Case 1 - we clicked on one of the
div
s inside the#results
wrapper - Case 2 - clicking outside the input field, but not on one of the
div
s inside the#results
wrapper
In the first case, we will modify the assignment of the onclick
handler like this:
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:
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:
document.onclick = function(e)
if (e.target.id !== 'input')
hideElements();
Note: this will override any previously assigned onclick
events assigned to the document
element.
As mentioned in the beginning, working demo is >> HERE (codepen.io) <<.
As mentioned, this was only a minimal working example. Replace the innerHtml with anything you like more. Thanks for your investigation :-). Of course I know some kind of Javascript solutions (but I did not thought about usingonfocus
event for this. Seems reasonable to prefer this over a pure onclick based solution). The CSS solution would have been cleaner in my opinion. That was the reason for trying this. Unfortunatelly, the event order forces me to use this kind of timeout.
– Josef Biehler
Mar 27 at 10:43
Usingonfocus
or:focus-within
in CSS both deal with thefocus
of an element. The difference is in readability and quality of the solution. If You end up using my code (or most of it), please accept this answer. :)
– Casper
Mar 27 at 11:14
add a comment |
As @Mark Baijens said in the comments, using timeouts is a bad practice, so here is a pretty clean solution.
I used JavaScript to render the dropdown, not the CSS, because the CSS is where Your issue is coming from.
I don't know why would You want to set the innerHTML
, but not some other property, like style.visibility
for example. 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
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
Just assign a function call to the onfocus
attribute of the input. Everything else in the HTML stays the same.
<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:
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
There are two cases for the click outside the input
element:
- Case 1 - we clicked on one of the
div
s inside the#results
wrapper - Case 2 - clicking outside the input field, but not on one of the
div
s inside the#results
wrapper
In the first case, we will modify the assignment of the onclick
handler like this:
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:
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:
document.onclick = function(e)
if (e.target.id !== 'input')
hideElements();
Note: this will override any previously assigned onclick
events assigned to the document
element.
As mentioned in the beginning, working demo is >> HERE (codepen.io) <<.
As mentioned, this was only a minimal working example. Replace the innerHtml with anything you like more. Thanks for your investigation :-). Of course I know some kind of Javascript solutions (but I did not thought about usingonfocus
event for this. Seems reasonable to prefer this over a pure onclick based solution). The CSS solution would have been cleaner in my opinion. That was the reason for trying this. Unfortunatelly, the event order forces me to use this kind of timeout.
– Josef Biehler
Mar 27 at 10:43
Usingonfocus
or:focus-within
in CSS both deal with thefocus
of an element. The difference is in readability and quality of the solution. If You end up using my code (or most of it), please accept this answer. :)
– Casper
Mar 27 at 11:14
add a comment |
As @Mark Baijens said in the comments, using timeouts is a bad practice, so here is a pretty clean solution.
I used JavaScript to render the dropdown, not the CSS, because the CSS is where Your issue is coming from.
I don't know why would You want to set the innerHTML
, but not some other property, like style.visibility
for example. 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
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
Just assign a function call to the onfocus
attribute of the input. Everything else in the HTML stays the same.
<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:
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
There are two cases for the click outside the input
element:
- Case 1 - we clicked on one of the
div
s inside the#results
wrapper - Case 2 - clicking outside the input field, but not on one of the
div
s inside the#results
wrapper
In the first case, we will modify the assignment of the onclick
handler like this:
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:
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:
document.onclick = function(e)
if (e.target.id !== 'input')
hideElements();
Note: this will override any previously assigned onclick
events assigned to the document
element.
As mentioned in the beginning, working demo is >> HERE (codepen.io) <<.
As @Mark Baijens said in the comments, using timeouts is a bad practice, so here is a pretty clean solution.
I used JavaScript to render the dropdown, not the CSS, because the CSS is where Your issue is coming from.
I don't know why would You want to set the innerHTML
, but not some other property, like style.visibility
for example. 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
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
Just assign a function call to the onfocus
attribute of the input. Everything else in the HTML stays the same.
<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:
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
There are two cases for the click outside the input
element:
- Case 1 - we clicked on one of the
div
s inside the#results
wrapper - Case 2 - clicking outside the input field, but not on one of the
div
s inside the#results
wrapper
In the first case, we will modify the assignment of the onclick
handler like this:
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:
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:
document.onclick = function(e)
if (e.target.id !== 'input')
hideElements();
Note: this will override any previously assigned onclick
events assigned to the document
element.
As mentioned in the beginning, working demo is >> HERE (codepen.io) <<.
edited Mar 27 at 10:31
answered Mar 27 at 10:03
CasperCasper
5966 silver badges15 bronze badges
5966 silver badges15 bronze badges
As mentioned, this was only a minimal working example. Replace the innerHtml with anything you like more. Thanks for your investigation :-). Of course I know some kind of Javascript solutions (but I did not thought about usingonfocus
event for this. Seems reasonable to prefer this over a pure onclick based solution). The CSS solution would have been cleaner in my opinion. That was the reason for trying this. Unfortunatelly, the event order forces me to use this kind of timeout.
– Josef Biehler
Mar 27 at 10:43
Usingonfocus
or:focus-within
in CSS both deal with thefocus
of an element. The difference is in readability and quality of the solution. If You end up using my code (or most of it), please accept this answer. :)
– Casper
Mar 27 at 11:14
add a comment |
As mentioned, this was only a minimal working example. Replace the innerHtml with anything you like more. Thanks for your investigation :-). Of course I know some kind of Javascript solutions (but I did not thought about usingonfocus
event for this. Seems reasonable to prefer this over a pure onclick based solution). The CSS solution would have been cleaner in my opinion. That was the reason for trying this. Unfortunatelly, the event order forces me to use this kind of timeout.
– Josef Biehler
Mar 27 at 10:43
Usingonfocus
or:focus-within
in CSS both deal with thefocus
of an element. The difference is in readability and quality of the solution. If You end up using my code (or most of it), please accept this answer. :)
– Casper
Mar 27 at 11:14
As mentioned, this was only a minimal working example. Replace the innerHtml with anything you like more. Thanks for your investigation :-). Of course I know some kind of Javascript solutions (but I did not thought about using
onfocus
event for this. Seems reasonable to prefer this over a pure onclick based solution). The CSS solution would have been cleaner in my opinion. That was the reason for trying this. Unfortunatelly, the event order forces me to use this kind of timeout.– Josef Biehler
Mar 27 at 10:43
As mentioned, this was only a minimal working example. Replace the innerHtml with anything you like more. Thanks for your investigation :-). Of course I know some kind of Javascript solutions (but I did not thought about using
onfocus
event for this. Seems reasonable to prefer this over a pure onclick based solution). The CSS solution would have been cleaner in my opinion. That was the reason for trying this. Unfortunatelly, the event order forces me to use this kind of timeout.– Josef Biehler
Mar 27 at 10:43
Using
onfocus
or :focus-within
in CSS both deal with the focus
of an element. The difference is in readability and quality of the solution. If You end up using my code (or most of it), please accept this answer. :)– Casper
Mar 27 at 11:14
Using
onfocus
or :focus-within
in CSS both deal with the focus
of an element. The difference is in readability and quality of the solution. If You end up using my code (or most of it), please accept this answer. :)– Casper
Mar 27 at 11:14
add a comment |
I tried another solution which requires no setting of additional JS events.
See: https://jsfiddle.net/hcetz1og/4/
I gave every result item
a tabindex of "0" to ensure, those items can be focusable.
Then i removed the #outer:not()
part from the css and replaced the hover
selector with this: #results:focus-within
. Additional I called node.blur()
on the node after clicking onto them.
Summary:
Change in HTML:
<div tabindex="0">Test 1 </div>
Change in JS:
function setText(t, node)
document.getElementById("label").innerHTML = t;
node.blur();
Change in 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.
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.
But I investigated this with chrome's performance timeline and did not recognize a new render between both events. One can see, that the result item is focused (outline is set onto it) and then it disappears as expected.
This will work, but it is far more complicated for understanding, I think. You should not write code that is hard to read and understand, that is why I think that JS solution is a better fit. CSS should handle styling of elements, but the logic of how something operates should be handled by JS. That's just my opinion.
– Casper
Mar 27 at 11:10
1
@Casper that is a good point! I think you're right. If another developer looks into my code, it would not be clear how this is working. Thanks for pointing this out.
– Josef Biehler
Mar 27 at 12:53
I am glad I helped :)
– Casper
Mar 27 at 12:57
add a comment |
I tried another solution which requires no setting of additional JS events.
See: https://jsfiddle.net/hcetz1og/4/
I gave every result item
a tabindex of "0" to ensure, those items can be focusable.
Then i removed the #outer:not()
part from the css and replaced the hover
selector with this: #results:focus-within
. Additional I called node.blur()
on the node after clicking onto them.
Summary:
Change in HTML:
<div tabindex="0">Test 1 </div>
Change in JS:
function setText(t, node)
document.getElementById("label").innerHTML = t;
node.blur();
Change in 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.
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.
But I investigated this with chrome's performance timeline and did not recognize a new render between both events. One can see, that the result item is focused (outline is set onto it) and then it disappears as expected.
This will work, but it is far more complicated for understanding, I think. You should not write code that is hard to read and understand, that is why I think that JS solution is a better fit. CSS should handle styling of elements, but the logic of how something operates should be handled by JS. That's just my opinion.
– Casper
Mar 27 at 11:10
1
@Casper that is a good point! I think you're right. If another developer looks into my code, it would not be clear how this is working. Thanks for pointing this out.
– Josef Biehler
Mar 27 at 12:53
I am glad I helped :)
– Casper
Mar 27 at 12:57
add a comment |
I tried another solution which requires no setting of additional JS events.
See: https://jsfiddle.net/hcetz1og/4/
I gave every result item
a tabindex of "0" to ensure, those items can be focusable.
Then i removed the #outer:not()
part from the css and replaced the hover
selector with this: #results:focus-within
. Additional I called node.blur()
on the node after clicking onto them.
Summary:
Change in HTML:
<div tabindex="0">Test 1 </div>
Change in JS:
function setText(t, node)
document.getElementById("label").innerHTML = t;
node.blur();
Change in 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.
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.
But I investigated this with chrome's performance timeline and did not recognize a new render between both events. One can see, that the result item is focused (outline is set onto it) and then it disappears as expected.
I tried another solution which requires no setting of additional JS events.
See: https://jsfiddle.net/hcetz1og/4/
I gave every result item
a tabindex of "0" to ensure, those items can be focusable.
Then i removed the #outer:not()
part from the css and replaced the hover
selector with this: #results:focus-within
. Additional I called node.blur()
on the node after clicking onto them.
Summary:
Change in HTML:
<div tabindex="0">Test 1 </div>
Change in JS:
function setText(t, node)
document.getElementById("label").innerHTML = t;
node.blur();
Change in 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.
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.
But I investigated this with chrome's performance timeline and did not recognize a new render between both events. One can see, that the result item is focused (outline is set onto it) and then it disappears as expected.
answered Mar 27 at 10:55
Josef BiehlerJosef Biehler
19412 bronze badges
19412 bronze badges
This will work, but it is far more complicated for understanding, I think. You should not write code that is hard to read and understand, that is why I think that JS solution is a better fit. CSS should handle styling of elements, but the logic of how something operates should be handled by JS. That's just my opinion.
– Casper
Mar 27 at 11:10
1
@Casper that is a good point! I think you're right. If another developer looks into my code, it would not be clear how this is working. Thanks for pointing this out.
– Josef Biehler
Mar 27 at 12:53
I am glad I helped :)
– Casper
Mar 27 at 12:57
add a comment |
This will work, but it is far more complicated for understanding, I think. You should not write code that is hard to read and understand, that is why I think that JS solution is a better fit. CSS should handle styling of elements, but the logic of how something operates should be handled by JS. That's just my opinion.
– Casper
Mar 27 at 11:10
1
@Casper that is a good point! I think you're right. If another developer looks into my code, it would not be clear how this is working. Thanks for pointing this out.
– Josef Biehler
Mar 27 at 12:53
I am glad I helped :)
– Casper
Mar 27 at 12:57
This will work, but it is far more complicated for understanding, I think. You should not write code that is hard to read and understand, that is why I think that JS solution is a better fit. CSS should handle styling of elements, but the logic of how something operates should be handled by JS. That's just my opinion.
– Casper
Mar 27 at 11:10
This will work, but it is far more complicated for understanding, I think. You should not write code that is hard to read and understand, that is why I think that JS solution is a better fit. CSS should handle styling of elements, but the logic of how something operates should be handled by JS. That's just my opinion.
– Casper
Mar 27 at 11:10
1
1
@Casper that is a good point! I think you're right. If another developer looks into my code, it would not be clear how this is working. Thanks for pointing this out.
– Josef Biehler
Mar 27 at 12:53
@Casper that is a good point! I think you're right. If another developer looks into my code, it would not be clear how this is working. Thanks for pointing this out.
– Josef Biehler
Mar 27 at 12:53
I am glad I helped :)
– Casper
Mar 27 at 12:57
I am glad I helped :)
– Casper
Mar 27 at 12:57
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55372942%2fhow-long-does-it-take-until-click-event-is-triggered%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
i don't think it is a delay after the click but rather you need to mouse out after the click??? or so it seems for me
– Paddy Hallihan
Mar 27 at 9:01
@PaddyHallihan Yes, I need to mouse out to force the
hover
selector to not be applied anymore. For this I introduced the second solution. By using a transition withstep-end
I am ensuring that the dropdown is "moved" away from the user's mouse position, forcing thehover
to be disabled. But when this happens too early, the click seems not to touch the result items, otherwise the item's value should be rendered below theouter
div. I am not sure about the exact process here. It is only a assumption by me. Maybe someone knows in depth what is happening here.– Josef Biehler
Mar 27 at 9:10
4
The time for a click event to trigger should be really short. It's impossible to say exactly how short because it depend on the computing power, browser and other factors. Therefore a design that depends on timings like this is bad in my opinion and should be avoided if possible. It is as asking for problems. A javascript solution based on event handlers would be much more reliable and easy to implement. Not sure if it can be accomplished with css.
– Mark Baijens
Mar 27 at 9:22