jekyll-theme-conference 3.0.4 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +44 -4
- data/_includes/js/conference-live.js +99 -26
- data/_includes/js/conference-map.js +1 -1
- data/_includes/js/conference-modal.js +4 -4
- data/_includes/js/conference-program.js +1 -1
- data/_includes/js/syncscroll.js +1 -1
- data/_includes/partials/modal_live.html +2 -2
- data/_includes/partials/navbar.html +12 -1
- data/_includes/partials/show_live_button.html +5 -1
- data/_layouts/data.html +21 -9
- data/_layouts/home.html +1 -1
- data/_layouts/page.html +4 -0
- data/_layouts/stream-overview.html +42 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d71db73a3994c514ebc0e7e8bd0c96905deb68f38dce861dd4bc21ba56b730ae
|
4
|
+
data.tar.gz: a4e171604b41298e1ecb60ffe429a4b2ae2bb9ff961d01ea0be35230ba635903
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 90add66ec86e0c30982031847189e4874a48cf7e0f5982350026fa8935464ff1465351af4a77cfb5e6e0d9ff8e9de1f5224e69b25efe93557008017a18a2fb31
|
7
|
+
data.tar.gz: 33f11b1a586ec07e1155b25bbab2461541a97c77a813d5ee72e60252e547392eb6c309282d4edfbb53b37b59d910b7213e27242d254e116fd27ee0c07546e666
|
data/README.md
CHANGED
@@ -18,6 +18,41 @@ The theme was originally created for the yearly Winterkongress conference of the
|
|
18
18
|
- [Demo: Winterkongress](https://digitale-gesellschaft.ch/kongress/)
|
19
19
|
|
20
20
|
|
21
|
+
## Table of Contents
|
22
|
+
|
23
|
+
- [Installation](#installation)
|
24
|
+
* [Gem-based Method](#gem-based-method)
|
25
|
+
* [Remote Theme Method](#remote-theme-method)
|
26
|
+
- [Setup](#setup)
|
27
|
+
* [Jump Start](#jump-start)
|
28
|
+
* [Automatic Import](#automatic-import)
|
29
|
+
* [Automatic Build](#automatic-build)
|
30
|
+
- [Configuration](#configuration)
|
31
|
+
* [Theme Verification](#theme-verification)
|
32
|
+
* [Collection URLs](#collection-urls)
|
33
|
+
* [Language](#language)
|
34
|
+
* [Navigation Bar](#navigation-bar)
|
35
|
+
* [Main Landing Page](#main-landing-page)
|
36
|
+
* [Information Boxes](#information-boxes)
|
37
|
+
* [Live Indications & Streaming](#live-indications---streaming)
|
38
|
+
* [Talk Settings](#talk-settings)
|
39
|
+
* [Speaker Settings](#speaker-settings)
|
40
|
+
* [Location Settings](#location-settings)
|
41
|
+
* [Program Settings](#program-settings)
|
42
|
+
- [Content](#content)
|
43
|
+
* [Schedule / Program](#schedule---program)
|
44
|
+
* [Talks](#talks)
|
45
|
+
* [Speakers](#speakers)
|
46
|
+
* [Rooms](#rooms)
|
47
|
+
* [Links](#links)
|
48
|
+
- [Overview Pages](#overview-pages)
|
49
|
+
* [Location / Room Overview](#location---room-overview)
|
50
|
+
* [Live Stream Overview](#live-stream-overview)
|
51
|
+
* [Additional Pages](#additional-pages)
|
52
|
+
- [Design](#design)
|
53
|
+
- [License](#license)
|
54
|
+
|
55
|
+
|
21
56
|
## Installation
|
22
57
|
|
23
58
|
There are three ways to install: As a [Gem-based theme](https://jekyllrb.com/docs/themes/#understanding-gem-based-themes), as a [remote theme](https://github.blog/2017-11-29-use-any-theme-with-github-pages/) (GitHub Pages compatible), or by cloning/forking this repository and reference to it directly.
|
@@ -130,7 +165,7 @@ There exists a Python file in this repository, `_tools/create_entries.py`, which
|
|
130
165
|
|
131
166
|
In case you do not want to install the entire Ruby/Jekyll toolchain on your machine you can make use of [GitHub Actions](https://github.com/features/actions), Github's continuous integration platform. This repository contains multiple example Github Action configuration files in the `_tools/` folder:
|
132
167
|
|
133
|
-
- `build.yml`: automatically builds and minimizes the website upon adding a new tag starting with a `v` (e.g. `v2020.01.01`). It then attaches the generated website as an archive to a release for easy downloading.
|
168
|
+
- `build.yml`: automatically builds and minimizes the website upon adding a new tag starting with a `v` (e.g. `v2020.01.01`). It then attaches the generated website as an archive to a release for easy downloading. Requires `purgecss.config.js` to be copied to the project's root too.
|
134
169
|
- `test.yml`: automatically tries to build the website upon a new pull request. It can thus be used as status check before merging.
|
135
170
|
- `schedule.yml`: automatically generates the schedule and content files when a new pull request contains a `schedule.json` file (see the _Automatic Import_subsection above). Thus, it allows quick updates of the site's content from [pretalx.com](https://pretalx.com/p/about/) exports.
|
136
171
|
|
@@ -319,15 +354,16 @@ conference:
|
|
319
354
|
|
320
355
|
In order to help users navigating the program during the congress, a _Live_ indication can be shown next to talks which are currently taking place. A small JavaScript functions keeps the site automatically up-to-date (without the need to refresh) showing the indication as soon as the talk has started and hiding it once it is over (according to the timetable indicated in the `_data/program.yml` file).
|
321
356
|
|
322
|
-
This can be further extended if some of the talks have an associated live stream: Upon clicking one of the live indications a modal will open containing the corresponding live stream embedded. The URL to the live stream has to be set via `live` property in each room (see the _Content_ > _Room_ section below).
|
357
|
+
This can be further extended if some of the talks have an associated live stream: Upon clicking one of the live indications a modal will open containing the corresponding live stream embedded. The URL to the live stream has to be set via `live` property in each room (see the _Content_ > _Room_ section below). Instead of opening the modal an external link can also be used.
|
323
358
|
|
324
359
|
In order to activate the functionality, each day in the `program.yml` file must contain a `date` property (see section _Content_ > _Schedule / Program_ below) and the `live` property has to be set in the configuration file containing
|
325
360
|
|
326
361
|
- how long a pause between two consecutive talks has to be for the live indication to pause (`time_stop`),
|
327
362
|
- optionally if streaming is enabled (`streaming`) with indications
|
328
363
|
+ how many minutes the stream goes active before a talk (`time_prepend`),
|
329
|
-
+ how many minutes the stream stays active after a talk (`time_extend`),
|
330
|
-
+ how long a pause between two consecutive talks has to be for the stream to pause (`time_pause`),
|
364
|
+
+ how many minutes the stream stays active after a talk (`time_extend`),
|
365
|
+
+ how long a pause between two consecutive talks has to be for the stream to pause (`time_pause`), and
|
366
|
+
+ optionally an external (absolute) link to which the user will be redirected instead of opening the modal (`external`),
|
331
367
|
- optionally a demo mode setting, whereby the JavaScript function cycles through the entire program in five minutes for demonstration purposes (`demo: true`, default: `false`).
|
332
368
|
|
333
369
|
```yaml
|
@@ -587,6 +623,10 @@ If you choose a different location for the overview pages you must:
|
|
587
623
|
|
588
624
|
The `location` layout contains a map container (if not disabled, see section _Location Settings_ above) which can be customized. See the section above for further details.
|
589
625
|
|
626
|
+
### Live Stream Overview
|
627
|
+
|
628
|
+
The `stream-overview` layout contains all active streams on a single page (see the section _Live Indications & Streaming_ above).
|
629
|
+
|
590
630
|
### Additional Pages
|
591
631
|
|
592
632
|
Additional static pages can easily be added as files and linked to via navigation bar or main landing page (see above on how to).
|
@@ -35,35 +35,42 @@ window.conference.live = (function() {
|
|
35
35
|
let streamInfoTimer;
|
36
36
|
|
37
37
|
let loadData = function () {
|
38
|
+
// Fetch schedule from external file
|
38
39
|
$.getJSON('{{ site.baseurl }}/assets/js/data.json', function(json) {
|
39
40
|
data = json;
|
40
41
|
});
|
41
42
|
};
|
42
43
|
|
43
44
|
let getData = function () {
|
45
|
+
// Return data
|
44
46
|
return data;
|
45
47
|
};
|
46
48
|
|
47
49
|
let mod = function (n, m) {
|
50
|
+
// Absolute modulo
|
48
51
|
return ((n % m) + m) % m;
|
49
52
|
};
|
50
53
|
|
51
54
|
let timeNow = function () {
|
55
|
+
// Current timestamp in seconds
|
52
56
|
return Math.floor(Date.now() / 1000);
|
53
57
|
};
|
54
58
|
|
55
59
|
let timeCont = function () {
|
60
|
+
// Continuous time (respecting previous pauses)
|
56
61
|
return timeNow() - timeOffset;
|
57
62
|
};
|
58
63
|
|
59
64
|
let timeCycle = function () {
|
65
|
+
// Cyclic timestamp in seconds
|
60
66
|
let actTime = timeNow();
|
61
|
-
let relTime = mod(actTime, durDemo + 2*durPause) / durDemo;
|
67
|
+
let relTime = mod(actTime, durDemo + 2*durPause) / (durDemo + 2*durPause);
|
62
68
|
let cycleTime = mod((demoEnd - demoStart) * relTime - timeOffset, (demoEnd - demoStart)) + demoStart;
|
63
69
|
return cycleTime;
|
64
70
|
};
|
65
71
|
|
66
72
|
let time = function () {
|
73
|
+
// Return app time
|
67
74
|
if (freezeTime) {
|
68
75
|
return timeFrozen;
|
69
76
|
}
|
@@ -76,6 +83,7 @@ window.conference.live = (function() {
|
|
76
83
|
};
|
77
84
|
|
78
85
|
let pauseTime = function () {
|
86
|
+
// Pause app time
|
79
87
|
if (!freezeTime) {
|
80
88
|
timeFrozen = time();
|
81
89
|
freezeTime = true;
|
@@ -85,6 +93,7 @@ window.conference.live = (function() {
|
|
85
93
|
};
|
86
94
|
|
87
95
|
let continueTime = function () {
|
96
|
+
// Continue app time
|
88
97
|
if (freezeTime) {
|
89
98
|
freezeTime = false;
|
90
99
|
timeOffset += time() - timeFrozen;
|
@@ -92,18 +101,23 @@ window.conference.live = (function() {
|
|
92
101
|
}
|
93
102
|
};
|
94
103
|
|
95
|
-
let resetTime = function (
|
104
|
+
let resetTime = function () {
|
105
|
+
// Reset app time
|
96
106
|
timeOffset = 0;
|
97
107
|
freezeTime = false;
|
98
108
|
|
99
109
|
startUpdate();
|
100
110
|
};
|
101
111
|
|
102
|
-
let setTime = function (newTime, newDay
|
112
|
+
let setTime = function (newTime, newDay) {
|
113
|
+
// Set and pause app time
|
103
114
|
pauseTime();
|
104
115
|
|
105
116
|
let dayIdx;
|
106
|
-
if (
|
117
|
+
if (arguments.length < 2) {
|
118
|
+
dayIdx = 0;
|
119
|
+
}
|
120
|
+
else if (Number.isInteger(newDay)) {
|
107
121
|
dayIdx = newDay-1;
|
108
122
|
}
|
109
123
|
else if (/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test(newDay)) {
|
@@ -112,7 +126,7 @@ window.conference.live = (function() {
|
|
112
126
|
else {
|
113
127
|
dayIdx = data.days.find(o => o.name === newDay);
|
114
128
|
}
|
115
|
-
newDate = data.days[dayIdx].date;
|
129
|
+
let newDate = data.days[dayIdx].date;
|
116
130
|
|
117
131
|
let d = new Date(newDate);
|
118
132
|
newTime = newTime.split(':');
|
@@ -123,7 +137,10 @@ window.conference.live = (function() {
|
|
123
137
|
update();
|
124
138
|
};
|
125
139
|
|
126
|
-
let getTime = function (
|
140
|
+
let getTime = function () {
|
141
|
+
// Return app time as string
|
142
|
+
let tConvert = time();
|
143
|
+
|
127
144
|
let d = new Date(tConvert * 1000);
|
128
145
|
let dStr = d.toISOString().slice(0,10);
|
129
146
|
let h = d.getHours();
|
@@ -133,6 +150,7 @@ window.conference.live = (function() {
|
|
133
150
|
};
|
134
151
|
|
135
152
|
let timeUnit = function () {
|
153
|
+
// App time refresh rate
|
136
154
|
if (demo) {
|
137
155
|
return 0.1;
|
138
156
|
}
|
@@ -142,6 +160,7 @@ window.conference.live = (function() {
|
|
142
160
|
};
|
143
161
|
|
144
162
|
let delayStart = function (startTime) {
|
163
|
+
// Seconds until given startTime occurs
|
145
164
|
let tNow = time();
|
146
165
|
let tUnit = timeUnit();
|
147
166
|
|
@@ -161,21 +180,25 @@ window.conference.live = (function() {
|
|
161
180
|
};
|
162
181
|
|
163
182
|
let toggleDemo = function () {
|
183
|
+
// Toggle app demo mode
|
164
184
|
demo = !demo;
|
165
185
|
resetTime();
|
166
186
|
};
|
167
187
|
|
168
188
|
let demoOn = function () {
|
189
|
+
// Return app demo status
|
169
190
|
return demo;
|
170
191
|
};
|
171
192
|
|
172
193
|
let updateLive = function () {
|
194
|
+
// Update status all live elements in DOM
|
173
195
|
let tNow = time();
|
174
196
|
let liveShow = document.getElementsByClassName('live-show');
|
175
197
|
let liveHide = document.getElementsByClassName('live-hide');
|
176
198
|
let liveTime = document.getElementsByClassName('live-time');
|
177
199
|
let livePast = document.getElementsByClassName('live-past');
|
178
200
|
|
201
|
+
// Show elements for a given period
|
179
202
|
for (let i = 0; i < liveShow.length; i++) {
|
180
203
|
let tStarts = liveShow[i].dataset.start.split(',');
|
181
204
|
let tEnds = liveShow[i].dataset.end.split(',');
|
@@ -193,6 +216,7 @@ window.conference.live = (function() {
|
|
193
216
|
}
|
194
217
|
}
|
195
218
|
|
219
|
+
// Hide elements for a given period
|
196
220
|
for (let i = 0; i < liveHide.length; i++) {
|
197
221
|
let tStarts = liveHide[i].dataset.start.split(',');
|
198
222
|
let tEnds = liveHide[i].dataset.end.split(',');
|
@@ -212,6 +236,7 @@ window.conference.live = (function() {
|
|
212
236
|
}
|
213
237
|
}
|
214
238
|
|
239
|
+
// Update duration string for given elements
|
215
240
|
for (let i = 0; i < liveTime.length; i++) {
|
216
241
|
let t = liveTime[i].dataset.time;
|
217
242
|
if (typeof t == "undefined") {
|
@@ -271,6 +296,7 @@ window.conference.live = (function() {
|
|
271
296
|
liveTime[i].innerHTML = tStr;
|
272
297
|
}
|
273
298
|
|
299
|
+
// Disable elements for a given period
|
274
300
|
for (let i = 0; i < livePast.length; i++) {
|
275
301
|
let t = livePast[i].dataset.time;
|
276
302
|
if (typeof t == "undefined") {
|
@@ -290,13 +316,14 @@ window.conference.live = (function() {
|
|
290
316
|
}
|
291
317
|
}
|
292
318
|
|
319
|
+
// Cancel timer after program is over
|
293
320
|
if (tNow > confEnd && !demo) {
|
294
|
-
// Cancel timer after program is over
|
295
321
|
stopUpdateLive();
|
296
322
|
}
|
297
323
|
};
|
298
324
|
|
299
325
|
let startUpdateLive = function () {
|
326
|
+
// Start update timer to update live elements in DOM
|
300
327
|
stopUpdateLive();
|
301
328
|
updateLive();
|
302
329
|
|
@@ -313,6 +340,7 @@ window.conference.live = (function() {
|
|
313
340
|
};
|
314
341
|
|
315
342
|
let stopUpdateLive = function () {
|
343
|
+
// stopUpdate update timer to update live elements in DOM
|
316
344
|
if (typeof liveTimer !== "undefined") {
|
317
345
|
clearInterval(liveTimer);
|
318
346
|
}
|
@@ -326,6 +354,7 @@ window.conference.live = (function() {
|
|
326
354
|
let streamModal;
|
327
355
|
|
328
356
|
let getRoom = function (roomName) {
|
357
|
+
// Return room object for given room name
|
329
358
|
if (roomName in data.rooms) {
|
330
359
|
return data.rooms[roomName];
|
331
360
|
}
|
@@ -334,11 +363,21 @@ window.conference.live = (function() {
|
|
334
363
|
}
|
335
364
|
};
|
336
365
|
|
366
|
+
let getTalks = function (roomName) {
|
367
|
+
if (roomName in data.talks) {
|
368
|
+
return data.talks[roomName];
|
369
|
+
}
|
370
|
+
else {
|
371
|
+
return false;
|
372
|
+
}
|
373
|
+
};
|
374
|
+
|
337
375
|
let getNextTalk = function (roomName) {
|
376
|
+
// Get talk object for next talk in given room
|
338
377
|
let timeNow = time();
|
339
|
-
let talksHere =
|
378
|
+
let talksHere = getTalks(roomName);
|
340
379
|
|
341
|
-
if (
|
380
|
+
if (talksHere) {
|
342
381
|
if (timeNow < talksHere[talksHere.length-1].end) {
|
343
382
|
for (var i = 0; i < talksHere.length; i++) {
|
344
383
|
if (timeNow < talksHere[i].end) {
|
@@ -351,10 +390,11 @@ window.conference.live = (function() {
|
|
351
390
|
};
|
352
391
|
|
353
392
|
let getNextPause = function (roomName) {
|
393
|
+
// Get time object for next pause in given room
|
354
394
|
let timeNow = time();
|
355
|
-
let talksHere =
|
395
|
+
let talksHere = getTalks(roomName);
|
356
396
|
|
357
|
-
if (
|
397
|
+
if (talksHere) {
|
358
398
|
if (timeNow < talksHere[talksHere.length-1].end) {
|
359
399
|
for (var i = 1; i < talksHere.length; i++) {
|
360
400
|
if (timeNow < talksHere[i].start && streamPause*60 <= talksHere[i].start - talksHere[i-1].end) {
|
@@ -369,25 +409,49 @@ window.conference.live = (function() {
|
|
369
409
|
return false;
|
370
410
|
};
|
371
411
|
|
372
|
-
let
|
412
|
+
let setStreamIframeContent = function (content) {
|
413
|
+
// Set stream modal iframe to show given text
|
373
414
|
streamModal.find('iframe').attr('src', '');
|
374
415
|
streamModal.find('iframe').addClass('d-none');
|
375
416
|
streamModal.find('#stream-placeholder > div').text(content);
|
376
417
|
streamModal.find('#stream-placeholder').addClass('d-flex');
|
377
418
|
};
|
378
419
|
|
379
|
-
let
|
420
|
+
let setStreamIframeSrc = function (href) {
|
421
|
+
// Set stream modal iframe to show given URL
|
380
422
|
streamModal.find('iframe').attr('src', href);
|
381
423
|
streamModal.find('#stream-placeholder').addClass('d-none').removeClass('d-flex');
|
382
424
|
streamModal.find('iframe').removeClass('d-none');
|
383
425
|
};
|
384
426
|
|
385
427
|
let setStreamVideo = function (roomName) {
|
428
|
+
// Update stream modal iframe:
|
429
|
+
// Show stream with start/pause/end message (for given room) and keep updated
|
386
430
|
let timeNow = time();
|
387
431
|
|
388
|
-
let talksHere =
|
389
|
-
let roomStart
|
390
|
-
|
432
|
+
let talksHere = getTalks(roomName);
|
433
|
+
let roomStart, roomEnd;
|
434
|
+
if (talksHere) {
|
435
|
+
roomStart = talksHere[0].start;
|
436
|
+
roomEnd = talksHere[talksHere.length-1].end;
|
437
|
+
}
|
438
|
+
else {
|
439
|
+
// If no program for given room, take overall first and last talk
|
440
|
+
roomStart = 0;
|
441
|
+
roomEnd = 0;
|
442
|
+
for (let roomNameTalk in data.talks) {
|
443
|
+
talksHere = getTalks(roomNameTalk);
|
444
|
+
let crntRoomStart = talksHere[0].start;
|
445
|
+
let crntRoomEnd = talksHere[talksHere.length-1].end;
|
446
|
+
|
447
|
+
if (roomStart == 0 || roomStart > crntRoomStart) {
|
448
|
+
roomStart = crntRoomStart;
|
449
|
+
}
|
450
|
+
if (roomEnd == 0 || roomEnd < crntRoomEnd) {
|
451
|
+
roomEnd = crntRoomEnd;
|
452
|
+
}
|
453
|
+
}
|
454
|
+
}
|
391
455
|
|
392
456
|
if (typeof streamVideoTimer !== "undefined") {
|
393
457
|
clearInterval(streamVideoTimer);
|
@@ -395,7 +459,7 @@ window.conference.live = (function() {
|
|
395
459
|
|
396
460
|
// Conference not yet started
|
397
461
|
if (timeNow < roomStart - streamPrepend*60) {
|
398
|
-
|
462
|
+
setStreamIframeContent('{{ site.data.lang[site.conference.lang].live.pre_stream | default: "Live stream has not started yet." }}');
|
399
463
|
|
400
464
|
if (!freezeTime) {
|
401
465
|
streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomStart - streamPrepend*60) * 1000, roomName);
|
@@ -404,7 +468,7 @@ window.conference.live = (function() {
|
|
404
468
|
|
405
469
|
// Conference is over
|
406
470
|
else if (timeNow > roomEnd + streamExtend*60) {
|
407
|
-
|
471
|
+
setStreamIframeContent('{{ site.data.lang[site.conference.lang].live.post_stream | default: "Live stream has ended." }}');
|
408
472
|
|
409
473
|
if (!freezeTime && demo) {
|
410
474
|
streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomEnd - streamPrepend*60) * 1000, roomName);
|
@@ -417,7 +481,7 @@ window.conference.live = (function() {
|
|
417
481
|
|
418
482
|
// Currently stream is paused
|
419
483
|
if (pauseNext && timeNow >= pauseNext.start + streamExtend*60 && timeNow <= pauseNext.end - streamPrepend*60) {
|
420
|
-
|
484
|
+
setStreamIframeContent('{{ site.data.lang[site.conference.lang].live.pause_stream | default: "Live stream is currently paused." }}');
|
421
485
|
|
422
486
|
if (!freezeTime) {
|
423
487
|
streamVideoTimer = setTimeout(setStreamVideo, delayStart(pauseNext.end - streamPrepend*60) * 1000, roomName);
|
@@ -426,7 +490,7 @@ window.conference.live = (function() {
|
|
426
490
|
// Currently a talk is active
|
427
491
|
else {
|
428
492
|
let room = getRoom(roomName);
|
429
|
-
|
493
|
+
setStreamIframeSrc(room.href);
|
430
494
|
|
431
495
|
if (!freezeTime) {
|
432
496
|
if (pauseNext) {
|
@@ -441,6 +505,8 @@ window.conference.live = (function() {
|
|
441
505
|
};
|
442
506
|
|
443
507
|
let setStreamInfo = function (roomName) {
|
508
|
+
// Update stream modal info bar:
|
509
|
+
// Show next talk and speaker (for given room) and keep updated
|
444
510
|
let timeNow = time();
|
445
511
|
let talkNext = getNextTalk(roomName);
|
446
512
|
|
@@ -448,7 +514,7 @@ window.conference.live = (function() {
|
|
448
514
|
clearInterval(streamInfoTimer);
|
449
515
|
}
|
450
516
|
|
451
|
-
if (timeNow >= talkNext.start - streamPause*60) {
|
517
|
+
if (talkNext && timeNow >= talkNext.start - streamPause*60) {
|
452
518
|
document.getElementById('stream-info').dataset.time = talkNext.start;
|
453
519
|
document.getElementById('stream-info-time').dataset.time = talkNext.start;
|
454
520
|
updateLive();
|
@@ -487,14 +553,17 @@ window.conference.live = (function() {
|
|
487
553
|
streamInfoTimer = setTimeout(setStreamInfo, delayStart(talkNext.start - streamPause*60) * 1000, roomName);
|
488
554
|
}
|
489
555
|
else if (demo) {
|
490
|
-
let talksHere =
|
491
|
-
|
556
|
+
let talksHere = getTalks(roomName);
|
557
|
+
if (talksHere) {
|
558
|
+
streamInfoTimer = setTimeout(setStreamInfo, delayStart(talksHere[0].start - streamPrepend*60) * 1000, roomName);
|
559
|
+
}
|
492
560
|
}
|
493
561
|
}
|
494
562
|
}
|
495
563
|
};
|
496
564
|
|
497
565
|
let setStream = function (roomName) {
|
566
|
+
// Update stream modal (iframe and info bar) for given room
|
498
567
|
streamModal.find('.modal-footer .btn').removeClass('active');
|
499
568
|
streamModal.find('#stream-select').val(0);
|
500
569
|
|
@@ -510,6 +579,7 @@ window.conference.live = (function() {
|
|
510
579
|
};
|
511
580
|
|
512
581
|
let updateStream = function () {
|
582
|
+
// Update stream modal for currently active room button
|
513
583
|
if (streamModal.hasClass('show')) {
|
514
584
|
let activeButton = streamModal.find('.modal-footer .btn.active');
|
515
585
|
let roomName = activeButton.data('room');
|
@@ -521,6 +591,7 @@ window.conference.live = (function() {
|
|
521
591
|
};
|
522
592
|
|
523
593
|
let stopUpdateStream = function () {
|
594
|
+
// Stop stream modal update timer
|
524
595
|
if (typeof streamVideoTimer !== "undefined") {
|
525
596
|
clearInterval(streamVideoTimer);
|
526
597
|
}
|
@@ -529,13 +600,15 @@ window.conference.live = (function() {
|
|
529
600
|
}
|
530
601
|
};
|
531
602
|
|
532
|
-
let hideModal = function (
|
603
|
+
let hideModal = function () {
|
604
|
+
// Close stream modal
|
533
605
|
streamModal.find('iframe').attr('src', '');
|
534
606
|
streamModal.find('.modal-footer .btn').removeClass('active');
|
535
607
|
streamModal.find('#stream-select').selectedIndex = -1;
|
536
608
|
};
|
537
609
|
|
538
610
|
let setupStream = function () {
|
611
|
+
// Setup events when modal opens/closes
|
539
612
|
streamModal = $('#stream-modal');
|
540
613
|
|
541
614
|
// configure modal opening buttons
|
@@ -544,8 +617,8 @@ window.conference.live = (function() {
|
|
544
617
|
let roomName = button.data('room');
|
545
618
|
setStream(roomName);
|
546
619
|
});
|
547
|
-
streamModal.on('hide.bs.modal', function (
|
548
|
-
hideModal(
|
620
|
+
streamModal.on('hide.bs.modal', function () {
|
621
|
+
hideModal();
|
549
622
|
});
|
550
623
|
|
551
624
|
// configure room selection buttons in modal
|
@@ -51,7 +51,7 @@ window.conference.modal = (function () {
|
|
51
51
|
}
|
52
52
|
};
|
53
53
|
|
54
|
-
let hide = function (el
|
54
|
+
let hide = function (el) {
|
55
55
|
let modal = $(el);
|
56
56
|
|
57
57
|
modal.find('.modal-title h3').text('');
|
@@ -61,13 +61,13 @@ window.conference.modal = (function () {
|
|
61
61
|
};
|
62
62
|
|
63
63
|
let init = function() {
|
64
|
-
elSel = '#link-modal';
|
64
|
+
let elSel = '#link-modal';
|
65
65
|
|
66
66
|
$(elSel).on('show.bs.modal', function (event) {
|
67
67
|
show(this, event);
|
68
68
|
});
|
69
|
-
$(elSel).on('hide.bs.modal', function (
|
70
|
-
hide(this
|
69
|
+
$(elSel).on('hide.bs.modal', function () {
|
70
|
+
hide(this);
|
71
71
|
});
|
72
72
|
};
|
73
73
|
|
@@ -34,7 +34,7 @@ window.conference.program = (function() {
|
|
34
34
|
}
|
35
35
|
|
36
36
|
// Add current selected day as hash to URL while keeping current scrolling position
|
37
|
-
$('a[data-toggle="tab"]').on('shown.bs.tab', function (
|
37
|
+
$('a[data-toggle="tab"]').on('shown.bs.tab', function () {
|
38
38
|
updateHash(this.hash);
|
39
39
|
});
|
40
40
|
}
|
data/_includes/js/syncscroll.js
CHANGED
@@ -29,7 +29,7 @@ function (exports) {
|
|
29
29
|
var elems = document.getElementsByClassName('syncscroll');
|
30
30
|
var i, j, el, found, name;
|
31
31
|
for (name in names) {
|
32
|
-
if (
|
32
|
+
if (Object.prototype.hasOwnProperty.call(names, name)) {
|
33
33
|
for (i = 0; i < names[name].length; i++) {
|
34
34
|
names[name][i].removeEventListener(
|
35
35
|
'scroll', names[name][i].syn, 0
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
<div class="modal-header">
|
6
6
|
<h5 class="modal-title">
|
7
|
-
{{ site.data.lang[site.conference.lang].live.
|
7
|
+
{{ site.data.lang[site.conference.lang].live.stream | default: "Live Stream" }}
|
8
8
|
</h5>
|
9
9
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
10
10
|
<span aria-hidden="true">×</span>
|
@@ -12,7 +12,7 @@
|
|
12
12
|
</div>
|
13
13
|
|
14
14
|
<div class="modal-body embed-responsive embed-responsive-16by9">
|
15
|
-
<iframe class="embed-responsive-item" src="" allowfullscreen></iframe>
|
15
|
+
<iframe class="embed-responsive-item" src="" frameborder="none" allowfullscreen="allowfullscreen" seamless="seamless" scrolling="no"></iframe>
|
16
16
|
<div id="stream-placeholder" class="embed-responsive-item d-none justify-content-center align-items-center">
|
17
17
|
<div></div>
|
18
18
|
</div>
|
@@ -41,7 +41,18 @@
|
|
41
41
|
|
42
42
|
<li class="nav-item live-show d-none" data-start="{{ live_starts }}" data-end="{{ live_ends }}">
|
43
43
|
{%- if site.conference.live.streaming %}
|
44
|
-
<a class="nav-link" title="
|
44
|
+
<a class="nav-link" title="
|
45
|
+
{%- if link.name -%}
|
46
|
+
{{- link.name -}}
|
47
|
+
{%- else -%}
|
48
|
+
{{- site.data.lang[site.conference.lang].live.stream | default: "Live Stream" -}}
|
49
|
+
{%- endif -%}
|
50
|
+
" {% if site.conference.live.streaming.external -%}
|
51
|
+
href="{{ site.conference.live.streaming.external }}"
|
52
|
+
{%- else -%}
|
53
|
+
data-toggle="modal" data-target="#stream-modal" data-room="{{ r.name }}" href="#"
|
54
|
+
{%- endif -%}
|
55
|
+
>
|
45
56
|
{%- else %}
|
46
57
|
{%- assign link_styleclass = "nav-link" -%}
|
47
58
|
{%- include partials/get_link.html %}
|
@@ -2,7 +2,11 @@
|
|
2
2
|
{%- include partials/get_talk_timestamp.html -%}
|
3
3
|
|
4
4
|
{%- if site.conference.live.streaming -%}
|
5
|
-
<a title="{{ link.name }}"
|
5
|
+
<a title="{{ link.name }}" {% if site.conference.live.streaming.external -%}
|
6
|
+
href="{{ site.conference.live.streaming.external }}"
|
7
|
+
{%- else -%}
|
8
|
+
data-toggle="modal" data-target="#stream-modal" data-room="{{ r.name }}" href="#"
|
9
|
+
{%- endif -%}
|
6
10
|
{%- else -%}
|
7
11
|
<span
|
8
12
|
{%- endif %} class="live-show live-button badge badge-dark font-weight-normal text-center d-none {{ live_button_styleclass }}" data-start="{{ timestamp_start }}" data-end="{{ timestamp_end }}">
|
data/_layouts/data.html
CHANGED
@@ -12,13 +12,19 @@
|
|
12
12
|
],
|
13
13
|
|
14
14
|
"rooms": {
|
15
|
+
{%- assign first_room = true -%}
|
15
16
|
{%- for room in site.rooms %}
|
16
|
-
{%- if room.live
|
17
|
+
{%- if room.live -%}
|
18
|
+
{%- unless first_room -%}
|
19
|
+
,
|
20
|
+
{%- else -%}
|
21
|
+
{%- assign first_room = false -%}
|
22
|
+
{%- endunless %}
|
17
23
|
"{{ room.name }}": {
|
18
24
|
"id": {{ forloop.index }},
|
19
25
|
"name": "{{ room.name }}",
|
20
26
|
"href": "{{ room.live }}"
|
21
|
-
}
|
27
|
+
}
|
22
28
|
{%- endif -%}
|
23
29
|
{%- endfor %}
|
24
30
|
},
|
@@ -41,18 +47,24 @@
|
|
41
47
|
},
|
42
48
|
|
43
49
|
"talks": {
|
50
|
+
{%- assign first_room = true -%}
|
44
51
|
{%- for room in site.rooms -%}
|
45
|
-
{%- assign
|
52
|
+
{%- assign first_talk = true -%}
|
46
53
|
{%- for d in site.data.program.days -%}
|
47
54
|
{%- for r in d.rooms -%}
|
48
55
|
{%- if room.name == r.name and room.live %}
|
49
56
|
|
50
|
-
{%-
|
57
|
+
{%- if first_talk -%}
|
58
|
+
{%- unless first_room -%}
|
59
|
+
,
|
60
|
+
{%- else -%}
|
61
|
+
{%- assign first_room = false -%}
|
62
|
+
{%- endunless %}
|
51
63
|
"{{ room.name | replace: '"', '\"' }}": [
|
52
|
-
{%- assign
|
64
|
+
{%- assign first_talk = false %}
|
53
65
|
{%- else -%}
|
54
66
|
,
|
55
|
-
{%-
|
67
|
+
{%- endif -%}
|
56
68
|
|
57
69
|
{%- for t in r.talks %}
|
58
70
|
{%- assign talk = site.talks | where: 'name', t.name | first %}
|
@@ -82,9 +94,9 @@
|
|
82
94
|
{%- endfor -%}
|
83
95
|
{%- endfor -%}
|
84
96
|
|
85
|
-
{%-
|
86
|
-
]
|
87
|
-
{%-
|
97
|
+
{%- unless first_talk %}
|
98
|
+
]
|
99
|
+
{%- endunless -%}
|
88
100
|
{%- endfor %}
|
89
101
|
}
|
90
102
|
}
|
data/_layouts/home.html
CHANGED
@@ -49,7 +49,7 @@
|
|
49
49
|
{%- if link.name -%}
|
50
50
|
{%- assign link_name = link.name -%}
|
51
51
|
{%- else -%}
|
52
|
-
{%- assign link_name = site.data.lang[site.conference.lang].live.
|
52
|
+
{%- assign link_name = site.data.lang[site.conference.lang].live.stream | default: "Live Stream" -%}
|
53
53
|
{%- endif -%}
|
54
54
|
|
55
55
|
{%- if link.name_inactive -%}
|
data/_layouts/page.html
CHANGED
@@ -0,0 +1,42 @@
|
|
1
|
+
{% include partials/header.html %}
|
2
|
+
|
3
|
+
<h1 class="display-5 mb-4">
|
4
|
+
{% if page.title %}
|
5
|
+
{{ page.title }}
|
6
|
+
{% else %}
|
7
|
+
{{ site.data.lang[site.conference.lang].live.stream | default: "Live Streams" }}
|
8
|
+
{% endif %}
|
9
|
+
</h1>
|
10
|
+
|
11
|
+
{{ content }}
|
12
|
+
|
13
|
+
{%- assign nbr_streams = 0 -%}
|
14
|
+
{%- for room in site.rooms -%}
|
15
|
+
{%- if room.live -%}
|
16
|
+
{%- assign mod_nbr_streams = nbr_streams | modulo: 2 -%}
|
17
|
+
{%- if mod_nbr_streams == 0 %}
|
18
|
+
<div class="row">
|
19
|
+
{%- endif %}
|
20
|
+
|
21
|
+
<div class="col-md">
|
22
|
+
<h3>{{ room.name }}</h3>
|
23
|
+
<div class="embed-responsive embed-responsive-16by9">
|
24
|
+
<iframe class="embed-responsive-item" src="{{ room.live }}" allowfullscreen></iframe>
|
25
|
+
</div>
|
26
|
+
</div>
|
27
|
+
|
28
|
+
{%- if mod_nbr_streams == 1 %}
|
29
|
+
</div>
|
30
|
+
{%- endif -%}
|
31
|
+
|
32
|
+
{%- assign nbr_streams = nbr_streams | plus: 1 -%}
|
33
|
+
{%- endif -%}
|
34
|
+
{%- endfor %}
|
35
|
+
|
36
|
+
{% assign mod_nbr_streams = nbr_streams | modulo: 2 %}
|
37
|
+
{%- if mod_nbr_streams == 1 %}
|
38
|
+
<div class="col-md"></div>
|
39
|
+
</div>
|
40
|
+
{%- endif %}
|
41
|
+
|
42
|
+
{% include partials/footer.html %}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll-theme-conference
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lorenz Schmid
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-02-
|
11
|
+
date: 2021-02-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jekyll
|
@@ -108,6 +108,7 @@ files:
|
|
108
108
|
- _layouts/room.html
|
109
109
|
- _layouts/speaker-overview.html
|
110
110
|
- _layouts/speaker.html
|
111
|
+
- _layouts/stream-overview.html
|
111
112
|
- _layouts/talk-overview.html
|
112
113
|
- _layouts/talk.html
|
113
114
|
- _sass/bootstrap/_alert.scss
|