Bug Tracker

Ticket #8157 (closed bug: fixed)

Opened 4 years ago

Last modified 2 years ago

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

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

Description (last modified by ajpiano) (diff)

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

comment:1 Changed 4 years ago by jitter

  • Component changed from unfiled to event

comment:2 Changed 4 years ago by jitter

  • Priority changed from undecided to high
  • Status changed from new to open

comment:3 Changed 3 years ago by john

  • Priority changed from high to blocker

comment:4 Changed 3 years ago by john

  • Keywords 1.7-discuss added

Nominating ticket for 1.7 discussion.

comment:5 Changed 3 years ago by rwaldron

  • Description modified (diff)

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

comment:6 follow-up: ↓ 8 Changed 3 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 3 years ago by timmywil

+1, confirmed

comment:8 in reply to: ↑ 6 Changed 3 years ago by scott.gonzalez

  • 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 3 years ago by dmethvin

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

comment:10 Changed 3 years ago by john

  • Description modified (diff)

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

comment:11 Changed 3 years ago by scott.gonzalez

+1

comment:12 Changed 3 years ago by ajpiano

  • Description modified (diff)

+1

comment:13 Changed 3 years ago by dmethvin

  • Owner set to dmethvin
  • Status changed from open to assigned
  • Milestone changed from 1.next to 1.7

comment:14 Changed 3 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 3 years ago by scott.gonzalez

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 3 years ago by scott.gonzalez (previous) (diff)

comment:16 Changed 3 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 3 years ago by scott.gonzalez

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 3 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 3 years ago by scott.gonzalez

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 3 years ago by dmethvin

  • Status changed from assigned to closed
  • Resolution set to fixed

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.