mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
beginning to populate guide
This commit is contained in:
parent
6e5adce35c
commit
a043f5af6d
6 changed files with 311 additions and 52 deletions
|
@ -474,12 +474,11 @@ a.itemTag:hover {
|
||||||
|
|
||||||
.libraryPage ::-webkit-scrollbar-track-piece {
|
.libraryPage ::-webkit-scrollbar-track-piece {
|
||||||
background-color: #3b3b3b;
|
background-color: #3b3b3b;
|
||||||
-webkit-border-radius: 6px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.libraryPage ::-webkit-scrollbar-thumb:vertical {
|
.libraryPage ::-webkit-scrollbar-thumb:vertical, .libraryPage ::-webkit-scrollbar-thumb:horizontal {
|
||||||
-webkit-border-radius: 6px;
|
-webkit-border-radius: 2px;
|
||||||
background: #666 no-repeat center;
|
background: #888 no-repeat center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detailSection {
|
.detailSection {
|
||||||
|
|
|
@ -61,6 +61,10 @@
|
||||||
color: #64A239;
|
color: #64A239;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.premiereTvProgram {
|
||||||
|
color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
.sportsProgramInfo {
|
.sportsProgramInfo {
|
||||||
background-color: #0F2624;
|
background-color: #0F2624;
|
||||||
border-bottom: 2px solid #0A7C33;
|
border-bottom: 2px solid #0A7C33;
|
||||||
|
@ -124,36 +128,134 @@
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.channelTimeslotHeader {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.timeslotHeaders {
|
.timeslotHeaders {
|
||||||
|
position: absolute;
|
||||||
|
right: 13px;
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.channelPrograms {
|
||||||
|
white-space: nowrap;
|
||||||
|
height: 47px;
|
||||||
|
}
|
||||||
|
|
||||||
.timeslotHeader {
|
.timeslotHeader {
|
||||||
width: 100px;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: .5em .5em;
|
}
|
||||||
background: #38c;
|
|
||||||
|
.timeslotHeaderInner {
|
||||||
|
padding: .5em .35em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeslotCell {
|
.timeslotCell {
|
||||||
width: 100px;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: .5em .5em;
|
border-bottom: 1px solid #444;
|
||||||
|
border-left: 1px solid #444;
|
||||||
border: 1px solid #444;
|
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
display: table-cell;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channelTimeslotCell {
|
.channelHeaderCell, .channelTimeslotHeader {
|
||||||
text-align: center;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
border-bottom: 1px solid #444;
|
||||||
|
border-left: 1px solid #444;
|
||||||
|
border-right: 1px solid #444;
|
||||||
|
width: 139px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.channelTimeslotHeader, .channelTimeslotCell {
|
.channelTimeslotHeader, .timeslotHeader {
|
||||||
width: 80px;
|
background: #1d1d1d;
|
||||||
color: #ddd;
|
border-bottom: 1px solid #333;
|
||||||
|
border-left: 1px solid #333;
|
||||||
|
border-top: 1px solid #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeslotHeader, .channelTimeslotHeader {
|
||||||
|
height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channelHeaderCellInner {
|
||||||
|
padding: .5em .5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channelList {
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: hidden;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.programGrid {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeslotCell, .timeslotHeader {
|
||||||
|
width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeslotCellInner {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeslotHeaders, .programGrid {
|
||||||
|
left: 141px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channelTimeslotHeader, .timeslotHeaders {
|
||||||
|
top: 135px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channelList, .programGrid {
|
||||||
|
top: 165px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channelHeaderCell, .timeslotCell {
|
||||||
|
height: 46px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guideProgramName {
|
||||||
|
padding: .35em .5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guideProgramTime {
|
||||||
|
padding: 0 .5em .35em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
|
||||||
|
.channelHeaderCell, .channelTimeslotHeader {
|
||||||
|
width: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeslotHeaders, .programGrid {
|
||||||
|
left: 91px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Account for hidden navigation */
|
||||||
|
@media (max-width: 750px) {
|
||||||
|
|
||||||
|
.channelTimeslotHeader, .timeslotHeaders {
|
||||||
|
top: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channelList, .programGrid {
|
||||||
|
top: 130px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.guideChannel {
|
|
||||||
}
|
|
|
@ -44,11 +44,6 @@ body {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
|
||||||
text-shadow: none;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
font-size: 2.22em;
|
font-size: 2.22em;
|
||||||
|
|
|
@ -12,15 +12,26 @@
|
||||||
<a href="livetvtimers.html">Scheduled</a>
|
<a href="livetvtimers.html">Scheduled</a>
|
||||||
<a href="livetvseriestimers.html">Series</a>
|
<a href="livetvseriestimers.html">Series</a>
|
||||||
</div>
|
</div>
|
||||||
<div data-role="content">
|
<div data-role="content" style="padding-top: 5px;">
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h2 class="detailSectionHeader tvProgramSectionHeader guideDate"></h2>
|
<div>
|
||||||
|
<select id="selectDate" data-mini="true" data-icon="calendar">
|
||||||
|
<option>Today</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div style="overflow-x: scroll;overflow-y:scroll;position:absolute;right: 1em;left: 1em;top: 135px;bottom: 30px;">
|
<div>
|
||||||
|
<div class="channelTimeslotHeader"> </div>
|
||||||
|
<div class="timeslotHeaders"></div>
|
||||||
|
<div class="channelList"></div>
|
||||||
|
<div class="programGrid">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div style="overflow-x: scroll;overflow-y:scroll;position:absolute;right: 1em;left: 1em;top: 135px;bottom: 30px;">
|
||||||
<div class="timeslotHeaders"></div>
|
<div class="timeslotHeaders"></div>
|
||||||
<div id="guide"></div>
|
<div id="guide"></div>
|
||||||
</div>
|
</div>-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
html += '<span class="liveTvProgram">LIVE </span>';
|
html += '<span class="liveTvProgram">LIVE </span>';
|
||||||
}
|
}
|
||||||
else if (program.IsPremiere) {
|
else if (program.IsPremiere) {
|
||||||
html += '<span class="liveTvProgram">PREMIERE </span>';
|
html += '<span class="premiereTvProgram">PREMIERE </span>';
|
||||||
}
|
}
|
||||||
else if (program.IsSeries && !program.IsRepeat) {
|
else if (program.IsSeries && !program.IsRepeat) {
|
||||||
html += '<span class="newTvProgram">NEW </span>';
|
html += '<span class="newTvProgram">NEW </span>';
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
(function ($, document, apiClient) {
|
(function ($, document, apiClient) {
|
||||||
|
|
||||||
|
// 30 mins
|
||||||
|
var cellDurationMs = 30 * 60 * 1000;
|
||||||
|
|
||||||
function formatDigit(i) {
|
function formatDigit(i) {
|
||||||
return i < 10 ? "0" + i : i;
|
return i < 10 ? "0" + i : i;
|
||||||
}
|
}
|
||||||
|
@ -29,6 +32,8 @@
|
||||||
|
|
||||||
date.setTime(date.getTime() - (date.getSeconds() * 1000));
|
date.setTime(date.getTime() - (date.getSeconds() * 1000));
|
||||||
|
|
||||||
|
date.setHours(date.getHours(), date.getMinutes(), 0, 0);
|
||||||
|
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,14 +51,14 @@
|
||||||
var date = currentDate;
|
var date = currentDate;
|
||||||
|
|
||||||
var nextDay = new Date(date.getTime());
|
var nextDay = new Date(date.getTime());
|
||||||
nextDay.setDate(nextDay.getDate() + 1);
|
nextDay.setDate(nextDay.getDate() + 2);
|
||||||
nextDay.setHours(1, 0, 0, 0);
|
nextDay.setHours(1, 0, 0, 0);
|
||||||
|
|
||||||
var promise1 = channelsPromise;
|
var promise1 = channelsPromise;
|
||||||
var promise2 = apiClient.getLiveTvPrograms({
|
var promise2 = apiClient.getLiveTvPrograms({
|
||||||
|
|
||||||
UserId: Dashboard.getCurrentUserId(),
|
UserId: Dashboard.getCurrentUserId(),
|
||||||
MaxEndDate: getDateFormat(nextDay)
|
MaxStartDate: getDateFormat(nextDay)
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -66,69 +71,216 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderDate(page, date) {
|
|
||||||
|
|
||||||
$('.guideDate', page).html(LibraryBrowser.getFutureDateText(date));
|
|
||||||
|
|
||||||
$('.timeslotHeaders', page).html(getTimeslotHeadersHtml(date));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTimeslotHeadersHtml(date) {
|
function getTimeslotHeadersHtml(date) {
|
||||||
|
|
||||||
var html = '';
|
var html = '';
|
||||||
|
|
||||||
html += '<div class="timeslotHeader channelTimeslotHeader"> </div>';
|
|
||||||
|
|
||||||
date = new Date(date.getTime());
|
date = new Date(date.getTime());
|
||||||
var dateNumber = date.getDate();
|
var dateNumber = date.getDate();
|
||||||
|
|
||||||
while (date.getDate() == dateNumber) {
|
while (date.getDate() == dateNumber) {
|
||||||
|
|
||||||
html += '<div class="timeslotHeader">';
|
html += '<div class="timeslotHeader">';
|
||||||
|
html += '<div class="timeslotHeaderInner">';
|
||||||
html += LiveTvHelpers.getDisplayTime(date);
|
html += LiveTvHelpers.getDisplayTime(date);
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
// Add 30 mins
|
// Add 30 mins
|
||||||
date.setTime(date.getTime() + (30 * 60 * 1000));
|
date.setTime(date.getTime() + cellDurationMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getChannelHtml(page, date, channel, programs) {
|
function findProgramStartingInCell(programs, startIndex, cellStart, cellEnd, cellIndex) {
|
||||||
|
|
||||||
|
for (var i = startIndex, length = programs.length; i < length; i++) {
|
||||||
|
|
||||||
|
var program = programs[i];
|
||||||
|
|
||||||
|
if (!program.StartDateLocal) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
program.StartDateLocal = parseISO8601Date(program.StartDate, { toLocal: true });
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!program.EndDateLocal) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
program.EndDateLocal = parseISO8601Date(program.EndDate, { toLocal: true });
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var localTime = program.StartDateLocal.getTime();
|
||||||
|
if ((localTime >= cellStart || cellIndex == 0) && localTime < cellEnd && program.EndDateLocal > cellStart) {
|
||||||
|
|
||||||
|
return {
|
||||||
|
|
||||||
|
index: i,
|
||||||
|
program: program
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getChannelProgramsHtml(page, date, channel, programs) {
|
||||||
|
|
||||||
var html = '';
|
var html = '';
|
||||||
|
|
||||||
html += '<div class="guideChannel">';
|
var dateNumber = date.getDate();
|
||||||
|
|
||||||
html += '<div class="timeslotCell channelTimeslotCell">';
|
programs = programs.filter(function (curr) {
|
||||||
html += channel.Name + '<br/>' + channel.Number;
|
return curr.ChannelId == channel.Id;
|
||||||
html += '</div>';
|
});
|
||||||
|
|
||||||
|
html += '<div class="channelPrograms">';
|
||||||
|
|
||||||
|
var programIndex = 0;
|
||||||
|
var cellIndex = 0;
|
||||||
|
|
||||||
|
while (date.getDate() == dateNumber) {
|
||||||
|
|
||||||
|
// Add 30 mins
|
||||||
|
var cellEndDate = new Date(date.getTime() + cellDurationMs);
|
||||||
|
|
||||||
|
var program = findProgramStartingInCell(programs, programIndex, date, cellEndDate, cellIndex);
|
||||||
|
|
||||||
|
if (program) {
|
||||||
|
programIndex = program.index + 1;
|
||||||
|
program = program.program;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '<div class="timeslotCell">';
|
||||||
|
|
||||||
|
var cssClass = "timeslotCellInner";
|
||||||
|
|
||||||
|
if (program) {
|
||||||
|
if (program.IsKids) {
|
||||||
|
cssClass += " childProgramInfo";
|
||||||
|
}
|
||||||
|
else if (program.IsSports) {
|
||||||
|
cssClass += " sportsProgramInfo";
|
||||||
|
}
|
||||||
|
else if (program.IsNews) {
|
||||||
|
cssClass += " newsProgramInfo";
|
||||||
|
}
|
||||||
|
else if (program.IsMovie) {
|
||||||
|
cssClass += " movieProgramInfo";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '<div class="' + cssClass + '">';
|
||||||
|
|
||||||
|
if (program) {
|
||||||
|
|
||||||
|
html += '<div class="guideProgramName">';
|
||||||
|
html += program.Name;
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '<div class="guideProgramTime">';
|
||||||
|
|
||||||
|
if (program.IsLive) {
|
||||||
|
html += '<span class="liveTvProgram">LIVE </span>';
|
||||||
|
}
|
||||||
|
else if (program.IsPremiere) {
|
||||||
|
html += '<span class="premiereTvProgram">PREMIERE </span>';
|
||||||
|
}
|
||||||
|
else if (program.IsSeries && !program.IsRepeat) {
|
||||||
|
html += '<span class="newTvProgram">NEW </span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
html += LiveTvHelpers.getDisplayTime(program.StartDateLocal);
|
||||||
|
html += ' - ';
|
||||||
|
html += LiveTvHelpers.getDisplayTime(program.EndDateLocal);
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
html += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
date = cellEndDate;
|
||||||
|
cellIndex++;
|
||||||
|
}
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderChannels(page, date, channels, programs) {
|
function renderPrograms(page, date, channels, programs) {
|
||||||
|
|
||||||
var html = [];
|
var html = [];
|
||||||
|
|
||||||
for (var i = 0, length = channels.length; i < length; i++) {
|
for (var i = 0, length = channels.length; i < length; i++) {
|
||||||
|
|
||||||
html.push(getChannelHtml(page, date, channels[i], programs));
|
html.push(getChannelProgramsHtml(page, date, channels[i], programs));
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#guide', page).html(html.join(''));
|
$('.programGrid', page).html(html.join(''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderChannelHeaders(page, channels) {
|
||||||
|
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
for (var i = 0, length = channels.length; i < length; i++) {
|
||||||
|
|
||||||
|
var channel = channels[i];
|
||||||
|
|
||||||
|
html += '<div class="channelHeaderCellContainer">';
|
||||||
|
|
||||||
|
html += '<div class="channelHeaderCell"><div class="channelHeaderCellInner">';
|
||||||
|
html += channel.Name + '<br/>' + channel.Number;
|
||||||
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.channelList', page).html(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderGuide(page, date, channels, programs) {
|
function renderGuide(page, date, channels, programs) {
|
||||||
|
|
||||||
renderDate(page, date);
|
renderChannelHeaders(page, channels);
|
||||||
renderChannels(page, date, channels, programs);
|
$('.timeslotHeaders', page).html(getTimeslotHeadersHtml(date));
|
||||||
|
renderPrograms(page, date, channels, programs);
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).on('pagebeforeshow', "#liveTvGuidePage", function () {
|
function onProgramGridScroll(page, elem) {
|
||||||
|
|
||||||
|
var grid = $(elem);
|
||||||
|
|
||||||
|
grid.prev().scrollTop(grid.scrollTop());
|
||||||
|
$('.timeslotHeaders', page).scrollLeft(grid.scrollLeft());
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).on('pageinit', "#liveTvGuidePage", function () {
|
||||||
|
|
||||||
|
var page = this;
|
||||||
|
|
||||||
|
$('.programGrid', page).on('scroll', function () {
|
||||||
|
|
||||||
|
onProgramGridScroll(page, this);
|
||||||
|
});
|
||||||
|
|
||||||
|
}).on('pagebeforeshow', "#liveTvGuidePage", function () {
|
||||||
|
|
||||||
var page = this;
|
var page = this;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue