mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
update search
This commit is contained in:
parent
a66d44127f
commit
036319e68b
8 changed files with 183 additions and 562 deletions
|
@ -1,193 +0,0 @@
|
||||||
.searchHints {
|
|
||||||
margin-top: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchHint {
|
|
||||||
display: block;
|
|
||||||
text-decoration: none;
|
|
||||||
color: #fff;
|
|
||||||
border-bottom: 1px solid #444;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchHint:hover {
|
|
||||||
background-color: #444;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchHint:focus {
|
|
||||||
background-color: #444;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchHintImage {
|
|
||||||
display: inline-block;
|
|
||||||
width: 20%;
|
|
||||||
vertical-align: middle;
|
|
||||||
margin: 4px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchHintContent {
|
|
||||||
vertical-align: top;
|
|
||||||
display: inline-block;
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchHintName {
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
color: #fff;
|
|
||||||
font-weight: normal !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchHintSecondaryText {
|
|
||||||
color: #fff;
|
|
||||||
margin-top: 3px;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchHintContentInner {
|
|
||||||
padding: 2px 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@-moz-keyframes spinPulse {
|
|
||||||
0% {
|
|
||||||
-moz-transform: rotate(160deg);
|
|
||||||
opacity: 0;
|
|
||||||
box-shadow: 0 0 1px #2187e7;
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
-moz-transform: rotate(145deg);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
-moz-transform: rotate(-320deg);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@-moz-keyframes spinoffPulse {
|
|
||||||
0% {
|
|
||||||
-moz-transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
-moz-transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes spinPulse {
|
|
||||||
0% {
|
|
||||||
-webkit-transform: rotate(160deg);
|
|
||||||
opacity: 0;
|
|
||||||
box-shadow: 0 0 1px #2187e7;
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
-webkit-transform: rotate(145deg);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
-webkit-transform: rotate(-320deg);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes spinoffPulse {
|
|
||||||
0% {
|
|
||||||
-webkit-transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
-webkit-transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerSearchInput {
|
|
||||||
margin: 0 !important;
|
|
||||||
background: #222 !important;
|
|
||||||
border: 0 !important;
|
|
||||||
color: #eee !important;
|
|
||||||
border-radius: 0 !important;
|
|
||||||
padding: 7px 0 6px 0 !important;
|
|
||||||
text-indent: 10px !important;
|
|
||||||
font-family: inherit;
|
|
||||||
outline: none;
|
|
||||||
vertical-align: middle;
|
|
||||||
width: 85% !important;
|
|
||||||
display: inline-block !important;
|
|
||||||
height: 100%!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.viewMenuSearch {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0%;
|
|
||||||
right: 0;
|
|
||||||
background: #000000;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (min-width: 600px) {
|
|
||||||
.headerSearchInput {
|
|
||||||
width: 90% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (min-width: 800px) {
|
|
||||||
.headerSearchInput {
|
|
||||||
width: 93% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (min-width: 1200px) {
|
|
||||||
.headerSearchInput {
|
|
||||||
width: 96% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.viewMenuSearch:not(.hide) {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.viewMenuSearchForm {
|
|
||||||
max-width: none;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchResultsOverlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 50px;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
border: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchResultsContainer {
|
|
||||||
padding: .5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (min-width: 800px) {
|
|
||||||
.searchResultsContainer {
|
|
||||||
padding-left: 1em;
|
|
||||||
padding-right: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (min-height: 800px) {
|
|
||||||
.searchResultsContainer {
|
|
||||||
padding-top: 1em;
|
|
||||||
padding-bottom: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btnCloseSearch {
|
|
||||||
padding-top: 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
|
@ -135,10 +135,6 @@ h1, h1 a {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.viewMenuSearch {
|
|
||||||
background: #1c1c1c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bottomFab {
|
.bottomFab {
|
||||||
bottom: 120px !important;
|
bottom: 120px !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,7 @@
|
||||||
html += '<button is="paper-icon-button-light" class="btnCast headerButton headerButtonRight hide autoSize"><i class="md-icon">cast</i></button>';
|
html += '<button is="paper-icon-button-light" class="btnCast headerButton headerButtonRight hide autoSize"><i class="md-icon">cast</i></button>';
|
||||||
|
|
||||||
if (AppInfo.enableSearchInTopMenu) {
|
if (AppInfo.enableSearchInTopMenu) {
|
||||||
html += '<button type="button" is="paper-icon-button-light" class=headerButton headerButtonRight headerSearchButton hide autoSize" onclick="Search.showSearchPanel();"><i class="md-icon">search</i></button>';
|
html += '<button type="button" is="paper-icon-button-light" class="headerButton headerButtonRight headerSearchButton hide autoSize"><i class="md-icon">search</i></button>';
|
||||||
html += '<div class="viewMenuSearch hide">';
|
|
||||||
html += '<form class="viewMenuSearchForm">';
|
|
||||||
html += '<input type="text" class="headerSearchInput" autocomplete="off" />';
|
|
||||||
html += '<button type="button" is="paper-icon-button-light" class="btnCloseSearch autoSize"><i class="md-icon">close</i></button>';
|
|
||||||
html += '</form>';
|
|
||||||
html += '</div>';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
html += '<button is="paper-icon-button-light" class="headerButton headerButtonRight headerVoiceButton hide autoSize"><i class="md-icon">mic</i></button>';
|
html += '<button is="paper-icon-button-light" class="headerButton headerButtonRight headerVoiceButton hide autoSize"><i class="md-icon">mic</i></button>';
|
||||||
|
@ -175,6 +169,10 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showSearch() {
|
||||||
|
Dashboard.navigate('search.html');
|
||||||
|
}
|
||||||
|
|
||||||
function onHeaderUserButtonClick(e) {
|
function onHeaderUserButtonClick(e) {
|
||||||
Dashboard.showUserFlyout(e.target);
|
Dashboard.showUserFlyout(e.target);
|
||||||
}
|
}
|
||||||
|
@ -252,6 +250,11 @@
|
||||||
headerVoiceButton.addEventListener('click', showVoice);
|
headerVoiceButton.addEventListener('click', showVoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var headerSearchButton = document.querySelector('.headerSearchButton');
|
||||||
|
if (headerSearchButton) {
|
||||||
|
headerSearchButton.addEventListener('click', showSearch);
|
||||||
|
}
|
||||||
|
|
||||||
var headerUserButton = document.querySelector('.headerUserButton');
|
var headerUserButton = document.querySelector('.headerUserButton');
|
||||||
if (headerUserButton) {
|
if (headerUserButton) {
|
||||||
headerUserButton.addEventListener('click', onHeaderUserButtonClick);
|
headerUserButton.addEventListener('click', onHeaderUserButtonClick);
|
||||||
|
|
|
@ -1,266 +0,0 @@
|
||||||
define(['libraryBrowser', 'events', 'scrollStyles', 'scripts/librarymenu'], function (libraryBrowser, events) {
|
|
||||||
|
|
||||||
var searchHintTimeout;
|
|
||||||
|
|
||||||
function clearSearchHintTimeout() {
|
|
||||||
|
|
||||||
if (searchHintTimeout) {
|
|
||||||
|
|
||||||
clearTimeout(searchHintTimeout);
|
|
||||||
searchHintTimeout = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAdditionalTextLines(hint) {
|
|
||||||
|
|
||||||
if (hint.Type == "Audio") {
|
|
||||||
|
|
||||||
return [[hint.AlbumArtist, hint.Album].join(" - ")];
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (hint.Type == "MusicAlbum") {
|
|
||||||
|
|
||||||
return [hint.AlbumArtist];
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (hint.Type == "MusicArtist") {
|
|
||||||
|
|
||||||
return [Globalize.translate('LabelArtist')];
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (hint.Type == "Movie") {
|
|
||||||
|
|
||||||
return [Globalize.translate('LabelMovie')];
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (hint.Type == "MusicVideo") {
|
|
||||||
|
|
||||||
return [Globalize.translate('LabelMusicVideo')];
|
|
||||||
}
|
|
||||||
else if (hint.Type == "Episode") {
|
|
||||||
|
|
||||||
return [Globalize.translate('LabelEpisode')];
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (hint.Type == "Series") {
|
|
||||||
|
|
||||||
return [Globalize.translate('Series')];
|
|
||||||
}
|
|
||||||
else if (hint.Type == "BoxSet") {
|
|
||||||
|
|
||||||
return [Globalize.translate('LabelCollection')];
|
|
||||||
}
|
|
||||||
else if (hint.ChannelName) {
|
|
||||||
|
|
||||||
return [hint.ChannelName];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [hint.Type];
|
|
||||||
}
|
|
||||||
|
|
||||||
function search() {
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
self.showSearchPanel = function () {
|
|
||||||
|
|
||||||
showSearchMenu();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
window.Search = new search();
|
|
||||||
|
|
||||||
function renderSearchResultsInOverlay(elem, hints) {
|
|
||||||
|
|
||||||
// Massage the objects to look like regular items
|
|
||||||
hints = hints.map(function (i) {
|
|
||||||
|
|
||||||
i.Id = i.ItemId;
|
|
||||||
i.ImageTags = {};
|
|
||||||
i.UserData = {};
|
|
||||||
|
|
||||||
if (i.PrimaryImageTag) {
|
|
||||||
i.ImageTags.Primary = i.PrimaryImageTag;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
});
|
|
||||||
|
|
||||||
var html = libraryBrowser.getPosterViewHtml({
|
|
||||||
items: hints,
|
|
||||||
shape: "auto",
|
|
||||||
lazy: true,
|
|
||||||
overlayText: false,
|
|
||||||
showTitle: true,
|
|
||||||
centerImage: true,
|
|
||||||
centerText: true,
|
|
||||||
textLines: getAdditionalTextLines,
|
|
||||||
overlayPlayButton: true
|
|
||||||
});
|
|
||||||
|
|
||||||
var itemsContainer = elem.querySelector('.itemsContainer');
|
|
||||||
itemsContainer.innerHTML = html;
|
|
||||||
ImageLoader.lazyChildren(itemsContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
function requestSearchHintsForOverlay(elem, searchTerm) {
|
|
||||||
|
|
||||||
var currentTimeout = searchHintTimeout;
|
|
||||||
Dashboard.showLoadingMsg();
|
|
||||||
|
|
||||||
ApiClient.getSearchHints({
|
|
||||||
|
|
||||||
userId: Dashboard.getCurrentUserId(),
|
|
||||||
searchTerm: (searchTerm || '').trim(),
|
|
||||||
limit: 30
|
|
||||||
|
|
||||||
}).then(function (result) {
|
|
||||||
|
|
||||||
if (currentTimeout == searchHintTimeout) {
|
|
||||||
renderSearchResultsInOverlay(elem, result.SearchHints);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dashboard.hideLoadingMsg();
|
|
||||||
}, function () {
|
|
||||||
Dashboard.hideLoadingMsg();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateSearchOverlay(elem, searchTerm) {
|
|
||||||
|
|
||||||
if (!searchTerm) {
|
|
||||||
|
|
||||||
var itemsContainer = elem.querySelector('.itemsContainer');
|
|
||||||
if (itemsContainer) {
|
|
||||||
itemsContainer.innerHTML = '';
|
|
||||||
}
|
|
||||||
clearSearchHintTimeout();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
clearSearchHintTimeout();
|
|
||||||
|
|
||||||
searchHintTimeout = setTimeout(function () {
|
|
||||||
|
|
||||||
requestSearchHintsForOverlay(elem, searchTerm);
|
|
||||||
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSearchOverlay(createIfNeeded) {
|
|
||||||
|
|
||||||
var elem = document.querySelector('.searchResultsOverlay');
|
|
||||||
|
|
||||||
if (createIfNeeded && !elem) {
|
|
||||||
|
|
||||||
var div = document.createElement('div');
|
|
||||||
div.className = 'searchResultsOverlay ui-body-b smoothScrollY background-theme-b';
|
|
||||||
|
|
||||||
div.innerHTML = '<div class="searchResultsContainer"><div class="itemsContainer"></div></div></div>';
|
|
||||||
|
|
||||||
document.body.appendChild(div);
|
|
||||||
libraryBrowser.createCardMenus(div);
|
|
||||||
|
|
||||||
elem = div;
|
|
||||||
}
|
|
||||||
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
var isVisible;
|
|
||||||
|
|
||||||
function onHeaderSearchChange(val) {
|
|
||||||
|
|
||||||
var elem;
|
|
||||||
|
|
||||||
if (val) {
|
|
||||||
|
|
||||||
elem = getSearchOverlay(true);
|
|
||||||
|
|
||||||
if (!isVisible) {
|
|
||||||
fadeIn(elem, 1);
|
|
||||||
}
|
|
||||||
isVisible = true;
|
|
||||||
|
|
||||||
document.body.classList.add('bodyWithPopupOpen');
|
|
||||||
|
|
||||||
updateSearchOverlay(elem, val);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
elem = getSearchOverlay(false);
|
|
||||||
|
|
||||||
if (elem) {
|
|
||||||
updateSearchOverlay(elem, '');
|
|
||||||
|
|
||||||
if (isVisible) {
|
|
||||||
fadeOut(elem, 1);
|
|
||||||
isVisible = false;
|
|
||||||
}
|
|
||||||
document.body.classList.remove('bodyWithPopupOpen');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fadeIn(elem, iterations) {
|
|
||||||
|
|
||||||
var keyframes = [
|
|
||||||
{ opacity: '0', offset: 0 },
|
|
||||||
{ opacity: '1', offset: 1 }];
|
|
||||||
var timing = { duration: 200, iterations: iterations, fill: 'both' };
|
|
||||||
|
|
||||||
if (elem.animate) {
|
|
||||||
elem.animate(keyframes, timing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fadeOut(elem, iterations) {
|
|
||||||
var keyframes = [
|
|
||||||
{ opacity: '1', offset: 0 },
|
|
||||||
{ opacity: '0', offset: 1 }];
|
|
||||||
var timing = { duration: 600, iterations: iterations, fill: 'both' };
|
|
||||||
|
|
||||||
var onfinish = function () {
|
|
||||||
elem.parentNode.removeChild(elem);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (elem.animate) {
|
|
||||||
elem.animate(keyframes, timing).onfinish = onfinish;
|
|
||||||
} else {
|
|
||||||
onfinish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function bindSearchEvents() {
|
|
||||||
|
|
||||||
require(['searchmenu'], function (searchmenu) {
|
|
||||||
events.on(window.SearchMenu, 'closed', closeSearchResults);
|
|
||||||
events.on(window.SearchMenu, 'change', function (e, value) {
|
|
||||||
onHeaderSearchChange(value);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeSearchResults() {
|
|
||||||
|
|
||||||
onHeaderSearchChange('');
|
|
||||||
hideSearchMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
function showSearchMenu() {
|
|
||||||
require(['searchmenu'], function (searchmenu) {
|
|
||||||
window.SearchMenu.show();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideSearchMenu() {
|
|
||||||
require(['searchmenu'], function (searchmenu) {
|
|
||||||
window.SearchMenu.hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('viewbeforehide', closeSearchResults);
|
|
||||||
|
|
||||||
bindSearchEvents();
|
|
||||||
|
|
||||||
// dismiss search UI if user clicks a play button on a search result
|
|
||||||
events.on(MediaController, 'beforeplaybackstart', closeSearchResults);
|
|
||||||
|
|
||||||
});
|
|
|
@ -1,73 +0,0 @@
|
||||||
define([], function () {
|
|
||||||
|
|
||||||
function fadeIn(elem, iterations) {
|
|
||||||
|
|
||||||
var keyframes = [
|
|
||||||
{ opacity: '0', offset: 0 },
|
|
||||||
{ opacity: '1', offset: 1 }];
|
|
||||||
var timing = { duration: 200, iterations: iterations };
|
|
||||||
return elem.animate(keyframes, timing);
|
|
||||||
}
|
|
||||||
|
|
||||||
function searchMenu() {
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
var headerSearchInput = document.querySelector('.headerSearchInput');
|
|
||||||
|
|
||||||
self.show = function () {
|
|
||||||
|
|
||||||
require(['css!css/search.css'], function () {
|
|
||||||
|
|
||||||
headerSearchInput.value = '';
|
|
||||||
|
|
||||||
document.querySelector('.btnCloseSearch').classList.add('hide');
|
|
||||||
var elem = document.querySelector('.viewMenuSearch');
|
|
||||||
|
|
||||||
elem.classList.remove('hide');
|
|
||||||
|
|
||||||
var onFinish = function() {
|
|
||||||
headerSearchInput.focus();
|
|
||||||
document.querySelector('.btnCloseSearch').classList.remove('hide');
|
|
||||||
};
|
|
||||||
|
|
||||||
if (elem.animate) {
|
|
||||||
fadeIn(elem, 1).onfinish = onFinish;
|
|
||||||
} else {
|
|
||||||
onFinish();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
self.hide = function () {
|
|
||||||
|
|
||||||
var viewMenuSearch = document.querySelector('.viewMenuSearch');
|
|
||||||
|
|
||||||
if (!viewMenuSearch) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!viewMenuSearch.classList.contains('hide')) {
|
|
||||||
document.querySelector('.btnCloseSearch').classList.add('hide');
|
|
||||||
viewMenuSearch.classList.add('hide');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document.querySelector('.viewMenuSearchForm').addEventListener('submit', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
document.querySelector('.btnCloseSearch').addEventListener('click', function () {
|
|
||||||
self.hide();
|
|
||||||
Events.trigger(self, 'closed');
|
|
||||||
});
|
|
||||||
|
|
||||||
headerSearchInput.addEventListener('input', function (e) {
|
|
||||||
Events.trigger(self, 'change', [this.value]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
window.SearchMenu = new searchMenu();
|
|
||||||
return Window.SearchMenu;
|
|
||||||
});
|
|
|
@ -1,4 +1,4 @@
|
||||||
define([], function () {
|
define(['libraryBrowser', 'focusManager', 'emby-input', 'paper-icon-button-light', 'material-icons'], function (libraryBrowser, focusManager) {
|
||||||
|
|
||||||
function loadSuggestions(page) {
|
function loadSuggestions(page) {
|
||||||
|
|
||||||
|
@ -29,13 +29,160 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pageIdOn('pageshow', "searchPage", function () {
|
return function (view, params) {
|
||||||
|
|
||||||
var page = this;
|
var textSuggestions = view.querySelector('.textSuggestions');
|
||||||
loadSuggestions(page);
|
var searchResults = view.querySelector('.searchResults');
|
||||||
|
var searchHintTimeout;
|
||||||
|
|
||||||
Search.showSearchPanel();
|
function clearSearchHintTimeout() {
|
||||||
|
|
||||||
|
if (searchHintTimeout) {
|
||||||
|
|
||||||
|
clearTimeout(searchHintTimeout);
|
||||||
|
searchHintTimeout = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showTextSuggestions() {
|
||||||
|
if (AppInfo.enableAppLayouts) {
|
||||||
|
textSuggestions.classList.remove('hide');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAdditionalTextLines(hint) {
|
||||||
|
|
||||||
|
if (hint.Type == "Audio") {
|
||||||
|
|
||||||
|
return [[hint.AlbumArtist, hint.Album].join(" - ")];
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (hint.Type == "MusicAlbum") {
|
||||||
|
|
||||||
|
return [hint.AlbumArtist];
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (hint.Type == "MusicArtist") {
|
||||||
|
|
||||||
|
return [Globalize.translate('LabelArtist')];
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (hint.Type == "Movie") {
|
||||||
|
|
||||||
|
return [Globalize.translate('LabelMovie')];
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (hint.Type == "MusicVideo") {
|
||||||
|
|
||||||
|
return [Globalize.translate('LabelMusicVideo')];
|
||||||
|
}
|
||||||
|
else if (hint.Type == "Episode") {
|
||||||
|
|
||||||
|
return [Globalize.translate('LabelEpisode')];
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (hint.Type == "Series") {
|
||||||
|
|
||||||
|
return [Globalize.translate('Series')];
|
||||||
|
}
|
||||||
|
else if (hint.Type == "BoxSet") {
|
||||||
|
|
||||||
|
return [Globalize.translate('LabelCollection')];
|
||||||
|
}
|
||||||
|
else if (hint.ChannelName) {
|
||||||
|
|
||||||
|
return [hint.ChannelName];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [hint.Type];
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderSearchResultsInOverlay(hints) {
|
||||||
|
|
||||||
|
// Massage the objects to look like regular items
|
||||||
|
hints = hints.map(function (i) {
|
||||||
|
|
||||||
|
i.Id = i.ItemId;
|
||||||
|
i.ImageTags = {};
|
||||||
|
i.UserData = {};
|
||||||
|
|
||||||
|
if (i.PrimaryImageTag) {
|
||||||
|
i.ImageTags.Primary = i.PrimaryImageTag;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var html = libraryBrowser.getPosterViewHtml({
|
||||||
|
items: hints,
|
||||||
|
shape: "auto",
|
||||||
|
lazy: true,
|
||||||
|
overlayText: false,
|
||||||
|
showTitle: true,
|
||||||
|
centerImage: true,
|
||||||
|
centerText: true,
|
||||||
|
textLines: getAdditionalTextLines,
|
||||||
|
overlayPlayButton: true
|
||||||
|
});
|
||||||
|
|
||||||
|
var itemsContainer = searchResults;
|
||||||
|
itemsContainer.innerHTML = html;
|
||||||
|
searchResults.classList.remove('hide');
|
||||||
|
textSuggestions.classList.add('hide');
|
||||||
|
ImageLoader.lazyChildren(itemsContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestSearchHintsForOverlay(searchTerm) {
|
||||||
|
|
||||||
|
var currentTimeout = searchHintTimeout;
|
||||||
|
Dashboard.showLoadingMsg();
|
||||||
|
|
||||||
|
ApiClient.getSearchHints({
|
||||||
|
|
||||||
|
userId: Dashboard.getCurrentUserId(),
|
||||||
|
searchTerm: (searchTerm || '').trim(),
|
||||||
|
limit: 30
|
||||||
|
|
||||||
|
}).then(function (result) {
|
||||||
|
|
||||||
|
if (currentTimeout == searchHintTimeout) {
|
||||||
|
renderSearchResultsInOverlay(result.SearchHints);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dashboard.hideLoadingMsg();
|
||||||
|
}, function () {
|
||||||
|
Dashboard.hideLoadingMsg();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSearchChange(val) {
|
||||||
|
|
||||||
|
if (!val) {
|
||||||
|
clearSearchHintTimeout();
|
||||||
|
searchResults.classList.add('hide');
|
||||||
|
searchResults.innerHTML = '';
|
||||||
|
showTextSuggestions();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearSearchHintTimeout();
|
||||||
|
|
||||||
|
searchHintTimeout = setTimeout(function () {
|
||||||
|
requestSearchHintsForOverlay(val);
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AppInfo.enableAppLayouts) {
|
||||||
|
showTextSuggestions();
|
||||||
|
loadSuggestions(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
view.addEventListener('viewshow', function () {
|
||||||
|
focusManager.focus(view.querySelector('.txtSearch'));
|
||||||
|
});
|
||||||
|
|
||||||
|
view.querySelector('.txtSearch').addEventListener('input', function () {
|
||||||
|
onSearchChange(this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
});
|
});
|
|
@ -830,7 +830,7 @@ var Dashboard = {
|
||||||
Dashboard.onBrowseCommand(cmd.Arguments);
|
Dashboard.onBrowseCommand(cmd.Arguments);
|
||||||
break;
|
break;
|
||||||
case 'GoToSearch':
|
case 'GoToSearch':
|
||||||
Search.showSearchPanel();
|
Dashboard.navigate('search.html');
|
||||||
break;
|
break;
|
||||||
case 'DisplayMessage':
|
case 'DisplayMessage':
|
||||||
{
|
{
|
||||||
|
@ -2212,12 +2212,6 @@ var AppInfo = {};
|
||||||
define("detailtablecss", ['css!css/detailtable.css']);
|
define("detailtablecss", ['css!css/detailtable.css']);
|
||||||
define("tileitemcss", ['css!css/tileitem.css']);
|
define("tileitemcss", ['css!css/tileitem.css']);
|
||||||
|
|
||||||
if (Dashboard.isRunningInCordova() && browserInfo.safari) {
|
|
||||||
define("searchmenu", ["cordova/searchmenu"]);
|
|
||||||
} else {
|
|
||||||
define("searchmenu", ["scripts/searchmenu"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
define("buttonenabled", ["legacy/buttonenabled"]);
|
define("buttonenabled", ["legacy/buttonenabled"]);
|
||||||
|
|
||||||
var deps = [];
|
var deps = [];
|
||||||
|
@ -2902,7 +2896,8 @@ var AppInfo = {};
|
||||||
defineRoute({
|
defineRoute({
|
||||||
path: '/search.html',
|
path: '/search.html',
|
||||||
dependencies: [],
|
dependencies: [],
|
||||||
autoFocus: false
|
autoFocus: false,
|
||||||
|
controller: 'scripts/searchpage'
|
||||||
});
|
});
|
||||||
|
|
||||||
defineRoute({
|
defineRoute({
|
||||||
|
@ -3159,7 +3154,6 @@ var AppInfo = {};
|
||||||
deps.push('devices/ie/ie');
|
deps.push('devices/ie/ie');
|
||||||
}
|
}
|
||||||
|
|
||||||
deps.push('scripts/search');
|
|
||||||
deps.push('scripts/librarylist');
|
deps.push('scripts/librarylist');
|
||||||
deps.push('scripts/librarymenu');
|
deps.push('scripts/librarymenu');
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,25 @@
|
||||||
<div id="searchPage" data-role="page" class="page homePage libraryPage allLibraryPage noSecondaryNavPage" data-title="${ButtonSearch}" data-require="scripts/searchpage">
|
<div id="searchPage" data-role="page" class="page libraryPage allLibraryPage noSecondaryNavPage" data-title="${ButtonSearch}" data-backbutton="true">
|
||||||
|
|
||||||
<div data-role="content">
|
<div data-role="content">
|
||||||
<div style="text-align:center;">
|
<div class="readOnlyContent" style="text-align: center;margin: 0 auto;">
|
||||||
|
|
||||||
|
<div class="inputContainer">
|
||||||
|
<div style="display: flex; align-items: center;">
|
||||||
|
<i class="md-icon" style="width:28px;height:28px;font-size:28px;color:#ccc;">search</i>
|
||||||
|
<div style="flex-grow:1;">
|
||||||
|
<input is="emby-input" class="txtSearch" autocomplete="off" autofocus />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="textSuggestions hide">
|
||||||
<h1>${TabSuggestions}</h1>
|
<h1>${TabSuggestions}</h1>
|
||||||
|
|
||||||
<div class="searchSuggestions">
|
<div class="searchSuggestions">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="searchResults hide"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
Loading…
Add table
Add a link
Reference in a new issue