Search code examples
javascriptjqueryhowler.js

jQuery problem referencing id - Using Howler.js


I have a maze I'm struggling to sort:

I have this grid with 12 anchor tags

for (let i = 1; i <= 12; i++) {
  $("#minuetti").append(
    `<div class="col-6 col-md-3"> <a id="minuetto${i}" class="btn btn-primary btn-lg mb-1 minuetto">Minuetto ${i}</a></div>`
  );
}

Each one of those will play a different mp3 file with the code below using Howler.js.

$(".minuetto").on("click", function() {
  let id = this.id;
  let minuettoPath = `assets/music/${id}.mp3`;
  let cell = new Howl({
    src: [minuettoPath],
    onplay: function() {
      $(`#${id}`).text("Stop");
      $(".minuetto").addClass("disabled");
      $(`#${id}`).removeClass("disabled");
      $(`#${id}`).removeClass("minuetto");
      $(`#${id}`).on("click", function() {
        cell.stop();
      });
    },
    onend: function() {
      $(".minuetto").removeClass("disabled");
      $(`#${id}`).text(`Minuetto ${id.slice(8)}`);
      $(`#${id}`).addClass("minuetto");
      this.unload();
    }
  });
  cell.play();
});

My problem:

I'm trying to change the text of the button clicked and keep it enabled. I'm disabling all remaining (11) buttons until the end of the mp3 file. But when I click on the enabled button (the one playing) instead of stopping my mp3, it restarts. What am I doing wrong with my jQuery here? I'm referencing to my id and calling the function to do cell.stop() but for some reason jQuery runs the playing again, even though I removed the class minuetto from the playing button. I'm really puzzled. Please help?


Solution

    • Use just const sound = new Howl({src: mp3.path});
    • Create a element using jQuery's Object Element constuctor $({})
    • Assign the needed events like click(), play(), and stop() that you can trigger when needed and perform your desired actions
    • Use Howler's sound.playing() to determine which trigger callback is needed

    // Use an array of objects instead, otherwise if one day
    // you decide to remove a numeric song you'll have to replace it with another.
    // This also allows you to change the order of songs:
    const mp3list = [
      {name:'Enter Sandman', path:'https://upload.wikimedia.org/wikipedia/en/3/39/Metallica_-_Enter_Sandman.ogg'},
      {name:'Back in Black', path:'http://upload.wikimedia.org/wikipedia/en/4/45/ACDC_-_Back_In_Black-sample.ogg',},
      {name:'U2 - One', path:'https://upload.wikimedia.org/wikipedia/en/5/5e/U2_One.ogg',},
    ];
    
    let $allMP3 = [];
    
    const $newMP3 = mp3 => {
    
      // HOWL
      const sound = new Howl({src: mp3.path});
    
      // $ ELEMENT
      return $('<div>', {
        class: 'minuetto',
        text: mp3.name,
        on: {
          click() {
            $allMP3.forEach($el => $el.not(this).trigger('stop'));
            $(this).trigger(sound.playing() ? 'stop' : 'play');
          },
          play() {
            $(this).text("Stop");
            sound.play();
          },
          stop() {
            $(this).text(mp3.name);
            sound.stop();
          }
        }
      });
    };
    
    $allMP3 = mp3list.map($newMP3); // Populate array of $ elements
    $("#minuetti").append($allMP3); // Append once!
    <div id="minuetti"></div>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.1.3/howler.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.1.0.js"></script>