Bug Tracker

Opened 12 years ago

Closed 12 years ago

Last modified 11 years ago

#8157 closed bug (fixed)

Focusing an already focused text field will prevent the change event from firing in IE

Reported by: scottgonzalez Owned by: dmethvin
Priority: blocker Milestone: 1.7
Component: event Version: 1.5
Keywords: 1.7-discuss Cc:
Blocked by: Blocking:

Description (last modified by ajpiano)

If a text field is being edited and it programmatically receives focus while already focused, the change event will not be fired in IE (if no additional changes are made after the field is focused again).

Test case: http://jsbin.com/ukihu5/2/edit

According to the pull request for jQuery UI, this was introduced in 1.4.3 and is caused by jQuery.event.special.change.filters.

Related jQuery UI bug: http://bugs.jqueryui.com/ticket/6694

Change History (20)

comment:1 Changed 12 years ago by jitter

Component: unfiledevent

comment:2 Changed 12 years ago by jitter

Priority: undecidedhigh
Status: newopen

comment:3 Changed 12 years ago by john

Priority: highblocker

comment:4 Changed 12 years ago by john

Keywords: 1.7-discuss added

Nominating ticket for 1.7 discussion.

comment:5 Changed 12 years ago by Rick Waldron

Description: modified (diff)

+1, Could be coupled with an "oninput" normalization

comment:6 Changed 12 years ago by jaubourg

-1, I think there's something I don't understand here... the value didn't change yet we expect a change event?

comment:7 Changed 12 years ago by timmywil

+1, confirmed

comment:8 in reply to:  6 Changed 12 years ago by scottgonzalez

Description: modified (diff)

Replying to jaubourg:

-1, I think there's something I don't understand here... the value didn't change yet we expect a change event?

focus the field, change the value, programmatically focus the field again, blur the field; there should be a change event, but there's not.

comment:9 Changed 12 years ago by dmethvin

+1, Seems like we should fix it but not sure why it's on the feature list.

comment:10 Changed 12 years ago by john

Description: modified (diff)

+1, Oof, would be good to get resolved. Not it!

comment:11 Changed 12 years ago by scottgonzalez

+1

comment:12 Changed 12 years ago by ajpiano

Description: modified (diff)

+1

comment:13 Changed 12 years ago by dmethvin

Milestone: 1.next1.7
Owner: set to dmethvin
Status: openassigned

comment:14 Changed 12 years ago by dmethvin

For some reason JSBin isn't working at all for me. Here's the test in jsFiddle:

http://jsfiddle.net/dmethvin/vn4kX/

If I change this line

  $( "input" ).focus();

to this

  $( "input" )[0].focus();

the problem goes away. One difference is that the jQuery .focus() tries to bubble a focus event up the DOM tree (as it does with *all* events, native or non-native). The W3C says focus and blur events are not supposed to bubble (but focusin and focusout should instead). I wonder if we should just run the DOM .focus() method *only* and let the browser sort out the rest.

comment:15 Changed 12 years ago by scottgonzalez

The problem comes from from jQuery.event.special.change.filters.focus being the same as the beforeactivate filter. If the focus filter simply checked to see if the target is the activeElement and bailed if it was, that'd probably fix this.

Last edited 12 years ago by scottgonzalez (previous) (diff)

comment:16 Changed 12 years ago by dmethvin

My concern is this:

http://jsfiddle.net/dmethvin/MW6B2/

If the element is already focused, the native DOM .focus() method doesn't re-fire a focus event. It is effectively a no-op; no handlers are run.

For the same case, jQuery .focus() runs any directly attached handler for the element (even though the native method would not), bubbles a focus event up the tree (but focus is not supposed to bubble) firing attached handlers even on non-form elements (not supposed to do that either), then runs the native DOM .focus() method if nobody called preventDefault(). The focus event is not supposed to be cancelable but our process does add the ability to cancel (*only*) a programmatic focus on a blurred element from a jQuery handler since we run the handlers first, rather than afterwards.

Other than that we're doing *exactly* the same thing as the browser. :-)

I agree that workaround should fix this particular issue, but the reason the issue exists is because we force-fired a focus event on the element when the native DOM method does not.

Do we want to do all those other things in the jQuery .focus() method?

comment:17 Changed 12 years ago by scottgonzalez

If you want to fix the focus event, then shouldn't you fix all events? And if you did that, wouldn't you break a large amount of existing user code?

I thought we've already discussed the possibility of doing events properly and decided it was either too much of a breaking change or too much work.

comment:18 Changed 12 years ago by dmethvin

The focus/blur events are unusual in that they don't bubble but they spawn focusin/focusout counterparts that do bubble. Calling the native method a second time in a row has no effect at all, unlike click.

jQuery .focus() doesn't get any of those three things right because it simply uses the .trigger("focus") behavior which isn't appropriate. There are differences in other events but nothing quite so much as this.

wouldn't you break a large amount of existing user code?

At least for this case, $el[0].focus() works perfectly when $el.focus() does not, and it mirrors the event behavior you'd see in user input focusing. I think it would match what people already expect $el.focus() does.

If there were situations where people expected $el.focus() programmatic behavior to be different than user input behavior (for example, handlers run even when re-focusing focused elements and a focus event bubbles to document) then yep it would be a breaking change.

Let me drop in a fix to address this specific bug in 1.6.3 and we'll talk about the rest later. Unless you just want to use $el[0].focus() for now.

comment:19 Changed 12 years ago by scottgonzalez

As long as the fix doesn't change the behavior of $el.triggerHandler( "focus" ) then I don't have anything against a proper fix for focus.

comment:20 Changed 12 years ago by dmethvin

Resolution: fixed
Status: assignedclosed

I think this closes this particular saga of the missing change event. I've landed a completely new set of code for IE change detection, let's hope there aren't too many new bugs.

https://github.com/jquery/jquery/commit/3bd7bed340f9077d39734ffce366ef2caeb9ce35

Note: See TracTickets for help on using tickets.