jellyfin-web/dashboard-ui/bower_components/emby-webcomponents/guide/guide.js

1012 lines
37 KiB
JavaScript
Raw Normal View History

2016-12-11 22:41:24 -07:00
define(['require', 'browser', 'globalize', 'connectionManager', 'serverNotifications', 'loading', 'datetime', 'focusManager', 'userSettings', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'registrationServices', 'dom', 'clearButtonStyle', 'css!./guide.css', 'programStyles', 'material-icons', 'scrollStyles', 'emby-button', 'paper-icon-button-light', 'emby-tabs'], function (require, browser, globalize, connectionManager, serverNotifications, loading, datetime, focusManager, userSettings, imageLoader, events, layoutManager, itemShortcuts, registrationServices, dom) {
2016-10-12 11:23:09 -07:00
'use strict';
2016-09-05 22:02:05 -07:00
function showViewSettings(instance) {
require(['guide-settings-dialog'], function (guideSettingsDialog) {
2016-12-11 22:41:24 -07:00
guideSettingsDialog.show(instance.categoryOptions).then(function () {
2016-09-27 22:11:41 -07:00
instance.refresh();
});
});
}
2016-04-26 11:28:04 -07:00
function Guide(options) {
var self = this;
var items = {};
2016-04-26 19:59:43 -07:00
self.options = options;
2016-09-27 22:11:41 -07:00
self.categoryOptions = { categories: [] };
2016-04-26 19:59:43 -07:00
2016-04-26 11:28:04 -07:00
// 30 mins
var cellCurationMinutes = 30;
var cellDurationMs = cellCurationMinutes * 60 * 1000;
var msPerDay = 86400000;
2016-06-06 10:33:27 -07:00
var totalRendererdMs = msPerDay;
2016-04-26 11:28:04 -07:00
var currentDate;
2016-08-18 10:03:22 -07:00
var currentStartIndex = 0;
var currentChannelLimit = 0;
2016-12-07 13:03:19 -07:00
var autoRefreshInterval;
2016-04-26 11:28:04 -07:00
2016-06-09 09:13:25 -07:00
self.refresh = function () {
currentDate = null;
reloadPage(options.element);
2016-12-07 13:03:19 -07:00
restartAutoRefresh();
2016-06-09 09:13:25 -07:00
};
2016-12-14 13:58:55 -07:00
self.pause = function () {
stopAutoRefresh();
};
self.resume = function (refreshData) {
if (refreshData) {
self.refresh();
} else {
restartAutoRefresh();
}
};
2016-06-09 09:13:25 -07:00
self.destroy = function () {
2016-12-07 13:03:19 -07:00
stopAutoRefresh();
2016-06-09 09:13:25 -07:00
events.off(serverNotifications, 'TimerCreated', onTimerCreated);
events.off(serverNotifications, 'SeriesTimerCreated', onSeriesTimerCreated);
events.off(serverNotifications, 'TimerCancelled', onTimerCancelled);
events.off(serverNotifications, 'SeriesTimerCancelled', onSeriesTimerCancelled);
clearCurrentTimeUpdateInterval();
2016-07-26 22:19:56 -07:00
setScrollEvents(options.element, false);
2016-06-09 09:13:25 -07:00
itemShortcuts.off(options.element);
items = {};
};
2016-12-07 13:03:19 -07:00
function restartAutoRefresh() {
stopAutoRefresh();
var intervalMs = 60000 * 15; // (minutes)
autoRefreshInterval = setInterval(function () {
self.refresh();
}, intervalMs);
}
function stopAutoRefresh() {
if (autoRefreshInterval) {
clearInterval(autoRefreshInterval);
autoRefreshInterval = null;
}
}
2016-04-26 11:28:04 -07:00
function normalizeDateToTimeslot(date) {
var minutesOffset = date.getMinutes() - cellCurationMinutes;
if (minutesOffset >= 0) {
date.setHours(date.getHours(), cellCurationMinutes, 0, 0);
} else {
date.setHours(date.getHours(), 0, 0, 0);
}
return date;
}
function showLoading() {
loading.show();
}
function hideLoading() {
loading.hide();
}
2016-06-06 10:33:27 -07:00
var currentTimeUpdateInterval;
2016-06-06 11:05:22 -07:00
var currentTimeIndicatorBar;
var currentTimeIndicatorArrow;
2016-06-06 10:33:27 -07:00
function startCurrentTimeUpdateInterval() {
clearCurrentTimeUpdateInterval();
//currentTimeUpdateInterval = setInterval(updateCurrentTimeIndicator, 1000);
currentTimeUpdateInterval = setInterval(updateCurrentTimeIndicator, 60000);
updateCurrentTimeIndicator();
}
function clearCurrentTimeUpdateInterval() {
var interval = currentTimeUpdateInterval;
if (interval) {
clearInterval(interval);
}
currentTimeUpdateInterval = null;
2016-06-06 11:05:22 -07:00
currentTimeIndicatorBar = null;
currentTimeIndicatorArrow = null;
2016-06-06 10:33:27 -07:00
}
function updateCurrentTimeIndicator() {
2016-06-06 11:05:22 -07:00
if (!currentTimeIndicatorBar) {
currentTimeIndicatorBar = options.element.querySelector('.currentTimeIndicatorBar');
}
if (!currentTimeIndicatorArrow) {
currentTimeIndicatorArrow = options.element.querySelector('.currentTimeIndicatorArrowContainer');
2016-06-06 10:33:27 -07:00
}
var dateDifference = new Date().getTime() - currentDate.getTime();
var pct = dateDifference > 0 ? (dateDifference / totalRendererdMs) : 0;
pct = Math.min(pct, 1);
if (pct <= 0 || pct >= 1) {
2016-06-06 11:05:22 -07:00
currentTimeIndicatorBar.classList.add('hide');
currentTimeIndicatorArrow.classList.add('hide');
2016-06-06 10:33:27 -07:00
} else {
2016-06-06 11:05:22 -07:00
currentTimeIndicatorBar.classList.remove('hide');
currentTimeIndicatorArrow.classList.remove('hide');
2016-06-06 10:33:27 -07:00
//pct *= 100;
//pct = 100 - pct;
2016-06-06 11:05:22 -07:00
//currentTimeIndicatorElement.style.width = (pct * 100) + '%';
currentTimeIndicatorBar.style.transform = 'scaleX(' + pct + ')';
currentTimeIndicatorArrow.style.transform = 'translateX(' + (pct * 100) + '%)';
2016-06-06 10:33:27 -07:00
}
}
2016-04-26 11:28:04 -07:00
function getChannelLimit(context) {
return registrationServices.validateFeature('livetv').then(function () {
2016-08-18 10:27:22 -07:00
var limit = browser.slow ? 100 : 500;
2016-04-26 11:28:04 -07:00
context.querySelector('.guideRequiresUnlock').classList.add('hide');
return limit;
}, function () {
var limit = 5;
context.querySelector('.guideRequiresUnlock').classList.remove('hide');
2016-06-09 09:13:25 -07:00
context.querySelector('.unlockText').innerHTML = globalize.translate('sharedcomponents#LiveTvGuideRequiresUnlock', limit);
2016-04-26 11:28:04 -07:00
return limit;
});
}
2016-12-12 15:43:07 -07:00
function reloadGuide(context, newStartDate, focusProgramOnRender) {
2016-04-26 11:28:04 -07:00
var apiClient = connectionManager.currentApiClient();
2016-09-29 05:55:49 -07:00
var channelQuery = {
StartIndex: 0,
2016-09-29 23:50:06 -07:00
EnableFavoriteSorting: userSettings.get('livetv-favoritechannelsattop') !== 'false'
2016-09-29 05:55:49 -07:00
};
2016-04-26 11:28:04 -07:00
channelQuery.UserId = apiClient.getCurrentUserId();
getChannelLimit(context).then(function (channelLimit) {
2016-08-18 10:03:22 -07:00
currentChannelLimit = channelLimit;
2016-04-26 11:28:04 -07:00
showLoading();
2016-08-18 10:03:22 -07:00
channelQuery.StartIndex = currentStartIndex;
2016-04-26 11:28:04 -07:00
channelQuery.Limit = channelLimit;
channelQuery.AddCurrentProgram = false;
2016-08-17 12:28:43 -07:00
channelQuery.EnableUserData = false;
channelQuery.EnableImageTypes = "Primary";
2016-04-26 11:28:04 -07:00
2016-09-29 05:55:49 -07:00
var categories = self.categoryOptions.categories || [];
2016-10-12 11:23:09 -07:00
var displayMovieContent = !categories.length || categories.indexOf('movies') !== -1;
var displaySportsContent = !categories.length || categories.indexOf('sports') !== -1;
var displayNewsContent = !categories.length || categories.indexOf('news') !== -1;
var displayKidsContent = !categories.length || categories.indexOf('kids') !== -1;
var displaySeriesContent = !categories.length || categories.indexOf('series') !== -1;
2016-09-29 05:55:49 -07:00
if (displayMovieContent && displaySportsContent && displayNewsContent && displayKidsContent) {
channelQuery.IsMovie = null;
channelQuery.IsSports = null;
channelQuery.IsKids = null;
channelQuery.IsNews = null;
channelQuery.IsSeries = null;
} else {
if (displayNewsContent) {
channelQuery.IsNews = true;
}
if (displaySportsContent) {
channelQuery.IsSports = true;
}
if (displayKidsContent) {
channelQuery.IsKids = true;
}
if (displayMovieContent) {
channelQuery.IsMovie = true;
}
if (displaySeriesContent) {
channelQuery.IsSeries = true;
}
}
2016-04-26 11:28:04 -07:00
2016-10-14 09:22:04 -07:00
if (userSettings.get('livetv-channelorder') === 'DatePlayed') {
2016-09-29 23:50:06 -07:00
channelQuery.SortBy = "DatePlayed";
channelQuery.SortOrder = "Descending";
2016-10-14 09:22:04 -07:00
} else {
2016-12-11 22:41:24 -07:00
channelQuery.SortBy = null;
channelQuery.SortOrder = null;
2016-09-29 23:50:06 -07:00
}
2016-04-26 11:28:04 -07:00
var date = newStartDate;
// Add one second to avoid getting programs that are just ending
date = new Date(date.getTime() + 1000);
// Subtract to avoid getting programs that are starting when the grid ends
var nextDay = new Date(date.getTime() + msPerDay - 2000);
console.log(nextDay);
2016-09-29 05:55:49 -07:00
apiClient.getLiveTvChannels(channelQuery).then(function (channelsResult) {
2016-04-26 11:28:04 -07:00
2016-09-05 22:02:05 -07:00
var btnPreviousPage = context.querySelector('.btnPreviousPage');
var btnNextPage = context.querySelector('.btnNextPage');
2016-08-18 10:03:22 -07:00
if (channelsResult.TotalRecordCount > channelLimit) {
2016-09-05 22:02:05 -07:00
2016-09-07 00:08:20 -07:00
context.querySelector('.guideOptions').classList.remove('hide');
2016-09-05 22:02:05 -07:00
btnPreviousPage.classList.remove('hide');
btnNextPage.classList.remove('hide');
2016-08-18 10:03:22 -07:00
if (channelQuery.StartIndex) {
context.querySelector('.btnPreviousPage').disabled = false;
} else {
context.querySelector('.btnPreviousPage').disabled = true;
}
if ((channelQuery.StartIndex + channelLimit) < channelsResult.TotalRecordCount) {
2016-09-05 22:02:05 -07:00
btnNextPage.disabled = false;
2016-08-18 10:03:22 -07:00
} else {
2016-09-05 22:02:05 -07:00
btnNextPage.disabled = true;
2016-08-18 10:03:22 -07:00
}
} else {
2016-09-07 00:08:20 -07:00
context.querySelector('.guideOptions').classList.add('hide');
2016-08-18 10:03:22 -07:00
}
2016-04-26 11:28:04 -07:00
apiClient.getLiveTvPrograms({
UserId: apiClient.getCurrentUserId(),
MaxStartDate: nextDay.toISOString(),
MinEndDate: date.toISOString(),
channelIds: channelsResult.Items.map(function (c) {
return c.Id;
}).join(','),
ImageTypeLimit: 1,
2016-08-17 22:56:10 -07:00
EnableImages: false,
//EnableImageTypes: layoutManager.tv ? "Primary,Backdrop" : "Primary",
2016-05-08 20:13:38 -07:00
SortBy: "StartDate",
2016-08-17 12:28:43 -07:00
EnableTotalRecordCount: false,
EnableUserData: false
2016-04-26 11:28:04 -07:00
}).then(function (programsResult) {
2016-12-12 15:43:07 -07:00
renderGuide(context, date, channelsResult.Items, programsResult.Items, apiClient, focusProgramOnRender);
2016-04-26 11:28:04 -07:00
hideLoading();
});
});
});
}
function getDisplayTime(date) {
if ((typeof date).toString().toLowerCase() === 'string') {
try {
date = datetime.parseISO8601Date(date, { toLocal: true });
} catch (err) {
return date;
}
}
return datetime.getDisplayTime(date).toLowerCase();
}
function getTimeslotHeadersHtml(startDate, endDateTime) {
var html = '';
// clone
startDate = new Date(startDate.getTime());
html += '<div class="timeslotHeadersInner">';
while (startDate.getTime() < endDateTime) {
html += '<div class="timeslotHeader">';
html += getDisplayTime(startDate);
html += '</div>';
// Add 30 mins
startDate.setTime(startDate.getTime() + cellDurationMs);
}
2016-06-06 10:33:27 -07:00
2016-06-06 11:05:22 -07:00
html += '<div class="currentTimeIndicatorBar hide">';
2016-06-06 10:33:27 -07:00
html += '</div>';
2016-06-06 11:05:22 -07:00
html += '<div class="currentTimeIndicatorArrowContainer hide">';
2016-06-09 23:54:03 -07:00
html += '<i class="currentTimeIndicatorArrow md-icon">arrow_drop_down</i>';
2016-04-26 11:28:04 -07:00
html += '</div>';
return html;
}
function parseDates(program) {
if (!program.StartDateLocal) {
try {
program.StartDateLocal = datetime.parseISO8601Date(program.StartDate, { toLocal: true });
} catch (err) {
}
}
if (!program.EndDateLocal) {
try {
program.EndDateLocal = datetime.parseISO8601Date(program.EndDate, { toLocal: true });
} catch (err) {
}
}
return null;
}
2016-10-03 22:15:39 -07:00
function getTimerIndicator(item) {
var status;
2016-10-12 11:23:09 -07:00
if (item.Type === 'SeriesTimer') {
2016-10-03 22:15:39 -07:00
return '<i class="md-icon programIcon seriesTimerIcon">&#xE062;</i>';
}
2016-10-10 23:46:59 -07:00
else if (item.TimerId || item.SeriesTimerId) {
2016-10-03 22:15:39 -07:00
2016-10-10 23:46:59 -07:00
status = item.Status || 'Cancelled';
2016-10-03 22:15:39 -07:00
}
2016-10-12 11:23:09 -07:00
else if (item.Type === 'Timer') {
2016-10-03 22:15:39 -07:00
status = item.Status;
}
else {
return '';
}
if (item.SeriesTimerId) {
2016-10-12 11:23:09 -07:00
if (status !== 'Cancelled') {
2016-10-03 22:15:39 -07:00
return '<i class="md-icon programIcon seriesTimerIcon">&#xE062;</i>';
}
return '<i class="md-icon programIcon seriesTimerIcon seriesTimerIcon-inactive">&#xE062;</i>';
}
2016-10-07 08:08:13 -07:00
return '<i class="md-icon programIcon timerIcon">&#xE061;</i>';
2016-10-03 22:15:39 -07:00
}
2016-10-17 09:41:18 -07:00
function getChannelProgramsHtml(context, date, channel, programs, options, index) {
2016-04-26 11:28:04 -07:00
var html = '';
var startMs = date.getTime();
var endMs = startMs + msPerDay - 1;
programs = programs.filter(function (curr) {
2016-10-12 11:23:09 -07:00
return curr.ChannelId === channel.Id;
2016-04-26 11:28:04 -07:00
});
2016-09-15 18:09:46 -07:00
var outerCssClass = layoutManager.tv ? 'channelPrograms channelPrograms-tv' : 'channelPrograms';
2016-08-24 20:07:31 -07:00
2016-09-15 18:09:46 -07:00
html += '<div class="' + outerCssClass + '" data-channelid="' + channel.Id + '">';
var clickAction = layoutManager.tv ? 'link' : 'programdialog';
2016-04-26 11:28:04 -07:00
2016-09-27 22:11:41 -07:00
var categories = self.categoryOptions.categories || [];
2016-10-12 11:23:09 -07:00
var displayMovieContent = !categories.length || categories.indexOf('movies') !== -1;
var displaySportsContent = !categories.length || categories.indexOf('sports') !== -1;
var displayNewsContent = !categories.length || categories.indexOf('news') !== -1;
var displayKidsContent = !categories.length || categories.indexOf('kids') !== -1;
var displaySeriesContent = !categories.length || categories.indexOf('series') !== -1;
var enableColorCodedBackgrounds = userSettings.get('guide-colorcodedbackgrounds') === 'true';
2016-09-27 22:11:41 -07:00
2016-04-26 11:28:04 -07:00
for (var i = 0, length = programs.length; i < length; i++) {
var program = programs[i];
2016-10-12 11:23:09 -07:00
if (program.ChannelId !== channel.Id) {
2016-04-26 11:28:04 -07:00
continue;
}
parseDates(program);
if (program.EndDateLocal.getTime() < startMs) {
continue;
}
if (program.StartDateLocal.getTime() > endMs) {
break;
}
items[program.Id] = program;
var renderStartMs = Math.max(program.StartDateLocal.getTime(), startMs);
var startPercent = (program.StartDateLocal.getTime() - startMs) / msPerDay;
startPercent *= 100;
startPercent = Math.max(startPercent, 0);
var renderEndMs = Math.min(program.EndDateLocal.getTime(), endMs);
var endPercent = (renderEndMs - renderStartMs) / msPerDay;
endPercent *= 100;
var cssClass = "programCell clearButton itemAction";
2016-09-29 05:55:49 -07:00
var accentCssClass = null;
2016-09-27 22:11:41 -07:00
var displayInnerContent = true;
2016-04-26 11:28:04 -07:00
if (program.IsKids) {
cssClass += " childProgramInfo";
2016-09-27 22:11:41 -07:00
displayInnerContent = displayKidsContent;
accentCssClass = 'childAccent';
2016-04-26 11:28:04 -07:00
} else if (program.IsSports) {
cssClass += " sportsProgramInfo";
2016-09-27 22:11:41 -07:00
displayInnerContent = displaySportsContent;
accentCssClass = 'sportsAccent';
2016-04-26 11:28:04 -07:00
} else if (program.IsNews) {
cssClass += " newsProgramInfo";
2016-09-27 22:11:41 -07:00
displayInnerContent = displayNewsContent;
accentCssClass = 'newsAccent';
2016-04-26 11:28:04 -07:00
} else if (program.IsMovie) {
cssClass += " movieProgramInfo";
2016-09-27 22:11:41 -07:00
displayInnerContent = displayMovieContent;
accentCssClass = 'movieAccent';
2016-04-26 11:28:04 -07:00
}
2016-09-29 05:55:49 -07:00
else if (program.IsSeries) {
cssClass += " plainProgramInfo";
displayInnerContent = displaySeriesContent;
}
2016-04-26 11:28:04 -07:00
else {
cssClass += " plainProgramInfo";
2016-09-29 05:55:49 -07:00
displayInnerContent = displayMovieContent && displayNewsContent && displaySportsContent && displayKidsContent && displaySeriesContent;
2016-09-27 22:11:41 -07:00
}
2016-09-28 00:50:20 -07:00
if (!displayInnerContent) {
accentCssClass = null;
}
2016-09-27 22:11:41 -07:00
if (enableColorCodedBackgrounds && accentCssClass) {
cssClass += ' ' + accentCssClass;
2016-10-02 20:49:52 -07:00
accentCssClass = null;
} else {
2016-09-27 22:11:41 -07:00
accentCssClass = null;
2016-04-26 11:28:04 -07:00
}
2016-05-28 11:03:38 -07:00
var timerAttributes = '';
if (program.TimerId) {
timerAttributes += ' data-timerid="' + program.TimerId + '"';
}
if (program.SeriesTimerId) {
timerAttributes += ' data-seriestimerid="' + program.SeriesTimerId + '"';
}
2016-04-26 11:28:04 -07:00
2016-12-14 13:58:55 -07:00
html += '<button data-action="' + clickAction + '"' + timerAttributes + ' data-channelid="' + program.ChannelId + '" data-id="' + program.Id + '" data-serverid="' + program.ServerId + '" data-type="' + program.Type + '" class="' + cssClass + '" style="left:' + startPercent + '%;width:' + endPercent + '%;">';
2016-04-26 11:28:04 -07:00
2016-09-27 22:11:41 -07:00
if (displayInnerContent) {
var guideProgramNameClass = "guideProgramName";
2016-04-26 11:28:04 -07:00
2016-09-27 22:11:41 -07:00
html += '<div class="' + guideProgramNameClass + '">';
2016-04-26 11:28:04 -07:00
2017-01-07 22:52:51 -07:00
html += '<div class="guideProgramNameText">' + program.Name + '</div>';
2017-01-11 21:27:01 -07:00
var indicatorHtml = null;
2016-09-27 22:11:41 -07:00
if (program.IsLive && options.showLiveIndicator) {
2017-01-07 22:52:51 -07:00
indicatorHtml = '<span class="liveTvProgram guideProgramIndicator">' + globalize.translate('sharedcomponents#Live') + '</span>';
2016-09-27 22:11:41 -07:00
}
else if (program.IsPremiere && options.showPremiereIndicator) {
2017-01-07 22:52:51 -07:00
indicatorHtml = '<span class="premiereTvProgram guideProgramIndicator">' + globalize.translate('sharedcomponents#Premiere') + '</span>';
2016-09-27 22:11:41 -07:00
}
else if (program.IsSeries && !program.IsRepeat && options.showNewIndicator) {
2017-01-07 22:52:51 -07:00
indicatorHtml = '<span class="newTvProgram guideProgramIndicator">' + globalize.translate('sharedcomponents#AttributeNew') + '</span>';
2016-09-27 22:11:41 -07:00
}
else if (program.IsSeries && program.IsRepeat && options.showRepeatIndicator) {
2017-01-07 22:52:51 -07:00
indicatorHtml = '<span class="repeatTvProgram guideProgramIndicator">' + globalize.translate('sharedcomponents#Repeat') + '</span>';
}
2017-01-08 16:56:34 -07:00
if (indicatorHtml || (program.EpisodeTitle && options.showEpisodeTitle)) {
2017-01-07 22:52:51 -07:00
html += '<div class="guideProgramSecondaryInfo">';
html += indicatorHtml || '';
2017-01-08 16:56:34 -07:00
if (program.EpisodeTitle && options.showEpisodeTitle) {
2017-01-07 22:52:51 -07:00
html += '<span class="programSecondaryTitle">' + program.EpisodeTitle + '</span>';
}
html += '</div>';
2016-09-27 22:11:41 -07:00
}
2016-04-26 11:28:04 -07:00
2016-09-27 22:11:41 -07:00
html += '</div>';
2016-04-26 11:28:04 -07:00
2016-09-27 22:11:41 -07:00
if (program.IsHD && options.showHdIcon) {
2016-10-17 09:41:18 -07:00
//html += '<i class="guideHdIcon md-icon programIcon">hd</i>';
2016-10-17 22:06:48 -07:00
if (layoutManager.tv) {
html += '<div class="programIcon programTextIcon programTextIcon-tv">HD</div>';
} else {
html += '<div class="programIcon programTextIcon">HD</div>';
}
2016-09-21 23:57:31 -07:00
}
2016-04-26 11:28:04 -07:00
2016-10-03 22:15:39 -07:00
html += getTimerIndicator(program);
2016-08-02 18:32:16 -07:00
2016-09-27 22:11:41 -07:00
if (accentCssClass) {
html += '<div class="programAccent ' + accentCssClass + '"></div>';
2016-08-02 18:32:16 -07:00
}
2016-04-26 11:28:04 -07:00
}
html += '</button>';
}
html += '</div>';
return html;
}
function renderPrograms(context, date, channels, programs) {
var html = [];
2016-05-20 08:57:07 -07:00
// Normally we'd want to just let responsive css handle this,
// but since mobile browsers are often underpowered,
// it can help performance to get them out of the markup
2016-09-07 10:17:26 -07:00
var allowIndicators = dom.getWindowSize().innerWidth >= 600;
2016-05-20 08:57:07 -07:00
var options = {
2016-10-12 11:23:09 -07:00
showHdIcon: allowIndicators && userSettings.get('guide-indicator-hd') === 'true',
showLiveIndicator: allowIndicators && userSettings.get('guide-indicator-live') !== 'false',
showPremiereIndicator: allowIndicators && userSettings.get('guide-indicator-premiere') !== 'false',
showNewIndicator: allowIndicators && userSettings.get('guide-indicator-new') === 'true',
2017-01-08 16:56:34 -07:00
showRepeatIndicator: allowIndicators && userSettings.get('guide-indicator-repeat') === 'true',
showEpisodeTitle: layoutManager.tv ? false : true
2016-05-20 08:57:07 -07:00
};
2016-04-26 11:28:04 -07:00
for (var i = 0, length = channels.length; i < length; i++) {
2016-10-17 09:41:18 -07:00
html.push(getChannelProgramsHtml(context, date, channels[i], programs, options, i));
2016-04-26 11:28:04 -07:00
}
var programGrid = context.querySelector('.programGrid');
programGrid.innerHTML = html.join('');
programGrid.scrollTop = 0;
programGrid.scrollLeft = 0;
}
function renderChannelHeaders(context, channels, apiClient) {
var html = '';
for (var i = 0, length = channels.length; i < length; i++) {
var channel = channels[i];
var hasChannelImage = channel.ImageTags.Primary;
var dataSrc = '';
if (hasChannelImage) {
var url = apiClient.getScaledImageUrl(channel.Id, {
maxHeight: 200,
tag: channel.ImageTags.Primary,
type: "Primary"
});
dataSrc = ' data-src="' + url + '"';
}
2016-04-27 18:43:09 -07:00
var cssClass = 'channelHeaderCell clearButton itemAction lazy';
2016-04-26 11:28:04 -07:00
2016-08-24 20:07:31 -07:00
if (layoutManager.tv) {
cssClass += ' channelHeaderCell-tv';
}
2016-04-27 18:43:09 -07:00
html += '<button type="button" class="' + cssClass + '"' + dataSrc + ' data-action="link" data-isfolder="' + channel.IsFolder + '" data-id="' + channel.Id + '" data-serverid="' + channel.ServerId + '" data-type="' + channel.Type + '">';
2016-04-26 11:28:04 -07:00
2016-08-02 18:32:16 -07:00
cssClass = 'guideChannelNumber';
2017-01-07 22:52:51 -07:00
html += '<h3 class="' + cssClass + '">' + channel.Number + '</h3>';
2016-04-27 18:43:09 -07:00
2017-01-08 16:56:34 -07:00
if (!hasChannelImage && channel.Name) {
2016-04-27 18:43:09 -07:00
html += '<div class="guideChannelName">' + channel.Name + '</div>';
}
2016-04-26 11:28:04 -07:00
html += '</button>';
}
2016-12-29 12:56:19 -07:00
var channelList = context.querySelector('.channelsContainer');
2016-04-26 11:28:04 -07:00
channelList.innerHTML = html;
imageLoader.lazyChildren(channelList);
}
2016-12-12 15:43:07 -07:00
function renderGuide(context, date, channels, programs, apiClient, focusProgramOnRender) {
2016-04-26 11:28:04 -07:00
//var list = [];
//channels.forEach(function(i) {
// list.push(i);
//});
//channels.forEach(function (i) {
// list.push(i);
//});
//channels.forEach(function (i) {
// list.push(i);
//});
//channels.forEach(function (i) {
// list.push(i);
//});
//channels.forEach(function (i) {
// list.push(i);
//});
//channels.forEach(function (i) {
// list.push(i);
//});
//channels.forEach(function (i) {
// list.push(i);
//});
//channels.forEach(function (i) {
// list.push(i);
//});
//channels.forEach(function (i) {
// list.push(i);
//});
//channels.forEach(function (i) {
// list.push(i);
//});
//channels.forEach(function (i) {
// list.push(i);
//});
//channels.forEach(function (i) {
// list.push(i);
//});
//channels = list;
2016-05-25 09:10:57 -07:00
var activeElement = document.activeElement;
var itemId = activeElement && activeElement.getAttribute ? activeElement.getAttribute('data-id') : null;
var channelRowId = null;
if (activeElement) {
2016-09-27 22:11:41 -07:00
channelRowId = dom.parentWithClass(activeElement, 'channelPrograms');
2016-05-25 09:10:57 -07:00
channelRowId = channelRowId && channelRowId.getAttribute ? channelRowId.getAttribute('data-channelid') : null;
}
2016-04-26 11:28:04 -07:00
renderChannelHeaders(context, channels, apiClient);
var startDate = date;
var endDate = new Date(startDate.getTime() + msPerDay);
context.querySelector('.timeslotHeaders').innerHTML = getTimeslotHeadersHtml(startDate, endDate);
2016-06-06 10:33:27 -07:00
startCurrentTimeUpdateInterval();
2016-04-26 11:28:04 -07:00
items = {};
renderPrograms(context, date, channels, programs);
2016-12-12 15:43:07 -07:00
if (focusProgramOnRender) {
2016-05-25 09:10:57 -07:00
var focusElem;
if (itemId) {
2016-10-12 11:23:09 -07:00
focusElem = context.querySelector('[data-id="' + itemId + '"]');
2016-05-25 09:10:57 -07:00
}
if (focusElem) {
focusManager.focus(focusElem);
} else {
var autoFocusParent;
if (channelRowId) {
2016-10-12 11:23:09 -07:00
autoFocusParent = context.querySelector('[data-channelid="' + channelRowId + '"]');
2016-05-25 09:10:57 -07:00
}
if (!autoFocusParent) {
autoFocusParent = context.querySelector('.programGrid');
}
focusManager.autoFocus(autoFocusParent, true);
}
2016-04-26 11:28:04 -07:00
}
}
function nativeScrollTo(container, pos, horizontal) {
if (container.scrollTo) {
if (horizontal) {
container.scrollTo(pos, 0);
} else {
container.scrollTo(0, pos);
}
} else {
if (horizontal) {
container.scrollLeft = Math.round(pos);
} else {
container.scrollTop = Math.round(pos);
}
}
}
var lastGridScroll = 0;
var lastHeaderScroll = 0;
function onProgramGridScroll(context, elem, timeslotHeaders) {
if ((new Date().getTime() - lastHeaderScroll) >= 1000) {
lastGridScroll = new Date().getTime();
nativeScrollTo(timeslotHeaders, elem.scrollLeft, true);
}
}
function onTimeslotHeadersScroll(context, elem, programGrid) {
if ((new Date().getTime() - lastGridScroll) >= 1000) {
lastHeaderScroll = new Date().getTime();
nativeScrollTo(programGrid, elem.scrollLeft, true);
}
}
2016-12-12 15:43:07 -07:00
function changeDate(page, date, focusProgramOnRender) {
2016-04-26 11:28:04 -07:00
2016-06-06 10:33:27 -07:00
clearCurrentTimeUpdateInterval();
2016-04-26 11:28:04 -07:00
var newStartDate = normalizeDateToTimeslot(date);
currentDate = newStartDate;
2016-12-12 15:43:07 -07:00
reloadGuide(page, newStartDate, focusProgramOnRender);
2016-12-11 22:41:24 -07:00
}
2016-04-26 11:28:04 -07:00
2016-12-11 22:41:24 -07:00
function getDateTabText(date, isActive, tabIndex) {
2016-09-07 00:08:20 -07:00
2016-12-11 22:41:24 -07:00
var cssClass = isActive ? 'emby-tab-button guide-date-tab-button emby-tab-button-active' : 'emby-tab-button guide-date-tab-button';
2016-04-26 11:28:04 -07:00
2016-12-11 22:41:24 -07:00
var html = '<button is="emby-button" class="' + cssClass + '" data-index="' + tabIndex + '" data-date="' + date.getTime() + '">';
var tabText = datetime.toLocaleDateString(date, { weekday: 'short' });
tabText += '<br/>';
tabText += date.getDate();
html += '<div class="emby-button-foreground">' + tabText + '</div>';
html += '</button>';
return html;
}
2016-04-26 11:28:04 -07:00
function setDateRange(page, guideInfo) {
var today = new Date();
today.setHours(today.getHours(), 0, 0, 0);
var start = datetime.parseISO8601Date(guideInfo.StartDate, { toLocal: true });
var end = datetime.parseISO8601Date(guideInfo.EndDate, { toLocal: true });
start.setHours(0, 0, 0, 0);
end.setHours(0, 0, 0, 0);
if (start.getTime() >= end.getTime()) {
end.setDate(start.getDate() + 1);
}
start = new Date(Math.max(today, start));
2016-12-11 22:41:24 -07:00
var dateTabsHtml = '';
var tabIndex = 0;
var date = new Date();
if (currentDate) {
date.setTime(currentDate.getTime());
}
2016-04-26 11:28:04 -07:00
while (start <= end) {
2016-12-11 22:41:24 -07:00
var isActive = date.getDate() === start.getDate() && date.getMonth() === start.getMonth() && date.getFullYear() === start.getFullYear();
dateTabsHtml += getDateTabText(start, isActive, tabIndex);
2016-04-26 11:28:04 -07:00
start.setDate(start.getDate() + 1);
start.setHours(0, 0, 0, 0);
2016-12-14 13:58:55 -07:00
tabIndex++;
2016-04-26 11:28:04 -07:00
}
2016-12-11 22:41:24 -07:00
page.querySelector('.emby-tabs-slider').innerHTML = dateTabsHtml;
page.querySelector('.guideDateTabs').refresh();
2016-04-26 11:28:04 -07:00
2016-12-12 15:43:07 -07:00
changeDate(page, date, layoutManager.tv);
2016-04-26 11:28:04 -07:00
}
function reloadPage(page) {
showLoading();
var apiClient = connectionManager.currentApiClient();
apiClient.getLiveTvGuideInfo().then(function (guideInfo) {
setDateRange(page, guideInfo);
});
}
2016-07-26 22:19:56 -07:00
function setScrollEvents(view, enabled) {
2016-04-26 11:28:04 -07:00
if (layoutManager.tv) {
2016-07-26 22:19:56 -07:00
require(['scrollHelper'], function (scrollHelper) {
2016-04-26 11:28:04 -07:00
2016-07-26 22:19:56 -07:00
var fn = enabled ? 'on' : 'off';
2016-12-07 14:11:13 -07:00
scrollHelper.centerFocus[fn](view.querySelector('.guideVerticalScroller'), false);
2016-07-26 22:19:56 -07:00
scrollHelper.centerFocus[fn](view.querySelector('.programGrid'), true);
});
2016-04-26 11:28:04 -07:00
}
}
function onProgramGridFocus(e) {
2016-09-27 22:11:41 -07:00
var programCell = dom.parentWithClass(e.target, 'programCell');
2016-04-26 11:28:04 -07:00
if (!programCell) {
return;
}
2016-08-29 11:42:53 -07:00
var focused = e.target;
var id = focused.getAttribute('data-id');
var item = items[id];
2016-04-26 11:28:04 -07:00
2016-08-29 11:42:53 -07:00
if (item) {
events.trigger(self, 'focus', [
{
item: item
}]);
2016-04-26 11:28:04 -07:00
}
}
2016-06-08 10:10:07 -07:00
function onTimerCreated(e, apiClient, data) {
var programId = data.ProgramId;
// This could be null, not supported by all tv providers
var newTimerId = data.Id;
// find guide cells by program id, ensure timer icon
var cells = options.element.querySelectorAll('.programCell[data-id="' + programId + '"]');
for (var i = 0, length = cells.length; i < length; i++) {
var cell = cells[i];
var icon = cell.querySelector('.timerIcon');
if (!icon) {
2016-12-17 23:18:42 -07:00
cell.insertAdjacentHTML('beforeend', '<i class="timerIcon md-icon programIcon">&#xE061;</i>');
2016-06-08 10:10:07 -07:00
}
if (newTimerId) {
cell.setAttribute('data-timerid', newTimerId);
}
}
}
function onSeriesTimerCreated(e, apiClient, data) {
}
function onTimerCancelled(e, apiClient, data) {
var id = data.Id;
// find guide cells by timer id, remove timer icon
var cells = options.element.querySelectorAll('.programCell[data-timerid="' + id + '"]');
for (var i = 0, length = cells.length; i < length; i++) {
var cell = cells[i];
2016-06-08 10:10:07 -07:00
var icon = cell.querySelector('.timerIcon');
if (icon) {
icon.parentNode.removeChild(icon);
}
cell.removeAttribute('data-timerid');
}
}
function onSeriesTimerCancelled(e, apiClient, data) {
var id = data.Id;
// find guide cells by timer id, remove timer icon
var cells = options.element.querySelectorAll('.programCell[data-seriestimerid="' + id + '"]');
for (var i = 0, length = cells.length; i < length; i++) {
var cell = cells[i];
2016-06-08 10:10:07 -07:00
var icon = cell.querySelector('.seriesTimerIcon');
if (icon) {
icon.parentNode.removeChild(icon);
}
cell.removeAttribute('data-seriestimerid');
}
}
2016-05-12 19:32:12 -07:00
require(['text!./tvguide.template.html'], function (template) {
2016-04-26 11:28:04 -07:00
var context = options.element;
2016-06-09 09:13:25 -07:00
context.innerHTML = globalize.translateDocument(template, 'sharedcomponents');
2016-04-26 11:28:04 -07:00
if (layoutManager.desktop) {
2016-12-05 11:46:38 -07:00
var guideScrollers = context.querySelectorAll('.guideScroller');
for (var i = 0, length = guideScrollers.length; i < length; i++) {
guideScrollers[i].classList.add('darkScroller');
}
}
2016-04-26 11:28:04 -07:00
var programGrid = context.querySelector('.programGrid');
var timeslotHeaders = context.querySelector('.timeslotHeaders');
programGrid.addEventListener('focus', onProgramGridFocus, true);
2016-12-07 14:11:13 -07:00
if (browser.iOS || browser.osx) {
context.querySelector('.channelsContainer').classList.add('noRubberBanding');
var programGridContainer = context.querySelector('.programGridContainer');
programGridContainer.classList.add('noRubberBanding');
programGridContainer.classList.remove('smoothScrollX');
programGridContainer.classList.add('hiddenScrollX');
}
2016-08-07 12:43:52 -07:00
dom.addEventListener(programGrid, 'scroll', function (e) {
2016-04-26 11:28:04 -07:00
onProgramGridScroll(context, this, timeslotHeaders);
2016-05-04 21:18:35 -07:00
}, {
passive: true
2016-04-26 11:28:04 -07:00
});
2016-08-07 12:43:52 -07:00
dom.addEventListener(timeslotHeaders, 'scroll', function () {
2016-04-26 11:28:04 -07:00
onTimeslotHeadersScroll(context, this, programGrid);
2016-05-04 21:18:35 -07:00
}, {
passive: true
2016-04-26 11:28:04 -07:00
});
context.querySelector('.btnUnlockGuide').addEventListener('click', function () {
2016-08-18 10:03:22 -07:00
currentStartIndex = 0;
reloadPage(context);
2016-12-07 13:03:19 -07:00
restartAutoRefresh();
2016-08-18 10:03:22 -07:00
});
context.querySelector('.btnNextPage').addEventListener('click', function () {
currentStartIndex += currentChannelLimit;
reloadPage(context);
2016-12-07 13:03:19 -07:00
restartAutoRefresh();
2016-08-18 10:03:22 -07:00
});
context.querySelector('.btnPreviousPage').addEventListener('click', function () {
currentStartIndex = Math.max(currentStartIndex - currentChannelLimit, 0);
2016-04-26 11:28:04 -07:00
reloadPage(context);
2016-12-07 13:03:19 -07:00
restartAutoRefresh();
2016-04-26 11:28:04 -07:00
});
2016-09-07 00:08:20 -07:00
context.querySelector('.btnGuideViewSettings').addEventListener('click', function () {
2016-09-05 22:02:05 -07:00
showViewSettings(self);
2016-12-07 13:03:19 -07:00
restartAutoRefresh();
2016-09-05 22:02:05 -07:00
});
2016-12-14 13:58:55 -07:00
context.querySelector('.guideDateTabs').addEventListener('tabchange', function (e) {
var tabButton = e.target.querySelectorAll('.guide-date-tab-button')[parseInt(e.detail.selectedTabIndex)];
2016-12-11 22:41:24 -07:00
if (tabButton) {
var date = new Date();
date.setTime(parseInt(tabButton.getAttribute('data-date')));
2016-12-12 15:43:07 -07:00
changeDate(context, date, false);
2016-12-11 22:41:24 -07:00
}
2016-09-27 22:11:41 -07:00
});
2016-04-26 11:28:04 -07:00
context.classList.add('tvguide');
2016-07-26 22:19:56 -07:00
setScrollEvents(context, true);
2016-04-26 11:28:04 -07:00
itemShortcuts.on(context);
2016-04-26 19:59:43 -07:00
events.trigger(self, 'load');
2016-06-08 10:10:07 -07:00
events.on(serverNotifications, 'TimerCreated', onTimerCreated);
events.on(serverNotifications, 'SeriesTimerCreated', onSeriesTimerCreated);
events.on(serverNotifications, 'TimerCancelled', onTimerCancelled);
events.on(serverNotifications, 'SeriesTimerCancelled', onSeriesTimerCancelled);
2016-04-26 11:28:04 -07:00
self.refresh();
2016-05-12 19:32:12 -07:00
});
2016-10-12 11:23:09 -07:00
}
2016-04-26 11:28:04 -07:00
return Guide;
});