Javascript newbie - it seems that the onBlur of one element "overrides" the onclick of another

I have two elements:

<input type="text" name="pmTo" id="pmTo" onkeyup="offerSuggs('none');" onfocus="showSelect();" onblur="hideSelect();" /> 

and dynamically created (this is all part of the automatic suggestion program):

 $suggString .= '<div name="'.$value.'" id="'.$value.'" class="suggMouseOver" onmouseover="highlightDivs(this);" onmouseout="blurDivs(this);" onclick="fillInput(this);">'.$value.'</div>'; 

Ok, and then there are event functions that match the onblur of the input element, and then the onclick of the div element:

 function hideSelect() { offerSuggs('checkFinal'); document.getElementById('nameSugg').style.display="none"; } function fillInput(elemName) { document.getElementById('pmTo').value=elemName.id; } 

EDIT: How to get onclick to properly launch the element they click on without the onblur event hiding the div, which makes onclick pointless? However, I would still like to keep the proposal rejection functionality when the text box loses focus. Thanks.

+3
javascript javascript-events onclick onblur
source share
2 answers

I think you are not responding because your question is confused. Presumably, you have an input that, when focused, displays a list of sentences based on the characters entered in the input.

If the user uses the cursor to select an item, then I assume that the input blur event fires before the div and div click events to display: none before clicking the arrow and, therefore, skips things.

The fix is ​​to call the onblur listener after a short timeout, therefore:

  <input ... onblur="setTimeout(function(){hideSelect();}, 100);"> 

Test in multiple browsers, you may need to set a timeout of up to 200 ms or so. It does not matter if there is a short visible delay after the blur event until the sentences disappear (i.e., a bit too long is better than too short).

Make sure the offers do not hide anything important on the page, or users can find more obstacles than help. :-)

+6
source share

The accepted answer will work as a quick fix, but relying on setTimeout , you assume that the user will continue to click down less than n milliseconds before they release (just look, someone hesitates on a click). To be sure that the click passes, you can set a longer timeout, but this means that your hidden element will remain visible, which is much more after blurring.

So, let's look at the root of the problem.

A click event that did not pass is the result of events being triggered in the following order:

  • mousedown
  • blur
  • mouseup
  • click

So, by the time the mouseup / click events are ready to fire, the blur listener was called, and the element that you once hung has already disappeared.

Here's a general fix (based on the mousedown event being fired first) that should work:

 var searchEl = $('#search'); var listEl = $('#dropdown'); var keepListOpen = false; searchEl .on('focus', function() { listEl.show(); }) .on('blur', function() { // Hide the list if the blur was triggered by anything other than // one of the list items if (!keepListOpen) { listEl.hide(); } }); listEl.find('li') .on('mousedown', function(event) { // Keep the list open so the onClick handler can fire keepListOpen = true; }) .on('click', function(event) { // Proof that the list item was clicked alert('clicked option'); }); $(window).on('mouseup', function(event) { // Return the keepListOpen setting to its default and hide the list // *NOTE* We could have tied this handler to the list items, // but it wouldn't have fired if a mousedown happened on a // list item and then the user dragged the mouse pointer // out of the area (or out of the window) if (keepListOpen) { listEl.hide(); keepListOpen = false; } }); // Bind to `window.top` if your page might be displayed in an iframe // $(window.top).on('mouseup', function(event) { // if (keepListOpen) { // listEl.hide(); // keepListOpen = false; // } //}); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <input id="search" type="text" placeholder="Click Here"> <ul id="dropdown" style="display: none;"> <li>Click Me 1</li> <li>Click Me 2</li> <li>Click Me 3</li> </ul> 
+1
source share

All Articles