Distinguish the click event from mouse vs screenre

2019-07-23 07:29发布

I built a drag and drop component, and it works like a charm, but now I need to make it accessible for screen reader users.

I already have the implementation of the solution done. Basically its a context menu that pops when the enter is pressed and allow to move things around.

This works like a charm when navigating without the SR (screen reader), because the implementation that I made listen to KeyEvents (keypress and keydown).

The problem is when using the SR (I tested with NVDA), the keyevents are not triggered, instead it goes to the click event (Which is part of drag and drop, not meant for non-visual users)

Changing the role attribute to application works, but other shortcuts from the SR doesn't.

Is there a reliable way to detect if the click event was triggered by the SR ? Or some other keyboard event that I can listen that is triggered when SR is turned on ?

There is already a question like this on SO, but is unanswered.

Edit1: Adding HTML structure information

<div>
  <img src="some-image.jpg" aria-hidden="true">
  <div class="card-container" (click)="cardClicked($event)" (keypress)="showContextMenu($event)">
    <span>Card name</span>
  </div>
</div>

3条回答
做自己的国王
2楼-- · 2019-07-23 08:02

I've figured out a not-so-pretty solution, which involves creating a screenreader only element and handle the click on this element, if the click happens on that element, it could only be triggered by the SR.

<div>
  <img src="some-image.jpg aria-hidden="true">
  <div class="card-container" (click)="cardClicked($event)">
    <span aria-hidden="true">Card name</span>
    <span class="sr-only" (click)="showContextMenu($event)">Card name</span> <---- It can only be clicked by the SR
  </div>
</div>
查看更多
Root(大扎)
3楼-- · 2019-07-23 08:11

The problem is when using the SR (I tested with NVDA), the keyevents are not triggered, instead it goes to the click event (Which is part of drag and drop, not meant for non-visual users)

A large part of potential screen reader users are in fact visual-users. Blind people are only a small part among them : visually impaired can still have some vision left, but also illiterate people might use a screenreader for assistance.

Screen reader will always send the default event, as specified by the W3C in SCR35: Making actions keyboard accessible by using the onclick event of anchors and buttons

While "onclick" sounds like it is tied to the mouse, the onclick event is actually mapped to the default action of a link or button. The default action occurs when the user clicks the element with a mouse, but it also occurs when the user focuses the element and hits enter or space, and when the element is triggered via the accessibility API.

You have no possibility to detect that it has been done by from a screenreader, from a keyboard, or from an eye tracking device.

查看更多
等我变得足够好
4楼-- · 2019-07-23 08:11

I would probably go for an onclick and an onmousedown.

If the onmousedown is fired, I would set a flag, that I would read in the onclick, telling me whether this was actually originally a pointer event.

Something like:

<button onmousedown="pointerFunction()" onclick="clickFunction()">Active this</button>

<script>
var isPointerEvent = false;
function pointerFunction() {
    isPointerEvent = true;

    // Do something for pointer users
}

function clickFunction() {
    if (isPointerEvent) {
        return isPointerEvent = false;
    }

    // Do something for keyboard / screen-reader users
}
</script>

While this will distinguish between keyboard users (screen-reader users included) and mouse users, if will not distinguish between keyboard users and screen-reader users. For that, your own proposed solution does the trick. However, remember to add a role="button" to the clickable <span> if you want to convey to the screen-reader that they can click it.

I would add that to your solution as a comment, but I'm new here, and I don't have to "Reputation" to be able to do that. :-)

查看更多
登录 后发表回答