(function ($, document, window, clearTimeout, setTimeout) { var searchHintTimeout; function clearSearchHintTimeout() { if (searchHintTimeout) { clearTimeout(searchHintTimeout); searchHintTimeout = null; } } function updateSearchHints(page, searchTerm) { if (!searchTerm) { $('#searchHints', page).empty(); clearSearchHintTimeout(); return; } clearSearchHintTimeout(); searchHintTimeout = setTimeout(function () { requestSearchHints(page, searchTerm); }, 100); } function requestSearchHints(page, searchTerm) { var currentTimeout = searchHintTimeout; ApiClient.getSearchHints({ userId: Dashboard.getCurrentUserId(), searchTerm: searchTerm, limit: 10 }).done(function (result) { if (currentTimeout != searchHintTimeout) { return; } renderSearchHintResult(page, result.SearchHints); }); } function preg_quote(str, delimiter) { // http://kevin.vanzonneveld.net // + original by: booeyOH // + improved by: Ates Goral (http://magnetiq.com) // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + bugfixed by: Onno Marsman // + improved by: Brett Zamir (http://brett-zamir.me) // * example 1: preg_quote("$40"); // * returns 1: '\$40' // * example 2: preg_quote("*RRRING* Hello?"); // * returns 2: '\*RRRING\* Hello\?' // * example 3: preg_quote("\\.+*?[^]$(){}=!<>|:"); // * returns 3: '\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:' return (str + '').replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&'); } function getHintDisplayName(data, term) { var regexp = new RegExp("(" + preg_quote(term) + ")", 'gi'); return data.replace(regexp, "$1"); } 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('LabelSeries')]; } else if (hint.Type == "BoxSet") { return [Globalize.translate('LabelCollection')]; } return [hint.Type]; } function getSearchHintHtml(hint) { var html = ''; html += ''; var imgUrl; if (hint.PrimaryImageTag) { hint.ImageTags = { Primary: hint.PrimaryImageTag }; imgUrl = ApiClient.getImageUrl(hint.ItemId, { type: "Primary", maxWidth: 150, maxHeight: 150, tag: hint.PrimaryImageTag }); } else if (hint.MediaType == "Game") { imgUrl = "css/images/items/searchhintsv2/game.png"; } else if (hint.Type == "Episode" || hint.Type == "Season" || hint.Type == "Series") { imgUrl = "css/images/items/searchhintsv2/tv.png"; } else if (hint.Type == "Audio" || hint.Type == "MusicAlbum" || hint.Type == "MusicArtist") { imgUrl = "css/images/items/searchhintsv2/music.png"; } else if (hint.Type == "Person") { imgUrl = "css/images/items/searchhintsv2/person.png"; } else { imgUrl = "css/images/items/searchhintsv2/film.png"; } html += ''; html += '
'; html += '
' + getHintDisplayName(hint.Name, hint.MatchedTerm) + '
'; if (hint.Type == "Audio") { html += '
' + [hint.AlbumArtist, hint.Album].join(" - ") + '
'; } else if (hint.Type == "MusicAlbum") { html += '
' + hint.AlbumArtist + '
'; } else if (hint.Type == "MusicArtist") { html += '
' + Globalize.translate('LabelArtist') + '
'; } else if (hint.Type == "Movie") { html += '
' + Globalize.translate('LabelMovie') + '
'; } else if (hint.Type == "MusicVideo") { html += '
' + Globalize.translate('LabelMusicVideo') + '
'; } else if (hint.Type == "Episode") { html += '
' + Globalize.translate('LabelEpisode') + '
'; } else if (hint.Type == "Series") { html += '
' + Globalize.translate('LabelSeries') + '
'; } else { html += '
' + (hint.Type) + '
'; } var text; if (hint.EpisodeCount) { text = hint.EpisodeCount == 1 ? "1 Episode" : hint.EpisodeCount + " Episodes"; html += '
' + text + '
'; } else if (hint.SongCount) { text = hint.SongCount == 1 ? "1 Song" : hint.SongCount + " Songs"; html += '
' + text + '
'; } else if (hint.ProductionYear && hint.MediaType != "Audio" && hint.Type != "Episode") { html += '
' + hint.ProductionYear + '
'; } else if (hint.RunTimeTicks) { html += '
' + Dashboard.getDisplayTime(hint.RunTimeTicks) + '
'; } html += '
'; html += '
'; return html; } function renderSearchHintResult(page, hints) { var html = ''; for (var i = 0, length = hints.length; i < length; i++) { html += getSearchHintHtml(hints[i]); } $('#searchHints', page).html(html); } function getSearchPanel(page) { var panel = $('#searchPanel', page); if (!panel.length) { var html = ''; html += '
'; html += '

'; html += Globalize.translate('HeaderSearch'); html += '

'; html += ''; html += '
'; html += '
'; $(page).append(html); panel = $('#searchPanel', page).panel({}).trigger('create'); $('#txtSearch', panel).on("keyup", function (e) { // Down if (e.keyCode == 40) { var first = $('.searchHint', panel)[0]; if (first) { first.focus(); } return false; } }).on("keyup", function (e) { if (e.keyCode != 40) { var value = this.value; updateSearchHints(panel, value); } }); $('#searchHints', page).on("keydown", '.searchHint', function (e) { // Down if (e.keyCode == 40) { var next = $(this).next()[0]; if (next) { next.focus(); } return false; } // Up if (e.keyCode == 38) { var prev = $(this).prev()[0]; if (prev) { prev.focus(); } else { $('#txtSearch', page)[0].focus(); } return false; } }); } return panel; } function search() { var self = this; self.showSearchPanel = function (page) { var panel = getSearchPanel(page); $(panel).panel('toggle'); $('#txtSearch').focus(); }; } 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: "square", lazy: true, overlayText: false, showTitle: true, coverImage: true, centerImage: true, textLines: getAdditionalTextLines }); $('.itemsContainer', elem).html(html).lazyChildren(); } function requestSearchHintsForOverlay(elem, searchTerm) { var currentTimeout = searchHintTimeout; ApiClient.getSearchHints({ userId: Dashboard.getCurrentUserId(), searchTerm: searchTerm, limit: 30 }).done(function (result) { if (currentTimeout != searchHintTimeout) { return; } renderSearchResultsInOverlay(elem, result.SearchHints); }); } function updateSearchOverlay(elem, searchTerm) { if (!searchTerm) { $('.itemsContainer', elem).empty(); clearSearchHintTimeout(); return; } clearSearchHintTimeout(); searchHintTimeout = setTimeout(function () { requestSearchHintsForOverlay(elem, searchTerm); }, 100); } function getSearchOverlay(createIfNeeded) { var elem = $('.searchResultsOverlay'); if (createIfNeeded && !elem.length) { var html = '
'; html += '
'; elem = $(html).appendTo(document.body).hide().trigger('create'); elem.createCardMenus(); } return elem; } function onHeaderSearchChange(val) { if (val) { $('.btnCloseSearch').show(); updateSearchOverlay(getSearchOverlay(true).fadeIn('fast'), val); $(document.body).addClass('bodyWithPopupOpen'); } else { $('.btnCloseSearch').hide(); updateSearchOverlay(getSearchOverlay(false).fadeOut('fast'), val); $(document.body).removeClass('bodyWithPopupOpen'); } } function bindSearchEvents() { $('.headerSearchInput').on("keyup", function (e) { // Down key if (e.keyCode == 40) { //var first = $('.card', panel)[0]; //if (first) { // first.focus(); //} return false; } else { onHeaderSearchChange(this.value); } }).on("search", function (e) { if (!this.value) { onHeaderSearchChange(''); } }); $('.btnCloseSearch').on('click', closeSearchOverlay); $('.viewMenuSearchForm').on('submit', function () { return false; }); } function closeSearchOverlay() { $('.headerSearchInput').val(''); onHeaderSearchChange(''); } $(document).on('pagehide', ".libraryPage", function () { $('#txtSearch', this).val(''); $('#searchHints', this).empty(); }).on('pagecontainerbeforehide', closeSearchOverlay); $(document).on('headercreated', function () { bindSearchEvents(); }); })(jQuery, document, window, clearTimeout, setTimeout);