This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 12949 - click() shouldn't have special powers over dispatching click event manually
Summary: click() shouldn't have special powers over dispatching click event manually
Status: RESOLVED WONTFIX
Alias: None
Product: HTML WG
Classification: Unclassified
Component: LC1 HTML5 spec (show other bugs)
Version: unspecified
Hardware: PC Linux
: P2 normal
Target Milestone: ---
Assignee: Ian 'Hixie' Hickson
QA Contact: HTML WG Bugzilla archive list
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-06-13 23:25 UTC by Olli Pettay
Modified: 2011-09-21 23:01 UTC (History)
9 users (show)

See Also:


Attachments
testcase (698 bytes, text/html)
2011-06-15 13:45 UTC, Olli Pettay
Details

Description Olli Pettay 2011-06-13 23:25:54 UTC
Right now the spec says that click() may cause the default action
to happen, but dispatching click manually doesn't have the same
effect.
I don't understand why. Gecko and webkit (if I read the webkit code correctly),
for example, seem to just dispatch click event when click() is called.
Default handling is bound to the elements in the event target chain through
which the event is dispatched. Default handling happens right after the event
has propagated through the chain.

Gecko has one special case for input.click() but I see that as a bug.

I see click() as a leftover from Netscape2/3/IE3 times, or as a 
helper method to dispatch untrusted click event.

(It is however clear that not all default handling should be
processed when handling untrusted event. Both click() and manual dispatching
do dispatch untrusted events.)
Comment 1 Jonas Sicking (Not reading bugmail) 2011-06-14 01:02:35 UTC
It's IMHO very strange that we take action in response to events being fired for a few events in Gecko.

Almost exclusively it works the other way around, events are fired in response to some action being taken.

Unless the web depends on it, this is something that I really think we should make consistent in Gecko (and webkit).
Comment 2 Olli Pettay 2011-06-14 11:05:09 UTC
Jonas, your comments was a response to
"(It is however clear that not all default handling should be
processed when handling untrusted event. Both click() and manual dispatching
do dispatch untrusted events.)" right?
If so, I'll file a followup bug about that.

In this bug I'm more worried about the click() handling being
different from dispatching click event manually without no reason.
Comment 3 Jonas Sicking (Not reading bugmail) 2011-06-15 02:53:47 UTC
Ok, so smaug pointed out to me that for calling click() firefox generally doesn't actually activate most elements, which at least for <a>.click() appears to be the case. (though <input type=file>.click() does bring up a file picker, but I think that's an exception).

The thing that I care most about is that the spec doesn't say that dispatching an event using the EventTarget interface should run what is usually that events default action. But if that's not what the spec says then I'm fine.
Comment 4 Olli Pettay 2011-06-15 10:13:47 UTC
(In reply to comment #3)
> (though <input type=file>.click() does bring up a file picker,
> but I think that's an exception).
And that is a recently added exception, which should be fixed to 
work like other event handling.
Comment 5 Olli Pettay 2011-06-15 13:45:19 UTC
Created attachment 997 [details]
testcase

This shows that default handling is done during event dispatch.
The testcase should work on Gecko, Webkit, Opera and IE9 and all
change the state of the checkbox.
Comment 6 Olli Pettay 2011-06-15 13:49:04 UTC
So the way activation behavior is defined in HTML is just wrong - 
well at least it doesn't reflect the reality.
Or I'm reading the spec wrong.
Anyway, click() doesn't work differently to dispatching click manually.

There can be differences in default handling, but that is a separate thing.

In Gecko, and I think in Webkit too, and based on the testcase also
other browsers there is
1. event target chain creation
2. pre-handle-event phase
3. actual dom event dispatch
4. post-handle-event phase, including default handling
Comment 7 Jonas Sicking (Not reading bugmail) 2011-06-16 17:12:50 UTC
I really don't think that dispatching an event manually should trigger default handling. For the vast majority of events that doesn't make any sense (onload for example) and for many others it doesn't work (onmousemove doesn't trigger :hover).

So we should really try to get rid of this broken behavior from gecko. Of course, if that ends up breaking too many sites we'll have to reevaluate, but we should at least try.
Comment 8 Olli Pettay 2011-06-16 17:41:34 UTC
load event doesn't have default handling.

I don't understand why HTML needs to specify something against all the
implementations.
Comment 9 Olli Pettay 2011-06-16 17:47:32 UTC
And if we want to change how all the browser work, we certainly should not
change click() handling, but add some new method activate() which would work
the new way.
Comment 10 Olli Pettay 2011-06-16 17:48:39 UTC
...though, the change to event handling and not changing click() would
break even more :/

I wish the spec would just specify the reality.
Comment 11 Olli Pettay 2011-06-16 18:50:02 UTC
Also, DOM 3 Events, at least the way I read, associate
default actions to events, and the default action may happen when
event is dispatched.
Comment 12 Jan Varga 2011-07-02 13:54:35 UTC
some info:
http://lists.w3.org/Archives/Public/public-html-diffs/2009Jun/0167.html

see the commit message:
Fold command.click() into the regular HTMLElement.click().
Comment 13 Jan Varga 2011-07-02 14:02:23 UTC
http://krijnhoetmer.nl/irc-logs/whatwg/20090723

"anyway, the idea was for DOM3Events to define activation behavior and various related thingies, but bjoern never got around to it so now it's defined in HTML5"
Comment 14 Jan Varga 2011-07-02 15:13:59 UTC
I think that "Firing a synthetic click event at the element does not cause any of the actions described above to happen." only applies to the <command> element.
Comment 15 Jan Varga 2011-07-03 09:37:17 UTC
(In reply to comment #6)
> So the way activation behavior is defined in HTML is just wrong - 
> well at least it doesn't reflect the reality.
> Or I'm reading the spec wrong.
> Anyway, click() doesn't work differently to dispatching click manually.
> 
> There can be differences in default handling, but that is a separate thing.
> 
> In Gecko, and I think in Webkit too, and based on the testcase also
> other browsers there is
> 1. event target chain creation
> 2. pre-handle-event phase
> 3. actual dom event dispatch
> 4. post-handle-event phase, including default handling

I think that pre-handle-event phase corresponds to "pre-click activation steps".
post-handle-event-phase runs "post-click activation steps" or "canceled activation steps" (at least for nsHTMLInputElement)

http://www.w3.org/TR/DOM-Level-3-Events/ - 3.5 Activation triggers and behavior) says it's up to host language to indicate which elements have activation behavior.

http://www.whatwg.org/specs/web-apps/current-work/ - 4.10.7.1.16 Checkbox state
"If the element is mutable, then: The pre-click activation steps consist of setting the element's checkedness to its opposite value (i.e. true if it is false, false if it is true), and of setting the element's indeterminate IDL attribute to false. The canceled activation steps consist of setting the checkedness and the element's indeterminate IDL attribute back to the values they had before the pre-click activation steps were run. The activation behavior is to fire a simple event that bubbles named change at the element."

that's exactly what nsHTMLInputElement does

however, the HTML5 spec adds command definitions and "enhance" element.click() in a way, I found out that there use to be a Command IDL interface:

interface Command {
  readonly attribute DOMString commandType;          
  readonly attribute DOMString id;
  readonly attribute DOMString label;
  readonly attribute DOMString title;
  readonly attribute DOMString icon;
  readonly attribute boolean hidden;
  readonly attribute boolean disabled;              
  readonly attribute boolean checked;              
  void click();
  readonly attribute HTMLCollection triggers;
  readonly attribute Command command;
};

you can find more details in the first (SVN) revision of the spec

at that time only <a>, <button>, <input>, <option> and <command> could define a command and command.click() was defined to trigger the action for the command

however, after some time (several years), accesskey="" was added as another possibility to define a command
http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2009-May/019579.html
so now any element can define a command and it is quite logical to merge the Command and HTMLElement IDL interface.

so element.click() got these "special" powers ... to trigger the action for the command

Now when I look at the definition of "Action" in http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#concept-command

4.11.5.1 <a href>
 - fire a click event at the element.

4.11.5.2 <button>
 - fire a click event at the element.

4.11.5.3 <input>
 - if the element has a defined activation behavior, is to run synthetic click activation steps on the element. Otherwise, it is just to fire a click event at the element.

4.11.5.4 <option>
 - If the command is of Type "radio" then it must pick the option element. Otherwise, it must toggle the option element.

4.11.5.5 <command>
 - if the element has a defined activation behavior, is to run synthetic click activation steps on the element. Otherwise, it is just to fire a click event at the element.

4.11.5.6 <label accesskey="">
 - the same as the respective facets of the element's labeled control.

4.11.5.7 <legend accesskey="">
 - similar to the above

4.11.5.8 any element with accesskey=""
1. If the element is focusable, run the focusing steps for the element.
2. If the element has a defined activation behavior, run synthetic click activation steps on the element.
3. Otherwise, if the element does not have a defined activation behavior, fire a click event at the element.


so the definition varies a bit, but:
4.11.5.3 is actually just to fire a click event, because pre-click activation steps will be done in the pre-handle-event phase and post-click activation steps / canceled activation steps will be done in the post-handle-event-phase

this should apply even for synthetic click events, the spec says that it shouldn't apply only for <command> if I'm reading it correctly

4.11.5.4 doesn't fire a click event, I haven't figured out why

4.11.5.6 and 4.11.5.7 are special, they just forward click() to other element

4.11.5.8 just adds the focus step


http://www.w3.org/TR/DOM-Level-3-Events/ also specifies Activation event synthesis (3.5.1)

so a synthetic click event is used to trigger activation and HTML5 says activation id done in click() (8.2 Activation)

I hope, it's now a bit clearer :)
Comment 16 Jan Varga 2011-07-03 10:21:49 UTC
(In reply to comment #3)
> Ok, so smaug pointed out to me that for calling click() firefox generally
> doesn't actually activate most elements, which at least for <a>.click() appears
> to be the case. (though <input type=file>.click() does bring up a file picker,
> but I think that's an exception).
> 
> The thing that I care most about is that the spec doesn't say that dispatching
> an event using the EventTarget interface should run what is usually that events
> default action. But if that's not what the spec says then I'm fine.

actually it seems that only <a>.click() doesn't activate, because the click event is untrusted

http://www.whatwg.org/specs/web-apps/current-work - 4.6.1

now I wonder, how can <a>.click() trigger the command action when it fires untrusted event
Comment 17 Jan Varga 2011-07-03 10:28:10 UTC
(In reply to comment #2)
> Jonas, your comments was a response to
> "(It is however clear that not all default handling should be
> processed when handling untrusted event. Both click() and manual dispatching
> do dispatch untrusted events.)" right?
> If so, I'll file a followup bug about that.
> 
> In this bug I'm more worried about the click() handling being
> different from dispatching click event manually without no reason.

you are right:
http://www.whatwg.org/specs/web-apps/current-work/ - 3.2.5.1.7 Interactive content

"The above doesn't happen for arbitrary synthetic events dispatched by author script. However, the click() method can be used to make it happen programmatically."

it's really confusing
Comment 18 Jan Varga 2011-07-03 11:03:29 UTC
(In reply to comment #16)

> actually it seems that only <a>.click() doesn't activate, because the click
> event is untrusted
> 

well, this was recently fixed in firefox
Comment 19 Jan Varga 2011-07-03 11:34:04 UTC
(In reply to comment #17)
> "The above doesn't happen for arbitrary synthetic events dispatched by author
> script. However, the click() method can be used to make it happen
> programmatically."
> 

this was first introduced in revision 539
http://html5.org/tools/web-apps-tracker?from=538&to=539
and then changed a bit in revision 541
http://html5.org/tools/web-apps-tracker?from=540&to=541
Comment 20 Jan Varga 2011-07-03 16:40:55 UTC
Ok, so it looks to me that element.click() should fire a click event and provide default action (if the click event was not cancelled). Firing a click event manually should not trigger default action according to the spec.

However, all browsers seem to trigger default handling after manual dispatch as Olli pointed out.
Comment 21 Anne 2011-07-05 09:28:40 UTC
From the logic of dispatching events it does not make sense that the event carries the default action. It should be the context that says to dispatch the event:

if(dispatchEvent(event))
  defaultAction()

It makes way more sense the way HTML defines it now.
Comment 22 Olli Pettay 2011-07-05 09:33:08 UTC
(In reply to comment #21)
> From the logic of dispatching events it does not make sense that the event
> carries the default action.
Event doesn't carry the default action.
Default action happens (usually) right after event dispatch, but
before the control is back to the caller.
Comment 23 Anne 2011-07-05 09:40:25 UTC
If an event does not carry a default action, it does not make sense that just firing an event would trigger a default action. And indeed it does not, given the code snippet I pasted in.
Comment 24 Olli Pettay 2011-07-05 09:54:56 UTC
(In reply to comment #23)
> If an event does not carry a default action, it does not make sense that just
> firing an event would trigger a default action.
That still doesn't explain why?
The default action can be bound to the event target, like it is often
in all the current browser engines.
Comment 25 Anne 2011-07-05 10:20:15 UTC
That is not how DOM Level 3 Events describes it: http://www.w3.org/TR/2011/WD-DOM-Level-3-Events-20110531/#event-flow-default-cancel

It also does not seem very logical to me. And what implementations do is not exposed as it generally only applies to trusted events so that does not much matter I think.
Comment 26 Olli Pettay 2011-07-05 11:01:01 UTC
(In reply to comment #25)
>  And what implementations do is not
> exposed as it generally only applies to trusted events so that does not much
> matter I think.
I'm talking about *untrusted* click event for example.
Comment 27 Anne 2011-07-05 11:05:07 UTC
click and submit are the only cases I know of and both have been corrected.
Comment 28 Michael[tm] Smith 2011-08-04 05:03:35 UTC
mass-moved component to LC1
Comment 29 Ian 'Hixie' Hickson 2011-08-10 23:28:34 UTC
EDITOR'S RESPONSE: This is an Editor's Response to your comment. If you are satisfied with this response, please change the state of this bug to CLOSED. If you have additional information and would like the editor to reconsider, please reopen this bug. If you would like to escalate the issue to the full HTML Working Group, please add the TrackerRequest keyword to this bug, and suggest title and text for the tracker issue; or you may create a tracker issue yourself, if you are able to do so. For more details, see this document:
   http://dev.w3.org/html5/decision-policy/decision-policy.html

Status: Rejected
Change Description: no spec change
Rationale: 

As others have said, it is the responsibility of the code (UA or script) that dispatches the event to ensure that a default action, if any, is performed. Indeed, the default action could differ based on how is firing the event. For example, one could have an event target to which one dispatches a "foo" event, and if it isn't canceled, one then pops up an alert... but some other code could instead dispatch a "foo" event, and if it isn't canceled, adds text to a console.

Historically, browsers have had exceptions to this — different exceptions in each browser. But we're moving away from this as a rationalisation of the platform.

Now given this model, we do need a mechanism by which one can invoke the default activation behaviour of an element, e.g. to click a button, open an input file dialog, or whatnot. And that's what click() does.
Comment 30 Olli Pettay 2011-08-11 09:38:59 UTC
Why do you want to move away from something which all the browsers
implement?
Comment 31 Ian 'Hixie' Hickson 2011-08-15 05:00:10 UTC
The premise of your question is false.
Comment 32 Olli Pettay 2011-08-15 07:21:20 UTC
How?
Comment 33 Jonas Sicking (Not reading bugmail) 2011-08-23 00:10:54 UTC
We shouldn't do or don't do something just because it's what browsers do. The first question should always be "what is the best API", *after* that we should ask "would that break the web". The latter question is *informed* by "what do browsers do". But just because browsers don't do something doesn't mean that it breaks the web.

Did Gecko ever get a bug filed on that dispatching "click" events against a link doesn't traverse it? Note that this is a different question to if click() traverses the link.
Comment 34 Olli Pettay 2011-08-23 12:12:49 UTC
(In reply to comment #33)
> Did Gecko ever get a bug filed on that dispatching "click" events against a
> link doesn't traverse it?
Yes.
Comment 35 Jonas Sicking (Not reading bugmail) 2011-09-04 07:33:02 UTC
Apparently we didn't get enough bugs filed that we decided to change our implementation. We only changed our implementation in order to make sure that callers of HTMLAnchorElement.click() got the behavior they expected.

I agree with Anne here. Events are a notification mechanism indicating that "something" just happened. They also carry the ability to stop whoever dispatched the event from taking the action they normally would in response to the "something" that just happened.

There are two problems with letting target.dispatchEvent() cause the default action to take place.

1.
We can't do that for a lot of events with default action since it doesn't really make sense. For example the default action for the "error" event in indexedDB is to cancel the transaction, but there might not be a transaction running if dispatchEvent is used.

And for the app-cache, the default action is to show various UI, but just calling dispatchEvent doesn't provide enough information as to what UI would be displayed. Additionally we probably don't want the page to be able to bring up app-cache UI at will.

And the default action for the "dragstart" event is to initialize a drag'n'drop operation. How would that work if the user isn't currently performing a drag'n'drop action with the mouse (or touch-screen once we have drag'n'drop there).

2.
If .dispatchEvent causes the default action to run, then that creates a weird secondary meta-API which provides largely duplicated functionality. For example if we let the "error" event in indexedDB abort the current transaction if there is one, then that would be duplicated API since transaction.abort() is already available.

And if we make dispatchEvent of a "keydown" event with .char set to " " execute the default action of dispatching a "click" event, then that means that we have two APIs for dispatching "click" events.


In short, events are fired in response to various things happening. They are not a meta-API for causing things to happen.


I'm aware that we've put some of the default action logic in the event-dispatch code in Gecko, but I think that's the wrong design. Feel free to grab me on irc or elsewhere to discuss what a better design should be.
Comment 36 Olli Pettay 2011-09-04 09:57:57 UTC
(In reply to comment #35)
> And if we make dispatchEvent of a "keydown" event with .char set to " " execute
> the default action of dispatching a "click" event, then that means that we have
> two APIs for dispatching "click" events.
dispatching 'return' keypress to links does dispatch a click event as
default handling. (' ' doesn't trigger links in Gecko)

> I'm aware that we've put some of the default action logic in the event-dispatch
> code in Gecko
Not only in Gecko but in all the browser engines.
Comment 37 Olli Pettay 2011-09-04 13:48:10 UTC
(In reply to comment #35)
> For example the default action for the "error" event in
> indexedDB is to cancel the transaction, but there might not be a transaction
> running if dispatchEvent is used.
Script initiated events aren't trusted.
It is easy to spec that  default handling should happen only for trusted events.
Comment 38 Jonas Sicking (Not reading bugmail) 2011-09-06 07:45:56 UTC
That doesn't reduce inconsistency. It'd still be the case that in some cases dispatchEvent executes the default action, in other cases it wouldn't.
Comment 39 Ian 'Hixie' Hickson 2011-09-21 23:01:16 UTC
EDITOR'S RESPONSE: This is an Editor's Response to your comment. If you are satisfied with this response, please change the state of this bug to CLOSED. If you have additional information and would like the editor to reconsider, please reopen this bug. If you would like to escalate the issue to the full HTML Working Group, please add the TrackerRequest keyword to this bug, and suggest title and text for the tracker issue; or you may create a tracker issue yourself, if you are able to do so. For more details, see this document:
   http://dev.w3.org/html5/decision-policy/decision-policy.html

Status: Rejected
Change Description: no spec change
Rationale: I couldn't put it better than comment 35.

Yes, for individual events, there are particular browsers that get it wrong. But those are bugs, that's all. A legacy of a poorly-specified age.