skip to Main Content

Trying to do this as simply as possible. I want to play an audio file when a hyperlink is clicked and display audio controls.

Also, is there a way to make the audio persist so that it will continue playing while the visitor navigates to other pages within the site?

Thanks!
Joe

HTML Hyperlink:

    <a href="audiofile.mp3" onclick="myFunction(this); return false;">[Audio]</a>

JS Code:

    function myFunction(audioFile){

    var myAudio = new Audio(audioFile);
    myAudio.controls = true;
    myAudio.play();

    }

This code plays the audio file, but does not display the audio controls.

I have also tried:

      var x = document.createElement("AUDIO");

      if (x.canPlayType("audio/mpeg")) {
        x.setAttribute("src","audioFile.mp3");
      } else {
        x.setAttribute("src","audioFile.ogg");
      }

      x.setAttribute("controls", "controls");
      document.body.appendChild(x);


which fails miserably.

Have also tried:

    var audio = new Audio(audioFile);
    audio.setAttribute("controls", "controls");
    audio.play();

Also fails to play the audio or display controls

3

Answers


  1. Replace return false with e.preventDefault(). What might be happening is that when the link is clicked, the audio element is created and added to the page, but the page is reloaded, so you don’t get to see it, as you can see in the example below:

    const audioLink = document.getElementById('audioLink');
    
    audioLink.addEventListener('click', () => {  
      const audioElement = document.createElement('AUDIO');
    
      audioElement.setAttribute('src', `audioFile.${ audioElement.canPlayType('audio/mpeg') ? 'mp3' : 'ogg' }`);
    
      audioElement.setAttribute('controls', 'controls');
      
      document.body.appendChild(audioElement);
      
      return false;
    });
    audio {
      display: block;
      margin-top: 16px;
    }
    <a id="audioLink" href="audiofile.mp3">[Audio]</a>

    Using return false as a way to prevent the event’s default behavior as well as its propagation (e.preventDefault() + e.stopPropagation()) is jQuery-specific. Take a look at these:

    Here’s the fixed version of your second snippet (using e.preventDefault()):

    const audioLink = document.getElementById('audioLink');
    
    audioLink.addEventListener('click', (e) => {
      e.preventDefault();
      
      const audioElement = document.createElement('AUDIO');
    
      audioElement.setAttribute('src', `audioFile.${ audioElement.canPlayType('audio/mpeg') ? 'mp3' : 'ogg' }`);
    
      audioElement.setAttribute('controls', 'controls');
      
      document.body.appendChild(audioElement);
    });
    audio {
      display: block;
      margin-top: 16px;
    }
    <a id="audioLink" href="audiofile.mp3">[Audio]</a>

    This is how it looks for me in this second example:

    enter image description here

    Login or Signup to reply.
  2. This is because you created a new audio which is not a part of the body so it will not be displayed.

    You can try this:

    function myFunction(audioFile){
    
    var myAudio = new Audio(audioFile);
    document.body.innerHTML += myAudio
    myAudio.controls = true;
    myAudio.play();
    
    }
    
    Login or Signup to reply.
  3. Hyperlinks shouldn’t be used as "hooks" for click events in the first place. Hyperlinks are for navigation and to use them for other purposes can cause problems for those who rely on assistive technologies to interact with the page.

    In your case, when you click the link, you have two things happening, first the native navigation to the href and second the click event handler, which is often a "conflict of interests" of sorts.

    Just about every element that you can see on a page supports a click event and so an element like a span should really be used here. A span or a div are semantically neutral – – they don’t convey any particular meaning for the data they contain, so they are great for custom non-semantical data like you need here.

    You’ve also got an issue with the way you’ve created the audio element – – you never actually included it into the DOM, so it’s never visible.

    Really, you just need to use the HTML5 native audio element that starts out as part of the DOM, just hidden. Then, with a click to a span you simply unhide the element (which has already been configured to show its controls) and instruct it to play the audio.

    Also, you should not be setting events up using HTML event attributes. That is a 25+ year old technique that we used before we had standards. Instead, do your event wiring in JavaScript with .addEventListener() as seen below.

    const player = document.querySelector("audio");
    
    document.querySelector("#audio").addEventListener("click", function(){
      player.classList.remove("hidden");
      player.play();
    });
    .hidden { display:none; }
    
    /* Make the span look and feel like a clickable element  */
    #audio { cursor:pointer; color:blue; }
    #audio:hover { color:red; }
    <span id="audio">Play Audio</span>
    <audio controls src="https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba.mp3" class="hidden"></audio>

    Also, is there a way to make the audio persist so that it will
    continue playing while the visitor navigates to other pages within the
    site?

    No. Most browsers will stop playing media when the browser tab loses focus and, in the case of navigating to another page in the site, the first page would be unloaded and so the audio element would no longer exist.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search