';
- return songLi;
+ ''
+ return songLi
}
-function resultsToTables(results, target, uri) {
+function resultsToTables (results, target, uri) {
if (!results) {
- return;
+ return
}
- var tlids = [];
+ var tlids = []
if (target == CURRENT_PLAYLIST_TABLE) {
for (i = 0; i < results.length; i++) {
- tlids[i] = results[i].tlid;
- results[i] = results[i].track;
+ tlids[i] = results[i].tlid
+ results[i] = results[i].track
}
}
- var newalbum = [];
- var newtlids = [];
- //keep a list of track URIs for retrieving of covers
- var coversList = [];
- var nextname = '';
- var count = 0;
- $(target).html('');
+ var newalbum = []
+ var newtlids = []
+ // keep a list of track URIs for retrieving of covers
+ var coversList = []
+ var nextname = ''
+ var count = 0
+ $(target).html('')
- //break into albums and put in tables
- var html = '';
- var tableid, j, artistname, alburi, name, iconClass;
- var targetmin = target.substr(1);
- $(target).attr('data', uri);
- var length = 0 || results.length;
+ // break into albums and put in tables
+ var html = ''
+ var tableid, j, artistname, alburi, name, iconClass
+ var targetmin = target.substr(1)
+ $(target).attr('data', uri)
+ var length = 0 || results.length
for (i = 0; i < length; i++) {
- //create album if none extists
+ // create album if none extists
if (!results[i].album) {
- results[i].album = {"__model__": "Album"};
+ results[i].album = {'__model__': 'Album'}
}
- //create album uri if there is none
+ // create album uri if there is none
if (!results[i].album.uri) {
- results[i].album.uri = 'x';
+ results[i].album.uri = 'x'
}
if (!results[i].album.name) {
- results[i].album.name = '';
+ results[i].album.name = ''
}
- //create name if there is no one
+ // create name if there is no one
if (!results[i].name || results[i].name === '') {
- name = results[i].uri.split('/');
- results[i].name = decodeURI(name[name.length - 1]) || 'Track ' + String(i);
+ name = results[i].uri.split('/')
+ results[i].name = decodeURI(name[name.length - 1]) || 'Track ' + String(i)
}
- //leave out unplayable items
- if (results[i].name.substring(0, 12) == '[unplayable]') continue;
+ // leave out unplayable items
+ if (results[i].name.substring(0, 12) == '[unplayable]') continue
- newalbum.push(results[i]);
- newtlids.push(tlids[i]);
- nextname = '';
+ newalbum.push(results[i])
+ newtlids.push(tlids[i])
+ nextname = ''
if ((i < length - 1) && results[i + 1].album && results[i + 1].album.name) {
- nextname = results[i + 1].album.name;
+ nextname = results[i + 1].album.name
}
if (results[i].length == -1) {
- html += '
'
+ newalbum = []
+ newtlids = []
+ nextname = ''
} else {
if ((results[i].album.name != nextname) || (nextname === '')) {
- tableid = 'art' + i;
- //render differently if only one track in the album
+ tableid = 'art' + i
+ // render differently if only one track in the album
if (newalbum.length == 1) {
if (i !== 0) {
- html += '
';
+ html += '
'
}
- iconClass = getMediaClass(newalbum[0].uri);
- var liID = targetmin + '-' + newalbum[0].uri;
+ iconClass = getMediaClass(newalbum[0].uri)
+ var liID = targetmin + '-' + newalbum[0].uri
if (target == CURRENT_PLAYLIST_TABLE) {
html += '
'
}
- $('.popupArtistsLi').hide();
- $('.popupArtistsLv').html(child).show();
- $('.popupArtistsDiv').show();
+ $('.popupArtistsLi').hide()
+ $('.popupArtistsLv').html(child).show()
+ $('.popupArtistsDiv').show()
// this makes the viewport of the window resize somehow
- $('.popupArtistsLv').listview("refresh");
+ $('.popupArtistsLv').listview('refresh')
}
} else {
- $('.popupArtistsDiv').hide();
- $('.popupArtistsLi').hide();
+ $('.popupArtistsDiv').hide()
+ $('.popupArtistsLi').hide()
}
- var hash = document.location.hash.split('?');
- var divid = hash[0].substr(1);
- var popupName = '';
+ var hash = document.location.hash.split('?')
+ var divid = hash[0].substr(1)
+ var popupName = ''
if (divid == 'current') {
- $(".addqueue").hide();
- popupName = '#popupQueue';
+ $('.addqueue').hide()
+ popupName = '#popupQueue'
} else if (divid == 'browse') {
- $(".addqueue").show();
- popupName = '#popupBrowse';
+ $('.addqueue').show()
+ popupName = '#popupBrowse'
} else {
- $(".addqueue").show();
- popupName = '#popupTracks';
+ $('.addqueue').show()
+ popupName = '#popupTracks'
}
if (typeof tlid != 'undefined' && tlid !== '') {
- $(popupName).data("list", listuri).data("track", trackuri).data("tlid", tlid).popup("open", {
+ $(popupName).data('list', listuri).data('track', trackuri).data('tlid', tlid).popup('open', {
x : e.pageX,
y : e.pageY
- });
+ })
} else {
- $(popupName).data("list", listuri).data("track", trackuri).popup("open", {
+ $(popupName).data('list', listuri).data('track', trackuri).popup('open', {
x : e.pageX,
y : e.pageY
- });
+ })
}
- return false;
+ return false
}
-function showAlbumPopup(popupId) {
- uri = $(popupId).data("track");
- showAlbum(popupData[uri].album.uri);
+function showAlbumPopup (popupId) {
+ uri = $(popupId).data('track')
+ showAlbum(popupData[uri].album.uri)
}
-/**********************
+/** ********************
* initialize sockets *
**********************/
-function initSocketevents() {
- mopidy.on("state:online", function() {
- showOffline(false);
- getCurrentPlaylist();
- updateStatusOfAll();
- getPlaylists();
- getUriSchemes().then(function() {
- showFavourites();
- });
- getBrowseDir();
- getSearchSchemes();
- showLoading(false);
- $(window).hashchange();
- });
+function initSocketevents () {
+ mopidy.on('state:online', function () {
+ showOffline(false)
+ getCurrentPlaylist()
+ updateStatusOfAll()
+ getPlaylists()
+ getUriSchemes().then(function () {
+ showFavourites()
+ })
+ getBrowseDir()
+ getSearchSchemes()
+ showLoading(false)
+ $(window).hashchange()
+ })
- mopidy.on("state:offline", function() {
- resetSong();
- showOffline(true);
- });
+ mopidy.on('state:offline', function () {
+ resetSong()
+ showOffline(true)
+ })
- mopidy.on("event:optionsChanged", updateOptions);
+ mopidy.on('event:optionsChanged', updateOptions)
- mopidy.on("event:trackPlaybackStarted", function(data) {
- setSongInfo(data.tl_track);
- setPlayState(true);
- });
+ mopidy.on('event:trackPlaybackStarted', function (data) {
+ setSongInfo(data.tl_track)
+ setPlayState(true)
+ })
- mopidy.on("event:playlistsLoaded", function(data) {
- showLoading(true);
- getPlaylists();
- });
+ mopidy.on('event:playlistsLoaded', function (data) {
+ showLoading(true)
+ getPlaylists()
+ })
- mopidy.on("event:playlistChanged", function(data) {
- $('#playlisttracksdiv').hide();
- $('#playlistslistdiv').show();
- delete playlists[data.playlist.uri];
- getPlaylists();
- });
+ mopidy.on('event:playlistChanged', function (data) {
+ $('#playlisttracksdiv').hide()
+ $('#playlistslistdiv').show()
+ delete playlists[data.playlist.uri]
+ getPlaylists()
+ })
- mopidy.on("event:playlistDeleted", function(data) {
- $('#playlisttracksdiv').hide();
- $('#playlistslistdiv').show();
- delete playlists[data.uri];
- getPlaylists();
- });
+ mopidy.on('event:playlistDeleted', function (data) {
+ $('#playlisttracksdiv').hide()
+ $('#playlistslistdiv').show()
+ delete playlists[data.uri]
+ getPlaylists()
+ })
- mopidy.on("event:volumeChanged", function(data) {
- setVolume(data.volume);
- });
+ mopidy.on('event:volumeChanged', function (data) {
+ setVolume(data.volume)
+ })
- mopidy.on("event:muteChanged", function(data) {
- setMute(data.mute);
- });
+ mopidy.on('event:muteChanged', function (data) {
+ setMute(data.mute)
+ })
- mopidy.on("event:playbackStateChanged", function(data) {
+ mopidy.on('event:playbackStateChanged', function (data) {
switch (data.new_state) {
- case "paused":
- case "stopped":
- setPlayState(false);
- break;
- case "playing":
- setPlayState(true);
- break;
+ case 'paused':
+ case 'stopped':
+ setPlayState(false)
+ break
+ case 'playing':
+ setPlayState(true)
+ break
}
- });
+ })
- mopidy.on("event:tracklistChanged", function(data) {
- getCurrentPlaylist();
- });
+ mopidy.on('event:tracklistChanged', function (data) {
+ getCurrentPlaylist()
+ })
- mopidy.on("event:seeked", function(data) {
- setPosition(parseInt(data.time_position));
+ mopidy.on('event:seeked', function (data) {
+ setPosition(parseInt(data.time_position))
if (play) {
- startProgressTimer();
+ startProgressTimer()
}
- });
+ })
- mopidy.on("event:streamTitleChanged", function(data) {
- setSongTitle(data.title, true);
- });
+ mopidy.on('event:streamTitleChanged', function (data) {
+ setSongTitle(data.title, true)
+ })
}
-$(document).bind("pageinit", function() {
- resizeMb();
+$(document).bind('pageinit', function () {
+ resizeMb()
-});
+})
-/**************
+/** ************
* gui stuff *
**************/
-function toggleFullscreen() {
- if (isMobileSafari) { alert ("To get this app in Full Screen, you have to add it to your home-screen using the Share button."); exit(); }
- if (!isFullscreen() ) { // current working methods
- var docElm = document.documentElement;
+function toggleFullscreen () {
+ if (isMobileSafari) { alert('To get this app in Full Screen, you have to add it to your home-screen using the Share button.'); exit() }
+ if (!isFullscreen()) { // current working methods
+ var docElm = document.documentElement
if (docElm.requestFullscreen) {
- docElm.requestFullscreen();
+ docElm.requestFullscreen()
} else if (docElm.msRequestFullscreen) {
- docElm.msRequestFullscreen();
+ docElm.msRequestFullscreen()
} else if (docElm.mozRequestFullScreen) {
- docElm.mozRequestFullScreen();
+ docElm.mozRequestFullScreen()
} else if (docElm.webkitRequestFullScreen) {
- docElm.webkitRequestFullScreen();
+ docElm.webkitRequestFullScreen()
}
} else {
if (document.exitFullscreen) {
- document.exitFullscreen();
+ document.exitFullscreen()
} else if (document.msExitFullscreen) {
- document.msExitFullscreen();
+ document.msExitFullscreen()
} else if (document.mozCancelFullScreen) {
- document.mozCancelFullScreen();
+ document.mozCancelFullScreen()
} else if (document.webkitCancelFullScreen) {
- document.webkitCancelFullScreen();
+ document.webkitCancelFullScreen()
}
}
}
-function isFullscreen() {
+function isFullscreen () {
return (document.fullscreenElement || // alternative standard method
- document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement ); // current working methods
+ document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement) // current working methods
}
-function switchContent(divid, uri) {
- var hash = divid;
+function switchContent (divid, uri) {
+ var hash = divid
if (uri) {
- hash += "?" + uri;
+ hash += '?' + uri
}
- location.hash = "#" + hash;
+ location.hash = '#' + hash
}
-function setHeadline(site){
- site = site.trim();
- str = $('.mainNav').find('a[href$='+site+']').text();
- if(str === ""){
- str = site.charAt(0).toUpperCase() + site.slice(1);
+function setHeadline (site) {
+ site = site.trim()
+ str = $('.mainNav').find('a[href$=' + site + ']').text()
+ if (str === '') {
+ str = site.charAt(0).toUpperCase() + site.slice(1)
}
- $('#contentHeadline').html('' + str + '');
+ $('#contentHeadline').html('' + str + '')
}
-//update tracklist options.
-function updateOptions() {
- mopidy.tracklist.getRepeat().then(processRepeat, console.error);
- mopidy.tracklist.getRandom().then(processRandom, console.error);
- mopidy.tracklist.getConsume().then(processConsume, console.error);
- mopidy.tracklist.getSingle().then(processSingle, console.error);
+// update tracklist options.
+function updateOptions () {
+ mopidy.tracklist.getRepeat().then(processRepeat, console.error)
+ mopidy.tracklist.getRandom().then(processRandom, console.error)
+ mopidy.tracklist.getConsume().then(processConsume, console.error)
+ mopidy.tracklist.getSingle().then(processSingle, console.error)
}
-//update everything as if reloaded
-function updateStatusOfAll() {
- mopidy.playback.getCurrentTlTrack().then(processCurrenttrack, console.error);
- mopidy.playback.getTimePosition().then(processCurrentposition, console.error);
- mopidy.playback.getState().then(processPlaystate, console.error);
+// update everything as if reloaded
+function updateStatusOfAll () {
+ mopidy.playback.getCurrentTlTrack().then(processCurrenttrack, console.error)
+ mopidy.playback.getTimePosition().then(processCurrentposition, console.error)
+ mopidy.playback.getState().then(processPlaystate, console.error)
- updateOptions();
+ updateOptions()
- mopidy.playback.getVolume().then(processVolume, console.error);
- mopidy.mixer.getMute().then(processMute, console.error);
+ mopidy.playback.getVolume().then(processVolume, console.error)
+ mopidy.mixer.getMute().then(processMute, console.error)
}
-function locationHashChanged() {
- var hash = document.location.hash.split('?');
- //remove #
- var divid = hash[0].substr(1);
- setHeadline(divid);
+function locationHashChanged () {
+ var hash = document.location.hash.split('?')
+ // remove #
+ var divid = hash[0].substr(1)
+ setHeadline(divid)
- var uri = hash[1];
- $('.mainNav a').removeClass('ui-state-active ui-state-persist ui-btn-active');
- //i don't know why some li elements have those classes, but they do, so we need to remove them
- $('.mainNav li').removeClass('ui-state-active ui-state-persist ui-btn-active');
+ var uri = hash[1]
+ $('.mainNav a').removeClass('ui-state-active ui-state-persist ui-btn-active')
+ // i don't know why some li elements have those classes, but they do, so we need to remove them
+ $('.mainNav li').removeClass('ui-state-active ui-state-persist ui-btn-active')
if ($(window).width() < 560) {
- $("#panel").panel("close");
+ $('#panel').panel('close')
}
- $('.pane').hide();
+ $('.pane').hide()
- $('#' + divid + 'pane').show();
+ $('#' + divid + 'pane').show()
- switch(divid) {
+ switch (divid) {
case 'home':
- $('#navhome a').addClass('ui-state-active ui-state-persist ui-btn-active');
- break;
+ $('#navhome a').addClass('ui-state-active ui-state-persist ui-btn-active')
+ break
case 'nowPlaying':
- $('#navnowPlaying a').addClass('ui-state-active ui-state-persist ui-btn-active');
- break;
+ $('#navnowPlaying a').addClass('ui-state-active ui-state-persist ui-btn-active')
+ break
case 'current':
- $('#navcurrent a').addClass('ui-state-active ui-state-persist ui-btn-active');
- getCurrentPlaylist();
- break;
+ $('#navcurrent a').addClass('ui-state-active ui-state-persist ui-btn-active')
+ getCurrentPlaylist()
+ break
case 'playlists':
- $('#navplaylists a').addClass('ui-state-active ui-state-persist ui-btn-active');
- break;
+ $('#navplaylists a').addClass('ui-state-active ui-state-persist ui-btn-active')
+ break
case 'browse':
- $('#navbrowse a').addClass('ui-state-active ui-state-persist ui-btn-active');
- break;
+ $('#navbrowse a').addClass('ui-state-active ui-state-persist ui-btn-active')
+ break
case 'search':
- $('#navsearch a').addClass($.mobile.activeBtnClass);
- $("#searchinput").focus();
+ $('#navsearch a').addClass($.mobile.activeBtnClass)
+ $('#searchinput').focus()
if (customTracklists['mbw:allresultscache'] === '') {
- initSearch($('#searchinput').val());
+ initSearch($('#searchinput').val())
}
- break;
+ break
case 'stream':
- $('#navstream a').addClass('ui-state-active ui-state-persist ui-btn-active');
- break;
+ $('#navstream a').addClass('ui-state-active ui-state-persist ui-btn-active')
+ break
case 'artists':
if (uri !== '') {
- showArtist(uri);
+ showArtist(uri)
}
- break;
+ break
case 'albums':
if (uri !== '') {
- showAlbum(uri);
+ showAlbum(uri)
}
- break;
+ break
}
- //switch the footer
- switch(divid) {
+ // switch the footer
+ switch (divid) {
case 'nowPlaying':
- $('#normalFooter').hide();
- $('#nowPlayingFooter').show();
- break;
+ $('#normalFooter').hide()
+ $('#nowPlayingFooter').show()
+ break
default:
- $('#normalFooter').show();
- $('#nowPlayingFooter').hide();
+ $('#normalFooter').show()
+ $('#nowPlayingFooter').hide()
}
// Set the page title based on the hash.
- document.title = PROGRAM_NAME;
- return false;
+ document.title = PROGRAM_NAME
+ return false
}
-/***********************
+/** *********************
* initialize software *
***********************/
-$(document).ready(function(event) {
- //check for websockets
+$(document).ready(function (event) {
+ // check for websockets
if (!window.WebSocket) {
- switchContent("playlists");
- $('#playlistspane').html('
Old Browser
Sorry. Your browser isn\'t modern enough for this webapp. Modern versions of Chrome, Firefox, Safari all will do. Maybe Opera and Internet Explorer 10 also work, but it\'s not tested.
Sorry. Your browser isn\'t modern enough for this webapp. Modern versions of Chrome, Firefox, Safari all will do. Maybe Opera and Internet Explorer 10 also work, but it\'s not tested.
')
+ exit
}
- //workaround for a bug in jQuery Mobile, without that the panel doesn't close on mobile devices...
- $('.ui-panel-dismiss').on( "tap", function() { $("#panel").panel("close"); } );
- //end of workaround
+ // workaround for a bug in jQuery Mobile, without that the panel doesn't close on mobile devices...
+ $('.ui-panel-dismiss').on( 'tap', function () { $('#panel').panel('close') })
+ // end of workaround
- $(window).hashchange();
+ $(window).hashchange()
// Connect to server
if (websocketUrl) {
@@ -481,196 +481,196 @@ $(document).ready(function(event) {
mopidy = new Mopidy({
webSocketUrl: websocketUrl,
callingConvention: 'by-position-or-by-name'
- });
+ })
} catch (e) {
- showOffline(true);
+ showOffline(true)
}
} else {
try {
- mopidy = new Mopidy({callingConvention: 'by-position-or-by-name'});
- } catch (e) {
- showOffline(true);
- }
+ mopidy = new Mopidy({callingConvention: 'by-position-or-by-name'})
+ } catch (e) {
+ showOffline(true)
+ }
}
- //initialize events
- initSocketevents();
+ // initialize events
+ initSocketevents()
progressTimer = new ProgressTimer({
callback: timerCallback,
- //updateRate: 2000,
- });
+ // updateRate: 2000,
+ })
- resetSong();
+ resetSong()
if (location.hash.length < 2) {
- switchContent("home");
+ switchContent('home')
}
- initgui = false;
- window.onhashchange = locationHashChanged;
+ initgui = false
+ window.onhashchange = locationHashChanged
- //only show backbutton if in UIWebview
+ // only show backbutton if in UIWebview
if (window.navigator.standalone) {
- $("#btback").show();
+ $('#btback').show()
} else {
- $("#btback").hide();
+ $('#btback').hide()
}
- $(window).resize(function() {
- resizeMb();
- });
+ $(window).resize(function () {
+ resizeMb()
+ })
- //navigation temporary, rewrite this!
- $('#songinfo').click(function() {
- return switchContent('nowPlaying');
- });
- $('#controlspopupimage').click(function() {
- return switchContent('current');
- });
- $('#navToggleFullscreen').click(function() {
- toggleFullscreen();
- });
+ // navigation temporary, rewrite this!
+ $('#songinfo').click(function () {
+ return switchContent('nowPlaying')
+ })
+ $('#controlspopupimage').click(function () {
+ return switchContent('current')
+ })
+ $('#navToggleFullscreen').click(function () {
+ toggleFullscreen()
+ })
// event handlers for full screen mode
- $(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange, MSFullscreenChange', function(e) {
+ $(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange, MSFullscreenChange', function (e) {
if (isFullscreen()) {
- document.getElementById("toggletxt").innerHTML = "Exit Fullscreen";
+ document.getElementById('toggletxt').innerHTML = "Exit Fullscreen"
} else {
- document.getElementById("toggletxt").innerHTML = "Fullscreen";
+ document.getElementById('toggletxt').innerHTML = "Fullscreen"
}
- });
+ })
// remove buttons only for MusicBox
if (!isMusicBox) {
- $('#navSettings').hide();
- $('#navshutdown').hide();
- $('#homesettings').hide();
- $('#homeshutdown').hide();
+ $('#navSettings').hide()
+ $('#navshutdown').hide()
+ $('#homesettings').hide()
+ $('#homeshutdown').hide()
}
// remove Alarm Clock if it is not present
if (!hasAlarmClock) {
- $('#navAlarmClock').hide();
- $('#homeAlarmClock').hide();
- $('#homeAlarmClock').nextAll().find('.ui-block-a, .ui-block-b').toggleClass('ui-block-a').toggleClass('ui-block-b');
+ $('#navAlarmClock').hide()
+ $('#homeAlarmClock').hide()
+ $('#homeAlarmClock').nextAll().find('.ui-block-a, .ui-block-b').toggleClass('ui-block-a').toggleClass('ui-block-b')
}
- //navigation stuff
+ // navigation stuff
- $(document).keypress( function (event) {
- //console.log('kp: '+event);
- if (event.target.tagName != 'INPUT') {
- var unicode=event.keyCode? event.keyCode : event.charCode;
- var actualkey=String.fromCharCode(unicode);
- switch(actualkey) {
- case ' ':
- doPlay();
- event.preventDefault();
- break;
- case '>':
- doNext();
- event.preventDefault();
- break;
- case '<':
- doPrevious();
- event.preventDefault();
- break;
+ $(document).keypress(function (event) {
+ // console.log('kp: '+event);
+ if (event.target.tagName != 'INPUT') {
+ var unicode = event.keyCode ? event.keyCode : event.charCode
+ var actualkey = String.fromCharCode(unicode)
+ switch (actualkey) {
+ case ' ':
+ doPlay()
+ event.preventDefault()
+ break
+ case '>':
+ doNext()
+ event.preventDefault()
+ break
+ case '<':
+ doPrevious()
+ event.preventDefault()
+ break
}
- return true;
+ return true
}
- });
+ })
if ($(window).width() < 980) {
- $("#panel").panel("close");
- }else{
- $("#panel").panel("open");
+ $('#panel').panel('close')
+ } else {
+ $('#panel').panel('open')
}
- $.event.special.swipe.horizontalDistanceThreshold = 125; // (default: 30px) Swipe horizontal displacement must be more than this.
- $.event.special.swipe.verticalDistanceThreshold = 50; // (default: 75px) Swipe vertical displacement must be less than this.
- $.event.special.swipe.durationThreshold = 500;
+ $.event.special.swipe.horizontalDistanceThreshold = 125 // (default: 30px) Swipe horizontal displacement must be more than this.
+ $.event.special.swipe.verticalDistanceThreshold = 50 // (default: 75px) Swipe vertical displacement must be less than this.
+ $.event.special.swipe.durationThreshold = 500
// swipe songinfo and panel
- $( "#normalFooter, #nowPlayingFooter" ).on( "swiperight", doPrevious );
- $( "#normalFooter, #nowPlayingFooter" ).on( "swipeleft", doNext );
- $( "#nowPlayingpane, .ui-body-c, #header, #panel, .pane" ).on( "swiperight", function() {
- if(!$(event.target).is("#normalFooter") && !$(event.target).is("#nowPlayingFooter")) {
- $("#panel").panel("open");
- event.stopImmediatePropagation(); }
- } );
- $( "#nowPlayingpane, .ui-body-c, #header, #panel, .pane" ).on( "swipeleft", function() {
- if(!$(event.target).is("#normalFooter") && !$(event.target).is("#nowPlayingFooter")) {
- $("#panel").panel("close");
- event.stopImmediatePropagation(); }
- } );
+ $("#normalFooter, #nowPlayingFooter").on( 'swiperight', doPrevious)
+ $("#normalFooter, #nowPlayingFooter").on( 'swipeleft', doNext)
+ $("#nowPlayingpane, .ui-body-c, #header, #panel, .pane").on( 'swiperight', function () {
+ if (!$(event.target).is('#normalFooter') && !$(event.target).is('#nowPlayingFooter')) {
+ $('#panel').panel('open')
+ event.stopImmediatePropagation() }
+ })
+ $("#nowPlayingpane, .ui-body-c, #header, #panel, .pane").on( 'swipeleft', function () {
+ if (!$(event.target).is('#normalFooter') && !$(event.target).is('#nowPlayingFooter')) {
+ $('#panel').panel('close')
+ event.stopImmediatePropagation() }
+ })
- $( "#trackslider" ).on( "slidestart", function() {
- progressTimer.stop();
- $( "#trackslider" ).on( "change", function() { updatePosition( $(this).val() ); } );
- } );
+ $("#trackslider").on( 'slidestart', function () {
+ progressTimer.stop()
+ $("#trackslider").on( 'change', function () { updatePosition($(this).val()) })
+ })
- $( "#trackslider" ).on( "slidestop", function() {
- $( "#trackslider" ).off( "change");
- doSeekPos( $(this).val() );
- } );
+ $("#trackslider").on( 'slidestop', function () {
+ $("#trackslider").off( 'change')
+ doSeekPos($(this).val())
+ })
- $( "#volumeslider" ).on( "slidestart", function() { volumeSliding = true; } );
- $( "#volumeslider" ).on( "slidestop", function() { volumeSliding = false; } );
- $( "#volumeslider" ).on( "change", function() { doVolume( $(this).val() ); } );
-});
+ $("#volumeslider").on( 'slidestart', function () { volumeSliding = true })
+ $("#volumeslider").on( 'slidestop', function () { volumeSliding = false })
+ $("#volumeslider").on( 'change', function () { doVolume($(this).val()) })
+})
function updatePlayIcons (uri, tlid) {
- //update styles of listviews
- $('#currenttable li').each(function() {
- var eachTlid = $(this).attr('tlid');
+ // update styles of listviews
+ $('#currenttable li').each(function () {
+ var eachTlid = $(this).attr('tlid')
if (typeof eachTlid != 'undefined') {
- eachTlid = parseInt(eachTlid);
+ eachTlid = parseInt(eachTlid)
}
if (this.id == 'currenttable-' + uri && eachTlid == tlid) {
- $(this).addClass('currenttrack');
+ $(this).addClass('currenttrack')
} else {
- $(this).removeClass("currenttrack");
- }
- });
+ $(this).removeClass('currenttrack')
+ }
+ })
- $('#playlisttracks li').each(function() {
+ $('#playlisttracks li').each(function () {
if (this.id == 'playlisttracks-' + uri) {
- $(this).addClass('currenttrack2');
+ $(this).addClass('currenttrack2')
} else {
- $(this).removeClass("currenttrack2");
- }
- });
+ $(this).removeClass('currenttrack2')
+ }
+ })
- $('#trackresulttable li').each(function() {
+ $('#trackresulttable li').each(function () {
if (this.id == 'trackresulttable-' + uri) {
- $(this).addClass('currenttrack2');
+ $(this).addClass('currenttrack2')
} else {
- $(this).removeClass("currenttrack2");
- }
- });
+ $(this).removeClass('currenttrack2')
+ }
+ })
- $('#artiststable li').each(function() {
+ $('#artiststable li').each(function () {
if (this.id == 'artiststable-' + uri) {
- $(this).addClass('currenttrack2');
+ $(this).addClass('currenttrack2')
} else {
- $(this).removeClass("currenttrack2");
- }
- });
+ $(this).removeClass('currenttrack2')
+ }
+ })
- $('#albumstable li').each(function() {
+ $('#albumstable li').each(function () {
if (this.id == 'albumstable-' + uri) {
- $(this).addClass('currenttrack2');
+ $(this).addClass('currenttrack2')
} else {
- $(this).removeClass("currenttrack2");
- }
- });
- $('#browselist li').each(function() {
+ $(this).removeClass('currenttrack2')
+ }
+ })
+ $('#browselist li').each(function () {
if (this.id == 'browselisttracks-' + uri) {
- $(this).addClass('currenttrack2');
+ $(this).addClass('currenttrack2')
} else {
- $(this).removeClass("currenttrack2");
- }
- });
+ $(this).removeClass('currenttrack2')
+ }
+ })
}
diff --git a/mopidy_musicbox_webclient/static/js/images.js b/mopidy_musicbox_webclient/static/js/images.js
index 652fae3..8cb61dc 100644
--- a/mopidy_musicbox_webclient/static/js/images.js
+++ b/mopidy_musicbox_webclient/static/js/images.js
@@ -2,91 +2,91 @@
* @author Wouter van Wijk
*/
-API_KEY = 'b6d34c3af91d62ab0ae00ab1b6fa8733';
-API_SECRET = '2c631802c2285d5d5d1502462fe42a2b';
+API_KEY = 'b6d34c3af91d62ab0ae00ab1b6fa8733'
+API_SECRET = '2c631802c2285d5d5d1502462fe42a2b'
-var fmcache;
-var lastfm;
+var fmcache
+var lastfm
$(window).load(function () {
// create a Cache object
- fmcache = new LastFMCache();
+ fmcache = new LastFMCache()
// create a LastFM object
lastfm = new LastFM({
apiKey : API_KEY,
apiSecret : API_SECRET,
cache : fmcache
- });
-});
+ })
+})
-function getCover(uri, images, size) {
- var defUrl = 'images/default_cover.png';
- $(images).attr('src', defUrl);
+function getCover (uri, images, size) {
+ var defUrl = 'images/default_cover.png'
+ $(images).attr('src', defUrl)
if (!uri) {
- return;
+ return
}
- mopidy.library.getImages({'uris': [uri]}).then(function(imageResults) {
- var uri = Object.keys(imageResults)[0];
+ mopidy.library.getImages({'uris': [uri]}).then(function (imageResults) {
+ var uri = Object.keys(imageResults)[0]
if (imageResults[uri].length > 0) {
- $(images).attr('src', imageResults[uri][0].uri);
+ $(images).attr('src', imageResults[uri][0].uri)
} else {
// Also check deprecated 'album.images' in case backend does not
// implement mopidy.library.getImages yet...
- getCoverFromAlbum(uri, images, size);
+ getCoverFromAlbum(uri, images, size)
}
- });
+ })
}
// Note that this approach has been deprecated in Mopidy
// TODO: Remove when Mopidy no longer supports getting images
// with 'album.images'.
-function getCoverFromAlbum(uri, images, size) {
- mopidy.library.lookup({'uris': [uri]}).then(function(resultDict) {
- var uri = Object.keys(resultDict)[0];
- var track = resultDict[uri][0];
- if (track.album && track.album.images && (track.album.images.length > 0) ) {
- $(images).attr('src', track.album.images[0]);
+function getCoverFromAlbum (uri, images, size) {
+ mopidy.library.lookup({'uris': [uri]}).then(function (resultDict) {
+ var uri = Object.keys(resultDict)[0]
+ var track = resultDict[uri][0]
+ if (track.album && track.album.images && (track.album.images.length > 0)) {
+ $(images).attr('src', track.album.images[0])
} else {
// Fallback to last.fm
- getCoverFromLastFm(track, images, size);
+ getCoverFromLastFm(track, images, size)
}
- });
+ })
}
-function getCoverFromLastFm(track, images, size) {
- var defUrl = 'images/default_cover.png';
+function getCoverFromLastFm (track, images, size) {
+ var defUrl = 'images/default_cover.png'
if (!(track.album || track.artist)) {
- return;
+ return
}
- var albumname = track.album.name || '';
- var artistname = '';
- if ( track.album.artists && (track.album.artists.length > 0) ) {
+ var albumname = track.album.name || ''
+ var artistname = ''
+ if (track.album.artists && (track.album.artists.length > 0)) {
// First look for the artist in the album
- artistname = track.album.artists[0].name;
- } else if (track.artists && (track.artists.length > 0) ) {
+ artistname = track.album.artists[0].name
+ } else if (track.artists && (track.artists.length > 0)) {
// Fallback to using artists for specific track
- artistname = track.artists[0].name;
+ artistname = track.artists[0].name
}
- lastfm.album.getInfo( {artist: artistname, album: albumname},
- { success: function(data) {
+ lastfm.album.getInfo({artist: artistname, album: albumname},
+ { success: function (data) {
for (var i = 0; i < data.album.image.length; i++) {
- if ( data.album.image[i].size == size) {
- $(images).attr('src', data.album.image[i]['#text'] || defUrl);
+ if (data.album.image[i].size == size) {
+ $(images).attr('src', data.album.image[i]['#text'] || defUrl)
}
}
}
- });
+ })
}
-function getArtistImage(nwartist, image, size) {
- var defUrl = 'images/user_24x32.png';
- lastfm.artist.getInfo({artist: nwartist}, {success: function(data){
+function getArtistImage (nwartist, image, size) {
+ var defUrl = 'images/user_24x32.png'
+ lastfm.artist.getInfo({artist: nwartist}, {success: function (data) {
for (var i = 0; i < data.artist.image.length; i++) {
- if ( data.artist.image[i].size == size) {
- $(image).attr('src', data.artist.image[i]['#text'] || defUrl);
+ if (data.artist.image[i].size == size) {
+ $(image).attr('src', data.artist.image[i]['#text'] || defUrl)
}
}
- }});
-}
\ No newline at end of file
+ }})
+}
diff --git a/mopidy_musicbox_webclient/static/js/library.js b/mopidy_musicbox_webclient/static/js/library.js
index 3a62e05..e91e6bc 100644
--- a/mopidy_musicbox_webclient/static/js/library.js
+++ b/mopidy_musicbox_webclient/static/js/library.js
@@ -1,167 +1,167 @@
-/*********************************
+/** *******************************
* Search
*********************************/
-function searchPressed(key) {
- var value = $('#searchinput').val();
- switchContent('search');
+function searchPressed (key) {
+ var value = $('#searchinput').val()
+ switchContent('search')
if (key == 13) {
- initSearch();
- return false;
+ initSearch()
+ return false
}
- return true;
+ return true
}
-//init search
-function initSearch() {
- var value = $('#searchinput').val();
- var searchService = $('#selectSearchService').val();
+// init search
+function initSearch () {
+ var value = $('#searchinput').val()
+ var searchService = $('#selectSearchService').val()
if ((value.length < 100) && (value.length > 0)) {
- showLoading(true);
- //hide ios/android keyboard
- document.activeElement.blur();
- $("input").blur();
+ showLoading(true)
+ // hide ios/android keyboard
+ document.activeElement.blur()
+ $('input').blur()
- delete customTracklists[URI_SCHEME+':allresultscache'];
- delete customTracklists[URI_SCHEME+':artistresultscache'];
- delete customTracklists[URI_SCHEME+':albumresultscache'];
- delete customTracklists[URI_SCHEME+':trackresultscache'];
- $("#searchartists").hide();
- $("#searchalbums").hide();
- $("#searchtracks").hide();
+ delete customTracklists[URI_SCHEME + ':allresultscache']
+ delete customTracklists[URI_SCHEME + ':artistresultscache']
+ delete customTracklists[URI_SCHEME + ':albumresultscache']
+ delete customTracklists[URI_SCHEME + ':trackresultscache']
+ $('#searchartists').hide()
+ $('#searchalbums').hide()
+ $('#searchtracks').hide()
if (searchService != 'all') {
- mopidy.library.search({'query': {any:[value]}, 'uris': [searchService + ':']}).then(processSearchResults, console.error);
+ mopidy.library.search({'query': {any:[value]}, 'uris': [searchService + ':']}).then(processSearchResults, console.error)
} else {
mopidy.getUriSchemes().then(function (schemes) {
var query = {},
- uris = [];
+ uris = []
var regexp = $.map(schemes, function (scheme) {
- return '^' + scheme + ':';
- }).join('|');
+ return '^' + scheme + ':'
+ }).join('|')
- var match = value.match(regexp);
+ var match = value.match(regexp)
if (match) {
- var scheme = match[0];
- query = {uri: [value]};
- uris = [scheme];
+ var scheme = match[0]
+ query = {uri: [value]}
+ uris = [scheme]
} else {
- query = {any: [value]};
+ query = {any: [value]}
}
- mopidy.library.search({'query': query, 'uris': uris}).then(processSearchResults, console.error);
- });
+ mopidy.library.search({'query': query, 'uris': uris}).then(processSearchResults, console.error)
+ })
}
}
}
-/********************************************************
+/** ******************************************************
* process results of a search
*********************************************************/
-//# speed clone http://jsperf.com/cloning-an-object/2
-function clone(obj) {
- var target = {};
+// # speed clone http://jsperf.com/cloning-an-object/2
+function clone (obj) {
+ var target = {}
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
- target[i] = obj[i];
+ target[i] = obj[i]
}
}
- return target;
+ return target
}
-function processSearchResults(resultArr) {
- $(SEARCH_TRACK_TABLE).empty();
- $(SEARCH_ARTIST_TABLE).empty();
- $(SEARCH_ALBUM_TABLE).empty();
+function processSearchResults (resultArr) {
+ $(SEARCH_TRACK_TABLE).empty()
+ $(SEARCH_ARTIST_TABLE).empty()
+ $(SEARCH_ALBUM_TABLE).empty()
// Merge results from different backends.
// TODO should of coures have multiple tables
- var results = {'tracks': [], 'artists': [], 'albums': []};
- var j, emptyResult = true;
+ var results = {'tracks': [], 'artists': [], 'albums': []}
+ var j, emptyResult = true
for (var i = 0; i < resultArr.length; i++) {
if (resultArr[i].tracks) {
for (j = 0; j < resultArr[i].tracks.length; j++) {
- results.tracks.push(resultArr[i].tracks[j]);
- emptyResult = false;
+ results.tracks.push(resultArr[i].tracks[j])
+ emptyResult = false
}
}
if (resultArr[i].artists) {
for (j = 0; j < resultArr[i].artists.length; j++) {
- results.artists.push(resultArr[i].artists[j]);
- emptyResult = false;
+ results.artists.push(resultArr[i].artists[j])
+ emptyResult = false
}
}
if (resultArr[i].albums) {
for (j = 0; j < resultArr[i].albums.length; j++) {
- results.albums.push(resultArr[i].albums[j]);
- emptyResult = false;
+ results.albums.push(resultArr[i].albums[j])
+ emptyResult = false
}
}
}
- customTracklists[URI_SCHEME+':trackresultscache'] = results.tracks;
+ customTracklists[URI_SCHEME + ':trackresultscache'] = results.tracks
if (emptyResult) {
- toast('No results');
- showLoading(false);
- return false;
+ toast('No results')
+ showLoading(false)
+ return false
}
if (results.artists.length > 0) {
- $("#searchartists").show();
+ $('#searchartists').show()
}
if (results.albums.length > 0) {
- $("#searchalbums").show();
+ $('#searchalbums').show()
}
if (results.tracks.length > 0) {
- $("#searchtracks").show();
+ $('#searchtracks').show()
}
// Returns a string where {x} in template is replaced by tokens[x].
- function theme(template, tokens) {
- return template.replace(/{[^}]+}/g, function(match) {
- return tokens[match.slice(1,-1)];
- });
+ function theme (template, tokens) {
+ return template.replace(/{[^}]+}/g, function (match) {
+ return tokens[match.slice(1, -1)]
+ })
}
// 'Show more' pattern
- var showMorePattern = '
'
newalbum = []
newtlids = []
nextname = ''
} else {
- if ((results[i].album.name != nextname) || (nextname === '')) {
+ if ((results[i].album.name !== nextname) || (nextname === '')) {
tableid = 'art' + i
// render differently if only one track in the album
- if (newalbum.length == 1) {
+ if (newalbum.length === 1) {
+ var liID = ''
if (i !== 0) {
html += '
'
}
iconClass = getMediaClass(newalbum[0].uri)
- var liID = targetmin + '-' + newalbum[0].uri
- if (target == CURRENT_PLAYLIST_TABLE) {
+ liID = targetmin + '-' + newalbum[0].uri
+ if (target === CURRENT_PLAYLIST_TABLE) {
html += '
'
var tokens
- for (var i = 0; i < results.artists.length; i++) {
+ for (i = 0; i < results.artists.length; i++) {
tokens = {
'id': results.artists[i].uri,
'name': results.artists[i].name,
@@ -145,7 +146,7 @@ function processSearchResults (resultArr) {
}
// Add 'Show all' item after a certain number of hits.
- if (i == 4 && results.artists.length > 5) {
+ if (i === 4 && results.artists.length > 5) {
child += theme(showMorePattern, {'count': results.artists.length - i})
pattern = pattern.replace('
'
- return songLi
+ return html
+}
+
+function isNewAlbumSection (track, previousTrack) {
+ // 'true' if album name is either not defined or has changed from the previous track.
+ return !track.album || !track.album.name || !previousTrack || !previousTrack.album || !previousTrack.album.name ||
+ track.album.name !== previousTrack.album.name
+}
+
+function isMultiTrackAlbum (track, nextTrack) {
+ // 'true' if there are more tracks of the same album after this one.
+ return nextTrack.album && nextTrack.album.name && track.album && track.album.name && track.album.name === nextTrack.album.name
+}
+
+function validateTrackName (track, trackNumber) {
+ // Create name if there is none
+ var name = ''
+ if (!track.name || track.name === '') {
+ name = track.uri.split('/')
+ name = decodeURI(name[name.length - 1]) || 'Track ' + String(trackNumber)
+ } else {
+ name = track.name
+ }
+ return name
}
function resultsToTables (results, target, uri) {
if (!results) {
return
}
- var tlids = []
- if (target === CURRENT_PLAYLIST_TABLE) {
- for (i = 0; i < results.length; i++) {
- tlids[i] = results[i].tlid
- results[i] = results[i].track
- }
- }
-
- var newalbum = []
- var newtlids = []
- // keep a list of track URIs for retrieving of covers
- var coversList = []
- var nextname = ''
- var count = 0
$(target).html('')
-
- // break into albums and put in tables
- var html = ''
- var tableid, j, artistname, alburi, name, iconClass
- var targetmin = target.substr(1)
$(target).attr('data', uri)
+
+ var track, previousTrack, nextTrack, tlid
+ var albumTrackSeen = 0
+ var renderAlbumInfo = true
+ var liID = ''
+ // Keep a list of track URIs for retrieving of covers
+ var coversList = []
+
+ var html = ''
+ var tableid, artistname, name, iconClass
+ var targetmin = target.substr(1)
var length = 0 || results.length
+
+ // Break into albums and put in tables
for (i = 0; i < length; i++) {
- // create album if none extists
- if (!results[i].album) {
- results[i].album = {'__model__': 'Album'}
+ previousTrack = track
+ track = results[i]
+ tlid = ''
+ if (i < length - 1) {
+ nextTrack = results[i + 1]
}
- // create album uri if there is none
- if (!results[i].album.uri) {
- results[i].album.uri = 'x'
+ if ('tlid' in results[i]) {
+ // Get track information from TlTrack instance
+ track = results[i].track
+ tlid = results[i].tlid
+ if (i < length - 1) {
+ nextTrack = results[i + 1].track
+ }
}
- if (!results[i].album.name) {
- results[i].album.name = ''
+ track.name = validateTrackName(track, i)
+ // Leave out unplayable items
+ if (track.name.substring(0, 12) === '[unplayable]') {
+ continue
}
- // create name if there is no one
- if (!results[i].name || results[i].name === '') {
- name = results[i].uri.split('/')
- results[i].name = decodeURI(name[name.length - 1]) || 'Track ' + String(i)
+ // Streams
+ if (track.length === -1) {
+ html += '
'
- newalbum = []
- newtlids = []
- nextname = ''
- } else {
- if ((results[i].album.name !== nextname) || (nextname === '')) {
- tableid = 'art' + i
- // render differently if only one track in the album
- if (newalbum.length === 1) {
- var liID = ''
- if (i !== 0) {
- html += '
'
- return songLi
+ // TODO: remove this hard-coded condition for 'ALBUM_TABLE'
+ if (target !== ALBUM_TABLE && !hasSameAlbum(previousTrack, track)) {
+ // Starting to render a new album in the list.
+ renderSongLiDivider(track, nextTrack, currentIndex, target)
+ }
+}
+
+function renderSongLiAlbumInfo (track, target) {
+ var html = ''
+ html += renderSongLiTrackArtists(track)
+ if (track.album && track.album.name) {
+ html += ' - ' + track.album.name + ''
+ }
+ target = getjQueryID(target.substr(1) + '-', track.uri, true)
+ $(target).children('a').eq(1).append(html)
+ $(target + ' a h1 i').addClass(getMediaClass(track.uri))
}
function renderSongLiTrackArtists (track) {
@@ -228,15 +244,49 @@ function renderSongLiTrackArtists (track) {
return html
}
-function isNewAlbumSection (track, previousTrack) {
- // 'true' if album name is either not defined or has changed from the previous track.
- return !track.album || !track.album.name || !previousTrack || !previousTrack.album || !previousTrack.album.name ||
- track.album.name !== previousTrack.album.name
+function renderSongLiDivider (track, nextTrack, currentIndex, target) {
+ targetmin = target.substr(1)
+ target = getjQueryID(targetmin + '-', track.uri, true)
+ // Render differently if part of an album
+ if (hasSameAlbum(track, nextTrack)) {
+ // Large divider with album cover
+ $(target).before(
+ '
'
- continue
- }
-
- if (isNewAlbumSection(track, previousTrack)) {
- // Starting to render a new album in the list.
- tableid = 'art' + i
- // Render differently if part of an album
- if (i < length - 1 && isMultiTrackAlbum(track, nextTrack)) {
- // Large divider with album cover
- renderAlbumInfo = false
- html += '
')
@@ -523,7 +521,7 @@ function isSpotifyStarredPlaylist (playlist) {
*
* @param {string} identifier - Identifier string to prefix to the URI. Can
* be used to ensure that the generated ID will be unique for the page that
- * it will be included on. Can be any string (e.g. ID of parent element).
+ * it will be included on. Also accepts jQuery identifiers starting with '#'.
*
* @param {string} uri - URI to encode, usually the URI of a Mopidy track.
*
@@ -535,8 +533,12 @@ function isSpotifyStarredPlaylist (playlist) {
* is safe to use as a jQuery identifier.
*/
function getjQueryID (identifier, uri, includePrefix) {
- var prefix = includePrefix ? '#' : ''
- return prefix + identifier + fixedEncodeURIComponent(uri).replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '')
+ if (identifier.charAt(0) === '#' && !includePrefix) {
+ identifier = identifier.substr(1)
+ } else if (identifier.charAt(0) !== '#' && includePrefix) {
+ identifier = '#' + identifier
+ }
+ return identifier + '-' + fixedEncodeURIComponent(uri).replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '')
}
// Strict URI encoding as per https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
diff --git a/mopidy_musicbox_webclient/static/js/gui.js b/mopidy_musicbox_webclient/static/js/gui.js
index a622a31..104732e 100644
--- a/mopidy_musicbox_webclient/static/js/gui.js
+++ b/mopidy_musicbox_webclient/static/js/gui.js
@@ -629,7 +629,7 @@ function updatePlayIcons (uri, tlid) {
if (typeof eachTlid !== 'undefined') {
eachTlid = parseInt(eachTlid)
}
- if (this.id === getjQueryID(target + '-', uri) && eachTlid === tlid) {
+ if (this.id === getjQueryID(target, uri) && eachTlid === tlid) {
$(this).addClass('currenttrack')
} else {
$(this).removeClass('currenttrack')
@@ -639,7 +639,7 @@ function updatePlayIcons (uri, tlid) {
for (var i = 0; i < listviews.length; i++) {
target = listviews[i].substr(1)
$(listviews[i]).children('li').each(function () {
- if (this.id === getjQueryID(target + '-', uri)) {
+ if (this.id === getjQueryID(target, uri)) {
$(this).addClass('currenttrack2')
} else {
$(this).removeClass('currenttrack2')
diff --git a/mopidy_musicbox_webclient/static/js/process_ws.js b/mopidy_musicbox_webclient/static/js/process_ws.js
index 1c6ed37..e4228af 100644
--- a/mopidy_musicbox_webclient/static/js/process_ws.js
+++ b/mopidy_musicbox_webclient/static/js/process_ws.js
@@ -98,7 +98,7 @@ function processBrowseDir (resultArr) {
uris.push(ref.uri)
$(BROWSE_TABLE).append(
- '
' +
+ '
' +
'' +
'' +
'' +
From f8db8be71f5b7d6eea8493b2c794017a036a26a9 Mon Sep 17 00:00:00 2001
From: jcass
Date: Thu, 10 Mar 2016 17:21:13 +0200
Subject: [PATCH 08/38] Add Javascript test and test coverage frameworks.
---
.gitignore | 1 +
.travis.yml | 5 +-
karma.conf.js | 81 +++++++
mopidy_musicbox_webclient/static/js/gui.js | 2 +-
mopidy_musicbox_webclient/static/js/images.js | 154 ++++++++------
.../static/js/process_ws.js | 6 +-
.../static/js/progress_timer.js | 7 +-
package.json | 36 +++-
tests/test_images.js | 201 ++++++++++++++++++
tox.ini | 14 +-
10 files changed, 421 insertions(+), 86 deletions(-)
create mode 100644 karma.conf.js
create mode 100644 tests/test_images.js
diff --git a/.gitignore b/.gitignore
index b754965..e2cf956 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@
MANIFEST
build/
cover/
+coverage/
coverage.xml
dist/
docs/_build/
diff --git a/.travis.yml b/.travis.yml
index 5ce0d3d..c1749cf 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,6 +8,7 @@ python:
env:
- TOX_ENV=py27
- TOX_ENV=flake8
+ - TOX_ENV=test
- TOX_ENV=eslint
- TOX_ENV=csslint
- TOX_ENV=tidy
@@ -19,4 +20,6 @@ script:
- "tox -e $TOX_ENV"
after_success:
- - "if [ $TOX_ENV == 'py27' ]; then pip install coveralls; coveralls; fi"
+ # TODO: find a way to combine .py and .js coverage reports.
+ # - "if [ $TOX_ENV == 'py27' ]; then pip install coveralls; coveralls; fi"
+ - "if [ $TOX_ENV == 'test' ]; then cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js; fi"
diff --git a/karma.conf.js b/karma.conf.js
new file mode 100644
index 0000000..6104b24
--- /dev/null
+++ b/karma.conf.js
@@ -0,0 +1,81 @@
+// Karma configuration
+
+module.exports = function (config) {
+ config.set({
+
+ // base path that will be used to resolve all patterns (eg. files, exclude)
+ basePath: '',
+
+ // frameworks to use
+ // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+ frameworks: ['browserify', 'mocha'],
+
+ // list of files / patterns to load in the browser
+ files: [
+ 'mopidy_musicbox_webclient/static/vendors/**/*.js',
+ // TODO: can remove the next line once JavaScript codebase has been modularized.
+ 'mopidy_musicbox_webclient/static/js/**/*.js',
+ 'tests/**/test_*.js'
+ ],
+
+ // list of files to exclude
+ exclude: [
+ ],
+
+ // preprocess matching files before serving them to the browser
+ // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+ preprocessors: {
+ 'tests/**/test_*.js': [ 'browserify' ],
+ 'mopidy_musicbox_webclient/static/js/**/*.js': ['coverage']
+ },
+
+ // test results reporter to use
+ // possible values: 'dots', 'progress'
+ // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+ reporters: ['progress', 'coverage'],
+
+ // web server port
+ port: 9876,
+
+ // enable / disable colors in the output (reporters and logs)
+ colors: true,
+
+ // level of logging
+ // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+ logLevel: config.LOG_INFO,
+
+ // enable / disable watching file and executing tests whenever any file changes
+ autoWatch: false,
+
+ // start these browsers
+ // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+ browsers: ['PhantomJS'],
+
+ // Continuous Integration mode
+ // if true, Karma captures browsers, runs the tests and exits
+ singleRun: true,
+
+ // Concurrency level
+ // how many browser should be started simultaneous
+ concurrency: Infinity,
+
+ // add additional browserify configuration properties here
+ // such as transform and/or debug=true to generate source maps
+ browserify: {
+ debug: true,
+ transform: [
+ 'babelify',
+ ['browserify-istanbul', { instrumenter: require('isparta') }]
+ ]
+ },
+
+ coverageReporter: {
+ // specify a common output directory
+ dir: 'coverage/',
+ reporters: [
+ { type: 'lcov', subdir: '.' },
+ { type: 'text'}
+ ]
+ }
+ })
+}
diff --git a/mopidy_musicbox_webclient/static/js/gui.js b/mopidy_musicbox_webclient/static/js/gui.js
index 104732e..7eff64c 100644
--- a/mopidy_musicbox_webclient/static/js/gui.js
+++ b/mopidy_musicbox_webclient/static/js/gui.js
@@ -128,7 +128,7 @@ function setSongInfo (data) {
}
if (data.track.album && data.track.album.name) {
$('#modalalbum').html('' + data.track.album.name + '')
- getCover(data.track.uri, '#infocover, #controlspopupimage', 'extralarge')
+ coverArt.getCover(data.track.uri, '#infocover, #controlspopupimage', 'extralarge')
} else {
$('#modalalbum').html('')
$('#infocover').attr('src', 'images/default_cover.png')
diff --git a/mopidy_musicbox_webclient/static/js/images.js b/mopidy_musicbox_webclient/static/js/images.js
index 5c16f18..0a1b531 100644
--- a/mopidy_musicbox_webclient/static/js/images.js
+++ b/mopidy_musicbox_webclient/static/js/images.js
@@ -5,88 +5,106 @@
API_KEY = 'b6d34c3af91d62ab0ae00ab1b6fa8733'
API_SECRET = '2c631802c2285d5d5d1502462fe42a2b'
-var fmcache
-var lastfm
-
-$(window).load(function () {
- // create a Cache object
- fmcache = new LastFMCache()
- // create a LastFM object
- lastfm = new LastFM({
+var coverArt = {
+ fmcache: new LastFMCache(),
+ lastfm: new LastFM({
apiKey: API_KEY,
apiSecret: API_SECRET,
- cache: fmcache
- })
-})
+ cache: this.fmcache
+ }),
-function getCover (uri, images, size) {
- var defUrl = 'images/default_cover.png'
- $(images).attr('src', defUrl)
- if (!uri) {
- return
- }
-
- mopidy.library.getImages({'uris': [uri]}).then(function (imageResults) {
- var uri = Object.keys(imageResults)[0]
- if (imageResults[uri].length > 0) {
- $(images).attr('src', imageResults[uri][0].uri)
- } else {
- // Also check deprecated 'album.images' in case backend does not
- // implement mopidy.library.getImages yet...
- getCoverFromAlbum(uri, images, size)
+ getCover: function (uri, images, size) {
+ var defUrl = 'images/default_cover.png'
+ $(images).attr('src', defUrl)
+ if (!uri) {
+ return
}
- })
-}
+ mopidy.library.getImages({'uris': [uri]}).then(function (imageResults) {
+ var uri = Object.keys(imageResults)[0]
+ if (imageResults[uri].length > 0) {
+ $(images).attr('src', imageResults[uri][0].uri)
+ } else {
+ // Also check deprecated 'album.images' in case backend does not
+ // implement mopidy.library.getImages yet...
+ coverArt.getCoverFromAlbum(uri, images, size)
+ }
+ })
+ },
-// Note that this approach has been deprecated in Mopidy
-// TODO: Remove when Mopidy no longer supports getting images
-// with 'album.images'.
-function getCoverFromAlbum (uri, images, size) {
- mopidy.library.lookup({'uris': [uri]}).then(function (resultDict) {
- var uri = Object.keys(resultDict)[0]
- var track = resultDict[uri][0]
- if (track.album && track.album.images && (track.album.images.length > 0)) {
- $(images).attr('src', track.album.images[0])
- } else {
- // Fallback to last.fm
- getCoverFromLastFm(track, images, size)
+ // Note that this approach has been deprecated in Mopidy
+ // TODO: Remove when Mopidy no longer supports getting images
+ // with 'album.images'.
+ getCoverFromAlbum: function (uri, images, size) {
+ var defUrl = 'images/default_cover.png'
+ $(images).attr('src', defUrl)
+ if (!uri) {
+ return
}
- })
-}
+ mopidy.library.lookup({'uris': [uri]}).then(function (resultDict) {
+ var uri = Object.keys(resultDict)[0]
+ var track = resultDict[uri][0]
+ if (track && track.album && track.album.images && track.album.images.length > 0) {
+ $(images).attr('src', track.album.images[0])
+ } else if (track && (track.album || track.artist)) {
+ // Fallback to last.fm
+ coverArt.getCoverFromLastFm(track, images, size)
+ } else {
+ return
+ }
+ })
+ },
-function getCoverFromLastFm (track, images, size) {
- var defUrl = 'images/default_cover.png'
- if (!(track.album || track.artist)) {
- return
- }
- var albumname = track.album.name || ''
- var artistname = ''
- if (track.album.artists && (track.album.artists.length > 0)) {
- // First look for the artist in the album
- artistname = track.album.artists[0].name
- } else if (track.artists && (track.artists.length > 0)) {
- // Fallback to using artists for specific track
- artistname = track.artists[0].name
- }
+ getCoverFromLastFm: function (track, images, size) {
+ var defUrl = 'images/default_cover.png'
+ $(images).attr('src', defUrl)
+ if (!track || !(track.album || track.artists)) {
+ return
+ }
+ var albumname = (track.album && track.album.name) ? track.album.name : ''
+ var artistname = ''
+ if (track.album && track.album.artists && track.album.artists.length > 0) {
+ // First look for the artist in the album
+ artistname = track.album.artists[0].name
+ } else if (track.artists && (track.artists.length > 0)) {
+ // Fallback to using artists for specific track
+ artistname = track.artists[0].name
+ }
- lastfm.album.getInfo({artist: artistname, album: albumname},
- { success: function (data) {
+ this.lastfm.album.getInfo({artist: artistname, album: albumname}, {success: function (data) {
for (var i = 0; i < data.album.image.length; i++) {
if (data.album.image[i].size === size) {
$(images).attr('src', data.album.image[i]['#text'] || defUrl)
}
}
+ }, error: function (code, message) {
+ console.log('Error retrieving album info from last.fm', code, message)
+ }})
+ },
+
+ getArtistImage: function (artist, images, size) {
+ var defUrl = 'images/user_24x32.png'
+ $(images).attr('src', defUrl)
+ if (!artist || artist.length === 0) {
+ return
}
- }, $(images).attr('src', defUrl))
+ this.lastfm.artist.getInfo({artist: artist}, {success: function (data) {
+ for (var i = 0; i < data.artist.image.length; i++) {
+ if (data.artist.image[i].size === size) {
+ $(images).attr('src', data.artist.image[i]['#text'] || defUrl)
+ }
+ }
+ }, error: function (code, message) {
+ console.log('Error retrieving artist info from last.fm', code, message)
+ }})
+ }
}
-function getArtistImage (nwartist, image, size) {
- var defUrl = 'images/user_24x32.png'
- lastfm.artist.getInfo({artist: nwartist}, {success: function (data) {
- for (var i = 0; i < data.artist.image.length; i++) {
- if (data.artist.image[i].size === size) {
- $(image).attr('src', data.artist.image[i]['#text'] || defUrl)
- }
- }
- }}, $(images).attr('src', defUrl))
+$(document).ready(coverArt.init)
+
+// TODO: Remove this once JavaScript codebase has been completely modularized
+// in favour of bundling everything using 'browserify'.
+if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ module.exports = coverArt
+ }
}
diff --git a/mopidy_musicbox_webclient/static/js/process_ws.js b/mopidy_musicbox_webclient/static/js/process_ws.js
index e4228af..4c0d287 100644
--- a/mopidy_musicbox_webclient/static/js/process_ws.js
+++ b/mopidy_musicbox_webclient/static/js/process_ws.js
@@ -220,7 +220,7 @@ function processCurrentPlaylist (resultArr) {
function processArtistResults (resultArr) {
if (!resultArr || (resultArr.length === 0)) {
$('#h_artistname').text('Artist not found...')
- getCover('', '#artistviewimage, #artistpopupimage', 'extralarge')
+ coverArt.getCover('', '#artistviewimage, #artistpopupimage', 'extralarge')
showLoading(false)
return
}
@@ -239,7 +239,7 @@ function processArtistResults (resultArr) {
function processAlbumResults (resultArr) {
if (!resultArr || (resultArr.length === 0)) {
$('#h_albumname').text('Album not found...')
- getCover('', '#albumviewcover, #coverpopupimage', 'extralarge')
+ coverArt.getCover('', '#albumviewcover, #coverpopupimage', 'extralarge')
showLoading(false)
return
}
@@ -252,6 +252,6 @@ function processAlbumResults (resultArr) {
$('#h_albumartist').html(artistname)
$('#coverpopupalbumname').html(albumname)
$('#coverpopupartist').html(artistname)
- getCover(resultArr[0].uri, '#albumviewcover, #coverpopupimage', 'extralarge')
+ coverArt.getCover(resultArr[0].uri, '#albumviewcover, #coverpopupimage', 'extralarge')
showLoading(false)
}
diff --git a/mopidy_musicbox_webclient/static/js/progress_timer.js b/mopidy_musicbox_webclient/static/js/progress_timer.js
index 0b371c7..00ff6e9 100644
--- a/mopidy_musicbox_webclient/static/js/progress_timer.js
+++ b/mopidy_musicbox_webclient/static/js/progress_timer.js
@@ -1,5 +1,4 @@
var progressTimer
-var progressElement = document.getElementById('trackslider')
var positionNode = document.createTextNode('')
var durationNode = document.createTextNode('')
@@ -13,8 +12,10 @@ var syncsLeft = MAX_SYNCS
var synced = false
var consecutiveSyncs = 0
-document.getElementById('songelapsed').appendChild(positionNode)
-document.getElementById('songlength').appendChild(durationNode)
+$(document).ready(function () {
+ $('#songelapsed').append(positionNode)
+ $('#songlength').append(durationNode)
+})
function timerCallback (position, duration, isRunning) {
updateTimers(position, duration, isRunning)
diff --git a/package.json b/package.json
index ee6c8e3..97fb1ac 100644
--- a/package.json
+++ b/package.json
@@ -7,8 +7,8 @@
"test": "tests"
},
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1",
- "eslint": "eslint mopidy_musicbox_webclient/static/js/**.js",
+ "test": "karma start karma.conf.js",
+ "eslint": "eslint mopidy_musicbox_webclient/static/js/**/**.js tests/**/test_*.js",
"csslint": "csslint mopidy_musicbox_webclient/static/css/**.css",
"tidy": "node tidy.js"
},
@@ -22,12 +22,32 @@
"url": "https://github.com/pimusicbox/mopidy-musicbox-webclient/issues"
},
"devDependencies": {
- "eslint": "latest",
- "eslint-config-standard": "latest",
- "eslint-plugin-standard": "latest",
- "eslint-plugin-promise": "latest",
- "csslint": "latest",
- "tidy-html5": "latest"
+ "babelify": "^7.2.0",
+ "browserify": "^13.0.0",
+ "browserify-istanbul": "^2.0.0",
+ "chai": "^3.5.0",
+ "chai-as-promised": "^5.2.0",
+ "chai-jquery": "^2.0.0",
+ "chai-string": "^1.2.0",
+ "coveralls": "^2.11.8",
+ "csslint": "^0.10.0",
+ "eslint": "^2.3.0",
+ "eslint-config-standard": "^5.1.0",
+ "eslint-plugin-promise": "^1.1.0",
+ "eslint-plugin-standard": "^1.3.2",
+ "install": "^0.5.6",
+ "isparta": "^4.0.0",
+ "karma": "^0.13.22",
+ "karma-browserify": "^5.0.2",
+ "karma-cli": "^0.1.2",
+ "karma-coverage": "^0.5.5",
+ "karma-mocha": "^0.2.2",
+ "karma-phantomjs-launcher": "^1.0.0",
+ "mocha": "^2.4.5",
+ "phantomjs-prebuilt": "^2.1.5",
+ "sinon": "^1.17.3",
+ "tidy-html5": "latest",
+ "watchify": "^3.7.0"
},
"homepage": "https://github.com/pimusicbox/mopidy-musicbox-webclient#readme"
}
diff --git a/tests/test_images.js b/tests/test_images.js
new file mode 100644
index 0000000..8d52232
--- /dev/null
+++ b/tests/test_images.js
@@ -0,0 +1,201 @@
+var chai = require('chai')
+var should = chai.should()
+var expect = chai.expect
+var assert = chai.assert
+chai.use(require('chai-string'))
+chai.use(require('chai-jquery'))
+
+var sinon = require('sinon')
+
+var coverArt = require('../mopidy_musicbox_webclient/static/js/images.js')
+
+var images
+
+before(function () {
+ html =
+ '' +
+ ''
+ $(document).ready(function () {
+ $(document.body).add(html)
+ })
+ mopidy = sinon.stub(new Mopidy({callingConvention: 'by-position-or-by-name'}))
+ images = $('')
+})
+
+describe('CoverArt', function () {
+ describe('#getCover()', function () {
+ beforeEach(function () {
+ $(images).removeAttr('src')
+ })
+
+ it('should use default image if no track URI is provided', function () {
+ coverArt.getCover('', images, '')
+ $(images).prop('src').should.endWith('images/default_cover.png')
+ })
+
+ it('should get image from Mopidy, if available', function () {
+ var getImagesResultMock = {'mock:track:uri': [{uri: 'mockImageUri'}]}
+ var library = { getImages: function () { return $.when(getImagesResultMock) } }
+ mopidy.library = library
+
+ var getImagesSpy = sinon.spy(mopidy.library, 'getImages')
+ coverArt.getCover('mock:track:uri', images, '')
+
+ assert(getImagesSpy.calledOnce)
+ $(images).prop('src').should.endWith('mockImageUri')
+ })
+
+ it('should fall back to retrieving image from deprecated track.album.images', function () {
+ var getImagesResultMock = {'mock:track:uri': []}
+ var lookupResultMock = {'mock:track:uri': [{album: {images: ['mockAlbumImageUri']}}]}
+ var library = {
+ getImages: function () { return $.when(getImagesResultMock) },
+ lookup: function () { return $.when(lookupResultMock) }
+ }
+ mopidy.library = library
+
+ var getImagesSpy = sinon.spy(mopidy.library, 'getImages')
+ var getCoverFromAlbumSpy = sinon.spy(coverArt, 'getCoverFromAlbum')
+
+ coverArt.getCover('mock:track:uri', images, '')
+
+ assert(getImagesSpy.calledOnce)
+ assert(getCoverFromAlbumSpy.calledOnce)
+ })
+ })
+
+ describe('#getCoverFromAlbum()', function () {
+ beforeEach(function () {
+ $(images).removeAttr('src')
+ })
+
+ it('should use default image if no track URI is provided', function () {
+ coverArt.getCoverFromAlbum('', images, '')
+ $(images).prop('src').should.endWith('images/default_cover.png')
+ })
+
+ it('should get image from Mopidy track.album.images, if available', function () {
+ var lookupResultMock = {'mock:track:uri': [{album: {images: ['mockAlbumImageUri']}}]}
+ var library = {
+ lookup: function () { return $.when(lookupResultMock) }
+ }
+ mopidy.library = library
+
+ var lookupSpy = sinon.spy(mopidy.library, 'lookup')
+ coverArt.getCoverFromAlbum('mock:track:uri', images, '')
+
+ assert(lookupSpy.calledOnce)
+ $(images).prop('src').should.endWith('mockAlbumImageUri')
+ })
+
+ it('should use default image if track.album or track.artist is not available', function () {
+ var lookupResultMock = {'mock:track:uri': []}
+ var library = {
+ lookup: function () { return $.when(lookupResultMock) }
+ }
+ mopidy.library = library
+
+ var lookupSpy = sinon.spy(mopidy.library, 'lookup')
+ coverArt.getCoverFromAlbum('mock:track:uri', images, '')
+
+ assert(lookupSpy.calledOnce)
+ $(images).prop('src').should.endWith('images/default_cover.png')
+ })
+
+ it('should fall back to retrieving image from last.fm if none provided by Mopidy', function () {
+ var lookupResultMock = {'mock:track:uri': [{album: {images: []}}]}
+ var library = {
+ lookup: function () { return $.when(lookupResultMock) }
+ }
+ mopidy.library = library
+
+ var getCoverFromLastFmSpy = sinon.spy(coverArt, 'getCoverFromLastFm')
+ coverArt.getCoverFromAlbum('mock:track:uri', images, '')
+
+ assert(getCoverFromLastFmSpy.calledOnce)
+ })
+ })
+
+ describe('#getCoverFromLastFm()', function () {
+ beforeEach(function () {
+ $(images).removeAttr('src')
+ })
+
+ it('should use default image if no track is provided', function () {
+ coverArt.getCoverFromLastFm(undefined, images, '')
+ $(images).prop('src').should.endWith('images/default_cover.png')
+ })
+
+ it('should fall back to using track artist if album artist is not available', function () {
+ var track = {artists: [{name: 'artistMock'}]}
+ var getInfoResultMock = {album: {image: []}}
+
+ var getInfoStub = sinon.stub(coverArt.lastfm.album, 'getInfo')
+ getInfoStub.returns($.when(getInfoResultMock))
+
+ coverArt.getCoverFromLastFm(track, images, '')
+ var args = getInfoStub.args
+ assert(args[0][0].artist === 'artistMock')
+ getInfoStub.restore()
+ })
+
+ it('should get album info from last.fm', function () {
+ var track = {album: {artists: [{name: 'albumMock'}]}}
+ var getInfoResultMock = {album: {image: [{'#text': 'mockAlbumImageUri', size: 'small'}]}}
+
+ var getInfoStub = sinon.stub(coverArt.lastfm.album, 'getInfo')
+ getInfoStub.yieldsTo('success', getInfoResultMock)
+
+ coverArt.getCoverFromLastFm(track, images, 'small')
+ $(images).prop('src').should.endWith('mockAlbumImageUri')
+ getInfoStub.restore()
+ })
+
+ it('should log errors', function () {
+ var track = {album: {artists: [{name: 'albumMock'}]}}
+ var getInfoStub = sinon.stub(coverArt.lastfm.album, 'getInfo')
+ getInfoStub.yieldsTo('error', 'code', 'message')
+
+ var consoleSpy = sinon.spy(console, 'log')
+ coverArt.getCoverFromLastFm(track, images, '')
+
+ assert(consoleSpy.calledOnce)
+ getInfoStub.restore()
+ consoleSpy.restore()
+ })
+ })
+
+ describe('#getArtistImage()', function () {
+ beforeEach(function () {
+ $(images).removeAttr('src')
+ })
+
+ it('should use default image if no artist is provided', function () {
+ coverArt.getArtistImage('', images, '')
+ $(images).prop('src').should.endWith('images/user_24x32.png')
+ })
+
+ it('should get artist info from last.fm', function () {
+ var getInfoResultMock = {artist: {image: [{'#text': 'mockArtistImageUri', size: 'small'}]}}
+
+ var getInfoStub = sinon.stub(coverArt.lastfm.artist, 'getInfo')
+ getInfoStub.yieldsTo('success', getInfoResultMock)
+
+ coverArt.getArtistImage('mockArtist', images, 'small')
+ $(images).prop('src').should.endWith('mockArtistImageUri')
+ getInfoStub.restore()
+ })
+
+ it('should log errors', function () {
+ var getInfoStub = sinon.stub(coverArt.lastfm.artist, 'getInfo')
+ getInfoStub.yieldsTo('error', 'code', 'message')
+
+ var consoleSpy = sinon.spy(console, 'log')
+
+ coverArt.getArtistImage('mockArtist', images, 'small')
+ assert(consoleSpy.calledOnce)
+ getInfoStub.restore()
+ consoleSpy.restore()
+ })
+ })
+})
diff --git a/tox.ini b/tox.ini
index 96a5099..b6a3ba3 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py27, flake8, eslint, csslint, tidy
+envlist = py27, flake8, test, eslint, csslint, tidy
[testenv]
deps =
@@ -20,7 +20,17 @@ deps =
flake8
flake8-import-order
skip_install = true
-commands = flake8 {posargs:mopidy_musicbox_webclient}
+commands = flake8 {posargs:mopidy_musicbox_webclient tests}
+
+[testenv:test]
+whitelist_externals =
+ /bin/bash
+deps =
+ nodeenv
+skip_install = true
+commands =
+ - nodeenv --prebuilt {toxworkdir}/node_env
+ bash -c '. {toxworkdir}/node_env/bin/activate; npm install; npm test'
[testenv:eslint]
whitelist_externals =
From 7944acecb9c89960f07181718baef874f1f8bb6b Mon Sep 17 00:00:00 2001
From: jcass
Date: Wed, 16 Mar 2016 21:54:49 +0200
Subject: [PATCH 09/38] Add missing object literal reference that was missed
during merge.
---
mopidy_musicbox_webclient/static/js/functionsvars.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mopidy_musicbox_webclient/static/js/functionsvars.js b/mopidy_musicbox_webclient/static/js/functionsvars.js
index 636e7f9..89ee24b 100644
--- a/mopidy_musicbox_webclient/static/js/functionsvars.js
+++ b/mopidy_musicbox_webclient/static/js/functionsvars.js
@@ -255,7 +255,7 @@ function renderSongLiDivider (track, nextTrack, currentIndex, target) {
renderSongLiTrackArtists(track) + '
'
- // Merge results from different backends.
- // TODO should of coures have multiple tables
- var results = {'tracks': [], 'artists': [], 'albums': []}
- var i, j
- var emptyResult = true
+ // Artist results
+ var child = ''
+ var pattern = '
'
+ return html
}
+/* Tracklist renderer for track artist and album name. */
function renderSongLiAlbumInfo (track, target) {
- var html = ''
- html += renderSongLiTrackArtists(track)
+ var html = renderSongLiTrackArtists(track)
if (track.album && track.album.name) {
html += ' - ' + track.album.name + ''
}
- target = getjQueryID(target, track.uri, true)
- $(target).children('a').eq(1).append(html)
- $(target + ' a h1 i').addClass(getMediaClass(track.uri))
+ if (typeof target !== 'undefined' && target.length > 0) {
+ target = getjQueryID(target, track.uri, true)
+ $(target).children('a').eq(1).append(html)
+ }
+ return html
}
+/* Tracklist renderer for track artist information. */
function renderSongLiTrackArtists (track) {
var html = ''
if (track.artists) {
@@ -252,23 +255,28 @@ function renderSongLiTrackArtists (track) {
return html
}
-function renderSongLiDivider (track, nextTrack, currentIndex, target) {
- target = getjQueryID(target, track.uri, true)
- // Render differently if part of an album
- if (hasSameAlbum(track, nextTrack)) {
- // Large divider with album cover
- $(target).before(
+/* Tracklist renderer to insert dividers between albums. */
+function renderSongLiDivider (previousTrack, track, nextTrack, currentIndex, target) {
+ var html = ''
+ // Render differently if part of an album.
+ if (!hasSameAlbum(previousTrack, track) && hasSameAlbum(track, nextTrack)) {
+ // Large divider with album cover.
+ html +=
'