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:
parent
09513af31b
commit
4678528d00
657 changed files with 422 additions and 0 deletions
517
src/bower_components/emby-webcomponents/guide/guide.js
vendored
Normal file
517
src/bower_components/emby-webcomponents/guide/guide.js
vendored
Normal file
|
@ -0,0 +1,517 @@
|
|||
define(["require", "inputManager", "browser", "globalize", "connectionManager", "scrollHelper", "serverNotifications", "loading", "datetime", "focusManager", "playbackManager", "userSettings", "imageLoader", "events", "layoutManager", "itemShortcuts", "dom", "css!./guide.css", "programStyles", "material-icons", "scrollStyles", "emby-button", "paper-icon-button-light", "emby-tabs", "emby-scroller", "flexStyles", "registerElement"], function(require, inputManager, browser, globalize, connectionManager, scrollHelper, serverNotifications, loading, datetime, focusManager, playbackManager, userSettings, imageLoader, events, layoutManager, itemShortcuts, dom) {
|
||||
"use strict";
|
||||
|
||||
function showViewSettings(instance) {
|
||||
require(["guide-settings-dialog"], function(guideSettingsDialog) {
|
||||
guideSettingsDialog.show(instance.categoryOptions).then(function() {
|
||||
instance.refresh()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function updateProgramCellOnScroll(cell, scrollPct) {
|
||||
var left = cell.posLeft;
|
||||
left || (left = parseFloat(cell.style.left.replace("%", "")), cell.posLeft = left);
|
||||
var width = cell.posWidth;
|
||||
width || (width = parseFloat(cell.style.width.replace("%", "")), cell.posWidth = width);
|
||||
var right = left + width,
|
||||
newPct = Math.max(Math.min(scrollPct, right), left),
|
||||
offset = newPct - left,
|
||||
pctOfWidth = offset / width * 100,
|
||||
guideProgramName = cell.guideProgramName;
|
||||
guideProgramName || (guideProgramName = cell.querySelector(".guideProgramName"), cell.guideProgramName = guideProgramName);
|
||||
var caret = cell.caret;
|
||||
caret || (caret = cell.querySelector(".guide-programNameCaret"), cell.caret = caret), guideProgramName && (pctOfWidth > 0 && pctOfWidth <= 100 ? (guideProgramName.style.transform = "translateX(" + pctOfWidth + "%)", caret.classList.remove("hide")) : (guideProgramName.style.transform = "none", caret.classList.add("hide")))
|
||||
}
|
||||
|
||||
function updateProgramCellsOnScroll(programGrid, programCells) {
|
||||
isUpdatingProgramCellScroll || (isUpdatingProgramCellScroll = !0, requestAnimationFrame(function() {
|
||||
for (var scrollLeft = programGrid.scrollLeft, scrollPct = scrollLeft ? scrollLeft / programGrid.scrollWidth * 100 : 0, i = 0, length = programCells.length; i < length; i++) updateProgramCellOnScroll(programCells[i], scrollPct);
|
||||
isUpdatingProgramCellScroll = !1
|
||||
}))
|
||||
}
|
||||
|
||||
function onProgramGridClick(e) {
|
||||
if (layoutManager.tv) {
|
||||
var programCell = dom.parentWithClass(e.target, "programCell");
|
||||
if (programCell) {
|
||||
var startDate = programCell.getAttribute("data-startdate"),
|
||||
endDate = programCell.getAttribute("data-enddate");
|
||||
startDate = datetime.parseISO8601Date(startDate, {
|
||||
toLocal: !0
|
||||
}).getTime(), endDate = datetime.parseISO8601Date(endDate, {
|
||||
toLocal: !0
|
||||
}).getTime();
|
||||
var now = (new Date).getTime();
|
||||
if (now >= startDate && now < endDate) {
|
||||
var channelId = programCell.getAttribute("data-channelid"),
|
||||
serverId = programCell.getAttribute("data-serverid");
|
||||
e.preventDefault(), e.stopPropagation(), playbackManager.play({
|
||||
ids: [channelId],
|
||||
serverId: serverId
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Guide(options) {
|
||||
function restartAutoRefresh() {
|
||||
stopAutoRefresh();
|
||||
autoRefreshInterval = setInterval(function() {
|
||||
self.refresh()
|
||||
}, 9e5)
|
||||
}
|
||||
|
||||
function stopAutoRefresh() {
|
||||
autoRefreshInterval && (clearInterval(autoRefreshInterval), autoRefreshInterval = null)
|
||||
}
|
||||
|
||||
function normalizeDateToTimeslot(date) {
|
||||
return date.getMinutes() - cellCurationMinutes >= 0 ? date.setHours(date.getHours(), cellCurationMinutes, 0, 0) : date.setHours(date.getHours(), 0, 0, 0), date
|
||||
}
|
||||
|
||||
function showLoading() {
|
||||
loading.show()
|
||||
}
|
||||
|
||||
function hideLoading() {
|
||||
loading.hide()
|
||||
}
|
||||
|
||||
function reloadGuide(context, newStartDate, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender) {
|
||||
var apiClient = connectionManager.getApiClient(options.serverId),
|
||||
channelQuery = {
|
||||
StartIndex: 0,
|
||||
EnableFavoriteSorting: "false" !== userSettings.get("livetv-favoritechannelsattop")
|
||||
};
|
||||
channelQuery.UserId = apiClient.getCurrentUserId();
|
||||
currentChannelLimit = 500, showLoading(), channelQuery.StartIndex = currentStartIndex, channelQuery.Limit = 500, channelQuery.AddCurrentProgram = !1, channelQuery.EnableUserData = !1, channelQuery.EnableImageTypes = "Primary";
|
||||
var categories = self.categoryOptions.categories || [],
|
||||
displayMovieContent = !categories.length || -1 !== categories.indexOf("movies"),
|
||||
displaySportsContent = !categories.length || -1 !== categories.indexOf("sports"),
|
||||
displayNewsContent = !categories.length || -1 !== categories.indexOf("news"),
|
||||
displayKidsContent = !categories.length || -1 !== categories.indexOf("kids"),
|
||||
displaySeriesContent = !categories.length || -1 !== categories.indexOf("series");
|
||||
displayMovieContent && displaySportsContent && displayNewsContent && displayKidsContent ? (channelQuery.IsMovie = null, channelQuery.IsSports = null, channelQuery.IsKids = null, channelQuery.IsNews = null, channelQuery.IsSeries = null) : (displayNewsContent && (channelQuery.IsNews = !0), displaySportsContent && (channelQuery.IsSports = !0), displayKidsContent && (channelQuery.IsKids = !0), displayMovieContent && (channelQuery.IsMovie = !0), displaySeriesContent && (channelQuery.IsSeries = !0)), "DatePlayed" === userSettings.get("livetv-channelorder") ? (channelQuery.SortBy = "DatePlayed", channelQuery.SortOrder = "Descending") : (channelQuery.SortBy = null, channelQuery.SortOrder = null);
|
||||
var date = newStartDate;
|
||||
date = new Date(date.getTime() + 1e3);
|
||||
var nextDay = new Date(date.getTime() + msPerDay - 2e3),
|
||||
allowIndicators = dom.getWindowSize().innerWidth >= 600,
|
||||
renderOptions = {
|
||||
showHdIcon: allowIndicators && "true" === userSettings.get("guide-indicator-hd"),
|
||||
showLiveIndicator: allowIndicators && "false" !== userSettings.get("guide-indicator-live"),
|
||||
showPremiereIndicator: allowIndicators && "false" !== userSettings.get("guide-indicator-premiere"),
|
||||
showNewIndicator: allowIndicators && "false" !== userSettings.get("guide-indicator-new"),
|
||||
showRepeatIndicator: allowIndicators && "true" === userSettings.get("guide-indicator-repeat"),
|
||||
showEpisodeTitle: !layoutManager.tv
|
||||
};
|
||||
apiClient.getLiveTvChannels(channelQuery).then(function(channelsResult) {
|
||||
var btnPreviousPage = context.querySelector(".btnPreviousPage"),
|
||||
btnNextPage = context.querySelector(".btnNextPage");
|
||||
channelsResult.TotalRecordCount > 500 ? (context.querySelector(".guideOptions").classList.remove("hide"), btnPreviousPage.classList.remove("hide"), btnNextPage.classList.remove("hide"), channelQuery.StartIndex ? context.querySelector(".btnPreviousPage").disabled = !1 : context.querySelector(".btnPreviousPage").disabled = !0, channelQuery.StartIndex + 500 < channelsResult.TotalRecordCount ? btnNextPage.disabled = !1 : btnNextPage.disabled = !0) : context.querySelector(".guideOptions").classList.add("hide");
|
||||
var programFields = [],
|
||||
programQuery = {
|
||||
UserId: apiClient.getCurrentUserId(),
|
||||
MaxStartDate: nextDay.toISOString(),
|
||||
MinEndDate: date.toISOString(),
|
||||
channelIds: channelsResult.Items.map(function(c) {
|
||||
return c.Id
|
||||
}).join(","),
|
||||
ImageTypeLimit: 1,
|
||||
EnableImages: !1,
|
||||
SortBy: "StartDate",
|
||||
EnableTotalRecordCount: !1,
|
||||
EnableUserData: !1
|
||||
};
|
||||
renderOptions.showHdIcon && programFields.push("IsHD"), programFields.length && (programQuery.Fields = programFields.join("")), apiClient.getLiveTvPrograms(programQuery).then(function(programsResult) {
|
||||
renderGuide(context, date, channelsResult.Items, programsResult.Items, renderOptions, apiClient, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender), hideLoading()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getDisplayTime(date) {
|
||||
if ("string" === (typeof date).toString().toLowerCase()) try {
|
||||
date = datetime.parseISO8601Date(date, {
|
||||
toLocal: !0
|
||||
})
|
||||
} catch (err) {
|
||||
return date
|
||||
}
|
||||
return datetime.getDisplayTime(date).toLowerCase()
|
||||
}
|
||||
|
||||
function getTimeslotHeadersHtml(startDate, endDateTime) {
|
||||
var html = "";
|
||||
for (startDate = new Date(startDate.getTime()), html += '<div class="timeslotHeadersInner">'; startDate.getTime() < endDateTime;) html += '<div class="timeslotHeader">', html += getDisplayTime(startDate), html += "</div>", startDate.setTime(startDate.getTime() + cellDurationMs);
|
||||
return html
|
||||
}
|
||||
|
||||
function parseDates(program) {
|
||||
if (!program.StartDateLocal) try {
|
||||
program.StartDateLocal = datetime.parseISO8601Date(program.StartDate, {
|
||||
toLocal: !0
|
||||
})
|
||||
} catch (err) {}
|
||||
if (!program.EndDateLocal) try {
|
||||
program.EndDateLocal = datetime.parseISO8601Date(program.EndDate, {
|
||||
toLocal: !0
|
||||
})
|
||||
} catch (err) {}
|
||||
return null
|
||||
}
|
||||
|
||||
function getTimerIndicator(item) {
|
||||
var status;
|
||||
if ("SeriesTimer" === item.Type) return '<i class="md-icon programIcon seriesTimerIcon"></i>';
|
||||
if (item.TimerId || item.SeriesTimerId) status = item.Status || "Cancelled";
|
||||
else {
|
||||
if ("Timer" !== item.Type) return "";
|
||||
status = item.Status
|
||||
}
|
||||
return item.SeriesTimerId ? "Cancelled" !== status ? '<i class="md-icon programIcon seriesTimerIcon"></i>' : '<i class="md-icon programIcon seriesTimerIcon seriesTimerIcon-inactive"></i>' : '<i class="md-icon programIcon timerIcon"></i>'
|
||||
}
|
||||
|
||||
function getChannelProgramsHtml(context, date, channel, programs, options, listInfo) {
|
||||
var html = "",
|
||||
startMs = date.getTime(),
|
||||
endMs = startMs + msPerDay - 1;
|
||||
html += '<div class="' + (layoutManager.tv ? "channelPrograms channelPrograms-tv" : "channelPrograms") + '" data-channelid="' + channel.Id + '">';
|
||||
for (var programsFound, clickAction = layoutManager.tv ? "link" : "programdialog", categories = self.categoryOptions.categories || [], displayMovieContent = !categories.length || -1 !== categories.indexOf("movies"), displaySportsContent = !categories.length || -1 !== categories.indexOf("sports"), displayNewsContent = !categories.length || -1 !== categories.indexOf("news"), displayKidsContent = !categories.length || -1 !== categories.indexOf("kids"), displaySeriesContent = !categories.length || -1 !== categories.indexOf("series"), enableColorCodedBackgrounds = "true" === userSettings.get("guide-colorcodedbackgrounds"), now = (new Date).getTime(), i = listInfo.startIndex, length = programs.length; i < length; i++) {
|
||||
var program = programs[i];
|
||||
if (program.ChannelId === channel.Id) {
|
||||
programsFound = !0, listInfo.startIndex++, parseDates(program);
|
||||
var startDateLocalMs = program.StartDateLocal.getTime(),
|
||||
endDateLocalMs = program.EndDateLocal.getTime();
|
||||
if (!(endDateLocalMs < startMs)) {
|
||||
if (startDateLocalMs > endMs) break;
|
||||
items[program.Id] = program;
|
||||
var renderStartMs = Math.max(startDateLocalMs, startMs),
|
||||
startPercent = (startDateLocalMs - startMs) / msPerDay;
|
||||
startPercent *= 100, startPercent = Math.max(startPercent, 0);
|
||||
var renderEndMs = Math.min(endDateLocalMs, endMs),
|
||||
endPercent = (renderEndMs - renderStartMs) / msPerDay;
|
||||
endPercent *= 100;
|
||||
var cssClass = "programCell itemAction",
|
||||
accentCssClass = null,
|
||||
displayInnerContent = !0;
|
||||
program.IsKids ? (displayInnerContent = displayKidsContent, accentCssClass = "kids") : program.IsSports ? (displayInnerContent = displaySportsContent, accentCssClass = "sports") : program.IsNews ? (displayInnerContent = displayNewsContent, accentCssClass = "news") : program.IsMovie ? (displayInnerContent = displayMovieContent, accentCssClass = "movie") : displayInnerContent = program.IsSeries ? displaySeriesContent : displayMovieContent && displayNewsContent && displaySportsContent && displayKidsContent && displaySeriesContent, displayInnerContent && enableColorCodedBackgrounds && accentCssClass && (cssClass += " programCell-" + accentCssClass), now >= startDateLocalMs && now < endDateLocalMs && (cssClass += " programCell-active");
|
||||
var timerAttributes = "";
|
||||
program.TimerId && (timerAttributes += ' data-timerid="' + program.TimerId + '"'), program.SeriesTimerId && (timerAttributes += ' data-seriestimerid="' + program.SeriesTimerId + '"');
|
||||
if (html += "<button" + (endPercent >= 2 ? ' is="emby-programcell"' : "") + ' data-action="' + clickAction + '"' + timerAttributes + ' data-channelid="' + program.ChannelId + '" data-id="' + program.Id + '" data-serverid="' + program.ServerId + '" data-startdate="' + program.StartDate + '" data-enddate="' + program.EndDate + '" data-type="' + program.Type + '" class="' + cssClass + '" style="left:' + startPercent + "%;width:" + endPercent + '%;">', displayInnerContent) {
|
||||
html += '<div class="guideProgramName">', html += '<div class="guide-programNameCaret hide"><i class="guideProgramNameCaretIcon md-icon"></i></div>', html += '<div class="guideProgramNameText">' + program.Name;
|
||||
var indicatorHtml = null;
|
||||
program.IsLive && options.showLiveIndicator ? indicatorHtml = '<span class="liveTvProgram guideProgramIndicator">' + globalize.translate("sharedcomponents#Live") + "</span>" : program.IsPremiere && options.showPremiereIndicator ? indicatorHtml = '<span class="premiereTvProgram guideProgramIndicator">' + globalize.translate("sharedcomponents#Premiere") + "</span>" : program.IsSeries && !program.IsRepeat && options.showNewIndicator ? indicatorHtml = '<span class="newTvProgram guideProgramIndicator">' + globalize.translate("sharedcomponents#AttributeNew") + "</span>" : program.IsSeries && program.IsRepeat && options.showRepeatIndicator && (indicatorHtml = '<span class="repeatTvProgram guideProgramIndicator">' + globalize.translate("sharedcomponents#Repeat") + "</span>"), html += indicatorHtml || "", program.EpisodeTitle && options.showEpisodeTitle && (html += '<div class="guideProgramSecondaryInfo">', program.EpisodeTitle && options.showEpisodeTitle && (html += '<span class="programSecondaryTitle">' + program.EpisodeTitle + "</span>"), html += "</div>"), html += "</div>", program.IsHD && options.showHdIcon && (layoutManager.tv ? html += '<div class="programIcon guide-programTextIcon guide-programTextIcon-tv">HD</div>' : html += '<div class="programIcon guide-programTextIcon">HD</div>'), html += getTimerIndicator(program), html += "</div>"
|
||||
}
|
||||
html += "</button>"
|
||||
}
|
||||
} else if (programsFound) break
|
||||
}
|
||||
return html += "</div>"
|
||||
}
|
||||
|
||||
function renderChannelHeaders(context, channels, apiClient) {
|
||||
for (var html = "", i = 0, length = channels.length; i < length; i++) {
|
||||
var channel = channels[i],
|
||||
hasChannelImage = channel.ImageTags.Primary,
|
||||
cssClass = "guide-channelHeaderCell itemAction";
|
||||
layoutManager.tv && (cssClass += " guide-channelHeaderCell-tv");
|
||||
var title = [];
|
||||
if (channel.ChannelNumber && title.push(channel.ChannelNumber), channel.Name && title.push(channel.Name), html += '<button title="' + title.join(" ") + '" type="button" class="' + cssClass + '" data-action="link" data-isfolder="' + channel.IsFolder + '" data-id="' + channel.Id + '" data-serverid="' + channel.ServerId + '" data-type="' + channel.Type + '">', hasChannelImage) {
|
||||
html += '<div class="guideChannelImage lazy" data-src="' + apiClient.getScaledImageUrl(channel.Id, {
|
||||
maxHeight: 220,
|
||||
tag: channel.ImageTags.Primary,
|
||||
type: "Primary"
|
||||
}) + '"></div>'
|
||||
}
|
||||
channel.ChannelNumber && (html += '<h3 class="guideChannelNumber">' + channel.ChannelNumber + "</h3>"), !hasChannelImage && channel.Name && (html += '<div class="guideChannelName">' + channel.Name + "</div>"), html += "</button>"
|
||||
}
|
||||
var channelList = context.querySelector(".channelsContainer");
|
||||
channelList.innerHTML = html, imageLoader.lazyChildren(channelList)
|
||||
}
|
||||
|
||||
function renderPrograms(context, date, channels, programs, options) {
|
||||
for (var listInfo = {
|
||||
startIndex: 0
|
||||
}, html = [], i = 0, length = channels.length; i < length; i++) html.push(getChannelProgramsHtml(context, date, channels[i], programs, options, listInfo));
|
||||
programGrid.innerHTML = html.join(""), programCells = programGrid.querySelectorAll("[is=emby-programcell]"), updateProgramCellsOnScroll(programGrid, programCells)
|
||||
}
|
||||
|
||||
function getProgramSortOrder(program, channels) {
|
||||
for (var channelId = program.ChannelId, channelIndex = -1, i = 0, length = channels.length; i < length; i++)
|
||||
if (channelId === channels[i].Id) {
|
||||
channelIndex = i;
|
||||
break
|
||||
} return 1e7 * channelIndex + datetime.parseISO8601Date(program.StartDate, {
|
||||
toLocal: !0
|
||||
}).getTime() / 6e4
|
||||
}
|
||||
|
||||
function renderGuide(context, date, channels, programs, renderOptions, apiClient, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender) {
|
||||
programs.sort(function(a, b) {
|
||||
return getProgramSortOrder(a, channels) - getProgramSortOrder(b, channels)
|
||||
});
|
||||
var activeElement = document.activeElement,
|
||||
itemId = activeElement && activeElement.getAttribute ? activeElement.getAttribute("data-id") : null,
|
||||
channelRowId = null;
|
||||
activeElement && (channelRowId = dom.parentWithClass(activeElement, "channelPrograms"), channelRowId = channelRowId && channelRowId.getAttribute ? channelRowId.getAttribute("data-channelid") : null), renderChannelHeaders(context, channels, apiClient);
|
||||
var startDate = date,
|
||||
endDate = new Date(startDate.getTime() + msPerDay);
|
||||
context.querySelector(".timeslotHeaders").innerHTML = getTimeslotHeadersHtml(startDate, endDate), items = {}, renderPrograms(context, date, channels, programs, renderOptions), focusProgramOnRender && focusProgram(context, itemId, channelRowId, focusToTimeMs, startTimeOfDayMs), scrollProgramGridToTimeMs(context, scrollToTimeMs, startTimeOfDayMs)
|
||||
}
|
||||
|
||||
function scrollProgramGridToTimeMs(context, scrollToTimeMs, startTimeOfDayMs) {
|
||||
scrollToTimeMs -= startTimeOfDayMs;
|
||||
var pct = scrollToTimeMs / msPerDay;
|
||||
programGrid.scrollTop = 0;
|
||||
var scrollPos = pct * programGrid.scrollWidth;
|
||||
nativeScrollTo(programGrid, scrollPos, !0)
|
||||
}
|
||||
|
||||
function focusProgram(context, itemId, channelRowId, focusToTimeMs, startTimeOfDayMs) {
|
||||
var focusElem;
|
||||
if (itemId && (focusElem = context.querySelector('[data-id="' + itemId + '"]')), focusElem) focusManager.focus(focusElem);
|
||||
else {
|
||||
var autoFocusParent;
|
||||
channelRowId && (autoFocusParent = context.querySelector('[data-channelid="' + channelRowId + '"]')), autoFocusParent || (autoFocusParent = programGrid), focusToTimeMs -= startTimeOfDayMs;
|
||||
for (var pct = focusToTimeMs / msPerDay * 100, programCell = autoFocusParent.querySelector(".programCell"); programCell;) {
|
||||
var left = (programCell.style.left || "").replace("%", "");
|
||||
left = left ? parseFloat(left) : 0;
|
||||
var width = (programCell.style.width || "").replace("%", "");
|
||||
if (width = width ? parseFloat(width) : 0, left >= pct || left + width >= pct) break;
|
||||
programCell = programCell.nextSibling
|
||||
}
|
||||
programCell ? focusManager.focus(programCell) : focusManager.autoFocus(autoFocusParent, !0)
|
||||
}
|
||||
}
|
||||
|
||||
function nativeScrollTo(container, pos, horizontal) {
|
||||
container.scrollTo ? horizontal ? container.scrollTo(pos, 0) : container.scrollTo(0, pos) : horizontal ? container.scrollLeft = Math.round(pos) : container.scrollTop = Math.round(pos)
|
||||
}
|
||||
|
||||
function onProgramGridScroll(context, elem, timeslotHeaders) {
|
||||
if ((new Date).getTime() - lastHeaderScroll >= 1e3) {
|
||||
lastGridScroll = (new Date).getTime();
|
||||
var scrollLeft = elem.scrollLeft;
|
||||
scrollXPct = 100 * scrollLeft / elem.scrollWidth, nativeScrollTo(timeslotHeaders, scrollLeft, !0)
|
||||
}
|
||||
updateProgramCellsOnScroll(elem, programCells)
|
||||
}
|
||||
|
||||
function onTimeslotHeadersScroll(context, elem) {
|
||||
(new Date).getTime() - lastGridScroll >= 1e3 && (lastHeaderScroll = (new Date).getTime(), nativeScrollTo(programGrid, elem.scrollLeft, !0))
|
||||
}
|
||||
|
||||
function changeDate(page, date, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender) {
|
||||
var newStartDate = normalizeDateToTimeslot(date);
|
||||
currentDate = newStartDate, reloadGuide(page, newStartDate, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender)
|
||||
}
|
||||
|
||||
function getDateTabText(date, isActive, tabIndex) {
|
||||
var cssClass = isActive ? "emby-tab-button guide-date-tab-button emby-tab-button-active" : "emby-tab-button guide-date-tab-button",
|
||||
html = '<button is="emby-button" class="' + cssClass + '" data-index="' + tabIndex + '" data-date="' + date.getTime() + '">',
|
||||
tabText = datetime.toLocaleDateString(date, {
|
||||
weekday: "short"
|
||||
});
|
||||
return tabText += "<br/>", tabText += date.getDate(), html += '<div class="emby-button-foreground">' + tabText + "</div>", html += "</button>"
|
||||
}
|
||||
|
||||
function setDateRange(page, guideInfo) {
|
||||
var today = new Date,
|
||||
nowHours = today.getHours();
|
||||
today.setHours(nowHours, 0, 0, 0);
|
||||
var start = datetime.parseISO8601Date(guideInfo.StartDate, {
|
||||
toLocal: !0
|
||||
}),
|
||||
end = datetime.parseISO8601Date(guideInfo.EndDate, {
|
||||
toLocal: !0
|
||||
});
|
||||
start.setHours(nowHours, 0, 0, 0), end.setHours(0, 0, 0, 0), start.getTime() >= end.getTime() && end.setDate(start.getDate() + 1), start = new Date(Math.max(today, start));
|
||||
var dateTabsHtml = "",
|
||||
tabIndex = 0,
|
||||
date = new Date;
|
||||
currentDate && date.setTime(currentDate.getTime()), date.setHours(nowHours, 0, 0, 0);
|
||||
var startTimeOfDayMs = 60 * start.getHours() * 60 * 1e3;
|
||||
for (startTimeOfDayMs += 60 * start.getMinutes() * 1e3; start <= end;) {
|
||||
dateTabsHtml += getDateTabText(start, date.getDate() === start.getDate() && date.getMonth() === start.getMonth() && date.getFullYear() === start.getFullYear(), tabIndex), start.setDate(start.getDate() + 1), start.setHours(0, 0, 0, 0), tabIndex++
|
||||
}
|
||||
page.querySelector(".emby-tabs-slider").innerHTML = dateTabsHtml, page.querySelector(".guideDateTabs").refresh();
|
||||
var newDate = new Date,
|
||||
newDateHours = newDate.getHours(),
|
||||
scrollToTimeMs = 60 * newDateHours * 60 * 1e3,
|
||||
minutes = newDate.getMinutes();
|
||||
minutes >= 30 && (scrollToTimeMs += 18e5), changeDate(page, date, scrollToTimeMs, 60 * (60 * newDateHours + minutes) * 1e3, startTimeOfDayMs, layoutManager.tv)
|
||||
}
|
||||
|
||||
function reloadPage(page) {
|
||||
showLoading(), connectionManager.getApiClient(options.serverId).getLiveTvGuideInfo().then(function(guideInfo) {
|
||||
setDateRange(page, guideInfo)
|
||||
})
|
||||
}
|
||||
|
||||
function getChannelProgramsFocusableElements(container) {
|
||||
for (var elements = container.querySelectorAll(".programCell"), list = [], currentScrollXPct = scrollXPct + 1, i = 0, length = elements.length; i < length; i++) {
|
||||
var elem = elements[i],
|
||||
left = (elem.style.left || "").replace("%", "");
|
||||
left = left ? parseFloat(left) : 0;
|
||||
var width = (elem.style.width || "").replace("%", "");
|
||||
width = width ? parseFloat(width) : 0, left + width >= currentScrollXPct && list.push(elem)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
function onInputCommand(e) {
|
||||
var container, channelPrograms, focusableElements, newRow, target = e.target,
|
||||
programCell = dom.parentWithClass(target, "programCell");
|
||||
switch (e.detail.command) {
|
||||
case "up":
|
||||
programCell ? (container = programGrid, channelPrograms = dom.parentWithClass(programCell, "channelPrograms"), newRow = channelPrograms.previousSibling, newRow ? (focusableElements = getChannelProgramsFocusableElements(newRow), focusableElements.length ? container = newRow : focusableElements = null) : container = null) : container = null, lastFocusDirection = e.detail.command, focusManager.moveUp(target, {
|
||||
container: container,
|
||||
focusableElements: focusableElements
|
||||
});
|
||||
break;
|
||||
case "down":
|
||||
programCell ? (container = programGrid, channelPrograms = dom.parentWithClass(programCell, "channelPrograms"), newRow = channelPrograms.nextSibling, newRow ? (focusableElements = getChannelProgramsFocusableElements(newRow), focusableElements.length ? container = newRow : focusableElements = null) : container = null) : container = null, lastFocusDirection = e.detail.command, focusManager.moveDown(target, {
|
||||
container: container,
|
||||
focusableElements: focusableElements
|
||||
});
|
||||
break;
|
||||
case "left":
|
||||
container = programCell ? dom.parentWithClass(programCell, "channelPrograms") : null, container && !programCell.previousSibling && (container = null), lastFocusDirection = e.detail.command, focusManager.moveLeft(target, {
|
||||
container: container
|
||||
}), !0;
|
||||
break;
|
||||
case "right":
|
||||
container = programCell ? dom.parentWithClass(programCell, "channelPrograms") : null, lastFocusDirection = e.detail.command, focusManager.moveRight(target, {
|
||||
container: container
|
||||
}), !0;
|
||||
break;
|
||||
default:
|
||||
return
|
||||
}
|
||||
e.preventDefault(), e.stopPropagation()
|
||||
}
|
||||
|
||||
function onScrollerFocus(e) {
|
||||
var target = e.target,
|
||||
programCell = dom.parentWithClass(target, "programCell");
|
||||
if (programCell) {
|
||||
var focused = target,
|
||||
id = focused.getAttribute("data-id"),
|
||||
item = items[id];
|
||||
item && events.trigger(self, "focus", [{
|
||||
item: item
|
||||
}])
|
||||
}
|
||||
if ("left" === lastFocusDirection) programCell && scrollHelper.toStart(programGrid, programCell, !0, !0);
|
||||
else if ("right" === lastFocusDirection) programCell && scrollHelper.toCenter(programGrid, programCell, !0, !0);
|
||||
else if ("up" === lastFocusDirection || "down" === lastFocusDirection) {
|
||||
var verticalScroller = dom.parentWithClass(target, "guideVerticalScroller");
|
||||
if (verticalScroller) {
|
||||
var focusedElement = programCell || dom.parentWithTag(target, "BUTTON");
|
||||
verticalScroller.toCenter(focusedElement, !0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setScrollEvents(view, enabled) {
|
||||
if (layoutManager.tv) {
|
||||
var guideVerticalScroller = view.querySelector(".guideVerticalScroller");
|
||||
enabled ? inputManager.on(guideVerticalScroller, onInputCommand) : inputManager.off(guideVerticalScroller, onInputCommand)
|
||||
}
|
||||
}
|
||||
|
||||
function onTimerCreated(e, apiClient, data) {
|
||||
for (var programId = data.ProgramId, newTimerId = data.Id, cells = options.element.querySelectorAll('.programCell[data-id="' + programId + '"]'), i = 0, length = cells.length; i < length; i++) {
|
||||
var cell = cells[i];
|
||||
cell.querySelector(".timerIcon") || cell.querySelector(".guideProgramName").insertAdjacentHTML("beforeend", '<i class="timerIcon md-icon programIcon"></i>'), newTimerId && cell.setAttribute("data-timerid", newTimerId)
|
||||
}
|
||||
}
|
||||
|
||||
function onSeriesTimerCreated(e, apiClient, data) {}
|
||||
|
||||
function onTimerCancelled(e, apiClient, data) {
|
||||
for (var id = data.Id, cells = options.element.querySelectorAll('.programCell[data-timerid="' + id + '"]'), i = 0, length = cells.length; i < length; i++) {
|
||||
var cell = cells[i],
|
||||
icon = cell.querySelector(".timerIcon");
|
||||
icon && icon.parentNode.removeChild(icon), cell.removeAttribute("data-timerid")
|
||||
}
|
||||
}
|
||||
|
||||
function onSeriesTimerCancelled(e, apiClient, data) {
|
||||
for (var id = data.Id, cells = options.element.querySelectorAll('.programCell[data-seriestimerid="' + id + '"]'), i = 0, length = cells.length; i < length; i++) {
|
||||
var cell = cells[i],
|
||||
icon = cell.querySelector(".seriesTimerIcon");
|
||||
icon && icon.parentNode.removeChild(icon), cell.removeAttribute("data-seriestimerid")
|
||||
}
|
||||
}
|
||||
var self = this,
|
||||
items = {};
|
||||
self.options = options, self.categoryOptions = {
|
||||
categories: []
|
||||
};
|
||||
var currentDate, autoRefreshInterval, programCells, lastFocusDirection, programGrid, cellCurationMinutes = 30,
|
||||
cellDurationMs = 60 * cellCurationMinutes * 1e3,
|
||||
msPerDay = 864e5,
|
||||
currentStartIndex = 0,
|
||||
currentChannelLimit = 0;
|
||||
self.refresh = function() {
|
||||
currentDate = null, reloadPage(options.element), restartAutoRefresh()
|
||||
}, self.pause = function() {
|
||||
stopAutoRefresh()
|
||||
}, self.resume = function(refreshData) {
|
||||
refreshData ? self.refresh() : restartAutoRefresh()
|
||||
}, self.destroy = function() {
|
||||
stopAutoRefresh(), events.off(serverNotifications, "TimerCreated", onTimerCreated), events.off(serverNotifications, "SeriesTimerCreated", onSeriesTimerCreated), events.off(serverNotifications, "TimerCancelled", onTimerCancelled), events.off(serverNotifications, "SeriesTimerCancelled", onSeriesTimerCancelled), setScrollEvents(options.element, !1), itemShortcuts.off(options.element), items = {}
|
||||
};
|
||||
var lastGridScroll = 0,
|
||||
lastHeaderScroll = 0,
|
||||
scrollXPct = 0;
|
||||
require(["text!./tvguide.template.html"], function(template) {
|
||||
var context = options.element;
|
||||
context.classList.add("tvguide"), context.innerHTML = globalize.translateDocument(template, "sharedcomponents"), programGrid = context.querySelector(".programGrid");
|
||||
var timeslotHeaders = context.querySelector(".timeslotHeaders");
|
||||
layoutManager.tv ? dom.addEventListener(context.querySelector(".guideVerticalScroller"), "focus", onScrollerFocus, {
|
||||
capture: !0,
|
||||
passive: !0
|
||||
}) : layoutManager.desktop && timeslotHeaders.classList.add("timeslotHeaders-desktop"), (browser.iOS || browser.osx) && (context.querySelector(".channelsContainer").classList.add("noRubberBanding"), programGrid.classList.add("noRubberBanding")), dom.addEventListener(programGrid, "scroll", function(e) {
|
||||
onProgramGridScroll(context, this, timeslotHeaders)
|
||||
}, {
|
||||
passive: !0
|
||||
}), dom.addEventListener(timeslotHeaders, "scroll", function() {
|
||||
onTimeslotHeadersScroll(context, this)
|
||||
}, {
|
||||
passive: !0
|
||||
}), programGrid.addEventListener("click", onProgramGridClick), context.querySelector(".btnNextPage").addEventListener("click", function() {
|
||||
currentStartIndex += currentChannelLimit, reloadPage(context), restartAutoRefresh()
|
||||
}), context.querySelector(".btnPreviousPage").addEventListener("click", function() {
|
||||
currentStartIndex = Math.max(currentStartIndex - currentChannelLimit, 0), reloadPage(context), restartAutoRefresh()
|
||||
}), context.querySelector(".btnGuideViewSettings").addEventListener("click", function() {
|
||||
showViewSettings(self), restartAutoRefresh()
|
||||
}), context.querySelector(".guideDateTabs").addEventListener("tabchange", function(e) {
|
||||
var allTabButtons = e.target.querySelectorAll(".guide-date-tab-button"),
|
||||
tabButton = allTabButtons[parseInt(e.detail.selectedTabIndex)];
|
||||
if (tabButton) {
|
||||
var previousButton = null == e.detail.previousIndex ? null : allTabButtons[parseInt(e.detail.previousIndex)],
|
||||
date = new Date;
|
||||
date.setTime(parseInt(tabButton.getAttribute("data-date")));
|
||||
var scrollToTimeMs, scrollWidth = programGrid.scrollWidth;
|
||||
if (scrollToTimeMs = scrollWidth ? programGrid.scrollLeft / scrollWidth * msPerDay : 0, previousButton) {
|
||||
var previousDate = new Date;
|
||||
previousDate.setTime(parseInt(previousButton.getAttribute("data-date"))), scrollToTimeMs += 60 * previousDate.getHours() * 60 * 1e3, scrollToTimeMs += 60 * previousDate.getMinutes() * 1e3
|
||||
}
|
||||
var startTimeOfDayMs = 60 * date.getHours() * 60 * 1e3;
|
||||
startTimeOfDayMs += 60 * date.getMinutes() * 1e3, changeDate(context, date, scrollToTimeMs, scrollToTimeMs, startTimeOfDayMs, !1)
|
||||
}
|
||||
}), setScrollEvents(context, !0), itemShortcuts.on(context), events.trigger(self, "load"), events.on(serverNotifications, "TimerCreated", onTimerCreated), events.on(serverNotifications, "SeriesTimerCreated", onSeriesTimerCreated), events.on(serverNotifications, "TimerCancelled", onTimerCancelled), events.on(serverNotifications, "SeriesTimerCancelled", onSeriesTimerCancelled), self.refresh()
|
||||
})
|
||||
}
|
||||
var isUpdatingProgramCellScroll = !1,
|
||||
ProgramCellPrototype = Object.create(HTMLButtonElement.prototype);
|
||||
return ProgramCellPrototype.detachedCallback = function() {
|
||||
this.posLeft = null, this.posWidth = null, this.guideProgramName = null
|
||||
}, document.registerElement("emby-programcell", {
|
||||
prototype: ProgramCellPrototype,
|
||||
extends: "button"
|
||||
}), Guide
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue