1

I am looking to create sound buttons.

Have used the answer here: Buttons click Sounds

and implemented it so that the buttons are divs and created dynamically from a MySQL DB.

Does anyone know how to preload that list of sounds on page load?

Also, I want to apply a CSS class to the div when clicked and then when the audio finishes, want it to switch back to the original CSS class.

This is what I have tried. The sounds play correctly but the onended fuction does not fire.

    <script type='text/javascript'>
    $(window).load(function(){
    var baseUrl = "http://[URL HERE]";
    var audio = [<?php echo $audiostring; ?>];

    $('div.ci').click(function() {
        var i = $(this).attr('id').substring(1);
        mySound = new Audio(baseUrl + audio[i-1]).play();       
        mySound.onended = function() {
        alert("The audio has ended");};

    });
    });

    </script>
Community
  • 1
  • 1
Amit
  • 11
  • 3

2 Answers2

1

If you are using HTML5 audio you can do something like the following:

 mySound.addEventListener("ended", function() 
 {
      alert("The audio has ended");
 });

Edit:

Try changing the way you create the audio tag, as referenced here.

$('div.ci').click(function() {
    var i = $(this).attr('id').substring(1);
    mySound = $(document.createElement('audio'));
    mySound.src = baseUrl + audio[i-1];  
    mySound.play();    
    mySound.addEventListener("ended", function() 
    {
      alert("The audio has ended");
    });

});
Community
  • 1
  • 1
mhatch
  • 4,441
  • 6
  • 36
  • 62
1

<audio> and new Audio() should be the same but it doesn't look like that is the case in practice. Whenever I need to create an audio object in JavaScript I actually just create an element like this:

The ended event is created based on .currentTime attribute. event-media-ended

the canplaythrough event was used to knowing when the browser has finished downloading the audio file and we can play

code complete use closest

<style type="text/css">
    body{background: #aaa;color:#fff;}
        div
        {
            width: 100px;
            height: 100px;
            background: #dda;
        }

    </style>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div >

</div>
<div >

</div>
<div >

</div>

<script type="text/javascript">

 $(window).load(function(){

    var audioFiles = [
    "http://www.soundjay.com/button/beep-01a.mp3",
    "http://www.soundjay.com/button/beep-02.mp3",
    "http://www.soundjay.com/button/beep-03.mp3",
    "http://www.soundjay.com/button/beep-05.mp3"
];

function Preload(url) {
    var audio = new Audio();
    // once this file loads, it will call loadedAudio()
    // the file will be kept by the browser as cache
    audio.addEventListener('canplaythrough', loadedAudio, false);
    audio.src = url;
}

var loaded = 0;
function loadedAudio() {
    // this will be called every time an audio file is loaded
    // we keep track of the loaded files vs the requested files
    loaded++;
    if (loaded == audioFiles.length){
        // all have loaded
        init();
    }
}

var player = document.createElement('audio');
function playAudio(index) {
    player.src = audioFiles[index];
    player.play();
}

function init() {
    $('div').click(function(event) {
        $(this).css('background', 'blue');

        playAudio(Math.floor(Math.random()*audioFiles.length));
        player.addEventListener("ended", function(){
             player.currentTime = 0;
             $(event.target).closest('div').css('background', '#dda');
        });

    });
}

// We begin to upload files array
for (var i in audioFiles) {
    Preload(audioFiles[i]);
}


 });
 </script>
Dev. Joel
  • 1,127
  • 1
  • 9
  • 14
  • Very complete answer :) – mhatch Aug 31 '16 at 03:50
  • Here's the link to the answer quoted above http://stackoverflow.com/a/21492698/4084574 – mhatch Aug 31 '16 at 05:27
  • I am using 'this' element to pick up the individual div which has been clicked (because there are lots on the page which are created dynamically from the DB. For the initial change style before playing I can just use the 'this' selector, but as the second change is in a function within the event listener, how can I pass the 'this' value into that function or how else can I pick up the same element? – Amit Aug 31 '16 at 05:39
  • @Amit I modified my answer, check – Dev. Joel Aug 31 '16 at 06:05
  • I just set the div ID to a variable in the outer function and then reused it in the event listener. All working. – Amit Aug 31 '16 at 06:07
  • Well the formatting and audio is working but how would I go about preloading the files onpage load so there is not a lag when the buttons are clicked? – Amit Sep 01 '16 at 00:08