Bug Tracker

Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#11806 closed bug (wontfix)

IE7 preventDefault() doesn't prevent F5 keydown causing browser Refresh

Reported by: jeffr@… Owned by:
Priority: undecided Milestone: None
Component: unfiled Version: 1.7.2
Keywords: Cc:
Blocked by: Blocking:

Description

jQuery works as expected on IE9, Chrome, and other more modern browsers. On IE7, however, the F5 key doesn't get "canceled" via preventDefault() (nor by stopPropagation() nor returning false from the event handler.)

$(window).load(function() {
                 $(document).ready(function() {                     $(document).bind('keydown', function(e) {                         if (e.keyCode == 116) {                             e.preventDefault();
.
.
.

On all tested browsers, the 'e.preventDefault()' gets called. But only by adding this hack:

e.originalEvent.keyCode = 0;

was I able to supress the F5 browser refresh on IE7.

I've seen several references on the web to the keyCode assignment hack, but I don't know why it works or if it is "correct". However, as it stands right now, jQuery's normalization fails for this special case on IE7.

Change History (13)

comment:1 Changed 7 years ago by jeffr@…

<!DOCTYPE html>

<html lang="en">

    <head> 

        <meta charset="utf-8" />

        <title>Frame 1b</title>

        <script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js'></script>        

        <script type='text/javascript'>//<![CDATA[

            $(window).load(function() {

                $(document).ready(function() { 

                    $(document).bind('keydown', function(e) {

                        if (e.keyCode == 116) {

                            e.preventDefault();
                            e.originalEvent.keyCode = 0;

                        }

                        $('#output1').val(String.fromCharCode(e.keyCode));
                    });

                });

            });//]]> 

        </script>

    </head> 

    <body> 

        frame1 

        <textarea id="output1"></textarea>   

    </body> 

</html>

comment:2 Changed 7 years ago by Rick Waldron

Function key behaviour is not going to be consistent across browsers and systems, eg. I'm on OSX in Chrome - F5 is not "refresh the browser".

Not confirmed. http://jsfiddle.net/rwaldron/Fq7rH/show/light

comment:3 Changed 7 years ago by jeffr@…

Here's a jsfiddle to see what I mean: http://jsfiddle.net/SMDcX/2/

I'm not expecting consistent function key behavior, but I am hoping we can make "event normalization" work consistently on IE7. Which, I believe, means some kind of hack like setting event.keyCode = 0.

comment:4 Changed 7 years ago by dmethvin

Resolution: wontfix
Status: newclosed

This seems sufficiently exceptional to justify a wontfix. Just add some of your own code to do this, we don't need to handle every corner case.

comment:5 Changed 7 years ago by jeffr@…

I've been singing the praises of jQuery to my dev team. One of the things I told them was that jQuery nicely normalized events. cf. http://api.jquery.com/category/events/event-object/

Which includes this:

event.preventDefault()

If this method is called, the default action of the event will not be triggered.

But this apparently isn't true on IE7, if the event is a key<down,press,up> event.

I guess I'm surprised to find out that this is considered a corner case. I thought jQuery was meant to allow me to NOT to have to know all the darned quirks of older browsers.

Is there a list of things not normalized that will help us know where jQuery does normalize things and where it does not?

comment:6 Changed 7 years ago by dmethvin

jQuery can't hide everything. IE7 has been around quite a while, I've been with the jQuery project since 2006, and I've never heard of anyone ask about this. So it is indeed a rare requirement.

This closed ticket can serve as a note that we're not normalizing this, it's too obscure to add to the documentation.

comment:7 Changed 7 years ago by jeffr@…

I understand the basis for your decision. Thanks for clarifying.

The search function on the ticket system is handy and there aren't that many corner cases mentioned as such. And all seem IE-related.

Thanks for responding and thanks for the excellent work on jQuery!

comment:8 Changed 7 years ago by Rick Waldron

How do you expect to "normalize" something that doesn't even exist on all machines? jQuery "normalizes" where disparity exists, not where actual, physical constraints exist eg. my F5 doesn't do "refresh", are you saying that jQuery should normalize OSX???

comment:9 Changed 7 years ago by jeffr@…

My example is confusing -- I apologize.

ANY keydown (or keypress, or keyup) event, as far as I understand it, is supposed to have its default processing prevented via a call to

event.preventDefault()

IE7 doesn't seem to do what Microsoft documents, and despite jQuery's correct efforts to "prevent" the event from bubbling (via IE7's proprietary "cancelBubble" and "returnValue"), the keys really do "bubble".

I don't want certain keys to "bubble" up. On IE9, Chrome,and1 Android, jQuery's event.preventDefault() works beautifully.

On IE7, despite correct efforts, it doesn't work.

Again, I chose F5 as that was the keydown I was testing with. The point wasn't to imply that jQuery should normalize the behavior of F5.

The point was that jQuery ought to do one more "IE special" so that, on IE7, the function event.preventDefault() works as documented.

To summarize: I was hoping jQuery would make event.preventDefault() work properly on key events on IE7.

I don't own a Mac, but I'm assuming that jQuery's event.preventDefault() already works fine for you -- I was just asking for it to be made to work fine on IE7. But, understandably, jQuery can't be responsible for smoothing over every nook and cranny of older browsers like IE7.

comment:10 Changed 7 years ago by Rick Waldron

According to the DOM 2 Event spec, there is no specified behaviour that Key Events abide: http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-keyevents

It's likely that IE7 is using DOM2 or worse...

So what should we normalize to?

comment:11 Changed 7 years ago by jeffr@…

jQuery has IE-specific code in order to implement the normalized

event.preventDefault()

What is it trying to do in that code? I've been assuming that it is trying to implement the DOM3 standard despite the shaky underpinnings that IE7 provides.

I would have thought that the goal is to make event.preventDefault() work.

No?

If not, why have the function at all?

If the goal is to make it work, then shouldn't the IE7 implementation of event.preventDefault() actually PREVENT the default behavior, by "canceling" the key event? It already has code to do just that! That code ought to work. But, for keys, apparently, it does not work. Based on numerous web postings, the undocumented hack for IE7 is to assign a different value into event.keyCode when the goal is to supress the default action of a given key.

Anway, jQuery already has code that's trying to implement preventDefault() for IE. Whoever wrote it presumably had some goal as to what he or she was trying to normalize to. If their goal was to support capturing a given key event, then the current jQuery implementation (via originalEvent.cancelBubble and originalEvent.returnValue) is inadequate on IE7.

Perhaps rather than asking me to define how event.preventDefault() should work on key events in IE7, you could tell me what you think preventDefault() ought to do on IE7?

// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
	preventDefault: function() {
		this.isDefaultPrevented = returnTrue;

		var e = this.originalEvent;
		if ( !e ) {
			return;
		}

		// if preventDefault exists run it on the original event
		if ( e.preventDefault ) {
			e.preventDefault();

		// otherwise set the returnValue property of the original event to false '''(IE)'''
		} else {
			e.returnValue = false;
		}
	},

comment:12 Changed 7 years ago by dmethvin

For the 99% case, you're right. the .preventDefault() is preventing the default action. But you've found a corner case where it doesn't, and the workaround of clobbering the event.keycode is probably not preventing the default action--it is most likely confusing the code that it bubbles to in a way that stops it from recognizing the keystroke.

It would be a bunch of extra code and complexity for us to implement inside jQuery--is this an F5 (or is it just F5), is this IE7 (or is it just IE7), did you preventDefault, should we clobber the keycode, will later handlers added by other code (potentially plugins or other code you didn't write) see the correct keystroke or the clobbered one? Coding and testing all of that takes time, and adds bytes that every jQuery user must download regardless of whether they need them or not.

Again, this is for a rare corner case on an old browser with declining market share that nobody has reported before. We're a bunch of volunteers and this is called bug triage precisely because some bugs cannot be effectively treated given our time and other tradeoffs so we have to leave them unfixed.

I'd think that for your case it's pretty straightforward to know you want to detect an F5 and stop it from refreshing, so a workaround should work pretty well. In the context of your application it is possible for you to know by context whether the workaround has negative implications. That isn't something easy for us to generalize in a way that avoids other negative consequences that would engender more bug reports.

comment:13 Changed 7 years ago by jeffr@…

I completely understand your reasoning and agree with you. I have no idea how or why the keycode hack works, and definitely wouldn't want to waste anyone's time potentially gumming up lots of straightforward code paths in order to solve this corner case!

This discussion helped me understand the context and challenges of an ambitious project like yours much better, and I hope you didn't mind me pressing the point in order to achieve a better understanding.

jQuery is an excellent tool and I really appreciate how well it accomplishes its mission.

Note: See TracTickets for help on using tickets.