define(['layoutManager', 'cardBuilder', 'datetime', 'mediaInfo', 'backdrop', 'listView', 'itemContextMenu', 'itemHelper', 'userdataButtons', 'dom', 'indicators', 'apphost', 'imageLoader', 'libraryMenu', 'shell', 'globalize', 'browser', 'events', 'scrollStyles', 'emby-itemscontainer', 'emby-checkbox'], function (layoutManager, cardBuilder, datetime, mediaInfo, backdrop, listView, itemContextMenu, itemHelper, userdataButtons, dom, indicators, appHost, imageLoader, libraryMenu, shell, globalize, browser, events) { 'use strict'; function getPromise(params) { var id = params.id; if (id) { return ApiClient.getItem(Dashboard.getCurrentUserId(), id); } var name = params.genre; if (name) { return ApiClient.getGenre(name, Dashboard.getCurrentUserId()); } name = params.musicgenre; if (name) { return ApiClient.getMusicGenre(name, Dashboard.getCurrentUserId()); } name = params.gamegenre; if (name) { return ApiClient.getGameGenre(name, Dashboard.getCurrentUserId()); } name = params.musicartist; if (name) { return ApiClient.getArtist(name, Dashboard.getCurrentUserId()); } else { throw new Error('Invalid request'); } } var currentItem; var currentRecordingFields; function reload(page, params) { Dashboard.showLoadingMsg(); getPromise(params).then(function (item) { reloadFromItem(page, params, item); }); } function hideAll(page, className, show) { var i, length; var elems = page.querySelectorAll('.' + className); for (i = 0, length = elems.length; i < length; i++) { if (show) { elems[i].classList.remove('hide'); } else { elems[i].classList.add('hide'); } } } function getContextMenuOptions(item, button) { var options = { item: item, open: false, play: false, queue: false, playAllFromHere: false, queueAllFromHere: false, positionTo: button, cancelTimer: false, record: false, editImages: false, deleteItem: item.IsFolder === true }; if (appHost.supports('sync')) { // Will be displayed via button options.syncLocal = false; } return options; } function renderSyncLocalContainer(page, params, user, item) { if (page.syncToggleInstance) { page.syncToggleInstance.refresh(item); return; } require(['syncToggle'], function (syncToggle) { page.syncToggleInstance = new syncToggle({ user: user, item: item, container: page.querySelector('.syncLocalContainer') }); events.on(page.syncToggleInstance, 'sync', function () { reload(page, params); }); }); } function reloadFromItem(page, params, item) { currentItem = item; var context = params.context; LibraryBrowser.renderName(item, page.querySelector('.itemName'), false, context); LibraryBrowser.renderParentName(item, page.querySelector('.parentName'), context); libraryMenu.setTitle(''); Dashboard.getCurrentUser().then(function (user) { window.scrollTo(0, 0); renderImage(page, item, user); renderLogo(page, item, ApiClient); setInitialCollapsibleState(page, item, context, user); renderDetails(page, item, context); if (dom.getWindowSize().innerWidth >= 800) { backdrop.setBackdrops([item], { blur: 20 }, false); } else { backdrop.clear(); } LibraryBrowser.renderDetailPageBackdrop(page, item, imageLoader); libraryMenu.setTransparentMenu(true); var canPlay = false; if (item.Type == 'Program') { var now = new Date(); if (now >= datetime.parseISO8601Date(item.StartDate, true) && now < datetime.parseISO8601Date(item.EndDate, true)) { hideAll(page, 'btnPlay', true); canPlay = true; } else { hideAll(page, 'btnPlay'); } } else if (MediaController.canPlay(item)) { hideAll(page, 'btnPlay', true); canPlay = true; } else { hideAll(page, 'btnPlay'); } var hasAnyButton = canPlay; if ((item.LocalTrailerCount || (item.RemoteTrailers && item.RemoteTrailers.length)) && item.PlayAccess == 'Full') { hideAll(page, 'btnPlayTrailer', true); hasAnyButton = true; } else { hideAll(page, 'btnPlayTrailer'); } if (item.CanDelete && !item.IsFolder) { hideAll(page, 'btnDeleteItem', true); hasAnyButton = true; } else { hideAll(page, 'btnDeleteItem'); } renderSyncLocalContainer(page, params, user, item); if (hasAnyButton || item.Type !== 'Program') { hideAll(page, 'mainDetailButtons', true); } else { hideAll(page, 'mainDetailButtons'); } showRecordingFields(page, item, user); var groupedVersions = (item.MediaSources || []).filter(function (g) { return g.Type == "Grouping"; }); if (user.Policy.IsAdministrator && groupedVersions.length) { page.querySelector('.splitVersionContainer').classList.remove('hide'); } else { page.querySelector('.splitVersionContainer').classList.add('hide'); } itemContextMenu.getCommands(getContextMenuOptions(item)).then(function (commands) { if (commands.length) { hideAll(page, 'btnMoreCommands', true); } else { hideAll(page, 'btnMoreCommands'); } }); var itemBirthday = page.querySelector('#itemBirthday'); if (item.Type == "Person" && item.PremiereDate) { try { var birthday = datetime.parseISO8601Date(item.PremiereDate, true).toDateString(); itemBirthday.classList.remove('hide'); itemBirthday.innerHTML = globalize.translate('BirthDateValue').replace('{0}', birthday); } catch (err) { itemBirthday.classList.add('hide'); } } else { itemBirthday.classList.add('hide'); } var itemDeathDate = page.querySelector('#itemDeathDate'); if (item.Type == "Person" && item.EndDate) { try { var deathday = datetime.parseISO8601Date(item.EndDate, true).toDateString(); itemDeathDate.classList.remove('hide'); itemDeathDate.innerHTML = globalize.translate('DeathDateValue').replace('{0}', deathday); } catch (err) { itemDeathDate.classList.add('hide'); } } else { } var itemBirthLocation = page.querySelector('#itemBirthLocation'); if (item.Type == "Person" && item.ProductionLocations && item.ProductionLocations.length) { var gmap = '' + item.ProductionLocations[0] + ''; itemBirthLocation.classList.remove('hide'); itemBirthLocation.innerHTML = globalize.translate('BirthPlaceValue').replace('{0}', gmap); } else { itemBirthLocation.classList.add('hide'); } }); setPeopleHeader(page, item); page.dispatchEvent(new CustomEvent("displayingitem", { detail: { item: item, context: context }, bubbles: true })); Dashboard.hideLoadingMsg(); } function logoImageUrl(item, apiClient, options) { options = options || {}; options.type = "Logo"; if (item.ImageTags && item.ImageTags.Logo) { options.tag = item.ImageTags.Logo; return apiClient.getScaledImageUrl(item.Id, options); } if (item.ParentLogoImageTag) { options.tag = item.ParentLogoImageTag; return apiClient.getScaledImageUrl(item.ParentLogoItemId, options); } return null; } function bounceIn(elem) { var keyframes = [ { transform: 'scale3d(.3, .3, .3)', opacity: '0', offset: 0 }, { transform: 'scale3d(1.1, 1.1, 1.1)', offset: 0.2 }, { transform: 'scale3d(.9, .9, .9)', offset: 0.4 }, { transform: 'scale3d(1.03, 1.03, 1.03)', opacity: '1', offset: 0.6 }, { transform: 'scale3d(.97, .97, .97)', offset: 0.8 }, { transform: 'scale3d(1, 1, 1)', opacity: '1', offset: 1 }]; var timing = { duration: 900, iterations: 1, easing: 'cubic-bezier(0.215, 0.610, 0.355, 1.000)' }; return elem.animate(keyframes, timing); } function renderLogo(page, item, apiClient) { var url = logoImageUrl(item, apiClient, { maxWidth: 300 }); var detailLogo = page.querySelector('.detailLogo'); if (url) { detailLogo.classList.remove('hide'); detailLogo.classList.add('lazy'); detailLogo.setAttribute('data-src', url); imageLoader.lazyImage(detailLogo); //if (detailLogo.animate) { // setTimeout(function() { // bounceIn(detailLogo); // }, 100); //} } else { detailLogo.classList.add('hide'); } } function showRecordingFields(page, item, user) { if (currentRecordingFields) { return; } var recordingFieldsElement = page.querySelector('.recordingFields'); if (item.Type == 'Program' && user.Policy.EnableLiveTvManagement) { require(['recordingFields'], function (recordingFields) { currentRecordingFields = new recordingFields({ parent: recordingFieldsElement, programId: item.Id, serverId: item.ServerId }); recordingFieldsElement.classList.remove('hide'); }); } else { recordingFieldsElement.classList.add('hide'); recordingFieldsElement.innerHTML = ''; } } function renderLinks(linksElem, item) { var links = []; if (item.HomePageUrl) { links.push('' + globalize.translate('ButtonWebsite') + ''); } if (item.ExternalUrls) { for (var i = 0, length = item.ExternalUrls.length; i < length; i++) { var url = item.ExternalUrls[i]; links.push('' + url.Name + ''); } } if (links.length) { var html = links.join('•'); linksElem.innerHTML = html; linksElem.classList.remove('hide'); } else { linksElem.classList.add('hide'); } } function shadeBlendConvert(p, from, to) { if (typeof (p) != "number" || p < -1 || p > 1 || typeof (from) != "string" || (from[0] != 'r' && from[0] != '#') || (typeof (to) != "string" && typeof (to) != "undefined")) return null; //ErrorCheck var sbcRip = function (d) { var l = d.length, RGB = new Object(); if (l > 9) { d = d.split(","); if (d.length < 3 || d.length > 4) return null; //ErrorCheck RGB[0] = i(d[0].slice(4)), RGB[1] = i(d[1]), RGB[2] = i(d[2]), RGB[3] = d[3] ? parseFloat(d[3]) : -1; } else { if (l == 8 || l == 6 || l < 4) return null; //ErrorCheck if (l < 6) d = "#" + d[1] + d[1] + d[2] + d[2] + d[3] + d[3] + (l > 4 ? d[4] + "" + d[4] : ""); //3 digit d = i(d.slice(1), 16), RGB[0] = d >> 16 & 255, RGB[1] = d >> 8 & 255, RGB[2] = d & 255, RGB[3] = l == 9 || l == 5 ? r(((d >> 24 & 255) / 255) * 10000) / 10000 : -1; } return RGB; }; var i = parseInt, r = Math.round, h = from.length > 9, h = typeof (to) == "string" ? to.length > 9 ? true : to == "c" ? !h : false : h, b = p < 0, p = b ? p * -1 : p, to = to && to != "c" ? to : b ? "#000000" : "#FFFFFF", f = sbcRip(from), t = sbcRip(to); if (!f || !t) return null; //ErrorCheck if (h) return "rgb(" + r((t[0] - f[0]) * p + f[0]) + "," + r((t[1] - f[1]) * p + f[1]) + "," + r((t[2] - f[2]) * p + f[2]) + (f[3] < 0 && t[3] < 0 ? ")" : "," + (f[3] > -1 && t[3] > -1 ? r(((t[3] - f[3]) * p + f[3]) * 10000) / 10000 : t[3] < 0 ? f[3] : t[3]) + ")"); else return "#" + (0x100000000 + (f[3] > -1 && t[3] > -1 ? r(((t[3] - f[3]) * p + f[3]) * 255) : t[3] > -1 ? r(t[3] * 255) : f[3] > -1 ? r(f[3] * 255) : 255) * 0x1000000 + r((t[0] - f[0]) * p + f[0]) * 0x10000 + r((t[1] - f[1]) * p + f[1]) * 0x100 + r((t[2] - f[2]) * p + f[2])).toString(16).slice(f[3] > -1 || t[3] > -1 ? 1 : 3); } function loadSwatch(page, item) { var imageTags = item.ImageTags || {}; if (item.PrimaryImageTag) { imageTags.Primary = item.PrimaryImageTag; } var url; var imageHeight = 300; if (item.SeriesId && item.SeriesPrimaryImageTag) { url = ApiClient.getScaledImageUrl(item.SeriesId, { type: "Primary", maxHeight: imageHeight, tag: item.SeriesPrimaryImageTag }); } else if (imageTags.Primary) { url = ApiClient.getScaledImageUrl(item.Id, { type: "Primary", maxHeight: imageHeight, tag: item.ImageTags.Primary }); } if (!url) { return; } var img = new Image(); img.onload = function () { imageLoader.getVibrantInfoFromElement(img, url).then(function (vibrantInfo) { vibrantInfo = vibrantInfo.split('|'); var detailPageContent = page.querySelector('.detailPageContent'); var detailPagePrimaryContainer = page.querySelector('.detailPagePrimaryContainer'); detailPageContent.style.color = vibrantInfo[1]; detailPagePrimaryContainer.style.backgroundColor = vibrantInfo[0]; }); }; img.src = url; } function renderImage(page, item, user) { var container = page.querySelector('.detailImageContainer'); LibraryBrowser.renderDetailImage(container, item, user.Policy.IsAdministrator && item.MediaType != 'Photo', null, imageLoader, indicators); //loadSwatch(page, item); } function refreshDetailImageUserData(elem, item) { var detailImageProgressContainer = elem.querySelector('.detailImageProgressContainer'); detailImageProgressContainer.innerHTML = indicators.getProgressBarHtml(item); } function refreshImage(page, item, user) { refreshDetailImageUserData(page.querySelector('.detailImageContainer'), item); } function setPeopleHeader(page, item) { if (item.MediaType == "Audio" || item.Type == "MusicAlbum" || item.MediaType == "Book" || item.MediaType == "Photo") { page.querySelector('#peopleHeader').innerHTML = globalize.translate('HeaderPeople'); } else { page.querySelector('#peopleHeader').innerHTML = globalize.translate('HeaderCastAndCrew'); } } function renderNextUp(page, item, user) { var section = page.querySelector('.nextUpSection'); if (item.Type != 'Series') { section.classList.add('hide'); return; } ApiClient.getNextUpEpisodes({ SeriesId: item.Id, UserId: user.Id }).then(function (result) { if (result.Items.length) { section.classList.remove('hide'); } else { section.classList.add('hide'); } var html = cardBuilder.getCardsHtml({ items: result.Items, shape: getThumbShape(false), showTitle: true, displayAsSpecial: item.Type == "Season" && item.IndexNumber, overlayText: true, lazy: true, overlayPlayButton: true }); var itemsContainer = section.querySelector('.nextUpItems'); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); }); } function setInitialCollapsibleState(page, item, context, user) { page.querySelector('.collectionItems').innerHTML = ''; if (item.Type == 'TvChannel') { page.querySelector('#childrenCollapsible').classList.remove('hide'); renderChannelGuide(page, item, user); } else if (item.Type == 'Playlist') { page.querySelector('#childrenCollapsible').classList.remove('hide'); renderPlaylistItems(page, item, user); } else if (item.Type == 'Studio' || item.Type == 'Person' || item.Type == 'Genre' || item.Type == 'MusicGenre' || item.Type == 'GameGenre' || item.Type == 'MusicArtist') { page.querySelector('#childrenCollapsible').classList.remove('hide'); renderItemsByName(page, item, user); } else if (item.IsFolder || item.Type == 'Episode') { if (item.Type == "BoxSet") { page.querySelector('#childrenCollapsible').classList.add('hide'); } renderChildren(page, item); } else { page.querySelector('#childrenCollapsible').classList.add('hide'); } if (item.Type == 'Series') { renderSeriesSchedule(page, item, user); } if (item.Type == 'Series') { renderNextUp(page, item, user); } else { page.querySelector('.nextUpSection').classList.add('hide'); } if (item.MediaSources && item.MediaSources.length) { renderMediaSources(page, user, item); } renderScenes(page, item); if (!item.SpecialFeatureCount || item.SpecialFeatureCount == 0 || item.Type == "Series") { page.querySelector('#specialsCollapsible').classList.add('hide'); } else { page.querySelector('#specialsCollapsible').classList.remove('hide'); renderSpecials(page, item, user, 6); } if (!item.People || !item.People.length) { page.querySelector('#castCollapsible').classList.add('hide'); } else { page.querySelector('#castCollapsible').classList.remove('hide'); renderCast(page, item, context, enableScrollX() ? null : 12); } if (item.PartCount && item.PartCount > 1) { page.querySelector('#additionalPartsCollapsible').classList.remove('hide'); renderAdditionalParts(page, item, user); } else { page.querySelector('#additionalPartsCollapsible').classList.add('hide'); } page.querySelector('#themeSongsCollapsible').classList.add('hide'); page.querySelector('#themeVideosCollapsible').classList.add('hide'); if (item.Type == "MusicAlbum") { renderMusicVideos(page, item, user); } else { page.querySelector('#musicVideosCollapsible').classList.add('hide'); } renderThemeMedia(page, item, user); if (enableScrollX()) { renderCriticReviews(page, item); } else { renderCriticReviews(page, item, 1); } } function renderOverview(elems, item) { for (var i = 0, length = elems.length; i < length; i++) { var elem = elems[i]; var overview = item.Overview || ''; if (overview) { elem.innerHTML = overview; elem.classList.remove('hide'); var anchors = elem.querySelectorAll('a'); for (var j = 0, length2 = anchors.length; j < length2; j++) { anchors[j].setAttribute("target", "_blank"); } } else { elem.innerHTML = ''; elem.classList.add('hide'); } } } function renderDetails(page, item, context, isStatic) { renderSimilarItems(page, item, context); renderMoreFromItems(page, item); var taglineElement = page.querySelector('.tagline'); if (item.Taglines && item.Taglines.length) { taglineElement.classList.remove('hide'); taglineElement.innerHTML = item.Taglines[0]; } else { taglineElement.classList.add('hide'); } var overview = page.querySelector('.overview'); var externalLinksElem = page.querySelector('.itemExternalLinks'); if (item.Type === 'Season' || item.Type === 'MusicAlbum' || item.Type === 'MusicArtist') { overview.classList.add('detailsHiddenOnMobile'); externalLinksElem.classList.add('detailsHiddenOnMobile'); } renderOverview([overview], item); renderAwardSummary(page.querySelector('#awardSummary'), item); var i, length; var itemMiscInfo = page.querySelectorAll('.itemMiscInfo-primary'); for (i = 0, length = itemMiscInfo.length; i < length; i++) { mediaInfo.fillPrimaryMediaInfo(itemMiscInfo[i], item, { interactive: true, episodeTitle: false }); if (itemMiscInfo[i].innerHTML) { itemMiscInfo[i].classList.remove('hide'); } else { itemMiscInfo[i].classList.add('hide'); } } itemMiscInfo = page.querySelectorAll('.itemMiscInfo-secondary'); for (i = 0, length = itemMiscInfo.length; i < length; i++) { mediaInfo.fillSecondaryMediaInfo(itemMiscInfo[i], item, { interactive: true }); if (itemMiscInfo[i].innerHTML) { itemMiscInfo[i].classList.remove('hide'); } else { itemMiscInfo[i].classList.add('hide'); } } var itemGenres = page.querySelectorAll('.itemGenres'); for (i = 0, length = itemGenres.length; i < length; i++) { renderGenres(itemGenres[i], item, null, isStatic); } renderStudios(page.querySelector('.itemStudios'), item, isStatic); renderUserDataIcons(page, item); renderLinks(externalLinksElem, item); page.querySelector('.criticRatingScore').innerHTML = (item.CriticRating || '0') + '%'; if (item.CriticRatingSummary) { page.querySelector('#criticRatingSummary').classList.remove('hide'); page.querySelector('.criticRatingSummaryText').innerHTML = item.CriticRatingSummary; } else { page.querySelector('#criticRatingSummary').classList.add('hide'); } renderTags(page, item); renderSeriesAirTime(page, item, isStatic); if (renderDynamicMediaIcons(page, item)) { page.querySelector('.mediaInfoIcons').classList.remove('hide'); } else { page.querySelector('.mediaInfoIcons').classList.add('hide'); } var artist = page.querySelectorAll('.artist'); for (i = 0, length = artist.length; i < length; i++) { if (item.ArtistItems && item.ArtistItems.length && item.Type != "MusicAlbum") { artist[i].classList.remove('hide'); artist[i].innerHTML = getArtistLinksHtml(item.ArtistItems, context); } else { artist[i].classList.add('hide'); } } if (item.MediaSources && item.MediaSources.length && item.Path) { page.querySelector('.audioVideoMediaInfo').classList.remove('hide'); } else { page.querySelector('.audioVideoMediaInfo').classList.add('hide'); } if (item.MediaType == 'Photo') { page.querySelector('.photoInfo').classList.remove('hide'); renderPhotoInfo(page, item); } else { page.querySelector('.photoInfo').classList.add('hide'); } } function renderDynamicMediaIcons(view, item) { var html = mediaInfo.getMediaInfoStats(item).map(function (mediaInfoItem) { var text = mediaInfoItem.text; if (mediaInfoItem.type === 'added') { return '