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 thehoverselector to not be applied anymore. For this I introduced the second solution. By using a transition withstep-endI am ensuring that the dropdown is "moved" away from the user's mouse position, forcing thehoverto 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 theouterdiv. 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 thehoverselector to not be applied anymore. For this I introduced the second solution. By using a transition withstep-endI am ensuring that the dropdown is "moved" away from the user's mouse position, forcing thehoverto 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 theouterdiv. 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 thehoverselector to not be applied anymore. For this I introduced the second solution. By using a transition withstep-endI am ensuring that the dropdown is "moved" away from the user's mouse position, forcing thehoverto 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 theouterdiv. 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
divs inside the#resultswrapper - Case 2 - clicking outside the input field, but not on one of the
divs inside the#resultswrapper
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) <<.
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 usingonfocusevent 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
Usingonfocusor:focus-withinin CSS both deal with thefocusof 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
divs inside the#resultswrapper - Case 2 - clicking outside the input field, but not on one of the
divs inside the#resultswrapper
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) <<.
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 usingonfocusevent 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
Usingonfocusor:focus-withinin CSS both deal with thefocusof 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
divs inside the#resultswrapper - Case 2 - clicking outside the input field, but not on one of the
divs inside the#resultswrapper
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) <<.
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 usingonfocusevent 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
Usingonfocusor:focus-withinin CSS both deal with thefocusof 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
divs inside the#resultswrapper - Case 2 - clicking outside the input field, but not on one of the
divs inside the#resultswrapper
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) <<.
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#resultswrapper - Case 2 - clicking outside the input field, but not on one of the
divs inside the#resultswrapper
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) <<.
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 usingonfocusevent 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
Usingonfocusor:focus-withinin CSS both deal with thefocusof 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 usingonfocusevent 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
Usingonfocusor:focus-withinin CSS both deal with thefocusof 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
hoverselector to not be applied anymore. For this I introduced the second solution. By using a transition withstep-endI am ensuring that the dropdown is "moved" away from the user's mouse position, forcing thehoverto 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 theouterdiv. 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