Merge pull request #182 from jcass77/fix/99_browse_track_artist
Refactor code for displaying track lists.
This commit is contained in:
commit
df0775e330
@ -74,10 +74,12 @@ v2.3.0 (UNRELEASED)
|
|||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
- Enhance build workflow to include style checks and syntax validation for HTML, CSS, and Javascript.
|
- Enhance build workflow to include style checks and syntax validation for HTML, CSS, and Javascript.
|
||||||
|
- Now displays album and artist info when browsing tracks. (Addresses: `#99 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/99>`_).
|
||||||
|
|
||||||
**Fixes**
|
**Fixes**
|
||||||
|
|
||||||
- Don't create Mopidy models manually. (Fixes: `#172 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/172>`_).
|
- Don't create Mopidy models manually. (Fixes: `#172 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/172>`_).
|
||||||
|
- Context menu is now available for all tracks in browse pane. (Fixes: `#126 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/126>`_).
|
||||||
|
|
||||||
v2.2.0 (2016-03-01)
|
v2.2.0 (2016-03-01)
|
||||||
-------------------
|
-------------------
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#playlisttracksback {
|
.backnav-optional {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +74,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#playlisttracksback {
|
.backnav-optional {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,13 +293,17 @@
|
|||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.song .moreBtn{
|
.song .moreBtn {
|
||||||
float: right;
|
float: right;
|
||||||
padding: 15px 18px 12px 22px;
|
padding: 15px 18px 12px 22px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
line-height: 100%;
|
line-height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.backnav {
|
||||||
|
background-color: #ccc !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* Now Playing area *
|
* Now Playing area *
|
||||||
@ -369,12 +373,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#popupTracksLv li,
|
#popupTracksLv li,
|
||||||
#popupQueueLv li {
|
#popupQueueLv li,
|
||||||
|
#popupBrowseLv li {
|
||||||
border-bottom: 1px solid #aaa;
|
border-bottom: 1px solid #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
#popupTracksLv,
|
#popupTracksLv,
|
||||||
#popupQueueLv {
|
#popupQueueLv,
|
||||||
|
#popupBrowseLv li {
|
||||||
border: 1px solid #aaa;
|
border: 1px solid #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,6 @@
|
|||||||
<div data-role="page" id="page" class="ui-responsive-panel" data-theme="c">
|
<div data-role="page" id="page" class="ui-responsive-panel" data-theme="c">
|
||||||
<div data-role="panel" id="panel" data-position="left" data-theme="a" data-display="reveal" data-position-fixed="true">
|
<div data-role="panel" id="panel" data-position="left" data-theme="a" data-display="reveal" data-position-fixed="true">
|
||||||
|
|
||||||
|
|
||||||
<ul class="ui-listview mainNav" data-role="listview" data-theme="a">
|
<ul class="ui-listview mainNav" data-role="listview" data-theme="a">
|
||||||
<li id="navhome" data-icon="false">
|
<li id="navhome" data-icon="false">
|
||||||
<a href="#home" onclick="switchContent('home' ); return false;">
|
<a href="#home" onclick="switchContent('home' ); return false;">
|
||||||
@ -164,8 +163,7 @@
|
|||||||
<a href="#" onclick="return playTrack(ADD_THIS_BOTTOM);">Add Track to Bottom of Queue</a>
|
<a href="#" onclick="return playTrack(ADD_THIS_BOTTOM);">Add Track to Bottom of Queue</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="addqueue">
|
<li class="addqueue">
|
||||||
<a href="#" onclick="return playTrack(ADD_ALL_BOTTOM);" id="liaddtobottom">Add all to Bottom of
|
<a href="#" onclick="return playTrack(ADD_ALL_BOTTOM);" id="liaddtobottom">Add all to Bottom of Queue</a>
|
||||||
Queue</a>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" onclick="showAlbumPopup('#popupTracks')">Show Album <span class="popupAlbumName"></span></a>
|
<a href="#" onclick="showAlbumPopup('#popupTracks')">Show Album <span class="popupAlbumName"></span></a>
|
||||||
@ -206,7 +204,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div data-role="popup" data-theme="b" id="popupSave" class="popupDialog">
|
<div data-role="popup" data-theme="b" id="popupSave" class="popupDialog">
|
||||||
<form>
|
<form>
|
||||||
<p>Save current queue to a playlist.
|
<p>Save current queue to a playlist.
|
||||||
@ -224,7 +221,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<!--/save queue to playlist-->
|
<!--/save queue to playlist-->
|
||||||
|
|
||||||
|
|
||||||
<div data-role="popup" data-theme="b" id="popupOverwrite" class="popupDialog">
|
<div data-role="popup" data-theme="b" id="popupOverwrite" class="popupDialog">
|
||||||
<form>
|
<form>
|
||||||
<p>Overwrite existing playlist with same name?
|
<p>Overwrite existing playlist with same name?
|
||||||
@ -307,12 +303,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<!--/homepane-->
|
<!--/homepane-->
|
||||||
|
|
||||||
|
|
||||||
<div id="nowPlayingpane" data-role="content" class="pane">
|
<div id="nowPlayingpane" data-role="content" class="pane">
|
||||||
|
|
||||||
<img id="controlspopupimage" src="images/default_cover.png" alt="Album cover"/>
|
<img id="controlspopupimage" src="images/default_cover.png" alt="Album cover"/>
|
||||||
|
|
||||||
|
|
||||||
<div class="nowPlaying-artistInfo">
|
<div class="nowPlaying-artistInfo">
|
||||||
<h3 id="modalname"></h3>
|
<h3 id="modalname"></h3>
|
||||||
<p class="artistAlbumLine"><span id="modalartist"></span> - <span id="modalalbum"></span></p>
|
<p class="artistAlbumLine"><span id="modalartist"></span> - <span id="modalalbum"></span></p>
|
||||||
@ -343,9 +337,6 @@
|
|||||||
<ul id="playlistslist" class="table"></ul>
|
<ul id="playlistslist" class="table"></ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui-block-b scroll" id="playlisttracksdiv">
|
<div class="ui-block-b scroll" id="playlisttracksdiv">
|
||||||
<div id="playlisttracksback" style="height: 30px; margin: 2px; padding-top: 2px; background-color: #aaa;">
|
|
||||||
<a style="display:block; padding: 5px;" href="#" onclick="return togglePlaylists();"><i class="fa fa-arrow-circle-left"></i> Back</a>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<ul class="table" id="playlisttracks"></ul>
|
<ul class="table" id="playlisttracks"></ul>
|
||||||
</div>
|
</div>
|
||||||
@ -356,8 +347,9 @@
|
|||||||
|
|
||||||
<div data-role="content" id="browsepane" class="pane">
|
<div data-role="content" id="browsepane" class="pane">
|
||||||
<h4>Browse</h4>
|
<h4>Browse</h4>
|
||||||
<h5 id="browsepath"></h5>
|
<div class="ui-grid">
|
||||||
<ul id="browselist" class="table"></ul>
|
<ul id="browsetable" class="table"></ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--/browsepane-->
|
<!--/browsepane-->
|
||||||
|
|
||||||
@ -385,7 +377,7 @@
|
|||||||
|
|
||||||
<h3 id="h_albumname"></h3>
|
<h3 id="h_albumname"></h3>
|
||||||
<h5 id="h_albumartist"></h5>
|
<h5 id="h_albumartist"></h5>
|
||||||
<div id="albumstable"></div>
|
<ul class="table" id="albumstable"></ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -477,7 +469,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div data-role="footer" data-tap-toggle="false" data-position="fixed" id="normalFooter">
|
<div data-role="footer" data-tap-toggle="false" data-position="fixed" id="normalFooter">
|
||||||
<div class="footerControls">
|
<div class="footerControls">
|
||||||
<div class="songinfo" id="songinfo">
|
<div class="songinfo" id="songinfo">
|
||||||
@ -492,6 +483,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-role="footer" data-tap-toggle="false" data-position="fixed" id="nowPlayingFooter">
|
<div data-role="footer" data-tap-toggle="false" data-position="fixed" id="nowPlayingFooter">
|
||||||
<div class="footerControls" style="padding-left: 10px;">
|
<div class="footerControls" style="padding-left: 10px;">
|
||||||
<div style="float: left;">
|
<div style="float: left;">
|
||||||
@ -507,11 +499,9 @@
|
|||||||
<a href="#" onclick="doShuffle(); return false"><span id="shufflebt" title="Shuffle"><i class="fa fa-arrows-v"></i></span></a>
|
<a href="#" onclick="doShuffle(); return false"><span id="shufflebt" title="Shuffle"><i class="fa fa-arrows-v"></i></span></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /footer -->
|
<!-- /footer -->
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /page one -->
|
<!-- /page one -->
|
||||||
<script type="text/javascript" src="vendors/mopidy/mopidy.min.js"></script>
|
<script type="text/javascript" src="vendors/mopidy/mopidy.min.js"></script>
|
||||||
|
|||||||
@ -52,6 +52,7 @@ var isWebkit = /WebKit/.test(ua)
|
|||||||
PROGRAM_NAME = 'MusicBox'
|
PROGRAM_NAME = 'MusicBox'
|
||||||
ARTIST_TABLE = '#artiststable'
|
ARTIST_TABLE = '#artiststable'
|
||||||
ALBUM_TABLE = '#albumstable'
|
ALBUM_TABLE = '#albumstable'
|
||||||
|
BROWSE_TABLE = '#browsetable'
|
||||||
PLAYLIST_TABLE = '#playlisttracks'
|
PLAYLIST_TABLE = '#playlisttracks'
|
||||||
CURRENT_PLAYLIST_TABLE = '#currenttable'
|
CURRENT_PLAYLIST_TABLE = '#currenttable'
|
||||||
SEARCH_ALL_TABLE = '#allresulttable'
|
SEARCH_ALL_TABLE = '#allresulttable'
|
||||||
@ -162,54 +163,68 @@ function artistsToString (artists, max) {
|
|||||||
* break up results and put them in album tables
|
* break up results and put them in album tables
|
||||||
*********************************************************/
|
*********************************************************/
|
||||||
function albumTracksToTable (pl, target, uri) {
|
function albumTracksToTable (pl, target, uri) {
|
||||||
var tmp = '<ul class="songsOfAlbum table" >'
|
var track, previousTrack, nextTrack
|
||||||
var liId = ''
|
|
||||||
var targetmin = target.substr(1)
|
|
||||||
$(target).empty()
|
$(target).empty()
|
||||||
for (var i = 0; i < pl.length; i++) {
|
|
||||||
popupData[pl[i].uri] = pl[i]
|
|
||||||
liID = targetmin + '-' + pl[i].uri
|
|
||||||
tmp += renderSongLi(pl[i], liID, uri)
|
|
||||||
}
|
|
||||||
tmp += '</ul>'
|
|
||||||
$(target).html(tmp)
|
|
||||||
$(target).attr('data', uri)
|
$(target).attr('data', uri)
|
||||||
|
for (var i = 0; i < pl.length; i++) {
|
||||||
|
previousTrack = track || undefined
|
||||||
|
nextTrack = i < pl.length - 1 ? pl[i + 1] : undefined
|
||||||
|
track = pl[i]
|
||||||
|
popupData[track.uri] = track
|
||||||
|
renderSongLi(previousTrack, track, nextTrack, uri, '', ALBUM_TABLE, i, pl.length)
|
||||||
|
}
|
||||||
|
updatePlayIcons(songdata.track.uri, songdata.tlid)
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSongLi (song, liID, uri, tlid, renderAlbumInfo) {
|
function renderSongLi (previousTrack, track, nextTrack, uri, tlid, target, currentIndex, listLength) {
|
||||||
var name, iconClass
|
var name
|
||||||
var tlidString = ''
|
|
||||||
var tlidParameter = ''
|
var tlidParameter = ''
|
||||||
var onClick = ''
|
var onClick = ''
|
||||||
// Determine if the song line item will be rendered as part of an album.
|
track.name = validateTrackName(track, currentIndex)
|
||||||
if (!song.album || !song.album.name) {
|
// Leave out unplayable items
|
||||||
iconClass = getMediaClass(song.uri)
|
if (track.name.substring(0, 12) === '[unplayable]') {
|
||||||
} else {
|
return
|
||||||
iconClass = 'trackname'
|
}
|
||||||
|
// Streams
|
||||||
|
if (track.length === -1) {
|
||||||
|
$(target).append('<li class="albumli"><a href="#"><h1><i class="' + getMediaClass(track.uri) + '"></i> ' + track.name + ' [Stream]</h1></a></li>')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
// Play by tlid if available.
|
// Play by tlid if available.
|
||||||
if (tlid) {
|
// TODO: Need to consolidate all of the 'play...' functions
|
||||||
tlidString = '" tlid="' + tlid
|
if (tlid && target === BROWSE_TABLE) {
|
||||||
|
onClick = 'return playBrowsedTracks(PLAY_ALL, ' + tlid + ');'
|
||||||
|
} else if (tlid) {
|
||||||
tlidParameter = '\',\'' + tlid
|
tlidParameter = '\',\'' + tlid
|
||||||
onClick = 'return playTrackQueueByTlid(\'' + song.uri + '\',\'' + tlid + '\');'
|
onClick = 'return playTrackQueueByTlid(\'' + track.uri + '\',\'' + tlid + '\');'
|
||||||
} else {
|
} else {
|
||||||
onClick = 'return playTrackByUri(\'' + song.uri + '\',\'' + uri + '\');'
|
onClick = 'return playTrackByUri(\'' + track.uri + '\',\'' + uri + '\');'
|
||||||
}
|
}
|
||||||
songLi = '<li class="song albumli" id="' + liID + tlidString + '">' +
|
$(target).append(
|
||||||
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + song.uri + tlidParameter + '\');">' +
|
'<li class="song albumli" id="' + getjQueryID(target, track.uri) + '" tlid="' + tlid + '">' +
|
||||||
|
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + track.uri + tlidParameter + '\');">' +
|
||||||
'<i class="fa fa-ellipsis-v"></i></a>' +
|
'<i class="fa fa-ellipsis-v"></i></a>' +
|
||||||
'<a href="#" onclick="' + onClick + '">' +
|
'<a href="#" onclick="' + onClick + '"><h1><i></i> ' + track.name + '</h1></a></li>'
|
||||||
'<h1><i class="' + iconClass + '"></i>' + song.name + '</h1>'
|
)
|
||||||
if (renderAlbumInfo) {
|
if (listLength === 1 || !hasSameAlbum(previousTrack, track) && !hasSameAlbum(track, nextTrack)) {
|
||||||
songLi += '</p>'
|
renderSongLiAlbumInfo(track, target)
|
||||||
songLi += renderSongLiTrackArtists(song)
|
|
||||||
if (song.album && song.album.name) {
|
|
||||||
songLi += ' - '
|
|
||||||
songLi += '<em>' + song.album.name + '</em></p>'
|
|
||||||
}
|
}
|
||||||
|
// 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)
|
||||||
}
|
}
|
||||||
songLi += '</a></li>'
|
}
|
||||||
return songLi
|
|
||||||
|
function renderSongLiAlbumInfo (track, target) {
|
||||||
|
var html = '</p>'
|
||||||
|
html += renderSongLiTrackArtists(track)
|
||||||
|
if (track.album && track.album.name) {
|
||||||
|
html += ' - <em>' + track.album.name + '</em></p>'
|
||||||
|
}
|
||||||
|
target = getjQueryID(target, track.uri, true)
|
||||||
|
$(target).children('a').eq(1).append(html)
|
||||||
|
$(target + ' a h1 i').addClass(getMediaClass(track.uri))
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSongLiTrackArtists (track) {
|
function renderSongLiTrackArtists (track) {
|
||||||
@ -228,15 +243,48 @@ function renderSongLiTrackArtists (track) {
|
|||||||
return html
|
return html
|
||||||
}
|
}
|
||||||
|
|
||||||
function isNewAlbumSection (track, previousTrack) {
|
function renderSongLiDivider (track, nextTrack, currentIndex, target) {
|
||||||
// 'true' if album name is either not defined or has changed from the previous track.
|
target = getjQueryID(target, track.uri, true)
|
||||||
return !track.album || !track.album.name || !previousTrack || !previousTrack.album || !previousTrack.album.name ||
|
// Render differently if part of an album
|
||||||
track.album.name !== previousTrack.album.name
|
if (hasSameAlbum(track, nextTrack)) {
|
||||||
|
// Large divider with album cover
|
||||||
|
$(target).before(
|
||||||
|
'<li class="albumdivider"><a href="#" onclick="return showAlbum(\'' + track.album.uri + '\');">' +
|
||||||
|
'<img id="' + getjQueryID(target + '-cover', track.uri) + '" class="artistcover" width="30" height="30"/>' +
|
||||||
|
'<h1><i class="' + getMediaClass(track.uri) + '"></i> ' + track.album.name + '</h1><p>' +
|
||||||
|
renderSongLiTrackArtists(track) + '</p></a></li>'
|
||||||
|
)
|
||||||
|
// Retrieve album covers
|
||||||
|
getCover(track.uri, getjQueryID(target + '-cover', track.uri, true), 'small')
|
||||||
|
} else if (currentIndex > 0) {
|
||||||
|
// Small divider
|
||||||
|
$(target).before('<li class="smalldivider"> </li>')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMultiTrackAlbum (track, nextTrack) {
|
function renderSongLiBackButton (results, target, onClick, optional) {
|
||||||
// 'true' if there are more tracks of the same album after this one.
|
if (onClick && onClick.length > 0) {
|
||||||
return nextTrack.album && nextTrack.album.name && track.album && track.album.name && track.album.name === nextTrack.album.name
|
if (!results || results.length === 0) {
|
||||||
|
$(target).empty()
|
||||||
|
$(target).append(
|
||||||
|
'<li class="song albumli"><a href="#" onclick="' + onClick + '"><h1><i></i>No tracks found...</h1></a></li>'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
var opt = ''
|
||||||
|
if (optional) {
|
||||||
|
opt = ' backnav-optional'
|
||||||
|
}
|
||||||
|
$(target).prepend(
|
||||||
|
'<li class="backnav' + opt + '"><a href="#" onclick="' + onClick + '"><h1><i class="fa fa-arrow-circle-left"></i> Back</h1></a></li>'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasSameAlbum (track1, track2) {
|
||||||
|
// 'true' if album for each track exists and has the same name
|
||||||
|
var name1 = track1 ? (track1.album ? track1.album.name : undefined) : undefined
|
||||||
|
var name2 = track2 ? (track2.album ? track2.album.name : undefined) : undefined
|
||||||
|
return name1 && name2 && (name1 === name2)
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateTrackName (track, trackNumber) {
|
function validateTrackName (track, trackNumber) {
|
||||||
@ -251,86 +299,33 @@ function validateTrackName (track, trackNumber) {
|
|||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
function resultsToTables (results, target, uri) {
|
function resultsToTables (results, target, uri, onClickBack, backIsOptional) {
|
||||||
if (!results) {
|
$(target).empty()
|
||||||
|
renderSongLiBackButton(results, target, onClickBack, backIsOptional)
|
||||||
|
if (!results || results.length === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
$(target).html('')
|
|
||||||
$(target).attr('data', uri)
|
$(target).attr('data', uri)
|
||||||
|
|
||||||
var track, previousTrack, nextTrack, tlid
|
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
|
// Break into albums and put in tables
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < results.length; i++) {
|
||||||
previousTrack = track
|
previousTrack = track || undefined
|
||||||
|
nextTrack = i < results.length - 1 ? results[i + 1] : undefined
|
||||||
track = results[i]
|
track = results[i]
|
||||||
tlid = ''
|
if (track) {
|
||||||
if (i < length - 1) {
|
if ('tlid' in track) {
|
||||||
nextTrack = results[i + 1]
|
|
||||||
}
|
|
||||||
if ('tlid' in results[i]) {
|
|
||||||
// Get track information from TlTrack instance
|
// Get track information from TlTrack instance
|
||||||
track = results[i].track
|
tlid = track.tlid
|
||||||
tlid = results[i].tlid
|
track = track.track
|
||||||
if (i < length - 1) {
|
nextTrack = nextTrack ? nextTrack.track : undefined
|
||||||
nextTrack = results[i + 1].track
|
|
||||||
}
|
|
||||||
}
|
|
||||||
track.name = validateTrackName(track, i)
|
|
||||||
// Leave out unplayable items
|
|
||||||
if (track.name.substring(0, 12) === '[unplayable]') {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Streams
|
|
||||||
if (track.length === -1) {
|
|
||||||
html += '<li class="albumli"><a href="#"><h1><i class="' + getMediaClass(track.uri) + '"></i> ' + track.name + ' [Stream]</h1></a></li>'
|
|
||||||
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 += '<li class="albumdivider">'
|
|
||||||
html += '<a href="#" onclick="return showAlbum(\'' + track.album.uri + '\');">' +
|
|
||||||
'<img id="' + targetmin + '-cover-' + i + '" class="artistcover" width="30" height="30" />' +
|
|
||||||
'<h1><i class="' + getMediaClass(track.uri) + '"></i> ' + track.album.name + '</h1><p>'
|
|
||||||
html += renderSongLiTrackArtists(track)
|
|
||||||
html += '</p></a></li>'
|
|
||||||
coversList.push([track.uri, i])
|
|
||||||
} else {
|
|
||||||
renderAlbumInfo = true
|
|
||||||
if (i > 0) {
|
|
||||||
// Small divider
|
|
||||||
html += '<li class="smalldivider"> </li>'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
albumTrackSeen = 0
|
|
||||||
}
|
}
|
||||||
popupData[track.uri] = track
|
popupData[track.uri] = track
|
||||||
liID = targetmin + '-' + track.uri
|
renderSongLi(previousTrack, track, nextTrack, uri, tlid, target, i, results.length)
|
||||||
html += renderSongLi(track, liID, uri, tlid, renderAlbumInfo)
|
|
||||||
albumTrackSeen += 1
|
|
||||||
}
|
}
|
||||||
tableid = '#' + tableid
|
|
||||||
$(target).html(html)
|
|
||||||
// Retrieve album covers
|
|
||||||
for (i = 0; i < coversList.length; i++) {
|
|
||||||
getCover(coversList[i][0], target + '-cover-' + coversList[i][1], 'small')
|
|
||||||
}
|
}
|
||||||
|
updatePlayIcons(songdata.track.uri, songdata.tlid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// process updated playlist to gui
|
// process updated playlist to gui
|
||||||
@ -519,3 +514,36 @@ function isSpotifyStarredPlaylist (playlist) {
|
|||||||
var starredRegex = /spotify:user:.*:starred/g
|
var starredRegex = /spotify:user:.*:starred/g
|
||||||
return (starredRegex.test(playlist.uri) && playlist.name === 'Starred')
|
return (starredRegex.test(playlist.uri) && playlist.name === 'Starred')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a URI to a jQuery-safe identifier. jQuery identifiers need to be
|
||||||
|
* unique per page and cannot contain special characters.
|
||||||
|
*
|
||||||
|
* @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. Also accepts jQuery identifiers starting with '#'.
|
||||||
|
*
|
||||||
|
* @param {string} uri - URI to encode, usually the URI of a Mopidy track.
|
||||||
|
*
|
||||||
|
* @param {boolean} includePrefix - Will prefix the generated identifier
|
||||||
|
* with the '#' character if set to 'true', ready to be passed to $() or
|
||||||
|
* jQuery().
|
||||||
|
*
|
||||||
|
* @return {string} - a string in the format '[#]identifier-encodedURI' that
|
||||||
|
* is safe to use as a jQuery identifier.
|
||||||
|
*/
|
||||||
|
function getjQueryID (identifier, uri, includePrefix) {
|
||||||
|
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
|
||||||
|
function fixedEncodeURIComponent (str) {
|
||||||
|
return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
|
||||||
|
return '%' + c.charCodeAt(0).toString(16)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@ -413,7 +413,6 @@ function locationHashChanged () {
|
|||||||
break
|
break
|
||||||
case 'current':
|
case 'current':
|
||||||
$('#navcurrent a').addClass('ui-state-active ui-state-persist ui-btn-active')
|
$('#navcurrent a').addClass('ui-state-active ui-state-persist ui-btn-active')
|
||||||
getCurrentPlaylist()
|
|
||||||
break
|
break
|
||||||
case 'playlists':
|
case 'playlists':
|
||||||
$('#navplaylists a').addClass('ui-state-active ui-state-persist ui-btn-active')
|
$('#navplaylists a').addClass('ui-state-active ui-state-persist ui-btn-active')
|
||||||
@ -622,55 +621,29 @@ $(document).ready(function (event) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
function updatePlayIcons (uri, tlid) {
|
function updatePlayIcons (uri, tlid) {
|
||||||
// update styles of listviews
|
// Update styles of listviews
|
||||||
$('#currenttable li').each(function () {
|
var listviews = [PLAYLIST_TABLE, SEARCH_TRACK_TABLE, ARTIST_TABLE, ALBUM_TABLE, BROWSE_TABLE]
|
||||||
|
var target = CURRENT_PLAYLIST_TABLE.substr(1)
|
||||||
|
$(CURRENT_PLAYLIST_TABLE).children('li').each(function () {
|
||||||
var eachTlid = $(this).attr('tlid')
|
var eachTlid = $(this).attr('tlid')
|
||||||
if (typeof eachTlid !== 'undefined') {
|
if (typeof eachTlid !== 'undefined') {
|
||||||
eachTlid = parseInt(eachTlid)
|
eachTlid = parseInt(eachTlid)
|
||||||
}
|
}
|
||||||
if (this.id === 'currenttable-' + uri && eachTlid === tlid) {
|
if (this.id === getjQueryID(target, uri) && eachTlid === tlid) {
|
||||||
$(this).addClass('currenttrack')
|
$(this).addClass('currenttrack')
|
||||||
} else {
|
} else {
|
||||||
$(this).removeClass('currenttrack')
|
$(this).removeClass('currenttrack')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
$('#playlisttracks li').each(function () {
|
for (var i = 0; i < listviews.length; i++) {
|
||||||
if (this.id === 'playlisttracks-' + uri) {
|
target = listviews[i].substr(1)
|
||||||
|
$(listviews[i]).children('li').each(function () {
|
||||||
|
if (this.id === getjQueryID(target, uri)) {
|
||||||
$(this).addClass('currenttrack2')
|
$(this).addClass('currenttrack2')
|
||||||
} else {
|
} else {
|
||||||
$(this).removeClass('currenttrack2')
|
$(this).removeClass('currenttrack2')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
$('#trackresulttable li').each(function () {
|
|
||||||
if (this.id === 'trackresulttable-' + uri) {
|
|
||||||
$(this).addClass('currenttrack2')
|
|
||||||
} else {
|
|
||||||
$(this).removeClass('currenttrack2')
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
$('#artiststable li').each(function () {
|
|
||||||
if (this.id === 'artiststable-' + uri) {
|
|
||||||
$(this).addClass('currenttrack2')
|
|
||||||
} else {
|
|
||||||
$(this).removeClass('currenttrack2')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
$('#albumstable li').each(function () {
|
|
||||||
if (this.id === 'albumstable-' + uri) {
|
|
||||||
$(this).addClass('currenttrack2')
|
|
||||||
} else {
|
|
||||||
$(this).removeClass('currenttrack2')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
$('#browselist li').each(function () {
|
|
||||||
if (this.id === 'browselisttracks-' + uri) {
|
|
||||||
$(this).addClass('currenttrack2')
|
|
||||||
} else {
|
|
||||||
$(this).removeClass('currenttrack2')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -77,7 +77,7 @@ function getCoverFromLastFm (track, images, size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}, $(images).attr('src', defUrl))
|
||||||
}
|
}
|
||||||
|
|
||||||
function getArtistImage (nwartist, image, size) {
|
function getArtistImage (nwartist, image, size) {
|
||||||
@ -88,5 +88,5 @@ function getArtistImage (nwartist, image, size) {
|
|||||||
$(image).attr('src', data.artist.image[i]['#text'] || defUrl)
|
$(image).attr('src', data.artist.image[i]['#text'] || defUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}})
|
}}, $(images).attr('src', defUrl))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -106,6 +106,10 @@ function processSearchResults (resultArr) {
|
|||||||
customTracklists[URI_SCHEME + ':trackresultscache'] = results.tracks
|
customTracklists[URI_SCHEME + ':trackresultscache'] = results.tracks
|
||||||
|
|
||||||
if (emptyResult) {
|
if (emptyResult) {
|
||||||
|
$('#searchtracks').show()
|
||||||
|
$(SEARCH_TRACK_TABLE).append(
|
||||||
|
'<li class="song albumli"><a href="#"><h1><i></i>No tracks found...</h1></a></li>'
|
||||||
|
)
|
||||||
toast('No results')
|
toast('No results')
|
||||||
showLoading(false)
|
showLoading(false)
|
||||||
return false
|
return false
|
||||||
@ -193,8 +197,6 @@ function processSearchResults (resultArr) {
|
|||||||
// Inject list items, refresh listview and hide superfluous items.
|
// Inject list items, refresh listview and hide superfluous items.
|
||||||
$(SEARCH_ALBUM_TABLE).html(child).listview('refresh').find('.overflow').hide()
|
$(SEARCH_ALBUM_TABLE).html(child).listview('refresh').find('.overflow').hide()
|
||||||
|
|
||||||
$('#expandsearch').show()
|
|
||||||
|
|
||||||
// Track results
|
// Track results
|
||||||
resultsToTables(results.tracks, SEARCH_TRACK_TABLE, URI_SCHEME + ':trackresultscache')
|
resultsToTables(results.tracks, SEARCH_TRACK_TABLE, URI_SCHEME + ':trackresultscache')
|
||||||
|
|
||||||
@ -250,12 +252,13 @@ function togglePlaylists () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showTracklist (uri) {
|
function showTracklist (uri) {
|
||||||
|
showLoading(true)
|
||||||
$(PLAYLIST_TABLE).empty()
|
$(PLAYLIST_TABLE).empty()
|
||||||
togglePlaylists()
|
togglePlaylists()
|
||||||
var tracks = getPlaylistTracks(uri).then(function (tracks) {
|
var tracks = getPlaylistTracks(uri).then(function (tracks) {
|
||||||
resultsToTables(tracks, PLAYLIST_TABLE, uri)
|
resultsToTables(tracks, PLAYLIST_TABLE, uri, 'return togglePlaylists();', true)
|
||||||
})
|
|
||||||
showLoading(false)
|
showLoading(false)
|
||||||
|
})
|
||||||
updatePlayIcons(uri)
|
updatePlayIcons(uri)
|
||||||
$('#playlistslist li a').each(function () {
|
$('#playlistslist li a').each(function () {
|
||||||
$(this).removeClass('playlistactive')
|
$(this).removeClass('playlistactive')
|
||||||
|
|||||||
@ -76,78 +76,78 @@ function processPlaystate (data) {
|
|||||||
* process results of a browse list
|
* process results of a browse list
|
||||||
*********************************************************/
|
*********************************************************/
|
||||||
function processBrowseDir (resultArr) {
|
function processBrowseDir (resultArr) {
|
||||||
var backHtml = '<li style="background-color:#ccc"><a href="#" onclick="return getBrowseDir();"><h1 class="trackname"><i class="fa fa-arrow-circle-left"></i> Back</h1></a></li>'
|
$(BROWSE_TABLE).empty()
|
||||||
if ((!resultArr) || (resultArr === '') || (resultArr.length === 0)) {
|
if (browseStack.length > 0) {
|
||||||
$('#browsepath').html('No tracks found...')
|
renderSongLiBackButton(resultArr, BROWSE_TABLE, 'return getBrowseDir();')
|
||||||
$('#browselist').html(backHtml)
|
}
|
||||||
|
if (!resultArr || resultArr.length === 0) {
|
||||||
showLoading(false)
|
showLoading(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#browselist').empty()
|
|
||||||
|
|
||||||
var child = ''
|
|
||||||
var rooturi = ''
|
|
||||||
var uri = resultArr[0].uri
|
|
||||||
|
|
||||||
// check root uri
|
|
||||||
// find last : or / (spltting the result)
|
|
||||||
// do it twice, since.
|
|
||||||
var colonindex = uri.lastIndexOf(':')
|
|
||||||
var slashindex = uri.lastIndexOf('/')
|
|
||||||
|
|
||||||
var lastindex = (colonindex > slashindex) ? colonindex : slashindex
|
|
||||||
rooturi = uri.slice(0, lastindex)
|
|
||||||
if (resultArr[0].type === 'track') {
|
|
||||||
rooturi = rooturi.replace(':track:', ':directory:')
|
|
||||||
}
|
|
||||||
colonindex = rooturi.lastIndexOf(':')
|
|
||||||
slashindex = rooturi.lastIndexOf('/')
|
|
||||||
|
|
||||||
lastindex = (colonindex > slashindex) ? colonindex : slashindex
|
|
||||||
rooturi = rooturi.slice(0, lastindex)
|
|
||||||
|
|
||||||
if (browseStack.length > 0) {
|
|
||||||
child += backHtml
|
|
||||||
}
|
|
||||||
|
|
||||||
browseTracks = []
|
browseTracks = []
|
||||||
|
uris = []
|
||||||
|
var ref, track, previousTrack, nextTrack
|
||||||
|
var uri = resultArr[0].uri
|
||||||
|
var length = 0 || resultArr.length
|
||||||
|
|
||||||
for (var i = 0, index = 0; i < resultArr.length; i++) {
|
for (var i = 0, index = 0; i < resultArr.length; i++) {
|
||||||
iconClass = getMediaClass(resultArr[i].uri)
|
|
||||||
if (resultArr[i].type === 'track') {
|
if (resultArr[i].type === 'track') {
|
||||||
// console.log(resultArr[i]);
|
ref = resultArr[i]
|
||||||
mopidy.library.lookup({'uris': [resultArr[i].uri]}).then(function (resultDict) {
|
popupData[ref.uri] = ref
|
||||||
var lookupUri = Object.keys(resultDict)[0]
|
browseTracks.push(ref)
|
||||||
popupData[lookupUri] = resultDict[lookupUri][0]
|
uris.push(ref.uri)
|
||||||
browseTracks.push(resultDict[lookupUri][0])
|
|
||||||
}, console.error)
|
$(BROWSE_TABLE).append(
|
||||||
child += '<li class="song albumli" id="browselisttracks-' + resultArr[i].uri + '">' +
|
'<li class="song albumli" id="' + getjQueryID(BROWSE_TABLE, ref.uri) + '">' +
|
||||||
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\', \'' + resultArr[i].uri + '\', \'' + index + '\');">' +
|
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\', \'' + ref.uri + '\', \'' + index + '\');">' +
|
||||||
'<i class="fa fa-ellipsis-v"></i></a>' +
|
'<i class="fa fa-ellipsis-v"></i></a>' +
|
||||||
'<a href="#" class="browsetrack" onclick="return playBrowsedTracks(PLAY_ALL, ' + index + ');" id="' + resultArr[i].uri +
|
'<a href="#" class="browsetrack" onclick="return playBrowsedTracks(PLAY_ALL, ' + index + ');">' +
|
||||||
'"><h1 class="trackname"><i class="' + iconClass + '"></i> ' + resultArr[i].name + '</h1></a></li>'
|
'<h1><i></i> ' + ref.name + '</h1></a></li>'
|
||||||
|
)
|
||||||
index++
|
index++
|
||||||
} else {
|
} else {
|
||||||
|
var iconClass = ''
|
||||||
if (browseStack.length > 0) {
|
if (browseStack.length > 0) {
|
||||||
iconClass = 'fa fa-folder-o'
|
iconClass = 'fa fa-folder-o'
|
||||||
}
|
|
||||||
child += '<li><a href="#" onclick="return getBrowseDir(this.id);" id="' + resultArr[i].uri +
|
|
||||||
'""><h1 class="trackname"><i class="' + iconClass + '"></i> ' + resultArr[i].name + '</h1></a></li>'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#browselist').html(child)
|
|
||||||
if (browseStack.length > 0) {
|
|
||||||
child = getMediaHuman(uri)
|
|
||||||
iconClass = getMediaClass(uri)
|
|
||||||
$('#browsepath').html('<i class="' + iconClass + '"></i> ' + child)
|
|
||||||
} else {
|
} else {
|
||||||
$('#browsepath').html('')
|
iconClass = getMediaClass(resultArr[i].uri)
|
||||||
|
}
|
||||||
|
$(BROWSE_TABLE).append(
|
||||||
|
'<li><a href="#" onclick="return getBrowseDir(this.id);" id="' + resultArr[i].uri + '">' +
|
||||||
|
'<h1><i class="' + iconClass + '"></i> ' + resultArr[i].name + '</h1></a></li>'
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePlayIcons(songdata.track.uri, songdata.tlid)
|
updatePlayIcons(songdata.track.uri, songdata.tlid)
|
||||||
|
|
||||||
|
if (uris.length > 0) {
|
||||||
|
mopidy.library.lookup({'uris': uris}).then(function (resultDict) {
|
||||||
|
// Break into albums and put in tables
|
||||||
|
var track, previousTrack, nextTrack, uri
|
||||||
|
$.each(resultArr, function (i, ref) {
|
||||||
|
if (ref.type === 'track') {
|
||||||
|
previousTrack = track || undefined
|
||||||
|
if (i < resultArr.length - 1 && resultDict[resultArr[i + 1].uri]) {
|
||||||
|
nextTrack = resultDict[resultArr[i + 1].uri][0]
|
||||||
|
} else {
|
||||||
|
nextTrack = undefined
|
||||||
|
}
|
||||||
|
track = resultDict[ref.uri][0]
|
||||||
|
if (uris.length === 1 || (previousTrack && !hasSameAlbum(previousTrack, track) && !hasSameAlbum(track, nextTrack))) {
|
||||||
|
renderSongLiAlbumInfo(track, BROWSE_TABLE)
|
||||||
|
}
|
||||||
|
if (!hasSameAlbum(previousTrack, track)) {
|
||||||
|
// Starting to render a new album in the list.
|
||||||
|
renderSongLiDivider(track, nextTrack, i, BROWSE_TABLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
showLoading(false)
|
showLoading(false)
|
||||||
|
}, console.error)
|
||||||
|
} else {
|
||||||
|
showLoading(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ******************************************************
|
/** ******************************************************
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
CACHE MANIFEST
|
CACHE MANIFEST
|
||||||
|
|
||||||
# 2016-03-06:v2
|
# 2016-03-14:v1
|
||||||
|
|
||||||
NETWORK:
|
NETWORK:
|
||||||
*
|
*
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user