[ 8 posts ]

Craig Phillips

  • Username: iwonbigbro
  • Joined: Tue Feb 01, 2011 3:50 am
  • Posts: 32
  • Location: United Kingdom
  • Offline
  • Profile

event-facade-dom.js - Something not quite right.

Post Posted: Tue Aug 14, 2012 6:41 am
+0-
I'll start by referring you to this elaborate comment about keyCode and charCode across different browsers. If you wouldn't mind reading it before reading what I have to say, so that we are on the same page. :-)

http://yuilibrary.com/yui/docs/api/files/event_js_event-facade-dom.js.html#l102

So the problem: The event facade will always have a 'which' property and it is always set to something, either 'which' native value, 'charCode' or 'keyCode'. The problem here is that in FF, the keypress event triggers when special keys are pressed, whereas other browsers omit this event for special keys. However, FF distinguishes between special keys and normal key strokes by setting the 'which' property to zero:

if (0 === evt.which) {
// A special key
return true;
}

However, the DOM event facade overrides this:

this.which = e.which || e.charCode || c;

This means that in a keypress event handler, you cannot determine what type of key stroke was entered, unless you look at the native event:

evt._event.which === 0;

For example, if I press 'Home' the keypress handler needs to allow it in order for the input control to reposition the cursor at 'home'. The problem is, evt.which is set to keyCode, which is set to a value of 36. So the easiest thing to do would be to allow keyCodes of 36 right? Let's do that...

So now I have a rule that says I can only type special characters, such as 'Page Up', and numeric character codes. However, I can still enter a '$' into the field, because the keyCode is 36, the same as 'Page Up'. Ordinarily, FF sets the 'charCode' and 'which' properties to zero when the 'Page Up' key is pressed, so it's easy to identify. But because the event facade replaces the zero value with 'keyCode' or 'charCode', which ever is set, spotting the special 'Page Up' key is only possible through the native event.

Ideally, the event facade should implicitly permit all special chars (where evt.which is zero), and supress calls to keypress event handlers, to bring the keypress events to some consistent closure across all browsers. That, or synthetically generate keypress events with the 'which' property set to zero for non-FF browsers, using the keydown event as a hook.

I have created a small jsfiddle example that demonstrates the issue when tried in multiple browsers.

http://jsfiddle.net/3ggNG/6/

Craig Phillips

  • Username: iwonbigbro
  • Joined: Tue Feb 01, 2011 3:50 am
  • Posts: 32
  • Location: United Kingdom
  • Offline
  • Profile

Re: event-facade-dom.js - Something not quite right.

Post Posted: Tue Aug 14, 2012 6:47 am
+0-
Ah, nearly forgot. One thing to note with the jsfiddle example, is that it implements the YUI 'feature' / 'bug', by overriding the 'which' state. This is fine if you can refer to the Native 'charCode' value. But what this doesn't allow is the passing of the 'ENTER' key. The enter key is considered by FF to be special in that 'charCode' is set to zero. However, it is also considered a legitimate character in that the 'which' property is set to 13. Since IE and Chrome receive the ENTER key in their keypress events, this is somewhat consistent. But relying on the YUI wrapped value of 'which' makes it impossible to identify, given that 'charCode' in the jsfiddle example is zero for enter and 'which' is 13, but the same said for 'Page Up' where 'which' is 36 and 'charCode' remains at zero.

Craig Phillips

  • Username: iwonbigbro
  • Joined: Tue Feb 01, 2011 3:50 am
  • Posts: 32
  • Location: United Kingdom
  • Offline
  • Profile
Tags:

Re: event-facade-dom.js - Something not quite right.

Post Posted: Wed Aug 15, 2012 2:21 am
+0-
I have measures in place for being able to fix various outstanding YUI issues, so I thought I'd see if I could use that to create a dynamic pluggable hotfix for this. Seems to work okay. I have created a jsfiddle example of how I have been able to fix this issue in the interim, but it would be advantageous to see something more robust and permanent, make its way into the YUI code base.

http://jsfiddle.net/7VNye/8/

The example basically shows how the Native behaviour is different across a variety of browsers. In IE and Chrome, the Native text box does not trigger kepress events for keys such as backspace, page-up, home, end, but at the same time allows them to provide their default behaviour. But Firefox or other Mozilla variants however, do issue keypress events for ALL keys, including these special keys, thus you see the keypress handler update the input field value with the keyCode. But the Fixed field, you will notice, filters out these events, making a consistent multi-browser event system for the keypress event.

Juan Ignacio Dopazo

YUI Contributor

  • Username: jdopazo
  • Joined: Fri Oct 02, 2009 5:39 am
  • Posts: 620
  • Location: Buenos Aires, Argentina
  • Twitter: juandopazo
  • GitHub: juandopazo
  • Gists: juandopazo
  • Offline
  • Profile

Re: event-facade-dom.js - Something not quite right.

Post Posted: Wed Aug 15, 2012 5:05 am
+0-
You should definitely file an issue and include all this information there. :)

Luke Smith

YUI Contributor

  • Username: lsmith
  • Joined: Thu Aug 28, 2008 7:50 am
  • Posts: 511
  • Location: Sunnyvale
  • Twitter: ls_n
  • GitHub: lsmith
  • Gists: lsmith
  • IRC: ls_n
  • YUI Developer
  • Offline
  • Profile

Re: event-facade-dom.js - Something not quite right.

Post Posted: Wed Aug 15, 2012 11:27 am
+0-
As the author of said elaborate comment, thanks for the extra info! I didn't know about FF's use of which to flag special characters (except enter). Do you know if this is specified anywhere? Changing the event system is best done to bring it into alignment with spec, if that's possible.

It seems the root of the problem you're describing is that when keyCode, charCode, and which are all set to the same value, collisions can occur, such as 36 for Page Up and $, with no way to tell the difference? You point out that the `which` property on the (browser inconsistent) keypress event was used as a flag to differentiate in (at least?) FF. Couldn't e.shiftKey also be used?

Wouldn't you agree that there is a third option to your two (1. suppress keypress, and d. synthesize one), which is 3. make no change?

Browsers have been divergent about key events, especially non-charCode keys, for a few years now. While suppressing keypress would bring browsers into better alignment, removing native functionality is always tough to justify. You can argue that setting `which` is effectively removing native functionality, of course. All this makes me wonder what the larger objective is, and would it be better solved a different way, such as relying on keydown or keyup.

Bottom line, though, Juan is right. This is good info for a ticket for sure! The specific approach of modifying the CustomEvent.prototype might be a bit broad brushed, though, since that will impact just about everything in YUI.

Craig Phillips

  • Username: iwonbigbro
  • Joined: Tue Feb 01, 2011 3:50 am
  • Posts: 32
  • Location: United Kingdom
  • Offline
  • Profile

Re: event-facade-dom.js - Something not quite right.

Post Posted: Thu Aug 16, 2012 10:14 am
+0-
Broad brushed indeed. It's the fix I have opted for in the interim, loading a bolt on module through metadata triggers. Seems to work for the browsers we support at least: Chrome, IE (7,8,9,10), FF (All versions).

I did read a really interesting article on the subject, which did include more browsers in it's research, such as Safari. It is one that shed light on how Mozilla overload the use of 'which', which is really intended for mouse clicks (which button).

http://unixpapa.com/js/key.html

Mozilla documentation about the which property is vague. It suggests that it is set to either the keyCode or charCode, depending whether a unicode character can be formed from the key combination. It doesn't indicated it will ever be zero. The doc on charCode however, says that charCode will be zero if keyCode is set and vice-versa, based on the same principle that a unicode character can be formed. It also suggests there is some complicated locale specific code that determines the charCode, so I'd say it's not simple to implement a synthetic keypress from a keydown.

https://developer.mozilla.org/en-US/docs/DOM/event.which

Also, I had thought about the Shift Key flag idea, but it doesn't really tell you anything about what happened. If you press Shift + PageUp the keyCode is still 33 as is '!', and obviously the shift key is depressed when constructing a '!'. You would still need to know whether a unicode character was pressed or not.

What I have understood from this experience and what I have read on the topic, is that most people would expect the browser not to issue a keypress event for a non-printing key, since keypress events are typically used to record textual key strokes. IE and Chrome can both agree on this, since you only receive the Enter key, given that it is a printing character when you think of it as '\n'. For example, if you want to validate data entry on a key stroke, you just need to know the character that would appear if your event handler doesn't prevent default. If there is no character, why would you want to know that a key was even pressed? If you wanted to listen to buttons and key combinations, you would most definitely use a keydown event, since that captures all keys pressed and never issues an event containing character codes.

I had thought about the synthesising the keypress for special chars in IE and Chrome, but really thought that there is no point. Natively, these two browsers don't do it, so without YUI you would be hard strapped to receive events for special chars in a keypress.

I have looked at ExtJS and how they deal with the issue, just as another point-of-view. It seems they don't fix the issue or synthesize a keypress event, but what they have done is created a new property on their event that encapsulates meaning across all browsers: isSpecialKey. They have normalized the other fields too, but only after creating this property, based on similar rules, though I fear they may have overlooked the backspace key, for which charCode is zero but which is set. But at least you get some idea in all browser variants, as to whether a special key was pressed or charCode is actually what it says it is, so your event handler can be simplified to:

if (e.isSpecialKey) { return true; }

I think I only provide part of the story given our small browser catalogue, so I do think a more robust solution needs to be developed, but that I will leave up to the YUI team to sort out. I will raise a ticket...

Craig Phillips

  • Username: iwonbigbro
  • Joined: Tue Feb 01, 2011 3:50 am
  • Posts: 32
  • Location: United Kingdom
  • Offline
  • Profile

Re: event-facade-dom.js - Something not quite right.

Post Posted: Thu Aug 16, 2012 10:26 am
+0-
Ticket: http://yuilibrary.com/ticket/?guid=4803bf602490cf733ff4723e05016d07

Luke Smith

YUI Contributor

  • Username: lsmith
  • Joined: Thu Aug 28, 2008 7:50 am
  • Posts: 511
  • Location: Sunnyvale
  • Twitter: ls_n
  • GitHub: lsmith
  • Gists: lsmith
  • IRC: ls_n
  • YUI Developer
  • Offline
  • Profile

Re: event-facade-dom.js - Something not quite right.

Post Posted: Thu Aug 16, 2012 12:40 pm
+0-
Thanks!
  [ 8 posts ]
Display posts from previous:  Sort by  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum