How do I change the order of jPlayer playlist without affecting playback?

1k views Asked by At

Setting a new playlist object causes my jPlayer to stop playing music. I have also tried to re-order the playlist array but it seems jPlayer keeps two arrays (current and original) and it doesn't seem to correct its play index. Meaning that if you change the array in JavaScript, the playlist will no longer behave correctly.

Is there a way to change the playlist's order of items without resetting the playlist object?

2

There are 2 answers

0
Marc Dingena On BEST ANSWER

I've written a fork of jPlayer 2.9.2 that enables sortable playlists without it affecting playback functionality.

jQuery UI Sortable support for jPlayer Playlists add-on

0
Marc Dingena On

jPlayer uses a JavaScript object to keep track of your playlist. But it also represents it in the DOM. If you re-order it in the DOM (for example, using jQuery UI Sortable), it's not synchronized with that JavaScript object.

But, it doesn't have to, since you can use the DOM to tell jPlayer about the new situation. You will need to add some extra information about each playlist item to make this work, so this solution is a bit of a hack.


Change the next and previous methods of the myPlaylist object

jplayer.playlist.min.js

Change

next:function(){var a=this.current+1<this.playlist.length?this.current+1:0;this.loop?0===a&&this.shuffled&&this.options.playlistOptions.shuffleOnLoop&&this.playlist.length>1?this.shuffle(!0,!0):this.play(a):a>0&&this.play(a)}

Into

next:function(){$(this).trigger("playlist_next")}

Change

previous:function(){var a=this.current-1>=0?this.current-1:this.playlist.length-1;(this.loop&&this.options.playlistOptions.loopOnPrevious||a<this.playlist.length-1)&&this.play(a)}

Into

previous:function(){$(this).trigger("playlist_previous")}

Inject a script tag for each playlist item

Change

_createListItem:function(b){var c=this,d="<li><div>";

Into

_createListItem:function(b){var c=this,d='<li><script class="jp-json" type="application/json">'+JSON.stringify(b)+'</script><div>';

Track your DOM playlist changes

For example, with jQuery UI Sortable plugin:

var playlistChanged = false;

$('.jp-playlist ul').sortable({
    update    : function( e, ui ) {
        playlistChanged = true;
    }
});

Create handlers for playlist behavior

function getCurrentPlaylistIndex() {
    var index = 0;
    $( '.jp-playlist ul li' ).each( function(){
        if( $( this ).hasClass( 'jp-playlist-current' ) ) {
            return false;
        }
        ++index;
    });
    return index;
}

function playNextJpItem() {
    var index = getCurrentPlaylistIndex();
    if( index == $( '.jp-playlist ul li' ).length ) {
        return false; // end of playlist reached, use index = 0 to cycle to beginning
    }
    if( playlistChanged ) {
        resetJpPlaylist();
    }
    myPlaylist.play( ++index );
}

function playPreviousJpItem() {
    var index = getCurrentPlaylistIndex();
    if( index == 0 ) {
        return false; // beginning of playlist reached, use index = length to cycle to end
    }
    if( playlistChanged ) {
        resetJpPlaylist();
    }
    myPlaylist.play( --index );
}

Bind the handlers to previous and next events

$( myPlaylist ).bind( 'playlist_next', function(e){
    playNextJpItem();
});
$( myPlaylist ).bind( 'playlist_previous', function(e){
    playPreviousJpItem();
});

If playlist DOM has changed, re-set myPlaylist's playlist array

Since this only occurs when the previous or next methods are called, the user expects the audio to stop playing anyways. This is your chance to rebuild the array to match your DOM again and instruct jPlayer to start playing from the previously known index, plus 1 or minus 1. Note: This function only rebuilds the array, the new index is to play is calculated in the previous and next handlers as shown earlier.

function resetJpPlaylist() {
    var playlist = new Array();
    $( '.jp-playlist ul li .jp-json' ).each( function( index, element ){
        playlist[ index ] = JSON.parse( $( element ).html() );
    });
    myPlaylist.setPlaylist( playlist );
    playlistChanged = false;
}