Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS :active and JS mousedown preventDefault complication #2262

Open
Nadya678 opened this issue Feb 2, 2018 · 16 comments
Open

CSS :active and JS mousedown preventDefault complication #2262

Nadya678 opened this issue Feb 2, 2018 · 16 comments
Labels
selectors-4 Current Work

Comments

@Nadya678
Copy link

Nadya678 commented Feb 2, 2018

Please read this topic. I also observe the problem. FF behaves differently than other browsers but the behaviour looks to be... undefined.

https://stackoverflow.com/questions/11464520/aactive-vs-mousedown-event-preventdefault-ed

Is here any dpec that define it to file a bug to Moz?

There is no way to fire :active from JS, thus I guess the behaviour of IE11 and Cr is correct in that case.

@fantasai
Copy link
Collaborator

fantasai commented Feb 2, 2018

The quoted section of Selectors is intended to connect with this definition in HTML: https://html.spec.whatwg.org/multipage/semantics-other.html#selector-active

Unfortunately, I can't make enough sense of the HTML definition to answer your question about what behavior should happen in the above situation (or if it's even fully defined). Maybe @annevk can help?

@fantasai fantasai added the selectors-4 Current Work label Feb 2, 2018
@annevk
Copy link
Member

annevk commented Feb 3, 2018

I'm not entirely sure I understand that definition either, but the main problem here is with hit testing not being defined, and UI events and selectors not being defined in terms of that. That should all be part of a set of algorithms dealing with user input.

@FremyCompany
Copy link
Contributor

I don't think either browser fail to comply with the definition, I think the actual issue is a difference in handling the 'mousedown' event. In firefox, preventDefault'ing the mousedown event prevents the click event to fire. As such, it cancels the navigation action of the link in Firefox while it does not in Edge and Chrome. From this difference, all else follows.

Just to be clear, here is the definition we are looking at:

If the element is an a element that has an href attribute, [...]
Then the element is being activated if it is in a formal activation state.

An element is said to be in a formal activation state between

  1. the time the user begins to indicate an intent to trigger the element's activation behavior and
  2. either
    1. the time the user stops indicating an intent to trigger the element's activation behavior, or
    2. the time the element's activation behavior has finished running, which ever comes first.

Since calling preventDefault on mousedown does prevent the click event in Firefox, and that the click event is where the activation behavior runs, preventDefault'ing in Firefox does finish the activation behavior (condition 2.2) and then :active stops to apply.

Since calling preventDefault on mousedown does not prevent the click event in Chrome and Edge, it does not cause condition 2.2 to become true, and therefore :active continue to apply.

@FremyCompany
Copy link
Contributor

I spent some time in the Pointer Events and UI Events specs, and I don't see any ground to justify the Firefox's behavior to cancel the 'click' event in case 'preventDefault' has been called on mousedown. I think we should file an issue on them regarding that behavior.

Test case: http://jsfiddle.net/n45k9/112/

@FremyCompany
Copy link
Contributor

@Nadya678
Copy link
Author

Nadya678 commented Feb 4, 2018

6 years and UNCONFIRMED? They should hire illuminati to confirm it.

From my bug report:

nsFileControlFrame::SetFocus hasn't got an implementation
https://bugzilla.mozilla.org/show_bug.cgi?id=1430196

Looks like the events are not implemented globally and are implemented for each control and element separately.

@bzbarsky
Copy link

bzbarsky commented Feb 4, 2018

@FremyCompany you generally want to talk to @smaug---- about event issues. But as I said in the bug you link, the default action of mousedown is to make things active. If you prevent its default action... they don't become active.

The definition of :active is not specific to links (or shouldn't be; lots of other things can become :active), so I'm not sure how a link-specific bit of text is relevant.

In firefox, preventDefault'ing the mousedown event prevents the click event to fire.

What makes you say that, exactly? My testcase at http://jsbin.com/qugizofuhe/edit?html,output shows an alert in Firefox.

@FremyCompany
Copy link
Contributor

FremyCompany commented Feb 4, 2018

Test case http://jsfiddle.net/n45k9/112/ (seems to be specific for links indeed)


The definition of :active is not specific to links (or shouldn't be)

Well, it is. I guess the reason is the past only links used to be :active things, so I'm fairly sure there is a bunch of content that depends on a specific behavior for active on links that might actually be different from other elements.

@bzbarsky
Copy link

bzbarsky commented Feb 4, 2018

Test case http://jsfiddle.net/n45k9/112/ (seems to be specific for links indeed)

That testcase removes the actual target of the event (the textnode) from the DOM onmousedown, so the mousedown and mouseup are happening on different nodes. You're right that Firefox doesn't fire click in that case (for the same reasons that click doesn't get fired if you mouse down on an element then move your mouse outside it before releasing), but that has nothing to do with preventDefault() in any way. That testcase shows the same behavior if the preventDefault() is taken out.

Well, it is.

Ugh. Gecko basically just implements the "If the element is being actively pointed at" bit, and has all along, instead of doing this bizarre per-tag list of different behaviors. Do other UAs actually do the per-tag behaviors, or is this something aspirational Hixie just wrote?

I guess the reason is the past only links used to be :active things

Fwiw, Gecko's current behavior has been in place ever since I recall. I'd bet it's the only :active behavior Gecko ever had. And it's allowed non-links to be :active all along.

In any case, a simple testcase for non-links at http://jsbin.com/sawafonogu/edit?html,output shows that browsers don't even agree on that. And this one should only involve the "actively pointed at" concept. Of course this concept is not defined in terms of events at all, which makes it vague enough that who knows what it means.

@FremyCompany
Copy link
Contributor

FremyCompany commented Feb 4, 2018

That testcase removes the actual target of the event (the textnode) from the DOM onmousedown, so the mousedown and mouseup are happening on different nodes.

Hashtag "When one line of debug code derails you testcase " :)

I wasn't able to find much of a specific behavior for links in Edge (except AREA) but I do see the special behavior for the space key and buttons.

The interop difference between Edge/Chrome and Firefox is shown here:
http://jsbin.com/bavexoneno/edit?html,console,output

Firefox adds "active" as a "default action" of mousedown (hence cancellable), while active is already set before firing mousedown in the other browsers.

@FremyCompany
Copy link
Contributor

FWIW, the processing for ":active" in Edge happens in the input/output message pipeline directly, (way) before event deciding to create a "mousedown" event.

@Nadya678
Copy link
Author

Nadya678 commented Feb 4, 2018

What makes you say that, exactly? My testcase at http://jsbin.com/qugizofuhe/edit?html,output shows an alert in Firefox.

Test 52 ESR version. I see only random numbers. In Chromium 63 two alerts.

I make preventDefaulting (in my commercial sites) on <datalist/>s and <option/>s. The effect: no :active pseudoclass, the :focus on input still present (and preventing blur is OK), I had to use .active class and additionally use mouseup on document to cancel the .active class. In FF the :active is not invoked, In Cr, IE11 and EDGE does.

I think we should clarify the spec that Firefox makes it badly if ALL OTHER browsers makes it identically. I am fan of Moz but if only Moz behaves differently...

@bzbarsky
Copy link

bzbarsky commented Feb 5, 2018

while active is already set before firing mousedown in the other browsers.

Lovely. This is why we need actual specs instead of handwaving. With a processing model, instead of handwaving. ;)

the processing for ":active" in Edge happens in the input/output message pipeline directly

Does it get affected by things like user-select, SVG bits that affect event targeting, etc? I mean, it must at least be happening after the event target is determined, right?

I am not wedded to the current Firefox behavior, and am willing to change it, but not willing to change it twice. Hence it would be good to have a clear spec for what the behavior should be.

Test 52 ESR version. I see only random numbers.

It would help if you were running the actual testcase I linked, which has no random numbers and the behavior I described. Including in ESR52.

@FremyCompany
Copy link
Contributor

FremyCompany commented Feb 5, 2018

the processing for ":active" in Edge happens in the input/output message pipeline directly

Does it get affected by things like user-select, SVG bits that affect event targeting, etc? I mean, it must at least be happening after the event target is determined, right?

Yes, after that indeed.

@Nadya678
Copy link
Author

The requested spec was not found. That's all we know...

I propose the :active should be invoked before (on)mousedown. There also should be specified that before or after touch event.

Why before? There is no JS function to fire :active and then preventDefault the rest.
In contrast to :focus, there are functions to fire focus and blur.

Also the :hover should be invoked before mousemove/mouseenter. The reason the same: no JS function to invoke :hover and preventDefault.

@chriswks
Copy link

Just adding two cents and maybe reinvoke this thread for consideration in spec; but I'd also like to see the presentation layer elements (aka pretty much everything handled first by compositor thread) handling their own events before main thread events.

Primarily because I just spent far more time than I would have liked hunting down this innocuous nuance that none of the other browsers are effected by just to have some nifty UX interactions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
selectors-4 Current Work
Projects
None yet
Development

No branches or pull requests

7 participants
@FremyCompany @fantasai @bzbarsky @annevk @chriswks @Nadya678 and others