Search code examples
javascripthtml

HTML5 and JS audio doesn't play


So i'm working on a school project, and i have to create a website. In this website, i made a page when you click on a guitar image, it play/pause a music, and everything was working fine ! But then, when i copy-pasted the code for another guitar and sound,nothing is working anymore. I made sure to change id and sources, class and everything so nothing is duplicate but it's not working Here is a part of the html5 code

<h2>Van Halen</h2>
         <audio src="son/légendes/vanhalen.mp3" id="vanhalenaudio" preload="auto"></audio>
<p style="float:right"><img src="images/légendes/vanhalenguitar.png" id="clickable" onclick="vanhalenbutton()" /></p>
        <script type="text/javascript" src="javascript/légendes/son/vanhalen.js"></script>

<p style="float:left"><img src="images/légendes/vanhalen.png" /></p>
        <br><br><br><br> 
      <p>stuff</p>
        
        <br><br><br><br><br><br><br>
        
        <h2>Jimi Hendrix</h2>
         <audio src="son/légendes/jimihendrix.mp3" id="jimihendrixaudio" preload="auto"></audio>
<p style="float:right"><img src="images/légendes/jimihendrixguitare.png" id="clickable" onclick="jimihendrixbutton()" width="350" height="350"/></p>
        <script type="text/javascript" src="javascript/légendes/son/jimihendrix.js"></script>
        
<p style="float:left"><img src="images/légendes/jimihendrix.png" width="500" height="300"/></p>
       <p>other stuff</p>
        <br><br><br><br><br><br><br><br><br><br>

And here is the JS, same thing for both but i replaced the "vanhalen" with "jimihendrix"

var playing = false;
var audio = document.getElementById("ritchieblackmoreaudio");

function ritchieblackmorebutton() {
    playing ? audio.pause() : audio.play();
}

audio.onplaying = function() {
  playing = true;
};
audio.onpause = function() {
  playing = false;
};

I tryed to remove the other sound, and everything was working again, but when i put it back, it was not working. I don't know what to do and i can't find anything about this on internet.


Solution

  • You definitely don't want to duplicate IDs, and you don't want to duplicate variable names in the same scope either. In any case, there are some better ways to handle this. As this is for a class, I'll add some detail for the whole thing to get you started in a better way.

    Firstly, there is no need for the IDs in most cases. They end up in the global scope which can cause some confusion and break things for you when you edit larger scripts later. Modern browsers have standardized ways of selecting elements, so IDs are almost never needed.

    Second, you don't need a separate function for each player.

    I would do something like this:

    <button data-audio-src="son/légendes/jimihendrix.mp3">
      <img src="images/légendes/jimihendrixguitare.png" />
    </button>
    

    This adds a data attribute to your button, indicating that the button should be associated with a particular audio URL. That way, your JavaScript stays the same, no matter which button is clicked. Also, the reason we use a <button> is that it helps screen readers and other alternative input devices know what is a real button and what isn't. You can always style it as you see fit with CSS.

    Now, in your JavaScript:

    // Create just one audio.  Some devices only support one anyway, and we only need one here.
    const audio = new Audio();
    
    // Add a click listener on the whole page, which we'll then filter down
    // to just elements with the `data-audio-src` attribute.  Note, if you can
    // choose a tighter selector than the whole document, you should, for efficiency.
    document.addEventListener('click', e => {
      // Did the clicked element have a `data-audio-src` attribute?
      // Or, was it a child of such an element?  If not, return, do nothing.
      if ( !e.target.closest('[data-audio-src]') ) {
        return;
      }
    
      // Are we currently playing audio for the clicked button?
      // If so, just pause it.
      if (
        !audio.paused && 
        audio.src === new URL(
          e.target.closest('[data-audio-src]').dataset.audioSrc, 
          location
        ).toString()
      ) {
        return audio.pause();
      }
    
      // Here, we load a new audio URL and play it.
      audio.src = e.target.dataset.audioSrc;
      return audio.play();
    });
    

    This code is untested so there may be a quirk here, but I think this will give you much more solid footing to start with.