Reduce number of DOM manipulations to improve performance.

This commit is contained in:
jcass 2016-04-16 17:10:52 +02:00
parent fd7ad26b52
commit 4474658d39
6 changed files with 52 additions and 36 deletions

2
.gitignore vendored
View File

@ -19,3 +19,5 @@ npm-debug.log
.project .project
*.pbxproj *.pbxproj
*.egg-info *.egg-info
.cache
.eggs

View File

@ -85,6 +85,7 @@ v2.3.0 (UNRELEASED)
(Addresses: `#133 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/133>`_). (Addresses: `#133 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/133>`_).
- Optimized updating of 'now playing' icons in tracklists. - Optimized updating of 'now playing' icons in tracklists.
(Addresses: `#184 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/184>`_). (Addresses: `#184 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/184>`_).
- Optimized rendering of large lists of tracks to make UI more responsive.
**Fixes** **Fixes**
@ -93,6 +94,8 @@ v2.3.0 (UNRELEASED)
- last.fm artist image lookups should now always return the correct image for similarly named artists. - last.fm artist image lookups should now always return the correct image for similarly named artists.
- Ensure that browsed tracks are always added to the queue using the track URI rather than the track's position in the folder. - Ensure that browsed tracks are always added to the queue using the track URI rather than the track's position in the folder.
(Fixes: `#124 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/124>`_). (Fixes: `#124 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/124>`_).
- Fixed an issue where searches would be performed as soon as the user switches to the 'Search' pane,
instead of waiting for the 'Search!' button to be clicked.
v2.2.0 (2016-03-01) v2.2.0 (2016-03-01)
------------------- -------------------

View File

@ -175,6 +175,7 @@ function artistsToString (artists, max) {
*********************************************************/ *********************************************************/
function albumTracksToTable (pl, target, uri) { function albumTracksToTable (pl, target, uri) {
var track, previousTrack, nextTrack var track, previousTrack, nextTrack
var html = ''
$(target).empty() $(target).empty()
$(target).attr('data', uri) $(target).attr('data', uri)
for (var i = 0; i < pl.length; i++) { for (var i = 0; i < pl.length; i++) {
@ -182,8 +183,9 @@ function albumTracksToTable (pl, target, uri) {
nextTrack = i < pl.length - 1 ? pl[i + 1] : undefined nextTrack = i < pl.length - 1 ? pl[i + 1] : undefined
track = pl[i] track = pl[i]
popupData[track.uri] = track popupData[track.uri] = track
renderSongLi(previousTrack, track, nextTrack, uri, '', target, i, pl.length) html += renderSongLi(previousTrack, track, nextTrack, uri, '', target, i, pl.length)
} }
$(target).append(html)
updatePlayIcons(songdata.track.uri, songdata.tlid, controls.getIconForAction()) updatePlayIcons(songdata.track.uri, songdata.tlid, controls.getIconForAction())
} }
@ -191,15 +193,16 @@ function renderSongLi (previousTrack, track, nextTrack, uri, tlid, target, curre
var name var name
var tlidParameter = '' var tlidParameter = ''
var onClick = '' var onClick = ''
var html = ''
track.name = validateTrackName(track, currentIndex) track.name = validateTrackName(track, currentIndex)
// Leave out unplayable items // Leave out unplayable items
if (track.name.substring(0, 12) === '[unplayable]') { if (track.name.substring(0, 12) === '[unplayable]') {
return return html
} }
// Streams // Streams
if (track.length === -1) { if (track.length === -1) {
$(target).append('<li class="albumli"><a href="#"><h1><i class="' + getMediaClass(track.uri) + '"></i> ' + track.name + ' [Stream]</h1></a></li>') html += '<li class="albumli"><a href="#"><h1><i class="' + getMediaClass(track.uri) + '"></i> ' + track.name + ' [Stream]</h1></a></li>'
return return html
} }
if (target === CURRENT_PLAYLIST_TABLE && typeof tlid === 'number' && tlid >= 0) { // Current queue: Show popup menu icon. onClick plays track. if (target === CURRENT_PLAYLIST_TABLE && typeof tlid === 'number' && tlid >= 0) { // Current queue: Show popup menu icon. onClick plays track.
@ -209,33 +212,33 @@ function renderSongLi (previousTrack, track, nextTrack, uri, tlid, target, curre
onClick = 'return controls.playTracks(\'\', mopidy, \'' + track.uri + '\', \'' + uri + '\');' onClick = 'return controls.playTracks(\'\', mopidy, \'' + track.uri + '\', \'' + uri + '\');'
} }
$(target).append( html +=
'<li class="song albumli" id="' + getjQueryID(target, track.uri) + '" tlid="' + tlid + '">' + '<li class="song albumli" id="' + getjQueryID(target, track.uri) + '" tlid="' + tlid + '">' +
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + track.uri + tlidParameter + '\');">' + '<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 + '"><h1><i></i> ' + track.name + '</h1></a></li>' '<a href="#" onclick="' + onClick + '"><h1><i class="' + getMediaClass(track.uri) + '"></i> ' + track.name + '</h1>'
)
if (listLength === 1 || !hasSameAlbum(previousTrack, track) && !hasSameAlbum(track, nextTrack)) { if (listLength === 1 || !hasSameAlbum(previousTrack, track) && !hasSameAlbum(track, nextTrack)) {
renderSongLiAlbumInfo(track, target) html += renderSongLiAlbumInfo(track)
}
// TODO: remove this hard-coded conditions for 'ALBUM_TABLE' and 'BROWSE_TABLE'
if (target !== ALBUM_TABLE && target !== BROWSE_TABLE && !hasSameAlbum(previousTrack, track)) {
// Starting to render a new album in the list.
renderSongLiDivider(track, nextTrack, currentIndex, target)
} }
html += '</a></li>'
return html
} }
/* Tracklist renderer for track artist and album name. */
function renderSongLiAlbumInfo (track, target) { function renderSongLiAlbumInfo (track, target) {
var html = '</p>' var html = renderSongLiTrackArtists(track)
html += renderSongLiTrackArtists(track)
if (track.album && track.album.name) { if (track.album && track.album.name) {
html += ' - <em>' + track.album.name + '</em></p>' html += ' - <em>' + track.album.name + '</em></p>'
} }
target = getjQueryID(target, track.uri, true) if (typeof target !== 'undefined' && target.length > 0) {
$(target).children('a').eq(1).append(html) target = getjQueryID(target, track.uri, true)
$(target + ' a h1 i').addClass(getMediaClass(track.uri)) $(target).children('a').eq(1).append(html)
}
return html
} }
/* Tracklist renderer for track artist information. */
function renderSongLiTrackArtists (track) { function renderSongLiTrackArtists (track) {
var html = '' var html = ''
if (track.artists) { if (track.artists) {
@ -252,23 +255,28 @@ function renderSongLiTrackArtists (track) {
return html return html
} }
function renderSongLiDivider (track, nextTrack, currentIndex, target) { /* Tracklist renderer to insert dividers between albums. */
target = getjQueryID(target, track.uri, true) function renderSongLiDivider (previousTrack, track, nextTrack, currentIndex, target) {
// Render differently if part of an album var html = ''
if (hasSameAlbum(track, nextTrack)) { // Render differently if part of an album.
// Large divider with album cover if (!hasSameAlbum(previousTrack, track) && hasSameAlbum(track, nextTrack)) {
$(target).before( // Large divider with album cover.
html +=
'<li class="albumdivider"><a href="#" onclick="return library.showAlbum(\'' + track.album.uri + '\');">' + '<li class="albumdivider"><a href="#" onclick="return library.showAlbum(\'' + track.album.uri + '\');">' +
'<img id="' + getjQueryID(target + '-cover', track.uri) + '" class="artistcover" width="30" height="30"/>' + '<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>' + '<h1><i class="' + getMediaClass(track.uri) + '"></i> ' + track.album.name + '</h1><p>' +
renderSongLiTrackArtists(track) + '</p></a></li>' renderSongLiTrackArtists(track) + '</p></a></li>'
)
// Retrieve album covers // Retrieve album covers
images.setAlbumImage(track.uri, getjQueryID(target + '-cover', track.uri, true), mopidy, 'small') images.setAlbumImage(track.uri, getjQueryID(target + '-cover', track.uri, true), mopidy, 'small')
} else if (currentIndex > 0) { } else if (!hasSameAlbum(track, nextTrack) && currentIndex > 0) {
// Small divider // Small divider
$(target).before('<li class="smalldivider"> &nbsp;</li>') html += '<li class="smalldivider"> &nbsp;</li>'
} }
if (typeof target !== 'undefined' && target.length > 0) {
target = getjQueryID(target, track.uri, true)
$(target).before(html)
}
return html
} }
function renderSongLiBackButton (results, target, onClick, optional) { function renderSongLiBackButton (results, target, onClick, optional) {
@ -317,6 +325,7 @@ function resultsToTables (results, target, uri, onClickBack, backIsOptional) {
$(target).attr('data', uri) $(target).attr('data', uri)
var track, previousTrack, nextTrack, tlid var track, previousTrack, nextTrack, tlid
var html = ''
// Break into albums and put in tables // Break into albums and put in tables
for (i = 0; i < results.length; i++) { for (i = 0; i < results.length; i++) {
@ -331,9 +340,11 @@ function resultsToTables (results, target, uri, onClickBack, backIsOptional) {
nextTrack = nextTrack ? nextTrack.track : undefined nextTrack = nextTrack ? nextTrack.track : undefined
} }
popupData[track.uri] = track popupData[track.uri] = track
renderSongLi(previousTrack, track, nextTrack, uri, tlid, target, i, results.length) html += renderSongLiDivider(previousTrack, track, nextTrack, i, target)
html += renderSongLi(previousTrack, track, nextTrack, uri, tlid, target, i, results.length)
} }
} }
$(target).append(html)
updatePlayIcons(songdata.track.uri, songdata.tlid, controls.getIconForAction()) updatePlayIcons(songdata.track.uri, songdata.tlid, controls.getIconForAction())
} }

View File

@ -419,7 +419,6 @@ function locationHashChanged () {
case 'search': case 'search':
$('#navsearch a').addClass($.mobile.activeBtnClass) $('#navsearch a').addClass($.mobile.activeBtnClass)
$('#searchinput').focus() $('#searchinput').focus()
library.initSearch($('#searchinput').val())
break break
case 'stream': case 'stream':
$('#navstream a').addClass('ui-state-active ui-state-persist ui-btn-active') $('#navstream a').addClass('ui-state-active ui-state-persist ui-btn-active')

View File

@ -89,6 +89,7 @@ function processBrowseDir (resultArr) {
var uri = resultArr[0].uri var uri = resultArr[0].uri
var length = 0 || resultArr.length var length = 0 || resultArr.length
customTracklists[BROWSE_TABLE] = [] customTracklists[BROWSE_TABLE] = []
var html = ''
for (var i = 0, index = 0; i < resultArr.length; i++) { for (var i = 0, index = 0; i < resultArr.length; i++) {
if (resultArr[i].type === 'track') { if (resultArr[i].type === 'track') {
@ -100,7 +101,7 @@ function processBrowseDir (resultArr) {
customTracklists[BROWSE_TABLE].push(ref) customTracklists[BROWSE_TABLE].push(ref)
uris.push(ref.uri) uris.push(ref.uri)
renderSongLi(previousRef, ref, nextRef, BROWSE_TABLE, '', BROWSE_TABLE, index, resultArr.length) html += renderSongLi(previousRef, ref, nextRef, BROWSE_TABLE, '', BROWSE_TABLE, index, resultArr.length)
index++ index++
} else { } else {
@ -110,13 +111,13 @@ function processBrowseDir (resultArr) {
} else { } else {
iconClass = getMediaClass(resultArr[i].uri) iconClass = getMediaClass(resultArr[i].uri)
} }
$(BROWSE_TABLE).append( html += '<li><a href="#" onclick="return library.getBrowseDir(this.id);" id="' + resultArr[i].uri + '">' +
'<li><a href="#" onclick="return library.getBrowseDir(this.id);" id="' + resultArr[i].uri + '">' + '<h1><i class="' + iconClass + '"></i> ' + resultArr[i].name + '</h1></a></li>'
'<h1><i class="' + iconClass + '"></i> ' + resultArr[i].name + '</h1></a></li>'
)
} }
} }
$(BROWSE_TABLE).append(html)
updatePlayIcons(songdata.track.uri, songdata.tlid, controls.getIconForAction()) updatePlayIcons(songdata.track.uri, songdata.tlid, controls.getIconForAction())
if (uris.length > 0) { if (uris.length > 0) {
@ -138,7 +139,7 @@ function processBrowseDir (resultArr) {
} }
if (!hasSameAlbum(previousTrack, track)) { if (!hasSameAlbum(previousTrack, track)) {
// Starting to render a new album in the list. // Starting to render a new album in the list.
renderSongLiDivider(track, nextTrack, i, BROWSE_TABLE) renderSongLiDivider(previousTrack, track, nextTrack, i, BROWSE_TABLE)
} }
} }
}) })

View File

@ -1,6 +1,6 @@
CACHE MANIFEST CACHE MANIFEST
# 2016-04-26:v2 # 2016-04-27:v1
NETWORK: NETWORK:
* *