astrXbian/www/jukebox/plugins/code/playlistmanager.js

304 lines
12 KiB
JavaScript

var playlistManager = function() {
var pmg = null;
var holders = new Array();
function putTracks(holder, tracks, title) {
var html = '<input type="hidden" value="'+title+'">';
html += '<table class="plmantable" align="center"';
if (tracks.length > 0 && tracks[0].plimage != "") {
debug.log("PLAYLISTMANAGER",title,"has a background image of",tracks[0].plimage);
html += ' image-content="'+tracks[0].plimage+'"';
}
var t = decodeURIComponent(title);
html += '>'+'<tr class="tagh"><th colspan="2" align="center">'+t+'</th>';
if (!t.match(/ \(by /)) {
html += '<th width="20px"><i class="icon-floppy playlisticon clickicon infoclick plugclickable clickrenplaylist tooltip" title="'+language.gettext('label_renameplaylist')+'"></i></th>'+
'<th width="20px"><i class="icon-cancel-circled playlisticon clickicon infoclick plugclickable clickdelplaylist tooltip" title="'+language.gettext('label_deleteplaylist')+'"></i></th>';
}
html += '</tr>';
if (tracks.length == 0) {
// Add a blank entry so we've got something to drop onto. Also the dropping doesn't work
// without at least one sortable in the target.
html += '<tr class="sortable" name="dummy" romprpos="playmanitem_null"><td style="height:24px"></td></tr>';
} else {
for (var i in tracks) {
if (tracks[i].Type == 'stream') {
html += '<tr class="sortable draggable clickstream playable" name="'+tracks[i].Uri+'" streamname="'+tracks[i].Album+'" streamimg="'+tracks[i].Image+'" romprpos="playmanitem_'+i+'">';
} else {
html += '<tr class="sortable draggable clicktrack playable" name="'+tracks[i].Uri+'" romprpos="playmanitem_'+i+'">';
}
html += '<td width="40px"><img class="smallcover';
if (tracks[i].Image) {
html += '" src="'+tracks[i].Image;
} else {
html += ' notfound';
}
if (tracks[i].Type == "stream") {
html += '" name="'+tracks[i].key+'"/></td><td colspan="2" class="dan"><b>'+tracks[i].Album+'</b>';
if (tracks[i].Album == rompr_unknown_stream) {
html += '<br>'+tracks[i].Uri;
}
html += '</td>';
} else {
html += '" /></td><td colspan="2" class="dan"><b>'+tracks[i].Title+'</b>';
if (tracks[i].Artist && tracks[i].Artist != 'Spotify' && tracks[i].Artist != 'spotify') {
html += '<br><i>by</i> <b>'+tracks[i].Artist+'</b>';
}
if (tracks[i].Album) {
html += '<br><i>on</i> <b>'+tracks[i].Album+'</b>';
}
html += '</td>';
}
if (!t.match(/ \(by /)) {
html += '<td class="dogsticks" align="center" class="alignmid"><i class="icon-cancel-circled playlisticon clickicon infoclick plugclickable clickremplay" name="'+tracks[i].pos+'"></i></td>';
}
html += '</tr>';
}
}
html += '</table>';
holder.html(html);
}
function reloadPlaylist(list) {
$.ajax({
url: 'plugins/code/playlistmanager.php',
type: "POST",
data: {action: 'getlist'},
dataType: 'json'
})
.done(function(data) {
putTracks(holders[list], data[list], list);
browser.rePoint();
infobar.markCurrentTrack();
})
.fail(function() {
infobar.error(language.gettext('label_general_error'));
});
}
function getAllPlaylists() {
$.ajax({
url: 'plugins/code/playlistmanager.php',
type: "POST",
data: {action: 'getlist'},
dataType: 'json'
})
.done(playlistManager.doMainLayout)
.fail(function() {
infobar.error(language.gettext('label_general_error'));
pmg.slideToggle('fast');
});
}
return {
open: function() {
if (pmg == null) {
pmg = browser.registerExtraPlugin("pmg", language.gettext("label_playlistmanager"), playlistManager, 'https://fatg3erman.github.io/RompR/Using-Saved-Playlists#editing-your-saved-playlists');
if (layoutProcessor.supportsDragDrop) {
$("#pmgfoldup").append('<div class="containerbox padright">'+
'<div class="expand"><b>'+language.gettext("label_playlistmanagertop")+'</b></div>'+
'</div>');
}
$("#pmgfoldup").append('<div class="containerbox padright noselection">'+
'<div class="expand">'+
'<input class="enter inbrowser clearbox" name="newplaylistnameinput" type="text" />'+
'</div>'+
'<button class="fixed" onclick="playlistManager.createPlaylist()">'+language.gettext("button_createplaylist")+'</button>'+
'</div>');
$("#pmgfoldup").append('<div class="noselection fullwidth masonified" id="playmunger"></div>');
getAllPlaylists();
// $('#pmgfoldup .enter').on('keyup', onKeyUp);
} else {
browser.goToPlugin("pmg");
}
},
doMainLayout: function(data) {
debug.log("PLAYLISTMANAGER","Got data",data);
for (var i in data) {
debug.log("PLAYLISTMANAGER",i);
holders[i] = $('<div>', {class: 'tagholder selecotron noselection'}).appendTo($("#playmunger"));
putTracks(holders[i], data[i], i);
holders[i].sortableTrackList({
items: '.sortable',
outsidedrop: playlistManager.dropped,
insidedrop: playlistManager.dragstopped,
scroll: false,
allowdragout: true
// scrollparent: '#infopane',
// scrollspeed: 80,
// scrollzone: 20
});
holders[i].acceptDroppedTracks({
scroll: true,
scrollparent: '#infopane'
});
}
pmg.slideToggle('fast', function() {
cement = true;
browser.goToPlugin("pmg");
browser.rePoint($("#playmunger"), {itemSelector: '.tagholder', percentPosition: true });
infobar.markCurrentTrack();
pmg.imagesLoaded(browser.rePoint);
});
},
handleClick: function(element, event) {
if (element.hasClass('clickremplay')) {
var list = element.parent().parent().parent().parent().parent().children('input').first().val();
var pos = element.attr('name');
element.makeSpinner();
debug.log("PLAYLISTMANAGER","Removing Track",pos,"from playlist",list);
player.controller.deletePlaylistTrack(list,pos, function() {
player.controller.reloadPlaylists();
reloadPlaylist(list);
});
} else if (element.hasClass('clickdelplaylist')) {
var list = element.parent().parent().parent().parent().prev().val();
var holder = element.parent().parent().parent().parent().parent();
debug.log("PLAYLISTMANAGER","Deleting Playlist",list);
player.controller.deletePlaylist(list,function() {
player.controller.reloadPlaylists();
holder.fadeOut('fast', function() {
$("#playmunger").masonry('remove',holder);
browser.rePoint();
});
});
} else if (element.hasClass('clickrenplaylist')) {
var list = unescapeHtml(element.parent().parent().parent().parent().prev().val());
player.controller.renamePlaylist(list, event, player.controller.doRenamePlaylist);
} else if (element.hasClass('clickfoldupplaylist')) {
element.parent().parent().parent().children('tr.sortable').slideToggle('fast');
}
},
checkToUpdateTheThing: function(list) {
// Callback to handle case where track is removed from a playlist via the playlists list
if (pmg !== null) {
reloadPlaylist(list);
}
},
dropped: function(event, ui) {
event.stopImmediatePropagation();
var tracks = new Array();
var which_playlist = ui.parent().parent().parent().children('input').first().val();
$.each($('.selected').filter(removeOpenItems), function (index, element) {
if ($(element).hasClass('directory')) {
var uri = decodeURIComponent($(element).children('input').first().attr('name'));
debug.log("PLAYLISTMANAGER","Dragged Directory",uri,"to",which_playlist);
tracks.push({dir: uri});
} else if (element.hasAttribute('romprid')) {
var playlistinfo = playlist.getId($(element).attr('romprid'));
tracks.push({uri: playlistinfo.file});
} else {
var uri = decodeURIComponent($(element).attr("name"));
debug.log("PLAYLISTMANAGER","Dragged",uri,"to",which_playlist);
tracks.push({uri: uri});
}
});
$('.selected').removeClass('selected');
var moveto = null;
var playlistlength = 0;
var next = ui.next('.sortable').attr('romprpos');
if (next && next != 'playmanitem_null') {
debug.log("PLAYLISTMANAGER","Next Item Is",next);
next = next.replace(/playmanitem_/, '');
moveto = next;
playlistlength = ui.parent().children('.sortable').last().attr('romprpos');
if (playlistlength && playlistlength != 'playmanitem_null') {
playlistlength = parseInt(playlistlength.replace(/playmanitem_/,''));
playlistlength += 1;
}
}
if (tracks.length > 0) {
debug.log("PLAYLISTMANAGER","Dragged to position",moveto);
player.controller.addTracksToPlaylist(which_playlist,tracks,moveto,playlistlength,function() {
player.controller.reloadPlaylists();
player.controller.checkProgress();
reloadPlaylist(which_playlist);
});
}
},
close: function() {
pmg = null;
holders = [];
cement = false;
},
reloadAll: function() {
if (pmg) {
$("#playmunger").masonry('destroy');
$("#playmunger").empty();
holders = [];
pmg.hide();
getAllPlaylists();
}
},
dragstopped: function(event, ui) {
event.stopImmediatePropagation();
var playlist = ui.parent().parent().parent().children('input').val();
var item = ui.attr('romprpos');
item = item.replace(/playmanitem_/,'');
var next = ui.next().attr('romprpos');
if (typeof next == "undefined") {
next = ui.prev().attr('romprpos');
}
next = next.replace(/playmanitem_/,'');
if (next == 'null') next = 0;
debug.log("PLAYLISTMANAGER","Dragged item",item,"to position",next,"within playlist",playlist);
// Oooh it's daft but the position we have to send is the position AFTER the track has been
// taken out of the list but before it's been put back in.
if (next > item) next--;
player.controller.movePlaylistTracks(playlist,item,next,function() {
reloadPlaylist(playlist);
player.controller.checkProgress();
player.controller.reloadPlaylists();
});
},
createPlaylist: function() {
// We don't need to actually create the playlist at the mpd end because
// mpd will create it automatically if we add a track to it. And what's the point
// of an empty playlist?
var n = $('[name=newplaylistnameinput]').val();
if (n == '') {
return false;
}
var playlist = rawurlencode(n);
holders[playlist] = $('<div>', {class: 'tagholder selecotron noselection'}).prependTo($("#playmunger"));
putTracks(holders[playlist],[],playlist);
holders[playlist].acceptDroppedTracks({
scroll: true,
scrollparent: '#infopane'
});
holders[playlist].sortableTrackList({
items: '.sortable',
outsidedrop: playlistManager.dropped,
insidedrop: playlistManager.dragstopped,
scroll: true,
allowdragout: true,
scrollparent: '#infopane',
scrollspeed: 80,
scrollzone: 40
});
$("#playmunger").masonry('prepended', holders[playlist]);
browser.rePoint();
}
}
}();
pluginManager.setAction(language.gettext("label_playlistmanager"), playlistManager.open);
playlistManager.open();