Search code examples
javascripthtmlformsaccessibilitywebspeech-api

WebSpeechAPI to make a site accessible


WebSpeechAPI to make a site accessible but it first starts with the whole document and then the hovered element again.

How to resolve this?

I referenced most of the code from WebSpeechAPI MDN page.

All I want is for the browser to output the text of the tag that I am hovering over.

But it does that after speaking out all the contents of the document first. I think it does that because it catches the document first before I can reach the element.

            var synth = window.speechSynthesis;
            var inputForm = document.querySelector('form');
            var inputTxt = document.querySelector('.txt');
            var voiceSelect = document.querySelector('select');
            var title = document.querySelector('#title');
            var pitch = document.querySelector('#pitch');
            var pitchValue = document.querySelector('.pitch-value');
            var rate = document.querySelector('#rate');
            var rateValue = document.querySelector('.rate-value'); 
 
          var voices = [];  //creat aan array to get thev voices  

       function populateVoiceList() {
         voices = synth.getVoices(); // get the voices form the browser

         for (i = 0; i < voices.length; i++) {
          var option = document.createElement('option');    //create an element named option
          option.textContent = voices[i].name + ' (' + voices[i].lang + ')';   //get all the info about the voice from the device and store in the text of the option tag
          if (voices[i].default) {
           option.textContent += ' -- DEFAULT';
           }
           option.setAttribute('data-lang', voices[i].lang); //set attributes of the option tag
           option.setAttribute('data-name', voices[i].name);
           voiceSelect.appendChild(option);
         }
       }
        populateVoiceList();
        if (speechSynthesis.onvoiceschanged !== undefined) {    // this handler gets fired when the list returned by the getVoices function get changed
             speechSynthesis.onvoiceschanged = populateVoiceList;   //requires a function to handle the change in the list
         }
       document.onmouseover = function(e)  {
         var targ;
        event.preventDefault();    //prevent default actions of the browser 
        
        if (e.target) targ = e.target;

         var utterThis = new    SpeechSynthesisUtterance(targ.textContent); //The SpeechSynthesisUtterance interface of the Web Speech API represents a speech request. 
          var selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');  //get the data-name attribute of the selected option 

      for (i = 0; i < voices.length; i++) {
         if (voices[i].name === selectedOption) {
            utterThis.voice = voices[i];     //. We set the matching voice object to be the value of the  SpeechSynthesisUtterance.voice property.
        }
     }

       utterThis.pitch = pitch.value;
      utterThis.rate = rate.value;
      synth.speak(utterThis);
       pitch.onchange = function() {
         pitchValue.textContent = pitch.value;
      }

      rate.onchange = function() {
         rateValue.textContent = rate.value;
       }
    }
<!DOCTYPE html>
<html lang="en">
    <head>
	    <meta charset="UTF-8">
	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
	    <title>Document</title>
    </head>

    <body>
	    <h1 id="Speech sYNTHESIZER" >Speech synthesiser</h1>

	    <p>Enter some text in the input below and press return to hear it. change voices using the dropdown menu.</p>

	    <form>
		    <input type="text" class="txt">
          <div>
            <label for="rate">Rate</label><input type="range" min="0.5" max="2" value="1" step="0.1" id="rate">
            <div class="rate-value">1</div>
            <div class="clearfix"></div>
     </div>
      <div>
        <label for="pitch">Pitch</label><input type="range" min="0" max="2" value="1" step="0.1" id="pitch">
        <div class="pitch-value">1</div>
        <div class="clearfix"></div>
      </div>
      <select></select>
       </form>    
   
    </body>
 </html>


Solution

  • All I want is for the browser to output the text of the tag that I am hovering over.

    You are starting from a legitimately good intention, but in fact except if you are making a special game or an innovative interface, it's a bad idea. Accessibility on the web simply doesn't work like this. You'd better try to conform to standards like WCAG to make your site accessible.

    Several reasons for this, at least two big ones:

    • Finding elements to be spoken with the mouse is a possibility, but isn't the common way to navigate on the web.
      • Blind people generally don't use a mouse because they don't care about the placement of elements on the screen, can quickly get lost or miss important information that way. They just need to have them appear logically when navigating with tab, heading by heading or by another mean provided by the screen reader.
      • For partially sighted users, using the mouse to read elements below the cursor is of help or not depending on their vision, but for the same reasons as blind users, it's often just a complementary help; and screen reader software have the feature built-in.
    • Screen reader users have their preferences about language, voice, rate, pitch, etc. fortunately they don't need to set them for each site they visit

    So, unless you are making something really special or new, prefer stick to largely used means to access your site.

    But it does that after speaking out all the contents of the document first. I think it does that because it catches the document first before I can reach the element.

    This is probably because of event bubbling.