Using WavePlayer with AJAX-powered Themes

AJAX (Asynchronous Javascript And Xml) is a technique incorporated by many themes and plugins nowadays. If you ever experienced a website that is capable of loading new web content in single portions of a web page, without the need to reload the whole page itself, you have already used – albeit without knowing it – AJAX.

In the WordPress ecosystem, themes use AJAX to offer a more fluid pagination experience to their customers. Also WavePlayer uses AJAX to complete several tasks: retrieving the information of the tracks loaded inside an instance, sending to the cart the information of the product the user has just added, updating the statistics of a track or the number of likes or downloads when a user clicks on a button. The advantage of using AJAX is that, whatever the visitors are doing on your website, all these operations won’t interrupt them, because the page doesn’t refresh, but the content of the page will reflect anyway the changes they made to the page.

If you like to read more about AJAX, I recommend you this AJAX INTRODUCTION on W3Schools.

WORKING WITH WAVEPLAYER AND AJAX

When the portion of the page the theme is loading via AJAX contains an instance of WavePlayer, the instance needs to be initialized manually. The reason is that the script that initializes all the instances of WavePlayer in a page has already run at the completion of the page loading. Thus, when the theme loads the new content via AJAX, you need to call the initialization function after the new content finishes loading. Otherwise, the markup of the player will be in the page, but the player never gets initialized.

The main function initializing the instances of WavePlayer on a page is loadInstances() and can be called as follows:

WavePlayer.loadInstances();

The main problem, here, is finding where we can call that function. Since the AJAX is by design an asynchronous operation (we cannot predict when the visitor is going to click on a pagination link or update a post search), we need to attach the initialization function to an event that fires after the new content has completed loading. In the next two paragraphs we are going to describe the main two scenarios you will see when using an AJAX-powered theme.

THE TRIGGER METHOD

Any AJAX operation starts with a Javascript call attached to an action of the visitor (the click on a button or the change of a selection). If the scripts of your theme are developed keeping in mind the web developer who needs to extend their functionalities, at some point in the code where the AJAX request returns the content of the page, you will find a call to a trigger method. This is a very basic example of an AJAX request that triggers a “content-loaded” event for the current document:

function searchPosts(keys) {
    $.ajax({
        type: 'post',
        dataType: 'json',
        data: {
            action: 'my_theme_search_posts',
            keys: keys
        },
        success: function( result ) {
            $('#search-container').html(result.html);
            $(document).trigger('content-loaded');
        }
    });
}

In that scenario, calling the loadInstances() function would be as simple as adding the following script to the “Custom JavaScript” text box of the WavePlayer Settings, in the HTML & CSS page:

$(document).on('content-loaded', function(event) {
    WavePlayer.loadInstances();
})

What happens is that, after the theme script retrieves the content it requested and triggers the content-loaded event, the document calls all the scripts bound to that event, including the one we added to the Custom JavaScript box.

In this scenario, the most important aspect is finding the information about the event triggered upon loading of nw content via AJAX. Usually, those events are mentioned in the theme documentation. If they are not, a short research in the theme script, using the keyword “trigger” should help you find what you need.

THE CUSTOM SCRIPT in the THEME OPTIONS

Some more advanced themes provide you with a Custom Javascript option, offering you the possibility to bind a script to a certain event. In that case, you only have to find the right place in the theme settings where to write the loadInstances() function, but the principle is still the same.

IF NOTHING WORKS

If none of the previous options are available and contacting the theme developer does not help, the last resource you can try is binding the loadInstances() method directly to the object responsible for sending the AJAX request (the button, the link, the dropdown box). Because of its asynchronous nature, though, we cannot predict when the AJAX request is going to return the values it gets from the server. Thus, the problem is that if we call the loadInstances() method BEFORE the AJAX request has returned, the method is not going to initialize any instance. A possible solution to that – but far less ideal than the previous approaches – is delaying the call to loadInstances() using a setTimeout() function with a reasonably long delay time.

In the following example, the loadInstances() method is bound directly to the click event of the pagination link:

$(document).on('click', '.pagination a', function(event) {
    setTimeout(function(e){
        WavePlayer.loadInstance();
    }, 2000);
});

The evident problem with that approach is that the loadInstances() method gets called 2 seconds (2000 ms) after the visitor clicked on the pagination link. If the AJAX call has not returned in those 2 seconds, the loadInstances() will have nothing to initialize, as the new content has not been loaded yet. Conversely, if the AJAX call returns in 100ms, the loadInstances() won’t be called for the subsequent 1900ms because the timeout has not fired yet.