jQuery problem with blur event


		// 1) Hide the dropdown if we lose focus
		$t.blur(function () {
			setTimeout(function () {
				$("#" + newid + " select").hide();
			}, 500);
		});
		
		// 2) Put the text in the box if we chose an options
		$("#" + newid + " select").change(function () {
			$t.val($(this).val());
			$(this).hide();
		});

$t is a reference to an input element I am working on. Code fragment #1 assigns a blur event to the input so that when focus is removed away from it, the corresponding select dropdown is hidden.

The 2nd fragment of code sets the value of the input to the value selected in the dropdown when it changes. And then it hides the dropdown.

The problem is that I have had to use this setTimeout function otherwise a race condition occurs. The reason for this is that when an element is chosen in the dropdown, the blur event is triggered before the change event. Therefore the code within the change event is never executed. The only way I could find around this was to use the setTimeout.

My question is, how can I solve this issue more elegantly.

That behaviour sounds very rough.

The dropdown disappears as soon as you select something from it, with no apparant way to reveal the dropdown again.
And as well, soon as you leave the textbox, the dropdown disappears again.

How can selecting an option from a dropdown list trigger an input box blur event?

I think that we’ll need to see the appropriate html form code as well.

Hi Paul,

Thanks for the quick reply. The idea is that when you select the input, the dropdown appears. You can then choose an option, and the dropdown disappears, placing its value in the input. To view the dropdown again you just focus on the input field. It’s the same behaviour as google calendar uses when creating the time for an event.

Here is an expanded portion of JS code:


		// 1) Show the dropdown if it's focused
		$t.focus(function () {
			$("#" + newid + " select").show();
		});
		
		// 2) Hide the dropdown if we lose focus
		$t.blur(function () {
			//setTimeout(function () {
				$("#" + newid + " select").hide();
			//}, 500);
		});
		
		// 3) Put the text in the box if we chose an options
		$("#" + newid + " select").change(function () {
			//$t.focus();
			$t.val($(this).val());
			$(this).hide();
		});

I’ve posted the whole code fragment here as not to spam the forums. It’s mostly irrelevent as none of the other code is interfering with the important bits I’ve posted.
http://pastebin.com/mfb41136

Stage 1 shows the dropdown. Stage 2 should hide it if focus is lost on the input. Stage 3 will hide the dropdown and put its value in the input. Usage is $(“#elementid”).timepicker()

Pretty bog standard stuff. Yet, this problem is occurring :slight_smile:

Is this the issue? Where the input field blur event is being triggered, when you change a select option?

If so, the HTML code will be kind of important too.

Please consider, how can any of us attempt to simulate the problem that you are facing on our own machines?

Hi Paul,

Okay here is a test case:
http://pastebin.com/m3f2e6a64

You should be able to run this directly on your machine :slight_smile: And yes, the issue is that the blur event is over-riding the change event on the select. Simply add an alert to the change event and you’ll see it’s never called. By adding the setTimeout as illustrated in my first post, it “fixes” the issue, but it’s not elegant and I’m sure it’s not the correct solution to my problem.

Dean

It seems that settimeout is mandetory, especially to resolve a google chrome onchange bug.

See: http://www.weeklywhinge.com/?p=19

I don’t think that’s the issue. Try changing the setTimeout to 5 instead of 250, and you’ll see it doesn’t fix the problem. 250 is the value I settled at for the “fix”, but I’m sure this is a different bug.

Since a hidden element cannot receive events, I think you would be better off taking tighter control over the hiding of the element.

What about using the change function of the menu, to hide itself? And using the blur event of the other element to call the change event on the menu? This would still work properly and close the menu even if someone didn’t make a selection in the menu, instead clicking somewhere else on the screen, or tabbing out.


$t.blur(function () {
    $("#" + newid + " select").change();
});

$("#" + newid + " select").change(function () {
        $t.val($(this).val());
        $(this).hide();
});

It’s kinda interesting that different browsers behave a lot different here. If you log the order in which those functions get called when clicking an option in the menu:

opera:
change
blur
change

firefox:
change
blur

ie:
change
change
blur

edit—this makes chrome crash :confused:

Thanks for your reply. It doesn’t make chrome crash for me (anymore) :slight_smile: I’ve open-sourced and published the code, so let’s see if it’s of use to anyone and if they have any issues :wink:

http://code.google.com/p/jquerytimepicker/

Edit: I take it back, I changed the code after applying your fix and quickly realised I had removed the blur event, which doesn’t close the dropdown when a user clicks out.