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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d6b3c4e4f2dd3a6f1d5964ff2dfccad58d737a96c58a4d34c7ee506d8ed50a07
4
- data.tar.gz: a2f1f59ff4abbe070bc95702001270fc56e6abdb3e3e8fc274705d1bf9a4661c
3
+ metadata.gz: d71db73a3994c514ebc0e7e8bd0c96905deb68f38dce861dd4bc21ba56b730ae
4
+ data.tar.gz: a4e171604b41298e1ecb60ffe429a4b2ae2bb9ff961d01ea0be35230ba635903
5
5
  SHA512:
6
- metadata.gz: b3424868268f6ff9003ae4a913f4d7985413db330bc2b8b4a4d94a15d39d496d5c21083e94e29d3242c56ae4f536d366b306cb7a2d80e5aedc3376c84b8332f6
7
- data.tar.gz: 387fa9c0e9a183949314c800397a56c1e41f231301dfed0396751257f036ab4e2be319f98f67f06ea56897b0f72b54facb590664775822a6c280632008d48081
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`), and
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 (timeStr) {
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=1) {
112
+ let setTime = function (newTime, newDay) {
113
+ // Set and pause app time
103
114
  pauseTime();
104
115
 
105
116
  let dayIdx;
106
- if (Number.isInteger(newDay)) {
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 (tConvert=time()) {
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 = data.talks[roomName];
378
+ let talksHere = getTalks(roomName);
340
379
 
341
- if (typeof talksHere !== "undefined") {
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 = data.talks[roomName];
395
+ let talksHere = getTalks(roomName);
356
396
 
357
- if (typeof talksHere !== "undefined") {
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 setStreamContent = function (content) {
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 setStreamSrc = function (href) {
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 = data.talks[roomName];
389
- let roomStart = talksHere[0].start;
390
- let roomEnd = talksHere[talksHere.length-1].end;
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
- setStreamContent('{{ site.data.lang[site.conference.lang].live.pre_stream | default: "Live stream has not started yet." }}');
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
- setStreamContent('{{ site.data.lang[site.conference.lang].live.post_stream | default: "Live stream has ended." }}');
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
- setStreamContent('{{ site.data.lang[site.conference.lang].live.pause_stream | default: "Live stream is currently paused." }}');
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
- setStreamSrc(room.href);
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 = data.talks[roomName];
491
- streamInfoTimer = setTimeout(setStreamInfo, delayStart(talksHere[0].start - streamPrepend*60) * 1000, roomName);
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 (event) {
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 (event) {
548
- hideModal(event);
620
+ streamModal.on('hide.bs.modal', function () {
621
+ hideModal();
549
622
  });
550
623
 
551
624
  // configure room selection buttons in modal
@@ -24,7 +24,7 @@ window.conference.mapConfig = (function() {
24
24
  };
25
25
 
26
26
  let init = function () {
27
- elId = 'map';
27
+ let elId = 'map';
28
28
 
29
29
  if (document.getElementById(elId)) {
30
30
  setup(elId);
@@ -51,7 +51,7 @@ window.conference.modal = (function () {
51
51
  }
52
52
  };
53
53
 
54
- let hide = function (el, event) {
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 (event) {
70
- hide(this, event);
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 (e) {
37
+ $('a[data-toggle="tab"]').on('shown.bs.tab', function () {
38
38
  updateHash(this.hash);
39
39
  });
40
40
  }
@@ -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 (names.hasOwnProperty(name)) {
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.streaming | default: "Live Stream" }}
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">&times;</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="{% if link.name %}{{ link.name }}{% else %}{{ site.data.lang[site.conference.lang].live.streaming | default: "Live Stream" }}{% endif %}" data-toggle="modal" data-target="#stream-modal" data-room="" href="#">
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 }}" data-toggle="modal" data-target="#stream-modal" data-room="{{ r.name }}" href="#"
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
- }{%- unless forloop.last -%},{%- endunless %}
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 room_has_talks = false %}
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
- {%- unless room_has_talks %}
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 room_has_talks = true %}
64
+ {%- assign first_talk = false %}
53
65
  {%- else -%}
54
66
  ,
55
- {%- endunless -%}
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
- {%- if room_has_talks %}
86
- ]{%- unless forloop.last -%},{%- endunless -%}
87
- {%- endif -%}
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.streaming | default: "Live Stream" -%}
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
@@ -1,5 +1,9 @@
1
1
  {% include partials/header.html %}
2
2
 
3
+ {% if page.title -%}
4
+ <h1 class="font-weight-light mb-2">{{ page.title }}</h1>
5
+ {%- endif %}
6
+
3
7
  {{ content }}
4
8
 
5
9
  {% include partials/footer.html %}
@@ -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.0.4
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-12 00:00:00.000000000 Z
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