dcsimg
www.webdeveloper.com
Results 1 to 14 of 14

Thread: Custom Audio Controls

  1. #1
    Join Date
    Apr 2009
    Posts
    368

    Custom Audio Controls

    I'm attempting to make a simple page that will list multiple audio files that can play independently of one another. I don't want to use the standard <audio controls>, but instead set something up with just a play button. I found the code below that seems simple enough, but I realize it's only for one audio file, and not multiple.

    HTML Code:
    <audio id="yourAudio" preload='none'>
        <source src='the url to the audio' type='audio/wav' />
    </audio>
    <a href="#" id="audioControl">play!</a>
    Code:
    var yourAudio = document.getElementById('yourAudio'),
        ctrl = document.getElementById('audioControl');
    
    ctrl.onclick = function () {
    
        // Update the Button
        var pause = ctrl.innerHTML === 'pause!';
        ctrl.innerHTML = pause ? 'play!' : 'pause!';
    
        // Update the Audio
        var method = pause ? 'pause' : 'play';
        yourAudio[method]();
    
        // Prevent Default Action
        return false;
    };
    My solution was just to give each audio file a separate ID (yourAudio1, yourAudio2, etc...), and write a new JS function for each audio file, but I was wondering if anyone knows a better solution. There will be dozens of audio files, so I was hoping to be able to make it a little less bloated and time consuming to do.

  2. #2
    Join Date
    Dec 2012
    Posts
    1,285
    Yes, it can be done by one function:
    HTML Code:
    <audio id="audio1" preload='none'>
        <source src='the url to the audio' type='audio/wav' />
    </audio>
    <a href="#" class="audioControl" data-audioid="audio1">play!</a>
    <audio id="audio2" preload='none'>
        <source src='the url to another audio' type='audio/wav' />
    </audio>
    <a href="#" class="audioControl" data-audioid="audio2">play!</a>
    [CODE]
    controls = document.getElementsByClassName("audioControls");
    fot (var i = 0; i < controls.length; i++) {
    controls[i].onclick = function () {
    // Update the Button
    var pause = ctrl.innerHTML === 'pause!';
    this.innerHTML = pause ? 'play!' : 'pause!';

    // Get audio from data attribute
    var yourAudioID = this.getAttribute("data-audioid");
    var yourAudo = document.getElementById(yourAudioID);

    // Update the Audio
    var method = pause ? 'pause' : %

  3. #3
    Join Date
    Jan 2004
    Location
    chertsey, a small town s.w. of london, england.
    Posts
    1,799
    Hi there Ntrimgs,

    try it like this...

    Code:
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
    
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,height=device-height,initial-scale=1">
    
    <title>untitled document</title>
    
    <link rel="stylesheet" href="screen.css" media="screen">
    
    <style>
    button {
        display: block;
        width: 5em;
        margin: 0.5em 0;
        box-shadow: 0.25em 0.25em 0.25em rgba(0, 0, 0, 0.3);
     }
    </style>
    
    </head>
    <body> 
    
    <div>
     <audio preload="none">
      <source src="the-url-to-the-audio.wav" type="audio/wav">
     </audio>
     <button>play</button>
    </div>
    
    <div>
     <audio preload="none">
      <source src="the-url-to-the-audio.wav" type="audio/wav">
     </audio>
     <button>play</button>
    </div>
    
    <div>
     <audio preload="none">
      <source src="the-url-to-the-audio.wav" type="audio/wav">
     </audio>
     <button>play</button>
    </div>
    
    <script>
    (function() {
       'use strict';
    
        var ctrl = document.getElementsByTagName('button');
    for(var c=0; c<ctrl.length; c++) {
        ctrl[c].addEventListener('click',audioControl(c),false);
     }
    
    function audioControl(c) {
    ctrl[c].onclick = function() {
       var sib = this.previousSibling;
        if(sib.type=3){
           sib = this.previousSibling.previousSibling;
    
        // Update the Button
        var pause = this.textContent === 'pause';
           this.textContent = pause ? 'play' : 'pause';
    
        // Update the Audio
        var method = pause ? 'pause' : 'play';
           sib[method]();
         }
        }
      }
    }());
    </script>
    
    </body>
    </html>

    coothead
    ~ the original bald headed old fart ~

  4. #4
    Join Date
    Dec 2012
    Posts
    1,285
    Editing failed, new attempt:
    HTML Code:
    <audio id="audio1" preload='none'>
        <source src='the url to the audio' type='audio/wav' />
    </audio>
    <a href="#" class="audioControl" data-audioid="audio1">play!</a>
    <audio id="audio2" preload='none'>
    <source src='the url to another audio' type='audio/wav' />
    </audio>
    <a href="#" class="audioControl" data-audioid="audio2">play!</a>
    Code:
    controls = document.getElementsByClassName("audioControls");
    fot (var i = 0; i < controls.length; i++) {
        controls[i].onclick = function () {
            // Update the Button
            var pause = ctrl.innerHTML === 'pause!';
            this.innerHTML = pause ? 'play!' : 'pause!';
    
            // Get audio from data attribute
            var yourAudioID = this.getAttribute("data-audioid");
            var yourAudo = document.getElementById(yourAudioID);
    
            // Update the Audio
            var method = pause ? 'pause' : 'play';
            yourAudio[method]();
    
           // Prevent Default Action
            return false;
        }
    };

  5. #5
    Join Date
    Apr 2009
    Posts
    368
    Quote Originally Posted by Sempervivum View Post
    Editing failed, new attempt:
    HTML Code:
    <audio id="audio1" preload='none'>
        <source src='the url to the audio' type='audio/wav' />
    </audio>
    <a href="#" class="audioControl" data-audioid="audio1">play!</a>
    <audio id="audio2" preload='none'>
    <source src='the url to another audio' type='audio/wav' />
    </audio>
    <a href="#" class="audioControl" data-audioid="audio2">play!</a>
    Code:
    controls = document.getElementsByClassName("audioControls");
    fot (var i = 0; i < controls.length; i++) {
        controls[i].onclick = function () {
            // Update the Button
            var pause = ctrl.innerHTML === 'pause!';
            this.innerHTML = pause ? 'play!' : 'pause!';
    
            // Get audio from data attribute
            var yourAudioID = this.getAttribute("data-audioid");
            var yourAudo = document.getElementById(yourAudioID);
    
            // Update the Audio
            var method = pause ? 'pause' : 'play';
            yourAudio[method]();
    
           // Prevent Default Action
            return false;
        }
    };
    Does audioControls in the JavaScript need to be audioControl to match the class in the HTML?

  6. #6
    Join Date
    Dec 2012
    Posts
    1,285
    You are right, there are still two errors in my script (didn't test it). This is correct:
    Code:
    controls = document.getElementsByClassName("audioControl");
    for (var i = 0; i < controls.length; i++) {

  7. #7
    Join Date
    Dec 2012
    Posts
    1,285
    Tested now and there where more errors in my script. This works:
    Code:
            <audio id="audio1" preload='none'>
                <source src='audio/Gong-1-2.mp3' type='audio/mpeg3' />
            </audio>
            <a href="#" class="audioControl" data-audioid="audio1">play!</a>
            <audio id="audio2" preload='none'>
                <source src='audio/Gong-1-3.mp3' type='audio/mpeg3' />
            </audio>
            <a href="#" class="audioControl" data-audioid="audio2">play!</a>
            <script>
                controls = document.getElementsByClassName("audioControl");
                for (var i = 0; i < controls.length; i++) {
                    controls[i].onclick = function () {
                        // Update the Button
                        var pause = this.innerHTML === 'pause!';
                        this.innerHTML = pause ? 'play!' : 'pause!';
    
                        // Get audio from data attribute
                        var yourAudioID = this.getAttribute("data-audioid");
                        var yourAudio = document.getElementById(yourAudioID);
    
                        // Update the Audio
                        var method = pause ? 'pause' : 'play';
                        yourAudio[method]();
    
                        // Prevent Default Action
                        return false;
                    }
                };
            </script>

  8. #8
    Join Date
    Apr 2009
    Posts
    368
    Quote Originally Posted by Sempervivum View Post
    Tested now and there where more errors in my script. This works:
    Code:
            <audio id="audio1" preload='none'>
                <source src='audio/Gong-1-2.mp3' type='audio/mpeg3' />
            </audio>
            <a href="#" class="audioControl" data-audioid="audio1">play!</a>
            <audio id="audio2" preload='none'>
                <source src='audio/Gong-1-3.mp3' type='audio/mpeg3' />
            </audio>
            <a href="#" class="audioControl" data-audioid="audio2">play!</a>
            <script>
                controls = document.getElementsByClassName("audioControl");
                for (var i = 0; i < controls.length; i++) {
                    controls[i].onclick = function () {
                        // Update the Button
                        var pause = this.innerHTML === 'pause!';
                        this.innerHTML = pause ? 'play!' : 'pause!';
    
                        // Get audio from data attribute
                        var yourAudioID = this.getAttribute("data-audioid");
                        var yourAudio = document.getElementById(yourAudioID);
    
                        // Update the Audio
                        var method = pause ? 'pause' : 'play';
                        yourAudio[method]();
    
                        // Prevent Default Action
                        return false;
                    }
                };
            </script>
    Thanks, that worked perfect!

  9. #9
    Join Date
    Apr 2009
    Posts
    368
    I was wondering how I could change this so it display an image of a play button, instead of saying "PLAY", and vice-versa for a pause button. I went and set the image in the control anchor like this:
    <a href="#" class="audioControl" data-audioid="audio2"><img src="images/play-btn.jpg"></a>

    But when the button is clicked, it reverts to displaying "PLAY" and "PAUSE". Is there a way to set this in the CSS, and change the class when it's clicked? That way I'll just set the btn as the background image...maybe?

  10. #10
    Join Date
    Dec 2012
    Posts
    1,285
    Yes, image as background and control by class is a good approach. This should do the job:
    Code:
        <style>
            .audioControl {
                display: inline-block;
                width: 42px;
                height: 44px;
                background-image: url(images/buttonplay.png);
            }
            .audioControl.playing {
                background-image: url(images/buttonpause.png);
            }
        </style>
        <audio id="audio1" preload='none'>
            <source src='audio/Gong-1-2.mp3' type='audio/mpeg3' />
        </audio>
        <a href="#" class="audioControl" data-audioid="audio1"></a>
        <audio id="audio2" preload='none'>
            <source src='audio/Gong-1-3.mp3' type='audio/mpeg3' />
        </audio>
        <a href="#" class="audioControl" data-audioid="audio2"></a>
        <script>
            var controls = document.getElementsByClassName("audioControl");
            for (var i = 0; i < controls.length; i++) {
                controls[i].onclick = function () {
                    // Get audio from data attribute
                    var yourAudioID = this.getAttribute("data-audioid");
                    var yourAudio = document.getElementById(yourAudioID);
                    // Update the Button
                    if (this.className.indexOf("playing") != -1) {
                        this.className = this.className.replace(" playing", "");
                        yourAudio.pause();
                    } else {
                        this.className = this.className + " playing";
                        yourAudio.play();
                    }
                    // Prevent Default Action
                    return false;
                }
            };
        </script>
    (you need to adjust the urls of the images to your own ones)

  11. #11
    Join Date
    Apr 2009
    Posts
    368
    Thanks again! That worked great.

  12. #12
    Join Date
    Apr 2009
    Posts
    368
    Quote Originally Posted by Sempervivum View Post
    Yes, image as background and control by class is a good approach. This should do the job:
    Code:
        <style>
            .audioControl {
                display: inline-block;
                width: 42px;
                height: 44px;
                background-image: url(images/buttonplay.png);
            }
            .audioControl.playing {
                background-image: url(images/buttonpause.png);
            }
        </style>
        <audio id="audio1" preload='none'>
            <source src='audio/Gong-1-2.mp3' type='audio/mpeg3' />
        </audio>
        <a href="#" class="audioControl" data-audioid="audio1"></a>
        <audio id="audio2" preload='none'>
            <source src='audio/Gong-1-3.mp3' type='audio/mpeg3' />
        </audio>
        <a href="#" class="audioControl" data-audioid="audio2"></a>
        <script>
            var controls = document.getElementsByClassName("audioControl");
            for (var i = 0; i < controls.length; i++) {
                controls[i].onclick = function () {
                    // Get audio from data attribute
                    var yourAudioID = this.getAttribute("data-audioid");
                    var yourAudio = document.getElementById(yourAudioID);
                    // Update the Button
                    if (this.className.indexOf("playing") != -1) {
                        this.className = this.className.replace(" playing", "");
                        yourAudio.pause();
                    } else {
                        this.className = this.className + " playing";
                        yourAudio.play();
                    }
                    // Prevent Default Action
                    return false;
                }
            };
        </script>
    (you need to adjust the urls of the images to your own ones)
    Sorry to be a bother, but I was wondering if there was a way to make the play button update back to play once the audio is finished playing. Currently it switches to pause once you hit play. And I was also wondering if there's a way that only one audio file can play at one time. So in other words, if someone tries playing a separate audio file, it stops the previous one?

  13. #13
    Join Date
    Dec 2012
    Posts
    1,285
    This should do the job:
    Code:
        <audio id="audio1" class="myaudio" preload='none'>
            <source src='audio/Gong-1-2.mp3' type='audio/mpeg3' />
        </audio>
        <a href="#" class="audioControl" data-audioid="audio1"></a>
        <audio id="audio2" class="myaudio" preload='none'>
            <source src='audio/Gong-1-3.mp3' type='audio/mpeg3' />
        </audio>
        <a href="#" class="audioControl" data-audioid="audio2"></a>
        <script>
            var audios = document.getElementsByClassName("myaudio");
            for (var i = 0; i < audios.length; i++) {
                audios[i].addEventListener("ended", function () {
                    var control = document.querySelector("[data-audioid='" + this.id + "']");
                    control.className = control.className.replace(" playing", "");
                });
            }
            var controls = document.getElementsByClassName("audioControl");
            for (var i = 0; i < controls.length; i++) {
                controls[i].onclick = function () {
                    // Get audio from data attribute
                    var yourAudioID = this.getAttribute("data-audioid");
                    var yourAudio = document.getElementById(yourAudioID);
                    // Update the Button
                    if (this.className.indexOf("playing") != -1) {
                        this.className = this.className.replace(" playing", "");
                        yourAudio.pause();
                    } else {
                        for (var i = 0; i < audios.length; i++) {
                            controls[i].className = controls[i].className.replace(" playing", "");
                            audios[i].pause();
                        }
                        this.className = this.className + " playing";
                        yourAudio.play();
                    }
                    // Prevent Default Action
                    return false;
                }
            };
        </script>
    Could be simplified by using jQuery.

  14. #14
    Join Date
    Apr 2009
    Posts
    368
    Quote Originally Posted by Sempervivum View Post
    This should do the job:
    Code:
        <audio id="audio1" class="myaudio" preload='none'>
            <source src='audio/Gong-1-2.mp3' type='audio/mpeg3' />
        </audio>
        <a href="#" class="audioControl" data-audioid="audio1"></a>
        <audio id="audio2" class="myaudio" preload='none'>
            <source src='audio/Gong-1-3.mp3' type='audio/mpeg3' />
        </audio>
        <a href="#" class="audioControl" data-audioid="audio2"></a>
        <script>
            var audios = document.getElementsByClassName("myaudio");
            for (var i = 0; i < audios.length; i++) {
                audios[i].addEventListener("ended", function () {
                    var control = document.querySelector("[data-audioid='" + this.id + "']");
                    control.className = control.className.replace(" playing", "");
                });
            }
            var controls = document.getElementsByClassName("audioControl");
            for (var i = 0; i < controls.length; i++) {
                controls[i].onclick = function () {
                    // Get audio from data attribute
                    var yourAudioID = this.getAttribute("data-audioid");
                    var yourAudio = document.getElementById(yourAudioID);
                    // Update the Button
                    if (this.className.indexOf("playing") != -1) {
                        this.className = this.className.replace(" playing", "");
                        yourAudio.pause();
                    } else {
                        for (var i = 0; i < audios.length; i++) {
                            controls[i].className = controls[i].className.replace(" playing", "");
                            audios[i].pause();
                        }
                        this.className = this.className + " playing";
                        yourAudio.play();
                    }
                    // Prevent Default Action
                    return false;
                }
            };
        </script>
    Could be simplified by using jQuery.
    Thanks so much! You really helped me out. Check your IM's.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles