jplayer playlist with jquery sortable?

498 views
Skip to first unread message

John Lim

unread,
Feb 13, 2014, 1:25:02 AM2/13/14
to jpl...@googlegroups.com
currently i am trying to use the jquery sortable UI to drag sort my playlist but it is not happening when the sorting is done but the player does not recognize the order and still play the previous order. 

tried my search on this and found this 

but apparent this is still using the jplayer.playlist.js....currently mine is jplayer.playlist.min.js which the codes are different and i am unable to apply this patch...is there a way for the latest build?

Mark Panaghiston

unread,
Feb 13, 2014, 10:21:40 AM2/13/14
to jpl...@googlegroups.com
If you know GIT, then clone the jplayer repo, then pull in this pull request to your local copy.
https://github.com/happyworm/jPlayer/pull/57

Since the core of jPlayer is starting to mature, I should really focus on the playlist part a little more again during my next review. I wrote that original playlist code in a few days just to try and formalize it a little more... Previously, it was just a bit of code in a demo and was not very pretty at all... Functional, but not well written.

That pull request should do what you needs... And if you are not into GIT, then take the plunge and set it up on your computer and start making your own repos.

John Lim

unread,
Feb 13, 2014, 10:56:32 PM2/13/14
to jpl...@googlegroups.com
hi, thanks for the help but i have no idea abt GIT but i hope there will be an update for the playlist with this type of function (drag drop sort for the playlist).

Marc Dingena

unread,
Feb 17, 2014, 5:45:11 AM2/17/14
to jpl...@googlegroups.com
Hi John Lim,

I'm currently working on a 'playlist manager' for Tjoonz.com.
Playlists are saved in JSON format in a MySQL database. I retrieve my playlist's JSON code from it through AJAX, and load it into the myPlaylist object.

With the 'playlist manager' I'm creating, I would load the same JSON string from MySQL, then display the tracks in jQuery UI-sortable <li> elements.
When the user is done re-sorting the items and clicks save, it will analyze the <ul> elements for all <li> elements (the playlist's items), and create the new JSON string, and insert it back into the MySQL database.

From that moment forward, if this playlist is loaded into jPlayer, it should have the new order of items. Of course it's also possible to omit the MySQL database, but this will not be part of Tjoonz functionality (yet).

When I have some example code I will post it here, and you can take whatever you need from it.

John Lim

unread,
Feb 17, 2014, 11:02:15 PM2/17/14
to jpl...@googlegroups.com
Hi Marc,

would like to see your sample code and thanks for sharing. Cant wait to see how this works with mysql sync

Marc Dingena

unread,
Feb 18, 2014, 5:08:51 AM2/18/14
to jpl...@googlegroups.com
Hi John,

While I'm working on this solution, I posted a thread earlier on how I save and load playlists in a MySQL database. Perhaps it will help you set up MySQL playlist sync.
It is possible to omit MySQL, and you could directly instruct your jPlayer instance with a playlist JSON object instead of saving it into a database and then loading it from the database in your player. It will save you some database queries that way. The reason I am saving it in a database is because I want my users to be able to save their personal playlists in their account.

You could implement both ways, but for a re-sorted playlist to take effect immediately you do not necessarily need a MySQL database in between. Just create a string in JavaScript that contains the new playlist and put it into jPlayer.

John Lim

unread,
Feb 19, 2014, 4:39:57 AM2/19/14
to jpl...@googlegroups.com
Hi Marc,

from what i see your implementation is having the whole playlist into 1 row of mysql. Which i think is quite cool but currently for my side, i have implement the simple and old fashion way for each song into song table with playlistId and another playlist table. but i am not sure whether this is a good approach? 

Marc Dingena

unread,
Feb 19, 2014, 7:09:14 AM2/19/14
to jpl...@googlegroups.com
I think having a playlist as a single record is probably faster with querying the database. But your approach is probably a bit more flexible to 'mix and match' as desired. It really depends on your setup and reasons.

For my site, a single record per playlist is definitely better. Especially considering that jPlayer holds the playlist in a single JSON object, which you can "stringify" and "un-stringify" very easily in both PHP and JavaScript:

Saving a playlist into database:
  1. JavaScript grabs the playlist object, for example 'myPlaylist'.
    my_playlist_var
    JSON.stringify( myPlaylist.original );
  2. Send it to PHP by AJAX.
    $.ajax({
        type     : 'POST',
        url      : 'http://example.com/save-playlist.php',
        data     : {
            playlist_string   : my_playlist_var
        },
        dataType : 'json'
    });
  3. Catch it on the other side in PHP.
    $playlist_json = $_POST['playlist_string'];
  4. Insert / Update into your database (if you use WordPress, you can use the $wpdb class).

Loading from database:
  1. JavaScript asks PHP script for answer through AJAX.
  2. $.ajax({
        type     : 'POST',
        url      : 'http://example.com/load-playlist.php',
        data     : {
            'playlist_id' : my_playlist_id_var
        },
        dataType : 'json'
    }).done(function( $answer_json ) {
        if( $answer_json.success ) {
            myPlaylist.option('autoPlay', true);
            myPlaylist.setPlaylist( JSON.parse( $answer_json.playlist_string ) );
            alert( 'Playlist loaded successfully!' );
        } else {
            alert( 'Error loading playlist!' );
        }
    });
  3. The above AJAX expects a JSON answer from the PHP script.
    $playlist_id = intval( $_POST['playlist_id'] );
    $playlist_string = //query database for playlist string using 
    $playlist_id
    die(
        json_encode(
            array(
                'success' => true,
                'playlist_string' => $playlist_string
            )

        )
    );
Note how the above colors correspond to each other in JavaScript and PHP.

Use JavaScript's JSON.parse() and JSON.stringify(), and PHP's json_encode() (and possibly json_decode(), but I don't have a use for it in my design).

John Lim

unread,
Feb 19, 2014, 11:22:59 PM2/19/14
to jpl...@googlegroups.com
so my question is that , for your site...it seems like there is no way a user could upload their own songs to build a playlist right? which means default jplayer on your site already has a list of fixed or controlled songs by you and user will only save those songs (fixed) am i right?

Marc Dingena

unread,
Feb 24, 2014, 1:50:42 AM2/24/14
to jpl...@googlegroups.com
Yes, it's a website where only our editors post new music content, and users can listen to it, and build their own playlists. They do not upload mixes to our site themselves.

I've been sick for a couple of days, so progress on coding sortable playlists is a bit slow...

Marc Dingena

unread,
Mar 19, 2014, 8:59:10 AM3/19/14
to jpl...@googlegroups.com
Hi John Lim, here is a simplified version of the code I am using on Tjoonz.com to create a Playlist Manager.
The basic flow is:
  • Placeholder UL element with sortable class, which will be targeted by jQuery sortable plugin.
  • PHP function to access MySQL database to fetch a playlist by ID, returns raw JSON in string text format (which needs to be parsed in JavaScript).
  • JavaScript handles the clicks on a "manage playlist link", sniffs out the playlist ID, and requests the PHP function to return the JSON string through AJAX.
  • When PHP returns the result to JavaScript, we check if the PHP function executed successfully (json.success boolean).
  • JavaScript then proceeds to interpret the raw JSON string, which we saved in json.message.
  • After parsing the message into actual JSON, we loop through all the object, which represent one item from the playlist each.
  • In every loop, we write the HTML code for one LI element which holds all data from the item from the playlist.
  • After looping through all playlist items, the string variable containing all the LI elements is inserted into our sortable UL element.
  • We call the jQuery sortable plugin on our filled UL element to make the LI elements sortable.
  • When the save link is clicked, JavaScript analyzes all the LI elements inside the sortable UL element (in their current order), and saves it into our database (as I described earlier in our conversation).
If you want to see a working example, please go to http://www.tjoonz.com/profiles/?u=marc-d and click the Manage Playlist icon next to one of my playlists. You will need an account, but it's free to register.

Here is the simplified code. For full code just check my site's source code. Take what you need.

HTML
<div id="playlist-manager"><!-- I've put this inside a modal window, the user can only close it with the Cancel or Save buttons -->
    <input id="playlist-manager-title" type="text" class="tjnz-input" placeholder="Name for your playlist" value="" />
    <span>Drag mixes to change their playlist order.</span>
    <ul class="sortable"></ul>
    <a href="javascript:;" class="manage-playlist-save">Save Playlist</a> <a href="javascript:;" class="manage-playlist-cancel">Cancel</a>
</div>

<a href="javascript:;" class="manage-playlist" data-pid="1234" title="Title of the playlist">Manage playlist with ID 1234</a>


jQuery and JavaScript
function tjnz_managePlaylist( list_id ) {
    $.ajax({
        type : 'POST',
        url  : 'http://www.example.com/ajax.php',
        data : {
            action  : 'tjnz-manage-playlist', // name of function to execute in your php file
            list_id : list_id
        },
        dataType: 'json'
    }).done(function( json ) {
        if( json.success ) {
            var playlistItems = JSON.parse( json.message ); // convert string to JSON and save in var
            var playlistItem = null;
            var playlistHtml = '';
            for( var i = 0; i < playlistItems.length; ++i ) { // loop through the parsed JSON objects, each object represents 1 item from the playlist
                playlistItem = playlistItems[i]; // saving the current object as a new variable
                playlistHtml += '<li>';
                playlistHtml += '<small><a class="playlist-manager-remove-item" href="#" title="Remove \'' + playlistItem.title + '\' from playlist" target="_blank">X</a></small> ';
                // adding hidden elements to the HTML so that later when we save the new re-ordered playlist we still have all the required playlist information
                playlistHtml += '<span class="hidden jp-page-id-' + playlistItem.id + '">' + playlistItem.id + '</span>';
                playlistHtml += '<span class="hidden jp-page-url-' + playlistItem.id + '">' + playlistItem.page + '</span>';
                playlistHtml += '<span class="hidden jp-genre-' + playlistItem.id + '">' + playlistItem.genre + '</span>';
                playlistHtml += '<span class="hidden jp-mp3-' + playlistItem.id + '">' + playlistItem.mp3 + '</span>';
                playlistHtml += '<div class="art"><img src="' + playlistItem.thumb + '" class="artwork jp-artwork-' + playlistItem.id + ' wp-post-image" alt="' + playlistItem.title + '"><span id="poster-url-' + playlistItem.id + '" class="hidden">' + playlistItem.poster + '</span></div>';
                playlistHtml += '<div class="meta"><span class="jp-title-' + playlistItem.id + '">' + playlistItem.title + '</span> <small>&nbsp;by&nbsp;</small> <span class="jp-artist-' + playlistItem.id + '">' + playlistItem.artist + '</span></div>';
                playlistHtml += '</li>';
            }
            $('#playlist-manager ul').html( playlistHtml ); // after looping through all JSON objects, set our filled HTML variable as the new HTML for the 'sortable UL' element
            $('.sortable').sortable(); // call the sortable jQuery plugin on our UL with class 'sortable' to make its elements, well... sortable! =)
        } else {
            alert( json.message ); // something went wrong, output the error message generated by the PHP code
        }
    }).fail(function() {
        // the AJAX call failed, try again
    }).always(function() {
        // you can do something here, like stopping a loading animation or changing your mouse cursor back to normal
    });
}

$('body').on('click', '.playlist-manager-remove-item', function(e) {
    e.preventDefault();
    $(this).parents( '#playlist-manager ul.sortable li' ).slideUp( 300, function() { $(this).remove(); } );
});

$('body').on('click', '.manage-playlist', function(e) {
    e.preventDefault(); 
    var list_id = $(this).attr( 'data-pid' );
    var list_name = $(this).attr( 'title' );
    $('#playlist-manager-title').val( list_name ); // sets the text field in the playlist manager div to the mix's name
    tjnz_managePlaylist( list_id ); // runs the function to fetch the playlist data for the given ID and fill the UL element
});

$('body').on('click', '.manage-playlist-cancel', function(e) {
    e.preventDefault();
    $('#playlist-manager ul').html( '' );
});

$('body').on('click', '.manage-playlist-save', function(e) {
    e.preventDefault();
    $('#playlist-manager-title').val( $.trim( $('#playlist-manager-title').val() ) ); // strip out spaces in front and back
    if( $.trim( $('#playlist-manager-title').val() ) == '' ) {
        alert( "Please give your playlist a name." );
        return false;
    }
    var json = new Array();
    $('#playlist-manager ul.sortable li').each( function() { // this each loop will scrape the required data from the current LI element and save it into the new items array. At the end, all items' elements are joined together and enclosed in {} brackets, then inserted into the json array.
        var items = new Array();
        items.push('"id":"' + $(this).find( 'span[class^="hidden jp-page-id-"]' ).text() + '"');
        items.push('"title":"' + tjnz_addslashes( $(this).find( 'span[class^="jp-title-"]' ).text() ) + '"');
        items.push('"artist":"' + tjnz_addslashes( $(this).find( 'span[class^="jp-artist-"]' ).text() ) + '"');
        items.push('"genre":"' + $(this).find( 'span[class^="hidden jp-genre-"]' ).text() + '"');
        items.push('"mp3":"' + $(this).find( 'span[class^="hidden jp-mp3-"]' ).text() + '"');
        items.push('"poster":"' + $(this).find( 'span[id^="poster-url-"]' ).text() + '"');
        items.push('"thumb":"' + $(this).find( 'img[class^="artwork jp-artwork-"]' ).attr( 'src' ) + '"');
        items.push('"page":"' + $(this).find( 'span[class^="hidden jp-page-url-"]' ).text() + '"');
        items.push('"actiontype":"play"');
        json.push( '{' + items.join() + '}' );
    });
    tjnz_playlistSave( $.trim( $('#playlist-manager-title').val() ), '[' + json + ']' );
    // this function I have demonstrated earlier in our conversation
    // this will save the playlist as a NEW playlist.
    // You may require an "update" function instead to update existing playlists in the database.
    // I have this in my site's live code, and depending if the user managing the playlist is
    // the original owner, I update or save the playlist.
});


PHP
/* Function: Get playlist for Playlist Manager
 * Since: 8.2
 */
add_action( 'wp_ajax_tjnz-manage-playlist', 'tjnz_manage_playlist' ); // bind the 'action' data POSTed by AJAX to the following PHP function
add_action( 'wp_ajax_nopriv_tjnz-manage-playlist', 'tjnz_manage_playlist' );
function tjnz_manage_playlist() {
    // extract POST data
    $list_id = intval( $_POST['list_id'] );
    
    // verify data
    if( $list_id <= 1 ) { // could be 0 in your case, but I have reserved playlist ID 1 for a tour playlist that is owned by nobody
        die( json_encode(array('success'=>false, 'message'=>"Don't try anything funny, dude...")) );
    }
    
    // get playlist json from WordPress database
    global $wpdb, $current_user;
    get_currentuserinfo();
    $playlist_owner = ( $current_user->ID == $user_id ? true : false );
    $table_name = $wpdb->prefix . 'tjnz_playlists';
    $sql     = "SELECT `json` FROM $table_name WHERE `list_id` = %u;";
    $json    = $wpdb->get_var( $wpdb->prepare( $sql, $list_id ) );
    if( $json == null )    { die( json_encode(array('success'=>false, 'message'=>'Durr... we couldn\'t find that playlist.')) ); }
    else                   { die( json_encode(array('success'=>true, 'owner'=>$playlist_owner, 'message'=>$json)) ); }
}
Reply all
Reply to author
Forward
0 new messages