(function (window, document, $, devicePixelRatio) { var backStack = []; var addNextToBackStack = true; function renderHeader() { var html = '
'; if (AppInfo.enableBackButton) { html += ''; } html += ''; html += '
' + Globalize.translate('ButtonHome') + '
'; html += '
'; html += ''; html += ''; html += '
'; html += '
'; html += ''; html += ''; html += ''; html += '
'; html += '
'; html += ''; if (!showUserAtTop()) { html += ''; } if (!$.browser.mobile && !AppInfo.isNativeApp) { html += 'settings'; //html += ''; } html += '
'; html += '
'; $(document.body).append(html); $('.viewMenuBar').lazyChildren(); $(document).trigger('headercreated'); bindMenuEvents(); } function onBackClick() { if (Dashboard.exitOnBack()) { Dashboard.exit(); } else { addNextToBackStack = false; backStack.length = Math.max(0, backStack.length - 1); history.back(); } } function addUserToHeader(user) { var header = $('.viewMenuBar'); if (user.localUser) { $('.btnCast', header).visible(true); $('.headerSearchButton', header).visible(true); requirejs(['voice/voice'], function () { if (VoiceInputManager.isSupported()) { $('.headerVoiceButton', header).visible(true); } else { $('.headerVoiceButton', header).visible(false); } }); } else { $('.btnCast', header).visible(false); $('.headerVoiceButton', header).visible(false); $('.headerSearchButton', header).visible(false); } if (user.canManageServer) { $('.dashboardEntryHeaderButton', header).visible(true); } else { $('.dashboardEntryHeaderButton', header).visible(false); } var userButtonHtml = ''; if (user.name) { if (user.imageUrl && AppInfo.enableUserImage) { var userButtonHeight = 26; var url = user.imageUrl; if (user.supportsImageParams) { url += "&height=" + (userButtonHeight * Math.max(devicePixelRatio || 1, 2)); } userButtonHtml += '
'; } else { userButtonHtml += '
'; } $('.headerUserButton', header).html(userButtonHtml).lazyChildren(); } } function bindMenuEvents() { if (AppInfo.isTouchPreferred) { if ('ontouchend' in document) { $('.mainDrawerButton').on('touchend click', openMainDrawer); } else { $('.mainDrawerButton').on('click', openMainDrawer); } } else { $('.mainDrawerButton').createHoverTouch().on('hovertouch', openMainDrawer); } $('.headerBackButton').on('click', onBackClick); // Have to wait for document ready here because otherwise // we may see the jQM redirect back and forth problem $(initViewMenuBarHeadroom); } function initViewMenuBarHeadroom() { // grab an element var viewMenuBar = document.getElementsByClassName("viewMenuBar")[0]; initHeadRoom(viewMenuBar); } function updateViewMenuBarHeadroom(page, viewMenuBar) { if ($(page).hasClass('libraryPage')) { // Don't like this timeout at all but if headroom is activated during the page events it will jump and flicker on us setTimeout(reEnableHeadroom, 700); } else { viewMenuBar.addClass('headroomDisabled'); } } function reEnableHeadroom() { $('.headroomDisabled').removeClass('headroomDisabled'); } function getItemHref(item, context) { return LibraryBrowser.getHref(item, context); } var requiresDrawerRefresh = true; var requiresDashboardDrawerRefresh = true; var lastOpenTime = new Date().getTime(); function openMainDrawer() { var drawerPanel = $('.mainDrawerPanel')[0]; drawerPanel.openDrawer(); lastOpenTime = new Date().getTime(); } function onMainDrawerOpened() { if ($.browser.mobile) { $(document.body).addClass('bodyWithPopupOpen'); } var drawer = $('.mainDrawerPanel .mainDrawer'); ConnectionManager.user(window.ApiClient).done(function (user) { if (requiresDrawerRefresh) { ensureDrawerStructure(drawer); refreshUserInfoInDrawer(user, drawer); refreshLibraryInfoInDrawer(user, drawer); refreshBottomUserInfoInDrawer(user, drawer); $(document).trigger('libraryMenuCreated'); updateLibraryMenu(user.localUser); } if (requiresDrawerRefresh || requiresDashboardDrawerRefresh) { refreshDashboardInfoInDrawer($.mobile.activePage, user, drawer); requiresDashboardDrawerRefresh = false; } requiresDrawerRefresh = false; updateLibraryNavLinks($.mobile.activePage); }); } function onMainDrawerClosed() { $(document.body).removeClass('bodyWithPopupOpen'); } function closeMainDrawer() { var drawerPanel = $('.mainDrawerPanel')[0]; drawerPanel.closeDrawer(); } function ensureDrawerStructure(drawer) { if ($('.mainDrawerContent', drawer).length) { return; } var html = '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; $(drawer).html(html); } function refreshUserInfoInDrawer(user, drawer) { var html = ''; var userAtTop = showUserAtTop(); var homeHref = window.ApiClient ? 'index.html' : 'selectserver.html'; var hasUserImage = user.imageUrl && AppInfo.enableUserImage; if (userAtTop) { html += '
'; html += '
'; html += '
'; var imgWidth = 60; if (hasUserImage) { var url = user.imageUrl; if (user.supportsImageParams) { url += "&width=" + (imgWidth * Math.max(devicePixelRatio || 1, 2)); html += '
'; } } else { html += '
'; } html += '
'; html += user.name; html += '
'; html += '
'; html += '
'; html += '
'; html += '' + Globalize.translate('ButtonHome') + ''; } else { html += '
'; html += ''; html += '
'; html += Globalize.translate('ButtonHome'); html += '
'; } html += '' + Globalize.translate('ButtonRemote') + ''; $('.userheader', drawer).html(html).lazyChildren(); } function refreshLibraryInfoInDrawer(user, drawer) { var html = ''; html += '
'; html += '
'; html += '
'; $('.libraryDrawerContent', drawer).html(html); } function refreshDashboardInfoInDrawer(page, user, drawer) { var html = ''; html += '
'; html += Dashboard.getToolsMenuHtml(page); $('.dashboardDrawerContent', drawer).html(html); } function refreshBottomUserInfoInDrawer(user, drawer) { var html = ''; html += '
'; html += '
'; html += '
'; html += Globalize.translate('HeaderAdmin'); html += '
'; html += '' + Globalize.translate('ButtonManageServer') + ''; html += '' + Globalize.translate('ButtonMetadataManager') + ''; if (!$.browser.mobile && !AppInfo.isTouchPreferred) { html += '' + Globalize.translate('ButtonReports') + ''; } html += '
'; html += '
'; html += '
'; html += ''; html += Globalize.translate('ButtonInbox'); html += '
0
'; html += '
'; if (user.localUser && showUserAtTop()) { html += '' + Globalize.translate('ButtonSettings') + ''; } html += '' + Globalize.translate('ButtonSync') + ''; if (Dashboard.isConnectMode()) { html += '' + Globalize.translate('ButtonSelectServer') + ''; } if (showUserAtTop()) { html += '' + Globalize.translate('ButtonSignOut') + ''; } html += '
'; $('.userFooter', drawer).html(html); $('.lnkManageServer', drawer).on('click', onManageServerClicked); } function updateLibraryMenu(user) { if (!user) { $('.adminMenuOptions').visible(false); $('.lnkMySync').visible(false); $('.userMenuOptions').visible(false); return; } var userId = Dashboard.getCurrentUserId(); var apiClient = window.ApiClient; apiClient.getUserViews(userId).done(function (result) { var items = result.Items; var html = ''; html += '
'; html += Globalize.translate('HeaderMedia'); html += '
'; html += items.map(function (i) { var icon = 'folder'; var color = 'inherit'; var itemId = i.Id; if (i.CollectionType == "channels") { itemId = "channels"; } else if (i.CollectionType == "livetv") { itemId = "livetv"; } if (i.Type == 'Channel') { } if (i.CollectionType == "photos") { icon = 'photo-library'; color = "#009688"; } else if (i.CollectionType == "music" || i.CollectionType == "musicvideos") { icon = 'library-music'; color = '#FB8521'; } else if (i.CollectionType == "books") { icon = 'library-books'; color = "#1AA1E1"; } else if (i.CollectionType == "playlists") { icon = 'view-list'; color = "#795548"; } else if (i.CollectionType == "games") { icon = 'games'; color = "#F44336"; } else if (i.CollectionType == "movies") { icon = 'video-library'; color = '#CE5043'; } else if (i.CollectionType == "channels" || i.Type == 'Channel') { icon = 'videocam'; color = '#E91E63'; } else if (i.CollectionType == "tvshows") { icon = 'tv'; color = "#4CAF50"; } else if (i.CollectionType == "livetv") { icon = 'live-tv'; color = "#293AAE"; } return '' + i.Name + ''; }).join(''); var elem = $('.libraryMenuOptions').html(html); $('.sidebarLink', elem).off('click.updateText').on('click.updateText', function () { var section = $('.sectionName', this)[0]; var text = section ? section.innerHTML : this.innerHTML; $('.libraryMenuButtonText').html(text); }); }); if (user.Policy.IsAdministrator) { $('.adminMenuOptions').visible(true); } else { $('.adminMenuOptions').visible(false); } if (user.Policy.EnableSync) { $('.lnkMySync').visible(true); } else { $('.lnkMySync').visible(false); } } function showUserAtTop() { return $.browser.mobile || AppInfo.isNativeApp; } var requiresLibraryMenuRefresh = false; var requiresViewMenuRefresh = false; function onManageServerClicked() { closeMainDrawer(); requirejs(["scripts/registrationservices"], function () { RegistrationServices.validateFeature('manageserver').done(function () { Dashboard.navigate('dashboard.html'); }); }); } function setLibraryMenuText(text) { $('.libraryMenuButtonText').html('' + text + ''); } function getTopParentId() { return getParameterByName('topParentId') || null; } window.LibraryMenu = { getTopParentId: getTopParentId, setText: setLibraryMenuText, onLinkClicked: function (link) { // There doesn't seem to be a way to detect if the drawer is in the process of opening, so try to handle that here if ((new Date().getTime() - lastOpenTime) > 200) { closeMainDrawer(); setTimeout(function () { Dashboard.navigate(link.href); }, 300); } return false; } }; function updateCastIcon() { var info = MediaController.getPlayerInfo(); if (info.isLocalPlayer) { $('.btnCast').addClass('btnDefaultCast').removeClass('btnActiveCast'); $('.headerSelectedPlayer').html(''); } else { $('.btnCast').removeClass('btnDefaultCast').addClass('btnActiveCast'); $('.headerSelectedPlayer').html((info.deviceName || info.name)); } } function updateLibraryNavLinks(page) { page = $(page); var isLiveTvPage = page.hasClass('liveTvPage'); var isChannelsPage = page.hasClass('channelsPage'); var isEditorPage = page.hasClass('metadataEditorPage'); var isReportsPage = page.hasClass('reportsPage'); var isMySyncPage = page.hasClass('mySyncPage'); var id = isLiveTvPage || isChannelsPage || isEditorPage || isReportsPage || isMySyncPage || page.hasClass('allLibraryPage') ? '' : getTopParentId() || ''; $('.lnkMediaFolder').each(function () { var itemId = this.getAttribute('data-itemid'); if (isChannelsPage && itemId == 'channels') { $(this).addClass('selectedMediaFolder'); } else if (isLiveTvPage && itemId == 'livetv') { $(this).addClass('selectedMediaFolder'); } else if (isEditorPage && itemId == 'editor') { $(this).addClass('selectedMediaFolder'); } else if (isReportsPage && itemId == 'reports') { $(this).addClass('selectedMediaFolder'); } else if (isMySyncPage && itemId == 'mysync') { $(this).addClass('selectedMediaFolder'); } else if (id && itemId == id) { $(this).addClass('selectedMediaFolder'); } else { $(this).removeClass('selectedMediaFolder'); } }); var context = getParameterByName('context'); if (context !== 'playlists') { $('.scopedLibraryViewNav a', page).each(function () { var src = this.href; if (src.indexOf('#') != -1) { return; } src = replaceQueryString(src, 'topParentId', id); this.href = src; }); } } function updateContextText(page) { var jPage = $(page); var name = jPage.attr('data-contextname'); if (name) { $('.libraryMenuButtonText').html('' + name + ''); } else if (jPage.hasClass('allLibraryPage') || jPage.hasClass('type-interior')) { $('.libraryMenuButtonText').html(Globalize.translate('ButtonHome')); } } function onWebSocketMessage(e, data) { var msg = data; if (msg.MessageType === "UserConfigurationUpdated") { if (msg.Data.Id == Dashboard.getCurrentUserId()) { requiresLibraryMenuRefresh = true; } } } function buildViewMenuBar(page) { if ($(page).hasClass('standalonePage')) { $('.viewMenuBar').visible(false); return; } if (requiresViewMenuRefresh) { $('.viewMenuBar').remove(); } var viewMenuBar = $('.viewMenuBar').visible(true); if (!$('.viewMenuBar').length) { renderHeader(); updateViewMenuBarHeadroom(page, $('.viewMenuBar')); updateCastIcon(); updateLibraryNavLinks(page); updateContextText(page); requiresViewMenuRefresh = false; ConnectionManager.user(window.ApiClient).done(addUserToHeader); } else { updateContextText(page); updateLibraryNavLinks(page); updateViewMenuBarHeadroom(page, viewMenuBar); requiresViewMenuRefresh = false; } } // The first time we create the view menu bar, wait until doc ready + login validated // Otherwise we run into the jQM redirect back and forth problem var updateViewMenuBarBeforePageShow = false; $(document).on('pagebeforeshowready', ".page", function () { var page = this; requiresDashboardDrawerRefresh = true; if (updateViewMenuBarBeforePageShow) { onPageBeforeShowDocumentReady(page); } }).one('pageshowready', ".page", function () { var page = this; $(function () { onPageBeforeShowDocumentReady(page); updateViewMenuBarBeforePageShow = true; }); }).on('pageshowready', ".page", function () { var page = this; onPageShowDocumentReady(page); }).on('pagebeforehide', ".page", function () { if (addNextToBackStack) { var text = $('.libraryMenuButtonText').text() || document.title; backStack.push(text); } addNextToBackStack = true; $('.headroomEnabled').addClass('headroomDisabled'); }); function onPageBeforeShowDocumentReady(page) { buildViewMenuBar(page); var jpage = $(page); var isLibraryPage = jpage.hasClass('libraryPage'); var darkDrawer = false; if (isLibraryPage) { $(document.body).addClass('libraryDocument').removeClass('dashboardDocument').removeClass('hideMainDrawer'); if (AppInfo.enableBottomTabs) { $(page).addClass('noSecondaryNavPage'); $(function () { $('.footer').addClass('footerOverBottomTabs'); }); } else { $('.libraryViewNav', page).each(function () { initHeadRoom(this); }); } if (!$.browser.mobile) { darkDrawer = true; } } else if (jpage.hasClass('type-interior')) { $(document.body).addClass('dashboardDocument').removeClass('libraryDocument').removeClass('hideMainDrawer'); } else { $(document.body).removeClass('dashboardDocument').removeClass('libraryDocument').addClass('hideMainDrawer'); } if (darkDrawer) { $('.mainDrawerPanel #drawer').addClass('darkDrawer'); } else { $('.mainDrawerPanel #drawer').removeClass('darkDrawer'); } if (AppInfo.enableBackButton) { updateBackButton(page); } } function updateBackButton(page) { var jPage = $(page); var canGoBack = backStack.length > 0 && jPage.is('.itemDetailPage'); $('.headerBackButton').visible(canGoBack); jPage.off('swiperight', onPageSwipeLeft); if (canGoBack) { jPage.on('swiperight', onPageSwipeLeft); } } function onPageSwipeLeft(e) { var target = $(e.target); if (!target.is('.hiddenScrollX') && !target.parents('.hiddenScrollX').length) { history.back(); } } function onPageShowDocumentReady(page) { var elem = $('.libraryViewNav .ui-btn-active:visible', page); if (elem.length) { elem[0].scrollIntoView(); // Scroll back up so in case vertical scroll was messed with $(document).scrollTop(0); } } function initHeadRoom(elem) { if (!AppInfo.enableHeadRoom) { return; } requirejs(["thirdparty/headroom"], function () { // construct an instance of Headroom, passing the element var headroom = new Headroom(elem, { // or scroll tolerance per direction tolerance: { down: 40, up: 0 } }); // initialise headroom.init(); $(elem).addClass('headroomEnabled'); }); } function initializeApiClient(apiClient) { requiresLibraryMenuRefresh = true; $(apiClient).off('websocketmessage.librarymenu', onWebSocketMessage).on('websocketmessage.librarymenu', onWebSocketMessage); } Dashboard.ready(function () { if (window.ApiClient) { initializeApiClient(window.ApiClient); } $(ConnectionManager).on('apiclientcreated', function (e, apiClient) { initializeApiClient(apiClient); }).on('localusersignedin localusersignedout', function () { requiresLibraryMenuRefresh = true; requiresViewMenuRefresh = true; requiresDrawerRefresh = true; }); $(MediaController).on('playerchange', function () { updateCastIcon(); }); $('.mainDrawerPanel').on('paper-drawer-panel-open', onMainDrawerOpened).on('paper-drawer-panel-close', onMainDrawerClosed); }); })(window, document, jQuery, window.devicePixelRatio); $.fn.createHoverTouch = function () { var preventHover = false; var timerId; function startTimer(elem) { stopTimer(); timerId = setTimeout(function () { $(elem).trigger('hovertouch'); }, 300); } function stopTimer(elem) { if (timerId) { clearTimeout(timerId); timerId = null; } } return $(this).on('mouseenter', function () { if (preventHover === true) { preventHover = false; return; } startTimer(this); }).on('mouseleave', function () { stopTimer(this); }).on('touchstart', function () { preventHover = true; }).on('click', function () { preventHover = true; if (preventHover) { $(this).trigger('hovertouch'); stopTimer(this); preventHover = false; } }); };