diff --git a/dashboard-ui/css/mediaplayer-video.css b/dashboard-ui/css/mediaplayer-video.css index 14f8b7b40d..814bc66e39 100644 --- a/dashboard-ui/css/mediaplayer-video.css +++ b/dashboard-ui/css/mediaplayer-video.css @@ -139,7 +139,7 @@ text-align: left; margin-left: 0; right: 0; - bottom: 83px; + bottom: 85px; } /* Media queries @@ -259,7 +259,7 @@ } #mediaPlayer #videoControls .mediaPlayerFlyout { - bottom: 148px; + bottom: 150px; } } diff --git a/dashboard-ui/scripts/chromecast.js b/dashboard-ui/scripts/chromecast.js index bca82b8327..51ad1ee90c 100644 --- a/dashboard-ui/scripts/chromecast.js +++ b/dashboard-ui/scripts/chromecast.js @@ -66,6 +66,17 @@ this.hasReceivers = false; + this.currentMediaOffset = 0; + + // Progress bar element id + this.progressBar = "positionSlider"; + + // Timec display element id + this.duration = "currentTime"; + + // Playback display element id + this.playback = "playTime"; + this.initializeCastPlayer(); }; @@ -89,7 +100,7 @@ // v1 Id AE4DA10A // v2 Id 472F0435 - var applicationID = 'AE4DA10A'; + var applicationID = '472F0435'; // request session var sessionRequest = new chrome.cast.SessionRequest(applicationID); @@ -445,6 +456,8 @@ function getMetadata(item) { + console.log("md item", item); + var metadata = {}; if (item.Type == 'Episode') { @@ -512,7 +525,7 @@ else if (item.MediaType == 'Movie') { metadata = new chrome.cast.media.MovieMediaMetadata(); - metadata.type = chrome.cast.media.MetadataType.MUSIC_TRACK; + metadata.type = chrome.cast.media.MetadataType.MOVIE; if (item.ProductionYear) { metadata.releaseYear = item.ProductionYear; @@ -617,6 +630,8 @@ return; } + this.currentMediaOffset = startTimeTicks || 0; + var maxBitrate = 12000000; var mediaInfo = getMediaSourceInfo(user, item, maxBitrate, mediaSourceId, audioStreamIndex, subtitleStreamIndex); @@ -653,40 +668,62 @@ console.log("chromecast new media session ID:" + mediaSession.mediaSessionId + ' (' + how + ')'); this.currentMediaSession = mediaSession; + this.currentMediaTime = this.session.media[0].currentTime; + if (how == 'loadMedia') { this.castPlayerState = PLAYER_STATE.PLAYING; + clearInterval(this.timer); + this.startProgressTimer(this.incrementMediaTime); } if (how == 'activeSession') { this.castPlayerState = this.session.media[0].playerState; - this.currentMediaTime = this.session.media[0].currentTime; } if (this.castPlayerState == PLAYER_STATE.PLAYING) { // start progress timer - //this.startProgressTimer(this.incrementMediaTime); + this.startProgressTimer(this.incrementMediaTime); } this.currentMediaSession.addUpdateListener(this.onMediaStatusUpdate.bind(this)); + this.currentMediaDuration = this.currentMediaSession.media.duration; - //this.currentMediaDuration = this.currentMediaSession.media.duration; - //var duration = this.currentMediaDuration; - //var hr = parseInt(duration / 3600); - //duration -= hr * 3600; - //var min = parseInt(duration / 60); - //var sec = parseInt(duration % 60); - //if (hr > 0) { - // duration = hr + ":" + min + ":" + sec; - //} - //else { - // if (min > 0) { - // duration = min + ":" + sec; - // } - // else { - // duration = sec; - // } - //} - //document.getElementById("duration").innerHTML = duration; + var playTime = document.getElementById(this.playback); + if (!playTime) { + // Set duration time + var totalTime = document.getElementById(this.duration); + totalTime.innerHTML = " / " + formatTime(this.currentMediaDuration); + + // Set play time + playTime = document.createElement("div"); + playTime.id = this.playback; + playTime.className = "currentTime"; + playTime.style.marginRight = "5px"; + totalTime.parentNode.insertBefore(playTime, totalTime); + playTime.innerHTML = formatTime(this.currentMediaTime); + } + }; + + function formatTime(duration) { + var hr = parseInt(duration / 3600); + duration -= hr * 3600; + var min = parseInt(duration / 60); + var sec = parseInt(duration % 60); + + hr = "" + hr; + min = "" + min; + sec = "" + sec; + var hh = pad(hr); + var mm = pad(min); + var ss = pad(sec); + + duration = hh + ":" + mm + ":" + ss; + + return duration; + }; + + function pad(s) { + return "00".substring(0, 2 - s.length) + s; }; /** @@ -707,7 +744,7 @@ this.castPlayerState = PLAYER_STATE.IDLE; } console.log("chromecast updating media"); - //this.updateProgressBar(e); + this.updateProgressBarByTimer(); }; /** @@ -745,6 +782,7 @@ this.currentMediaSession.addUpdateListener(this.onMediaStatusUpdate.bind(this)); this.castPlayerState = PLAYER_STATE.PLAYING; // start progress timer + clearInterval(this.timer); this.startProgressTimer(this.incrementMediaTime); break; case PLAYER_STATE.IDLE: @@ -791,6 +829,10 @@ this.onError.bind(this)); this.castPlayerState = PLAYER_STATE.STOPPED; clearInterval(this.timer); + var playTime = document.getElementById(this.playback); + if (playTime) { + playTime.parentNode.removeChild(playTime); + } }; /** @@ -849,19 +891,10 @@ * @param {Event} e An event object from seek */ CastPlayer.prototype.seekMedia = function (event) { - var pos = parseInt(event.offsetX); - var pi = document.getElementById("progress_indicator"); - var p = document.getElementById("progress"); - if (event.currentTarget.id == 'progress_indicator') { - var curr = parseInt(this.currentMediaTime + this.currentMediaDuration * pos / PROGRESS_BAR_WIDTH); - var pp = parseInt(pi.style.marginLeft) + pos; - var pw = parseInt(p.style.width) + pos; - } - else { - var curr = parseInt(pos * this.currentMediaDuration / PROGRESS_BAR_WIDTH); - var pp = pos - 21 - PROGRESS_BAR_WIDTH; - var pw = pos; - } + var pos = parseInt(event); + var p = document.getElementById(this.progressBar); + var curr = parseInt(this.currentMediaTime + this.currentMediaDuration * pos); + var pw = parseInt(p.value) + pos; if (this.castPlayerState != PLAYER_STATE.PLAYING && this.castPlayerState != PLAYER_STATE.PAUSED) { return; @@ -899,20 +932,20 @@ * @param {Object} e An media status update object */ CastPlayer.prototype.updateProgressBar = function (e) { - var p = document.getElementById("progress"); - var pi = document.getElementById("progress_indicator"); + var p = document.getElementById(this.progressBar); if (e.idleReason == 'FINISHED' && e.playerState == 'IDLE') { - p.style.width = '0px'; - pi.style.marginLeft = -21 - PROGRESS_BAR_WIDTH + 'px'; + p.value = 0; clearInterval(this.timer); this.castPlayerState = PLAYER_STATE.STOPPED; + if (e.idleReason == 'FINISHED') { + $.publish("/playback/complete", e); + console.log("playback complete", e); + } } else { - p.style.width = Math.ceil(PROGRESS_BAR_WIDTH * e.currentTime / this.currentMediaSession.media.duration + 1) + 'px'; + p.value = Number(e.currentTime / this.currentMediaSession.media.duration + 1).toFixed(3); this.progressFlag = false; setTimeout(this.setProgressFlag.bind(this), 1000); // don't update progress in 1 second - var pp = Math.ceil(PROGRESS_BAR_WIDTH * e.currentTime / this.currentMediaSession.media.duration); - pi.style.marginLeft = -21 - PROGRESS_BAR_WIDTH + pp + 'px'; } }; @@ -928,47 +961,159 @@ * Update progress bar based on timer */ CastPlayer.prototype.updateProgressBarByTimer = function () { - var p = document.getElementById("progress"); - if (isNaN(parseInt(p.style.width))) { - p.style.width = 0; + var p = document.getElementById(this.progressBar); + if (isNaN(parseInt(p.value))) { + p.value = 0; } + if (this.currentMediaDuration > 0) { - var pp = Math.floor(PROGRESS_BAR_WIDTH * this.currentMediaTime / this.currentMediaDuration); + var pp = Number(this.currentMediaTime / this.currentMediaDuration).toFixed(3); + + var startTime = this.currentMediaOffset / 10000000; + var playTime = document.getElementById(this.playback); + if (playTime) { + playTime.innerHTML = formatTime(startTime + this.currentMediaTime); + } } if (this.progressFlag) { // don't update progress if it's been updated on media status update event - p.style.width = pp + 'px'; - var pi = document.getElementById("progress_indicator"); - pi.style.marginLeft = -21 - PROGRESS_BAR_WIDTH + pp + 'px'; + p.value = pp; } - if (pp > PROGRESS_BAR_WIDTH) { + if (pp > 100 || this.castPlayerState == PLAYER_STATE.IDLE) { clearInterval(this.timer); this.deviceState = DEVICE_STATE.IDLE; this.castPlayerState = PLAYER_STATE.IDLE; + $.publish("/playback/complete", true); + console.log("playback complete"); } }; + /** + * @param {function} A callback function for the fucntion to start timer + */ + CastPlayer.prototype.startProgressTimer = function(callback) { + if(this.timer) { + clearInterval(this.timer); + this.timer = null; + } + + // start progress timer + this.timer = setInterval(callback.bind(this), this.timerStep); + }; + var castPlayer = new CastPlayer(); - function chromecastPlayer() { + function chromecastPlayer(castPlayer) { var self = this; + var isPositionSliderActive = false; + self.name = PlayerName; - self.play = function (options) { + self.isPaused = false; - if (options.items) { + self.playlist = []; - Dashboard.getCurrentUser().done(function (user) { + self.playlistIndex = 0; - castPlayer.loadMedia(user, options.items[0], options.startTimeTicks); + $.subscribe("/playback/complete", function (e) { + if (self.playlistIndex < (self.playlist.items || []).length) { + self.play(self.playlist); + } + }); + + ////$(".positionSlider", "#footer").off("slidestart slidestop") + //// .on('slidestart', function (e) { + //// isPositionSliderActive = true; + ////}).on('slidestop', positionSliderChange); + + ////function positionSliderChange() { + //// isPositionSliderActive = false; + //// var newPercent = parseInt(this.value); + //// self.changeStream(newPercent); + ////} + + function getItemsForPlayback(query) { + var userId = Dashboard.getCurrentUserId(); + + query.Limit = query.Limit || 100; + query.Fields = getItemFields; + query.ExcludeLocationTypes = "Virtual"; + + return ApiClient.getItems(userId, query); + }; + + function queueItems (items) { + for (var i = 0, length = items.length; i < length; i++) { + self.playlist.push(items[i]); + } + }; + + function queueItemsNext(items) { + var insertIndex = 1; + for (var i = 0, length = items.length; i < length; i++) { + self.playlist.splice(insertIndex, 0, items[i]); + insertIndex++; + } + }; + + function translateItemsForPlayback(items) { + var deferred = $.Deferred(); + var firstItem = items[0]; + var promise; + if (firstItem.IsFolder) { + promise = self.getItemsForPlayback({ + ParentId: firstItem.Id, + Filters: "IsNotFolder", + Recursive: true, + SortBy: "SortName", + MediaTypes: "Audio,Video" }); + } + else if (firstItem.Type == "MusicArtist") { + promise = self.getItemsForPlayback({ + Artists: firstItem.Name, + Filters: "IsNotFolder", + Recursive: true, + SortBy: "SortName", + MediaTypes: "Audio" + }); + } + else if (firstItem.Type == "MusicGenre") { + promise = self.getItemsForPlayback({ + Genres: firstItem.Name, + Filters: "IsNotFolder", + Recursive: true, + SortBy: "SortName", + MediaTypes: "Audio" + }); + } + if (promise) { + promise.done(function (result) { + deferred.resolveWith(null, [result.Items]); + }); } else { + deferred.resolveWith(null, [items]); + } + return deferred.promise(); + }; + + self.play = function (options) { + console.log("play", options); + $("#nowPlayingBar", "#footer").show(); + if (self.isPaused) { + self.isPaused = !self.isPaused; + castPlayer.playMedia(); + } else if (options.items) { + Dashboard.getCurrentUser().done(function (user) { + castPlayer.loadMedia(user, options.items[self.playlistIndex++], options.startPositionTicks); + }); + } else { var userId = Dashboard.getCurrentUserId(); var query = {}; @@ -978,46 +1123,154 @@ query.Ids = options.ids.join(','); ApiClient.getItems(userId, query).done(function (result) { - options.items = result.Items; - self.play(options); - }); } + }; + self.unpause = function () { + console.log("unpause"); + self.isPaused = !self.isPaused; + castPlayer.playMedia(); + }; + + self.pause = function () { + console.log("pause"); + self.isPaused = true; + castPlayer.pauseMedia(); }; self.shuffle = function (id) { - self.play({ ids: [id] }); + var userId = Dashboard.getCurrentUserId(); + ApiClient.getItem(userId, id).done(function (item) { + var query = { + UserId: userId, + Fields: getItemFields, + Limit: 50, + Filters: "IsNotFolder", + Recursive: true, + SortBy: "Random" + }; + + if (item.IsFolder) { + query.ParentId = id; + } + else if (item.Type == "MusicArtist") { + query.MediaTypes = "Audio"; + query.Artists = item.Name; + } + else if (item.Type == "MusicGenre") { + query.MediaTypes = "Audio"; + query.Genres = item.Name; + } else { + return; + } + + self.getItemsForPlayback(query).done(function (result) { + self.playlist = { items: result.Items }; + console.log("shuffle items", result.Items); + self.play(self.playlist); + }); + }); }; self.instantMix = function (id) { - self.play({ ids: [id] }); - }; + var userId = Dashboard.getCurrentUserId(); + ApiClient.getItem(userId, id).done(function (item) { + var promise; + var getItemFields = "MediaSources,Chapters"; + var mixLimit = 3; - self.queue = function (options) { + if (item.Type == "MusicArtist") { + promise = ApiClient.getInstantMixFromArtist(name, { + UserId: userId, + Fields: getItemFields, + Limit: mixLimit + }); + } + else if (item.Type == "MusicGenre") { + promise = ApiClient.getInstantMixFromMusicGenre(name, { + UserId: userId, + Fields: getItemFields, + Limit: mixLimit + }); + } + else if (item.Type == "MusicAlbum") { + promise = ApiClient.getInstantMixFromAlbum(id, { + UserId: userId, + Fields: getItemFields, + Limit: mixLimit + }); + } + else if (item.Type == "Audio") { + promise = ApiClient.getInstantMixFromSong(id, { + UserId: userId, + Fields: getItemFields, + Limit: mixLimit + }); + } + else { + return; + } - }; - - self.queueNext = function (options) { - - }; - - self.stop = function () { - castPlayer.stop(); + promise.done(function (result) { + self.playlist = { items: result.Items }; + console.log("instant mix items", result.Items); + self.play(self.playlist); + }); + }); }; self.canQueueMediaType = function (mediaType) { + return mediaType == "Audio"; + }; - return false; + self.queue = function (options) { + Dashboard.getCurrentUser().done(function (user) { + if (options.items) { + translateItemsForPlayback(options.items).done(function (items) { + queueItems(items); + }); + } else { + getItemsForPlayback({ + Ids: options.ids.join(',') + }).done(function (result) { + translateItemsForPlayback(result.Items).done(function (items) { + queueItems(items); + }); + }); + } + }); + }; + + self.queueNext = function (options) { + Dashboard.getCurrentUser().done(function (user) { + if (options.items) { + queueItemsNext(options.items); + } else { + self.getItemsForPlayback({ + Ids: options.ids.join(',') + }).done(function (result) { + options.items = result.Items; + queueItemsNext(options.items); + }); + } + }); + }; + + self.stop = function () { + $("#nowPlayingBar", "#footer").hide(); + self.playlist = []; + self.playlistIndex = 0; + castPlayer.stopMedia(); }; self.mute = function () { castPlayer.mute(); }; - self.unMute = function () { + self.unmute = function () { castPlayer.unMute(); }; @@ -1026,18 +1279,13 @@ }; self.getTargets = function () { - var targets = []; - targets.push(self.getCurrentTargetInfo()); - return targets; }; self.getCurrentTargetInfo = function () { - var appName = null; - if (castPlayer.session && castPlayer.session.receiver && castPlayer.session.friendlyName) { appName = castPlayer.session.friendlyName; } @@ -1051,9 +1299,80 @@ appName: appName }; }; + + self.setCurrentTime = function (ticks, item, updateSlider) { + // Convert to ticks + ticks = Math.floor(ticks); + var timeText = Dashboard.getDisplayTime(ticks); + if (self.currentDurationTicks) { + timeText += " / " + Dashboard.getDisplayTime(self.currentDurationTicks); + if (updateSlider) { + var percent = ticks / self.currentDurationTicks; + percent *= 100; + self.positionSlider.val(percent).slider('enable').slider('refresh'); + } + } else { + self.positionSlider.slider('disable').slider('refresh'); + } + + self.currentTimeElement.html(timeText); + }; + + self.changeStream = function (position) { + console.log("seek", position); + ////castPlayer.seekMedia(position); + }; + + self.removeFromPlaylist = function (i) { + self.playlist.remove(i); + }; + + self.currentPlaylistIndex = function (i) { + if (i == null) { + return currentPlaylistIndex; + } + + var newItem = self.playlist[i]; + + Dashboard.getCurrentUser().done(function (user) { + self.playInternal(newItem, 0, user); + currentPlaylistIndex = i; + }); + }; + + self.nextTrack = function () { + var newIndex = currentPlaylistIndex + 1; + var newItem = self.playlist[newIndex]; + + if (newItem) { + Dashboard.getCurrentUser().done(function (user) { + self.playInternal(newItem, 0, user); + currentPlaylistIndex = newIndex; + }); + } + }; + + self.previousTrack = function () { + var newIndex = currentPlaylistIndex - 1; + if (newIndex >= 0) { + var newItem = self.playlist[newIndex]; + if (newItem) { + Dashboard.getCurrentUser().done(function (user) { + self.playInternal(newItem, 0, user); + currentPlaylistIndex = newIndex; + }); + } + } + }; + + self.volumeDown = function () { + }; + + self.volumeUp = function () { + }; } - MediaController.registerPlayer(new chromecastPlayer()); + MediaController.registerPlayer(new chromecastPlayer(castPlayer)); $(MediaController).on('playerchange', function () { diff --git a/dashboard-ui/scripts/episodes.js b/dashboard-ui/scripts/episodes.js index d596716ffc..6f2dc42e30 100644 --- a/dashboard-ui/scripts/episodes.js +++ b/dashboard-ui/scripts/episodes.js @@ -34,7 +34,8 @@ showTitle: true, showParentTitle: true, overlayText: true, - selectionPanel: true + selectionPanel: true, + lazy: true }); $('.itemsContainer', page).removeClass('timelineItemsContainer'); diff --git a/dashboard-ui/scripts/librarybrowser.js b/dashboard-ui/scripts/librarybrowser.js index f71a426a52..6468b53de0 100644 --- a/dashboard-ui/scripts/librarybrowser.js +++ b/dashboard-ui/scripts/librarybrowser.js @@ -432,6 +432,8 @@ options.shape = options.shape || "portrait"; + options.lazy = options.lazy || false; + var html = ""; var primaryImageAspectRatio = options.shape == 'auto' ? LibraryBrowser.getAveragePrimaryImageAspectRatio(items) : null; @@ -667,7 +669,7 @@ var style = ""; - if (imgUrl) { + if (imgUrl && !options.lazy) { style += 'background-image:url(\'' + imgUrl + '\');'; } @@ -680,9 +682,16 @@ imageCssClass += " coveredPosterItemImage"; } + var dataSrc = ""; + + if (options.lazy) { + imageCssClass += " lazy"; + dataSrc = ' data-src="' + imgUrl + '"'; + } + var progressHtml = options.showProgress === false ? '' : LibraryBrowser.getItemProgressBarHtml(item); - html += '
'; + html += '
'; html += '
'; @@ -755,6 +764,10 @@ var itemCountHtml = LibraryBrowser.getItemCountsHtml(options, item); + if (item.Type == "Person" && !itemCountHtml) { + itemCountHtml = " "; + } + if (itemCountHtml) { html += "
"; html += itemCountHtml; diff --git a/dashboard-ui/scripts/mediacontroller.js b/dashboard-ui/scripts/mediacontroller.js index 074bc880f1..c755df654f 100644 --- a/dashboard-ui/scripts/mediacontroller.js +++ b/dashboard-ui/scripts/mediacontroller.js @@ -174,6 +174,62 @@ return p.isDefaultPlayer; })[0]; }; + + self.pause = function () { + currentPlayer.pause(); + }; + + self.stop = function () { + currentPlayer.stop(); + }; + + self.unpause = function () { + currentPlayer.unpause(); + }; + + self.seek = function (position) { + currentPlayer.changeStream(position); + }; + + self.currentPlaylistIndex = function (i) { + currentPlayer.currentPlaylistIndex(i); + }; + + self.removeFromPlaylist = function (i) { + currentPlayer.removeFromPlaylist(i); + }; + + self.nextTrack = function () { + currentPlayer.nextTrack(); + }; + + self.previousTrack = function () { + currentPlayer.previousTrack(); + }; + + self.mute = function () { + currentPlayer.mute(); + }; + + self.unmute = function () { + currentPlayer.unmute(); + }; + + self.toggleMute = function () { + currentPlayer.toggleMute(); + }; + + self.volumeDown = function () { + currentPlayer.volumeDown(); + }; + + self.volumeUp = function () { + currentPlayer.volumeUp(); + }; + + self.shuffle = function (id) { + currentPlayer.shuffle(id); + }; } window.MediaController = new mediaController(); diff --git a/dashboard-ui/scripts/mediaplayer-video.js b/dashboard-ui/scripts/mediaplayer-video.js index 1b5e513efa..1a7395a0a0 100644 --- a/dashboard-ui/scripts/mediaplayer-video.js +++ b/dashboard-ui/scripts/mediaplayer-video.js @@ -872,18 +872,18 @@ $('#video-fullscreenButton', videoControls).show(); } - var videoElement = $("video", videoElement); + var video = $("video", videoElement); initialVolume = localStorage.getItem("volume") || 0.5; - videoElement.each(function () { + video.each(function () { this.volume = initialVolume; }); self.volumeSlider.val(initialVolume).slider('refresh'); self.updateVolumeButtons(initialVolume); - videoElement.on("volumechange", function (e) { + video.on("volumechange", function (e) { var muted = this.muted; @@ -899,13 +899,13 @@ }).on("play.once", function () { - videoElement.off("play.once"); + video.off("play.once"); }).on("playing.once", function () { self.updateCanClientSeek(this); - videoElement.off("playing.once"); + video.off("playing.once"); ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, true, item.MediaType); @@ -1037,7 +1037,7 @@ currentItem = item; currentMediaSource = mediaSource; - return videoElement[0]; + return video[0]; } }; })(); \ No newline at end of file diff --git a/dashboard-ui/scripts/moviecollections.js b/dashboard-ui/scripts/moviecollections.js index 8a04646073..8985316792 100644 --- a/dashboard-ui/scripts/moviecollections.js +++ b/dashboard-ui/scripts/moviecollections.js @@ -33,7 +33,8 @@ shape: "portrait", context: 'movies', showTitle: true, - centerText: true + centerText: true, + lazy: true }); html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount); diff --git a/dashboard-ui/scripts/moviepeople.js b/dashboard-ui/scripts/moviepeople.js index 3e35afca1c..0ef500846b 100644 --- a/dashboard-ui/scripts/moviepeople.js +++ b/dashboard-ui/scripts/moviepeople.js @@ -34,7 +34,8 @@ context: 'movies', showTitle: true, showItemCounts: true, - coverImage: true + coverImage: true, + lazy: true }); html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, false, [], false); diff --git a/dashboard-ui/scripts/movies.js b/dashboard-ui/scripts/movies.js index 4f44bbe16b..e3d2689c8d 100644 --- a/dashboard-ui/scripts/movies.js +++ b/dashboard-ui/scripts/movies.js @@ -35,7 +35,8 @@ shape: "backdrop", preferThumb: true, context: 'movies', - selectionPanel: true + selectionPanel: true, + lazy: true }); $('.itemsContainer', page).removeClass('timelineItemsContainer'); } @@ -45,7 +46,8 @@ items: result.Items, shape: "banner", preferBanner: true, - context: 'movies' + context: 'movies', + lazy: true }); $('.itemsContainer', page).removeClass('timelineItemsContainer'); } @@ -56,7 +58,8 @@ context: 'movies', showTitle: true, centerText: true, - selectionPanel: true + selectionPanel: true, + lazy: true }); $('.itemsContainer', page).removeClass('timelineItemsContainer'); } @@ -68,7 +71,8 @@ showTitle: true, timeline: true, centerText: true, - selectionPanel: true + selectionPanel: true, + lazy: true }); $('.itemsContainer', page).addClass('timelineItemsContainer'); } diff --git a/dashboard-ui/scripts/musicalbumartists.js b/dashboard-ui/scripts/musicalbumartists.js index 26f7b070b0..a53c140035 100644 --- a/dashboard-ui/scripts/musicalbumartists.js +++ b/dashboard-ui/scripts/musicalbumartists.js @@ -32,7 +32,8 @@ context: 'music', showTitle: true, coverImage: true, - centerText: true + centerText: true, + lazy: true }); html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount); diff --git a/dashboard-ui/scripts/musicalbums.js b/dashboard-ui/scripts/musicalbums.js index 523835ba29..003e046761 100644 --- a/dashboard-ui/scripts/musicalbums.js +++ b/dashboard-ui/scripts/musicalbums.js @@ -34,7 +34,8 @@ shape: "square", context: 'music', showTitle: true, - showParentTitle: true + showParentTitle: true, + lazy: true }); $('.itemsContainer', page).removeClass('timelineItemsContainer'); } @@ -45,7 +46,8 @@ context: 'music', showTitle: true, showParentTitle: true, - timeline: true + timeline: true, + lazy: true }); $('.itemsContainer', page).addClass('timelineItemsContainer'); } diff --git a/dashboard-ui/scripts/musicartists.js b/dashboard-ui/scripts/musicartists.js index 60d2fe572a..142bfaa3b2 100644 --- a/dashboard-ui/scripts/musicartists.js +++ b/dashboard-ui/scripts/musicartists.js @@ -31,7 +31,8 @@ context: 'music', showTitle: true, coverImage: true, - centerText: true + centerText: true, + lazy: true }); html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount); @@ -119,4 +120,10 @@ updateFilterControls(this); }); + $(function () { + $("body").on("create", function () { + $(".lazy").unveil(200); + }); + }); + })(jQuery, document); \ No newline at end of file diff --git a/dashboard-ui/scripts/musicgenres.js b/dashboard-ui/scripts/musicgenres.js index 51e38e50f7..a0aa9331c4 100644 --- a/dashboard-ui/scripts/musicgenres.js +++ b/dashboard-ui/scripts/musicgenres.js @@ -32,7 +32,8 @@ preferThumb: true, context: 'music', showItemCounts: true, - centerText: true + centerText: true, + lazy: true }); html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount); @@ -55,8 +56,8 @@ reloadItems(page); }); - LibraryBrowser.saveQueryValues('musicgenres', query); - + LibraryBrowser.saveQueryValues('musicgenres', query); + Dashboard.hideLoadingMsg(); }); } diff --git a/dashboard-ui/scripts/playlist.js b/dashboard-ui/scripts/playlist.js index 187767152d..651a4d2104 100644 --- a/dashboard-ui/scripts/playlist.js +++ b/dashboard-ui/scripts/playlist.js @@ -17,7 +17,7 @@ html += ''; - $.each(MediaPlayer.playlist, function (i, item) { + $.each(MediaController.playlist, function (i, item) { var name = LibraryBrowser.getPosterViewDisplayName(item); @@ -65,14 +65,14 @@ var index = parseInt(this.getAttribute('data-index')); - MediaPlayer.currentPlaylistIndex(index); + MediaController.currentPlaylistIndex(index); reloadPlaylist(page); }).on('click', '.lnkRemove', function () { var index = parseInt(this.getAttribute('data-index')); - MediaPlayer.removeFromPlaylist(index); + MediaController.removeFromPlaylist(index); reloadPlaylist(page); }); diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js index d7afb9e2cb..ddc4e42d00 100644 --- a/dashboard-ui/scripts/site.js +++ b/dashboard-ui/scripts/site.js @@ -1330,42 +1330,42 @@ $(function () { footerHtml += '
'; footerHtml += '
'; footerHtml += 'Playlist'; - footerHtml += ''; - footerHtml += ''; - footerHtml += ''; + footerHtml += ''; + footerHtml += ''; + footerHtml += ''; footerHtml += '
'; - footerHtml += ''; - footerHtml += ''; + footerHtml += ''; + footerHtml += ''; footerHtml += '
'; - footerHtml += ''; + footerHtml += ''; footerHtml += '
'; - footerHtml += '
'; + footerHtml += '
'; footerHtml += '
'; - footerHtml += ''; - footerHtml += ''; + footerHtml += ''; + footerHtml += ''; footerHtml += '
'; footerHtml += ''; footerHtml += '
'; - footerHtml += ''; + footerHtml += ''; footerHtml += '
'; - footerHtml += ''; + footerHtml += ''; footerHtml += '
'; - footerHtml += ''; + footerHtml += ''; footerHtml += '
'; - footerHtml += ''; + footerHtml += ''; footerHtml += '
'; - footerHtml += ''; + footerHtml += ''; footerHtml += '
'; @@ -1386,6 +1386,10 @@ $(function () { ApiClient.closeWebSocket(); } }); + + $("body").on("create", function () { + $(".lazy").unveil(200); + }); }); Dashboard.jQueryMobileInit(); @@ -1427,5 +1431,4 @@ $(document).on('pagebeforeshow', ".page", function () { if (!ApiClient.isWebSocketOpen()) { Dashboard.refreshSystemInfoFromServer(); } -}); - +}); \ No newline at end of file diff --git a/dashboard-ui/scripts/tvpeople.js b/dashboard-ui/scripts/tvpeople.js index e8a573ac9a..d434886be1 100644 --- a/dashboard-ui/scripts/tvpeople.js +++ b/dashboard-ui/scripts/tvpeople.js @@ -34,7 +34,8 @@ context: 'tv', showTitle: true, showItemCounts: true, - coverImage: true + coverImage: true, + lazy: true }); html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, false, [], false); diff --git a/dashboard-ui/scripts/tvshows.js b/dashboard-ui/scripts/tvshows.js index 2e751fa82e..96635ea906 100644 --- a/dashboard-ui/scripts/tvshows.js +++ b/dashboard-ui/scripts/tvshows.js @@ -34,7 +34,8 @@ items: result.Items, shape: "backdrop", preferThumb: true, - context: 'tv' + context: 'tv', + lazy: true }); $('.itemsContainer', page).removeClass('timelineItemsContainer'); @@ -45,7 +46,8 @@ items: result.Items, shape: "banner", preferBanner: true, - context: 'tv' + context: 'tv', + lazy: true }); $('.itemsContainer', page).removeClass('timelineItemsContainer'); } @@ -56,7 +58,8 @@ shape: "portrait", context: 'tv', showTitle: true, - centerText: true + centerText: true, + lazy: true }); $('.itemsContainer', page).removeClass('timelineItemsContainer'); } @@ -67,7 +70,8 @@ shape: "portrait", context: 'tv', timeline: true, - showTitle: true + showTitle: true, + lazy: true }); $('.itemsContainer', page).addClass('timelineItemsContainer'); diff --git a/dashboard-ui/thirdparty/jquery.ba-tinypubsub.min.js b/dashboard-ui/thirdparty/jquery.ba-tinypubsub.min.js new file mode 100644 index 0000000000..9c552b4bc7 --- /dev/null +++ b/dashboard-ui/thirdparty/jquery.ba-tinypubsub.min.js @@ -0,0 +1,4 @@ +/* jQuery Tiny Pub/Sub - v0.7 - 10/27/2011 + * http://benalman.com/ + * Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT, GPL */ +(function (a) { var b = a({}); a.subscribe = function () { b.on.apply(b, arguments) }, a.unsubscribe = function () { b.off.apply(b, arguments) }, a.publish = function () { b.trigger.apply(b, arguments) } })(jQuery) \ No newline at end of file diff --git a/dashboard-ui/thirdparty/jquery.unveil-custom.js b/dashboard-ui/thirdparty/jquery.unveil-custom.js new file mode 100644 index 0000000000..79f275a309 --- /dev/null +++ b/dashboard-ui/thirdparty/jquery.unveil-custom.js @@ -0,0 +1,62 @@ +/** + * jQuery Unveil + * A very lightweight jQuery plugin to lazy load images + * http://luis-almeida.github.com/unveil + * + * Licensed under the MIT license. + * Copyright 2013 Luís Almeida + * https://github.com/luis-almeida + */ + +; (function ($) { + + $.fn.unveil = function (threshold, callback) { + + var $w = $(window), + th = threshold || 0, + retina = window.devicePixelRatio > 1, + attrib = retina ? "data-src-retina" : "data-src", + images = this, + loaded; + + this.one("unveil", function () { + var elemType = $(this).get(0).tagName; + var source = this.getAttribute(attrib); + source = source || this.getAttribute("data-src"); + if (source) { + if (elemType === "DIV") { + this.style.backgroundImage = "url('" + source + "')"; + } else { + this.setAttribute("src", source); + } + if (typeof callback === "function") callback.call(this); + } + }); + + function unveil() { + var inview = images.filter(function () { + var $e = $(this); + if ($e.is(":hidden")) return; + + var wt = $w.scrollTop(), + wb = wt + $w.height(), + et = $e.offset().top, + eb = et + $e.height(); + + return eb >= wt - th && et <= wb + th; + }); + + loaded = inview.trigger("unveil"); + images = images.not(loaded); + } + + $w.scroll(unveil); + $w.resize(unveil); + + unveil(); + + return this; + + }; + +})(window.jQuery || window.Zepto); \ No newline at end of file