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;
}