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;








1















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.










share|improve this question


























  • 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






  • 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

















1















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.










share|improve this question


























  • 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






  • 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













1












1








1








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.










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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





    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











  • @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





    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












2 Answers
2






active

oldest

votes


















1














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 divs inside the #results wrapper

  • Case 2 - clicking outside the input field, but not on one of the divs 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 divs 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) <<.






share|improve this answer



























  • 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


















1














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.






share|improve this answer

























  • 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













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
);



);













draft saved

draft discarded


















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









1














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 divs inside the #results wrapper

  • Case 2 - clicking outside the input field, but not on one of the divs 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 divs 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) <<.






share|improve this answer



























  • 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















1














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 divs inside the #results wrapper

  • Case 2 - clicking outside the input field, but not on one of the divs 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 divs 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) <<.






share|improve this answer



























  • 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













1












1








1







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 divs inside the #results wrapper

  • Case 2 - clicking outside the input field, but not on one of the divs 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 divs 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) <<.






share|improve this answer















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 divs inside the #results wrapper

  • Case 2 - clicking outside the input field, but not on one of the divs 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 divs 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) <<.







share|improve this answer














share|improve this answer



share|improve this answer








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 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

















  • 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
















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













1














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.






share|improve this answer

























  • 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















1














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.






share|improve this answer

























  • 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













1












1








1







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.






share|improve this answer













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.







share|improve this answer












share|improve this answer



share|improve this answer










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

















  • 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

















draft saved

draft discarded
















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript