-1

I know that maybe this layout is not the best practice, but I have a code that I should NOT and can NOT modify, so it is very exciting for me to understand and find some way with the current code using the structure of having an anchor tag and inside it and a text and a button as it is in this case:

<a href="home.html">
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Corrupti quidem
    quia beatae cupiditate tenetur doloremque rerum facilis vel fugiat
    tempora, voluptates ipsum alias eius dolor omnis modi numquam perferendis
    sint?
    <br /><br />
    <button onclick="functionClick(event)">clickme</button>
</a>

I have an anchor tag that inside has a text and a button, when I tap on the button it executes the function "function click()" and it avoids continuing to the navigation of home.html. This is the desired behavior and it works on the web.

But in ios, with the screen reader (voiceover) happens what you see in this gif:

enter image description here

when selecting the button the screen reader navigates without taking into account the behavior of the button, the function is not executed.

I want the screen reader to execute the button and not navigate to home.html unless you manually select what is outside the button.

this is my edit code:

https://codesandbox.io/s/confident-neumann-2dm2fe

this is my live code:

https://0d7cnh.csb.app/

my full code:

<!DOCTYPE html>
<html>
    <head>
        <title>Parcel Sandbox</title>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    </head>

    <body>
        <a href="home.html">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Corrupti quidem
            quia beatae cupiditate tenetur doloremque rerum facilis vel fugiat
            tempora, voluptates ipsum alias eius dolor omnis modi numquam perferendis
            sint?

            <br /><br />
            <button onclick="functionClick(event)">clickme</button>
        </a>

        <script>
            function functionClick(event) {
                event.preventDefault();
                alert("click");
                console.log("click");
            }
        </script>
    </body>
</html>

How can I fix it?

yavgz
  • 275
  • 3
  • 17
  • Try adding `event.stopPropagation()` after the `event.preventDefault();` line. This prevents your event from "bubbling" up to the anchor – itodd Aug 03 '22 at 05:40
  • It's not just "Not best practice", it is invalid HTML. This is just one of the problems with using interactive content within interactive content, specifically , and invalid HTML generally – Jon P Aug 03 '22 at 05:45
  • @itodd not works :( – yavgz Aug 03 '22 at 05:48
  • The button event is not even dispatched, so there is no way to use `event.stopPropagation();` On option might be to look at the `event.target` in a click handler for the ``. Do you get the button if the button was clicked? – Andy Aug 03 '22 at 10:13
  • You state that you cannot change the underlying invalid HTML, but can you change the DOM and fix the structure by moving the button out of the ``? – Andy Aug 03 '22 at 10:13
  • Just to be clear: With invalid HTML you cannot achieve WCAG compliance, should you be interested in that. See [Success Criterion 4.1.1 Parsing](https://www.w3.org/TR/WCAG22/#parsing): “elements are nested according to their specifications” – Andy Aug 03 '22 at 10:18
  • Have you tried to reach the button by using the rotor rather than just simple sweeps ? Maybe in this case you can activate the button without activating the link. IN any case, you won't be able to find a good solution with incorrect code. By the way, why can't you change it ? Where there's a will, there's a way. – QuentinC Aug 03 '22 at 15:13
  • Could you please test this, @yavgz? https://js-2bsflm.stackblitz.io it’s removing the native behaviour from the link and re-building it using javascript. – Andy Aug 03 '22 at 17:24
  • I'm puzzled why this is being discussed. Why try to come up with a solution for invalid code? You absolutely cannot have a button embedded in a link. The HTML spec is very clear on this: "**there must be no interactive content descendant**", https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-a-element – slugolicious Aug 03 '22 at 18:06

3 Answers3

0

Use the <a href...>then put the button next/under/over it with CSS, do not stack the button inside the <a href...>. this way, you do not interfere with the link and/or the button.

inQrt
  • 35
  • 5
  • thanks for answering, I dont understand you... something like: `text` I must respect this structure, this is the challenge – yavgz Aug 03 '22 at 05:41
  • While you are absolutely correct this shouldn't be done, OP said they can't change it, which sadly happens. @yavgz - why can you not change the structure? – Lisa Aug 03 '22 at 05:43
  • @Lisa it's a complex code, and this is defined in a real project I'm working on. – yavgz Aug 03 '22 at 05:46
  • @yavgz sorry didnt read the OP properly (the part with cannot/must not change the code) - as the foreposters wrote: using .stopPropagation() and/or "return false" should do the trick – inQrt Aug 03 '22 at 07:15
0

Edit:

Seems that the problem you're having is that the IOS screen reader is not firing a click event, but a touchstart event. So you'd need to add a ontouchstart="functionClick(event)" attribute to your button to make it work. See also event.stopPropogation() not working in IPAD/Tablet

Original Answer:

This is the expected behaviour as preventDefault() only cancels the default behaviour of the button, but doesn't stop the event from bubbling up. Every event, in your case the click event, does bubble up the cascade until it's either reaching the most outer tag or is stopped by either stopPropagation() or a return false (which equals to both preventDefault() and stopPropagation()).

Johannes Stadler
  • 737
  • 12
  • 24
  • not works... :( – yavgz Aug 03 '22 at 05:47
  • If it worked, reacting only on `touchstart` would be in conflict with [2.5.2 Pointer Cancellation](https://www.w3.org/TR/WCAG22/#pointer-cancellation), but it might be a start. Then again, using invalid HTML already makes WCAG conformance impossible due to [4.1.1 Parsing](https://www.w3.org/TR/WCAG22/#parsing): “…elements are nested according to their specifications…” – Andy Aug 03 '22 at 10:17
  • the onclick or ontouchstart event is never fired :( – yavgz Aug 03 '22 at 15:22
0

A shot in the dark, as I don’t have iOS to test.

The only click event that is dispatched is that of the <a>, so you might be able to use it to determine which child actually got clicked.

/* link or one of its descendants got clicked */
const somethingClicked = e => {
  if (e.target.tagName === 'BUTTON') {
    alert('Button clicked');
    e.preventDefault();
  }
  
  // else, let the browser handle the link click
}
<a href="#gosomewhere" onclick="somethingClicked(event)">
  Lorem ipsum dolor sit amet consectetur adipisicing elit. Corrupti quidem quia beatae cupiditate tenetur doloremque rerum facilis vel fugiat tempora, voluptates ipsum alias eius dolor omnis modi numquam perferendis sint?

            <br /><br />
            <button>clickme</button>
        </a>
Andy
  • 4,783
  • 2
  • 26
  • 51