1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

infinite scroll proof of concept on tv series

This commit is contained in:
Luke Pulverenti 2016-04-24 00:24:16 -04:00
parent 826a115d81
commit b9f3bc6cf1
9 changed files with 1000 additions and 359 deletions

View file

@ -1,21 +1,24 @@
define(['iron-list', 'lazyload-image'], function () {
define(['layoutManager', 'iron-list', 'lazyload-image'], function (layoutManager) {
function getTemplate(scrollTarget) {
var html = '';
var maxPhysical = 60;
html += '<template is="dom-bind">\
<iron-list as="item" id="ironList" scroll-target="' + scrollTarget + '" max-physical-count="60" style="width:96%;" grid>\
<iron-list as="item" id="ironList" scroll-target="' + scrollTarget + '" max-physical-count="' + maxPhysical + '" style="width:96%;" grid>\
<template>\
<div class$="{{item.elemClass}}" data-action$="{{item.defaultAction}}">\
<div class$="{{item.elemClass}}" data-action$="{{item.defaultAction}}" data-itemid$="{{item.data-itemid}}" data-commands$="{{item.data-commands}}" data-context$="{{item.data-context}}" data-isfolder$="{{item.data-isfolder}}" data-itemtype$="{{item.data-itemtype}}" data-mediatype$="{{item.data-mediatype}}" data-positionticks$="{{item.data-positionticks}}" data-playaccess$="{{item.data-playaccess}}" data-locationtype$="{{item.data-locationtype}}" data-index$="{{item.data-index}}" data-albumid$="{{item.data-albumid}}" data-channelid$="{{item.data-channelid}}" data-artistid$="{{item.data-artistid}}">\
<div class$="{{item.cardBoxClass}}">\
<div class="cardScalable">\
<div class="cardPadder"></div>\
<a onclick$="{{item.onclick}}" class$="{{item.anchorClass}}" href$="{{item.href}}">\
<a onclick$="{{item.onclick}}" data-action$="{{item.defaultAction}}" class$="{{item.anchorClass}}" href$="{{item.href}}">\
<img class$="{{item.imageClass}}" is="lazyload-image" src$="{{item.imgUrl}}" />\
<div inner-h-t-m-l="{{item.overlayHtml}}"></div>\
</a>\
</div>\
<!--cardFooter will be here-->\
<div inner-h-t-m-l="{{item.footerHtml}}"></div>\
</div>\
</div>\
</template>\

View file

@ -62,10 +62,18 @@
padding-bottom: 0;
}
.pageWithAbsoluteTabs .pageTabContent, .libraryPage > .ui-content {
.pageWithAbsoluteTabs .pageTabsContainer, .libraryPage > .ui-content {
padding-top: 10px;
}
.absolutePageTabContent {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
/*.pageWithAbsoluteTabs .pageTabContent {
padding-left: .5em !important;
padding-right: .5em !important;
@ -1174,7 +1182,7 @@ span.itemCommunityRating:not(:empty) + .userDataIcons {
.alphabetPicker {
position: fixed;
right: 0;
right: 5px;
bottom: 0;
z-index: 999;
text-align: center;
@ -1183,10 +1191,14 @@ span.itemCommunityRating:not(:empty) + .userDataIcons {
line-height: 1;
}
.layout-desktop .absolutePageTabContent .alphabetPicker {
right: 15px;
}
.alphabetPicker a {
display: block;
text-decoration: none;
padding: 1px 5px 1px 10px;
padding: 1px 2px 1px 5px;
font-weight: 500;
}
@ -1256,6 +1268,17 @@ span.itemCommunityRating:not(:empty) + .userDataIcons {
.itemsContainerWithAlphaPicker {
margin-right: 20px;
}
.absolutePageTabContent .itemsContainerWithAlphaPicker {
margin-right: 30px;
}
}
@media all and (min-height: 480px) and (max-width: 800px) {
.absolutePageTabContent .itemsContainerWithAlphaPicker iron-list {
width: 99.5% !important;
}
}
@media all and (min-height: 500px) {
@ -1267,7 +1290,7 @@ span.itemCommunityRating:not(:empty) + .userDataIcons {
@media all and (min-width: 1200px) {
.itemsContainerWithAlphaPicker {
.itemsContainerWithAlphaPicker, .absolutePageTabContent .itemsContainerWithAlphaPicker {
margin-right: 0;
}
}

View file

@ -10,6 +10,12 @@
padding-top: 98px !important;
}
.absolutePageTabContent {
margin: 0 !important;
width: 100% !important;
top: 98px !important;
}
.sidebarDivider {
height: 1px;
background: #eaeaea;

View file

@ -870,7 +870,7 @@ paper-input + .fieldDescription {
padding: 1em;
}
.page > .ui-content, .pageWithAbsoluteTabs .pageTabContent {
.page > .ui-content, .pageWithAbsoluteTabs .pageTabContent, .absolutePageTabContent .itemsContainer {
/* Need this so that the audio player doesn't cover content, but also for unveil lazy loading. */
padding-bottom: 160px;
}

View file

@ -1,8 +1,9 @@
define(['jQuery'], function ($) {
define(['ironCardList', 'scrollThreshold', 'events', 'libraryBrowser', 'jQuery'], function (ironCardList, scrollThreshold, events, libraryBrowser, $) {
return function (view, params, tabContent) {
var self = this;
var pageSize = libraryBrowser.getDefaultPageSize();
var data = {};
@ -23,13 +24,13 @@
ImageTypeLimit: 1,
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
StartIndex: 0,
Limit: LibraryBrowser.getDefaultPageSize()
Limit: pageSize
},
view: LibraryBrowser.getSavedView(key) || LibraryBrowser.getDefaultItemsView('Poster', 'Poster')
view: libraryBrowser.getSavedView(key) || libraryBrowser.getDefaultItemsView('Poster', 'Poster')
};
pageData.query.ParentId = params.topParentId;
LibraryBrowser.loadSavedQueryValues(key, pageData.query);
libraryBrowser.loadSavedQueryValues(key, pageData.query);
}
return pageData;
}
@ -42,50 +43,38 @@
function getSavedQueryKey(context) {
if (!context.savedQueryKey) {
context.savedQueryKey = LibraryBrowser.getSavedQueryKey('episodes');
context.savedQueryKey = libraryBrowser.getSavedQueryKey('episodes');
}
return context.savedQueryKey;
}
function reloadItems(page) {
function setCardOptions(result) {
Dashboard.showLoadingMsg();
var cardOptions;
var query = getQuery(page);
ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function (result) {
// Scroll back up so they can see the results from the beginning
window.scrollTo(0, 0);
var view = getPageData(page).view;
var html = '';
var pagingHtml = LibraryBrowser.getQueryPagingHtml({
startIndex: query.StartIndex,
limit: query.Limit,
totalRecordCount: result.TotalRecordCount,
showLimit: false,
updatePageSizeSetting: false,
addLayoutButton: true,
sortButton: true,
currentLayout: view,
layouts: 'Poster,PosterCard',
filterButton: true
});
page.querySelector('.listTopPaging').innerHTML = pagingHtml;
updateFilterControls(page);
var view = self.getCurrentViewStyle();
if (view == "List") {
html = LibraryBrowser.getListViewHtml({
html = libraryBrowser.getListViewHtml({
items: result.Items,
sortBy: query.SortBy
});
}
else if (view == "Poster") {
html += LibraryBrowser.getPosterViewHtml({
else if (view == "PosterCard") {
cardOptions = {
items: result.Items,
shape: "backdrop",
showTitle: true,
showParentTitle: true,
lazy: true,
cardLayout: true,
showDetailsMenu: true
};
}
else {
// poster
cardOptions = {
items: result.Items,
shape: "backdrop",
showTitle: true,
@ -94,47 +83,108 @@
lazy: true,
showDetailsMenu: true,
overlayPlayButton: true
});
};
}
else if (view == "PosterCard") {
html += LibraryBrowser.getPosterViewHtml({
items: result.Items,
shape: "backdrop",
showTitle: true,
showParentTitle: true,
lazy: true,
cardLayout: true,
showDetailsMenu: true
self.cardOptions = cardOptions;
}
function reloadItems(page) {
self.isLoading = true;
Dashboard.showLoadingMsg();
var query = getQuery(page);
var startIndex = query.StartIndex;
var reloadList = !self.cardOptions || startIndex == 0;
ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function (result) {
updateFilterControls(page);
var pushItems = true;
if (reloadList) {
setCardOptions(result);
pushItems = false;
}
libraryBrowser.setPosterViewData(self.cardOptions);
libraryBrowser.setPosterViewDataOnItems(self.cardOptions, result.Items);
var ironList = page.querySelector('#ironList');
if (pushItems) {
for (var i = 0, length = result.Items.length; i < length; i++) {
ironList.push('items', result.Items[i]);
}
} else {
ironList.items = result.Items;
}
// Hack: notifyResize needs to be done after the items have been rendered
setTimeout(function () {
ironList.notifyResize();
self.scrollThreshold.resetSize();
}, 300);
libraryBrowser.saveQueryValues(getSavedQueryKey(page), query);
Dashboard.hideLoadingMsg();
self.hasMoreItems = result.TotalRecordCount > (startIndex + result.Items.length);
self.isLoading = false;
});
}
var elem = page.querySelector('.itemsContainer');
elem.innerHTML = html + pagingHtml;
ImageLoader.lazyChildren(elem);
self.showFilterMenu = function () {
require(['components/filterdialog/filterdialog'], function (filterDialogFactory) {
$('.btnNextPage', page).on('click', function () {
query.StartIndex += query.Limit;
reloadItems(page);
var filterDialog = new filterDialogFactory({
query: getQuery(tabContent),
mode: 'episodes'
});
$('.btnPreviousPage', page).on('click', function () {
query.StartIndex -= query.Limit;
reloadItems(page);
Events.on(filterDialog, 'filterchange', function () {
reloadItems(tabContent);
});
$('.btnChangeLayout', page).on('layoutchange', function (e, layout) {
getPageData(page).view = layout;
LibraryBrowser.saveViewSetting(getSavedQueryKey(page), layout);
reloadItems(page);
filterDialog.show();
});
};
function updateFilterControls(tabContent) {
var query = getQuery(tabContent);
$('.alphabetPicker', tabContent).alphaValue(query.NameStartsWithOrGreater);
}
function initPage(tabContent) {
$('.alphabetPicker', tabContent).on('alphaselect', function (e, character) {
var query = getQuery(tabContent);
query.NameStartsWithOrGreater = character;
query.StartIndex = 0;
reloadItems(tabContent);
}).on('alphaclear', function (e) {
var query = getQuery(tabContent);
query.NameStartsWithOrGreater = '';
reloadItems(tabContent);
});
$('.btnFilter', page).on('click', function () {
showFilterMenu(page);
$('.itemsContainer', tabContent).on('needsrefresh', function () {
reloadItems(tabContent);
});
// On callback make sure to set StartIndex = 0
$('.btnSort', page).on('click', function () {
LibraryBrowser.showSortMenu({
tabContent.querySelector('.btnFilter').addEventListener('click', function () {
self.showFilterMenu();
});
tabContent.querySelector('.btnSort').addEventListener('click', function () {
libraryBrowser.showSortMenu({
items: [{
name: Globalize.translate('OptionNameSort'),
id: 'SeriesSortName,SortName'
@ -172,71 +222,69 @@
id: 'VideoBitRate,SeriesSortName,SortName'
}],
callback: function () {
reloadItems(page);
reloadItems(tabContent);
},
query: query
query: getQuery(tabContent)
});
});
LibraryBrowser.saveQueryValues(getSavedQueryKey(page), query);
tabContent.querySelector('.btnSelectView').addEventListener('click', function (e) {
Dashboard.hideLoadingMsg();
});
}
function showFilterMenu(page) {
require(['components/filterdialog/filterdialog'], function (filterDialogFactory) {
var filterDialog = new filterDialogFactory({
query: getQuery(page),
mode: 'episodes'
libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), 'List,Poster,PosterCard'.split(','));
});
Events.on(filterDialog, 'filterchange', function () {
reloadItems(page);
});
filterDialog.show();
});
}
function updateFilterControls(tabContent) {
var query = getQuery(tabContent);
$('.alphabetPicker', tabContent).alphaValue(query.NameStartsWithOrGreater);
}
function initPage(tabContent) {
$('.alphabetPicker', tabContent).on('alphaselect', function (e, character) {
var query = getQuery(tabContent);
query.NameStartsWithOrGreater = character;
query.StartIndex = 0;
reloadItems(tabContent);
}).on('alphaclear', function (e) {
var query = getQuery(tabContent);
query.NameStartsWithOrGreater = '';
reloadItems(tabContent);
});
$('.itemsContainer', tabContent).on('needsrefresh', function () {
tabContent.querySelector('.btnSelectView').addEventListener('layoutchange', function (e) {
var viewStyle = e.detail.viewStyle;
getPageData(tabContent).view = viewStyle;
libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle);
reloadItems(tabContent);
});
}
self.getCurrentViewStyle = function () {
return getPageData(tabContent).view;
};
initPage(tabContent);
function createList() {
if (self.listCreated) {
return Promise.resolve();
}
return ironCardList.getTemplate('episodesTab').then(function (html) {
tabContent.querySelector('.itemsContainer').innerHTML = html;
self.listCreated = true;
});
}
function loadMoreItems() {
if (!self.isLoading && self.hasMoreItems) {
getQuery(tabContent).StartIndex += pageSize;
reloadItems(tabContent);
}
}
self.scrollThreshold = new scrollThreshold(tabContent, false);
events.on(self.scrollThreshold, 'lower-threshold', loadMoreItems);
self.renderTab = function () {
createList().then(function () {
reloadItems(tabContent);
updateFilterControls(tabContent);
});
};
self.destroy = function () {
events.off(self.scrollThreshold, 'lower-threshold', loadMoreItems);
if (self.scrollThreshold) {
self.scrollThreshold.destroy();
}
};
};
});

View file

@ -173,6 +173,7 @@
enableFullPaperTabs: function () {
return true;
if (browserInfo.animate && !browserInfo.mobile) {
//return true;
}
@ -1489,49 +1490,94 @@
return outerHtml;
},
getItemDataAttributes: function (item, options, index) {
getItemDataAttributesList: function (item, options, index) {
var atts = [];
var itemCommands = LibraryBrowser.getItemCommands(item, options);
atts.push('data-itemid="' + item.Id + '"');
atts.push('data-commands="' + itemCommands.join(',') + '"');
atts.push({
name: 'itemid',
value: item.Id
});
atts.push({
name: 'commands',
value: itemCommands.join(',')
});
if (options.context) {
atts.push('data-context="' + (options.context || '') + '"');
atts.push({
name: 'context',
value: options.context || ''
});
}
if (item.IsFolder) {
atts.push('data-isfolder="' + item.IsFolder + '"');
atts.push({
name: 'isfolder',
value: item.IsFolder
});
}
atts.push('data-itemtype="' + item.Type + '"');
atts.push({
name: 'itemtype',
value: item.Type
});
if (item.MediaType) {
atts.push('data-mediatype="' + (item.MediaType || '') + '"');
atts.push({
name: 'mediatype',
value: item.MediaType || ''
});
}
if (item.UserData.PlaybackPositionTicks) {
atts.push('data-positionticks="' + (item.UserData.PlaybackPositionTicks || 0) + '"');
atts.push({
name: 'positionticks',
value: (item.UserData.PlaybackPositionTicks || 0)
});
}
atts.push('data-playaccess="' + (item.PlayAccess || '') + '"');
atts.push('data-locationtype="' + (item.LocationType || '') + '"');
atts.push('data-index="' + index + '"');
atts.push({
name: 'playaccess',
value: item.PlayAccess || ''
});
atts.push({
name: 'locationtype',
value: item.LocationType || ''
});
if (item.AlbumId) {
atts.push('data-albumid="' + item.AlbumId + '"');
atts.push({
name: 'albumid',
value: item.AlbumId
});
}
if (item.ChannelId) {
atts.push('data-channelid="' + item.ChannelId + '"');
atts.push({
name: 'channelid',
value: item.ChannelId
});
}
if (item.ArtistItems && item.ArtistItems.length) {
atts.push('data-artistid="' + item.ArtistItems[0].Id + '"');
atts.push({
name: 'artistid',
value: item.ArtistItems[0].Id
});
}
return atts;
},
getItemDataAttributes: function (item, options, index) {
var atts = LibraryBrowser.getItemDataAttributesList(item, options, index).map(function (i) {
return 'data-' + i.name + '="' + i.value + '"';
});
var html = atts.join(' ');
if (html) {
@ -1754,15 +1800,12 @@
return result;
},
getPosterViewHtml: function (options) {
setPosterViewData: function (options) {
var items = options.items;
var currentIndexValue;
options.shape = options.shape || "portrait";
var html = "";
var primaryImageAspectRatio = LibraryBrowser.getAveragePrimaryImageAspectRatio(items);
var isThumbAspectRatio = primaryImageAspectRatio && Math.abs(primaryImageAspectRatio - 1.777777778) < .3;
var isSquareAspectRatio = primaryImageAspectRatio && Math.abs(primaryImageAspectRatio - 1) < .33 ||
@ -1827,8 +1870,446 @@
thumbWidth = 320;
}
options.uiAspect = getDesiredAspect(options.shape);
options.primaryImageAspectRatio = primaryImageAspectRatio;
options.posterWidth = posterWidth;
options.thumbWidth = thumbWidth;
options.bannerWidth = bannerWidth;
options.squareSize = squareSize;
},
setPosterViewDataOnItems: function (options, items) {
LibraryBrowser.setPosterViewData(options);
options.shape = options.shape || "portrait";
var html = "";
var primaryImageAspectRatio;
var thumbWidth = options.thumbWidth;
var posterWidth = options.posterWidth;
var squareSize = options.squareSize;
var bannerWidth = options.bannerWidth;
var uiAspect = options.uiAspect;
for (var i = 0, length = items.length; i < length; i++) {
var item = items[i];
primaryImageAspectRatio = LibraryBrowser.getAveragePrimaryImageAspectRatio([item]);
LibraryBrowser.setPosterViewDataOnItem(item, i, options, primaryImageAspectRatio, thumbWidth, posterWidth, squareSize, bannerWidth, uiAspect);
}
return html;
},
setPosterViewDataOnItem: function (item, index, options, primaryImageAspectRatio, thumbWidth, posterWidth, squareSize, bannerWidth, uiAspect) {
var imgUrl = null;
var icon;
var width = null;
var height = null;
var forceName = false;
var enableImageEnhancers = options.enableImageEnhancers !== false;
var cssClass = "card";
if (options.fullWidthOnMobile) {
cssClass += " fullWidthCardOnMobile";
}
var showTitle = options.showTitle == 'auto' ? true : options.showTitle;
var coverImage = options.coverImage;
if (options.autoThumb && item.ImageTags && item.ImageTags.Primary && item.PrimaryImageAspectRatio && item.PrimaryImageAspectRatio >= 1.34) {
width = posterWidth;
height = primaryImageAspectRatio ? Math.round(posterWidth / primaryImageAspectRatio) : null;
imgUrl = ApiClient.getImageUrl(item.Id, {
type: "Primary",
maxHeight: height,
maxWidth: width,
tag: item.ImageTags.Primary,
enableImageEnhancers: enableImageEnhancers
});
if (primaryImageAspectRatio) {
if (uiAspect) {
if (Math.abs(primaryImageAspectRatio - uiAspect) <= .2) {
coverImage = true;
}
}
}
} else if (options.autoThumb && item.ImageTags && item.ImageTags.Thumb) {
imgUrl = ApiClient.getScaledImageUrl(item.Id, {
type: "Thumb",
maxWidth: thumbWidth,
tag: item.ImageTags.Thumb,
enableImageEnhancers: enableImageEnhancers
});
} else if (options.preferBackdrop && item.BackdropImageTags && item.BackdropImageTags.length) {
imgUrl = ApiClient.getScaledImageUrl(item.Id, {
type: "Backdrop",
maxWidth: thumbWidth,
tag: item.BackdropImageTags[0],
enableImageEnhancers: enableImageEnhancers
});
} else if (options.preferThumb && item.ImageTags && item.ImageTags.Thumb) {
imgUrl = ApiClient.getScaledImageUrl(item.Id, {
type: "Thumb",
maxWidth: thumbWidth,
tag: item.ImageTags.Thumb,
enableImageEnhancers: enableImageEnhancers
});
} else if (options.preferBanner && item.ImageTags && item.ImageTags.Banner) {
imgUrl = ApiClient.getScaledImageUrl(item.Id, {
type: "Banner",
maxWidth: bannerWidth,
tag: item.ImageTags.Banner,
enableImageEnhancers: enableImageEnhancers
});
} else if (options.preferThumb && item.SeriesThumbImageTag && options.inheritThumb !== false) {
imgUrl = ApiClient.getScaledImageUrl(item.SeriesId, {
type: "Thumb",
maxWidth: thumbWidth,
tag: item.SeriesThumbImageTag,
enableImageEnhancers: enableImageEnhancers
});
} else if (options.preferThumb && item.ParentThumbItemId && options.inheritThumb !== false) {
imgUrl = ApiClient.getThumbImageUrl(item.ParentThumbItemId, {
type: "Thumb",
maxWidth: thumbWidth,
enableImageEnhancers: enableImageEnhancers
});
} else if (options.preferThumb && item.BackdropImageTags && item.BackdropImageTags.length) {
imgUrl = ApiClient.getScaledImageUrl(item.Id, {
type: "Backdrop",
maxWidth: thumbWidth,
tag: item.BackdropImageTags[0],
enableImageEnhancers: enableImageEnhancers
});
forceName = true;
} else if (item.ImageTags && item.ImageTags.Primary) {
width = posterWidth;
height = primaryImageAspectRatio ? Math.round(posterWidth / primaryImageAspectRatio) : null;
imgUrl = ApiClient.getImageUrl(item.Id, {
type: "Primary",
maxHeight: height,
maxWidth: width,
tag: item.ImageTags.Primary,
enableImageEnhancers: enableImageEnhancers
});
if (primaryImageAspectRatio) {
if (uiAspect) {
if (Math.abs(primaryImageAspectRatio - uiAspect) <= .2) {
coverImage = true;
}
}
}
}
else if (item.ParentPrimaryImageTag) {
imgUrl = ApiClient.getImageUrl(item.ParentPrimaryImageItemId, {
type: "Primary",
maxWidth: posterWidth,
tag: item.ParentPrimaryImageTag,
enableImageEnhancers: enableImageEnhancers
});
}
else if (item.AlbumId && item.AlbumPrimaryImageTag) {
height = squareSize;
width = primaryImageAspectRatio ? Math.round(height * primaryImageAspectRatio) : null;
imgUrl = ApiClient.getScaledImageUrl(item.AlbumId, {
type: "Primary",
maxHeight: height,
maxWidth: width,
tag: item.AlbumPrimaryImageTag,
enableImageEnhancers: enableImageEnhancers
});
if (primaryImageAspectRatio) {
if (uiAspect) {
if (Math.abs(primaryImageAspectRatio - uiAspect) <= .2) {
coverImage = true;
}
}
}
}
else if (item.Type == 'Season' && item.ImageTags && item.ImageTags.Thumb) {
imgUrl = ApiClient.getScaledImageUrl(item.Id, {
type: "Thumb",
maxWidth: thumbWidth,
tag: item.ImageTags.Thumb,
enableImageEnhancers: enableImageEnhancers
});
}
else if (item.BackdropImageTags && item.BackdropImageTags.length) {
imgUrl = ApiClient.getScaledImageUrl(item.Id, {
type: "Backdrop",
maxWidth: thumbWidth,
tag: item.BackdropImageTags[0],
enableImageEnhancers: enableImageEnhancers
});
} else if (item.ImageTags && item.ImageTags.Thumb) {
imgUrl = ApiClient.getScaledImageUrl(item.Id, {
type: "Thumb",
maxWidth: thumbWidth,
tag: item.ImageTags.Thumb,
enableImageEnhancers: enableImageEnhancers
});
} else if (item.SeriesThumbImageTag) {
imgUrl = ApiClient.getScaledImageUrl(item.SeriesId, {
type: "Thumb",
maxWidth: thumbWidth,
tag: item.SeriesThumbImageTag,
enableImageEnhancers: enableImageEnhancers
});
} else if (item.ParentThumbItemId) {
imgUrl = ApiClient.getThumbImageUrl(item, {
type: "Thumb",
maxWidth: thumbWidth,
enableImageEnhancers: enableImageEnhancers
});
} else if (item.MediaType == "Audio" || item.Type == "MusicAlbum" || item.Type == "MusicArtist") {
if (item.Name && showTitle) {
icon = 'library-music';
}
cssClass += " defaultBackground";
} else if (item.Type == "Recording" || item.Type == "Program" || item.Type == "TvChannel") {
if (item.Name && showTitle) {
icon = 'folder-open';
}
cssClass += " defaultBackground";
} else if (item.MediaType == "Video" || item.Type == "Season" || item.Type == "Series") {
if (item.Name && showTitle) {
icon = 'videocam';
}
cssClass += " defaultBackground";
} else if (item.Type == "Person") {
if (item.Name && showTitle) {
icon = 'person';
}
cssClass += " defaultBackground";
} else {
if (item.Name && showTitle) {
icon = 'folder-open';
}
cssClass += " defaultBackground";
}
icon = item.icon || icon;
cssClass += ' ' + options.shape + 'Card';
var mediaSourceCount = item.MediaSourceCount || 1;
var href = options.linkItem === false ? '#' : LibraryBrowser.getHref(item, options.context);
if (options.showChildCountIndicator && item.ChildCount && options.showLatestItemsPopup !== false) {
cssClass += ' groupedCard';
}
if ((showTitle || options.showItemCounts) && !options.overlayText) {
cssClass += ' bottomPaddedCard';
}
var dataAttributes = LibraryBrowser.getItemDataAttributesList(item, options, index);
for (var i = 0, length = dataAttributes.length; i < length; i++) {
var att = dataAttributes[i];
if (att.value) {
item['data-' + att.name] = att.value;
}
}
console.log(item['data-commands']);
var defaultAction = options.defaultAction;
if (defaultAction == 'play' || defaultAction == 'playallfromhere') {
if (item.PlayAccess != 'Full') {
defaultAction = null;
}
}
// card
//html += '<div' + dataAttributes + ' class="' + cssClass + '">';
item.elemClass = cssClass;
item.defaultAction = defaultAction;
var style = "";
if (imgUrl && !options.lazy) {
style += 'background-image:url(\'' + imgUrl + '\');';
}
var imageCssClass = 'cardImage';
if (icon) {
imageCssClass += " iconCardImage";
}
if (coverImage) {
imageCssClass += " coveredCardImage";
if (item.MediaType == 'Photo' || item.Type == 'PhotoAlbum' || item.Type == 'Folder' || item.Type == 'Program' || item.Type == 'Recording') {
imageCssClass += " noScale";
}
}
if (options.centerImage) {
imageCssClass += " centeredCardImage";
}
var dataSrc = "";
if (options.lazy && imgUrl) {
imageCssClass += " lazy";
dataSrc = ' data-src="' + imgUrl + '"';
}
var cardboxCssClass = 'cardBox';
if (options.cardLayout) {
cardboxCssClass += ' visualCardBox';
}
item.cardBoxClass = cardboxCssClass;
var anchorCssClass = "cardContent";
anchorCssClass += ' mediaItem';
if (defaultAction) {
anchorCssClass += ' itemWithAction';
}
item.anchorClass = anchorCssClass;
item.href = href;
item.imgUrl = imgUrl;
item.imageClass = imageCssClass;
if (imgUrl) {
item.imageStyle = 'background-image:url("' + imgUrl + '");';
} else {
item.imageStyle = null;
}
var overlayHtml = '';
if (item.LocationType == "Virtual" || item.LocationType == "Offline") {
if (options.showLocationTypeIndicator !== false) {
overlayHtml += LibraryBrowser.getOfflineIndicatorHtml(item);
}
} else if (options.showUnplayedIndicator !== false) {
overlayHtml += LibraryBrowser.getPlayedIndicatorHtml(item);
} else if (options.showChildCountIndicator) {
overlayHtml += LibraryBrowser.getGroupCountIndicator(item);
}
overlayHtml += LibraryBrowser.getSyncIndicator(item);
if (mediaSourceCount > 1) {
overlayHtml += '<div class="mediaSourceIndicator">' + mediaSourceCount + '</div>';
}
var progressHtml = options.showProgress === false || item.IsFolder ? '' : LibraryBrowser.getItemProgressBarHtml((item.Type == 'Recording' ? item : item.UserData));
var footerOverlayed = false;
if (options.overlayText || (forceName && !showTitle)) {
var footerCssClass = progressHtml ? 'cardFooter fullCardFooter' : 'cardFooter';
overlayHtml += LibraryBrowser.getCardFooterText(item, options, showTitle, imgUrl, forceName, footerCssClass, progressHtml);
footerOverlayed = true;
}
else if (progressHtml) {
overlayHtml += '<div class="cardFooter fullCardFooter lightCardFooter">';
overlayHtml += "<div class='cardProgress cardText'>";
overlayHtml += progressHtml;
overlayHtml += "</div>";
//cardFooter
overlayHtml += "</div>";
progressHtml = '';
}
if (options.overlayPlayButton && !item.IsPlaceHolder && (item.LocationType != 'Virtual' || !item.MediaType || item.Type == 'Program') && item.Type != 'Person') {
overlayHtml += '<div class="cardOverlayButtonContainer"><paper-icon-button icon="play-arrow" class="cardOverlayPlayButton" onclick="return false;"></paper-icon-button></div>';
}
if (options.overlayMoreButton) {
overlayHtml += '<div class="cardOverlayButtonContainer"><paper-icon-button icon="' + AppInfo.moreIcon + '" class="cardOverlayMoreButton" onclick="return false;"></paper-icon-button></div>';
}
//// cardScalable
if (!options.overlayText && !footerOverlayed) {
item.footerHtml = LibraryBrowser.getCardFooterText(item, options, showTitle, imgUrl, forceName, 'cardFooter outerCardFooter', progressHtml);
} else {
item.footerHtml = '';
}
item.overlayHtml = overlayHtml;
},
getPosterViewHtml: function (options) {
LibraryBrowser.setPosterViewData(options);
var items = options.items;
var currentIndexValue;
options.shape = options.shape || "portrait";
var html = "";
var primaryImageAspectRatio;
var thumbWidth = options.thumbWidth;
var posterWidth = options.posterWidth;
var squareSize = options.squareSize;
var bannerWidth = options.bannerWidth;
var dateText;
var uiAspect = getDesiredAspect(options.shape);
var uiAspect = options.uiAspect;
for (var i = 0, length = items.length; i < length; i++) {
@ -2765,23 +3246,24 @@
}
},
getDefaultPageSizeSelections: function () {
showLayoutMenu: function (button, currentLayout, views) {
return [20, 50, 100, 200, 300, 400, 500];
},
var dispatchEvent = true;
showLayoutMenu: function (button, currentLayout) {
if (!views) {
dispatchEvent = false;
// Add banner and list once all screens support them
var views = button.getAttribute('data-layouts');
views = button.getAttribute('data-layouts');
views = views ? views.split(',') : ['List', 'Poster', 'PosterCard', 'Thumb', 'ThumbCard'];
}
var menuItems = views.map(function (v) {
return {
name: Globalize.translate('Option' + v),
id: v,
ironIcon: currentLayout == v ? 'check' : null
selected: currentLayout == v
};
});
@ -2792,11 +3274,21 @@
positionTo: button,
callback: function (id) {
if (dispatchEvent) {
button.dispatchEvent(new CustomEvent('layoutchange', {
detail: {
viewStyle: id
},
bubbles: true,
cancelable: false
}));
} else {
// TODO: remove jQuery
require(['jQuery'], function ($) {
$(button).trigger('layoutchange', [id]);
});
}
}
});
});
@ -2866,7 +3358,7 @@
var id = "selectPageSize";
var pageSizes = options.pageSizes || LibraryBrowser.getDefaultPageSizeSelections();
var pageSizes = options.pageSizes || [20, 50, 100, 200, 300, 400, 500];
var optionsHtml = pageSizes.map(function (val) {

View file

@ -294,5 +294,14 @@
Events.off(MediaController, 'playbackstop', onPlaybackStop);
});
view.addEventListener('viewdestroy', function (e) {
tabControllers.forEach(function (t) {
if (t.destroy) {
t.destroy();
}
});
});
};
});

View file

@ -1,8 +1,9 @@
define(['jQuery'], function ($) {
define(['ironCardList', 'scrollThreshold', 'events', 'libraryBrowser', 'jQuery'], function (ironCardList, scrollThreshold, events, libraryBrowser, $) {
return function (view, params, tabContent) {
var self = this;
var pageSize = libraryBrowser.getDefaultPageSize();
var data = {};
@ -21,13 +22,13 @@
ImageTypeLimit: 1,
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
StartIndex: 0,
Limit: LibraryBrowser.getDefaultPageSize()
Limit: pageSize
},
view: LibraryBrowser.getSavedView(key) || LibraryBrowser.getDefaultItemsView('Poster', 'Thumb')
view: libraryBrowser.getSavedView(key) || libraryBrowser.getDefaultItemsView('Poster', 'Thumb')
};
pageData.query.ParentId = params.topParentId;
LibraryBrowser.loadSavedQueryValues(key, pageData.query);
libraryBrowser.loadSavedQueryValues(key, pageData.query);
}
return pageData;
}
@ -40,57 +41,31 @@
function getSavedQueryKey(context) {
if (!context.savedQueryKey) {
context.savedQueryKey = LibraryBrowser.getSavedQueryKey('series');
context.savedQueryKey = libraryBrowser.getSavedQueryKey('series');
}
return context.savedQueryKey;
}
function reloadItems(page) {
function setCardOptions(result) {
Dashboard.showLoadingMsg();
var cardOptions;
var query = getQuery(page);
ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function (result) {
// Scroll back up so they can see the results from the beginning
window.scrollTo(0, 0);
var view = getPageData(page).view;
var html = '';
var pagingHtml = LibraryBrowser.getQueryPagingHtml({
startIndex: query.StartIndex,
limit: query.Limit,
totalRecordCount: result.TotalRecordCount,
showLimit: false,
updatePageSizeSetting: false,
addLayoutButton: true,
sortButton: true,
currentLayout: view,
layouts: 'Banner,List,Poster,PosterCard,Thumb,ThumbCard',
filterButton: true
});
page.querySelector('.listTopPaging').innerHTML = pagingHtml;
updateFilterControls(page);
var view = self.getCurrentViewStyle();
if (view == "Thumb") {
html = LibraryBrowser.getPosterViewHtml({
cardOptions = {
items: result.Items,
shape: "backdrop",
preferThumb: true,
context: 'tv',
lazy: true,
overlayPlayButton: true
});
};
}
else if (view == "ThumbCard") {
html = LibraryBrowser.getPosterViewHtml({
cardOptions = {
items: result.Items,
shape: "backdrop",
preferThumb: true,
@ -99,28 +74,28 @@
cardLayout: true,
showTitle: true,
showSeriesYear: true
});
};
}
else if (view == "Banner") {
html = LibraryBrowser.getPosterViewHtml({
cardOptions = {
items: result.Items,
shape: "banner",
preferBanner: true,
context: 'tv',
lazy: true
});
};
}
else if (view == "List") {
html = LibraryBrowser.getListViewHtml({
html = libraryBrowser.getListViewHtml({
items: result.Items,
context: 'tv',
sortBy: query.SortBy
});
}
else if (view == "PosterCard") {
html = LibraryBrowser.getPosterViewHtml({
cardOptions = {
items: result.Items,
shape: "portrait",
context: 'tv',
@ -128,48 +103,118 @@
showYear: true,
lazy: true,
cardLayout: true
});
};
}
else {
// Poster
html = LibraryBrowser.getPosterViewHtml({
cardOptions = {
items: result.Items,
shape: "portrait",
context: 'tv',
centerText: true,
lazy: true,
overlayPlayButton: true
};
}
self.cardOptions = cardOptions;
}
function reloadItems(page) {
self.isLoading = true;
Dashboard.showLoadingMsg();
var query = getQuery(page);
var startIndex = query.StartIndex;
var reloadList = !self.cardOptions || startIndex == 0;
ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function (result) {
updateFilterControls(page);
var pushItems = true;
if (reloadList) {
setCardOptions(result);
pushItems = false;
}
libraryBrowser.setPosterViewData(self.cardOptions);
libraryBrowser.setPosterViewDataOnItems(self.cardOptions, result.Items);
var ironList = page.querySelector('#ironList');
if (pushItems) {
for (var i = 0, length = result.Items.length; i < length; i++) {
ironList.push('items', result.Items[i]);
}
} else {
ironList.items = result.Items;
}
// Hack: notifyResize needs to be done after the items have been rendered
setTimeout(function () {
ironList.notifyResize();
self.scrollThreshold.resetSize();
}, 300);
libraryBrowser.saveQueryValues(getSavedQueryKey(page), query);
Dashboard.hideLoadingMsg();
self.hasMoreItems = result.TotalRecordCount > (startIndex + result.Items.length);
self.isLoading = false;
});
}
var elem = page.querySelector('#items');
elem.innerHTML = html + pagingHtml;
ImageLoader.lazyChildren(elem);
self.showFilterMenu = function () {
$('.btnNextPage', page).on('click', function () {
query.StartIndex += query.Limit;
reloadItems(page);
require(['components/filterdialog/filterdialog'], function (filterDialogFactory) {
var filterDialog = new filterDialogFactory({
query: getQuery(tabContent),
mode: 'series'
});
$('.btnPreviousPage', page).on('click', function () {
query.StartIndex -= query.Limit;
reloadItems(page);
Events.on(filterDialog, 'filterchange', function () {
getQuery(tabContent).StartIndex = 0;
reloadItems(tabContent);
});
$('.btnChangeLayout', page).on('layoutchange', function (e, layout) {
getPageData(page).view = layout;
LibraryBrowser.saveViewSetting(getSavedQueryKey(page), layout);
reloadItems(page);
filterDialog.show();
});
}
function updateFilterControls(tabContent) {
var query = getQuery(tabContent);
$('.alphabetPicker', tabContent).alphaValue(query.NameStartsWith);
}
function initPage(tabContent) {
$('.alphabetPicker', tabContent).on('alphaselect', function (e, character) {
var query = getQuery(tabContent);
query.NameStartsWithOrGreater = character;
query.StartIndex = 0;
reloadItems(tabContent);
}).on('alphaclear', function (e) {
var query = getQuery(tabContent);
query.NameStartsWithOrGreater = '';
getQuery(tabContent).StartIndex = 0;
reloadItems(tabContent);
});
$('.btnFilter', page).on('click', function () {
showFilterMenu(page);
tabContent.querySelector('.btnFilter').addEventListener('click', function () {
self.showFilterMenu();
});
// On callback make sure to set StartIndex = 0
$('.btnSort', page).on('click', function () {
LibraryBrowser.showSortMenu({
tabContent.querySelector('.btnSort').addEventListener('click', function () {
libraryBrowser.showSortMenu({
items: [{
name: Globalize.translate('OptionNameSort'),
id: 'SortName'
@ -203,65 +248,73 @@
id: 'PremiereDate,SortName'
}],
callback: function () {
reloadItems(page);
getQuery(tabContent).StartIndex = 0;
reloadItems(tabContent);
},
query: query
query: getQuery(tabContent)
});
});
LibraryBrowser.saveQueryValues(getSavedQueryKey(page), query);
tabContent.querySelector('.btnSelectView').addEventListener('click', function (e) {
Dashboard.hideLoadingMsg();
});
}
function showFilterMenu(page) {
require(['components/filterdialog/filterdialog'], function (filterDialogFactory) {
var filterDialog = new filterDialogFactory({
query: getQuery(page),
mode: 'series'
libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), 'Banner,List,Poster,PosterCard,Thumb,ThumbCard'.split(','));
});
Events.on(filterDialog, 'filterchange', function () {
reloadItems(page);
});
tabContent.querySelector('.btnSelectView').addEventListener('layoutchange', function (e) {
filterDialog.show();
});
}
function updateFilterControls(tabContent) {
var query = getQuery(tabContent);
$('.alphabetPicker', tabContent).alphaValue(query.NameStartsWith);
}
function initPage(tabContent) {
$('.alphabetPicker', tabContent).on('alphaselect', function (e, character) {
var query = getQuery(tabContent);
query.NameStartsWithOrGreater = character;
query.StartIndex = 0;
reloadItems(tabContent);
}).on('alphaclear', function (e) {
var query = getQuery(tabContent);
query.NameStartsWithOrGreater = '';
var viewStyle = e.detail.viewStyle;
getPageData(tabContent).view = viewStyle;
libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle);
getQuery(tabContent).StartIndex = 0;
reloadItems(tabContent);
});
}
self.getCurrentViewStyle = function () {
return getPageData(tabContent).view;
};
initPage(tabContent);
function createList() {
if (self.listCreated) {
return Promise.resolve();
}
return ironCardList.getTemplate('seriesTab').then(function (html) {
tabContent.querySelector('.itemsContainer').innerHTML = html;
self.listCreated = true;
});
}
function loadMoreItems() {
if (!self.isLoading && self.hasMoreItems) {
getQuery(tabContent).StartIndex += pageSize;
reloadItems(tabContent);
}
}
self.scrollThreshold = new scrollThreshold(tabContent, false);
events.on(self.scrollThreshold, 'lower-threshold', loadMoreItems);
self.renderTab = function () {
createList().then(function () {
reloadItems(tabContent);
updateFilterControls(tabContent);
});
};
self.destroy = function () {
events.off(self.scrollThreshold, 'lower-threshold', loadMoreItems);
if (self.scrollThreshold) {
self.scrollThreshold.destroy();
}
};
};
});

View file

@ -22,6 +22,7 @@
</div>
<div class="ehsContent fullWidth pageTabsContainer">
<div class="pageTabContent hide" data-index="0">
<div id="resumableSection" class="homePageSection">
<div>
@ -63,26 +64,32 @@
</p>
</div>
</div>
<div class="pageTabContent hide" data-index="3">
<div id="seriesTab" class="pageTabContent absolutePageTabContent hide smoothScrollY" data-index="3">
<div style="text-align: center;padding:.7em 0;">
<paper-icon-button class="btnSelectView" icon="view-comfy" title="${ButtonSelectView}"></paper-icon-button>
<paper-icon-button class="btnSort" title="${ButtonSort}" icon="sort-by-alpha"></paper-icon-button>
<paper-icon-button class="btnFilter" title="${ButtonFilter}" icon="filter-list"></paper-icon-button>
</div>
<div class="alphabetPicker">
</div>
<div class="viewSettings">
<div class="listTopPaging">
<div class="itemsContainer" style="margin-left:-10px;">
</div>
</div>
<div id="items" class="itemsContainer paddedItemsContainer" style="text-align: center;"></div>
<div id="episodesTab" class="pageTabContent absolutePageTabContent hide smoothScrollY" data-index="4">
<div style="text-align: center;padding:.7em 0;">
<paper-icon-button class="btnSelectView" icon="view-comfy" title="${ButtonSelectView}"></paper-icon-button>
<paper-icon-button class="btnSort" title="${ButtonSort}" icon="sort-by-alpha"></paper-icon-button>
<paper-icon-button class="btnFilter" title="${ButtonFilter}" icon="filter-list"></paper-icon-button>
</div>
<div class="pageTabContent hide" data-index="4">
<div class="viewSettings">
<div class="listTopPaging">
<div class="itemsContainer">
</div>
</div>
<div id="items" class="itemsContainer paddedItemsContainer"></div>
</div>
<div class="pageTabContent hide" data-index="5">
<div class="viewSettings">
<div class="listTopPaging">
</div>
<div style="text-align: center;">
<paper-icon-button class="btnSelectView" icon="view-comfy" title="${ButtonSelectView}"></paper-icon-button>
</div>
<div id="items" class="itemsContainer paddedItemsContainer"></div>
</div>