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

First separation commit.

Added LICENSE, README.md, CONTRIBUTORS.md
This commit is contained in:
Erwin de Haan 2019-01-09 12:36:54 +01:00
parent 09513af31b
commit 4678528d00
657 changed files with 422 additions and 0 deletions

View file

@ -0,0 +1,12 @@
.searchFieldsInner {
max-width: 60em;
margin: 0 auto
}
.searchfields-icon {
margin-bottom: .1em;
margin-right: .25em;
font-size: 2em;
-webkit-align-self: flex-end;
align-self: flex-end
}

View file

@ -0,0 +1,64 @@
define(["layoutManager", "globalize", "require", "events", "browser", "alphaPicker", "emby-input", "flexStyles", "material-icons", "css!./searchfields"], function(layoutManager, globalize, require, events, browser, AlphaPicker) {
"use strict";
function onSearchTimeout() {
var instance = this,
value = instance.nextSearchValue;
value = (value || "").trim(), events.trigger(instance, "search", [value])
}
function triggerSearch(instance, value) {
instance.searchTimeout && clearTimeout(instance.searchTimeout), instance.nextSearchValue = value, instance.searchTimeout = setTimeout(onSearchTimeout.bind(instance), 400)
}
function onAlphaValueClicked(e) {
var value = e.detail.value,
searchFieldsInstance = this,
txtSearch = searchFieldsInstance.options.element.querySelector(".searchfields-txtSearch");
if ("backspace" === value) {
var val = txtSearch.value;
txtSearch.value = val.length ? val.substring(0, val.length - 1) : ""
} else txtSearch.value += value;
txtSearch.dispatchEvent(new CustomEvent("input", {
bubbles: !0
}))
}
function initAlphaPicker(alphaPickerElement, instance) {
instance.alphaPicker = new AlphaPicker({
element: alphaPickerElement,
mode: "keyboard"
}), alphaPickerElement.addEventListener("alphavalueclicked", onAlphaValueClicked.bind(instance))
}
function onSearchInput(e) {
triggerSearch(this, e.target.value)
}
function embed(elem, instance, options) {
require(["text!./searchfields.template.html"], function(template) {
var html = globalize.translateDocument(template, "sharedcomponents");
(browser.tizen || browser.orsay) && (html = html.replace("<input ", "<input readonly ")), elem.innerHTML = html, elem.classList.add("searchFields");
var txtSearch = elem.querySelector(".searchfields-txtSearch");
if (layoutManager.tv) {
var alphaPickerElement = elem.querySelector(".alphaPicker");
elem.querySelector(".alphaPicker").classList.remove("hide"), initAlphaPicker(alphaPickerElement, instance)
}
txtSearch.addEventListener("input", onSearchInput.bind(instance)), instance.focus()
})
}
function SearchFields(options) {
this.options = options, embed(options.element, this, options)
}
return SearchFields.prototype.focus = function() {
this.options.element.querySelector(".searchfields-txtSearch").focus()
}, SearchFields.prototype.destroy = function() {
var options = this.options;
options && options.element.classList.remove("searchFields"), this.options = null;
var alphaPicker = this.alphaPicker;
alphaPicker && alphaPicker.destroy(), this.alphaPicker = null;
var searchTimeout = this.searchTimeout;
searchTimeout && clearTimeout(searchTimeout), this.searchTimeout = null, this.nextSearchValue = null
}, SearchFields
});

View file

@ -0,0 +1,7 @@
<div class="searchFieldsInner flex align-items-center justify-content-center">
<i class="searchfields-icon md-icon">&#xE8B6;</i>
<div class="inputContainer flex-grow" style="margin-bottom: 0;">
<input is="emby-input" class="searchfields-txtSearch" type="text" data-keyboard="false" placeholder="${Search}" autocomplete="off" maxlength="40" autofocus />
</div>
</div>
<div class="alphaPicker align-items-center hide"></div>

View file

@ -0,0 +1,396 @@
define(["layoutManager", "globalize", "require", "events", "connectionManager", "cardBuilder", "appRouter", "emby-scroller", "emby-itemscontainer", "emby-linkbutton"], function(layoutManager, globalize, require, events, connectionManager, cardBuilder, appRouter) {
"use strict";
function loadSuggestions(instance, context, apiClient) {
var options = {
SortBy: "IsFavoriteOrLiked,Random",
IncludeItemTypes: "Movie,Series,MusicArtist",
Limit: 20,
Recursive: !0,
ImageTypeLimit: 0,
EnableImages: !1,
ParentId: instance.options.parentId,
EnableTotalRecordCount: !1
};
apiClient.getItems(apiClient.getCurrentUserId(), options).then(function(result) {
"suggestions" !== instance.mode && (result.Items = []);
var html = result.Items.map(function(i) {
var href = appRouter.getRouteUrl(i),
itemHtml = '<div><a is="emby-linkbutton" class="button-link" style="display:inline-block;padding:.5em 1em;" href="' + href + '">';
return itemHtml += i.Name, itemHtml += "</a></div>"
}).join(""),
searchSuggestions = context.querySelector(".searchSuggestions");
searchSuggestions.querySelector(".searchSuggestionsList").innerHTML = html, result.Items.length && searchSuggestions.classList.remove("hide")
})
}
function getSearchHints(instance, apiClient, query) {
if (!query.searchTerm) return Promise.resolve({
SearchHints: []
});
var allowSearch = !0,
queryIncludeItemTypes = query.IncludeItemTypes;
if ("tvshows" === instance.options.collectionType ? query.IncludeArtists ? allowSearch = !1 : "Movie" !== queryIncludeItemTypes && "LiveTvProgram" !== queryIncludeItemTypes && "MusicAlbum" !== queryIncludeItemTypes && "Audio" !== queryIncludeItemTypes && "Book" !== queryIncludeItemTypes && "AudioBook" !== queryIncludeItemTypes && "Playlist" !== queryIncludeItemTypes && "PhotoAlbum" !== queryIncludeItemTypes && "Video" !== query.MediaTypes && "Photo" !== query.MediaTypes || (allowSearch = !1) : "movies" === instance.options.collectionType ? query.IncludeArtists ? allowSearch = !1 : "Series" !== queryIncludeItemTypes && "Episode" !== queryIncludeItemTypes && "LiveTvProgram" !== queryIncludeItemTypes && "MusicAlbum" !== queryIncludeItemTypes && "Audio" !== queryIncludeItemTypes && "Book" !== queryIncludeItemTypes && "AudioBook" !== queryIncludeItemTypes && "Playlist" !== queryIncludeItemTypes && "PhotoAlbum" !== queryIncludeItemTypes && "Video" !== query.MediaTypes && "Photo" !== query.MediaTypes || (allowSearch = !1) : "music" === instance.options.collectionType ? query.People ? allowSearch = !1 : "Series" !== queryIncludeItemTypes && "Episode" !== queryIncludeItemTypes && "LiveTvProgram" !== queryIncludeItemTypes && "Movie" !== queryIncludeItemTypes || (allowSearch = !1) : "livetv" === instance.options.collectionType && (query.IncludeArtists || query.IncludePeople ? allowSearch = !1 : "Series" !== queryIncludeItemTypes && "Episode" !== queryIncludeItemTypes && "MusicAlbum" !== queryIncludeItemTypes && "Audio" !== queryIncludeItemTypes && "Book" !== queryIncludeItemTypes && "AudioBook" !== queryIncludeItemTypes && "PhotoAlbum" !== queryIncludeItemTypes && "Movie" !== queryIncludeItemTypes && "Video" !== query.MediaTypes && "Photo" !== query.MediaTypes || (allowSearch = !1)), "NullType" === queryIncludeItemTypes && (allowSearch = !1), !allowSearch) return Promise.resolve({
SearchHints: []
});
if (apiClient.isMinServerVersion("3.4.1.31")) {
query.Fields = "PrimaryImageAspectRatio,CanDelete,BasicSyncInfo,MediaSourceCount", query.Recursive = !0, query.EnableTotalRecordCount = !1, query.ImageTypeLimit = 1;
var methodName = "getItems";
return query.IncludeMedia || (query.IncludePeople ? methodName = "getPeople" : query.IncludeArtists && (methodName = "getArtists")), apiClient[methodName](apiClient.getCurrentUserId(), query)
}
return query.UserId = apiClient.getCurrentUserId(), apiClient.getSearchHints(query)
}
function search(instance, apiClient, context, value) {
value || layoutManager.tv ? (instance.mode = "search", context.querySelector(".searchSuggestions").classList.add("hide")) : (instance.mode = "suggestions", loadSuggestions(instance, context, apiClient)), "livetv" === instance.options.collectionType ? searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "LiveTvProgram",
IsMovie: !0,
IsKids: !1,
IsNews: !1
}, context, ".movieResults", {
preferThumb: !0,
inheritThumb: !1,
shape: enableScrollX() ? "overflowPortrait" : "portrait",
showParentTitleOrTitle: !0,
showTitle: !1,
centerText: !0,
coverImage: !0,
overlayText: !1,
overlayMoreButton: !0,
showAirTime: !0,
showAirDateTime: !0,
showChannelName: !0
}) : searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "Movie"
}, context, ".movieResults", {
showTitle: !0,
overlayText: !1,
centerText: !0,
showYear: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "Series"
}, context, ".seriesResults", {
showTitle: !0,
overlayText: !1,
centerText: !0,
showYear: !0
}), "livetv" === instance.options.collectionType ? searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "LiveTvProgram",
IsSeries: !0,
IsSports: !1,
IsKids: !1,
IsNews: !1
}, context, ".episodeResults", {
preferThumb: !0,
inheritThumb: !1,
shape: enableScrollX() ? "overflowBackdrop" : "backdrop",
showParentTitleOrTitle: !0,
showTitle: !1,
centerText: !0,
coverImage: !0,
overlayText: !1,
overlayMoreButton: !0,
showAirTime: !0,
showAirDateTime: !0,
showChannelName: !0
}) : searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "Episode"
}, context, ".episodeResults", {
coverImage: !0,
showTitle: !0,
showParentTitle: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "livetv" === instance.options.collectionType ? "LiveTvProgram" : "NullType",
IsSports: !0
}, context, ".sportsResults", {
preferThumb: !0,
inheritThumb: !1,
shape: enableScrollX() ? "overflowBackdrop" : "backdrop",
showParentTitleOrTitle: !0,
showTitle: !1,
centerText: !0,
coverImage: !0,
overlayText: !1,
overlayMoreButton: !0,
showAirTime: !0,
showAirDateTime: !0,
showChannelName: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "livetv" === instance.options.collectionType ? "LiveTvProgram" : "NullType",
IsKids: !0
}, context, ".kidsResults", {
preferThumb: !0,
inheritThumb: !1,
shape: enableScrollX() ? "overflowBackdrop" : "backdrop",
showParentTitleOrTitle: !0,
showTitle: !1,
centerText: !0,
coverImage: !0,
overlayText: !1,
overlayMoreButton: !0,
showAirTime: !0,
showAirDateTime: !0,
showChannelName: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "livetv" === instance.options.collectionType ? "LiveTvProgram" : "NullType",
IsNews: !0
}, context, ".newsResults", {
preferThumb: !0,
inheritThumb: !1,
shape: enableScrollX() ? "overflowBackdrop" : "backdrop",
showParentTitleOrTitle: !0,
showTitle: !1,
centerText: !0,
coverImage: !0,
overlayText: !1,
overlayMoreButton: !0,
showAirTime: !0,
showAirDateTime: !0,
showChannelName: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "LiveTvProgram",
IsMovie: "livetv" !== instance.options.collectionType && null,
IsSeries: "livetv" !== instance.options.collectionType && null,
IsSports: "livetv" !== instance.options.collectionType && null,
IsKids: "livetv" !== instance.options.collectionType && null,
IsNews: "livetv" !== instance.options.collectionType && null
}, context, ".programResults", {
preferThumb: !0,
inheritThumb: !1,
shape: enableScrollX() ? "overflowBackdrop" : "backdrop",
showParentTitleOrTitle: !0,
showTitle: !1,
centerText: !0,
coverImage: !0,
overlayText: !1,
overlayMoreButton: !0,
showAirTime: !0,
showAirDateTime: !0,
showChannelName: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
MediaTypes: "Video",
ExcludeItemTypes: "Movie,Episode"
}, context, ".videoResults", {
showParentTitle: !0,
showTitle: !0,
overlayText: !1,
centerText: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !0,
IncludeMedia: !1,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1
}, context, ".peopleResults", {
coverImage: !0,
showTitle: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !1,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !0
}, context, ".artistResults", {
coverImage: !0,
showTitle: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "MusicAlbum"
}, context, ".albumResults", {
showParentTitle: !0,
showTitle: !0,
overlayText: !1,
centerText: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "Audio"
}, context, ".songResults", {
showParentTitle: !0,
showTitle: !0,
overlayText: !1,
centerText: !0,
action: "play"
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
MediaTypes: "Photo"
}, context, ".photoResults", {
showParentTitle: !1,
showTitle: !0,
overlayText: !1,
centerText: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "PhotoAlbum"
}, context, ".photoAlbumResults", {
showTitle: !0,
overlayText: !1,
centerText: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "Book"
}, context, ".bookResults", {
showTitle: !0,
overlayText: !1,
centerText: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "AudioBook"
}, context, ".audioBookResults", {
showTitle: !0,
overlayText: !1,
centerText: !0
}), searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: !1,
IncludeMedia: !0,
IncludeGenres: !1,
IncludeStudios: !1,
IncludeArtists: !1,
IncludeItemTypes: "Playlist"
}, context, ".playlistResults", {
showTitle: !0,
overlayText: !1,
centerText: !0
})
}
function searchType(instance, apiClient, query, context, section, cardOptions) {
query.Limit = enableScrollX() ? 24 : 16, query.ParentId = instance.options.parentId, getSearchHints(instance, apiClient, query).then(function(result) {
populateResults(result, context, section, cardOptions)
})
}
function populateResults(result, context, section, cardOptions) {
section = context.querySelector(section);
var items = result.Items || result.SearchHints,
itemsContainer = section.querySelector(".itemsContainer");
cardBuilder.buildCards(items, Object.assign({
itemsContainer: itemsContainer,
parentContainer: section,
shape: enableScrollX() ? "autooverflow" : "auto",
scalable: !0,
overlayText: !1,
centerText: !0,
allowBottomPadding: !enableScrollX()
}, cardOptions || {})), section.querySelector(".emby-scroller").scrollToBeginning(!0)
}
function enableScrollX() {
return !0
}
function replaceAll(originalString, strReplace, strWith) {
var reg = new RegExp(strReplace, "ig");
return originalString.replace(reg, strWith)
}
function embed(elem, instance, options) {
require(["text!./searchresults.template.html"], function(template) {
enableScrollX() || (template = replaceAll(template, 'data-horizontal="true"', 'data-horizontal="false"'), template = replaceAll(template, "itemsContainer scrollSlider", "itemsContainer scrollSlider vertical-wrap"));
var html = globalize.translateDocument(template, "sharedcomponents");
elem.innerHTML = html, elem.classList.add("searchResults"), instance.search("")
})
}
function SearchResults(options) {
this.options = options, embed(options.element, this, options)
}
return SearchResults.prototype.search = function(value) {
search(this, connectionManager.getApiClient(this.options.serverId), this.options.element, value)
}, SearchResults.prototype.destroy = function() {
var options = this.options;
options && options.element.classList.remove("searchFields"), this.options = null
}, SearchResults
});

View file

@ -0,0 +1,146 @@
<div class="hide verticalSection searchSuggestions" style="text-align:center;">
<div>
<h2 class="sectionTitle padded-left padded-right">${Suggestions}</h2>
</div>
<div class="searchSuggestionsList padded-left padded-right">
</div>
</div>
<div class="hide verticalSection movieResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Movies}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection seriesResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Shows}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection episodeResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Episodes}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection sportsResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Sports}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection kidsResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Kids}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection newsResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${News}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection programResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Programs}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection videoResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Videos}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection playlistResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Playlists}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection artistResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Artists}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection albumResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Albums}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection songResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Songs}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection photoAlbumResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${HeaderPhotoAlbums}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection photoResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Photos}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection audioBookResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${HeaderAudioBooks}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection bookResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Books}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>
<div class="hide verticalSection peopleResults">
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${People}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
</div>
</div>