astrXbian/www/jukebox/ui/uihelper.js

499 lines
17 KiB
JavaScript

// skin.js may redefine these jQuery functionss if necessary
jQuery.fn.menuReveal = function(callback) {
if (callback) {
this.slideToggle('fast',callback);
} else {
this.slideToggle('fast');
}
return this;
}
jQuery.fn.menuHide = function(callback) {
if (callback) {
this.slideToggle('fast',callback);
} else {
this.slideToggle('fast');
}
return this;
}
jQuery.fn.isOpen = function() {
return this.hasClass('icon-toggle-open');
}
jQuery.fn.isClosed = function() {
return this.hasClass('icon-toggle-closed');
}
jQuery.fn.toggleOpen = function() {
if (this.hasClass('icon-toggle-closed')) {
this.removeClass('icon-toggle-closed').addClass('icon-toggle-open');
}
return this;
}
jQuery.fn.toggleClosed = function() {
if (this.hasClass('icon-toggle-open')) {
this.removeClass('icon-toggle-open').addClass('icon-toggle-closed');
}
return this;
}
jQuery.fn.makeSpinner = function() {
return this.each(function() {
var originalclasses = new Array();
var classes = '';
if ($(this).attr("class")) {
var classes = $(this).attr("class").split(/\s/);
}
for (var i = 0, len = classes.length; i < len; i++) {
if (classes[i] == "invisible" || (/^icon/.test(classes[i]))) {
originalclasses.push(classes[i]);
$(this).removeClass(classes[i]);
}
}
$(this).attr("originalclass", originalclasses.join(" "));
$(this).addClass('icon-spin6 spinner');
});
}
jQuery.fn.stopSpinner = function() {
this.each(function() {
$(this).removeClass('icon-spin6 spinner');
if ($(this).attr("originalclass")) {
$(this).addClass($(this).attr("originalclass"));
$(this).removeAttr("originalclass");
}
});
return this;
}
jQuery.fn.makeTagMenu = function(options) {
var settings = $.extend({
textboxname: "",
textboxextraclass: "",
labelhtml: "",
populatefunction: null,
buttontext: null,
buttonfunc: null,
buttonclass: ""
},options);
this.each(function() {
var tbc = "enter combobox-entry";
if (settings.textboxextraclass) {
tbc = tbc + " "+settings.textboxextraclass;
}
if ($(this).is('td')) {
$(this).prev().html(settings.labelhtml);
var holder = $('<div>', { class: "expand"}).appendTo($(this));
var textbox = $('<input>', { type: "text", class: tbc, name: settings.textboxname }).appendTo(holder);
var dropbox = $('<div>', {class: "drop-box tagmenu dropshadow"}).appendTo($(this));
} else {
$(this).append(settings.labelhtml);
var holder = $('<div>', { class: "expand"}).appendTo($(this));
var textbox = $('<input>', { type: "text", class: tbc, name: settings.textboxname }).appendTo(holder);
var dropbox = $('<div>', {class: "drop-box tagmenu dropshadow"}).insertAfter($(this));
}
var menucontents = $('<div>', {class: "tagmenu-contents"}).appendTo(dropbox);
if (settings.buttontext !== null) {
var submitbutton = $('<button>', {class: "fixed"+settings.buttonclass,
style: "margin-left: 8px"}).appendTo($(this));
submitbutton.html(settings.buttontext);
if (settings.buttonfunc) {
submitbutton.on('click', function() {
settings.buttonfunc(textbox.val());
});
}
}
dropbox.mCustomScrollbar({
theme: "light-thick",
scrollInertia: 120,
contentTouchScroll: 25,
advanced: {
updateOnContentResize: true,
updateOnImageLoad: false,
autoScrollOnFocus: false,
autoUpdateTimeout: 500,
}
});
textbox.on('click', function(ev) {
ev.preventDefault();
ev.stopPropagation();
var position = getPosition(ev);
// This function relies on the fact that the size of the background image
// that provides the icon we want to click on is 50% of the height of the element,
// as defined in the icon theme css
var elemright = textbox.width() + textbox.offset().left;
var elh = textbox.height()/2+2;
if (position.x > elemright - elh) {
if (dropbox.is(':visible')) {
dropbox.slideToggle('fast');
} else {
var data = settings.populatefunction(function(data) {
menucontents.empty();
for (var i in data) {
var d = $('<div>', {class: "backhi"}).appendTo(menucontents);
d.html(data[i]);
d.on('click', function() {
var cv = textbox.val();
if (cv != "") {
cv += ",";
}
cv += $(this).html();
textbox.val(cv);
});
}
dropbox.slideToggle('fast', function() {
dropbox.mCustomScrollbar("update");
});
});
}
}
});
});
}
jQuery.fn.fanoogleMenus = function() {
this.each( function() {
if ($(this).is(':visible')) {
var top = $(this).children().first().children('.mCSB_container').offset().top;
var conheight = $(this).children().first().children('.mCSB_container').height();
var ws = getWindowSize();
var avheight = ws.y - top;
var nh = Math.min(avheight, conheight);
$(this).css({height: nh+"px"});
$(this).mCustomScrollbar("update");
}
});
return this;
}
jQuery.fn.addBunnyEars = function() {
this.each(function() {
if ($(this).hasBunnyEars()) {
$(this).removeBunnyEars();
} else {
var w = $(this).outerWidth(true);
var up = $('<div>', { class: 'playlistup containerbox clickplaylist'}).prependTo($(this));
up.html('<i class="icon-increase medicon expand"></i>').css('width', w+'px');
var down = $('<div>', { class: 'playlistdown containerbox clickplaylist'}).appendTo($(this));
down.html('<i class="icon-decrease medicon expand"></i>').css('width', w+'px');
$(this).addClass('highlighted');
if ($(this).hasClass('item')) {
$(this).next().addClass('highlighted').slideUp('fast');
}
}
});
return this;
}
jQuery.fn.hasBunnyEars = function() {
if ($(this).find('.playlistup').length > 0) {
return true;
} else {
return false;
}
}
jQuery.fn.removeBunnyEars = function() {
this.each(function() {
$(this).find('.playlistup').remove();
$(this).find('.playlistdown').remove();
$(this).removeClass('highlighted');
if ($(this).hasClass('item')) {
$(this).next().removeClass('highlighted');
}
});
playlist.doPopMove();
return this;
}
// Functions that could just be in layoutProcessor, but it makes maintenance easier
// if we have a proxy like this so we don't have to add new stuff to every single skin.
var uiHelper = function() {
return {
findAlbumDisplayer: function(key) {
try {
return layoutProcessor.findAlbumDisplayer(key);
} catch (err) {
if ($("#"+key).length > 0) {
return $("#"+key);
} else {
return $('i[name="'+key+'"]').parent();
}
}
},
findAlbumParent: function(key) {
try {
return layoutProcessor.findAlbumParent(key);
} catch (err) {
return $('i[name="'+key+'"]').parent();
}
},
findArtistDisplayer: function(key) {
try {
return layoutProcessor.findArtistDisplayer(key);
} catch (err) {
if ($("#"+key).length > 0) {
// If it already exists
return $("#"+key);
} else {
// Opener div (standard UI)
return $('i[name="'+key+'"]').parent();
}
}
},
insertAlbum: function(v) {
try {
return layoutProcessor.insertAlbum(v);
} catch (err) {
var albumindex = v.id;
var reinsert = false;
$('#'+v.why+'album'+albumindex).html(v.tracklist);
// This may look slightly messy but re-inserting the dropdown instead
// of just removing it re-opening it is much cleaner from a user
// experience perspective.
var dropdown = $('#'+v.why+'album'+albumindex);
if (dropdown.is(':visible')) {
reinsert = true;
dropdown.detach().html(v.tracklist);
}
uiHelper.findAlbumParent(v.why+'album'+albumindex).remove();
switch (v.type) {
case 'insertAfter':
debug.log("Insert After",v.where);
$(v.html).insertAfter(uiHelper.findAlbumDisplayer(v.where));
break;
case 'insertAtStart':
debug.log("Insert At Start",v.where);
$(v.html).prependTo($('#'+v.where));
break;
}
if (reinsert) {
uiHelper.findAlbumDisplayer(v.why+'album'+albumindex).find('.menu').toggleOpen();
dropdown.insertAfter(uiHelper.findAlbumDisplayer(v.why+'album'+albumindex));
infobar.markCurrentTrack();
}
uiHelper.makeResumeBar(dropdown);
layoutProcessor.postAlbumActions();
}
},
insertArtist: function(v) {
try {
return layoutProcessor.insertArtist(v);
} catch(err) {
switch (v.type) {
case 'insertAfter':
debug.log("Insert After",v.where);
switch (prefs.sortcollectionby) {
case 'album':
case 'albumbyartist':
$(v.html).insertAfter(uiHelper.findAlbumDisplayer(v.where));
break;
case 'artist':
$(v.html).insertAfter(uiHelper.findArtistDisplayer(v.where));
break;
}
break;
case 'insertAtStart':
debug.log("Insert At Start",v.where);
$(v.html).prependTo($('#'+v.where));
break;
}
}
},
removeAlbum: function(key) {
try {
return layoutProcessor.removeAlbum(key);
} catch (err) {
$('#'+key).remove();
uiHelper.findAlbumDisplayer(key).remove();
uiHelper.findAlbumParent(key).remove();
layoutProcessor.postAlbumActions();
}
},
removeArtist: function(v) {
try {
return layoutProcessor.removeArtist(v);
} catch (err) {
$("#aartist"+v).remove();
uiHelper.findArtistDisplayer('aartist'+v).remove();
layoutProcessor.postAlbumActions();
}
},
setupPersonalRadio: function(key) {
try {
return layoutProcessor.setupPersonalRadio(key);
} catch (err) {
}
},
setupPersonalRadioAdditions: function(key) {
try {
return layoutProcessor.setupPersonalRadioAdditions(key);
} catch (err) {
}
},
emptySearchResults: function() {
try {
return layoutProcessor.emptySearchResults();
} catch (err) {
$('#searchresultholder').empty();
}
},
fixupArtistDiv: function(jq, name) {
try {
return layoutProcessor.fixupArtistDiv(jq, name);
} catch (err) {
}
},
hackForSkinsThatModifyStuff: function(id) {
try {
return layoutProcessor.hackForSkinsThatModifyStuff(id);
} catch (err) {
}
},
postPlaylistLoad: function() {
try {
return layoutProcessor.postPlaylistLoad();
} catch (err) {
}
},
getElementPlaylistOffset: function(element) {
try {
return layoutProcessor.getElementPlaylistOffset(element);
} catch (err) {
}
},
createPluginHolder: function(icon, title, id, panel) {
try {
return layoutProcessor.createPluginHolder(icon, title, id, panel);
} catch (err) {
return false;
}
},
makeDropHolder: function(name, d, dontsteal) {
try {
return layoutProcessor.makeDropHolder(name);
} catch (err) {
var c = 'topdropmenu dropshadow rightmenu normalmenu stayopen';
if (dontsteal) {
c += ' dontstealmyclicks';
}
return $('<div>', {class: c, id: name}).appendTo(d);
}
},
postAlbumMenu: function(element) {
try {
return layoutProcessor.postAlbumMenu(element);
} catch (err) {
}
},
postPodcastSubscribe: function(data, index) {
try {
return layoutProcessor.postPodcastSubscribe(data, index);
} catch (err) {
$('i[name="podcast_'+index+'"]').parent().fadeOut('fast', function() {
$('i[name="podcast_'+index+'"]').parent().remove();
$('#podcast_'+index).remove();
$("#fruitbat").html(data);
infobar.notify(language.gettext('label_subscribed'));
podcasts.doNewCount();
layoutProcessor.postAlbumActions();
});
}
},
panelMapping: function() {
try {
return layoutProcessor.panelMapping();
} catch(err) {
return {
"albumlist": 'albumlist',
"searcher": 'searcher',
"filelist": 'filelist',
"radiolist": 'radiolist',
"podcastslist": 'podcastslist',
"audiobooklist": 'audiobooklist',
"playlistslist": 'playlistslist',
"pluginplaylistslist": 'pluginplaylistslist'
}
}
},
makeResumeBar: function(target) {
try {
layoutProcessor.makeResumeBar(target);
} catch(err) {
target.find('input.resumepos').each(function() {
var pos = parseInt($(this).val());
var duration = parseInt($(this).next().val());
debug.log("PODCASTS", "Episode has a progress bar",pos,duration);
var thething = $(
'<div>',
{
class: 'containerbox fullwidth playlistrow2 dropdown-container podcastresume playable ',
name: $(this).prev().attr('name')
}
).insertBefore($(this));
thething.append('<div class="fixed padright">'+language.gettext('label_resume')+'</div>');
var bar = $('<div>', {class: 'expand', style: "height: 0.5em"}).appendTo(thething);
bar.rangechooser({range: duration, startmax: pos/duration, interactive: false});
});
}
},
setupCollectionDisplay: function() {
try {
layoutProcessor.setupCollectionDisplay();
} catch (err) {
}
},
showTagButton: function() {
try {
return layoutProcessor.showTagButton();
} catch (err) {
return true;
}
}
}
}();