jQuery Function malfunctioning after initial click

I have developed a function that plays and pauses music. It is designed to be simple and lightweight for small audio samples, with basic play and stop functionalities. The issue I'm encountering is that after playing the music for the second time, the classes are not switching correctly for pausing.

Below is the jQuery code snippet:

var isPlaying = false;
function playMusic(){
    var audioElement = document.createElement('audio');
    var audioElementSrc = $(this).attr('data-audio-src');               

    if (isPlaying != true)
    {
        isPlaying = true;
        audioElement.setAttribute('src', audioElementSrc);
        $.get();
        audioElement.addEventListener("loadeddata", function(){
            audioElement.play();                
        }, true);
        audioElement.addEventListener("ended", function() {
            isPlaying = false;    
        });  
        $(this).addClass('pause');
        $(this).removeClass('play'); 
        $('.pause').click(function() {
            audioElement.pause();
            isPlaying = false
            $(this).removeClass('pause');
            $(this).addClass('play');
        });             
    }
    else
    {
        return false;
    }           
}

$(function(e){
    $('.play').click(playMusic);  
});

You can view the jsfiddle Here which showcases the issue - when you click on stop and then try to play again, the classes do not switch as expected.

Answer №1

You have definitely made things more complicated by using plain JavaScript functions and replacing the audio element every time the play button is clicked.

Try incorporating more jQuery into your code and storing the audio element - it will make things much simpler

$(function (e) {
    $('.play').click(function() {
        var self = $(this).toggleClass('pause play');

        if (!this.audio) {
            this.audio = $('<audio />', {src : self.data('audio-src')}).on({
                loadeddata : function() {
                    this.play();
                },
                ended : function() {
                    self.toggleClass('pause play');
                }
            }).get(0);
        }else{
            this.audio[this.audio.paused ? 'play' : 'pause']();
        }
    });
});

FIDDLE

Answer №2

Upon reviewing the play code, I came across the following:

$('.pause').click(function() {
  audioElement.pause();
  isPlaying = false
  $(this).removeClass('pause');
  $(this).addClass('play');
});

The issue here is that this code is changing an element with the class .pause, which ends up overriding the function it's contained in! Additionally, the main if statement appears as follows:

if (isPlaying != true)
{
// Play code here           
}
else
{
return false;
}

What you actually need is:

    if (isPlaying != true)
    {
    // Play code here           
    }
    else
    {
    // Pause code here
    }

With these changes implemented, your new code will be structured like so:

 var isPlaying = false;
            function playTune(){
                    var audioTrack = document.createElement('audio');
                    var trackSource = $(this).attr('data-track-source');               

                    if (isPlaying != true)
                    {
                        isPlaying = true;
                        audioTrack.setAttribute('src', trackSource);
                        $.get();
                        audioTrack.addEventListener("loadeddata", function(){
                        audioTrack.play();                
                        }, true);
                         audioTrack.addEventListener("ended", function() {
                         isPlaying = false;    
                        });  
                        $(this).addClass('pause');
                        $(this).removeClass('play');            
                    }
                    else
                    {
                        audioTrack.pause(); 
                        isPlaying = false
                        $(this).removeClass('pause');
                        $(this).addClass('play');
                    }           
                }

            $(function(e){
                $('.play').click(playTune);  
            });

Answer №3

Avoid placing the code snippet within this section as it may cause issues. Instead, consider adding the pause function at the beginning only once using a delegate like this:

$(".songPlayer").delegate('.pause','click', function());

The issue arises from attaching the event on pause multiple times, leading to it being called repeatedly with each click.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Capture Video on iOS devices using the MediaRecorder API and display it using HTML5 Video Player

Issue: I am facing an issue where I cannot record video or get a video stream from the camera on iOS through my Angular web application built using ng build. Investigation: In my investigation, I explored various websites that discuss Apple iOS features ...

Tips for automatically inserting a "read more" link once text exceeds a certain character count

Currently utilizing an open-source code to fetch Google reviews, but facing an issue with long reviews. They are messing up the layout of my site. I need to limit the characters displayed for each review and provide an option for users to read the full rev ...

Utilizing inline javascript to dynamically update the selected option of a radio button

A form on my website includes two radio buttons: one labeled 'trigger_unit' and the other labeled 'normal_unit'. In addition, there is a select drop-down menu with four values and a default NULL option. <select rel="dropdown" name=" ...

What could be the reason my black overlay doesn't show up when the button is clicked?

Attempting to craft a pop-up window on my own, I encountered an issue. Upon pressing the button, instead of the anticipated pop-up appearing and darkening the background below it, the entire page freezes with no sign of the pop-up box. If I eliminate the ...

Tips for avoiding word wrapping in text with white spaces

I am currently experiencing an issue with word-wrapping in my category names when there are two words separated by a space. Below is the CSS code snippet: .post-item .cat { height: 25px; display: inline-block; background: #CC0000; font-size: 11px; paddin ...

Enhancing Transparency of WMS Layers in OpenLayers

I need help figuring out how to add transparency to a WMS layer in openlayers. Here is the current javascript code for a non-transparent layer: var lyr_GDPSETAAirtemperatureC = new ol.layer.Tile({ source: new ol.source.TileWMS(({ ...

Is it possible to create two custom WP queries that both use the same 'rand' parameter with the 'orderby' set to 'rand'?

My homepage currently displays 9 posts with a "Load More" button that fetches another 9 posts using ajax. The posts are ordered by date, but I want to change the order to random. However, when I use orderby rand in two wp_query instances, the second query ...

Tips for including event information in a form submission using Ajax and jQuery

I have successfully implemented the code below to send a request to the backend using ajax/jquery. My goal: Now, I am looking to dynamically capture form input data when the user interacts with the input fields and include this data in the ajax request. ...

Using Django to pass context data in a JsonResponse

Currently working on a webpage that incorporates filters to refine the displayed results. Upon triggering an Ajax call, the filters are transmitted to the Django backend for processing. The filtered data is then expected to be returned to the front-end. T ...

Reloading jQuery event handlers following successful ajax request

I have been working on implementing behavior for DOM objects that are added via AJAX. After reviewing the jQuery API Docs, I believe it would be most effective to incorporate a scoped onInit(scope) handler to handle event binding on the new content. Here ...

The conversion of a newline in an Angular page is done using &lt;br/&gt tag

Here is a function I have: setLocalVariableOnAccepted(ogp, hb, responseJson) { if (responseJson.ofgp === undefined) { this.ogpStatus = 'orange'; this.ogpStatusMsg = responseJson.ofgp + ', <br/> No change. Previous va ...

Is there a way to verify the presence of a specific sequence of words within a string using php

I need help with a jquery-ajax quiz that relies on php for validation. One particular question is about identifying the three main characters of a story, but the user may enter them in different sequences like char1 char2 char3    &nb ...

Steps to showcase specific data in the bootstrap multi-select dropdown menu sourced from the database

Utilizing CodeIgniter, I have set up multiple select dropdowns using bootstrap. The issue I am facing is with displaying the selected values in these drop-downs on the edit page. Would appreciate some guidance on how to tackle this problem. Here is a sni ...

Struggling to make AngularJS routes function properly

After starting from scratch, I rebuilt it with freshly downloaded angularJS (version 1.5.8). I simply placed both angular.js and angular-route.js in the library folder following this setup: https://gyazo.com/311679bf07249109671d621bc89d2d52 Here is how in ...

Troubleshooting problem with responsive image display and blurred effects

Initial problem I have a photo gallery on my website. When you click on a photo, you can view a larger preview. To cater to mobile users, I set the following CSS: .overview img { height: auto; width: 90%; } However, I am facing an issue where the hei ...

Is there a way to invoke a function within a mat-error element?

I need to display an error message in my input field! The function will return true if both passwords match, otherwise it will return false. How can I invoke a boolean function inside mat-error! My Function: checkPasswords(): Boolean { // 'passwords& ...

Hide, show, toggle, or empty elements using jQuery

I am having trouble getting this jQuery code to function properly. Within a div, there is a paragraph that I want to hide when a specific button is clicked and show when another button is clicked. Check out the code here $("#details").on("c ...

Is there a way in Angular to activate the contenteditable feature through a controller?

I have a collection of items, and the currently selected one is displayed in more detail on another section of the screen. The detailed section allows users to modify specific parts of the chosen item using contenteditable. When a user adds a new item to ...

Ways to enhance $.post() capabilities by incorporating additional features from $.ajax()

Can I customize the options and properties of jQuery's $.post() function? Sometimes I find myself needing to include additional properties in $.post(), such as async, beforeSend, contentType, context, crossDomain, error, global, headers, ifModified, ...

CKEditor's height automatically increases as the user types

I am using a ckEditor and looking for a way to make its height automatically grow as I type. https://i.stack.imgur.com/m7eyi.png <textarea name="description" id="description"> </textarea> <script> CKEDITOR.replace( 'description ...