jekyll-theme-conference 3.0.2 → 3.1.2

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: 2db4dc4680aa85647500757325334eb2e5e4db739cf56247839bed4ebcbd281c
4
- data.tar.gz: aecfefef9ad494d5ed8069e5fd1ce504ca1a3c33b21b8a150bb73c9e4bf37f40
3
+ metadata.gz: d6dfd46bcf846b9381cf7a9f0b88a063339e1ba62ca33bfd979c56b2ffb20621
4
+ data.tar.gz: 9d6fb33e2b5d0c1c690af32947d7c93f8ae3003f78b0c179d28ed7e3dfe825c9
5
5
  SHA512:
6
- metadata.gz: 10b0fe0bf595f54070bf936326d5498b7d0c79a8668f61251f5695bff52ea281a69889af57ebed2e3904d4d6f2323ea5447b479078a554c03c633861858e2fc2
7
- data.tar.gz: ad815822f66b57d2f2a3919ee0f3d5771d6898c427cb275e38259fa2849eeeeb3ab1002ba9d92e95cd7cf766711c08523356e7f75d717776885c33279f4458b9
6
+ metadata.gz: 8b8ace8e151d2bac7f2a4f2624f8ab947cbb255c4c40de094e60ebb0205d87a5047bb33de6faea4deff3276ba6e6d0cea9f1bc920c0bacbc7946bcf999a251de
7
+ data.tar.gz: 96ee3c142c692447badd23a59244614d272f34ff86092fbe138465ac4257484de610ea3b2db9718b4fe7fbe7ff8179d7e69969818e1eba947c58cf3b7a7cfbb5
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).
@@ -13,6 +13,8 @@ window.conference.live = (function() {
13
13
  {%- include partials/get_talk_timestamp.html -%}
14
14
  {%- assign conf_end = timestamp_end -%}
15
15
 
16
+ let data;
17
+
16
18
  let confStart = {{ conf_start }};
17
19
  let confEnd = {{ conf_end }};
18
20
  let confDur = confEnd - confStart;
@@ -32,26 +34,43 @@ window.conference.live = (function() {
32
34
  let streamVideoTimer;
33
35
  let streamInfoTimer;
34
36
 
37
+ let loadData = function () {
38
+ // Fetch schedule from external file
39
+ $.getJSON('{{ site.baseurl }}/assets/js/data.json', function(json) {
40
+ data = json;
41
+ });
42
+ };
43
+
44
+ let getData = function () {
45
+ // Return data
46
+ return data;
47
+ };
48
+
35
49
  let mod = function (n, m) {
50
+ // Absolute modulo
36
51
  return ((n % m) + m) % m;
37
52
  };
38
53
 
39
54
  let timeNow = function () {
55
+ // Current timestamp in seconds
40
56
  return Math.floor(Date.now() / 1000);
41
57
  };
42
58
 
43
59
  let timeCont = function () {
60
+ // Continuous time (respecting previous pauses)
44
61
  return timeNow() - timeOffset;
45
62
  };
46
63
 
47
64
  let timeCycle = function () {
65
+ // Cyclic timestamp in seconds
48
66
  let actTime = timeNow();
49
- let relTime = mod(actTime, durDemo + 2*durPause) / durDemo;
67
+ let relTime = mod(actTime, durDemo + 2*durPause) / (durDemo + 2*durPause);
50
68
  let cycleTime = mod((demoEnd - demoStart) * relTime - timeOffset, (demoEnd - demoStart)) + demoStart;
51
69
  return cycleTime;
52
70
  };
53
71
 
54
72
  let time = function () {
73
+ // Return app time
55
74
  if (freezeTime) {
56
75
  return timeFrozen;
57
76
  }
@@ -64,6 +83,7 @@ window.conference.live = (function() {
64
83
  };
65
84
 
66
85
  let pauseTime = function () {
86
+ // Pause app time
67
87
  if (!freezeTime) {
68
88
  timeFrozen = time();
69
89
  freezeTime = true;
@@ -73,6 +93,7 @@ window.conference.live = (function() {
73
93
  };
74
94
 
75
95
  let continueTime = function () {
96
+ // Continue app time
76
97
  if (freezeTime) {
77
98
  freezeTime = false;
78
99
  timeOffset += time() - timeFrozen;
@@ -80,18 +101,23 @@ window.conference.live = (function() {
80
101
  }
81
102
  };
82
103
 
83
- let resetTime = function (timeStr) {
104
+ let resetTime = function () {
105
+ // Reset app time
84
106
  timeOffset = 0;
85
107
  freezeTime = false;
86
108
 
87
109
  startUpdate();
88
110
  };
89
111
 
90
- let setTime = function (newTime, newDay=1) {
112
+ let setTime = function (newTime, newDay) {
113
+ // Set and pause app time
91
114
  pauseTime();
92
115
 
93
116
  let dayIdx;
94
- if (Number.isInteger(newDay)) {
117
+ if (arguments.length < 2) {
118
+ dayIdx = 0;
119
+ }
120
+ else if (Number.isInteger(newDay)) {
95
121
  dayIdx = newDay-1;
96
122
  }
97
123
  else if (/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test(newDay)) {
@@ -100,7 +126,7 @@ window.conference.live = (function() {
100
126
  else {
101
127
  dayIdx = data.days.find(o => o.name === newDay);
102
128
  }
103
- newDate = data.days[dayIdx].date;
129
+ let newDate = data.days[dayIdx].date;
104
130
 
105
131
  let d = new Date(newDate);
106
132
  newTime = newTime.split(':');
@@ -111,7 +137,10 @@ window.conference.live = (function() {
111
137
  update();
112
138
  };
113
139
 
114
- let getTime = function (tConvert=time()) {
140
+ let getTime = function () {
141
+ // Return app time as string
142
+ let tConvert = time();
143
+
115
144
  let d = new Date(tConvert * 1000);
116
145
  let dStr = d.toISOString().slice(0,10);
117
146
  let h = d.getHours();
@@ -121,6 +150,7 @@ window.conference.live = (function() {
121
150
  };
122
151
 
123
152
  let timeUnit = function () {
153
+ // App time refresh rate
124
154
  if (demo) {
125
155
  return 0.1;
126
156
  }
@@ -130,6 +160,7 @@ window.conference.live = (function() {
130
160
  };
131
161
 
132
162
  let delayStart = function (startTime) {
163
+ // Seconds until given startTime occurs
133
164
  let tNow = time();
134
165
  let tUnit = timeUnit();
135
166
 
@@ -149,21 +180,25 @@ window.conference.live = (function() {
149
180
  };
150
181
 
151
182
  let toggleDemo = function () {
183
+ // Toggle app demo mode
152
184
  demo = !demo;
153
185
  resetTime();
154
186
  };
155
187
 
156
188
  let demoOn = function () {
189
+ // Return app demo status
157
190
  return demo;
158
191
  };
159
192
 
160
193
  let updateLive = function () {
194
+ // Update status all live elements in DOM
161
195
  let tNow = time();
162
196
  let liveShow = document.getElementsByClassName('live-show');
163
197
  let liveHide = document.getElementsByClassName('live-hide');
164
198
  let liveTime = document.getElementsByClassName('live-time');
165
199
  let livePast = document.getElementsByClassName('live-past');
166
200
 
201
+ // Show elements for a given period
167
202
  for (let i = 0; i < liveShow.length; i++) {
168
203
  let tStarts = liveShow[i].dataset.start.split(',');
169
204
  let tEnds = liveShow[i].dataset.end.split(',');
@@ -181,6 +216,7 @@ window.conference.live = (function() {
181
216
  }
182
217
  }
183
218
 
219
+ // Hide elements for a given period
184
220
  for (let i = 0; i < liveHide.length; i++) {
185
221
  let tStarts = liveHide[i].dataset.start.split(',');
186
222
  let tEnds = liveHide[i].dataset.end.split(',');
@@ -200,6 +236,7 @@ window.conference.live = (function() {
200
236
  }
201
237
  }
202
238
 
239
+ // Update duration string for given elements
203
240
  for (let i = 0; i < liveTime.length; i++) {
204
241
  let t = liveTime[i].dataset.time;
205
242
  if (typeof t == "undefined") {
@@ -259,6 +296,7 @@ window.conference.live = (function() {
259
296
  liveTime[i].innerHTML = tStr;
260
297
  }
261
298
 
299
+ // Disable elements for a given period
262
300
  for (let i = 0; i < livePast.length; i++) {
263
301
  let t = livePast[i].dataset.time;
264
302
  if (typeof t == "undefined") {
@@ -278,13 +316,14 @@ window.conference.live = (function() {
278
316
  }
279
317
  }
280
318
 
319
+ // Cancel timer after program is over
281
320
  if (tNow > confEnd && !demo) {
282
- // Cancel timer after program is over
283
321
  stopUpdateLive();
284
322
  }
285
323
  };
286
324
 
287
325
  let startUpdateLive = function () {
326
+ // Start update timer to update live elements in DOM
288
327
  stopUpdateLive();
289
328
  updateLive();
290
329
 
@@ -301,6 +340,7 @@ window.conference.live = (function() {
301
340
  };
302
341
 
303
342
  let stopUpdateLive = function () {
343
+ // stopUpdate update timer to update live elements in DOM
304
344
  if (typeof liveTimer !== "undefined") {
305
345
  clearInterval(liveTimer);
306
346
  }
@@ -312,9 +352,9 @@ window.conference.live = (function() {
312
352
  let streamExtend = {{ site.conference.live.streaming.time_extend | default: 5 }}; // in minutes
313
353
 
314
354
  let streamModal;
315
- let data;
316
355
 
317
356
  let getRoom = function (roomName) {
357
+ // Return room object for given room name
318
358
  if (roomName in data.rooms) {
319
359
  return data.rooms[roomName];
320
360
  }
@@ -323,11 +363,21 @@ window.conference.live = (function() {
323
363
  }
324
364
  };
325
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
+
326
375
  let getNextTalk = function (roomName) {
376
+ // Get talk object for next talk in given room
327
377
  let timeNow = time();
328
- let talksHere = data.talks[roomName];
378
+ let talksHere = getTalks(roomName);
329
379
 
330
- if (typeof talksHere !== "undefined") {
380
+ if (talksHere) {
331
381
  if (timeNow < talksHere[talksHere.length-1].end) {
332
382
  for (var i = 0; i < talksHere.length; i++) {
333
383
  if (timeNow < talksHere[i].end) {
@@ -340,10 +390,11 @@ window.conference.live = (function() {
340
390
  };
341
391
 
342
392
  let getNextPause = function (roomName) {
393
+ // Get time object for next pause in given room
343
394
  let timeNow = time();
344
- let talksHere = data.talks[roomName];
395
+ let talksHere = getTalks(roomName);
345
396
 
346
- if (typeof talksHere !== "undefined") {
397
+ if (talksHere) {
347
398
  if (timeNow < talksHere[talksHere.length-1].end) {
348
399
  for (var i = 1; i < talksHere.length; i++) {
349
400
  if (timeNow < talksHere[i].start && streamPause*60 <= talksHere[i].start - talksHere[i-1].end) {
@@ -358,25 +409,49 @@ window.conference.live = (function() {
358
409
  return false;
359
410
  };
360
411
 
361
- let setStreamContent = function (content) {
412
+ let setStreamIframeContent = function (content) {
413
+ // Set stream modal iframe to show given text
362
414
  streamModal.find('iframe').attr('src', '');
363
415
  streamModal.find('iframe').addClass('d-none');
364
416
  streamModal.find('#stream-placeholder > div').text(content);
365
417
  streamModal.find('#stream-placeholder').addClass('d-flex');
366
418
  };
367
419
 
368
- let setStreamSrc = function (href) {
420
+ let setStreamIframeSrc = function (href) {
421
+ // Set stream modal iframe to show given URL
369
422
  streamModal.find('iframe').attr('src', href);
370
423
  streamModal.find('#stream-placeholder').addClass('d-none').removeClass('d-flex');
371
424
  streamModal.find('iframe').removeClass('d-none');
372
425
  };
373
426
 
374
427
  let setStreamVideo = function (roomName) {
428
+ // Update stream modal iframe:
429
+ // Show stream with start/pause/end message (for given room) and keep updated
375
430
  let timeNow = time();
376
431
 
377
- let talksHere = data.talks[roomName];
378
- let roomStart = talksHere[0].start;
379
- 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
+ }
380
455
 
381
456
  if (typeof streamVideoTimer !== "undefined") {
382
457
  clearInterval(streamVideoTimer);
@@ -384,7 +459,7 @@ window.conference.live = (function() {
384
459
 
385
460
  // Conference not yet started
386
461
  if (timeNow < roomStart - streamPrepend*60) {
387
- 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." }}');
388
463
 
389
464
  if (!freezeTime) {
390
465
  streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomStart - streamPrepend*60) * 1000, roomName);
@@ -393,7 +468,7 @@ window.conference.live = (function() {
393
468
 
394
469
  // Conference is over
395
470
  else if (timeNow > roomEnd + streamExtend*60) {
396
- 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." }}');
397
472
 
398
473
  if (!freezeTime && demo) {
399
474
  streamVideoTimer = setTimeout(setStreamVideo, delayStart(roomEnd - streamPrepend*60) * 1000, roomName);
@@ -406,7 +481,7 @@ window.conference.live = (function() {
406
481
 
407
482
  // Currently stream is paused
408
483
  if (pauseNext && timeNow >= pauseNext.start + streamExtend*60 && timeNow <= pauseNext.end - streamPrepend*60) {
409
- 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." }}');
410
485
 
411
486
  if (!freezeTime) {
412
487
  streamVideoTimer = setTimeout(setStreamVideo, delayStart(pauseNext.end - streamPrepend*60) * 1000, roomName);
@@ -415,7 +490,7 @@ window.conference.live = (function() {
415
490
  // Currently a talk is active
416
491
  else {
417
492
  let room = getRoom(roomName);
418
- setStreamSrc(room.href);
493
+ setStreamIframeSrc(room.href);
419
494
 
420
495
  if (!freezeTime) {
421
496
  if (pauseNext) {
@@ -430,6 +505,8 @@ window.conference.live = (function() {
430
505
  };
431
506
 
432
507
  let setStreamInfo = function (roomName) {
508
+ // Update stream modal info bar:
509
+ // Show next talk and speaker (for given room) and keep updated
433
510
  let timeNow = time();
434
511
  let talkNext = getNextTalk(roomName);
435
512
 
@@ -437,7 +514,7 @@ window.conference.live = (function() {
437
514
  clearInterval(streamInfoTimer);
438
515
  }
439
516
 
440
- if (timeNow >= talkNext.start - streamPause*60) {
517
+ if (talkNext && timeNow >= talkNext.start - streamPause*60) {
441
518
  document.getElementById('stream-info').dataset.time = talkNext.start;
442
519
  document.getElementById('stream-info-time').dataset.time = talkNext.start;
443
520
  updateLive();
@@ -476,14 +553,17 @@ window.conference.live = (function() {
476
553
  streamInfoTimer = setTimeout(setStreamInfo, delayStart(talkNext.start - streamPause*60) * 1000, roomName);
477
554
  }
478
555
  else if (demo) {
479
- let talksHere = data.talks[roomName];
480
- 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
+ }
481
560
  }
482
561
  }
483
562
  }
484
563
  };
485
564
 
486
565
  let setStream = function (roomName) {
566
+ // Update stream modal (iframe and info bar) for given room
487
567
  streamModal.find('.modal-footer .btn').removeClass('active');
488
568
  streamModal.find('#stream-select').val(0);
489
569
 
@@ -499,6 +579,7 @@ window.conference.live = (function() {
499
579
  };
500
580
 
501
581
  let updateStream = function () {
582
+ // Update stream modal for currently active room button
502
583
  if (streamModal.hasClass('show')) {
503
584
  let activeButton = streamModal.find('.modal-footer .btn.active');
504
585
  let roomName = activeButton.data('room');
@@ -510,6 +591,7 @@ window.conference.live = (function() {
510
591
  };
511
592
 
512
593
  let stopUpdateStream = function () {
594
+ // Stop stream modal update timer
513
595
  if (typeof streamVideoTimer !== "undefined") {
514
596
  clearInterval(streamVideoTimer);
515
597
  }
@@ -518,13 +600,15 @@ window.conference.live = (function() {
518
600
  }
519
601
  };
520
602
 
521
- let hideModal = function (event) {
603
+ let hideModal = function () {
604
+ // Close stream modal
522
605
  streamModal.find('iframe').attr('src', '');
523
606
  streamModal.find('.modal-footer .btn').removeClass('active');
524
607
  streamModal.find('#stream-select').selectedIndex = -1;
525
608
  };
526
609
 
527
610
  let setupStream = function () {
611
+ // Setup events when modal opens/closes
528
612
  streamModal = $('#stream-modal');
529
613
 
530
614
  // configure modal opening buttons
@@ -533,8 +617,8 @@ window.conference.live = (function() {
533
617
  let roomName = button.data('room');
534
618
  setStream(roomName);
535
619
  });
536
- streamModal.on('hide.bs.modal', function (event) {
537
- hideModal(event);
620
+ streamModal.on('hide.bs.modal', function () {
621
+ hideModal();
538
622
  });
539
623
 
540
624
  // configure room selection buttons in modal
@@ -552,14 +636,10 @@ window.conference.live = (function() {
552
636
  let roomName = $(this).children('option:selected').text();
553
637
  setStream(roomName);
554
638
  });
555
-
556
- // load data
557
- $.getJSON('{{ site.baseurl }}/assets/js/data.json', function(json) {
558
- data = json;
559
- });
560
639
  };
561
640
 
562
641
  let setup = function () {
642
+ loadData();
563
643
  startUpdateLive();
564
644
  setupStream();
565
645
  };
@@ -582,6 +662,7 @@ window.conference.live = (function() {
582
662
  {%- else -%}
583
663
 
584
664
  let setup = function () {
665
+ loadData();
585
666
  startUpdateLive();
586
667
  };
587
668
 
@@ -601,6 +682,7 @@ window.conference.live = (function() {
601
682
 
602
683
  return {
603
684
  init: setup,
685
+ getData: getData,
604
686
 
605
687
  pauseTime: pauseTime,
606
688
  continueTime: continueTime,
@@ -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>
@@ -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
@@ -23,11 +23,12 @@
23
23
 
24
24
  {% if site.conference.main.links %}
25
25
  <div class="lead d-print-none">
26
+ {% assign btn_default = 'btn btn-outline-primary btn-lg mt-2 ml-1' %}
26
27
  {% for link in site.conference.main.links %}
27
28
 
28
29
  {% if link.menu %}
29
30
  <div class="dropdown d-inline">
30
- <a class="btn btn-outline-primary btn-lg mt-2 dropdown-toggle" href="#" role="button" id="main-dropdown{{ forloop.index0 }}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
31
+ <a class="{{ btn_default }} dropdown-toggle" href="#" role="button" id="main-dropdown{{ forloop.index0 }}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
31
32
  {{ link.name }}
32
33
  </a>
33
34
  <div class="dropdown-menu" aria-labelledby="main-dropdown{{ forloop.index0 }}">
@@ -48,20 +49,20 @@
48
49
  {%- if link.name -%}
49
50
  {%- assign link_name = link.name -%}
50
51
  {%- else -%}
51
- {%- 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" -%}
52
53
  {%- endif -%}
53
54
 
54
55
  {%- if link.name_inactive -%}
55
- <span class="live-hide btn btn-outline-primary btn-lg mt-2 disabled" data-start="{{ live_starts }}" data-end="{{ live_ends }}">
56
+ <span class="live-hide {{ btn_default }} disabled" data-start="{{ live_starts }}" data-end="{{ live_ends }}">
56
57
  {{ link.name_inactive }}
57
58
  </span>
58
59
  {%- endif -%}
59
60
 
60
61
  <span class="live-show d-none" data-start="{{ live_starts }}" data-end="{{ live_ends }}">
61
62
  {% if site.conference.live.streaming %}
62
- <a class="btn btn-outline-primary btn-lg mt-2" title="{{ link_name }}" data-toggle="modal" data-target="#stream-modal" data-room="" href="#">
63
+ <a class="{{ btn_default }}" title="{{ link_name }}" data-toggle="modal" data-target="#stream-modal" data-room="" href="#">
63
64
  {% else %}
64
- {% assign link_styleclass = "btn btn-outline-primary btn-lg mt-2" %}
65
+ {% assign link_styleclass = "{{ btn_default }}" %}
65
66
  {% include partials/get_link.html %}
66
67
  {{ link_tag }}
67
68
  {% endif %}
@@ -71,7 +72,7 @@
71
72
  </span>
72
73
 
73
74
  {% else %}
74
- {% assign link_styleclass = "btn btn-outline-primary btn-lg mt-2" %}
75
+ {% assign link_styleclass = btn_default %}
75
76
  {% include partials/get_link.html %}
76
77
  {{ link_tag }}
77
78
  {{ link.name }}
@@ -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 %}
@@ -79,6 +79,12 @@ ul.btn-group {
79
79
 
80
80
  // General
81
81
 
82
+ // Keep images in container
83
+ main.container img {
84
+ max-width: 100%;
85
+ height: auto;
86
+ }
87
+
82
88
  // No bottom margin on info-bar
83
89
  .alert > p:last-of-type {
84
90
  margin-bottom: 0;
@@ -135,19 +141,21 @@ ul.btn-group {
135
141
 
136
142
  // Column widths
137
143
  th, td {
144
+ // Total available container width is 1110px
145
+
138
146
  // Width of columns with content (default)
139
- width: 220px;
140
- min-width: 220px;
147
+ width: 245px;
148
+ min-width: 245px;
141
149
 
142
150
  // Spacing between columns
143
151
  &.col-space {
144
- width: 10px;
145
- min-width: 10px;
152
+ width: 15px;
153
+ min-width: 15px;
146
154
  }
147
155
  // Width of first column containing timestamps
148
156
  &.col-title {
149
- width: 4.5em;
150
- min-width: 4.5em;
157
+ width: 70px;
158
+ min-width: 70px;
151
159
  }
152
160
  }
153
161
  }
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.2
4
+ version: 3.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorenz Schmid
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-14 00:00:00.000000000 Z
11
+ date: 2021-02-15 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
@@ -278,7 +279,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
278
279
  - !ruby/object:Gem::Version
279
280
  version: '0'
280
281
  requirements: []
281
- rubygems_version: 3.1.4
282
+ rubygems_version: 3.2.3
282
283
  signing_key:
283
284
  specification_version: 4
284
285
  summary: Jekyll template for a conference website containing program, speaker, talks