[HN Gopher] A BBC navigation bar component broke depending on th...
       ___________________________________________________________________
        
       A BBC navigation bar component broke depending on the external
       monitor
        
       Author : ulrischa
       Score  : 176 points
       Date   : 2024-11-18 15:28 UTC (7 hours ago)
        
 (HTM) web link (www.joshtumath.uk)
 (TXT) w3m dump (www.joshtumath.uk)
        
       | marcellus23 wrote:
       | > All we had to do was change the isInvokedByMouse to check that
       | screenX and screenY don't equal 0, rather than checking if they
       | are greater than 0.
       | 
       | It's obviously extremely unlikely but what if the mouse is
       | actually at 0,0 when the user clicks? I'm not very familiar with
       | JS, is checking for != 0 really the best/only way to do this?
       | 
       | EDIT: actually upon going back, I realized I didn't fully process
       | this sentence originally but it seems to address this:
       | 
       | > We should probably do further refactoring of the event handler
       | function, since it's complicated by the fact that it also handles
       | keydown events. For now, though, this fix will do just fine.
        
         | nightpool wrote:
         | But they're already checking for event.name == 'click' in the
         | revised code. So why would you want to filter _out_ some
         | legitimate click events?
        
           | marcellus23 wrote:
           | Maybe browsers will report `click` events that aren't
           | actually created by a pointer device (maybe a screen reader
           | or something?). But that still raises the question of why you
           | would care. It seems to me like if the platform wants to
           | report it as a `click`, your app should treat it as one and
           | not try to get "clever" about it.
        
             | pornel wrote:
             | For compatibility with the Web content, the `click` event
             | has become a device-independent activation event. Sites
             | can't be expected to listen for events from every kind of
             | device, so instead all devices send `click`s.
             | 
             | They care, because focus for keyboard-controlled screen
             | readers sending "click" should behave differently: an
             | element inside the menu should receive focus, even though
             | it's not the element that has been clicked. Otherwise if
             | focus stayed on top-level menu bar, screen reader users
             | would be lost, and had to navigate to menu's content
             | themselves.
        
               | marcellus23 wrote:
               | Interesting. Seems like something that should be exposed
               | more explicitly.
        
           | kulor wrote:
           | Apply Chesterton's Fence principle and assume there are
           | (hopefully) comments in the real code around why this has
           | been put in place
        
         | whstl wrote:
         | It seems that querying the screen position is just a heuristic
         | they came up with to determine the nature of the event.
         | Instinctively I would use _instance of MouseEvent_ for this,
         | but even this feels risky /hacky to me.
         | 
         | My question is why they're relying on those heuristics. My
         | guess is that _toggleMenu_ is being used by multiple event
         | handlers. Or maybe there 's something else going on that is
         | specific to their codebase.
         | 
         | It's hard to judge without knowing the full picture.
         | 
         | EDIT: Aha, there's an answer here:
         | https://news.ycombinator.com/item?id=42174177
        
         | tomjen3 wrote:
         | No its not. You can do media select on if the primary input
         | device is a pointer device (and, further, if it has high
         | accuracy) and then filter on that.
         | 
         | I used it to select which layout to show in the past.
         | 
         | If you want to listen to input on touch only then you can do
         | that and call preventDefault on the event so that the browser
         | does not then cause a click event. Or you can just save
         | yourself the trouble and write a click handler.
        
       | account42 wrote:
       | Why are websites getting mouse position in screen coordinates in
       | the first place?
        
         | jazzyjackson wrote:
         | If you're reacting to click events, you might want to know the
         | coordinates of where you're clicking. I mostly use this for
         | click and drag stuff since you can get the delta between events
         | and update position of the thing being dragged.
         | 
         | As for why they're checking for coordinates instead of checking
         | for event.type is beyond me. Still I appreciate the write up,
         | it is a good puzzle and relatable to come across code you
         | didn't write and ask, why is it important that the click
         | coordinate is nonzero? Why can't we just check that
         | event.target is the button we want to activate? Why are we
         | using JavaScript at all when a details/summary tag would do the
         | same job?
        
           | yarg wrote:
           | Relative coordinates sure, but why would you need the
           | absolute position?
           | 
           | I'm with you on the second point - as unlikely as it is for
           | the click to occur at the origin, it's still a legitimate
           | value being abused as an indicator of something that might
           | not actually be true - quite frankly the code was bad to
           | begin with, and it was still bad after the fix.
        
         | DCH3416 wrote:
         | Uh. So they can keep track of what the user is doing?
         | 
         | Why would you just send a document when you can generate a heat
         | map of where the user is on your website. And then complain
         | about the performance and wonder why it costs so much to run a
         | modern website.
        
           | Sayrus wrote:
           | The issue isn't so much the coordinate of the mouse within a
           | page, but that the coordinates are relative to the virtual
           | screen layout. It describes where your window is located on
           | the screen(s) and the click is expressed in screen
           | coordinates. Mapping those coordinates to your website's
           | renderer coordinates requires additional calculation.
           | 
           | layerX[1] while non-standard is supported and returns a
           | position relative to the top of the page or the top of the
           | parent element. This makes coordinates positive only and
           | 50,50 is the same for all users. For screenX, 3000,1567 is
           | the same coordinate as 15,37 depending on where the window is
           | located.
           | 
           | [1] https://developer.mozilla.org/en-
           | US/docs/Web/API/MouseEvent/...
        
         | Sayrus wrote:
         | I've searched for reasons and couldn't find much. The fact that
         | a website can know where a browser window is located
         | (window.screenX/window.screenY) and that clicks position can be
         | reported in that coordinate system sounds insane for a desktop.
         | TOR Browser seems to spoof screenX and screenY to avoid
         | fingerprinting.
         | 
         | Has anyone seen good use-cases for that feature? I'm thinking
         | about dual window applications that interacts with each other
         | (I think I saw a demo of something like this a while ago on HN
         | but I wasn't able to find it again), or sites where behavior
         | depends on their location on the virtual screen.
        
           | diggan wrote:
           | The webkit report talks about it
           | (https://bugs.webkit.org/show_bug.cgi?id=281430), while the
           | article doesn't seem to, for some reason. Another HN comment
           | with summary: https://news.ycombinator.com/item?id=42174177
        
           | willwade wrote:
           | Back in html 4 days we did this shenanigans all the time. I
           | worked on very over the top sites that played with multiple
           | windows talking to each other and moving in synchrony. I've
           | tried looking for examples on archive.org (eg I know we did
           | this a ton on flash heavy sites like design museum in London
           | ) but alas the ones I was looking for a broken in that
           | archive.
        
         | Taylor_OD wrote:
         | Haha. Welcome to the world of analytics. Lots of sites are
         | recording exactly what you are doing on their site including
         | mouse movement at all times.
        
         | tshaddox wrote:
         | It's useful for creating games where the graphics are composed
         | of many small browser windows which interact with one another.
         | 
         | For example:
         | 
         | https://youtu.be/3al8prbfK5o?si=loNtyqIfMFkppm5V
        
         | johnisgood wrote:
         | I use it for a JavaScript-free CAPTCHA, works well, but it only
         | sends the x and y of mouse click upon clicking on it.
        
         | nine_k wrote:
         | Because this was easy to do during the 10 days allocated to
         | develop JavaScript in 1995, and then backwards compatibility
         | kicked in :(
        
         | grumple wrote:
         | Well, I used it for bounding box and reading order annotations,
         | but that's a pretty specialized use case.
        
       | chgs wrote:
       | I'm impressed he wrote a blog without having to get authorisation
       | from a dozen layers of bbc management and lawyers.
        
       | nightpool wrote:
       | Why are you filtering for screen coordinates in the first place?
       | What if the user is using e.g. an alternative input device that
       | doesn't have a screen? The `click` event should be enough
       | indication that the user has tried to activate the menu. Why
       | reinvent the wheel?
        
         | codetrotter wrote:
         | > Why are you filtering for screen coordinates in the first
         | place?
         | 
         | FTA:
         | 
         | > The isInvokedByMouse was checking whether the click event was
         | invoked by a mouse or touch pointer - rather than a keyboard -
         | by checking if the screenX or screenY coordinates were a
         | positive number.
         | 
         | They were trying to detect whether it was keyboard or mouse
         | activation, and whoever wrote it assumed that screen
         | coordinates of mouse events would always be positive.
        
           | nightpool wrote:
           | Right, but the article doesn't explain _why_ they cared
           | whether it was keyboard or mouse activation. The linked
           | WebKit bug goes into more detail, but it 's still lacking an
           | explanation of why alternative, more common and widely
           | deployed strategies (like having a capturing keyup event that
           | triggers earlier in the render loop) wouldn't be a better
           | idea instead.
           | 
           | Also, if you _really_ want to determine whether a MouseEvent
           | is  "real" or "synthetic", and you don't want to worry about
           | when mouse events are triggered relative to keyboard events
           | in the event loop (although it doesn't seem very hard to keep
           | track of), it seems like you can use the current click count
           | (i.e., event.detail). This works on both Chrome and Safari--
           | it's 1 for mouse clicks, and 0 for keyboard "clicks", but the
           | spec text is also a little contradictory and under-specified:
           | the "click" event handler says that "the attribute value MUST
           | be 1 when the user begins this action and increments by 1 for
           | each click" (https://w3c.github.io/uievents/#event-type-
           | click) but it also says "This MUST be a non-negative integer
           | indicating the number of consecutive clicks of a pointing
           | device button within a specific time"
           | (https://w3c.github.io/uievents/#current-click-count), and
           | the definition of "pointing device button" seems to exclude
           | synthetic keyboard events (since those are handled
           | separately)
        
           | echoangle wrote:
           | > They were trying to detect whether it was keyboard or mouse
           | activation
           | 
           | But the code shown doesn't do different stuff for Keyboard vs
           | Mouse, it just checks if it is either one of them. Why would
           | you do that? Which other click event types are there that you
           | want to filter?
        
             | joshtumath wrote:
             | I omitted that code to keep the article simpler. We want to
             | turn off the animation on keyboard, and move the focus to
             | different things depending on if it's a keyboard or pointer
             | user.
        
           | Aaargh20318 wrote:
           | They are breaking Curly's Law here
           | (https://blog.codinghorror.com/curlys-law-do-one-thing/), the
           | screenX/Y location mean one thing: the location of the mouse
           | event on screen. Using it for anything else is a huge red
           | flag.
        
       | duxup wrote:
       | Why are screenX and screenY relevant here as far as their code
       | goes?
       | 
       | Where they using those values in their code?
       | 
       | Very interesting article but I'm missing the step where it would
       | impact their code ...
        
         | t43562 wrote:
         | ...because when they are 0 one can infer that the event came
         | from a keypress rather than a mouse. They want to know this.
        
           | shdon wrote:
           | Then it would make a lot more sense to check
           | event.pointerType == 'mouse' vs event.pointerType == '' (for
           | keyboard)
        
             | jorams wrote:
             | That does seem quite obviously better. Even when insisting
             | on checking coordinates why use the coordinate system
             | carried by the event that you have the _least_ control
             | over. Why not .pageX /.pageY, which can't trigger the
             | failure case as long as you make sure the element isn't in
             | the far top left.
        
           | G1N wrote:
           | Based on the other replies here it seems like it's to
           | differentiate taps vs mouse clicks, keyboard events in js
           | don't have a screenX or screenY property (you can run this in
           | your browser console on this HN post to confirm):
           | (() => {         const logEvent = event => console.log({
           | coords: [event.screenX, event.screenY],           type:
           | event.type         });         const input =
           | document.querySelector("textarea");         // use "keydown"
           | instead of "keypress" to detect all keyboard input instead of
           | just character producing input
           | input.addEventListener("keydown", logEvent);
           | input.addEventListener("click", logEvent);       })();
           | 
           | Type in or click on the reply text input and you'll see that
           | the coords array is undefined for all keyboard events. I
           | haven't tried this equivalent on a touch device however, so
           | not sure how it's handled there.
        
           | hyperhopper wrote:
           | This does not work when the mouse is actually at 0,0
        
             | xboxnolifes wrote:
             | An imperfect solution for a situation that will practically
             | never happen and have no noticeable downside.
        
       | nozzlegear wrote:
       | For anyone who didn't click through to the WebKit bug report the
       | author submitted, a WebKit dev asked him to clarify why the BBC
       | finds it beneficial to be able to detect that the event was sent
       | from a keyboard. This is the author's response:
       | 
       | > _Ironically, I want interoperability on this to help with use
       | cases relating to accessibility._
       | 
       | > _I work at the BBC and, on our UK website, our navigation bar
       | menu button behaves slightly differently depending on if it is
       | opened with a pointer or keyboard. The click event will always
       | open the menu, but:_
       | 
       | > - _when opening with a pointer, the focus moves to the menu
       | container._
       | 
       | > - _when opening with a keyboard, there is no animation to open
       | the menu and the focus moves to the first link in the menu._
       | 
       | > _Often when opening a menu, we don 't want a slightly different
       | behaviour around focus and animations depending on if the user
       | 'clicks' with a pointer or keyboard._
       | 
       | > _The 'click' event is great when creating user experiences for
       | keyboard users because it is device independent. On keyboards, it
       | is only invoked by Space or Enter key presses. If we were to use
       | the keydown event, we would have to check whether only the the
       | Space or Enter keys were pressed._
       | 
       | Source: https://bugs.webkit.org/show_bug.cgi?id=281430
        
         | Sayrus wrote:
         | While I can understand the author's need for screenX and
         | screenY, the question remains. Why would screenX return the
         | real screenX position instead of the position within the
         | renderer (I don't think that exists?) or the rendered page
         | (layerX and layerY)? The author's need would be met the same
         | with the renderer position and window positions wouldn't be
         | leaked to all visited websites.
        
         | tshaddox wrote:
         | > Often when opening a menu, we don't want a slightly different
         | behaviour around focus and animations depending on if the user
         | 'clicks' with a pointer or keyboard.
         | 
         | Is the word "don't" a mistake which gives the sentence the
         | opposite of the intended meaning?
        
           | joshtumath wrote:
           | Hello I am the author and that was indeed a mistake. Whoops!
        
         | O-stevns wrote:
         | Seems like a non bug to me.
         | 
         | The first mistake the developer made, was that he wanted to
         | create a different user experience between keyboard and mouse.
         | Stick to what you get by default and design your components so
         | they work for both usecases. Don't try to be smart when it
         | comes to accessibility.
         | 
         | What he ended up doing is what I would have considered a hack.
         | A solution that inevitably breaks or has side effects.
         | 
         | The reason there rarely are good handles to do things
         | differently in accessibility context, is because it's not
         | something that's meant to be handled differently.
        
           | f1shy wrote:
           | > Don't try to be smart when it comes to accessibility.
           | 
           | "Don't try to be smart" alone is good advice in general and
           | everywhere. Also in UI "don't try to be original"
        
             | afandian wrote:
             | The BBC site has a "search box" that's actually a button
             | that brings up the real search box. Always feels confusing.
             | At least it's consistent across News / Sounds / iPlayer.
        
             | josephg wrote:
             | I prefer the line: "make it as simple as possible, but no
             | simpler"
             | 
             | Sometimes complexity is simply the right tool for the job.
             | Complexity is essential and valuable in all sorts of places
             | - like fuzzers, LLMs, compilers, rendering engines, kernel
             | schedulers and so on. But projects only have so much
             | complexity budget to spend. Choosing when to push for
             | simplicity and when to make things complex is a wildly
             | difficult thing to learn. I've been programming for 30
             | years and I still make mistakes here constantly.
        
           | willwade wrote:
           | See I work in accessibility. Like I provide and create
           | solutions direct to end users with complex needs. Not regular
           | web accessibility. I get the view of this. It's the same idea
           | of universal access. But actually I don't fully agree. Yes.
           | If you can stick to this principle - and do try / but I
           | promise you edge cases - which in itself is what
           | accessibility users are all about - cause headaches. At some
           | level you have to do custom stuff. It's the best way. Take
           | for example switch users. Yes. If your ui is tab able -
           | great. But what if you need your items scannable in frequency
           | order. Your tab index needs to change to meet the end users
           | needs. Or eye gaze users. The accuracy level changes. Add in
           | cognitive issues. You can't just make a one size fits all
           | interface. At some stage you need to significantly customize
           | it. You can't rely on a user just learning a complex system
           | level interaction technique- if they can't do that you have
           | to customise on an individual level.
        
             | joshtumath wrote:
             | Well said! It certainly applies to web development as well.
             | Sadly, sometimes more complex solutions are needed -
             | especially when based on user research.
        
             | hinkley wrote:
             | Also note, it's been about 10-15 years since the rules
             | changed and if you want to work on a government contract,
             | accessibility is mandatory.
        
             | O-stevns wrote:
             | Of course there are edge cases, I work with accessibility
             | too, for an app in the public sector where WCAG rules are
             | no joke, so I know this as well but even so, we don't build
             | custom accessibility UI for our users. We (try to) build
             | the UI with accessibility in mind so it's scalable, can be
             | used and navigate properly by voice over and keyboard.
             | 
             | On mobile it's not perfect either but in general you do
             | have features to change stuff like. focus, grouping of
             | elements, how the keyboard navigate the view stack, how to
             | access a button through custom actions and like you
             | mention, change the tab index programmatically.
             | 
             | Even so, not everything can be fixed or handled through
             | standard accessibility means and as such hacks will
             | inevitably make it into the products.
             | 
             | I get what you're saying but I still think that making
             | things accessible and designing with common accessibility
             | in mind should be default and as such it has to be thought
             | about when designing and developing from the get go. Having
             | to create custom interfaces to fulfill a specific need
             | might be a good fit for some things but not when developing
             | apps and websites unless you're targeting that user-group
             | specifically.
        
           | joshtumath wrote:
           | I am the author.
           | 
           | > The first mistake the developer made, was that he wanted to
           | create a different user experience between keyboard and
           | mouse. Stick to what you get by default and design your
           | components so they work for both usecases.
           | 
           | We have. The behaviour is mostly the same whether you're
           | using the keyboard or a pointer (mouse/touch/pen). The only
           | difference is that, for keyboard users, we want to turn off
           | the animation and move the focus to the first link in the
           | menu instead of focussing on the menu's parent <ul>.
           | 
           | The problem was that, as various devs have iterated on the
           | menu over the years, it's broken the fallback behaviour. For
           | my colleague on the funny multi-monitor set up, it should
           | have fallen back to the keyboard no-animation behaviour with
           | no real major difference to the UX, but instead it fell back
           | to the no-JS experience.
           | 
           | So yes, generally don't try to be smart with accessibility,
           | avoid ARIA attributes except where necessary, etc, but click
           | events are the universal input event and work on any kind of
           | input device and have perfect browser support. It's far
           | better for accessibility using them instead of a mix of
           | keydown and mousedown or pointerdown, and potentially missing
           | other kinds of input events.
           | 
           | As I stated in another comment, if it was a scenario where
           | there needs to be a major difference in behaviour between
           | keyboard and pointers, then I would rather use separate
           | keydown and pointerdown events.
        
             | O-stevns wrote:
             | The _mostly_ same behavior is what caused the problem
             | though :P I'm curious, did these solutions come to pass
             | because you had to make adjustments based on actual user
             | feedback or was it just a developer trying to think ahead?
             | I'm questioning whether forcing the user to tab to get to
             | the menu item is a hindrance at all or whether the
             | animation was a problem.
             | 
             | Maybe the former could have been solved using ARIA tags or
             | maybe it would require bigger changes to the component
             | itself. Accessibility is a roller-coaster for all these
             | reasons alone.
        
           | that_guy_iain wrote:
           | > The first mistake the developer made, was that he wanted to
           | create a different user experience between keyboard and
           | mouse.
           | 
           | No, they wanted to make them the same. It's just to give a
           | blind person the same experience as a seeing person requires
           | different things because they operate differently for obvious
           | reasons. For example, a blind person can't see when an
           | animation has finished. They expect that menu to be available
           | once they've triggered it. However, seeing people see the
           | dropdown appearing and then go to use it once it's ready.
           | 
           | > Don't try to be smart when it comes to accessibility.
           | 
           | In all seriousness, considering the state of accessibility as
           | is, I think going outside the box isn't trying to be smart.
           | It's actually being smart. The BBC frontend team is probably
           | at the forefront of making high-traffic websites extremely
           | usable.
        
             | pwg wrote:
             | > For example, a blind person can't see when an animation
             | has finished. They expect that menu to be available once
             | they've triggered it. However, seeing people see the
             | dropdown appearing and then go to use it once it's ready.
             | 
             | For my two-cents, the BBC was simply trying too much to be
             | "cutesy". Don't animate anything, because the silly
             | animation on mouse click simply makes the website feel
             | slower overall. Just open the menu as fast as the user's
             | browser will open it.
        
               | unclad5968 wrote:
               | That wouldn't change anything. They want the first
               | element of the menu to be focused when "clicked" from a
               | keyboard but not from a mouse. The animation doesn't
               | affect that.
        
         | kypro wrote:
         | Does anyone else find this write up confusing?
         | 
         | My understanding from this is that BBC want slightly different
         | behaviour depending on whether it's a mouse or keyboard "click"
         | (keyboard shouldn't show the animation and should focus the
         | first link in the menu).
         | 
         | However, they also want the ease of binding to a single event
         | and while binding to "click" can do this, they have no way to
         | tell whether it was a mouse click or keyboard press which
         | triggered the event.
         | 
         | To solve this they're using an unreliable heuristic after
         | realising in Chrome if the mouse position is screenX=0,
         | screenY=0 it means the event was either triggered by a mouse
         | click at screenX=0, screenY=0 or a keyboard.
         | 
         | As someone whose worked on accessibility projects in the past,
         | this is a really stupid idea imo, and had I reviewed a PR with
         | something like this I would have asked it to be reworked. While
         | I agree browsers should ideally do the same thing, the real
         | issue here seems to me that screenX and screenY make little
         | sense on "click" triggered by a keyboard.
         | 
         | The solution ideally would be a new event ("trigger" or
         | something) which doesn't emit a "MouseEvent", but something
         | more generic which could apply to both a keyboard and mouse
         | event and provide information about the "trigger" source. Imo
         | keyboard "clicks" are weird to begin with and would ideally be
         | fixed with a more appropriate event.
         | 
         | That said, I understand this doesn't currently exist in the
         | spec and a solution is needed now. Therefore I don't see why
         | they couldn't also bind to a "keydown" event then if the click
         | is triggered alongside the "keydown" on the same element,
         | assume it was a keyboard press. That would be far more reliable
         | and far less hacky than what they're doing, and would allow
         | them to trigger from the single event with a bit of extra code
         | to detect if it was a keyboard or mouse.
        
           | joshtumath wrote:
           | Hello I am the author and, yes, I totally agree some generic
           | 'trigger' event would be far better.
           | 
           | To use the keydown event means we have to assume that the
           | 'Enter' and 'Space' are the only keys we need to check for.
           | Using 'click' is far safer from an accessibility point of
           | view because it will always respect what your device
           | considers to be some kind of input trigger.
           | 
           | As stated in the UI Events spec:
           | 
           | > For maximum accessibility, content authors are encouraged
           | to use the click event type when defining activation behavior
           | for custom controls, rather than other pointing-device event
           | types such as mousedown or mouseup, which are more device-
           | specific. Though the click event type has its origins in
           | pointer devices (e.g., a mouse), subsequent implementation
           | enhancements have extended it beyond that association, and it
           | can be considered a device-independent event type for element
           | activation.
           | 
           | And to be clear, I would not want to do it this way if it was
           | for some really critical difference in behaviour between
           | pointer or keyboard interactions. I'm OK with this strange
           | mechanism here because the fallback behaviour is not that
           | different. If you're on Safari, for example, which can't
           | check for `screenX === 0`, then all that happens is that
           | there will be an animation when you open the menu.
           | 
           | However, sadly, because of the ways various developers have
           | added to this code over the years, it's broken that fallback
           | behaviour and stopped it working entirely. So I've just
           | finished a refactor to sort that out and it will hopefully be
           | going live soon.
        
         | amluto wrote:
         | This is fascinating, because the naive English interpretation
         | of the code and the comment on that WebKit bug don't match the
         | actual structure of the code. Here's the relevant code:
         | const isInvokedByMouse = event => event.screenX > 0 ||
         | event.screenY > 0;         const isInvokedByKeyboard = event =>
         | isEnterKey(event) || isSpaceKey(event);
         | 
         | Ignoring the actual conditions entirely, this code seems to be
         | trying to categorize the event into one of two categories:
         | mouse or keyboard. But what it actually does is to categorize
         | into one of four categories: (mouse and not keyboard),
         | (keyboard and not mouse), (keyboard and mouse), and (neither
         | keyboard nor mouse). And, as the original bug shows, (neither
         | keyboard nor mouse) is handled inappropriately. One might
         | wonder whether (keyboard and mouse) works well.
         | 
         | Either the code should be deliberate about the fact that (is it
         | a keyboard) and (is it a mouse) are separate booleans, or the
         | code should be structured so that the actual categories are
         | mutually exclusive. For example:                   const
         | isInvokedByMouse = ...
         | 
         | and use !isInvokedByMouse to check for keyboardiness, or:
         | const eventSource = ... (returns "keyboard" or "mouse")
         | 
         | or, perhaps even better:                   const eventSource =
         | ... (returns "keyboard", "mouse", or "not sure")
        
           | nightpool wrote:
           | This is a great comment ^ whenever you use two booleans like
           | this, you're opening yourself up to "unrepresentable state"
           | logic errors. Finding and noticing this in code can be
           | tricky, but it's a great example of something that should be
           | caught during code review.
        
             | politelemon wrote:
             | Not sure if exactly the same thing but reminds me of
             | "Booleans are a trap"
             | 
             | https://katafrakt.me/2024/11/09/booleans-are-a-trap/
        
           | robocat wrote:
           | And just to add an extra corner case, Mobile Safari changes
           | the click behavior if an onclick handler is registered - even
           | if the click handler is an empty function that does nothing.
           | The onclick handler itself acts as another Boolean that
           | affects the browser's behavior. I don't remember the exact
           | details because it was a corner case (I think to do with
           | scrolling or popovers or touchcancel - I know it was
           | surprisingly nasty). This page mentions something else http:/
           | /www.quirksmode.org/blog/archives/2010/09/click_event_...
           | "Fortunately it's pretty easy to solve: you have to make the
           | element clickable by giving it an onclick event handler of
           | its very own. That handler can be empty; as long as it's
           | present it will make any element clickable.".
        
       | G1N wrote:
       | RE this line of code at the bottom of the article:
       | const isInvokedByMouse = event =>       event.type === 'click' &&
       | (event.screenX !== 0 || event.screenY !== 0);
       | 
       | Why do you even have to check if screenX and screenY are non-zero
       | (as opposed to just checking typeof event.screenX == "number")?
       | Wouldn't that mean (and this is a wild edge-case) that if someone
       | positioned their browser window so that the menu was in the top
       | left corner (at position 0,0) the event handler would break
       | again? Is this to block synthetic click events like (<div
       | />).click()? Keyboard events don't have a screenX or screenY from
       | what I remember as well.
        
         | whstl wrote:
         | This is just a heuristic to determine if the event is keydown
         | or click.
         | 
         | In the article the author says that the issue is that the same
         | function is handling both events, and they will work on
         | refactoring it to something better.
         | 
         | The normal approach is just have different functions answering
         | to different events. Or using more precise information about
         | the event [1], instead of a heuristic.
         | 
         | [1] A suggestion was made by this poster:
         | https://news.ycombinator.com/item?id=42174436
        
       | watusername wrote:
       | This seems like a self-inflicted bug resulted from incorrect
       | heuristics (assumption that positive screenX/Y values represent
       | mouse event), and the investigation was complicated by inadequate
       | tracing/logging.
       | 
       | Instead of checking the more appropriate property that other
       | commenters have suggested (pointerType), I'm a bit surprised that
       | the solution given by the author is to patch up the shaky
       | heuristics even more:
       | 
       | > We could deduce from our final two clues the solution: we need
       | to check for negative numbers as well as positive numbers when
       | checking the screenX and screenY coordinates.
        
         | joshtumath wrote:
         | Actually that is what we're going to do. I'm hoping to merging
         | in code, soon, that will change it to use pointerId === -1 and
         | then fall back to screenX === 0.
         | 
         | At the time this code was originally written four years ago or
         | whenever it was, not all browsers used PointerEvent for click.
        
       | Brian_K_White wrote:
       | I would not write a blog post advertizing how I filed a bug with
       | WebKit for my own coding 101 error: unsafe assumptions and
       | relying on side effects and heuristics.
       | 
       | Actually not just 101, it's basically with all of us at all
       | levels and for life. So they're in good company having made a
       | mistake everyone makes all the time, but it was a mistake on
       | their part not a bug in WebKit, nore even a "interoperability
       | issue" in WebKit or any browser.
       | 
       | They say they weren't aware that negative values were possible
       | and that different browsers produce different values.
       | 
       | Ok, but neither of those matters.
       | 
       | If the function is even allowed to contain or express a negative
       | value (IE right at the lowest basic level, is the returned data
       | type actually a uint, or is it _anything else_? a regular int? a
       | string?) then negetive values were always a possibility even if
       | you personally never saw one before. Saying  "I didn't expect a
       | number below 0" is barely any different from saying "I didn't
       | expect a number above 10000".
       | 
       | The discrepency between browsers doesn't matter and isn't the
       | browsers fault that it tripped you up. You just made a standard
       | boring unsafe assumption like every other programmer ever.
       | 
       | The entire problem is that you cared about something you don't
       | actually care about.
       | 
       | You assumed that there was meaning in the absolute position of
       | the window or the mouse pointer, when there never was, and you
       | don't actually care about those anyway. The absolute position is
       | like the actual internal-only row number in a db. Every row has a
       | unique one, but it's none of your business what it is. There is
       | only meaning in it's position relative to something else like a
       | button, or relative to it's previous position to track movement.
       | 
       | Similarly checking for 0,0 and assuming that means keyboard is
       | just another false heuristic that doesn't actually prove any such
       | thing. The specs may or may not promise that the value will be
       | 0,0 in the event of a keyboard initiated click, but no way it
       | says that it can't be 0,0 any other way.
       | 
       | Don't de ashamed of this error because it's common, but don't be
       | proud of calling these WebKit or browser interoperability bugs.
       | 
       | Do write up and publish the experience though as a warning and
       | lesson to new developers about assumptions and heuristics and
       | relying on side effects that just happen to work on the
       | developers laptop when they tried it once and shipped it.
       | 
       | Also "it's for accessibility" doesn't change anything. Trying to
       | be too smart just makes it worse. Actually that's true just
       | generally for everything.
        
       | andy_ppp wrote:
       | What is the correct way to check if you have a mouse click rather
       | than a keyboard click? I would be tempted to set a module level
       | flag based on what most recently happened - if there was a
       | "mousedown" event more recently we'll set isKeyboard to false and
       | isMouse to true and vice-versa if "keydown" is pressed.
       | 
       | Then we wouldn't need the isInvokedByMouse and
       | isInvokedByKeyboard functions.
       | 
       | Is there a better way? Relying on screen coordinates for this is
       | highly dubious and I would argue a hack.
        
         | matijs wrote:
         | `event.detail` [1] is 0 for keyboard "clicks" and 1 for pointer
         | clicks.
         | 
         | 1: https://developer.mozilla.org/en-
         | US/docs/Web/API/UIEvent/det...
        
       | 8organicbits wrote:
       | Kudos to BBC for investing in accessibility, and unfortunately
       | discovering a nasty bug.
       | 
       | As an industry, why haven't we figured out how to make drop downs
       | that consistently open for all users? Is accessibility just that
       | hard? Are there web frameworks/web components BBC should be using
       | that already handle this?
       | 
       | I've been wary (as a backend-focused full-stack developer) about
       | tweaking the browsers components. There's so much nuance to how
       | they work and the implementations are battle tested. The idea of
       | creating a custom text box (for example) without doing extensive
       | research of text box behavior across platforms seems ripe for
       | failure. I notice broken copy/paste and dropped characters often
       | enough (on major corporate sites too). Why are text boxes broken
       | in 2024? React feels arrogant to me now.
       | 
       | Personally, I've tried to handle this with server-side templates,
       | CSS frameworks like Bulma, minimal JS. It's not viable for sites
       | demanding slick custom branding (vanity?) but my text boxes work
       | and my site doesn't cost a fortune to develop. Is it accessible
       | to BBC standards? I'm not sure.
        
         | spookie wrote:
         | Agreed. But ultimately many issues arise when user agents
         | customize these elements in very dubious ways. It's ok for the
         | most part, but there's a reason behind reset.css files, and I
         | wager a more nuclear approach was used here to circumvent these
         | issues completely.
         | 
         | I'm just trying to reason on their decision here.
        
       | kernal wrote:
       | That flickering Ace Attorney GIF was extremely annoying.
        
       | Kwpolska wrote:
       | Checking for position != 0 still does not fix it. On Windows and
       | Linux, it is possible for a window to span multiple displays.
       | Someone could set things up so that a valid click target for the
       | button ends up in the (0, 0) position.
        
       | a1o wrote:
       | > I checked the (DOM UI Events) spec to see if that was correct,
       | but there didn't seem to be any specific information about it
       | 
       | Story of my life is finding out the details that apparently
       | matter when I am debugging stuff has not been actually written in
       | the spec (any)
        
       | owaislone wrote:
       | Very interesting but why would a browser report different
       | coordinates depending on the monitor? I'd assume browser would
       | treat the webpage as if it was the entire screen irrespective of
       | which display it was on. Is there a reason for web APIs to have
       | this information at all? Seems like a potential
       | security/information/tracking risk.
        
       ___________________________________________________________________
       (page generated 2024-11-18 23:00 UTC)