ariatemplates/ariatemplates — pull request #71 by juliandescottes (2012-07-14 17:40:11+00:00)
Title: aria:Button onclick callback triggered twice on FF when using SPACE

Hi,

Disclaimer : couldn't check the behavior on IE, no windows computer available here ...

Problem
------------
There is a small bug with the aria:Button widget. When the focus is on the button and user presses SPACE or ENTER, the onclick callback of the button is triggered.
However, on Firefox (3.6 to 12), when using SPACE, the callback is triggered twice !

You can quickly check this using this kind of template :

{Template {
$classpath:'TestButton'
}}
{macro main()}
{@aria:Button {
label: "Test",
onclick: {fn: function() {console.log('button clicked');}, scope: this}
}/}
{/macro}
{/Template}

Investigation
-------------------
This comes from the fact that SPACE and ENTER trigger events in a different order : http://help.dottoro.com/ljxevnps.php. I'm trying to find something in the specs about this, but no luck so far.

When pressing SPACE :
keydown -> keyup -> click

When pressing ENTER :
keydown -> click -> keyup

On Chrome/Safari, the _performAction of the button is only triggered by keyup or mouseup, so no conflict here. However, on Firefox, there is a flag _keyPressed which is used to avoid calling _performAction twice.

If we look at what happens when pressing ENTER on Firefox :
* keydown : _keyPressed -> true
* click : _keyPressed is set to true, skip _performAction
* keyup : _keyPressed -> false + call _performAction

But for SPACE :
* keydown : _keyPressed -> true
* keyup : _keyPressed -> false + call _performAction
* click : _keyPressed is false, call _performAction AGAIN

Proposed solution
--------------------------
1) One easy solution here would be to make all browsers use the same approach as for Chrome/Safari : trigger _performAction only on keyup and mouseup.

2) Another solution is that since onclick is always triggered in the event sequence after pressing SPACE or ENTER, we could only rely on onclick for calling _performAction. This seems also more logical : rely on the click event to trigger the onclick callback !

3) If there is a real crossbrowser issue here in using the same implementation for all browser, we can implement solution 2 only for FF/IE/Opera

I don't know why we would need to have different code running on Chrome/Safari here, and IMO best solution is solution 2, so it's what I implemented here.

Cheers,
Julian