Bug Tracker

Opened 8 years ago

Closed 8 years ago

Last modified 7 years ago

#7891 closed bug (invalid)

jQuery.blur() and focus() don't behave as expected, behave differently than HTMLInputElement.blur() and focus()

Reported by: jmm Owned by:
Priority: undecided Milestone: 1.6
Component: unfiled Version: 1.4.4
Keywords: Cc:
Blocked by: Blocking:

Description

I'm having problems where jQuery.blur() and focus() are not producing the expected effect, and not producing the same effect as HTMLInputElement.blur() and focus().

I brought this up on the forum first to try to confirm it's a bug, but I received no feedback:

http://forum.jquery.com/topic/jquery-blur-not-producing-intended-effect-same-effect-as-dom-blur-in-firefox

I) Blur

I have a text INPUT. When the INPUT has focus and the enter key is pressed, I want to blur the INPUT and if the change event fires I want to handle that and perform some actions. I want to blur the field even if the value hasn't changed and the change event doesn't fire, so I'm handling keydown to detect the enter key and calling jQuery.blur() in the keydown handler, which I expect to blur the INPUT and possibly make the change event fire. But it's not working as expected.

Example 1:

http://jsfiddle.net/feXRh/1/

Instructions:

1) Type something in the text box then tab or click out of it to blur it.

2) Focus the INPUT again, change the text, and press enter.

Expected results:

1) Name and Blurs values should update.

2a) Name and Blurs values should update.

2b) INPUT should blur.

Actual results:

  • Firefox 3.6.13 Win XP Home SP3 = #2a fails
  • Safari 5.0.3 Win XP Home SP3 = #2a fails
  • Opera 11.00 Win XP Home SP3 = works

Example 2:

http://jsfiddle.net/feXRh/2/

Instructions:

Same as #1.

Expected results:

Same as #1.

Actual results:

  • Firefox 3.6.13 Win XP Home SP3 = works
  • Safari 5.0.3 Win XP Home SP3 = works
  • Opera 11.00 Win XP Home SP3 = works

The only difference is that instead of calling jQuery.blur() I'm calling the DOM HTMLInputElement.blur() method directly.

Example 3:

http://jsfiddle.net/feXRh/3/

Instructions:

Same as #1.

Expected results:

Unknown.

Actual results (see expected results for #1):

  • Firefox 3.6.13 Win XP Home SP3 = #2b fails
  • Safari 5.0.3 Win XP Home SP3 = #2b fails
  • Opera 11.00 Win XP Home SP3 = #2b fails

If I call jQuery.blur(), then event.preventDefault() in the blur handler, then the change event fires in Firefox and Safari, but the INPUT isn't blurred.

Example 4:

http://jsfiddle.net/feXRh/4/

Instructions:

Same as #1.

Expected results:

Unknown.

Actual results (see expected results for #1):

  • Firefox 3.6.13 Win XP Home SP3 = works
  • Safari 5.0.3 Win XP Home SP3 = works
  • Opera 11.00 Win XP Home SP3 = works

If I call HTMLInputElement.blur(), then event.preventDefault() in the blur handler, then the change event fires in Firefox and Safari, and the INPUT is blurred (just like example 2 where event.preventDefault() wasn't called):

II) Focus

I'm experiencing a similar problem with jQuery.focus().

Example 1:

http://jsfiddle.net/a7Yks/1/

Instructions:

1) Open the testcase.

2) jsfiddle steals focus after loading the page, so click "Run".

Expected results:

1) The blur handler for radio button "One" should execute, resulting in it not having the 'focused' class and having a transparent background.

Actual results:

  • Firefox 3.6.13 Win XP Home SP3 = fails
  • Safari 5.0.3 Win XP Home SP3 = fails
  • Opera 11.00 Win XP Home SP3 = fails

Example 2:

http://jsfiddle.net/a7Yks/2/

Instructions:

Same as #1.

Expected results:

Same as #1.

Actual results:

  • Firefox 3.6.13 Win XP Home SP3 = works
  • Safari 5.0.3 Win XP Home SP3 = works
  • Opera 11.00 Win XP Home SP3 = works

The only difference is that to focus radio button "Two", I call HTMLInputElement.focus() instead of jQuery.focus().

Change History (8)

comment:1 Changed 8 years ago by danheberden

Possible duplicate of #7768

comment:2 Changed 8 years ago by jmm

I saw bug #7768 before I filed this report and I don't think it has anything to do with this issue.

#7768 complains of 'focus' not firing in WebKit (in response to the 'click' event apparently).

My report is about:

  • 'change' events not firing when programmatically blurring using jQuery.blur(). That happens in WebKit, AND Gecko.
  • 'change' / 'blur' events not firing when programmatically focusing using jQuery.focus(). That happens in WebKit, and Gecko, and Presto.

Conversely, calling HTMLInputElement.blur() / HTMLInputElement.focus() works as expected and doesn't block the 'change' / 'blur' events from firing.

comment:3 Changed 8 years ago by snover

Resolution: invalid
Status: newclosed

Thanks for the report, but this is not a jQuery bug, just a confusing quirk of the hell that is HTML forms.

The blur and focus methods on an HTMLInputElement are action methods that call code that actively change the state of the DOM element. The blur and focus methods in jQuery, however, are just event dispatchers. They perform two completely different functions.

For example, a focus event is normally dispatched after an element is focused—this is why, for instance, you cannot prevent an element from focusing by calling preventDefault from inside a focus event. You can still dispatch a focus event whenever you want, but it will never actually focus the element, because that’s not what a focus event does. Maybe it should, but that’s a discussion for the spec authors, not jQuery.

comment:4 Changed 8 years ago by jmm

Replying to snover:

The blur and focus methods in jQuery, however, are just event dispatchers. They perform two completely different functions.

That's not consistent with the documented or actual behavior of jQuery.blur() and jQuery.focus(). See:

  • Last example here ("Example: To focus on a login input box with id 'login' on page startup, try:"):

http://api.jquery.com/focus/

You can still dispatch a focus event whenever you want, but it will never actually focus the element, because that's not what a focus event does.

jQuery.focus() actually focuses the element. In the versions of Firefox, Safari, and Opera I listed previously, the INPUT is focused in the testcase above (64AFS).

Have you even looked at the testcases from my original report? In the focus testcase it's not even in question that jQuery.focus() actually focuses the target element, the issue is that it prevents 'blur' and 'change' events from firing on the element that is blurred when focus() is called.

comment:5 Changed 7 years ago by jmm

The "blur example 1" and "focus example 1" testcases still fail to behave as expected in Firefox 7 Win, but work as expected when updated to jQuery 1.5.2 (the next version after 1.4.4 available on jsfiddle), so obviously something was wrong with 1.4.4 and it was changed by 1.5.2.

Blur example

Original (1.4.4)

http://jsfiddle.net/feXRh/1/

Updated (1.5.2)

http://jsfiddle.net/feXRh/41/

Focus example

This one had to be updated slightly, since jsfiddle now does something with focus that makes it impossible to run the original testcase. The "click Run" part of the original instructions referred to jsfiddle's Run button. That no longer works. It's now necessary to click the "Run test" link in the output panel, but it otherwise performs as before with jQuery 1.4.4.

Original (1.4.4)

http://jsfiddle.net/a7Yks/11/

Updated (1.5.2)

http://jsfiddle.net/a7Yks/12/

comment:6 Changed 7 years ago by dmethvin

The test case itself is somewhat complex, so before I start to investigate can you update to jQuery-git (or at least jQuery 1.7.2) to see if anything has changed, and give a clear explanation of the behavior you expected vs the behavior you observed? Be sure to explain which browsers you used for testing.

comment:7 Changed 7 years ago by jmm

Thanks for your reply. To be clear, this does not work as expected in 1.4.4, but does work as expected in 1.5.2 and 1.7.2 (and perhaps everything in between) -- at least in Firefox (I haven't retested all of the browsers I did originally). So whatever was wrong in 1.4.4 was changed by 1.5.2, despite my report getting short shrift and marked as invalid.

But since the report was marked invalid, who knows what happened, e.g. if it was even fixed deliberately, or accidentally.

If you're going to investigate (perhaps to make sure there are tests for whatever the problem was so it doesn't reoccur?), I will provide whatever you need.

Blur Example #1 from the original report would illustrate the problem and has a test case with only 2 steps to reproduce (I did it today in Firefox 7 Win), and includes expected and actual results. But if that isn't something you can work with, I'll make a new test case and / or description that is as clear and minimal as I can.

Basically, if you try blur example #1 and follow the 2 steps to reproduce, when you press Enter at the end of step 2, the "Name:" and "Blurs:" parts of the output should both update. In 1.4.4, only the "Blurs:" part does. jQuery.blur() prevents the change event from firing on the INPUT. If I instead call DOM HTMLInputElement.blur() or use jQuery 1.5.2, it works as expected.

If you're going to investigate, I will create a new test case / description if you want.

Thanks

comment:8 Changed 7 years ago by dmethvin

The only version we support at the moment is the latest one, so if 1.7.2 works fine then all we have to do is avoid breaking it in 1.8. :)

Note: See TracTickets for help on using tickets.