How to hide a dropdown when a user clicks on it

The following is a simplified version of the input drop-down I am working with.

The main summary of what he does is: if you focus on typing, a drop-down list will appear. If you select one of the options from the drop-down list, the option will fill in the input and the drop-down menu will disappear. This is achieved using onfocus and the functions that I called dropdown(); and undropdown(); .

I have a dilemma when I cannot make the drop-down list disappear when someone clicks elsewhere. If I use onblur , it successfully hides the drop-down list, but if you click on the parameter, it will not fill the input, this is because the onblur function onblur launched first, and therefore the input(); function input(); doesn’t start because the dropdown menu is already hidden.

If you put the onclick tag in the body tag or another parent element, it treats onfocus as a click, where it runs the dropdown(); function dropdown(); , and then the undropdown(); function undropdown(); , so the drop-down menu never appears overlapping functions.

I would appreciate help in figuring out how to arrange the functions so that they execute in the correct order without overlapping each other.

JSFiddle is available here.

 function input(pos) { var dropdown = document.getElementsByClassName('drop'); var li = dropdown[0].getElementsByTagName("li"); document.getElementsByTagName('input')[0].value = li[pos].innerHTML; undropdown(0); } function dropdown(pos) { document.getElementsByClassName('content')[pos].style.display = "block" } function undropdown(pos) { document.getElementsByClassName('content')[pos].style.display = "none"; } 
 .drop { position: relative; display: inline-block; vertical-align: top; overflow: visible; } .content { display: none; list-style-type: none; border: 1px solid #000; padding: 0; margin: 0; position: absolute; z-index: 2; width: 100%; max-height: 190px; overflow-y: scroll; } .content li { padding: 12px 16px; display: block; margin: 0; } 
 <div class="drop"> <input type="text" name="class" placeholder="Class" onfocus="dropdown(0)"/> <ul class="content"> <li onclick="input(0)">Option 1</li> <li onclick="input(1)">Option 2</li> <li onclick="input(2)">Option 3</li> <li onclick="input(3)">Option 4</li> </ul> </div> 

PS: In addition to the above problem, I would appreciate a change to get a better name for this question, so that someone experiencing a similar problem could find it more easily.

+6
source share
2 answers

In this case, On onblur you can call a function that instantly starts undropdown(0); after a very small setTimeout. For instance:

 function set() { setTimeout(function(){ undropdown(0); }, 100); } 

HTML

 <input type="text" name="class" placeholder="Class" onfocus="dropdown(0)" onblur="set()" /> 

No other changes are required.

 function input(pos) { var dropdown = document.getElementsByClassName('drop'); var li = dropdown[0].getElementsByTagName("li"); document.getElementsByTagName('input')[0].value = li[pos].innerHTML; undropdown(0); } function dropdown(pos) { document.getElementsByClassName('content')[pos].style.display= "block" } function undropdown(pos) { document.getElementsByClassName('content')[pos].style.display= "none"; } function set() { setTimeout(function(){ undropdown(0); }, 100); } 
  .drop { position: relative; display: inline-block; vertical-align:top; overflow: visible; } .content { display: none; list-style-type: none; border: 1px solid #000; padding: 0; margin: 0; position: absolute; z-index: 2; width: 100%; max-height: 190px; overflow-y: scroll; } .content li { padding: 12px 16px; display: block; margin: 0; } 
  <div class="drop"> <input type="text" name="class" placeholder="Class" onfocus="dropdown(0)" onblur="set()" /> <ul class="content"> <li onclick="input(0)">Option 1</li> <li onclick="input(1)">Option 2</li> <li onclick="input(2)">Option 3</li> <li onclick="input(3)">Option 4</li> </ul> </div> 
+3
source

You can make a drop-down menu with tabindex , and in the blur event input listener, hide only the drop-down menu if the focus is not in the drop-down list (see When onblur, how can I find out which element is focused on?

 <ul class="content" tabindex="-1"></ul> 
 input.addEventListener('blur', function(e) { if(!e.relatedTarget || !e.relatedTarget.classList.contains('content')) { undropdown(0); } }); 

 function input(e) { var dropdown = document.getElementsByClassName('drop'); var li = dropdown[0].getElementsByTagName("li"); document.getElementsByTagName('input')[0].value = e.target.textContent; undropdown(0); } [].forEach.call(document.getElementsByTagName('li'), function(el) { el.addEventListener('click', input); }); function dropdown(pos) { document.getElementsByClassName('content')[pos].style.display = "block" } function undropdown(pos) { document.getElementsByClassName('content')[pos].style.display = "none"; } var input = document.getElementsByTagName('input')[0]; input.addEventListener('focus', function(e) { dropdown(0); }); input.addEventListener('blur', function(e) { if(!e.relatedTarget || !e.relatedTarget.classList.contains('content')) { undropdown(0); } }); 
 .drop { position: relative; display: inline-block; vertical-align: top; overflow: visible; } .content { display: none; list-style-type: none; border: 1px solid #000; padding: 0; margin: 0; position: absolute; z-index: 2; width: 100%; max-height: 190px; overflow-y: scroll; outline: none; } .content li { padding: 12px 16px; display: block; margin: 0; } 
 <div class="drop"> <input type="text" name="class" placeholder="Class" /> <ul class="content" tabindex="-1"> <li>Option 1</li> <li>Option 2</li> <li>Option 3</li> <li>Option 4</li> </ul> </div> 
+1
source

Source: https://habr.com/ru/post/1012998/


All Articles