Did html spec require focus fire after mousedown? - html

Or it's just every browser happen to implement same behaviour? Only place I found in spec is in click event section which says
If the event target is focusable, the default action MUST be to give that element document focus.
But actually focus is the default action of mousedown event, which is widely used in today's frontend development, so I'd like to know why

Isn't the answer in the very quote you've posted?
If the event target is focusable, the default action MUST be to give that element document focus.
And then https://www.w3.org/TR/uievents/#event-type-focus
4.2.4.2. focus
...
A user agent MUST dispatch this event when an event target receives focus.
In other words: the spec indeed requires focus event to be fired when and if an element receives focus
By the way, the focus as event and focus as a property - is two different things.
But!.. The quote is actually from click event, not from mousedown
And if you test it in browsers you'll see that:
They behave differently (at least mine Chrome 81 and FF 75).
If you click inside <textarea>, but move out an only then release the button Chrome won't send click to the <textarea>, but FF will
But they give focus to <textarea> and fire focus event right after mousedown.
So that probably means, that:
No the spec doesn't require focus event to be fired after mousedown. (Instead it requires it to be fired after click)
Yes it's just so happens that every browser (well... at least those two I've tested) implement same non-standard behavior

So far the only thing I found in spec is
Many implementations use the mousedown event to begin a variety of contextually dependent default actions. These default actions can be prevented if this event is canceled. Some of these default actions could include: beginning a drag/drop interaction with an image or link, starting text selection, etc. Additionally, some implementations provide a mouse-driven panning feature that is activated when the middle mouse button is pressed at the time the mousedown event is dispatched.
Although it didn't explicitly says focus, I guess it's still enough evidence

Related

How can I monitor focus events in Chrome?

I'm trying to track which element gets focus in a web app. I came across the monitorEvents API, but I'm having difficulty using it for control or focus events. Other events on body are working as expected, but not the control events. Any advice?
I'm not sure how exactly you want to "monitor" control events, but you can set event listener breakpoints on the entire category, or individual events like focus. Whenever a focus listener runs for any node on the page, DevTools pauses on the first line of the listener.
I was trying to monitor focus and blur events on the entire document today.
When using monitorEvents(document.body, 'control') I would only see the event fired when I left the tab entirely and then refocused. I believe what's happening is that once you're focused on the body, it'll never change when you focus on child elements since the listener is at a high level and the events just bubble up to the body with no change in focus.
I tried monitoring events on a few specific child elements and saw that those triggered how I expected. So I decided to add an event listener to each element in the document and that worked well. Here's the one-liner for that.
document.querySelectorAll("*").forEach((el)=> monitorEvents(el, 'control'))

dragexit vs dragleave - which should be used?

The HTML Drag and Drop API defines two very similar events, dragleave and dragexit, which along with dragenter are intended to help track the current drop target.
A quick search didn't turn up any current and clear documentation of the two events, when one should be used over another, and the browser support, so I thought I'd ask here.
I'll share the resources I found so far:
The HTML specification has detailed description of when each event is supposed to be fired, but it requires some deciphering.
The MDN docs (HTML Drag and Drop API and individual dragexit/dragleave pages) are not much of a help, saying "The dragexit event is fired when an element is no longer the drag operation's immediate selection target." / "The dragleave event is fired when a dragged element or text selection leaves a valid drop target." and providing no information about browser support for dragexit (as of 2017-03)
Dottoro's dragexit docs (another of the top Google hits) seems out of date, claiming that "The dragexit event is obsolete in Firefox from version 3.5. Use the ondragleave event instead."
Mozilla's bug 619703 and W3C bug 11568 referenced there shed some light on the history of these two events:
Looks like Gecko/Firefox initially implemented dragexit while IE at least implemented dragleave, the major difference being the order of events: dragexit fires before corresponding dragenter, while dragleave, confusingly, fires after.
The HTML5 spec initially only defined dragleave with IE semantics, but later (~2013) added dragexit with Mozilla's semantics.
Gecko appears to have implemented dragleave in Firefox 3.5 (2009), originally synonymous with dragexit, but later (4.0, ~2011?) changing it to match the spec.
caniuse indicates that the HTML DnD API is more-or-less supported across modern browsers, but does not say anything about dragexit specifically
I have taken code sample from MDN and ran it on Chrome 57.0.2987.110 and Firefox 52.0.2.
Firefox event sequence is
dragexit
dragleave
drop
But Chrome never fired dragexit event.
Chrome event sequence is
dragleave
drop
Further analysis on dragexit event, I found out in Wikipedia that it's part of Mozilla XUL events which says:
In addition to the common/W3C events, Mozilla defined a set of events that work only with XUL elements
In case you need code snippets, here it is dragexit and dragleave event snippet from plunkr.
document.addEventListener("dragexit", function(event) {
console.log(event.type);
// reset the transparency
event.target.style.opacity = "";
}, false);
document.addEventListener("dragleave", function(event) {
console.log(event.type);
// reset background of potential drop target when the draggable element leaves it
if (event.target.className == "dropzone") {
event.target.style.background = "";
}
}, false);
There is an interesting tutorial that shows that DnD API can be fully implemented without using the dragexit event which is not fully supported by all browsers. Your safe bet is to use the dragleave event instead that is well supported by all major browsers.
The MDN web documents you cite are indeed correct. Dragexit is when a dragging and the cursor is "outside of the selected target", whereas Dragleave fires when dragging and the cursor "leaves."
If you drag your cursor slowly, then it goes is displacing pixel-by-pixel (i.e. a straight line): i.e., your cursor might be at position 500x500, 500x501, 500x502, etc.. If you drag your cursor fast, it might displace by multiple pixels: i.e., your cursor might be at position 500x500, then at 500x510, then at 500x520.
If your cursor moves outside of the element and doesn't touch the boundary of the element, then the DragLeave event will not fire, but the DragExit event will fire. For this reason, I usually just bind both events to the same handler, to get the absolute outcome.
Works for me on Chrome (v. 103.0.5060.134). To test, try dragging and dropping really fast, as that is the only way to produce the error of DragLeave not firing when you actually leave the element. But to be clear, drag and drop in HTML isn't something that I would consider stable across all browsers. (After all, what's your top 5 favorite sites that use drag and drop with their elements? Can you even think of 1?)

Spark Button trapping keydown (spaceBar) event

Update: Apparently this is part of the accessibility scheme of Flex Spark Components
Button control Press the Spacebar to activate the Button control. To cancel activating a button, press the Tab key to move the focus off
the Button control before releasing the Spacebar.
I guess it can be turned off through compiler directives: Accessibility best practices
Question: Is there any reason a Spark Button would trap key events, in particular a "spacebar" key event?
Background: I've inherited and am maintaining a large legacy project done in Flex 4.6. I am seeing a weird behavior with a Spark Button. Essentially, once the button has been clicked on (i.e. given focus) a keyEvent (spaceBar) will trigger the click event handler attached to the button.
Weird, right?
The button is defined in MXML (below) within an MX:Module. The module has key event listeners attached to the stage but the event handlers for those do nothing with the button:
this.stage.addEventListener(KeyboardEvent.KEY_DOWN, echoKeyDownHandler);
this.stage.addEventListener(KeyboardEvent.KEY_UP, echoKeyUpHandler);
If I put a trace statement in the button's event handler to check the event type when this weird behavior occurs, the type is reported as a click. I don't see anything in the docs for the Spark Button about capturing key events like this.
<s:Button id="toggleBtn"
label="Editor"
click="toggleBtn_clickHandler(event)"
x="943" y="8"/>
This is quite normal with Flex. You should also be able to navigate through the interactive elements by using the <tab> key. <space> usually acts like a click. You could try to avoid this by either
a) set the focus to another object after pressing the button
or
b) by checking the keyboardPressed property.
Both is a bit hacky imho. I am not sure if it is possible to turn of keyboard navigation completely in Flex.
[edit 1] I am just thinking if it wouldn't help to simply overwrite the default keyboard handler like this:
override protected function keyDownHandler(evt:KeyboardEvent):void {}
this is inherited by UIComponent. and you would need to create an own component extending s:Button. A little drawback...
[edit 2] I wasn't able to stop thinking about that, even I stopped using Flex 2-3 years ago. So I googled a bit and found this stack overflow post:
How to disable default browser navigation with Space in Flex

Opting out of `dragenter` and `dragover` events (html5)

I have a collection of draggable "content" elements, and a root-level "feedback" UI element which is displayed above them to provide feedback during drag and drop.
The problem is, during the drag operation, hovering over the "feedback" element causes the dragenter and dragover events to be fired on that element, rather than the underlying content element. It effectively "blocks" the dragenter event from firing on the correct element.
Is there a way for an element to cancel, or "opt out" of a dragenter/dragover event? I could display the feedback element underneath the content, but I'd rather not do that.
jsFiddle: http://jsfiddle.net/jact8/1/
I'm using the HTML drag/drop API, not jQuery or anything like that.
I've created a new fiddle. I think you want to use currentTarget instead of target in your handler on the columns to ensure that the event you receive is from the element you added the listener to (column) rather than the element it originated from (italicised text). See explanation here (it's for ActionScript but I believe it's valid for JavaScript also).
I'm assuming the listener on the insertionCaret element is for debug purposes only and have removed it (let me know if I'm mistaken here). You won't receive the event if you don't listen for it so won't need to opt out of it!

Actionscript UIScrollbar and Click Event on containing Element

I'm creating a game in Flash CS5.5, basically a version of "Who wants to be a millionaire?".
I have an answerDisplay Class which contains an answer text. Answer texts can become rather long, and since I have limited screen space I check for very long texts and if a text is too big I add a UIScrollbar besides the text field.
Which works nicely, except for one thing - when the user drags the scroll tab, the text scrolls fine. When the user clicks one of the scrollbar arrows the text field also scrolls fine, as long as the button is clicked, but as soon as the mouse button is released the click event of the containing answerDisplay class is fired, which leads to my program wrongly thinking the user had selected the answer while he just tried to scroll.
I tried catching this via e.target and/or e.currenttarget, but it's no use, I never get a reference to the scrollbar, so I'm never sure if the user clicked one of the arrows or if he genuinely clicked the answer to select it.
How can I make certain that the click event of my answerDisplay Class is not fired when the UIScrollbar is used?
Checking e.target and e.currentTarget is a good start.
You might also want to check the event phase:
For more details on event phase, check grapefrukt's answer
A click from the answerDisplay Class dispatched event should have AT_TARGET phase, while the UIScrollbar event should have the BUBBLING_PHASE. This should help you differentiate between the two.
Also, you could add event listener to the UIScrollbar in your answerDisplay Class to capture the event and then suppress it via stopPropagation().
Depending on how UIScrollbar uses event bubbles internally, you can try either stopPropagation(), either stopImmediatePropagation(). The goal is to stop the event bubbling up from answerDisplay, but not breaking the UIScrollbar functionality.